2 * *****************************************************************************
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * *****************************************************************************
43 * Takes an error code and aborts if it actually is an error.
44 * @param e The error code.
49 if (e != BCL_ERROR_NONE) abort();
58 BclNumber n, n2, n3, n4, n5, n6;
65 // We do this twice to test the reference counting code.
71 // If bcl is set to abort on fatal error, that is a bug because it should
73 if (bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
75 bcl_setAbortOnFatalError(true);
77 // Now it *should* be set.
78 if (!bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
80 // We do this twice to test the context stack.
81 ctxt = bcl_ctxt_create();
82 bcl_pushContext(ctxt);
83 ctxt = bcl_ctxt_create();
84 bcl_pushContext(ctxt);
86 // Ensure that the scale is properly set.
88 bcl_ctxt_setScale(ctxt, scale);
89 scale = bcl_ctxt_scale(ctxt);
90 if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
93 bcl_ctxt_setIbase(ctxt, scale);
94 scale = bcl_ctxt_ibase(ctxt);
95 if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
98 bcl_ctxt_setObase(ctxt, scale);
99 scale = bcl_ctxt_obase(ctxt);
100 if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
102 // Set the back for the tests
103 bcl_ctxt_setIbase(ctxt, 10);
104 scale = bcl_ctxt_ibase(ctxt);
105 if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
106 bcl_ctxt_setObase(ctxt, 10);
107 scale = bcl_ctxt_obase(ctxt);
108 if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
110 // Ensure that creating, duping, and copying works.
111 n = bcl_num_create();
115 // Ensure that parsing works.
116 n3 = bcl_parse("2938");
118 n4 = bcl_parse("-28390.9108273");
121 // We also want to be sure that negatives work. This is a special case
122 // because bc and dc generate a negative instruction; they don't actually
123 // parse numbers as negative.
124 if (!bcl_num_neg(n4)) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
126 // Add them and check the result.
127 n3 = bcl_add(n3, n4);
129 res = bcl_string(bcl_dup(n3));
130 if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
132 // We want to ensure all memory gets freed because we run this under
136 // Ensure that divmod, a special case, works.
137 n4 = bcl_parse("8937458902.2890347");
139 e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6);
142 res = bcl_string(n5);
144 if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
148 res = bcl_string(n6);
150 if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
154 // Ensure that sqrt works. This is also a special case. The reason is
155 // because it is a one-argument function. Since all binary operators go
156 // through the same code (basically), we can test add and be done. However,
157 // sqrt does not, so we want to specifically test it.
161 res = bcl_string(bcl_dup(n4));
163 if (strcmp(res, "94538.1346457028")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
167 // We want to check that numbers are properly extended...
168 e = bcl_num_setScale(n4, 20);
171 res = bcl_string(bcl_dup(n4));
173 if (strcmp(res, "94538.13464570280000000000"))
174 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
179 e = bcl_num_setScale(n4, 0);
182 res = bcl_string(bcl_dup(n4));
184 if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
188 // Check conversion to hardware integers...
189 e = bcl_bigdig(n4, &b);
192 if (b != 94538) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
195 n4 = bcl_bigdig2num(b);
198 res = bcl_string(bcl_dup(n4));
200 if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
208 // Check that no asserts fire in shifting.
209 n4 = bcl_lshift(n4, bcl_bigdig2num(10));
217 n2 = bcl_ifrand(bcl_dup(n3), 10);
220 // Still checking asserts.
221 e = bcl_rand_seedWithNum(n3);
224 // Still checking asserts.
225 n4 = bcl_rand_seed2num();
228 // Finally, check modexp, yet another special case.
229 n5 = bcl_parse("10");
232 n6 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5));
238 // Test leading zeroes.
239 if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
241 n = bcl_parse("0.01");
244 n2 = bcl_parse("-0.01");
247 n3 = bcl_parse("1.01");
250 n4 = bcl_parse("-1.01");
253 res = bcl_string(bcl_dup(n));
254 if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
258 res = bcl_string(bcl_dup(n2));
259 if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
263 res = bcl_string(bcl_dup(n3));
264 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
268 res = bcl_string(bcl_dup(n4));
269 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
273 bcl_setLeadingZeroes(true);
275 if (!bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
277 res = bcl_string(bcl_dup(n));
278 if (strcmp(res, "0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
282 res = bcl_string(bcl_dup(n2));
283 if (strcmp(res, "-0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
287 res = bcl_string(bcl_dup(n3));
288 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
292 res = bcl_string(bcl_dup(n4));
293 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
297 bcl_setLeadingZeroes(false);
299 if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
302 if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
306 res = bcl_string(n2);
307 if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
311 res = bcl_string(n3);
312 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
316 res = bcl_string(n4);
317 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
321 bcl_ctxt_freeNums(ctxt);
325 // We need to pop both contexts and free them.
330 ctxt = bcl_context();
336 // Decrement the reference counter to ensure all is freed.