Source file test/abi/idata.go

     1  // run
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Excerpted from go/constant/value.go to capture a bug from there.
     8  
     9  package main
    10  
    11  import (
    12  	"fmt"
    13  	"math"
    14  	"math/big"
    15  )
    16  
    17  type (
    18  	unknownVal struct{}
    19  	intVal     struct{ val *big.Int }   // Int values not representable as an int64
    20  	ratVal     struct{ val *big.Rat }   // Float values representable as a fraction
    21  	floatVal   struct{ val *big.Float } // Float values not representable as a fraction
    22  	complexVal struct{ re, im Value }
    23  )
    24  
    25  const prec = 512
    26  
    27  func (unknownVal) String() string { return "unknown" }
    28  
    29  func (x intVal) String() string   { return x.val.String() }
    30  func (x ratVal) String() string   { return rtof(x).String() }
    31  
    32  func (x floatVal) String() string {
    33  	f := x.val
    34  
    35  	// Use exact fmt formatting if in float64 range (common case):
    36  	// proceed if f doesn't underflow to 0 or overflow to inf.
    37  	if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
    38  		return fmt.Sprintf("%.6g", x)
    39  	}
    40  
    41  	return "OOPS"
    42  }
    43  
    44  func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
    45  
    46  func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }
    47  
    48  //go:noinline
    49  //go:registerparams
    50  func itor(x intVal) ratVal       { return ratVal{nil} }
    51  
    52  //go:noinline
    53  //go:registerparams
    54  func itof(x intVal) floatVal     { return floatVal{nil} }
    55  func rtof(x ratVal) floatVal     { return floatVal{newFloat().SetRat(x.val)} }
    56  
    57  type Value interface {
    58  	String() string
    59  }
    60  
    61  //go:noinline
    62  //go:registerparams
    63  func ToFloat(x Value) Value {
    64  	switch x := x.(type) {
    65  	case intVal:
    66  		if smallInt(x.val) {
    67  			return itor(x)
    68  		}
    69  		return itof(x)
    70  	case ratVal, floatVal:
    71  		return x
    72  	case complexVal:
    73  		if Sign(x.im) == 0 {
    74  			return ToFloat(x.re)
    75  		}
    76  	}
    77  	return unknownVal{}
    78  }
    79  
    80  //go:noinline
    81  //go:registerparams
    82  func smallInt(x *big.Int) bool {
    83  	return false
    84  }
    85  
    86  //go:noinline
    87  //go:registerparams
    88  func Sign(x Value) int {
    89  	return 0
    90  }
    91  
    92  
    93  func main() {
    94  	v := ratVal{big.NewRat(22,7)}
    95  	s := ToFloat(v).String()
    96  	fmt.Printf("s=%s\n", s)
    97  }
    98  

View as plain text