charconv_bigint_test.cc
Go to the documentation of this file.
00001 // Copyright 2018 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/strings/internal/charconv_bigint.h"
00016 
00017 #include <string>
00018 
00019 #include "gtest/gtest.h"
00020 
00021 namespace absl {
00022 namespace strings_internal {
00023 
00024 TEST(BigUnsigned, ShiftLeft) {
00025   {
00026     // Check that 3 * 2**100 is calculated correctly
00027     BigUnsigned<4> num(3u);
00028     num.ShiftLeft(100);
00029     EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128"));
00030   }
00031   {
00032     // Test that overflow is truncated properly.
00033     // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint.
00034     // Shifting left by 125 bits should truncate off the high bit, so that
00035     //   15 << 125 == 7 << 125
00036     // after truncation.
00037     BigUnsigned<4> a(15u);
00038     BigUnsigned<4> b(7u);
00039     BigUnsigned<4> c(3u);
00040     a.ShiftLeft(125);
00041     b.ShiftLeft(125);
00042     c.ShiftLeft(125);
00043     EXPECT_EQ(a, b);
00044     EXPECT_NE(a, c);
00045   }
00046   {
00047     // Same test, larger bigint:
00048     BigUnsigned<84> a(15u);
00049     BigUnsigned<84> b(7u);
00050     BigUnsigned<84> c(3u);
00051     a.ShiftLeft(84 * 32 - 3);
00052     b.ShiftLeft(84 * 32 - 3);
00053     c.ShiftLeft(84 * 32 - 3);
00054     EXPECT_EQ(a, b);
00055     EXPECT_NE(a, c);
00056   }
00057   {
00058     // Check that incrementally shifting has the same result as doing it all at
00059     // once (attempting to capture corner cases.)
00060     const std::string seed = "1234567890123456789012345678901234567890";
00061     BigUnsigned<84> a(seed);
00062     for (int i = 1; i <= 84 * 32; ++i) {
00063       a.ShiftLeft(1);
00064       BigUnsigned<84> b(seed);
00065       b.ShiftLeft(i);
00066       EXPECT_EQ(a, b);
00067     }
00068     // And we should have fully rotated all bits off by now:
00069     EXPECT_EQ(a, BigUnsigned<84>(0u));
00070   }
00071 }
00072 
00073 TEST(BigUnsigned, MultiplyByUint32) {
00074   const BigUnsigned<84> factorial_100(
00075       "933262154439441526816992388562667004907159682643816214685929638952175999"
00076       "932299156089414639761565182862536979208272237582511852109168640000000000"
00077       "00000000000000");
00078   BigUnsigned<84> a(1u);
00079   for (uint32_t i = 1; i <= 100; ++i) {
00080     a.MultiplyBy(i);
00081   }
00082   EXPECT_EQ(a, BigUnsigned<84>(factorial_100));
00083 }
00084 
00085 TEST(BigUnsigned, MultiplyByBigUnsigned) {
00086   {
00087     // Put the terms of factorial_200 into two bigints, and multiply them
00088     // together.
00089     const BigUnsigned<84> factorial_200(
00090         "7886578673647905035523632139321850622951359776871732632947425332443594"
00091         "4996340334292030428401198462390417721213891963883025764279024263710506"
00092         "1926624952829931113462857270763317237396988943922445621451664240254033"
00093         "2918641312274282948532775242424075739032403212574055795686602260319041"
00094         "7032406235170085879617892222278962370389737472000000000000000000000000"
00095         "0000000000000000000000000");
00096     BigUnsigned<84> evens(1u);
00097     BigUnsigned<84> odds(1u);
00098     for (uint32_t i = 1; i < 200; i += 2) {
00099       odds.MultiplyBy(i);
00100       evens.MultiplyBy(i + 1);
00101     }
00102     evens.MultiplyBy(odds);
00103     EXPECT_EQ(evens, factorial_200);
00104   }
00105   {
00106     // Multiply various powers of 10 together.
00107     for (int a = 0 ; a < 700; a += 25) {
00108       SCOPED_TRACE(a);
00109       BigUnsigned<84> a_value("3" + std::string(a, '0'));
00110       for (int b = 0; b < (700 - a); b += 25) {
00111         SCOPED_TRACE(b);
00112         BigUnsigned<84> b_value("2" + std::string(b, '0'));
00113         BigUnsigned<84> expected_product("6" + std::string(a + b, '0'));
00114         b_value.MultiplyBy(a_value);
00115         EXPECT_EQ(b_value, expected_product);
00116       }
00117     }
00118   }
00119 }
00120 
00121 TEST(BigUnsigned, MultiplyByOverflow) {
00122   {
00123     // Check that multiplcation overflow predictably truncates.
00124 
00125     // A big int with all bits on.
00126     BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
00127     // Modulo 2**128, this is equal to -1.  Therefore the square of this,
00128     // modulo 2**128, should be 1.
00129     all_bits_on.MultiplyBy(all_bits_on);
00130     EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u));
00131   }
00132   {
00133     // Try multiplying a large bigint by 2**50, and compare the result to
00134     // shifting.
00135     BigUnsigned<4> value_1("12345678901234567890123456789012345678");
00136     BigUnsigned<4> value_2("12345678901234567890123456789012345678");
00137     BigUnsigned<4> two_to_fiftieth(1u);
00138     two_to_fiftieth.ShiftLeft(50);
00139 
00140     value_1.ShiftLeft(50);
00141     value_2.MultiplyBy(two_to_fiftieth);
00142     EXPECT_EQ(value_1, value_2);
00143   }
00144 }
00145 
00146 TEST(BigUnsigned, FiveToTheNth) {
00147   {
00148     // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to
00149     // and including overflow.
00150     for (int i = 0; i < 1160; ++i) {
00151       SCOPED_TRACE(i);
00152       BigUnsigned<84> value_1(123u);
00153       BigUnsigned<84> value_2(123u);
00154       value_1.MultiplyByFiveToTheNth(i);
00155       for (int j = 0; j < i; j++) {
00156         value_2.MultiplyBy(5u);
00157       }
00158       EXPECT_EQ(value_1, value_2);
00159     }
00160   }
00161   {
00162     // Check that the faster, table-lookup-based static method returns the same
00163     // result that multiplying in-place would return, up to and including
00164     // overflow.
00165     for (int i = 0; i < 1160; ++i) {
00166       SCOPED_TRACE(i);
00167       BigUnsigned<84> value_1(1u);
00168       value_1.MultiplyByFiveToTheNth(i);
00169       BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i);
00170       EXPECT_EQ(value_1, value_2);
00171     }
00172   }
00173 }
00174 
00175 TEST(BigUnsigned, TenToTheNth) {
00176   {
00177     // Sanity check MultiplyByTenToTheNth.
00178     for (int i = 0; i < 800; ++i) {
00179       SCOPED_TRACE(i);
00180       BigUnsigned<84> value_1(123u);
00181       BigUnsigned<84> value_2(123u);
00182       value_1.MultiplyByTenToTheNth(i);
00183       for (int j = 0; j < i; j++) {
00184         value_2.MultiplyBy(10u);
00185       }
00186       EXPECT_EQ(value_1, value_2);
00187     }
00188   }
00189   {
00190     // Alternate testing approach, taking advantage of the decimal parser.
00191     for (int i = 0; i < 200; ++i) {
00192       SCOPED_TRACE(i);
00193       BigUnsigned<84> value_1(135u);
00194       value_1.MultiplyByTenToTheNth(i);
00195       BigUnsigned<84> value_2("135" + std::string(i, '0'));
00196       EXPECT_EQ(value_1, value_2);
00197     }
00198   }
00199 }
00200 
00201 
00202 }  // namespace strings_internal
00203 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14