📄 nn.c
字号:
/*
NN.C - natural numbers routines
Copyright (c) J.S.A.Kapp 1994 - 1996.
RSAEURO - RSA Library compatible with RSAREF(tm) 2.0.
All functions prototypes are the Same as for RSAREF(tm).
To aid compatiblity the source and the files follow the
same naming comventions that RSAREF(tm) uses. This should aid
direct importing to you applications.
This library is legal everywhere outside the US. And should
NOT be imported to the US and used there.
All Trademarks Acknowledged.
Revision hisitory
0.90 First revision, this revision was the basic routines.
Routines slower than final revision.
0.91 Second revision, this is the current revision, all
routines have been altered for speed increases. Also the
addition of assembler equivalents.
1.02 Third revision, minor bug fixes.
dmult bug fix, Bug reported by Anders Heerfordt <i3683@dc.dk>.
1.03 Fourth revision, SunCompiler patch
1.04 Fifth revision, Fix to fix problem with NN_Encode
and NN_Decode when running with MS Visual C++ 4.x.
*/
#include "rsaeuro.h"
#include "nn.h"
/* internal static functions */
static NN_DIGIT subdigitmult PROTO_LIST
((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int));
static void dmult PROTO_LIST ((NN_DIGIT, NN_DIGIT, NN_DIGIT *, NN_DIGIT *));
static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT));
#ifndef USEASM
/* Decodes character string b into a, where character string is ordered
from most to least significant.
Lengths: a[digits], b[len].
Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
significant bytes are truncated.)
*/
void NN_Decode (a, digits, b, len)
NN_DIGIT *a;
unsigned char *b;
unsigned int digits, len;
{
NN_DIGIT t;
unsigned int i, u;
int j;
/* @##$ unsigned/signed bug fix added JSAK - Fri 31/05/96 18:09:11 */
for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
t = 0;
for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
t |= ((NN_DIGIT)b[j]) << u;
a[i] = t;
}
for (; i < digits; i++)
a[i] = 0;
}
/* Encodes b into character string a, where character string is ordered
from most to least significant.
Lengths: a[len], b[digits].
Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
digits are truncated.)
*/
void NN_Encode (a, len, b, digits)
NN_DIGIT *b;
unsigned char *a;
unsigned int digits, len;
{
NN_DIGIT t;
unsigned int i, u;
int j;
/* @##$ unsigned/signed bug fix added JSAK - Fri 31/05/96 18:09:11 */
for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
t = b[i];
for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
a[j] = (unsigned char)(t >> u);
}
for (; j >= 0; j--)
a[j] = 0;
}
/* Assigns a = 0. */
void NN_AssignZero (a, digits)
NN_DIGIT *a;
unsigned int digits;
{
if(digits) {
do {
*a++ = 0;
}while(--digits);
}
}
#endif
/* Assigns a = 2^b.
Lengths: a[digits].
Requires b < digits * NN_DIGIT_BITS.
*/
void NN_Assign2Exp (a, b, digits)
NN_DIGIT *a;
unsigned int b, digits;
{
NN_AssignZero (a, digits);
if (b >= digits * NN_DIGIT_BITS)
return;
a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
}
/* Computes a = b - c. Returns borrow.
Lengths: a[digits], b[digits], c[digits].
*/
NN_DIGIT NN_Sub (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT temp, borrow = 0;
if(digits)
do {
/* Bug fix 16/10/95 - JSK, code below removed, caused bug with
Sun Compiler SC4.
if((temp = (*b++) - borrow) == MAX_NN_DIGIT)
temp = MAX_NN_DIGIT - *c++;
*/
temp = *b - borrow;
b++;
if(temp == MAX_NN_DIGIT) {
temp = MAX_NN_DIGIT - *c;
c++;
}else { /* Patch to prevent bug for Sun CC */
if((temp -= *c) > (MAX_NN_DIGIT - *c))
borrow = 1;
else
borrow = 0;
c++;
}
*a++ = temp;
}while(--digits);
return(borrow);
}
/* Computes a = b * c.
Lengths: a[2*digits], b[digits], c[digits].
Assumes digits < MAX_NN_DIGITS.
*/
void NN_Mult (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned int digits;
{
NN_DIGIT t[2*MAX_NN_DIGITS];
NN_DIGIT dhigh, dlow, carry;
unsigned int bDigits, cDigits, i, j;
NN_AssignZero (t, 2 * digits);
bDigits = NN_Digits (b, digits);
cDigits = NN_Digits (c, digits);
for (i = 0; i < bDigits; i++) {
carry = 0;
if(*(b+i) != 0) {
for(j = 0; j < cDigits; j++) {
dmult(*(b+i), *(c+j), &dhigh, &dlow);
if((*(t+(i+j)) = *(t+(i+j)) + carry) < carry)
carry = 1;
else
carry = 0;
if((*(t+(i+j)) += dlow) < dlow)
carry++;
carry += dhigh;
}
}
*(t+(i+cDigits)) += carry;
}
NN_Assign(a, t, 2 * digits);
}
/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
Requires c < NN_DIGIT_BITS. */
NN_DIGIT NN_LShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned int c, digits;
{
NN_DIGIT temp, carry = 0;
unsigned int t;
if(c < NN_DIGIT_BITS)
if(digits) {
t = NN_DIGIT_BITS - c;
do {
temp = *b++;
*a++ = (temp << c) | carry;
carry = c ? (temp >> t) : 0;
}while(--digits);
}
return (carry);
}
/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
Requires: c < NN_DIGIT_BITS. */
NN_DIGIT NN_RShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned int c, digits;
{
NN_DIGIT temp, carry = 0;
unsigned int t;
if(c < NN_DIGIT_BITS)
if(digits) {
t = NN_DIGIT_BITS - c;
do {
digits--;
temp = *(b+digits);
*(a+digits) = (temp >> c) | carry;
carry = c ? (temp << t) : 0;
}while(digits);
}
return (carry);
}
/* Computes a = c div d and b = c mod d.
Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
dDigits < MAX_NN_DIGITS.
*/
void NN_Div (a, b, c, cDigits, d, dDigits)
NN_DIGIT *a, *b, *c, *d;
unsigned int cDigits, dDigits;
{
NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s;
NN_DIGIT t[2], u, v, *ccptr;
NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
int i;
unsigned int ddDigits, shift;
ddDigits = NN_Digits (d, dDigits);
if(ddDigits == 0)
return;
shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
NN_AssignZero (cc, ddDigits);
cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
NN_LShift (dd, d, shift, ddDigits);
s = dd[ddDigits-1];
NN_AssignZero (a, cDigits);
for (i = cDigits-ddDigits; i >= 0; i--) {
if (s == MAX_NN_DIGIT)
ai = cc[i+ddDigits];
else {
ccptr = &cc[i+ddDigits-1];
s++;
cHigh = (NN_HALF_DIGIT)HIGH_HALF (s);
cLow = (NN_HALF_DIGIT)LOW_HALF (s);
*t = *ccptr;
*(t+1) = *(ccptr+1);
if (cHigh == MAX_NN_HALF_DIGIT)
aHigh = (NN_HALF_DIGIT)HIGH_HALF (*(t+1));
else
aHigh = (NN_HALF_DIGIT)(*(t+1) / (cHigh + 1));
u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
if ((*t -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
t[1]--;
*(t+1) -= HIGH_HALF (u);
*(t+1) -= v;
while ((*(t+1) > cHigh) ||
((*(t+1) == cHigh) && (*t >= TO_HIGH_HALF (cLow)))) {
if ((*t -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
t[1]--;
*(t+1) -= cHigh;
aHigh++;
}
if (cHigh == MAX_NN_HALF_DIGIT)
aLow = (NN_HALF_DIGIT)LOW_HALF (*(t+1));
else
aLow =
(NN_HALF_DIGIT)((TO_HIGH_HALF (*(t+1)) + HIGH_HALF (*t)) / (cHigh + 1));
u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
if ((*t -= u) > (MAX_NN_DIGIT - u))
t[1]--;
if ((*t -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
t[1]--;
*(t+1) -= HIGH_HALF (v);
while ((*(t+1) > 0) || ((*(t+1) == 0) && *t >= s)) {
if ((*t -= s) > (MAX_NN_DIGIT - s))
t[1]--;
aLow++;
}
ai = TO_HIGH_HALF (aHigh) + aLow;
s--;
}
cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -