xref: /aosp_15_r20/external/bc/src/library.c (revision 5a6e848804d15c18a0125914844ee4eb0bda4fcf)
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