github.com/dubbogo/gost@v1.14.0/math/big/decimal_test.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package gxbig
    19  
    20  import (
    21  	"fmt"
    22  	"strconv"
    23  	"strings"
    24  	"testing"
    25  )
    26  
    27  import (
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestFromInt(t *testing.T) {
    32  	tests := []struct {
    33  		input  int64
    34  		output string
    35  	}{
    36  		{-12345, "-12345"},
    37  		{-1, "-1"},
    38  		{1, "1"},
    39  		{-9223372036854775807, "-9223372036854775807"},
    40  		{-9223372036854775808, "-9223372036854775808"},
    41  	}
    42  	for _, tt := range tests {
    43  		dec := NewDecFromInt(tt.input)
    44  		str := dec.ToString()
    45  		require.Equal(t, tt.output, string(str))
    46  	}
    47  }
    48  
    49  func TestFromUint(t *testing.T) {
    50  	tests := []struct {
    51  		input  uint64
    52  		output string
    53  	}{
    54  		{12345, "12345"},
    55  		{0, "0"},
    56  		{18446744073709551615, "18446744073709551615"},
    57  	}
    58  	for _, tt := range tests {
    59  		var dec Decimal
    60  		dec.FromUint(tt.input)
    61  		str := dec.ToString()
    62  		require.Equal(t, tt.output, string(str))
    63  	}
    64  }
    65  
    66  func TestToInt(t *testing.T) {
    67  	tests := []struct {
    68  		input  string
    69  		output int64
    70  		err    error
    71  	}{
    72  		{"18446744073709551615", 9223372036854775807, ErrOverflow},
    73  		{"-1", -1, nil},
    74  		{"1", 1, nil},
    75  		{"-1.23", -1, ErrTruncated},
    76  		{"-9223372036854775807", -9223372036854775807, nil},
    77  		{"-9223372036854775808", -9223372036854775808, nil},
    78  		{"9223372036854775808", 9223372036854775807, ErrOverflow},
    79  		{"-9223372036854775809", -9223372036854775808, ErrOverflow},
    80  	}
    81  	for _, tt := range tests {
    82  		var dec Decimal
    83  		err := dec.FromString(tt.input)
    84  		require.NoError(t, err)
    85  		result, ec := dec.ToInt()
    86  		require.Equal(t, tt.err, ec)
    87  		require.Equal(t, tt.output, result)
    88  	}
    89  }
    90  
    91  func TestToUint(t *testing.T) {
    92  	tests := []struct {
    93  		input  string
    94  		output uint64
    95  		err    error
    96  	}{
    97  		{"12345", 12345, nil},
    98  		{"0", 0, nil},
    99  		/* ULLONG_MAX = 18446744073709551615ULL */
   100  		{"18446744073709551615", 18446744073709551615, nil},
   101  		{"18446744073709551616", 18446744073709551615, ErrOverflow},
   102  		{"-1", 0, ErrOverflow},
   103  		{"1.23", 1, ErrTruncated},
   104  		{"9999999999999999999999999.000", 18446744073709551615, ErrOverflow},
   105  	}
   106  	for _, tt := range tests {
   107  		var dec Decimal
   108  		err := dec.FromString(tt.input)
   109  		require.NoError(t, err)
   110  		result, ec := dec.ToUint()
   111  		require.Equal(t, tt.err, ec)
   112  		require.Equal(t, tt.output, result)
   113  	}
   114  }
   115  
   116  func TestFromFloat(t *testing.T) {
   117  	tests := []struct {
   118  		s string
   119  		f float64
   120  	}{
   121  		{"12345", 12345},
   122  		{"123.45", 123.45},
   123  		{"-123.45", -123.45},
   124  		{"0.00012345000098765", 0.00012345000098765},
   125  		{"1234500009876.5", 1234500009876.5},
   126  	}
   127  	for _, tt := range tests {
   128  		dec, err := NewDecFromFloat(tt.f)
   129  		str := dec.ToString()
   130  		require.Equal(t, err, nil)
   131  		require.Equal(t, tt.s, string(str))
   132  	}
   133  }
   134  
   135  func TestToFloat(t *testing.T) {
   136  	tests := []struct {
   137  		in  string
   138  		out string
   139  		err error
   140  	}{
   141  		{"12345", "12345", nil},
   142  		{"123.45", "123.45", nil},
   143  		{"-123.45", "-123.45", nil},
   144  		{"0.00012345000098765", "0.00012345000098765", nil},
   145  		{"1234500009876.5", "1234500009876.5", nil},
   146  		{"1e39", "1e39", nil},
   147  		{"1e-39", "1e-39", nil},
   148  		{"1e00", "1", nil},
   149  		{"1e001", "10", nil},
   150  		{"-9223372036854775807", "-9223372036854775807", nil},
   151  		{"-9223372036854775808", "-9223372036854775808", nil},
   152  		{"18446744073709551615", "18446744073709551615", nil},
   153  		{"123456789.987654321", "123456789.987654321", nil},
   154  		// Testcases from https://github.com/golang/go/blob/master/src/strconv/atof_test.go#L24
   155  		{"1", "1", nil},
   156  		{"+1", "1", nil},
   157  		{"1e23", "1e+23", nil},
   158  		{"1E23", "1e+23", nil},
   159  		{"100000000000000000000000", "1e+23", nil},
   160  		{"123456700", "1.234567e+08", nil},
   161  		{"99999999999999974834176", "9.999999999999997e+22", nil},
   162  		{"100000000000000000000001", "1.0000000000000001e+23", nil},
   163  		{"100000000000000008388608", "1.0000000000000001e+23", nil},
   164  		{"100000000000000016777215", "1.0000000000000001e+23", nil},
   165  		{"100000000000000016777216", "1.0000000000000003e+23", nil},
   166  		{"-1", "-1", nil},
   167  		{"-0.1", "-0.1", nil},
   168  		{"-0", "-0", nil},
   169  		{"1e-20", "1e-20", nil},
   170  		{"625e-3", "0.625", nil},
   171  		{"0", "0", nil},
   172  		{"22.222222222222222", "22.22222222222222", nil},
   173  		{"1.00000000000000011102230246251565404236316680908203125", "1", nil},
   174  		{"1.00000000000000011102230246251565404236316680908203124", "1", nil},
   175  		{"1.00000000000000011102230246251565404236316680908203126", "1.0000000000000002", nil},
   176  		{"1.00000000000000033306690738754696212708950042724609375", "1.0000000000000004", nil},
   177  		{"1090544144181609348671888949248", "1.0905441441816093e+30", nil},
   178  		{"1090544144181609348835077142190", "1.0905441441816094e+30", nil},
   179  	}
   180  	for _, ca := range tests {
   181  		var dec Decimal
   182  		err := dec.FromString(ca.in)
   183  		require.NoError(t, err)
   184  		f, err := dec.ToFloat64()
   185  		require.NoError(t, err)
   186  		std, err := strconv.ParseFloat(ca.out, 64)
   187  		require.NoError(t, err)
   188  		require.Equal(t, std, f)
   189  	}
   190  }
   191  
   192  func TestToHashKey(t *testing.T) {
   193  	tests := []struct {
   194  		numbers []string
   195  	}{
   196  		{[]string{"1.1", "1.1000", "1.1000000", "1.10000000000", "01.1", "0001.1", "001.1000000"}},
   197  		{[]string{"-1.1", "-1.1000", "-1.1000000", "-1.10000000000", "-01.1", "-0001.1", "-001.1000000"}},
   198  		{[]string{".1", "0.1", "0.10", "000000.1", ".10000", "0000.10000", "000000000000000000.1"}},
   199  		{[]string{"0", "0000", ".0", ".00000", "00000.00000", "-0", "-0000", "-.0", "-.00000", "-00000.00000"}},
   200  		{[]string{".123456789123456789", ".1234567891234567890", ".12345678912345678900", ".123456789123456789000", ".1234567891234567890000", "0.123456789123456789",
   201  			".1234567891234567890000000000", "0000000.123456789123456789000"}},
   202  		{[]string{"12345", "012345", "0012345", "0000012345", "0000000012345", "00000000000012345", "12345.", "12345.00", "12345.000000000", "000012345.0000"}},
   203  		{[]string{"123E5", "12300000", "00123E5", "000000123E5", "12300000.00000000"}},
   204  		{[]string{"123E-2", "1.23", "00000001.23", "1.2300000000000000", "000000001.23000000000000"}},
   205  	}
   206  	for _, ca := range tests {
   207  		keys := make([]string, 0, len(ca.numbers))
   208  		for _, num := range ca.numbers {
   209  			var dec Decimal
   210  			require.NoError(t, dec.FromString(num))
   211  			key, err := dec.ToHashKey()
   212  			require.NoError(t, err)
   213  			keys = append(keys, string(key))
   214  		}
   215  
   216  		for i := 1; i < len(keys); i++ {
   217  			require.Equal(t, keys[0], keys[i])
   218  		}
   219  	}
   220  
   221  	binTests := []struct {
   222  		hashNumbers []string
   223  		binNumbers  []string
   224  	}{
   225  		{[]string{"1.1", "1.1000", "1.1000000", "1.10000000000", "01.1", "0001.1", "001.1000000"},
   226  			[]string{"1.1", "0001.1", "01.1"}},
   227  		{[]string{"-1.1", "-1.1000", "-1.1000000", "-1.10000000000", "-01.1", "-0001.1", "-001.1000000"},
   228  			[]string{"-1.1", "-0001.1", "-01.1"}},
   229  		{[]string{".1", "0.1", "000000.1", ".10000", "0000.10000", "000000000000000000.1"},
   230  			[]string{".1", "0.1", "000000.1", "00.1"}},
   231  		{[]string{"0", "0000", ".0", ".00000", "00000.00000", "-0", "-0000", "-.0", "-.00000", "-00000.00000"},
   232  			[]string{"0", "0000", "00", "-0", "-00", "-000000"}},
   233  		{[]string{".123456789123456789", ".1234567891234567890", ".12345678912345678900", ".123456789123456789000", ".1234567891234567890000", "0.123456789123456789",
   234  			".1234567891234567890000000000", "0000000.123456789123456789000"},
   235  			[]string{".123456789123456789", "0.123456789123456789", "0000.123456789123456789", "0000000.123456789123456789"}},
   236  		{[]string{"12345", "012345", "0012345", "0000012345", "0000000012345", "00000000000012345", "12345.", "12345.00", "12345.000000000", "000012345.0000"},
   237  			[]string{"12345", "012345", "000012345", "000000000000012345"}},
   238  		{[]string{"123E5", "12300000", "00123E5", "000000123E5", "12300000.00000000"},
   239  			[]string{"12300000", "123E5", "00123E5", "0000000000123E5"}},
   240  		{[]string{"123E-2", "1.23", "00000001.23", "1.2300000000000000", "000000001.23000000000000"},
   241  			[]string{"123E-2", "1.23", "000001.23", "0000000000001.23"}},
   242  	}
   243  	for _, ca := range binTests {
   244  		keys := make([]string, 0, len(ca.hashNumbers)+len(ca.binNumbers))
   245  		for _, num := range ca.hashNumbers {
   246  			var dec Decimal
   247  			require.NoError(t, dec.FromString(num))
   248  			key, err := dec.ToHashKey()
   249  			// remove digit len
   250  			key = key[:len(key)-1]
   251  			require.NoError(t, err)
   252  			keys = append(keys, string(key))
   253  		}
   254  		for _, num := range ca.binNumbers {
   255  			var dec Decimal
   256  			require.NoError(t, dec.FromString(num))
   257  			prec, frac := dec.PrecisionAndFrac() // remove leading zeros but trailing zeros remain
   258  			key, err := dec.ToBin(prec, frac)
   259  			require.NoError(t, err)
   260  			keys = append(keys, string(key))
   261  		}
   262  
   263  		for i := 1; i < len(keys); i++ {
   264  			require.Equal(t, keys[0], keys[i])
   265  		}
   266  	}
   267  }
   268  
   269  func TestRemoveTrailingZeros(t *testing.T) {
   270  	tests := []string{
   271  		"0", "0.0", ".0", ".00000000", "0.0000", "0000", "0000.0", "0000.000",
   272  		"-0", "-0.0", "-.0", "-.00000000", "-0.0000", "-0000", "-0000.0", "-0000.000",
   273  		"123123123", "213123.", "21312.000", "21321.123", "213.1230000", "213123.000123000",
   274  		"-123123123", "-213123.", "-21312.000", "-21321.123", "-213.1230000", "-213123.000123000",
   275  		"123E5", "12300E-5", "0.00100E1", "0.001230E-3",
   276  		"123987654321.123456789000", "000000000123", "123456789.987654321", "999.999000",
   277  	}
   278  	for _, ca := range tests {
   279  		var dec Decimal
   280  		require.NoError(t, dec.FromString(ca))
   281  
   282  		// calculate the number of digits after point but trailing zero
   283  		digitsFracExp := 0
   284  		str := string(dec.ToString())
   285  		point := strings.Index(str, ".")
   286  		if point != -1 {
   287  			pos := len(str) - 1
   288  			for pos > point {
   289  				if str[pos] != '0' {
   290  					break
   291  				}
   292  				pos--
   293  			}
   294  			digitsFracExp = pos - point
   295  		}
   296  
   297  		_, digitsFrac := dec.removeTrailingZeros()
   298  		require.Equal(t, digitsFracExp, digitsFrac)
   299  	}
   300  }
   301  
   302  func TestRoundWithHalfEven(t *testing.T) {
   303  	tests := []struct {
   304  		input  string
   305  		scale  int
   306  		output string
   307  		err    error
   308  	}{
   309  		{"123456789.987654321", 1, "123456790.0", nil},
   310  		{"15.1", 0, "15", nil},
   311  		{"15.5", 0, "16", nil},
   312  		{"15.9", 0, "16", nil},
   313  		{"-15.1", 0, "-15", nil},
   314  		{"-15.5", 0, "-16", nil},
   315  		{"-15.9", 0, "-16", nil},
   316  		{"15.1", 1, "15.1", nil},
   317  		{"-15.1", 1, "-15.1", nil},
   318  		{"15.17", 1, "15.2", nil},
   319  		{"15.4", -1, "20", nil},
   320  		{"-15.4", -1, "-20", nil},
   321  		{"5.4", -1, "10", nil},
   322  		{".999", 0, "1", nil},
   323  		{"999999999", -9, "1000000000", nil},
   324  	}
   325  
   326  	for _, ca := range tests {
   327  		var dec Decimal
   328  		err := dec.FromString(ca.input)
   329  		require.NoError(t, err)
   330  		var rounded Decimal
   331  		err = dec.Round(&rounded, ca.scale, ModeHalfEven)
   332  		require.Equal(t, ca.err, err)
   333  		result := rounded.ToString()
   334  		require.Equal(t, ca.output, string(result))
   335  	}
   336  }
   337  
   338  func TestRoundWithTruncate(t *testing.T) {
   339  	tests := []struct {
   340  		input  string
   341  		scale  int
   342  		output string
   343  		err    error
   344  	}{
   345  		{"123456789.987654321", 1, "123456789.9", nil},
   346  		{"15.1", 0, "15", nil},
   347  		{"15.5", 0, "15", nil},
   348  		{"15.9", 0, "15", nil},
   349  		{"-15.1", 0, "-15", nil},
   350  		{"-15.5", 0, "-15", nil},
   351  		{"-15.9", 0, "-15", nil},
   352  		{"15.1", 1, "15.1", nil},
   353  		{"-15.1", 1, "-15.1", nil},
   354  		{"15.17", 1, "15.1", nil},
   355  		{"15.4", -1, "10", nil},
   356  		{"-15.4", -1, "-10", nil},
   357  		{"5.4", -1, "0", nil},
   358  		{".999", 0, "0", nil},
   359  		{"999999999", -9, "0", nil},
   360  	}
   361  	for _, ca := range tests {
   362  		var dec Decimal
   363  		err := dec.FromString(ca.input)
   364  		require.NoError(t, err)
   365  		var rounded Decimal
   366  		err = dec.Round(&rounded, ca.scale, ModeTruncate)
   367  		require.Equal(t, ca.err, err)
   368  		result := rounded.ToString()
   369  		require.Equal(t, ca.output, string(result))
   370  	}
   371  }
   372  
   373  func TestRoundWithCeil(t *testing.T) {
   374  	tests := []struct {
   375  		input  string
   376  		scale  int
   377  		output string
   378  		err    error
   379  	}{
   380  		{"123456789.987654321", 1, "123456790.0", nil},
   381  		{"15.1", 0, "16", nil},
   382  		{"15.5", 0, "16", nil},
   383  		{"15.9", 0, "16", nil},
   384  		//TODO:fix me
   385  		{"-15.1", 0, "-16", nil},
   386  		{"-15.5", 0, "-16", nil},
   387  		{"-15.9", 0, "-16", nil},
   388  		{"15.1", 1, "15.1", nil},
   389  		{"-15.1", 1, "-15.1", nil},
   390  		{"15.17", 1, "15.2", nil},
   391  		{"15.4", -1, "20", nil},
   392  		{"-15.4", -1, "-20", nil},
   393  		{"5.4", -1, "10", nil},
   394  		{".999", 0, "1", nil},
   395  		{"999999999", -9, "1000000000", nil},
   396  	}
   397  	for _, ca := range tests {
   398  		var dec Decimal
   399  		err := dec.FromString(ca.input)
   400  		require.NoError(t, err)
   401  		var rounded Decimal
   402  		err = dec.Round(&rounded, ca.scale, modeCeiling)
   403  		require.Equal(t, ca.err, err)
   404  		result := rounded.ToString()
   405  		require.Equal(t, ca.output, string(result))
   406  	}
   407  }
   408  
   409  func TestToString(t *testing.T) {
   410  	type tcase struct {
   411  		input  string
   412  		output string
   413  	}
   414  	tests := []tcase{
   415  		{"123.123", "123.123"},
   416  		{"123.1230", "123.1230"},
   417  		{"00123.123", "123.123"},
   418  	}
   419  	for _, ca := range tests {
   420  		var dec Decimal
   421  		err := dec.FromString(ca.input)
   422  		require.NoError(t, err)
   423  		result := dec.ToString()
   424  		require.Equal(t, ca.output, string(result))
   425  	}
   426  }
   427  
   428  func TestToBinFromBin(t *testing.T) {
   429  	type tcase struct {
   430  		input     string
   431  		precision int
   432  		frac      int
   433  		output    string
   434  		err       error
   435  	}
   436  	tests := []tcase{
   437  		{"-10.55", 4, 2, "-10.55", nil},
   438  		{"0.0123456789012345678912345", 30, 25, "0.0123456789012345678912345", nil},
   439  		{"12345", 5, 0, "12345", nil},
   440  		{"12345", 10, 3, "12345.000", nil},
   441  		{"123.45", 10, 3, "123.450", nil},
   442  		{"-123.45", 20, 10, "-123.4500000000", nil},
   443  		{".00012345000098765", 15, 14, "0.00012345000098", ErrTruncated},
   444  		{".00012345000098765", 22, 20, "0.00012345000098765000", nil},
   445  		{".12345000098765", 30, 20, "0.12345000098765000000", nil},
   446  		{"-.000000012345000098765", 30, 20, "-0.00000001234500009876", ErrTruncated},
   447  		{"1234500009876.5", 30, 5, "1234500009876.50000", nil},
   448  		{"111111111.11", 10, 2, "11111111.11", ErrOverflow},
   449  		{"000000000.01", 7, 3, "0.010", nil},
   450  		{"123.4", 10, 2, "123.40", nil},
   451  		{"1000", 3, 0, "0", ErrOverflow},
   452  		{"0.1", 1, 1, "0.1", nil},
   453  		{"0.100", 1, 1, "0.1", ErrTruncated},
   454  		{"0.1000", 1, 1, "0.1", ErrTruncated},
   455  		{"0.10000", 1, 1, "0.1", ErrTruncated},
   456  		{"0.100000", 1, 1, "0.1", ErrTruncated},
   457  		{"0.1000000", 1, 1, "0.1", ErrTruncated},
   458  		{"0.10", 1, 1, "0.1", ErrTruncated},
   459  		{"0000000000000000000000000000000000000000000.000000000000123000000000000000", 15, 15, "0.000000000000123", ErrTruncated},
   460  		{"00000000000000000000000000000.00000000000012300", 15, 15, "0.000000000000123", ErrTruncated},
   461  		{"0000000000000000000000000000000000000000000.0000000000001234000000000000000", 16, 16, "0.0000000000001234", ErrTruncated},
   462  		{"00000000000000000000000000000.000000000000123400", 16, 16, "0.0000000000001234", ErrTruncated},
   463  		{"0.1", 2, 2, "0.10", nil},
   464  		{"0.10", 3, 3, "0.100", nil},
   465  		{"0.1", 3, 1, "0.1", nil},
   466  		{"0.0000000000001234", 32, 17, "0.00000000000012340", nil},
   467  		{"0.0000000000001234", 20, 20, "0.00000000000012340000", nil},
   468  	}
   469  	for _, ca := range tests {
   470  		var dec Decimal
   471  		err := dec.FromString(ca.input)
   472  		require.NoError(t, err)
   473  		buf, err := dec.ToBin(ca.precision, ca.frac)
   474  		require.Equal(t, ca.err, err)
   475  		var dec2 Decimal
   476  		_, err = dec2.FromBin(buf, ca.precision, ca.frac)
   477  		require.NoError(t, err)
   478  		str := dec2.ToString()
   479  		require.Equal(t, ca.output, string(str))
   480  	}
   481  	var dec Decimal
   482  	dec.FromInt(1)
   483  	errTests := []struct {
   484  		prec int
   485  		frac int
   486  	}{
   487  		{82, 1},
   488  		{-1, 1},
   489  		{10, 31},
   490  		{10, -1},
   491  	}
   492  	for _, tt := range errTests {
   493  		_, _ = dec.ToBin(tt.prec, tt.frac)
   494  		// assert.Equal(t,ErrBadNumber.Equal(err), IsTrue)
   495  	}
   496  }
   497  
   498  func TestCompareMyDecimal(t *testing.T) {
   499  	type tcase struct {
   500  		a   string
   501  		b   string
   502  		cmp int
   503  	}
   504  	tests := []tcase{
   505  		{"12", "13", -1},
   506  		{"13", "12", 1},
   507  		{"-10", "10", -1},
   508  		{"10", "-10", 1},
   509  		{"-12", "-13", 1},
   510  		{"0", "12", -1},
   511  		{"-10", "0", -1},
   512  		{"4", "4", 0},
   513  		{"-1.1", "-1.2", 1},
   514  		{"1.2", "1.1", 1},
   515  		{"1.1", "1.2", -1},
   516  	}
   517  	for _, tt := range tests {
   518  		var a, b Decimal
   519  		err := a.FromString(tt.a)
   520  		require.NoError(t, err)
   521  		err = b.FromString(tt.b)
   522  		require.NoError(t, err)
   523  		require.Equal(t, tt.cmp, a.Compare(&b))
   524  	}
   525  }
   526  
   527  func TestMaxDecimal(t *testing.T) {
   528  	type tcase struct {
   529  		prec   int
   530  		frac   int
   531  		result string
   532  	}
   533  	tests := []tcase{
   534  		{1, 1, "0.9"},
   535  		{1, 0, "9"},
   536  		{2, 1, "9.9"},
   537  		{4, 2, "99.99"},
   538  		{6, 3, "999.999"},
   539  		{8, 4, "9999.9999"},
   540  		{10, 5, "99999.99999"},
   541  		{12, 6, "999999.999999"},
   542  		{14, 7, "9999999.9999999"},
   543  		{16, 8, "99999999.99999999"},
   544  		{18, 9, "999999999.999999999"},
   545  		{20, 10, "9999999999.9999999999"},
   546  		{20, 20, "0.99999999999999999999"},
   547  		{20, 0, "99999999999999999999"},
   548  		{40, 20, "99999999999999999999.99999999999999999999"},
   549  	}
   550  	for _, tt := range tests {
   551  		var dec Decimal
   552  		maxDecimal(tt.prec, tt.frac, &dec)
   553  		str := dec.ToString()
   554  		require.Equal(t, tt.result, string(str))
   555  	}
   556  }
   557  
   558  func TestNegMyDecimal(t *testing.T) {
   559  	type testCase struct {
   560  		a      string
   561  		result string
   562  	}
   563  	tests := []testCase{
   564  		{"-0.0000000000000000000000000000000000000000000000000017382578996420603", "0.0000000000000000000000000000000000000000000000000017382578996420603"},
   565  		{"-13890436710184412000000000000000000000000000000000000000000000000000000000000", "13890436710184412000000000000000000000000000000000000000000000000000000000000"},
   566  		{"0", "0"},
   567  	}
   568  	for _, tt := range tests {
   569  		a, err := NewDecFromString(tt.a)
   570  		negResult := DecimalNeg(a)
   571  		result := negResult.ToString()
   572  		require.Equal(t, err, nil)
   573  		require.Equal(t, tt.result, string(result))
   574  	}
   575  }
   576  
   577  func TestAddMyDecimal(t *testing.T) {
   578  	type testCase struct {
   579  		a      string
   580  		b      string
   581  		result string
   582  		err    error
   583  	}
   584  	tests := []testCase{
   585  		{".00012345000098765", "123.45", "123.45012345000098765", nil},
   586  		{".1", ".45", "0.55", nil},
   587  		{"1234500009876.5", ".00012345000098765", "1234500009876.50012345000098765", nil},
   588  		{"9999909999999.5", ".555", "9999910000000.055", nil},
   589  		{"99999999", "1", "100000000", nil},
   590  		{"989999999", "1", "990000000", nil},
   591  		{"999999999", "1", "1000000000", nil},
   592  		{"12345", "123.45", "12468.45", nil},
   593  		{"-12345", "-123.45", "-12468.45", nil},
   594  		{"-12345", "123.45", "-12221.55", nil},
   595  		{"12345", "-123.45", "12221.55", nil},
   596  		{"123.45", "-12345", "-12221.55", nil},
   597  		{"-123.45", "12345", "12221.55", nil},
   598  		{"5", "-6.0", "-1.0", nil},
   599  		{"2" + strings.Repeat("1", 71), strings.Repeat("8", 81), "8888888890" + strings.Repeat("9", 71), nil},
   600  		{"-1234.1234", "1234.1234", "0.0000", nil},
   601  	}
   602  	for _, tt := range tests {
   603  		a, err1 := NewDecFromString(tt.a)
   604  		b, err2 := NewDecFromString(tt.b)
   605  		require.Equal(t, err1, nil)
   606  		require.Equal(t, err2, nil)
   607  		var sum Decimal
   608  		err := DecimalAdd(a, b, &sum)
   609  		require.Equal(t, tt.err, err)
   610  		result := sum.ToString()
   611  		require.Equal(t, tt.result, string(result))
   612  	}
   613  }
   614  
   615  func TestSubMyDecimal(t *testing.T) {
   616  	type tcase struct {
   617  		a      string
   618  		b      string
   619  		result string
   620  		err    error
   621  	}
   622  	tests := []tcase{
   623  		{".00012345000098765", "123.45", "-123.44987654999901235", nil},
   624  		{"1234500009876.5", ".00012345000098765", "1234500009876.49987654999901235", nil},
   625  		{"9999900000000.5", ".555", "9999899999999.945", nil},
   626  		{"1111.5551", "1111.555", "0.0001", nil},
   627  		{".555", ".555", "0.000", nil},
   628  		{"10000000", "1", "9999999", nil},
   629  		{"1000001000", ".1", "1000000999.9", nil},
   630  		{"1000000000", ".1", "999999999.9", nil},
   631  		{"12345", "123.45", "12221.55", nil},
   632  		{"-12345", "-123.45", "-12221.55", nil},
   633  		{"123.45", "12345", "-12221.55", nil},
   634  		{"-123.45", "-12345", "12221.55", nil},
   635  		{"-12345", "123.45", "-12468.45", nil},
   636  		{"12345", "-123.45", "12468.45", nil},
   637  		{"12.12", "12.12", "0.00", nil},
   638  	}
   639  	for _, tt := range tests {
   640  		var a, b, sum Decimal
   641  		err := a.FromString(tt.a)
   642  		require.NoError(t, err)
   643  		err = b.FromString(tt.b)
   644  		require.NoError(t, err)
   645  		err = DecimalSub(&a, &b, &sum)
   646  		require.Equal(t, tt.err, err)
   647  		result := sum.ToString()
   648  		require.Equal(t, tt.result, string(result))
   649  	}
   650  }
   651  
   652  func TestMulMyDecimal(t *testing.T) {
   653  	type tcase struct {
   654  		a      string
   655  		b      string
   656  		result string
   657  		err    error
   658  	}
   659  	tests := []tcase{
   660  		{"12", "10", "120", nil},
   661  		{"-123.456", "98765.4321", "-12193185.1853376", nil},
   662  		{"-123456000000", "98765432100000", "-12193185185337600000000000", nil},
   663  		{"123456", "987654321", "121931851853376", nil},
   664  		{"123456", "9876543210", "1219318518533760", nil},
   665  		{"123", "0.01", "1.23", nil},
   666  		{"123", "0", "0", nil},
   667  		{"-0.0000000000000000000000000000000000000000000000000017382578996420603", "-13890436710184412000000000000000000000000000000000000000000000000000000000000", "0.000000000000000000000000000000", ErrTruncated},
   668  		{"1" + strings.Repeat("0", 60), "1" + strings.Repeat("0", 60), "0", ErrOverflow},
   669  		{"0.5999991229316", "0.918755041726043", "0.5512522192246113614062276588", nil},
   670  		{"0.5999991229317", "0.918755041726042", "0.5512522192247026369112773314", nil},
   671  		{"0.000", "-1", "0.000", nil},
   672  	}
   673  	for _, tt := range tests {
   674  		var a, b, product Decimal
   675  		err := a.FromString(tt.a)
   676  		require.NoError(t, err)
   677  		err = b.FromString(tt.b)
   678  		require.NoError(t, err)
   679  		err = DecimalMul(&a, &b, &product)
   680  		require.Equal(t, tt.err, err)
   681  		result := product.String()
   682  		require.Equal(t, tt.result, result)
   683  	}
   684  }
   685  
   686  func TestDivModMyDecimal(t *testing.T) {
   687  	type tcase struct {
   688  		a      string
   689  		b      string
   690  		result string
   691  		err    error
   692  	}
   693  	tests := []tcase{
   694  		{"120", "10", "12.000000000", nil},
   695  		{"123", "0.01", "12300.000000000", nil},
   696  		{"120", "100000000000.00000", "0.000000001200000000", nil},
   697  		{"123", "0", "", ErrDivByZero},
   698  		{"0", "0", "", ErrDivByZero},
   699  		{"-12193185.1853376", "98765.4321", "-123.456000000000000000", nil},
   700  		{"121931851853376", "987654321", "123456.000000000", nil},
   701  		{"0", "987", "0.00000", nil},
   702  		{"1", "3", "0.333333333", nil},
   703  		{"1.000000000000", "3", "0.333333333333333333", nil},
   704  		{"1", "1", "1.000000000", nil},
   705  		{"0.0123456789012345678912345", "9999999999", "0.000000000001234567890246913578148141", nil},
   706  		{"10.333000000", "12.34500", "0.837019036046982584042122316", nil},
   707  		{"10.000000000060", "2", "5.000000000030000000", nil},
   708  		{"51", "0.003430", "14868.804664723032069970", nil},
   709  	}
   710  	for _, tt := range tests {
   711  		var a, b, to Decimal
   712  		err := a.FromString(tt.a)
   713  		require.NoError(t, err)
   714  		err = b.FromString(tt.b)
   715  		require.NoError(t, err)
   716  		err = DecimalDiv(&a, &b, &to, 5)
   717  		require.Equal(t, tt.err, err)
   718  		if tt.err == ErrDivByZero {
   719  			continue
   720  		}
   721  		result := to.ToString()
   722  		require.Equal(t, tt.result, string(result))
   723  	}
   724  
   725  	tests = []tcase{
   726  		{"234", "10", "4", nil},
   727  		{"234.567", "10.555", "2.357", nil},
   728  		{"-234.567", "10.555", "-2.357", nil},
   729  		{"234.567", "-10.555", "2.357", nil},
   730  		{"99999999999999999999999999999999999999", "3", "0", nil},
   731  		{"51", "0.003430", "0.002760", nil},
   732  		{"0.0000000001", "1.0", "0.0000000001", nil},
   733  		{"0.000", "0.1", "0.000", nil},
   734  	}
   735  	for _, tt := range tests {
   736  		var a, b, to Decimal
   737  		err := a.FromString(tt.a)
   738  		require.NoError(t, err)
   739  		err = b.FromString(tt.b)
   740  		require.NoError(t, err)
   741  		ec := DecimalMod(&a, &b, &to)
   742  		require.Equal(t, tt.err, ec)
   743  		if tt.err == ErrDivByZero {
   744  			continue
   745  		}
   746  		result := to.ToString()
   747  		require.Equal(t, tt.result, string(result))
   748  	}
   749  
   750  	tests = []tcase{
   751  		{"1", "1", "1.0000", nil},
   752  		{"1.00", "1", "1.000000", nil},
   753  		{"1", "1.000", "1.0000", nil},
   754  		{"2", "3", "0.6667", nil},
   755  		{"51", "0.003430", "14868.8047", nil},
   756  		{"0.000", "0.1", "0.0000000", nil},
   757  	}
   758  	for _, tt := range tests {
   759  		var a, b, to Decimal
   760  		err := a.FromString(tt.a)
   761  		require.NoError(t, err)
   762  		err = b.FromString(tt.b)
   763  		require.NoError(t, err)
   764  		ec := DecimalDiv(&a, &b, &to, DivFracIncr)
   765  		require.Equal(t, tt.err, ec)
   766  		if tt.err == ErrDivByZero {
   767  			continue
   768  		}
   769  		require.Equal(t, tt.result, to.String())
   770  	}
   771  
   772  	tests = []tcase{
   773  		{"1", "2.0", "1.0", nil},
   774  		{"1.0", "2", "1.0", nil},
   775  		{"2.23", "3", "2.23", nil},
   776  		{"51", "0.003430", "0.002760", nil},
   777  	}
   778  	for _, tt := range tests {
   779  		var a, b, to Decimal
   780  		err := a.FromString(tt.a)
   781  		require.NoError(t, err)
   782  		err = b.FromString(tt.b)
   783  		require.NoError(t, err)
   784  		ec := DecimalMod(&a, &b, &to)
   785  		require.Equal(t, tt.err, ec)
   786  		if tt.err == ErrDivByZero {
   787  			continue
   788  		}
   789  		require.Equal(t, tt.result, to.String())
   790  	}
   791  }
   792  
   793  func TestMaxOrMinMyDecimal(t *testing.T) {
   794  	type tcase struct {
   795  		neg    bool
   796  		prec   int
   797  		frac   int
   798  		result string
   799  	}
   800  	tests := []tcase{
   801  		{true, 2, 1, "-9.9"},
   802  		{false, 1, 1, "0.9"},
   803  		{true, 1, 0, "-9"},
   804  		{false, 0, 0, "0"},
   805  		{false, 4, 2, "99.99"},
   806  	}
   807  	for _, tt := range tests {
   808  		dec := NewMaxOrMinDec(tt.neg, tt.prec, tt.frac)
   809  		require.Equal(t, tt.result, dec.String())
   810  	}
   811  }
   812  
   813  func TestReset(t *testing.T) {
   814  	var x1, y1, z1 Decimal
   815  	require.NoError(t, x1.FromString("38520.130741106671"))
   816  	require.NoError(t, y1.FromString("9863.944799797851"))
   817  	require.NoError(t, DecimalAdd(&x1, &y1, &z1))
   818  
   819  	var x2, y2, z2 Decimal
   820  	require.NoError(t, x2.FromString("121519.080207244"))
   821  	require.NoError(t, y2.FromString("54982.444519146"))
   822  	require.NoError(t, DecimalAdd(&x2, &y2, &z2))
   823  
   824  	require.NoError(t, DecimalAdd(&x2, &y2, &z1))
   825  	require.Equal(t, z2, z1)
   826  }
   827  
   828  // this test will change global variable `wordBufLen`, so it must run in serial
   829  func TestShiftMyDecimal(t *testing.T) {
   830  	type tcase struct {
   831  		input  string
   832  		shift  int
   833  		output string
   834  		err    error
   835  	}
   836  
   837  	var dotest = func(tests []tcase) {
   838  		for _, test := range tests {
   839  			t.Run(fmt.Sprintf("%v (shift: %v, wordBufLen: %v)", test.input, test.shift, wordBufLen), func(t *testing.T) {
   840  				var dec Decimal
   841  				require.NoError(t, dec.FromString(test.input))
   842  				require.Equal(t, test.err, dec.Shift(test.shift))
   843  				require.Equal(t, test.output, string(dec.ToString()))
   844  			})
   845  		}
   846  	}
   847  
   848  	wordBufLen = maxWordBufLen
   849  	tests := []tcase{
   850  		{"123.123", 1, "1231.23", nil},
   851  		{"123457189.123123456789000", 1, "1234571891.23123456789", nil},
   852  		{"123457189.123123456789000", 8, "12345718912312345.6789", nil},
   853  		{"123457189.123123456789000", 9, "123457189123123456.789", nil},
   854  		{"123457189.123123456789000", 10, "1234571891231234567.89", nil},
   855  		{"123457189.123123456789000", 17, "12345718912312345678900000", nil},
   856  		{"123457189.123123456789000", 18, "123457189123123456789000000", nil},
   857  		{"123457189.123123456789000", 19, "1234571891231234567890000000", nil},
   858  		{"123457189.123123456789000", 26, "12345718912312345678900000000000000", nil},
   859  		{"123457189.123123456789000", 27, "123457189123123456789000000000000000", nil},
   860  		{"123457189.123123456789000", 28, "1234571891231234567890000000000000000", nil},
   861  		{"000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", nil},
   862  		{"00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", nil},
   863  		{"00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", nil},
   864  		{"123", 1, "1230", nil},
   865  		{"123", 10, "1230000000000", nil},
   866  		{".123", 1, "1.23", nil},
   867  		{".123", 10, "1230000000", nil},
   868  		{".123", 14, "12300000000000", nil},
   869  		{"000.000", 1000, "0", nil},
   870  		{"000.", 1000, "0", nil},
   871  		{".000", 1000, "0", nil},
   872  		{"1", 1000, "1", ErrOverflow},
   873  		{"123.123", -1, "12.3123", nil},
   874  		{"123987654321.123456789000", -1, "12398765432.1123456789", nil},
   875  		{"123987654321.123456789000", -2, "1239876543.21123456789", nil},
   876  		{"123987654321.123456789000", -3, "123987654.321123456789", nil},
   877  		{"123987654321.123456789000", -8, "1239.87654321123456789", nil},
   878  		{"123987654321.123456789000", -9, "123.987654321123456789", nil},
   879  		{"123987654321.123456789000", -10, "12.3987654321123456789", nil},
   880  		{"123987654321.123456789000", -11, "1.23987654321123456789", nil},
   881  		{"123987654321.123456789000", -12, "0.123987654321123456789", nil},
   882  		{"123987654321.123456789000", -13, "0.0123987654321123456789", nil},
   883  		{"123987654321.123456789000", -14, "0.00123987654321123456789", nil},
   884  		{"00000087654321.123456789000", -14, "0.00000087654321123456789", nil},
   885  	}
   886  	dotest(tests)
   887  
   888  	wordBufLen = 2
   889  	tests = []tcase{
   890  		{"123.123", -2, "1.23123", nil},
   891  		{"123.123", -3, "0.123123", nil},
   892  		{"123.123", -6, "0.000123123", nil},
   893  		{"123.123", -7, "0.0000123123", nil},
   894  		{"123.123", -15, "0.000000000000123123", nil},
   895  		{"123.123", -16, "0.000000000000012312", ErrTruncated},
   896  		{"123.123", -17, "0.000000000000001231", ErrTruncated},
   897  		{"123.123", -18, "0.000000000000000123", ErrTruncated},
   898  		{"123.123", -19, "0.000000000000000012", ErrTruncated},
   899  		{"123.123", -20, "0.000000000000000001", ErrTruncated},
   900  		{"123.123", -21, "0", ErrTruncated},
   901  		{".000000000123", -1, "0.0000000000123", nil},
   902  		{".000000000123", -6, "0.000000000000000123", nil},
   903  		{".000000000123", -7, "0.000000000000000012", ErrTruncated},
   904  		{".000000000123", -8, "0.000000000000000001", ErrTruncated},
   905  		{".000000000123", -9, "0", ErrTruncated},
   906  		{".000000000123", 1, "0.00000000123", nil},
   907  		{".000000000123", 8, "0.0123", nil},
   908  		{".000000000123", 9, "0.123", nil},
   909  		{".000000000123", 10, "1.23", nil},
   910  		{".000000000123", 17, "12300000", nil},
   911  		{".000000000123", 18, "123000000", nil},
   912  		{".000000000123", 19, "1230000000", nil},
   913  		{".000000000123", 20, "12300000000", nil},
   914  		{".000000000123", 21, "123000000000", nil},
   915  		{".000000000123", 22, "1230000000000", nil},
   916  		{".000000000123", 23, "12300000000000", nil},
   917  		{".000000000123", 24, "123000000000000", nil},
   918  		{".000000000123", 25, "1230000000000000", nil},
   919  		{".000000000123", 26, "12300000000000000", nil},
   920  		{".000000000123", 27, "123000000000000000", nil},
   921  		{".000000000123", 28, "0.000000000123", ErrOverflow},
   922  		{"123456789.987654321", -1, "12345678.998765432", ErrTruncated},
   923  		{"123456789.987654321", -2, "1234567.899876543", ErrTruncated},
   924  		{"123456789.987654321", -8, "1.234567900", ErrTruncated},
   925  		{"123456789.987654321", -9, "0.123456789987654321", nil},
   926  		{"123456789.987654321", -10, "0.012345678998765432", ErrTruncated},
   927  		{"123456789.987654321", -17, "0.000000001234567900", ErrTruncated},
   928  		{"123456789.987654321", -18, "0.000000000123456790", ErrTruncated},
   929  		{"123456789.987654321", -19, "0.000000000012345679", ErrTruncated},
   930  		{"123456789.987654321", -26, "0.000000000000000001", ErrTruncated},
   931  		{"123456789.987654321", -27, "0", ErrTruncated},
   932  		{"123456789.987654321", 1, "1234567900", ErrTruncated},
   933  		{"123456789.987654321", 2, "12345678999", ErrTruncated},
   934  		{"123456789.987654321", 4, "1234567899877", ErrTruncated},
   935  		{"123456789.987654321", 8, "12345678998765432", ErrTruncated},
   936  		{"123456789.987654321", 9, "123456789987654321", nil},
   937  		{"123456789.987654321", 10, "123456789.987654321", ErrOverflow},
   938  		{"123456789.987654321", 0, "123456789.987654321", nil},
   939  	}
   940  	dotest(tests)
   941  
   942  	// reset
   943  	wordBufLen = maxWordBufLen
   944  }
   945  
   946  // this test will change global variable `wordBufLen`, so it must run in serial
   947  func TestFromStringMyDecimal(t *testing.T) {
   948  	type tcase struct {
   949  		input  string
   950  		output string
   951  		err    error
   952  	}
   953  
   954  	var dotest = func(tests []tcase) {
   955  		for _, test := range tests {
   956  			t.Run(fmt.Sprintf("%v (wordBufLen: %v)", test.input, wordBufLen), func(t *testing.T) {
   957  				var dec Decimal
   958  				require.Equal(t, test.err, dec.FromString(test.input))
   959  				require.Equal(t, test.output, string(dec.ToString()))
   960  			})
   961  		}
   962  	}
   963  
   964  	wordBufLen = maxWordBufLen
   965  	tests := []tcase{
   966  		{"12345", "12345", nil},
   967  		{"12345.", "12345", nil},
   968  		{"123.45.", "123.45", ErrTruncated},
   969  		{"-123.45.", "-123.45", ErrTruncated},
   970  		{".00012345000098765", "0.00012345000098765", nil},
   971  		{".12345000098765", "0.12345000098765", nil},
   972  		{"-.000000012345000098765", "-0.000000012345000098765", nil},
   973  		{"1234500009876.5", "1234500009876.5", nil},
   974  		{"123E5", "12300000", nil},
   975  		{"123E-2", "1.23", nil},
   976  		{"1e1073741823", "999999999999999999999999999999999999999999999999999999999999999999999999999999999", ErrOverflow},
   977  		{"-1e1073741823", "-999999999999999999999999999999999999999999999999999999999999999999999999999999999", ErrOverflow},
   978  		{"1e18446744073709551620", "0", ErrBadNumber},
   979  		{"1e", "1", ErrTruncated},
   980  		{"1e001", "10", nil},
   981  		{"1e00", "1", nil},
   982  		{"1eabc", "1", ErrTruncated},
   983  		{"1e 1dddd ", "10", ErrTruncated},
   984  		{"1e - 1", "1", ErrTruncated},
   985  		{"1e -1", "0.1", nil},
   986  		{"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0.000000000000000000000000000000000000000000000000000000000000000000000000", ErrTruncated},
   987  		{"1asf", "1", ErrTruncated},
   988  		{"1.1.1.1.1", "1.1", ErrTruncated},
   989  		{"1  1", "1", ErrTruncated},
   990  		{"1  ", "1", nil},
   991  	}
   992  	dotest(tests)
   993  
   994  	wordBufLen = 1
   995  	tests = []tcase{
   996  		{"123450000098765", "98765", ErrOverflow},
   997  		{"123450.000098765", "123450", ErrTruncated},
   998  	}
   999  	dotest(tests)
  1000  
  1001  	// reset
  1002  	wordBufLen = maxWordBufLen
  1003  }