gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }