mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 03:30:17 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
433 lines
8.8 KiB
C
433 lines
8.8 KiB
C
/*
|
|
* mplogic.c
|
|
*
|
|
* Bitwise logical operations on MPI values
|
|
*
|
|
* 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/. */
|
|
|
|
#include "mpi-priv.h"
|
|
#include "mplogic.h"
|
|
|
|
/* {{{ Lookup table for population count */
|
|
|
|
static unsigned char bitc[] = {
|
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
|
};
|
|
|
|
/* }}} */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/*
|
|
mpl_not(a, b) - compute b = ~a
|
|
mpl_and(a, b, c) - compute c = a & b
|
|
mpl_or(a, b, c) - compute c = a | b
|
|
mpl_xor(a, b, c) - compute c = a ^ b
|
|
*/
|
|
|
|
/* {{{ mpl_not(a, b) */
|
|
|
|
mp_err mpl_not(mp_int *a, mp_int *b)
|
|
{
|
|
mp_err res;
|
|
unsigned int ix;
|
|
|
|
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
|
|
|
if((res = mp_copy(a, b)) != MP_OKAY)
|
|
return res;
|
|
|
|
/* This relies on the fact that the digit type is unsigned */
|
|
for(ix = 0; ix < USED(b); ix++)
|
|
DIGIT(b, ix) = ~DIGIT(b, ix);
|
|
|
|
s_mp_clamp(b);
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_not() */
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ mpl_and(a, b, c) */
|
|
|
|
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c)
|
|
{
|
|
mp_int *which, *other;
|
|
mp_err res;
|
|
unsigned int ix;
|
|
|
|
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
|
|
|
if(USED(a) <= USED(b)) {
|
|
which = a;
|
|
other = b;
|
|
} else {
|
|
which = b;
|
|
other = a;
|
|
}
|
|
|
|
if((res = mp_copy(which, c)) != MP_OKAY)
|
|
return res;
|
|
|
|
for(ix = 0; ix < USED(which); ix++)
|
|
DIGIT(c, ix) &= DIGIT(other, ix);
|
|
|
|
s_mp_clamp(c);
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_and() */
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ mpl_or(a, b, c) */
|
|
|
|
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c)
|
|
{
|
|
mp_int *which, *other;
|
|
mp_err res;
|
|
unsigned int ix;
|
|
|
|
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
|
|
|
if(USED(a) >= USED(b)) {
|
|
which = a;
|
|
other = b;
|
|
} else {
|
|
which = b;
|
|
other = a;
|
|
}
|
|
|
|
if((res = mp_copy(which, c)) != MP_OKAY)
|
|
return res;
|
|
|
|
for(ix = 0; ix < USED(which); ix++)
|
|
DIGIT(c, ix) |= DIGIT(other, ix);
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_or() */
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ mpl_xor(a, b, c) */
|
|
|
|
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c)
|
|
{
|
|
mp_int *which, *other;
|
|
mp_err res;
|
|
unsigned int ix;
|
|
|
|
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
|
|
|
if(USED(a) >= USED(b)) {
|
|
which = a;
|
|
other = b;
|
|
} else {
|
|
which = b;
|
|
other = a;
|
|
}
|
|
|
|
if((res = mp_copy(which, c)) != MP_OKAY)
|
|
return res;
|
|
|
|
for(ix = 0; ix < USED(which); ix++)
|
|
DIGIT(c, ix) ^= DIGIT(other, ix);
|
|
|
|
s_mp_clamp(c);
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_xor() */
|
|
|
|
/* }}} */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/*
|
|
mpl_rsh(a, b, d) - b = a >> d
|
|
mpl_lsh(a, b, d) - b = a << d
|
|
*/
|
|
|
|
/* {{{ mpl_rsh(a, b, d) */
|
|
|
|
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
|
|
{
|
|
mp_err res;
|
|
|
|
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
|
|
|
if((res = mp_copy(a, b)) != MP_OKAY)
|
|
return res;
|
|
|
|
s_mp_div_2d(b, d);
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_rsh() */
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ mpl_lsh(a, b, d) */
|
|
|
|
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
|
|
{
|
|
mp_err res;
|
|
|
|
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
|
|
|
if((res = mp_copy(a, b)) != MP_OKAY)
|
|
return res;
|
|
|
|
return s_mp_mul_2d(b, d);
|
|
|
|
} /* end mpl_lsh() */
|
|
|
|
/* }}} */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/*
|
|
mpl_num_set(a, num)
|
|
|
|
Count the number of set bits in the binary representation of a.
|
|
Returns MP_OKAY and sets 'num' to be the number of such bits, if
|
|
possible. If num is NULL, the result is thrown away, but it is
|
|
not considered an error.
|
|
|
|
mpl_num_clear() does basically the same thing for clear bits.
|
|
*/
|
|
|
|
/* {{{ mpl_num_set(a, num) */
|
|
|
|
mp_err mpl_num_set(mp_int *a, int *num)
|
|
{
|
|
unsigned int ix;
|
|
int db, nset = 0;
|
|
mp_digit cur;
|
|
unsigned char reg;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
for(ix = 0; ix < USED(a); ix++) {
|
|
cur = DIGIT(a, ix);
|
|
|
|
for(db = 0; db < sizeof(mp_digit); db++) {
|
|
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
|
|
|
nset += bitc[reg];
|
|
}
|
|
}
|
|
|
|
if(num)
|
|
*num = nset;
|
|
|
|
return MP_OKAY;
|
|
|
|
} /* end mpl_num_set() */
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ mpl_num_clear(a, num) */
|
|
|
|
mp_err mpl_num_clear(mp_int *a, int *num)
|
|
{
|
|
unsigned int ix;
|
|
int db, nset = 0;
|
|
mp_digit cur;
|
|
unsigned char reg;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
for(ix = 0; ix < USED(a); ix++) {
|
|
cur = DIGIT(a, ix);
|
|
|
|
for(db = 0; db < sizeof(mp_digit); db++) {
|
|
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
|
|
|
nset += bitc[UCHAR_MAX - reg];
|
|
}
|
|
}
|
|
|
|
if(num)
|
|
*num = nset;
|
|
|
|
return MP_OKAY;
|
|
|
|
|
|
} /* end mpl_num_clear() */
|
|
|
|
/* }}} */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/*
|
|
mpl_parity(a)
|
|
|
|
Determines the bitwise parity of the value given. Returns MP_EVEN
|
|
if an even number of digits are set, MP_ODD if an odd number are
|
|
set.
|
|
*/
|
|
|
|
/* {{{ mpl_parity(a) */
|
|
|
|
mp_err mpl_parity(mp_int *a)
|
|
{
|
|
unsigned int ix;
|
|
int par = 0;
|
|
mp_digit cur;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
for(ix = 0; ix < USED(a); ix++) {
|
|
int shft = (sizeof(mp_digit) * CHAR_BIT) / 2;
|
|
|
|
cur = DIGIT(a, ix);
|
|
|
|
/* Compute parity for current digit */
|
|
while(shft != 0) {
|
|
cur ^= (cur >> shft);
|
|
shft >>= 1;
|
|
}
|
|
cur &= 1;
|
|
|
|
/* XOR with running parity so far */
|
|
par ^= cur;
|
|
}
|
|
|
|
if(par)
|
|
return MP_ODD;
|
|
else
|
|
return MP_EVEN;
|
|
|
|
} /* end mpl_parity() */
|
|
|
|
/* }}} */
|
|
|
|
/*
|
|
mpl_set_bit
|
|
|
|
Returns MP_OKAY or some error code.
|
|
Grows a if needed to set a bit to 1.
|
|
*/
|
|
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
|
|
{
|
|
mp_size ix;
|
|
mp_err rv;
|
|
mp_digit mask;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
ix = bitNum / MP_DIGIT_BIT;
|
|
if (ix + 1 > MP_USED(a)) {
|
|
rv = s_mp_pad(a, ix + 1);
|
|
if (rv != MP_OKAY)
|
|
return rv;
|
|
}
|
|
|
|
bitNum = bitNum % MP_DIGIT_BIT;
|
|
mask = (mp_digit)1 << bitNum;
|
|
if (value)
|
|
MP_DIGIT(a,ix) |= mask;
|
|
else
|
|
MP_DIGIT(a,ix) &= ~mask;
|
|
s_mp_clamp(a);
|
|
return MP_OKAY;
|
|
}
|
|
|
|
/*
|
|
mpl_get_bit
|
|
|
|
returns 0 or 1 or some (negative) error code.
|
|
*/
|
|
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
|
|
{
|
|
mp_size bit, ix;
|
|
mp_err rv;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
ix = bitNum / MP_DIGIT_BIT;
|
|
ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
|
|
|
|
bit = bitNum % MP_DIGIT_BIT;
|
|
rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
mpl_get_bits
|
|
- Extracts numBits bits from a, where the least significant extracted bit
|
|
is bit lsbNum. Returns a negative value if error occurs.
|
|
- Because sign bit is used to indicate error, maximum number of bits to
|
|
be returned is the lesser of (a) the number of bits in an mp_digit, or
|
|
(b) one less than the number of bits in an mp_err.
|
|
- lsbNum + numbits can be greater than the number of significant bits in
|
|
integer a, as long as bit lsbNum is in the high order digit of a.
|
|
*/
|
|
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
|
|
{
|
|
mp_size rshift = (lsbNum % MP_DIGIT_BIT);
|
|
mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
|
|
mp_digit * digit = MP_DIGITS(a) + lsWndx;
|
|
mp_digit mask = ((1 << numBits) - 1);
|
|
|
|
ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
|
|
ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
|
|
|
|
if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
|
|
(lsWndx + 1 >= MP_USED(a))) {
|
|
mask &= (digit[0] >> rshift);
|
|
} else {
|
|
mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
|
|
}
|
|
return (mp_err)mask;
|
|
}
|
|
|
|
/*
|
|
mpl_significant_bits
|
|
returns number of significnant bits in abs(a).
|
|
returns 1 if value is zero.
|
|
*/
|
|
mp_size mpl_significant_bits(const mp_int *a)
|
|
{
|
|
mp_size bits = 0;
|
|
int ix;
|
|
|
|
ARGCHK(a != NULL, MP_BADARG);
|
|
|
|
ix = MP_USED(a);
|
|
for (ix = MP_USED(a); ix > 0; ) {
|
|
mp_digit d;
|
|
d = MP_DIGIT(a, --ix);
|
|
if (d) {
|
|
while (d) {
|
|
++bits;
|
|
d >>= 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
bits += ix * MP_DIGIT_BIT;
|
|
if (!bits)
|
|
bits = 1;
|
|
return bits;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
/* HERE THERE BE DRAGONS */
|