static char rcsid[] = "$Id: H:/drh/idioms/book/RCS/mp.doc,v 1.11 1996/06/26 23:02:01 drh Exp $";
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "assert.h"
#include "fmt.h"
#include "mem.h"
#include "xp.h"
#include "mp.h"
#define T MP_T
#define sign(x) ((x)[nbytes-1]>>shift)
#define ones(n) (~(~0UL<<(((n)-1)%8+1)))
#define iszero(x) (XP_length(nbytes,(x))==1 && (x)[0]==0)
#define BASE (1<<8)
#define bitop(op) \
int i; assert(z); assert(x); assert(y); \
for (i = 0; i < nbytes; i++) z[i] = x[i] op y[i]; \
return z
#define bitopi(op) assert(z); assert(x); \
applyu(op, z, x, y); \
return z
#define shft(fill, op) \
assert(x); assert(z); assert(s >= 0); \
if (s >= nbits) memset(z, fill, nbytes); \
else op(nbytes, z, nbytes, x, s, fill); \
z[nbytes-1] &= msb; \
return z
const Except_T MP_Dividebyzero = { "Division by zero" };
const Except_T MP_Overflow = { "Overflow" };
static int nbits = 32;
static int nbytes = (32-1)/8 + 1;
static int shift = (32-1)%8;
static unsigned char msb = 0xFF;
static unsigned char temp[16 + 16 + 16 + 2*16+2];
static T tmp[] = {temp, temp+1*16, temp+2*16, temp+3*16};
static int applyu(T op(T, T, T), T z, T x,
unsigned long u) {
unsigned long carry;
{ T z = tmp[2]; carry = XP_fromint(nbytes, z, u);
carry |= z[nbytes-1]&~msb;
z[nbytes-1] &= msb; }
op(z, x, tmp[2]);
return carry != 0;
}
static int apply(T op(T, T, T), T z, T x, long v) {
{ T z = tmp[2]; if (v == LONG_MIN) {
XP_fromint(nbytes, z, LONG_MAX + 1UL);
XP_neg(nbytes, z, z, 1);
} else if (v < 0) {
XP_fromint(nbytes, z, -v);
XP_neg(nbytes, z, z, 1);
} else
XP_fromint(nbytes, z, v);
z[nbytes-1] &= msb; }
op(z, x, tmp[2]);
return (nbits < 8*(int)sizeof (v) &&
(v < -(1L<<(nbits-1)) || v >= (1L<<(nbits-1))));
}
int MP_set(int n) {
int prev = nbits;
assert(n > 1);
nbits = n;
nbytes = (n-1)/8 + 1;
shift = (n-1)%8;
msb = ones(n);
if (tmp[0] != temp)
FREE(tmp[0]);
if (nbytes <= 16)
tmp[0] = temp;
else
tmp[0] = ALLOC(3*nbytes + 2*nbytes + 2);
tmp[1] = tmp[0] + 1*nbytes;
tmp[2] = tmp[0] + 2*nbytes;
tmp[3] = tmp[0] + 3*nbytes;
return prev;
}
T MP_new(unsigned long u) {
return MP_fromintu(ALLOC(nbytes), u);
}
T MP_fromintu(T z, unsigned long u) {
unsigned long carry;
assert(z);
carry = XP_fromint(nbytes, z, u);
carry |= z[nbytes-1]&~msb;
z[nbytes-1] &= msb;
if (carry)
RAISE(MP_Overflow);
return z;
}
T MP_fromint(T z, long v) {
assert(z);
if (v == LONG_MIN) {
XP_fromint(nbytes, z, LONG_MAX + 1UL);
XP_neg(nbytes, z, z, 1);
} else if (v < 0) {
XP_fromint(nbytes, z, -v);
XP_neg(nbytes, z, z, 1);
} else
XP_fromint(nbytes, z, v);
z[nbytes-1] &= msb;
if ((nbits < 8*(int)sizeof (v) &&
(v < -(1L<<(nbits-1)) || v >= (1L<<(nbits-1)))))
RAISE(MP_Overflow);
return z;
}
long MP_toint(T x) {
unsigned char d[sizeof (unsigned long)];
assert(x);
MP_cvt(8*sizeof d, d, x);
return XP_toint(sizeof d, d);
}
T MP_cvt(int m, T z, T x) {
int fill, i, mbytes = (m - 1)/8 + 1;
assert(m > 1);
assert(x); assert(z);
fill = sign(x) ? 0xFF : 0;
if (m < nbits) {
int carry = (x[mbytes-1]^fill)&~ones(m);
for (i = mbytes; i < nbytes; i++)
carry |= x[i]^fill;
memcpy(z, x, mbytes);
z[mbytes-1] &= ones(m);
if (carry)
RAISE(MP_Overflow);
} else {
memcpy(z, x, nbytes);
z[nbytes-1] |= fill&~msb;
for (i = nbytes; i < mbytes; i++)
z[i] = fill;
z[mbytes-1] &= ones(m);
}
return z;
}
unsigned long MP_tointu(T x) {
unsigned char d[sizeof (unsigned long)];
assert(x);
MP_cvtu(8*sizeof d, d, x);
return XP_toint(sizeof d, d);
}
T MP_cvtu(int m, T z, T x) {
int i, mbytes = (m - 1)/8 + 1;
assert(m > 1);
assert(x); assert(z);
if (m < nbits) {
int carry = x[mbytes-1]&~ones(m);
for (i = mbytes; i < nbytes; i++)
carry |= x[i];
memcpy(z, x, mbytes);
z[mbytes-1] &= ones(m);
if (carry)
RAISE(MP_Overflow);
} else {
memcpy(z, x, nbytes);
for (i = nbytes; i < mbytes; i++)
z[i] = 0;
}
return z;
}
T MP_addu(T z, T x, T y) {
int carry;
assert(x); assert(y); assert(z);
carry = XP_add(nbytes, z, x, y, 0);
carry |= z[nbytes-1]&~msb;
z[nbytes-1] &= msb;
if (carry)
RAISE(MP_Overflow);
return z;
}
T MP_subu(T z, T x, T y) {
int borrow;
assert(x); assert(y); assert(z);
borrow = XP_sub(nbytes, z, x, y, 0);
borrow |= z[nbytes-1]&~msb;
z[nbytes-1] &= msb;
if (borrow)
RAISE(MP_Overflow);
return z;
}
T MP_mul2u(T z, T x, T y) {
assert(x); assert(y); assert(z);
memset(tmp[3], '\0', 2*nbytes);
XP_mul(tmp[3], nbytes, x, nbytes, y);
memcpy(z, tmp[3], (2*nbits - 1)/8 + 1);
return z;
}
T MP_mulu(T z, T x, T y) {
assert(x); assert(y); assert(z);
memset(tmp[3], '\0', 2*nbytes);
XP_mul(tmp[3], nbytes, x, nbytes, y);
memcpy(z, tmp[3], nbytes);
z[nbytes-1] &= msb;
{
int i;
if (tmp[3][nbytes-1]&~msb)
RAISE(MP_Overflow);
for (i = 0; i < nbytes; i++)
if (tmp[3][i+nbytes] != 0)
RAISE(MP_Overflow);
}
return z;
}
T MP_divu(T z, T x, T y) {
assert(x); assert(y); assert(z);
{
memcpy(tmp[1], y, nbytes);
y = tmp[1];
}
if (!XP_div(nbytes, z, x, nbytes, y, tmp[2], tmp[3]))
RAISE(MP_Dividebyzero);
return z;
}
T MP_modu(T z, T x, T y) {
assert(x); assert(y); assert(z);
{
memcpy(tmp[1], y, nbytes);
y = tmp[1];
}
if (!XP_div(nbytes, tmp[2], x, nbytes, y, z, tmp[3]))
RAISE(MP_Dividebyzero);
return z;
}
T MP_add(T z, T x, T y) {
int sx, sy;
assert(x); assert(y); assert(z);
sx = sign(x);
sy = sign(y);
XP_add(nbytes, z, x, y, 0);
z[nbytes-1] &= msb;
if (sx == sy && sy != sign(z))
RAISE(MP_Overflow);
return z;
}
T MP_sub(T z, T x, T y) {
int sx, sy;
assert(x); assert(y); assert(z);
sx = sign(x);
sy = sign(y);
XP_sub(nbytes, z, x, y, 0);
z[nbytes-1] &= msb;
if (sx != sy && sy == sign(z))
RAISE(MP_Overflow);
return z;
}
T MP_neg(T z, T x) {
int sx;
assert(x); assert(z);
sx = sign(x);
XP_neg(nbytes, z, x, 1);
z[nbytes-1] &= msb;
if (sx && sx == sign(z))
RAISE(MP_Overflow);
return z;
}
T MP_mul2(T z, T x, T y) {
int sx, sy;
assert(x); assert(y); assert(z);
sx = sign(x);
sy = sign(y);
if (sx) {
XP_neg(nbytes, tmp[0], x, 1);
x = tmp[0];
x[nbytes-1] &= msb;
}
if (sy) {
XP_neg(nbytes, tmp[1], y, 1);
y = tmp[1];
y[nbytes-1] &= msb;
}
memset(tmp[3], '\0', 2*nbytes);
XP_mul(tmp[3], nbytes, x, nbytes, y);
if (sx != sy)
XP_neg((2*nbits - 1)/8 + 1, z, tmp[3], 1);
else
memcpy(z, tmp[3], (2*nbits - 1)/8 + 1);
return z;
}
T MP_mul(T z, T x, T y) {
int sx, sy;
assert(x); assert(y); assert(z);
sx = sign(x);
sy = sign(y);
if (sx) {
XP_neg(nbytes, tmp[0], x, 1);
x = tmp[0];
x[nbytes-1] &= msb;
}
if (sy) {
XP_neg(nbytes, tmp[1], y, 1);
y = tmp[1];
y[nbytes-1] &= msb;
}
memset(tmp[3], '\0', 2*nbytes);
XP_mul(tmp[3], nbytes, x, nbytes, y);
if (sx != sy)
XP_neg(nbytes, z, tmp[3], 1);
else
memcpy(z, tmp[3], nbytes);
z[nbytes-1] &= msb;
{
int i;
if (tmp[3][nbytes-1]&~msb)
RAISE(MP_Overflow);
for (i = 0; i < nbytes; i++)
if (tmp[3][i+nbytes] != 0)
RAISE(MP_Overflow);
}
if (sx == sy && sign(z))
RAISE(MP_Overflow);
return z;
}
T MP_div(T z, T x, T y) {
int sx, sy;
assert(x); assert(y); assert(z);
sx = sign(x);
sy = sign(y);
if (sx) {
XP_neg(nbytes, tmp[0], x, 1);
x = tmp[0];
x[nbytes-1] &= msb;
}
if (sy) {
XP_neg(nbytes, tmp[1], y, 1);
y = tmp[1];
y[nbytes-1] &= msb;
} else {
memcpy(tmp[1], y, nbytes);
y = tmp[1];
}
if (!XP_div(nbytes, z, x, nbytes, y, tmp[2], tmp[3]))
RAISE(MP_Dividebyzero);
if (sx != sy) {
XP_neg(nbytes, z, z, 1);
if (!iszero(tmp[2]))
XP_diff(nbytes, z, z, 1);
z[nbytes-1] &= msb;
} else if
没有合适的资源?快使用搜索试试~ 我知道了~
《C语言接口与实现》实验——多精度算数(MPCalc)
共61个文件
c:29个
h:24个
lib:1个
需积分: 5 13 下载量 172 浏览量
2012-04-01
20:47:16
上传
评论 1
收藏 151KB ZIP 举报
温馨提示
《C语言接口与实现》实验——多精度算数(MPCalc),书中P263页示例
资源推荐
资源详情
资源评论
收起资源包目录
C语言与实现测试-多精度算数(MPCalc).zip (61个子文件)
C语言与实现测试-多精度算数(MPCalc)
1.c 5KB
libcii.lib 267KB
1.dsw 527B
1.plg 1KB
src
memcmp.c 378B
array.c 2KB
except.c 837B
mp.c 16KB
seq.c 3KB
arena.c 2KB
set.c 7KB
ap.c 9KB
list.c 2KB
arith.c 636B
xp.c 6KB
chan.c 937B
strerror.c 405B
memchk.c 3KB
swtch.s 4KB
atom.c 5KB
fmt.c 9KB
memmove.c 473B
ring.c 4KB
libcii.def 3KB
assert.c 219B
thread.c 7KB
thread-nt.c 7KB
text.c 10KB
bit.c 4KB
stack.c 954B
strncmp.c 393B
mem.c 1KB
str.c 6KB
table.c 3KB
1.opt 55KB
1.dsp 3KB
1.ncb 57KB
include
sem.h 486B
list.h 685B
table.h 704B
arena.h 565B
set.h 769B
mem.h 910B
chan.h 335B
text.h 2KB
assert.h 265B
fmt.h 1KB
mp.h 2KB
arith.h 312B
except.h 2KB
bit.h 827B
atom.h 335B
arrayrep.h 302B
ap.h 1KB
seq.h 534B
stack.h 370B
xp.h 1KB
array.h 531B
ring.h 691B
thread.h 583B
str.h 2KB
共 61 条
- 1
资源评论
dijkstar
- 粉丝: 266
- 资源: 120
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功