-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathbigdigits.h
580 lines (457 loc) · 20.6 KB
/
bigdigits.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
/* $Id: bigdigits.h $ */
/** @file
Interface to core BigDigits "mp" functions using fixed-length arrays
*/
/***** BEGIN LICENSE BLOCK *****
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2001-16 David Ireland, D.I. Management Services Pty Limited
* <http://www.di-mgt.com.au/bigdigits.html>. All rights reserved.
*
***** END LICENSE BLOCK *****/
/*
* Last updated:
* $Date: 2016-03-31 09:51:00 $
* $Revision: 2.6.1 $
* $Author: dai $
*/
#ifndef BIGDIGITS_H_
#define BIGDIGITS_H_ 1
#include <cctype> // workaround for a bug in the embarcadero headers
#include <cstdlib>
#include "bigdtypes.h"
namespace DotNetPELib { // DAL
/**** USER CONFIGURABLE SECTION ****/
/* Define type and size of DIGIT */
/* [v2.1] Changed to use C99 exact-width types. */
/* [v2.2] Put macros for exact-width types in separate file "bigdtypes.h" */
/** The basic BigDigit element, an unsigned 32-bit integer */
typedef uint32_t DIGIT_T;
/** @cond */
typedef uint16_t HALF_DIGIT_T;
/* Sizes to match */
#define MAX_DIGIT 0xFFFFFFFFUL
#define MAX_HALF_DIGIT 0xFFFFUL /* NB 'L' */
#define BITS_PER_DIGIT 32
#define HIBITMASK 0x80000000UL
/* [v2.2] added option to avoid allocating temp storage in the heap
and use (faster) fixed automatic arrays on the stack instead.
Define NO_ALLOCS to invoke this.
Only applicable to mp functions. Do not use with bd.
*/
/* Specify the maximum number of digits allowed in a temp mp array
-- ignored unless NO_ALLOCS is defined
-- [v2.6] user may override MAX_FIXED_BIT_LENGTH with global definition
e.g. /D "MAX_FIXED_BIT_LENGTH=640" or -D MAX_FIXED_BIT_LENGTH=640
*/
#ifdef NO_ALLOCS
#ifndef MAX_FIXED_BIT_LENGTH
#define MAX_FIXED_BIT_LENGTH 8192
#endif
#define MAX_FIXED_DIGITS ((MAX_FIXED_BIT_LENGTH + BITS_PER_DIGIT - 1) / BITS_PER_DIGIT)
#endif
/**** END OF USER CONFIGURABLE SECTION ****/
/**** OPTIONAL PREPROCESSOR DEFINITIONS ****/
/*
Choose one of {USE_SPASM | USE_64WITH32}
USE_SPASM: to use the faster x86 ASM routines (if __asm option is available with your compiler).
USE_64WITH32: to use the 64-bit integers if available (e.g. long long).
Default: use default internal routines spDivide and spMultiply.
The USE_SPASM option takes precedence over USE_64WITH32.
*/
/* Useful macros */
#define ISODD(x) ((x) & 0x1)
#define ISEVEN(x) (!ISODD(x))
#define mpISODD(x, n) (x[0] & 0x1)
#define mpISEVEN(x, n) (!(x[0] & 0x1))
#ifdef __cplusplus
//extern "C" {
#endif
/* Forces linker to include copyright notice in executable */
volatile char *copyright_notice(void);
/** @endcond */
/*
* Multiple precision calculations
* Using known, equal ndigits
* except where noted
*/
/*************************/
/* ARITHMETIC OPERATIONS */
/*************************/
/** Computes w = u + v, returns carry
@pre `w` and `v` must not overlap.
*/
DIGIT_T mpAdd(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T v[], size_t ndigits);
/** Computes w = u - v, returns borrow
@pre `w` and `v` must not overlap.
*/
DIGIT_T mpSubtract(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T v[], size_t ndigits);
/** Computes product w = u * v
@param[out] w To receive the product, an array of size 2 x `ndigits`
@param[in] u An array of size `ndigits`
@param[in] v An array of size `ndigits`
@param[in] ndigits size of arrays `u` and `v`
@pre `w` and `u` must not overlap.
@warning The product must be of size 2 x `ndigits`
*/
int mpMultiply(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T v[], size_t ndigits);
/** Computes integer division of u by v such that u=qv+r
@param[out] q to receive quotient = u div v, an array of size `udigits`
@param[out] r to receive divisor = u mod v, an array of size `udigits`
@param[in] u dividend of size `udigits`
@param[in] udigits size of arrays `q` `r` and `u`
@param[in] v divisor of size `vdigits`
@param[in] vdigits size of array `v`
@pre `q` and `r` must be independent of `u` and `v`.
@warning Trashes q and r first
*/
int mpDivide(DIGIT_T q[], DIGIT_T r[], const DIGIT_T u[],
size_t udigits, DIGIT_T v[], size_t vdigits);
/** Computes remainder r = u mod v
@param[out] r to receive divisor = u mod v, an array of size `vdigits`
@param[in] u dividend of size `udigits`
@param[in] udigits size of arrays `r` and `u`
@param[in] v divisor of size `vdigits`
@param[in] vdigits size of array `v`
@pre `r` and `u` must not overlap.
@remark Note that `r` is `vdigits` long here, but is `udigits` long in mpDivide().
*/
int mpModulo(DIGIT_T r[], const DIGIT_T u[], size_t udigits, DIGIT_T v[], size_t vdigits);
/** Computes square w = x^2
@param[out] w array of size 2 x `ndigits` to receive square
@param[in] x array of size `ndigits`
@param[in] ndigits size of array `x`
@pre `w` and `x` must not overlap.
@warning The product `w` must be of size 2 x `ndigits`
*/
int mpSquare(DIGIT_T w[], const DIGIT_T x[], size_t ndigits);
/** Computes integer square root s = floor(sqrt(x)) */
int mpSqrt(DIGIT_T s[], const DIGIT_T x[], size_t ndigits);
/** Computes integer cube root s = floor(cuberoot(x)) */
int mpCubeRoot(DIGIT_T s[], const DIGIT_T x[], size_t ndigits);
/*************************/
/* COMPARISON OPERATIONS */
/*************************/
/** Returns true if a == b, else false
* @remark Not constant-time.
*/
int mpEqual(const DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/** Returns sign of `(a-b)` as `{-1,0,+1}`
* @remark Not constant-time.
*/
int mpCompare(const DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/** Returns true if a is zero, else false
* @remark Not constant-time.
*/
int mpIsZero(const DIGIT_T a[], size_t ndigits);
/***************************************/
/* CONSTANT-TIME COMPARISON ALGORITHMS */
/***************************************/
/* -- added [v2.5] to replace originals. Renamed as "_ct" in [v2.6] */
/** Returns true if a == b, else false, using constant-time algorithm */
int mpEqual_ct(const DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/** Returns sign of `(a-b)` as `{-1,0,+1}` using constant-time algorithm */
int mpCompare_ct(const DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/** Returns true if a is zero, else false, using constant-time algorithm */
int mpIsZero_ct(const DIGIT_T a[], size_t ndigits);
/* Keep the faith for [v2.5] users - DEPRECATED in [v2.6] */
#define mpEqual_q(a,b,n) mpEqual((a),(b),(n))
#define mpCompare_q(a,b,n) mpCompare((a),(b),(n))
#define mpIsZero_q(a,n) mpIsZero((a),(n))
/****************************/
/* NUMBER THEORY OPERATIONS */
/****************************/
/* [v2.2] removed `const` restriction on m[] for mpModMult and mpModExp
* (to allow faster in-place manipulation instead of using a temp variable).
* [v2.5] added mpModExp_ct(), a constant-time variant of mpModExp().
* [v2.6] added mpModSquare(), mpModAdd(), mpModSubtract() and mpModSqrt().
*/
/** Computes y = x^e mod m */
int mpModExp(DIGIT_T y[], const DIGIT_T x[], const DIGIT_T e[], DIGIT_T m[], size_t ndigits);
/** Computes y = x^e mod m in constant time
* @remark Resistant to simple power analysis attack on private exponent.
* Slower than mpModExp().
*/
int mpModExp_ct(DIGIT_T yout[], const DIGIT_T x[], const DIGIT_T e[], DIGIT_T m[], size_t ndigits);
/** Computes a = (x * y) mod m */
int mpModMult(DIGIT_T a[], const DIGIT_T x[], const DIGIT_T y[], DIGIT_T m[], size_t ndigits);
/** Computes a = x^2 mod m */
int mpModSquare(DIGIT_T a[], const DIGIT_T x[], DIGIT_T m[], size_t ndigits);
/** Computes the inverse of `u` modulo `m`, inv = u^{-1} mod m */
int mpModInv(DIGIT_T inv[], const DIGIT_T u[], const DIGIT_T m[], size_t ndigits);
/** Computes g = gcd(x, y), the greatest common divisor of x and y */
int mpGcd(DIGIT_T g[], const DIGIT_T x[], const DIGIT_T y[], size_t ndigits);
/** Returns the Jacobi symbol (a/n) in {-1, 0, +1}
@remark If n is prime then the Jacobi symbol becomes the Legendre symbol (a/p) defined to be
- (a/p) = +1 if a is a quadratic residue modulo p
- (a/p) = -1 if a is a quadratic non-residue modulo p
- (a/p) = 0 if a is divisible by p
*/
int mpJacobi(const DIGIT_T a[], const DIGIT_T n[], size_t ndigits);
/** Computes x = one square root of an integer `a` modulo an odd prime `p`
* @param x To receive the result
* @param a An integer expected to be a quadratic residue modulo p
* @param p An odd prime
* @param ndigits The number of digits in each of the parameters
* @return 0 if successful, or -1 if square root does not exist
* @remark More precisely, find an integer x such that x^2 mod p = a.
* Uses the Tonelli-Shanks algorithm. The other square root is `p - x`.
* @warning Check the return value before using the result `x`.
*/
int mpModSqrt(DIGIT_T x[], const DIGIT_T a[], DIGIT_T p[], size_t ndigits);
/** Computes w = u/2 (mod p) for an odd prime p
* @pre Require u to be in the range `[0,p-1]` */
void mpModHalve(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T p[], size_t ndigits);
/** Computes w = u + v (mod m)
* @pre Require u and v to be in the range `[0, m-1]`.
* The variables `w` and `v` must not overlap.
* @remark Quicker than adding then using mpModulo()
*/
void mpModAdd(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T v[], const DIGIT_T m[], size_t ndigits);
/** Computes w = u - v (mod m)
* @pre Require u and v to be in the range `[0, m-1]`.
* The variables `w` and `v` must not overlap.
* @remark Quicker than subtracting then using mpModulo()
*/
void mpModSub(DIGIT_T w[], const DIGIT_T u[], const DIGIT_T v[], const DIGIT_T m[], size_t ndigits);
/** Computes u = v (mod m) in the special case where `0<=v<km` for small k
* @remark Uses subtraction instead of division, so is much faster than mpModulo() in this case.
* @pre `v` is in the range `[0,km]` where `k` is a small integer
* @warning Use only if you know `k` is small, say < 3.
*/
void mpModSpecial(DIGIT_T u[], const DIGIT_T v[], const DIGIT_T m[], size_t ndigits);
/**********************/
/* BITWISE OPERATIONS */
/**********************/
/** Returns number of significant bits in a */
size_t mpBitLength(const DIGIT_T a[], size_t ndigits);
/** Computes a = b << x */
DIGIT_T mpShiftLeft(DIGIT_T a[], const DIGIT_T b[], size_t x, size_t ndigits);
/** Computes a = b >> x */
DIGIT_T mpShiftRight(DIGIT_T a[], const DIGIT_T b[], size_t x, size_t ndigits);
/** Computes bitwise a = b XOR c */
void mpXorBits(DIGIT_T a[], const DIGIT_T b[], const DIGIT_T c[], size_t ndigits);
/** Computes bitwise a = b OR c */
void mpOrBits(DIGIT_T a[], const DIGIT_T b[], const DIGIT_T c[], size_t ndigits);
/** Computes bitwise a = b AND c */
void mpAndBits(DIGIT_T a[], const DIGIT_T b[], const DIGIT_T c[], size_t ndigits);
/** Computes bitwise a = NOT b */
void mpNotBits(DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/** Computes a = a mod 2^L, ie clears all bits greater than L */
void mpModPowerOf2(DIGIT_T a[], size_t ndigits, size_t L);
/** Sets bit n of a (0..nbits-1) with value 1 or 0 */
int mpSetBit(DIGIT_T a[], size_t ndigits, size_t n, int value);
/** Returns value 1 or 0 of bit n (0..nbits-1) */
int mpGetBit(const DIGIT_T a[], size_t ndigits, size_t n);
/*************************/
/* ASSIGNMENT OPERATIONS */
/*************************/
/** Sets a = 0 */
volatile DIGIT_T mpSetZero(volatile DIGIT_T a[], size_t ndigits);
/** Sets a = d where d is a single digit */
void mpSetDigit(DIGIT_T a[], DIGIT_T d, size_t ndigits);
/** Sets a = b */
void mpSetEqual(DIGIT_T a[], const DIGIT_T b[], size_t ndigits);
/**********************/
/* OTHER MP UTILITIES */
/**********************/
/** Returns number of significant non-zero digits in a */
size_t mpSizeof(const DIGIT_T a[], size_t ndigits);
/** Returns true (1) if `w` is probably prime
@param[in] w Number to test
@param[in] ndigits size of array `w`
@param[in] t The count of Rabin-Miller primality tests to carry out (recommended at least 80)
@returns true (1) if w is probably prime otherwise false (0)
@remark Uses FIPS-186-2/Rabin-Miller with trial division by small primes,
which is faster in most cases than mpRabinMiller().
@see mpRabinMiller().
*/
int mpIsPrime(DIGIT_T w[], size_t ndigits, size_t t);
/** Returns true (1) if `w` is probably prime using just the Rabin-Miller test
@see mpIsPrime() is preferred.
*/
int mpRabinMiller(DIGIT_T w[], size_t ndigits, size_t t);
/**********************************************/
/* FUNCTIONS THAT OPERATE WITH A SINGLE DIGIT */
/**********************************************/
/** Computes w = u + d, returns carry */
DIGIT_T mpShortAdd(DIGIT_T w[], const DIGIT_T u[], DIGIT_T d, size_t ndigits);
/** Computes w = u - d, returns borrow */
DIGIT_T mpShortSub(DIGIT_T w[], const DIGIT_T u[], DIGIT_T d, size_t ndigits);
/** Computes product p = x * d */
DIGIT_T mpShortMult(DIGIT_T p[], const DIGIT_T x[], DIGIT_T d, size_t ndigits);
/** Computes quotient q = u div d, returns remainder */
DIGIT_T mpShortDiv(DIGIT_T q[], const DIGIT_T u[], DIGIT_T d, size_t ndigits);
/** Computes remainder r = a mod d */
DIGIT_T mpShortMod(const DIGIT_T a[], DIGIT_T d, size_t ndigits);
/** Returns sign of (a - d) where d is a single digit */
int mpShortCmp(const DIGIT_T a[], DIGIT_T d, size_t ndigits);
/** Returns true if a == d, else false, where d is a single digit */
int mpShortIsEqual(const DIGIT_T a[], DIGIT_T d, size_t ndigits);
/** Returns the least significant digit in a */
DIGIT_T mpToShort(const DIGIT_T a[], size_t ndigits);
/**************************************/
/* CORE SINGLE PRECISION CALCULATIONS */
/* (double where necessary) */
/**************************************/
/* NOTE spMultiply and spDivide are used by almost all mp functions.
Using the Intel MASM alternatives gives significant speed improvements
-- to use, define USE_SPASM as a preprocessor directive.
[v2.2] Removed references to spasm* versions.
*/
/** Computes p = x * y, where x and y are single digits */
int spMultiply(DIGIT_T p[2], DIGIT_T x, DIGIT_T y);
/** Computes quotient q = u div v, remainder r = u mod v, where q, r and v are single digits */
DIGIT_T spDivide(DIGIT_T *q, DIGIT_T *r, const DIGIT_T u[2], DIGIT_T v);
/****************************/
/* RANDOM NUMBER FUNCTIONS */
/* CAUTION: NOT thread-safe */
/****************************/
/** Returns a simple pseudo-random digit between lower and upper.
@remark Not crypto secure.
@see spBetterRand()
*/
DIGIT_T spSimpleRand(DIGIT_T lower, DIGIT_T upper);
/** Generate a quick-and-dirty random mp number a of bit length at most `nbits` using plain-old-rand
@remark Not crypto secure.
@see mpRandomBits()
*/
size_t mpQuickRandBits(DIGIT_T a[], size_t ndigits, size_t nbits);
/* [Version 2.1: spBetterRand moved to spRandom.h] */
/*******************/
/* PRINT UTILITIES */
/*******************/
/* [v2.3] Added these more convenient print functions */
/** Print in hex format with optional prefix and suffix strings */
void mpPrintHex(const char *prefix, const DIGIT_T *a, size_t ndigits, const char *suffix);
/** Print in decimal format with optional prefix and suffix strings */
void mpPrintDecimal(const char *prefix, const DIGIT_T *a, size_t ndigits, const char *suffix);
/* See also mpPrintDecimalSigned() - new in [v2.5] */
/* New in [v2.6] */
/** Print in bit (0/1) format with optional prefix and suffix strings */
void mpPrintBits(const char *prefix, DIGIT_T *a, size_t ndigits, const char *suffix);
/* OLDER PRINT FUNCTIONS, ALL PRINTING IN HEX */
/** Print all digits in hex incl leading zero digits */
void mpPrint(const DIGIT_T *a, size_t ndigits);
/** Print all digits in hex with newlines */
void mpPrintNL(const DIGIT_T *a, size_t ndigits);
/** Print in hex but trim leading zero digits
@deprecated Use mpPrintHex()
*/
void mpPrintTrim(const DIGIT_T *a, size_t ndigits);
/** Print in hex, trim leading zeroes, add newlines
@deprecated Use mpPrintHex()
*/
void mpPrintTrimNL(const DIGIT_T *a, size_t ndigits);
/************************/
/* CONVERSION UTILITIES */
/************************/
/** Converts nbytes octets into big digit a of max size ndigits
@returns actual number of digits set */
size_t mpConvFromOctets(DIGIT_T a[], size_t ndigits, const unsigned char *c, size_t nbytes);
/** Converts big digit a into string of octets, in big-endian order, padding to nbytes or truncating if necessary.
@returns number of non-zero octets required. */
size_t mpConvToOctets(const DIGIT_T a[], size_t ndigits, unsigned char *c, size_t nbytes);
/** Converts a string in decimal format to a big digit.
@returns actual number of (possibly zero) digits set. */
size_t mpConvFromDecimal(DIGIT_T a[], size_t ndigits, const char *s);
/** Converts big digit a into a string in decimal format, where s has size smax including the terminating zero.
@returns number of chars required excluding leading zeroes. */
size_t mpConvToDecimal(const DIGIT_T a[], size_t ndigits, char *s, size_t smax);
/** Converts a string in hexadecimal format to a big digit.
@return actual number of (possibly zero) digits set. */
size_t mpConvFromHex(DIGIT_T a[], size_t ndigits, const char *s);
/** Converts big digit a into a string in hexadecimal format,
where s has size smax including the terminating zero.
@return number of chars required excluding leading zeroes. */
size_t mpConvToHex(const DIGIT_T a[], size_t ndigits, char *s, size_t smax);
/****************************/
/* SIGNED INTEGER FUNCTIONS */
/****************************/
/*
NOTES ON SIGNED-INTEGER OPERATIONS
----------------------------------
You can choose to treat BigDigits integers as "signed" with their values stored in two's-complement representation.
A negative number will be a BigDigit integer with its left-most bit set to one, i.e.
mpGetBit(a, ndigits, (ndigits * BITS_PER_DIGIT - 1)) == 1
This works automatically for simple arithmetic operations like add, subtract and multiply (but not division).
For example,
mpSetDigit(u, 2, NDIGITS);
mpSetDigit(v, 5, NDIGITS);
mpSubtract(w, u, v, NDIGITS);
mpPrintDecimalSigned("signed w=", w, NDIGITS, "\n");
mpPrintHex("unsigned w=", w, NDIGITS, "\n");
will result in the output
signed w=-3
unsigned w=0xfffffffffffffffffffffffffffffffd
It does *not* work for division or any number-theoretic function like mpModExp(),
all of which treat their parameters as "unsigned" integers and will not give the "signed" result you expect.
To set a small negative number do:
mpSetDigit(v, 5, NDIGITS);
mpChs(v, v, NDIGITS);
--------------
*/
/** Returns true (1) if x < 0, else false (0)
* @remark Expects a negative number to be stored in two's-complement representation.
*/
int mpIsNegative(const DIGIT_T x[], size_t ndigits);
/** Sets x = -y
* @remark Expects a negative number to be stored in two's-complement representation.
*/
int mpChs(DIGIT_T x[], const DIGIT_T y[], size_t ndigits);
/** Sets x = |y|, the absolute value of y
* @remark Expects a negative number to be stored in two's-complement representation.
*/
int mpAbs(DIGIT_T x[], const DIGIT_T y[], size_t ndigits);
/* New in [v2.5] - note that `a` is not `const` */
/** Print a signed integer in decimal format with optional prefix and suffix strings
* @remark Expects a negative number to be stored in two's-complement representation.
*/
void mpPrintDecimalSigned(const char *prefix, DIGIT_T *a, size_t ndigits, const char *suffix);
/****************/
/* VERSION INFO */
/****************/
/** Returns version number = major*1000+minor*100+release*10+PP_OPTIONS */
int mpVersion(void);
/* Version number = major*1000+minor*100+release*10+uses_asm(0|1)+uses_64(0|2)+uses_noalloc(0|5)
E.g. Version 2.3.0 will return 230x where x denotes the preprocessor options
x | USE_SPASM | USE_64WITH32 | NO_ALLOCS
----------------------------------------
0 No No No
1 Yes No No
2 No Yes No
3 Yes Yes* No
5 No No Yes
6 Yes No Yes
7 No Yes Yes
8 Yes Yes* Yes
----------------------------------------
* USE_SPASM will take precedence over USE_64WITH32.
*/
/** Returns a pointer to a static string containing the time of compilation */
const char *mpCompileTime(void);
/** @cond */
/*************************************************************/
/* MEMORY ALLOCATION FUNCTIONS - USED INTERNALLY AND BY BIGD */
/*************************************************************/
/* [v2.2] added option to avoid memory allocation if NO_ALLOCS is defined */
#ifndef NO_ALLOCS
DIGIT_T *mpAlloc(size_t ndigits);
void mpFree(DIGIT_T **p);
#endif
void mpFail(char *msg);
/* Clean up by zeroising and freeing allocated memory */
#ifdef NO_ALLOCS
#define mpDESTROY(b, n) do{if(b)mpSetZero(b,n);}while(0)
#else
#define mpDESTROY(b, n) do{if(b)mpSetZero(b,n);mpFree(&b);}while(0)
#endif
/** @endcond */
#ifdef __cplusplus
//}
#endif
} // namespace DAL
#endif /* BIGDIGITS_H_ */