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

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>
This commit is contained in:
liu 2022-09-20 10:26:18 +08:00 committed by GitHub
parent 2138136685
commit ccc0f3f1e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 20751 additions and 13684 deletions

View file

@ -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)

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

@ -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

@ -601,3 +601,83 @@ func BenchmarkCompact_Std(b *testing.B) {
_ = 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

@ -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)

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 {
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[:], val, 'g', -1, 64) }},
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], val) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
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: "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: "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: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
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 benchmarks {
b.Run(bm.name, bm.test)
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,16 +97,16 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
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) }},
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[:], -int64(i), 10) }},
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)) }},
@ -116,20 +117,37 @@ func BenchmarkFastInt_IntToString(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
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[:], uint64(i), 10) }},
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], uint64(i)) }},
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 {
b.Run(bm.name, bm.test)
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}
}

View file

@ -39,6 +39,11 @@ func __u64toa(out *byte, val uint64) (ret int)
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter

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,28 +9,30 @@ package avx
func __native_entry__() uintptr
var (
_subr__f64toa = __native_entry__() + 704
_subr__html_escape = __native_entry__() + 9920
_subr__i64toa = __native_entry__() + 3616
_subr__f32toa = __native_entry__() + 24880
_subr__f64toa = __native_entry__() + 720
_subr__html_escape = __native_entry__() + 10768
_subr__i64toa = __native_entry__() + 4464
_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__quote = __native_entry__() + 5840
_subr__skip_array = __native_entry__() + 23152
_subr__skip_number = __native_entry__() + 24624
_subr__skip_object = __native_entry__() + 23200
_subr__skip_one = __native_entry__() + 21280
_subr__u64toa = __native_entry__() + 4576
_subr__unquote = __native_entry__() + 7584
_subr__validate_one = __native_entry__() + 24768
_subr__value = __native_entry__() + 14016
_subr__vnumber = __native_entry__() + 19024
_subr__vsigned = __native_entry__() + 20576
_subr__vstring = __native_entry__() + 16096
_subr__vunsigned = __native_entry__() + 20928
)
const (
_stack__f64toa = 128
_stack__f32toa = 728
_stack__f64toa = 712
_stack__html_escape = 64
_stack__i64toa = 16
_stack__lspace = 8
@ -51,6 +53,7 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
@ -72,6 +75,7 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa

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 {
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[:], val, 'g', -1, 64) }},
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], val) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
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: "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: "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: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
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 benchmarks {
b.Run(bm.name, bm.test)
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,16 +97,16 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
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) }},
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[:], -int64(i), 10) }},
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)) }},
@ -116,20 +117,37 @@ func BenchmarkFastInt_IntToString(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
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[:], uint64(i), 10) }},
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], uint64(i)) }},
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 {
b.Run(bm.name, bm.test)
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}
}

View file

@ -39,6 +39,11 @@ func __u64toa(out *byte, val uint64) (ret int)
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter

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,28 +9,30 @@ package avx2
func __native_entry__() uintptr
var (
_subr__f64toa = __native_entry__() + 960
_subr__html_escape = __native_entry__() + 11776
_subr__i64toa = __native_entry__() + 3872
_subr__f32toa = __native_entry__() + 28752
_subr__f64toa = __native_entry__() + 976
_subr__html_escape = __native_entry__() + 12608
_subr__i64toa = __native_entry__() + 4720
_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__quote = __native_entry__() + 6192
_subr__skip_array = __native_entry__() + 26400
_subr__skip_number = __native_entry__() + 28496
_subr__skip_object = __native_entry__() + 26448
_subr__skip_one = __native_entry__() + 24496
_subr__u64toa = __native_entry__() + 4832
_subr__unquote = __native_entry__() + 9136
_subr__validate_one = __native_entry__() + 28640
_subr__value = __native_entry__() + 17184
_subr__vnumber = __native_entry__() + 22240
_subr__vsigned = __native_entry__() + 23792
_subr__vstring = __native_entry__() + 19568
_subr__vunsigned = __native_entry__() + 24144
)
const (
_stack__f64toa = 128
_stack__f32toa = 728
_stack__f64toa = 712
_stack__html_escape = 72
_stack__i64toa = 16
_stack__lspace = 8
@ -51,6 +53,7 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
@ -72,6 +75,7 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa

View file

@ -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
@ -133,6 +136,7 @@ func useAVX2() {
func useSSE4() {
S_f64toa = sse4.S_f64toa
S_f32toa = sse4.S_f32toa
S_i64toa = sse4.S_i64toa
S_u64toa = sse4.S_u64toa
S_lspace = sse4.S_lspace

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 {
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[:], val, 'g', -1, 64) }},
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], val) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
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: "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: "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: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
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 benchmarks {
b.Run(bm.name, bm.test)
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,16 +95,16 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
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) }},
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[:], -int64(i), 10) }},
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)) }},
@ -114,20 +115,37 @@ func BenchmarkFastInt_IntToString(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
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[:], uint64(i), 10) }},
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], uint64(i)) }},
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 {
b.Run(bm.name, bm.test)
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}
}

View file

@ -37,6 +37,11 @@ func __u64toa(out *byte, val uint64) (ret int)
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter

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

@ -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 {
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[:], val, 'g', -1, 64) }},
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], val) }},
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], c.float) }},
}}
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
for _, bm := range f64bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}
func BenchmarkFastFloat_EncodeZero(b *testing.B) {
val := float64(0)
benchmarks := []struct {
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: "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: "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: "FastFloat",
test: func(b *testing.B) { var buf [64]byte; for i := 0; i < b.N; i++ { __f64toa(&buf[0], val) }},
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 benchmarks {
b.Run(bm.name, bm.test)
for _, bm := range bench {
name := bm.name + "_" + c.name
b.Run(name, bm.test)
}
}
}

View file

@ -21,6 +21,7 @@ package sse4
import (
`strconv`
`testing`
`fmt`
`github.com/stretchr/testify/assert`
)
@ -96,16 +97,16 @@ func TestFastInt_UintToString(t *testing.T) {
assert.Equal(t, "18446744073709551615" , string(buf[:__u64toa(&buf[0], 18446744073709551615)]))
}
func BenchmarkFastInt_IntToString(b *testing.B) {
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) }},
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[:], -int64(i), 10) }},
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)) }},
@ -116,20 +117,37 @@ func BenchmarkFastInt_IntToString(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, bm.test)
}
}
}
func BenchmarkFastInt_UintToString(b *testing.B) {
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[:], uint64(i), 10) }},
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], uint64(i)) }},
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 {
b.Run(bm.name, bm.test)
name := fmt.Sprintf("%s_%s", bm.name, t.name)
b.Run(name, bm.test)
}
}
}
}

View file

@ -39,6 +39,11 @@ func __u64toa(out *byte, val uint64) (ret int)
//goland:noinspection GoUnusedParameter
func __f64toa(out *byte, val float64) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func __f32toa(out *byte, val float32) (ret int)
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter

File diff suppressed because it is too large Load diff

View file

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

View file

@ -9,28 +9,30 @@ package sse4
func __native_entry__() uintptr
var (
_subr__f32toa = __native_entry__() + 24896
_subr__f64toa = __native_entry__() + 640
_subr__html_escape = __native_entry__() + 9808
_subr__i64toa = __native_entry__() + 3440
_subr__html_escape = __native_entry__() + 10672
_subr__i64toa = __native_entry__() + 4304
_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__quote = __native_entry__() + 5712
_subr__skip_array = __native_entry__() + 23184
_subr__skip_number = __native_entry__() + 24688
_subr__skip_object = __native_entry__() + 23232
_subr__skip_one = __native_entry__() + 21312
_subr__u64toa = __native_entry__() + 4432
_subr__unquote = __native_entry__() + 7488
_subr__validate_one = __native_entry__() + 24832
_subr__value = __native_entry__() + 13936
_subr__vnumber = __native_entry__() + 19056
_subr__vsigned = __native_entry__() + 20608
_subr__vstring = __native_entry__() + 16016
_subr__vunsigned = __native_entry__() + 20960
)
const (
_stack__f64toa = 128
_stack__f32toa = 632
_stack__f64toa = 616
_stack__html_escape = 64
_stack__i64toa = 16
_stack__lspace = 8
@ -51,6 +53,7 @@ const (
)
var (
_ = _subr__f32toa
_ = _subr__f64toa
_ = _subr__html_escape
_ = _subr__i64toa
@ -72,6 +75,7 @@ var (
)
const (
_ = _stack__f32toa
_ = _stack__f64toa
_ = _stack__html_escape
_ = _stack__i64toa

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

@ -1,485 +1,405 @@
/* Copyright 2018 Ulf Adams.
* Modifications copyright 2021 ByteDance Inc.
/* Copyright 2020 Alexander Bolz
*
* The contents of this file may be used under the terms of the Apache License,
* Version 2.0.
* Boost Software License - Version 1.0 - August 17th, 2003
*
* (See accompanying file LICENSE-Apache or copy at
* http: *www.apache.org/licenses/LICENSE-2.0)
* 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:
*
* 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)
* 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;
}
return cnt;
}
/* 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;
}
/* 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;
}
/* 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;
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;
}
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;
}
/* 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));
}
static inline char* format_significand(uint64_t sig, char *out, int cnt) {
char *p = out + cnt;
int ctz = 0;
#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;
} else {
e2 = (int32_t) exp - 1023 - 52 - 2;
m2 = (1ull << 52) | man;
}
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;
}
/* 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;
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(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);
} else {
ctz += 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;
p -= 8;
}
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 - ctz;
}
static inline int print_exponent(f64_d v, char *out, int mlen) {
int idx = 0;
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;
} else {
++idx;
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(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;
}
/* Print the exponent */
out[idx++] = 'e';
int32_t exp = v.exp + (int32_t) mlen - 1;
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 {
*out = (char) ('0' + sig2);
}
return out + cnt;
}
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 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) {
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;
/* 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(v.sig, p, cnt);
while (*(end - 1) == '0') end--;
if (point <= 0) {
return end;
}
/* 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 {
rzeros = exp10 - mlen + 1;
for (int i = 0; i < point - digs; i++) {
*end++ = '0';
}
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];
}
out[idx + point] = '.';
idx += 1;
}
/* add right zeros */
idx += mlen;
for (i = 0; i < rzeros; ++i) {
out[idx++] = '0';
}
return idx;
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

@ -21,3 +21,4 @@
#include "atof_eisel_lemire.c"
#include "atof_native.c"
#include "scanning.c"
#include "f32toa.c"

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)) \