package math32 // The original C code and the comment below are from // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came // with this notice. The go code is a simplified version of // the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // __ieee754_remainder(x,y) // Return : // returns x REM y = x - [x/y]*y as if in infinite // precision arithmetic, where [x/y] is the (infinite bit) // integer nearest x/y (in half way cases, choose the even one). // Method : // Based on Mod() returning x - [x/y]chopped * y exactly. // Remainder returns the IEEE 754 floating-point remainder of x/y. // // Special cases are: // Remainder(±Inf, y) = NaN // Remainder(NaN, y) = NaN // Remainder(x, 0) = NaN // Remainder(x, ±Inf) = x // Remainder(x, NaN) = NaN func Remainder(x, y float32) float32 { if haveArchRemainder { return archRemainder(x, y) } return remainder(x, y) } func remainder(x, y float32) float32 { // special cases switch { case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0: return NaN() case IsInf(y, 0): return x } hx := Float32bits(x) hy := Float32bits(y) hy &= 0x7fffffff hx &= 0x7fffffff if hy <= 0x7effffff { x = Mod(x, y+y) // now x < 2y } if hx-hy == 0 { return 0 } sign := false if x < 0 { x = -x sign = true } if y < 0 { y = -y } if hy < 0x01000000 { if x+x > y { x -= y if x+x >= y { x -= y } } } else { yHalf := 0.5 * y if x > yHalf { x -= y if x >= yHalf { x -= y } } } if sign { x = -x } return x }