int bdDivide_s(T q, T r, T u, T v) /* Computes quotient q = u / v and remainder r = u mod v (safe) */ { size_t dig_size; BIGD qq, rr; assert(q && r && u && v); /* Use temps because mpDivide trashes q and r */ qq = bdNew(); rr = bdNew(); dig_size = u->ndigits; bd_resize(qq, dig_size); bd_resize(rr, dig_size); /* Do the business */ mpDivide(qq->digits, rr->digits, u->digits, dig_size, v->digits, v->ndigits); /* Copy temps */ qq->ndigits = dig_size; rr->ndigits = dig_size; bdSetEqual(q, qq); bdSetEqual(r, rr); /* Set final sizes */ q->ndigits = mpSizeof(q->digits, dig_size); r->ndigits = mpSizeof(r->digits, dig_size); /* Free temps */ bdFree(&qq); bdFree(&rr); return 0; }
int bdSubtract(T w, T u, T v) /* Compute w = u - v, return borrow, w#v */ { size_t dig_size; DIGIT_T borrow; assert(w && u && v); /* Check for cheaper option */ if (v->ndigits == 1) return bdShortSub(w, u, v->digits[0]); /* Make sure u and v are the same size */ dig_size = max(u->ndigits, v->ndigits); bd_resize(v, dig_size); bd_resize(u, dig_size); bd_resize(w, dig_size); /* Finally, do the business */ borrow = mpSubtract(w->digits, u->digits, v->digits, dig_size); /* Make sure we've set the right size for w */ w->ndigits = mpSizeof(w->digits, dig_size); return borrow; }
int bdModExp(T y, T x, T e, T m) { /* Compute y = x^e mod m x,e < m */ size_t n; int status; assert(y && x && e && m); /* Make sure all variables are the same size */ n = max(e->ndigits, m->ndigits); n = max(x->ndigits, n); bd_resize(y, n); bd_resize(x, n); bd_resize(e, n); bd_resize(m, n); /* Finally, do the business */ status = mpModExp(y->digits, x->digits, e->digits, m->digits, n); y->ndigits = mpSizeof(y->digits, n); return status; }
int bdAdd(T w, T u, T v) /* Compute w = u + v, w#v*/ { size_t dig_size; DIGIT_T carry; assert(w && u && v); /* Check for cheaper option */ if (v->ndigits == 1) return bdShortAdd(w, u, v->digits[0]); /* Make sure u and v are the same size */ dig_size = max(u->ndigits, v->ndigits); bd_resize(v, dig_size); bd_resize(u, dig_size); /* Now make sure w is big enough for sum (incl carry) */ bd_resize(w, dig_size + 1); /* Finally, do the business */ carry = mpAdd(w->digits, u->digits, v->digits, dig_size); /* Make sure we've set the right size for w */ if (carry) { w->digits[dig_size] = carry; w->ndigits = dig_size + 1; } else w->ndigits = mpSizeof(w->digits, dig_size); return carry; }
void bdShiftLeft(T a, T b, size_t s) /* Computes a = b << s */ { /* Increases the size of a if necessary. */ /* [v2.1.0] modified to allow any size of shift */ size_t dig_size = b->ndigits; assert(a && b); if (s >= BITS_PER_DIGIT) dig_size += (s / BITS_PER_DIGIT); /* Assume overflow */ dig_size++; /* Make sure both big enough */ bd_resize(a, dig_size); bd_resize(b, dig_size); /* Set the final size */ mpShiftLeft(a->digits, b->digits, s, dig_size); a->ndigits = mpSizeof(a->digits, dig_size); }
int bdMultiply(T w, T u, T v) /* Compute w = u * v -- no overlap permitted */ { size_t dig_size; assert(w && u && v); /* Check for cheaper option */ if (v->ndigits == 1) return bdShortMult(w, u, v->digits[0]); /* Make sure u and v are the same size */ dig_size = max(u->ndigits, v->ndigits); bd_resize(v, dig_size); bd_resize(u, dig_size); /* Now make sure w is big enough for product */ bd_resize(w, 2 * dig_size); /* Finally, do the business */ mpMultiply(w->digits, u->digits, v->digits, dig_size); /* Make sure we've set the right size for w */ w->ndigits = mpSizeof(w->digits, 2 * dig_size); return 0; }
int bdSetBit(T a, size_t ibit, int value) /* Set bit ibit (0..nbits-1) with value 1 or 0 -- increases size if a too small but does not shrink */ { size_t idigit; assert(a); /* Which digit? (0-based) */ idigit = ibit / BITS_PER_DIGIT; /* Check size */ /* [EDIT v2.1:] change a->maxdigits to a->ndigits */ if (idigit >= a->ndigits) { bd_resize(a, idigit+1); a->ndigits = idigit+1; } /* [v2.2] use mp function */ mpSetBit(a->digits, a->ndigits, ibit, value); /* Set the right size */ a->ndigits = mpSizeof(a->digits, a->ndigits); return 0; }
size_t bdSetRandTest(T a, size_t ndigits) /* Make a random bigd a of up to ndigits digits -- NB just for testing Return # digits actually set */ { size_t i, n, bits; DIGIT_T mask; assert(a); /* Pick a random size */ n = (size_t)spSimpleRand(1, (DIGIT_T)ndigits); /* Check allocated memory */ bd_resize(a, n); /* Now fill with random digits */ for (i = 0; i < n; i++) a->digits[i] = spSimpleRand(0, MAX_DIGIT); a->ndigits = n; /* Zero out a random number of bits in leading digit about half the time */ bits = (size_t)spSimpleRand(0, 2*BITS_PER_DIGIT); if (bits != 0 && bits < BITS_PER_DIGIT) { mask = HIBITMASK; for (i = 1; i < bits; i++) { mask |= (mask >> 1); } mask = ~mask; a->digits[n-1] &= mask; }
BAND *bd_copy(const BAND *A, BAND *B) #endif { int lb,ub,i,j,n; if ( !A ) error(E_NULL,"bd_copy"); if (A == B) return B; n = A->mat->n; if ( !B ) B = bd_get(A->lb,A->ub,n); else if (B->lb != A->lb || B->ub != A->ub || B->mat->n != n ) B = bd_resize(B,A->lb,A->ub,n); if (A->mat == B->mat) return B; ub = B->ub = A->ub; lb = B->lb = A->lb; for ( i=0, j=n-lb; i <= lb; i++, j++ ) MEM_COPY(A->mat->me[i],B->mat->me[i],j*sizeof(Real)); for ( i=lb+1, j=1; i <= lb+ub; i++, j++ ) MEM_COPY(A->mat->me[i]+j,B->mat->me[i]+j,(n - j)*sizeof(Real)); return B; }
BAND *mat2band(const MAT *A, int lb, int ub,BAND *bA) #endif { int i, j, l, n1; Real **bmat; if (! A ) error(E_NULL,"mat2band"); if (ub < 0 || lb < 0) error(E_SIZES,"mat2band"); if ( bA != (BAND *)NULL && bA->mat == A ) error(E_INSITU,"mat2band"); n1 = A->n-1; lb = min(n1,lb); ub = min(n1,ub); bA = bd_resize(bA,lb,ub,n1+1); bmat = bA->mat->me; for (j=0; j <= n1; j++) for (i=min(n1,j+lb),l=lb+j-i; i >= max(0,j-ub); i--,l++) bmat[l][j] = A->me[i][j]; return bA; }
int bdJacobi(T a, T m) /* Returns Jacobi(a, m) = {0, +1, -1} */ { size_t n; /* Careful with n and m here! */ int status; assert(a && m); n = max(a->ndigits, m->ndigits); bd_resize(a, n); bd_resize(m, n); /* Do the business */ status = mpJacobi(a->digits, m->digits, n); return status; }
int bdSetEqual(T a, T b) /* Sets a = b */ { assert(a && b); bd_resize(a, b->ndigits); mpSetEqual(a->digits, b->digits, b->ndigits); a->ndigits = b->ndigits; return 0; }
int bdSetShort(T b, bdigit_t value) /* Converts value into a (single-digit) big digit b */ { assert(b); bd_resize(b, 1); b->digits[0] = (DIGIT_T)value; b->ndigits = (value ? 1 : 0); return 0; }
void bdAndBits(T a, T b, T c) /* Computes bitwise operation a = b AND c */ { size_t n; assert(a && b && c); /* Make sure all variables are the same size */ n = max(b->ndigits, c->ndigits); bd_resize(a, n); bd_resize(b, n); bd_resize(c, n); /* Do the business */ mpAndBits(a->digits, b->digits, c->digits, n); /* Set the final size */ a->ndigits = mpSizeof(a->digits, n); }
int bdGcd(T g, T x, T y) /* Compute g = gcd(x, y) */ { size_t n; int status; assert(g && x && y); n = max(x->ndigits, y->ndigits); bd_resize(g, n); bd_resize(y, n); bd_resize(x, n); /* Do the business */ status = mpGcd(g->digits, x->digits, y->digits, n); g->ndigits = mpSizeof(g->digits, n); return status; }
BAND *sbd_mlt(Real s, const BAND *A, BAND *OUT) #endif { if ( ! A ) error(E_NULL,"sbd_mlt"); OUT = bd_resize(OUT,A->lb,A->ub,A->mat->n); sm_mlt(s,A->mat,OUT->mat); return OUT; }
int bdDivide(T q, T r, T u, T v) /* Computes quotient q = u / v and remainder r = u mod v trashes q and r first */ { size_t dig_size; assert(q && r && u && v); dig_size = u->ndigits; bd_resize(q, dig_size); bd_resize(r, dig_size); /* Do the business */ mpDivide(q->digits, r->digits, u->digits, dig_size, v->digits, v->ndigits); /* Set final sizes */ q->ndigits = mpSizeof(q->digits, dig_size); r->ndigits = mpSizeof(r->digits, dig_size); return 0; }
int bdModInv(T x, T a, T m) /* Compute x = a^-1 mod m */ { size_t n; int status; assert(x && a && m); /* Make sure all variables are the same size */ n = max(a->ndigits, m->ndigits); bd_resize(x, n); bd_resize(a, n); bd_resize(m, n); /* Do the business */ status = mpModInv(x->digits, a->digits, m->digits, n); x->ndigits = mpSizeof(x->digits, n); return status; }
int bdModMult(T a, T x, T y, T m) /* Compute a = (x * y) mod m */ { size_t n; int status; assert(a && x && y && m); /* Make sure all variables are the same size */ n = max(y->ndigits, m->ndigits); n = max(x->ndigits, n); bd_resize(a, n); bd_resize(y, n); bd_resize(x, n); bd_resize(m, n); /* Do the business */ status = mpModMult(a->digits, x->digits, y->digits, m->digits, n); a->ndigits = mpSizeof(a->digits, n); return status; }
size_t bdConvFromDecimal(BIGD b, const char *s) { size_t ndigits, n; assert(b); /* approx size but never too small */ ndigits = (strlen(s) / 2 + OCTETS_PER_DIGIT) / OCTETS_PER_DIGIT; bd_resize(b, ndigits); n = mpConvFromDecimal(b->digits, ndigits, s); b->ndigits = n; return n; }
int bdCubeRoot(BIGD s, BIGD x) /* Computes integer cube root s = floor(cuberoot(x)) */ { size_t dig_size; int r; assert(s && x); dig_size = x->ndigits; bd_resize(s, dig_size); r = mpCubeRoot(s->digits, x->digits, dig_size); s->ndigits = mpSizeof(s->digits, dig_size); return r; }
size_t bdConvFromOctets(T b, const unsigned char *c, size_t nbytes) /* Converts nbytes octets into big digit b, resizing if necessary */ { size_t ndigits, n; assert(b); ndigits = (nbytes + OCTETS_PER_DIGIT - 1) / OCTETS_PER_DIGIT; bd_resize(b, ndigits); n = mpConvFromOctets(b->digits, ndigits, c, nbytes); b->ndigits = mpSizeof(b->digits, n); return n; }
int bdShortSub(T w, T u, bdigit_t d) /* Compute w = u - d, return borrow */ { DIGIT_T borrow; size_t dig_size = max(u->ndigits, 1); assert(w && u); bd_resize(w, dig_size); borrow = mpShortSub(w->digits, u->digits, d, dig_size); w->ndigits = dig_size; return borrow; }
void bdNotBits(BIGD a, BIGD b) /* Computes bitwise a = NOT b */ { size_t n; assert(a && b); /* Make sure all variables are the same size */ n = b->ndigits; bd_resize(a, n); /* Do the business */ mpNotBits(a->digits, b->digits, n); /* Set the final size */ a->ndigits = mpSizeof(a->digits, n); }
void bdShiftRight(T a, T b, size_t n) /* Computes a = b >> n */ { /* Throws away shifted bits */ /* [v2.1.0] modified to allow any size of shift */ size_t dig_size = b->ndigits; assert(a && b); bd_resize(a, dig_size); mpShiftRight(a->digits, b->digits, n, dig_size); /* Set the final size */ a->ndigits = mpSizeof(a->digits, dig_size); }
size_t bdConvFromHex(T b, const char *s) /* Converts a hex string into big digit b */ { size_t ndigits, n; assert(b); /* Revision [2006-02-21] */ /* EDIT: ndigits = (strlen(s) / 2 + OCTETS_PER_DIGIT - 1) / OCTETS_PER_DIGIT; */ ndigits = ((strlen(s) + 1) / 2 + OCTETS_PER_DIGIT - 1) / OCTETS_PER_DIGIT; bd_resize(b, ndigits); n = mpConvFromHex(b->digits, ndigits, s); b->ndigits = mpSizeof(b->digits, n); return n; }
int bdShortDiv(T q, T r, T u, bdigit_t d) /* Computes quotient q = u / d and remainder r = u mod d */ { DIGIT_T rem; size_t dig_size; assert(q && r && u); dig_size = u->ndigits; bd_resize(q, dig_size); rem = mpShortDiv(q->digits, u->digits, d, dig_size); bdSetShort(r, rem); q->ndigits = mpSizeof(q->digits, dig_size); return 0; }
BAND *bds_mltadd(const BAND *A, const BAND *B, double alpha, BAND *OUT) #endif { int i; if ( ! A || ! B ) error(E_NULL,"bds_mltadd"); if ( A->mat->n != B->mat->n ) error(E_SIZES,"bds_mltadd"); if ( A == OUT || B == OUT ) error(E_INSITU,"bds_mltadd"); OUT = bd_copy(A,OUT); OUT = bd_resize(OUT,max(A->lb,B->lb),max(A->ub,B->ub),A->mat->n); for ( i = 0; i <= B->lb + B->ub; i++ ) __mltadd__(OUT->mat->me[i+OUT->lb-B->lb],B->mat->me[i],alpha,B->mat->n); return OUT; }
int bdModulo(T r, T u, T v) /* Computes r = u mod v, r#u */ { size_t nr; assert(r && u && v); /* NB r is only vdigits long at most */ nr = v->ndigits; bd_resize(r, nr); /* Do the business */ mpModulo(r->digits, u->digits, u->ndigits, v->digits, v->ndigits); /* Set final size */ r->ndigits = mpSizeof(r->digits, nr); return 0; }
int bdSquare(T w, T x) /* Computes w = x^2, w#x */ { size_t dig_size; assert(w && x); dig_size = max(x->ndigits, 1); /* Make sure w is big enough for product */ bd_resize(w, 2 * dig_size); /* Finally, do the business */ mpSquare(w->digits, x->digits, dig_size); /* Make sure we've set the right size for w */ w->ndigits = mpSizeof(w->digits, 2 * dig_size); return 0; }