# Source file test/typeparam/absdiffimp2.dir/a.go

```     1  // Copyright 2022 The Go Authors. All rights reserved.
2  // Use of this source code is governed by a BSD-style
4
5  package a
6
7  import (
8  	"math"
9  )
10
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  // numericAbs matches a struct containing a numeric type that has an Abs method.
19  type numericAbs[T Numeric] interface {
20  	~struct{ Value_ T }
21  	Abs() T
22  	Value() T
23  }
24
25  // absDifference computes the absolute value of the difference of
26  // a and b, where the absolute value is determined by the Abs method.
27  func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
28  	d := a.Value() - b.Value()
29  	dt := U{Value_: d}
30  	return dt.Abs()
31  }
32
33  // orderedNumeric matches numeric types that support the < operator.
34  type orderedNumeric interface {
35  	~int | ~int8 | ~int16 | ~int32 | ~int64 |
36  		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
37  		~float32 | ~float64
38  }
39
40  // Complex matches the two complex types, which do not have a < operator.
41  type Complex interface {
42  	~complex64 | ~complex128
43  }
44
45  // orderedAbs is a helper type that defines an Abs method for
46  // a struct containing an ordered numeric type.
47  type orderedAbs[T orderedNumeric] struct {
48  	Value_ T
49  }
50
51  func (a orderedAbs[T]) Abs() T {
52  	if a.Value_ < 0 {
53  		return -a.Value_
54  	}
55  	return a.Value_
56  }
57
58  // Field accesses through type parameters are disabled
59  // until we have a more thorough understanding of the
60  // implications on the spec. See issue #51576.
61  // Use accessor method instead.
62
63  func (a orderedAbs[T]) Value() T {
64  	return a.Value_
65  }
66
67  // complexAbs is a helper type that defines an Abs method for
68  // a struct containing a complex type.
69  type complexAbs[T Complex] struct {
70  	Value_ T
71  }
72
73  func realimag(x any) (re, im float64) {
74  	switch z := x.(type) {
75  	case complex64:
76  		re = float64(real(z))
77  		im = float64(imag(z))
78  	case complex128:
79  		re = real(z)
80  		im = imag(z)
81  	default:
82  		panic("unknown complex type")
83  	}
84  	return
85  }
86
87  func (a complexAbs[T]) Abs() T {
88  	// TODO use direct conversion instead of realimag once #50937 is fixed
89  	r, i := realimag(a.Value_)
90  	// r := float64(real(a.Value))
91  	// i := float64(imag(a.Value))
92  	d := math.Sqrt(r*r + i*i)
93  	return T(complex(d, 0))
94  }
95
96  func (a complexAbs[T]) Value() T {
97  	return a.Value_
98  }
99
100  // OrderedAbsDifference returns the absolute value of the difference
101  // between a and b, where a and b are of an ordered type.
102  func OrderedAbsDifference[T orderedNumeric](a, b T) T {
103  	return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
104  }
105
106  // ComplexAbsDifference returns the absolute value of the difference
107  // between a and b, where a and b are of a complex type.
108  func ComplexAbsDifference[T Complex](a, b T) T {
109  	return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
110  }
111
```

View as plain text