1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package linalg
6
7 import "math"
8
9 // Numeric is type bound that matches any numeric type.
10 // It would likely be in a constraints package in the standard library.
11 type Numeric interface {
12 ~int | ~int8 | ~int16 | ~int32 | ~int64 |
13 uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
14 float32 | ~float64 |
15 complex64 | ~complex128
16 }
17
18 func DotProduct[T Numeric](s1, s2 []T) T {
19 if len(s1) != len(s2) {
20 panic("DotProduct: slices of unequal length")
21 }
22 var r T
23 for i := range s1 {
24 r += s1[i] * s2[i]
25 }
26 return r
27 }
28
29 // NumericAbs matches numeric types with an Abs method.
30 type NumericAbs[T any] interface {
31 Numeric
32
33 Abs() T
34 }
35
36 // AbsDifference computes the absolute value of the difference of
37 // a and b, where the absolute value is determined by the Abs method.
38 func AbsDifference[T NumericAbs[T]](a, b T) T {
39 d := a - b
40 return d.Abs()
41 }
42
43 // OrderedNumeric is a type bound that matches numeric types that support the < operator.
44 type OrderedNumeric interface {
45 ~int | ~int8 | ~int16 | ~int32 | ~int64 |
46 uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
47 float32 | ~float64
48 }
49
50 // Complex is a type bound that matches the two complex types, which do not have a < operator.
51 type Complex interface {
52 ~complex64 | ~complex128
53 }
54
55 // OrderedAbs is a helper type that defines an Abs method for
56 // ordered numeric types.
57 type OrderedAbs[T OrderedNumeric] T
58
59 func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
60 if a < 0 {
61 return -a
62 }
63 return a
64 }
65
66 // ComplexAbs is a helper type that defines an Abs method for
67 // complex types.
68 type ComplexAbs[T Complex] T
69
70 func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
71 r := float64(real(a))
72 i := float64(imag(a))
73 d := math.Sqrt(r * r + i * i)
74 return ComplexAbs[T](complex(d, 0))
75 }
76
77 func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
78 return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
79 }
80
81 func ComplexAbsDifference[T Complex](a, b T) T {
82 return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
83 }
84
View as plain text