198 lines
3.5 KiB
C
198 lines
3.5 KiB
C
#include "factor.h"
|
|
|
|
COMPLEX* complex(CELL real, CELL imaginary)
|
|
{
|
|
COMPLEX* complex = allot(sizeof(COMPLEX));
|
|
complex->real = real;
|
|
complex->imaginary = imaginary;
|
|
return complex;
|
|
}
|
|
|
|
COMPLEX* to_complex(CELL x)
|
|
{
|
|
switch(type_of(x))
|
|
{
|
|
case FIXNUM_TYPE:
|
|
case BIGNUM_TYPE:
|
|
case FLOAT_TYPE:
|
|
case RATIO_TYPE:
|
|
return complex(x,0);
|
|
case COMPLEX_TYPE:
|
|
return (COMPLEX*)UNTAG(x);
|
|
default:
|
|
type_error(NUMBER_TYPE,x);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
CELL possibly_complex(CELL real, CELL imaginary)
|
|
{
|
|
if(zerop(imaginary))
|
|
return real;
|
|
else
|
|
return tag_complex(complex(real,imaginary));
|
|
}
|
|
|
|
void primitive_complexp(void)
|
|
{
|
|
drepl(tag_boolean(typep(COMPLEX_TYPE,dpeek())));
|
|
}
|
|
|
|
void primitive_real(void)
|
|
{
|
|
switch(type_of(dpeek()))
|
|
{
|
|
case FIXNUM_TYPE:
|
|
case BIGNUM_TYPE:
|
|
case FLOAT_TYPE:
|
|
case RATIO_TYPE:
|
|
/* No op */
|
|
break;
|
|
case COMPLEX_TYPE:
|
|
drepl(untag_complex(dpeek())->real);
|
|
break;
|
|
default:
|
|
type_error(NUMBER_TYPE,dpeek());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void primitive_imaginary(void)
|
|
{
|
|
switch(type_of(dpeek()))
|
|
{
|
|
case FIXNUM_TYPE:
|
|
case BIGNUM_TYPE:
|
|
case FLOAT_TYPE:
|
|
case RATIO_TYPE:
|
|
drepl(tag_fixnum(0));
|
|
break;
|
|
case COMPLEX_TYPE:
|
|
drepl(untag_complex(dpeek())->imaginary);
|
|
break;
|
|
default:
|
|
type_error(NUMBER_TYPE,dpeek());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void primitive_to_rect(void)
|
|
{
|
|
COMPLEX* c;
|
|
switch(type_of(dpeek()))
|
|
{
|
|
case FIXNUM_TYPE:
|
|
case BIGNUM_TYPE:
|
|
case FLOAT_TYPE:
|
|
case RATIO_TYPE:
|
|
dpush(tag_fixnum(0));
|
|
break;
|
|
case COMPLEX_TYPE:
|
|
c = untag_complex(dpop());
|
|
dpush(c->real);
|
|
dpush(c->imaginary);
|
|
break;
|
|
default:
|
|
type_error(NUMBER_TYPE,dpeek());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void primitive_from_rect(void)
|
|
{
|
|
CELL imaginary = dpop();
|
|
CELL real = dpop();
|
|
|
|
if(!realp(imaginary))
|
|
type_error(REAL_TYPE,imaginary);
|
|
|
|
if(!realp(real))
|
|
type_error(REAL_TYPE,real);
|
|
|
|
dpush(possibly_complex(real,imaginary));
|
|
}
|
|
|
|
CELL number_eq_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
return tag_boolean(
|
|
untag_boolean(number_eq(x->real,y->real)) &&
|
|
untag_boolean(number_eq(x->imaginary,y->imaginary)));
|
|
}
|
|
|
|
CELL add_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
return possibly_complex(
|
|
add(x->real,y->real),
|
|
add(x->imaginary,y->imaginary));
|
|
}
|
|
|
|
CELL subtract_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
return possibly_complex(
|
|
subtract(x->real,y->real),
|
|
subtract(x->imaginary,y->imaginary));
|
|
}
|
|
|
|
CELL multiply_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
return possibly_complex(
|
|
subtract(
|
|
multiply(x->real,y->real),
|
|
multiply(x->imaginary,y->imaginary)),
|
|
add(
|
|
multiply(x->real,y->imaginary),
|
|
multiply(x->imaginary,y->real)));
|
|
}
|
|
|
|
#define COMPLEX_DIVIDE(x,y) \
|
|
\
|
|
CELL mag = add( \
|
|
multiply(y->real,y->real), \
|
|
multiply(y->imaginary,y->imaginary)); \
|
|
\
|
|
CELL r = add( \
|
|
multiply(x->real,y->real), \
|
|
multiply(x->imaginary,y->imaginary)); \
|
|
CELL i = subtract( \
|
|
multiply(x->imaginary,y->real), \
|
|
multiply(x->real,y->imaginary));
|
|
|
|
CELL divide_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
COMPLEX_DIVIDE(x,y);
|
|
return possibly_complex(divide(r,mag),divide(i,mag));
|
|
}
|
|
|
|
CELL divfloat_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
COMPLEX_DIVIDE(x,y);
|
|
return possibly_complex(divfloat(r,mag),divfloat(i,mag));
|
|
}
|
|
|
|
#define INCOMPARABLE(x,y) general_error(ERROR_INCOMPARABLE, \
|
|
tag_cons(cons(RETAG(x,COMPLEX_TYPE),RETAG(y,COMPLEX_TYPE))));
|
|
|
|
CELL less_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
INCOMPARABLE(x,y);
|
|
return F;
|
|
}
|
|
|
|
CELL lesseq_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
INCOMPARABLE(x,y);
|
|
return F;
|
|
}
|
|
|
|
CELL greater_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
INCOMPARABLE(x,y);
|
|
return F;
|
|
}
|
|
|
|
CELL greatereq_complex(COMPLEX* x, COMPLEX* y)
|
|
{
|
|
INCOMPARABLE(x,y);
|
|
return F;
|
|
}
|