...

Source file src/github.com/cockroachdb/apd/v3/table_test.go

Documentation: github.com/cockroachdb/apd/v3

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied. See the License for the specific language governing
    13  // permissions and limitations under the License.
    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  	// Make sure all elements in table make sense.
   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  	// Throw random big.Ints at the table and make sure the
   128  	// digit lengths line up.
   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