传说中的实现除数比较复杂,我自己做的运算比他简单
只是风格不一样,回头改掉他
#include <ctype.h>
#include <string.h>
#include "assert.h"
#include "calc.h"
#define T XP_T
#define BASE (1<<8)
unsigned long XP_fromint(int n, T z, unsigned long u)
{
int i = 0;
do
z[i++] = u%BASE;
while((u/=BASE)>0 && i < n);
for( ; i < n; i++ )
z[i++] = 0;
return u;
}
unsigned long XP_toint(int n, T x)
{
unsigned long u = 0;
int i = (int) sizeof u;
if( i > n )
i = n;
while( --i >= 0 )
u = BASE*u + x[i];
return u;
}
int XP_length( int n, T x)
{
while( n>1 && x[n-1]==0 )
n--;
return n;
}
int XP_add( int n, T z, T x, T y, int carry )
{
int i = 0;
for( i=0; i<n; i++ )
{
carry += x[i] + y[i];
z[i] = carry % BASE;
carry /= BASE;
}
return carry;
}
int XP_sub( int n, T z, T x, T y, int borrow )
{
int i;
for( i=0; i<n; i++ )
{
int d = (x[i]+BASE) - borrow - y[i];
z[i] = d % BASE;
borrow = 1 - d/BASE ;
}
return borrow;
}
int XP_sum( int n, T z, T x, int y)
{
int i;
for( i = 0; i < n; i++ )
{
y += x[i];
z[i] = y%BASE;
y /= BASE;
}
return y;
}
int XP_diff( int n, T z, T x, int y)
{
int i;
for( i = 0; i < n; i++ )
{
int d = ( x[i] + BASE ) - y;
z[i] = d%BASE;
y /= 1- d/BASE;
}
return y;
}
int XP_neg( int n, T z, T x, int carry )
{
int i;
for( i = 0; i < n; i++ )
{
carry += (unsigned char)~x[i];
z[i] = carry%BASE;
carry /= BASE;
}
return carry;
}
int XP_mul( T z, int n, T x, int m, T y)
{
int i, j, carryout = 0;
for( i = 0; i < n; i++ )
{
unsigned carry = 0;
for( j = 0; j < m; j++ )
{
carry += x[i]*y[j] + z[i+j];
z[i+j] = carry%BASE;
carry /= BASE;
}
for( ; j< n+m-1; j++ )
{
carry += z[i+j];
z[i+j] = carry%BASE;
carry /= BASE;
}
carryout |= carry;
}
return carryout;
}
int XP_product(int n, T z, T x, int y)
{
int i;
unsigned carry = 0;
for( i = 0; i < n; i++ )
{
carry += x[i]*y;
z[i] = carry%BASE;
carry / BASE;
}
return carry;
}
//////////////////////////////////////////////////////////////////////////
int XP_div(int n, T q, T x, int m, T y, T r, T tmp)
{
int nx = n, my = m;
n = XP_length(n, x);
m = XP_length(m, y);
//只有一个元素
if( m == 1 )
{
//并且除数为0
if(y[0]==0)
return 0;
//single digit division
r[0] = XP_quotient(nx,q,x,y[0]);
//fill zero
memset(r+1, '/0', my-1);
}
else if( m > n)
{
memset( q, '/0', nx);
memcpy(r, x, n);
memset(r+n, '/0', my - n);
}
else
{
int k;
unsigned char *rem = tmp, *dq = tmp+n+1;
assert(2<=m && m<=n);
memcpy( rem, x, n);
rem[n] = 0;
for( k = n - m; k >= 0; k-- )
{
int qk;
{
int i;
assert(2<=m && m < k+m & k+m < n );
{
int km = k + m;
unsigned long y2 = y[m-1]*BASE + y[m-2];
unsigned long r3 = rem[km]*(BASE*BASE) + rem[km-1]*BASE+rem[km-2];
qk = r3/y2;
if(qk>=BASE)
qk = BASE - 1;
}
}
q[k] = qk;
{
int borrow;
assert( 0 <= k && k <= k+m );
borrow = XP_sub( m+1, &rem[k], &rem[k], dq, 0 );
assert(borrow==0);
}
}
memcpy(r, rem, m );
{
int i;
for( i = n- m +1; i < nx; i++ )
q[i] = 0;
for( i = m; i < my; i++ )
r[i] = 0;
}
}
}
/*
* 这里的数值计算David分析的比较透彻,除法
*
*/
int XP_quotient(int n, T z, T x, int y)
{
int i;
unsigned carry = 0;
for( i = n - 1; i >= 0; i--)
{
carry = carry*BASE+x[i];
z[i] = carry/y;
carry %= y;
}
return carry;
}