/* * Lisp math * Don Hopkins */ #include "lisp.h" #include /* * Compute the sum of all the arguments. */ object plus(args) object args; { double sum = 0.0; while (Object_Type(args) == cons_object) { if (Object_Type(Cons_Car(args)) != number_object) return(bad_args("plus")); sum += Number_Value(Cons_Car(args)); args = Cons_Cdr(args); } if (args != Nil) return(bad_args("plus")); return(make_number(sum)); } /* * Compute the product of all the arguments. */ object times(args) object args; { double product = 1.0; while (Object_Type(args) == cons_object) { if (Object_Type(Cons_Car(args)) != number_object) return(bad_args("times")); product *= Number_Value(Cons_Car(args)); args = Cons_Cdr(args); } if (args != Nil) return(bad_args("times")); return(make_number(product)); } /* * Compute the quotient of arg1 / arg2. Complain if arg2 is zero. */ object quotient(args) object args; { if (Object_Type(ARG1) == number_object && Object_Type(ARG2) == number_object && zerop(Cons_Cdr(args)) == Nil) return(make_number(Number_Value(ARG1) / Number_Value(ARG2))); return(bad_args("quotient")); } /* * Compute the remainder of arg1 / arg2. truncate the arguments to * longs before calculating the remainder. Complain if arg2 is zero. */ object lremainder(args) object args; { if (Object_Type(ARG1) == number_object && Object_Type(ARG2) == number_object && zerop(Cons_Cdr(args)) == Nil) return(make_number((double)(((long)Number_Value(ARG1)) % ((long)Number_Value(ARG2))))); return(bad_args("remainder")); } /* * Return -arg1. */ object minus(args) object args; { if (Object_Type(ARG1) == number_object) return(make_number(-Number_Value(Cons_Car(args)))); return(bad_args("minus")); } /* * Compute the floor of arg1. */ object lfloor(args) object args; { double floor(); if (Object_Type(ARG1) == number_object) return(make_number(floor(Number_Value(ARG1)))); return(bad_args("floor")); } /* * Return T of arg1 is a number object, otherwise return Nil. */ object numberp(args) object args; { if (Object_Type(ARG1) == number_object) return(T); else return(Nil); } /* * Return T if arg1 > arg2, otherwise return Nil. */ object greaterp(args) object args; { if (Object_Type(ARG1) == number_object && Object_Type(ARG2) == number_object) if (Number_Value(ARG1) > Number_Value(ARG2)) return(T); else return(Nil); return(bad_args("greaterp")); } /* * Return T if arg1 is within ZERO_THRESHOLD if zero, otherwise return Nil. */ object zerop(args) object args; { double fabs(); if (Object_Type(ARG1) == number_object) if (fabs(Number_Value(ARG1)) <= ZERO_THRESHOLD) return(T); else return(Nil); return(bad_args("zerop")); } /* * If arg is greater than zero, return a random integer from 0 .. arg-1 * Otherwise, return return a random real x, such that 0 <= x < 1. */ object lrandom(args) object args; { double floor(); double rnd; long random(); if (Object_Type(ARG1) != number_object) { return(bad_args("random")); } rnd = ((double)(random()&2147483647) / 2147483648.0); if (Number_Value(ARG1) > ZERO_THRESHOLD) { return(make_number(floor(rnd * Number_Value(ARG1)))); } return(make_number(rnd)); }