github.com/kaydxh/golang@v0.0.131/pkg/gocv/vector/vector.go (about)

     1  /*
     2   *Copyright (c) 2023, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package vector
    23  
    24  import (
    25  	"bytes"
    26  	"encoding/binary"
    27  	"fmt"
    28  	"math"
    29  
    30  	rand_ "github.com/kaydxh/golang/go/math/rand"
    31  	"golang.org/x/exp/constraints"
    32  )
    33  
    34  type Vector[T constraints.Integer | constraints.Float] struct {
    35  	data []T
    36  }
    37  
    38  func NewVector[T constraints.Integer | constraints.Float](data ...T) *Vector[T] {
    39  	v := &Vector[T]{
    40  		data: make([]T, 0),
    41  	}
    42  	if len(data) > 0 {
    43  		v.data = data
    44  	}
    45  	return v
    46  }
    47  
    48  func (v *Vector[T]) Append(t T) {
    49  	v.data = append(v.data, t)
    50  }
    51  
    52  func (v *Vector[T]) Norm() {
    53  	var sum T
    54  	for _, data := range v.data {
    55  		sum += data * data
    56  	}
    57  	magnitude := math.Sqrt(float64(sum))
    58  
    59  	for i, value := range v.data {
    60  		v.data[i] = T(float64(value) / magnitude)
    61  	}
    62  }
    63  func (v *Vector[T]) Assign(data []byte) error {
    64  	buf := bytes.NewReader(data)
    65  	err := binary.Read(buf, binary.LittleEndian, v.data)
    66  	return err
    67  }
    68  
    69  func (v *Vector[T]) Dims() int {
    70  	return len(v.data)
    71  }
    72  
    73  func (v *Vector[T]) Len() int {
    74  	return len(v.data)
    75  }
    76  
    77  func (v *Vector[T]) Data() []T {
    78  	return v.data
    79  }
    80  
    81  func (v Vector[T]) Bytes() ([]byte, error) {
    82  	buf := new(bytes.Buffer)
    83  	err := binary.Write(buf, binary.LittleEndian, v.data)
    84  	return buf.Bytes(), err
    85  }
    86  
    87  func (v Vector[T]) String() (string, error) {
    88  	var err error
    89  	buf := bytes.NewBuffer([]byte{'['})
    90  	for i, value := range v.data {
    91  		if i < len(v.data)-1 {
    92  			_, err = buf.WriteString(fmt.Sprintf("%v,", value))
    93  		} else {
    94  			_, err = buf.WriteString(fmt.Sprintf("%v", value))
    95  		}
    96  		if err != nil {
    97  			return "", err
    98  		}
    99  	}
   100  	_, err = buf.Write([]byte{']'})
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  	return buf.String(), nil
   105  }
   106  
   107  func (v Vector[T]) CosineDistance(r *Vector[T]) float64 {
   108  	if v.Len() != r.Len() {
   109  		return 0
   110  	}
   111  
   112  	var (
   113  		sum   float64
   114  		normL float64
   115  		normR float64
   116  	)
   117  	for i := 0; i < v.Len(); i++ {
   118  		sum += float64(v.Data()[i] * r.Data()[i])
   119  		normL += float64(v.Data()[i] * v.Data()[i])
   120  		normR += float64(r.Data()[i] * r.Data()[i])
   121  	}
   122  
   123  	return sum / (math.Sqrt(normL) * math.Sqrt(normR))
   124  }
   125  
   126  func (v Vector[T]) EuclideanDistance(r *Vector[T]) float64 {
   127  	if v.Len() != r.Len() {
   128  		return 0
   129  	}
   130  
   131  	var sum float64
   132  	for i := 0; i < v.Len(); i++ {
   133  		sum += math.Pow(float64(v.Data()[i]-r.Data()[i]), 2)
   134  	}
   135  
   136  	return math.Sqrt(sum)
   137  }
   138  
   139  func CreateNormalizedVector[T constraints.Integer | constraints.Float](dim int) []T {
   140  	var ve Vector[T]
   141  	for i := 0; i < dim; i++ {
   142  		ve.Append(T(rand_.Float64()))
   143  	}
   144  	ve.Norm()
   145  
   146  	return ve.Data()
   147  }
   148  
   149  func CosineDistance[T constraints.Integer | constraints.Float](l, r []T) float64 {
   150  	v1 := NewVector(l...)
   151  	v2 := NewVector(r...)
   152  	return v1.CosineDistance(v2)
   153  }
   154  
   155  func EuclideanDistance[T constraints.Integer | constraints.Float](l, r []T) float64 {
   156  	v1 := NewVector(l...)
   157  	v2 := NewVector(r...)
   158  	return v1.EuclideanDistance(v2)
   159  }