summaryrefslogtreecommitdiffstats
path: root/test/typeparam/absdiffimp2.dir/a.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/typeparam/absdiffimp2.dir/a.go')
-rw-r--r--test/typeparam/absdiffimp2.dir/a.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/test/typeparam/absdiffimp2.dir/a.go b/test/typeparam/absdiffimp2.dir/a.go
new file mode 100644
index 0000000..dc64f2d
--- /dev/null
+++ b/test/typeparam/absdiffimp2.dir/a.go
@@ -0,0 +1,110 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import (
+ "math"
+)
+
+type Numeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64 |
+ ~complex64 | ~complex128
+}
+
+// numericAbs matches a struct containing a numeric type that has an Abs method.
+type numericAbs[T Numeric] interface {
+ ~struct{ Value_ T }
+ Abs() T
+ Value() T
+}
+
+// absDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
+ d := a.Value() - b.Value()
+ dt := U{Value_: d}
+ return dt.Abs()
+}
+
+// orderedNumeric matches numeric types that support the < operator.
+type orderedNumeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+ ~complex64 | ~complex128
+}
+
+// orderedAbs is a helper type that defines an Abs method for
+// a struct containing an ordered numeric type.
+type orderedAbs[T orderedNumeric] struct {
+ Value_ T
+}
+
+func (a orderedAbs[T]) Abs() T {
+ if a.Value_ < 0 {
+ return -a.Value_
+ }
+ return a.Value_
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (a orderedAbs[T]) Value() T {
+ return a.Value_
+}
+
+// complexAbs is a helper type that defines an Abs method for
+// a struct containing a complex type.
+type complexAbs[T Complex] struct {
+ Value_ T
+}
+
+func realimag(x any) (re, im float64) {
+ switch z := x.(type) {
+ case complex64:
+ re = float64(real(z))
+ im = float64(imag(z))
+ case complex128:
+ re = real(z)
+ im = imag(z)
+ default:
+ panic("unknown complex type")
+ }
+ return
+}
+
+func (a complexAbs[T]) Abs() T {
+ // TODO use direct conversion instead of realimag once #50937 is fixed
+ r, i := realimag(a.Value_)
+ // r := float64(real(a.Value))
+ // i := float64(imag(a.Value))
+ d := math.Sqrt(r*r + i*i)
+ return T(complex(d, 0))
+}
+
+func (a complexAbs[T]) Value() T {
+ return a.Value_
+}
+
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func OrderedAbsDifference[T orderedNumeric](a, b T) T {
+ return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+func ComplexAbsDifference[T Complex](a, b T) T {
+ return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
+}