int div_b(BN a, BN b, BN q, BN rem)
{
memset(rem, 0, sizeof(rem));
memset(q, 0, sizeof(q));
BND b_t;//临时存放b
BND q_t = { 0 };//每个商
uint32_t r_t[2 + (BNMAXDGT << 1)];
uint32_t *bptr, *mbptr, *rptr, *rcir, *mrptr, *qptr;
uint32_t d = 0, qh = 0,qh1=0;
uint64_t kuo, left, right, borrow, carry;
uint32_t bn_1 = 0, bn_2 = 0;
uint32_t ri = 0, ri_1 = 0, ri_2 = 0;//三个r',乘了d以后的
cpy_b(r_t, a);
cpy_b(b_t, b);
if (DIGITS_B(b) == 0)//如果b是0,除0错误
return FLAG_DIVZERO;
else if (DIGITS_B(r_t) == 0)//如果a=0
{
SETZERO_B(q);
SETZERO_B(rem);
return FLAG_OK;
}
else if (cmp_b(r_t, b_t) == -1)//如果a
{
cpy_b(rem, r_t);
SETZERO_B(q);//商为0
return FLAG_OK;
}
else if (cmp_b(r_t, b_t) == 0)//如果a=b,返回1就好了
{
q[0] = 1; q[1] = 1;//商为1
SETZERO_B(rem);//余数为0
return FLAG_OK;
}
else if (DIGITS_B(r_t) == 0)//如果a=0,非常好
{
SETZERO_B(q);
SETZERO_B(rem);
return FLAG_OK;
}
//如果除数位数为1,使用移位除法,后面要求除数大于等于两位
if (DIGITS_B(b_t) == 1)
{
mydiv_b(r_t, b_t, q, rem);
return FLAG_OK;
}
mbptr = MSDPTR_B(b_t);
bn_1 = *mbptr;
while (bn_1 < BASEDIV2)
{
bn_1 = bn_1 << 1;
d++;
}
uint64_t shiftr =(int)(BITPERDIGIT - d);//左移时配合的右移次数
if (d > 0)
{
bn_1 = bn_1 + (uint32_t)((uint64_t)*(mbptr - 1) >> shiftr);
if (DIGITS_B(b_t) > 2)
bn_2 = (uint32_t)((uint32_t)((uint64_t)(*(mbptr - 1)) << d) + (uint32_t)((uint64_t)(*(mbptr - 2)) >> shiftr));
else//等于两位则直接赋值
{
bn_2 = (uint32_t)((uint64_t)(*(mbptr - 1)) << d);
}
}
else//没有移动则原封不动
{
bn_2 = (uint32_t)(*(mbptr - 1));
}
mbptr = MSDPTR_B(b_t);
mrptr = MSDPTR_B(r_t) + 1;//指向滑动窗口最高位,填了一位,之后可能是0可能不是,由后面移位决定
rptr = MSDPTR_B(r_t) - DIGITS_B(b_t) + 1;//指向滑动窗口最低位
qptr = q + DIGITS_B(r_t) - DIGITS_B(b_t) + 1;//最高即将可能为0可能不是,由后面移位决定
*mrptr = 0;//初始化为0
while (rptr >= LSDPTR_B(r_t))//开始做事情,下标对应,r(m+n)对应a(m),r(m+n-1)对应a(m-1)
{
ri = (uint32_t)((uint32_t)((uint64_t)(*mrptr) << d) + (uint32_t)((uint64_t)(*(mrptr - 1)) >> shiftr));
ri_1 = (uint32_t)(((uint32_t)((uint64_t)(*(mrptr - 1)) << d) + (uint32_t)((uint64_t)(*(mrptr - 2)) >> shiftr)));
if (mrptr - 3 > r_t)//不止有3位
{
ri_2 = (uint32_t)(((uint32_t)((uint64_t)(*(mrptr - 2)) << d) + (uint32_t)((uint64_t)(*(mrptr - 3)) >> shiftr)));
}
else//只有2位
{
ri_2 = (uint32_t)((uint64_t)(*(mrptr - 2)) << d);
}
//计算q估计,kuo是64位的,取整数部分
kuo = (uint64_t)((((uint64_t)ri << BITPERDIGIT) + (uint64_t)ri_1) / bn_1);
if (kuo < ALLONE)//选择小的那个,最大估计的q不会超过B-1,不会超过B进制
{
qh = (uint32_t)kuo;
}
else
qh = ALLONE;
kuo = ((uint64_t)ri << BITPERDIGIT) + (uint64_t)ri_1 - (uint64_t)bn_1*(uint64_t)qh;
if (kuo < BASE)//如果括号中的都比B大了,左边肯定b[n-2]*q小于B*B,小于才比较,大于会溢出,也比较不了
{
right = (uint64_t)(kuo << BITPERDIGIT) + (uint64_t)ri_2;
left = (uint64_t)bn_2 *(uint64_t)qh;
if (left > right)//没有溢出,需要比较
{
qh--;
//重复这一过程
kuo = ((uint64_t)ri << BITPERDIGIT) + (uint64_t)ri_1 - (uint64_t)bn_1*(uint64_t)qh;
if (kuo< BASE)//如果括号中的都比B大了,左边肯定b[n-2]*q小于B*B,小于才比较,大于会溢出,也比较不了
{
right = (uint64_t)(kuo << BITPERDIGIT) + (uint64_t)ri_2;
left = (uint64_t)bn_2 *(uint64_t)qh;
if (left > right)//没有溢出,需要比较
qh--;
}
else
{
//printf("rh = %llX
", rh);
//printf("rh*B = %llX
",rh <
//printf("rh*B+ri-2 = %llX
", (rh << BITPERDIGIT) + (uint64_t)ri_2);
}
}
}
borrow = BASE;//借位默认
carry = 0;
int i = 0;
for (bptr = LSDPTR_B(b_t), rcir = rptr; bptr <= mbptr; bptr++, rcir++)
{
if (borrow>= BASE)// 没有发生借位的情况,最高处总是BASE
{
carry = (uint64_t)qh * (uint64_t)*bptr + (uint64_t)(uint32_t)(carry >> BITPERDIGIT);
borrow = (uint64_t)*rcir + BASE - (uint64_t)(uint32_t)carry;
*rcir = (uint32_t)(borrow);
}
else//发生了借位,恢复
{
carry = (uint64_t)qh * (uint64_t)*bptr + (uint64_t)(uint32_t)(carry >> BITPERDIGIT);
borrow = (uint64_t)*rcir + (uint64_t)BASE - (uint64_t)(uint32_t)carry - 1ULL;//借位了
*rcir = (uint32_t)(borrow);
}
}
if (borrow >= BASE) //没有发生借位的情况,最高处总是BASE
{
borrow = (uint64_t)*rcir + BASE - (uint64_t)(uint32_t)(carry >> BITPERDIGIT);
*rcir = (uint32_t)(borrow);
}
else//发生了借位
{
borrow = (uint64_t)*rcir + BASE - (uint64_t)(uint32_t)(carry >> BITPERDIGIT) - 1ULL;//借位了
*rcir = (uint32_t)(borrow);
}
*qptr = qh;
if (borrow < BASE)//borrow还被借位了没有还回来,q大了一位,b加会到a中,和加法过程一样
{
carry = 0;
for (bptr = LSDPTR_B(b_t), rcir = rptr; bptr <= mbptr; bptr++, rcir++)
{
carry = ((uint64_t)*rcir + (uint64_t)*bptr + (uint64_t)(uint32_t)(carry >> BITPERDIGIT));
*rcir = (uint32_t)carry;
}
*rcir = *rcir + (uint32_t)(carry >> BITPERDIGIT);
*qptr = *qptr - 1;
}
qptr--; mrptr--; rptr--;
}
SETDIGITS_B(q, DIGITS_B(r_t) - DIGITS_B(b_t) + 1);
RMLDZRS_B(q);
SETDIGITS_B(r_t, DIGITS_B(b_t));
cpy_b(rem, r_t);
return FLAG_OK;
}