1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2024 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, n7; 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 n5 = bcl_add_keep(n3, n4); 128 err(bcl_err(n5)); 129 res = bcl_string(n5); 130 if (res == NULL) err(BCL_ERROR_FATAL_ALLOC_ERR); 131 if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 132 133 // We want to ensure all memory gets freed because we run this under 134 // Valgrind. 135 free(res); 136 137 // Add them and check the result. 138 n3 = bcl_add(n3, n4); 139 err(bcl_err(n3)); 140 res = bcl_string_keep(n3); 141 if (res == NULL) err(BCL_ERROR_FATAL_ALLOC_ERR); 142 if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 143 144 // We want to ensure all memory gets freed because we run this under 145 // Valgrind. 146 free(res); 147 148 // Ensure that divmod, a special case, works. 149 n4 = bcl_parse("8937458902.2890347"); 150 err(bcl_err(n4)); 151 e = bcl_divmod_keep(n4, n3, &n5, &n6); 152 err(e); 153 154 res = bcl_string(n5); 155 if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 156 free(res); 157 158 res = bcl_string(n6); 159 if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 160 free(res); 161 162 // Ensure that divmod, a special case, works. 163 n4 = bcl_parse("8937458902.2890347"); 164 err(bcl_err(n4)); 165 e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6); 166 err(e); 167 168 res = bcl_string(n5); 169 if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 170 free(res); 171 172 res = bcl_string(n6); 173 if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 174 free(res); 175 176 // Ensure that sqrt works. This is also a special case. The reason is 177 // because it is a one-argument function. Since all binary operators go 178 // through the same code (basically), we can test add and be done. However, 179 // sqrt does not, so we want to specifically test it. 180 n4 = bcl_sqrt(n4); 181 err(bcl_err(n4)); 182 183 res = bcl_string(bcl_dup(n4)); 184 185 if (strcmp(res, "94538.1346457028")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 186 187 free(res); 188 189 // We want to check that numbers are properly extended... 190 e = bcl_num_setScale(n4, 20); 191 err(e); 192 193 res = bcl_string(bcl_dup(n4)); 194 195 if (strcmp(res, "94538.13464570280000000000")) 196 err(BCL_ERROR_FATAL_UNKNOWN_ERR); 197 198 free(res); 199 200 // ...and truncated. 201 e = bcl_num_setScale(n4, 0); 202 err(e); 203 204 res = bcl_string(bcl_dup(n4)); 205 206 if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 207 208 free(res); 209 210 // Check conversion to hardware integers... 211 e = bcl_bigdig(n4, &b); 212 err(e); 213 214 if (b != 94538) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 215 216 // ...and back. 217 n4 = bcl_bigdig2num(b); 218 err(bcl_err(n4)); 219 220 res = bcl_string(bcl_dup(n4)); 221 222 if (strcmp(res, "94538")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 223 224 free(res); 225 226 // Check rand. 227 n4 = bcl_frand(10); 228 err(bcl_err(n4)); 229 230 // Check that no asserts fire in shifting. 231 n4 = bcl_lshift(n4, bcl_bigdig2num(10)); 232 err(bcl_err(n4)); 233 234 // Repeat. 235 n3 = bcl_irand(n4); 236 err(bcl_err(n3)); 237 238 // Repeat. 239 n2 = bcl_ifrand_keep(n3, 10); 240 err(bcl_err(n2)); 241 242 // Repeat. 243 n2 = bcl_ifrand(bcl_dup(n3), 10); 244 err(bcl_err(n2)); 245 246 // Still checking asserts. 247 e = bcl_rand_seedWithNum_keep(n3); 248 err(e); 249 250 // Still checking asserts. 251 e = bcl_rand_seedWithNum(n3); 252 err(e); 253 254 // Still checking asserts. 255 n4 = bcl_rand_seed2num(); 256 err(bcl_err(n4)); 257 258 // Finally, check modexp, yet another special case. 259 n5 = bcl_parse("10"); 260 err(bcl_err(n5)); 261 262 n6 = bcl_modexp_keep(n5, n5, n5); 263 err(bcl_err(n6)); 264 265 n7 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5)); 266 err(bcl_err(n7)); 267 268 // Clean up. 269 bcl_num_free(n); 270 271 // Test leading zeroes. 272 if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 273 274 n = bcl_parse("0.01"); 275 err(bcl_err(n)); 276 277 n2 = bcl_parse("-0.01"); 278 err(bcl_err(n2)); 279 280 n3 = bcl_parse("1.01"); 281 err(bcl_err(n3)); 282 283 n4 = bcl_parse("-1.01"); 284 err(bcl_err(n4)); 285 286 res = bcl_string_keep(n); 287 if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 288 289 free(res); 290 291 res = bcl_string(bcl_dup(n)); 292 if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 293 294 free(res); 295 296 res = bcl_string(bcl_dup(n2)); 297 if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 298 299 free(res); 300 301 res = bcl_string(bcl_dup(n3)); 302 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 303 304 free(res); 305 306 res = bcl_string(bcl_dup(n4)); 307 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 308 309 free(res); 310 311 bcl_setLeadingZeroes(true); 312 313 if (!bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 314 315 res = bcl_string(bcl_dup(n)); 316 if (strcmp(res, "0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 317 318 free(res); 319 320 res = bcl_string(bcl_dup(n2)); 321 if (strcmp(res, "-0.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 322 323 free(res); 324 325 res = bcl_string(bcl_dup(n3)); 326 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 327 328 free(res); 329 330 res = bcl_string(bcl_dup(n4)); 331 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 332 333 free(res); 334 335 bcl_setLeadingZeroes(false); 336 337 if (bcl_leadingZeroes()) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 338 339 res = bcl_string(n); 340 if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 341 342 free(res); 343 344 res = bcl_string(n2); 345 if (strcmp(res, "-.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 346 347 free(res); 348 349 res = bcl_string(n3); 350 if (strcmp(res, "1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 351 352 free(res); 353 354 res = bcl_string(n4); 355 if (strcmp(res, "-1.01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR); 356 357 free(res); 358 359 bcl_ctxt_freeNums(ctxt); 360 361 bcl_gc(); 362 363 // We need to pop both contexts and free them. 364 bcl_popContext(); 365 366 bcl_ctxt_free(ctxt); 367 368 ctxt = bcl_context(); 369 370 bcl_popContext(); 371 372 bcl_ctxt_free(ctxt); 373 374 // Decrement the reference counter to ensure all is freed. 375 bcl_free(); 376 377 bcl_free(); 378 379 bcl_end(); 380 381 return 0; 382 } 383