2 * *****************************************************************************
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2020 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 * *****************************************************************************
32 * The public functions for libbc.
48 static void bcl_num_destruct(void *num);
50 void bcl_handleSignal(void) {
52 // Signal already in flight, or bc is not executing.
53 if (vm.sig || !vm.running) return;
57 assert(vm.jmp_bufs.len);
59 if (!vm.sig_lock) BC_VM_JMP;
62 bool bcl_running(void) {
63 return vm.running != 0;
66 BclError bcl_init(void) {
68 BclError e = BCL_ERROR_NONE;
72 if (vm.refs > 1) return e;
82 bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), NULL);
84 BC_FUNC_HEADER_INIT(err);
88 bc_vec_init(&vm.ctxts, sizeof(BclContext), NULL);
89 bc_vec_init(&vm.out, sizeof(uchar), NULL);
91 srand((unsigned int) time(NULL));
92 bc_rand_init(&vm.rng);
96 if (vm.out.v != NULL) bc_vec_free(&vm.out);
97 if (vm.jmp_bufs.v != NULL) bc_vec_free(&vm.jmp_bufs);
98 if (vm.ctxts.v != NULL) bc_vec_free(&vm.ctxts);
101 BC_FUNC_FOOTER_UNLOCK(e);
103 assert(!vm.running && !vm.sig && !vm.sig_lock);
108 BclError bcl_pushContext(BclContext ctxt) {
110 BclError e = BCL_ERROR_NONE;
112 BC_FUNC_HEADER_LOCK(err);
114 bc_vec_push(&vm.ctxts, &ctxt);
117 BC_FUNC_FOOTER_UNLOCK(e);
121 void bcl_popContext(void) {
122 if (vm.ctxts.len) bc_vec_pop(&vm.ctxts);
125 BclContext bcl_context(void) {
126 if (!vm.ctxts.len) return NULL;
127 return *((BclContext*) bc_vec_top(&vm.ctxts));
130 void bcl_free(void) {
139 bc_rand_free(&vm.rng);
140 bc_vec_free(&vm.out);
145 for (i = 0; i < vm.ctxts.len; ++i) {
146 BclContext ctxt = *((BclContext*) bc_vec_item(&vm.ctxts, i));
151 bc_vec_free(&vm.ctxts);
156 bc_vec_free(&vm.jmp_bufs);
160 memset(&vm, 0, sizeof(BcVm));
162 assert(!vm.running && !vm.sig && !vm.sig_lock);
170 bool bcl_abortOnFatalError(void) {
174 void bcl_setAbortOnFatalError(bool abrt) {
178 BclContext bcl_ctxt_create(void) {
180 BclContext ctxt = NULL;
182 BC_FUNC_HEADER_LOCK(err);
184 ctxt = bc_vm_malloc(sizeof(BclCtxt));
186 bc_vec_init(&ctxt->nums, sizeof(BcNum), bcl_num_destruct);
187 bc_vec_init(&ctxt->free_nums, sizeof(BclNumber), NULL);
194 if (BC_ERR(vm.err && ctxt != NULL)) {
195 if (ctxt->nums.v != NULL) bc_vec_free(&ctxt->nums);
200 BC_FUNC_FOOTER_NO_ERR;
202 assert(!vm.running && !vm.sig && !vm.sig_lock);
207 void bcl_ctxt_free(BclContext ctxt) {
209 bc_vec_free(&ctxt->free_nums);
210 bc_vec_free(&ctxt->nums);
215 void bcl_ctxt_freeNums(BclContext ctxt) {
216 bc_vec_npop(&ctxt->nums, ctxt->nums.len);
217 bc_vec_npop(&ctxt->free_nums, ctxt->free_nums.len);
220 size_t bcl_ctxt_scale(BclContext ctxt) {
224 void bcl_ctxt_setScale(BclContext ctxt, size_t scale) {
228 size_t bcl_ctxt_ibase(BclContext ctxt) {
232 void bcl_ctxt_setIbase(BclContext ctxt, size_t ibase) {
233 if (ibase < BC_NUM_MIN_BASE) ibase = BC_NUM_MIN_BASE;
234 else if (ibase > BC_NUM_MAX_IBASE) ibase = BC_NUM_MAX_IBASE;
238 size_t bcl_ctxt_obase(BclContext ctxt) {
242 void bcl_ctxt_setObase(BclContext ctxt, size_t obase) {
246 BclError bcl_err(BclNumber n) {
250 BC_CHECK_CTXT_ERR(ctxt);
252 if (n.i >= ctxt->nums.len) {
253 if (n.i > 0 - (size_t) BCL_ERROR_NELEMS) return (BclError) (0 - n.i);
254 else return BCL_ERROR_INVALID_NUM;
256 else return BCL_ERROR_NONE;
259 static BclNumber bcl_num_insert(BclContext ctxt, BcNum *restrict n) {
263 if (ctxt->free_nums.len) {
267 idx = *((BclNumber*) bc_vec_top(&ctxt->free_nums));
269 bc_vec_pop(&ctxt->free_nums);
271 ptr = bc_vec_item(&ctxt->nums, idx.i);
272 memcpy(ptr, n, sizeof(BcNum));
275 idx.i = ctxt->nums.len;
276 bc_vec_push(&ctxt->nums, n);
279 assert(!vm.running && !vm.sig && !vm.sig_lock);
284 BclNumber bcl_num_create(void) {
286 BclError e = BCL_ERROR_NONE;
293 BC_FUNC_HEADER_LOCK(err);
295 bc_vec_grow(&ctxt->nums, 1);
297 bc_num_init(&n, BC_NUM_DEF_SIZE);
300 BC_FUNC_FOOTER_UNLOCK(e);
301 BC_MAYBE_SETUP(ctxt, e, n, idx);
303 assert(!vm.running && !vm.sig && !vm.sig_lock);
308 static void bcl_num_dtor(BclContext ctxt, BclNumber n, BcNum *restrict num) {
310 BC_SIG_ASSERT_LOCKED;
312 assert(num != NULL && num->num != NULL);
314 bcl_num_destruct(num);
315 bc_vec_push(&ctxt->free_nums, &n);
318 void bcl_num_free(BclNumber n) {
323 BC_CHECK_CTXT_ASSERT(ctxt);
327 assert(n.i < ctxt->nums.len);
329 num = BC_NUM(ctxt, n);
331 bcl_num_dtor(ctxt, n, num);
336 BclError bcl_copy(BclNumber d, BclNumber s) {
338 BclError e = BCL_ERROR_NONE;
342 BC_CHECK_CTXT_ERR(ctxt);
344 BC_FUNC_HEADER_LOCK(err);
346 assert(d.i < ctxt->nums.len && s.i < ctxt->nums.len);
348 dest = BC_NUM(ctxt, d);
349 src = BC_NUM(ctxt, s);
351 assert(dest != NULL && src != NULL);
352 assert(dest->num != NULL && src->num != NULL);
354 bc_num_copy(dest, src);
357 BC_FUNC_FOOTER_UNLOCK(e);
359 assert(!vm.running && !vm.sig && !vm.sig_lock);
364 BclNumber bcl_dup(BclNumber s) {
366 BclError e = BCL_ERROR_NONE;
373 BC_FUNC_HEADER_LOCK(err);
375 bc_vec_grow(&ctxt->nums, 1);
377 assert(s.i < ctxt->nums.len);
379 src = BC_NUM(ctxt, s);
381 assert(src != NULL && src->num != NULL);
385 bc_num_createCopy(&dest, src);
388 BC_FUNC_FOOTER_UNLOCK(e);
389 BC_MAYBE_SETUP(ctxt, e, dest, idx);
391 assert(!vm.running && !vm.sig && !vm.sig_lock);
396 static void bcl_num_destruct(void *num) {
398 BcNum *n = (BcNum*) num;
402 if (n->num == NULL) return;
408 bool bcl_num_neg(BclNumber n) {
413 BC_CHECK_CTXT_ASSERT(ctxt);
415 assert(n.i < ctxt->nums.len);
417 num = BC_NUM(ctxt, n);
419 assert(num != NULL && num->num != NULL);
421 return BC_NUM_NEG(num) != 0;
424 void bcl_num_setNeg(BclNumber n, bool neg) {
429 BC_CHECK_CTXT_ASSERT(ctxt);
431 assert(n.i < ctxt->nums.len);
433 num = BC_NUM(ctxt, n);
435 assert(num != NULL && num->num != NULL);
437 num->rdx = BC_NUM_NEG_VAL(num, neg);
440 size_t bcl_num_scale(BclNumber n) {
445 BC_CHECK_CTXT_ASSERT(ctxt);
447 assert(n.i < ctxt->nums.len);
449 num = BC_NUM(ctxt, n);
451 assert(num != NULL && num->num != NULL);
453 return bc_num_scale(num);
456 BclError bcl_num_setScale(BclNumber n, size_t scale) {
458 BclError e = BCL_ERROR_NONE;
462 BC_CHECK_CTXT_ERR(ctxt);
464 BC_CHECK_NUM_ERR(ctxt, n);
468 assert(n.i < ctxt->nums.len);
470 nptr = BC_NUM(ctxt, n);
472 assert(nptr != NULL && nptr->num != NULL);
474 if (scale > nptr->scale) bc_num_extend(nptr, scale - nptr->scale);
475 else if (scale < nptr->scale) bc_num_truncate(nptr, nptr->scale - scale);
481 assert(!vm.running && !vm.sig && !vm.sig_lock);
486 size_t bcl_num_len(BclNumber n) {
491 BC_CHECK_CTXT_ASSERT(ctxt);
493 assert(n.i < ctxt->nums.len);
495 num = BC_NUM(ctxt, n);
497 assert(num != NULL && num->num != NULL);
499 return bc_num_len(num);
502 BclError bcl_bigdig(BclNumber n, BclBigDig *result) {
504 BclError e = BCL_ERROR_NONE;
508 BC_CHECK_CTXT_ERR(ctxt);
510 BC_FUNC_HEADER_LOCK(err);
512 assert(n.i < ctxt->nums.len);
513 assert(result != NULL);
515 num = BC_NUM(ctxt, n);
517 assert(num != NULL && num->num != NULL);
519 bc_num_bigdig(num, result);
522 bcl_num_dtor(ctxt, n, num);
523 BC_FUNC_FOOTER_UNLOCK(e);
525 assert(!vm.running && !vm.sig && !vm.sig_lock);
530 BclNumber bcl_bigdig2num(BclBigDig val) {
532 BclError e = BCL_ERROR_NONE;
539 BC_FUNC_HEADER_LOCK(err);
541 bc_vec_grow(&ctxt->nums, 1);
543 bc_num_createFromBigdig(&n, val);
546 BC_FUNC_FOOTER_UNLOCK(e);
547 BC_MAYBE_SETUP(ctxt, e, n, idx);
549 assert(!vm.running && !vm.sig && !vm.sig_lock);
554 static BclNumber bcl_binary(BclNumber a, BclNumber b,
555 const BcNumBinaryOp op,
556 const BcNumBinaryOpReq req)
558 BclError e = BCL_ERROR_NONE;
566 BC_CHECK_NUM(ctxt, a);
567 BC_CHECK_NUM(ctxt, b);
569 BC_FUNC_HEADER_LOCK(err);
571 bc_vec_grow(&ctxt->nums, 1);
573 assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
575 aptr = BC_NUM(ctxt, a);
576 bptr = BC_NUM(ctxt, b);
578 assert(aptr != NULL && bptr != NULL);
579 assert(aptr->num != NULL && bptr->num != NULL);
583 bc_num_init(&c, req(aptr, bptr, ctxt->scale));
587 op(aptr, bptr, &c, ctxt->scale);
591 bcl_num_dtor(ctxt, a, aptr);
592 if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
594 BC_MAYBE_SETUP(ctxt, e, c, idx);
596 assert(!vm.running && !vm.sig && !vm.sig_lock);
601 BclNumber bcl_add(BclNumber a, BclNumber b) {
602 return bcl_binary(a, b, bc_num_add, bc_num_addReq);
605 BclNumber bcl_sub(BclNumber a, BclNumber b) {
606 return bcl_binary(a, b, bc_num_sub, bc_num_addReq);
609 BclNumber bcl_mul(BclNumber a, BclNumber b) {
610 return bcl_binary(a, b, bc_num_mul, bc_num_mulReq);
613 BclNumber bcl_div(BclNumber a, BclNumber b) {
614 return bcl_binary(a, b, bc_num_div, bc_num_divReq);
617 BclNumber bcl_mod(BclNumber a, BclNumber b) {
618 return bcl_binary(a, b, bc_num_mod, bc_num_divReq);
621 BclNumber bcl_pow(BclNumber a, BclNumber b) {
622 return bcl_binary(a, b, bc_num_pow, bc_num_powReq);
625 BclNumber bcl_lshift(BclNumber a, BclNumber b) {
626 return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq);
629 BclNumber bcl_rshift(BclNumber a, BclNumber b) {
630 return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq);
633 BclNumber bcl_sqrt(BclNumber a) {
635 BclError e = BCL_ERROR_NONE;
643 BC_CHECK_NUM(ctxt, a);
647 bc_vec_grow(&ctxt->nums, 1);
649 assert(a.i < ctxt->nums.len);
651 aptr = BC_NUM(ctxt, a);
653 bc_num_sqrt(aptr, &b, ctxt->scale);
657 bcl_num_dtor(ctxt, a, aptr);
659 BC_MAYBE_SETUP(ctxt, e, b, idx);
661 assert(!vm.running && !vm.sig && !vm.sig_lock);
666 BclError bcl_divmod(BclNumber a, BclNumber b, BclNumber *c, BclNumber *d) {
668 BclError e = BCL_ERROR_NONE;
674 BC_CHECK_CTXT_ERR(ctxt);
676 BC_CHECK_NUM_ERR(ctxt, a);
677 BC_CHECK_NUM_ERR(ctxt, b);
679 BC_FUNC_HEADER_LOCK(err);
681 bc_vec_grow(&ctxt->nums, 2);
683 assert(c != NULL && d != NULL);
685 aptr = BC_NUM(ctxt, a);
686 bptr = BC_NUM(ctxt, b);
688 assert(aptr != NULL && bptr != NULL);
689 assert(aptr->num != NULL && bptr->num != NULL);
694 req = bc_num_divReq(aptr, bptr, ctxt->scale);
696 bc_num_init(&cnum, req);
697 bc_num_init(&dnum, req);
701 bc_num_divmod(aptr, bptr, &cnum, &dnum, ctxt->scale);
706 bcl_num_dtor(ctxt, a, aptr);
707 if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
709 if (BC_ERR(vm.err)) {
710 if (cnum.num != NULL) bc_num_free(&cnum);
711 if (dnum.num != NULL) bc_num_free(&dnum);
712 c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
718 *c = bcl_num_insert(ctxt, &cnum);
719 *d = bcl_num_insert(ctxt, &dnum);
722 assert(!vm.running && !vm.sig && !vm.sig_lock);
727 BclNumber bcl_modexp(BclNumber a, BclNumber b, BclNumber c) {
729 BclError e = BCL_ERROR_NONE;
731 BcNum *aptr, *bptr, *cptr;
738 BC_CHECK_NUM(ctxt, a);
739 BC_CHECK_NUM(ctxt, b);
740 BC_CHECK_NUM(ctxt, c);
742 BC_FUNC_HEADER_LOCK(err);
744 bc_vec_grow(&ctxt->nums, 1);
746 assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
747 assert(c.i < ctxt->nums.len);
749 aptr = BC_NUM(ctxt, a);
750 bptr = BC_NUM(ctxt, b);
751 cptr = BC_NUM(ctxt, c);
753 assert(aptr != NULL && bptr != NULL && cptr != NULL);
754 assert(aptr->num != NULL && bptr->num != NULL && cptr->num != NULL);
758 req = bc_num_divReq(aptr, cptr, 0);
760 bc_num_init(&d, req);
764 bc_num_modexp(aptr, bptr, cptr, &d);
769 bcl_num_dtor(ctxt, a, aptr);
770 if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
771 if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
774 BC_MAYBE_SETUP(ctxt, e, d, idx);
776 assert(!vm.running && !vm.sig && !vm.sig_lock);
781 ssize_t bcl_cmp(BclNumber a, BclNumber b) {
786 BC_CHECK_CTXT_ASSERT(ctxt);
788 assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
790 aptr = BC_NUM(ctxt, a);
791 bptr = BC_NUM(ctxt, b);
793 assert(aptr != NULL && bptr != NULL);
794 assert(aptr->num != NULL && bptr->num != NULL);
796 return bc_num_cmp(aptr, bptr);
799 void bcl_zero(BclNumber n) {
804 BC_CHECK_CTXT_ASSERT(ctxt);
806 assert(n.i < ctxt->nums.len);
808 nptr = BC_NUM(ctxt, n);
810 assert(nptr != NULL && nptr->num != NULL);
815 void bcl_one(BclNumber n) {
820 BC_CHECK_CTXT_ASSERT(ctxt);
822 assert(n.i < ctxt->nums.len);
824 nptr = BC_NUM(ctxt, n);
826 assert(nptr != NULL && nptr->num != NULL);
831 BclNumber bcl_parse(const char *restrict val) {
833 BclError e = BCL_ERROR_NONE;
841 BC_FUNC_HEADER_LOCK(err);
843 bc_vec_grow(&ctxt->nums, 1);
847 neg = (val[0] == '-');
851 if (!bc_num_strValid(val)) {
852 vm.err = BCL_ERROR_PARSE_INVALID_STR;
858 bc_num_init(&n, BC_NUM_DEF_SIZE);
862 bc_num_parse(&n, val, (BcBigDig) ctxt->ibase);
864 n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
869 BC_MAYBE_SETUP(ctxt, e, n, idx);
871 assert(!vm.running && !vm.sig && !vm.sig_lock);
876 char* bcl_string(BclNumber n) {
882 BC_CHECK_CTXT_ASSERT(ctxt);
884 if (BC_ERR(n.i >= ctxt->nums.len)) return str;
888 assert(n.i < ctxt->nums.len);
890 nptr = BC_NUM(ctxt, n);
892 assert(nptr != NULL && nptr->num != NULL);
894 bc_vec_npop(&vm.out, vm.out.len);
896 bc_num_print(nptr, (BcBigDig) ctxt->obase, false);
897 bc_vec_pushByte(&vm.out, '\0');
900 str = bc_vm_strdup(vm.out.v);
903 bcl_num_dtor(ctxt, n, nptr);
905 BC_FUNC_FOOTER_NO_ERR;
907 assert(!vm.running && !vm.sig && !vm.sig_lock);
912 BclNumber bcl_irand(BclNumber a) {
914 BclError e = BCL_ERROR_NONE;
922 BC_CHECK_NUM(ctxt, a);
924 BC_FUNC_HEADER_LOCK(err);
926 bc_vec_grow(&ctxt->nums, 1);
928 assert(a.i < ctxt->nums.len);
930 aptr = BC_NUM(ctxt, a);
932 assert(aptr != NULL && aptr->num != NULL);
936 bc_num_init(&b, BC_NUM_DEF_SIZE);
940 bc_num_irand(aptr, &b, &vm.rng);
944 bcl_num_dtor(ctxt, a, aptr);
946 BC_MAYBE_SETUP(ctxt, e, b, idx);
948 assert(!vm.running && !vm.sig && !vm.sig_lock);
953 static void bcl_frandHelper(BcNum *restrict b, size_t places) {
956 BcDig exp_digs[BC_NUM_BIGDIG_LOG10];
957 BcDig ten_digs[BC_NUM_BIGDIG_LOG10];
959 bc_num_setup(&exp, exp_digs, BC_NUM_BIGDIG_LOG10);
960 bc_num_setup(&ten, ten_digs, BC_NUM_BIGDIG_LOG10);
965 bc_num_bigdig2num(&exp, (BcBigDig) places);
971 BC_SETJMP_LOCKED(err);
973 bc_num_init(&pow, bc_num_powReq(&ten, &exp, 0));
977 bc_num_pow(&ten, &exp, &pow, 0);
979 bc_num_irand(&pow, b, &vm.rng);
981 bc_num_shiftRight(b, places);
989 BclNumber bcl_frand(size_t places) {
991 BclError e = BCL_ERROR_NONE;
998 BC_FUNC_HEADER_LOCK(err);
1000 bc_vec_grow(&ctxt->nums, 1);
1004 bc_num_init(&n, BC_NUM_DEF_SIZE);
1008 bcl_frandHelper(&n, places);
1013 BC_MAYBE_SETUP(ctxt, e, n, idx);
1015 assert(!vm.running && !vm.sig && !vm.sig_lock);
1020 static void bcl_ifrandHelper(BcNum *restrict a, BcNum *restrict b,
1030 BC_SETJMP_LOCKED(err);
1032 bc_num_init(&ir, BC_NUM_DEF_SIZE);
1033 bc_num_init(&fr, BC_NUM_DEF_SIZE);
1037 bc_num_irand(a, &ir, &vm.rng);
1038 bcl_frandHelper(&fr, places);
1040 bc_num_add(&ir, &fr, b, 0);
1049 BclNumber bcl_ifrand(BclNumber a, size_t places) {
1051 BclError e = BCL_ERROR_NONE;
1057 BC_CHECK_CTXT(ctxt);
1059 BC_CHECK_NUM(ctxt, a);
1061 BC_FUNC_HEADER_LOCK(err);
1063 bc_vec_grow(&ctxt->nums, 1);
1065 assert(a.i < ctxt->nums.len);
1067 aptr = BC_NUM(ctxt, a);
1069 assert(aptr != NULL && aptr->num != NULL);
1073 bc_num_init(&b, BC_NUM_DEF_SIZE);
1077 bcl_ifrandHelper(aptr, &b, places);
1081 bcl_num_dtor(ctxt, a, aptr);
1083 BC_MAYBE_SETUP(ctxt, e, b, idx);
1085 assert(!vm.running && !vm.sig && !vm.sig_lock);
1090 BclError bcl_rand_seedWithNum(BclNumber n) {
1092 BclError e = BCL_ERROR_NONE;
1096 BC_CHECK_CTXT_ERR(ctxt);
1098 BC_CHECK_NUM_ERR(ctxt, n);
1100 BC_FUNC_HEADER(err);
1102 assert(n.i < ctxt->nums.len);
1104 nptr = BC_NUM(ctxt, n);
1106 assert(nptr != NULL && nptr->num != NULL);
1108 bc_num_rng(nptr, &vm.rng);
1114 assert(!vm.running && !vm.sig && !vm.sig_lock);
1119 BclError bcl_rand_seed(unsigned char seed[BC_SEED_SIZE]) {
1121 BclError e = BCL_ERROR_NONE;
1123 ulong vals[BC_SEED_ULONGS];
1125 BC_FUNC_HEADER(err);
1127 for (i = 0; i < BC_SEED_SIZE; ++i) {
1128 ulong val = ((ulong) seed[i]) << (((ulong) CHAR_BIT) *
1129 (i % sizeof(ulong)));
1130 vals[i / sizeof(long)] |= val;
1133 bc_rand_seed(&vm.rng, vals[0], vals[1], vals[2], vals[3]);
1141 void bcl_rand_reseed(void) {
1142 bc_rand_srand(bc_vec_top(&vm.rng.v));
1145 BclNumber bcl_rand_seed2num(void) {
1147 BclError e = BCL_ERROR_NONE;
1152 BC_CHECK_CTXT(ctxt);
1154 BC_FUNC_HEADER_LOCK(err);
1158 bc_num_init(&n, BC_NUM_DEF_SIZE);
1162 bc_num_createFromRNG(&n, &vm.rng);
1167 BC_MAYBE_SETUP(ctxt, e, n, idx);
1169 assert(!vm.running && !vm.sig && !vm.sig_lock);
1174 BclRandInt bcl_rand_int(void) {
1175 return (BclRandInt) bc_rand_int(&vm.rng);
1178 BclRandInt bcl_rand_bounded(BclRandInt bound) {
1179 if (bound <= 1) return 0;
1180 return (BclRandInt) bc_rand_bounded(&vm.rng, (BcRand) bound);
1183 #endif // BC_ENABLE_LIBRARY