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
     3  // license that can be found in the LICENSE file.
     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