Implement rough versions of mod, remainder, copy_sign
This commit is contained in:
parent
2f413e88dd
commit
c6d3f17e27
117
gb_math.h
117
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<<n;
|
||||
}
|
||||
if (iy >= -126) {
|
||||
hy = 0x00800000|(0x007fffff&hy);
|
||||
} else { /* NOTE(bill): Subnormal y, shift y to normal */
|
||||
n = -126-iy;
|
||||
hy = hy<<n;
|
||||
}
|
||||
|
||||
/* NOTE(bill): Fix point fmod */
|
||||
n = ix - iy;
|
||||
while(n--) {
|
||||
hz= hx-hy;
|
||||
if (hz < 0) {
|
||||
hx = hx+hx;
|
||||
} else {
|
||||
if (hz == 0) /* NOTE(bill): Return gb_sign(x)*0 */
|
||||
return gb__zero[(unsigned int)sx>>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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue