1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package apd
16
17 import (
18 "bytes"
19 "math/rand"
20 "strings"
21 "testing"
22 )
23
24 func BenchmarkNumDigitsLookup(b *testing.B) {
25 prep := func(start string, c byte) []*Decimal {
26 var ds []*Decimal
27 buf := bytes.NewBufferString(start)
28 for i := 1; i < digitsTableSize; i++ {
29 buf.WriteByte(c)
30 d, _, _ := NewFromString(buf.String())
31 ds = append(ds, d)
32 }
33 return ds
34 }
35 var ds []*Decimal
36 ds = append(ds, prep("", '9')...)
37 ds = append(ds, prep("1", '0')...)
38 ds = append(ds, prep("-", '9')...)
39 ds = append(ds, prep("-1", '0')...)
40 b.ResetTimer()
41 for i := 0; i < b.N; i++ {
42 for _, d := range ds {
43 d.NumDigits()
44 }
45 }
46 }
47
48 func BenchmarkNumDigitsFull(b *testing.B) {
49 prep := func(start string, c byte) []*Decimal {
50 var ds []*Decimal
51 buf := bytes.NewBufferString(start)
52 for i := 1; i < 1000; i++ {
53 buf.WriteByte(c)
54 d, _, _ := NewFromString(buf.String())
55 ds = append(ds, d)
56 }
57 return ds
58 }
59 var ds []*Decimal
60 ds = append(ds, prep("", '9')...)
61 ds = append(ds, prep("1", '0')...)
62 ds = append(ds, prep("-", '9')...)
63 ds = append(ds, prep("-1", '0')...)
64 b.ResetTimer()
65 for i := 0; i < b.N; i++ {
66 for _, d := range ds {
67 d.NumDigits()
68 }
69 }
70 }
71
72 func TestNumDigits(t *testing.T) {
73 runTest := func(start string, c byte) {
74 buf := bytes.NewBufferString(start)
75 var offset int
76 if strings.HasPrefix(start, "-") {
77 offset--
78 }
79 for i := 1; i < 1000; i++ {
80 buf.WriteByte(c)
81 bs := buf.String()
82 t.Run(bs, func(t *testing.T) {
83 d := newDecimal(t, testCtx, bs)
84 n := d.NumDigits()
85 e := int64(buf.Len() + offset)
86 if n != e {
87 t.Fatalf("%s ('%c'): expected %d, got %d", bs, c, e, n)
88 }
89 })
90 }
91 }
92 runTest("", '9')
93 runTest("1", '0')
94 runTest("-", '9')
95 runTest("-1", '0')
96 }
97
98 func TestDigitsLookupTable(t *testing.T) {
99
100 min := new(BigInt)
101 prevBorder := NewBigInt(0)
102 for i := 1; i <= digitsTableSize; i++ {
103 elem := &digitsLookupTable[i]
104
105 min.SetInt64(2)
106 min.Exp(min, NewBigInt(int64(i-1)), nil)
107 if minLen := int64(len(min.String())); minLen != elem.digits {
108 t.Errorf("expected 2^%d to have %d digits, found %d", i, elem.digits, minLen)
109 }
110
111 if zeros := int64(strings.Count(elem.border.String(), "0")); zeros != elem.digits {
112 t.Errorf("the %d digits for digitsLookupTable[%d] does not agree with the border %v", elem.digits, i, &elem.border)
113 }
114
115 if min.Cmp(&elem.border) >= 0 {
116 t.Errorf("expected 2^%d = %v to be less than the border, found %v", i-1, min, &elem.border)
117 }
118
119 if elem.border.Cmp(prevBorder) > 0 {
120 if min.Cmp(prevBorder) <= 0 {
121 t.Errorf("expected 2^%d = %v to be greater than or equal to the border, found %v", i-1, min, prevBorder)
122 }
123 prevBorder = &elem.border
124 }
125 }
126
127
128
129 const randomTrials = 100
130 for i := 0; i < randomTrials; i++ {
131 a := NewBigInt(rand.Int63())
132 b := NewBigInt(rand.Int63())
133 a.Mul(a, b)
134
135 d := NewWithBigInt(a, 0)
136 tableDigits := d.NumDigits()
137 if actualDigits := int64(len(a.String())); actualDigits != tableDigits {
138 t.Errorf("expected %d digits for %v, found %d", tableDigits, a, actualDigits)
139 }
140 }
141 }
142
143 func TestTableExp10(t *testing.T) {
144 tests := []struct {
145 pow int64
146 str string
147 }{
148 {
149 pow: 0,
150 str: "1",
151 },
152 {
153 pow: 1,
154 str: "10",
155 },
156 {
157 pow: 5,
158 str: "100000",
159 },
160 {
161 pow: powerTenTableSize + 1,
162 str: "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
163 },
164 }
165
166 for i, test := range tests {
167 var tmpE BigInt
168 d := tableExp10(test.pow, &tmpE)
169 if s := d.String(); s != test.str {
170 t.Errorf("%d: expected PowerOfTenDec(%d) to give %s, got %s", i, test.pow, test.str, s)
171 }
172 }
173 }
174
View as plain text