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  }