2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-21 00:46:43 +08:00

Compare commits

...

3 commits

Author SHA1 Message Date
liu
56e81a633e
fix: use sse instead of sse4 (#305)
* fix: use sse instead of sse4

* fix: use dispatch

* fix: remove lzero

Co-authored-by: liuqiang <liuqiang.06@bytedance.com>
2022-09-26 12:45:01 +08:00
Chen Yannan
5e54c02172
fmt: move thrid-party tests into another module (#299)
* fix:move benchmarkTests and unitTests related to external json library

* remove extra spaces

* merge go.mod files

* refactor: add external_jsonlib_test into go.work and CI

Co-authored-by: Yi Duan <duanyi.aster@bytedance.com>
2022-09-20 12:02:41 +08:00
liu
ccc0f3f1e3
opt: faster ftoa (#291)
* opt: faster f64toa

* feat:(option) add option `MaxInlineDepth` for addjust compilation inline depth (#287)

* feat: make compilation depth changeable

* feat: add option `DefaultMaxInlineDepth`

* add recurse depth = 10

* refactor

* doc: readme and comment

* opt: add `_MAX_FIELDS` to limit the inlining of big struct

* update license

* fix typo

* feat:(ast) support cast `null` to empty value (#278)

* fix: recompile

* test: add ftoa benchmarks

* feat: add f32toa

* fix: add license

* opt: optimize decimal

* fix benchmarks

* fix: poor performance in atof32

* test: add more integer test

Co-authored-by: liuqiang <liuqiang.06@bytedance.com>
Co-authored-by: Yi Duan <duanyi.aster@bytedance.com>
2022-09-20 10:26:18 +08:00
75 changed files with 15021 additions and 9607 deletions

View file

@ -23,8 +23,11 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Benchmark
- name: Benchmark sonic
run: sh bench.sh
# - name: Benchmark third-party
# run: go test -benchmem -run=^$ -bench . -v ./generic_test
# - name: Diff
# run: ./bench.py -b '"^Benchmark.*Sonic"' -c

View file

@ -21,10 +21,9 @@ jobs:
${{ runner.os }}-go-
- name: Unit Test
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race ./...
run: |
GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race ./...
GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race ./external_jsonlib_test/...
- name: Generic Test
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race ./generic_test
- name: Benchmark
run: go test -benchmem -run=^$ -bench . -v ./generic_test
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race ./generic_test

View file

@ -24,4 +24,7 @@ jobs:
${{ runner.os }}-go-
- name: Unit Test
run: go test -v -gcflags=-d=checkptr=0 ./...
run: |
go test -v -gcflags=-d=checkptr=0 ./...
cd ./external_jsonlib_test
go test -v -gcflags=-d=checkptr=0 ./...

View file

@ -14,22 +14,22 @@
# limitations under the License.
#
ARCH := avx avx2 sse4
ARCH := avx avx2 sse
TMP_DIR := output
OUT_DIR := internal/native
SRC_FILE := native/native.c
CPU_avx := amd64
CPU_avx2 := amd64
CPU_sse4 := amd64
CPU_sse := amd64
TMPL_avx := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
TMPL_avx2 := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
TMPL_sse4 := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
TMPL_sse := fastint_amd64_test fastfloat_amd64_test native_amd64_test native_export_amd64
CFLAGS_avx := -msse4 -mavx -mno-avx2 -DUSE_AVX=1 -DUSE_AVX2=0
CFLAGS_avx2 := -msse4 -mavx -mavx2 -DUSE_AVX=1 -DUSE_AVX2=1
CFLAGS_sse4 := -msse4 -mno-avx -mno-avx2
CFLAGS_avx := -msse -mno-sse4 -mavx -mno-avx2 -DUSE_AVX=1 -DUSE_AVX2=0
CFLAGS_avx2 := -msse -mno-sse4 -mavx -mavx2 -DUSE_AVX=1 -DUSE_AVX2=1
CFLAGS_sse := -msse -mno-sse4 -mno-avx -mno-avx2
CC_amd64 := clang
ASM2ASM_amd64 := tools/asm2asm/asm2asm.py
@ -43,6 +43,7 @@ CFLAGS += -fno-rtti
CFLAGS += -fno-stack-protector
CFLAGS += -nostdlib
CFLAGS += -O3
CFLAGS += -Wall -Werror
NATIVE_SRC := $(wildcard native/*.h)
NATIVE_SRC += $(wildcard native/*.c)
@ -99,8 +100,8 @@ endef
all: ${ARCH}
clean:
rm -vfr ${TMP_DIR}/{sse4,avx,avx2}
rm -vfr ${OUT_DIR}/{sse4,avx,avx2}
rm -vfr ${TMP_DIR}/{sse,avx,avx2}
rm -vfr ${OUT_DIR}/{sse,avx,avx2}
$(foreach \
arch, \

View file

@ -17,17 +17,15 @@
package ast
import (
`os`
`encoding/json`
`testing`
`time`
`os`
`runtime`
`runtime/debug`
`sync`
`testing`
`time`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/tidwall/gjson`
)
var (
@ -43,7 +41,7 @@ func TestMain(m *testing.M) {
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
@ -108,7 +106,7 @@ func runDecoderTestUseNumber(t *testing.T, src string, expect interface{}) {
}
}
func n2f64(i json.Number) float64{
func n2f64(i json.Number) float64{
x, err := i.Float64()
if err != nil {
panic(err)
@ -257,39 +255,6 @@ func BenchmarkParser_Sonic(b *testing.B) {
}
}
func BenchmarkParser_Gjson(b *testing.B) {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
}
func BenchmarkParser_Jsoniter(b *testing.B) {
v := jsoniter.Get([]byte(_TwitterJson)).GetInterface()
if v == nil {
b.Fatal(v)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = jsoniter.Get([]byte(_TwitterJson)).GetInterface()
}
}
func BenchmarkParser_Parallel_Sonic(b *testing.B) {
r, _ := NewParser(_TwitterJson).Parse()
if err := r.LoadAll(); err != nil {
@ -305,40 +270,6 @@ func BenchmarkParser_Parallel_Sonic(b *testing.B) {
})
}
func BenchmarkParser_Parallel_Gjson(b *testing.B) {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
return true
})
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
})
}
func BenchmarkParser_Parallel_Jsoniter(b *testing.B) {
var bv = []byte(_TwitterJson)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var out interface{}
_ = jsoniter.Unmarshal(bv, &out)
}
})
}
func BenchmarkParseOne_Sonic(b *testing.B) {
ast, _ := NewParser(_TwitterJson).Parse()
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
@ -353,37 +284,6 @@ func BenchmarkParseOne_Sonic(b *testing.B) {
}
}
func BenchmarkParseOne_Gjson(b *testing.B) {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
}
func BenchmarkParseOne_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
}
func BenchmarkParseOne_Parallel_Sonic(b *testing.B) {
ast, _ := NewParser(_TwitterJson).Parse()
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
@ -400,42 +300,6 @@ func BenchmarkParseOne_Parallel_Sonic(b *testing.B) {
})
}
func BenchmarkParseOne_Parallel_Gjson(b *testing.B) {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
})
}
func BenchmarkParseOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
})
}
func BenchmarkParseSeven_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
@ -454,43 +318,6 @@ func BenchmarkParseSeven_Sonic(b *testing.B) {
}
}
func BenchmarkParseSeven_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get( "statuses.3.user.entities.description")
node = ast.Get( "statuses.3.user.entities.url.urls")
node = ast.Get( "statuses.3.user.entities.url")
node = ast.Get( "statuses.3.user.created_at")
node = ast.Get( "statuses.3.user.name")
node = ast.Get( "statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities","description")
node = ast.Get("statuses", 3, "user", "entities","url","urls")
node = ast.Get("statuses", 3, "user", "entities","url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Parallel_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
@ -509,45 +336,4 @@ func BenchmarkParseSeven_Parallel_Sonic(b *testing.B) {
}
}
})
}
func BenchmarkParseSeven_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get( "statuses.3.user.entities.description")
node = ast.Get( "statuses.3.user.entities.url.urls")
node = ast.Get( "statuses.3.user.entities.url")
node = ast.Get( "statuses.3.user.created_at")
node = ast.Get( "statuses.3.user.name")
node = ast.Get( "statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
})
}
func BenchmarkParseSeven_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities","description")
node = ast.Get("statuses", 3, "user", "entities","url","urls")
node = ast.Get("statuses", 3, "user", "entities","url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
})
}
}

View file

@ -17,17 +17,13 @@
package ast
import (
`testing`
`runtime`
`sync`
`fmt`
`math`
`runtime`
`strconv`
`sync`
`testing`
`github.com/tidwall/sjson`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/tidwall/gjson`
)
@ -192,29 +188,6 @@ func TestSearchNotExist(t *testing.T) {
}
}
func BenchmarkGetOne_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
for i := 0; i < b.N; i++ {
ast := gjson.Get(_TwitterJson, "statuses.3.id")
node := ast.Int()
if node != 249279667666817024 {
b.Fail()
}
}
}
func BenchmarkGetOne_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 3, "id")
node := ast.ToInt()
if node != 249279667666817024 {
b.Fail()
}
}
}
func BenchmarkGetOne_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
ast := NewSearcher(_TwitterJson)
@ -230,33 +203,6 @@ func BenchmarkGetOne_Sonic(b *testing.B) {
}
}
func BenchmarkGetOne_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Get(_TwitterJson, "statuses.3.id")
node := ast.Int()
if node != 249279667666817024 {
b.Fail()
}
}
})
}
func BenchmarkGetOne_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
data := []byte(_TwitterJson)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := jsoniter.Get(data, "statuses", 3, "id")
node := ast.ToInt()
if node != 249279667666817024 {
b.Fail()
}
}
})
}
func BenchmarkGetOne_Parallel_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.RunParallel(func(pb *testing.PB) {
@ -293,36 +239,6 @@ func BenchmarkSetOne_Sonic(b *testing.B) {
}
}
func BenchmarkSetOne_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(_TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
sjson.Set(_TwitterJson, path, math.MaxInt32)
}
}
func BenchmarkSetOne_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
}
func BenchmarkSetOne_Parallel_Sonic(b *testing.B) {
node, err := NewSearcher(_TwitterJson).GetByPath("statuses", 3)
if err != nil {
@ -342,38 +258,4 @@ func BenchmarkSetOne_Parallel_Sonic(b *testing.B) {
_, _ = node.Set("id", n)
}
})
}
func BenchmarkSetOne_Parallel_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(_TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
sjson.Set(_TwitterJson, path, math.MaxInt32)
}
})
}
func BenchmarkSetOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
})
}

View file

@ -16,5 +16,12 @@ go test -benchmem -run=^$ -benchtime=10000x -bench "^(BenchmarkParser_.*|Benchma
go test -benchmem -run=^$ -benchtime=10000000x -bench "^(BenchmarkNodeGetByPath|BenchmarkStructGetByPath|BenchmarkNodeIndex|BenchmarkStructIndex|BenchmarkSliceIndex|BenchmarkMapIndex|BenchmarkNodeGet|BenchmarkSliceGet|BenchmarkMapGet|BenchmarkNodeSet|BenchmarkMapSet|BenchmarkNodeSetByIndex|BenchmarkSliceSetByIndex|BenchmarkStructSetByIndex|BenchmarkNodeUnset|BenchmarkMapUnset|BenchmarkNodUnsetByIndex|BenchmarkSliceUnsetByIndex|BenchmarkNodeAdd|BenchmarkSliceAdd|BenchmarkMapAdd)$"
cd $pwd/external_jsonlib_test/benchmark_test
go test -benchmem -run=^$ -benchtime=100000x -bench "^(BenchmarkEncoder_.*|BenchmarkDecoder_.*)$"
go test -benchmem -run=^$ -benchtime=1000000x -bench "^(BenchmarkGet.*|BenchmarkSet.*)$"
go test -benchmem -run=^$ -benchtime=10000x -bench "^(BenchmarkParser_.*)$"
unset SONIC_NO_ASYNC_GC
cd $pwd

View file

@ -828,11 +828,11 @@ var unmarshalTests = []unmarshalTest{
{in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true},
{in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true},
{in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true},
{in: `1e21`, ptr: new(float64), out: 1e21, golden: true},
{in: `1e+21`, ptr: new(float64), out: 1e21, golden: true},
{in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true},
{in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true},
{in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true},
{in: `-1e21`, ptr: new(float64), out: -1e21, golden: true},
{in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true},
{in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true},
{in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true},
{in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false},

View file

@ -27,8 +27,6 @@ import (
`github.com/bytedance/sonic/internal/rt`
`github.com/davecgh/go-spew/spew`
gojson `github.com/goccy/go-json`
`github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/stretchr/testify/require`
)
@ -328,30 +326,6 @@ func BenchmarkDecoder_Generic_StdLib(b *testing.B) {
}
}
func BenchmarkDecoder_Generic_JsonIter(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = jsoniter.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_Sonic(b *testing.B) {
var w TwitterStruct
_, _ = decode(TwitterJson, &w, true)
@ -386,30 +360,6 @@ func BenchmarkDecoder_Binding_StdLib(b *testing.B) {
}
}
func BenchmarkDecoder_Binding_JsonIter(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = jsoniter.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Parallel_Generic_Sonic(b *testing.B) {
var w interface{}
_, _ = decode(TwitterJson, &w, true)
@ -450,34 +400,6 @@ func BenchmarkDecoder_Parallel_Generic_StdLib(b *testing.B) {
})
}
func BenchmarkDecoder_Parallel_Generic_JsonIter(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = jsoniter.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_Sonic(b *testing.B) {
var w TwitterStruct
_, _ = decode(TwitterJson, &w, true)
@ -518,34 +440,6 @@ func BenchmarkDecoder_Parallel_Binding_StdLib(b *testing.B) {
})
}
func BenchmarkDecoder_Parallel_Binding_JsonIter(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = jsoniter.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
})
}
func BenchmarkSkip_Sonic(b *testing.B) {
var data = rt.Str2Mem(TwitterJson)
if ret, _ := Skip(data); ret < 0 {

View file

@ -24,7 +24,6 @@ import (
`strings`
`testing`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/stretchr/testify/require`
)
@ -83,76 +82,6 @@ func TestDecodeEmpty(t *testing.T) {
assert.Equal(t, v1, v2)
}
func TestDecodeSingle(t *testing.T) {
var str = _Single_JSON
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var r2 = strings.NewReader(str)
var v2 map[string]interface{}
var d2 = NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
es1 := d1.Decode(&v1)
ee1 := d2.Decode(&v2)
assert.Equal(t, es1, ee1)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
}
func TestDecodeMulti(t *testing.T) {
var str = _Triple_JSON
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var r2 = strings.NewReader(str)
var v2 map[string]interface{}
var d2 = NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
es1 := d1.Decode(&v1)
ee1 := d2.Decode(&v2)
assert.Equal(t, es1, ee1)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
// fmt.Printf("v:%#v\n", v1)
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
}
type HaltReader struct {
halts map[int]bool
buf string
@ -199,49 +128,6 @@ var testHalts = func () map[int]bool {
20: true}
}
func TestDecodeHalt(t *testing.T) {
var str = _Triple_JSON
var r1 = NewHaltReader(str, testHalts())
var r2 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
var v2 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var d2 = NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
err1 := d1.Decode(&v1)
err2 := d2.Decode(&v2)
assert.Equal(t, err1, err2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
}
func TestBuffered(t *testing.T) {
var str = _Triple_JSON
var r1 = NewHaltReader(str, testHalts())
@ -274,43 +160,6 @@ func TestBuffered(t *testing.T) {
assert.Equal(t, d1.InputOffset(), d2.InputOffset())
}
func TestMore(t *testing.T) {
var str = _Triple_JSON
var r2 = NewHaltReader(str, testHalts())
var v2 map[string]interface{}
var d2 = NewStreamDecoder(r2)
var r1 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
require.Nil(t, d1.Decode(&v1))
require.Nil(t, d2.Decode(&v2))
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
require.Equal(t, d1.More(), d2.More())
}
func BenchmarkDecodeStream_Std(b *testing.B) {
b.Run("single", func (b *testing.B) {
var str = _Single_JSON
@ -345,40 +194,6 @@ func BenchmarkDecodeStream_Std(b *testing.B) {
})
}
func BenchmarkDecodeStream_Jsoniter(b *testing.B) {
b.Run("single", func (b *testing.B) {
var str = _Single_JSON
for i:=0; i<b.N; i++ {
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
_ = dc.Decode(&v1)
}
})
b.Run("double", func (b *testing.B) {
var str = _Double_JSON
for i:=0; i<b.N; i++ {
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
_ = dc.Decode(&v1)
}
})
b.Run("halt", func (b *testing.B) {
var str = _Double_JSON
for i:=0; i<b.N; i++ {
var r1 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
}
})
}
// func BenchmarkDecodeError_Sonic(b *testing.B) {
// var str = `\b测试1234`
// for i:=0; i<b.N; i++ {

View file

@ -732,6 +732,7 @@ var (
var (
_F_f64toa = jit.Imm(int64(native.S_f64toa))
_F_f32toa = jit.Imm(int64(native.S_f32toa))
_F_i64toa = jit.Imm(int64(native.S_i64toa))
_F_u64toa = jit.Imm(int64(native.S_u64toa))
_F_b64encode = jit.Imm(int64(_subr__b64encode))
@ -851,8 +852,7 @@ func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
self.save_c() // SAVE $C_regs
self.rbuf_di() // MOVQ RP, DI
self.Emit("MOVSS" , jit.Ptr(_SP_p, 0), _X0) // MOVSS (SP.p), X0
self.Emit("CVTSS2SD", _X0, _X0) // CVTSS2SD X0, X0
self.call_c(_F_f64toa) // CALL_C f64toa
self.call_c(_F_f32toa) // CALL_C f64toa
self.Emit("ADDQ" , _AX, _RL) // ADDQ AX, RL
}

View file

@ -745,6 +745,7 @@ var (
var (
_F_f64toa = jit.Imm(int64(native.S_f64toa))
_F_f32toa = jit.Imm(int64(native.S_f32toa))
_F_i64toa = jit.Imm(int64(native.S_i64toa))
_F_u64toa = jit.Imm(int64(native.S_u64toa))
_F_b64encode = jit.Imm(int64(_subr__b64encode))
@ -864,8 +865,7 @@ func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
self.save_c() // SAVE $C_regs
self.rbuf_di() // MOVQ RP, DI
self.Emit("MOVSS" , jit.Ptr(_SP_p, 0), _X0) // MOVSS (SP.p), X0
self.Emit("CVTSS2SD", _X0, _X0) // CVTSS2SD X0, X0
self.call_c(_F_f64toa) // CALL_C f64toa
self.call_c(_F_f32toa) // CALL_C f64toa
self.Emit("ADDQ" , _AX, _RL) // ADDQ AX, RL
}

View file

@ -27,20 +27,18 @@ import (
`time`
`github.com/bytedance/sonic/internal/rt`
gojson `github.com/goccy/go-json`
`github.com/json-iterator/go`
`github.com/stretchr/testify/require`
)
func TestMain(m *testing.M) {
go func () {
if !debugAsyncGC {
return
return
}
println("Begin GC looping...")
for {
runtime.GC()
debug.FreeOSMemory()
debug.FreeOSMemory()
}
println("stop GC looping!")
}()
@ -50,7 +48,7 @@ func TestMain(m *testing.M) {
func TestGC(t *testing.T) {
if debugSyncGC {
return
return
}
out, err := Encode(_GenericValue, 0)
if err != nil {
@ -92,7 +90,7 @@ func TestOptionSliceOrMapNoNull(t *testing.T) {
t.Fatal(err)
}
require.Equal(t, `{"M":{},"S":[],"A":[],"MP":null,"SP":null,"AP":null}`, string(out))
obj2 := sample{}
out, err = Encode(obj2, 0)
if err != nil {
@ -113,7 +111,7 @@ func BenchmarkOptionSliceOrMapNoNull(b *testing.B) {
_, _ = Encode(obj, NoNullSliceOrMap)
}
})
b.Run("false", func (b *testing.B) {
obj2 := sample{}
_, err := Encode(obj2, 0)
@ -356,24 +354,6 @@ func BenchmarkEncoder_Generic_Sonic_Fast(b *testing.B) {
}
}
func BenchmarkEncoder_Generic_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = jsoniter.Marshal(_GenericValue)
}
}
func BenchmarkEncoder_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(_GenericValue)
}
}
func BenchmarkEncoder_Generic_StdLib(b *testing.B) {
_, _ = json.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
@ -401,24 +381,6 @@ func BenchmarkEncoder_Binding_Sonic_Fast(b *testing.B) {
}
}
func BenchmarkEncoder_Binding_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = jsoniter.Marshal(&_BindingValue)
}
}
func BenchmarkEncoder_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(&_BindingValue)
}
}
func BenchmarkEncoder_Binding_StdLib(b *testing.B) {
_, _ = json.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
@ -450,28 +412,6 @@ func BenchmarkEncoder_Parallel_Generic_Sonic_Fast(b *testing.B) {
})
}
func BenchmarkEncoder_Parallel_Generic_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = jsoniter.Marshal(_GenericValue)
}
})
}
func BenchmarkEncoder_Parallel_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(_GenericValue)
}
})
}
func BenchmarkEncoder_Parallel_Generic_StdLib(b *testing.B) {
_, _ = json.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
@ -505,28 +445,6 @@ func BenchmarkEncoder_Parallel_Binding_Sonic_Fast(b *testing.B) {
})
}
func BenchmarkEncoder_Parallel_Binding_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = jsoniter.Marshal(&_BindingValue)
}
})
}
func BenchmarkEncoder_Parallel_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(&_BindingValue)
}
})
}
func BenchmarkEncoder_Parallel_Binding_StdLib(b *testing.B) {
_, _ = json.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
@ -600,4 +518,84 @@ func BenchmarkCompact_Std(b *testing.B) {
dst.Reset()
_ = json.Compact(dst, data)
}
}
type f64Bench struct {
name string
float float64
}
func BenchmarkEncoder_Float64(b *testing.B) {
var bench = []f64Bench{
{"Zero", 0},
{"ShortDecimal", 1000},
{"Decimal", 33909},
{"Float", 339.7784},
{"Exp", -5.09e75},
{"NegExp", -5.11e-95},
{"LongExp", 1.234567890123456e-78},
{"Big", 123456789123456789123456789},
}
maxUint := "18446744073709551615"
for i := 1; i <= len(maxUint); i++ {
name := strconv.FormatInt(int64(i), 10) + "-Digs"
num, _ := strconv.ParseUint(string(maxUint[:i]), 10, 64)
bench = append(bench, f64Bench{name, float64(num)})
}
for _, c := range bench {
libs := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { _, _ = json.Marshal(c.float); for i := 0; i < b.N; i++ { _, _ = json.Marshal(c.float) }},
}, {
name: "Sonic",
test: func(b *testing.B) { _, _ = Encode(c.float, 0); for i := 0; i < b.N; i++ { _, _ = Encode(c.float, 0) }},
}}
for _, lib := range libs {
name := lib.name + "_" + c.name
b.Run(name, lib.test)
}
}
}
type f32Bench struct {
name string
float float32
}
func BenchmarkEncoder_Float32(b *testing.B) {
var bench = []f32Bench{
{"Zero", 0},
{"ShortDecimal", 1000},
{"Decimal", 33909},
{"ExactFraction", 3.375},
{"Point", 339.7784},
{"Exp", -5.09e25},
{"NegExp", -5.11e-25},
{"Shortest", 1.234567e-8},
}
maxUint := "18446744073709551615"
for i := 1; i <= len(maxUint); i++ {
name := strconv.FormatInt(int64(i), 10) + "-Digs"
num, _ := strconv.ParseUint(string(maxUint[:i]), 10, 64)
bench = append(bench, f32Bench{name, float32(num)})
}
for _, c := range bench {
libs := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { _, _ = json.Marshal(c.float); for i := 0; i < b.N; i++ { _, _ = json.Marshal(c.float) }},
}, {
name: "Sonic",
test: func(b *testing.B) { _, _ = Encode(c.float, 0); for i := 0; i < b.N; i++ { _, _ = Encode(c.float, 0) }},
}}
for _, lib := range libs {
name := lib.name + "_" + c.name
b.Run(name, lib.test)
}
}
}

View file

@ -22,7 +22,6 @@ import (
`strings`
`testing`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/require`
)
@ -138,53 +137,4 @@ func BenchmarkEncodeStream_Std(b *testing.B) {
w.Reset()
}
})
}
func BenchmarkEncodeStream_Jsoniter(b *testing.B) {
var o = map[string]interface{}{
"a": `<`+strings.Repeat("1", 1024)+`>`,
"b": json.RawMessage(` [ `+strings.Repeat(" ", 1024)+` ] `),
}
b.Run("single", func(b *testing.B){
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i:=0; i<b.N; i++ {
_ = enc.Encode(o)
w.Reset()
}
})
b.Run("double", func(b *testing.B){
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i:=0; i<b.N; i++ {
_ = enc.Encode(o)
_ = enc.Encode(o)
w.Reset()
}
})
b.Run("compatible", func(b *testing.B){
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
EscapeHTML: true,
SortMapKeys: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i:=0; i<b.N; i++ {
_ = enc.Encode(o)
w.Reset()
}
})
}

View file

@ -0,0 +1,111 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
"io"
`strings`
`testing`
jsoniter `github.com/json-iterator/go`
)
var (
defaultBufferSize uint = 4096
_Single_JSON = `{"aaaaa":"` + strings.Repeat("b", int(defaultBufferSize)) + `"} { `
_Double_JSON = `{"aaaaa":"` + strings.Repeat("b", int(defaultBufferSize)) + `"} {"11111":"` + strings.Repeat("2", int(defaultBufferSize)) + `"}`
)
type HaltReader struct {
halts map[int]bool
buf string
p int
}
func NewHaltReader(buf string, halts map[int]bool) *HaltReader {
return &HaltReader{
halts: halts,
buf: buf,
p: 0,
}
}
func (self *HaltReader) Read(p []byte) (int, error) {
t := 0
for ; t < len(p); {
if self.p >= len(self.buf) {
return t, io.EOF
}
if b, ok := self.halts[self.p]; b {
self.halts[self.p] = false
return t, nil
} else if ok {
delete(self.halts, self.p)
return 0, nil
}
p[t] = self.buf[self.p]
self.p++
t++
}
return t, nil
}
func (self *HaltReader) Reset(buf string) {
self.p = 0
self.buf = buf
}
var testHalts = func() map[int]bool {
return map[int]bool{
1: true,
10: true,
20: true}
}
func BenchmarkDecodeStream_Jsoniter(b *testing.B) {
b.Run("single", func(b *testing.B) {
var str = _Single_JSON
for i := 0; i < b.N; i++ {
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
_ = dc.Decode(&v1)
}
})
b.Run("double", func(b *testing.B) {
var str = _Double_JSON
for i := 0; i < b.N; i++ {
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
_ = dc.Decode(&v1)
}
})
b.Run("halt", func(b *testing.B) {
var str = _Double_JSON
for i := 0; i < b.N; i++ {
var r1 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
dc := jsoniter.NewDecoder(r1)
_ = dc.Decode(&v1)
}
})
}

View file

@ -0,0 +1,185 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
`encoding/json`
`testing`
gojson `github.com/goccy/go-json`
jsoniter "github.com/json-iterator/go"
)
func init() {
_ = json.Unmarshal([]byte(TwitterJson), &_BindingValue)
}
func BenchmarkDecoder_Generic_StdLib(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = json.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = json.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Generic_JsonIter(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = jsoniter.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_StdLib(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = json.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = json.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_JsonIter(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = jsoniter.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Parallel_Generic_StdLib(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = json.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = json.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Generic_JsonIter(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = jsoniter.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_StdLib(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = json.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = json.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_JsonIter(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = jsoniter.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = jsoniter.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
})
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
`bytes`
`encoding/json`
`strings`
`testing`
jsoniter `github.com/json-iterator/go`
)
func BenchmarkEncodeStream_Jsoniter(b *testing.B) {
var o = map[string]interface{}{
"a": `<` + strings.Repeat("1", 1024) + `>`,
"b": json.RawMessage(` [ ` + strings.Repeat(" ", 1024) + ` ] `),
}
b.Run("single", func(b *testing.B) {
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = enc.Encode(o)
w.Reset()
}
})
b.Run("double", func(b *testing.B) {
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = enc.Encode(o)
_ = enc.Encode(o)
w.Reset()
}
})
b.Run("compatible", func(b *testing.B) {
var w = bytes.NewBuffer(nil)
var jt = jsoniter.Config{
ValidateJsonRawMessage: true,
EscapeHTML: true,
SortMapKeys: true,
}.Froze()
var enc = jt.NewEncoder(w)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = enc.Encode(o)
w.Reset()
}
})
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
`encoding/json`
`testing`
gojson `github.com/goccy/go-json`
jsoniter `github.com/json-iterator/go`
)
var _GenericValue interface{}
var _BindingValue TwitterStruct
func init() {
_ = json.Unmarshal([]byte(TwitterJson), &_GenericValue)
_ = json.Unmarshal([]byte(TwitterJson), &_BindingValue)
}
func BenchmarkEncoder_Generic_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = jsoniter.Marshal(_GenericValue)
}
}
func BenchmarkEncoder_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(_GenericValue)
}
}
func BenchmarkEncoder_Binding_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = jsoniter.Marshal(&_BindingValue)
}
}
func BenchmarkEncoder_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(&_BindingValue)
}
}
func BenchmarkEncoder_Parallel_Generic_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = jsoniter.Marshal(_GenericValue)
}
})
}
func BenchmarkEncoder_Parallel_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(_GenericValue)
}
})
}
func BenchmarkEncoder_Parallel_Binding_JsonIter(b *testing.B) {
_, _ = jsoniter.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = jsoniter.Marshal(&_BindingValue)
}
})
}
func BenchmarkEncoder_Parallel_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(&_BindingValue)
}
})
}

View file

@ -0,0 +1,236 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
`testing`
jsoniter `github.com/json-iterator/go`
`github.com/tidwall/gjson`
)
func BenchmarkParser_Gjson(b *testing.B) {
gjson.Parse(TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
gjson.Parse(TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
}
func BenchmarkParser_Jsoniter(b *testing.B) {
v := jsoniter.Get([]byte(TwitterJson)).GetInterface()
if v == nil {
b.Fatal(v)
}
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = jsoniter.Get([]byte(TwitterJson)).GetInterface()
}
}
func BenchmarkParser_Parallel_Gjson(b *testing.B) {
gjson.Parse(TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
return true
})
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
gjson.Parse(TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
})
}
func BenchmarkParser_Parallel_Jsoniter(b *testing.B) {
var bv = []byte(TwitterJson)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var out interface{}
_ = jsoniter.Unmarshal(bv, &out)
}
})
}
func BenchmarkParseOne_Gjson(b *testing.B) {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
}
func BenchmarkParseOne_Jsoniter(b *testing.B) {
data := []byte(TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
}
func BenchmarkParseOne_Parallel_Gjson(b *testing.B) {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
})
}
func BenchmarkParseOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
})
}
func BenchmarkParseSeven_Gjson(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get("statuses.3.user.entities.description")
node = ast.Get("statuses.3.user.entities.url.urls")
node = ast.Get("statuses.3.user.entities.url")
node = ast.Get("statuses.3.user.created_at")
node = ast.Get("statuses.3.user.name")
node = ast.Get("statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
data := []byte(TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities", "description")
node = ast.Get("statuses", 3, "user", "entities", "url", "urls")
node = ast.Get("statuses", 3, "user", "entities", "url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get("statuses.3.user.entities.description")
node = ast.Get("statuses.3.user.entities.url.urls")
node = ast.Get("statuses.3.user.entities.url")
node = ast.Get("statuses.3.user.created_at")
node = ast.Get("statuses.3.user.name")
node = ast.Get("statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
})
}
func BenchmarkParseSeven_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(TwitterJson)
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities", "description")
node = ast.Get("statuses", 3, "user", "entities", "url", "urls")
node = ast.Get("statuses", 3, "user", "entities", "url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
})
}

View file

@ -0,0 +1,141 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
import (
`fmt`
`math`
`testing`
jsoniter `github.com/json-iterator/go`
`github.com/tidwall/gjson`
`github.com/tidwall/sjson`
)
func BenchmarkGetOne_Gjson(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
for i := 0; i < b.N; i++ {
ast := gjson.Get(TwitterJson, "statuses.3.id")
node := ast.Int()
if node != 249279667666817024 {
b.Fail()
}
}
}
func BenchmarkGetOne_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
data := []byte(TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 3, "id")
node := ast.ToInt()
if node != 249279667666817024 {
b.Fail()
}
}
}
func BenchmarkGetOne_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Get(TwitterJson, "statuses.3.id")
node := ast.Int()
if node != 249279667666817024 {
b.Fail()
}
}
})
}
func BenchmarkGetOne_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(TwitterJson)))
data := []byte(TwitterJson)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := jsoniter.Get(data, "statuses", 3, "id")
node := ast.ToInt()
if node != 249279667666817024 {
b.Fail()
}
}
})
}
func BenchmarkSetOne_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
sjson.Set(TwitterJson, path, math.MaxInt32)
}
}
func BenchmarkSetOne_Jsoniter(b *testing.B) {
data := []byte(TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
}
func BenchmarkSetOne_Parallel_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
sjson.Set(TwitterJson, path, math.MaxInt32)
}
})
}
func BenchmarkSetOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
})
}

View file

@ -0,0 +1,551 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package benchmark_test
const TwitterJson = `{
"statuses": [
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Mon Sep 24 03:35:21 +0000 2012",
"id_str": "250075927172759552",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Aggressive Ponytail #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 250075927172759552,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDEEF6",
"profile_sidebar_border_color": "C0DEED",
"profile_background_tile": false,
"name": "Sean Cummings",
"profile_image_url": "https://a0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"created_at": "Mon Apr 26 06:01:55 +0000 2010",
"location": "LA, CA",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "137238150",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": true,
"contributors_enabled": false,
"favourites_count": 0,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"utc_offset": -28800,
"id": 137238150,
"profile_use_background_image": true,
"listed_count": 2,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 70,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme1/bg.png",
"profile_background_color": "C0DEED",
"verified": false,
"geo_enabled": true,
"time_zone": "Pacific Time (US & Canada)",
"description": "Born 330 Live 310",
"default_profile_image": false,
"profile_background_image_url": "https://a0.twimg.com/images/themes/theme1/bg.png",
"statuses_count": 579,
"friends_count": 110,
"following": null,
"show_all_inline_media": false,
"screen_name": "sean_cummings"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:40:54 +0000 2012",
"id_str": "249292149810667520",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "FreeBandNames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Thee Namaste Nerdz. #FreeBandNames",
"metadata": {
"iso_language_code": "pl",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249292149810667520,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDFFCC",
"profile_sidebar_border_color": "BDDCAD",
"profile_background_tile": true,
"name": "Chaz Martenstein",
"profile_image_url": "https://a0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"created_at": "Tue Apr 07 19:05:07 +0000 2009",
"location": "Durham, NC",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "29516238",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "https://bullcityrecords.com/wnng/",
"indices": [
0,
32
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 8,
"url": "https://bullcityrecords.com/wnng/",
"profile_image_url_https": "https://si0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"utc_offset": -18000,
"id": 29516238,
"profile_use_background_image": true,
"listed_count": 118,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 2052,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"profile_background_color": "9AE4E8",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "You will come to Durham, North Carolina. I will sell you some records then, here in Durham, North Carolina. Fun will happen.",
"default_profile_image": false,
"profile_background_image_url": "https://a0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"statuses_count": 7579,
"friends_count": 348,
"following": null,
"show_all_inline_media": true,
"screen_name": "bullcityrecords"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:30:20 +0000 2012",
"id_str": "249289491129438208",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
29,
43
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Mexican Heaven, Mexican Hell #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249289491129438208,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "99CC33",
"profile_sidebar_border_color": "829D5E",
"profile_background_tile": false,
"name": "Thomas John Wakeman",
"profile_image_url": "https://a0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"created_at": "Tue Sep 01 21:21:35 +0000 2009",
"location": "Kingston New York",
"follow_request_sent": null,
"profile_link_color": "D02B55",
"is_translator": false,
"id_str": "70789458",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 19,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"utc_offset": -18000,
"id": 70789458,
"profile_use_background_image": true,
"listed_count": 1,
"profile_text_color": "3E4415",
"lang": "en",
"followers_count": 63,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme5/bg.gif",
"profile_background_color": "352726",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "Science Fiction Writer, sort of. Likes Superheroes, Mole People, Alt. Timelines.",
"default_profile_image": false,
"profile_background_image_url": "https://a0.twimg.com/images/themes/theme5/bg.gif",
"statuses_count": 1048,
"friends_count": 63,
"following": null,
"show_all_inline_media": false,
"screen_name": "MonkiesFist"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 22:51:18 +0000 2012",
"id_str": "249279667666817024",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "The Foolish Mortals #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249279667666817024,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "BFAC83",
"profile_sidebar_border_color": "615A44",
"profile_background_tile": true,
"name": "Marty Elmer",
"profile_image_url": "https://a0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"created_at": "Mon May 04 00:05:00 +0000 2009",
"location": "Wisconsin, USA",
"follow_request_sent": null,
"profile_link_color": "3B2A26",
"is_translator": false,
"id_str": "37539828",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "https://www.omnitarian.me",
"indices": [
0,
24
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 647,
"url": "https://www.omnitarian.me",
"profile_image_url_https": "https://si0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"utc_offset": -21600,
"id": 37539828,
"profile_use_background_image": true,
"listed_count": 52,
"profile_text_color": "000000",
"lang": "en",
"followers_count": 608,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"profile_background_color": "EEE3C4",
"verified": false,
"geo_enabled": false,
"time_zone": "Central Time (US & Canada)",
"description": "Cartoonist, Illustrator, and T-Shirt connoisseur",
"default_profile_image": false,
"profile_background_image_url": "https://a0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"statuses_count": 3575,
"friends_count": 249,
"following": null,
"show_all_inline_media": true,
"screen_name": "Omnitarian"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//twitter.com/download/iphone%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for iPhone</a>",
"in_reply_to_status_id": null
}
],
"search_metadata": {
"max_id": 250126199840518145,
"since_id": 24012619984051000,
"refresh_url": "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
"next_results": "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
"count": 4,
"completed_in": 0.035,
"since_id_str": "24012619984051000",
"query": "%23freebandnames",
"max_id_str": "250126199840518145"
}
}`
type TwitterStruct struct {
Statuses []Statuses `json:"statuses"`
SearchMetadata SearchMetadata `json:"search_metadata"`
}
type Hashtags struct {
Text string `json:"text"`
Indices []int `json:"indices"`
}
type Entities struct {
Urls []interface{} `json:"urls"`
Hashtags []Hashtags `json:"hashtags"`
UserMentions []interface{} `json:"user_mentions"`
}
type Metadata struct {
IsoLanguageCode string `json:"iso_language_code"`
ResultType string `json:"result_type"`
}
type Urls struct {
ExpandedURL interface{} `json:"expanded_url"`
URL string `json:"url"`
Indices []int `json:"indices"`
}
type URL struct {
Urls []Urls `json:"urls"`
}
type Description struct {
Urls []interface{} `json:"urls"`
}
type UserEntities struct {
URL URL `json:"url"`
Description Description `json:"description"`
}
type User struct {
ProfileSidebarFillColor string `json:"profile_sidebar_fill_color"`
ProfileSidebarBorderColor string `json:"profile_sidebar_border_color"`
ProfileBackgroundTile bool `json:"profile_background_tile"`
Name string `json:"name"`
ProfileImageURL string `json:"profile_image_url"`
CreatedAt string `json:"created_at"`
Location string `json:"location"`
FollowRequestSent interface{} `json:"follow_request_sent"`
ProfileLinkColor string `json:"profile_link_color"`
IsTranslator bool `json:"is_translator"`
IDStr string `json:"id_str"`
Entities UserEntities `json:"entities"`
DefaultProfile bool `json:"default_profile"`
ContributorsEnabled bool `json:"contributors_enabled"`
FavouritesCount int `json:"favourites_count"`
URL interface{} `json:"url"`
ProfileImageURLHTTPS string `json:"profile_image_url_https"`
UtcOffset int `json:"utc_offset"`
ID int `json:"id"`
ProfileUseBackgroundImage bool `json:"profile_use_background_image"`
ListedCount int `json:"listed_count"`
ProfileTextColor string `json:"profile_text_color"`
Lang string `json:"lang"`
FollowersCount int `json:"followers_count"`
Protected bool `json:"protected"`
Notifications interface{} `json:"notifications"`
ProfileBackgroundImageURLHTTPS string `json:"profile_background_image_url_https"`
ProfileBackgroundColor string `json:"profile_background_color"`
Verified bool `json:"verified"`
GeoEnabled bool `json:"geo_enabled"`
TimeZone string `json:"time_zone"`
Description string `json:"description"`
DefaultProfileImage bool `json:"default_profile_image"`
ProfileBackgroundImageURL string `json:"profile_background_image_url"`
StatusesCount int `json:"statuses_count"`
FriendsCount int `json:"friends_count"`
Following interface{} `json:"following"`
ShowAllInlineMedia bool `json:"show_all_inline_media"`
ScreenName string `json:"screen_name"`
}
type Statuses struct {
Coordinates interface{} `json:"coordinates"`
Favorited bool `json:"favorited"`
Truncated bool `json:"truncated"`
CreatedAt string `json:"created_at"`
IDStr string `json:"id_str"`
Entities Entities `json:"entities"`
InReplyToUserIDStr interface{} `json:"in_reply_to_user_id_str"`
Contributors interface{} `json:"contributors"`
Text string `json:"text"`
Metadata Metadata `json:"metadata"`
RetweetCount int `json:"retweet_count"`
InReplyToStatusIDStr interface{} `json:"in_reply_to_status_id_str"`
ID int64 `json:"id"`
Geo interface{} `json:"geo"`
Retweeted bool `json:"retweeted"`
InReplyToUserID interface{} `json:"in_reply_to_user_id"`
Place interface{} `json:"place"`
User User `json:"user"`
InReplyToScreenName interface{} `json:"in_reply_to_screen_name"`
Source string `json:"source"`
InReplyToStatusID interface{} `json:"in_reply_to_status_id"`
}
type SearchMetadata struct {
MaxID int64 `json:"max_id"`
SinceID int64 `json:"since_id"`
RefreshURL string `json:"refresh_url"`
NextResults string `json:"next_results"`
Count int `json:"count"`
CompletedIn float64 `json:"completed_in"`
SinceIDStr string `json:"since_id_str"`
Query string `json:"query"`
MaxIDStr string `json:"max_id_str"`
}

View file

@ -0,0 +1,26 @@
module github.com/bytedance/sonic/external_jsonlib_test
go 1.18
require (
github.com/bytedance/sonic v1.4.0
github.com/goccy/go-json v0.9.11
github.com/json-iterator/go v1.1.12
github.com/stretchr/testify v1.8.0
github.com/tidwall/gjson v1.14.3
github.com/tidwall/sjson v1.2.5
)
require (
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View file

@ -0,0 +1,50 @@
github.com/bytedance/sonic v1.4.0 h1:d6vgPhwgHfpmEiz/9Fzea9fGzWY7RO1TQEySBiRwDLY=
github.com/bytedance/sonic v1.4.0/go.mod h1:V973WhNhGmvHxW6nQmsHEfHaoU9F3zTF+93rH03hcUQ=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View file

@ -14,13 +14,14 @@
* limitations under the License.
*/
package sonic
package unit_test
import (
`bytes`
`encoding/json`
`testing`
`github.com/bytedance/sonic`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/require`
)
@ -33,7 +34,7 @@ func TestCompatMarshalDefault(t *testing.T){
var obj = map[string]interface{}{
"c": json.RawMessage("[\"<&>\"]"),
}
sout, serr := ConfigDefault.Marshal(obj)
sout, serr := sonic.ConfigDefault.Marshal(obj)
jout, jerr := jt.Marshal(obj)
require.Equal(t, jerr, serr)
require.Equal(t, string(jout), string(sout))
@ -41,18 +42,18 @@ func TestCompatMarshalDefault(t *testing.T){
// obj = map[string]interface{}{
// "a": json.RawMessage(" [} "),
// }
// sout, serr = ConfigDefault.Marshal(obj)
// sout, serr = sonic.ConfigDefault.Marshal(obj)
// jout, jerr = json.Marshal(obj)
// require.NotNil(t, jerr)
// require.NotNil(t, serr)
// require.Equal(t, string(jout), string(sout))
obj = map[string]interface{}{
// require.Equal(t, string(jout), string(sout))
obj = map[string]interface{}{
"a": json.RawMessage("1"),
}
sout, serr = ConfigDefault.MarshalIndent(obj, "", " ")
sout, serr = sonic.ConfigDefault.MarshalIndent(obj, "", " ")
jout, jerr = jt.MarshalIndent(obj, "", " ")
require.Equal(t, jerr, serr)
require.Equal(t, jerr, serr)
require.Equal(t, string(jout), string(sout))
}
@ -62,7 +63,7 @@ func TestCompatMarshalStd(t *testing.T) {
"c": json.RawMessage(" [ \"<&>\" ] "),
"b": json.RawMessage(" [ ] "),
}
sout, serr := ConfigStd.Marshal(obj)
sout, serr := sonic.ConfigStd.Marshal(obj)
jout, jerr := json.Marshal(obj)
require.Equal(t, jerr, serr)
require.Equal(t, string(jout), string(sout))
@ -70,7 +71,7 @@ func TestCompatMarshalStd(t *testing.T) {
obj = map[string]interface{}{
"a": json.RawMessage(" [} "),
}
sout, serr = ConfigStd.Marshal(obj)
sout, serr = sonic.ConfigStd.Marshal(obj)
jout, jerr = json.Marshal(obj)
require.NotNil(t, jerr)
require.NotNil(t, serr)
@ -79,7 +80,7 @@ func TestCompatMarshalStd(t *testing.T) {
obj = map[string]interface{}{
"a": json.RawMessage("1"),
}
sout, serr = ConfigStd.MarshalIndent(obj, "xxxx", " ")
sout, serr = sonic.ConfigStd.MarshalIndent(obj, "xxxx", " ")
jout, jerr = json.MarshalIndent(obj, "xxxx", " ")
require.Equal(t, jerr, serr)
require.Equal(t, string(jout), string(sout))
@ -90,15 +91,15 @@ func TestCompatUnmarshalDefault(t *testing.T) {
var jobj = map[string]interface{}{}
var data = []byte(`{"a":-0}`)
var str = string(data)
serr := ConfigDefault.UnmarshalFromString(str, &sobj)
serr := sonic.ConfigDefault.UnmarshalFromString(str, &sobj)
jerr := jt.UnmarshalFromString(str, &jobj)
require.Equal(t, jerr, serr)
require.Equal(t, jobj, sobj)
require.Equal(t, jobj, sobj)
x := struct{A json.Number}{}
y := struct{A json.Number}{}
data = []byte(`{"A":"1", "B":-1}`)
serr = ConfigDefault.Unmarshal(data, &x)
serr = sonic.ConfigDefault.Unmarshal(data, &x)
jerr = jt.Unmarshal(data, &y)
require.Equal(t, jerr, serr)
require.Equal(t, y, x)
@ -109,7 +110,7 @@ func TestCompatUnmarshalStd(t *testing.T) {
var jobj = map[string]interface{}{}
var data = []byte(`{"a":1.00000001E-10}`)
var str = string(data)
serr := ConfigStd.UnmarshalFromString(str, &sobj)
serr := sonic.ConfigStd.UnmarshalFromString(str, &sobj)
jerr := json.Unmarshal(data, &jobj)
require.Equal(t, jerr, serr)
require.Equal(t, jobj, sobj)
@ -119,7 +120,7 @@ func TestCompatUnmarshalStd(t *testing.T) {
sobj = map[string]interface{}{}
jobj = map[string]interface{}{}
data = []byte(`{"a":1}`)
cfg := Config{
cfg := sonic.Config{
UseNumber: true,
}.Froze()
serr = cfg.Unmarshal(data, &sobj)
@ -132,7 +133,7 @@ func TestCompatUnmarshalStd(t *testing.T) {
x := struct{A json.Number}{}
y := struct{A json.Number}{}
data = []byte(`{"A":"1", "B":-1}`)
cfg = Config{
cfg = sonic.Config{
DisallowUnknownFields: true,
}.Froze()
serr = cfg.Unmarshal(data, &x)
@ -152,7 +153,7 @@ func TestCompatEncoderDefault(t *testing.T) {
var w1 = bytes.NewBuffer(nil)
var w2 = bytes.NewBuffer(nil)
var enc1 = jt.NewEncoder(w1)
var enc2 = ConfigDefault.NewEncoder(w2)
var enc2 = sonic.ConfigDefault.NewEncoder(w2)
require.Nil(t, enc1.Encode(o))
require.Nil(t, enc2.Encode(o))
@ -165,7 +166,7 @@ func TestCompatEncoderDefault(t *testing.T) {
require.Nil(t, enc1.Encode(o))
require.Nil(t, enc2.Encode(o))
require.Equal(t, w1.String(), w2.String())
enc1.SetEscapeHTML(false)
enc2.SetEscapeHTML(false)
enc1.SetIndent("", "")
@ -183,7 +184,7 @@ func TestCompatEncoderStd(t *testing.T) {
var w1 = bytes.NewBuffer(nil)
var w2 = bytes.NewBuffer(nil)
var enc1 = json.NewEncoder(w1)
var enc2 = ConfigStd.NewEncoder(w2)
var enc2 = sonic.ConfigStd.NewEncoder(w2)
require.Nil(t, enc1.Encode(o))
require.Nil(t, enc2.Encode(o))
@ -196,7 +197,7 @@ func TestCompatEncoderStd(t *testing.T) {
require.Nil(t, enc1.Encode(o))
require.Nil(t, enc2.Encode(o))
require.Equal(t, w1.String(), w2.String())
enc1.SetEscapeHTML(false)
enc2.SetEscapeHTML(false)
enc1.SetIndent("", "")
@ -213,7 +214,7 @@ func TestCompatDecoderStd(t *testing.T) {
var w1 = bytes.NewBuffer([]byte(s))
var w2 = bytes.NewBuffer([]byte(s))
var enc1 = json.NewDecoder(w1)
var enc2 = ConfigStd.NewDecoder(w2)
var enc2 = sonic.ConfigStd.NewDecoder(w2)
require.Equal(t, enc1.More(), enc2.More())
require.Nil(t, enc1.Decode(&o1))
@ -224,7 +225,7 @@ func TestCompatDecoderStd(t *testing.T) {
require.Nil(t, enc1.Decode(&o1))
require.Nil(t, enc2.Decode(&o2))
require.Equal(t, w1.String(), w2.String())
require.Equal(t, enc1.More(), enc2.More())
require.NotNil(t, enc1.Decode(&o1))
require.NotNil(t, enc2.Decode(&o2))
@ -238,7 +239,7 @@ func TestCompatDecoderDefault(t *testing.T) {
var w1 = bytes.NewBuffer([]byte(s))
var w2 = bytes.NewBuffer([]byte(s))
var enc1 = jt.NewDecoder(w1)
var enc2 = ConfigDefault.NewDecoder(w2)
var enc2 = sonic.ConfigDefault.NewDecoder(w2)
require.Equal(t, enc1.More(), enc2.More())
require.Nil(t, enc1.Decode(&o1))
@ -249,7 +250,7 @@ func TestCompatDecoderDefault(t *testing.T) {
require.Nil(t, enc1.Decode(&o1))
require.Nil(t, enc2.Decode(&o2))
require.Equal(t, w1.String(), w2.String())
require.Equal(t, enc1.More(), enc2.More())
require.NotNil(t, enc1.Decode(&o1))
require.NotNil(t, enc2.Decode(&o2))

View file

@ -14,11 +14,12 @@
* limitations under the License.
*/
package ast
package unit_test
import (
`testing`
`github.com/bytedance/sonic/ast`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/require`
`github.com/tidwall/gjson`
@ -35,8 +36,8 @@ func TestNotFoud(t *testing.T) {
require.True(t, ga.Type == gjson.Null)
require.Equal(t, false, ga.Bool())
sa, err := NewSearcher(data).GetByPath("b")
require.True(t, sa.Type() == V_NONE)
sa, err := ast.NewSearcher(data).GetByPath("b")
require.True(t, sa.Type() == ast.V_NONE)
require.Error(t, err)
sv, err := sa.Bool()
require.Error(t, err)
@ -54,10 +55,10 @@ func TestNull(t *testing.T) {
require.True(t, ga.Type == gjson.Null)
require.Equal(t, false, ga.Bool())
sa, err := NewSearcher(data).GetByPath("b")
require.True(t, sa.Type() == V_NULL)
sa, err := ast.NewSearcher(data).GetByPath("b")
require.True(t, sa.Type() == ast.V_NULL)
require.NoError(t, err)
sv, err := sa.Bool()
require.NoError(t, err)
require.Equal(t, false, sv)
}
}

View file

@ -0,0 +1,231 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package unit_test
import (
`io`
`strings`
`testing`
`github.com/bytedance/sonic/decoder`
jsoniter "github.com/json-iterator/go"
`github.com/stretchr/testify/assert`
`github.com/stretchr/testify/require`
)
var (
defaultBufferSize uint = 4096
_Single_JSON = `{"aaaaa":"` + strings.Repeat("b", int(defaultBufferSize)) + `"} { `
_Triple_JSON = `{"aaaaa":"` + strings.Repeat("b", int(defaultBufferSize)) + `"}{ } {"11111":"` +
strings.Repeat("2", int(defaultBufferSize)) + `"} b {}`
)
func TestDecodeSingle(t *testing.T) {
var str = _Single_JSON
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var r2 = strings.NewReader(str)
var v2 map[string]interface{}
var d2 = decoder.NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
es1 := d1.Decode(&v1)
ee1 := d2.Decode(&v2)
assert.Equal(t, es1, ee1)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
}
func TestDecodeMulti(t *testing.T) {
var str = _Triple_JSON
var r1 = strings.NewReader(str)
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var r2 = strings.NewReader(str)
var v2 map[string]interface{}
var d2 = decoder.NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
es1 := d1.Decode(&v1)
ee1 := d2.Decode(&v2)
assert.Equal(t, es1, ee1)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
// fmt.Printf("v:%#v\n", v1)
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
}
type HaltReader struct {
halts map[int]bool
buf string
p int
}
func NewHaltReader(buf string, halts map[int]bool) *HaltReader {
return &HaltReader{
halts: halts,
buf: buf,
p: 0,
}
}
func (self *HaltReader) Read(p []byte) (int, error) {
t := 0
for ; t < len(p); {
if self.p >= len(self.buf) {
return t, io.EOF
}
if b, ok := self.halts[self.p]; b {
self.halts[self.p] = false
return t, nil
} else if ok {
delete(self.halts, self.p)
return 0, nil
}
p[t] = self.buf[self.p]
self.p++
t++
}
return t, nil
}
func (self *HaltReader) Reset(buf string) {
self.p = 0
self.buf = buf
}
var testHalts = func() map[int]bool {
return map[int]bool{
1: true,
10: true,
20: true}
}
func TestDecodeHalt(t *testing.T) {
var str = _Triple_JSON
var r1 = NewHaltReader(str, testHalts())
var r2 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
var v2 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
var d2 = decoder.NewStreamDecoder(r2)
require.Equal(t, d1.More(), d2.More())
err1 := d1.Decode(&v1)
err2 := d2.Decode(&v2)
assert.Equal(t, err1, err2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
// assert.Equal(t, d1.InputOffset(), d2.InputOffset())
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
}
func TestMore(t *testing.T) {
var str = _Triple_JSON
var r2 = NewHaltReader(str, testHalts())
var v2 map[string]interface{}
var d2 = decoder.NewStreamDecoder(r2)
var r1 = NewHaltReader(str, testHalts())
var v1 map[string]interface{}
var d1 = jsoniter.NewDecoder(r1)
require.Nil(t, d1.Decode(&v1))
require.Nil(t, d2.Decode(&v2))
require.Equal(t, d1.More(), d2.More())
es4 := d1.Decode(&v1)
ee4 := d2.Decode(&v2)
assert.Equal(t, es4, ee4)
assert.Equal(t, v1, v2)
require.Equal(t, d1.More(), d2.More())
es2 := d1.Decode(&v1)
ee2 := d2.Decode(&v2)
assert.Equal(t, es2, ee2)
assert.Equal(t, v1, v2)
require.Equal(t, d1.More(), d2.More())
es3 := d1.Decode(&v1)
assert.NotNil(t, es3)
ee3 := d2.Decode(&v2)
assert.NotNil(t, ee3)
require.Equal(t, d1.More(), d2.More())
es5 := d1.Decode(&v1)
assert.NotNil(t, es5)
ee5 := d2.Decode(&v2)
assert.NotNil(t, ee5)
require.Equal(t, d1.More(), d2.More())
}

View file

@ -82,11 +82,18 @@ func fuzzMain(t *testing.T, data []byte) {
jout, jerr := json.Marshal(jv)
require.NoError(t, serr, "error in sonic marshal %v", reflect.TypeOf(jv))
require.NoError(t, jerr, "error in json marshal %v", reflect.TypeOf(jv))
// not comparing here because sonic marshal is different from encoding/json, as:
// case 1: 1.23e2 -> `1.23e2` in sonic, but 1.23e2 -> `1.23e+2` in encoding/json
// case 2: "\b" -> `\\b` in sonic, but `\u0008` in encoding/json
// require.Equal(t, sout, jout, "different in sonic marshal %v", reflect.TypeOf(jv))
var _, _ = sout, jout
{
sv, jv := typ(), typ()
serr := sonic.Unmarshal(sout, sv)
jerr := json.Unmarshal(jout, jv)
require.Equalf(t, serr != nil, jerr != nil, "different error in sonic unmarshal again %v", reflect.TypeOf(jv))
if jerr != nil {
return
}
require.Equal(t, sv, jv, "different result in sonic unmarshal again %v", reflect.TypeOf(jv))
}
if m, ok := sv.(*map[string]interface{}); ok {
fuzzDynamicStruct(t, jout, *m)
fuzzASTGetFromObject(t, jout, *m)

4
go.mod
View file

@ -5,12 +5,8 @@ go 1.15
require (
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06
github.com/davecgh/go-spew v1.1.1
github.com/goccy/go-json v0.9.4
github.com/json-iterator/go v1.1.12
github.com/klauspost/cpuid/v2 v2.0.9
github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.13.0
github.com/tidwall/sjson v1.2.4
github.com/twitchyliquid64/golang-asm v0.15.1
golang.org/x/arch v0.0.0-20210923205945-b76863e36670
)

19
go.sum
View file

@ -3,32 +3,13 @@ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=

View file

@ -4,4 +4,5 @@ use (
.
./generic_test
./fuzz
./external_jsonlib_test
)

View file

@ -26,7 +26,7 @@ import (
var (
HasAVX = cpuid.CPU.Has(cpuid.AVX)
HasAVX2 = cpuid.CPU.Has(cpuid.AVX2)
HasSSE4 = cpuid.CPU.Has(cpuid.SSE4)
HasSSE = cpuid.CPU.Has(cpuid.SSE)
)
func init() {

View file

@ -22,6 +22,8 @@ import (
`math`
`strconv`
`testing`
`math/rand`
`encoding/json`
`github.com/stretchr/testify/assert`
)
@ -33,52 +35,106 @@ func TestFastFloat_Encode(t *testing.T) {
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1e+30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1e+30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func BenchmarkFastFloat_Encode(b *testing.B) {
val := -2.2250738585072014e-308
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func TestFastFloat_Random(t *testing.T) {
var buf [64]byte
N := 10000
for i := 0; i < N; i++ {
b64 := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
f64 := math.Float64frombits(b64)
jout, jerr := json.Marshal(f64)
n := __f64toa(&buf[0], f64)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
f32 := math.Float32frombits(rand.Uint32())
jout, jerr = json.Marshal(f32)
n = __f32toa(&buf[0], f32)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func BenchmarkParseFloat64(b *testing.B) {
var f64toaBenches = []struct {
name string
float float64
}{
{"Zero", 0},
{"Decimal", 33909},
{"Float", 339.7784},
{"Exp", -5.09e75},
{"NegExp", -5.11e-95},
{"LongExp", 1.234567890123456e-78},
{"Big", 123456789123456789123456789},
}
for _, c := range f64toaBenches {
f64bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
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) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkParseFloat32(b *testing.B) {
var f32toaBenches = []struct {
name string
float float32
}{
{"Zero", 0},
{"Integer", 33909},
{"ExactFraction", 3.375},
{"Point", 339.7784},
{"Exp", -5.09e25},
{"NegExp", -5.11e-25},
{"Shortest", 1.234567e-8},
}
for _, c := range f32toaBenches {
bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib32",
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) }},
}, {
name: "FastFloat32",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f32toa(&buf[0], c.float) }},
}}
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}

View file

@ -21,6 +21,7 @@ package avx
import (
`strconv`
`testing`
`fmt`
`github.com/stretchr/testify/assert`
)
@ -96,40 +97,57 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}

View file

@ -42,7 +42,7 @@ func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lzero(p unsafe.Pointer, n int) (ret int)
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@ package avx
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace

View file

@ -9,32 +9,32 @@ package avx
func __native_entry__() uintptr
var (
_subr__f64toa = __native_entry__() + 704
_subr__html_escape = __native_entry__() + 9920
_subr__i64toa = __native_entry__() + 3616
_subr__lspace = __native_entry__() + 320
_subr__lzero = __native_entry__() + 16
_subr__quote = __native_entry__() + 4992
_subr__skip_array = __native_entry__() + 22304
_subr__skip_number = __native_entry__() + 23776
_subr__skip_object = __native_entry__() + 22352
_subr__skip_one = __native_entry__() + 20432
_subr__u64toa = __native_entry__() + 3728
_subr__unquote = __native_entry__() + 6736
_subr__validate_one = __native_entry__() + 23920
_subr__value = __native_entry__() + 13168
_subr__vnumber = __native_entry__() + 18176
_subr__vsigned = __native_entry__() + 19728
_subr__vstring = __native_entry__() + 15248
_subr__vunsigned = __native_entry__() + 20080
_subr__f32toa = __native_entry__() + 24592
_subr__f64toa = __native_entry__() + 496
_subr__html_escape = __native_entry__() + 10480
_subr__i64toa = __native_entry__() + 4176
_subr__lspace = __native_entry__() + 80
_subr__quote = __native_entry__() + 5552
_subr__skip_array = __native_entry__() + 22864
_subr__skip_number = __native_entry__() + 24336
_subr__skip_object = __native_entry__() + 22912
_subr__skip_one = __native_entry__() + 20992
_subr__u64toa = __native_entry__() + 4288
_subr__unquote = __native_entry__() + 7296
_subr__validate_one = __native_entry__() + 24480
_subr__value = __native_entry__() + 13728
_subr__vnumber = __native_entry__() + 18736
_subr__vsigned = __native_entry__() + 20288
_subr__vstring = __native_entry__() + 15808
_subr__vunsigned = __native_entry__() + 20640
)
const (
_stack__f64toa = 128
_stack__f32toa = 64
_stack__f64toa = 80
_stack__html_escape = 64
_stack__i64toa = 16
_stack__lspace = 8
_stack__lzero = 8
_stack__quote = 80
_stack__skip_array = 128
_stack__skip_number = 72
@ -51,11 +51,11 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__lzero
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
@ -72,11 +72,11 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__lzero
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number

View file

@ -22,6 +22,8 @@ import (
`math`
`strconv`
`testing`
`math/rand`
`encoding/json`
`github.com/stretchr/testify/assert`
)
@ -33,52 +35,106 @@ func TestFastFloat_Encode(t *testing.T) {
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1e+30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1e+30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func BenchmarkFastFloat_Encode(b *testing.B) {
val := -2.2250738585072014e-308
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func TestFastFloat_Random(t *testing.T) {
var buf [64]byte
N := 10000
for i := 0; i < N; i++ {
b64 := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
f64 := math.Float64frombits(b64)
jout, jerr := json.Marshal(f64)
n := __f64toa(&buf[0], f64)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
f32 := math.Float32frombits(rand.Uint32())
jout, jerr = json.Marshal(f32)
n = __f32toa(&buf[0], f32)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func BenchmarkParseFloat64(b *testing.B) {
var f64toaBenches = []struct {
name string
float float64
}{
{"Zero", 0},
{"Decimal", 33909},
{"Float", 339.7784},
{"Exp", -5.09e75},
{"NegExp", -5.11e-95},
{"LongExp", 1.234567890123456e-78},
{"Big", 123456789123456789123456789},
}
for _, c := range f64toaBenches {
f64bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
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) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkParseFloat32(b *testing.B) {
var f32toaBenches = []struct {
name string
float float32
}{
{"Zero", 0},
{"Integer", 33909},
{"ExactFraction", 3.375},
{"Point", 339.7784},
{"Exp", -5.09e25},
{"NegExp", -5.11e-25},
{"Shortest", 1.234567e-8},
}
for _, c := range f32toaBenches {
bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib32",
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) }},
}, {
name: "FastFloat32",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f32toa(&buf[0], c.float) }},
}}
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}

View file

@ -21,6 +21,7 @@ package avx2
import (
`strconv`
`testing`
`fmt`
`github.com/stretchr/testify/assert`
)
@ -96,40 +97,57 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}

View file

@ -42,7 +42,7 @@ func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lzero(p unsafe.Pointer, n int) (ret int)
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@ package avx2
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace

View file

@ -9,32 +9,32 @@ package avx2
func __native_entry__() uintptr
var (
_subr__f64toa = __native_entry__() + 960
_subr__html_escape = __native_entry__() + 11776
_subr__i64toa = __native_entry__() + 3872
_subr__lspace = __native_entry__() + 448
_subr__lzero = __native_entry__() + 16
_subr__quote = __native_entry__() + 5360
_subr__skip_array = __native_entry__() + 25568
_subr__skip_number = __native_entry__() + 27664
_subr__skip_object = __native_entry__() + 25616
_subr__skip_one = __native_entry__() + 23664
_subr__u64toa = __native_entry__() + 3984
_subr__unquote = __native_entry__() + 8304
_subr__validate_one = __native_entry__() + 27808
_subr__value = __native_entry__() + 16352
_subr__vnumber = __native_entry__() + 21408
_subr__vsigned = __native_entry__() + 22960
_subr__vstring = __native_entry__() + 18736
_subr__vunsigned = __native_entry__() + 23312
_subr__f32toa = __native_entry__() + 28464
_subr__f64toa = __native_entry__() + 752
_subr__html_escape = __native_entry__() + 12320
_subr__i64toa = __native_entry__() + 4432
_subr__lspace = __native_entry__() + 224
_subr__quote = __native_entry__() + 5904
_subr__skip_array = __native_entry__() + 26112
_subr__skip_number = __native_entry__() + 28208
_subr__skip_object = __native_entry__() + 26160
_subr__skip_one = __native_entry__() + 24208
_subr__u64toa = __native_entry__() + 4544
_subr__unquote = __native_entry__() + 8848
_subr__validate_one = __native_entry__() + 28352
_subr__value = __native_entry__() + 16896
_subr__vnumber = __native_entry__() + 21952
_subr__vsigned = __native_entry__() + 23504
_subr__vstring = __native_entry__() + 19280
_subr__vunsigned = __native_entry__() + 23856
)
const (
_stack__f64toa = 128
_stack__f32toa = 64
_stack__f64toa = 80
_stack__html_escape = 72
_stack__i64toa = 16
_stack__lspace = 8
_stack__lzero = 8
_stack__quote = 72
_stack__skip_array = 136
_stack__skip_number = 80
@ -51,11 +51,11 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__lzero
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
@ -72,11 +72,11 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__lzero
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number

View file

@ -22,7 +22,7 @@ import (
`github.com/bytedance/sonic/internal/cpu`
`github.com/bytedance/sonic/internal/native/avx`
`github.com/bytedance/sonic/internal/native/avx2`
`github.com/bytedance/sonic/internal/native/sse4`
`github.com/bytedance/sonic/internal/native/sse`
`github.com/bytedance/sonic/internal/native/types`
)
@ -30,6 +30,7 @@ const MaxFrameSize uintptr = 400
var (
S_f64toa uintptr
S_f32toa uintptr
S_i64toa uintptr
S_u64toa uintptr
S_lspace uintptr
@ -97,6 +98,7 @@ func U64toa(out *byte, val uint64) (ret int)
func useAVX() {
S_f64toa = avx.S_f64toa
S_f32toa = avx.S_f32toa
S_i64toa = avx.S_i64toa
S_u64toa = avx.S_u64toa
S_lspace = avx.S_lspace
@ -115,6 +117,7 @@ func useAVX() {
func useAVX2() {
S_f64toa = avx2.S_f64toa
S_f32toa = avx2.S_f32toa
S_i64toa = avx2.S_i64toa
S_u64toa = avx2.S_u64toa
S_lspace = avx2.S_lspace
@ -131,22 +134,23 @@ func useAVX2() {
S_skip_number = avx2.S_skip_number
}
func useSSE4() {
S_f64toa = sse4.S_f64toa
S_i64toa = sse4.S_i64toa
S_u64toa = sse4.S_u64toa
S_lspace = sse4.S_lspace
S_quote = sse4.S_quote
S_unquote = sse4.S_unquote
S_value = sse4.S_value
S_vstring = sse4.S_vstring
S_vnumber = sse4.S_vnumber
S_vsigned = sse4.S_vsigned
S_vunsigned = sse4.S_vunsigned
S_skip_one = sse4.S_skip_one
S_skip_array = sse4.S_skip_array
S_skip_object = sse4.S_skip_object
S_skip_number = sse4.S_skip_number
func useSSE() {
S_f64toa = sse.S_f64toa
S_f32toa = sse.S_f32toa
S_i64toa = sse.S_i64toa
S_u64toa = sse.S_u64toa
S_lspace = sse.S_lspace
S_quote = sse.S_quote
S_unquote = sse.S_unquote
S_value = sse.S_value
S_vstring = sse.S_vstring
S_vnumber = sse.S_vnumber
S_vsigned = sse.S_vsigned
S_vunsigned = sse.S_vunsigned
S_skip_one = sse.S_skip_one
S_skip_array = sse.S_skip_array
S_skip_object = sse.S_skip_object
S_skip_number = sse.S_skip_number
}
func init() {
@ -154,8 +158,8 @@ func init() {
useAVX2()
} else if cpu.HasAVX {
useAVX()
} else if cpu.HasSSE4 {
useSSE4()
} else if cpu.HasSSE {
useSSE()
} else {
panic("Unsupported CPU, maybe it's too old to run Sonic.")
}

View file

@ -25,7 +25,7 @@ TEXT ·Quote(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__quote(SB)
JMP github·combytedancesonicinternalnativesse4·__quote(SB)
JMP github·combytedancesonicinternalnativesse·__quote(SB)
TEXT ·Unquote(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -34,7 +34,7 @@ TEXT ·Unquote(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__unquote(SB)
JMP github·combytedancesonicinternalnativesse4·__unquote(SB)
JMP github·combytedancesonicinternalnativesse·__unquote(SB)
TEXT ·HTMLEscape(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -43,7 +43,7 @@ TEXT ·HTMLEscape(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__html_escape(SB)
JMP github·combytedancesonicinternalnativesse4·__html_escape(SB)
JMP github·combytedancesonicinternalnativesse·__html_escape(SB)
TEXT ·Value(SB), NOSPLIT, $0 - 48
@ -53,7 +53,7 @@ TEXT ·Value(SB), NOSPLIT, $0 - 48
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__value(SB)
JMP github·combytedancesonicinternalnativesse4·__value(SB)
JMP github·combytedancesonicinternalnativesse·__value(SB)
TEXT ·SkipOne(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -62,7 +62,7 @@ TEXT ·SkipOne(SB), NOSPLIT, $0 - 40
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__skip_one(SB)
JMP github·combytedancesonicinternalnativesse4·__skip_one(SB)
JMP github·combytedancesonicinternalnativesse·__skip_one(SB)
TEXT ·ValidateOne(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -71,7 +71,7 @@ TEXT ·ValidateOne(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__validate_one(SB)
JMP github·combytedancesonicinternalnativesse4·__validate_one(SB)
JMP github·combytedancesonicinternalnativesse·__validate_one(SB)
TEXT ·I64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -80,7 +80,7 @@ TEXT ·I64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__i64toa(SB)
JMP github·combytedancesonicinternalnativesse4·__i64toa(SB)
JMP github·combytedancesonicinternalnativesse·__i64toa(SB)
TEXT ·U64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX2(SB), $0
@ -89,5 +89,5 @@ TEXT ·U64toa(SB), NOSPLIT, $0 - 32
CMPB github·combytedancesonicinternalcpu·HasAVX(SB), $0
JE 2(PC)
JMP github·combytedancesonicinternalnativeavx·__u64toa(SB)
JMP github·combytedancesonicinternalnativesse4·__u64toa(SB)
JMP github·combytedancesonicinternalnativesse·__u64toa(SB)

View file

@ -20,6 +20,8 @@ import (
`math`
`strconv`
`testing`
`math/rand`
`encoding/json`
`github.com/stretchr/testify/assert`
)
@ -31,52 +33,106 @@ func TestFastFloat_Encode(t *testing.T) {
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1e+30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1e+30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func BenchmarkFastFloat_Encode(b *testing.B) {
val := -2.2250738585072014e-308
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func TestFastFloat_Random(t *testing.T) {
var buf [64]byte
N := 10000
for i := 0; i < N; i++ {
b64 := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
f64 := math.Float64frombits(b64)
jout, jerr := json.Marshal(f64)
n := __f64toa(&buf[0], f64)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
f32 := math.Float32frombits(rand.Uint32())
jout, jerr = json.Marshal(f32)
n = __f32toa(&buf[0], f32)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
func BenchmarkParseFloat64(b *testing.B) {
var f64toaBenches = []struct {
name string
float float64
}{
{"Zero", 0},
{"Decimal", 33909},
{"Float", 339.7784},
{"Exp", -5.09e75},
{"NegExp", -5.11e-95},
{"LongExp", 1.234567890123456e-78},
{"Big", 123456789123456789123456789},
}
for _, c := range f64toaBenches {
f64bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
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) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkParseFloat32(b *testing.B) {
var f32toaBenches = []struct {
name string
float float32
}{
{"Zero", 0},
{"Integer", 33909},
{"ExactFraction", 3.375},
{"Point", 339.7784},
{"Exp", -5.09e25},
{"NegExp", -5.11e-25},
{"Shortest", 1.234567e-8},
}
for _, c := range f32toaBenches {
bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib32",
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) }},
}, {
name: "FastFloat32",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f32toa(&buf[0], c.float) }},
}}
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}

View file

@ -19,6 +19,7 @@ package {{PACKAGE}}
import (
`strconv`
`testing`
`fmt`
`github.com/stretchr/testify/assert`
)
@ -94,40 +95,57 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}

View file

@ -40,7 +40,7 @@ func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lzero(p unsafe.Pointer, n int) (ret int)
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape

View file

@ -18,6 +18,7 @@ package {{PACKAGE}}
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace

View file

@ -0,0 +1,140 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sse
import (
`math`
`strconv`
`testing`
`math/rand`
`encoding/json`
`github.com/stretchr/testify/assert`
)
func TestFastFloat_Encode(t *testing.T) {
var buf [64]byte
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], 0)]))
assert.Equal(t, "-0" , string(buf[:__f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e+30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e+33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e+308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e+308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e+30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e+33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e+308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func TestFastFloat_Random(t *testing.T) {
var buf [64]byte
N := 10000
for i := 0; i < N; i++ {
b64 := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
f64 := math.Float64frombits(b64)
jout, jerr := json.Marshal(f64)
n := __f64toa(&buf[0], f64)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
f32 := math.Float32frombits(rand.Uint32())
jout, jerr = json.Marshal(f32)
n = __f32toa(&buf[0], f32)
if jerr == nil {
assert.Equal(t, jout, buf[:n])
} else {
assert.True(t, n == 0)
}
}
}
func BenchmarkParseFloat64(b *testing.B) {
var f64toaBenches = []struct {
name string
float float64
}{
{"Zero", 0},
{"Decimal", 33909},
{"Float", 339.7784},
{"Exp", -5.09e75},
{"NegExp", -5.11e-95},
{"LongExp", 1.234567890123456e-78},
{"Big", 123456789123456789123456789},
}
for _, c := range f64toaBenches {
f64bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
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) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkParseFloat32(b *testing.B) {
var f32toaBenches = []struct {
name string
float float32
}{
{"Zero", 0},
{"Integer", 33909},
{"ExactFraction", 3.375},
{"Point", 339.7784},
{"Exp", -5.09e25},
{"NegExp", -5.11e-25},
{"Shortest", 1.234567e-8},
}
for _, c := range f32toaBenches {
bench := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib32",
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) }},
}, {
name: "FastFloat32",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f32toa(&buf[0], c.float) }},
}}
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}

View file

@ -16,11 +16,12 @@
* limitations under the License.
*/
package sse4
package sse
import (
`strconv`
`testing`
`fmt`
`github.com/stretchr/testify/assert`
)
@ -96,40 +97,57 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:], uint64(i), 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], uint64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastInt_IntToString(b *testing.B) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], int64(i), 10) }},
}, {
name: "StdLib-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendInt(buf[:0], -int64(i), 10) }},
}, {
name: "FastInt-Positive",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], int64(i)) }},
}, {
name: "FastInt-Negative",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __i64toa(&buf[0], -int64(i)) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
type utoaBench struct {
name string
num uint64
}
func BenchmarkFastInt_UintToString(b *testing.B) {
maxUint := "18446744073709551615"
benchs := make([]utoaBench, len(maxUint) + 1)
benchs[0].name = "Zero"
benchs[0].num = 0
for i := 1; i <= len(maxUint); i++ {
benchs[i].name = strconv.FormatInt(int64(i), 10) + "-Digs"
benchs[i].num, _ = strconv.ParseUint(string(maxUint[:i]), 10, 64)
}
for _, t := range(benchs) {
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { strconv.AppendUint(buf[:0], t.num, 10) }},
}, {
name: "FastInt",
test: func(b *testing.B) { var buf [32]byte; for i := 0; i < b.N; i++ { __u64toa(&buf[0], t.num) }},
}}
for _, bm := range benchmarks {
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}

View file

@ -16,7 +16,7 @@
* limitations under the License.
*/
package sse4
package sse
import (
`unsafe`
@ -42,7 +42,7 @@ func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __lzero(p unsafe.Pointer, n int) (ret int)
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape

View file

@ -16,7 +16,7 @@
* limitations under the License.
*/
package sse4
package sse
import (
`encoding/hex`

View file

@ -16,10 +16,11 @@
* limitations under the License.
*/
package sse4
package sse
var (
S_f64toa = _subr__f64toa
S_f32toa = _subr__f32toa
S_i64toa = _subr__i64toa
S_u64toa = _subr__u64toa
S_lspace = _subr__lspace

View file

@ -1,7 +1,7 @@
// +build !noasm !appengine
// Code generated by asm2asm, DO NOT EDIT.
package sse4
package sse
//go:nosplit
//go:noescape
@ -9,32 +9,32 @@ package sse4
func __native_entry__() uintptr
var (
_subr__f64toa = __native_entry__() + 640
_subr__html_escape = __native_entry__() + 9808
_subr__i64toa = __native_entry__() + 3440
_subr__lspace = __native_entry__() + 256
_subr__lzero = __native_entry__() + 16
_subr__quote = __native_entry__() + 4848
_subr__skip_array = __native_entry__() + 22320
_subr__skip_number = __native_entry__() + 23824
_subr__skip_object = __native_entry__() + 22368
_subr__skip_one = __native_entry__() + 20448
_subr__u64toa = __native_entry__() + 3568
_subr__unquote = __native_entry__() + 6624
_subr__validate_one = __native_entry__() + 23968
_subr__value = __native_entry__() + 13072
_subr__vnumber = __native_entry__() + 18192
_subr__vsigned = __native_entry__() + 19744
_subr__vstring = __native_entry__() + 15152
_subr__vunsigned = __native_entry__() + 20096
_subr__f32toa = __native_entry__() + 24640
_subr__f64toa = __native_entry__() + 464
_subr__html_escape = __native_entry__() + 10416
_subr__i64toa = __native_entry__() + 4048
_subr__lspace = __native_entry__() + 80
_subr__quote = __native_entry__() + 5456
_subr__skip_array = __native_entry__() + 22928
_subr__skip_number = __native_entry__() + 24432
_subr__skip_object = __native_entry__() + 22976
_subr__skip_one = __native_entry__() + 21056
_subr__u64toa = __native_entry__() + 4176
_subr__unquote = __native_entry__() + 7232
_subr__validate_one = __native_entry__() + 24576
_subr__value = __native_entry__() + 13680
_subr__vnumber = __native_entry__() + 18800
_subr__vsigned = __native_entry__() + 20352
_subr__vstring = __native_entry__() + 15760
_subr__vunsigned = __native_entry__() + 20704
)
const (
_stack__f64toa = 128
_stack__f32toa = 64
_stack__f64toa = 80
_stack__html_escape = 64
_stack__i64toa = 16
_stack__lspace = 8
_stack__lzero = 8
_stack__quote = 80
_stack__skip_array = 128
_stack__skip_number = 72
@ -51,11 +51,11 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
_ = _subr__lspace
_ = _subr__lzero
_ = _subr__quote
_ = _subr__skip_array
_ = _subr__skip_number
@ -72,11 +72,11 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa
_ = _stack__lspace
_ = _stack__lzero
_ = _stack__quote
_ = _stack__skip_array
_ = _stack__skip_number

View file

@ -1,84 +0,0 @@
// Code generated by Makefile, DO NOT EDIT.
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sse4
import (
`math`
`strconv`
`testing`
`github.com/stretchr/testify/assert`
)
func TestFastFloat_Encode(t *testing.T) {
var buf [64]byte
assert.Equal(t, "0" , string(buf[:__f64toa(&buf[0], 0)]))
assert.Equal(t, "-0" , string(buf[:__f64toa(&buf[0], math.Float64frombits(0x8000000000000000))]))
assert.Equal(t, "12340000000" , string(buf[:__f64toa(&buf[0], 1234e7)]))
assert.Equal(t, "12.34" , string(buf[:__f64toa(&buf[0], 1234e-2)]))
assert.Equal(t, "0.001234" , string(buf[:__f64toa(&buf[0], 1234e-6)]))
assert.Equal(t, "1e30" , string(buf[:__f64toa(&buf[0], 1e30)]))
assert.Equal(t, "1.234e33" , string(buf[:__f64toa(&buf[0], 1234e30)]))
assert.Equal(t, "1.234e308" , string(buf[:__f64toa(&buf[0], 1234e305)]))
assert.Equal(t, "1.234e-317" , string(buf[:__f64toa(&buf[0], 1234e-320)]))
assert.Equal(t, "1.7976931348623157e308" , string(buf[:__f64toa(&buf[0], 1.7976931348623157e308)]))
assert.Equal(t, "-12340000000" , string(buf[:__f64toa(&buf[0], -1234e7)]))
assert.Equal(t, "-12.34" , string(buf[:__f64toa(&buf[0], -1234e-2)]))
assert.Equal(t, "-0.001234" , string(buf[:__f64toa(&buf[0], -1234e-6)]))
assert.Equal(t, "-1e30" , string(buf[:__f64toa(&buf[0], -1e30)]))
assert.Equal(t, "-1.234e33" , string(buf[:__f64toa(&buf[0], -1234e30)]))
assert.Equal(t, "-1.234e308" , string(buf[:__f64toa(&buf[0], -1234e305)]))
assert.Equal(t, "-1.234e-317" , string(buf[:__f64toa(&buf[0], -1234e-320)]))
assert.Equal(t, "-2.2250738585072014e-308" , string(buf[:__f64toa(&buf[0], -2.2250738585072014e-308)]))
}
func BenchmarkFastFloat_Encode(b *testing.B) {
val := -2.2250738585072014e-308
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
name string
test func(*testing.B)
}{{
name: "StdLib",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { strconv.AppendFloat(buf[:], val, 'g', -1, 64) }},
}, {
name: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}

View file

@ -80,7 +80,7 @@ var issue13ExpectedNonemptyOpt = `{
"uint32": 32,
"uint64": 64,
"float32": 1,
"float64": -2.34e64,
"float64": -2.34e+64,
"uintptr": 1,
"string": "string",
"array": [

View file

@ -1,3 +1,19 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package issue_test
import (

View file

@ -1,3 +1,19 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package issue_test
import (

View file

@ -0,0 +1,40 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package issue_test
import (
`testing`
`encoding/json`
`github.com/bytedance/sonic`
`github.com/stretchr/testify/require`
)
func TestMarshal_Float32To64(t *testing.T) {
var f float32 = 0.1
oe,ee := json.Marshal(f)
os,es := sonic.Marshal(f)
require.Equal(t, ee == nil, es == nil)
require.Equal(t, string(oe), string(os))
var f2,f3 float64
require.Nil(t, json.Unmarshal(oe, &f2))
require.Nil(t, sonic.Unmarshal(os, &f3))
require.Equal(t, f2, f3)
}

View file

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

452
native/f32toa.c Normal file
View file

@ -0,0 +1,452 @@
/* Copyright 2020 Alexander Bolz
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* Unless required by applicable law or agreed to in writing, this software
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.
*
* This file may have been modified by ByteDance authors. All ByteDance
* Modifications are Copyright 2022 ByteDance Authors.
*/
#include "native.h"
#include "tab.h"
#include "test/xassert.h"
#define F32_BITS 32
#define F32_EXP_BITS 8
#define F32_SIG_BITS 23
#define F32_EXP_MASK 0x7F800000u // middle 8 bits
#define F32_SIG_MASK 0x007FFFFFu // lower 23 bits
#define F32_EXP_BIAS 127
#define F32_INF_NAN_EXP 0xFF
#define F32_HIDDEN_BIT 0x00800000u
typedef struct {
uint32_t sig;
int32_t exp;
} f32_dec;
static inline unsigned ctz10_u32(const uint32_t v) {
xassert(0 <= v && v < 1000000000u);
if (v >= 100000) {
if (v < 1000000) return 6;
if (v < 10000000) return 7;
if (v < 100000000) return 8;
return 9;
} else {
if (v < 10) return 1;
if (v < 100) return 2;
if (v < 1000) return 3;
if (v < 10000) return 4;
return 5;
}
}
static inline char* format_significand_f32(uint32_t sig, char *out, int cnt) {
char *r = out + cnt;
int ctz = 0;
/* at most 9 digits here */
if (sig >= 10000) {
uint32_t c = sig - 10000 * (sig / 10000);
sig /= 10000;
if (c != 0) {
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
copy_two_digs(r - 2, Digits + c0);
copy_two_digs(r - 4, Digits + c1);
} else {
ctz = 4;
}
r -= 4;
}
while (sig >= 100) {
uint32_t c = (sig % 100) << 1;
sig /= 100;
copy_two_digs(r - 2, Digits + c);
r -= 2;
}
if (sig >= 10) {
uint32_t c = sig << 1;
copy_two_digs(out, Digits + c);
} else {
*out = (char) ('0' + sig);
}
return out + cnt - ctz;
}
static inline char* format_integer_u32(uint32_t sig, char *out, unsigned cnt) {
char *r = out + cnt;
/* at most 9 digits here */
if (sig >= 10000) {
uint32_t c = sig - 10000 * (sig / 10000);
sig /= 10000;
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
copy_two_digs(r - 2, Digits + c0);
copy_two_digs(r - 4, Digits + c1);
r -= 4;
}
while (sig >= 100) {
uint32_t c = (sig % 100) << 1;
sig /= 100;
copy_two_digs(r - 2, Digits + c);
r -= 2;
}
if (sig >= 10) {
uint32_t c = sig << 1;
copy_two_digs(out, Digits + c);
} else {
*out = (char) ('0' + sig);
}
return out + cnt;
}
static inline char* format_exponent_f32(f32_dec v, char *out, int cnt) {
char* p = out + 1;
char* end = format_significand_f32(v.sig, p, cnt);
while (*(end - 1) == '0') end--;
/* Print decimal point if needed */
*out = *p;
if (end - p > 1) {
*p = '.';
} else {
end--;
}
/* Print the exponent */
*end++ = 'e';
int32_t exp = v.exp + (int32_t) cnt - 1;
if (exp < 0) {
*end++ = '-';
exp = -exp;
} else {
*end++ = '+';
}
if (exp >= 100) {
int32_t c = exp % 10;
copy_two_digs(end, Digits + 2 * (exp / 10));
end[2] = (char) ('0' + c);
end += 3;
} else if (exp >= 10) {
copy_two_digs(end, Digits + 2 * exp);
end += 2;
} else {
*end++ = (char) ('0' + exp);
}
return end;
}
static inline char* format_decimal_f32(f32_dec v, char* out, int cnt) {
char* p = out;
char* end;
int point = cnt + v.exp;
/* print leading zeros if fp < 1 */
if (point <= 0) {
*p++ = '0', *p++ = '.';
for (int i = 0; i < -point; i++) {
*p++ = '0';
}
}
/* add the remaining digits */
end = format_significand_f32(v.sig, p, cnt);
while (*(end - 1) == '0') end--;
if (point <= 0) {
return end;
}
/* insert point or add trailing zeros */
int digs = end - p, frac = digs - point;
if (digs > point) {
for (int i = 0; i < frac; i++) {
*(end - i) = *(end - i - 1);
}
p[point] = '.';
end++;
} else {
for (int i = 0; i < point - digs; i++) {
*end++ = '0';
}
}
return end;
}
static inline char* write_dec_f32(f32_dec dec, char* p) {
int cnt = ctz10_u32(dec.sig);
int dot = cnt + dec.exp;
int sci_exp = dot - 1;
bool exp_fmt = sci_exp < -6 || sci_exp > 20;
bool has_dot = dot < cnt;
if (exp_fmt) {
return format_exponent_f32(dec, p, cnt);
}
if (has_dot) {
return format_decimal_f32(dec, p, cnt);
}
char* end = p + dot;
p = format_integer_u32(dec.sig, p, cnt);
while (p < end) *p++ = '0';
return end;
}
static inline uint32_t f32toraw(float fp) {
union {
uint32_t u32;
float f32;
} uval;
uval.f32 = fp;
return uval.u32;
}
static inline uint64_t pow10_ceil_sig_f32(int32_t k)
{
// There are unique beta and r such that 10^k = beta 2^r and
// 2^63 <= beta < 2^64, namely r = floor(log_2 10^k) - 63 and
// beta = 2^-r 10^k.
// Let g = ceil(beta), so (g-1) 2^r < 10^k <= g 2^r, with the latter
// value being a pretty good overestimate for 10^k.
// NB: Since for all the required exponents k, we have g < 2^64,
// all constants can be stored in 128-bit integers.
// reference from:
// https://github.com/abolz/Drachennest/blob/master/src/schubfach_32.cc#L144
#define KMAX 45
#define KMIN -31
static const uint64_t g[KMAX - KMIN + 1] = {
0x81CEB32C4B43FCF5, // -31
0xA2425FF75E14FC32, // -30
0xCAD2F7F5359A3B3F, // -29
0xFD87B5F28300CA0E, // -28
0x9E74D1B791E07E49, // -27
0xC612062576589DDB, // -26
0xF79687AED3EEC552, // -25
0x9ABE14CD44753B53, // -24
0xC16D9A0095928A28, // -23
0xF1C90080BAF72CB2, // -22
0x971DA05074DA7BEF, // -21
0xBCE5086492111AEB, // -20
0xEC1E4A7DB69561A6, // -19
0x9392EE8E921D5D08, // -18
0xB877AA3236A4B44A, // -17
0xE69594BEC44DE15C, // -16
0x901D7CF73AB0ACDA, // -15
0xB424DC35095CD810, // -14
0xE12E13424BB40E14, // -13
0x8CBCCC096F5088CC, // -12
0xAFEBFF0BCB24AAFF, // -11
0xDBE6FECEBDEDD5BF, // -10
0x89705F4136B4A598, // -9
0xABCC77118461CEFD, // -8
0xD6BF94D5E57A42BD, // -7
0x8637BD05AF6C69B6, // -6
0xA7C5AC471B478424, // -5
0xD1B71758E219652C, // -4
0x83126E978D4FDF3C, // -3
0xA3D70A3D70A3D70B, // -2
0xCCCCCCCCCCCCCCCD, // -1
0x8000000000000000, // 0
0xA000000000000000, // 1
0xC800000000000000, // 2
0xFA00000000000000, // 3
0x9C40000000000000, // 4
0xC350000000000000, // 5
0xF424000000000000, // 6
0x9896800000000000, // 7
0xBEBC200000000000, // 8
0xEE6B280000000000, // 9
0x9502F90000000000, // 10
0xBA43B74000000000, // 11
0xE8D4A51000000000, // 12
0x9184E72A00000000, // 13
0xB5E620F480000000, // 14
0xE35FA931A0000000, // 15
0x8E1BC9BF04000000, // 16
0xB1A2BC2EC5000000, // 17
0xDE0B6B3A76400000, // 18
0x8AC7230489E80000, // 19
0xAD78EBC5AC620000, // 20
0xD8D726B7177A8000, // 21
0x878678326EAC9000, // 22
0xA968163F0A57B400, // 23
0xD3C21BCECCEDA100, // 24
0x84595161401484A0, // 25
0xA56FA5B99019A5C8, // 26
0xCECB8F27F4200F3A, // 27
0x813F3978F8940985, // 28
0xA18F07D736B90BE6, // 29
0xC9F2C9CD04674EDF, // 30
0xFC6F7C4045812297, // 31
0x9DC5ADA82B70B59E, // 32
0xC5371912364CE306, // 33
0xF684DF56C3E01BC7, // 34
0x9A130B963A6C115D, // 35
0xC097CE7BC90715B4, // 36
0xF0BDC21ABB48DB21, // 37
0x96769950B50D88F5, // 38
0xBC143FA4E250EB32, // 39
0xEB194F8E1AE525FE, // 40
0x92EFD1B8D0CF37BF, // 41
0xB7ABC627050305AE, // 42
0xE596B7B0C643C71A, // 43
0x8F7E32CE7BEA5C70, // 44
0xB35DBF821AE4F38C, // 45
};
xassert(k >= KMIN && k <= KMAX);
return g[k - KMIN];
#undef KMIN
#undef KMAX
}
static inline uint32_t round_odd_f32(uint64_t g, uint32_t cp) {
const uint128_t p = ((uint128_t)g) * cp;
const uint32_t y1 = (uint64_t)(p >> 64);
const uint32_t y0 = ((uint64_t)(p)) >> 32;
return y1 | (y0 > 1);
}
/**
Rendering float point number into decimal.
The function used Schubfach algorithm, reference:
The Schubfach way to render doubles, Raffaello Giulietti, 2022-03-20.
https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb
https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html
https://github.com/openjdk/jdk/pull/3402 (Java implementation)
https://github.com/abolz/Drachennest (C++ implementation)
*/
static inline f32_dec f32todec(uint32_t rsig, int32_t rexp, uint32_t c, int32_t q) {
uint32_t cbl, cb, cbr, vbl, vb, vbr, lower, upper, s;
int32_t k, h;
bool even, irregular, w_inside, u_inside;
f32_dec dec;
even = !(c & 1);
irregular = rsig == 0 && rexp > 1;
cbl = 4 * c - 2 + irregular;
cb = 4 * c;
cbr = 4 * c + 2;
k = (q * 1262611 - (irregular ? 524031 : 0)) >> 22;
h = q + ((-k) * 1741647 >> 19) + 1;
uint64_t pow10 = pow10_ceil_sig_f32(-k);
vbl = round_odd_f32(pow10, cbl << h);
vb = round_odd_f32(pow10, cb << h);
vbr = round_odd_f32(pow10, cbr << h);
lower = vbl + !even;
upper = vbr - !even;
s = vb / 4;
if (s >= 10) {
uint64_t sp = s / 10;
bool up_inside = lower <= (40 * sp);
bool wp_inside = (40 * sp + 40) <= upper;
if (up_inside != wp_inside) {
dec.sig = sp + wp_inside;
dec.exp = k + 1;
return dec;
}
}
u_inside = lower <= (4 * s);
w_inside = (4 * s + 4) <= upper;
if (u_inside != w_inside) {
dec.sig = s + w_inside;
dec.exp = k;
return dec;
}
uint64_t mid = 4 * s + 2;
bool round_up = vb > mid || (vb == mid && (s & 1) != 0);
dec.sig = s + round_up;
dec.exp = k;
return dec;
}
int f32toa(char *out, float fp) {
char* p = out;
uint32_t raw = f32toraw(fp);
bool neg;
uint32_t rsig, c;
int32_t rexp, q;
neg = ((raw >> (F32_BITS - 1)) != 0);
rsig = raw & F32_SIG_MASK;
rexp = (int32_t)((raw & F32_EXP_MASK) >> F32_SIG_BITS);
/* check infinity and nan */
if (unlikely(rexp == F32_INF_NAN_EXP)) {
return 0;
}
/* check negative numbers */
*p = '-';
p += neg;
/* simple case of 0.0 */
if ((raw << 1) == 0) {
*p++ = '0';
return p - out;
}
if (likely(rexp != 0)) {
/* double is normal */
c = rsig | F32_HIDDEN_BIT;
q = rexp - F32_EXP_BIAS - F32_SIG_BITS;
/* fast path for integer */
if (q <= 0 && q >= -F32_SIG_BITS && is_div_pow2(c, -q)) {
uint32_t u = c >> -q;
p = format_integer_u32(u, p, ctz10_u32(u));
return p - out;
}
} else {
c = rsig;
q = 1 - F32_EXP_BIAS - F32_SIG_BITS;
}
f32_dec dec = f32todec(rsig, rexp, c, q);
p = write_dec_f32(dec, p);
return p - out;
}
#undef F32_BITS
#undef F32_EXP_BITS
#undef F32_SIG_BITS
#undef F32_EXP_MASK
#undef F32_SIG_MASK
#undef F32_EXP_BIAS
#undef F32_INF_NAN_EXP
#undef F32_HIDDEN_BIT

View file

@ -16,84 +16,6 @@
#include "native.h"
static inline int is_zero_sse(__m128i v) {
return _mm_testz_si128(v, v);
}
#if USE_AVX
static inline int is_zero_avx(__m256i v) {
return _mm256_testz_si256(v, v);
}
#endif
size_t lzero(const char *sp, size_t nb) {
size_t n = nb;
const char * p = sp;
#if USE_AVX
/* 32-byte loop */
while (n >= 32) {
if (!is_zero_avx(_mm256_loadu_si256((const void *)p))) {
_mm256_zeroupper();
return 1;
} else {
p += 32;
n -= 32;
}
}
/* clear upper half to avoid AVX-SSE transition penalty */
_mm256_zeroupper();
#endif
/* 16-byte loop */
while (n >= 16) {
if (!is_zero_sse(_mm_loadu_si128((const void *)p))) {
return 1;
} else {
p += 16;
n -= 16;
}
}
/* 8-byte test */
if (n >= 8) {
if (*(uint64_t *)p) {
return 1;
} else {
p += 8;
n -= 8;
}
}
/* 4-byte test */
if (n >= 4) {
if (*(uint32_t *)p) {
return 1;
} else {
p += 4;
n -= 4;
}
}
/* 2-byte test */
if (n >= 2) {
if (*(uint16_t *)p) {
return 1;
} else {
p += 2;
n -= 2;
}
}
/* the final byte */
if (n == 0) {
return 0;
} else {
return *p != 0;
}
}
#if USE_AVX2
static const uintptr_t ALIGN_MASK = 31;
#else

View file

@ -1,485 +1,405 @@
/* Copyright 2018 Ulf Adams.
* Modifications copyright 2021 ByteDance Inc.
*
* The contents of this file may be used under the terms of the Apache License,
* Version 2.0.
*
* (See accompanying file LICENSE-Apache or copy at
* http: *www.apache.org/licenses/LICENSE-2.0)
*
* Alternatively, the contents of this file may be used under the terms of
* the Boost Software License, Version 1.0.
* (See accompanying file LICENSE-Boost or copy at
* https: *www.boost.org/LICENSE_1_0.txt)
/* Copyright 2020 Alexander Bolz
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* Unless required by applicable law or agreed to in writing, this software
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.
*
* This file may have been modified by ByteDance authors. All ByteDance
* Modifications are Copyright 2022 ByteDance Authors.
*/
#include "native.h"
#include "ryu_tab.h"
/* use 128-bit type for performance */
#include "native.h"
#include "tab.h"
#include "test/xassert.h"
#define F64_BITS 64
#define F64_EXP_BITS 11
#define F64_SIG_BITS 52
#define F64_EXP_MASK 0x7FF0000000000000ull // middle 11 bits
#define F64_SIG_MASK 0x000FFFFFFFFFFFFFull // lower 52 bits
#define F64_EXP_BIAS 1023
#define F64_INF_NAN_EXP 0x7FF
#define F64_HIDDEN_BIT 0x0010000000000000ull
struct f64_dec {
uint64_t sig;
int64_t exp;
};
typedef struct f64_dec f64_dec;
typedef __uint128_t uint128_t;
/* Returns e == 0 ? 1 : ceil(log_2(5^e)) */
static inline int32_t pow5bits(const int32_t e) {
return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
}
/* Returns floor(log_10(2^e)) */
static inline uint32_t log10pow2(const int32_t e) {
return (((uint32_t) e) * 78913) >> 18;
}
/* Returns floor(log_10(5^e)) */
static inline uint32_t log10pow5(const int32_t e) {
return (((uint32_t) e) * 732923) >> 20;
}
static inline uint32_t pow5factor(uint64_t v) {
uint64_t m_inv5 = 14757395258967641293u; // *5 = 1(mod 2^64)
uint64_t n_div5 = 3689348814741910323u; // =2^64 / 5
uint32_t cnt = 0;
for (;;) {
v *= m_inv5;
if (v > n_div5)
break;
++cnt;
static inline unsigned ctz10(const uint64_t v) {
xassert(0 <= v && v < 100000000000000000ull);
if (v >= 10000000000ull) {
if (v < 100000000000ull) return 11;
if (v < 1000000000000ull) return 12;
if (v < 10000000000000ull) return 13;
if (v < 100000000000000ull) return 14;
if (v < 1000000000000000ull) return 15;
if (v < 10000000000000000ull) return 16;
return 17;
}
return cnt;
if (v < 10ull) return 1;
if (v < 100ull) return 2;
if (v < 1000ull) return 3;
if (v < 10000ull) return 4;
if (v < 100000ull) return 5;
if (v < 1000000ull) return 6;
if (v < 10000000ull) return 7;
if (v < 100000000ull) return 8;
if (v < 1000000000ull) return 9;
return 10;
}
/* Returns true if value is divisible by 5^p */
static inline bool ispow5(const uint64_t v, const uint32_t p) {
return pow5factor(v) >= p;
}
static inline char* format_significand(uint64_t sig, char *out, int cnt) {
char *p = out + cnt;
int ctz = 0;
/* Returns true if value is divisible by 2^p */
static inline bool ispow2(const uint64_t v, const uint32_t p) {
return (v & ((1ull << p) - 1)) == 0;
}
if ((sig >> 32) != 0) {
uint64_t q = sig / 100000000;
uint32_t r = ((uint32_t)sig) - 100000000 * ((uint32_t) q);
sig = q;
if (r != 0) {
uint32_t c = r % 10000;
r /= 10000;
uint32_t d = r % 10000;
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
uint32_t d0 = (d % 100) << 1;
uint32_t d1 = (d / 100) << 1;
copy_two_digs(p - 2, Digits + c0);
copy_two_digs(p - 4, Digits + c1);
copy_two_digs(p - 6, Digits + d0);
copy_two_digs(p - 8, Digits + d1);
} else {
ctz += 8;
}
p -= 8;
}
/* Requires 0 <= v < v < 100000000000000000L */
static inline uint32_t ctz10(const uint64_t v) {
if (v < 10) return 1;
if (v < 100) return 2;
if (v < 1000) return 3;
if (v < 10000) return 4;
if (v < 100000) return 5;
if (v < 1000000) return 6;
if (v < 10000000) return 7;
if (v < 100000000) return 8;
if (v < 1000000000) return 9;
if (v < 10000000000) return 10;
if (v < 100000000000) return 11;
if (v < 1000000000000) return 12;
if (v < 10000000000000) return 13;
if (v < 100000000000000) return 14;
if (v < 1000000000000000) return 15;
if (v < 10000000000000000) return 16;
return 17;
}
/* Best case: use 128-bit type */
static inline uint64_t mulshift(const uint64_t m, const uint64_t *mul, const int32_t j) {
uint128_t lo = ((uint128_t) m) * mul[0];
uint128_t hi = ((uint128_t) m) * mul[1];
return (uint64_t) (((lo >> 64) + hi) >> (j - 64));
}
#define mul_shift_all(m, mul, j, shift) \
vp = mulshift(4 * m + 2, mul, j); \
vm = mulshift(4 * m - 1 - shift, mul, j); \
vr = mulshift(4 * m, mul, j);
#define copy_two_digs(dst, src) \
*(dst) = *(src); \
*(dst+1) = *(src+1);
/* A floating decimal representing man * 10^exp */
typedef struct f64_d {
uint64_t man;
int32_t exp;
} f64_d;
static inline f64_d f64tod(const uint64_t man,const uint32_t exp) {
int32_t e2;
uint64_t m2;
if (exp == 0) {
/* subtract 2 so that the bounds computation has 2 additional bits */
e2 = 1 - 1023 - 52 - 2;
m2 = man;
uint32_t sig2 = (uint32_t)sig;
while (sig2 >= 10000) {
uint32_t c = sig2 - 10000 * (sig2 / 10000);
sig2 /= 10000;
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
copy_two_digs(p - 2, Digits + c0);
copy_two_digs(p - 4, Digits + c1);
p -= 4;
}
if (sig2 >= 100) {
uint32_t c = (sig2 % 100) << 1;
sig2 /= 100;
copy_two_digs(p - 2, Digits + c);
p -= 2;
}
if (sig2 >= 10) {
uint32_t c = sig2 << 1;
copy_two_digs(p - 2, Digits + c);
} else {
e2 = (int32_t) exp - 1023 - 52 - 2;
m2 = (1ull << 52) | man;
*out = (char) ('0' + sig2);
}
bool even = (m2 & 1) == 0;
/* Step 2: Determine the interval of valid decimal representations */
uint64_t mv = 4 * m2;
/* Implicit bool -> int conversion. True is 1, false is 0 */
uint32_t shift = man != 0 || exp <= 1;
/* Step 3: Convert to a decimal power base using 128-bit arithmetic */
uint64_t vr, vp, vm;
int32_t e10;
bool vmzeros = false;
bool vrzeros = false;
if (e2 >= 0) {
uint32_t q = log10pow2(e2) - (e2 > 3); // max(0, log10pow2(e2) - 1)
e10 = (int32_t) q;
int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t) q) - 1;
int32_t i = -e2 + (int32_t) q + k;
uint64_t *mul = (uint64_t*)DOUBLE_POW5_INV_SPLIT[q];
/* {vm, vr, vp} * 10^e10 = {mm, mv, mp} * 2^e2
* mp = 4 * m2 + 2
* mm = mv - 1 - shift
*/
mul_shift_all(m2, mul, i, shift)
if (q <= 21) {
if (mv % 5 == 0) {
vrzeros = ispow5(mv, q);
} else if (even) {
/* Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
* <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
* <=> true && pow5Factor(mm) >= q, since e2 >= q.
*/
vmzeros = ispow5(mv - 1 - shift, q);
} else {
/* Same as min(e2 + 1, pow5Factor(mp)) >= q. */
vp -= ispow5(mv + 2, q);
}
}
} else {
uint32_t q = log10pow5(-e2) - (-e2 > 1); // max(0, log10pow5(-e2) - 1)
e10 = (int32_t) q + e2;
int32_t i = -e2 - (int32_t) q;
int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
int32_t j = (int32_t) q - k;
uint64_t *mul = (uint64_t*)DOUBLE_POW5_SPLIT[i];
/* {vm, vr, vp} * 10^e10 = {mm, mv, mp} * 2^e2 */
mul_shift_all(m2, mul, j, shift)
if (q <= 1) {
/* {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing
* 0 bits. mv = 4 * m2, so it always has at least two trailing 0 bits.
*/
vrzeros = true;
if (even) {
/* mm = mv - 1 - shift, so it has 1 trailing 0 bit if shift = 1 */
vmzeros = shift == 1;
} else {
/* mp = mv + 2, so it always has at least one trailing 0 bit */
--vp;
}
} else if (q < 63) {
vrzeros = ispow2(mv, q);
}
}
/* Step 4: Find the shortest decimal representation in the interval */
int32_t removed = 0;
uint8_t lastrmdig = 0;
uint64_t dman;
/* On average, we remove ~2 DIGs */
if (vmzeros || vrzeros) {
/* General case, which happens rarely (~0.7%) */
for (;;) {
uint64_t vpdiv10 = vp / 10;
uint64_t vmdiv10 = vm / 10;
if (vpdiv10 <= vmdiv10) {
break;
}
uint32_t vmmod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmdiv10);
uint64_t vrdiv10 = vr / 10;
uint32_t vrmod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrdiv10);
vmzeros &= vmmod10 == 0;
vrzeros &= lastrmdig == 0;
lastrmdig = (uint8_t) vrmod10;
vr = vrdiv10;
vp = vpdiv10;
vm = vmdiv10;
++removed;
}
if (vmzeros) {
for (;;) {
uint64_t vmdiv10 = vm / 10;
uint32_t vmmod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmdiv10);
if (vmmod10 != 0) {
break;
}
uint64_t vpdiv10 = vp / 10;
uint64_t vrdiv10 = vr / 10;
uint32_t vrmod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrdiv10);
vrzeros &= lastrmdig == 0;
lastrmdig = (uint8_t) vrmod10;
vr = vrdiv10;
vp = vpdiv10;
vm = vmdiv10;
++removed;
}
}
if (vrzeros && lastrmdig == 5 && vr % 2 == 0) {
/* Round even if the exact number is .....50..0 */
lastrmdig = 4;
}
/* We need to take vr + 1 if vr is outside bounds or we need to round up */
dman = vr + ((vr == vm && (!even || !vmzeros)) || lastrmdig >= 5);
} else {
/* Specialized for the common case (~99.3%). Percentages below are relative to this */
bool roundup= false;
uint64_t vpdiv100 = vp / 100;
uint64_t vmdiv100 = vm / 100;
if (vpdiv100 > vmdiv100) { // Optimization: remove two DIGs at a time (~86.2%).
uint64_t vrdiv100 = vr / 100;
uint32_t vrmod100 = ((uint32_t) vr) - 100 * ((uint32_t) vrdiv100);
roundup = vrmod100 >= 50;
vr = vrdiv100;
vp = vpdiv100;
vm = vmdiv100;
removed += 2;
}
/* Loop iterations below (approximately), without optimization above:
* 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
* Loop iterations below (approximately), with optimization above:
* 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
*/
for (;;) {
uint64_t vpdiv10 = vp / 10;
uint64_t vmdiv10 = vm / 10;
if (vpdiv10 <= vmdiv10) {
break;
}
uint64_t vrdiv10 = vr / 10;
uint32_t vrmod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrdiv10);
roundup = vrmod10 >= 5;
vr = vrdiv10;
vp = vpdiv10;
vm = vmdiv10;
++removed;
}
/* We need to take vr + 1 if vr is outside bounds or we need to round up */
dman = vr + (vr == vm || roundup);
}
f64_d fd = {
.exp = e10 + removed,
.man = dman,
};
return fd;
return out + cnt - ctz;
}
/* Print the decimal DIGs from mantissa */
static inline void print_mantissa(uint64_t man, char *out, int mlen) {
/* We have at most 17 DIGs, and uint32_t can store 9 DIGs.
* If man doesn't fit into uint32_t, we cut off 8 DIGs,
* so the rest will fit into uint32_t.
*/
char *r = out + mlen;
if (man < 10) {}
if ((man >> 32) != 0) {
/* Expensive 64-bit division */
uint64_t q = man / 100000000;
uint32_t man2 = ((uint32_t) man) - 100000000 * ((uint32_t) q);
man = q;
uint32_t c = man2 % 10000;
man2 /= 10000;
uint32_t d = man2 % 10000;
static inline char* format_integer(uint64_t sig, char *out, unsigned cnt) {
char *p = out + cnt;
if ((sig >> 32) != 0) {
uint64_t q = sig / 100000000;
uint32_t r = ((uint32_t)sig) - 100000000 * ((uint32_t) q);
sig = q;
uint32_t c = r % 10000;
r /= 10000;
uint32_t d = r % 10000;
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
uint32_t d0 = (d % 100) << 1;
uint32_t d1 = (d / 100) << 1;
copy_two_digs(r - 2, DIG_TAB + c0)
copy_two_digs(r - 4, DIG_TAB + c1)
copy_two_digs(r - 6, DIG_TAB + d0)
copy_two_digs(r - 8, DIG_TAB + d1)
r -= 8;
copy_two_digs(p - 2, Digits + c0);
copy_two_digs(p - 4, Digits + c1);
copy_two_digs(p - 6, Digits + d0);
copy_two_digs(p - 8, Digits + d1);
p -= 8;
}
uint32_t man2 = (uint32_t) man;
while (man2 >= 10000) {
#ifdef __clang__ // https://bugs.llvm.org/show_bug.cgi?id=38217
uint32_t c = man2 - 10000 * (man2 / 10000);
#else
uint32_t c = man2 % 10000;
#endif
man2 /= 10000;
uint32_t sig2 = (uint32_t)sig;
while (sig2 >= 10000) {
uint32_t c = sig2 - 10000 * (sig2 / 10000);
sig2 /= 10000;
uint32_t c0 = (c % 100) << 1;
uint32_t c1 = (c / 100) << 1;
copy_two_digs(r - 2, DIG_TAB + c0)
copy_two_digs(r - 4, DIG_TAB + c1)
r -= 4;
copy_two_digs(p - 2, Digits + c0);
copy_two_digs(p - 4, Digits + c1);
p -= 4;
}
if (man2 >= 100) {
uint32_t c = (man2 % 100) << 1;
man2 /= 100;
copy_two_digs(r - 2, DIG_TAB + c)
r -= 2;
if (sig2 >= 100) {
uint32_t c = (sig2 % 100) << 1;
sig2 /= 100;
copy_two_digs(p - 2, Digits + c);
p -= 2;
}
if (man2 >= 10) {
uint32_t c = man2 << 1;
copy_two_digs(r - 2, DIG_TAB + c)
if (sig2 >= 10) {
uint32_t c = sig2 << 1;
copy_two_digs(p - 2, Digits + c);
} else {
*out = (char) ('0' + man2);
*out = (char) ('0' + sig2);
}
return out + cnt;
}
static inline int print_exponent(f64_d v, char *out, int mlen) {
int idx = 0;
static inline char* format_exponent(f64_dec v, char *out, unsigned cnt) {
char* p = out + 1;
char* end = format_significand(v.sig, p, cnt);
while (*(end - 1) == '0') end--;
print_mantissa(v.man, out + idx + 1, mlen);
/* Print decimal point if needed */
out[idx] = out[idx + 1];
if (mlen > 1) {
out[idx + 1] = '.';
idx += mlen + 1;
/* print decimal point if needed */
*out = *p;
if (end - p > 1) {
*p = '.';
} else {
++idx;
end--;
}
/* Print the exponent */
out[idx++] = 'e';
int32_t exp = v.exp + (int32_t) mlen - 1;
/* print the exponent */
*end++ = 'e';
int32_t exp = v.exp + (int32_t) cnt - 1;
if (exp < 0) {
out[idx++] = '-';
*end++ = '-';
exp = -exp;
} else {
*end++ = '+';
}
if (exp >= 100) {
int32_t c = exp % 10;
copy_two_digs(out + idx, DIG_TAB + 2 * (exp / 10))
out[idx + 2] = (char) ('0' + c);
idx += 3;
copy_two_digs(end, Digits + 2 * (exp / 10));
end[2] = (char) ('0' + c);
end += 3;
} else if (exp >= 10) {
copy_two_digs(out + idx, DIG_TAB + 2 * exp)
idx += 2;
copy_two_digs(end, Digits + 2 * exp);
end += 2;
} else {
out[idx++] = (char) ('0' + exp);
*end++ = (char) ('0' + exp);
}
return idx;
return end;
}
static inline int print_decimal(const f64_d v, char *out, int mlen) {
int idx = 0;
int lzeros = 0;
int rzeros = 0;
int point = 0;
int exp10 = mlen - 1 + v.exp;
static inline char* format_decimal(f64_dec v, char* out, unsigned cnt) {
char* p = out;
char* end;
int point = cnt + v.exp;
/* parse the point idx and additional zeros */
if (exp10 < 0) {
lzeros = -exp10;
point = 1;
} else if (exp10 < mlen - 1) {
point = 1 + exp10;
} else {
rzeros = exp10 - mlen + 1;
}
int i = 0;
/* add left zeros */
if (lzeros) {
out[idx++] = '0';
out[idx++] = '.';
point = 0;
}
for (i = 1; i < lzeros; ++i) {
out[idx++] = '0';
}
/* add the mantissa DIGs */
print_mantissa(v.man, out + idx, mlen);
if (point) {
for (i = idx + mlen; i > idx + point; --i) {
out[i] = out[i-1];
/* print leading zeros if fp < 1 */
if (point <= 0) {
*p++ = '0', *p++ = '.';
for (int i = 0; i < -point; i++) {
*p++ = '0';
}
out[idx + point] = '.';
idx += 1;
}
/* add right zeros */
idx += mlen;
for (i = 0; i < rzeros; ++i) {
out[idx++] = '0';
/* add the remaining digits */
end = format_significand(v.sig, p, cnt);
while (*(end - 1) == '0') end--;
if (point <= 0) {
return end;
}
return idx;
/* insert point or add trailing zeros */
int digs = end - p;
if (digs > point) {
for (int i = 0; i < digs - point; i++) {
*(end - i) = *(end - i - 1);
}
p[point] = '.';
end++;
} else {
for (int i = 0; i < point - digs; i++) {
*end++ = '0';
}
}
return end;
}
static inline bool f64tod_exct_int(const uint64_t man, const uint32_t exp,
f64_d* v) {
uint64_t m2 = (1ull << 52) | man; // implicit 1
int32_t e2 = (int32_t) exp - 1023 - 52;
static inline char* write_dec(f64_dec dec, char* p) {
int cnt = ctz10(dec.sig);
int dot = cnt + dec.exp;
int sci_exp = dot - 1;
bool exp_fmt = sci_exp < -6 || sci_exp > 20;
bool has_dot = dot < cnt;
if (e2 > 0 || e2 < -52) {
return false;
if (exp_fmt) {
return format_exponent(dec, p, cnt);
}
if (has_dot) {
return format_decimal(dec, p, cnt);
}
uint64_t mask = (1ull << -e2) - 1;
if ((m2 & mask) != 0) { // with fraction
return false;
}
v->man = m2 >> -e2;
v->exp = 0;
return true;
char* end = p + dot;
p = format_integer(dec.sig, p, cnt);
while (p < end) *p++ = '0';
return end;
}
static int inline ryu(uint64_t bits, char *out) {
/* Step 1: Decode the floating-point number */
uint64_t man = bits & ((1ull << 52) - 1);
uint32_t exp = (uint32_t) ((bits >> 52) & ((1u << 11) - 1));
static inline uint64_t f64toraw(double fp) {
union {
uint64_t u64;
double f64;
} uval;
uval.f64 = fp;
return uval.u64;
}
/* Skip when Infinity */
if (exp == ((1u << 11) - 1u)) {
static inline uint64_t round_odd(uint64x2 g, uint64_t cp) {
const uint128_t x = ((uint128_t)cp) * g.lo;
const uint128_t y = ((uint128_t)cp) * g.hi + ((uint64_t)(x >> 64));
const uint64_t y0 = ((uint64_t)y);
const uint64_t y1 = ((uint64_t)(y >> 64));
return y1 | (y0 > 1);
}
/**
Rendering float point number into decimal.
The function used Schubfach algorithm, reference:
The Schubfach way to render doubles, Raffaello Giulietti, 2022-03-20.
https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb
https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html
https://github.com/openjdk/jdk/pull/3402 (Java implementation)
https://github.com/abolz/Drachennest (C++ implementation)
*/
static inline f64_dec f64todec(uint64_t rsig, int32_t rexp, uint64_t c, int32_t q) {
uint64_t cbl, cb, cbr, vbl, vb, vbr, lower, upper, s;
int32_t k, h;
bool even, irregular, w_inside, u_inside;
f64_dec dec;
even = !(c & 1);
irregular = rsig == 0 && rexp > 1;
cbl = 4 * c - 2 + irregular;
cb = 4 * c;
cbr = 4 * c + 2;
/* q is in [-1500, 1500]
k = irregular ? floor(log_10(3/4 * 2^q)) : floor(log10(pow(2^q)))
floor(log10(3/4 * 2^q)) = (q * 1262611 - 524031) >> 22
floor(log10(pow(2^q))) = (q * 1262611) >> 22 */
k = (q * 1262611 - (irregular ? 524031 : 0)) >> 22;
/* k is in [-1233, 1233]
s = floor(V) = floor(c * 2^q * 10^-k)
vb = 4V = 4 * c * 2^q * 10^-k */
h = q + ((-k) * 1741647 >> 19) + 1;
uint64x2 pow10 = pow10_ceil_sig(-k);
vbl = round_odd(pow10, cbl << h);
vb = round_odd(pow10, cb << h);
vbr = round_odd(pow10, cbr << h);
lower = vbl + !even;
upper = vbr - !even;
s = vb / 4;
if (s >= 10) {
/* R_k+1 interval contains at most one: up or wp */
uint64_t sp = s / 10;
bool up_inside = lower <= (40 * sp);
bool wp_inside = (40 * sp + 40) <= upper;
if (up_inside != wp_inside) {
dec.sig = sp + wp_inside;
dec.exp = k + 1;
return dec;
}
}
/* R_k interval contains at least one: u or w */
u_inside = lower <= (4 * s);
w_inside = (4 * s + 4) <= upper;
if (u_inside != w_inside) {
dec.sig = s + w_inside;
dec.exp = k;
return dec;
}
/* R_k interval contains both u or w */
uint64_t mid = 4 * s + 2;
bool round_up = vb > mid || (vb == mid && (s & 1) != 0);
dec.sig = s + round_up;
dec.exp = k;
return dec;
}
int f64toa(char *out, double fp) {
char* p = out;
uint64_t raw = f64toraw(fp);
bool neg;
uint64_t rsig, c;
int32_t rexp, q;
neg = ((raw >> (F64_BITS - 1)) != 0);
rsig = raw & F64_SIG_MASK;
rexp = (int32_t)((raw & F64_EXP_MASK) >> F64_SIG_BITS);
/* check infinity and nan */
if (unlikely(rexp == F64_INF_NAN_EXP)) {
return 0;
}
f64_d v;
/* for integer from [1, 2^53], can be resepensated exactly by double */
bool is_exact_int = f64tod_exct_int(man, exp, &v);
if (!is_exact_int){ // find the shortest decimal representation
v = f64tod(man, exp);
}
/* Step 5: Print the decimal representation */
int idx = 0;
uint32_t mlen = ctz10(v.man);
int exp10 = mlen - 1 + v.exp;
/* The format as Go encoding/json package */
bool isexp = exp10 < -6 || exp10 >= 21;
if (isexp) // exponent format
idx += print_exponent(v, out + idx, mlen);
else // decimal format
idx += print_decimal(v, out + idx, mlen);
return idx;
}
int f64toa(char *out, double val) {
int i = 0;
char *p = out;
uint64_t uval = *(uint64_t *)&val;
/* negative numbers */
if (unlikely(uval >> 63) == 1) {
i = 1;
uval &= ((1ull << 63) - 1);
*p++ = '-';
}
/* check negative numbers */
*p = '-';
p += neg;
/* simple case of 0.0 */
if (uval == 0) {
*p = '0';
return i + 1;
if ((raw << 1) == 0) {
*p++ = '0';
return p - out;
}
/* print the number with Ryu algorithm */
int n = ryu(uval, p);
return n + i;
/* fp = c * 2^q */
if (likely(rexp != 0)) {
/* double is normal */
c = rsig | F64_HIDDEN_BIT;
q = rexp - F64_EXP_BIAS - F64_SIG_BITS;
/* fast path for integer */
if (q <= 0 && q >= -F64_SIG_BITS && is_div_pow2(c, -q)) {
uint64_t u = c >> -q;
p = format_integer(u, p, ctz10(u));
return p - out;
}
} else {
c = rsig;
q = 1 - F64_EXP_BIAS - F64_SIG_BITS;
}
f64_dec dec = f64todec(rsig, rexp, c, q);
p = write_dec(dec, p);
return p - out;
}
#undef F64_BITS
#undef F64_EXP_BITS
#undef F64_SIG_BITS
#undef F64_EXP_MASK
#undef F64_SIG_MASK
#undef F64_EXP_BIAS
#undef F64_INF_NAN_EXP
#undef F64_HIDDEN_BIT

View file

@ -15,19 +15,7 @@
*/
#include "native.h"
static const char Digits[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9',
};
#include "tab.h"
static const char Vec16xA0[16] __attribute__((aligned(16))) = {
'0', '0', '0', '0', '0', '0', '0', '0',

View file

@ -20,4 +20,5 @@
#include "parsing.c"
#include "atof_eisel_lemire.c"
#include "atof_native.c"
#include "scanning.c"
#include "scanning.c"
#include "f32toa.c"

View file

@ -101,7 +101,6 @@ int f64toa(char *out, double val);
int i64toa(char *out, int64_t val);
int u64toa(char *out, uint64_t val);
size_t lzero(const char *sp, size_t nb);
size_t lspace(const char *sp, size_t nb, size_t p);
ssize_t quote(const char *sp, ssize_t nb, char *dp, ssize_t *dn, uint64_t flags);

View file

@ -268,10 +268,8 @@ static inline uint8_t escape_mask4(const char *sp) {
static inline ssize_t memcchr_quote_unsafe(const char *sp, ssize_t nb, char *dp, const quoted_t * tab) {
uint32_t mm;
const char * ss = sp;
const char * ds = dp;
size_t cn = 0;
uint8_t ch;
simd_copy:

View file

@ -1,385 +0,0 @@
/* Copyright 2018 Ulf Adams.
* Modifications copyright 2021 ByteDance Inc.
*
* The contents of this file may be used under the terms of the Apache License,
* Version 2.0.
*
* (See accompanying file LICENSE-Apache or copy at
* http: *www.apache.org/licenses/LICENSE-2.0)
*
* Alternatively, the contents of this file may be used under the terms of
* the Boost Software License, Version 1.0.
* (See accompanying file LICENSE-Boost or copy at
* https: *www.boost.org/LICENSE_1_0.txt)
*
* Unless required by applicable law or agreed to in writing, this software
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.
*/
#ifndef RYU_TAB_H
#define RYU_TAB_H
/* These tables are generated by PrintDoubleLookupTable */
#define DOUBLE_POW5_INV_BITCOUNT 125
#define DOUBLE_POW5_BITCOUNT 125
#define DOUBLE_POW5_INV_TABLE_SIZE 342
#define DOUBLE_POW5_TABLE_SIZE 326
/* A table of all two-digit numbers. This is used to speed up decimal digit
* generation by copying pairs of digits into the final output.
*/
static const char DIG_TAB[200] = {
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
};
static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = {
{ 1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u },
{ 5165088340638674453u, 1475739525896764129u }, { 7821419487252849886u, 1180591620717411303u },
{ 8824922364862649494u, 1888946593147858085u }, { 7059937891890119595u, 1511157274518286468u },
{ 13026647942995916322u, 1208925819614629174u }, { 9774590264567735146u, 1934281311383406679u },
{ 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u },
{ 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u },
{ 9162556910162266299u, 1267650600228229401u }, { 7281393426775805432u, 2028240960365167042u },
{ 16893161185646375315u, 1622592768292133633u }, { 2446482504291369283u, 1298074214633706907u },
{ 7603720821608101175u, 2076918743413931051u }, { 2393627842544570617u, 1661534994731144841u },
{ 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u },
{ 5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u },
{ 3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u },
{ 6382248639981364905u, 1393796574908163946u }, { 2832900194486363201u, 2230074519853062314u },
{ 5955668970331000884u, 1784059615882449851u }, { 1075186361522890384u, 1427247692705959881u },
{ 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u },
{ 3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u },
{ 5547241898389809503u, 1870722095783555735u }, { 4437793518711847602u, 1496577676626844588u },
{ 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u },
{ 6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u },
{ 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u },
{ 14151565162110759939u, 1255420347077336152u }, { 7885109000409574610u, 2008672555323737844u },
{ 9997436015069570011u, 1606938044258990275u }, { 7997948812055656009u, 1285550435407192220u },
{ 12796718099289049614u, 2056880696651507552u }, { 2858676849947419045u, 1645504557321206042u },
{ 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u },
{ 3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u },
{ 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u },
{ 8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u },
{ 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u },
{ 15986332124095098083u, 2261564242916331941u }, { 9099716884534168143u, 1809251394333065553u },
{ 14658471137111155161u, 1447401115466452442u }, { 4348079280205103483u, 1157920892373161954u },
{ 14335624477811986218u, 1852673427797059126u }, { 7779150767507678651u, 1482138742237647301u },
{ 2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u },
{ 12097921058438802501u, 1517710072051350836u }, { 5988988032009131678u, 1214168057641080669u },
{ 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u },
{ 7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u },
{ 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u },
{ 4951948911778577463u, 2037035976334486086u }, { 272210314680951647u, 1629628781067588869u },
{ 3907117066486671641u, 1303703024854071095u }, { 6251387306378674625u, 2085924839766513752u },
{ 16069156289328670670u, 1668739871813211001u }, { 9165976216721026213u, 1334991897450568801u },
{ 7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u },
{ 13518030318433270404u, 1367031702989382452u }, { 6871453250525591353u, 2187250724783011924u },
{ 9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u },
{ 10282995085511086630u, 2239744742177804210u }, { 8226396068408869304u, 1791795793742243368u },
{ 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u },
{ 5324776569667477496u, 1834798892792057209u }, { 7949170070475892320u, 1467839114233645767u },
{ 17427382500606444826u, 1174271291386916613u }, { 5747719112518849781u, 1878834066219066582u },
{ 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u },
{ 5295368560860596524u, 1923926083808324180u }, { 4236294848688477220u, 1539140867046659344u },
{ 7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u },
{ 9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u },
{ 12335095245094488799u, 2017382717255397335u }, { 9868076196075591040u, 1613906173804317868u },
{ 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u },
{ 7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u },
{ 11918976037903224966u, 2115379100128795516u }, { 5845832015580669650u, 1692303280103036413u },
{ 12055363241948356366u, 1353842624082429130u }, { 841837113407818570u, 2166148198531886609u },
{ 4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u },
{ 12225235553534690011u, 2218135755296651887u }, { 2401490813343931363u, 1774508604237321510u },
{ 1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u },
{ 6886345170554478103u, 1817096810739017226u }, { 1819727321701672159u, 1453677448591213781u },
{ 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u },
{ 15587778368262418694u, 1488565707357402911u }, { 8780873879868024632u, 1190852565885922329u },
{ 2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u },
{ 7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u },
{ 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u },
{ 1553625868034358140u, 1997919072202235028u }, { 8621598323911307159u, 1598335257761788022u },
{ 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u },
{ 121653480894270168u, 1636695303948070935u }, { 97322784715416134u, 1309356243158456748u },
{ 14913111714512307107u, 2094969989053530796u }, { 8241140556867935363u, 1675975991242824637u },
{ 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u },
{ 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u },
{ 14650556434236701088u, 2196735251241795108u }, { 652398703163629901u, 1757388200993436087u },
{ 11589965406756634890u, 1405910560794748869u }, { 7475898206584884855u, 2249456897271598191u },
{ 2291369750525997561u, 1799565517817278553u }, { 9211793429904618695u, 1439652414253822842u },
{ 18428218302589300235u, 2303443862806116547u }, { 7363877012587619542u, 1842755090244893238u },
{ 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u },
{ 2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u },
{ 13231802778477390823u, 1207667975942893232u }, { 6413489186596184024u, 1932268761508629172u },
{ 16198837793502678189u, 1545815009206903337u }, { 5580372605318321905u, 1236652007365522670u },
{ 8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u },
{ 7190041073742725760u, 1266331655542295214u }, { 436019273762630246u, 2026130648867672343u },
{ 7727513048493924843u, 1620904519094137874u }, { 9871359253537050198u, 1296723615275310299u },
{ 4726128361433549347u, 2074757784440496479u }, { 7470251503888749801u, 1659806227552397183u },
{ 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u },
{ 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u },
{ 4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u },
{ 3483374466074094362u, 1392346379889585943u }, { 1884050330976640656u, 2227754207823337509u },
{ 5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u },
{ 5913764258841343181u, 2281220308811097609u }, { 8420360221814984868u, 1824976247048878087u },
{ 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u },
{ 10245762345624985047u, 1868775676978051161u }, { 4507261061758077715u, 1495020541582440929u },
{ 7295157664148372495u, 1196016433265952743u }, { 7982903447895485668u, 1913626293225524389u },
{ 10075671573058298858u, 1530901034580419511u }, { 4371188443704728763u, 1224720827664335609u },
{ 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u },
{ 15839291315758726049u, 1254114127528279663u }, { 3206773216762499739u, 2006582604045247462u },
{ 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u },
{ 4907049252451240275u, 2054740586542333401u }, { 236290587219081897u, 1643792469233866721u },
{ 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u },
{ 5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u },
{ 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u },
{ 12584037722297574282u, 1378913065775496824u }, { 9066413911450387881u, 2206260905240794919u },
{ 10942479943902220628u, 1765008724192635935u }, { 8753983955121776503u, 1412006979354108748u },
{ 10317025513452932081u, 2259211166966573997u }, { 874922781278525018u, 1807368933573259198u },
{ 8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u },
{ 14767872471458792434u, 1850745787979017418u }, { 746251532941302978u, 1480596630383213935u },
{ 597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u },
{ 8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u },
{ 17270291175157100626u, 1940647615375886168u }, { 2748186495899949531u, 1552518092300708935u },
{ 2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u },
{ 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u },
{ 8826220925580526867u, 2034916513940385215u }, { 7060976740464421494u, 1627933211152308172u },
{ 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u },
{ 9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u },
{ 13015147745246481542u, 2133764618521553367u }, { 3033420566713364587u, 1707011694817242694u },
{ 6116085268112601993u, 1365609355853794155u }, { 9785736428980163188u, 2184974969366070648u },
{ 15207286772667951197u, 1747979975492856518u }, { 1097782973908629988u, 1398383980394285215u },
{ 1756452758253807981u, 2237414368630856344u }, { 5094511021344956708u, 1789931494904685075u },
{ 4075608817075965366u, 1431945195923748060u }, { 6520974107321544586u, 2291112313477996896u },
{ 1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u },
{ 17210690286378213644u, 1173049504500734410u }, { 9090360384495590213u, 1876879207201175057u },
{ 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u },
{ 16096930852848599373u, 1921924308174003258u }, { 1809498238053148529u, 1537539446539202607u },
{ 12515645034668249793u, 1230031557231362085u }, { 1578287981759648052u, 1968050491570179337u },
{ 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u },
{ 3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u },
{ 6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u },
{ 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u },
{ 7551343283653851484u, 2113178124542660985u }, { 6041074626923081187u, 1690542499634128788u },
{ 12211557331022285596u, 1352433999707303030u }, { 1091747655926105338u, 2163894399531684849u },
{ 4562746939482794594u, 1731115519625347879u }, { 7339546366328145998u, 1384892415700278303u },
{ 8053925371383123274u, 2215827865120445285u }, { 6443140297106498619u, 1772662292096356228u },
{ 12533209867169019542u, 1418129833677084982u }, { 5295740528502789974u, 2269007733883335972u },
{ 15304638867027962949u, 1815206187106668777u }, { 4865013464138549713u, 1452164949685335022u },
{ 14960057215536570740u, 1161731959748268017u }, { 9178696285890871890u, 1858771135597228828u },
{ 14721654658196518159u, 1487016908477783062u }, { 4398626097073393881u, 1189613526782226450u },
{ 7037801755317430209u, 1903381642851562320u }, { 5630241404253944167u, 1522705314281249856u },
{ 814844308661245011u, 1218164251424999885u }, { 1303750893857992017u, 1949062802279999816u },
{ 15800395974054034906u, 1559250241823999852u }, { 5261619149759407279u, 1247400193459199882u },
{ 12107939454356961969u, 1995840309534719811u }, { 5997002748743659252u, 1596672247627775849u },
{ 8486951013736837725u, 1277337798102220679u }, { 2511075177753209390u, 2043740476963553087u },
{ 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u },
{ 4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u },
{ 3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u },
{ 9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u },
{ 5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u },
{ 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u },
{ 13453306206113055875u, 1797693134862315907u }, { 3383947335406624054u, 1438154507889852726u },
{ 16482362180876329456u, 2301047212623764361u }, { 9496540929959153242u, 1840837770099011489u },
{ 11286581558709232917u, 1472670216079209191u }, { 5339916432225476010u, 1178136172863367353u },
{ 4854517476818851293u, 1885017876581387765u }, { 3883613981455081034u, 1508014301265110212u },
{ 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u },
{ 5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u },
{ 6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u },
{ 12969830440044306787u, 1265014083170691364u }, { 9683682259845159889u, 2024022533073106183u },
{ 15125643437359948558u, 1619218026458484946u }, { 8411165935146048523u, 1295374421166787957u },
{ 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u },
{ 8022738107230848036u, 1326463407274790868u }, { 9147032156827446534u, 2122341451639665389u },
{ 11006974540203867551u, 1697873161311732311u }, { 5116230817421183718u, 1358298529049385849u },
{ 15564666937357714594u, 2173277646479017358u }, { 1383687105660440706u, 1738622117183213887u },
{ 12174996128754083534u, 1390897693746571109u }, { 8411947361780802685u, 2225436309994513775u },
{ 6729557889424642148u, 1780349047995611020u }, { 5383646311539713719u, 1424279238396488816u },
{ 1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u },
{ 16285752362063044992u, 1458461940118004547u }, { 5649904260166615347u, 1166769552094403638u },
{ 5350498001524674232u, 1866831283351045821u }, { 591049586477829062u, 1493465026680836657u },
{ 11540886113407994219u, 1194772021344669325u }, { 18673707743239135u, 1911635234151470921u },
{ 14772334225162232601u, 1529308187321176736u }, { 8128518565387875758u, 1223446549856941389u },
{ 1937583260394870242u, 1957514479771106223u }, { 8928764237799716840u, 1566011583816884978u },
{ 14521709019723594119u, 1252809267053507982u }, { 8477339172590109297u, 2004494827285612772u },
{ 17849917782297818407u, 1603595861828490217u }, { 6901236596354434079u, 1282876689462792174u },
{ 18420676183650915173u, 2052602703140467478u }, { 3668494502695001169u, 1642082162512373983u },
{ 10313493231639821582u, 1313665730009899186u }, { 9122891541139893884u, 2101865168015838698u },
{ 14677010862395735754u, 1681492134412670958u }, { 673562245690857633u, 1345193707530136767u }
};
static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = {
{ 0u, 1152921504606846976u }, { 0u, 1441151880758558720u },
{ 0u, 1801439850948198400u }, { 0u, 2251799813685248000u },
{ 0u, 1407374883553280000u }, { 0u, 1759218604441600000u },
{ 0u, 2199023255552000000u }, { 0u, 1374389534720000000u },
{ 0u, 1717986918400000000u }, { 0u, 2147483648000000000u },
{ 0u, 1342177280000000000u }, { 0u, 1677721600000000000u },
{ 0u, 2097152000000000000u }, { 0u, 1310720000000000000u },
{ 0u, 1638400000000000000u }, { 0u, 2048000000000000000u },
{ 0u, 1280000000000000000u }, { 0u, 1600000000000000000u },
{ 0u, 2000000000000000000u }, { 0u, 1250000000000000000u },
{ 0u, 1562500000000000000u }, { 0u, 1953125000000000000u },
{ 0u, 1220703125000000000u }, { 0u, 1525878906250000000u },
{ 0u, 1907348632812500000u }, { 0u, 1192092895507812500u },
{ 0u, 1490116119384765625u }, { 4611686018427387904u, 1862645149230957031u },
{ 9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u },
{ 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u },
{ 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u },
{ 15629249925580062720u, 2220446049250313080u }, { 9768281203487539200u, 1387778780781445675u },
{ 7598665485932036096u, 1734723475976807094u }, { 274959820560269312u, 2168404344971008868u },
{ 9395221924704944128u, 1355252715606880542u }, { 2520655369026404352u, 1694065894508600678u },
{ 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u },
{ 13702562178731606016u, 1654361225106055349u }, { 3293144668132343808u, 2067951531382569187u },
{ 18199116482078572544u, 1292469707114105741u }, { 8913837547316051968u, 1615587133892632177u },
{ 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u },
{ 15190102943214346240u, 1577721810442023610u }, { 9764256642163156992u, 1972152263052529513u },
{ 17631875447420442880u, 1232595164407830945u }, { 8204786253993389888u, 1540743955509788682u },
{ 1032610780636961552u, 1925929944387235853u }, { 2951224747111794922u, 1203706215242022408u },
{ 3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u },
{ 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u },
{ 3710578054803671186u, 1836709923159824231u }, { 26536550077201078u, 2295887403949780289u },
{ 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u },
{ 8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u },
{ 12076381983474541759u, 1751623080406021338u }, { 5872105442488401391u, 2189528850507526673u },
{ 15199280947623720629u, 1368455531567204170u }, { 9775729147674874978u, 1710569414459005213u },
{ 16831347453020981627u, 2138211768073756516u }, { 1296220121283337709u, 1336382355046097823u },
{ 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u },
{ 6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u },
{ 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u },
{ 532749306367912313u, 1593091911132452277u }, { 5277622651387278295u, 1991364888915565346u },
{ 7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u },
{ 8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u },
{ 10989071563364309441u, 1519290839321567799u }, { 9124653435777998898u, 1899113549151959749u },
{ 8008751406574943263u, 1186945968219974843u }, { 5399253239791291175u, 1483682460274968554u },
{ 15972438586593889776u, 1854603075343710692u }, { 759402079766405302u, 1159126922089819183u },
{ 14784310654990170340u, 1448908652612273978u }, { 9257016281882937117u, 1811135815765342473u },
{ 16182956370781059300u, 2263919769706678091u }, { 7808504722524468110u, 1414949856066673807u },
{ 5148944884728197234u, 1768687320083342259u }, { 1824495087482858639u, 2210859150104177824u },
{ 1140309429676786649u, 1381786968815111140u }, { 1425386787095983311u, 1727233711018888925u },
{ 6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u },
{ 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u },
{ 803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u },
{ 4714634887749086344u, 2059023035787211567u }, { 9864175832484260821u, 1286889397367007229u },
{ 16941905809032713930u, 1608611746708759036u }, { 2730638187581340797u, 2010764683385948796u },
{ 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u },
{ 4396021111970173586u, 1963637386119090621u }, { 5053356204195052443u, 1227273366324431638u },
{ 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u },
{ 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u },
{ 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u },
{ 4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u },
{ 7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u },
{ 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u },
{ 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u },
{ 10956397575869330579u, 2180075438084173168u }, { 6847748484918331612u, 1362547148802608230u },
{ 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u },
{ 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u },
{ 13024893955298202172u, 2079081953128979843u }, { 5834715712847682405u, 1299426220705612402u },
{ 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u },
{ 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u },
{ 12596021324643517422u, 1982767060402850955u }, { 5566670318688504437u, 1239229412751781847u },
{ 2346651879933242642u, 1549036765939727309u }, { 7545000868343941206u, 1936295957424659136u },
{ 4715625542714963254u, 1210184973390411960u }, { 5894531928393704067u, 1512731216738014950u },
{ 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u },
{ 16997363506238734644u, 1477276578845717724u }, { 2799960309088866689u, 1846595723557147156u },
{ 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u },
{ 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u },
{ 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u },
{ 3447025083132431277u, 2201313642927583642u }, { 6766076695385157452u, 1375821026829739776u },
{ 8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u },
{ 6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u },
{ 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u },
{ 5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u },
{ 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u },
{ 7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u },
{ 3885132398186337741u, 1564127418111797597u }, { 9468101516160310080u, 1955159272639746996u },
{ 15140935484454969608u, 1221974545399841872u }, { 479425281859160394u, 1527468181749802341u },
{ 5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u },
{ 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u },
{ 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u },
{ 8047776328842869663u, 1820883967578175474u }, { 836348374198811271u, 2276104959472719343u },
{ 7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u },
{ 8166621051047176104u, 2222758749485077483u }, { 2798295147690791113u, 1389224218428173427u },
{ 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u },
{ 8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u },
{ 3828506775840797949u, 2119787930951192363u }, { 86973725686804766u, 1324867456844495227u },
{ 13943775212390669669u, 1656084321055619033u }, { 3594660960206173375u, 2070105401319523792u },
{ 2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u },
{ 5816254103165035138u, 2021587305976097453u }, { 5941001823691840913u, 1263492066235060908u },
{ 7426252279614801142u, 1579365082793826135u }, { 4671129331091113523u, 1974206353492282669u },
{ 5225298841145639904u, 1233878970932676668u }, { 6531623551432049880u, 1542348713665845835u },
{ 3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u },
{ 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u },
{ 11355826773077190286u, 1176718684132267635u }, { 9583097447919099954u, 1470898355165334544u },
{ 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u },
{ 2440964573842414192u, 1436424174966147016u }, { 3051205717303017741u, 1795530218707683770u },
{ 13037379183483547984u, 2244412773384604712u }, { 8148361989677217490u, 1402757983365377945u },
{ 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u },
{ 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u },
{ 9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u },
{ 3292878744173340370u, 1672217826086733276u }, { 4116098430216675462u, 2090272282608416595u },
{ 266718509671728212u, 1306420176630260372u }, { 333398137089660265u, 1633025220787825465u },
{ 5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u },
{ 12575375104699370472u, 1594751192175610805u }, { 1884160825592049379u, 1993438990219513507u },
{ 17318501580490888525u, 1245899368887195941u }, { 7813068920331446945u, 1557374211108994927u },
{ 5154650131986920777u, 1946717763886243659u }, { 915813323278131534u, 1216698602428902287u },
{ 14979824709379828129u, 1520873253036127858u }, { 9501408849870009354u, 1901091566295159823u },
{ 12855909558809837702u, 1188182228934474889u }, { 2234828893230133415u, 1485227786168093612u },
{ 2793536116537666769u, 1856534732710117015u }, { 8663489100477123587u, 1160334207943823134u },
{ 1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u },
{ 9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u },
{ 16011667041914537212u, 1770529492101780905u }, { 6179525747111007803u, 2213161865127226132u },
{ 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u },
{ 15834525901571292854u, 2161290883913306769u }, { 2979049660840976177u, 1350806802445816731u },
{ 17558870131333383934u, 1688508503057270913u }, { 8113529608884566205u, 2110635628821588642u },
{ 9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u },
{ 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u },
{ 1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u },
{ 4853210475701136017u, 1258036869061940099u }, { 1454827076199032118u, 1572546086327425124u },
{ 1818533845248790147u, 1965682607909281405u }, { 3442426662494187794u, 1228551629943300878u },
{ 13526405364972510550u, 1535689537429126097u }, { 3072948650933474476u, 1919611921786407622u },
{ 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u },
{ 9630225068416591280u, 1874621017369538693u }, { 8324733676974063502u, 1171638135855961683u },
{ 5794231077790191473u, 1464547669819952104u }, { 7242788847237739342u, 1830684587274940130u },
{ 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u },
{ 1596658836748081690u, 1787777917260683721u }, { 6607509564362490017u, 2234722396575854651u },
{ 1823850468512862308u, 1396701497859909157u }, { 6891499104068465790u, 1745876872324886446u },
{ 17837745916940358045u, 2182346090406108057u }, { 4231062170446641922u, 1363966306503817536u },
{ 5288827713058302403u, 1704957883129771920u }, { 6611034641322878003u, 2131197353912214900u },
{ 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u },
{ 11644235287647684442u, 2081247415929897363u }, { 4971804045566108824u, 1300779634956185852u },
{ 6214755056957636030u, 1625974543695232315u }, { 3156757802769657134u, 2032468179619040394u },
{ 6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u },
{ 17206059723201118751u, 1984832206659219134u }, { 6142101308573311315u, 1240520129162011959u },
{ 3065940617289251240u, 1550650161452514949u }, { 8444111790038951954u, 1938312701815643686u },
{ 665883850346957067u, 1211445438634777304u }, { 832354812933696334u, 1514306798293471630u },
{ 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u },
{ 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u },
{ 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u },
{ 1277659885424598868u, 1805194375864829576u }, { 1597074856780748586u, 2256492969831036970u },
{ 5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u },
{ 1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u },
{ 11243484188358716120u, 1721567512383298469u }, { 219297180166231438u, 2151959390479123087u },
{ 7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u },
{ 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u },
{ 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u },
{ 16925056528170176201u, 1282667750405742577u }, { 7321262604930556539u, 1603334688007178222u },
{ 18374950293017971482u, 2004168360008972777u }, { 4566814905495150320u, 1252605225005607986u },
{ 14931890668723713708u, 1565756531257009982u }, { 9441491299049866327u, 1957195664071262478u },
{ 1289246043478778550u, 1223247290044539049u }, { 6223243572775861092u, 1529059112555673811u },
{ 3167368447542438461u, 1911323890694592264u }, { 1979605279714024038u, 1194577431684120165u },
{ 7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u },
{ 13606538515115052232u, 1166579523129023598u }, { 7784801107039039482u, 1458224403911279498u },
{ 507629346944023544u, 1822780504889099373u }, { 5246222702107417334u, 2278475631111374216u },
{ 3278889188817135834u, 1424047269444608885u }, { 8710297504448807696u, 1780059086805761106u }
};
#endif // RYU_TAB_H

View file

@ -16,7 +16,6 @@
#include "native.h"
#include "utf8.h"
#include "test/xprintf.h"
static const uint64_t ODD_MASK = 0xaaaaaaaaaaaaaaaa;
static const uint64_t EVEN_MASK = 0x5555555555555555;

695
native/tab.h Normal file
View file

@ -0,0 +1,695 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TAB_H
#define TAB_H
#include "test/xassert.h"
struct uint64x2 {
uint64_t hi;
uint64_t lo;
};
typedef struct uint64x2 uint64x2;
static const char Digits[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9',
};
static inline bool is_div_pow2(uint64_t val, int32_t e) {
xassert(e >= 0 && e <= 63);
uint64_t mask = (1ull << e) - 1;
return (val & mask) == 0;
}
static inline char* utoa2(char* p, uint32_t val) {
p[0] = Digits[val];
p[1] = Digits[val + 1];
return p + 2;
}
static inline void copy_two_digs(char* dst, const char* src) {
*(dst) = *(src);
*(dst + 1) = *(src + 1);
}
static inline const uint64x2 pow10_ceil_sig(int32_t k) {
// There are unique beta and r such that 10^k = beta 2^r and
// 2^127 <= beta < 2^128, namely r = floor(log_2 10^k) - 127 and
// beta = 2^-r 10^k.
// Let g = ceil(beta), so (g-1) 2^r < 10^k <= g 2^r, with the latter
// value being a pretty good overestimate for 10^k.
// NB: Since for all the required exponents k, we have g < 2^128,
// all constants can be stored in 128-bit integers.
// Reference from:
// https://github.com/abolz/Drachennest/blob/master/src/schubfach_64.cc#L151
#define KMIN -292
#define KMAX 324
static const uint64x2 g[KMAX - KMIN + 1] = {
{0xFF77B1FCBEBCDC4F, 0x25E8E89C13BB0F7B}, // -292
{0x9FAACF3DF73609B1, 0x77B191618C54E9AD}, // -291
{0xC795830D75038C1D, 0xD59DF5B9EF6A2418}, // -290
{0xF97AE3D0D2446F25, 0x4B0573286B44AD1E}, // -289
{0x9BECCE62836AC577, 0x4EE367F9430AEC33}, // -288
{0xC2E801FB244576D5, 0x229C41F793CDA740}, // -287
{0xF3A20279ED56D48A, 0x6B43527578C11110}, // -286
{0x9845418C345644D6, 0x830A13896B78AAAA}, // -285
{0xBE5691EF416BD60C, 0x23CC986BC656D554}, // -284
{0xEDEC366B11C6CB8F, 0x2CBFBE86B7EC8AA9}, // -283
{0x94B3A202EB1C3F39, 0x7BF7D71432F3D6AA}, // -282
{0xB9E08A83A5E34F07, 0xDAF5CCD93FB0CC54}, // -281
{0xE858AD248F5C22C9, 0xD1B3400F8F9CFF69}, // -280
{0x91376C36D99995BE, 0x23100809B9C21FA2}, // -279
{0xB58547448FFFFB2D, 0xABD40A0C2832A78B}, // -278
{0xE2E69915B3FFF9F9, 0x16C90C8F323F516D}, // -277
{0x8DD01FAD907FFC3B, 0xAE3DA7D97F6792E4}, // -276
{0xB1442798F49FFB4A, 0x99CD11CFDF41779D}, // -275
{0xDD95317F31C7FA1D, 0x40405643D711D584}, // -274
{0x8A7D3EEF7F1CFC52, 0x482835EA666B2573}, // -273
{0xAD1C8EAB5EE43B66, 0xDA3243650005EED0}, // -272
{0xD863B256369D4A40, 0x90BED43E40076A83}, // -271
{0x873E4F75E2224E68, 0x5A7744A6E804A292}, // -270
{0xA90DE3535AAAE202, 0x711515D0A205CB37}, // -269
{0xD3515C2831559A83, 0x0D5A5B44CA873E04}, // -268
{0x8412D9991ED58091, 0xE858790AFE9486C3}, // -267
{0xA5178FFF668AE0B6, 0x626E974DBE39A873}, // -266
{0xCE5D73FF402D98E3, 0xFB0A3D212DC81290}, // -265
{0x80FA687F881C7F8E, 0x7CE66634BC9D0B9A}, // -264
{0xA139029F6A239F72, 0x1C1FFFC1EBC44E81}, // -263
{0xC987434744AC874E, 0xA327FFB266B56221}, // -262
{0xFBE9141915D7A922, 0x4BF1FF9F0062BAA9}, // -261
{0x9D71AC8FADA6C9B5, 0x6F773FC3603DB4AA}, // -260
{0xC4CE17B399107C22, 0xCB550FB4384D21D4}, // -259
{0xF6019DA07F549B2B, 0x7E2A53A146606A49}, // -258
{0x99C102844F94E0FB, 0x2EDA7444CBFC426E}, // -257
{0xC0314325637A1939, 0xFA911155FEFB5309}, // -256
{0xF03D93EEBC589F88, 0x793555AB7EBA27CB}, // -255
{0x96267C7535B763B5, 0x4BC1558B2F3458DF}, // -254
{0xBBB01B9283253CA2, 0x9EB1AAEDFB016F17}, // -253
{0xEA9C227723EE8BCB, 0x465E15A979C1CADD}, // -252
{0x92A1958A7675175F, 0x0BFACD89EC191ECA}, // -251
{0xB749FAED14125D36, 0xCEF980EC671F667C}, // -250
{0xE51C79A85916F484, 0x82B7E12780E7401B}, // -249
{0x8F31CC0937AE58D2, 0xD1B2ECB8B0908811}, // -248
{0xB2FE3F0B8599EF07, 0x861FA7E6DCB4AA16}, // -247
{0xDFBDCECE67006AC9, 0x67A791E093E1D49B}, // -246
{0x8BD6A141006042BD, 0xE0C8BB2C5C6D24E1}, // -245
{0xAECC49914078536D, 0x58FAE9F773886E19}, // -244
{0xDA7F5BF590966848, 0xAF39A475506A899F}, // -243
{0x888F99797A5E012D, 0x6D8406C952429604}, // -242
{0xAAB37FD7D8F58178, 0xC8E5087BA6D33B84}, // -241
{0xD5605FCDCF32E1D6, 0xFB1E4A9A90880A65}, // -240
{0x855C3BE0A17FCD26, 0x5CF2EEA09A550680}, // -239
{0xA6B34AD8C9DFC06F, 0xF42FAA48C0EA481F}, // -238
{0xD0601D8EFC57B08B, 0xF13B94DAF124DA27}, // -237
{0x823C12795DB6CE57, 0x76C53D08D6B70859}, // -236
{0xA2CB1717B52481ED, 0x54768C4B0C64CA6F}, // -235
{0xCB7DDCDDA26DA268, 0xA9942F5DCF7DFD0A}, // -234
{0xFE5D54150B090B02, 0xD3F93B35435D7C4D}, // -233
{0x9EFA548D26E5A6E1, 0xC47BC5014A1A6DB0}, // -232
{0xC6B8E9B0709F109A, 0x359AB6419CA1091C}, // -231
{0xF867241C8CC6D4C0, 0xC30163D203C94B63}, // -230
{0x9B407691D7FC44F8, 0x79E0DE63425DCF1E}, // -229
{0xC21094364DFB5636, 0x985915FC12F542E5}, // -228
{0xF294B943E17A2BC4, 0x3E6F5B7B17B2939E}, // -227
{0x979CF3CA6CEC5B5A, 0xA705992CEECF9C43}, // -226
{0xBD8430BD08277231, 0x50C6FF782A838354}, // -225
{0xECE53CEC4A314EBD, 0xA4F8BF5635246429}, // -224
{0x940F4613AE5ED136, 0x871B7795E136BE9A}, // -223
{0xB913179899F68584, 0x28E2557B59846E40}, // -222
{0xE757DD7EC07426E5, 0x331AEADA2FE589D0}, // -221
{0x9096EA6F3848984F, 0x3FF0D2C85DEF7622}, // -220
{0xB4BCA50B065ABE63, 0x0FED077A756B53AA}, // -219
{0xE1EBCE4DC7F16DFB, 0xD3E8495912C62895}, // -218
{0x8D3360F09CF6E4BD, 0x64712DD7ABBBD95D}, // -217
{0xB080392CC4349DEC, 0xBD8D794D96AACFB4}, // -216
{0xDCA04777F541C567, 0xECF0D7A0FC5583A1}, // -215
{0x89E42CAAF9491B60, 0xF41686C49DB57245}, // -214
{0xAC5D37D5B79B6239, 0x311C2875C522CED6}, // -213
{0xD77485CB25823AC7, 0x7D633293366B828C}, // -212
{0x86A8D39EF77164BC, 0xAE5DFF9C02033198}, // -211
{0xA8530886B54DBDEB, 0xD9F57F830283FDFD}, // -210
{0xD267CAA862A12D66, 0xD072DF63C324FD7C}, // -209
{0x8380DEA93DA4BC60, 0x4247CB9E59F71E6E}, // -208
{0xA46116538D0DEB78, 0x52D9BE85F074E609}, // -207
{0xCD795BE870516656, 0x67902E276C921F8C}, // -206
{0x806BD9714632DFF6, 0x00BA1CD8A3DB53B7}, // -205
{0xA086CFCD97BF97F3, 0x80E8A40ECCD228A5}, // -204
{0xC8A883C0FDAF7DF0, 0x6122CD128006B2CE}, // -203
{0xFAD2A4B13D1B5D6C, 0x796B805720085F82}, // -202
{0x9CC3A6EEC6311A63, 0xCBE3303674053BB1}, // -201
{0xC3F490AA77BD60FC, 0xBEDBFC4411068A9D}, // -200
{0xF4F1B4D515ACB93B, 0xEE92FB5515482D45}, // -199
{0x991711052D8BF3C5, 0x751BDD152D4D1C4B}, // -198
{0xBF5CD54678EEF0B6, 0xD262D45A78A0635E}, // -197
{0xEF340A98172AACE4, 0x86FB897116C87C35}, // -196
{0x9580869F0E7AAC0E, 0xD45D35E6AE3D4DA1}, // -195
{0xBAE0A846D2195712, 0x8974836059CCA10A}, // -194
{0xE998D258869FACD7, 0x2BD1A438703FC94C}, // -193
{0x91FF83775423CC06, 0x7B6306A34627DDD0}, // -192
{0xB67F6455292CBF08, 0x1A3BC84C17B1D543}, // -191
{0xE41F3D6A7377EECA, 0x20CABA5F1D9E4A94}, // -190
{0x8E938662882AF53E, 0x547EB47B7282EE9D}, // -189
{0xB23867FB2A35B28D, 0xE99E619A4F23AA44}, // -188
{0xDEC681F9F4C31F31, 0x6405FA00E2EC94D5}, // -187
{0x8B3C113C38F9F37E, 0xDE83BC408DD3DD05}, // -186
{0xAE0B158B4738705E, 0x9624AB50B148D446}, // -185
{0xD98DDAEE19068C76, 0x3BADD624DD9B0958}, // -184
{0x87F8A8D4CFA417C9, 0xE54CA5D70A80E5D7}, // -183
{0xA9F6D30A038D1DBC, 0x5E9FCF4CCD211F4D}, // -182
{0xD47487CC8470652B, 0x7647C32000696720}, // -181
{0x84C8D4DFD2C63F3B, 0x29ECD9F40041E074}, // -180
{0xA5FB0A17C777CF09, 0xF468107100525891}, // -179
{0xCF79CC9DB955C2CC, 0x7182148D4066EEB5}, // -178
{0x81AC1FE293D599BF, 0xC6F14CD848405531}, // -177
{0xA21727DB38CB002F, 0xB8ADA00E5A506A7D}, // -176
{0xCA9CF1D206FDC03B, 0xA6D90811F0E4851D}, // -175
{0xFD442E4688BD304A, 0x908F4A166D1DA664}, // -174
{0x9E4A9CEC15763E2E, 0x9A598E4E043287FF}, // -173
{0xC5DD44271AD3CDBA, 0x40EFF1E1853F29FE}, // -172
{0xF7549530E188C128, 0xD12BEE59E68EF47D}, // -171
{0x9A94DD3E8CF578B9, 0x82BB74F8301958CF}, // -170
{0xC13A148E3032D6E7, 0xE36A52363C1FAF02}, // -169
{0xF18899B1BC3F8CA1, 0xDC44E6C3CB279AC2}, // -168
{0x96F5600F15A7B7E5, 0x29AB103A5EF8C0BA}, // -167
{0xBCB2B812DB11A5DE, 0x7415D448F6B6F0E8}, // -166
{0xEBDF661791D60F56, 0x111B495B3464AD22}, // -165
{0x936B9FCEBB25C995, 0xCAB10DD900BEEC35}, // -164
{0xB84687C269EF3BFB, 0x3D5D514F40EEA743}, // -163
{0xE65829B3046B0AFA, 0x0CB4A5A3112A5113}, // -162
{0x8FF71A0FE2C2E6DC, 0x47F0E785EABA72AC}, // -161
{0xB3F4E093DB73A093, 0x59ED216765690F57}, // -160
{0xE0F218B8D25088B8, 0x306869C13EC3532D}, // -159
{0x8C974F7383725573, 0x1E414218C73A13FC}, // -158
{0xAFBD2350644EEACF, 0xE5D1929EF90898FB}, // -157
{0xDBAC6C247D62A583, 0xDF45F746B74ABF3A}, // -156
{0x894BC396CE5DA772, 0x6B8BBA8C328EB784}, // -155
{0xAB9EB47C81F5114F, 0x066EA92F3F326565}, // -154
{0xD686619BA27255A2, 0xC80A537B0EFEFEBE}, // -153
{0x8613FD0145877585, 0xBD06742CE95F5F37}, // -152
{0xA798FC4196E952E7, 0x2C48113823B73705}, // -151
{0xD17F3B51FCA3A7A0, 0xF75A15862CA504C6}, // -150
{0x82EF85133DE648C4, 0x9A984D73DBE722FC}, // -149
{0xA3AB66580D5FDAF5, 0xC13E60D0D2E0EBBB}, // -148
{0xCC963FEE10B7D1B3, 0x318DF905079926A9}, // -147
{0xFFBBCFE994E5C61F, 0xFDF17746497F7053}, // -146
{0x9FD561F1FD0F9BD3, 0xFEB6EA8BEDEFA634}, // -145
{0xC7CABA6E7C5382C8, 0xFE64A52EE96B8FC1}, // -144
{0xF9BD690A1B68637B, 0x3DFDCE7AA3C673B1}, // -143
{0x9C1661A651213E2D, 0x06BEA10CA65C084F}, // -142
{0xC31BFA0FE5698DB8, 0x486E494FCFF30A63}, // -141
{0xF3E2F893DEC3F126, 0x5A89DBA3C3EFCCFB}, // -140
{0x986DDB5C6B3A76B7, 0xF89629465A75E01D}, // -139
{0xBE89523386091465, 0xF6BBB397F1135824}, // -138
{0xEE2BA6C0678B597F, 0x746AA07DED582E2D}, // -137
{0x94DB483840B717EF, 0xA8C2A44EB4571CDD}, // -136
{0xBA121A4650E4DDEB, 0x92F34D62616CE414}, // -135
{0xE896A0D7E51E1566, 0x77B020BAF9C81D18}, // -134
{0x915E2486EF32CD60, 0x0ACE1474DC1D122F}, // -133
{0xB5B5ADA8AAFF80B8, 0x0D819992132456BB}, // -132
{0xE3231912D5BF60E6, 0x10E1FFF697ED6C6A}, // -131
{0x8DF5EFABC5979C8F, 0xCA8D3FFA1EF463C2}, // -130
{0xB1736B96B6FD83B3, 0xBD308FF8A6B17CB3}, // -129
{0xDDD0467C64BCE4A0, 0xAC7CB3F6D05DDBDF}, // -128
{0x8AA22C0DBEF60EE4, 0x6BCDF07A423AA96C}, // -127
{0xAD4AB7112EB3929D, 0x86C16C98D2C953C7}, // -126
{0xD89D64D57A607744, 0xE871C7BF077BA8B8}, // -125
{0x87625F056C7C4A8B, 0x11471CD764AD4973}, // -124
{0xA93AF6C6C79B5D2D, 0xD598E40D3DD89BD0}, // -123
{0xD389B47879823479, 0x4AFF1D108D4EC2C4}, // -122
{0x843610CB4BF160CB, 0xCEDF722A585139BB}, // -121
{0xA54394FE1EEDB8FE, 0xC2974EB4EE658829}, // -120
{0xCE947A3DA6A9273E, 0x733D226229FEEA33}, // -119
{0x811CCC668829B887, 0x0806357D5A3F5260}, // -118
{0xA163FF802A3426A8, 0xCA07C2DCB0CF26F8}, // -117
{0xC9BCFF6034C13052, 0xFC89B393DD02F0B6}, // -116
{0xFC2C3F3841F17C67, 0xBBAC2078D443ACE3}, // -115
{0x9D9BA7832936EDC0, 0xD54B944B84AA4C0E}, // -114
{0xC5029163F384A931, 0x0A9E795E65D4DF12}, // -113
{0xF64335BCF065D37D, 0x4D4617B5FF4A16D6}, // -112
{0x99EA0196163FA42E, 0x504BCED1BF8E4E46}, // -111
{0xC06481FB9BCF8D39, 0xE45EC2862F71E1D7}, // -110
{0xF07DA27A82C37088, 0x5D767327BB4E5A4D}, // -109
{0x964E858C91BA2655, 0x3A6A07F8D510F870}, // -108
{0xBBE226EFB628AFEA, 0x890489F70A55368C}, // -107
{0xEADAB0ABA3B2DBE5, 0x2B45AC74CCEA842F}, // -106
{0x92C8AE6B464FC96F, 0x3B0B8BC90012929E}, // -105
{0xB77ADA0617E3BBCB, 0x09CE6EBB40173745}, // -104
{0xE55990879DDCAABD, 0xCC420A6A101D0516}, // -103
{0x8F57FA54C2A9EAB6, 0x9FA946824A12232E}, // -102
{0xB32DF8E9F3546564, 0x47939822DC96ABFA}, // -101
{0xDFF9772470297EBD, 0x59787E2B93BC56F8}, // -100
{0x8BFBEA76C619EF36, 0x57EB4EDB3C55B65B}, // -99
{0xAEFAE51477A06B03, 0xEDE622920B6B23F2}, // -98
{0xDAB99E59958885C4, 0xE95FAB368E45ECEE}, // -97
{0x88B402F7FD75539B, 0x11DBCB0218EBB415}, // -96
{0xAAE103B5FCD2A881, 0xD652BDC29F26A11A}, // -95
{0xD59944A37C0752A2, 0x4BE76D3346F04960}, // -94
{0x857FCAE62D8493A5, 0x6F70A4400C562DDC}, // -93
{0xA6DFBD9FB8E5B88E, 0xCB4CCD500F6BB953}, // -92
{0xD097AD07A71F26B2, 0x7E2000A41346A7A8}, // -91
{0x825ECC24C873782F, 0x8ED400668C0C28C9}, // -90
{0xA2F67F2DFA90563B, 0x728900802F0F32FB}, // -89
{0xCBB41EF979346BCA, 0x4F2B40A03AD2FFBA}, // -88
{0xFEA126B7D78186BC, 0xE2F610C84987BFA9}, // -87
{0x9F24B832E6B0F436, 0x0DD9CA7D2DF4D7CA}, // -86
{0xC6EDE63FA05D3143, 0x91503D1C79720DBC}, // -85
{0xF8A95FCF88747D94, 0x75A44C6397CE912B}, // -84
{0x9B69DBE1B548CE7C, 0xC986AFBE3EE11ABB}, // -83
{0xC24452DA229B021B, 0xFBE85BADCE996169}, // -82
{0xF2D56790AB41C2A2, 0xFAE27299423FB9C4}, // -81
{0x97C560BA6B0919A5, 0xDCCD879FC967D41B}, // -80
{0xBDB6B8E905CB600F, 0x5400E987BBC1C921}, // -79
{0xED246723473E3813, 0x290123E9AAB23B69}, // -78
{0x9436C0760C86E30B, 0xF9A0B6720AAF6522}, // -77
{0xB94470938FA89BCE, 0xF808E40E8D5B3E6A}, // -76
{0xE7958CB87392C2C2, 0xB60B1D1230B20E05}, // -75
{0x90BD77F3483BB9B9, 0xB1C6F22B5E6F48C3}, // -74
{0xB4ECD5F01A4AA828, 0x1E38AEB6360B1AF4}, // -73
{0xE2280B6C20DD5232, 0x25C6DA63C38DE1B1}, // -72
{0x8D590723948A535F, 0x579C487E5A38AD0F}, // -71
{0xB0AF48EC79ACE837, 0x2D835A9DF0C6D852}, // -70
{0xDCDB1B2798182244, 0xF8E431456CF88E66}, // -69
{0x8A08F0F8BF0F156B, 0x1B8E9ECB641B5900}, // -68
{0xAC8B2D36EED2DAC5, 0xE272467E3D222F40}, // -67
{0xD7ADF884AA879177, 0x5B0ED81DCC6ABB10}, // -66
{0x86CCBB52EA94BAEA, 0x98E947129FC2B4EA}, // -65
{0xA87FEA27A539E9A5, 0x3F2398D747B36225}, // -64
{0xD29FE4B18E88640E, 0x8EEC7F0D19A03AAE}, // -63
{0x83A3EEEEF9153E89, 0x1953CF68300424AD}, // -62
{0xA48CEAAAB75A8E2B, 0x5FA8C3423C052DD8}, // -61
{0xCDB02555653131B6, 0x3792F412CB06794E}, // -60
{0x808E17555F3EBF11, 0xE2BBD88BBEE40BD1}, // -59
{0xA0B19D2AB70E6ED6, 0x5B6ACEAEAE9D0EC5}, // -58
{0xC8DE047564D20A8B, 0xF245825A5A445276}, // -57
{0xFB158592BE068D2E, 0xEED6E2F0F0D56713}, // -56
{0x9CED737BB6C4183D, 0x55464DD69685606C}, // -55
{0xC428D05AA4751E4C, 0xAA97E14C3C26B887}, // -54
{0xF53304714D9265DF, 0xD53DD99F4B3066A9}, // -53
{0x993FE2C6D07B7FAB, 0xE546A8038EFE402A}, // -52
{0xBF8FDB78849A5F96, 0xDE98520472BDD034}, // -51
{0xEF73D256A5C0F77C, 0x963E66858F6D4441}, // -50
{0x95A8637627989AAD, 0xDDE7001379A44AA9}, // -49
{0xBB127C53B17EC159, 0x5560C018580D5D53}, // -48
{0xE9D71B689DDE71AF, 0xAAB8F01E6E10B4A7}, // -47
{0x9226712162AB070D, 0xCAB3961304CA70E9}, // -46
{0xB6B00D69BB55C8D1, 0x3D607B97C5FD0D23}, // -45
{0xE45C10C42A2B3B05, 0x8CB89A7DB77C506B}, // -44
{0x8EB98A7A9A5B04E3, 0x77F3608E92ADB243}, // -43
{0xB267ED1940F1C61C, 0x55F038B237591ED4}, // -42
{0xDF01E85F912E37A3, 0x6B6C46DEC52F6689}, // -41
{0x8B61313BBABCE2C6, 0x2323AC4B3B3DA016}, // -40
{0xAE397D8AA96C1B77, 0xABEC975E0A0D081B}, // -39
{0xD9C7DCED53C72255, 0x96E7BD358C904A22}, // -38
{0x881CEA14545C7575, 0x7E50D64177DA2E55}, // -37
{0xAA242499697392D2, 0xDDE50BD1D5D0B9EA}, // -36
{0xD4AD2DBFC3D07787, 0x955E4EC64B44E865}, // -35
{0x84EC3C97DA624AB4, 0xBD5AF13BEF0B113F}, // -34
{0xA6274BBDD0FADD61, 0xECB1AD8AEACDD58F}, // -33
{0xCFB11EAD453994BA, 0x67DE18EDA5814AF3}, // -32
{0x81CEB32C4B43FCF4, 0x80EACF948770CED8}, // -31
{0xA2425FF75E14FC31, 0xA1258379A94D028E}, // -30
{0xCAD2F7F5359A3B3E, 0x096EE45813A04331}, // -29
{0xFD87B5F28300CA0D, 0x8BCA9D6E188853FD}, // -28
{0x9E74D1B791E07E48, 0x775EA264CF55347E}, // -27
{0xC612062576589DDA, 0x95364AFE032A819E}, // -26
{0xF79687AED3EEC551, 0x3A83DDBD83F52205}, // -25
{0x9ABE14CD44753B52, 0xC4926A9672793543}, // -24
{0xC16D9A0095928A27, 0x75B7053C0F178294}, // -23
{0xF1C90080BAF72CB1, 0x5324C68B12DD6339}, // -22
{0x971DA05074DA7BEE, 0xD3F6FC16EBCA5E04}, // -21
{0xBCE5086492111AEA, 0x88F4BB1CA6BCF585}, // -20
{0xEC1E4A7DB69561A5, 0x2B31E9E3D06C32E6}, // -19
{0x9392EE8E921D5D07, 0x3AFF322E62439FD0}, // -18
{0xB877AA3236A4B449, 0x09BEFEB9FAD487C3}, // -17
{0xE69594BEC44DE15B, 0x4C2EBE687989A9B4}, // -16
{0x901D7CF73AB0ACD9, 0x0F9D37014BF60A11}, // -15
{0xB424DC35095CD80F, 0x538484C19EF38C95}, // -14
{0xE12E13424BB40E13, 0x2865A5F206B06FBA}, // -13
{0x8CBCCC096F5088CB, 0xF93F87B7442E45D4}, // -12
{0xAFEBFF0BCB24AAFE, 0xF78F69A51539D749}, // -11
{0xDBE6FECEBDEDD5BE, 0xB573440E5A884D1C}, // -10
{0x89705F4136B4A597, 0x31680A88F8953031}, // -9
{0xABCC77118461CEFC, 0xFDC20D2B36BA7C3E}, // -8
{0xD6BF94D5E57A42BC, 0x3D32907604691B4D}, // -7
{0x8637BD05AF6C69B5, 0xA63F9A49C2C1B110}, // -6
{0xA7C5AC471B478423, 0x0FCF80DC33721D54}, // -5
{0xD1B71758E219652B, 0xD3C36113404EA4A9}, // -4
{0x83126E978D4FDF3B, 0x645A1CAC083126EA}, // -3
{0xA3D70A3D70A3D70A, 0x3D70A3D70A3D70A4}, // -2
{0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCD}, // -1
{0x8000000000000000, 0x0000000000000000}, // 0
{0xA000000000000000, 0x0000000000000000}, // 1
{0xC800000000000000, 0x0000000000000000}, // 2
{0xFA00000000000000, 0x0000000000000000}, // 3
{0x9C40000000000000, 0x0000000000000000}, // 4
{0xC350000000000000, 0x0000000000000000}, // 5
{0xF424000000000000, 0x0000000000000000}, // 6
{0x9896800000000000, 0x0000000000000000}, // 7
{0xBEBC200000000000, 0x0000000000000000}, // 8
{0xEE6B280000000000, 0x0000000000000000}, // 9
{0x9502F90000000000, 0x0000000000000000}, // 10
{0xBA43B74000000000, 0x0000000000000000}, // 11
{0xE8D4A51000000000, 0x0000000000000000}, // 12
{0x9184E72A00000000, 0x0000000000000000}, // 13
{0xB5E620F480000000, 0x0000000000000000}, // 14
{0xE35FA931A0000000, 0x0000000000000000}, // 15
{0x8E1BC9BF04000000, 0x0000000000000000}, // 16
{0xB1A2BC2EC5000000, 0x0000000000000000}, // 17
{0xDE0B6B3A76400000, 0x0000000000000000}, // 18
{0x8AC7230489E80000, 0x0000000000000000}, // 19
{0xAD78EBC5AC620000, 0x0000000000000000}, // 20
{0xD8D726B7177A8000, 0x0000000000000000}, // 21
{0x878678326EAC9000, 0x0000000000000000}, // 22
{0xA968163F0A57B400, 0x0000000000000000}, // 23
{0xD3C21BCECCEDA100, 0x0000000000000000}, // 24
{0x84595161401484A0, 0x0000000000000000}, // 25
{0xA56FA5B99019A5C8, 0x0000000000000000}, // 26
{0xCECB8F27F4200F3A, 0x0000000000000000}, // 27
{0x813F3978F8940984, 0x4000000000000000}, // 28
{0xA18F07D736B90BE5, 0x5000000000000000}, // 29
{0xC9F2C9CD04674EDE, 0xA400000000000000}, // 30
{0xFC6F7C4045812296, 0x4D00000000000000}, // 31
{0x9DC5ADA82B70B59D, 0xF020000000000000}, // 32
{0xC5371912364CE305, 0x6C28000000000000}, // 33
{0xF684DF56C3E01BC6, 0xC732000000000000}, // 34
{0x9A130B963A6C115C, 0x3C7F400000000000}, // 35
{0xC097CE7BC90715B3, 0x4B9F100000000000}, // 36
{0xF0BDC21ABB48DB20, 0x1E86D40000000000}, // 37
{0x96769950B50D88F4, 0x1314448000000000}, // 38
{0xBC143FA4E250EB31, 0x17D955A000000000}, // 39
{0xEB194F8E1AE525FD, 0x5DCFAB0800000000}, // 40
{0x92EFD1B8D0CF37BE, 0x5AA1CAE500000000}, // 41
{0xB7ABC627050305AD, 0xF14A3D9E40000000}, // 42
{0xE596B7B0C643C719, 0x6D9CCD05D0000000}, // 43
{0x8F7E32CE7BEA5C6F, 0xE4820023A2000000}, // 44
{0xB35DBF821AE4F38B, 0xDDA2802C8A800000}, // 45
{0xE0352F62A19E306E, 0xD50B2037AD200000}, // 46
{0x8C213D9DA502DE45, 0x4526F422CC340000}, // 47
{0xAF298D050E4395D6, 0x9670B12B7F410000}, // 48
{0xDAF3F04651D47B4C, 0x3C0CDD765F114000}, // 49
{0x88D8762BF324CD0F, 0xA5880A69FB6AC800}, // 50
{0xAB0E93B6EFEE0053, 0x8EEA0D047A457A00}, // 51
{0xD5D238A4ABE98068, 0x72A4904598D6D880}, // 52
{0x85A36366EB71F041, 0x47A6DA2B7F864750}, // 53
{0xA70C3C40A64E6C51, 0x999090B65F67D924}, // 54
{0xD0CF4B50CFE20765, 0xFFF4B4E3F741CF6D}, // 55
{0x82818F1281ED449F, 0xBFF8F10E7A8921A5}, // 56
{0xA321F2D7226895C7, 0xAFF72D52192B6A0E}, // 57
{0xCBEA6F8CEB02BB39, 0x9BF4F8A69F764491}, // 58
{0xFEE50B7025C36A08, 0x02F236D04753D5B5}, // 59
{0x9F4F2726179A2245, 0x01D762422C946591}, // 60
{0xC722F0EF9D80AAD6, 0x424D3AD2B7B97EF6}, // 61
{0xF8EBAD2B84E0D58B, 0xD2E0898765A7DEB3}, // 62
{0x9B934C3B330C8577, 0x63CC55F49F88EB30}, // 63
{0xC2781F49FFCFA6D5, 0x3CBF6B71C76B25FC}, // 64
{0xF316271C7FC3908A, 0x8BEF464E3945EF7B}, // 65
{0x97EDD871CFDA3A56, 0x97758BF0E3CBB5AD}, // 66
{0xBDE94E8E43D0C8EC, 0x3D52EEED1CBEA318}, // 67
{0xED63A231D4C4FB27, 0x4CA7AAA863EE4BDE}, // 68
{0x945E455F24FB1CF8, 0x8FE8CAA93E74EF6B}, // 69
{0xB975D6B6EE39E436, 0xB3E2FD538E122B45}, // 70
{0xE7D34C64A9C85D44, 0x60DBBCA87196B617}, // 71
{0x90E40FBEEA1D3A4A, 0xBC8955E946FE31CE}, // 72
{0xB51D13AEA4A488DD, 0x6BABAB6398BDBE42}, // 73
{0xE264589A4DCDAB14, 0xC696963C7EED2DD2}, // 74
{0x8D7EB76070A08AEC, 0xFC1E1DE5CF543CA3}, // 75
{0xB0DE65388CC8ADA8, 0x3B25A55F43294BCC}, // 76
{0xDD15FE86AFFAD912, 0x49EF0EB713F39EBF}, // 77
{0x8A2DBF142DFCC7AB, 0x6E3569326C784338}, // 78
{0xACB92ED9397BF996, 0x49C2C37F07965405}, // 79
{0xD7E77A8F87DAF7FB, 0xDC33745EC97BE907}, // 80
{0x86F0AC99B4E8DAFD, 0x69A028BB3DED71A4}, // 81
{0xA8ACD7C0222311BC, 0xC40832EA0D68CE0D}, // 82
{0xD2D80DB02AABD62B, 0xF50A3FA490C30191}, // 83
{0x83C7088E1AAB65DB, 0x792667C6DA79E0FB}, // 84
{0xA4B8CAB1A1563F52, 0x577001B891185939}, // 85
{0xCDE6FD5E09ABCF26, 0xED4C0226B55E6F87}, // 86
{0x80B05E5AC60B6178, 0x544F8158315B05B5}, // 87
{0xA0DC75F1778E39D6, 0x696361AE3DB1C722}, // 88
{0xC913936DD571C84C, 0x03BC3A19CD1E38EA}, // 89
{0xFB5878494ACE3A5F, 0x04AB48A04065C724}, // 90
{0x9D174B2DCEC0E47B, 0x62EB0D64283F9C77}, // 91
{0xC45D1DF942711D9A, 0x3BA5D0BD324F8395}, // 92
{0xF5746577930D6500, 0xCA8F44EC7EE3647A}, // 93
{0x9968BF6ABBE85F20, 0x7E998B13CF4E1ECC}, // 94
{0xBFC2EF456AE276E8, 0x9E3FEDD8C321A67F}, // 95
{0xEFB3AB16C59B14A2, 0xC5CFE94EF3EA101F}, // 96
{0x95D04AEE3B80ECE5, 0xBBA1F1D158724A13}, // 97
{0xBB445DA9CA61281F, 0x2A8A6E45AE8EDC98}, // 98
{0xEA1575143CF97226, 0xF52D09D71A3293BE}, // 99
{0x924D692CA61BE758, 0x593C2626705F9C57}, // 100
{0xB6E0C377CFA2E12E, 0x6F8B2FB00C77836D}, // 101
{0xE498F455C38B997A, 0x0B6DFB9C0F956448}, // 102
{0x8EDF98B59A373FEC, 0x4724BD4189BD5EAD}, // 103
{0xB2977EE300C50FE7, 0x58EDEC91EC2CB658}, // 104
{0xDF3D5E9BC0F653E1, 0x2F2967B66737E3EE}, // 105
{0x8B865B215899F46C, 0xBD79E0D20082EE75}, // 106
{0xAE67F1E9AEC07187, 0xECD8590680A3AA12}, // 107
{0xDA01EE641A708DE9, 0xE80E6F4820CC9496}, // 108
{0x884134FE908658B2, 0x3109058D147FDCDE}, // 109
{0xAA51823E34A7EEDE, 0xBD4B46F0599FD416}, // 110
{0xD4E5E2CDC1D1EA96, 0x6C9E18AC7007C91B}, // 111
{0x850FADC09923329E, 0x03E2CF6BC604DDB1}, // 112
{0xA6539930BF6BFF45, 0x84DB8346B786151D}, // 113
{0xCFE87F7CEF46FF16, 0xE612641865679A64}, // 114
{0x81F14FAE158C5F6E, 0x4FCB7E8F3F60C07F}, // 115
{0xA26DA3999AEF7749, 0xE3BE5E330F38F09E}, // 116
{0xCB090C8001AB551C, 0x5CADF5BFD3072CC6}, // 117
{0xFDCB4FA002162A63, 0x73D9732FC7C8F7F7}, // 118
{0x9E9F11C4014DDA7E, 0x2867E7FDDCDD9AFB}, // 119
{0xC646D63501A1511D, 0xB281E1FD541501B9}, // 120
{0xF7D88BC24209A565, 0x1F225A7CA91A4227}, // 121
{0x9AE757596946075F, 0x3375788DE9B06959}, // 122
{0xC1A12D2FC3978937, 0x0052D6B1641C83AF}, // 123
{0xF209787BB47D6B84, 0xC0678C5DBD23A49B}, // 124
{0x9745EB4D50CE6332, 0xF840B7BA963646E1}, // 125
{0xBD176620A501FBFF, 0xB650E5A93BC3D899}, // 126
{0xEC5D3FA8CE427AFF, 0xA3E51F138AB4CEBF}, // 127
{0x93BA47C980E98CDF, 0xC66F336C36B10138}, // 128
{0xB8A8D9BBE123F017, 0xB80B0047445D4185}, // 129
{0xE6D3102AD96CEC1D, 0xA60DC059157491E6}, // 130
{0x9043EA1AC7E41392, 0x87C89837AD68DB30}, // 131
{0xB454E4A179DD1877, 0x29BABE4598C311FC}, // 132
{0xE16A1DC9D8545E94, 0xF4296DD6FEF3D67B}, // 133
{0x8CE2529E2734BB1D, 0x1899E4A65F58660D}, // 134
{0xB01AE745B101E9E4, 0x5EC05DCFF72E7F90}, // 135
{0xDC21A1171D42645D, 0x76707543F4FA1F74}, // 136
{0x899504AE72497EBA, 0x6A06494A791C53A9}, // 137
{0xABFA45DA0EDBDE69, 0x0487DB9D17636893}, // 138
{0xD6F8D7509292D603, 0x45A9D2845D3C42B7}, // 139
{0x865B86925B9BC5C2, 0x0B8A2392BA45A9B3}, // 140
{0xA7F26836F282B732, 0x8E6CAC7768D7141F}, // 141
{0xD1EF0244AF2364FF, 0x3207D795430CD927}, // 142
{0x8335616AED761F1F, 0x7F44E6BD49E807B9}, // 143
{0xA402B9C5A8D3A6E7, 0x5F16206C9C6209A7}, // 144
{0xCD036837130890A1, 0x36DBA887C37A8C10}, // 145
{0x802221226BE55A64, 0xC2494954DA2C978A}, // 146
{0xA02AA96B06DEB0FD, 0xF2DB9BAA10B7BD6D}, // 147
{0xC83553C5C8965D3D, 0x6F92829494E5ACC8}, // 148
{0xFA42A8B73ABBF48C, 0xCB772339BA1F17FA}, // 149
{0x9C69A97284B578D7, 0xFF2A760414536EFC}, // 150
{0xC38413CF25E2D70D, 0xFEF5138519684ABB}, // 151
{0xF46518C2EF5B8CD1, 0x7EB258665FC25D6A}, // 152
{0x98BF2F79D5993802, 0xEF2F773FFBD97A62}, // 153
{0xBEEEFB584AFF8603, 0xAAFB550FFACFD8FB}, // 154
{0xEEAABA2E5DBF6784, 0x95BA2A53F983CF39}, // 155
{0x952AB45CFA97A0B2, 0xDD945A747BF26184}, // 156
{0xBA756174393D88DF, 0x94F971119AEEF9E5}, // 157
{0xE912B9D1478CEB17, 0x7A37CD5601AAB85E}, // 158
{0x91ABB422CCB812EE, 0xAC62E055C10AB33B}, // 159
{0xB616A12B7FE617AA, 0x577B986B314D600A}, // 160
{0xE39C49765FDF9D94, 0xED5A7E85FDA0B80C}, // 161
{0x8E41ADE9FBEBC27D, 0x14588F13BE847308}, // 162
{0xB1D219647AE6B31C, 0x596EB2D8AE258FC9}, // 163
{0xDE469FBD99A05FE3, 0x6FCA5F8ED9AEF3BC}, // 164
{0x8AEC23D680043BEE, 0x25DE7BB9480D5855}, // 165
{0xADA72CCC20054AE9, 0xAF561AA79A10AE6B}, // 166
{0xD910F7FF28069DA4, 0x1B2BA1518094DA05}, // 167
{0x87AA9AFF79042286, 0x90FB44D2F05D0843}, // 168
{0xA99541BF57452B28, 0x353A1607AC744A54}, // 169
{0xD3FA922F2D1675F2, 0x42889B8997915CE9}, // 170
{0x847C9B5D7C2E09B7, 0x69956135FEBADA12}, // 171
{0xA59BC234DB398C25, 0x43FAB9837E699096}, // 172
{0xCF02B2C21207EF2E, 0x94F967E45E03F4BC}, // 173
{0x8161AFB94B44F57D, 0x1D1BE0EEBAC278F6}, // 174
{0xA1BA1BA79E1632DC, 0x6462D92A69731733}, // 175
{0xCA28A291859BBF93, 0x7D7B8F7503CFDCFF}, // 176
{0xFCB2CB35E702AF78, 0x5CDA735244C3D43F}, // 177
{0x9DEFBF01B061ADAB, 0x3A0888136AFA64A8}, // 178
{0xC56BAEC21C7A1916, 0x088AAA1845B8FDD1}, // 179
{0xF6C69A72A3989F5B, 0x8AAD549E57273D46}, // 180
{0x9A3C2087A63F6399, 0x36AC54E2F678864C}, // 181
{0xC0CB28A98FCF3C7F, 0x84576A1BB416A7DE}, // 182
{0xF0FDF2D3F3C30B9F, 0x656D44A2A11C51D6}, // 183
{0x969EB7C47859E743, 0x9F644AE5A4B1B326}, // 184
{0xBC4665B596706114, 0x873D5D9F0DDE1FEF}, // 185
{0xEB57FF22FC0C7959, 0xA90CB506D155A7EB}, // 186
{0x9316FF75DD87CBD8, 0x09A7F12442D588F3}, // 187
{0xB7DCBF5354E9BECE, 0x0C11ED6D538AEB30}, // 188
{0xE5D3EF282A242E81, 0x8F1668C8A86DA5FB}, // 189
{0x8FA475791A569D10, 0xF96E017D694487BD}, // 190
{0xB38D92D760EC4455, 0x37C981DCC395A9AD}, // 191
{0xE070F78D3927556A, 0x85BBE253F47B1418}, // 192
{0x8C469AB843B89562, 0x93956D7478CCEC8F}, // 193
{0xAF58416654A6BABB, 0x387AC8D1970027B3}, // 194
{0xDB2E51BFE9D0696A, 0x06997B05FCC0319F}, // 195
{0x88FCF317F22241E2, 0x441FECE3BDF81F04}, // 196
{0xAB3C2FDDEEAAD25A, 0xD527E81CAD7626C4}, // 197
{0xD60B3BD56A5586F1, 0x8A71E223D8D3B075}, // 198
{0x85C7056562757456, 0xF6872D5667844E4A}, // 199
{0xA738C6BEBB12D16C, 0xB428F8AC016561DC}, // 200
{0xD106F86E69D785C7, 0xE13336D701BEBA53}, // 201
{0x82A45B450226B39C, 0xECC0024661173474}, // 202
{0xA34D721642B06084, 0x27F002D7F95D0191}, // 203
{0xCC20CE9BD35C78A5, 0x31EC038DF7B441F5}, // 204
{0xFF290242C83396CE, 0x7E67047175A15272}, // 205
{0x9F79A169BD203E41, 0x0F0062C6E984D387}, // 206
{0xC75809C42C684DD1, 0x52C07B78A3E60869}, // 207
{0xF92E0C3537826145, 0xA7709A56CCDF8A83}, // 208
{0x9BBCC7A142B17CCB, 0x88A66076400BB692}, // 209
{0xC2ABF989935DDBFE, 0x6ACFF893D00EA436}, // 210
{0xF356F7EBF83552FE, 0x0583F6B8C4124D44}, // 211
{0x98165AF37B2153DE, 0xC3727A337A8B704B}, // 212
{0xBE1BF1B059E9A8D6, 0x744F18C0592E4C5D}, // 213
{0xEDA2EE1C7064130C, 0x1162DEF06F79DF74}, // 214
{0x9485D4D1C63E8BE7, 0x8ADDCB5645AC2BA9}, // 215
{0xB9A74A0637CE2EE1, 0x6D953E2BD7173693}, // 216
{0xE8111C87C5C1BA99, 0xC8FA8DB6CCDD0438}, // 217
{0x910AB1D4DB9914A0, 0x1D9C9892400A22A3}, // 218
{0xB54D5E4A127F59C8, 0x2503BEB6D00CAB4C}, // 219
{0xE2A0B5DC971F303A, 0x2E44AE64840FD61E}, // 220
{0x8DA471A9DE737E24, 0x5CEAECFED289E5D3}, // 221
{0xB10D8E1456105DAD, 0x7425A83E872C5F48}, // 222
{0xDD50F1996B947518, 0xD12F124E28F7771A}, // 223
{0x8A5296FFE33CC92F, 0x82BD6B70D99AAA70}, // 224
{0xACE73CBFDC0BFB7B, 0x636CC64D1001550C}, // 225
{0xD8210BEFD30EFA5A, 0x3C47F7E05401AA4F}, // 226
{0x8714A775E3E95C78, 0x65ACFAEC34810A72}, // 227
{0xA8D9D1535CE3B396, 0x7F1839A741A14D0E}, // 228
{0xD31045A8341CA07C, 0x1EDE48111209A051}, // 229
{0x83EA2B892091E44D, 0x934AED0AAB460433}, // 230
{0xA4E4B66B68B65D60, 0xF81DA84D56178540}, // 231
{0xCE1DE40642E3F4B9, 0x36251260AB9D668F}, // 232
{0x80D2AE83E9CE78F3, 0xC1D72B7C6B42601A}, // 233
{0xA1075A24E4421730, 0xB24CF65B8612F820}, // 234
{0xC94930AE1D529CFC, 0xDEE033F26797B628}, // 235
{0xFB9B7CD9A4A7443C, 0x169840EF017DA3B2}, // 236
{0x9D412E0806E88AA5, 0x8E1F289560EE864F}, // 237
{0xC491798A08A2AD4E, 0xF1A6F2BAB92A27E3}, // 238
{0xF5B5D7EC8ACB58A2, 0xAE10AF696774B1DC}, // 239
{0x9991A6F3D6BF1765, 0xACCA6DA1E0A8EF2A}, // 240
{0xBFF610B0CC6EDD3F, 0x17FD090A58D32AF4}, // 241
{0xEFF394DCFF8A948E, 0xDDFC4B4CEF07F5B1}, // 242
{0x95F83D0A1FB69CD9, 0x4ABDAF101564F98F}, // 243
{0xBB764C4CA7A4440F, 0x9D6D1AD41ABE37F2}, // 244
{0xEA53DF5FD18D5513, 0x84C86189216DC5EE}, // 245
{0x92746B9BE2F8552C, 0x32FD3CF5B4E49BB5}, // 246
{0xB7118682DBB66A77, 0x3FBC8C33221DC2A2}, // 247
{0xE4D5E82392A40515, 0x0FABAF3FEAA5334B}, // 248
{0x8F05B1163BA6832D, 0x29CB4D87F2A7400F}, // 249
{0xB2C71D5BCA9023F8, 0x743E20E9EF511013}, // 250
{0xDF78E4B2BD342CF6, 0x914DA9246B255417}, // 251
{0x8BAB8EEFB6409C1A, 0x1AD089B6C2F7548F}, // 252
{0xAE9672ABA3D0C320, 0xA184AC2473B529B2}, // 253
{0xDA3C0F568CC4F3E8, 0xC9E5D72D90A2741F}, // 254
{0x8865899617FB1871, 0x7E2FA67C7A658893}, // 255
{0xAA7EEBFB9DF9DE8D, 0xDDBB901B98FEEAB8}, // 256
{0xD51EA6FA85785631, 0x552A74227F3EA566}, // 257
{0x8533285C936B35DE, 0xD53A88958F872760}, // 258
{0xA67FF273B8460356, 0x8A892ABAF368F138}, // 259
{0xD01FEF10A657842C, 0x2D2B7569B0432D86}, // 260
{0x8213F56A67F6B29B, 0x9C3B29620E29FC74}, // 261
{0xA298F2C501F45F42, 0x8349F3BA91B47B90}, // 262
{0xCB3F2F7642717713, 0x241C70A936219A74}, // 263
{0xFE0EFB53D30DD4D7, 0xED238CD383AA0111}, // 264
{0x9EC95D1463E8A506, 0xF4363804324A40AB}, // 265
{0xC67BB4597CE2CE48, 0xB143C6053EDCD0D6}, // 266
{0xF81AA16FDC1B81DA, 0xDD94B7868E94050B}, // 267
{0x9B10A4E5E9913128, 0xCA7CF2B4191C8327}, // 268
{0xC1D4CE1F63F57D72, 0xFD1C2F611F63A3F1}, // 269
{0xF24A01A73CF2DCCF, 0xBC633B39673C8CED}, // 270
{0x976E41088617CA01, 0xD5BE0503E085D814}, // 271
{0xBD49D14AA79DBC82, 0x4B2D8644D8A74E19}, // 272
{0xEC9C459D51852BA2, 0xDDF8E7D60ED1219F}, // 273
{0x93E1AB8252F33B45, 0xCABB90E5C942B504}, // 274
{0xB8DA1662E7B00A17, 0x3D6A751F3B936244}, // 275
{0xE7109BFBA19C0C9D, 0x0CC512670A783AD5}, // 276
{0x906A617D450187E2, 0x27FB2B80668B24C6}, // 277
{0xB484F9DC9641E9DA, 0xB1F9F660802DEDF7}, // 278
{0xE1A63853BBD26451, 0x5E7873F8A0396974}, // 279
{0x8D07E33455637EB2, 0xDB0B487B6423E1E9}, // 280
{0xB049DC016ABC5E5F, 0x91CE1A9A3D2CDA63}, // 281
{0xDC5C5301C56B75F7, 0x7641A140CC7810FC}, // 282
{0x89B9B3E11B6329BA, 0xA9E904C87FCB0A9E}, // 283
{0xAC2820D9623BF429, 0x546345FA9FBDCD45}, // 284
{0xD732290FBACAF133, 0xA97C177947AD4096}, // 285
{0x867F59A9D4BED6C0, 0x49ED8EABCCCC485E}, // 286
{0xA81F301449EE8C70, 0x5C68F256BFFF5A75}, // 287
{0xD226FC195C6A2F8C, 0x73832EEC6FFF3112}, // 288
{0x83585D8FD9C25DB7, 0xC831FD53C5FF7EAC}, // 289
{0xA42E74F3D032F525, 0xBA3E7CA8B77F5E56}, // 290
{0xCD3A1230C43FB26F, 0x28CE1BD2E55F35EC}, // 291
{0x80444B5E7AA7CF85, 0x7980D163CF5B81B4}, // 292
{0xA0555E361951C366, 0xD7E105BCC3326220}, // 293
{0xC86AB5C39FA63440, 0x8DD9472BF3FEFAA8}, // 294
{0xFA856334878FC150, 0xB14F98F6F0FEB952}, // 295
{0x9C935E00D4B9D8D2, 0x6ED1BF9A569F33D4}, // 296
{0xC3B8358109E84F07, 0x0A862F80EC4700C9}, // 297
{0xF4A642E14C6262C8, 0xCD27BB612758C0FB}, // 298
{0x98E7E9CCCFBD7DBD, 0x8038D51CB897789D}, // 299
{0xBF21E44003ACDD2C, 0xE0470A63E6BD56C4}, // 300
{0xEEEA5D5004981478, 0x1858CCFCE06CAC75}, // 301
{0x95527A5202DF0CCB, 0x0F37801E0C43EBC9}, // 302
{0xBAA718E68396CFFD, 0xD30560258F54E6BB}, // 303
{0xE950DF20247C83FD, 0x47C6B82EF32A206A}, // 304
{0x91D28B7416CDD27E, 0x4CDC331D57FA5442}, // 305
{0xB6472E511C81471D, 0xE0133FE4ADF8E953}, // 306
{0xE3D8F9E563A198E5, 0x58180FDDD97723A7}, // 307
{0x8E679C2F5E44FF8F, 0x570F09EAA7EA7649}, // 308
{0xB201833B35D63F73, 0x2CD2CC6551E513DB}, // 309
{0xDE81E40A034BCF4F, 0xF8077F7EA65E58D2}, // 310
{0x8B112E86420F6191, 0xFB04AFAF27FAF783}, // 311
{0xADD57A27D29339F6, 0x79C5DB9AF1F9B564}, // 312
{0xD94AD8B1C7380874, 0x18375281AE7822BD}, // 313
{0x87CEC76F1C830548, 0x8F2293910D0B15B6}, // 314
{0xA9C2794AE3A3C69A, 0xB2EB3875504DDB23}, // 315
{0xD433179D9C8CB841, 0x5FA60692A46151EC}, // 316
{0x849FEEC281D7F328, 0xDBC7C41BA6BCD334}, // 317
{0xA5C7EA73224DEFF3, 0x12B9B522906C0801}, // 318
{0xCF39E50FEAE16BEF, 0xD768226B34870A01}, // 319
{0x81842F29F2CCE375, 0xE6A1158300D46641}, // 320
{0xA1E53AF46F801C53, 0x60495AE3C1097FD1}, // 321
{0xCA5E89B18B602368, 0x385BB19CB14BDFC5}, // 322
{0xFCF62C1DEE382C42, 0x46729E03DD9ED7B6}, // 323
{0x9E19DB92B4E31BA9, 0x6C07A2C26A8346D2}, // 324
};
return g[k - KMIN];
#undef KMIN
#undef KMAX
}
#endif

41
native/test/xassert.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef XASSERT_H
#define XASSERT_H
#ifndef DEBUG
#define xassert(expr) ((void)0)
#else
#include "xprintf.h"
#define xassert(expr) \
((expr) \
? ((void)0) \
: _xassert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__))
static void* raise = 0;
static void xabort() {
*(int*)(raise) = 1;
}
static void _xassert(const char *assertion, const char *file,
const unsigned line, const char *func) {
xprintf("%s:%u: %s Assertion `%s' failed.\n",
file, line, func ? func : "?", assertion);
xabort();
}
#endif // DEBUG
#endif // XASSERT_H

View file

@ -53,6 +53,28 @@ static void printstr(const char *s)
static void printint(int64_t v)
{
char neg = 0;
char buf[32] = {};
char *p = &buf[31];
uint64_t u;
if (v < 0) {
u = ~v + 1;
neg = 1;
} else {
u = v;
}
while (u)
{
*--p = (u % 10) + '0';
u /= 10;
}
if (neg) {
*--p = '-';
}
printstr(p);
}
static void printuint(uint64_t v)
{
char buf[32] = {};
char *p = &buf[31];
if (v == 0)
@ -60,20 +82,11 @@ static void printint(int64_t v)
printch('0');
return;
}
if (v < 0)
{
v = -v;
neg = 1;
}
while (v)
{
*--p = (v % 10) + '0';
v /= 10;
}
if (neg)
{
*--p = '-';
}
printstr(p);
}
@ -160,16 +173,26 @@ static void xprintf(const char *fmt, ...)
printch('%');
break;
}
case 's':
case 'g':
{
printgostr(__builtin_va_arg(va, GoString *));
break;
}
case 's':
{
printstr(__builtin_va_arg(va, const char *));
break;
}
case 'd':
{
printint(__builtin_va_arg(va, int64_t));
break;
}
case 'u':
{
printuint(__builtin_va_arg(va, uint64_t));
break;
}
case 'f':
{
printint(__builtin_va_arg(va, double));
@ -177,7 +200,7 @@ static void xprintf(const char *fmt, ...)
}
case 'c':
{
printch(__builtin_va_arg(va, const char));
printch((char)(__builtin_va_arg(va, int)));
break;
}
case 'x':

View file

@ -67,8 +67,6 @@ static inline ssize_t valid_utf8_4byte(uint32_t ubin) {
bit pattern [11110... 10...... 10...... 10......] (F0 80 80 80)
---------------------------------------------------
*/
const uint32_t b1_mask = 0x00000080UL;
const uint32_t b1_patt = 0x00000000UL;
const uint32_t b2_mask = 0x0000C0E0UL;
const uint32_t b2_patt = 0x000080C0UL;
const uint32_t b2_requ = 0x0000001EUL;
@ -82,10 +80,6 @@ static inline ssize_t valid_utf8_4byte(uint32_t ubin) {
const uint32_t b4_err0 = 0x00000004UL;
const uint32_t b4_err1 = 0x00003003UL;
#define is_valid_seq_1(uni) ( \
((uni & b1_mask) == b1_patt) \
)
#define is_valid_seq_2(uni) ( \
((uni & b2_mask) == b2_patt) && \
((uni & b2_requ)) \