diff --git a/gb_math.h b/gb_math.h index c352644..41e17b8 100644 --- a/gb_math.h +++ b/gb_math.h @@ -1,9 +1,9 @@ -/* gb_math.h - v0.06 - public domain C math library - no warranty implied; use at your own risk */ -/* A C math library geared towards game development */ -/* use '#define GB_MATH_IMPLEMENTATION' before including to create the implementation in _ONE_ file */ +/* gb_math.h - v0.06a - public domain C math library - no warranty implied; use at your own risk + A C math library geared towards game development + use '#define GB_MATH_IMPLEMENTATION' before including to create the implementation in _ONE_ file -/* Version History: + 0.06a - Implement rough versions of mod, remainder, copy_sign 0.06 - Windows GCC Support and C90-ish Support 0.05 - Less/no dependencies or CRT 0.04d - License Update @@ -205,6 +205,8 @@ GB_MATH_DEF float gb_angle_diff(float radians_a, float radians_b); #define gb_max(a, b) ((a) > (b) ? (a) : (b)) #endif +GB_MATH_DEF float gb_copy_sign(float x, float y); +GB_MATH_DEF float gb_remainder(float x, float y); GB_MATH_DEF float gb_mod(float x, float y); GB_MATH_DEF float gb_sqrt(float a); GB_MATH_DEF float gb_rsqrt(float a); @@ -771,95 +773,32 @@ gb_angle_diff(float radians_a, float radians_b) return delta; } +float +gb_copy_sign(float x, float y) +{ + int ix, iy; + ix = *(int *)&x; + iy = *(int *)&y; + + ix &= 0x7fffffff; + ix |= iy & 0x80000000; + return *(float *)ix; +} + +float +gb_remainder(float x, float y) +{ + return x - (gb_round(x/y)*y); +} float gb_mod(float x, float y) { - static float const gb__zero[] = {0, -0}; - - int n, hx, hy, hz, ix, iy, sx, i; - - hx = *(int *)&x; - hy = *(int *)&y; - sx = hx & 0x80000000; - hx ^= sx; - hy &= 0x7fffffff; - - /* NOTE(bill): Purge off exception values */ - if (hy == 0||(hx >= 0x7f800000)|| /* NOTE(bill): Y=0,or x not finite */ - (hy > 0x7f800000)) /* NOTE(bill): Or y is NaN */ - return (x*y)/(x*y); - if (hx < hy) return x; /* NOTE(bill): |x|<|y| return x */ - if (hx == hy) return gb__zero[(unsigned int)sx>>31]; /* NOTE(bill): |x|=|y| return x*0 */ - - /* NOTE(bill): Determine ix = ilogb(x) */ - if (hx < 0x00800000) { /* NOTE(bill): Subnormal x */ - for (ix = -126, i = (hx<<8); i > 0; i <<= 1) - ix -=1; - } else { - ix = (hx>>23)-127; - } - - /* NOTE(bill): Determine iy = ilogb(y) */ - if (hy < 0x00800000) { /* NOTE(bill): Subnormal y */ - for (iy = -126, i = (hy<<8); i >= 0; i <<=1 ) - iy -=1; - } else { - iy = (hy>>23)-127; - } - - /* NOTE(bill): Set up {hx, lx}, {hy, ly} and align y to x */ - if (ix >= -126) { - hx = 0x00800000|(0x007fffff&hx); - } else { /* NOTE(bill): Subnormal x, shift x to normal */ - n = -126-ix; - hx = hx<= -126) { - hy = 0x00800000|(0x007fffff&hy); - } else { /* NOTE(bill): Subnormal y, shift y to normal */ - n = -126-iy; - hy = hy<>31]; - hx = hz+hz; - } - } - hz = hx-hy; - if (hz >= 0) - hx = hz; - - /* NOTE(bill): Convert back to floating value and restore the sign */ - if (hx == 0) /* NOTE(bill): Return sign(x)*0 */ - return gb__zero[(unsigned int)sx>>31]; - - while (hx < 0x00800000) { /* NOTE(bill): Normalize x */ - hx = hx+hx; - iy -= 1; - } - if (iy >= -126) { /* NOTE(bill): Normalize output */ - int t; - hx = ((hx-0x00800000) | ((iy + 127)<<23)); - t = hx | sx; - x = *(float *)&t; - } else { - int t; - n = -126 - iy; - hx >>= n; - t = hx | sx; - x = *(float *)&t; - x *= 1.0f; - } - return x; + float result; + y = gb_abs(y); + result = gb_remainder(gb_abs(x), (y = gb_abs(y))); + if (gb_sign(result)) result += y; + return gb_copy_sign(result, x); }