This is logonum.m in view mode; [Download] [Up]
/* Numeric operations in LOGO. * In arithmetic operations, the input, which is a character, is * converted to numeric, the operations are done, and the result is * converted back to character. * In all cases, the inputs are freed, and a new output is created. * * Copyright (C) 1979, The Children's Museum, Boston, Mass. * Written by Douglas B. Klunder. */ #include "logo.h" #ifndef NEXT #include <math.h> #else NEXT #import <math.h> #endif NEXT nump(x) /* non-LOGO numberp, just for strings */ register struct object *x; { /* a number is a series of at least one digit, with an optional * starting + or -. */ register char ch,*cp; cp = x->obstr; if (*cp=='\0') return(0); if (*cp!='-' && *cp!='+' && (*cp<'0' || *cp>'9') && *cp!='.') return(0); if ((*cp=='-' || *cp=='+' || *cp=='.') && *(cp+1)=='\0') return(0); if(*cp=='.' && index(cp+1,'.')) return(0); cp++; while ((ch = *cp)!='\0') { if ((ch<'0'||ch>'9')&&(ch!='e')&&(ch!='E')&&(ch!='.')) return(0); if ((ch == 'e') || (ch == 'E')) { if (index(cp+1,'e') || index(cp+1,'E') || index(cp+1,'.')) return(0); if (((ch = *(cp+1))=='+') || (ch=='-')) cp++; } else if (ch == '.') { if (index(cp+1,'e') || index(cp+1,'E') || index(cp+1,'.')) return(0); } cp++; } return(1); } /* Check a STRING object to see if it's an integer string */ isint(x) register struct object *x; { register char ch,*cp; cp = x->obstr; while (ch = *cp++) if ((ch == '.') || (ch == 'e') || (ch == 'E')) return(0); return(1); } /* convert object (which might be a word of digits) to a number */ struct object *numconv(thing,op) register struct object *thing; char *op; { register struct object *newthing; FIXNUM ithing; NUMBER dthing; if (thing == 0) ungood(op,thing); switch (thing->obtype) { case CONS: ungood(op,thing); case INT: case DUB: return(thing); default: if (!nump(thing)) ungood(op,thing); if (isint(thing)) { sscanf(thing->obstr,FIXFMT,&ithing); newthing = localize(objint(ithing)); } else { sscanf(thing->obstr,EFMT,&dthing); newthing = localize(objdub(dthing)); } } mfree(thing); return(newthing); } /* convert integer to double */ struct object *dubconv(num) register struct object *num; { NUMBER d; if (dubp(num)) return(num); d = num->obint; mfree(num); return(localize(objdub(d))); } struct object *opp(x) /* Unary - */ register struct object *x; { register struct object *ans; x = numconv(x,"Minus"); if (intp(x)) { ans = objint(-(x->obint)); } else { ans = objdub(-(x->obdub)); } mfree(x); return(localize(ans)); } struct object *add(x,y) /* sum */ register struct object *x,*y; { FIXNUM iz; NUMBER dz; register struct object *z; x = numconv(x,"Sum"); y = numconv(y,"Sum"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { iz = (x->obint)+(y->obint); z = objint(iz); } else { dz = (x->obdub)+(y->obdub); z = objdub(dz); } mfree(x); mfree(y); return(localize(z)); } struct object *sub(x,y) /* difference */ register struct object *x,*y; { FIXNUM iz; NUMBER dz; register struct object *z; x = numconv(x,"Difference"); y = numconv(y,"Difference"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { iz = (x->obint)-(y->obint); z = objint(iz); } else { dz = (x->obdub)-(y->obdub); z = objdub(dz); } mfree(x); mfree(y); return(localize(z)); } struct object *mult(x,y) /* product */ register struct object *x,*y; { FIXNUM iz; NUMBER dz; register struct object *z; x = numconv(x,"Product"); y = numconv(y,"Product"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { iz = (x->obint)*(y->obint); z = objint(iz); } else { dz = (x->obdub)*(y->obdub); z = objdub(dz); } mfree(x); mfree(y); return(localize(z)); } divzero(name) char *name; { pf1("%s can't divide by zero.\n",name); errhand(); } struct object *div(x,y) /* quotient */ register struct object *x,*y; { NUMBER dz; x = numconv(x,"Quotient"); y = numconv(y,"Quotient"); x = dubconv(x); y = dubconv(y); if (y->obdub == 0.0) divzero("Quotient"); dz = (x->obdub)/(y->obdub); mfree(x); mfree(y); if (dz == (NUMBER)(FIXNUM)dz) { return(localize(objint((FIXNUM)dz))); } else { return(localize(objdub(dz))); } } struct object *rem(x,y) /* remainder */ register struct object *x,*y; { FIXNUM iz; register struct object *z; x = numconv(x,"Remainder"); y = numconv(y,"Remainder"); if (!intp(x)) ungood("Remainder",x); if (!intp(y)) ungood("Remainder",y); if (y->obint == 0) divzero("Remainder"); iz = (x->obint)%(y->obint); z = objint(iz); mfree(x); mfree(y); return(localize(z)); } struct object *torf(pred) int pred; { if (pred) return(true()); return(false()); } struct object *greatp(x,y) /* greaterp */ register struct object *x,*y; { int iz; x = numconv(x,"Greaterp"); y = numconv(y,"Greaterp"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { iz = ((x->obint)>(y->obint)); } else { iz = ((x->obdub)>(y->obdub)); } mfree(x); mfree(y); return torf(iz); } struct object *lessp(x,y) /* lessp */ register struct object *x,*y; { int iz; x = numconv(x,"Lessp"); y = numconv(y,"Lessp"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { iz = ((x->obint)<(y->obint)); } else { iz = ((x->obdub)<(y->obdub)); } mfree(x); mfree(y); return torf(iz); } struct object *lmax(x,y) /* maximum */ register struct object *x,*y; { x = numconv(x,"Maximum"); y = numconv(y,"Maximum"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { if ((x->obint) > (y->obint)) { mfree(y); return(x); } else { mfree(x); return(y); } } else { if ((x->obdub) > (y->obdub)) { mfree(y); return(x); } else { mfree(x); return(y); } } } struct object *lmin(x,y) /* minimum */ register struct object *x,*y; { x = numconv(x,"Minimum"); y = numconv(y,"Minimum"); if (!intp(x) || !intp(y)) { x = dubconv(x); y = dubconv(y); } if (intp(x)) { if ((x->obint) < (y->obint)) { mfree(y); return(x); } else { mfree(x); return(y); } } else { if ((x->obdub) < (y->obdub)) { mfree(y); return(x); } else { mfree(x); return(y); } } } struct object *lnump(x) /* LOGO numberp */ register struct object *x; { if (x == 0) return(false()); switch (x->obtype) { case CONS: mfree(x); return(false()); case INT: case DUB: mfree(x); return(true()); default: /* case STRING */ if (nump(x)) { mfree(x); return(true()); } else { mfree(x); return(false()); } } } struct object *lrandd() /* random */ { register struct object *val; register temp; temp=(RAND()/100)%10; val = objint((FIXNUM)temp); return(localize(val)); } struct object *rnd(arg) register struct object *arg; { register temp; arg = numconv(arg,"Rnd"); if(!intp(arg)) ungood("Rnd",arg); if ((arg->obint) <= 0) ungood("Rnd",arg); temp=RAND() % (int)(arg->obint); mfree(arg); return(localize(objint((FIXNUM)temp))); } struct object *sq(arg) register struct object *arg; { NUMBER temp; arg = numconv(arg,"Sqrt"); arg = dubconv(arg); temp = sqrt(arg->obdub); mfree(arg); return(localize(objdub(temp))); } struct object *lsin(arg) register struct object *arg; { NUMBER temp; arg = numconv(arg,"Sin"); arg = dubconv(arg); temp = sin((3.1415926/180.0)*(arg->obdub)); mfree(arg); return(localize(objdub(temp))); } struct object *lcos(arg) register struct object *arg; { NUMBER temp; arg = numconv(arg,"Cos"); arg = dubconv(arg); temp = cos((3.1415926/180.0)*(arg->obdub)); mfree(arg); return(localize(objdub(temp))); } struct object *lpow(x,y) register struct object *x,*y; { FIXNUM iz; NUMBER dz; register struct object *z; x = numconv(x,"Pow"); y = numconv(y,"Pow"); x = dubconv(x); y = dubconv(y); dz = pow((x->obdub),(y->obdub)); iz = dz; /* convert to integer for integerness test */ if (dz == (NUMBER)iz) z = objint(iz); else z = objdub(dz); mfree(x); mfree(y); return(localize(z)); } struct object *latan(arg) register struct object *arg; { NUMBER temp; arg = numconv(arg,"Atan"); arg = dubconv(arg); temp = (180.0/3.1415926)*atan(arg->obdub); mfree(arg); return(localize(objdub(temp))); } struct object *zerop(x) /* zerop */ register struct object *x; { register int iz; x = numconv(x,"Zerop"); if (intp(x)) iz = ((x->obint)==0); else iz = ((x->obdub)==0.0); mfree(x); return(torf(iz)); } struct object *intpart(arg) register struct object *arg; { register FIXNUM result; arg = numconv(arg,"Int"); if (intp(arg)) return(arg); result = arg->obdub; mfree(arg); return(localize(objint(result))); } struct object *round(arg) register struct object *arg; { register FIXNUM result; arg = numconv(arg,"Round"); if (intp(arg)) return(arg); if (arg->obdub >= 0.0) result = arg->obdub + 0.5; else result = arg->obdub - 0.5; mfree(arg); return(localize(objint(result))); } struct object *toascii(arg) register struct object *arg; { register char *cp; char str[50]; if (arg==0) ungood("Ascii",arg); switch(arg->obtype) { case CONS: ungood("Ascii",arg); case STRING: cp = arg->obstr; break; case INT: sprintf(str,FIXFMT,arg->obint); cp = str; break; case DUB: sprintf(str,"%g",arg->obdub); cp = str; break; } if (strlen(cp) != 1) ungood("Ascii",arg); mfree(arg); return(localize(objint((FIXNUM)((*cp)&0377)))); } struct object *tochar(arg) register struct object *arg; { register int ichar; char str[2]; arg = numconv(arg,"Char"); if (intp(arg)) ichar = arg->obint; else ichar = arg->obdub; if ((ichar < 0) || (ichar > 255)) ungood("Char",arg); mfree(arg); str[0] = ichar; str[1] = '\0'; return(localize(objcpstr(str))); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.