#include "bg_math.h" #define crumb Com_Printf int Q_floor (float x) { int retval; retval = (int)(floor(x)); return retval; } int Q_ceil (float x) { int retval; retval = (int)(ceil(x)); return retval; } int Q_trunc (float x) { int retval; //crumb("trunc: start %f\n", x); retval = (int)x; /* XXX: ghetto. */ //crumb("trunc: done %d\n", retval); return retval; } /* Round towards nearest, towards even if halfway. */ int Q_round (float x) { int retval; int i, up, down; float checkpart; //crumb("round: start %f\n", x); i = Q_trunc(x); checkpart = x - (float)i; if (x < 0) { up = i; down = i - 1; if (checkpart == -0.5) { if ((up % 2) == 0) { retval = up; } else { retval = down; } } else if (checkpart > -0.5) { retval = up; } else if (checkpart < -0.5) { retval = down; } } else if (x > 0) { down = i; up = i + 1; if (checkpart == 0.5) { if ((up % 2) == 0) { retval = up; } else { retval = down; } } else if (checkpart > 0.5) { retval = up; } else if (checkpart < 0.5) { retval = down; } } else { retval = 0; } //crumb("round: done %d\n", retval); return retval; } float Q_exp (float x) { float retval; retval = exp(x); /* The re-implemented log. */ return retval; } float Q_log (float x) { float retval; retval = ln(x); return retval; } float Q_sin (float theta) { float retval; retval = sin(theta); return retval; } float Q_cos (float theta) { float retval; retval = cos(theta); return retval; } float Q_tan (float theta) { float retval; retval = (Q_sin(theta) / Q_cos(theta)); return retval; } float Q_atan2 (float y, float x) { float retval; retval = atan2(y, x); return retval; } float Q_atan (float x) { return atan2(x, 1.0); } float Q_asin (float x) { float retval; retval = Q_atan2(x, sqrt(1 - (x * x))); return retval; } /* Derivation of arccosine/inverse-cosine, by PhaethonH: /| h / | / | o / | T --------+ a (1) x = cos(T) (2) sin(T) = o/h (3) cos(T) = a/h (4) tan(T) = o/a (5) (sin(T))^2 + (cos(T))^2 = 1 (6) tan(T) = sin(T) / cos(T) Equation (1) tells us we know what the value of cos(T) is, but not of sin(T). From (5); getting sin(T) in terms of cos(T): (sin(T))^2 + (cos(T))^2 = 1 (sin(T))^2 = 1 - (cos(T))^2 (7) sin(T) = sqrt(1 - (cos(T))^2) Taking (6): tan(T) = sin(T) / cos(T) Applying (7); substituting sin(T): tan(T) = (sqrt(1 - (cos(T))^2)) / cos(T) Apply atan; isolating T: (8) T = atan(sqrt(1 - (cos(T))^2)) / cos(T)) Apply (1); substituting cos(T): (9) T = atan(sqrt(1 - (x * x)) / x) Similar process for obtaining asin. */ float Q_acos (float x) { float retval; retval = Q_atan2(sqrt(1 - (x * x)), x); return retval; } float Q_sqrt (float x) { float retval; retval = sqrt(x); return retval; } float Q_hypot (float a, float b) { float retval; retval = Q_sqrt(a*a + b*b); return retval; } float Q_rint (float x) { float retval; //crumb("rint: start %f\n", x); retval = (float)(Q_round(x)); /* Raise inexact exception how? */ //crumb("rint: done %f\n", x); return retval; } /* Following added to support Ogg Vorbis. */ double atan (double x) { double retval; retval = Q_atan(x); return retval; } double log (double x) { double retval; retval = Q_log(x); return retval; } float hypot (float a, float b) { return (sqrt(a*a + b*b)); } double rint (double x) { double retval; //crumb("_rint: start %f\n", x); retval = Q_rint(x); //crumb("_rint: done %f\n", retval); return retval; } long int labs (long int x) { return abs(x); } double ldexp (double x, int y) { double retval; double z; /* x * (2 ^ y) */ //crumb("ldexp: start %f * 2 ^ %d\n", x, y); z = pow(2.0, (float)y); //crumb("ldexp: z = %f\n", z); retval = x * z; //crumb("ldexp: retval = %f\n", retval); return retval; }