photoprism/pkg/vector/vector.go

215 lines
4.7 KiB
Go

/*
Package vector provides floating-point vector types and math, including
distances, norms, means, and correlation.
Copyright (c) 2018 - 2026 PhotoPrism UG. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
<https://docs.photoprism.app/license/agpl>
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
The AGPL is supplemented by our Trademark and Brand Guidelines,
which describe how our Brand Assets may be used:
<https://www.photoprism.app/trademark/>
Feel free to send an email to hello@photoprism.app if you have questions,
want to support our work, or just want to say hello.
Additional information can be found in our Developer Guide:
<https://docs.photoprism.app/developer-guide/>
*/
package vector
import (
"fmt"
)
// Vector represents a set of floating-point values.
type Vector []float64
// Vectors represents a set of vectors.
type Vectors = []Vector
// NewVector creates a new vector from the given values.
func NewVector(values any) (Vector, error) {
switch v := values.(type) {
case []uint8:
return uint8ToVector(v), nil
case []uint16:
return uint16ToVector(v), nil
case []uint32:
return uint32ToVector(v), nil
case []uint64:
return uint64ToVector(v), nil
case []int:
return intToVector(v), nil
case []int8:
return int8ToVector(v), nil
case []int16:
return int16ToVector(v), nil
case []int32:
return int32ToVector(v), nil
case []int64:
return int64ToVector(v), nil
case []float32:
return float32ToVector(v), nil
case []float64:
return float64ToVector(v), nil
case Vector:
return v.Copy(), nil
default:
return nil, fmt.Errorf("cannot create vector from type %T", values)
}
}
// NullVector creates a new null vector with the given dimension.
func NullVector(dim int) Vector {
return make(Vector, dim)
}
// Copy returns a copy of the vector.
func (v Vector) Copy() Vector {
y := make(Vector, len(v))
copy(y, v)
return y
}
// Dim returns the number of values (dimension).
func (v Vector) Dim() int {
return len(v)
}
// Sum returns the sum of the vector values.
func (v Vector) Sum() float64 {
s := 0.0
for _, f := range v {
s += f
}
return s
}
// uint8ToVector creates a new vector from a uint8 slice.
func uint8ToVector(values []uint8) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// uint16ToVector creates a new vector from a uint16 slice.
func uint16ToVector(values []uint16) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// uint32ToVector creates a new vector from a uint32 slice.
func uint32ToVector(values []uint32) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// uint64ToVector creates a new vector from a uint64 slice.
func uint64ToVector(values []uint64) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// intToVector creates a new vector from a int slice.
func intToVector(values []int) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// int8ToVector creates a new vector from a int8 slice.
func int8ToVector(values []int8) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// int16ToVector creates a new vector from a int16 slice.
func int16ToVector(values []int16) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// int32ToVector creates a new vector from a int32 slice.
func int32ToVector(values []int32) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// int64ToVector creates a new vector from a int64 slice.
func int64ToVector(values []int64) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// float32ToVector creates a new vector from a float32 slice.
func float32ToVector(values []float32) Vector {
v := make(Vector, len(values))
for i := range values {
v[i] = float64(values[i])
}
return v
}
// float64ToVector creates a new vector from a float64 slice.
// The values are copied so the result is independent of the input slice,
// consistent with the other type-specific converters.
func float64ToVector(values []float64) Vector {
v := make(Vector, len(values))
copy(v, values)
return v
}