mirror of
https://github.com/Warky-Devs/vecna.git
synced 2026-05-05 01:26:58 +00:00
46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
package adapter
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
type randomAdapter struct {
|
|
sourceDim int
|
|
targetDim int
|
|
matrix [][]float32
|
|
}
|
|
|
|
func newRandomAdapter(sourceDim, targetDim int, seed int64) *randomAdapter {
|
|
if seed == 0 {
|
|
seed = time.Now().UnixNano()
|
|
}
|
|
//nolint:gosec // deterministic seeded RNG for projection matrix generation, not security use
|
|
rng := rand.New(rand.NewSource(seed))
|
|
|
|
// Gaussian N(0, 1/targetDim) — preserves expected squared norms (Johnson-Lindenstrauss)
|
|
stddev := 1.0 / math.Sqrt(float64(targetDim))
|
|
matrix := make([][]float32, targetDim)
|
|
for i := range matrix {
|
|
row := make([]float32, sourceDim)
|
|
for j := range row {
|
|
row[j] = float32(rng.NormFloat64() * stddev)
|
|
}
|
|
matrix[i] = row
|
|
}
|
|
|
|
return &randomAdapter{sourceDim: sourceDim, targetDim: targetDim, matrix: matrix}
|
|
}
|
|
|
|
func (a *randomAdapter) SourceDim() int { return a.sourceDim }
|
|
func (a *randomAdapter) TargetDim() int { return a.targetDim }
|
|
|
|
func (a *randomAdapter) Adapt(vec []float32) ([]float32, error) {
|
|
if len(vec) != a.sourceDim {
|
|
return nil, fmt.Errorf("random adapt: %w: got %d, want %d", ErrDimMismatch, len(vec), a.sourceDim)
|
|
}
|
|
return L2Norm(matVecMul(a.matrix, vec)), nil
|
|
}
|