Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / math / remainder.go
blobbe8724c7f3ad13c46151f6acd0824cb3944d1563
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package math
7 // The original C code and the the comment below are from
8 // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
9 // with this notice. The go code is a simplified version of
10 // the original C.
12 // ====================================================
13 // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
15 // Developed at SunPro, a Sun Microsystems, Inc. business.
16 // Permission to use, copy, modify, and distribute this
17 // software is freely granted, provided that this notice
18 // is preserved.
19 // ====================================================
21 // __ieee754_remainder(x,y)
22 // Return :
23 // returns x REM y = x - [x/y]*y as if in infinite
24 // precision arithmetic, where [x/y] is the (infinite bit)
25 // integer nearest x/y (in half way cases, choose the even one).
26 // Method :
27 // Based on fmod() returning x - [x/y]chopped * y exactly.
29 // Remainder returns the IEEE 754 floating-point remainder of x/y.
31 // Special cases are:
32 // Remainder(x, NaN) = NaN
33 // Remainder(NaN, y) = NaN
34 // Remainder(Inf, y) = NaN
35 // Remainder(x, 0) = NaN
36 // Remainder(x, Inf) = x
37 func Remainder(x, y float64) float64 {
38 const (
39 Tiny = 4.45014771701440276618e-308 // 0x0020000000000000
40 HalfMax = MaxFloat64 / 2
42 // TODO(rsc): Remove manual inlining of IsNaN, IsInf
43 // when compiler does it for us
44 // special cases
45 switch {
46 case x != x || y != y || x < -MaxFloat64 || x > MaxFloat64 || y == 0: // IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0:
47 return NaN()
48 case y < -MaxFloat64 || y > MaxFloat64: // IsInf(y):
49 return x
51 sign := false
52 if x < 0 {
53 x = -x
54 sign = true
56 if y < 0 {
57 y = -y
59 if x == y {
60 return 0
62 if y <= HalfMax {
63 x = Fmod(x, y+y) // now x < 2y
65 if y < Tiny {
66 if x+x > y {
67 x -= y
68 if x+x >= y {
69 x -= y
72 } else {
73 yHalf := 0.5 * y
74 if x > yHalf {
75 x -= y
76 if x >= yHalf {
77 x -= y
81 if sign {
82 x = -x
84 return x