static inline DItype __udivmoddi4 (UDItype x, UDItype y, DItype *res) { static unsigned char unrt[256] = {-2, -4, -6, -8, -10, -12, -14, -16, -18, -20, -22, -23, -25, -27, -29, -31, -32, -34, -36, -38, -39, -41, -43, -44, -46, -48, -49, -51, -53, -54, -56, -57, -59, -61, -62, -64, -65, -67, -68, -70, -71, -73, -74, -76, -77, -78, -80, -81, -83, -84, -86, -87, -88, -90, -91, -92, -94, -95, -96, -98, -99, -100, -102, -103, -104, -105, -107, -108, -109, -110, -112, -113, -114, -115, -117, -118, -119, -120, -121, -122, -124, -125, -126, -127, -128, 127, 126, 125, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 88, 87, 86, 85, 84, 83, 82, 81, 80, 80, 79, 78, 77, 76, 75, 74, 74, 73, 72, 71, 70, 70, 69, 68, 67, 66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 59, 58, 57, 56, 56, 55, 54, 53, 53, 52, 51, 50, 50, 49, 48, 48, 47, 46, 46, 45, 44, 43, 43, 42, 41, 41, 40, 39, 39, 38, 37, 37, 36, 35, 35, 34, 33, 33, 32, 32, 31, 30, 30, 29, 28, 28, 27, 27, 26, 25, 25, 24, 24, 23, 22, 22, 21, 21, 20, 19, 19, 18, 18, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0}; BIT_RESIZE(y,32); // table lookup start #define W 64 unsigned char k32 =__builtin_clz(y); UDItype lshifted_y = ((UDItype)(((USItype)y) << k32))<<32; /// remove the leading 1 lshifted_y = lshifted_y << 1; UDItype ty = lsr64(lshifted_y, W-8 ); // prescaling UDItype t = unrt[ ty ] | 256; // table lookup UDItype z = lsr64(lsl64(t,W-9), (W-32-1)-k32 ); // postscaling // z recurrence UDItype my = 0-y; //#define NR_UNROLLED #ifdef NR_UNROLLED z = z + umulh64(z,mul64(my,z)); z = z + umulh64(z,mul64(my,z)); z = z + umulh64(z,mul64(my,z)); #else unsigned int index; for (index = 0; index < 3; ++index) { UDItype zd = umulh64(z,mul64(my,z)); //if (zd == 0) break; z = z + zd; } #endif // q estimate UDItype q = umulh64(x,z); UDItype r = x - mul64(y,q); // q refinement if (r >= y) { r = r - y; q = q + 1; if (r >= y) { r = r - y; q = q + 1; if (r >= y) { //add this in case of three iterations r = r - y; q = q + 1; } } } if (res != 0) *res = r; return q; }
PRIVATE void estimate_cpu_freq(void) { u64_t tsc_delta; u64_t cpu_freq; irq_hook_t calib_cpu; /* set the probe, we use the legacy timer, IRQ 0 */ put_irq_handler(&calib_cpu, CLOCK_IRQ, calib_cpu_handler); /* just in case we are in an SMP single cpu fallback mode */ BKL_UNLOCK(); /* set the PIC timer to get some time */ intr_enable(); /* loop for some time to get a sample */ while(probe_ticks < PROBE_TICKS) { intr_enable(); } intr_disable(); /* just in case we are in an SMP single cpu fallback mode */ BKL_LOCK(); /* remove the probe */ rm_irq_handler(&calib_cpu); tsc_delta = sub64(tsc1, tsc0); cpu_freq = mul64(div64u64(tsc_delta, PROBE_TICKS - 1), make64(system_hz, 0)); cpu_set_freq(cpuid, cpu_freq); cpu_info[cpuid].freq = div64u(cpu_freq, 1000000); BOOT_VERBOSE(cpu_print_freq(cpuid)); }
/* Unsigned 64x64 -> 128 multiplication */ void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) { mul64(plow, phigh, a, b); #if defined(DEBUG_MULDIV) printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", a, b, *phigh, *plow); #endif }
static void testdiv(void) { u64_t q, r; #if TIMED struct timeval tvstart, tvend; printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n", ex64hi(i), ex64lo(i), ex64hi(j), ex64lo(j)); fflush(stdout); if (gettimeofday(&tvstart, NULL) < 0) ERR; #endif /* division by zero has a separate test */ if (cmp64u(j, 0) == 0) { testdiv0(); return; } /* perform division, store q in k to make ERR more informative */ q = div64(i, j); r = rem64(i, j); k = q; #if TIMED if (gettimeofday(&tvend, NULL) < 0) ERR; tvend.tv_sec -= tvstart.tv_sec; tvend.tv_usec -= tvstart.tv_usec; if (tvend.tv_usec < 0) { tvend.tv_sec -= 1; tvend.tv_usec += 1000000; } printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n", ex64hi(q), ex64lo(q), ex64hi(r), ex64lo(r), tvend.tv_sec, tvend.tv_usec); fflush(stdout); #endif /* compare to 64/32-bit division if possible */ if (!ex64hi(j)) { if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR; if (!ex64hi(q)) { if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR; } if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR; /* compare to 32-bit division if possible */ if (!ex64hi(i)) { if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR; if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR; } } /* check results using i = q j + r and r < j */ if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR; if (cmp64(r, j) >= 0) ERR; }
void SetIntNum16(void) { /* 1 */ /* 64 bit 演算のための数値をセット var: 数値の入った変数 */ int *var = getCaliVariable(); l_1000A0D8 = mul64(*var, numbase); DEBUG_COMMAND("ShCalc.SetIntNum16 %p:\n", var); }
void AddIntNum16(void) { /* 5 */ /* 64 bit 加算 var: 足す数の入った変数 */ int *var = getCaliVariable(); l_1000A0D8 += mul64(*var, numbase); DEBUG_COMMAND("ShCalc.AddIntNum16 %p:\n", var); }
void MulIntNum16(void) { /* 9 */ /* 64 bit 乗算 var: 掛ける数の入った変数 */ int *var = getCaliVariable(); l_1000A0D8 *= mul64(*var, numbase); DEBUG_COMMAND("ShCalc.MulIntNum16: %p:\n", var); }
CFixVector& CFixVector::Cross (CFixVector& dest, const CFixVector& v0, const CFixVector& v1) { #if 0 double x = (double (v0 [Y]) * double (v1 [Z]) - double (v0 [Z]) * double (v1 [Y])) / 65536.0; double y = (double (v0 [Z]) * double (v1 [X]) - double (v0 [X]) * double (v1 [Z])) / 65536.0; double z = (double (v0 [X]) * double (v1 [Y]) - double (v0 [Y]) * double (v1 [X])) / 65536.0; if (x > double (0x7fffffff)) x = double (0x7fffffff); else if (x < double (-0x7fffffff)) x = double (-0x7fffffff); if (y > double (0x7fffffff)) y = double (0x7fffffff); else if (y < double (-0x7fffffff)) y = double (-0x7fffffff); if (z > double (0x7fffffff)) z = double (0x7fffffff); else if (z < double (-0x7fffffff)) z = double (-0x7fffffff); dest.Set (fix (x), fix (y), fix (z)); #else QLONG x, y, z; x = mul64 (v0 [Y], v1 [Z]); x += mul64 (-v0 [Z], v1 [Y]); y = mul64 (v0 [Z], v1 [X]); y += mul64 (-v0 [X], v1 [Z]); z = mul64 (v0 [X], v1 [Y]); z += mul64 (-v0 [Y], v1 [X]); dest.Set (fix (x / 65536), fix (y / 65536), fix (z / 65536)); #endif return dest; }
void DivIntNum16(void) { /* 11 */ /* 64 bit 除算 var: 足す数の入った変数 */ int *var = getCaliVariable(); gint64 i; l_1000A0C8 = *var; i = mul64(l_1000A0C8, numbase); l_1000A0D8 = div64(l_1000A0D8, i); DEBUG_COMMAND("ShCalc.DivIntNum16 %p:\n", var); }
/* Signed 64x64 -> 128 multiplication */ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) { int sa, sb; sa = (a < 0); if (sa) a = -a; sb = (b < 0); if (sb) b = -b; mul64(plow, phigh, a, b); if (sa ^ sb) { neg128(plow, phigh); } #if defined(DEBUG_MULDIV) printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", a, b, *phigh, *plow); #endif }
PUBLIC short cpu_load(void) { u64_t current_tsc, *current_idle; u64_t tsc_delta, idle_delta, busy; struct proc *idle; short load; #ifdef CONFIG_SMP unsigned cpu = cpuid; #endif u64_t *last_tsc, *last_idle; last_tsc = get_cpu_var_ptr(cpu, cpu_last_tsc); last_idle = get_cpu_var_ptr(cpu, cpu_last_idle); idle = get_cpu_var_ptr(cpu, idle_proc);; read_tsc_64(¤t_tsc); current_idle = &idle->p_cycles; /* ptr to idle proc */ /* calculate load since last cpu_load invocation */ if (!is_zero64(*last_tsc)) { tsc_delta = sub64(current_tsc, *last_tsc); idle_delta = sub64(*current_idle, *last_idle); busy = sub64(tsc_delta, idle_delta); busy = mul64(busy, make64(100, 0)); load = ex64lo(div64(busy, tsc_delta)); if (load > 100) load = 100; } else load = 0; *last_tsc = current_tsc; *last_idle = *current_idle; return load; }
/* BN_div_no_branch is a special version of BN_div. It does not contain * branches that may leak sensitive information. */ static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift,i,loop; BIGNUM *tmp,wnum,*snum,*sdiv,*res; BN_ULONG *resp,*wnump; BN_ULONG d0,d1; int num_n,div_n; bn_check_top(dv); bn_check_top(rm); /* bn_check_top(num); */ /* 'num' has been checked in BN_div() */ bn_check_top(divisor); if (BN_is_zero(divisor)) { BNerr(BN_F_BN_DIV_NO_BRANCH,BN_R_DIV_BY_ZERO); return(0); } BN_CTX_start(ctx); tmp=BN_CTX_get(ctx); snum=BN_CTX_get(ctx); sdiv=BN_CTX_get(ctx); if (dv == NULL) res=BN_CTX_get(ctx); else res=dv; if (sdiv == NULL || res == NULL) goto err; /* First we normalise the numbers */ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; sdiv->neg=0; norm_shift+=BN_BITS2; if (!(BN_lshift(snum,num,norm_shift))) goto err; snum->neg=0; /* Since we don't know whether snum is larger than sdiv, * we pad snum with enough zeroes without changing its * value. */ if (snum->top <= sdiv->top+1) { if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err; for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0; snum->top = sdiv->top + 2; } else { if (bn_wexpand(snum, snum->top + 1) == NULL) goto err; snum->d[snum->top] = 0; snum->top ++; } div_n=sdiv->top; num_n=snum->top; loop=num_n-div_n; /* Lets setup a 'window' into snum * This is the part that corresponds to the current * 'area' being divided */ wnum.neg = 0; wnum.d = &(snum->d[loop]); wnum.top = div_n; /* only needed when BN_ucmp messes up the values between top and max */ wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ /* Get the top 2 words of sdiv */ /* div_n=sdiv->top; */ d0=sdiv->d[div_n-1]; d1=(div_n == 1)?0:sdiv->d[div_n-2]; /* pointer to the 'top' of snum */ wnump= &(snum->d[num_n-1]); /* Setup to 'res' */ res->neg= (num->neg^divisor->neg); if (!bn_wexpand(res,(loop+1))) goto err; res->top=loop-1; resp= &(res->d[loop-1]); /* space for temp */ if (!bn_wexpand(tmp,(div_n+1))) goto err; /* if res->top == 0 then clear the neg value otherwise decrease * the resp pointer */ if (res->top == 0) res->neg = 0; else resp--; for (i=0; i<loop-1; i++, wnump--, resp--) { BN_ULONG q,l0; /* the first part of the loop uses the top two words of * snum and sdiv to calculate a BN_ULONG q such that * | wnum - sdiv * q | < sdiv */ #if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG); q=bn_div_3_words(wnump,d1,d0); #else BN_ULONG n0,n1,rem=0; n0=wnump[0]; n1=wnump[-1]; if (n0 == d0) q=BN_MASK2; else /* n0 < d0 */ { #ifdef BN_LLONG BN_ULLONG t2; #if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0); #else q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem=(n1-q*d0)&BN_MASK2; #endif t2=(BN_ULLONG)d1*q; for (;;) { if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2])) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ t2 -= d1; } #else /* !BN_LLONG */ BN_ULONG t2l,t2h; q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED rem=(n1-q*d0)&BN_MASK2; #endif #if defined(BN_UMULT_LOHI) BN_UMULT_LOHI(t2l,t2h,d1,q); #elif defined(BN_UMULT_HIGH) t2l = d1 * q; t2h = BN_UMULT_HIGH(d1,q); #else { BN_ULONG ql, qh; t2l=LBITS(d1); t2h=HBITS(d1); ql =LBITS(q); qh =HBITS(q); mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */ } #endif for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } #endif /* !BN_LLONG */ } #endif /* !BN_DIV3W */ l0=bn_mul_words(tmp->d,sdiv->d,div_n,q); tmp->d[div_n]=l0; wnum.d--; /* ingore top values of the bignums just sub the two * BN_ULONG arrays with bn_sub_words */ if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1)) { /* Note: As we have considered only the leading * two BN_ULONGs in the calculation of q, sdiv * q * might be greater than wnum (but then (q-1) * sdiv * is less or equal than wnum) */ q--; if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) /* we can't have an overflow here (assuming * that q != 0, but if q == 0 then tmp is * zero anyway) */ (*wnump)++; } /* store part of the result */ *resp = q; } bn_correct_top(snum); if (rm != NULL) { /* Keep a copy of the neg flag in num because if rm==num * BN_rshift() will overwrite it. */ int neg = num->neg; BN_rshift(rm,snum,norm_shift); if (!BN_is_zero(rm)) rm->neg = neg; bn_check_top(rm); } bn_correct_top(res); BN_CTX_end(ctx); return(1); err: bn_check_top(rm); BN_CTX_end(ctx); return(0); }
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift, i, j, loop; BIGNUM *tmp, wnum, *snum, *sdiv, *res; BN_ULONG *resp, *wnump; BN_ULONG d0, d1; int num_n, div_n; bn_check_top(num); bn_check_top(divisor); if(BN_is_zero(divisor)) { return (0); } if(BN_ucmp(num, divisor) < 0) { if(rm != NULL) { if(BN_copy(rm, num) == NULL) { return (0); } } if(dv != NULL) { BN_zero(dv); } return (1); } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); snum = BN_CTX_get(ctx); sdiv = BN_CTX_get(ctx); if(dv == NULL) { res = BN_CTX_get(ctx); } else { res = dv; } if(sdiv == NULL || res == NULL) { goto err; } tmp->neg = 0; /* First we normalise the numbers */ norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); BN_lshift(sdiv, divisor, norm_shift); sdiv->neg = 0; norm_shift += BN_BITS2; BN_lshift(snum, num, norm_shift); snum->neg = 0; div_n = sdiv->top; num_n = snum->top; loop = num_n - div_n; /* Lets setup a 'window' into snum * This is the part that corresponds to the current * 'area' being divided */ BN_init(&wnum); wnum.d = &(snum->d[loop]); wnum.top = div_n; wnum.dmax = snum->dmax + 1; /* a bit of a lie */ /* Get the top 2 words of sdiv */ /* i=sdiv->top; */ d0 = sdiv->d[div_n - 1]; d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; /* pointer to the 'top' of snum */ wnump = &(snum->d[num_n - 1]); /* Setup to 'res' */ res->neg = (num->neg ^ divisor->neg); if(!bn_wexpand(res, (loop + 1))) { goto err; } res->top = loop; resp = &(res->d[loop - 1]); /* space for temp */ if(!bn_wexpand(tmp, (div_n + 1))) { goto err; } if(BN_ucmp(&wnum, sdiv) >= 0) { if(!BN_usub(&wnum, &wnum, sdiv)) { goto err; } *resp = 1; res->d[res->top - 1] = 1; } else { res->top--; } resp--; for(i = 0; i < loop - 1; i++) { BN_ULONG q, l0; #if defined(BN_DIV3W) && !defined(NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG); q = bn_div_3_words(wnump, d1, d0); #else BN_ULONG n0, n1, rem = 0; n0 = wnump[0]; n1 = wnump[-1]; if(n0 == d0) { q = BN_MASK2; } else /* n0 < d0 */ { #ifdef BN_LLONG BN_ULLONG t2; #if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0); #else q = bn_div_words(n0, n1, d0); #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem = (n1 - q * d0)&BN_MASK2; #endif t2 = (BN_ULLONG)d1 * q; for(;;) { if(t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) { break; } q--; rem += d0; if(rem < d0) { break; } /* don't let rem overflow */ t2 -= d1; } #else /* !BN_LLONG */ BN_ULONG t2l, t2h, ql, qh; q = bn_div_words(n0, n1, d0); #ifndef REMAINDER_IS_ALREADY_CALCULATED rem = (n1 - q * d0)&BN_MASK2; #endif #ifdef BN_UMULT_HIGH t2l = d1 * q; t2h = BN_UMULT_HIGH(d1, q); #else t2l = LBITS(d1); t2h = HBITS(d1); ql = LBITS(q); qh = HBITS(q); mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ #endif for(;;) { if((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) { break; } q--; rem += d0; if(rem < d0) { break; } /* don't let rem overflow */ if(t2l < d1) { t2h--; } t2l -= d1; } #endif /* !BN_LLONG */ } #endif /* !BN_DIV3W */ l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); wnum.d--; wnum.top++; tmp->d[div_n] = l0; for(j = div_n + 1; j > 0; j--) if(tmp->d[j - 1]) { break; } tmp->top = j; j = wnum.top; BN_sub(&wnum, &wnum, tmp); snum->top = snum->top + wnum.top - j; if(wnum.neg) { q--; j = wnum.top; BN_add(&wnum, &wnum, sdiv); snum->top += wnum.top - j; } *(resp--) = q; wnump--; } if(rm != NULL) { BN_rshift(rm, snum, norm_shift); rm->neg = num->neg; } BN_CTX_end(ctx); return (1); err: BN_CTX_end(ctx); return (0); }
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift,i,loop; BIGNUM *tmp,*snum,*sdiv,*res; #ifdef BN_ALLOC /* pcg */ BIGNUM wnum; #else BN_ULONG *wnum_d; #endif /* !BN_ALLOC */ BN_ULONG *resp,*wnump; BN_ULONG d0,d1; int num_n,div_n; /* Invalid zero-padding would have particularly bad consequences * in the case of 'num', so don't just rely on bn_check_top() for this one * (bn_check_top() works only for BN_DEBUG builds) */ if (num->top > 0 && num->d[num->top - 1] == 0) { BNerr(BN_F_BN_DIV,BN_R_NOT_INITIALIZED); return 0; } bn_check_top(num); if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) { return BN_div_no_branch(dv, rm, num, divisor, ctx); } bn_check_top(dv); bn_check_top(rm); /* bn_check_top(num); */ /* 'num' has been checked already */ bn_check_top(divisor); if (BN_is_zero(divisor)) { BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); return(0); } if (BN_ucmp(num,divisor) < 0) { if (rm != NULL) { if (BN_copy(rm,num) == NULL) return(0); } if (dv != NULL) BN_zero(dv); return(1); } BN_CTX_start(ctx); tmp=BN_CTX_get(ctx); snum=BN_CTX_get_ext( ctx, BIGNUM_EXT_MUL1 ); /* pcg */ sdiv=BN_CTX_get(ctx); if (dv == NULL) res=BN_CTX_get(ctx); else res=dv; if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL) goto err; /* First we normalise the numbers */ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; sdiv->neg=0; norm_shift+=BN_BITS2; if (!(BN_lshift(snum,num,norm_shift))) goto err; snum->neg=0; div_n=sdiv->top; num_n=snum->top; loop=num_n-div_n; /* Lets setup a 'window' into snum * This is the part that corresponds to the current * 'area' being divided */ #ifdef BN_ALLOC /* pcg */ wnum.neg = 0; wnum.d = &(snum->d[loop]); wnum.top = div_n; /* only needed when BN_ucmp messes up the values between top and max */ wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ #else wnum_d = &(snum->d[loop]); #endif /* BN_ALLOC */ /* Get the top 2 words of sdiv */ /* div_n=sdiv->top; */ d0=sdiv->d[div_n-1]; d1=(div_n == 1)?0:sdiv->d[div_n-2]; /* pointer to the 'top' of snum */ wnump= &(snum->d[num_n-1]); /* Setup to 'res' */ res->neg= (num->neg^divisor->neg); if (!bn_wexpand(res,(loop+1))) goto err; res->top=loop; resp= &(res->d[loop-1]); /* space for temp */ if( div_n+1 > BIGNUM_ALLOC_WORDS ) { assert( 0 ); goto err; } if (BN_ucmp_word(wnum_d,div_n,sdiv) >= 0) { /* If BN_DEBUG_RAND is defined BN_ucmp changes (via * bn_pollute) the const bignum arguments => * clean the values between top and max again */ bn_clear_top2max(&wnum); bn_sub_words(wnum_d, wnum_d, sdiv->d, div_n); *resp=1; } else res->top--; /* if res->top == 0 then clear the neg value otherwise decrease * the resp pointer */ if (res->top == 0) res->neg = 0; else resp--; for (i=0; i<loop-1; i++, wnump--, resp--) { BN_ULONG q,l0; /* the first part of the loop uses the top two words of * snum and sdiv to calculate a BN_ULONG q such that * | wnum - sdiv * q | < sdiv */ #if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG); q=bn_div_3_words(wnump,d1,d0); #else BN_ULONG n0,n1,rem=0; n0=wnump[0]; n1=wnump[-1]; if (n0 == d0) q=BN_MASK2; else /* n0 < d0 */ { #ifdef BN_LLONG BN_ULLONG t2; #if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0); #else q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem=(n1-q*d0)&BN_MASK2; #endif t2=(BN_ULLONG)d1*q; for (;;) { if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2])) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ t2 -= d1; } #else /* !BN_LLONG */ BN_ULONG t2l,t2h; #if !defined( BN_UMULT_LOHI ) && !defined( BN_UMULT_HIGH ) /* pcg */ BN_ULONG ql,qh; #endif q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED rem=(n1-q*d0)&BN_MASK2; #endif #if defined(BN_UMULT_LOHI) BN_UMULT_LOHI(t2l,t2h,d1,q); #elif defined(BN_UMULT_HIGH) t2l = d1 * q; t2h = BN_UMULT_HIGH(d1,q); #else { BN_ULONG ql, qh; t2l=LBITS(d1); t2h=HBITS(d1); ql =LBITS(q); qh =HBITS(q); mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */ } #endif for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } #endif /* !BN_LLONG */ } #endif /* !BN_DIV3W */ l0=bn_mul_words(tmp->d,sdiv->d,div_n,q); tmp->d[div_n]=l0; wnum_d--; /* ingore top values of the bignums just sub the two * BN_ULONG arrays with bn_sub_words */ if (bn_sub_words(wnum_d, wnum_d, tmp->d, div_n+1)) { /* Note: As we have considered only the leading * two BN_ULONGs in the calculation of q, sdiv * q * might be greater than wnum (but then (q-1) * sdiv * is less or equal than wnum) */ q--; if (bn_add_words(wnum_d, wnum_d, sdiv->d, div_n)) /* we can't have an overflow here (assuming * that q != 0, but if q == 0 then tmp is * zero anyway) */ (*wnump)++; } /* store part of the result */ *resp = q; } bn_correct_top(snum); if (rm != NULL) { /* Keep a copy of the neg flag in num because if rm==num * BN_rshift() will overwrite it. */ int neg = num->neg; BN_rshift(rm,snum,norm_shift); if (!BN_is_zero(rm)) rm->neg = neg; bn_check_top(rm); } BN_CTX_end_ext( ctx, BIGNUM_EXT_MUL1 ); /* pcg */ return(1); err: bn_check_top(rm); BN_CTX_end_ext( ctx, BIGNUM_EXT_MUL1 ); /* pcg */ return(0); }
/*--- poly_sine() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ void poly_sine(FPU_REG const *arg, FPU_REG *result) { short exponent; FPU_REG fixed_arg, arg_sqrd, arg_to_4, accum, negaccum; exponent = arg->exp - EXP_BIAS; if ( arg->tag == TW_Zero ) { /* Return 0.0 */ reg_move(&CONST_Z, result); return; } #ifdef PARANOID if ( arg->sign != 0 ) /* Can't hack a number < 0.0 */ { EXCEPTION(EX_Invalid); reg_move(&CONST_QNaN, result); return; } if ( exponent >= 0 ) /* Can't hack a number > 1.0 */ { if ( (exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000) ) { reg_move(&CONST_1, result); return; } EXCEPTION(EX_Invalid); reg_move(&CONST_QNaN, result); return; } #endif PARANOID fixed_arg.sigl = arg->sigl; fixed_arg.sigh = arg->sigh; if ( exponent < -1 ) { /* shift the argument right by the required places */ if ( shrx(&(fixed_arg.sigl), -1-exponent) >= 0x80000000U ) significand(&fixed_arg)++; /* round up */ } mul64(&significand(&fixed_arg), &significand(&fixed_arg), &significand(&arg_sqrd)); mul64(&significand(&arg_sqrd), &significand(&arg_sqrd), &significand(&arg_to_4)); /* will be a valid positive nr with expon = 0 */ *(short *)&(accum.sign) = 0; accum.exp = 0; /* Do the basic fixed point polynomial evaluation */ polynomial(&(accum.sigl), &(arg_to_4.sigl), lterms, HIPOWER-1); /* will be a valid positive nr with expon = 0 */ *(short *)&(negaccum.sign) = 0; negaccum.exp = 0; /* Do the basic fixed point polynomial evaluation */ polynomial(&(negaccum.sigl), &(arg_to_4.sigl), negterms, HIPOWER-1); mul64(&significand(&arg_sqrd), &significand(&negaccum), &significand(&negaccum)); /* Subtract the mantissas */ significand(&accum) -= significand(&negaccum); /* Convert to 64 bit signed-compatible */ accum.exp = EXP_BIAS - 1 + accum.exp; reg_move(&accum, result); normalize(result); reg_mul(result, arg, result, FULL_PRECISION); reg_u_add(result, arg, result, FULL_PRECISION); if ( result->exp >= EXP_BIAS ) { /* A small overflow may be possible... but an illegal result. */ if ( (result->exp > EXP_BIAS) /* Larger or equal 2.0 */ || (result->sigl > 1) /* Larger than 1.0+msb */ || (result->sigh != 0x80000000) /* Much > 1.0 */ ) { #ifdef DEBUGGING RE_ENTRANT_CHECK_OFF; printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp, result->sigh, result->sigl); RE_ENTRANT_CHECK_ON; #endif DEBUGGING EXCEPTION(EX_INTERNAL|0x103); } #ifdef DEBUGGING RE_ENTRANT_CHECK_OFF; printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n"); printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp, result->sigh, result->sigl); RE_ENTRANT_CHECK_ON; #endif DEBUGGING result->sigl = 0; /* Truncate the result to 1.00 */ } }
/*--- poly_atan() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ void poly_atan(FPU_REG * arg) { char recursions = 0; short exponent; FPU_REG odd_poly, even_poly, pos_poly, neg_poly; FPU_REG argSq; long long arg_signif, argSqSq; #ifdef PARANOID if (arg->sign != 0) { /* Can't hack a number < 0.0 */ arith_invalid(arg); return; } /* Need a positive number */ #endif /* PARANOID */ exponent = arg->exp - EXP_BIAS; if (arg->tag == TW_Zero) { /* Return 0.0 */ reg_move(&CONST_Z, arg); return; } if (exponent >= -2) { /* argument is in the range [0.25 .. 1.0] */ if (exponent >= 0) { #ifdef PARANOID if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) #endif /* PARANOID */ { reg_move(&CONST_PI4, arg); return; } #ifdef PARANOID EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic * error */ #endif /* PARANOID */ } /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */ /* convert the argument by an identity for atan */ if ((exponent >= -1) || (arg->sigh > 0xd413ccd0)) { FPU_REG numerator, denom; recursions++; arg_signif = *(long long *) &(arg->sigl); if (exponent < -1) { if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) arg_signif++; /* round up */ } *(long long *) &(numerator.sigl) = -arg_signif; numerator.exp = EXP_BIAS - 1; normalize(&numerator); /* 1 - arg */ arg_signif = *(long long *) &(arg->sigl); if (shrx(&arg_signif, -exponent) >= (unsigned)0x80000000) arg_signif++; /* round up */ *(long long *) &(denom.sigl) = arg_signif; denom.sigh |= 0x80000000; /* 1 + arg */ arg->exp = numerator.exp; reg_u_div(&numerator, &denom, arg, FULL_PRECISION); exponent = arg->exp - EXP_BIAS; } } *(long long *) &arg_signif = *(long long *) &(arg->sigl); #ifdef PARANOID /* This must always be true */ if (exponent >= -1) { EXCEPTION(EX_INTERNAL | 0x120); /* There must be a logic error */ } #endif /* PARANOID */ /* shift the argument right by the required places */ if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) arg_signif++; /* round up */ /* Now have arg_signif with binary point at the left .1xxxxxxxx */ mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); /* will be a valid positive nr with expon = 0 */ *(short *) &(pos_poly.sign) = 0; pos_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial(&pos_poly.sigl, (unsigned *) &argSqSq, (unsigned short (*)[4]) oddplterms, HIPOWERop - 1); mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl)); /* will be a valid positive nr with expon = 0 */ *(short *) &(neg_poly.sign) = 0; neg_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial(&neg_poly.sigl, (unsigned *) &argSqSq, (unsigned short (*)[4]) oddnegterms, HIPOWERon - 1); /* Subtract the mantissas */ *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); reg_move(&pos_poly, &odd_poly); poly_add_1(&odd_poly); /* The complete odd polynomial */ reg_u_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* will be a valid positive nr with expon = 0 */ *(short *) &(even_poly.sign) = 0; mul64((long long *) (&argSq.sigl), (long long *) (&denomterm), (long long *) (&even_poly.sigl)); poly_add_1(&even_poly); reg_div(&odd_poly, &even_poly, arg, FULL_PRECISION); if (recursions) reg_sub(&CONST_PI4, arg, arg, FULL_PRECISION); }
size_t THSoundArchive::getSoundDuration(size_t iIndex) { SDL_RWops *pFile = loadSound(iIndex); if(!pFile) return 0; uint16_t iWaveAudioFormat = 0; uint16_t iWaveChannelCount = 0; uint32_t iWaveSampleRate = 0; uint32_t iWaveByteRate = 0; uint16_t iWaveBlockAlign = 0; uint16_t iWaveBitsPerSample = 0; uint32_t iWaveDataLength = 0; // This is a very crude RIFF parser, but it does the job. uint32_t iFourCC; uint32_t iChunkLength; for(;;) { if(SDL_RWread(pFile, &iFourCC, 4, 1) != 1) break; if(SDL_RWread(pFile, &iChunkLength, 4, 1) != 1) break; if(iFourCC == FOURCC('R','I','F','F') || iFourCC == FOURCC('L','I','S','T')) { if(iChunkLength >= 4) { if(SDL_RWread(pFile, &iFourCC, 4, 1) != 1) break; else continue; } } if(iFourCC == FOURCC('f','m','t',' ') && iChunkLength >= 16) { if(SDL_RWread(pFile, &iWaveAudioFormat, 2, 1) != 1) break; if(SDL_RWread(pFile, &iWaveChannelCount, 2, 1) != 1) break; if(SDL_RWread(pFile, &iWaveSampleRate, 4, 1) != 1) break; if(SDL_RWread(pFile, &iWaveByteRate, 4, 1) != 1) break; if(SDL_RWread(pFile, &iWaveBlockAlign, 2, 1) != 1) break; if(SDL_RWread(pFile, &iWaveBitsPerSample, 2, 1) != 1) break; iChunkLength -= 16; } //Finally: if(iFourCC == FOURCC('d','a','t','a')) { iWaveDataLength = iChunkLength; break; } if(SDL_RWseek(pFile, iChunkLength + (iChunkLength & 1), RW_SEEK_CUR) == -1) { break; } } SDL_RWclose(pFile); if(iWaveAudioFormat != 1 || iWaveChannelCount == 0 || iWaveSampleRate == 0 || iWaveDataLength == 0 || iWaveBitsPerSample == 0) { return 0; } #define mul64(a, b) (static_cast<uint64_t>(a) * static_cast<uint64_t>(b)) return static_cast<size_t>(mul64(iWaveDataLength, 8000) / mul64(mul64(iWaveBitsPerSample, iWaveChannelCount), iWaveSampleRate)); #undef mul64 }
/*--- poly_tan() ------------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ void poly_tan(FPU_REG * arg, FPU_REG * y_reg) { char invert = 0; short exponent; FPU_REG odd_poly, even_poly, pos_poly, neg_poly; FPU_REG argSq; long long arg_signif, argSqSq; exponent = arg->exp - EXP_BIAS; if (arg->tag == TW_Zero) { /* Return 0.0 */ reg_move(&CONST_Z, y_reg); return; } if (exponent >= -1) { /* argument is in the range [0.5 .. 1.0] */ if (exponent >= 0) { #ifdef PARANOID if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) #endif /* PARANOID */ { arith_overflow(y_reg); return; } #ifdef PARANOID EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic * error */ return; #endif /* PARANOID */ } /* The argument is in the range [0.5 .. 1.0) */ /* Convert the argument to a number in the range (0.0 .. 0.5] */ *((long long *) (&arg->sigl)) = -*((long long *) (&arg->sigl)); normalize(arg); /* Needed later */ exponent = arg->exp - EXP_BIAS; invert = 1; } #ifdef PARANOID if (arg->sign != 0) { /* Can't hack a number < 0.0 */ arith_invalid(y_reg); return; } /* Need a positive number */ #endif /* PARANOID */ *(long long *) &arg_signif = *(long long *) &(arg->sigl); if (exponent < -1) { /* shift the argument right by the required places */ if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) arg_signif++; /* round up */ } mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); /* will be a valid positive nr with expon = 0 */ *(short *) &(pos_poly.sign) = 0; pos_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, oddplterms, HIPOWERop - 1); /* will be a valid positive nr with expon = 0 */ *(short *) &(neg_poly.sign) = 0; neg_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, oddnegterms, HIPOWERon - 1); mul64((long long *) (&argSq.sigl), (long long *) (&neg_poly.sigl), (long long *) (&neg_poly.sigl)); /* Subtract the mantissas */ *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); /* Convert to 64 bit signed-compatible */ pos_poly.exp -= 1; reg_move(&pos_poly, &odd_poly); normalize(&odd_poly); reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd * polynomial */ /* will be a valid positive nr with expon = 0 */ *(short *) &(pos_poly.sign) = 0; pos_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, evenplterms, HIPOWERep - 1); mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl)); /* will be a valid positive nr with expon = 0 */ *(short *) &(neg_poly.sign) = 0; neg_poly.exp = EXP_BIAS; /* Do the basic fixed point polynomial evaluation */ polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, evennegterms, HIPOWERen - 1); /* Subtract the mantissas */ *((long long *) (&neg_poly.sigl)) -= *((long long *) (&pos_poly.sigl)); /* and multiply by argSq */ /* Convert argSq to a valid reg number */ *(short *) &(argSq.sign) = 0; argSq.exp = EXP_BIAS - 1; normalize(&argSq); /* Convert to 64 bit signed-compatible */ neg_poly.exp -= 1; reg_move(&neg_poly, &even_poly); normalize(&even_poly); reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION); reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION); reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION); /* This is just the even * polynomial */ /* Now ready to copy the results */ if (invert) { reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); } else { reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); } }
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift,i,j,loop; BIGNUM *tmp,wnum,*snum,*sdiv,*res; BN_ULONG *resp,*wnump; BN_ULONG d0,d1; int num_n,div_n; bn_check_top(num); bn_check_top(divisor); if (BN_is_zero(divisor)) return(0); if (BN_ucmp(num,divisor) < 0) { if (rm != NULL) { if (BN_copy(rm,num) == NULL) return(0); } if (dv != NULL) BN_zero(dv); return(1); } BN_CTX_start(ctx); tmp=BN_CTX_get(ctx); snum=BN_CTX_get(ctx); sdiv=BN_CTX_get(ctx); if (dv == NULL) res=BN_CTX_get(ctx); else res=dv; if (sdiv==NULL || res == NULL) goto err; tmp->neg=0; /* First we normalise the numbers */ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; sdiv->neg=0; norm_shift+=BN_BITS2; if (!(BN_lshift(snum,num,norm_shift))) goto err; snum->neg=0; div_n=sdiv->top; num_n=snum->top; loop=num_n-div_n; /* Lets setup a 'window' into snum * This is the part that corresponds to the current * 'area' being divided */ BN_init(&wnum); wnum.d= &(snum->d[loop]); wnum.top= div_n; wnum.dmax= snum->dmax+1; /* a bit of a lie */ /* Get the top 2 words of sdiv */ /* i=sdiv->top; */ d0=sdiv->d[div_n-1]; d1=(div_n == 1)?0:sdiv->d[div_n-2]; /* pointer to the 'top' of snum */ wnump= &(snum->d[num_n-1]); /* Setup to 'res' */ res->neg= (num->neg^divisor->neg); if (!bn_wexpand(res,(loop+1))) goto err; res->top=loop; resp= &(res->d[loop-1]); /* space for temp */ if (!bn_wexpand(tmp,(div_n+1))) goto err; if (BN_ucmp(&wnum,sdiv) >= 0) { if (!BN_usub(&wnum,&wnum,sdiv)) goto err; *resp=1; res->d[res->top-1]=1; } else res->top--; resp--; for (i=0; i<loop-1; i++) { BN_ULONG q,l0; BN_ULONG n0,n1,rem=0; n0=wnump[0]; n1=wnump[-1]; if (n0 == d0) q=BN_MASK2; else /* n0 < d0 */ { BN_ULONG t2l,t2h,ql,qh; q=bn_div_words(n0,n1,d0); rem=(n1-q*d0)&BN_MASK2; t2l=LBITS(d1); t2h=HBITS(d1); ql =LBITS(q); qh =HBITS(q); mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */ for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } } l0=bn_mul_words(tmp->d,sdiv->d,div_n,q); wnum.d--; wnum.top++; tmp->d[div_n]=l0; for (j=div_n+1; j>0; j--) if (tmp->d[j-1]) break; tmp->top=j; j=wnum.top; if (!BN_sub(&wnum,&wnum,tmp)) goto err; snum->top=snum->top+wnum.top-j; if (wnum.neg) { q--; j=wnum.top; if (!BN_add(&wnum,&wnum,sdiv)) goto err; snum->top+=wnum.top-j; } *(resp--)=q; wnump--; } if (rm != NULL) { BN_rshift(rm,snum,norm_shift); rm->neg=num->neg; } BN_CTX_end(ctx); return(1); err: BN_CTX_end(ctx); return(0); }
/*- * BN_div computes dv := num / divisor, rounding towards * zero, and sets up rm such that dv*divisor + rm = num holds. * Thus: * dv->neg == num->neg ^ divisor->neg (unless the result is zero) * rm->neg == num->neg (unless the remainder is zero) * If 'dv' or 'rm' is NULL, the respective value is not returned. */ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift, i, loop; BIGNUM *tmp, wnum, *snum, *sdiv, *res; BN_ULONG *resp, *wnump; BN_ULONG d0, d1; int num_n, div_n; int no_branch = 0; /* * Invalid zero-padding would have particularly bad consequences so don't * just rely on bn_check_top() here (bn_check_top() works only for * BN_DEBUG builds) */ if ((num->top > 0 && num->d[num->top - 1] == 0) || (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) { BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED); return 0; } bn_check_top(num); bn_check_top(divisor); if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) { no_branch = 1; } bn_check_top(dv); bn_check_top(rm); /*- bn_check_top(num); *//* * 'num' has been checked already */ /*- bn_check_top(divisor); *//* * 'divisor' has been checked already */ if (BN_is_zero(divisor)) { BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); return 0; } if (!no_branch && BN_ucmp(num, divisor) < 0) { if (rm != NULL) { if (BN_copy(rm, num) == NULL) return 0; } if (dv != NULL) BN_zero(dv); return 1; } BN_CTX_start(ctx); res = (dv == NULL) ? BN_CTX_get(ctx) : dv; tmp = BN_CTX_get(ctx); snum = BN_CTX_get(ctx); sdiv = BN_CTX_get(ctx); if (sdiv == NULL) goto err; /* First we normalise the numbers */ norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); if (!(BN_lshift(sdiv, divisor, norm_shift))) goto err; sdiv->neg = 0; norm_shift += BN_BITS2; if (!(BN_lshift(snum, num, norm_shift))) goto err; snum->neg = 0; if (no_branch) { /* * Since we don't know whether snum is larger than sdiv, we pad snum * with enough zeroes without changing its value. */ if (snum->top <= sdiv->top + 1) { if (bn_wexpand(snum, sdiv->top + 2) == NULL) goto err; for (i = snum->top; i < sdiv->top + 2; i++) snum->d[i] = 0; snum->top = sdiv->top + 2; } else { if (bn_wexpand(snum, snum->top + 1) == NULL) goto err; snum->d[snum->top] = 0; snum->top++; } } div_n = sdiv->top; num_n = snum->top; loop = num_n - div_n; /* * Lets setup a 'window' into snum This is the part that corresponds to * the current 'area' being divided */ wnum.neg = 0; wnum.d = &(snum->d[loop]); wnum.top = div_n; wnum.flags = BN_FLG_STATIC_DATA; /* * only needed when BN_ucmp messes up the values between top and max */ wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ /* Get the top 2 words of sdiv */ /* div_n=sdiv->top; */ d0 = sdiv->d[div_n - 1]; d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; /* pointer to the 'top' of snum */ wnump = &(snum->d[num_n - 1]); /* Setup to 'res' */ if (!bn_wexpand(res, (loop + 1))) goto err; res->neg = (num->neg ^ divisor->neg); res->top = loop - no_branch; resp = &(res->d[loop - 1]); /* space for temp */ if (!bn_wexpand(tmp, (div_n + 1))) goto err; if (!no_branch) { if (BN_ucmp(&wnum, sdiv) >= 0) { /* * If BN_DEBUG_RAND is defined BN_ucmp changes (via bn_pollute) * the const bignum arguments => clean the values between top and * max again */ bn_clear_top2max(&wnum); bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n); *resp = 1; } else res->top--; } /* Increase the resp pointer so that we never create an invalid pointer. */ resp++; /* * if res->top == 0 then clear the neg value otherwise decrease the resp * pointer */ if (res->top == 0) res->neg = 0; else resp--; for (i = 0; i < loop - 1; i++, wnump--) { BN_ULONG q, l0; /* * the first part of the loop uses the top two words of snum and sdiv * to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv */ # if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG); q = bn_div_3_words(wnump, d1, d0); # else BN_ULONG n0, n1, rem = 0; n0 = wnump[0]; n1 = wnump[-1]; if (n0 == d0) q = BN_MASK2; else { /* n0 < d0 */ # ifdef BN_LLONG BN_ULLONG t2; # if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0); # else q = bn_div_words(n0, n1, d0); # endif # ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem = (n1 - q * d0) & BN_MASK2; # endif t2 = (BN_ULLONG) d1 *q; for (;;) { if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2])) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ t2 -= d1; } # else /* !BN_LLONG */ BN_ULONG t2l, t2h; q = bn_div_words(n0, n1, d0); # ifndef REMAINDER_IS_ALREADY_CALCULATED rem = (n1 - q * d0) & BN_MASK2; # endif # if defined(BN_UMULT_LOHI) BN_UMULT_LOHI(t2l, t2h, d1, q); # elif defined(BN_UMULT_HIGH) t2l = d1 * q; t2h = BN_UMULT_HIGH(d1, q); # else { BN_ULONG ql, qh; t2l = LBITS(d1); t2h = HBITS(d1); ql = LBITS(q); qh = HBITS(q); mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ } # endif for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } # endif /* !BN_LLONG */ } # endif /* !BN_DIV3W */ l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); tmp->d[div_n] = l0; wnum.d--; /* * ingore top values of the bignums just sub the two BN_ULONG arrays * with bn_sub_words */ if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { /* * Note: As we have considered only the leading two BN_ULONGs in * the calculation of q, sdiv * q might be greater than wnum (but * then (q-1) * sdiv is less or equal than wnum) */ q--; if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) /* * we can't have an overflow here (assuming that q != 0, but * if q == 0 then tmp is zero anyway) */ (*wnump)++; } /* store part of the result */ resp--; *resp = q; } bn_correct_top(snum); if (rm != NULL) { /* * Keep a copy of the neg flag in num because if rm==num BN_rshift() * will overwrite it. */ int neg = num->neg; BN_rshift(rm, snum, norm_shift); if (!BN_is_zero(rm)) rm->neg = neg; bn_check_top(rm); } if (no_branch) bn_correct_top(res); BN_CTX_end(ctx); return 1; err: bn_check_top(rm); BN_CTX_end(ctx); return 0; }
static void testmul(void) { int kdone, kidx; u32_t ilo = ex64lo(i), jlo = ex64lo(j); u64_t prod = mul64(i, j); int prodbits; /* compute maximum index of highest-order bit */ prodbits = bsr64(i) + bsr64(j) + 1; if (cmp64u(i, 0) == 0 || cmp64u(j, 0) == 0) prodbits = -1; if (bsr64(prod) > prodbits) ERR; /* compare to 32-bit multiplication if possible */ if (ex64hi(i) == 0 && ex64hi(j) == 0) { if (cmp64(prod, mul64u(ilo, jlo)) != 0) ERR; /* if there is no overflow we can check against pure 32-bit */ if (prodbits < 32 && cmp64u(prod, ilo * jlo) != 0) ERR; } /* in 32-bit arith low-order DWORD matches regardless of overflow */ if (ex64lo(prod) != ilo * jlo) ERR; /* multiplication by zero yields zero */ if (prodbits < 0 && cmp64u(prod, 0) != 0) ERR; /* if there is no overflow, check absence of zero divisors */ if (prodbits >= 0 && prodbits < 64 && cmp64u(prod, 0) == 0) ERR; /* commutativity */ if (cmp64(prod, mul64(j, i)) != 0) ERR; /* loop though all argument value combinations for third argument */ for (kdone = 0, kidx = 0; k = getargval(kidx, &kdone), !kdone; kidx++) { /* associativity */ if (cmp64(mul64(mul64(i, j), k), mul64(i, mul64(j, k))) != 0) ERR; /* left and right distributivity */ if (cmp64(mul64(add64(i, j), k), add64(mul64(i, k), mul64(j, k))) != 0) ERR; if (cmp64(mul64(i, add64(j, k)), add64(mul64(i, j), mul64(i, k))) != 0) ERR; } }
int CRT(int x1, int x2) { return (mul64(M1, x1, MM) + mul64(M2, x2, MM)) % MM % P; }