60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|||
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
|
||
|
|
package linalg
|
||
|
|
|
||
|
|
import (
|
||
|
|
"math"
|
||
|
|
"math/cmplx"
|
||
|
|
|
||
|
|
"sourcedock.dev/petrbalvin/tensor/internal/base"
|
||
|
|
"sourcedock.dev/petrbalvin/tensor/internal/core"
|
||
|
|
)
|
||
|
|
|
||
|
|
// scalar is the element type the generic kernels serve.
|
||
|
|
type scalar interface {
|
||
|
|
float64 | complex128
|
||
|
|
}
|
||
|
|
|
||
|
|
// absComplex returns |z|, the shared magnitude used for tolerances.
|
||
|
|
func absComplex(z complex128) float64 { return base.AbsComplex(z) }
|
||
|
|
|
||
|
|
func absOf[T scalar](v T) float64 {
|
||
|
|
switch x := any(v).(type) {
|
||
|
|
case float64:
|
||
|
|
return math.Abs(x)
|
||
|
|
case complex128:
|
||
|
|
return cmplx.Abs(x)
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// zeros allocates a zeroed array for internally derived shapes. The
|
||
|
|
// error is part of the signature on purpose: a caller whose shape is
|
||
|
|
// not provably valid must propagate the failure, not nil-deref.
|
||
|
|
func zeros(dt core.Dtype, shape []int) (*core.Array, error) {
|
||
|
|
return core.Zeros(dt, shape...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// finiteF64 reports whether v is neither NaN nor infinite.
|
||
|
|
func finiteF64(v float64) bool { return !math.IsNaN(v) && !math.IsInf(v, 0) }
|
||
|
|
|
||
|
|
// vecFinite reports whether every entry of v is finite.
|
||
|
|
func vecFinite(v []float64) bool {
|
||
|
|
for _, x := range v {
|
||
|
|
if !finiteF64(x) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
// isRealDtype reports whether a holds real (non-complex) numeric data.
|
||
|
|
func isRealDtype(a *core.Array) bool {
|
||
|
|
switch a.Dtype() {
|
||
|
|
case core.Float, core.Float32, core.Int:
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|