blob: 745714aca1b3a8942e907e8ff4b1dd88044e1287 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// 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
21namespace absl {
22namespace strings_internal {
23
24TEST(BigUnsigned, ShiftLeft) {
25 {
26 // Check that 3 * 2**100 is calculated correctly
27 BigUnsigned<4> num(3u);
28 num.ShiftLeft(100);
29 EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128"));
30 }
31 {
32 // Test that overflow is truncated properly.
33 // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint.
34 // Shifting left by 125 bits should truncate off the high bit, so that
35 // 15 << 125 == 7 << 125
36 // after truncation.
37 BigUnsigned<4> a(15u);
38 BigUnsigned<4> b(7u);
39 BigUnsigned<4> c(3u);
40 a.ShiftLeft(125);
41 b.ShiftLeft(125);
42 c.ShiftLeft(125);
43 EXPECT_EQ(a, b);
44 EXPECT_NE(a, c);
45 }
46 {
47 // Same test, larger bigint:
48 BigUnsigned<84> a(15u);
49 BigUnsigned<84> b(7u);
50 BigUnsigned<84> c(3u);
51 a.ShiftLeft(84 * 32 - 3);
52 b.ShiftLeft(84 * 32 - 3);
53 c.ShiftLeft(84 * 32 - 3);
54 EXPECT_EQ(a, b);
55 EXPECT_NE(a, c);
56 }
57 {
58 // Check that incrementally shifting has the same result as doing it all at
59 // once (attempting to capture corner cases.)
60 const std::string seed = "1234567890123456789012345678901234567890";
61 BigUnsigned<84> a(seed);
62 for (int i = 1; i <= 84 * 32; ++i) {
63 a.ShiftLeft(1);
64 BigUnsigned<84> b(seed);
65 b.ShiftLeft(i);
66 EXPECT_EQ(a, b);
67 }
68 // And we should have fully rotated all bits off by now:
69 EXPECT_EQ(a, BigUnsigned<84>(0u));
70 }
71}
72
73TEST(BigUnsigned, MultiplyByUint32) {
74 const BigUnsigned<84> factorial_100(
75 "933262154439441526816992388562667004907159682643816214685929638952175999"
76 "932299156089414639761565182862536979208272237582511852109168640000000000"
77 "00000000000000");
78 BigUnsigned<84> a(1u);
79 for (uint32_t i = 1; i <= 100; ++i) {
80 a.MultiplyBy(i);
81 }
82 EXPECT_EQ(a, BigUnsigned<84>(factorial_100));
83}
84
85TEST(BigUnsigned, MultiplyByBigUnsigned) {
86 {
87 // Put the terms of factorial_200 into two bigints, and multiply them
88 // together.
89 const BigUnsigned<84> factorial_200(
90 "7886578673647905035523632139321850622951359776871732632947425332443594"
91 "4996340334292030428401198462390417721213891963883025764279024263710506"
92 "1926624952829931113462857270763317237396988943922445621451664240254033"
93 "2918641312274282948532775242424075739032403212574055795686602260319041"
94 "7032406235170085879617892222278962370389737472000000000000000000000000"
95 "0000000000000000000000000");
96 BigUnsigned<84> evens(1u);
97 BigUnsigned<84> odds(1u);
98 for (uint32_t i = 1; i < 200; i += 2) {
99 odds.MultiplyBy(i);
100 evens.MultiplyBy(i + 1);
101 }
102 evens.MultiplyBy(odds);
103 EXPECT_EQ(evens, factorial_200);
104 }
105 {
106 // Multiply various powers of 10 together.
107 for (int a = 0 ; a < 700; a += 25) {
108 SCOPED_TRACE(a);
109 BigUnsigned<84> a_value("3" + std::string(a, '0'));
110 for (int b = 0; b < (700 - a); b += 25) {
111 SCOPED_TRACE(b);
112 BigUnsigned<84> b_value("2" + std::string(b, '0'));
113 BigUnsigned<84> expected_product("6" + std::string(a + b, '0'));
114 b_value.MultiplyBy(a_value);
115 EXPECT_EQ(b_value, expected_product);
116 }
117 }
118 }
119}
120
121TEST(BigUnsigned, MultiplyByOverflow) {
122 {
123 // Check that multiplcation overflow predictably truncates.
124
125 // A big int with all bits on.
126 BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
127 // Modulo 2**128, this is equal to -1. Therefore the square of this,
128 // modulo 2**128, should be 1.
129 all_bits_on.MultiplyBy(all_bits_on);
130 EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u));
131 }
132 {
133 // Try multiplying a large bigint by 2**50, and compare the result to
134 // shifting.
135 BigUnsigned<4> value_1("12345678901234567890123456789012345678");
136 BigUnsigned<4> value_2("12345678901234567890123456789012345678");
137 BigUnsigned<4> two_to_fiftieth(1u);
138 two_to_fiftieth.ShiftLeft(50);
139
140 value_1.ShiftLeft(50);
141 value_2.MultiplyBy(two_to_fiftieth);
142 EXPECT_EQ(value_1, value_2);
143 }
144}
145
146TEST(BigUnsigned, FiveToTheNth) {
147 {
148 // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to
149 // and including overflow.
150 for (int i = 0; i < 1160; ++i) {
151 SCOPED_TRACE(i);
152 BigUnsigned<84> value_1(123u);
153 BigUnsigned<84> value_2(123u);
154 value_1.MultiplyByFiveToTheNth(i);
155 for (int j = 0; j < i; j++) {
156 value_2.MultiplyBy(5u);
157 }
158 EXPECT_EQ(value_1, value_2);
159 }
160 }
161 {
162 // Check that the faster, table-lookup-based static method returns the same
163 // result that multiplying in-place would return, up to and including
164 // overflow.
165 for (int i = 0; i < 1160; ++i) {
166 SCOPED_TRACE(i);
167 BigUnsigned<84> value_1(1u);
168 value_1.MultiplyByFiveToTheNth(i);
169 BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i);
170 EXPECT_EQ(value_1, value_2);
171 }
172 }
173}
174
175TEST(BigUnsigned, TenToTheNth) {
176 {
177 // Sanity check MultiplyByTenToTheNth.
178 for (int i = 0; i < 800; ++i) {
179 SCOPED_TRACE(i);
180 BigUnsigned<84> value_1(123u);
181 BigUnsigned<84> value_2(123u);
182 value_1.MultiplyByTenToTheNth(i);
183 for (int j = 0; j < i; j++) {
184 value_2.MultiplyBy(10u);
185 }
186 EXPECT_EQ(value_1, value_2);
187 }
188 }
189 {
190 // Alternate testing approach, taking advantage of the decimal parser.
191 for (int i = 0; i < 200; ++i) {
192 SCOPED_TRACE(i);
193 BigUnsigned<84> value_1(135u);
194 value_1.MultiplyByTenToTheNth(i);
195 BigUnsigned<84> value_2("135" + std::string(i, '0'));
196 EXPECT_EQ(value_1, value_2);
197 }
198 }
199}
200
201
202} // namespace strings_internal
203} // namespace absl