codekingpro/portable-devtools
114k
1// Copyright 2022 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5package a6 7import (8 "math"9)10 11type Numeric interface {12 ~int | ~int8 | ~int16 | ~int32 | ~int64 |13 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |14 ~float32 | ~float64 |15 ~complex64 | ~complex12816}17 18// numericAbs matches a struct containing a numeric type that has an Abs method.19type numericAbs[T Numeric] interface {20 ~struct{ Value_ T }21 Abs() T22 Value() T23}24 25// absDifference computes the absolute value of the difference of26// a and b, where the absolute value is determined by the Abs method.27func 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.34type orderedNumeric interface {35 ~int | ~int8 | ~int16 | ~int32 | ~int64 |36 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |37 ~float32 | ~float6438}39 40// Complex matches the two complex types, which do not have a < operator.41type Complex interface {42 ~complex64 | ~complex12843}44 45// orderedAbs is a helper type that defines an Abs method for46// a struct containing an ordered numeric type.47type orderedAbs[T orderedNumeric] struct {48 Value_ T49}50 51func (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 disabled59// until we have a more thorough understanding of the60// implications on the spec. See issue #51576.61// Use accessor method instead.62 63func (a orderedAbs[T]) Value() T {64 return a.Value_65}66 67// complexAbs is a helper type that defines an Abs method for68// a struct containing a complex type.69type complexAbs[T Complex] struct {70 Value_ T71}72 73func 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 return85}86 87func (a complexAbs[T]) Abs() T {88 // TODO use direct conversion instead of realimag once #50937 is fixed89 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 96func (a complexAbs[T]) Value() T {97 return a.Value_98}99 100// OrderedAbsDifference returns the absolute value of the difference101// between a and b, where a and b are of an ordered type.102func 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 difference107// between a and b, where a and b are of a complex type.108func ComplexAbsDifference[T Complex](a, b T) T {109 return absDifference(complexAbs[T]{a}, complexAbs[T]{b})110}111 