Ratio addition now works
This commit is contained in:
parent
4c9fdfc3db
commit
813b24406d
|
@ -80,8 +80,8 @@ bool equal( struct cons_pointer a, struct cons_pointer b ) {
|
||||||
&& ( equal( cell_a->payload.string.cdr,
|
&& ( equal( cell_a->payload.string.cdr,
|
||||||
cell_b->payload.string.cdr )
|
cell_b->payload.string.cdr )
|
||||||
|| ( end_of_string( cell_a->payload.string.cdr )
|
|| ( end_of_string( cell_a->payload.string.cdr )
|
||||||
&& end_of_string( cell_b->payload.string.
|
&& end_of_string( cell_b->payload.
|
||||||
cdr ) ) );
|
string.cdr ) ) );
|
||||||
break;
|
break;
|
||||||
case INTEGERTV:
|
case INTEGERTV:
|
||||||
result =
|
result =
|
||||||
|
|
53
src/peano.c
53
src/peano.c
|
@ -116,7 +116,7 @@ long int greatest_common_divisor( long int m, long int n ) {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int least_common_multiplier( long int m, long int n ) {
|
long int least_common_multiple( long int m, long int n ) {
|
||||||
return m / greatest_common_divisor( m, n ) * n;
|
return m / greatest_common_divisor( m, n ) * n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,24 +128,49 @@ long int least_common_multiplier( long int m, long int n ) {
|
||||||
struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
|
struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
|
||||||
struct cons_pointer arg1,
|
struct cons_pointer arg1,
|
||||||
struct cons_pointer arg2 ) {
|
struct cons_pointer arg2 ) {
|
||||||
|
fputws( L"add_ratio_ratio: srg1 = ", stderr );
|
||||||
|
print( stderr, arg1 );
|
||||||
|
fputws( L"; srg2 = ", stderr );
|
||||||
|
print( stderr, arg2 );
|
||||||
|
|
||||||
struct cons_pointer result;
|
struct cons_pointer result;
|
||||||
struct cons_space_object cell1 = pointer2cell( arg1 );
|
struct cons_space_object cell1 = pointer2cell( arg1 );
|
||||||
struct cons_space_object cell2 = pointer2cell( arg2 );
|
struct cons_space_object cell2 = pointer2cell( arg2 );
|
||||||
long int dd1v = pointer2cell(cell1.payload.ratio.dividend).payload.integer.value,
|
long int dd1v =
|
||||||
dd2v = pointer2cell(cell2.payload.ratio.dividend).payload.integer.value,
|
pointer2cell( cell1.payload.ratio.dividend ).payload.integer.value,
|
||||||
dr1v = pointer2cell(cell1.payload.ratio.divisor).payload.integer.value,
|
dd2v =
|
||||||
dr2v = pointer2cell(cell2.payload.ratio.divisor).payload.integer.value,
|
pointer2cell( cell2.payload.ratio.dividend ).payload.integer.value,
|
||||||
lcm = least_common_multiplier(dr1v, dr2v),
|
dr1v =
|
||||||
m1 = lcm/dr2v,
|
pointer2cell( cell1.payload.ratio.divisor ).payload.integer.value,
|
||||||
m2 = lcm/dr1v;
|
dr2v =
|
||||||
|
pointer2cell( cell2.payload.ratio.divisor ).payload.integer.value,
|
||||||
|
lcm = least_common_multiple( dr1v, dr2v ),
|
||||||
|
m1 = lcm / dr1v,
|
||||||
|
m2 = lcm / dr2v;
|
||||||
|
|
||||||
|
fwprintf(stderr , L"; lcm = %ld; m1 = %ld; m2 = %ld\n", lcm, m1, m2);
|
||||||
|
|
||||||
if ( dr1v == dr2v ) {
|
if ( dr1v == dr2v ) {
|
||||||
result = make_ratio( frame, add_2(frame, cell1.payload.ratio.dividend, cell2.payload.ratio.dividend),
|
result =
|
||||||
|
make_ratio( frame,
|
||||||
|
make_integer( dd1v + dd2v ),
|
||||||
cell1.payload.ratio.divisor );
|
cell1.payload.ratio.divisor );
|
||||||
|
|
||||||
|
long int ddrv = pointer2cell(pointer2cell(result).payload.ratio.dividend).payload.integer.value,
|
||||||
|
drrv = pointer2cell(pointer2cell(result).payload.ratio.divisor).payload.integer.value,
|
||||||
|
gcd = greatest_common_divisor(ddrv, drrv);
|
||||||
|
|
||||||
|
if (gcd > 1) {
|
||||||
|
result = make_ratio( frame, make_integer(ddrv/gcd),make_integer(drrv/gcd));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result = make_ratio( frame,
|
result = add_ratio_ratio( frame,
|
||||||
make_integer((dd1v * m1) + (dd2v * m2)),
|
make_ratio( frame,
|
||||||
make_integer((dr1v * m1) + (dr2v * m2)));
|
make_integer( dd1v * m1 ),
|
||||||
|
make_integer( dr1v * m1 )),
|
||||||
|
make_ratio( frame,
|
||||||
|
make_integer( dd2v * m2 ),
|
||||||
|
make_integer( dr2v * m2 ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -242,7 +267,9 @@ struct cons_pointer lisp_add( struct stack_frame
|
||||||
*frame, struct
|
*frame, struct
|
||||||
cons_pointer env ) {
|
cons_pointer env ) {
|
||||||
struct cons_pointer result = make_integer( 0 );
|
struct cons_pointer result = make_integer( 0 );
|
||||||
for ( int i = 0; i < args_in_frame && !nilp( frame->arg[i]) && !exceptionp(result); i++ ) {
|
for ( int i = 0;
|
||||||
|
i < args_in_frame && !nilp( frame->arg[i] ) && !exceptionp( result );
|
||||||
|
i++ ) {
|
||||||
result = add_2( frame, result, frame->arg[i] );
|
result = add_2( frame, result, frame->arg[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,8 +132,8 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
|
||||||
case LAMBDATV:
|
case LAMBDATV:
|
||||||
print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
|
print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
|
||||||
make_cons( cell.payload.lambda.args,
|
make_cons( cell.payload.lambda.args,
|
||||||
cell.payload.
|
cell.payload.lambda.
|
||||||
lambda.body ) ) );
|
body ) ) );
|
||||||
break;
|
break;
|
||||||
case NILTV:
|
case NILTV:
|
||||||
fwprintf( output, L"nil" );
|
fwprintf( output, L"nil" );
|
||||||
|
@ -141,8 +141,8 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
|
||||||
case NLAMBDATV:
|
case NLAMBDATV:
|
||||||
print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
|
print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
|
||||||
make_cons( cell.payload.lambda.args,
|
make_cons( cell.payload.lambda.args,
|
||||||
cell.payload.
|
cell.payload.lambda.
|
||||||
lambda.body ) ) );
|
body ) ) );
|
||||||
break;
|
break;
|
||||||
case RATIOTV:
|
case RATIOTV:
|
||||||
print( output, cell.payload.ratio.dividend );
|
print( output, cell.payload.ratio.dividend );
|
||||||
|
|
12
unit-tests/ratio-addition.sh
Normal file
12
unit-tests/ratio-addition.sh
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
expected='1/4'
|
||||||
|
actual=`echo "(+ 3/14 1/28)" | target/psse 2> /dev/null | head -2 | tail -1`
|
||||||
|
|
||||||
|
if [ "${expected}" = "${actual}" ]
|
||||||
|
then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "Fail: expected '${expected}', got '${actual}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
Loading…
Reference in a new issue