1 /* 2 Haiku ATI video driver adapted from the X.org ATI driver. 3 4 Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 5 6 Copyright 2009 Haiku, Inc. All rights reserved. 7 Distributed under the terms of the MIT license. 8 9 Authors: 10 Gerald Zajac 2009 11 */ 12 13 #include "accelerant.h" 14 #include "mach64.h" 15 16 17 #define MAX_INT ((int)((unsigned int)(-1) >> 2)) 18 19 20 21 void 22 Mach64_ReduceRatio(int *numerator, int *denominator) 23 { 24 // Reduce a fraction by factoring out the largest common divider of the 25 // fraction's numerator and denominator. 26 27 int multiplier = *numerator; 28 int divider = *denominator; 29 int remainder; 30 31 while ((remainder = multiplier % divider)) { 32 multiplier = divider; 33 divider = remainder; 34 } 35 36 *numerator /= divider; 37 *denominator /= divider; 38 } 39 40 41 42 int 43 Mach64_Divide(int numerator, int denominator, int shift, const int roundingKind) 44 { 45 // Using integer arithmetic and avoiding overflows, this function finds the 46 // rounded integer that best approximates 47 // 48 // numerator shift 49 // ----------- * 2 50 // denominator 51 // 52 // using the specified rounding (floor (<0), nearest (=0) or ceiling (>0)). 53 54 Mach64_ReduceRatio(&numerator, &denominator); 55 56 // Deal with left shifts but try to keep the denominator even. 57 if (denominator & 1) { 58 if (denominator <= MAX_INT) { 59 denominator <<= 1; 60 shift++; 61 } 62 } else { 63 while ((shift > 0) && !(denominator & 3)) { 64 denominator >>= 1; 65 shift--; 66 } 67 } 68 69 // Deal with right shifts. 70 while (shift < 0) { 71 if ((numerator & 1) && (denominator <= MAX_INT)) 72 denominator <<= 1; 73 else 74 numerator >>= 1; 75 76 shift++; 77 } 78 79 int rounding = 0; // Default to floor 80 81 if (!roundingKind) // nearest 82 rounding = denominator >> 1; 83 else if (roundingKind > 0) // ceiling 84 rounding = denominator - 1; 85 86 return ((numerator / denominator) << shift) + 87 ((((numerator % denominator) << shift) + rounding) / denominator); 88 } 89