package adapter

import "fmt"

type projectionAdapter struct {
	sourceDim int
	targetDim int
	matrix    [][]float32
}

func (a *projectionAdapter) SourceDim() int { return a.sourceDim }
func (a *projectionAdapter) TargetDim() int { return a.targetDim }

func (a *projectionAdapter) Adapt(vec []float32) ([]float32, error) {
	if len(vec) != a.sourceDim {
		return nil, fmt.Errorf("projection adapt: %w: got %d, want %d", ErrDimMismatch, len(vec), a.sourceDim)
	}
	return L2Norm(matVecMul(a.matrix, vec)), nil
}

// matVecMul computes m·v where m is [rows][cols] and v has len cols.
func matVecMul(m [][]float32, v []float32) []float32 {
	out := make([]float32, len(m))
	for i, row := range m {
		var sum float32
		for j, val := range row {
			sum += val * v[j]
		}
		out[i] = sum
	}
	return out
}
