]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/bcl.c
vendor/bc: import version 6.2.2
[FreeBSD/FreeBSD.git] / tests / bcl.c
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
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.
17  *
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.
29  *
30  * *****************************************************************************
31  *
32  * Tests for bcl(3).
33  *
34  */
35
36 #include <stdlib.h>
37 #include <stdbool.h>
38 #include <string.h>
39
40 #include <bcl.h>
41
42 /**
43  * Takes an error code and aborts if it actually is an error.
44  * @param e  The error code.
45  */
46 static void
47 err(BclError e)
48 {
49         if (e != BCL_ERROR_NONE) abort();
50 }
51
52 int
53 main(void)
54 {
55         BclError e;
56         BclContext ctxt;
57         size_t scale;
58         BclNumber n, n2, n3, n4, n5, n6;
59         char* res;
60         BclBigDig b = 0;
61
62         e = bcl_start();
63         err(e);
64
65         // We do this twice to test the reference counting code.
66         e = bcl_init();
67         err(e);
68         e = bcl_init();
69         err(e);
70
71         // If bcl is set to abort on fatal error, that is a bug because it should
72         // default to off.
73         if (bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
74
75         bcl_setAbortOnFatalError(true);
76
77         // Now it *should* be set.
78         if (!bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
79
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);
85
86         // Ensure that the scale is properly set.
87         scale = 10;
88         bcl_ctxt_setScale(ctxt, scale);
89         scale = bcl_ctxt_scale(ctxt);
90         if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
91
92         scale = 16;
93         bcl_ctxt_setIbase(ctxt, scale);
94         scale = bcl_ctxt_ibase(ctxt);
95         if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
96
97         // Now the obase.
98         bcl_ctxt_setObase(ctxt, scale);
99         scale = bcl_ctxt_obase(ctxt);
100         if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
101
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);
109
110         // Ensure that creating, duping, and copying works.
111         n = bcl_num_create();
112         n2 = bcl_dup(n);
113         bcl_copy(n, n2);
114
115         // Ensure that parsing works.
116         n3 = bcl_parse("2938");
117         err(bcl_err(n3));
118         n4 = bcl_parse("-28390.9108273");
119         err(bcl_err(n4));
120
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);
125
126         // Add them and check the result.
127         n3 = bcl_add(n3, n4);
128         err(bcl_err(n3));
129         res = bcl_string(bcl_dup(n3));
130         if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
131
132         // We want to ensure all memory gets freed because we run this under
133         // Valgrind.
134         free(res);
135
136         // Ensure that divmod, a special case, works.
137         n4 = bcl_parse("8937458902.2890347");
138         err(bcl_err(n4));
139         e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6);
140         err(e);
141
142         res = bcl_string(n5);
143
144         if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
145
146         free(res);
147
148         res = bcl_string(n6);
149
150         if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
151
152         free(res);
153
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.
158         n4 = bcl_sqrt(n4);
159         err(bcl_err(n4));
160
161         res = bcl_string(bcl_dup(n4));
162
163         if (strcmp(res, "94538.1346457028")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
164
165         free(res);
166
167         // We want to check that numbers are properly extended...
168         e = bcl_num_setScale(n4, 20);
169         err(e);
170
171         res = bcl_string(bcl_dup(n4));
172
173         if (strcmp(res, "94538.13464570280000000000"))
174                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
175
176         free(res);
177
178         // ...and truncated.
179         e = bcl_num_setScale(n4, 0);
180         err(e);
181
182         res = bcl_string(bcl_dup(n4));
183
184         if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
185
186         free(res);
187
188         // Check conversion to hardware integers...
189         e = bcl_bigdig(n4, &b);
190         err(e);
191
192         if (b != 94538) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
193
194         // ...and back.
195         n4 = bcl_bigdig2num(b);
196         err(bcl_err(n4));
197
198         res = bcl_string(bcl_dup(n4));
199
200         if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
201
202         free(res);
203
204         // Check rand.
205         n4 = bcl_frand(10);
206         err(bcl_err(n4));
207
208         // Check that no asserts fire in shifting.
209         n4 = bcl_lshift(n4, bcl_bigdig2num(10));
210         err(bcl_err(n4));
211
212         // Repeat.
213         n3 = bcl_irand(n4);
214         err(bcl_err(n3));
215
216         // Repeat.
217         n2 = bcl_ifrand(bcl_dup(n3), 10);
218         err(bcl_err(n2));
219
220         // Still checking asserts.
221         e = bcl_rand_seedWithNum(n3);
222         err(e);
223
224         // Still checking asserts.
225         n4 = bcl_rand_seed2num();
226         err(bcl_err(n4));
227
228         // Finally, check modexp, yet another special case.
229         n5 = bcl_parse("10");
230         err(bcl_err(n5));
231
232         n6 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5));
233         err(bcl_err(n6));
234
235         // Clean up.
236         bcl_num_free(n);
237
238         // Test leading zeroes.
239         if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
240
241         n = bcl_parse("0.01");
242         err(bcl_err(n));
243
244         n2 = bcl_parse("-0.01");
245         err(bcl_err(n2));
246
247         n3 = bcl_parse("1.01");
248         err(bcl_err(n3));
249
250         n4 = bcl_parse("-1.01");
251         err(bcl_err(n4));
252
253         res = bcl_string(bcl_dup(n));
254         if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
255
256         free(res);
257
258         res = bcl_string(bcl_dup(n2));
259         if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
260
261         free(res);
262
263         res = bcl_string(bcl_dup(n3));
264         if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
265
266         free(res);
267
268         res = bcl_string(bcl_dup(n4));
269         if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
270
271         free(res);
272
273         bcl_setLeadingZeroes(true);
274
275         if (!bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
276
277         res = bcl_string(bcl_dup(n));
278         if (strcmp(res, "0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
279
280         free(res);
281
282         res = bcl_string(bcl_dup(n2));
283         if (strcmp(res, "-0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
284
285         free(res);
286
287         res = bcl_string(bcl_dup(n3));
288         if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
289
290         free(res);
291
292         res = bcl_string(bcl_dup(n4));
293         if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
294
295         free(res);
296
297         bcl_setLeadingZeroes(false);
298
299         if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
300
301         res = bcl_string(n);
302         if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
303
304         free(res);
305
306         res = bcl_string(n2);
307         if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
308
309         free(res);
310
311         res = bcl_string(n3);
312         if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
313
314         free(res);
315
316         res = bcl_string(n4);
317         if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
318
319         free(res);
320
321         bcl_ctxt_freeNums(ctxt);
322
323         bcl_gc();
324
325         // We need to pop both contexts and free them.
326         bcl_popContext();
327
328         bcl_ctxt_free(ctxt);
329
330         ctxt = bcl_context();
331
332         bcl_popContext();
333
334         bcl_ctxt_free(ctxt);
335
336         // Decrement the reference counter to ensure all is freed.
337         bcl_free();
338
339         bcl_free();
340
341         bcl_end();
342
343         return 0;
344 }