mirror of
https://github.com/photoprism/photoprism.git
synced 2026-07-17 16:49:04 +00:00
Split the catch-all values.go into one file per concept, each mirrored by its test: distance.go, norm.go, stats.go, product.go, centroid.go, plus the mean methods folded into mean.go and Copy/Dim/Sum into vector.go. Remove values.go, values_test.go, and values_more_test.go so functionality and tests live where developers expect them. Hoist the two 512-dimensional face embeddings shared by the distance, norm, and cosine tests into fixtures_test.go, removing the previous triplication, and decompose the monolithic TestVector into per-concept tests. Close pre-existing coverage gaps in the integer converters and the GeometricMean/HarmonicMean method wrappers, bringing the package to 100% statement coverage. Pure code movement; no behavior change.
215 lines
4.7 KiB
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
|
|
}
|