precisevector.go (5569B)
1 // Copyright 2016 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package r3 16 17 import ( 18 "fmt" 19 "math/big" 20 ) 21 22 const ( 23 // prec is the number of bits of precision to use for the Float values. 24 // To keep things simple, we use the maximum allowable precision on big 25 // values. This allows us to handle all values we expect in the s2 library. 26 prec = big.MaxPrec 27 ) 28 29 // define some commonly referenced values. 30 var ( 31 precise0 = precInt(0) 32 precise1 = precInt(1) 33 ) 34 35 // precStr wraps the conversion from a string into a big.Float. For results that 36 // actually can be represented exactly, this should only be used on values that 37 // are integer multiples of integer powers of 2. 38 func precStr(s string) *big.Float { 39 // Explicitly ignoring the bool return for this usage. 40 f, _ := new(big.Float).SetPrec(prec).SetString(s) 41 return f 42 } 43 44 func precInt(i int64) *big.Float { 45 return new(big.Float).SetPrec(prec).SetInt64(i) 46 } 47 48 func precFloat(f float64) *big.Float { 49 return new(big.Float).SetPrec(prec).SetFloat64(f) 50 } 51 52 func precAdd(a, b *big.Float) *big.Float { 53 return new(big.Float).SetPrec(prec).Add(a, b) 54 } 55 56 func precSub(a, b *big.Float) *big.Float { 57 return new(big.Float).SetPrec(prec).Sub(a, b) 58 } 59 60 func precMul(a, b *big.Float) *big.Float { 61 return new(big.Float).SetPrec(prec).Mul(a, b) 62 } 63 64 // PreciseVector represents a point in ℝ³ using high-precision values. 65 // Note that this is NOT a complete implementation because there are some 66 // operations that Vector supports that are not feasible with arbitrary precision 67 // math. (e.g., methods that need division like Normalize, or methods needing a 68 // square root operation such as Norm) 69 type PreciseVector struct { 70 X, Y, Z *big.Float 71 } 72 73 // PreciseVectorFromVector creates a high precision vector from the given Vector. 74 func PreciseVectorFromVector(v Vector) PreciseVector { 75 return NewPreciseVector(v.X, v.Y, v.Z) 76 } 77 78 // NewPreciseVector creates a high precision vector from the given floating point values. 79 func NewPreciseVector(x, y, z float64) PreciseVector { 80 return PreciseVector{ 81 X: precFloat(x), 82 Y: precFloat(y), 83 Z: precFloat(z), 84 } 85 } 86 87 // Vector returns this precise vector converted to a Vector. 88 func (v PreciseVector) Vector() Vector { 89 // The accuracy flag is ignored on these conversions back to float64. 90 x, _ := v.X.Float64() 91 y, _ := v.Y.Float64() 92 z, _ := v.Z.Float64() 93 return Vector{x, y, z}.Normalize() 94 } 95 96 // Equal reports whether v and ov are equal. 97 func (v PreciseVector) Equal(ov PreciseVector) bool { 98 return v.X.Cmp(ov.X) == 0 && v.Y.Cmp(ov.Y) == 0 && v.Z.Cmp(ov.Z) == 0 99 } 100 101 func (v PreciseVector) String() string { 102 return fmt.Sprintf("(%10g, %10g, %10g)", v.X, v.Y, v.Z) 103 } 104 105 // Norm2 returns the square of the norm. 106 func (v PreciseVector) Norm2() *big.Float { return v.Dot(v) } 107 108 // IsUnit reports whether this vector is of unit length. 109 func (v PreciseVector) IsUnit() bool { 110 return v.Norm2().Cmp(precise1) == 0 111 } 112 113 // Abs returns the vector with nonnegative components. 114 func (v PreciseVector) Abs() PreciseVector { 115 return PreciseVector{ 116 X: new(big.Float).Abs(v.X), 117 Y: new(big.Float).Abs(v.Y), 118 Z: new(big.Float).Abs(v.Z), 119 } 120 } 121 122 // Add returns the standard vector sum of v and ov. 123 func (v PreciseVector) Add(ov PreciseVector) PreciseVector { 124 return PreciseVector{ 125 X: precAdd(v.X, ov.X), 126 Y: precAdd(v.Y, ov.Y), 127 Z: precAdd(v.Z, ov.Z), 128 } 129 } 130 131 // Sub returns the standard vector difference of v and ov. 132 func (v PreciseVector) Sub(ov PreciseVector) PreciseVector { 133 return PreciseVector{ 134 X: precSub(v.X, ov.X), 135 Y: precSub(v.Y, ov.Y), 136 Z: precSub(v.Z, ov.Z), 137 } 138 } 139 140 // Mul returns the standard scalar product of v and f. 141 func (v PreciseVector) Mul(f *big.Float) PreciseVector { 142 return PreciseVector{ 143 X: precMul(v.X, f), 144 Y: precMul(v.Y, f), 145 Z: precMul(v.Z, f), 146 } 147 } 148 149 // MulByFloat64 returns the standard scalar product of v and f. 150 func (v PreciseVector) MulByFloat64(f float64) PreciseVector { 151 return v.Mul(precFloat(f)) 152 } 153 154 // Dot returns the standard dot product of v and ov. 155 func (v PreciseVector) Dot(ov PreciseVector) *big.Float { 156 return precAdd(precMul(v.X, ov.X), precAdd(precMul(v.Y, ov.Y), precMul(v.Z, ov.Z))) 157 } 158 159 // Cross returns the standard cross product of v and ov. 160 func (v PreciseVector) Cross(ov PreciseVector) PreciseVector { 161 return PreciseVector{ 162 X: precSub(precMul(v.Y, ov.Z), precMul(v.Z, ov.Y)), 163 Y: precSub(precMul(v.Z, ov.X), precMul(v.X, ov.Z)), 164 Z: precSub(precMul(v.X, ov.Y), precMul(v.Y, ov.X)), 165 } 166 } 167 168 // LargestComponent returns the axis that represents the largest component in this vector. 169 func (v PreciseVector) LargestComponent() Axis { 170 t := v.Abs() 171 172 if t.X.Cmp(t.Y) > 0 { 173 if t.X.Cmp(t.Z) > 0 { 174 return XAxis 175 } 176 return ZAxis 177 } 178 if t.Y.Cmp(t.Z) > 0 { 179 return YAxis 180 } 181 return ZAxis 182 } 183 184 // SmallestComponent returns the axis that represents the smallest component in this vector. 185 func (v PreciseVector) SmallestComponent() Axis { 186 t := v.Abs() 187 188 if t.X.Cmp(t.Y) < 0 { 189 if t.X.Cmp(t.Z) < 0 { 190 return XAxis 191 } 192 return ZAxis 193 } 194 if t.Y.Cmp(t.Z) < 0 { 195 return YAxis 196 } 197 return ZAxis 198 }