github.com/evanw/esbuild@v0.21.4/internal/helpers/float.go (about) 1 package helpers 2 3 import "math" 4 5 // This wraps float64 math operations. Why does this exist? The Go compiler 6 // contains some optimizations to take advantage of "fused multiply and add" 7 // (FMA) instructions on certain processors. These instructions lead to 8 // different output on those processors, which means esbuild's output is no 9 // longer deterministic across all platforms. From the Go specification itself 10 // (https://go.dev/ref/spec#Floating_point_operators): 11 // 12 // An implementation may combine multiple floating-point operations into a 13 // single fused operation, possibly across statements, and produce a result 14 // that differs from the value obtained by executing and rounding the 15 // instructions individually. An explicit floating-point type conversion 16 // rounds to the precision of the target type, preventing fusion that would 17 // discard that rounding. 18 // 19 // For instance, some architectures provide a "fused multiply and add" (FMA) 20 // instruction that computes x*y + z without rounding the intermediate result 21 // x*y. 22 // 23 // Therefore we need to add explicit type conversions such as "float64(x)" to 24 // prevent optimizations that break correctness. Rather than adding them on a 25 // case-by-case basis as real correctness issues are discovered, we instead 26 // preemptively force them to be added everywhere by using this wrapper type 27 // for all floating-point math. 28 type F64 struct { 29 value float64 30 } 31 32 func NewF64(a float64) F64 { 33 return F64{value: float64(a)} 34 } 35 36 func (a F64) Value() float64 { 37 return a.value 38 } 39 40 func (a F64) IsNaN() bool { 41 return math.IsNaN(a.value) 42 } 43 44 func (a F64) Neg() F64 { 45 return NewF64(-a.value) 46 } 47 48 func (a F64) Abs() F64 { 49 return NewF64(math.Abs(a.value)) 50 } 51 52 func (a F64) Sin() F64 { 53 return NewF64(math.Sin(a.value)) 54 } 55 56 func (a F64) Cos() F64 { 57 return NewF64(math.Cos(a.value)) 58 } 59 60 func (a F64) Log2() F64 { 61 return NewF64(math.Log2(a.value)) 62 } 63 64 func (a F64) Round() F64 { 65 return NewF64(math.Round(a.value)) 66 } 67 68 func (a F64) Floor() F64 { 69 return NewF64(math.Floor(a.value)) 70 } 71 72 func (a F64) Ceil() F64 { 73 return NewF64(math.Ceil(a.value)) 74 } 75 76 func (a F64) Squared() F64 { 77 return a.Mul(a) 78 } 79 80 func (a F64) Cubed() F64 { 81 return a.Mul(a).Mul(a) 82 } 83 84 func (a F64) Sqrt() F64 { 85 return NewF64(math.Sqrt(a.value)) 86 } 87 88 func (a F64) Cbrt() F64 { 89 return NewF64(math.Cbrt(a.value)) 90 } 91 92 func (a F64) Add(b F64) F64 { 93 return NewF64(a.value + b.value) 94 } 95 96 func (a F64) AddConst(b float64) F64 { 97 return NewF64(a.value + b) 98 } 99 100 func (a F64) Sub(b F64) F64 { 101 return NewF64(a.value - b.value) 102 } 103 104 func (a F64) SubConst(b float64) F64 { 105 return NewF64(a.value - b) 106 } 107 108 func (a F64) Mul(b F64) F64 { 109 return NewF64(a.value * b.value) 110 } 111 112 func (a F64) MulConst(b float64) F64 { 113 return NewF64(a.value * b) 114 } 115 116 func (a F64) Div(b F64) F64 { 117 return NewF64(a.value / b.value) 118 } 119 120 func (a F64) DivConst(b float64) F64 { 121 return NewF64(a.value / b) 122 } 123 124 func (a F64) Pow(b F64) F64 { 125 return NewF64(math.Pow(a.value, b.value)) 126 } 127 128 func (a F64) PowConst(b float64) F64 { 129 return NewF64(math.Pow(a.value, b)) 130 } 131 132 func (a F64) Atan2(b F64) F64 { 133 return NewF64(math.Atan2(a.value, b.value)) 134 } 135 136 func (a F64) WithSignFrom(b F64) F64 { 137 return NewF64(math.Copysign(a.value, b.value)) 138 } 139 140 func Min2(a F64, b F64) F64 { 141 return NewF64(math.Min(a.value, b.value)) 142 } 143 144 func Max2(a F64, b F64) F64 { 145 return NewF64(math.Max(a.value, b.value)) 146 } 147 148 func Min3(a F64, b F64, c F64) F64 { 149 return NewF64(math.Min(math.Min(a.value, b.value), c.value)) 150 } 151 152 func Max3(a F64, b F64, c F64) F64 { 153 return NewF64(math.Max(math.Max(a.value, b.value), c.value)) 154 } 155 156 func Lerp(a F64, b F64, t F64) F64 { 157 return b.Sub(a).Mul(t).Add(a) 158 }