factor/native/ratio.c

159 lines
3.1 KiB
C
Raw Normal View History

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)));
}
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)
{
switch(type_of(dpeek()))
2004-08-04 22:43:58 -04:00
{
case FIXNUM_TYPE:
case BIGNUM_TYPE:
/* No op */
break;
case RATIO_TYPE:
drepl(untag_ratio(dpeek())->numerator);
2004-08-04 22:43:58 -04:00
break;
default:
type_error(RATIONAL_TYPE,dpeek());
2004-08-04 22:43:58 -04:00
break;
}
}
void primitive_denominator(void)
{
switch(type_of(dpeek()))
2004-08-04 22:43:58 -04:00
{
case FIXNUM_TYPE:
case BIGNUM_TYPE:
drepl(tag_fixnum(1));
2004-08-04 22:43:58 -04:00
break;
case RATIO_TYPE:
drepl(untag_ratio(dpeek())->denominator);
2004-08-04 22:43:58 -04:00
break;
default:
type_error(RATIONAL_TYPE,dpeek());
2004-08-04 22:43:58 -04:00
break;
}
}
2004-08-05 15:18:31 -04:00
CELL number_eq_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return tag_boolean(
untag_boolean(number_eq(x->numerator,y->numerator)) &&
untag_boolean(number_eq(x->denominator,y->denominator)));
2004-08-05 15:18:31 -04:00
}
CELL add_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -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
}
CELL subtract_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -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
}
CELL multiply_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return divide(
multiply(x->numerator,y->numerator),
multiply(x->denominator,y->denominator));
2004-08-05 15:18:31 -04:00
}
CELL divide_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return divide(
multiply(x->numerator,y->denominator),
multiply(x->denominator,y->numerator));
2004-08-05 15:18:31 -04:00
}
CELL divfloat_ratio(RATIO* x, RATIO* y)
2004-08-05 16:49:55 -04:00
{
return divfloat(
multiply(x->numerator,y->denominator),
multiply(x->denominator,y->numerator));
2004-08-05 16:49:55 -04:00
}
CELL less_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return less(multiply(x->numerator,y->denominator),
multiply(y->numerator,x->denominator));
2004-08-05 15:18:31 -04:00
}
CELL lesseq_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return lesseq(multiply(x->numerator,y->denominator),
multiply(y->numerator,x->denominator));
2004-08-05 15:18:31 -04:00
}
CELL greater_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return greater(multiply(x->numerator,y->denominator),
multiply(y->numerator,x->denominator));
2004-08-05 15:18:31 -04:00
}
CELL greatereq_ratio(RATIO* x, RATIO* y)
2004-08-05 15:18:31 -04:00
{
return greatereq(multiply(x->numerator,y->denominator),
multiply(y->numerator,x->denominator));
2004-08-05 15:18:31 -04:00
}