132b578d3Smrg/* 232b578d3Smrg * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 332b578d3Smrg * 432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its 532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that 632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright 732b578d3Smrg * notice and this permission notice appear in supporting documentation, and 832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or 932b578d3Smrg * publicity pertaining to distribution of the software without specific, 1032b578d3Smrg * written prior permission. Marc Aurele La France makes no representations 1132b578d3Smrg * about the suitability of this software for any purpose. It is provided 1232b578d3Smrg * "as-is" without express or implied warranty. 1332b578d3Smrg * 1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE. 2132b578d3Smrg */ 2232b578d3Smrg 2332b578d3Smrg#ifdef HAVE_CONFIG_H 2432b578d3Smrg#include "config.h" 2532b578d3Smrg#endif 2632b578d3Smrg 2732b578d3Smrg#include "atiutil.h" 2832b578d3Smrg 2932b578d3Smrg/* 3032b578d3Smrg * ATIReduceRatio -- 3132b578d3Smrg * 3232b578d3Smrg * Reduce a fraction by factoring out the largest common divider of the 3332b578d3Smrg * fraction's numerator and denominator. 3432b578d3Smrg */ 3532b578d3Smrgvoid 3632b578d3SmrgATIReduceRatio 3732b578d3Smrg( 3832b578d3Smrg int *Numerator, 3932b578d3Smrg int *Denominator 4032b578d3Smrg) 4132b578d3Smrg{ 4232b578d3Smrg int Multiplier, Divider, Remainder; 4332b578d3Smrg 4432b578d3Smrg Multiplier = *Numerator; 4532b578d3Smrg Divider = *Denominator; 4632b578d3Smrg 4732b578d3Smrg while ((Remainder = Multiplier % Divider)) 4832b578d3Smrg { 4932b578d3Smrg Multiplier = Divider; 5032b578d3Smrg Divider = Remainder; 5132b578d3Smrg } 5232b578d3Smrg 5332b578d3Smrg *Numerator /= Divider; 5432b578d3Smrg *Denominator /= Divider; 5532b578d3Smrg} 5632b578d3Smrg 5732b578d3Smrg/* 5832b578d3Smrg * ATIDivide -- 5932b578d3Smrg * 6032b578d3Smrg * Using integer arithmetic and avoiding overflows, this function finds the 6132b578d3Smrg * rounded integer that best approximates 6232b578d3Smrg * 6332b578d3Smrg * Numerator Shift 6432b578d3Smrg * ----------- * 2 6532b578d3Smrg * Denominator 6632b578d3Smrg * 6732b578d3Smrg * using the specified rounding (floor (<0), nearest (=0) or ceiling (>0)). 6832b578d3Smrg */ 6932b578d3Smrgint 7032b578d3SmrgATIDivide 7132b578d3Smrg( 7232b578d3Smrg int Numerator, 7332b578d3Smrg int Denominator, 7432b578d3Smrg int Shift, 7532b578d3Smrg const int RoundingKind 7632b578d3Smrg) 7732b578d3Smrg{ 7832b578d3Smrg int Rounding = 0; /* Default to floor */ 7932b578d3Smrg 8032b578d3Smrg#define MaxInt ((int)((unsigned int)(-1) >> 2)) 8132b578d3Smrg 8232b578d3Smrg ATIReduceRatio(&Numerator, &Denominator); 8332b578d3Smrg 8432b578d3Smrg /* Deal with left shifts but try to keep the denominator even */ 8532b578d3Smrg if (Denominator & 1) 8632b578d3Smrg { 8732b578d3Smrg if (Denominator <= MaxInt) 8832b578d3Smrg { 8932b578d3Smrg Denominator <<= 1; 9032b578d3Smrg Shift++; 9132b578d3Smrg } 9232b578d3Smrg } 9332b578d3Smrg else while ((Shift > 0) && !(Denominator & 3)) 9432b578d3Smrg { 9532b578d3Smrg Denominator >>= 1; 9632b578d3Smrg Shift--; 9732b578d3Smrg } 9832b578d3Smrg 9932b578d3Smrg /* Deal with right shifts */ 10032b578d3Smrg while (Shift < 0) 10132b578d3Smrg { 10232b578d3Smrg if ((Numerator & 1) && (Denominator <= MaxInt)) 10332b578d3Smrg Denominator <<= 1; 10432b578d3Smrg else 10532b578d3Smrg Numerator >>= 1; 10632b578d3Smrg 10732b578d3Smrg Shift++; 10832b578d3Smrg } 10932b578d3Smrg 11032b578d3Smrg if (!RoundingKind) /* Nearest */ 11132b578d3Smrg Rounding = Denominator >> 1; 11232b578d3Smrg else if (RoundingKind > 0) /* Ceiling */ 11332b578d3Smrg Rounding = Denominator - 1; 11432b578d3Smrg 11532b578d3Smrg return ((Numerator / Denominator) << Shift) + 11632b578d3Smrg ((((Numerator % Denominator) << Shift) + Rounding) / Denominator); 11732b578d3Smrg} 118