- Fix a sign-checking bug in the BigInteger(..., Sign) constructors.
[bigint/bigint.git] / testsuite.cc
CommitLineData
0afe80d5
MM
1/* Test suite for the library. First, it ``tests'' that all the constructs it
2 * uses compile successfully. Then, its output to stdout is compared to the
e6866cd0
MM
3 * expected output automatically extracted from slash-slash comments below.
4 *
5 * NOTE: For now, the test suite expects a 32-bit system. On others, some tests
6 * may fail, and it may be ineffective at catching bugs. TODO: Remedy this. */
0afe80d5
MM
7
8#include "BigIntegerLibrary.hh"
9
10#include <string>
11#include <iostream>
12using namespace std;
13
e6866cd0
MM
14// Evaluate expr and print the result or "error" as appropriate.
15#define TEST(expr) do {\
16 cout << "Line " << __LINE__ << ": ";\
17 try {\
18 cout << (expr);\
19 } catch (const char *err) {\
20 cout << "error";\
21 }\
22 cout << endl;\
23} while (0)
24
706f6a7e
MM
25const BigUnsigned &check(const BigUnsigned &x) {
26 unsigned int l = x.getLength();
27 if (l != 0 && x.getBlock(l-1) == 0)
e6866cd0 28 cout << "check: Unzapped number!" << endl;
706f6a7e 29 if (l > x.getCapacity())
e6866cd0 30 cout << "check: Capacity inconsistent with length!" << endl;
706f6a7e
MM
31 return x;
32}
33
34const BigInteger &check(const BigInteger &x) {
35 if (x.getSign() == 0 && !x.getMagnitude().isZero())
e6866cd0 36 cout << "check: Sign should not be zero!" << endl;
706f6a7e 37 if (x.getSign() != 0 && x.getMagnitude().isZero())
e6866cd0 38 cout << "check: Sign should be zero!" << endl;
706f6a7e
MM
39 check(x.getMagnitude());
40 return x;
41}
42
e6866cd0
MM
43short pathologicalShort = ~((unsigned short)(~0) >> 1);
44int pathologicalInt = ~((unsigned int)(~0) >> 1);
45long pathologicalLong = ~((unsigned long)(~0) >> 1);
706f6a7e 46
0afe80d5 47int main() {
706f6a7e
MM
48
49try {
50
0afe80d5 51BigUnsigned z(0), one(1), ten(10);
e6866cd0
MM
52TEST(z); //0
53TEST(1); //1
54TEST(10); //10
0afe80d5 55
706f6a7e
MM
56// TODO: Comprehensively test the general and special cases of each function.
57
82cba2ff
MM
58// === Default constructors ===
59
e6866cd0
MM
60TEST(check(BigUnsigned())); //0
61TEST(check(BigInteger())); //0
62
cb2f0c28
MM
63// === Block-array constructors ===
64
65BigUnsigned::Blk myBlocks[3];
66myBlocks[0] = 3;
67myBlocks[1] = 4;
68myBlocks[2] = 0;
69BigUnsigned bu(myBlocks, 3);
70TEST(check(bu)); //17179869187
71TEST(check(BigInteger(myBlocks, 3))); //17179869187
72TEST(check(BigInteger(bu ))); //17179869187
73
74// For nonzero magnitude, reject zero and invalid signs.
75TEST(check(BigInteger(myBlocks, 3, BigInteger::positive))); //17179869187
76TEST(check(BigInteger(myBlocks, 3, BigInteger::negative))); //-17179869187
77TEST(check(BigInteger(myBlocks, 3, BigInteger::zero ))); //error
78TEST(check(BigInteger(bu, BigInteger::positive))); //17179869187
79TEST(check(BigInteger(bu, BigInteger::negative))); //-17179869187
80TEST(check(BigInteger(bu, BigInteger::zero ))); //error
81
82// For zero magnitude, force the sign to zero without error.
83BigUnsigned::Blk myZeroBlocks[1];
84myZeroBlocks[0] = 0;
85TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::positive))); //0
86TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::negative))); //0
87TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::zero ))); //0
88
82cba2ff
MM
89// === BigUnsigned conversion limits ===
90
e6866cd0
MM
91TEST(BigUnsigned(0).toUnsignedLong()); //0
92TEST(BigUnsigned(4294967295U).toUnsignedLong()); //4294967295
93TEST(stringToBigUnsigned("4294967296").toUnsignedLong()); //error
94
95TEST(BigUnsigned(0).toLong()); //0
96TEST(BigUnsigned(2147483647).toLong()); //2147483647
97TEST(BigUnsigned(2147483648U).toLong()); //error
98
99// int is the same as long on a 32-bit system
100TEST(BigUnsigned(0).toUnsignedInt()); //0
101TEST(BigUnsigned(4294967295U).toUnsignedInt()); //4294967295
102TEST(stringToBigUnsigned("4294967296").toUnsignedInt()); //error
103
104TEST(BigUnsigned(0).toInt()); //0
105TEST(BigUnsigned(2147483647).toInt()); //2147483647
106TEST(BigUnsigned(2147483648U).toInt()); //error
107
108TEST(BigUnsigned(0).toUnsignedShort()); //0
109TEST(BigUnsigned(65535).toUnsignedShort()); //65535
110TEST(BigUnsigned(65536).toUnsignedShort()); //error
111
112TEST(BigUnsigned(0).toShort()); //0
113TEST(BigUnsigned(32767).toShort()); //32767
114TEST(BigUnsigned(32768).toShort()); //error
115
82cba2ff
MM
116// === BigInteger conversion limits ===
117
e6866cd0
MM
118TEST(BigInteger(-1).toUnsignedLong()); //error
119TEST(BigInteger(0).toUnsignedLong()); //0
120TEST(BigInteger(4294967295U).toUnsignedLong()); //4294967295
121TEST(stringToBigInteger("4294967296").toUnsignedLong()); //error
122
123TEST(stringToBigInteger("-2147483649").toLong()); //error
124TEST(stringToBigInteger("-2147483648").toLong()); //-2147483648
125TEST(BigInteger(-2147483647).toLong()); //-2147483647
126TEST(BigInteger(0).toLong()); //0
127TEST(BigInteger(2147483647).toLong()); //2147483647
128TEST(BigInteger(2147483648U).toLong()); //error
129
130// int is the same as long on a 32-bit system
131TEST(BigInteger(-1).toUnsignedInt()); //error
132TEST(BigInteger(0).toUnsignedInt()); //0
133TEST(BigInteger(4294967295U).toUnsignedInt()); //4294967295
134TEST(stringToBigInteger("4294967296").toUnsignedInt()); //error
135
136TEST(stringToBigInteger("-2147483649").toInt()); //error
137TEST(stringToBigInteger("-2147483648").toInt()); //-2147483648
138TEST(BigInteger(-2147483647).toInt()); //-2147483647
139TEST(BigInteger(0).toInt()); //0
140TEST(BigInteger(2147483647).toInt()); //2147483647
141TEST(BigInteger(2147483648U).toInt()); //error
142
143TEST(BigInteger(-1).toUnsignedShort()); //error
144TEST(BigInteger(0).toUnsignedShort()); //0
145TEST(BigInteger(65535).toUnsignedShort()); //65535
146TEST(BigInteger(65536).toUnsignedShort()); //error
147
148TEST(BigInteger(-32769).toShort()); //error
149TEST(BigInteger(-32768).toShort()); //-32768
150TEST(BigInteger(-32767).toShort()); //-32767
151TEST(BigInteger(0).toShort()); //0
152TEST(BigInteger(32767).toShort()); //32767
153TEST(BigInteger(32768).toShort()); //error
706f6a7e 154
82cba2ff
MM
155// === Negative BigUnsigneds ===
156
e6866cd0
MM
157// ...during construction
158TEST(BigUnsigned(short(-1))); //error
159TEST(BigUnsigned(pathologicalShort)); //error
160TEST(BigUnsigned(-1)); //error
161TEST(BigUnsigned(pathologicalInt)); //error
162TEST(BigUnsigned(long(-1))); //error
163TEST(BigUnsigned(pathologicalLong)); //error
82cba2ff 164
e6866cd0
MM
165// ...during subtraction
166TEST(BigUnsigned(5) - BigUnsigned(6)); //error
167TEST(stringToBigUnsigned("314159265358979323") - stringToBigUnsigned("314159265358979324")); //error
168TEST(check(BigUnsigned(5) - BigUnsigned(5))); //0
169TEST(check(stringToBigUnsigned("314159265358979323") - stringToBigUnsigned("314159265358979323"))); //0
170TEST(check(stringToBigUnsigned("4294967296") - BigUnsigned(1))); //4294967295
171
82cba2ff
MM
172// === BigUnsigned addition ===
173
e6866cd0
MM
174TEST(check(BigUnsigned(0) + 0)); //0
175TEST(check(BigUnsigned(0) + 1)); //1
176// Ordinary carry
177TEST(check(stringToBigUnsigned("8589934591" /* 2^33 - 1*/)
178 + stringToBigUnsigned("4294967298" /* 2^32 + 2 */))); //12884901889
179// Creation of a new block
180TEST(check(BigUnsigned(0xFFFFFFFFU) + 1)); //4294967296
181
82cba2ff
MM
182// === BigUnsigned subtraction ===
183
e6866cd0
MM
184TEST(check(BigUnsigned(1) - 0)); //1
185TEST(check(BigUnsigned(1) - 1)); //0
186TEST(check(BigUnsigned(2) - 1)); //1
187// Ordinary borrow
188TEST(check(stringToBigUnsigned("12884901889")
189 - stringToBigUnsigned("4294967298"))); //8589934591
190// Borrow that removes a block
191TEST(check(stringToBigUnsigned("4294967296") - 1)); //4294967295
706f6a7e 192
82cba2ff
MM
193// === BigUnsigned multiplication and division ===
194
706f6a7e 195BigUnsigned a = check(BigUnsigned(314159265) * 358979323);
e6866cd0
MM
196TEST(a); //112776680263877595
197TEST(a / 123); //916883579381118
198TEST(a % 123); //81
199
200TEST(BigUnsigned(5) / 0); //error
201
82cba2ff
MM
202// === Block accessors ===
203
88dbe518
MM
204BigUnsigned b;
205TEST(b); //0
206TEST(b.getBlock(0)); //0
207b.setBlock(1, 314);
208// Did b grow properly? And did we zero intermediate blocks?
209TEST(check(b)); //1348619730944
210TEST(b.getLength()); //2
211TEST(b.getBlock(0)); //0
212TEST(b.getBlock(1)); //314
213// Did b shrink properly?
214b.setBlock(1, 0);
215TEST(check(b)); //0
216
217BigUnsigned bb(314);
218bb.setBlock(1, 159);
219// Make sure we used allocateAndCopy, not allocate
220TEST(bb.getBlock(0)); //314
221TEST(bb.getBlock(1)); //159
222// Blocks beyond the number should be zero regardless of whether they are
223// within the capacity.
224bb.add(1, 2);
225TEST(bb.getBlock(0)); //3
226TEST(bb.getBlock(1)); //0
227TEST(bb.getBlock(2)); //0
228TEST(bb.getBlock(314159)); //0
229
82cba2ff
MM
230// === Bit accessors ===
231
88dbe518
MM
232TEST(BigUnsigned(0).bitLength()); //0
233TEST(BigUnsigned(1).bitLength()); //1
234TEST(BigUnsigned(4095).bitLength()); //12
235TEST(BigUnsigned(4096).bitLength()); //13
236// 5 billion is between 2^32 (about 4 billion) and 2^33 (about 8 billion).
237TEST(stringToBigUnsigned("5000000000").bitLength()); //33
238
239// 25 is binary 11001.
240BigUnsigned bbb(25);
241TEST(bbb.getBit(4)); //1
242TEST(bbb.getBit(3)); //1
243TEST(bbb.getBit(2)); //0
244TEST(bbb.getBit(1)); //0
245TEST(bbb.getBit(0)); //1
246TEST(bbb.bitLength()); //5
247// Effectively add 2^32.
248bbb.setBit(32, true);
249TEST(bbb); //4294967321
250bbb.setBit(31, true);
251bbb.setBit(32, false);
252TEST(check(bbb)); //2147483673
253
82cba2ff
MM
254// === Combining BigUnsigned, BigInteger, and primitive integers ===
255
e6866cd0
MM
256BigUnsigned p1 = BigUnsigned(3) * 5;
257TEST(p1); //15
258/* In this case, we would like g++ to implicitly promote the BigUnsigned to a
259 * BigInteger, but it seems to prefer converting the -5 to a BigUnsigned, which
260 * causes an error. If I take out constructors for BigUnsigned from signed
261 * primitive integers, the BigUnsigned(3) becomes ambiguous, and if I take out
262 * all the constructors but BigUnsigned(unsigned long), g++ uses that
263 * constructor and gets a wrong (positive) answer. Thus, I think we'll just
264 * have to live with this cast. */
265BigInteger p2 = BigInteger(BigUnsigned(3)) * -5;
266TEST(p2); //-15
706f6a7e 267
82cba2ff
MM
268// === Test some previous bugs ===
269
706f6a7e
MM
270{
271 /* Test that BigInteger division sets the sign to zero.
272 * Bug reported by David Allen. */
273 BigInteger num(3), denom(5), quotient;
274 num.divideWithRemainder(denom, quotient);
275 check(quotient);
276 num = 5;
277 num.divideWithRemainder(denom, quotient);
278 check(num);
279}
280
281{
282 /* Test that BigInteger subtraction sets the sign properly.
283 * Bug reported by Samuel Larkin. */
284 BigInteger zero(0), three(3), ans;
285 ans = zero - three;
e6866cd0 286 TEST(check(ans).getSign()); //-1
706f6a7e
MM
287}
288
289{
290 /* Test that BigInteger multiplication shifts bits properly on systems
291 * where long is bigger than int. (Obviously, this would only catch the
292 * bug when run on such a system.)
293 * Bug reported by Mohand Mezmaz. */
294 BigInteger f=4; f*=3;
e6866cd0 295 TEST(check(f)); //12
706f6a7e
MM
296}
297
298{
299 /* Test that bitwise XOR allocates the larger length.
300 * Bug reported by Sriram Sankararaman. */
301 BigUnsigned a(0), b(3), ans;
302 ans = a ^ b;
e6866cd0 303 TEST(ans); //3
706f6a7e
MM
304}
305
306{
307 /* Test that an aliased multiplication works.
308 * Bug reported by Boris Dessy. */
309 BigInteger num(5);
310 num *= num;
e6866cd0 311 TEST(check(num)); //25
706f6a7e
MM
312}
313
314} catch (const char *err) {
e6866cd0 315 cout << "UNCAUGHT ERROR: " << err << endl;
706f6a7e
MM
316}
317
0afe80d5
MM
318return 0;
319}