]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/bcl.c
vendor/bc: imoport release 5.0.0
[FreeBSD/FreeBSD.git] / tests / bcl.c
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2021 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 err(BclError e) {
47         if (e != BCL_ERROR_NONE) abort();
48 }
49
50 int main(void) {
51
52         BclError e;
53         BclContext ctxt;
54         size_t scale;
55         BclNumber n, n2, n3, n4, n5, n6;
56         char* res;
57         BclBigDig b = 0;
58
59         // We do this twice to test the reference counting code.
60         e = bcl_init();
61         err(e);
62         e = bcl_init();
63         err(e);
64
65         // If bcl is set to abort on fatal error, that is a bug because it should
66         // default to off.
67         if (bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
68
69         bcl_setAbortOnFatalError(true);
70
71         // Now it *should* be set.
72         if (!bcl_abortOnFatalError()) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
73
74         // We do this twice to test the context stack.
75         ctxt = bcl_ctxt_create();
76         bcl_pushContext(ctxt);
77         ctxt = bcl_ctxt_create();
78         bcl_pushContext(ctxt);
79
80         // Ensure that the scale is properly set.
81         scale = 10;
82         bcl_ctxt_setScale(ctxt, scale);
83         scale = bcl_ctxt_scale(ctxt);
84         if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
85
86         scale = 16;
87         bcl_ctxt_setIbase(ctxt, scale);
88         scale = bcl_ctxt_ibase(ctxt);
89         if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
90
91         // Now the obase.
92         bcl_ctxt_setObase(ctxt, scale);
93         scale = bcl_ctxt_obase(ctxt);
94         if (scale != 16) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
95
96         // Set the back for the tests
97         bcl_ctxt_setIbase(ctxt, 10);
98         scale = bcl_ctxt_ibase(ctxt);
99         if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
100         bcl_ctxt_setObase(ctxt, 10);
101         scale = bcl_ctxt_obase(ctxt);
102         if (scale != 10) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
103
104         // Ensure that creating, duping, and copying works.
105         n = bcl_num_create();
106         n2 = bcl_dup(n);
107         bcl_copy(n, n2);
108
109         // Ensure that parsing works.
110         n3 = bcl_parse("2938");
111         err(bcl_err(n3));
112         n4 = bcl_parse("-28390.9108273");
113         err(bcl_err(n4));
114
115         // We also want to be sure that negatives work. This is a special case
116         // because bc and dc generate a negative instruction; they don't actually
117         // parse numbers as negative.
118         if (!bcl_num_neg(n4)) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
119
120         // Add them and check the result.
121         n3 = bcl_add(n3, n4);
122         err(bcl_err(n3));
123         res = bcl_string(bcl_dup(n3));
124         if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
125
126         // We want to ensure all memory gets freed because we run this under
127         // Valgrind.
128         free(res);
129
130         // Ensure that divmod, a special case, works.
131         n4 = bcl_parse("8937458902.2890347");
132         err(bcl_err(n4));
133         e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6);
134         err(e);
135
136         res = bcl_string(n5);
137
138         if (strcmp(res, "-351137.0060159482"))
139                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
140
141         free(res);
142
143         res = bcl_string(n6);
144
145         if (strcmp(res, ".00000152374405414"))
146                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
147
148         free(res);
149
150         // Ensure that sqrt works. This is also a special case. The reason is
151         // because it is a one-argument function. Since all binary operators go
152         // through the same code (basically), we can test add and be done. However,
153         // sqrt does not, so we want to specifically test it.
154         n4 = bcl_sqrt(n4);
155         err(bcl_err(n4));
156
157         res = bcl_string(bcl_dup(n4));
158
159         if (strcmp(res, "94538.1346457028"))
160                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
161
162         free(res);
163
164         // We want to check that numbers are properly extended...
165         e = bcl_num_setScale(n4, 20);
166         err(e);
167
168         res = bcl_string(bcl_dup(n4));
169
170         if (strcmp(res, "94538.13464570280000000000"))
171                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
172
173         free(res);
174
175         // ...and truncated.
176         e = bcl_num_setScale(n4, 0);
177         err(e);
178
179         res = bcl_string(bcl_dup(n4));
180
181         if (strcmp(res, "94538"))
182                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
183
184         free(res);
185
186         // Check conversion to hardware integers...
187         e = bcl_bigdig(n4, &b);
188         err(e);
189
190         if (b != 94538) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
191
192         // ...and back.
193         n4 = bcl_bigdig2num(b);
194         err(bcl_err(n4));
195
196         res = bcl_string(bcl_dup(n4));
197
198         if (strcmp(res, "94538"))
199                 err(BCL_ERROR_FATAL_UNKNOWN_ERR);
200
201         free(res);
202
203         // Check rand.
204         n4 = bcl_frand(10);
205         err(bcl_err(n4));
206
207         // Check that no asserts fire in shifting.
208         n4 = bcl_lshift(n4, bcl_bigdig2num(10));
209         err(bcl_err(n4));
210
211         // Repeat.
212         n3 = bcl_irand(n4);
213         err(bcl_err(n3));
214
215         // Repeat.
216         n2 = bcl_ifrand(bcl_dup(n3), 10);
217         err(bcl_err(n2));
218
219         // Still checking asserts.
220         e = bcl_rand_seedWithNum(n3);
221         err(e);
222
223         // Still checking asserts.
224         n4 = bcl_rand_seed2num();
225         err(bcl_err(n4));
226
227         // Finally, check modexp, yet another special case.
228         n5 = bcl_parse("10");
229         err(bcl_err(n5));
230
231         n6 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5));
232         err(bcl_err(n6));
233
234         // Clean up.
235         bcl_num_free(n);
236
237         bcl_ctxt_freeNums(ctxt);
238
239         bcl_gc();
240
241         // We need to pop both contexts and free them.
242         bcl_popContext();
243
244         bcl_ctxt_free(ctxt);
245
246         ctxt = bcl_context();
247
248         bcl_popContext();
249
250         bcl_ctxt_free(ctxt);
251
252         // Decrement the reference counter to ensure all is freed.
253         bcl_free();
254
255         bcl_free();
256
257         return 0;
258 }