|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 4791 (0x12b7)
Types: TextFile
Notes: UNIX file
Names: »bcmch.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/bc/bcmch.c«
#include <stdio.h>
#include <assert.h>
#include "bc.h"
/*
* Sscale takes the rvalue pointed to by lval and sets
* the scale register to it if it is in range (ie. non-negative
* and small enough to fit in an int).
*/
sscale(lval)
rvalue *lval;
{
register int res;
res = rtoint(lval);
if (res < 0)
bcmerr("Invalid scale register value");
scale = res;
}
/*
* Bcclean frees up the automatic variables and parameters on
* function exit. `fnc' is the function from which we are returning
* and `stkp' is a pointer to the top thing to remove.
*/
bcclean(fnc, stkp)
func *fnc;
stkent *stkp;
{
register type *tp;
register int left;
tp = &fnc->types[fnc->nautos + fnc->nparams];
for (left = fnc->nautos; --left >= 0; --stkp)
switch (*--tp) {
case SCALAR:
mvfree(&stkp->rvalue.mantissa);
break;
case ARRAY:
arfree(stkp->alvalue);
mpfree(stkp->alvalue);
break;
default:
assert(FALSE);
}
for (left = fnc->nparams; --left >= 0; --stkp)
switch (*--tp) {
case SCALAR:
mvfree(&stkp->rvalue.mantissa);
break;
case ARRAY:
break;
default:
assert(FALSE);
}
}
/*
* Bcadd adds the rvalue pointed to by `src' to that pointed to
* by `dst'. Note that `src' is freed.
*/
bcadd(src, dst)
register rvalue *src, *dst;
{
if (dst->scale >= src->scale)
rescale(src, dst->scale);
else
rescale(dst, src->scale);
madd(&dst->mantissa, &src->mantissa, &dst->mantissa);
mvfree(&src->mantissa);
}
/*
* Bcmul multiplies the rvalue pointed to by `dst' by that
* pointed to by `src'. Note that `src' is freed.
* The scale factor of the result is set to
* min( src->scale + dst->scale, max(scale, src->scale, dst->scale)).
*/
bcmul(src, dst)
register rvalue *src, *dst;
{
register int scl;
mult(&dst->mantissa, &src->mantissa, &dst->mantissa);
mvfree(&src->mantissa);
scl = src->scale;
if (scl < scale)
scl = scale;
if (scl < dst->scale)
scl = dst->scale;
dst->scale += src->scale;
if (scl < dst->scale)
rescale(dst, scl);
}
/*
* Bcdiv divides the rvalue pointed to by `dst' by that pointed
* to by `src'. Note that `src' is freed. The scale of the
* result is alway equal to the value of the scale register.
*/
bcdiv(src, dst)
register rvalue *src, *dst;
{
if (zerop(&src->mantissa))
bcmerr("Division by zero");
rescale(dst, src->scale + scale);
mdiv(&dst->mantissa, &src->mantissa, &dst->mantissa, &src->mantissa);
dst->scale = scale;
mvfree(&src->mantissa);
}
/*
* Bcrem sets the rvalue pointed to by `dst' to the remainder one
* would get when divideing `dst' by `src'. Note that `src' is freed.
*/
bcrem(src, dst)
register rvalue *src, *dst;
{
if (zerop(&src->mantissa))
bcmerr("Modulo zero");
rescale(dst, src->scale + scale);
mdiv(&dst->mantissa, &src->mantissa, &src->mantissa, &dst->mantissa);
mvfree(&src->mantissa);
}
/*
* Bcexp raises the rvalue pointed to by `dst' to the `src' power.
* Note that first `src' is truncated to an integer. Note that
* `src' is freed. The scale factor of the result is as if the
* corresponding multiplications had been done.
*/
bcexp(src, dst)
register rvalue *src, *dst;
{
register int limit;
mint temp;
int rem;
minit(&temp);
shift(&src->mantissa, - src->scale, &temp);
sdiv(&temp, 2, &temp, &rem);
if (rem == 0) {
mvfree(&src->mantissa);
*src = *dst;
minit(&dst->mantissa);
mcopy(mone, &dst->mantissa);
dst->scale = 0;
} else {
mcopy(&dst->mantissa, &src->mantissa);
src->scale = dst->scale;
}
limit = (src->scale > scale ? src->scale : scale);
while (!zerop(&temp)) {
mult(&src->mantissa, &src->mantissa, &src->mantissa);
src->scale *= 2;
if (src->scale > limit)
rescale(src, limit);
sdiv(&temp, 2, &temp, &rem);
if (rem != 0) {
mult(&src->mantissa, &dst->mantissa, &dst->mantissa);
dst->scale += src->scale;
if (dst->scale > limit)
rescale(dst, limit);
}
}
mvfree(&temp);
mvfree(&src->mantissa);
}
/*
* Bcsqrt relaces the rvalue pointed to by `dst' with its
* square root. The scale factor of the result is the maximum
* of the scale register and of the scale of the argument.
*/
bcsqrt(dst)
register rvalue *dst;
{
register int prec;
mint temp;
prec = scale;
if (prec < dst->scale)
prec = dst->scale;
rescale(dst, 2 * prec);
minit(&temp);
msqrt(&dst->mantissa, &dst->mantissa, &temp);
mvfree(&temp);
dst->scale = prec;
}
/*
* Bccmp returns an int which compares to zero as the rvalue `dst'
* compares to the rvalue `src'. Note that both `src' and `dst'
* are freed.
*/
bccmp(src, dst)
register rvalue *src, *dst;
{
register int res;
if (dst->scale >= src->scale)
rescale(src, dst->scale);
else
rescale(dst, src->scale);
res = mcmp(&dst->mantissa, &src->mantissa);
mvfree(&src->mantissa);
mvfree(&dst->mantissa);
return (res);
}