|
|
Initial revision
/*
* Copyright (c) 1982 Regents of the University of California
*/
#ifndef lint
static char sccsid[] = "@(#)bignum1.c 4.4 6/30/83";
#endif not lint
#include <errno.h>
#include <stdio.h>
#include "as.h"
Bignum Znumber;
/*
* Construct an integer.
*/
Bignum as_atoi(ccp, radix, ovfp)
reg char *ccp; /* character cp */
int radix;
Ovf *ovfp;
{
reg chptr bcp;
chptr tcp;
reg int i;
int val;
Bignum n_n;
Bignum t_n;
int sign;
Ovf ovf;
ovf = 0;
sign = 0;
for (; *ccp; ccp++){
switch(*ccp){
case '0':
case '+': continue;
case '-': sign ^= 1;
continue;
}
break;
}
n_n = Znumber;
t_n = Znumber;
bcp = CH_FIELD(n_n); (void)numclear(bcp);
tcp = CH_FIELD(t_n); (void)numclear(tcp);
for (; *ccp; ccp++){
switch(*ccp){
case '8': case '9':
if (radix < 10)
goto done;
/*FALLTHROUGH*/
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
val = *ccp - '0';
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
if (radix < 16)
goto done;
val = *ccp - 'A' + 10;
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
if (radix < 16)
goto done;
val = *ccp - 'a' + 10;
break;
default:
goto done;
}
switch(radix){
case 8:
ovf |= numshift(3, bcp, bcp);
break;
case 16:
ovf |= numshift(4, bcp, bcp);
break;
case 10:
ovf |= numshift(1, tcp, bcp);
ovf |= numshift(3, bcp, bcp);
ovf |= numaddv(bcp, tcp, bcp);
break;
}
ovf |= numaddd(bcp, bcp, val);
}
done: ;
ovf |= posovf(bcp);
if (sign){
if (ovf & OVF_MAXINT) {
ovf &= ~(OVF_MAXINT | OVF_POSOVF);
} else {
ovf |= numnegate(bcp, bcp);
}
}
/*
* find the highest set unit of the number
*/
val = sign ? -1 : 0;
for (i = 0; i < CH_N; i++){
if (bcp[i] == val)
break;
}
{
static u_char tagtab[4][8] = {
{ TYPB,
TYPW,
TYPL, TYPL,
TYPQ, TYPQ, TYPQ, TYPQ },
{ TYPW,
TYPL,
TYPQ, TYPQ },
{ 0 },
{ TYPL,
TYPQ }
};
/*
* i indexes to the null chunk; make it point to the
* last non null chunk
*/
i -= 1;
if (i < 0)
i = 0;
n_n.num_tag = tagtab[HOC][i];
assert(n_n.num_tag != 0, " Botch width computation");
}
*ovfp = ovf;
return(n_n);
}
Bignum as_atof (numbuf, radix)
char *numbuf;
{
double atof ();
Bignum number;
number = Znumber;
number.num_tag = radix;
switch (radix)
{
case TYPD:
number.num_num.numFd_float.Fd_value = atof (numbuf);
break;
case TYPF:
number.num_num.numFf_float.Ff_value = atof (numbuf);
break;
}
return (number);
}
Ovf posovf(src)
reg chptr src;
{
reg int i;
Ovf overflow = 0;
if (src[HOC] & SIGNBIT)
overflow = OVF_POSOVF;
if (src[HOC] == SIGNBIT){
for (i = HOC - 1; i >= 0; --i){
if (src[i] != 0)
return(overflow);
}
overflow |= OVF_MAXINT;
}
return(overflow);
}
/*
* check if the number is clear
*/
int isclear(dst)
reg chptr dst;
{
return(!isunequal(dst, CH_FIELD(Znumber)));
}
int isunequal(src1, src2)
reg chptr src1, src2;
{
reg int i;
i = CH_N;
do{
if (*src1++ != *src2++)
return(i);
}while(--i);
return(0);
}
Ovf numclear(dst)
reg chptr dst;
{
reg int i;
i = CH_N;
do{
*dst++ = 0;
}while(--i);
return(0);
}
Ovf numshift(n, dst, src)
int n;
reg chptr dst, src;
{
reg int i;
reg u_int carryi, carryo;
reg u_int mask;
reg u_int value;
i = CH_N;
if (n == 0){
do{
*dst++ = *src++;
} while(--i);
return(0);
}
carryi = 0;
mask = ONES(n);
if (n > 0){
do{
value = *src++;
carryo = (value >> (CH_BITS - n)) & mask;
value <<= n;
value &= ~mask;
*dst++ = value | carryi;
carryi = carryo;
} while (--i);
return(carryi ? OVF_LSHIFT : 0);
} else {
n = -n;
src += CH_N;
dst += CH_N;
do{
value = *--src;
carryo = value & mask;
value >>= n;
value &= ONES(CH_BITS - n);
*--dst = value | carryi;
carryi = carryo << (CH_BITS - n);
} while (--i);
return(carryi ? OVF_LSHIFT : 0);
}
}
Ovf numaddd(dst, src1, val)
chptr dst, src1;
int val;
{
static Bignum work;
work.num_uchar[3] = val;
return (numaddv(dst, src1, CH_FIELD(work)));
}
Ovf numaddv(dst, src1, src2)
reg chptr dst, src1, src2;
{
reg int i;
reg int carry;
reg u_int A,B,value;
carry = 0;
i = CH_N;
do{
A = *src1++;
B = *src2++;
value = A + B + carry;
*dst++ = value;
carry = 0;
if (value < A || value < B)
carry = 1;
} while (--i);
return(carry ? OVF_ADDV : 0);
}
Ovf numnegate(dst, src)
chptr dst, src;
{
Ovf ovf;
ovf = num1comp(dst, src) ;
ovf |= numaddd(dst, dst, 1);
return(ovf);
}
Ovf num1comp(dst, src)
reg chptr dst, src;
{
reg int i;
i = CH_N;
do{
*dst++ = ~ *src++;
}while (--i);
return(0);
}
bignumprint(number)
Bignum number; /* number presented */
{
switch (num_type)
{
case TYPQ:
printf ("val[msd] = 0x%x, val[lsd] = 0x%x.",
number.num_num.numIq_int.Iq_ulong[1],
number.num_num.numIq_int.Iq_ulong[0]);
break;
case TYPF:
printf ("value %20.17f",
number.num_num.numFf_float.Ff_value);
break;
case TYPD:
printf ("value %20.17f",
number.num_num.numFd_float.Fd_value);
break;
default:
break;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.