home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
dev
/
umbscheme-2.12.lha
/
UMBScheme
/
src
/
real.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-29
|
10KB
|
617 lines
/* real.c -- UMB Scheme, specific realnum procedures.
UMB Scheme Interpreter $Revision: 2.12 $
Copyright (C) 1988, 1991 William R Campbell
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
UMB Scheme was written by Bill Campbell with help from Karl Berry,
Barbara Dixey, Ira Gerstein, Mary Glaser, Kathy Hargreaves, Bill McCabe,
Long Nguyen, Susan Quina, Jeyashree Sivasubram, Bela Sohoni and Thang Quoc Tran.
For additional information about UMB Scheme, contact the author:
Bill Campbell
Department of Mathematics and Computer Science
University of Massachusetts at Boston
Harbor Campus
Boston, MA 02125
Telephone: 617-287-6449 Internet: bill@cs.umb.edu
*/
/* Reals are implemented as the native double precision floating
point type. As a result, all the operations can use native (C)
functions. */
#include "portable.h"
#include "eval.h"
#include "object.h"
#include "architecture.h"
#include "number.h"
#include "fixnum.h"
#include "bignum.h"
#include "rational.h"
#include "real.h"
#include "complex.h"
#include "steering.h"
#include "io.h"
/* Predicates. */
Public Boolean Is_Real_Zero()
{
return Get_Number_Real_Value(Top(1)) == 0.0;
}
Public Boolean Is_Real_Positive()
{
return Get_Number_Real_Value(Top(1)) > 0.0;
}
Public Boolean Is_Real_Negative()
{
return Get_Number_Real_Value(Top(1)) < 0.0;
}
Public Boolean Is_Real_Odd()
{
Error("Reals aren't odd or even");
return FALSE;
}
Public Boolean Is_Real_Even()
{
Error("Reals aren't even or odd");
return FALSE;
}
Public Boolean Is_Real_Exact()
{
return FALSE;
}
Public Boolean Is_Real_Inexact()
{
return TRUE;
}
/* Comparisons. */
Public Boolean Real_Less_Than()
{
return Get_Number_Real_Value(Top(2)) < Get_Number_Real_Value(Top(1));
}
Public Boolean Real_Greater_Than()
{
return Get_Number_Real_Value(Top(2)) > Get_Number_Real_Value(Top(1));
}
Public Boolean Real_Equal()
{
return Get_Number_Real_Value(Top(2)) == Get_Number_Real_Value(Top(1));
}
Public Boolean Real_Less_Than_Or_Equal()
{
return Get_Number_Real_Value(Top(2)) <= Get_Number_Real_Value(Top(1));
}
Public Boolean Real_Greater_Than_Or_Equal()
{
return Get_Number_Real_Value(Top(2)) >= Get_Number_Real_Value(Top(1));
}
/* Arithmetic. */
Public void Real_Add()
{
Make_Real_Number(Get_Number_Real_Value(Top(2))+
Get_Number_Real_Value(Top(1)));
}
Public void Real_Subtract()
{
Make_Real_Number(Get_Number_Real_Value(Top(2))-
Get_Number_Real_Value(Top(1)));
}
Public void Real_Multiply()
{
Make_Real_Number(Get_Number_Real_Value(Top(2))*
Get_Number_Real_Value(Top(1)));
}
Public void Real_Divide()
{
Make_Real_Number(Get_Number_Real_Value(Top(2))/
Get_Number_Real_Value(Top(1)));
}
Public void Real_Quotient()
{
Error("Quotient makes no sense on reals");
}
Public void Real_Remainder()
{
Error("Remainder makes no sense on reals");
}
Public void Real_Modulo()
{
Error("Modulo makes no sense on reals");
}
Public void Real_Negate()
{
Value_Register = Copy_Object(Top(1), Real_Size);
Get_Number_Real_Value(Value_Register) =
- Get_Number_Real_Value(Value_Register);
}
Public void Real_Abs()
{
if (Is_Real_Negative())
{
Real_Negate();
}
else
{
Value_Register = Top(1);
}
}
Public void Real_Numerator()
{
Error("Numerator makes no sense on reals");
}
Public void Real_Denominator()
{
Error("Denominator makes no sense on reals");
}
Public void Real_Rationalize()
{
Error("Real_Rationaize is not yet implemented");
}
/* And other operations. */
Public void Real_Max()
{
Value_Register =
(Get_Number_Real_Value(Top(2)) > Get_Number_Real_Value(Top(1)))
? Top(2)
: Top(1) ;
}
Public void Real_Min()
{
Value_Register =
(Get_Number_Real_Value(Top(2)) < Get_Number_Real_Value(Top(1)))
? Top(2)
: Top(1) ;
}
Public void Real_GCD()
{
Error("GCD makes no sense on reals");
}
Public void Real_LCM()
{
Error("LCM makes no sense on reals");
}
Public void Real_Floor()
{
Make_Real_Number( floor( Get_Number_Real_Value(Top(1))));
}
Public void Real_Ceiling()
{
Make_Real_Number( ceil( Get_Number_Real_Value(Top(1))));
}
Public void Real_Truncate()
{
if (Is_Real_Positive())
{
Real_Floor();
}
else
{
Real_Ceiling();
}
}
Public void Real_Round()
{
/* Compare real to average of floor and ceiling and
choose either floor or ceiling depending on result;
reals ending in .5 round to even */
Double input = Get_Number_Real_Value(Top(1));
if (input < (floor(input) + ceil(input))/2 )
{
Real_Floor();
}
else if (input > (floor(input) + ceil(input))/2 )
{
Real_Ceiling();
}
else
{
Number_Floor();
Push(Value_Register);
Number_Inexact_To_Exact();
Push( Value_Register );
Is_Number_Even(); Pop(1);
if (Value_Register == The_True_Object)
{
Value_Register = Top(1);
Pop(1);
}
else
{
Pop(1);
Real_Ceiling();
}
}
}
Public void Real_Sqrt()
{
if( Get_Number_Real_Value(Top(1)) < 0 )
{
Make_Complex_Number( (Double) 0.0 ,
sqrt( - Get_Number_Real_Value(Top(1))) );
}
else
{
Make_Real_Number( sqrt (Get_Number_Real_Value(Top(1))) );
}
}
Public void Real_Exp()
{
Make_Real_Number( exp( Get_Number_Real_Value(Top(1))));
}
Public void Real_Log()
{
if(Get_Number_Real_Value(Top(1)) <= 0)
{
Error("Argument of log must be positive");
}
Make_Real_Number( log( Get_Number_Real_Value(Top(1))));
}
Public void Real_Expt()
{
Promote( 2 , REAL_LEVEL );
Make_Real_Number( pow( Get_Number_Real_Value(Top(2)),
Get_Number_Real_Value(Top(1))));
}
Public void Real_Sin()
{
Make_Real_Number( sin( Get_Number_Real_Value(Top(1))));
}
Public void Real_Cos()
{
Make_Real_Number( cos( Get_Number_Real_Value(Top(1))));
}
Public void Real_Tan()
{
Make_Real_Number( tan( Get_Number_Real_Value(Top(1))));
}
Public void Real_Asin()
{
if( (Get_Number_Real_Value(Top(1)) < -1) ||
(Get_Number_Real_Value(Top(1)) > 1) )
{
Error("Argument of asin must lie between -1 and 1, inclusive");
}
Make_Real_Number( asin( Get_Number_Real_Value(Top(1))));
}
Public void Real_Acos()
{
if( (Get_Number_Real_Value(Top(1)) < -1) ||
(Get_Number_Real_Value(Top(1)) > 1) )
{
Error("Argument of acos must lie between -1 and 1, inclusive");
}
Make_Real_Number( acos( Get_Number_Real_Value(Top(1))));
}
Public void Real_Atan()
{
Make_Real_Number( atan( Get_Number_Real_Value(Top(1))));
}
Public void Real_Atan2()
{
Make_Real_Number( atan2( Get_Number_Real_Value(Top(2)),
Get_Number_Real_Value(Top(1))));
}
/* Transfer functions */
Public void Real_Exact_To_Inexact()
{
Value_Register = Top(1);
}
Public void Real_Inexact_To_Exact()
{
Push( Top(1) );
Make_Real_Number( DBL_MIN );
Push( Value_Register );
Number_Rationalize(); Pop(2);
Is_Exact_Number( Value_Register ) = TRUE;
}
Public void XReal_Inexact_To_Exact()
{
Double whole;
Double fraction;
Double quotient;
Integer remainder;
whole = floor( fabs( Get_Number_Real_Value( Top(1) ) ) );
fraction = fabs( Get_Number_Real_Value( Top(1) ) ) - whole;
/* The whole part */
quotient = floor( whole / RADIX );
remainder = whole - (quotient * RADIX);
whole = quotient;
Integer_To_Number( remainder );
Push( Value_Register );
if ( whole > 0.0 )
{
Integer_To_Number( 1 );
Push( Value_Register );
while ( whole > 0.0 )
{
Push( Top(1) );
Integer_To_Number( RADIX );
Push( Value_Register );
Number_Multiply(); Pop(2);
Replace( 1 , Value_Register );
quotient = floor( whole / RADIX );
remainder = whole - (quotient * RADIX);
whole = quotient;
Push( Top(1) );
Integ