|  | // 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 { | 
|  | return remainder(x, y) | 
|  | } | 
|  |  | 
|  | 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 | 
|  | } |