Exemple #1
0
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;

}
Exemple #2
0
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
}
Exemple #4
0
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;
}
Exemple #5
0
void SetIntNum16(void) { /* 1 */
	/*
	  64 bit 演算のための数値をセット

	  var: 数値の入った変数
	*/
	int *var = getCaliVariable();
	
	l_1000A0D8 = mul64(*var, numbase);
	
	DEBUG_COMMAND("ShCalc.SetIntNum16 %p:\n", var);
}
Exemple #6
0
void AddIntNum16(void) { /* 5 */
	/*
	  64 bit 加算

	  var: 足す数の入った変数
	 */
	int *var = getCaliVariable();
	
	l_1000A0D8 += mul64(*var, numbase);
	
	DEBUG_COMMAND("ShCalc.AddIntNum16 %p:\n", var);
}
Exemple #7
0
void MulIntNum16(void) {  /* 9 */
	/*
	  64 bit 乗算
	  
	  var: 掛ける数の入った変数
	 */
	int *var = getCaliVariable();
	
	l_1000A0D8 *= mul64(*var, numbase);
	
	DEBUG_COMMAND("ShCalc.MulIntNum16: %p:\n", var);
}
Exemple #8
0
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;
}
Exemple #9
0
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
}
Exemple #11
0
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(&current_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;
}
Exemple #12
0
/* 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);
	}
Exemple #13
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);
}
Exemple #14
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);
}
Exemple #17
0
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
}
Exemple #18
0
/*--- 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);
	}

}
Exemple #19
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);
	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);
	}
Exemple #20
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;
}
Exemple #21
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;
}