| // Copyright 2010 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package math | |
| // 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 float64) float64 | |
| func remainder(x, y float64) float64 { | |
| const ( | |
| Tiny = 4.45014771701440276618e-308 // 0x0020000000000000 | |
| HalfMax = MaxFloat64 / 2 | |
| ) | |
| // special cases | |
| switch { | |
| case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0: | |
| return NaN() | |
| case IsInf(y, 0): | |
| return x | |
| } | |
| sign := false | |
| if x < 0 { | |
| x = -x | |
| sign = true | |
| } | |
| if y < 0 { | |
| y = -y | |
| } | |
| if x == y { | |
| return 0 | |
| } | |
| if y <= HalfMax { | |
| x = Mod(x, y+y) // now x < 2y | |
| } | |
| if y < Tiny { | |
| 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 | |
| } |