1
2
3
4
5
20
21 package neon
22
23 import (
24 `encoding/json`
25 `math`
26 `math/rand`
27 `strconv`
28 `testing`
29
30 `github.com/stretchr/testify/assert`
31 )
32
33 func TestFastFloat_Encode(t *testing.T) {
34 var buf [64]byte
35 assert.Equal(t, "0" , string(buf[:f64toa(&buf[0], 0)]))
36 assert.Equal(t, "-0" , string(buf[:f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
37 assert.Equal(t, "12340000000" , string(buf[:f64toa(&buf[0], 1234e7)]))
38 assert.Equal(t, "12.34" , string(buf[:f64toa(&buf[0], 1234e-2)]))
39 assert.Equal(t, "0.001234" , string(buf[:f64toa(&buf[0], 1234e-6)]))
40 assert.Equal(t, "1e+30" , string(buf[:f64toa(&buf[0], 1e30)]))
41 assert.Equal(t, "1.234e+33" , string(buf[:f64toa(&buf[0], 1234e30)]))
42 assert.Equal(t, "1.234e+308" , string(buf[:f64toa(&buf[0], 1234e305)]))
43 assert.Equal(t, "1.234e-317" , string(buf[:f64toa(&buf[0], 1234e-320)]))
44 assert.Equal(t, "1.7976931348623157e+308" , string(buf[:f64toa(&buf[0], 1.7976931348623157e308)]))
45 assert.Equal(t, "-12340000000" , string(buf[:f64toa(&buf[0], -1234e7)]))
46 assert.Equal(t, "-12.34" , string(buf[:f64toa(&buf[0], -1234e-2)]))
47 assert.Equal(t, "-0.001234" , string(buf[:f64toa(&buf[0], -1234e-6)]))
48 assert.Equal(t, "-1e+30" , string(buf[:f64toa(&buf[0], -1e30)]))
49 assert.Equal(t, "-1.234e+33" , string(buf[:f64toa(&buf[0], -1234e30)]))
50 assert.Equal(t, "-1.234e+308" , string(buf[:f64toa(&buf[0], -1234e305)]))
51 assert.Equal(t, "-1.234e-317" , string(buf[:f64toa(&buf[0], -1234e-320)]))
52 assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:f64toa(&buf[0], -2.2250738585072014e-308)]))
53 }
54
55 func TestFastFloat_Random(t *testing.T) {
56 var buf [64]byte
57 N := 10000
58 for i := 0; i < N; i++ {
59 b64 := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
60 f64 := math.Float64frombits(b64)
61
62 jout, jerr := json.Marshal(f64)
63 n := f64toa(&buf[0], f64)
64 if jerr == nil {
65 assert.Equal(t, jout, buf[:n])
66 } else {
67 assert.True(t, n == 0)
68 }
69
70 f32 := math.Float32frombits(rand.Uint32())
71 jout, jerr = json.Marshal(f32)
72 n = f32toa(&buf[0], f32)
73 if jerr == nil {
74 assert.Equal(t, jout, buf[:n])
75 } else {
76 assert.True(t, n == 0)
77 }
78 }
79 }
80
81 func BenchmarkParseFloat64(b *testing.B) {
82 var f64toaBenches = []struct {
83 name string
84 float float64
85 }{
86 {"Zero", 0},
87 {"Decimal1", 39},
88 {"Decimal2", 33909},
89 {"Float1", 3.77},
90 {"Float2", 339.778442},
91 {"Exp1", 5.9e5},
92 {"Exp2", 521.091e25},
93 {"NegExp1", -5.1e-5},
94 {"NegExp2", -52.132e-35},
95 {"LongExp", 1.234567890123456e-78},
96 {"Big", 123456789123456789123456789},
97
98 }
99 for _, c := range f64toaBenches {
100 f64bench := []struct {
101 name string
102 test func(*testing.B)
103 }{{
104 name: "StdLib",
105 test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:0], c.float, 'g', -1, 64) }},
106 }, {
107 name: "FastFloat",
108 test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { f64toa(&buf[0], c.float) }},
109 }}
110 for _, bm := range f64bench {
111 name := bm.name + "_" + c.name
112 b.Run(name, bm.test)
113 }
114 }
115 }
116
117 func BenchmarkParseFloat32(b *testing.B) {
118 var f32toaBenches = []struct {
119 name string
120 float float32
121 }{
122 {"Zero", 0},
123 {"Decimal1", 39},
124 {"Decimal2", 33909},
125 {"Float1", 3.77},
126 {"Float2", 339.778442},
127 {"Exp1", 5.9e5},
128 {"Exp2", 521.091e19},
129 {"NegExp1", -5.1e-5},
130 {"NegExp2", -52.132e-19},
131 {"Shortest", 1.234567e-8},
132 }
133 for _, c := range f32toaBenches {
134 bench := []struct {
135 name string
136 test func(*testing.B)
137 }{{
138 name: "StdLib32",
139 test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:0], float64(c.float), 'g', -1, 32) }},
140 }, {
141 name: "FastFloat32",
142 test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { f32toa(&buf[0], c.float) }},
143 }}
144 for _, bm := range bench {
145 name := bm.name + "_" + c.name
146 b.Run(name, bm.test)
147 }
148 }
149 }
150
View as plain text