2004-08-04 22:43:58 -04:00
|
|
|
#include "factor.h"
|
|
|
|
|
|
|
|
RATIO* ratio(CELL numerator, CELL denominator)
|
|
|
|
{
|
2004-08-05 20:29:52 -04:00
|
|
|
RATIO* ratio = allot(sizeof(RATIO));
|
2004-08-04 22:43:58 -04:00
|
|
|
ratio->numerator = numerator;
|
|
|
|
ratio->denominator = denominator;
|
|
|
|
return ratio;
|
|
|
|
}
|
|
|
|
|
2004-09-18 22:29:29 -04:00
|
|
|
/* Does not reduce to lowest terms, so should only be used by math
|
|
|
|
library implementation, to avoid breaking invariants. */
|
|
|
|
void primitive_from_fraction(void)
|
|
|
|
{
|
|
|
|
CELL denominator = dpop();
|
|
|
|
CELL numerator = dpop();
|
|
|
|
if(zerop(denominator))
|
|
|
|
raise(SIGFPE);
|
|
|
|
if(onep(denominator))
|
|
|
|
dpush(numerator);
|
|
|
|
dpush(tag_ratio(ratio(numerator,denominator)));
|
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
RATIO* to_ratio(CELL x)
|
|
|
|
{
|
|
|
|
switch(type_of(x))
|
|
|
|
{
|
|
|
|
case FIXNUM_TYPE:
|
|
|
|
case BIGNUM_TYPE:
|
|
|
|
return ratio(x,tag_fixnum(1));
|
|
|
|
case RATIO_TYPE:
|
|
|
|
return (RATIO*)UNTAG(x);
|
|
|
|
default:
|
|
|
|
type_error(RATIONAL_TYPE,x);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-18 22:29:29 -04:00
|
|
|
void primitive_to_fraction(void)
|
2004-08-04 22:43:58 -04:00
|
|
|
{
|
2004-09-18 22:29:29 -04:00
|
|
|
RATIO* r;
|
|
|
|
|
|
|
|
switch(type_of(dpeek()))
|
|
|
|
{
|
|
|
|
case FIXNUM_TYPE:
|
|
|
|
case BIGNUM_TYPE:
|
|
|
|
dpush(tag_fixnum(1));
|
|
|
|
break;
|
|
|
|
case RATIO_TYPE:
|
|
|
|
r = untag_ratio(dpeek());
|
|
|
|
drepl(r->numerator);
|
|
|
|
dpush(r->denominator);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type_error(RATIONAL_TYPE,dpeek());
|
|
|
|
break;
|
|
|
|
}
|
2004-08-04 22:43:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_numerator(void)
|
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
switch(type_of(dpeek()))
|
2004-08-04 22:43:58 -04:00
|
|
|
{
|
|
|
|
case FIXNUM_TYPE:
|
|
|
|
case BIGNUM_TYPE:
|
|
|
|
/* No op */
|
|
|
|
break;
|
|
|
|
case RATIO_TYPE:
|
2004-08-12 17:36:36 -04:00
|
|
|
drepl(untag_ratio(dpeek())->numerator);
|
2004-08-04 22:43:58 -04:00
|
|
|
break;
|
|
|
|
default:
|
2004-08-12 17:36:36 -04:00
|
|
|
type_error(RATIONAL_TYPE,dpeek());
|
2004-08-04 22:43:58 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_denominator(void)
|
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
switch(type_of(dpeek()))
|
2004-08-04 22:43:58 -04:00
|
|
|
{
|
|
|
|
case FIXNUM_TYPE:
|
|
|
|
case BIGNUM_TYPE:
|
2004-08-12 17:36:36 -04:00
|
|
|
drepl(tag_fixnum(1));
|
2004-08-04 22:43:58 -04:00
|
|
|
break;
|
|
|
|
case RATIO_TYPE:
|
2004-08-12 17:36:36 -04:00
|
|
|
drepl(untag_ratio(dpeek())->denominator);
|
2004-08-04 22:43:58 -04:00
|
|
|
break;
|
|
|
|
default:
|
2004-08-12 17:36:36 -04:00
|
|
|
type_error(RATIONAL_TYPE,dpeek());
|
2004-08-04 22:43:58 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-08-05 15:18:31 -04:00
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL number_eq_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
|
|
|
return tag_boolean(
|
2004-08-25 00:26:49 -04:00
|
|
|
untag_boolean(number_eq(x->numerator,y->numerator)) &&
|
|
|
|
untag_boolean(number_eq(x->denominator,y->denominator)));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL add_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return divide(add(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(x->denominator,y->numerator)),
|
|
|
|
multiply(x->denominator,y->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL subtract_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return divide(subtract(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(x->denominator,y->numerator)),
|
|
|
|
multiply(x->denominator,y->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL multiply_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
|
|
|
return divide(
|
2004-08-25 00:26:49 -04:00
|
|
|
multiply(x->numerator,y->numerator),
|
|
|
|
multiply(x->denominator,y->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL divide_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
|
|
|
return divide(
|
2004-08-25 00:26:49 -04:00
|
|
|
multiply(x->numerator,y->denominator),
|
|
|
|
multiply(x->denominator,y->numerator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL divfloat_ratio(RATIO* x, RATIO* y)
|
2004-08-05 16:49:55 -04:00
|
|
|
{
|
|
|
|
return divfloat(
|
2004-08-25 00:26:49 -04:00
|
|
|
multiply(x->numerator,y->denominator),
|
|
|
|
multiply(x->denominator,y->numerator));
|
2004-08-05 16:49:55 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL less_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return less(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(y->numerator,x->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL lesseq_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return lesseq(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(y->numerator,x->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL greater_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return greater(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(y->numerator,x->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|
|
|
|
|
2004-08-25 00:26:49 -04:00
|
|
|
CELL greatereq_ratio(RATIO* x, RATIO* y)
|
2004-08-05 15:18:31 -04:00
|
|
|
{
|
2004-08-25 00:26:49 -04:00
|
|
|
return greatereq(multiply(x->numerator,y->denominator),
|
|
|
|
multiply(y->numerator,x->denominator));
|
2004-08-05 15:18:31 -04:00
|
|
|
}
|