124 lines
4.7 KiB
C
124 lines
4.7 KiB
C
#ifndef __BIGNUM_H__
|
|
#define __BIGNUM_H__
|
|
/*
|
|
|
|
Big number library - arithmetic on multiple-precision unsigned integers.
|
|
|
|
This library is an implementation of arithmetic on arbitrarily large integers.
|
|
|
|
The difference between this and other implementations, is that the data structure
|
|
has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM),
|
|
and all memory is allocated statically: no dynamic allocation for better or worse.
|
|
|
|
Primary goals are correctness, clarity of code and clean, portable implementation.
|
|
Secondary goal is a memory footprint small enough to make it suitable for use in
|
|
embedded applications.
|
|
|
|
|
|
The current state is correct functionality and adequate performance.
|
|
There may well be room for performance-optimizations and improvements.
|
|
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <assert.h>
|
|
|
|
|
|
/* This macro defines the word size in bytes of the array that constitues the big-number data structure. */
|
|
#ifndef WORD_SIZE
|
|
#define WORD_SIZE 4
|
|
#endif
|
|
|
|
/* Size of big-numbers in bytes */
|
|
#define BN_ARRAY_SIZE (128 / WORD_SIZE)
|
|
|
|
|
|
/* Here comes the compile-time specialization for how large the underlying array size should be. */
|
|
/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */
|
|
#ifndef WORD_SIZE
|
|
#error Must define WORD_SIZE to be 1, 2, 4
|
|
#elif (WORD_SIZE == 1)
|
|
/* Data type of array in structure */
|
|
#define DTYPE uint8_t
|
|
/* bitmask for getting MSB */
|
|
#define DTYPE_MSB ((DTYPE_TMP)(0x80))
|
|
/* Data-type larger than DTYPE, for holding intermediate results of calculations */
|
|
#define DTYPE_TMP uint32_t
|
|
/* sprintf format string */
|
|
#define SPRINTF_FORMAT_STR "%.02x"
|
|
#define SSCANF_FORMAT_STR "%2hhx"
|
|
/* Max value of integer type */
|
|
#define MAX_VAL ((DTYPE_TMP)0xFF)
|
|
#elif (WORD_SIZE == 2)
|
|
#define DTYPE uint16_t
|
|
#define DTYPE_TMP uint32_t
|
|
#define DTYPE_MSB ((DTYPE_TMP)(0x8000))
|
|
#define SPRINTF_FORMAT_STR "%.04x"
|
|
#define SSCANF_FORMAT_STR "%4hx"
|
|
#define MAX_VAL ((DTYPE_TMP)0xFFFF)
|
|
#elif (WORD_SIZE == 4)
|
|
#define DTYPE uint32_t
|
|
#define DTYPE_TMP uint64_t
|
|
#define DTYPE_MSB ((DTYPE_TMP)(0x80000000))
|
|
#define SPRINTF_FORMAT_STR "%.08x"
|
|
#define SSCANF_FORMAT_STR "%8x"
|
|
#define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF)
|
|
#endif
|
|
#ifndef DTYPE
|
|
#error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever
|
|
#endif
|
|
|
|
|
|
/* Custom assert macro - easy to disable */
|
|
#define require(p, msg) assert(p && #msg)
|
|
|
|
|
|
/* Data-holding structure: array of DTYPEs */
|
|
struct bn
|
|
{
|
|
DTYPE array[BN_ARRAY_SIZE];
|
|
};
|
|
|
|
|
|
|
|
/* Tokens returned by bignum_cmp() for value comparison */
|
|
enum { SMALLER = -1, EQUAL = 0, LARGER = 1 };
|
|
|
|
|
|
|
|
/* Initialization functions: */
|
|
void bignum_init(struct bn* n);
|
|
void bignum_from_int(struct bn* n, DTYPE_TMP i);
|
|
int bignum_to_int(struct bn* n);
|
|
void bignum_from_string(struct bn* n, char* str, int nbytes);
|
|
void bignum_to_string(struct bn* n, char* str, int maxsize);
|
|
|
|
/* Basic arithmetic operations: */
|
|
void bignum_add(struct bn* a, struct bn* b, struct bn* c); /* c = a + b */
|
|
void bignum_sub(struct bn* a, struct bn* b, struct bn* c); /* c = a - b */
|
|
void bignum_mul(struct bn* a, struct bn* b, struct bn* c); /* c = a * b */
|
|
void bignum_div(struct bn* a, struct bn* b, struct bn* c); /* c = a / b */
|
|
void bignum_mod(struct bn* a, struct bn* b, struct bn* c); /* c = a % b */
|
|
void bignum_divmod(struct bn* a, struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */
|
|
|
|
/* Bitwise operations: */
|
|
void bignum_and(struct bn* a, struct bn* b, struct bn* c); /* c = a & b */
|
|
void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */
|
|
void bignum_xor(struct bn* a, struct bn* b, struct bn* c); /* c = a ^ b */
|
|
void bignum_lshift(struct bn* a, struct bn* b, int nbits); /* b = a << nbits */
|
|
void bignum_rshift(struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */
|
|
|
|
/* Special operators and comparison */
|
|
int bignum_cmp(struct bn* a, struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */
|
|
int bignum_is_zero(struct bn* n); /* For comparison with zero */
|
|
void bignum_inc(struct bn* n); /* Increment: add one to n */
|
|
void bignum_dec(struct bn* n); /* Decrement: subtract one from n */
|
|
void bignum_pow(struct bn* a, struct bn* b, struct bn* c); /* Calculate a^b -- e.g. 2^10 => 1024 */
|
|
void bignum_isqrt(struct bn* a, struct bn* b); /* Integer square root -- e.g. isqrt(5) => 2*/
|
|
void bignum_assign(struct bn* dst, struct bn* src); /* Copy src into dst -- dst := src */
|
|
|
|
|
|
#endif /* #ifndef __BIGNUM_H__ */
|
|
|
|
|