xref: /freebsd/contrib/bc/src/library.c (revision 2faf504d1ab821fe2b9df9d2afb49bb35e1334f4)
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  * The public functions for libbc.
33  *
34  */
35 
36 #if BC_ENABLE_LIBRARY
37 
38 #include <setjmp.h>
39 #include <string.h>
40 #include <time.h>
41 
42 #include <bcl.h>
43 
44 #include <library.h>
45 #include <num.h>
46 #include <vm.h>
47 
48 // The asserts in this file are important to testing; in many cases, the test
49 // would not work without the asserts, so don't remove them without reason.
50 //
51 // Also, there are many uses of bc_num_clear() here; that is because numbers are
52 // being reused, and a clean slate is required.
53 //
54 // Also, there are a bunch of BC_UNSETJMP and BC_SETJMP_LOCKED() between calls
55 // to bc_num_init(). That is because locals are being initialized, and unlike bc
56 // proper, this code cannot assume that allocation failures are fatal. So we
57 // have to reset the jumps every time to ensure that the locals will be correct
58 // after jumping.
59 
60 void bcl_handleSignal(void) {
61 
62 	// Signal already in flight, or bc is not executing.
63 	if (vm.sig || !vm.running) return;
64 
65 	vm.sig = 1;
66 
67 	assert(vm.jmp_bufs.len);
68 
69 	if (!vm.sig_lock) BC_JMP;
70 }
71 
72 bool bcl_running(void) {
73 	return vm.running != 0;
74 }
75 
76 BclError bcl_init(void) {
77 
78 	BclError e = BCL_ERROR_NONE;
79 
80 	vm.refs += 1;
81 
82 	if (vm.refs > 1) return e;
83 
84 	// Setting these to NULL ensures that if an error occurs, we only free what
85 	// is necessary.
86 	vm.ctxts.v = NULL;
87 	vm.jmp_bufs.v = NULL;
88 	vm.out.v = NULL;
89 
90 	vm.abrt = false;
91 
92 	BC_SIG_LOCK;
93 
94 	// The jmp_bufs always has to be initialized first.
95 	bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
96 
97 	BC_FUNC_HEADER_INIT(err);
98 
99 	bc_vm_init();
100 
101 	bc_vec_init(&vm.ctxts, sizeof(BclContext), BC_DTOR_NONE);
102 	bc_vec_init(&vm.out, sizeof(uchar), BC_DTOR_NONE);
103 
104 	// We need to seed this in case /dev/random and /dev/urandm don't work.
105 	srand((unsigned int) time(NULL));
106 	bc_rand_init(&vm.rng);
107 
108 err:
109 	// This is why we had to set them to NULL.
110 	if (BC_ERR(vm.err)) {
111 		if (vm.out.v != NULL) bc_vec_free(&vm.out);
112 		if (vm.jmp_bufs.v != NULL) bc_vec_free(&vm.jmp_bufs);
113 		if (vm.ctxts.v != NULL) bc_vec_free(&vm.ctxts);
114 	}
115 
116 	BC_FUNC_FOOTER_UNLOCK(e);
117 
118 	assert(!vm.running && !vm.sig && !vm.sig_lock);
119 
120 	return e;
121 }
122 
123 BclError bcl_pushContext(BclContext ctxt) {
124 
125 	BclError e = BCL_ERROR_NONE;
126 
127 	BC_FUNC_HEADER_LOCK(err);
128 
129 	bc_vec_push(&vm.ctxts, &ctxt);
130 
131 err:
132 	BC_FUNC_FOOTER_UNLOCK(e);
133 	return e;
134 }
135 
136 void bcl_popContext(void) {
137 	if (vm.ctxts.len) bc_vec_pop(&vm.ctxts);
138 }
139 
140 BclContext bcl_context(void) {
141 	if (!vm.ctxts.len) return NULL;
142 	return *((BclContext*) bc_vec_top(&vm.ctxts));
143 }
144 
145 void bcl_free(void) {
146 
147 	size_t i;
148 
149 	vm.refs -= 1;
150 
151 	if (vm.refs) return;
152 
153 	BC_SIG_LOCK;
154 
155 	bc_rand_free(&vm.rng);
156 	bc_vec_free(&vm.out);
157 
158 	for (i = 0; i < vm.ctxts.len; ++i) {
159 		BclContext ctxt = *((BclContext*) bc_vec_item(&vm.ctxts, i));
160 		bcl_ctxt_free(ctxt);
161 	}
162 
163 	bc_vec_free(&vm.ctxts);
164 
165 	bc_vm_atexit();
166 
167 	BC_SIG_UNLOCK;
168 
169 	memset(&vm, 0, sizeof(BcVm));
170 
171 	assert(!vm.running && !vm.sig && !vm.sig_lock);
172 }
173 
174 void bcl_gc(void) {
175 	BC_SIG_LOCK;
176 	bc_vm_freeTemps();
177 	BC_SIG_UNLOCK;
178 }
179 
180 bool bcl_abortOnFatalError(void) {
181 	return vm.abrt;
182 }
183 
184 void bcl_setAbortOnFatalError(bool abrt) {
185 	vm.abrt = abrt;
186 }
187 
188 BclContext bcl_ctxt_create(void) {
189 
190 	BclContext ctxt = NULL;
191 
192 	BC_FUNC_HEADER_LOCK(err);
193 
194 	// We want the context to be free of any interference of other parties, so
195 	// malloc() is appropriate here.
196 	ctxt = bc_vm_malloc(sizeof(BclCtxt));
197 
198 	bc_vec_init(&ctxt->nums, sizeof(BcNum), BC_DTOR_BCL_NUM);
199 	bc_vec_init(&ctxt->free_nums, sizeof(BclNumber), BC_DTOR_NONE);
200 
201 	ctxt->scale = 0;
202 	ctxt->ibase = 10;
203 	ctxt->obase= 10;
204 
205 err:
206 	if (BC_ERR(vm.err && ctxt != NULL)) {
207 		if (ctxt->nums.v != NULL) bc_vec_free(&ctxt->nums);
208 		free(ctxt);
209 		ctxt = NULL;
210 	}
211 
212 	BC_FUNC_FOOTER_NO_ERR;
213 
214 	assert(!vm.running && !vm.sig && !vm.sig_lock);
215 
216 	return ctxt;
217 }
218 
219 void bcl_ctxt_free(BclContext ctxt) {
220 	BC_SIG_LOCK;
221 	bc_vec_free(&ctxt->free_nums);
222 	bc_vec_free(&ctxt->nums);
223 	free(ctxt);
224 	BC_SIG_UNLOCK;
225 }
226 
227 void bcl_ctxt_freeNums(BclContext ctxt) {
228 	bc_vec_popAll(&ctxt->nums);
229 	bc_vec_popAll(&ctxt->free_nums);
230 }
231 
232 size_t bcl_ctxt_scale(BclContext ctxt) {
233 	return ctxt->scale;
234 }
235 
236 void bcl_ctxt_setScale(BclContext ctxt, size_t scale) {
237 	ctxt->scale = scale;
238 }
239 
240 size_t bcl_ctxt_ibase(BclContext ctxt) {
241 	return ctxt->ibase;
242 }
243 
244 void bcl_ctxt_setIbase(BclContext ctxt, size_t ibase) {
245 	if (ibase < BC_NUM_MIN_BASE) ibase = BC_NUM_MIN_BASE;
246 	else if (ibase > BC_NUM_MAX_IBASE) ibase = BC_NUM_MAX_IBASE;
247 	ctxt->ibase = ibase;
248 }
249 
250 size_t bcl_ctxt_obase(BclContext ctxt) {
251 	return ctxt->obase;
252 }
253 
254 void bcl_ctxt_setObase(BclContext ctxt, size_t obase) {
255 	ctxt->obase = obase;
256 }
257 
258 BclError bcl_err(BclNumber n) {
259 
260 	BclContext ctxt;
261 
262 	BC_CHECK_CTXT_ERR(ctxt);
263 
264 	// Errors are encoded as (0 - error_code). If the index is in that range, it
265 	// is an encoded error.
266 	if (n.i >= ctxt->nums.len) {
267 		if (n.i > 0 - (size_t) BCL_ERROR_NELEMS) return (BclError) (0 - n.i);
268 		else return BCL_ERROR_INVALID_NUM;
269 	}
270 	else return BCL_ERROR_NONE;
271 }
272 
273 /**
274  * Inserts a BcNum into a context's list of numbers.
275  * @param ctxt  The context to insert into.
276  * @param n     The BcNum to insert.
277  * @return      The resulting BclNumber from the insert.
278  */
279 static BclNumber bcl_num_insert(BclContext ctxt, BcNum *restrict n) {
280 
281 	BclNumber idx;
282 
283 	// If there is a free spot...
284 	if (ctxt->free_nums.len) {
285 
286 		BcNum *ptr;
287 
288 		// Get the index of the free spot and remove it.
289 		idx = *((BclNumber*) bc_vec_top(&ctxt->free_nums));
290 		bc_vec_pop(&ctxt->free_nums);
291 
292 		// Copy the number into the spot.
293 		ptr = bc_vec_item(&ctxt->nums, idx.i);
294 		memcpy(ptr, n, sizeof(BcNum));
295 	}
296 	else {
297 		// Just push the number onto the vector.
298 		idx.i = ctxt->nums.len;
299 		bc_vec_push(&ctxt->nums, n);
300 	}
301 
302 	assert(!vm.running && !vm.sig && !vm.sig_lock);
303 
304 	return idx;
305 }
306 
307 BclNumber bcl_num_create(void) {
308 
309 	BclError e = BCL_ERROR_NONE;
310 	BcNum n;
311 	BclNumber idx;
312 	BclContext ctxt;
313 
314 	BC_CHECK_CTXT(ctxt);
315 
316 	BC_FUNC_HEADER_LOCK(err);
317 
318 	bc_vec_grow(&ctxt->nums, 1);
319 
320 	bc_num_init(&n, BC_NUM_DEF_SIZE);
321 
322 err:
323 	BC_FUNC_FOOTER_UNLOCK(e);
324 	BC_MAYBE_SETUP(ctxt, e, n, idx);
325 
326 	assert(!vm.running && !vm.sig && !vm.sig_lock);
327 
328 	return idx;
329 }
330 
331 /**
332  * Destructs a number and marks its spot as free.
333  * @param ctxt  The context.
334  * @param n     The index of the number.
335  * @param num   The number to destroy.
336  */
337 static void bcl_num_dtor(BclContext ctxt, BclNumber n, BcNum *restrict num) {
338 
339 	BC_SIG_ASSERT_LOCKED;
340 
341 	assert(num != NULL && num->num != NULL);
342 
343 	bcl_num_destruct(num);
344 	bc_vec_push(&ctxt->free_nums, &n);
345 }
346 
347 void bcl_num_free(BclNumber n) {
348 
349 	BcNum *num;
350 	BclContext ctxt;
351 
352 	BC_CHECK_CTXT_ASSERT(ctxt);
353 
354 	BC_SIG_LOCK;
355 
356 	assert(n.i < ctxt->nums.len);
357 
358 	num = BC_NUM(ctxt, n);
359 
360 	bcl_num_dtor(ctxt, n, num);
361 
362 	BC_SIG_UNLOCK;
363 }
364 
365 BclError bcl_copy(BclNumber d, BclNumber s) {
366 
367 	BclError e = BCL_ERROR_NONE;
368 	BcNum *dest, *src;
369 	BclContext ctxt;
370 
371 	BC_CHECK_CTXT_ERR(ctxt);
372 
373 	BC_FUNC_HEADER_LOCK(err);
374 
375 	assert(d.i < ctxt->nums.len && s.i < ctxt->nums.len);
376 
377 	dest = BC_NUM(ctxt, d);
378 	src = BC_NUM(ctxt, s);
379 
380 	assert(dest != NULL && src != NULL);
381 	assert(dest->num != NULL && src->num != NULL);
382 
383 	bc_num_copy(dest, src);
384 
385 err:
386 	BC_FUNC_FOOTER_UNLOCK(e);
387 
388 	assert(!vm.running && !vm.sig && !vm.sig_lock);
389 
390 	return e;
391 }
392 
393 BclNumber bcl_dup(BclNumber s) {
394 
395 	BclError e = BCL_ERROR_NONE;
396 	BcNum *src, dest;
397 	BclNumber idx;
398 	BclContext ctxt;
399 
400 	BC_CHECK_CTXT(ctxt);
401 
402 	BC_FUNC_HEADER_LOCK(err);
403 
404 	bc_vec_grow(&ctxt->nums, 1);
405 
406 	assert(s.i < ctxt->nums.len);
407 
408 	src = BC_NUM(ctxt, s);
409 
410 	assert(src != NULL && src->num != NULL);
411 
412 	// Copy the number.
413 	bc_num_clear(&dest);
414 	bc_num_createCopy(&dest, src);
415 
416 err:
417 	BC_FUNC_FOOTER_UNLOCK(e);
418 	BC_MAYBE_SETUP(ctxt, e, dest, idx);
419 
420 	assert(!vm.running && !vm.sig && !vm.sig_lock);
421 
422 	return idx;
423 }
424 
425 void bcl_num_destruct(void *num) {
426 
427 	BcNum *n = (BcNum*) num;
428 
429 	assert(n != NULL);
430 
431 	if (n->num == NULL) return;
432 
433 	bc_num_free(num);
434 	bc_num_clear(num);
435 }
436 
437 bool bcl_num_neg(BclNumber n) {
438 
439 	BcNum *num;
440 	BclContext ctxt;
441 
442 	BC_CHECK_CTXT_ASSERT(ctxt);
443 
444 	assert(n.i < ctxt->nums.len);
445 
446 	num = BC_NUM(ctxt, n);
447 
448 	assert(num != NULL && num->num != NULL);
449 
450 	return BC_NUM_NEG(num) != 0;
451 }
452 
453 void bcl_num_setNeg(BclNumber n, bool neg) {
454 
455 	BcNum *num;
456 	BclContext ctxt;
457 
458 	BC_CHECK_CTXT_ASSERT(ctxt);
459 
460 	assert(n.i < ctxt->nums.len);
461 
462 	num = BC_NUM(ctxt, n);
463 
464 	assert(num != NULL && num->num != NULL);
465 
466 	num->rdx = BC_NUM_NEG_VAL(num, neg);
467 }
468 
469 size_t bcl_num_scale(BclNumber n) {
470 
471 	BcNum *num;
472 	BclContext ctxt;
473 
474 	BC_CHECK_CTXT_ASSERT(ctxt);
475 
476 	assert(n.i < ctxt->nums.len);
477 
478 	num = BC_NUM(ctxt, n);
479 
480 	assert(num != NULL && num->num != NULL);
481 
482 	return bc_num_scale(num);
483 }
484 
485 BclError bcl_num_setScale(BclNumber n, size_t scale) {
486 
487 	BclError e = BCL_ERROR_NONE;
488 	BcNum *nptr;
489 	BclContext ctxt;
490 
491 	BC_CHECK_CTXT_ERR(ctxt);
492 
493 	BC_CHECK_NUM_ERR(ctxt, n);
494 
495 	BC_FUNC_HEADER(err);
496 
497 	assert(n.i < ctxt->nums.len);
498 
499 	nptr = BC_NUM(ctxt, n);
500 
501 	assert(nptr != NULL && nptr->num != NULL);
502 
503 	if (scale > nptr->scale) bc_num_extend(nptr, scale - nptr->scale);
504 	else if (scale < nptr->scale) bc_num_truncate(nptr, nptr->scale - scale);
505 
506 err:
507 	BC_SIG_MAYLOCK;
508 	BC_FUNC_FOOTER(e);
509 
510 	assert(!vm.running && !vm.sig && !vm.sig_lock);
511 
512 	return e;
513 }
514 
515 size_t bcl_num_len(BclNumber n) {
516 
517 	BcNum *num;
518 	BclContext ctxt;
519 
520 	BC_CHECK_CTXT_ASSERT(ctxt);
521 
522 	assert(n.i < ctxt->nums.len);
523 
524 	num = BC_NUM(ctxt, n);
525 
526 	assert(num != NULL && num->num != NULL);
527 
528 	return bc_num_len(num);
529 }
530 
531 BclError bcl_bigdig(BclNumber n, BclBigDig *result) {
532 
533 	BclError e = BCL_ERROR_NONE;
534 	BcNum *num;
535 	BclContext ctxt;
536 
537 	BC_CHECK_CTXT_ERR(ctxt);
538 
539 	BC_FUNC_HEADER_LOCK(err);
540 
541 	assert(n.i < ctxt->nums.len);
542 	assert(result != NULL);
543 
544 	num = BC_NUM(ctxt, n);
545 
546 	assert(num != NULL && num->num != NULL);
547 
548 	*result = bc_num_bigdig(num);
549 
550 err:
551 	bcl_num_dtor(ctxt, n, num);
552 	BC_FUNC_FOOTER_UNLOCK(e);
553 
554 	assert(!vm.running && !vm.sig && !vm.sig_lock);
555 
556 	return e;
557 }
558 
559 BclNumber bcl_bigdig2num(BclBigDig val) {
560 
561 	BclError e = BCL_ERROR_NONE;
562 	BcNum n;
563 	BclNumber idx;
564 	BclContext ctxt;
565 
566 	BC_CHECK_CTXT(ctxt);
567 
568 	BC_FUNC_HEADER_LOCK(err);
569 
570 	bc_vec_grow(&ctxt->nums, 1);
571 
572 	bc_num_createFromBigdig(&n, val);
573 
574 err:
575 	BC_FUNC_FOOTER_UNLOCK(e);
576 	BC_MAYBE_SETUP(ctxt, e, n, idx);
577 
578 	assert(!vm.running && !vm.sig && !vm.sig_lock);
579 
580 	return idx;
581 }
582 
583 /**
584  * Sets up and executes a binary operator operation.
585  * @param a     The first operand.
586  * @param b     The second operand.
587  * @param op    The operation.
588  * @param req   The function to get the size of the result for preallocation.
589  * @return      The result of the operation.
590  */
591 static BclNumber bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
592                             const BcNumBinaryOpReq req)
593 {
594 	BclError e = BCL_ERROR_NONE;
595 	BcNum *aptr, *bptr;
596 	BcNum c;
597 	BclNumber idx;
598 	BclContext ctxt;
599 
600 	BC_CHECK_CTXT(ctxt);
601 
602 	BC_CHECK_NUM(ctxt, a);
603 	BC_CHECK_NUM(ctxt, b);
604 
605 	BC_FUNC_HEADER_LOCK(err);
606 
607 	bc_vec_grow(&ctxt->nums, 1);
608 
609 	assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
610 
611 	aptr = BC_NUM(ctxt, a);
612 	bptr = BC_NUM(ctxt, b);
613 
614 	assert(aptr != NULL && bptr != NULL);
615 	assert(aptr->num != NULL && bptr->num != NULL);
616 
617 	// Clear and initialize the result.
618 	bc_num_clear(&c);
619 	bc_num_init(&c, req(aptr, bptr, ctxt->scale));
620 
621 	BC_SIG_UNLOCK;
622 
623 	op(aptr, bptr, &c, ctxt->scale);
624 
625 err:
626 
627 	BC_SIG_MAYLOCK;
628 
629 	// Eat the operands.
630 	bcl_num_dtor(ctxt, a, aptr);
631 	if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
632 
633 	BC_FUNC_FOOTER(e);
634 	BC_MAYBE_SETUP(ctxt, e, c, idx);
635 
636 	assert(!vm.running && !vm.sig && !vm.sig_lock);
637 
638 	return idx;
639 }
640 
641 BclNumber bcl_add(BclNumber a, BclNumber b) {
642 	return bcl_binary(a, b, bc_num_add, bc_num_addReq);
643 }
644 
645 BclNumber bcl_sub(BclNumber a, BclNumber b) {
646 	return bcl_binary(a, b, bc_num_sub, bc_num_addReq);
647 }
648 
649 BclNumber bcl_mul(BclNumber a, BclNumber b) {
650 	return bcl_binary(a, b, bc_num_mul, bc_num_mulReq);
651 }
652 
653 BclNumber bcl_div(BclNumber a, BclNumber b) {
654 	return bcl_binary(a, b, bc_num_div, bc_num_divReq);
655 }
656 
657 BclNumber bcl_mod(BclNumber a, BclNumber b) {
658 	return bcl_binary(a, b, bc_num_mod, bc_num_divReq);
659 }
660 
661 BclNumber bcl_pow(BclNumber a, BclNumber b) {
662 	return bcl_binary(a, b, bc_num_pow, bc_num_powReq);
663 }
664 
665 BclNumber bcl_lshift(BclNumber a, BclNumber b) {
666 	return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq);
667 }
668 
669 BclNumber bcl_rshift(BclNumber a, BclNumber b) {
670 	return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq);
671 }
672 
673 BclNumber bcl_sqrt(BclNumber a) {
674 
675 	BclError e = BCL_ERROR_NONE;
676 	BcNum *aptr;
677 	BcNum b;
678 	BclNumber idx;
679 	BclContext ctxt;
680 
681 	BC_CHECK_CTXT(ctxt);
682 
683 	BC_CHECK_NUM(ctxt, a);
684 
685 	BC_FUNC_HEADER(err);
686 
687 	bc_vec_grow(&ctxt->nums, 1);
688 
689 	assert(a.i < ctxt->nums.len);
690 
691 	aptr = BC_NUM(ctxt, a);
692 
693 	bc_num_sqrt(aptr, &b, ctxt->scale);
694 
695 err:
696 	BC_SIG_MAYLOCK;
697 	bcl_num_dtor(ctxt, a, aptr);
698 	BC_FUNC_FOOTER(e);
699 	BC_MAYBE_SETUP(ctxt, e, b, idx);
700 
701 	assert(!vm.running && !vm.sig && !vm.sig_lock);
702 
703 	return idx;
704 }
705 
706 BclError bcl_divmod(BclNumber a, BclNumber b, BclNumber *c, BclNumber *d) {
707 
708 	BclError e = BCL_ERROR_NONE;
709 	size_t req;
710 	BcNum *aptr, *bptr;
711 	BcNum cnum, dnum;
712 	BclContext ctxt;
713 
714 	BC_CHECK_CTXT_ERR(ctxt);
715 
716 	BC_CHECK_NUM_ERR(ctxt, a);
717 	BC_CHECK_NUM_ERR(ctxt, b);
718 
719 	BC_FUNC_HEADER_LOCK(err);
720 
721 	bc_vec_grow(&ctxt->nums, 2);
722 
723 	assert(c != NULL && d != NULL);
724 
725 	aptr = BC_NUM(ctxt, a);
726 	bptr = BC_NUM(ctxt, b);
727 
728 	assert(aptr != NULL && bptr != NULL);
729 	assert(aptr->num != NULL && bptr->num != NULL);
730 
731 	bc_num_clear(&cnum);
732 	bc_num_clear(&dnum);
733 
734 	req = bc_num_divReq(aptr, bptr, ctxt->scale);
735 
736 	// Initialize the numbers.
737 	bc_num_init(&cnum, req);
738 	BC_UNSETJMP;
739 	BC_SETJMP_LOCKED(err);
740 	bc_num_init(&dnum, req);
741 
742 	BC_SIG_UNLOCK;
743 
744 	bc_num_divmod(aptr, bptr, &cnum, &dnum, ctxt->scale);
745 
746 err:
747 	BC_SIG_MAYLOCK;
748 
749 	// Eat the operands.
750 	bcl_num_dtor(ctxt, a, aptr);
751 	if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
752 
753 	// If there was an error...
754 	if (BC_ERR(vm.err)) {
755 
756 		// Free the results.
757 		if (cnum.num != NULL) bc_num_free(&cnum);
758 		if (dnum.num != NULL) bc_num_free(&dnum);
759 
760 		// Make sure the return values are invalid.
761 		c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
762 		d->i = c->i;
763 
764 		BC_FUNC_FOOTER(e);
765 	}
766 	else {
767 
768 		BC_FUNC_FOOTER(e);
769 
770 		// Insert the results into the context.
771 		*c = bcl_num_insert(ctxt, &cnum);
772 		*d = bcl_num_insert(ctxt, &dnum);
773 	}
774 
775 	assert(!vm.running && !vm.sig && !vm.sig_lock);
776 
777 	return e;
778 }
779 
780 BclNumber bcl_modexp(BclNumber a, BclNumber b, BclNumber c) {
781 
782 	BclError e = BCL_ERROR_NONE;
783 	size_t req;
784 	BcNum *aptr, *bptr, *cptr;
785 	BcNum d;
786 	BclNumber idx;
787 	BclContext ctxt;
788 
789 	BC_CHECK_CTXT(ctxt);
790 
791 	BC_CHECK_NUM(ctxt, a);
792 	BC_CHECK_NUM(ctxt, b);
793 	BC_CHECK_NUM(ctxt, c);
794 
795 	BC_FUNC_HEADER_LOCK(err);
796 
797 	bc_vec_grow(&ctxt->nums, 1);
798 
799 	assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
800 	assert(c.i < ctxt->nums.len);
801 
802 	aptr = BC_NUM(ctxt, a);
803 	bptr = BC_NUM(ctxt, b);
804 	cptr = BC_NUM(ctxt, c);
805 
806 	assert(aptr != NULL && bptr != NULL && cptr != NULL);
807 	assert(aptr->num != NULL && bptr->num != NULL && cptr->num != NULL);
808 
809 	// Prepare the result.
810 	bc_num_clear(&d);
811 
812 	req = bc_num_divReq(aptr, cptr, 0);
813 
814 	// Initialize the result.
815 	bc_num_init(&d, req);
816 
817 	BC_SIG_UNLOCK;
818 
819 	bc_num_modexp(aptr, bptr, cptr, &d);
820 
821 err:
822 	BC_SIG_MAYLOCK;
823 
824 	// Eat the operands.
825 	bcl_num_dtor(ctxt, a, aptr);
826 	if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
827 	if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
828 
829 	BC_FUNC_FOOTER(e);
830 	BC_MAYBE_SETUP(ctxt, e, d, idx);
831 
832 	assert(!vm.running && !vm.sig && !vm.sig_lock);
833 
834 	return idx;
835 }
836 
837 ssize_t bcl_cmp(BclNumber a, BclNumber b) {
838 
839 	BcNum *aptr, *bptr;
840 	BclContext ctxt;
841 
842 	BC_CHECK_CTXT_ASSERT(ctxt);
843 
844 	assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
845 
846 	aptr = BC_NUM(ctxt, a);
847 	bptr = BC_NUM(ctxt, b);
848 
849 	assert(aptr != NULL && bptr != NULL);
850 	assert(aptr->num != NULL && bptr->num != NULL);
851 
852 	return bc_num_cmp(aptr, bptr);
853 }
854 
855 void bcl_zero(BclNumber n) {
856 
857 	BcNum *nptr;
858 	BclContext ctxt;
859 
860 	BC_CHECK_CTXT_ASSERT(ctxt);
861 
862 	assert(n.i < ctxt->nums.len);
863 
864 	nptr = BC_NUM(ctxt, n);
865 
866 	assert(nptr != NULL && nptr->num != NULL);
867 
868 	bc_num_zero(nptr);
869 }
870 
871 void bcl_one(BclNumber n) {
872 
873 	BcNum *nptr;
874 	BclContext ctxt;
875 
876 	BC_CHECK_CTXT_ASSERT(ctxt);
877 
878 	assert(n.i < ctxt->nums.len);
879 
880 	nptr = BC_NUM(ctxt, n);
881 
882 	assert(nptr != NULL && nptr->num != NULL);
883 
884 	bc_num_one(nptr);
885 }
886 
887 BclNumber bcl_parse(const char *restrict val) {
888 
889 	BclError e = BCL_ERROR_NONE;
890 	BcNum n;
891 	BclNumber idx;
892 	BclContext ctxt;
893 	bool neg;
894 
895 	BC_CHECK_CTXT(ctxt);
896 
897 	BC_FUNC_HEADER_LOCK(err);
898 
899 	bc_vec_grow(&ctxt->nums, 1);
900 
901 	assert(val != NULL);
902 
903 	// We have to take care of negative here because bc's number parsing does
904 	// not.
905 	neg = (val[0] == '-');
906 
907 	if (neg) val += 1;
908 
909 	if (!bc_num_strValid(val)) {
910 		vm.err = BCL_ERROR_PARSE_INVALID_STR;
911 		goto err;
912 	}
913 
914 	// Clear and initialize the number.
915 	bc_num_clear(&n);
916 	bc_num_init(&n, BC_NUM_DEF_SIZE);
917 
918 	BC_SIG_UNLOCK;
919 
920 	bc_num_parse(&n, val, (BcBigDig) ctxt->ibase);
921 
922 	// Set the negative.
923 	n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
924 
925 err:
926 	BC_SIG_MAYLOCK;
927 	BC_FUNC_FOOTER(e);
928 	BC_MAYBE_SETUP(ctxt, e, n, idx);
929 
930 	assert(!vm.running && !vm.sig && !vm.sig_lock);
931 
932 	return idx;
933 }
934 
935 char* bcl_string(BclNumber n) {
936 
937 	BcNum *nptr;
938 	char *str = NULL;
939 	BclContext ctxt;
940 
941 	BC_CHECK_CTXT_ASSERT(ctxt);
942 
943 	if (BC_ERR(n.i >= ctxt->nums.len)) return str;
944 
945 	BC_FUNC_HEADER(err);
946 
947 	assert(n.i < ctxt->nums.len);
948 
949 	nptr = BC_NUM(ctxt, n);
950 
951 	assert(nptr != NULL && nptr->num != NULL);
952 
953 	// Clear the buffer.
954 	bc_vec_popAll(&vm.out);
955 
956 	// Print to the buffer.
957 	bc_num_print(nptr, (BcBigDig) ctxt->obase, false);
958 	bc_vec_pushByte(&vm.out, '\0');
959 
960 	BC_SIG_LOCK;
961 
962 	// Just dup the string; the caller is responsible for it.
963 	str = bc_vm_strdup(vm.out.v);
964 
965 err:
966 
967 	// Eat the operand.
968 	bcl_num_dtor(ctxt, n, nptr);
969 
970 	BC_FUNC_FOOTER_NO_ERR;
971 
972 	assert(!vm.running && !vm.sig && !vm.sig_lock);
973 
974 	return str;
975 }
976 
977 BclNumber bcl_irand(BclNumber a) {
978 
979 	BclError e = BCL_ERROR_NONE;
980 	BcNum *aptr;
981 	BcNum b;
982 	BclNumber idx;
983 	BclContext ctxt;
984 
985 	BC_CHECK_CTXT(ctxt);
986 
987 	BC_CHECK_NUM(ctxt, a);
988 
989 	BC_FUNC_HEADER_LOCK(err);
990 
991 	bc_vec_grow(&ctxt->nums, 1);
992 
993 	assert(a.i < ctxt->nums.len);
994 
995 	aptr = BC_NUM(ctxt, a);
996 
997 	assert(aptr != NULL && aptr->num != NULL);
998 
999 	// Clear and initialize the result.
1000 	bc_num_clear(&b);
1001 	bc_num_init(&b, BC_NUM_DEF_SIZE);
1002 
1003 	BC_SIG_UNLOCK;
1004 
1005 	bc_num_irand(aptr, &b, &vm.rng);
1006 
1007 err:
1008 	BC_SIG_MAYLOCK;
1009 
1010 	// Eat the operand.
1011 	bcl_num_dtor(ctxt, a, aptr);
1012 
1013 	BC_FUNC_FOOTER(e);
1014 	BC_MAYBE_SETUP(ctxt, e, b, idx);
1015 
1016 	assert(!vm.running && !vm.sig && !vm.sig_lock);
1017 
1018 	return idx;
1019 }
1020 
1021 /**
1022  * Helps bcl_frand(). This is separate because the error handling is easier that
1023  * way. It is also easier to do ifrand that way.
1024  * @param b       The return parameter.
1025  * @param places  The number of decimal places to generate.
1026  */
1027 static void bcl_frandHelper(BcNum *restrict b, size_t places) {
1028 
1029 	BcNum exp, pow, ten;
1030 	BcDig exp_digs[BC_NUM_BIGDIG_LOG10];
1031 	BcDig ten_digs[BC_NUM_BIGDIG_LOG10];
1032 
1033 	// Set up temporaries.
1034 	bc_num_setup(&exp, exp_digs, BC_NUM_BIGDIG_LOG10);
1035 	bc_num_setup(&ten, ten_digs, BC_NUM_BIGDIG_LOG10);
1036 
1037 	ten.num[0] = 10;
1038 	ten.len = 1;
1039 
1040 	bc_num_bigdig2num(&exp, (BcBigDig) places);
1041 
1042 	// Clear the temporary that might need to grow.
1043 	bc_num_clear(&pow);
1044 
1045 	BC_SIG_LOCK;
1046 
1047 	// Initialize the temporary that might need to grow.
1048 	bc_num_init(&pow, bc_num_powReq(&ten, &exp, 0));
1049 
1050 	BC_SETJMP_LOCKED(err);
1051 
1052 	BC_SIG_UNLOCK;
1053 
1054 	// Generate the number.
1055 	bc_num_pow(&ten, &exp, &pow, 0);
1056 	bc_num_irand(&pow, b, &vm.rng);
1057 
1058 	// Make the number entirely fraction.
1059 	bc_num_shiftRight(b, places);
1060 
1061 err:
1062 	BC_SIG_MAYLOCK;
1063 	bc_num_free(&pow);
1064 	BC_LONGJMP_CONT;
1065 }
1066 
1067 BclNumber bcl_frand(size_t places) {
1068 
1069 	BclError e = BCL_ERROR_NONE;
1070 	BcNum n;
1071 	BclNumber idx;
1072 	BclContext ctxt;
1073 
1074 	BC_CHECK_CTXT(ctxt);
1075 
1076 	BC_FUNC_HEADER_LOCK(err);
1077 
1078 	bc_vec_grow(&ctxt->nums, 1);
1079 
1080 	// Clear and initialize the number.
1081 	bc_num_clear(&n);
1082 	bc_num_init(&n, BC_NUM_DEF_SIZE);
1083 
1084 	BC_SIG_UNLOCK;
1085 
1086 	bcl_frandHelper(&n, places);
1087 
1088 err:
1089 	BC_SIG_MAYLOCK;
1090 
1091 	BC_FUNC_FOOTER(e);
1092 	BC_MAYBE_SETUP(ctxt, e, n, idx);
1093 
1094 	assert(!vm.running && !vm.sig && !vm.sig_lock);
1095 
1096 	return idx;
1097 }
1098 
1099 /**
1100  * Helps bc_ifrand(). This is separate because error handling is easier that
1101  * way.
1102  * @param a       The limit for bc_num_irand().
1103  * @param b       The return parameter.
1104  * @param places  The number of decimal places to generate.
1105  */
1106 static void bcl_ifrandHelper(BcNum *restrict a, BcNum *restrict b,
1107                              size_t places)
1108 {
1109 	BcNum ir, fr;
1110 
1111 	// Clear the integer and fractional numbers.
1112 	bc_num_clear(&ir);
1113 	bc_num_clear(&fr);
1114 
1115 	BC_SIG_LOCK;
1116 
1117 	// Initialize the integer and fractional numbers.
1118 	bc_num_init(&ir, BC_NUM_DEF_SIZE);
1119 	bc_num_init(&fr, BC_NUM_DEF_SIZE);
1120 
1121 	BC_SETJMP_LOCKED(err);
1122 
1123 	BC_SIG_UNLOCK;
1124 
1125 	bc_num_irand(a, &ir, &vm.rng);
1126 	bcl_frandHelper(&fr, places);
1127 
1128 	bc_num_add(&ir, &fr, b, 0);
1129 
1130 err:
1131 	BC_SIG_MAYLOCK;
1132 	bc_num_free(&fr);
1133 	bc_num_free(&ir);
1134 	BC_LONGJMP_CONT;
1135 }
1136 
1137 BclNumber bcl_ifrand(BclNumber a, size_t places) {
1138 
1139 	BclError e = BCL_ERROR_NONE;
1140 	BcNum *aptr;
1141 	BcNum b;
1142 	BclNumber idx;
1143 	BclContext ctxt;
1144 
1145 	BC_CHECK_CTXT(ctxt);
1146 	BC_CHECK_NUM(ctxt, a);
1147 
1148 	BC_FUNC_HEADER_LOCK(err);
1149 
1150 	bc_vec_grow(&ctxt->nums, 1);
1151 
1152 	assert(a.i < ctxt->nums.len);
1153 
1154 	aptr = BC_NUM(ctxt, a);
1155 
1156 	assert(aptr != NULL && aptr->num != NULL);
1157 
1158 	// Clear and initialize the number.
1159 	bc_num_clear(&b);
1160 	bc_num_init(&b, BC_NUM_DEF_SIZE);
1161 
1162 	BC_SIG_UNLOCK;
1163 
1164 	bcl_ifrandHelper(aptr, &b, places);
1165 
1166 err:
1167 	BC_SIG_MAYLOCK;
1168 
1169 	// Eat the oprand.
1170 	bcl_num_dtor(ctxt, a, aptr);
1171 
1172 	BC_FUNC_FOOTER(e);
1173 	BC_MAYBE_SETUP(ctxt, e, b, idx);
1174 
1175 	assert(!vm.running && !vm.sig && !vm.sig_lock);
1176 
1177 	return idx;
1178 }
1179 
1180 BclError bcl_rand_seedWithNum(BclNumber n) {
1181 
1182 	BclError e = BCL_ERROR_NONE;
1183 	BcNum *nptr;
1184 	BclContext ctxt;
1185 
1186 	BC_CHECK_CTXT_ERR(ctxt);
1187 	BC_CHECK_NUM_ERR(ctxt, n);
1188 
1189 	BC_FUNC_HEADER(err);
1190 
1191 	assert(n.i < ctxt->nums.len);
1192 
1193 	nptr = BC_NUM(ctxt, n);
1194 
1195 	assert(nptr != NULL && nptr->num != NULL);
1196 
1197 	bc_num_rng(nptr, &vm.rng);
1198 
1199 err:
1200 	BC_SIG_MAYLOCK;
1201 	BC_FUNC_FOOTER(e);
1202 
1203 	assert(!vm.running && !vm.sig && !vm.sig_lock);
1204 
1205 	return e;
1206 }
1207 
1208 BclError bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE]) {
1209 
1210 	BclError e = BCL_ERROR_NONE;
1211 	size_t i;
1212 	ulong vals[BCL_SEED_ULONGS];
1213 
1214 	BC_FUNC_HEADER(err);
1215 
1216 	// Fill the array.
1217 	for (i = 0; i < BCL_SEED_SIZE; ++i) {
1218 		ulong val = ((ulong) seed[i]) << (((ulong) CHAR_BIT) *
1219 		                                  (i % sizeof(ulong)));
1220 		vals[i / sizeof(long)] |= val;
1221 	}
1222 
1223 	bc_rand_seed(&vm.rng, vals[0], vals[1], vals[2], vals[3]);
1224 
1225 err:
1226 	BC_SIG_MAYLOCK;
1227 	BC_FUNC_FOOTER(e);
1228 	return e;
1229 }
1230 
1231 void bcl_rand_reseed(void) {
1232 	bc_rand_srand(bc_vec_top(&vm.rng.v));
1233 }
1234 
1235 BclNumber bcl_rand_seed2num(void) {
1236 
1237 	BclError e = BCL_ERROR_NONE;
1238 	BcNum n;
1239 	BclNumber idx;
1240 	BclContext ctxt;
1241 
1242 	BC_CHECK_CTXT(ctxt);
1243 
1244 	BC_FUNC_HEADER_LOCK(err);
1245 
1246 	// Clear and initialize the number.
1247 	bc_num_clear(&n);
1248 	bc_num_init(&n, BC_NUM_DEF_SIZE);
1249 
1250 	BC_SIG_UNLOCK;
1251 
1252 	bc_num_createFromRNG(&n, &vm.rng);
1253 
1254 err:
1255 	BC_SIG_MAYLOCK;
1256 	BC_FUNC_FOOTER(e);
1257 	BC_MAYBE_SETUP(ctxt, e, n, idx);
1258 
1259 	assert(!vm.running && !vm.sig && !vm.sig_lock);
1260 
1261 	return idx;
1262 }
1263 
1264 BclRandInt bcl_rand_int(void) {
1265 	return (BclRandInt) bc_rand_int(&vm.rng);
1266 }
1267 
1268 BclRandInt bcl_rand_bounded(BclRandInt bound) {
1269 	if (bound <= 1) return 0;
1270 	return (BclRandInt) bc_rand_bounded(&vm.rng, (BcRand) bound);
1271 }
1272 
1273 #endif // BC_ENABLE_LIBRARY
1274