1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "fmt"
14 "math"
15 )
16
17 type Numeric interface {
18 ~int | ~int8 | ~int16 | ~int32 | ~int64 |
19 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
20 ~float32 | ~float64 |
21 ~complex64 | ~complex128
22 }
23
24
25 type numericAbs[T Numeric] interface {
26 ~struct{ Value_ T }
27 Abs() T
28 Value() T
29 }
30
31
32
33 func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
34 d := a.Value() - b.Value()
35 dt := U{Value_: d}
36 return dt.Abs()
37 }
38
39
40 type orderedNumeric interface {
41 ~int | ~int8 | ~int16 | ~int32 | ~int64 |
42 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
43 ~float32 | ~float64
44 }
45
46
47 type Complex interface {
48 ~complex64 | ~complex128
49 }
50
51
52
53 type orderedAbs[T orderedNumeric] struct {
54 Value_ T
55 }
56
57 func (a orderedAbs[T]) Abs() T {
58 if a.Value_ < 0 {
59 return -a.Value_
60 }
61 return a.Value_
62 }
63
64
65
66
67
68
69 func (a orderedAbs[T]) Value() T {
70 return a.Value_
71 }
72
73
74
75 type complexAbs[T Complex] struct {
76 Value_ T
77 }
78
79 func realimag(x any) (re, im float64) {
80 switch z := x.(type) {
81 case complex64:
82 re = float64(real(z))
83 im = float64(imag(z))
84 case complex128:
85 re = real(z)
86 im = imag(z)
87 default:
88 panic("unknown complex type")
89 }
90 return
91 }
92
93 func (a complexAbs[T]) Abs() T {
94
95 r, i := realimag(a.Value_)
96
97
98 d := math.Sqrt(r*r + i*i)
99 return T(complex(d, 0))
100 }
101
102 func (a complexAbs[T]) Value() T {
103 return a.Value_
104 }
105
106
107
108 func OrderedAbsDifference[T orderedNumeric](a, b T) T {
109 return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
110 }
111
112
113
114 func ComplexAbsDifference[T Complex](a, b T) T {
115 return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
116 }
117
118 func main() {
119 if got, want := OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
120 panic(fmt.Sprintf("got = %v, want = %v", got, want))
121 }
122 if got, want := OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
123 panic(fmt.Sprintf("got = %v, want = %v", got, want))
124 }
125 if got, want := OrderedAbsDifference(-20, 15), 35; got != want {
126 panic(fmt.Sprintf("got = %v, want = %v", got, want))
127 }
128
129 if got, want := ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
130 panic(fmt.Sprintf("got = %v, want = %v", got, want))
131 }
132 if got, want := ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
133 panic(fmt.Sprintf("got = %v, want = %v", got, want))
134 }
135 }
136
View as plain text