github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/json/ryu/floatconv.gno (about) 1 // Copyright 2018 Ulf Adams 2 // Modifications copyright 2019 Caleb Spare 3 // 4 // The contents of this file may be used under the terms of the Apache License, 5 // Version 2.0. 6 // 7 // (See accompanying file LICENSE or copy at 8 // http://www.apache.org/licenses/LICENSE-2.0) 9 // 10 // Unless required by applicable law or agreed to in writing, this software 11 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 12 // KIND, either express or implied. 13 // 14 // The code in this file is part of a Go translation of the C code originally written by 15 // Ulf Adams, which can be found at https://github.com/ulfjack/ryu. The original source 16 // code is licensed under the Apache License 2.0. This code is a derivative work thereof, 17 // adapted and modified to meet the specifications of the Gno language project. 18 // 19 // original Go implementation can be found at https://github.com/cespare/ryu. 20 // 21 // Please note that the modifications are also under the Apache License 2.0 unless 22 // otherwise specified. 23 24 // Package ryu implements the Ryu algorithm for quickly converting floating 25 // point numbers into strings. 26 package ryu 27 28 import ( 29 "math" 30 ) 31 32 const ( 33 mantBits32 = 23 34 expBits32 = 8 35 bias32 = 127 36 37 mantBits64 = 52 38 expBits64 = 11 39 bias64 = 1023 40 ) 41 42 // FormatFloat64 converts a 64-bit floating point number f to a string. 43 // It behaves like strconv.FormatFloat(f, 'e', -1, 64). 44 func FormatFloat64(f float64) string { 45 b := make([]byte, 0, 24) 46 b = AppendFloat64(b, f) 47 return string(b) 48 } 49 50 // AppendFloat64 appends the string form of the 64-bit floating point number f, 51 // as generated by FormatFloat64, to b and returns the extended buffer. 52 func AppendFloat64(b []byte, f float64) []byte { 53 // Step 1: Decode the floating-point number. 54 // Unify normalized and subnormal cases. 55 u := math.Float64bits(f) 56 neg := u>>(mantBits64+expBits64) != 0 57 mant := u & (uint64(1)<<mantBits64 - 1) 58 exp := (u >> mantBits64) & (uint64(1)<<expBits64 - 1) 59 60 // Exit early for easy cases. 61 if exp == uint64(1)<<expBits64-1 || (exp == 0 && mant == 0) { 62 return appendSpecial(b, neg, exp == 0, mant == 0) 63 } 64 65 d, ok := float64ToDecimalExactInt(mant, exp) 66 if !ok { 67 d = float64ToDecimal(mant, exp) 68 } 69 return d.append(b, neg) 70 } 71 72 func appendSpecial(b []byte, neg, expZero, mantZero bool) []byte { 73 if !mantZero { 74 return append(b, "NaN"...) 75 } 76 if !expZero { 77 if neg { 78 return append(b, "-Inf"...) 79 } 80 81 return append(b, "+Inf"...) 82 } 83 84 if neg { 85 b = append(b, '-') 86 } 87 return append(b, "0e+00"...) 88 } 89 90 func boolToInt(b bool) int { 91 if b { 92 return 1 93 } 94 return 0 95 } 96 97 func boolToUint32(b bool) uint32 { 98 if b { 99 return 1 100 } 101 return 0 102 } 103 104 func boolToUint64(b bool) uint64 { 105 if b { 106 return 1 107 } 108 return 0 109 } 110 111 func assert(t bool, msg string) { 112 if !t { 113 panic(msg) 114 } 115 } 116 117 // log10Pow2 returns floor(log_10(2^e)). 118 func log10Pow2(e int32) uint32 { 119 // The first value this approximation fails for is 2^1651 120 // which is just greater than 10^297. 121 assert(e >= 0, "e >= 0") 122 assert(e <= 1650, "e <= 1650") 123 return (uint32(e) * 78913) >> 18 124 } 125 126 // log10Pow5 returns floor(log_10(5^e)). 127 func log10Pow5(e int32) uint32 { 128 // The first value this approximation fails for is 5^2621 129 // which is just greater than 10^1832. 130 assert(e >= 0, "e >= 0") 131 assert(e <= 2620, "e <= 2620") 132 return (uint32(e) * 732923) >> 20 133 } 134 135 // pow5Bits returns ceil(log_2(5^e)), or else 1 if e==0. 136 func pow5Bits(e int32) int32 { 137 // This approximation works up to the point that the multiplication 138 // overflows at e = 3529. If the multiplication were done in 64 bits, 139 // it would fail at 5^4004 which is just greater than 2^9297. 140 assert(e >= 0, "e >= 0") 141 assert(e <= 3528, "e <= 3528") 142 return int32((uint32(e)*1217359)>>19 + 1) 143 }