1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker *
4*5a6e8488SAndroid Build Coastguard Worker * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker *
6*5a6e8488SAndroid Build Coastguard Worker * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker *
8*5a6e8488SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker *
11*5a6e8488SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker *
14*5a6e8488SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker *
18*5a6e8488SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker *
30*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker *
32*5a6e8488SAndroid Build Coastguard Worker * The public functions for libbc.
33*5a6e8488SAndroid Build Coastguard Worker *
34*5a6e8488SAndroid Build Coastguard Worker */
35*5a6e8488SAndroid Build Coastguard Worker
36*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
37*5a6e8488SAndroid Build Coastguard Worker
38*5a6e8488SAndroid Build Coastguard Worker #include <setjmp.h>
39*5a6e8488SAndroid Build Coastguard Worker #include <string.h>
40*5a6e8488SAndroid Build Coastguard Worker #include <time.h>
41*5a6e8488SAndroid Build Coastguard Worker
42*5a6e8488SAndroid Build Coastguard Worker #include <bcl.h>
43*5a6e8488SAndroid Build Coastguard Worker
44*5a6e8488SAndroid Build Coastguard Worker #include <library.h>
45*5a6e8488SAndroid Build Coastguard Worker #include <num.h>
46*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
47*5a6e8488SAndroid Build Coastguard Worker
48*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
49*5a6e8488SAndroid Build Coastguard Worker #include <pthread.h>
50*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
51*5a6e8488SAndroid Build Coastguard Worker
52*5a6e8488SAndroid Build Coastguard Worker // The asserts in this file are important to testing; in many cases, the test
53*5a6e8488SAndroid Build Coastguard Worker // would not work without the asserts, so don't remove them without reason.
54*5a6e8488SAndroid Build Coastguard Worker //
55*5a6e8488SAndroid Build Coastguard Worker // Also, there are many uses of bc_num_clear() here; that is because numbers are
56*5a6e8488SAndroid Build Coastguard Worker // being reused, and a clean slate is required.
57*5a6e8488SAndroid Build Coastguard Worker //
58*5a6e8488SAndroid Build Coastguard Worker // Also, there are a bunch of BC_UNSETJMP between calls to bc_num_init(). That
59*5a6e8488SAndroid Build Coastguard Worker // is because locals are being initialized, and unlike bc proper, this code
60*5a6e8488SAndroid Build Coastguard Worker // cannot assume that allocation failures are fatal. So we have to reset the
61*5a6e8488SAndroid Build Coastguard Worker // jumps every time to ensure that the locals will be correct after jumping.
62*5a6e8488SAndroid Build Coastguard Worker
63*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
64*5a6e8488SAndroid Build Coastguard Worker
65*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
bcl_invalidGeneration(void)66*5a6e8488SAndroid Build Coastguard Worker bcl_invalidGeneration(void)
67*5a6e8488SAndroid Build Coastguard Worker {
68*5a6e8488SAndroid Build Coastguard Worker abort();
69*5a6e8488SAndroid Build Coastguard Worker }
70*5a6e8488SAndroid Build Coastguard Worker
71*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
bcl_nonexistentNum(void)72*5a6e8488SAndroid Build Coastguard Worker bcl_nonexistentNum(void)
73*5a6e8488SAndroid Build Coastguard Worker {
74*5a6e8488SAndroid Build Coastguard Worker abort();
75*5a6e8488SAndroid Build Coastguard Worker }
76*5a6e8488SAndroid Build Coastguard Worker
77*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
bcl_numIdxOutOfRange(void)78*5a6e8488SAndroid Build Coastguard Worker bcl_numIdxOutOfRange(void)
79*5a6e8488SAndroid Build Coastguard Worker {
80*5a6e8488SAndroid Build Coastguard Worker abort();
81*5a6e8488SAndroid Build Coastguard Worker }
82*5a6e8488SAndroid Build Coastguard Worker
83*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
84*5a6e8488SAndroid Build Coastguard Worker
85*5a6e8488SAndroid Build Coastguard Worker static BclTls* tls = NULL;
86*5a6e8488SAndroid Build Coastguard Worker static BclTls tls_real;
87*5a6e8488SAndroid Build Coastguard Worker
88*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_start(void)89*5a6e8488SAndroid Build Coastguard Worker bcl_start(void)
90*5a6e8488SAndroid Build Coastguard Worker {
91*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
92*5a6e8488SAndroid Build Coastguard Worker
93*5a6e8488SAndroid Build Coastguard Worker int r;
94*5a6e8488SAndroid Build Coastguard Worker
95*5a6e8488SAndroid Build Coastguard Worker if (tls != NULL) return BCL_ERROR_NONE;
96*5a6e8488SAndroid Build Coastguard Worker
97*5a6e8488SAndroid Build Coastguard Worker r = pthread_key_create(&tls_real, NULL);
98*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(r != 0)) return BCL_ERROR_FATAL_ALLOC_ERR;
99*5a6e8488SAndroid Build Coastguard Worker
100*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
101*5a6e8488SAndroid Build Coastguard Worker
102*5a6e8488SAndroid Build Coastguard Worker if (tls != NULL) return BCL_ERROR_NONE;
103*5a6e8488SAndroid Build Coastguard Worker
104*5a6e8488SAndroid Build Coastguard Worker tls_real = TlsAlloc();
105*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(tls_real == TLS_OUT_OF_INDEXES))
106*5a6e8488SAndroid Build Coastguard Worker {
107*5a6e8488SAndroid Build Coastguard Worker return BCL_ERROR_FATAL_ALLOC_ERR;
108*5a6e8488SAndroid Build Coastguard Worker }
109*5a6e8488SAndroid Build Coastguard Worker
110*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
111*5a6e8488SAndroid Build Coastguard Worker
112*5a6e8488SAndroid Build Coastguard Worker tls = &tls_real;
113*5a6e8488SAndroid Build Coastguard Worker
114*5a6e8488SAndroid Build Coastguard Worker return BCL_ERROR_NONE;
115*5a6e8488SAndroid Build Coastguard Worker }
116*5a6e8488SAndroid Build Coastguard Worker
117*5a6e8488SAndroid Build Coastguard Worker /**
118*5a6e8488SAndroid Build Coastguard Worker * Sets the thread-specific data for the thread.
119*5a6e8488SAndroid Build Coastguard Worker * @param vm The @a BcVm to set as the thread data.
120*5a6e8488SAndroid Build Coastguard Worker * @return An error code, if any.
121*5a6e8488SAndroid Build Coastguard Worker */
122*5a6e8488SAndroid Build Coastguard Worker static BclError
bcl_setspecific(BcVm * vm)123*5a6e8488SAndroid Build Coastguard Worker bcl_setspecific(BcVm* vm)
124*5a6e8488SAndroid Build Coastguard Worker {
125*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
126*5a6e8488SAndroid Build Coastguard Worker
127*5a6e8488SAndroid Build Coastguard Worker int r;
128*5a6e8488SAndroid Build Coastguard Worker
129*5a6e8488SAndroid Build Coastguard Worker assert(tls != NULL);
130*5a6e8488SAndroid Build Coastguard Worker
131*5a6e8488SAndroid Build Coastguard Worker r = pthread_setspecific(tls_real, vm);
132*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(r != 0)) return BCL_ERROR_FATAL_ALLOC_ERR;
133*5a6e8488SAndroid Build Coastguard Worker
134*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
135*5a6e8488SAndroid Build Coastguard Worker
136*5a6e8488SAndroid Build Coastguard Worker bool r;
137*5a6e8488SAndroid Build Coastguard Worker
138*5a6e8488SAndroid Build Coastguard Worker assert(tls != NULL);
139*5a6e8488SAndroid Build Coastguard Worker
140*5a6e8488SAndroid Build Coastguard Worker r = TlsSetValue(tls_real, vm);
141*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(!r)) return BCL_ERROR_FATAL_ALLOC_ERR;
142*5a6e8488SAndroid Build Coastguard Worker
143*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
144*5a6e8488SAndroid Build Coastguard Worker
145*5a6e8488SAndroid Build Coastguard Worker return BCL_ERROR_NONE;
146*5a6e8488SAndroid Build Coastguard Worker }
147*5a6e8488SAndroid Build Coastguard Worker
148*5a6e8488SAndroid Build Coastguard Worker BcVm*
bcl_getspecific(void)149*5a6e8488SAndroid Build Coastguard Worker bcl_getspecific(void)
150*5a6e8488SAndroid Build Coastguard Worker {
151*5a6e8488SAndroid Build Coastguard Worker BcVm* vm;
152*5a6e8488SAndroid Build Coastguard Worker
153*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
154*5a6e8488SAndroid Build Coastguard Worker
155*5a6e8488SAndroid Build Coastguard Worker vm = pthread_getspecific(tls_real);
156*5a6e8488SAndroid Build Coastguard Worker
157*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
158*5a6e8488SAndroid Build Coastguard Worker
159*5a6e8488SAndroid Build Coastguard Worker vm = TlsGetValue(tls_real);
160*5a6e8488SAndroid Build Coastguard Worker
161*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
162*5a6e8488SAndroid Build Coastguard Worker
163*5a6e8488SAndroid Build Coastguard Worker return vm;
164*5a6e8488SAndroid Build Coastguard Worker }
165*5a6e8488SAndroid Build Coastguard Worker
166*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_init(void)167*5a6e8488SAndroid Build Coastguard Worker bcl_init(void)
168*5a6e8488SAndroid Build Coastguard Worker {
169*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
170*5a6e8488SAndroid Build Coastguard Worker BcVm* vm;
171*5a6e8488SAndroid Build Coastguard Worker
172*5a6e8488SAndroid Build Coastguard Worker assert(tls != NULL);
173*5a6e8488SAndroid Build Coastguard Worker
174*5a6e8488SAndroid Build Coastguard Worker vm = bcl_getspecific();
175*5a6e8488SAndroid Build Coastguard Worker if (vm != NULL)
176*5a6e8488SAndroid Build Coastguard Worker {
177*5a6e8488SAndroid Build Coastguard Worker assert(vm->refs >= 1);
178*5a6e8488SAndroid Build Coastguard Worker
179*5a6e8488SAndroid Build Coastguard Worker vm->refs += 1;
180*5a6e8488SAndroid Build Coastguard Worker
181*5a6e8488SAndroid Build Coastguard Worker return e;
182*5a6e8488SAndroid Build Coastguard Worker }
183*5a6e8488SAndroid Build Coastguard Worker
184*5a6e8488SAndroid Build Coastguard Worker vm = bc_vm_malloc(sizeof(BcVm));
185*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(vm == NULL)) return BCL_ERROR_FATAL_ALLOC_ERR;
186*5a6e8488SAndroid Build Coastguard Worker
187*5a6e8488SAndroid Build Coastguard Worker e = bcl_setspecific(vm);
188*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(e != BCL_ERROR_NONE))
189*5a6e8488SAndroid Build Coastguard Worker {
190*5a6e8488SAndroid Build Coastguard Worker free(vm);
191*5a6e8488SAndroid Build Coastguard Worker return e;
192*5a6e8488SAndroid Build Coastguard Worker }
193*5a6e8488SAndroid Build Coastguard Worker
194*5a6e8488SAndroid Build Coastguard Worker memset(vm, 0, sizeof(BcVm));
195*5a6e8488SAndroid Build Coastguard Worker
196*5a6e8488SAndroid Build Coastguard Worker vm->refs += 1;
197*5a6e8488SAndroid Build Coastguard Worker
198*5a6e8488SAndroid Build Coastguard Worker assert(vm->refs == 1);
199*5a6e8488SAndroid Build Coastguard Worker
200*5a6e8488SAndroid Build Coastguard Worker // Setting these to NULL ensures that if an error occurs, we only free what
201*5a6e8488SAndroid Build Coastguard Worker // is necessary.
202*5a6e8488SAndroid Build Coastguard Worker vm->ctxts.v = NULL;
203*5a6e8488SAndroid Build Coastguard Worker vm->jmp_bufs.v = NULL;
204*5a6e8488SAndroid Build Coastguard Worker vm->out.v = NULL;
205*5a6e8488SAndroid Build Coastguard Worker
206*5a6e8488SAndroid Build Coastguard Worker vm->abrt = false;
207*5a6e8488SAndroid Build Coastguard Worker vm->leading_zeroes = false;
208*5a6e8488SAndroid Build Coastguard Worker vm->digit_clamp = true;
209*5a6e8488SAndroid Build Coastguard Worker
210*5a6e8488SAndroid Build Coastguard Worker // The jmp_bufs always has to be initialized first.
211*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&vm->jmp_bufs, sizeof(sigjmp_buf), BC_DTOR_NONE);
212*5a6e8488SAndroid Build Coastguard Worker
213*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
214*5a6e8488SAndroid Build Coastguard Worker
215*5a6e8488SAndroid Build Coastguard Worker bc_vm_init();
216*5a6e8488SAndroid Build Coastguard Worker
217*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&vm->ctxts, sizeof(BclContext), BC_DTOR_NONE);
218*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&vm->out, sizeof(uchar), BC_DTOR_NONE);
219*5a6e8488SAndroid Build Coastguard Worker
220*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
221*5a6e8488SAndroid Build Coastguard Worker
222*5a6e8488SAndroid Build Coastguard Worker // We need to seed this in case /dev/random and /dev/urandom don't work.
223*5a6e8488SAndroid Build Coastguard Worker srand((unsigned int) time(NULL));
224*5a6e8488SAndroid Build Coastguard Worker bc_rand_init(&vm->rng);
225*5a6e8488SAndroid Build Coastguard Worker
226*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
227*5a6e8488SAndroid Build Coastguard Worker
228*5a6e8488SAndroid Build Coastguard Worker err:
229*5a6e8488SAndroid Build Coastguard Worker
230*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
231*5a6e8488SAndroid Build Coastguard Worker
232*5a6e8488SAndroid Build Coastguard Worker // This is why we had to set them to NULL.
233*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(vm != NULL && vm->err))
234*5a6e8488SAndroid Build Coastguard Worker {
235*5a6e8488SAndroid Build Coastguard Worker if (vm->out.v != NULL) bc_vec_free(&vm->out);
236*5a6e8488SAndroid Build Coastguard Worker if (vm->jmp_bufs.v != NULL) bc_vec_free(&vm->jmp_bufs);
237*5a6e8488SAndroid Build Coastguard Worker if (vm->ctxts.v != NULL) bc_vec_free(&vm->ctxts);
238*5a6e8488SAndroid Build Coastguard Worker bcl_setspecific(NULL);
239*5a6e8488SAndroid Build Coastguard Worker free(vm);
240*5a6e8488SAndroid Build Coastguard Worker }
241*5a6e8488SAndroid Build Coastguard Worker
242*5a6e8488SAndroid Build Coastguard Worker return e;
243*5a6e8488SAndroid Build Coastguard Worker }
244*5a6e8488SAndroid Build Coastguard Worker
245*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_pushContext(BclContext ctxt)246*5a6e8488SAndroid Build Coastguard Worker bcl_pushContext(BclContext ctxt)
247*5a6e8488SAndroid Build Coastguard Worker {
248*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
249*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
250*5a6e8488SAndroid Build Coastguard Worker
251*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
252*5a6e8488SAndroid Build Coastguard Worker
253*5a6e8488SAndroid Build Coastguard Worker bc_vec_push(&vm->ctxts, &ctxt);
254*5a6e8488SAndroid Build Coastguard Worker
255*5a6e8488SAndroid Build Coastguard Worker err:
256*5a6e8488SAndroid Build Coastguard Worker
257*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
258*5a6e8488SAndroid Build Coastguard Worker return e;
259*5a6e8488SAndroid Build Coastguard Worker }
260*5a6e8488SAndroid Build Coastguard Worker
261*5a6e8488SAndroid Build Coastguard Worker void
bcl_popContext(void)262*5a6e8488SAndroid Build Coastguard Worker bcl_popContext(void)
263*5a6e8488SAndroid Build Coastguard Worker {
264*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
265*5a6e8488SAndroid Build Coastguard Worker
266*5a6e8488SAndroid Build Coastguard Worker if (vm->ctxts.len) bc_vec_pop(&vm->ctxts);
267*5a6e8488SAndroid Build Coastguard Worker }
268*5a6e8488SAndroid Build Coastguard Worker
269*5a6e8488SAndroid Build Coastguard Worker static BclContext
bcl_contextHelper(BcVm * vm)270*5a6e8488SAndroid Build Coastguard Worker bcl_contextHelper(BcVm* vm)
271*5a6e8488SAndroid Build Coastguard Worker {
272*5a6e8488SAndroid Build Coastguard Worker if (!vm->ctxts.len) return NULL;
273*5a6e8488SAndroid Build Coastguard Worker return *((BclContext*) bc_vec_top(&vm->ctxts));
274*5a6e8488SAndroid Build Coastguard Worker }
275*5a6e8488SAndroid Build Coastguard Worker
276*5a6e8488SAndroid Build Coastguard Worker BclContext
bcl_context(void)277*5a6e8488SAndroid Build Coastguard Worker bcl_context(void)
278*5a6e8488SAndroid Build Coastguard Worker {
279*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
280*5a6e8488SAndroid Build Coastguard Worker return bcl_contextHelper(vm);
281*5a6e8488SAndroid Build Coastguard Worker }
282*5a6e8488SAndroid Build Coastguard Worker
283*5a6e8488SAndroid Build Coastguard Worker void
bcl_free(void)284*5a6e8488SAndroid Build Coastguard Worker bcl_free(void)
285*5a6e8488SAndroid Build Coastguard Worker {
286*5a6e8488SAndroid Build Coastguard Worker size_t i;
287*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
288*5a6e8488SAndroid Build Coastguard Worker
289*5a6e8488SAndroid Build Coastguard Worker vm->refs -= 1;
290*5a6e8488SAndroid Build Coastguard Worker if (vm->refs) return;
291*5a6e8488SAndroid Build Coastguard Worker
292*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
293*5a6e8488SAndroid Build Coastguard Worker bc_rand_free(&vm->rng);
294*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
295*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(&vm->out);
296*5a6e8488SAndroid Build Coastguard Worker
297*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < vm->ctxts.len; ++i)
298*5a6e8488SAndroid Build Coastguard Worker {
299*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt = *((BclContext*) bc_vec_item(&vm->ctxts, i));
300*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_free(ctxt);
301*5a6e8488SAndroid Build Coastguard Worker }
302*5a6e8488SAndroid Build Coastguard Worker
303*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(&vm->ctxts);
304*5a6e8488SAndroid Build Coastguard Worker
305*5a6e8488SAndroid Build Coastguard Worker bc_vm_atexit();
306*5a6e8488SAndroid Build Coastguard Worker
307*5a6e8488SAndroid Build Coastguard Worker free(vm);
308*5a6e8488SAndroid Build Coastguard Worker bcl_setspecific(NULL);
309*5a6e8488SAndroid Build Coastguard Worker }
310*5a6e8488SAndroid Build Coastguard Worker
311*5a6e8488SAndroid Build Coastguard Worker void
bcl_end(void)312*5a6e8488SAndroid Build Coastguard Worker bcl_end(void)
313*5a6e8488SAndroid Build Coastguard Worker {
314*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
315*5a6e8488SAndroid Build Coastguard Worker
316*5a6e8488SAndroid Build Coastguard Worker // We ignore the return value.
317*5a6e8488SAndroid Build Coastguard Worker pthread_key_delete(tls_real);
318*5a6e8488SAndroid Build Coastguard Worker
319*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
320*5a6e8488SAndroid Build Coastguard Worker
321*5a6e8488SAndroid Build Coastguard Worker // We ignore the return value.
322*5a6e8488SAndroid Build Coastguard Worker TlsFree(tls_real);
323*5a6e8488SAndroid Build Coastguard Worker
324*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
325*5a6e8488SAndroid Build Coastguard Worker
326*5a6e8488SAndroid Build Coastguard Worker tls = NULL;
327*5a6e8488SAndroid Build Coastguard Worker }
328*5a6e8488SAndroid Build Coastguard Worker
329*5a6e8488SAndroid Build Coastguard Worker void
bcl_gc(void)330*5a6e8488SAndroid Build Coastguard Worker bcl_gc(void)
331*5a6e8488SAndroid Build Coastguard Worker {
332*5a6e8488SAndroid Build Coastguard Worker bc_vm_freeTemps();
333*5a6e8488SAndroid Build Coastguard Worker }
334*5a6e8488SAndroid Build Coastguard Worker
335*5a6e8488SAndroid Build Coastguard Worker bool
bcl_abortOnFatalError(void)336*5a6e8488SAndroid Build Coastguard Worker bcl_abortOnFatalError(void)
337*5a6e8488SAndroid Build Coastguard Worker {
338*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
339*5a6e8488SAndroid Build Coastguard Worker
340*5a6e8488SAndroid Build Coastguard Worker return vm->abrt;
341*5a6e8488SAndroid Build Coastguard Worker }
342*5a6e8488SAndroid Build Coastguard Worker
343*5a6e8488SAndroid Build Coastguard Worker void
bcl_setAbortOnFatalError(bool abrt)344*5a6e8488SAndroid Build Coastguard Worker bcl_setAbortOnFatalError(bool abrt)
345*5a6e8488SAndroid Build Coastguard Worker {
346*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
347*5a6e8488SAndroid Build Coastguard Worker
348*5a6e8488SAndroid Build Coastguard Worker vm->abrt = abrt;
349*5a6e8488SAndroid Build Coastguard Worker }
350*5a6e8488SAndroid Build Coastguard Worker
351*5a6e8488SAndroid Build Coastguard Worker bool
bcl_leadingZeroes(void)352*5a6e8488SAndroid Build Coastguard Worker bcl_leadingZeroes(void)
353*5a6e8488SAndroid Build Coastguard Worker {
354*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
355*5a6e8488SAndroid Build Coastguard Worker
356*5a6e8488SAndroid Build Coastguard Worker return vm->leading_zeroes;
357*5a6e8488SAndroid Build Coastguard Worker }
358*5a6e8488SAndroid Build Coastguard Worker
359*5a6e8488SAndroid Build Coastguard Worker void
bcl_setLeadingZeroes(bool leadingZeroes)360*5a6e8488SAndroid Build Coastguard Worker bcl_setLeadingZeroes(bool leadingZeroes)
361*5a6e8488SAndroid Build Coastguard Worker {
362*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
363*5a6e8488SAndroid Build Coastguard Worker
364*5a6e8488SAndroid Build Coastguard Worker vm->leading_zeroes = leadingZeroes;
365*5a6e8488SAndroid Build Coastguard Worker }
366*5a6e8488SAndroid Build Coastguard Worker
367*5a6e8488SAndroid Build Coastguard Worker bool
bcl_digitClamp(void)368*5a6e8488SAndroid Build Coastguard Worker bcl_digitClamp(void)
369*5a6e8488SAndroid Build Coastguard Worker {
370*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
371*5a6e8488SAndroid Build Coastguard Worker
372*5a6e8488SAndroid Build Coastguard Worker return vm->digit_clamp;
373*5a6e8488SAndroid Build Coastguard Worker }
374*5a6e8488SAndroid Build Coastguard Worker
375*5a6e8488SAndroid Build Coastguard Worker void
bcl_setDigitClamp(bool digitClamp)376*5a6e8488SAndroid Build Coastguard Worker bcl_setDigitClamp(bool digitClamp)
377*5a6e8488SAndroid Build Coastguard Worker {
378*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
379*5a6e8488SAndroid Build Coastguard Worker
380*5a6e8488SAndroid Build Coastguard Worker vm->digit_clamp = digitClamp;
381*5a6e8488SAndroid Build Coastguard Worker }
382*5a6e8488SAndroid Build Coastguard Worker
383*5a6e8488SAndroid Build Coastguard Worker BclContext
bcl_ctxt_create(void)384*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_create(void)
385*5a6e8488SAndroid Build Coastguard Worker {
386*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
387*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt = NULL;
388*5a6e8488SAndroid Build Coastguard Worker
389*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
390*5a6e8488SAndroid Build Coastguard Worker
391*5a6e8488SAndroid Build Coastguard Worker // We want the context to be free of any interference of other parties, so
392*5a6e8488SAndroid Build Coastguard Worker // malloc() is appropriate here.
393*5a6e8488SAndroid Build Coastguard Worker ctxt = bc_vm_malloc(sizeof(BclCtxt));
394*5a6e8488SAndroid Build Coastguard Worker
395*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&ctxt->nums, sizeof(BclNum), BC_DTOR_BCL_NUM);
396*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&ctxt->free_nums, sizeof(BclNumber), BC_DTOR_NONE);
397*5a6e8488SAndroid Build Coastguard Worker
398*5a6e8488SAndroid Build Coastguard Worker ctxt->scale = 0;
399*5a6e8488SAndroid Build Coastguard Worker ctxt->ibase = 10;
400*5a6e8488SAndroid Build Coastguard Worker ctxt->obase = 10;
401*5a6e8488SAndroid Build Coastguard Worker
402*5a6e8488SAndroid Build Coastguard Worker err:
403*5a6e8488SAndroid Build Coastguard Worker
404*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(vm->err && ctxt != NULL))
405*5a6e8488SAndroid Build Coastguard Worker {
406*5a6e8488SAndroid Build Coastguard Worker if (ctxt->nums.v != NULL) bc_vec_free(&ctxt->nums);
407*5a6e8488SAndroid Build Coastguard Worker free(ctxt);
408*5a6e8488SAndroid Build Coastguard Worker ctxt = NULL;
409*5a6e8488SAndroid Build Coastguard Worker }
410*5a6e8488SAndroid Build Coastguard Worker
411*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER_NO_ERR(vm);
412*5a6e8488SAndroid Build Coastguard Worker
413*5a6e8488SAndroid Build Coastguard Worker return ctxt;
414*5a6e8488SAndroid Build Coastguard Worker }
415*5a6e8488SAndroid Build Coastguard Worker
416*5a6e8488SAndroid Build Coastguard Worker void
bcl_ctxt_free(BclContext ctxt)417*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_free(BclContext ctxt)
418*5a6e8488SAndroid Build Coastguard Worker {
419*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(&ctxt->free_nums);
420*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(&ctxt->nums);
421*5a6e8488SAndroid Build Coastguard Worker free(ctxt);
422*5a6e8488SAndroid Build Coastguard Worker }
423*5a6e8488SAndroid Build Coastguard Worker
424*5a6e8488SAndroid Build Coastguard Worker void
bcl_ctxt_freeNums(BclContext ctxt)425*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_freeNums(BclContext ctxt)
426*5a6e8488SAndroid Build Coastguard Worker {
427*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(&ctxt->nums);
428*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(&ctxt->free_nums);
429*5a6e8488SAndroid Build Coastguard Worker }
430*5a6e8488SAndroid Build Coastguard Worker
431*5a6e8488SAndroid Build Coastguard Worker size_t
bcl_ctxt_scale(BclContext ctxt)432*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_scale(BclContext ctxt)
433*5a6e8488SAndroid Build Coastguard Worker {
434*5a6e8488SAndroid Build Coastguard Worker return ctxt->scale;
435*5a6e8488SAndroid Build Coastguard Worker }
436*5a6e8488SAndroid Build Coastguard Worker
437*5a6e8488SAndroid Build Coastguard Worker void
bcl_ctxt_setScale(BclContext ctxt,size_t scale)438*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_setScale(BclContext ctxt, size_t scale)
439*5a6e8488SAndroid Build Coastguard Worker {
440*5a6e8488SAndroid Build Coastguard Worker ctxt->scale = scale;
441*5a6e8488SAndroid Build Coastguard Worker }
442*5a6e8488SAndroid Build Coastguard Worker
443*5a6e8488SAndroid Build Coastguard Worker size_t
bcl_ctxt_ibase(BclContext ctxt)444*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_ibase(BclContext ctxt)
445*5a6e8488SAndroid Build Coastguard Worker {
446*5a6e8488SAndroid Build Coastguard Worker return ctxt->ibase;
447*5a6e8488SAndroid Build Coastguard Worker }
448*5a6e8488SAndroid Build Coastguard Worker
449*5a6e8488SAndroid Build Coastguard Worker void
bcl_ctxt_setIbase(BclContext ctxt,size_t ibase)450*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_setIbase(BclContext ctxt, size_t ibase)
451*5a6e8488SAndroid Build Coastguard Worker {
452*5a6e8488SAndroid Build Coastguard Worker if (ibase < BC_NUM_MIN_BASE) ibase = BC_NUM_MIN_BASE;
453*5a6e8488SAndroid Build Coastguard Worker else if (ibase > BC_NUM_MAX_IBASE) ibase = BC_NUM_MAX_IBASE;
454*5a6e8488SAndroid Build Coastguard Worker ctxt->ibase = ibase;
455*5a6e8488SAndroid Build Coastguard Worker }
456*5a6e8488SAndroid Build Coastguard Worker
457*5a6e8488SAndroid Build Coastguard Worker size_t
bcl_ctxt_obase(BclContext ctxt)458*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_obase(BclContext ctxt)
459*5a6e8488SAndroid Build Coastguard Worker {
460*5a6e8488SAndroid Build Coastguard Worker return ctxt->obase;
461*5a6e8488SAndroid Build Coastguard Worker }
462*5a6e8488SAndroid Build Coastguard Worker
463*5a6e8488SAndroid Build Coastguard Worker void
bcl_ctxt_setObase(BclContext ctxt,size_t obase)464*5a6e8488SAndroid Build Coastguard Worker bcl_ctxt_setObase(BclContext ctxt, size_t obase)
465*5a6e8488SAndroid Build Coastguard Worker {
466*5a6e8488SAndroid Build Coastguard Worker ctxt->obase = obase;
467*5a6e8488SAndroid Build Coastguard Worker }
468*5a6e8488SAndroid Build Coastguard Worker
469*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_err(BclNumber n)470*5a6e8488SAndroid Build Coastguard Worker bcl_err(BclNumber n)
471*5a6e8488SAndroid Build Coastguard Worker {
472*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
473*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
474*5a6e8488SAndroid Build Coastguard Worker
475*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
476*5a6e8488SAndroid Build Coastguard Worker
477*5a6e8488SAndroid Build Coastguard Worker // We need to clear the top byte in memcheck mode. We can do this because
478*5a6e8488SAndroid Build Coastguard Worker // the parameter is a copy.
479*5a6e8488SAndroid Build Coastguard Worker BCL_CLEAR_GEN(n);
480*5a6e8488SAndroid Build Coastguard Worker
481*5a6e8488SAndroid Build Coastguard Worker // Errors are encoded as (0 - error_code). If the index is in that range, it
482*5a6e8488SAndroid Build Coastguard Worker // is an encoded error.
483*5a6e8488SAndroid Build Coastguard Worker if (n.i >= ctxt->nums.len)
484*5a6e8488SAndroid Build Coastguard Worker {
485*5a6e8488SAndroid Build Coastguard Worker if (n.i > 0 - (size_t) BCL_ERROR_NELEMS) return (BclError) (0 - n.i);
486*5a6e8488SAndroid Build Coastguard Worker else return BCL_ERROR_INVALID_NUM;
487*5a6e8488SAndroid Build Coastguard Worker }
488*5a6e8488SAndroid Build Coastguard Worker else return BCL_ERROR_NONE;
489*5a6e8488SAndroid Build Coastguard Worker }
490*5a6e8488SAndroid Build Coastguard Worker
491*5a6e8488SAndroid Build Coastguard Worker /**
492*5a6e8488SAndroid Build Coastguard Worker * Inserts a BcNum into a context's list of numbers.
493*5a6e8488SAndroid Build Coastguard Worker * @param ctxt The context to insert into.
494*5a6e8488SAndroid Build Coastguard Worker * @param n The BcNum to insert.
495*5a6e8488SAndroid Build Coastguard Worker * @return The resulting BclNumber from the insert.
496*5a6e8488SAndroid Build Coastguard Worker */
497*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_num_insert(BclContext ctxt,BclNum * restrict n)498*5a6e8488SAndroid Build Coastguard Worker bcl_num_insert(BclContext ctxt, BclNum* restrict n)
499*5a6e8488SAndroid Build Coastguard Worker {
500*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
501*5a6e8488SAndroid Build Coastguard Worker
502*5a6e8488SAndroid Build Coastguard Worker // If there is a free spot...
503*5a6e8488SAndroid Build Coastguard Worker if (ctxt->free_nums.len)
504*5a6e8488SAndroid Build Coastguard Worker {
505*5a6e8488SAndroid Build Coastguard Worker BclNum* ptr;
506*5a6e8488SAndroid Build Coastguard Worker
507*5a6e8488SAndroid Build Coastguard Worker // Get the index of the free spot and remove it.
508*5a6e8488SAndroid Build Coastguard Worker idx = *((BclNumber*) bc_vec_top(&ctxt->free_nums));
509*5a6e8488SAndroid Build Coastguard Worker bc_vec_pop(&ctxt->free_nums);
510*5a6e8488SAndroid Build Coastguard Worker
511*5a6e8488SAndroid Build Coastguard Worker // Copy the number into the spot.
512*5a6e8488SAndroid Build Coastguard Worker ptr = bc_vec_item(&ctxt->nums, idx.i);
513*5a6e8488SAndroid Build Coastguard Worker
514*5a6e8488SAndroid Build Coastguard Worker memcpy(BCL_NUM_NUM(ptr), n, sizeof(BcNum));
515*5a6e8488SAndroid Build Coastguard Worker
516*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
517*5a6e8488SAndroid Build Coastguard Worker
518*5a6e8488SAndroid Build Coastguard Worker ptr->gen_idx += 1;
519*5a6e8488SAndroid Build Coastguard Worker
520*5a6e8488SAndroid Build Coastguard Worker if (ptr->gen_idx == UCHAR_MAX)
521*5a6e8488SAndroid Build Coastguard Worker {
522*5a6e8488SAndroid Build Coastguard Worker ptr->gen_idx = 0;
523*5a6e8488SAndroid Build Coastguard Worker }
524*5a6e8488SAndroid Build Coastguard Worker
525*5a6e8488SAndroid Build Coastguard Worker idx.i |= (ptr->gen_idx << ((sizeof(size_t) - 1) * CHAR_BIT));
526*5a6e8488SAndroid Build Coastguard Worker
527*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
528*5a6e8488SAndroid Build Coastguard Worker }
529*5a6e8488SAndroid Build Coastguard Worker else
530*5a6e8488SAndroid Build Coastguard Worker {
531*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
532*5a6e8488SAndroid Build Coastguard Worker n->gen_idx = 0;
533*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
534*5a6e8488SAndroid Build Coastguard Worker
535*5a6e8488SAndroid Build Coastguard Worker // Just push the number onto the vector because the generation index is
536*5a6e8488SAndroid Build Coastguard Worker // 0.
537*5a6e8488SAndroid Build Coastguard Worker idx.i = ctxt->nums.len;
538*5a6e8488SAndroid Build Coastguard Worker bc_vec_push(&ctxt->nums, n);
539*5a6e8488SAndroid Build Coastguard Worker }
540*5a6e8488SAndroid Build Coastguard Worker
541*5a6e8488SAndroid Build Coastguard Worker return idx;
542*5a6e8488SAndroid Build Coastguard Worker }
543*5a6e8488SAndroid Build Coastguard Worker
544*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_num_create(void)545*5a6e8488SAndroid Build Coastguard Worker bcl_num_create(void)
546*5a6e8488SAndroid Build Coastguard Worker {
547*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
548*5a6e8488SAndroid Build Coastguard Worker BclNum n;
549*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
550*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
551*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
552*5a6e8488SAndroid Build Coastguard Worker
553*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
554*5a6e8488SAndroid Build Coastguard Worker
555*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
556*5a6e8488SAndroid Build Coastguard Worker
557*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
558*5a6e8488SAndroid Build Coastguard Worker
559*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
560*5a6e8488SAndroid Build Coastguard Worker
561*5a6e8488SAndroid Build Coastguard Worker err:
562*5a6e8488SAndroid Build Coastguard Worker
563*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
564*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, n, idx);
565*5a6e8488SAndroid Build Coastguard Worker
566*5a6e8488SAndroid Build Coastguard Worker return idx;
567*5a6e8488SAndroid Build Coastguard Worker }
568*5a6e8488SAndroid Build Coastguard Worker
569*5a6e8488SAndroid Build Coastguard Worker /**
570*5a6e8488SAndroid Build Coastguard Worker * Destructs a number and marks its spot as free.
571*5a6e8488SAndroid Build Coastguard Worker * @param ctxt The context.
572*5a6e8488SAndroid Build Coastguard Worker * @param n The index of the number.
573*5a6e8488SAndroid Build Coastguard Worker * @param num The number to destroy.
574*5a6e8488SAndroid Build Coastguard Worker */
575*5a6e8488SAndroid Build Coastguard Worker static void
bcl_num_dtor(BclContext ctxt,BclNumber n,BclNum * restrict num)576*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(BclContext ctxt, BclNumber n, BclNum* restrict num)
577*5a6e8488SAndroid Build Coastguard Worker {
578*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
579*5a6e8488SAndroid Build Coastguard Worker
580*5a6e8488SAndroid Build Coastguard Worker BCL_CLEAR_GEN(n);
581*5a6e8488SAndroid Build Coastguard Worker
582*5a6e8488SAndroid Build Coastguard Worker bcl_num_destruct(num);
583*5a6e8488SAndroid Build Coastguard Worker bc_vec_push(&ctxt->free_nums, &n);
584*5a6e8488SAndroid Build Coastguard Worker
585*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
586*5a6e8488SAndroid Build Coastguard Worker num->n.num = NULL;
587*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
588*5a6e8488SAndroid Build Coastguard Worker }
589*5a6e8488SAndroid Build Coastguard Worker
590*5a6e8488SAndroid Build Coastguard Worker void
bcl_num_free(BclNumber n)591*5a6e8488SAndroid Build Coastguard Worker bcl_num_free(BclNumber n)
592*5a6e8488SAndroid Build Coastguard Worker {
593*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
594*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
595*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
596*5a6e8488SAndroid Build Coastguard Worker
597*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
598*5a6e8488SAndroid Build Coastguard Worker
599*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
600*5a6e8488SAndroid Build Coastguard Worker
601*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
602*5a6e8488SAndroid Build Coastguard Worker
603*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
604*5a6e8488SAndroid Build Coastguard Worker
605*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, n, num);
606*5a6e8488SAndroid Build Coastguard Worker }
607*5a6e8488SAndroid Build Coastguard Worker
608*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_copy(BclNumber d,BclNumber s)609*5a6e8488SAndroid Build Coastguard Worker bcl_copy(BclNumber d, BclNumber s)
610*5a6e8488SAndroid Build Coastguard Worker {
611*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
612*5a6e8488SAndroid Build Coastguard Worker BclNum* dest;
613*5a6e8488SAndroid Build Coastguard Worker BclNum* src;
614*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
615*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
616*5a6e8488SAndroid Build Coastguard Worker
617*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
618*5a6e8488SAndroid Build Coastguard Worker
619*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, d);
620*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, s);
621*5a6e8488SAndroid Build Coastguard Worker
622*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
623*5a6e8488SAndroid Build Coastguard Worker
624*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(d) < ctxt->nums.len);
625*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(s) < ctxt->nums.len);
626*5a6e8488SAndroid Build Coastguard Worker
627*5a6e8488SAndroid Build Coastguard Worker dest = BCL_NUM(ctxt, d);
628*5a6e8488SAndroid Build Coastguard Worker src = BCL_NUM(ctxt, s);
629*5a6e8488SAndroid Build Coastguard Worker
630*5a6e8488SAndroid Build Coastguard Worker assert(dest != NULL && src != NULL);
631*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NUM_ARRAY(dest) != NULL && BCL_NUM_ARRAY(src) != NULL);
632*5a6e8488SAndroid Build Coastguard Worker
633*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(BCL_NUM_NUM(dest), BCL_NUM_NUM(src));
634*5a6e8488SAndroid Build Coastguard Worker
635*5a6e8488SAndroid Build Coastguard Worker err:
636*5a6e8488SAndroid Build Coastguard Worker
637*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
638*5a6e8488SAndroid Build Coastguard Worker
639*5a6e8488SAndroid Build Coastguard Worker return e;
640*5a6e8488SAndroid Build Coastguard Worker }
641*5a6e8488SAndroid Build Coastguard Worker
642*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_dup(BclNumber s)643*5a6e8488SAndroid Build Coastguard Worker bcl_dup(BclNumber s)
644*5a6e8488SAndroid Build Coastguard Worker {
645*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
646*5a6e8488SAndroid Build Coastguard Worker BclNum *src, dest;
647*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
648*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
649*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
650*5a6e8488SAndroid Build Coastguard Worker
651*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
652*5a6e8488SAndroid Build Coastguard Worker
653*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, s);
654*5a6e8488SAndroid Build Coastguard Worker
655*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
656*5a6e8488SAndroid Build Coastguard Worker
657*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
658*5a6e8488SAndroid Build Coastguard Worker
659*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(s) < ctxt->nums.len);
660*5a6e8488SAndroid Build Coastguard Worker
661*5a6e8488SAndroid Build Coastguard Worker src = BCL_NUM(ctxt, s);
662*5a6e8488SAndroid Build Coastguard Worker
663*5a6e8488SAndroid Build Coastguard Worker assert(src != NULL && BCL_NUM_NUM(src) != NULL);
664*5a6e8488SAndroid Build Coastguard Worker
665*5a6e8488SAndroid Build Coastguard Worker // Copy the number.
666*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM(&dest));
667*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(BCL_NUM_NUM(&dest), BCL_NUM_NUM(src));
668*5a6e8488SAndroid Build Coastguard Worker
669*5a6e8488SAndroid Build Coastguard Worker err:
670*5a6e8488SAndroid Build Coastguard Worker
671*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
672*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, dest, idx);
673*5a6e8488SAndroid Build Coastguard Worker
674*5a6e8488SAndroid Build Coastguard Worker return idx;
675*5a6e8488SAndroid Build Coastguard Worker }
676*5a6e8488SAndroid Build Coastguard Worker
677*5a6e8488SAndroid Build Coastguard Worker void
bcl_num_destruct(void * num)678*5a6e8488SAndroid Build Coastguard Worker bcl_num_destruct(void* num)
679*5a6e8488SAndroid Build Coastguard Worker {
680*5a6e8488SAndroid Build Coastguard Worker BclNum* n = (BclNum*) num;
681*5a6e8488SAndroid Build Coastguard Worker
682*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
683*5a6e8488SAndroid Build Coastguard Worker
684*5a6e8488SAndroid Build Coastguard Worker if (BCL_NUM_ARRAY(n) == NULL) return;
685*5a6e8488SAndroid Build Coastguard Worker
686*5a6e8488SAndroid Build Coastguard Worker bc_num_free(BCL_NUM_NUM(n));
687*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM(n));
688*5a6e8488SAndroid Build Coastguard Worker }
689*5a6e8488SAndroid Build Coastguard Worker
690*5a6e8488SAndroid Build Coastguard Worker bool
bcl_num_neg(BclNumber n)691*5a6e8488SAndroid Build Coastguard Worker bcl_num_neg(BclNumber n)
692*5a6e8488SAndroid Build Coastguard Worker {
693*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
694*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
695*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
696*5a6e8488SAndroid Build Coastguard Worker
697*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
698*5a6e8488SAndroid Build Coastguard Worker
699*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
700*5a6e8488SAndroid Build Coastguard Worker
701*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
702*5a6e8488SAndroid Build Coastguard Worker
703*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
704*5a6e8488SAndroid Build Coastguard Worker
705*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
706*5a6e8488SAndroid Build Coastguard Worker
707*5a6e8488SAndroid Build Coastguard Worker return BC_NUM_NEG(BCL_NUM_NUM(num)) != 0;
708*5a6e8488SAndroid Build Coastguard Worker }
709*5a6e8488SAndroid Build Coastguard Worker
710*5a6e8488SAndroid Build Coastguard Worker void
bcl_num_setNeg(BclNumber n,bool neg)711*5a6e8488SAndroid Build Coastguard Worker bcl_num_setNeg(BclNumber n, bool neg)
712*5a6e8488SAndroid Build Coastguard Worker {
713*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
714*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
715*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
716*5a6e8488SAndroid Build Coastguard Worker
717*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
718*5a6e8488SAndroid Build Coastguard Worker
719*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
720*5a6e8488SAndroid Build Coastguard Worker
721*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
722*5a6e8488SAndroid Build Coastguard Worker
723*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
724*5a6e8488SAndroid Build Coastguard Worker
725*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
726*5a6e8488SAndroid Build Coastguard Worker
727*5a6e8488SAndroid Build Coastguard Worker BCL_NUM_NUM(num)->rdx = BC_NUM_NEG_VAL(BCL_NUM_NUM(num), neg);
728*5a6e8488SAndroid Build Coastguard Worker }
729*5a6e8488SAndroid Build Coastguard Worker
730*5a6e8488SAndroid Build Coastguard Worker size_t
bcl_num_scale(BclNumber n)731*5a6e8488SAndroid Build Coastguard Worker bcl_num_scale(BclNumber n)
732*5a6e8488SAndroid Build Coastguard Worker {
733*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
734*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
735*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
736*5a6e8488SAndroid Build Coastguard Worker
737*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
738*5a6e8488SAndroid Build Coastguard Worker
739*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
740*5a6e8488SAndroid Build Coastguard Worker
741*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
742*5a6e8488SAndroid Build Coastguard Worker
743*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
744*5a6e8488SAndroid Build Coastguard Worker
745*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
746*5a6e8488SAndroid Build Coastguard Worker
747*5a6e8488SAndroid Build Coastguard Worker return bc_num_scale(BCL_NUM_NUM(num));
748*5a6e8488SAndroid Build Coastguard Worker }
749*5a6e8488SAndroid Build Coastguard Worker
750*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_num_setScale(BclNumber n,size_t scale)751*5a6e8488SAndroid Build Coastguard Worker bcl_num_setScale(BclNumber n, size_t scale)
752*5a6e8488SAndroid Build Coastguard Worker {
753*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
754*5a6e8488SAndroid Build Coastguard Worker BclNum* nptr;
755*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
756*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
757*5a6e8488SAndroid Build Coastguard Worker
758*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
759*5a6e8488SAndroid Build Coastguard Worker
760*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM_ERR(ctxt, n);
761*5a6e8488SAndroid Build Coastguard Worker
762*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
763*5a6e8488SAndroid Build Coastguard Worker
764*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
765*5a6e8488SAndroid Build Coastguard Worker
766*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
767*5a6e8488SAndroid Build Coastguard Worker
768*5a6e8488SAndroid Build Coastguard Worker nptr = BCL_NUM(ctxt, n);
769*5a6e8488SAndroid Build Coastguard Worker
770*5a6e8488SAndroid Build Coastguard Worker assert(nptr != NULL && BCL_NUM_ARRAY(nptr) != NULL);
771*5a6e8488SAndroid Build Coastguard Worker
772*5a6e8488SAndroid Build Coastguard Worker if (scale > BCL_NUM_NUM(nptr)->scale)
773*5a6e8488SAndroid Build Coastguard Worker {
774*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(BCL_NUM_NUM(nptr), scale - BCL_NUM_NUM(nptr)->scale);
775*5a6e8488SAndroid Build Coastguard Worker }
776*5a6e8488SAndroid Build Coastguard Worker else if (scale < BCL_NUM_NUM(nptr)->scale)
777*5a6e8488SAndroid Build Coastguard Worker {
778*5a6e8488SAndroid Build Coastguard Worker bc_num_truncate(BCL_NUM_NUM(nptr), BCL_NUM_NUM(nptr)->scale - scale);
779*5a6e8488SAndroid Build Coastguard Worker }
780*5a6e8488SAndroid Build Coastguard Worker
781*5a6e8488SAndroid Build Coastguard Worker err:
782*5a6e8488SAndroid Build Coastguard Worker
783*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
784*5a6e8488SAndroid Build Coastguard Worker
785*5a6e8488SAndroid Build Coastguard Worker return e;
786*5a6e8488SAndroid Build Coastguard Worker }
787*5a6e8488SAndroid Build Coastguard Worker
788*5a6e8488SAndroid Build Coastguard Worker size_t
bcl_num_len(BclNumber n)789*5a6e8488SAndroid Build Coastguard Worker bcl_num_len(BclNumber n)
790*5a6e8488SAndroid Build Coastguard Worker {
791*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
792*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
793*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
794*5a6e8488SAndroid Build Coastguard Worker
795*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
796*5a6e8488SAndroid Build Coastguard Worker
797*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
798*5a6e8488SAndroid Build Coastguard Worker
799*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
800*5a6e8488SAndroid Build Coastguard Worker
801*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
802*5a6e8488SAndroid Build Coastguard Worker
803*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
804*5a6e8488SAndroid Build Coastguard Worker
805*5a6e8488SAndroid Build Coastguard Worker return bc_num_len(BCL_NUM_NUM(num));
806*5a6e8488SAndroid Build Coastguard Worker }
807*5a6e8488SAndroid Build Coastguard Worker
808*5a6e8488SAndroid Build Coastguard Worker static BclError
bcl_bigdig_helper(BclNumber n,BclBigDig * result,bool destruct)809*5a6e8488SAndroid Build Coastguard Worker bcl_bigdig_helper(BclNumber n, BclBigDig* result, bool destruct)
810*5a6e8488SAndroid Build Coastguard Worker {
811*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
812*5a6e8488SAndroid Build Coastguard Worker BclNum* num;
813*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
814*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
815*5a6e8488SAndroid Build Coastguard Worker
816*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
817*5a6e8488SAndroid Build Coastguard Worker
818*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
819*5a6e8488SAndroid Build Coastguard Worker
820*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
821*5a6e8488SAndroid Build Coastguard Worker
822*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
823*5a6e8488SAndroid Build Coastguard Worker assert(result != NULL);
824*5a6e8488SAndroid Build Coastguard Worker
825*5a6e8488SAndroid Build Coastguard Worker num = BCL_NUM(ctxt, n);
826*5a6e8488SAndroid Build Coastguard Worker
827*5a6e8488SAndroid Build Coastguard Worker assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
828*5a6e8488SAndroid Build Coastguard Worker
829*5a6e8488SAndroid Build Coastguard Worker *result = bc_num_bigdig(BCL_NUM_NUM(num));
830*5a6e8488SAndroid Build Coastguard Worker
831*5a6e8488SAndroid Build Coastguard Worker err:
832*5a6e8488SAndroid Build Coastguard Worker
833*5a6e8488SAndroid Build Coastguard Worker if (destruct)
834*5a6e8488SAndroid Build Coastguard Worker {
835*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, n, num);
836*5a6e8488SAndroid Build Coastguard Worker }
837*5a6e8488SAndroid Build Coastguard Worker
838*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
839*5a6e8488SAndroid Build Coastguard Worker
840*5a6e8488SAndroid Build Coastguard Worker return e;
841*5a6e8488SAndroid Build Coastguard Worker }
842*5a6e8488SAndroid Build Coastguard Worker
843*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_bigdig(BclNumber n,BclBigDig * result)844*5a6e8488SAndroid Build Coastguard Worker bcl_bigdig(BclNumber n, BclBigDig* result)
845*5a6e8488SAndroid Build Coastguard Worker {
846*5a6e8488SAndroid Build Coastguard Worker return bcl_bigdig_helper(n, result, true);
847*5a6e8488SAndroid Build Coastguard Worker }
848*5a6e8488SAndroid Build Coastguard Worker
849*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_bigdig_keep(BclNumber n,BclBigDig * result)850*5a6e8488SAndroid Build Coastguard Worker bcl_bigdig_keep(BclNumber n, BclBigDig* result)
851*5a6e8488SAndroid Build Coastguard Worker {
852*5a6e8488SAndroid Build Coastguard Worker return bcl_bigdig_helper(n, result, false);
853*5a6e8488SAndroid Build Coastguard Worker }
854*5a6e8488SAndroid Build Coastguard Worker
855*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_bigdig2num(BclBigDig val)856*5a6e8488SAndroid Build Coastguard Worker bcl_bigdig2num(BclBigDig val)
857*5a6e8488SAndroid Build Coastguard Worker {
858*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
859*5a6e8488SAndroid Build Coastguard Worker BclNum n;
860*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
861*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
862*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
863*5a6e8488SAndroid Build Coastguard Worker
864*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
865*5a6e8488SAndroid Build Coastguard Worker
866*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
867*5a6e8488SAndroid Build Coastguard Worker
868*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
869*5a6e8488SAndroid Build Coastguard Worker
870*5a6e8488SAndroid Build Coastguard Worker bc_num_createFromBigdig(BCL_NUM_NUM_NP(n), val);
871*5a6e8488SAndroid Build Coastguard Worker
872*5a6e8488SAndroid Build Coastguard Worker err:
873*5a6e8488SAndroid Build Coastguard Worker
874*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
875*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, n, idx);
876*5a6e8488SAndroid Build Coastguard Worker
877*5a6e8488SAndroid Build Coastguard Worker return idx;
878*5a6e8488SAndroid Build Coastguard Worker }
879*5a6e8488SAndroid Build Coastguard Worker
880*5a6e8488SAndroid Build Coastguard Worker /**
881*5a6e8488SAndroid Build Coastguard Worker * Sets up and executes a binary operator operation.
882*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
883*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
884*5a6e8488SAndroid Build Coastguard Worker * @param op The operation.
885*5a6e8488SAndroid Build Coastguard Worker * @param req The function to get the size of the result for
886*5a6e8488SAndroid Build Coastguard Worker * preallocation.
887*5a6e8488SAndroid Build Coastguard Worker * @param destruct True if the parameters should be consumed, false otherwise.
888*5a6e8488SAndroid Build Coastguard Worker * @return The result of the operation.
889*5a6e8488SAndroid Build Coastguard Worker */
890*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_binary(BclNumber a,BclNumber b,const BcNumBinaryOp op,const BcNumBinaryOpReq req,bool destruct)891*5a6e8488SAndroid Build Coastguard Worker bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
892*5a6e8488SAndroid Build Coastguard Worker const BcNumBinaryOpReq req, bool destruct)
893*5a6e8488SAndroid Build Coastguard Worker {
894*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
895*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
896*5a6e8488SAndroid Build Coastguard Worker BclNum* bptr;
897*5a6e8488SAndroid Build Coastguard Worker BclNum c;
898*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
899*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
900*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
901*5a6e8488SAndroid Build Coastguard Worker
902*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
903*5a6e8488SAndroid Build Coastguard Worker
904*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, a);
905*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, b);
906*5a6e8488SAndroid Build Coastguard Worker
907*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
908*5a6e8488SAndroid Build Coastguard Worker
909*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
910*5a6e8488SAndroid Build Coastguard Worker
911*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
912*5a6e8488SAndroid Build Coastguard Worker
913*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
914*5a6e8488SAndroid Build Coastguard Worker bptr = BCL_NUM(ctxt, b);
915*5a6e8488SAndroid Build Coastguard Worker
916*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && bptr != NULL);
917*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NUM_ARRAY(aptr) != NULL && BCL_NUM_ARRAY(bptr) != NULL);
918*5a6e8488SAndroid Build Coastguard Worker
919*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the result.
920*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(c));
921*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(c),
922*5a6e8488SAndroid Build Coastguard Worker req(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), ctxt->scale));
923*5a6e8488SAndroid Build Coastguard Worker
924*5a6e8488SAndroid Build Coastguard Worker op(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM_NP(c), ctxt->scale);
925*5a6e8488SAndroid Build Coastguard Worker
926*5a6e8488SAndroid Build Coastguard Worker err:
927*5a6e8488SAndroid Build Coastguard Worker
928*5a6e8488SAndroid Build Coastguard Worker if (destruct)
929*5a6e8488SAndroid Build Coastguard Worker {
930*5a6e8488SAndroid Build Coastguard Worker // Eat the operands.
931*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
932*5a6e8488SAndroid Build Coastguard Worker if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
933*5a6e8488SAndroid Build Coastguard Worker }
934*5a6e8488SAndroid Build Coastguard Worker
935*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
936*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, c, idx);
937*5a6e8488SAndroid Build Coastguard Worker
938*5a6e8488SAndroid Build Coastguard Worker return idx;
939*5a6e8488SAndroid Build Coastguard Worker }
940*5a6e8488SAndroid Build Coastguard Worker
941*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_add(BclNumber a,BclNumber b)942*5a6e8488SAndroid Build Coastguard Worker bcl_add(BclNumber a, BclNumber b)
943*5a6e8488SAndroid Build Coastguard Worker {
944*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_add, bc_num_addReq, true);
945*5a6e8488SAndroid Build Coastguard Worker }
946*5a6e8488SAndroid Build Coastguard Worker
947*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_add_keep(BclNumber a,BclNumber b)948*5a6e8488SAndroid Build Coastguard Worker bcl_add_keep(BclNumber a, BclNumber b)
949*5a6e8488SAndroid Build Coastguard Worker {
950*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_add, bc_num_addReq, false);
951*5a6e8488SAndroid Build Coastguard Worker }
952*5a6e8488SAndroid Build Coastguard Worker
953*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_sub(BclNumber a,BclNumber b)954*5a6e8488SAndroid Build Coastguard Worker bcl_sub(BclNumber a, BclNumber b)
955*5a6e8488SAndroid Build Coastguard Worker {
956*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_sub, bc_num_addReq, true);
957*5a6e8488SAndroid Build Coastguard Worker }
958*5a6e8488SAndroid Build Coastguard Worker
959*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_sub_keep(BclNumber a,BclNumber b)960*5a6e8488SAndroid Build Coastguard Worker bcl_sub_keep(BclNumber a, BclNumber b)
961*5a6e8488SAndroid Build Coastguard Worker {
962*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_sub, bc_num_addReq, false);
963*5a6e8488SAndroid Build Coastguard Worker }
964*5a6e8488SAndroid Build Coastguard Worker
965*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_mul(BclNumber a,BclNumber b)966*5a6e8488SAndroid Build Coastguard Worker bcl_mul(BclNumber a, BclNumber b)
967*5a6e8488SAndroid Build Coastguard Worker {
968*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_mul, bc_num_mulReq, true);
969*5a6e8488SAndroid Build Coastguard Worker }
970*5a6e8488SAndroid Build Coastguard Worker
971*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_mul_keep(BclNumber a,BclNumber b)972*5a6e8488SAndroid Build Coastguard Worker bcl_mul_keep(BclNumber a, BclNumber b)
973*5a6e8488SAndroid Build Coastguard Worker {
974*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_mul, bc_num_mulReq, false);
975*5a6e8488SAndroid Build Coastguard Worker }
976*5a6e8488SAndroid Build Coastguard Worker
977*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_div(BclNumber a,BclNumber b)978*5a6e8488SAndroid Build Coastguard Worker bcl_div(BclNumber a, BclNumber b)
979*5a6e8488SAndroid Build Coastguard Worker {
980*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_div, bc_num_divReq, true);
981*5a6e8488SAndroid Build Coastguard Worker }
982*5a6e8488SAndroid Build Coastguard Worker
983*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_div_keep(BclNumber a,BclNumber b)984*5a6e8488SAndroid Build Coastguard Worker bcl_div_keep(BclNumber a, BclNumber b)
985*5a6e8488SAndroid Build Coastguard Worker {
986*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_div, bc_num_divReq, false);
987*5a6e8488SAndroid Build Coastguard Worker }
988*5a6e8488SAndroid Build Coastguard Worker
989*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_mod(BclNumber a,BclNumber b)990*5a6e8488SAndroid Build Coastguard Worker bcl_mod(BclNumber a, BclNumber b)
991*5a6e8488SAndroid Build Coastguard Worker {
992*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_mod, bc_num_divReq, true);
993*5a6e8488SAndroid Build Coastguard Worker }
994*5a6e8488SAndroid Build Coastguard Worker
995*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_mod_keep(BclNumber a,BclNumber b)996*5a6e8488SAndroid Build Coastguard Worker bcl_mod_keep(BclNumber a, BclNumber b)
997*5a6e8488SAndroid Build Coastguard Worker {
998*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_mod, bc_num_divReq, false);
999*5a6e8488SAndroid Build Coastguard Worker }
1000*5a6e8488SAndroid Build Coastguard Worker
1001*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_pow(BclNumber a,BclNumber b)1002*5a6e8488SAndroid Build Coastguard Worker bcl_pow(BclNumber a, BclNumber b)
1003*5a6e8488SAndroid Build Coastguard Worker {
1004*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_pow, bc_num_powReq, true);
1005*5a6e8488SAndroid Build Coastguard Worker }
1006*5a6e8488SAndroid Build Coastguard Worker
1007*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_pow_keep(BclNumber a,BclNumber b)1008*5a6e8488SAndroid Build Coastguard Worker bcl_pow_keep(BclNumber a, BclNumber b)
1009*5a6e8488SAndroid Build Coastguard Worker {
1010*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_pow, bc_num_powReq, false);
1011*5a6e8488SAndroid Build Coastguard Worker }
1012*5a6e8488SAndroid Build Coastguard Worker
1013*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_lshift(BclNumber a,BclNumber b)1014*5a6e8488SAndroid Build Coastguard Worker bcl_lshift(BclNumber a, BclNumber b)
1015*5a6e8488SAndroid Build Coastguard Worker {
1016*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq, true);
1017*5a6e8488SAndroid Build Coastguard Worker }
1018*5a6e8488SAndroid Build Coastguard Worker
1019*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_lshift_keep(BclNumber a,BclNumber b)1020*5a6e8488SAndroid Build Coastguard Worker bcl_lshift_keep(BclNumber a, BclNumber b)
1021*5a6e8488SAndroid Build Coastguard Worker {
1022*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq, false);
1023*5a6e8488SAndroid Build Coastguard Worker }
1024*5a6e8488SAndroid Build Coastguard Worker
1025*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_rshift(BclNumber a,BclNumber b)1026*5a6e8488SAndroid Build Coastguard Worker bcl_rshift(BclNumber a, BclNumber b)
1027*5a6e8488SAndroid Build Coastguard Worker {
1028*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq, true);
1029*5a6e8488SAndroid Build Coastguard Worker }
1030*5a6e8488SAndroid Build Coastguard Worker
1031*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_rshift_keep(BclNumber a,BclNumber b)1032*5a6e8488SAndroid Build Coastguard Worker bcl_rshift_keep(BclNumber a, BclNumber b)
1033*5a6e8488SAndroid Build Coastguard Worker {
1034*5a6e8488SAndroid Build Coastguard Worker return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq, false);
1035*5a6e8488SAndroid Build Coastguard Worker }
1036*5a6e8488SAndroid Build Coastguard Worker
1037*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_sqrt_helper(BclNumber a,bool destruct)1038*5a6e8488SAndroid Build Coastguard Worker bcl_sqrt_helper(BclNumber a, bool destruct)
1039*5a6e8488SAndroid Build Coastguard Worker {
1040*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1041*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1042*5a6e8488SAndroid Build Coastguard Worker BclNum b;
1043*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1044*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1045*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1046*5a6e8488SAndroid Build Coastguard Worker
1047*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1048*5a6e8488SAndroid Build Coastguard Worker
1049*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, a);
1050*5a6e8488SAndroid Build Coastguard Worker
1051*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1052*5a6e8488SAndroid Build Coastguard Worker
1053*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1054*5a6e8488SAndroid Build Coastguard Worker
1055*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len);
1056*5a6e8488SAndroid Build Coastguard Worker
1057*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1058*5a6e8488SAndroid Build Coastguard Worker
1059*5a6e8488SAndroid Build Coastguard Worker bc_num_sqrt(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), ctxt->scale);
1060*5a6e8488SAndroid Build Coastguard Worker
1061*5a6e8488SAndroid Build Coastguard Worker err:
1062*5a6e8488SAndroid Build Coastguard Worker
1063*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1064*5a6e8488SAndroid Build Coastguard Worker {
1065*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
1066*5a6e8488SAndroid Build Coastguard Worker }
1067*5a6e8488SAndroid Build Coastguard Worker
1068*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1069*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, b, idx);
1070*5a6e8488SAndroid Build Coastguard Worker
1071*5a6e8488SAndroid Build Coastguard Worker return idx;
1072*5a6e8488SAndroid Build Coastguard Worker }
1073*5a6e8488SAndroid Build Coastguard Worker
1074*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_sqrt(BclNumber a)1075*5a6e8488SAndroid Build Coastguard Worker bcl_sqrt(BclNumber a)
1076*5a6e8488SAndroid Build Coastguard Worker {
1077*5a6e8488SAndroid Build Coastguard Worker return bcl_sqrt_helper(a, true);
1078*5a6e8488SAndroid Build Coastguard Worker }
1079*5a6e8488SAndroid Build Coastguard Worker
1080*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_sqrt_keep(BclNumber a)1081*5a6e8488SAndroid Build Coastguard Worker bcl_sqrt_keep(BclNumber a)
1082*5a6e8488SAndroid Build Coastguard Worker {
1083*5a6e8488SAndroid Build Coastguard Worker return bcl_sqrt_helper(a, false);
1084*5a6e8488SAndroid Build Coastguard Worker }
1085*5a6e8488SAndroid Build Coastguard Worker
1086*5a6e8488SAndroid Build Coastguard Worker static BclError
bcl_divmod_helper(BclNumber a,BclNumber b,BclNumber * c,BclNumber * d,bool destruct)1087*5a6e8488SAndroid Build Coastguard Worker bcl_divmod_helper(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d,
1088*5a6e8488SAndroid Build Coastguard Worker bool destruct)
1089*5a6e8488SAndroid Build Coastguard Worker {
1090*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1091*5a6e8488SAndroid Build Coastguard Worker size_t req;
1092*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1093*5a6e8488SAndroid Build Coastguard Worker BclNum* bptr;
1094*5a6e8488SAndroid Build Coastguard Worker BclNum cnum, dnum;
1095*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1096*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1097*5a6e8488SAndroid Build Coastguard Worker
1098*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
1099*5a6e8488SAndroid Build Coastguard Worker
1100*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM_ERR(ctxt, a);
1101*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM_ERR(ctxt, b);
1102*5a6e8488SAndroid Build Coastguard Worker
1103*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1104*5a6e8488SAndroid Build Coastguard Worker
1105*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1106*5a6e8488SAndroid Build Coastguard Worker
1107*5a6e8488SAndroid Build Coastguard Worker assert(c != NULL && d != NULL);
1108*5a6e8488SAndroid Build Coastguard Worker
1109*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1110*5a6e8488SAndroid Build Coastguard Worker bptr = BCL_NUM(ctxt, b);
1111*5a6e8488SAndroid Build Coastguard Worker
1112*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && bptr != NULL);
1113*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NUM_ARRAY(aptr) != NULL && BCL_NUM_ARRAY(bptr) != NULL);
1114*5a6e8488SAndroid Build Coastguard Worker
1115*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(cnum));
1116*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(dnum));
1117*5a6e8488SAndroid Build Coastguard Worker
1118*5a6e8488SAndroid Build Coastguard Worker req = bc_num_divReq(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), ctxt->scale);
1119*5a6e8488SAndroid Build Coastguard Worker
1120*5a6e8488SAndroid Build Coastguard Worker // Initialize the numbers.
1121*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(cnum), req);
1122*5a6e8488SAndroid Build Coastguard Worker BC_UNSETJMP(vm);
1123*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP(vm, err);
1124*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(dnum), req);
1125*5a6e8488SAndroid Build Coastguard Worker
1126*5a6e8488SAndroid Build Coastguard Worker bc_num_divmod(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM_NP(cnum),
1127*5a6e8488SAndroid Build Coastguard Worker BCL_NUM_NUM_NP(dnum), ctxt->scale);
1128*5a6e8488SAndroid Build Coastguard Worker
1129*5a6e8488SAndroid Build Coastguard Worker err:
1130*5a6e8488SAndroid Build Coastguard Worker
1131*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1132*5a6e8488SAndroid Build Coastguard Worker {
1133*5a6e8488SAndroid Build Coastguard Worker // Eat the operands.
1134*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
1135*5a6e8488SAndroid Build Coastguard Worker if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
1136*5a6e8488SAndroid Build Coastguard Worker }
1137*5a6e8488SAndroid Build Coastguard Worker
1138*5a6e8488SAndroid Build Coastguard Worker // If there was an error...
1139*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(vm->err))
1140*5a6e8488SAndroid Build Coastguard Worker {
1141*5a6e8488SAndroid Build Coastguard Worker // Free the results.
1142*5a6e8488SAndroid Build Coastguard Worker if (BCL_NUM_ARRAY_NP(cnum) != NULL) bc_num_free(&cnum);
1143*5a6e8488SAndroid Build Coastguard Worker if (BCL_NUM_ARRAY_NP(cnum) != NULL) bc_num_free(&dnum);
1144*5a6e8488SAndroid Build Coastguard Worker
1145*5a6e8488SAndroid Build Coastguard Worker // Make sure the return values are invalid.
1146*5a6e8488SAndroid Build Coastguard Worker c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
1147*5a6e8488SAndroid Build Coastguard Worker d->i = c->i;
1148*5a6e8488SAndroid Build Coastguard Worker
1149*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1150*5a6e8488SAndroid Build Coastguard Worker }
1151*5a6e8488SAndroid Build Coastguard Worker else
1152*5a6e8488SAndroid Build Coastguard Worker {
1153*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1154*5a6e8488SAndroid Build Coastguard Worker
1155*5a6e8488SAndroid Build Coastguard Worker // Insert the results into the context.
1156*5a6e8488SAndroid Build Coastguard Worker *c = bcl_num_insert(ctxt, &cnum);
1157*5a6e8488SAndroid Build Coastguard Worker *d = bcl_num_insert(ctxt, &dnum);
1158*5a6e8488SAndroid Build Coastguard Worker }
1159*5a6e8488SAndroid Build Coastguard Worker
1160*5a6e8488SAndroid Build Coastguard Worker return e;
1161*5a6e8488SAndroid Build Coastguard Worker }
1162*5a6e8488SAndroid Build Coastguard Worker
1163*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_divmod(BclNumber a,BclNumber b,BclNumber * c,BclNumber * d)1164*5a6e8488SAndroid Build Coastguard Worker bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
1165*5a6e8488SAndroid Build Coastguard Worker {
1166*5a6e8488SAndroid Build Coastguard Worker return bcl_divmod_helper(a, b, c, d, true);
1167*5a6e8488SAndroid Build Coastguard Worker }
1168*5a6e8488SAndroid Build Coastguard Worker
1169*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_divmod_keep(BclNumber a,BclNumber b,BclNumber * c,BclNumber * d)1170*5a6e8488SAndroid Build Coastguard Worker bcl_divmod_keep(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
1171*5a6e8488SAndroid Build Coastguard Worker {
1172*5a6e8488SAndroid Build Coastguard Worker return bcl_divmod_helper(a, b, c, d, false);
1173*5a6e8488SAndroid Build Coastguard Worker }
1174*5a6e8488SAndroid Build Coastguard Worker
1175*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_modexp_helper(BclNumber a,BclNumber b,BclNumber c,bool destruct)1176*5a6e8488SAndroid Build Coastguard Worker bcl_modexp_helper(BclNumber a, BclNumber b, BclNumber c, bool destruct)
1177*5a6e8488SAndroid Build Coastguard Worker {
1178*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1179*5a6e8488SAndroid Build Coastguard Worker size_t req;
1180*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1181*5a6e8488SAndroid Build Coastguard Worker BclNum* bptr;
1182*5a6e8488SAndroid Build Coastguard Worker BclNum* cptr;
1183*5a6e8488SAndroid Build Coastguard Worker BclNum d;
1184*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1185*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1186*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1187*5a6e8488SAndroid Build Coastguard Worker
1188*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1189*5a6e8488SAndroid Build Coastguard Worker
1190*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, a);
1191*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, b);
1192*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, c);
1193*5a6e8488SAndroid Build Coastguard Worker
1194*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1195*5a6e8488SAndroid Build Coastguard Worker
1196*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1197*5a6e8488SAndroid Build Coastguard Worker
1198*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
1199*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(c) < ctxt->nums.len);
1200*5a6e8488SAndroid Build Coastguard Worker
1201*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1202*5a6e8488SAndroid Build Coastguard Worker bptr = BCL_NUM(ctxt, b);
1203*5a6e8488SAndroid Build Coastguard Worker cptr = BCL_NUM(ctxt, c);
1204*5a6e8488SAndroid Build Coastguard Worker
1205*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && bptr != NULL && cptr != NULL);
1206*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NUM_NUM(aptr) != NULL && BCL_NUM_NUM(bptr) != NULL &&
1207*5a6e8488SAndroid Build Coastguard Worker BCL_NUM_NUM(cptr) != NULL);
1208*5a6e8488SAndroid Build Coastguard Worker
1209*5a6e8488SAndroid Build Coastguard Worker // Prepare the result.
1210*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(d));
1211*5a6e8488SAndroid Build Coastguard Worker
1212*5a6e8488SAndroid Build Coastguard Worker req = bc_num_divReq(BCL_NUM_NUM(aptr), BCL_NUM_NUM(cptr), 0);
1213*5a6e8488SAndroid Build Coastguard Worker
1214*5a6e8488SAndroid Build Coastguard Worker // Initialize the result.
1215*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(d), req);
1216*5a6e8488SAndroid Build Coastguard Worker
1217*5a6e8488SAndroid Build Coastguard Worker bc_num_modexp(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM(cptr),
1218*5a6e8488SAndroid Build Coastguard Worker BCL_NUM_NUM_NP(d));
1219*5a6e8488SAndroid Build Coastguard Worker
1220*5a6e8488SAndroid Build Coastguard Worker err:
1221*5a6e8488SAndroid Build Coastguard Worker
1222*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1223*5a6e8488SAndroid Build Coastguard Worker {
1224*5a6e8488SAndroid Build Coastguard Worker // Eat the operands.
1225*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
1226*5a6e8488SAndroid Build Coastguard Worker if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
1227*5a6e8488SAndroid Build Coastguard Worker if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
1228*5a6e8488SAndroid Build Coastguard Worker }
1229*5a6e8488SAndroid Build Coastguard Worker
1230*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1231*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, d, idx);
1232*5a6e8488SAndroid Build Coastguard Worker
1233*5a6e8488SAndroid Build Coastguard Worker return idx;
1234*5a6e8488SAndroid Build Coastguard Worker }
1235*5a6e8488SAndroid Build Coastguard Worker
1236*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_modexp(BclNumber a,BclNumber b,BclNumber c)1237*5a6e8488SAndroid Build Coastguard Worker bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
1238*5a6e8488SAndroid Build Coastguard Worker {
1239*5a6e8488SAndroid Build Coastguard Worker return bcl_modexp_helper(a, b, c, true);
1240*5a6e8488SAndroid Build Coastguard Worker }
1241*5a6e8488SAndroid Build Coastguard Worker
1242*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_modexp_keep(BclNumber a,BclNumber b,BclNumber c)1243*5a6e8488SAndroid Build Coastguard Worker bcl_modexp_keep(BclNumber a, BclNumber b, BclNumber c)
1244*5a6e8488SAndroid Build Coastguard Worker {
1245*5a6e8488SAndroid Build Coastguard Worker return bcl_modexp_helper(a, b, c, false);
1246*5a6e8488SAndroid Build Coastguard Worker }
1247*5a6e8488SAndroid Build Coastguard Worker
1248*5a6e8488SAndroid Build Coastguard Worker ssize_t
bcl_cmp(BclNumber a,BclNumber b)1249*5a6e8488SAndroid Build Coastguard Worker bcl_cmp(BclNumber a, BclNumber b)
1250*5a6e8488SAndroid Build Coastguard Worker {
1251*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1252*5a6e8488SAndroid Build Coastguard Worker BclNum* bptr;
1253*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1254*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1255*5a6e8488SAndroid Build Coastguard Worker
1256*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
1257*5a6e8488SAndroid Build Coastguard Worker
1258*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, a);
1259*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, b);
1260*5a6e8488SAndroid Build Coastguard Worker
1261*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
1262*5a6e8488SAndroid Build Coastguard Worker
1263*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1264*5a6e8488SAndroid Build Coastguard Worker bptr = BCL_NUM(ctxt, b);
1265*5a6e8488SAndroid Build Coastguard Worker
1266*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && bptr != NULL);
1267*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NUM_NUM(aptr) != NULL && BCL_NUM_NUM(bptr));
1268*5a6e8488SAndroid Build Coastguard Worker
1269*5a6e8488SAndroid Build Coastguard Worker return bc_num_cmp(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr));
1270*5a6e8488SAndroid Build Coastguard Worker }
1271*5a6e8488SAndroid Build Coastguard Worker
1272*5a6e8488SAndroid Build Coastguard Worker void
bcl_zero(BclNumber n)1273*5a6e8488SAndroid Build Coastguard Worker bcl_zero(BclNumber n)
1274*5a6e8488SAndroid Build Coastguard Worker {
1275*5a6e8488SAndroid Build Coastguard Worker BclNum* nptr;
1276*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1277*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1278*5a6e8488SAndroid Build Coastguard Worker
1279*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
1280*5a6e8488SAndroid Build Coastguard Worker
1281*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
1282*5a6e8488SAndroid Build Coastguard Worker
1283*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
1284*5a6e8488SAndroid Build Coastguard Worker
1285*5a6e8488SAndroid Build Coastguard Worker nptr = BCL_NUM(ctxt, n);
1286*5a6e8488SAndroid Build Coastguard Worker
1287*5a6e8488SAndroid Build Coastguard Worker assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
1288*5a6e8488SAndroid Build Coastguard Worker
1289*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(BCL_NUM_NUM(nptr));
1290*5a6e8488SAndroid Build Coastguard Worker }
1291*5a6e8488SAndroid Build Coastguard Worker
1292*5a6e8488SAndroid Build Coastguard Worker void
bcl_one(BclNumber n)1293*5a6e8488SAndroid Build Coastguard Worker bcl_one(BclNumber n)
1294*5a6e8488SAndroid Build Coastguard Worker {
1295*5a6e8488SAndroid Build Coastguard Worker BclNum* nptr;
1296*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1297*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1298*5a6e8488SAndroid Build Coastguard Worker
1299*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
1300*5a6e8488SAndroid Build Coastguard Worker
1301*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
1302*5a6e8488SAndroid Build Coastguard Worker
1303*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
1304*5a6e8488SAndroid Build Coastguard Worker
1305*5a6e8488SAndroid Build Coastguard Worker nptr = BCL_NUM(ctxt, n);
1306*5a6e8488SAndroid Build Coastguard Worker
1307*5a6e8488SAndroid Build Coastguard Worker assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
1308*5a6e8488SAndroid Build Coastguard Worker
1309*5a6e8488SAndroid Build Coastguard Worker bc_num_one(BCL_NUM_NUM(nptr));
1310*5a6e8488SAndroid Build Coastguard Worker }
1311*5a6e8488SAndroid Build Coastguard Worker
1312*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_parse(const char * restrict val)1313*5a6e8488SAndroid Build Coastguard Worker bcl_parse(const char* restrict val)
1314*5a6e8488SAndroid Build Coastguard Worker {
1315*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1316*5a6e8488SAndroid Build Coastguard Worker BclNum n;
1317*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1318*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1319*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1320*5a6e8488SAndroid Build Coastguard Worker bool neg;
1321*5a6e8488SAndroid Build Coastguard Worker
1322*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1323*5a6e8488SAndroid Build Coastguard Worker
1324*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1325*5a6e8488SAndroid Build Coastguard Worker
1326*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1327*5a6e8488SAndroid Build Coastguard Worker
1328*5a6e8488SAndroid Build Coastguard Worker assert(val != NULL);
1329*5a6e8488SAndroid Build Coastguard Worker
1330*5a6e8488SAndroid Build Coastguard Worker // We have to take care of negative here because bc's number parsing does
1331*5a6e8488SAndroid Build Coastguard Worker // not.
1332*5a6e8488SAndroid Build Coastguard Worker neg = (val[0] == '-');
1333*5a6e8488SAndroid Build Coastguard Worker
1334*5a6e8488SAndroid Build Coastguard Worker if (neg) val += 1;
1335*5a6e8488SAndroid Build Coastguard Worker
1336*5a6e8488SAndroid Build Coastguard Worker if (!bc_num_strValid(val))
1337*5a6e8488SAndroid Build Coastguard Worker {
1338*5a6e8488SAndroid Build Coastguard Worker vm->err = BCL_ERROR_PARSE_INVALID_STR;
1339*5a6e8488SAndroid Build Coastguard Worker goto err;
1340*5a6e8488SAndroid Build Coastguard Worker }
1341*5a6e8488SAndroid Build Coastguard Worker
1342*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the number.
1343*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(n));
1344*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
1345*5a6e8488SAndroid Build Coastguard Worker
1346*5a6e8488SAndroid Build Coastguard Worker bc_num_parse(BCL_NUM_NUM_NP(n), val, (BcBigDig) ctxt->ibase);
1347*5a6e8488SAndroid Build Coastguard Worker
1348*5a6e8488SAndroid Build Coastguard Worker // Set the negative.
1349*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
1350*5a6e8488SAndroid Build Coastguard Worker n.n.rdx = BC_NUM_NEG_VAL(BCL_NUM_NUM_NP(n), neg);
1351*5a6e8488SAndroid Build Coastguard Worker #else // BC_ENABLE_MEMCHECK
1352*5a6e8488SAndroid Build Coastguard Worker n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
1353*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
1354*5a6e8488SAndroid Build Coastguard Worker
1355*5a6e8488SAndroid Build Coastguard Worker err:
1356*5a6e8488SAndroid Build Coastguard Worker
1357*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1358*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, n, idx);
1359*5a6e8488SAndroid Build Coastguard Worker
1360*5a6e8488SAndroid Build Coastguard Worker return idx;
1361*5a6e8488SAndroid Build Coastguard Worker }
1362*5a6e8488SAndroid Build Coastguard Worker
1363*5a6e8488SAndroid Build Coastguard Worker static char*
bcl_string_helper(BclNumber n,bool destruct)1364*5a6e8488SAndroid Build Coastguard Worker bcl_string_helper(BclNumber n, bool destruct)
1365*5a6e8488SAndroid Build Coastguard Worker {
1366*5a6e8488SAndroid Build Coastguard Worker BclNum* nptr;
1367*5a6e8488SAndroid Build Coastguard Worker char* str = NULL;
1368*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1369*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1370*5a6e8488SAndroid Build Coastguard Worker
1371*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ASSERT(vm, ctxt);
1372*5a6e8488SAndroid Build Coastguard Worker
1373*5a6e8488SAndroid Build Coastguard Worker BCL_CHECK_NUM_VALID(ctxt, n);
1374*5a6e8488SAndroid Build Coastguard Worker
1375*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BCL_NO_GEN(n) >= ctxt->nums.len)) return str;
1376*5a6e8488SAndroid Build Coastguard Worker
1377*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1378*5a6e8488SAndroid Build Coastguard Worker
1379*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
1380*5a6e8488SAndroid Build Coastguard Worker
1381*5a6e8488SAndroid Build Coastguard Worker nptr = BCL_NUM(ctxt, n);
1382*5a6e8488SAndroid Build Coastguard Worker
1383*5a6e8488SAndroid Build Coastguard Worker assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
1384*5a6e8488SAndroid Build Coastguard Worker
1385*5a6e8488SAndroid Build Coastguard Worker // Clear the buffer.
1386*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(&vm->out);
1387*5a6e8488SAndroid Build Coastguard Worker
1388*5a6e8488SAndroid Build Coastguard Worker // Print to the buffer.
1389*5a6e8488SAndroid Build Coastguard Worker bc_num_print(BCL_NUM_NUM(nptr), (BcBigDig) ctxt->obase, false);
1390*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushByte(&vm->out, '\0');
1391*5a6e8488SAndroid Build Coastguard Worker
1392*5a6e8488SAndroid Build Coastguard Worker // Just dup the string; the caller is responsible for it.
1393*5a6e8488SAndroid Build Coastguard Worker str = bc_vm_strdup(vm->out.v);
1394*5a6e8488SAndroid Build Coastguard Worker
1395*5a6e8488SAndroid Build Coastguard Worker err:
1396*5a6e8488SAndroid Build Coastguard Worker
1397*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1398*5a6e8488SAndroid Build Coastguard Worker {
1399*5a6e8488SAndroid Build Coastguard Worker // Eat the operand.
1400*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, n, nptr);
1401*5a6e8488SAndroid Build Coastguard Worker }
1402*5a6e8488SAndroid Build Coastguard Worker
1403*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER_NO_ERR(vm);
1404*5a6e8488SAndroid Build Coastguard Worker
1405*5a6e8488SAndroid Build Coastguard Worker return str;
1406*5a6e8488SAndroid Build Coastguard Worker }
1407*5a6e8488SAndroid Build Coastguard Worker
1408*5a6e8488SAndroid Build Coastguard Worker char*
bcl_string(BclNumber n)1409*5a6e8488SAndroid Build Coastguard Worker bcl_string(BclNumber n)
1410*5a6e8488SAndroid Build Coastguard Worker {
1411*5a6e8488SAndroid Build Coastguard Worker return bcl_string_helper(n, true);
1412*5a6e8488SAndroid Build Coastguard Worker }
1413*5a6e8488SAndroid Build Coastguard Worker
1414*5a6e8488SAndroid Build Coastguard Worker char*
bcl_string_keep(BclNumber n)1415*5a6e8488SAndroid Build Coastguard Worker bcl_string_keep(BclNumber n)
1416*5a6e8488SAndroid Build Coastguard Worker {
1417*5a6e8488SAndroid Build Coastguard Worker return bcl_string_helper(n, false);
1418*5a6e8488SAndroid Build Coastguard Worker }
1419*5a6e8488SAndroid Build Coastguard Worker
1420*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1421*5a6e8488SAndroid Build Coastguard Worker
1422*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_irand_helper(BclNumber a,bool destruct)1423*5a6e8488SAndroid Build Coastguard Worker bcl_irand_helper(BclNumber a, bool destruct)
1424*5a6e8488SAndroid Build Coastguard Worker {
1425*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1426*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1427*5a6e8488SAndroid Build Coastguard Worker BclNum b;
1428*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1429*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1430*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1431*5a6e8488SAndroid Build Coastguard Worker
1432*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1433*5a6e8488SAndroid Build Coastguard Worker
1434*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, a);
1435*5a6e8488SAndroid Build Coastguard Worker
1436*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1437*5a6e8488SAndroid Build Coastguard Worker
1438*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1439*5a6e8488SAndroid Build Coastguard Worker
1440*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len);
1441*5a6e8488SAndroid Build Coastguard Worker
1442*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1443*5a6e8488SAndroid Build Coastguard Worker
1444*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && BCL_NUM_NUM(aptr) != NULL);
1445*5a6e8488SAndroid Build Coastguard Worker
1446*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the result.
1447*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(b));
1448*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(b), BC_NUM_DEF_SIZE);
1449*5a6e8488SAndroid Build Coastguard Worker
1450*5a6e8488SAndroid Build Coastguard Worker bc_num_irand(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), &vm->rng);
1451*5a6e8488SAndroid Build Coastguard Worker
1452*5a6e8488SAndroid Build Coastguard Worker err:
1453*5a6e8488SAndroid Build Coastguard Worker
1454*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1455*5a6e8488SAndroid Build Coastguard Worker {
1456*5a6e8488SAndroid Build Coastguard Worker // Eat the operand.
1457*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
1458*5a6e8488SAndroid Build Coastguard Worker }
1459*5a6e8488SAndroid Build Coastguard Worker
1460*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1461*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, b, idx);
1462*5a6e8488SAndroid Build Coastguard Worker
1463*5a6e8488SAndroid Build Coastguard Worker return idx;
1464*5a6e8488SAndroid Build Coastguard Worker }
1465*5a6e8488SAndroid Build Coastguard Worker
1466*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_irand(BclNumber a)1467*5a6e8488SAndroid Build Coastguard Worker bcl_irand(BclNumber a)
1468*5a6e8488SAndroid Build Coastguard Worker {
1469*5a6e8488SAndroid Build Coastguard Worker return bcl_irand_helper(a, true);
1470*5a6e8488SAndroid Build Coastguard Worker }
1471*5a6e8488SAndroid Build Coastguard Worker
1472*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_irand_keep(BclNumber a)1473*5a6e8488SAndroid Build Coastguard Worker bcl_irand_keep(BclNumber a)
1474*5a6e8488SAndroid Build Coastguard Worker {
1475*5a6e8488SAndroid Build Coastguard Worker return bcl_irand_helper(a, false);
1476*5a6e8488SAndroid Build Coastguard Worker }
1477*5a6e8488SAndroid Build Coastguard Worker
1478*5a6e8488SAndroid Build Coastguard Worker /**
1479*5a6e8488SAndroid Build Coastguard Worker * Helps bcl_frand(). This is separate because the error handling is easier that
1480*5a6e8488SAndroid Build Coastguard Worker * way. It is also easier to do ifrand that way.
1481*5a6e8488SAndroid Build Coastguard Worker * @param b The return parameter.
1482*5a6e8488SAndroid Build Coastguard Worker * @param places The number of decimal places to generate.
1483*5a6e8488SAndroid Build Coastguard Worker */
1484*5a6e8488SAndroid Build Coastguard Worker static void
bcl_frandHelper(BcNum * restrict b,size_t places)1485*5a6e8488SAndroid Build Coastguard Worker bcl_frandHelper(BcNum* restrict b, size_t places)
1486*5a6e8488SAndroid Build Coastguard Worker {
1487*5a6e8488SAndroid Build Coastguard Worker BcNum exp, pow, ten;
1488*5a6e8488SAndroid Build Coastguard Worker BcDig exp_digs[BC_NUM_BIGDIG_LOG10];
1489*5a6e8488SAndroid Build Coastguard Worker BcDig ten_digs[BC_NUM_BIGDIG_LOG10];
1490*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1491*5a6e8488SAndroid Build Coastguard Worker
1492*5a6e8488SAndroid Build Coastguard Worker // Set up temporaries.
1493*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&exp, exp_digs, BC_NUM_BIGDIG_LOG10);
1494*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&ten, ten_digs, BC_NUM_BIGDIG_LOG10);
1495*5a6e8488SAndroid Build Coastguard Worker
1496*5a6e8488SAndroid Build Coastguard Worker ten.num[0] = 10;
1497*5a6e8488SAndroid Build Coastguard Worker ten.len = 1;
1498*5a6e8488SAndroid Build Coastguard Worker
1499*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&exp, (BcBigDig) places);
1500*5a6e8488SAndroid Build Coastguard Worker
1501*5a6e8488SAndroid Build Coastguard Worker // Clear the temporary that might need to grow.
1502*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(&pow);
1503*5a6e8488SAndroid Build Coastguard Worker
1504*5a6e8488SAndroid Build Coastguard Worker // Initialize the temporary that might need to grow.
1505*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&pow, bc_num_powReq(&ten, &exp, 0));
1506*5a6e8488SAndroid Build Coastguard Worker
1507*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP(vm, err);
1508*5a6e8488SAndroid Build Coastguard Worker
1509*5a6e8488SAndroid Build Coastguard Worker // Generate the number.
1510*5a6e8488SAndroid Build Coastguard Worker bc_num_pow(&ten, &exp, &pow, 0);
1511*5a6e8488SAndroid Build Coastguard Worker bc_num_irand(&pow, b, &vm->rng);
1512*5a6e8488SAndroid Build Coastguard Worker
1513*5a6e8488SAndroid Build Coastguard Worker // Make the number entirely fraction.
1514*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRight(b, places);
1515*5a6e8488SAndroid Build Coastguard Worker
1516*5a6e8488SAndroid Build Coastguard Worker err:
1517*5a6e8488SAndroid Build Coastguard Worker
1518*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&pow);
1519*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1520*5a6e8488SAndroid Build Coastguard Worker }
1521*5a6e8488SAndroid Build Coastguard Worker
1522*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_frand(size_t places)1523*5a6e8488SAndroid Build Coastguard Worker bcl_frand(size_t places)
1524*5a6e8488SAndroid Build Coastguard Worker {
1525*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1526*5a6e8488SAndroid Build Coastguard Worker BclNum n;
1527*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1528*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1529*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1530*5a6e8488SAndroid Build Coastguard Worker
1531*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1532*5a6e8488SAndroid Build Coastguard Worker
1533*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1534*5a6e8488SAndroid Build Coastguard Worker
1535*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1536*5a6e8488SAndroid Build Coastguard Worker
1537*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the number.
1538*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(n));
1539*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
1540*5a6e8488SAndroid Build Coastguard Worker
1541*5a6e8488SAndroid Build Coastguard Worker bcl_frandHelper(BCL_NUM_NUM_NP(n), places);
1542*5a6e8488SAndroid Build Coastguard Worker
1543*5a6e8488SAndroid Build Coastguard Worker err:
1544*5a6e8488SAndroid Build Coastguard Worker
1545*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1546*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, n, idx);
1547*5a6e8488SAndroid Build Coastguard Worker
1548*5a6e8488SAndroid Build Coastguard Worker return idx;
1549*5a6e8488SAndroid Build Coastguard Worker }
1550*5a6e8488SAndroid Build Coastguard Worker
1551*5a6e8488SAndroid Build Coastguard Worker /**
1552*5a6e8488SAndroid Build Coastguard Worker * Helps bc_ifrand(). This is separate because error handling is easier that
1553*5a6e8488SAndroid Build Coastguard Worker * way.
1554*5a6e8488SAndroid Build Coastguard Worker * @param a The limit for bc_num_irand().
1555*5a6e8488SAndroid Build Coastguard Worker * @param b The return parameter.
1556*5a6e8488SAndroid Build Coastguard Worker * @param places The number of decimal places to generate.
1557*5a6e8488SAndroid Build Coastguard Worker */
1558*5a6e8488SAndroid Build Coastguard Worker static void
bcl_ifrandHelper(BcNum * restrict a,BcNum * restrict b,size_t places)1559*5a6e8488SAndroid Build Coastguard Worker bcl_ifrandHelper(BcNum* restrict a, BcNum* restrict b, size_t places)
1560*5a6e8488SAndroid Build Coastguard Worker {
1561*5a6e8488SAndroid Build Coastguard Worker BcNum ir, fr;
1562*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1563*5a6e8488SAndroid Build Coastguard Worker
1564*5a6e8488SAndroid Build Coastguard Worker // Clear the integer and fractional numbers.
1565*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(&ir);
1566*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(&fr);
1567*5a6e8488SAndroid Build Coastguard Worker
1568*5a6e8488SAndroid Build Coastguard Worker // Initialize the integer and fractional numbers.
1569*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&ir, BC_NUM_DEF_SIZE);
1570*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&fr, BC_NUM_DEF_SIZE);
1571*5a6e8488SAndroid Build Coastguard Worker
1572*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP(vm, err);
1573*5a6e8488SAndroid Build Coastguard Worker
1574*5a6e8488SAndroid Build Coastguard Worker bc_num_irand(a, &ir, &vm->rng);
1575*5a6e8488SAndroid Build Coastguard Worker bcl_frandHelper(&fr, places);
1576*5a6e8488SAndroid Build Coastguard Worker
1577*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&ir, &fr, b, 0);
1578*5a6e8488SAndroid Build Coastguard Worker
1579*5a6e8488SAndroid Build Coastguard Worker err:
1580*5a6e8488SAndroid Build Coastguard Worker
1581*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&fr);
1582*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&ir);
1583*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1584*5a6e8488SAndroid Build Coastguard Worker }
1585*5a6e8488SAndroid Build Coastguard Worker
1586*5a6e8488SAndroid Build Coastguard Worker static BclNumber
bcl_ifrand_helper(BclNumber a,size_t places,bool destruct)1587*5a6e8488SAndroid Build Coastguard Worker bcl_ifrand_helper(BclNumber a, size_t places, bool destruct)
1588*5a6e8488SAndroid Build Coastguard Worker {
1589*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1590*5a6e8488SAndroid Build Coastguard Worker BclNum* aptr;
1591*5a6e8488SAndroid Build Coastguard Worker BclNum b;
1592*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1593*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1594*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1595*5a6e8488SAndroid Build Coastguard Worker
1596*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1597*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM(ctxt, a);
1598*5a6e8488SAndroid Build Coastguard Worker
1599*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1600*5a6e8488SAndroid Build Coastguard Worker
1601*5a6e8488SAndroid Build Coastguard Worker BCL_GROW_NUMS(ctxt);
1602*5a6e8488SAndroid Build Coastguard Worker
1603*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(a) < ctxt->nums.len);
1604*5a6e8488SAndroid Build Coastguard Worker
1605*5a6e8488SAndroid Build Coastguard Worker aptr = BCL_NUM(ctxt, a);
1606*5a6e8488SAndroid Build Coastguard Worker
1607*5a6e8488SAndroid Build Coastguard Worker assert(aptr != NULL && BCL_NUM_NUM(aptr) != NULL);
1608*5a6e8488SAndroid Build Coastguard Worker
1609*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the number.
1610*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(b));
1611*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(b), BC_NUM_DEF_SIZE);
1612*5a6e8488SAndroid Build Coastguard Worker
1613*5a6e8488SAndroid Build Coastguard Worker bcl_ifrandHelper(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), places);
1614*5a6e8488SAndroid Build Coastguard Worker
1615*5a6e8488SAndroid Build Coastguard Worker err:
1616*5a6e8488SAndroid Build Coastguard Worker
1617*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1618*5a6e8488SAndroid Build Coastguard Worker {
1619*5a6e8488SAndroid Build Coastguard Worker // Eat the oprand.
1620*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, a, aptr);
1621*5a6e8488SAndroid Build Coastguard Worker }
1622*5a6e8488SAndroid Build Coastguard Worker
1623*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1624*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, b, idx);
1625*5a6e8488SAndroid Build Coastguard Worker
1626*5a6e8488SAndroid Build Coastguard Worker return idx;
1627*5a6e8488SAndroid Build Coastguard Worker }
1628*5a6e8488SAndroid Build Coastguard Worker
1629*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_ifrand(BclNumber a,size_t places)1630*5a6e8488SAndroid Build Coastguard Worker bcl_ifrand(BclNumber a, size_t places)
1631*5a6e8488SAndroid Build Coastguard Worker {
1632*5a6e8488SAndroid Build Coastguard Worker return bcl_ifrand_helper(a, places, true);
1633*5a6e8488SAndroid Build Coastguard Worker }
1634*5a6e8488SAndroid Build Coastguard Worker
1635*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_ifrand_keep(BclNumber a,size_t places)1636*5a6e8488SAndroid Build Coastguard Worker bcl_ifrand_keep(BclNumber a, size_t places)
1637*5a6e8488SAndroid Build Coastguard Worker {
1638*5a6e8488SAndroid Build Coastguard Worker return bcl_ifrand_helper(a, places, false);
1639*5a6e8488SAndroid Build Coastguard Worker }
1640*5a6e8488SAndroid Build Coastguard Worker
1641*5a6e8488SAndroid Build Coastguard Worker static BclError
bcl_rand_seedWithNum_helper(BclNumber n,bool destruct)1642*5a6e8488SAndroid Build Coastguard Worker bcl_rand_seedWithNum_helper(BclNumber n, bool destruct)
1643*5a6e8488SAndroid Build Coastguard Worker {
1644*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1645*5a6e8488SAndroid Build Coastguard Worker BclNum* nptr;
1646*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1647*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1648*5a6e8488SAndroid Build Coastguard Worker
1649*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT_ERR(vm, ctxt);
1650*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_NUM_ERR(ctxt, n);
1651*5a6e8488SAndroid Build Coastguard Worker
1652*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1653*5a6e8488SAndroid Build Coastguard Worker
1654*5a6e8488SAndroid Build Coastguard Worker assert(BCL_NO_GEN(n) < ctxt->nums.len);
1655*5a6e8488SAndroid Build Coastguard Worker
1656*5a6e8488SAndroid Build Coastguard Worker nptr = BCL_NUM(ctxt, n);
1657*5a6e8488SAndroid Build Coastguard Worker
1658*5a6e8488SAndroid Build Coastguard Worker assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
1659*5a6e8488SAndroid Build Coastguard Worker
1660*5a6e8488SAndroid Build Coastguard Worker bc_num_rng(BCL_NUM_NUM(nptr), &vm->rng);
1661*5a6e8488SAndroid Build Coastguard Worker
1662*5a6e8488SAndroid Build Coastguard Worker err:
1663*5a6e8488SAndroid Build Coastguard Worker
1664*5a6e8488SAndroid Build Coastguard Worker if (destruct)
1665*5a6e8488SAndroid Build Coastguard Worker {
1666*5a6e8488SAndroid Build Coastguard Worker // Eat the oprand.
1667*5a6e8488SAndroid Build Coastguard Worker bcl_num_dtor(ctxt, n, nptr);
1668*5a6e8488SAndroid Build Coastguard Worker }
1669*5a6e8488SAndroid Build Coastguard Worker
1670*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1671*5a6e8488SAndroid Build Coastguard Worker
1672*5a6e8488SAndroid Build Coastguard Worker return e;
1673*5a6e8488SAndroid Build Coastguard Worker }
1674*5a6e8488SAndroid Build Coastguard Worker
1675*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_rand_seedWithNum(BclNumber n)1676*5a6e8488SAndroid Build Coastguard Worker bcl_rand_seedWithNum(BclNumber n)
1677*5a6e8488SAndroid Build Coastguard Worker {
1678*5a6e8488SAndroid Build Coastguard Worker return bcl_rand_seedWithNum_helper(n, true);
1679*5a6e8488SAndroid Build Coastguard Worker }
1680*5a6e8488SAndroid Build Coastguard Worker
1681*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_rand_seedWithNum_keep(BclNumber n)1682*5a6e8488SAndroid Build Coastguard Worker bcl_rand_seedWithNum_keep(BclNumber n)
1683*5a6e8488SAndroid Build Coastguard Worker {
1684*5a6e8488SAndroid Build Coastguard Worker return bcl_rand_seedWithNum_helper(n, false);
1685*5a6e8488SAndroid Build Coastguard Worker }
1686*5a6e8488SAndroid Build Coastguard Worker
1687*5a6e8488SAndroid Build Coastguard Worker BclError
bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])1688*5a6e8488SAndroid Build Coastguard Worker bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])
1689*5a6e8488SAndroid Build Coastguard Worker {
1690*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1691*5a6e8488SAndroid Build Coastguard Worker size_t i;
1692*5a6e8488SAndroid Build Coastguard Worker ulong vals[BCL_SEED_ULONGS];
1693*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1694*5a6e8488SAndroid Build Coastguard Worker
1695*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1696*5a6e8488SAndroid Build Coastguard Worker
1697*5a6e8488SAndroid Build Coastguard Worker // Fill the array.
1698*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < BCL_SEED_SIZE; ++i)
1699*5a6e8488SAndroid Build Coastguard Worker {
1700*5a6e8488SAndroid Build Coastguard Worker ulong val = ((ulong) seed[i])
1701*5a6e8488SAndroid Build Coastguard Worker << (((ulong) CHAR_BIT) * (i % sizeof(ulong)));
1702*5a6e8488SAndroid Build Coastguard Worker vals[i / sizeof(long)] |= val;
1703*5a6e8488SAndroid Build Coastguard Worker }
1704*5a6e8488SAndroid Build Coastguard Worker
1705*5a6e8488SAndroid Build Coastguard Worker bc_rand_seed(&vm->rng, vals[0], vals[1], vals[2], vals[3]);
1706*5a6e8488SAndroid Build Coastguard Worker
1707*5a6e8488SAndroid Build Coastguard Worker err:
1708*5a6e8488SAndroid Build Coastguard Worker
1709*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1710*5a6e8488SAndroid Build Coastguard Worker
1711*5a6e8488SAndroid Build Coastguard Worker return e;
1712*5a6e8488SAndroid Build Coastguard Worker }
1713*5a6e8488SAndroid Build Coastguard Worker
1714*5a6e8488SAndroid Build Coastguard Worker void
bcl_rand_reseed(void)1715*5a6e8488SAndroid Build Coastguard Worker bcl_rand_reseed(void)
1716*5a6e8488SAndroid Build Coastguard Worker {
1717*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1718*5a6e8488SAndroid Build Coastguard Worker
1719*5a6e8488SAndroid Build Coastguard Worker bc_rand_srand(bc_vec_top(&vm->rng.v));
1720*5a6e8488SAndroid Build Coastguard Worker }
1721*5a6e8488SAndroid Build Coastguard Worker
1722*5a6e8488SAndroid Build Coastguard Worker BclNumber
bcl_rand_seed2num(void)1723*5a6e8488SAndroid Build Coastguard Worker bcl_rand_seed2num(void)
1724*5a6e8488SAndroid Build Coastguard Worker {
1725*5a6e8488SAndroid Build Coastguard Worker BclError e = BCL_ERROR_NONE;
1726*5a6e8488SAndroid Build Coastguard Worker BclNum n;
1727*5a6e8488SAndroid Build Coastguard Worker BclNumber idx;
1728*5a6e8488SAndroid Build Coastguard Worker BclContext ctxt;
1729*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1730*5a6e8488SAndroid Build Coastguard Worker
1731*5a6e8488SAndroid Build Coastguard Worker BC_CHECK_CTXT(vm, ctxt);
1732*5a6e8488SAndroid Build Coastguard Worker
1733*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_HEADER(vm, err);
1734*5a6e8488SAndroid Build Coastguard Worker
1735*5a6e8488SAndroid Build Coastguard Worker // Clear and initialize the number.
1736*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BCL_NUM_NUM_NP(n));
1737*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
1738*5a6e8488SAndroid Build Coastguard Worker
1739*5a6e8488SAndroid Build Coastguard Worker bc_num_createFromRNG(BCL_NUM_NUM_NP(n), &vm->rng);
1740*5a6e8488SAndroid Build Coastguard Worker
1741*5a6e8488SAndroid Build Coastguard Worker err:
1742*5a6e8488SAndroid Build Coastguard Worker
1743*5a6e8488SAndroid Build Coastguard Worker BC_FUNC_FOOTER(vm, e);
1744*5a6e8488SAndroid Build Coastguard Worker BC_MAYBE_SETUP(ctxt, e, n, idx);
1745*5a6e8488SAndroid Build Coastguard Worker
1746*5a6e8488SAndroid Build Coastguard Worker return idx;
1747*5a6e8488SAndroid Build Coastguard Worker }
1748*5a6e8488SAndroid Build Coastguard Worker
1749*5a6e8488SAndroid Build Coastguard Worker BclRandInt
bcl_rand_int(void)1750*5a6e8488SAndroid Build Coastguard Worker bcl_rand_int(void)
1751*5a6e8488SAndroid Build Coastguard Worker {
1752*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1753*5a6e8488SAndroid Build Coastguard Worker
1754*5a6e8488SAndroid Build Coastguard Worker return (BclRandInt) bc_rand_int(&vm->rng);
1755*5a6e8488SAndroid Build Coastguard Worker }
1756*5a6e8488SAndroid Build Coastguard Worker
1757*5a6e8488SAndroid Build Coastguard Worker BclRandInt
bcl_rand_bounded(BclRandInt bound)1758*5a6e8488SAndroid Build Coastguard Worker bcl_rand_bounded(BclRandInt bound)
1759*5a6e8488SAndroid Build Coastguard Worker {
1760*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1761*5a6e8488SAndroid Build Coastguard Worker
1762*5a6e8488SAndroid Build Coastguard Worker if (bound <= 1) return 0;
1763*5a6e8488SAndroid Build Coastguard Worker return (BclRandInt) bc_rand_bounded(&vm->rng, (BcRand) bound);
1764*5a6e8488SAndroid Build Coastguard Worker }
1765*5a6e8488SAndroid Build Coastguard Worker
1766*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1767*5a6e8488SAndroid Build Coastguard Worker
1768*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
1769