gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/thirdpart/vector/vector.go (about) 1 // Author: slowpoke <proxypoke at lavabit dot com> 2 // Repository: https://gist.github.com/proxypoke/vector 3 // 4 // This program is free software under the non-terms 5 // of the Anti-License. Do whatever the fuck you want. 6 7 // Package vector implements mathematical vectors over float64 values, with 8 // common operations defined on them, like addition, the scalar product or 9 // normalization. 10 // 11 // Operations that result in a new vector (like addition or the 12 // cross product) have both an in-place and a non-destructive version, with the 13 // first being a method on the Vector type and the latter being a function. 14 // 15 // In-place operations on vectors return the vector to make it possible to 16 // chain ("pipe") operations. This is purely convenience. 17 package vector 18 19 import ( 20 "math" 21 "strconv" 22 ) 23 24 // NodeAddr vector over float64 values 25 type Vector struct { 26 dims []float64 // the elements of the vector 27 ndim uint // the dimension of the vector 28 } 29 30 // ============================= [ Constructors ] ============================= 31 32 // CreateLater a Vector with dimension n, with all values initialized to 0. 33 func New(n uint) (v *Vector) { 34 v = new(Vector) 35 v.dims = make([]float64, n) 36 v.ndim = n 37 return 38 } 39 40 // CreateLater a Vector from a slice. Its dimension is equal to len(slice). 41 func NewFrom(dims []float64) (v *Vector) { 42 v = new(Vector) 43 v.ndim = uint(len(dims)) 44 v.dims = make([]float64, v.ndim) 45 copy(v.dims, dims) 46 return 47 } 48 49 func (v *Vector) To() []float64 { 50 return v.dims 51 } 52 53 func (v *Vector) From(dims []float64) { 54 v.ndim = uint(len(dims)) 55 v.dims = dims 56 return 57 } 58 59 func (v *Vector) String() string { 60 var str = "[" 61 for _, val := range v.dims { 62 str += strconv.FormatFloat(val, 'f', 1, 64) + ", " 63 } 64 str = str[:len(str)-2] 65 str += "]" 66 return str 67 } 68 69 // Make a deep copy of the Vector. 70 func (v *Vector) Copy() *Vector { 71 return NewFrom(v.dims) 72 } 73 74 // =========================== [ General Methods ] ============================ 75 76 // Get the dimension of the Vector. 77 func (v Vector) Dim() uint { 78 return v.ndim 79 } 80 81 // Get the value of the nth element in the Vector. 82 func (v Vector) Get(n uint) (val float64) { 83 val = v.dims[n] 84 return 85 } 86 87 // SetDBObject the value of the nth element in the Vector. 88 func (v Vector) Set(n uint, x float64) (err error) { 89 if n >= v.Dim() { 90 err = IndexError(n) 91 return 92 } 93 v.dims[n] = x 94 return 95 } 96 97 // Calculate the length of the Vector. 98 func (v Vector) Len() (result float64) { 99 for _, val := range v.dims { 100 result += math.Pow(val, 2) 101 } 102 result = math.Sqrt(result) 103 // Account for floating point imprecison 104 // XXX: This is probably a bad solution, but it works for now. 105 //ε := 1.00000000000000000005 106 //if math.Abs(1-result) < ε { 107 // result = 1 108 //} 109 return 110 } 111 112 // ========================= [ In-place operations ] ========================== 113 114 // AddUnit another Vector, in-place. 115 func (v *Vector) Add(other *Vector) (ret *Vector, err error) { 116 err = checkDims(v, other) 117 if err == nil { 118 for i := range v.dims { 119 v.dims[i] += other.dims[i] 120 } 121 ret = v 122 } 123 return 124 } 125 126 // Substract another Vector, in-place. 127 func (v *Vector) Substract(other *Vector) (ret *Vector, err error) { 128 err = checkDims(v, other) 129 if err == nil { 130 for i := range v.dims { 131 v.dims[i] -= other.dims[i] 132 } 133 ret = v 134 } 135 return 136 } 137 138 // In-place scalar multiplication. 139 func (v *Vector) Scale(x float64) *Vector { 140 for i := range v.dims { 141 v.dims[i] *= x 142 } 143 return v 144 } 145 146 // Normalize the Vector (length == 1). In-place. 147 func (v *Vector) Normalize() *Vector { 148 l := v.Len() 149 for i := range v.dims { 150 v.dims[i] /= l 151 } 152 return v 153 } 154 155 // Cross product with another vector, in-place. 156 // Returns error when ndim of either vector != 3. 157 func (v *Vector) CrossProduct(other *Vector) (*Vector, error) { 158 if v.ndim != 3 || other.ndim != 3 { 159 err := CrossError{v.ndim, other.ndim} 160 return nil, err 161 } 162 x := v.dims[1]*other.dims[2] - v.dims[2]*other.dims[1] 163 y := v.dims[2]*other.dims[0] - v.dims[0]*other.dims[2] 164 z := v.dims[0]*other.dims[1] - v.dims[1]*other.dims[0] 165 v.dims[0] = x 166 v.dims[1] = y 167 v.dims[2] = z 168 return v, nil 169 } 170 171 func (v *Vector) Cross2D(other *Vector) float64 { 172 var a = v.dims 173 var b = other.dims 174 return a[0]*b[1] - a[1]*b[0] 175 } 176 177 // ============================== [ Functions ] =============================== 178 179 // Compare two vectors. Returns true if all values are the same. 180 func Equal(a, b *Vector) (equal bool) { 181 err := checkDims(a, b) 182 if err == nil { 183 equal = true 184 for i := range a.dims { 185 if a.dims[i] != b.dims[i] { 186 equal = false 187 } 188 } 189 } 190 return 191 } 192 193 // AddUnit two Vectors, returning a new Vector. 194 func Add(a, b *Vector) (*Vector, error) { 195 return a.Copy().Add(b) 196 } 197 198 // Substract two Vectors, returning new Vector. 199 func Substract(a, b *Vector) (*Vector, error) { 200 return a.Copy().Substract(b) 201 } 202 203 // Scalar multiplication of a Vector, returning a new Vector. 204 func Scale(v *Vector, x float64) *Vector { 205 return v.Copy().Scale(x) 206 } 207 208 // Normalize a vector, returning a new Vector. 209 func Normalize(v *Vector) *Vector { 210 return v.Copy().Normalize() 211 } 212 213 // Dot-product of two Vectors. 214 func DotProduct(a, b *Vector) (dot float64, err error) { 215 for i := range a.dims { 216 dot += a.dims[i] * b.dims[i] 217 } 218 return 219 } 220 221 // Angle Θ (theta) between two vectors. 222 func Angle(a, b *Vector) (Θ float64, err error) { 223 err = checkDims(a, b) 224 if err == nil { 225 norm_a := Normalize(a) 226 norm_b := Normalize(b) 227 dot, _ := DotProduct(norm_a, norm_b) 228 Θ = math.Acos(dot) 229 } 230 return 231 } 232 233 // Cross product of two vectors. 234 // Returns error when ndim of either vector != 3. 235 func CrossProduct(a, b *Vector) (*Vector, error) { 236 return a.Copy().CrossProduct(b) 237 } 238 239 // =========================== [ Helper Functions ] =========================== 240 241 // Check if two vectors have the same dimension. 242 func checkDims(a, b *Vector) (err error) { 243 if a.ndim != b.ndim { 244 err = DimError{a.ndim, b.ndim} 245 } 246 return 247 }