ronnie
2022-10-14 1504bb53e29d3d46222c0b3ea994fc494b48e153
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 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
}