/
comparisons.go
134 lines (124 loc) · 5.06 KB
/
comparisons.go
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package float
// Eq returns true if the extended double-precision floating-point value `a' is
// equal to the corresponding value `b', and false otherwise. The comparison is
// performed according to the IEC/IEEE Standard for Binary Floating-Point
// Arithmetic.
func (a X80) Eq(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
if a.IsSignalingNaN() || b.IsSignalingNaN() {
Raise(ExceptionInvalid)
}
return false
}
return (a.low == b.low && a.high == b.high) ||
(a.low == 0 && (a.high|b.high)<<1 == 0)
}
// Gt returns true if the extended double-precision floating-point value `a' is greater
// than the corresponding value `b', and false otherwise.
func (a X80) Gt(b X80) bool {
return !a.Le(b)
}
// Le returns true if the extended double-precision floating-point value `a' is less than or
// equal to the corresponding value `b', and false otherwise.
func (a X80) Le(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
Raise(ExceptionInvalid)
return false
}
aSign, bSign := a.sign(), b.sign()
if aSign != bSign {
return aSign || ((a.high|b.high)<<1 != 0 || (a.low|b.low) == 0)
}
if aSign {
return le128(uint64(b.high), b.low, uint64(a.high), a.low)
}
return le128(uint64(a.high), a.low, uint64(b.high), b.low)
}
// Ge returns true if the extended double-precision floating-point value `a' is greater than or
// equal to the corresponding value `b', and false otherwise.
func (a X80) Ge(b X80) bool {
return !a.Lt(b)
}
// Lt returns true if the extended double-precision floating-point value `a' is
// less than the corresponding value `b', and false otherwise. The comparison
// is performed according to the IEC/IEEE Standard for Binary Floating-Point
// Arithmetic.
func (a X80) Lt(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
Raise(ExceptionInvalid)
return false
}
aSign, bSign := a.sign(), b.sign()
if aSign != bSign {
return aSign && ((a.high|b.high)<<1 != 0 || (a.low|b.low) != 0)
}
if aSign {
return lt128(uint64(b.high), b.low, uint64(a.high), a.low)
}
return lt128(uint64(a.high), a.low, uint64(b.high), b.low)
}
// EqSignaling returns true if the extended double-precision floating-point value `a' is equal
// to the corresponding value `b', and false otherwise. The invalid exception is
// raised if either operand is a NaN. Otherwise, the comparison is performed
// according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
func (a X80) EqSignaling(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
Raise(ExceptionInvalid)
return false
}
return a.low == b.low && (a.high == b.high || (a.low == 0 && (a.high|b.high)<<1 == 0))
}
// GtQuiet returns true if the extended double-precision floating-point value `a' is
// greater than the corresponding value `b', and false otherwise. Quiet NaNs
// do not cause an exception. Otherwise, the comparison is performed according
// to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
func (a X80) GtQuiet(b X80) bool {
return !a.LeQuiet(b)
}
// LeQuiet returns true if the extended double-precision floating-point value `a' is less
// than or equal to the corresponding value `b', and false otherwise. Quiet NaNs
// do not cause an exception. Otherwise, the comparison is performed according
// to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
func (a X80) LeQuiet(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
if a.IsSignalingNaN() || b.IsSignalingNaN() {
Raise(ExceptionInvalid)
}
return false
}
aSign, bSign := a.sign(), b.sign()
if aSign != bSign {
return aSign || (((a.high|b.high)<<1 != 0) || (a.low|b.low) == 0)
}
if aSign {
return le128(uint64(b.high), b.low, uint64(a.high), a.low)
}
return le128(uint64(a.high), a.low, uint64(b.high), b.low)
}
// GeQuiet returns true if the extended double-precision floating-point value `a' is greater
// than or equal to the corresponding value `b', and false otherwise. Quiet NaNs
// do not cause an exception. Otherwise, the comparison is performed according
// to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
func (a X80) GeQuiet(b X80) bool {
return !a.LtQuiet(b)
}
// LtQuiet returns true if the extended double-precision floating-point value `a' is less
// than the corresponding value `b', and false otherwise. Quiet NaNs do not cause
// an exception. Otherwise, the comparison is performed according to the
// IEC/IEEE Standard for Binary Floating-Point Arithmetic.
func (a X80) LtQuiet(b X80) bool {
if (a.exp() == 0x7FFF && a.frac()<<1 != 0) || (b.exp() == 0x7FFF && b.frac()<<1 != 0) {
if a.IsSignalingNaN() || b.IsSignalingNaN() {
Raise(ExceptionInvalid)
}
return false
}
aSign, bSign := a.sign(), b.sign()
if aSign != bSign {
return aSign && (((a.high|b.high)<<1 != 0) || (a.low|b.low) != 0)
}
if aSign {
return lt128(uint64(b.high), b.low, uint64(a.high), a.low)
}
return lt128(uint64(a.high), a.low, uint64(b.high), b.low)
}