charconv_bigint_test.cc (9073B)
1 // Copyright 2018 The Abseil 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 // https://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 implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/strings/internal/charconv_bigint.h" 16 17 #include <string> 18 19 #include "gtest/gtest.h" 20 21 namespace absl { 22 ABSL_NAMESPACE_BEGIN 23 namespace strings_internal { 24 25 TEST(BigUnsigned, ShiftLeft) { 26 { 27 // Check that 3 * 2**100 is calculated correctly 28 BigUnsigned<4> num(3u); 29 num.ShiftLeft(100); 30 EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128")); 31 } 32 { 33 // Test that overflow is truncated properly. 34 // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint. 35 // Shifting left by 125 bits should truncate off the high bit, so that 36 // 15 << 125 == 7 << 125 37 // after truncation. 38 BigUnsigned<4> a(15u); 39 BigUnsigned<4> b(7u); 40 BigUnsigned<4> c(3u); 41 a.ShiftLeft(125); 42 b.ShiftLeft(125); 43 c.ShiftLeft(125); 44 EXPECT_EQ(a, b); 45 EXPECT_NE(a, c); 46 } 47 { 48 // Same test, larger bigint: 49 BigUnsigned<84> a(15u); 50 BigUnsigned<84> b(7u); 51 BigUnsigned<84> c(3u); 52 a.ShiftLeft(84 * 32 - 3); 53 b.ShiftLeft(84 * 32 - 3); 54 c.ShiftLeft(84 * 32 - 3); 55 EXPECT_EQ(a, b); 56 EXPECT_NE(a, c); 57 } 58 { 59 // Check that incrementally shifting has the same result as doing it all at 60 // once (attempting to capture corner cases.) 61 const std::string seed = "1234567890123456789012345678901234567890"; 62 BigUnsigned<84> a(seed); 63 for (int i = 1; i <= 84 * 32; ++i) { 64 a.ShiftLeft(1); 65 BigUnsigned<84> b(seed); 66 b.ShiftLeft(i); 67 EXPECT_EQ(a, b); 68 } 69 // And we should have fully rotated all bits off by now: 70 EXPECT_EQ(a, BigUnsigned<84>(0u)); 71 } 72 { 73 // Bit shifting large and small numbers by large and small offsets. 74 // Intended to exercise bounds-checking corner on ShiftLeft() (directly 75 // and under asan). 76 77 // 2**(32*84)-1 78 const BigUnsigned<84> all_bits_one( 79 "1474444211396924248063325089479706787923460402125687709454567433186613" 80 "6228083464060749874845919674257665016359189106695900028098437021384227" 81 "3285029708032466536084583113729486015826557532750465299832071590813090" 82 "2011853039837649252477307070509704043541368002938784757296893793903797" 83 "8180292336310543540677175225040919704702800559606097685920595947397024" 84 "8303316808753252115729411497720357971050627997031988036134171378490368" 85 "6008000778741115399296162550786288457245180872759047016734959330367829" 86 "5235612397427686310674725251378116268607113017720538636924549612987647" 87 "5767411074510311386444547332882472126067840027882117834454260409440463" 88 "9345147252664893456053258463203120637089916304618696601333953616715125" 89 "2115882482473279040772264257431663818610405673876655957323083702713344" 90 "4201105427930770976052393421467136557055"); 91 const BigUnsigned<84> zero(0u); 92 const BigUnsigned<84> one(1u); 93 // in bounds shifts 94 for (int i = 1; i < 84*32; ++i) { 95 // shifting all_bits_one to the left should result in a smaller number, 96 // since the high bits rotate off and the low bits are replaced with 97 // zeroes. 98 BigUnsigned<84> big_shifted = all_bits_one; 99 big_shifted.ShiftLeft(i); 100 EXPECT_GT(all_bits_one, big_shifted); 101 // Shifting 1 to the left should instead result in a larger number. 102 BigUnsigned<84> small_shifted = one; 103 small_shifted.ShiftLeft(i); 104 EXPECT_LT(one, small_shifted); 105 } 106 // Shifting by zero or a negative number has no effect 107 for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) { 108 BigUnsigned<84> big_shifted = all_bits_one; 109 big_shifted.ShiftLeft(no_op_shift); 110 EXPECT_EQ(all_bits_one, big_shifted); 111 BigUnsigned<84> small_shifted = one; 112 big_shifted.ShiftLeft(no_op_shift); 113 EXPECT_EQ(one, small_shifted); 114 } 115 // Shifting by an amount greater than the number of bits should result in 116 // zero. 117 for (int out_of_bounds_shift : 118 {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) { 119 BigUnsigned<84> big_shifted = all_bits_one; 120 big_shifted.ShiftLeft(out_of_bounds_shift); 121 EXPECT_EQ(zero, big_shifted); 122 BigUnsigned<84> small_shifted = one; 123 small_shifted.ShiftLeft(out_of_bounds_shift); 124 EXPECT_EQ(zero, small_shifted); 125 } 126 } 127 } 128 129 TEST(BigUnsigned, MultiplyByUint32) { 130 const BigUnsigned<84> factorial_100( 131 "933262154439441526816992388562667004907159682643816214685929638952175999" 132 "932299156089414639761565182862536979208272237582511852109168640000000000" 133 "00000000000000"); 134 BigUnsigned<84> a(1u); 135 for (uint32_t i = 1; i <= 100; ++i) { 136 a.MultiplyBy(i); 137 } 138 EXPECT_EQ(a, BigUnsigned<84>(factorial_100)); 139 } 140 141 TEST(BigUnsigned, MultiplyByBigUnsigned) { 142 { 143 // Put the terms of factorial_200 into two bigints, and multiply them 144 // together. 145 const BigUnsigned<84> factorial_200( 146 "7886578673647905035523632139321850622951359776871732632947425332443594" 147 "4996340334292030428401198462390417721213891963883025764279024263710506" 148 "1926624952829931113462857270763317237396988943922445621451664240254033" 149 "2918641312274282948532775242424075739032403212574055795686602260319041" 150 "7032406235170085879617892222278962370389737472000000000000000000000000" 151 "0000000000000000000000000"); 152 BigUnsigned<84> evens(1u); 153 BigUnsigned<84> odds(1u); 154 for (uint32_t i = 1; i < 200; i += 2) { 155 odds.MultiplyBy(i); 156 evens.MultiplyBy(i + 1); 157 } 158 evens.MultiplyBy(odds); 159 EXPECT_EQ(evens, factorial_200); 160 } 161 { 162 // Multiply various powers of 10 together. 163 for (int a = 0 ; a < 700; a += 25) { 164 SCOPED_TRACE(a); 165 BigUnsigned<84> a_value("3" + std::string(a, '0')); 166 for (int b = 0; b < (700 - a); b += 25) { 167 SCOPED_TRACE(b); 168 BigUnsigned<84> b_value("2" + std::string(b, '0')); 169 BigUnsigned<84> expected_product("6" + std::string(a + b, '0')); 170 b_value.MultiplyBy(a_value); 171 EXPECT_EQ(b_value, expected_product); 172 } 173 } 174 } 175 } 176 177 TEST(BigUnsigned, MultiplyByOverflow) { 178 { 179 // Check that multiplcation overflow predictably truncates. 180 181 // A big int with all bits on. 182 BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455"); 183 // Modulo 2**128, this is equal to -1. Therefore the square of this, 184 // modulo 2**128, should be 1. 185 all_bits_on.MultiplyBy(all_bits_on); 186 EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u)); 187 } 188 { 189 // Try multiplying a large bigint by 2**50, and compare the result to 190 // shifting. 191 BigUnsigned<4> value_1("12345678901234567890123456789012345678"); 192 BigUnsigned<4> value_2("12345678901234567890123456789012345678"); 193 BigUnsigned<4> two_to_fiftieth(1u); 194 two_to_fiftieth.ShiftLeft(50); 195 196 value_1.ShiftLeft(50); 197 value_2.MultiplyBy(two_to_fiftieth); 198 EXPECT_EQ(value_1, value_2); 199 } 200 } 201 202 TEST(BigUnsigned, FiveToTheNth) { 203 { 204 // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to 205 // and including overflow. 206 for (int i = 0; i < 1160; ++i) { 207 SCOPED_TRACE(i); 208 BigUnsigned<84> value_1(123u); 209 BigUnsigned<84> value_2(123u); 210 value_1.MultiplyByFiveToTheNth(i); 211 for (int j = 0; j < i; j++) { 212 value_2.MultiplyBy(5u); 213 } 214 EXPECT_EQ(value_1, value_2); 215 } 216 } 217 { 218 // Check that the faster, table-lookup-based static method returns the same 219 // result that multiplying in-place would return, up to and including 220 // overflow. 221 for (int i = 0; i < 1160; ++i) { 222 SCOPED_TRACE(i); 223 BigUnsigned<84> value_1(1u); 224 value_1.MultiplyByFiveToTheNth(i); 225 BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i); 226 EXPECT_EQ(value_1, value_2); 227 } 228 } 229 } 230 231 TEST(BigUnsigned, TenToTheNth) { 232 { 233 // Sanity check MultiplyByTenToTheNth. 234 for (int i = 0; i < 800; ++i) { 235 SCOPED_TRACE(i); 236 BigUnsigned<84> value_1(123u); 237 BigUnsigned<84> value_2(123u); 238 value_1.MultiplyByTenToTheNth(i); 239 for (int j = 0; j < i; j++) { 240 value_2.MultiplyBy(10u); 241 } 242 EXPECT_EQ(value_1, value_2); 243 } 244 } 245 { 246 // Alternate testing approach, taking advantage of the decimal parser. 247 for (int i = 0; i < 200; ++i) { 248 SCOPED_TRACE(i); 249 BigUnsigned<84> value_1(135u); 250 value_1.MultiplyByTenToTheNth(i); 251 BigUnsigned<84> value_2("135" + std::string(i, '0')); 252 EXPECT_EQ(value_1, value_2); 253 } 254 } 255 } 256 257 258 } // namespace strings_internal 259 ABSL_NAMESPACE_END 260 } // namespace absl