home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-15 | 73.4 KB | 2,050 lines |
- # Arithmetik für CLISP
- # Bruno Haible 15.1.1995
-
- #include "lispbibl.c"
-
- #define LISPARIT # im folgenden nicht nur die Macros, auch die Funktionen
-
- #undef LF # LF bedeutet hier nicht 'Linefeed', sondern 'LongFloat'
-
-
- # UP: entscheidet auf Zahlgleichheit
- # number_gleich(x,y)
- # > x,y: zwei Zahlen
- # < ergebnis: TRUE, falls (= x y) gilt
- # kann GC auslösen
- global boolean number_gleich (object x, object y);
- #define N_N_gleich number_gleich # N_N_gleich wird später definiert
-
-
- # zur Arithmetik allgemein:
- #include "aridecl.c" # Deklarationen
- #include "arilev0.c" # Maschinen-Arithmetik
- #include "arilev1.c" # Digit-Sequences
- # zu Integers:
- #include "intelem.c" # Elementaroperationen auf Integers
- #include "intlog.c" # logische Operationen auf Integers
- #include "intplus.c" # Addition, Subtraktion auf Integers
- #include "intcomp.c" # Vergleichsoperationen auf Integers
- #include "intbyte.c" # Byte-Operationen LDB, LOAD-BYTE, ...
- #include "intmal.c" # Multiplikation von Integers
- #include "intdiv.c" # Division von Integers
- #include "intgcd.c" # ggT und kgV
- #include "int2adic.c" # Operationen mit 2-adischen Integers
- #include "intsqrt.c" # Wurzel, ISQRT
- #include "intprint.c" # Hilfsfunktion zur Ausgabe von Integers
- #include "intread.c" # Hilfsfunktion zur Eingabe von Integers
- # zu rationalen Zahlen:
- #include "rational.c" # Rationale Zahlen
- # zu Floats:
- #include "sfloat.c" # Short-Float-Grundfunktionen
- #include "ffloat.c" # Single-Float-Grundfunktionen
- #include "dfloat.c" # Double-Float-Grundfunktionen
- #include "lfloat.c" # Long-Float-Grundfunktionen
- #include "flo_konv.c" # Float-Konversionen
- #include "flo_rest.c" # Floats allgemein
- # zu reellen Zahlen:
- #include "realelem.c" # elementare Funktionen für reelle Zahlen
- #include "realrand.c" # Funktionen für Zufallszahlen
- #include "realtran.c" # transzendente Funktionen für reelle Zahlen
- # zu komplexen Zahlen:
- #include "compelem.c" # elementare Funktionen für komplexe Zahlen
- #include "comptran.c" # transzendente Funktionen für komplexe Zahlen
-
-
- # ============================================================================ #
- # Einleseroutinen für Zahlen
-
- # UP: Multipliziert ein Integer mit 10 und addiert eine weitere Ziffer.
- # mal_10_plus_x(y,x)
- # > y: Integer Y (>=0)
- # > x: Ziffernwert X (>=0,<10)
- # < ergebnis: Integer Y*10+X (>=0)
- # kann GC auslösen
- global object mal_10_plus_x (object y, uintB x);
- global object mal_10_plus_x(y,x)
- var reg4 object y;
- var reg6 uintB x;
- { SAVE_NUM_STACK # num_stack retten
- var reg1 uintD* MSDptr;
- var reg2 uintC len;
- var reg5 uintD* LSDptr;
- I_to_NDS_1(y, MSDptr=,len=,LSDptr=); # NDS zu Y
- {var reg3 uintD carry = mulusmall_loop_down(10,LSDptr,len,x); # mal 10, plus x
- if (!(carry==0))
- { *--MSDptr = carry; len++;
- if (uintCoverflow(len)) { BN_ueberlauf(); } # Überlauf der Länge?
- }
- RESTORE_NUM_STACK # num_stack (vorzeitig) zurück
- return UDS_to_I(MSDptr,len); # UDS als Integer zurück
- }}
-
- # UP: Wandelt eine Zeichenkette mit Integer-Syntax in ein Integer um.
- # Punkte werden überlesen.
- # read_integer(base,sign,string,index1,index2)
- # > base: Lesebasis (>=2, <=36)
- # > sign: Vorzeichen (/=0 falls negativ)
- # > string: Simple-String (enthält Ziffern mit Wert <base und evtl. Punkt)
- # > index1: Index der ersten Ziffer
- # > index2: Index nach der letzten Ziffer
- # (also index2-index1 Ziffern, incl. evtl. Dezimalpunkt am Schluß)
- # < ergebnis: Integer
- # kann GC auslösen
- global object read_integer (uintWL base,
- signean sign, object string, uintL index1, uintL index2);
- global object read_integer(base,sign,string,index1,index2)
- var reg6 uintWL base;
- var reg5 signean sign;
- var reg3 object string;
- var reg1 uintL index1;
- var reg4 uintL index2;
- { var reg2 object x = # in Integer umwandeln:
- DIGITS_to_I(&TheSstring(string)->data[index1],index2-index1,(uintD)base);
- if (sign==0)
- { return x; }
- else
- { return I_minus_I(x); } # negatives Vorzeichen -> Vorzeichenwechsel
- }
-
- # UP: Wandelt eine Zeichenkette mit Rational-Syntax in eine rationale Zahl um.
- # read_rational(base,sign,string,index1,index3,index2)
- # > base: Lesebasis (>=2, <=36)
- # > sign: Vorzeichen (/=0 falls negativ)
- # > string: Simple-String (enthält Ziffern mit Wert <base und Bruchstrich)
- # > index1: Index der ersten Ziffer
- # > index3: Index von '/'
- # > index2: Index nach der letzten Ziffer
- # (also index3-index1 Zähler-Ziffern, index2-index3-1 Nenner-Ziffern)
- # < ergebnis: rationale Zahl
- # kann GC auslösen
- global object read_rational (uintWL base,
- signean sign, object string, uintL index1, uintL index3, uintL index2);
- global object read_rational(base,sign,string,index1,index3,index2)
- var reg7 uintWL base;
- var reg8 signean sign;
- var reg2 object string;
- var reg5 uintL index1;
- var reg3 uintL index3;
- var reg6 uintL index2;
- { pushSTACK(string); # string retten
- {var reg4 uintL index3_1 = index3+1; # Index der ersten Nennerziffer
- var reg1 object x = # Nenner
- DIGITS_to_I(&TheSstring(string)->data[index3_1],index2-index3_1,(uintD)base);
- if (eq(x,Fixnum_0)) { divide_0(); } # Division durch 0 abfangen
- string = STACK_0; STACK_0 = x;
- }
- {var reg1 object x = # Zähler
- DIGITS_to_I(&TheSstring(string)->data[index1],index3-index1,(uintD)base);
- if (!(sign==0)) { x = I_minus_I(x); } # incl. Vorzeichen
- return I_posI_durch_RA(x,popSTACK()); # Zähler/Nenner als Bruch
- }}
-
- # UP: Wandelt eine Zeichenkette mit Float-Syntax in ein Float um.
- # read_float(base,sign,string,index1,index4,index2,index3)
- # > base: Lesebasis (=10)
- # > sign: Vorzeichen (/=0 falls negativ)
- # > string: Simple-String (enthält Ziffern und evtl. Punkt und Exponentmarker)
- # > index1: Index vom Mantissenanfang (excl. Vorzeichen)
- # > index4: Index nach dem Mantissenende
- # > index2: Index beim Ende der Characters
- # > index3: Index nach dem Dezimalpunkt (=index4 falls keiner da)
- # (also Mantisse mit index4-index1 Characters: Ziffern und max. 1 '.')
- # (also index4-index3 Nachkommaziffern)
- # (also bei index4<index2: index4 = Index des Exponent-Markers,
- # index4+1 = Index des Exponenten-Vorzeichens oder der ersten
- # Exponenten-Ziffer)
- # < ergebnis: Float
- # kann GC auslösen
- global object read_float (uintWL base,
- signean sign, object string, uintL index1, uintL index4, uintL index2, uintL index3);
- global object read_float(base,sign,string,index1,index4,index2,index3)
- var reg7 uintWL base;
- var reg10 signean sign;
- var reg5 object string;
- var reg9 uintL index1;
- var reg8 uintL index4;
- var reg9 uintL index2;
- var reg9 uintL index3;
- { pushSTACK(string); # string retten
- # Exponent:
- {var reg3 uintB exp_marker;
- var reg2 object exponent;
- {var reg6 uintL exp_len = index2-index4; # Anzahl Stellen des Exponenten
- if (exp_len > 0)
- { var reg1 uintB* ptr = &TheSstring(string)->data[index4]; # zeigt auf den Exponentmarker
- exp_marker = *ptr++; exp_len--; # Exponentmarker überlesen
- # (als Großbuchstabe, da vom Aufrufer umgewandelt)
- {var reg4 signean exp_sign = 0; # Exponenten-Vorzeichen
- switch (*ptr)
- { case '-': exp_sign = ~exp_sign; # Vorzeichen := negativ
- case '+': ptr++; exp_len--; # Exponenten-Vorzeichen überlesen
- default: ;
- }
- exponent = DIGITS_to_I(ptr,exp_len,(uintD)base); # Exponent in Integer umwandeln
- if (!(exp_sign==0)) { exponent = I_minus_I(exponent); } # incl. Vorzeichen
- }}
- else
- # kein Exponent da
- { exp_marker = 'E'; exponent = Fixnum_0; }
- # exp_marker = Exponentmarker als Großbuchtabe,
- # exponent = Exponent als Integer.
- exponent = # Exponent - Anzahl der Nachkommaziffern
- I_I_minus_I(exponent,fixnum(index4-index3));
- exponent = # 10^exponent = zu multiplizierende Zehnerpotenz
- R_I_expt_R(fixnum(base),exponent);
- string = STACK_0; STACK_0 = exponent;
- # Mantisse:
- {var reg1 object mantisse = # Mantisse als Integer
- DIGITS_to_I(&TheSstring(string)->data[index1],index4-index1,(uintD)base);
- exponent = popSTACK();
- # Mantisse (Integer) und Exponent (rational >0) unelegant zusammenmultiplizieren:
- if (RA_integerp(exponent))
- { mantisse = I_I_mal_I(mantisse,exponent); }
- else
- { # falls mantisse/=0, in exponent=1/10^i den Zähler durch mantisse
- # ersetzen (liefert ungekürzten Bruch, Vorsicht!)
- if (!(eq(mantisse,Fixnum_0)))
- { TheRatio(exponent)->rt_num = mantisse; mantisse = exponent; }
- }
- # mantisse = Mantisse * Zehnerpotenz, als ungekürzte rationale Zahl!
- switch (exp_marker)
- { case 'S': SF: # in Short-Float umwandeln
- {var reg4 object x = RA_to_SF(mantisse);
- return (sign==0 ? x : SF_minus_SF(x)); # evtl. noch Vorzeichenwechsel
- }
- case 'F': FF: # in Single-Float umwandeln
- {var reg4 object x = RA_to_FF(mantisse);
- return (sign==0 ? x : FF_minus_FF(x)); # evtl. noch Vorzeichenwechsel
- }
- case 'D': DF: # in Double-Float umwandeln
- {var reg4 object x = RA_to_DF(mantisse);
- return (sign==0 ? x : DF_minus_DF(x)); # evtl. noch Vorzeichenwechsel
- }
- case 'L': LF: # in Long-Float der Default-Genauigkeit umwandeln
- {var reg4 object x = RA_to_LF(mantisse,I_to_UL(O(LF_digits)));
- return (sign==0 ? x : LF_minus_LF(x)); # evtl. noch Vorzeichenwechsel
- }
- default: # case 'E':
- defaultfloatcase(S(read_default_float_format),
- goto SF; , goto FF; , goto DF; , goto LF; ,
- pushSTACK(mantisse); , mantisse = popSTACK();
- );
- }
- }}}}
-
-
- # ============================================================================ #
- # Ausgaberoutinen für Zahlen
-
- # UP: Gibt ein Integer aus.
- # print_integer(z,base,&stream);
- # > z: Integer
- # > base: Basis (>=2, <=36)
- # > stream: Stream
- # < stream: Stream
- # kann GC auslösen
- global void print_integer (object z, uintWL base, object* stream_);
- global void print_integer(z,base,stream_)
- var reg6 object z;
- var reg8 uintWL base;
- var reg3 object* stream_;
- { if (R_minusp(z))
- # z<0 -> Vorzeichen ausgeben:
- { pushSTACK(z);
- write_schar(stream_,'-');
- z = I_minus_I(popSTACK());
- }
- { SAVE_NUM_STACK # num_stack retten
- var reg5 uintD* MSDptr;
- var reg4 uintC len;
- I_to_NDS(z, MSDptr=,len=,_EMA_); # z als UDS
- {var reg7 uintL need = digits_need(len,base);
- var DYNAMIC_ARRAY(reg9,ziffern,uintB,need); # Platz für die Ziffern
- var DIGITS erg; erg.LSBptr = &ziffern[need];
- UDS_to_DIGITS(MSDptr,len,(uintD)base,&erg); # Umwandlung in Ziffern
- # Ziffern ausgeben:
- if (write_schar_array(*stream_,erg.MSBptr,erg.len) == NULL)
- { var reg1 uintB* ptr = erg.MSBptr;
- var reg2 uintL count;
- dotimespL(count,erg.len, { write_schar(stream_,*ptr++); } );
- }
- FREE_DYNAMIC_ARRAY(ziffern);
- RESTORE_NUM_STACK # num_stack zurück
- }}}
-
- # UP: Gibt ein Float aus.
- # print_float(z,&stream);
- # > z: Float
- # > stream: Stream
- # < stream: Stream
- # kann GC auslösen
- global void print_float (object z, object* stream_);
- global void print_float(z,stream_)
- var reg4 object z;
- var reg1 object* stream_;
- { # Falls SYS::WRITE-FLOAT definiert ist, (SYS::WRITE-FLOAT stream z) aufrufen:
- var reg3 object fun = Symbol_function(S(write_float));
- if (!eq(fun,unbound))
- # Funktion aufrufen
- { pushSTACK(*stream_); pushSTACK(z); funcall(fun,2); }
- else
- # eigene Routine: gibt
- # Vorzeichen, Punkt, Mantisse (binär), (Zweiersystem-)Exponent (dezimal)
- # aus.
- { pushSTACK(z);
- F_integer_decode_float_I_I_I(z);
- # Stackaufbau: z, m, e, s.
- # Vorzeichen ausgeben, falls <0:
- if (eq(STACK_0,Fixnum_minus1)) { write_schar(stream_,'-'); }
- # Mantisse binär(!) ausgeben:
- write_schar(stream_,'.');
- print_integer(STACK_2,2,stream_);
- # Exponent-Marker ausgeben:
- {var reg2 object exp_marker;
- floatcase(STACK_3,
- { exp_marker = code_char('s'); },
- { exp_marker = code_char('f'); },
- { exp_marker = code_char('d'); },
- { exp_marker = code_char('L'); }
- );
- write_char(stream_,exp_marker);
- }
- # Exponenten dezimal ausgeben:
- print_integer(L_to_I(F_exponent_L(STACK_3)),10,stream_);
- skipSTACK(4);
- }
- }
-
-
- # ============================================================================ #
- # Lisp-Funktionen
-
- # Fehlermeldung, wenn keine Zahl kommt.
- # > obj: Objekt, keine Zahl
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_not_N, (object obj));
- local void fehler_not_N(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(number)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine Zahl sein: ~"
- //: ENGLISH "argument to ~ should be a number: ~"
- //: FRANCAIS "L'argument pour ~ doit être un nombre et non ~."
- fehler(type_error, GETTEXT("argument to ~ should be a number: ~"));
- }
-
- # Fehlermeldung, wenn keine reelle Zahl kommt.
- # > obj: Objekt, keine reelle Zahl
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_not_R, (object obj));
- local void fehler_not_R(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(real)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine reelle Zahl sein: ~"
- //: ENGLISH "argument to ~ should be a real number: ~"
- //: FRANCAIS "L'argument pour ~ doit être un nombre réel et non ~."
- fehler(type_error, GETTEXT("argument to ~ should be a real number: ~"));
- }
-
- # Fehlermeldung, wenn keine Floating-Point-Zahl kommt.
- # > obj: Objekt, keine Floating-Point-Zahl
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_not_F, (object obj));
- local void fehler_not_F(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(float)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine Floating-Point-Zahl sein: ~"
- //: ENGLISH "argument to ~ should be a floating point number: ~"
- //: FRANCAIS "L'argument pour ~ doit être un nombre à virgule flottante et non ~."
- fehler(type_error, GETTEXT("argument to ~ should be a floating point number: ~"));
- }
-
- # Fehlermeldung, wenn keine rationale Zahl kommt.
- # > obj: Objekt, keine rationale Zahl
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_not_RA, (object obj));
- local void fehler_not_RA(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(rational)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine rationale Zahl sein: ~"
- //: ENGLISH "argument to ~ should be a rational number: ~"
- //: FRANCAIS "L'argument pour ~ doit être un nombre rationnel et non ~."
- fehler(type_error, GETTEXT("argument to ~ should be a rational number: ~"));
- }
-
- # Fehlermeldung, wenn keine ganze Zahl kommt.
- # > obj: Objekt, keine ganze Zahl
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_not_I, (object obj));
- local void fehler_not_I(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(integer)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "Argument zu ~ muß eine ganze Zahl sein: ~"
- //: ENGLISH "argument to ~ should be an integer: ~"
- //: FRANCAIS "L'argument pour ~ doit être un nombre entier et non ~."
- fehler(type_error, GETTEXT("argument to ~ should be an integer: ~"));
- }
-
- # Fehlermeldung wegen illegalem Digits-Argument obj.
- # > obj: Objekt
- # > subr_self: Aufrufer (ein SUBR)
- nonreturning_function(local, fehler_digits, (object obj));
- local void fehler_digits(obj)
- var reg1 object obj;
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(O(type_posfixnum1)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument muß ein Fixnum >0 sein, nicht ~"
- //: ENGLISH "~: argument should be a positive fixnum, not ~"
- //: FRANCAIS "~ : L'argument doit être de type FIXNUM positif et non ~."
- fehler(type_error, GETTEXT("~: argument should be a positive fixnum, not ~"));
- }
-
- # check_number(obj) überprüft, ob obj eine Zahl ist.
- # > subr_self: Aufrufer (ein SUBR)
- #define check_number(obj) { if (!numberp(obj)) { fehler_not_N(obj); } }
-
- # check_real(obj) überprüft, ob obj eine reelle Zahl ist.
- # > subr_self: Aufrufer (ein SUBR)
- #define check_real(obj) if_realp(obj, ; , { fehler_not_R(obj); } );
-
- # check_float(obj) überprüft, ob obj eine Floating-Point-Zahl ist.
- # > subr_self: Aufrufer (ein SUBR)
- #define check_float(obj) { if (!floatp(obj)) { fehler_not_F(obj); } }
-
- # check_rational(obj) überprüft, ob obj eine rationale Zahl ist.
- # > subr_self: Aufrufer (ein SUBR)
- #define check_rational(obj) if_rationalp(obj, ; , { fehler_not_RA(obj); } );
-
- # check_integer(obj) überprüft, ob obj eine ganze Zahl ist.
- # > subr_self: Aufrufer (ein SUBR)
- #define check_integer(obj) { if (!integerp(obj)) { fehler_not_I(obj); } }
-
- LISPFUNN(decimal_string,1)
- # (SYS::DECIMAL-STRING integer)
- # liefert zu einem Integer >=0 (write-to-string integer :base 10 :radix nil),
- # also die Ziffernfolge als Simple-String.
- { var reg1 object x = popSTACK();
- check_integer(x);
- { SAVE_NUM_STACK # num_stack retten
- var reg3 uintD* MSDptr;
- var reg2 uintC len;
- I_to_NDS(x, MSDptr=,len=,_EMA_); # x (>=0) als UDS
- {var reg4 uintL need = digits_need(len,10);
- var DYNAMIC_ARRAY(reg5,ziffern,uintB,need); # Platz für die Ziffern
- var DIGITS erg; erg.LSBptr = &ziffern[need];
- UDS_to_DIGITS(MSDptr,len,10,&erg); # Umwandlung in Ziffern
- RESTORE_NUM_STACK # num_stack (vorzeitig) zurück
- value1 = make_string(erg.MSBptr,erg.len); # Ziffern in Simple-String schreiben
- mv_count=1;
- FREE_DYNAMIC_ARRAY(ziffern);
- } }}
-
- LISPFUNN(zerop,1)
- # (ZEROP number), CLTL S. 195
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = (N_zerop(x) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(plusp,1)
- # (PLUSP real), CLTL S. 196
- { var reg1 object x = popSTACK();
- check_real(x);
- value1 = (R_plusp(x) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(minusp,1)
- # (MINUSP real), CLTL S. 196
- { var reg1 object x = popSTACK();
- check_real(x);
- value1 = (R_minusp(x) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(oddp,1)
- # (ODDP integer), CLTL S. 196
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = (I_oddp(x) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(evenp,1)
- # (EVENP integer), CLTL S. 196
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = (I_oddp(x) ? NIL : T); mv_count=1;
- }
-
- # UP: Testet, ob alle argcount+1 Argumente unterhalb von args_pointer
- # Zahlen sind. Wenn nein, Error.
- # > argcount: Argumentezahl-1
- # > args_pointer: Pointer über die Argumente
- # > subr_self: Aufrufer (ein SUBR)
- local void test_number_args (uintC argcount, object* args_pointer);
- local void test_number_args(argcount,args_pointer)
- var reg2 uintC argcount;
- var reg1 object* args_pointer;
- { dotimespC(argcount,argcount+1,
- { var reg3 object arg = NEXT(args_pointer); # nächstes Argument
- check_number(arg); # muß eine Zahl sein
- });
- }
-
- # UP: Testet, ob alle argcount+1 Argumente unterhalb von args_pointer
- # reelle Zahlen sind. Wenn nein, Error.
- # > argcount: Argumentezahl-1
- # > args_pointer: Pointer über die Argumente
- # > subr_self: Aufrufer (ein SUBR)
- local void test_real_args (uintC argcount, object* args_pointer);
- local void test_real_args(argcount,args_pointer)
- var reg2 uintC argcount;
- var reg1 object* args_pointer;
- { dotimespC(argcount,argcount+1,
- { var reg3 object arg = NEXT(args_pointer); # nächstes Argument
- check_real(arg); # muß eine reelle Zahl sein
- });
- }
-
- # UP: Testet, ob alle argcount+1 Argumente unterhalb von args_pointer
- # ganze Zahlen sind. Wenn nein, Error.
- # > argcount: Argumentezahl-1
- # > args_pointer: Pointer über die Argumente
- # > subr_self: Aufrufer (ein SUBR)
- local void test_integer_args (uintC argcount, object* args_pointer);
- local void test_integer_args(argcount,args_pointer)
- var reg2 uintC argcount;
- var reg1 object* args_pointer;
- { dotimespC(argcount,argcount+1,
- { var reg3 object arg = NEXT(args_pointer); # nächstes Argument
- check_integer(arg); # muß eine ganze Zahl sein
- });
- }
-
- LISPFUN(gleich,1,0,rest,nokey,0,NIL)
- # (= number {number}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_number_args(argcount,args_pointer); # Alle Argumente Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for i:=0 to n-1 do ( if Arg[i]/=Arg[i+1] then return(NIL) ), return(T).
- { var reg1 object* arg_i_ptr = args_pointer;
- dotimesC(argcount,argcount,
- { var reg3 object arg_i = NEXT(arg_i_ptr);
- if (!N_N_gleich(arg_i,Next(arg_i_ptr))) goto no;
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(ungleich,1,0,rest,nokey,0,NIL)
- # (/= number {number}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_number_args(argcount,args_pointer); # Alle Argumente Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for j:=1 to n do
- # for i:=0 to j-1 do
- # if Arg[i]=Arg[j] then return(NIL),
- # return(T).
- { var reg2 object* arg_j_ptr = rest_args_pointer;
- dotimesC(argcount,argcount,
- { var reg1 object* arg_i_ptr = args_pointer;
- do { if (N_N_gleich(NEXT(arg_i_ptr),Next(arg_j_ptr))) goto no; }
- until (arg_i_ptr==arg_j_ptr);
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(kleiner,1,0,rest,nokey,0,NIL)
- # (< real {real}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for i:=0 to n-1 do ( if Arg[i]>=Arg[i+1] then return(NIL) ), return(T).
- { var reg1 object* arg_i_ptr = args_pointer;
- dotimesC(argcount,argcount,
- { var reg3 object arg_i = NEXT(arg_i_ptr);
- if (R_R_comp(arg_i,Next(arg_i_ptr))>=0) goto no;
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(groesser,1,0,rest,nokey,0,NIL)
- # (> real {real}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for i:=0 to n-1 do ( if Arg[i]<=Arg[i+1] then return(NIL) ), return(T).
- { var reg1 object* arg_i_ptr = args_pointer;
- dotimesC(argcount,argcount,
- { var reg3 object arg_i = NEXT(arg_i_ptr);
- if (R_R_comp(arg_i,Next(arg_i_ptr))<=0) goto no;
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(klgleich,1,0,rest,nokey,0,NIL)
- # (<= real {real}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for i:=0 to n-1 do ( if Arg[i]>Arg[i+1] then return(NIL) ), return(T).
- { var reg1 object* arg_i_ptr = args_pointer;
- dotimesC(argcount,argcount,
- { var reg3 object arg_i = NEXT(arg_i_ptr);
- if (R_R_comp(arg_i,Next(arg_i_ptr))>0) goto no;
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(grgleich,1,0,rest,nokey,0,NIL)
- # (>= real {real}), CLTL S. 196
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # for i:=0 to n-1 do ( if Arg[i]<Arg[i+1] then return(NIL) ), return(T).
- { var reg1 object* arg_i_ptr = args_pointer;
- dotimesC(argcount,argcount,
- { var reg3 object arg_i = NEXT(arg_i_ptr);
- if (R_R_comp(arg_i,Next(arg_i_ptr))<0) goto no;
- });
- }
- yes: value1 = T; goto ok;
- no: value1 = NIL; goto ok;
- ok: mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(max,1,0,rest,nokey,0,NIL)
- # (MAX real {real}), CLTL S. 198
- # Methode:
- # (max x1 x2 x3 ... xn) = (max ...(max (max x1 x2) x3)... xn)
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := max(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Maximum
- dotimesC(argcount,argcount, { x = R_R_max_R(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(args_pointer);
- } }
-
- LISPFUN(min,1,0,rest,nokey,0,NIL)
- # (MIN real {real}), CLTL S. 198
- # Methode:
- # (min x1 x2 x3 ... xn) = (min ...(min (min x1 x2) x3)... xn)
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_real_args(argcount,args_pointer); # Alle Argumente reelle Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := min(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Minimum
- dotimesC(argcount,argcount, { x = R_R_min_R(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(args_pointer);
- } }
-
- LISPFUN(plus,0,0,rest,nokey,0,NIL)
- # (+ {number}), CLTL S. 199
- # Methode:
- # (+) = 0
- # (+ x1 x2 x3 ... xn) = (+ ...(+ (+ x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_0; mv_count=1; return; }
- argcount--;
- test_number_args(argcount,rest_args_pointer); # Alle Argumente Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := x+Arg[i] ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisherige Summe
- dotimesC(argcount,argcount, { x = N_N_plus_N(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUN(minus,1,0,rest,nokey,0,NIL)
- # (- number {number}), CLTL S. 199
- # Methode:
- # (- x) extra.
- # (- x1 x2 x3 ... xn) = (- ...(- (- x1 x2) x3)... xn)
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_number_args(argcount,args_pointer); # Alle Argumente Zahlen?
- if (argcount==0)
- # unäres Minus
- { value1 = N_minus_N(Next(args_pointer)); }
- else
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := x-Arg[i] ), return(x).
- { var reg1 object* arg_i_ptr = args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisherige Differenz
- dotimespC(argcount,argcount, { x = N_N_minus_N(x,NEXT(arg_i_ptr)); } );
- value1 = x;
- }
- mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUN(mal,0,0,rest,nokey,0,NIL)
- # (* {number}), CLTL S. 199
- # Methode:
- # (*) = 1
- # (* x1 x2 x3 ... xn) = (* ...(* (* x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_1; mv_count=1; return; }
- argcount--;
- test_number_args(argcount,rest_args_pointer); # Alle Argumente Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := x*Arg[i] ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Produkt
- dotimesC(argcount,argcount, { x = N_N_mal_N(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUN(durch,1,0,rest,nokey,0,NIL)
- # (/ number {number}), CLTL S. 200
- # Methode:
- # (/ x) extra.
- # (/ x1 x2 x3 ... xn) = (/ ...(/ (/ x1 x2) x3)... xn)
- { var reg4 object* args_pointer = rest_args_pointer STACKop 1;
- test_number_args(argcount,args_pointer); # Alle Argumente Zahlen?
- if (argcount==0)
- # unäres Durch
- { value1 = N_durch_N(Next(args_pointer)); }
- else
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := x/Arg[i] ), return(x).
- { var reg1 object* arg_i_ptr = args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisherige Differenz
- dotimespC(argcount,argcount, { x = N_N_durch_N(x,NEXT(arg_i_ptr)); } );
- value1 = x;
- }
- mv_count=1; set_args_end_pointer(args_pointer);
- }
-
- LISPFUNN(einsplus,1)
- # (1+ number), CLTL S. 200
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_1_plus_N(x); mv_count=1;
- }
-
- LISPFUNN(einsminus,1)
- # (1- number), CLTL S. 200
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_minus1_plus_N(x); mv_count=1;
- }
-
- LISPFUNN(conjugate,1)
- # (CONJUGATE number), CLTL S. 201
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_conjugate_N(x); mv_count=1;
- }
-
- LISPFUN(gcd,0,0,rest,nokey,0,NIL)
- # (GCD {integer}), CLTL S. 202
- # Methode:
- # (gcd) = 0
- # (gcd x) = (abs x)
- # (gcd x1 x2 x3 ... xn) = (gcd ...(gcd (gcd x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_0; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- if (argcount==0)
- { value1 = I_abs_I(Next(rest_args_pointer)); }
- else
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := gcd(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriger ggT
- dotimespC(argcount,argcount, { x = I_I_gcd_I(x,NEXT(arg_i_ptr)); } );
- value1 = x;
- }
- mv_count=1; set_args_end_pointer(rest_args_pointer);
- }
-
- LISPFUN(xgcd,0,0,rest,nokey,0,NIL)
- # (XGCD {integer})
- # (XGCD x1 ... xn) liefert n+1 Werte: g = (gcd x1 ... xn), ein Integer >=0,
- # und n Integers u1,...,un mit g = u1*x1+...+un*xn.
- # Methode:
- # (xgcd) = 0
- # (xgcd x) = (abs x), (signum x)
- # (xgcd x1 x2 x3 ... xn) mit n>=2:
- # (g,u[1],u[2]) := (xgcd x1 x2),
- # für i=3,...,n:
- # (g',u,v) := (xgcd g xi),
- # (g,u[1],...,u[i]) := (g',u*u[1],...,u*u[i-1],v).
- { if (argcount==0) { value1 = Fixnum_0; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- if (argcount==0)
- { var reg1 object arg = Next(rest_args_pointer);
- if (R_minusp(arg))
- { value1 = arg; value2 = Fixnum_minus1; }
- else
- { value1 = I_minus_I(arg); value2 = Fixnum_1; }
- mv_count=2;
- }
- else
- # Methode:
- # n+1 Argumente Arg[0..n].
- # (g,u,v):=xgcd(Arg[0],Arg[1]), Arg[0]:=u, Arg[1]:=v,
- # for i:=2 to n do
- # ( (g,u,v):=xgcd(g,Arg[i]), Arg[i]:=v,
- # for j:=i-1 downto 0 do Arg[j]:=u*Arg[j],
- # ),
- # return values(g,Arg[0],...,Arg[n]).
- { var reg3 object* arg_i_ptr = rest_args_pointer;
- var reg4 object g; # bisheriger ggT
- {var reg2 object arg_0 = NEXT(arg_i_ptr);
- var reg1 object arg_1 = Next(arg_i_ptr);
- I_I_xgcd_I_I_I(arg_0,arg_1);
- Before(arg_i_ptr) = STACK_2;
- }
- loop
- { NEXT(arg_i_ptr) = STACK_1;
- g = STACK_0; skipSTACK(3);
- if (arg_i_ptr == args_end_pointer) break;
- I_I_xgcd_I_I_I(g,Next(arg_i_ptr));
- {var reg1 object* arg_j_ptr = arg_i_ptr;
- do { var reg2 object arg_j = Before(arg_j_ptr);
- BEFORE(arg_j_ptr) = I_I_mal_I(STACK_2,arg_j);
- }
- until (arg_j_ptr == rest_args_pointer);
- }}
- value1 = g; # g als 1. Wert
- # Beifaktoren als weitere Werte:
- {var reg2 object* mvp = &value2;
- var reg1 object* arg_i_ptr = rest_args_pointer;
- if (argcount >= mv_limit-2) { fehler_mv_zuviel(S(xgcd)); }
- mv_count = argcount+2;
- dotimespC(argcount,argcount+1, { *mvp++ = NEXT(arg_i_ptr); } );
- } }
- set_args_end_pointer(rest_args_pointer);
- }
-
- LISPFUN(lcm,0,0,rest,nokey,0,NIL)
- # (LCM {integer})
- # Methode:
- # (lcm) = 1 (neutrales Element der lcm-Operation)
- # (lcm x) = (abs x)
- # (lcm x1 x2 x3 ... xn) = (lcm ...(lcm (lcm x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_1; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- if (argcount==0)
- { value1 = I_abs_I(Next(rest_args_pointer)); }
- else
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := lcm(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges kgV
- dotimespC(argcount,argcount, { x = I_I_lcm_I(x,NEXT(arg_i_ptr)); } );
- value1 = x;
- }
- mv_count=1; set_args_end_pointer(rest_args_pointer);
- }
-
- LISPFUNN(exp,1)
- # (EXP number), CLTL S. 203
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_exp_N(x); mv_count=1;
- }
-
- LISPFUNN(expt,2)
- # (EXPT number number), CLTL S. 203
- { var reg1 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_number(x); check_number(y); skipSTACK(2);
- value1 = N_N_expt_N(x,y); mv_count=1;
- }
-
- LISPFUN(log,1,1,norest,nokey,0,NIL)
- # (LOG number [base-number]), CLTL S. 204
- { var reg1 object base = popSTACK();
- var reg2 object arg = popSTACK();
- check_number(arg);
- if (eq(base,unbound))
- # LOG mit einem Argument
- { value1 = N_log_N(arg); }
- else
- # LOG mit zwei Argumenten
- { check_number(base);
- value1 = N_N_log_N(arg,base);
- }
- mv_count=1;
- }
-
- LISPFUNN(sqrt,1)
- # (SQRT number), CLTL S. 205
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_sqrt_N(x); mv_count=1;
- }
-
- LISPFUNN(isqrt,1)
- # (ISQRT integer), CLTL S. 205
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = (I_isqrt_I(x), popSTACK()); mv_count=1;
- }
-
- LISPFUNN(abs,1)
- # (ABS number), CLTL S. 205
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_abs_R(x); mv_count=1;
- }
-
- LISPFUNN(phase,1)
- # (PHASE number), CLTL S. 206
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_phase_R(x); mv_count=1;
- }
-
- LISPFUNN(signum,1)
- # (SIGNUM number), CLTL S. 206
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_signum_N(x); mv_count=1;
- }
-
- LISPFUNN(sin,1)
- # (SIN number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_sin_N(x); mv_count=1;
- }
-
- LISPFUNN(cos,1)
- # (COS number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_cos_N(x); mv_count=1;
- }
-
- LISPFUNN(tan,1)
- # (TAN number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_tan_N(x); mv_count=1;
- }
-
- LISPFUNN(cis,1)
- # (CIS number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_cis_N(x); mv_count=1;
- }
-
- LISPFUNN(asin,1)
- # (ASIN number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_asin_N(x); mv_count=1;
- }
-
- LISPFUNN(acos,1)
- # (ACOS number), CLTL S. 207
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_acos_N(x); mv_count=1;
- }
-
- LISPFUN(atan,1,1,norest,nokey,0,NIL)
- # (ATAN number [real]), CLTL S. 207
- { var reg2 object arg2 = popSTACK();
- var reg1 object arg1 = popSTACK();
- if (eq(arg2,unbound))
- # 1 Argument
- { check_number(arg1);
- value1 = N_atan_N(arg1);
- }
- else
- # 2 Argumente
- { check_real(arg1); check_real(arg2);
- value1 = R_R_atan_R(arg2,arg1); # atan(X=arg2,Y=arg1)
- }
- mv_count=1;
- }
-
- LISPFUNN(sinh,1)
- # (SINH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_sinh_N(x); mv_count=1;
- }
-
- LISPFUNN(cosh,1)
- # (COSH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_cosh_N(x); mv_count=1;
- }
-
- LISPFUNN(tanh,1)
- # (TANH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_tanh_N(x); mv_count=1;
- }
-
- LISPFUNN(asinh,1)
- # (ASINH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_asinh_N(x); mv_count=1;
- }
-
- LISPFUNN(acosh,1)
- # (ACOSH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_acosh_N(x); mv_count=1;
- }
-
- LISPFUNN(atanh,1)
- # (ATANH number), CLTL S. 209
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_atanh_N(x); mv_count=1;
- }
-
- LISPFUN(float,1,1,norest,nokey,0,NIL)
- # (FLOAT number [float]), CLTL S. 214
- { var reg2 object arg2 = popSTACK();
- var reg1 object arg1 = popSTACK();
- check_real(arg1);
- if (eq(arg2,unbound))
- # 1 Argument
- { value1 = R_float_F(arg1); }
- else
- # 2 Argumente
- { check_float(arg2); value1 = R_F_float_F(arg1,arg2); }
- mv_count=1;
- }
-
- # UP: Wandelt ein Objekt in ein Float von gegebenem Typ um.
- # coerce_float(obj,type)
- # > obj: Objekt
- # > type: Eines der Symbole
- # FLOAT, SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT
- # > subr_self: Aufrufer (ein SUBR)
- # < ergebnis: (coerce obj type)
- # kann GC auslösen
- global object coerce_float (object obj, object type);
- global object coerce_float(obj,type)
- var reg2 object obj;
- var reg1 object type;
- { check_real(obj);
- if (eq(type,S(short_float))) # SHORT-FLOAT
- { return R_to_SF(obj); }
- elif (eq(type,S(single_float))) # SINGLE-FLOAT
- { return R_to_FF(obj); }
- elif (eq(type,S(double_float))) # DOUBLE-FLOAT
- { return R_to_DF(obj); }
- elif (eq(type,S(long_float))) # LONG-FLOAT
- { return R_to_LF(obj,I_to_UL(O(LF_digits))); } # Default-Genauigkeit
- else # FLOAT
- { return R_float_F(obj); }
- }
-
- LISPFUNN(rational,1)
- # (RATIONAL real), CLTL S. 214
- { var reg1 object x = popSTACK();
- check_real(x);
- value1 = R_rational_RA(x); mv_count=1;
- }
-
- LISPFUNN(rationalize,1)
- # (RATIONALIZE real), CLTL S. 214
- { var reg1 object x = popSTACK();
- check_real(x);
- value1 = R_rationalize_RA(x); mv_count=1;
- }
-
- LISPFUNN(numerator,1)
- # (NUMERATOR rational), CLTL S. 215
- { var reg1 object x = popSTACK();
- check_rational(x);
- value1 = (RA_integerp(x) ? x : TheRatio(x)->rt_num); mv_count=1;
- }
-
- LISPFUNN(denominator,1)
- # (DENOMINATOR rational), CLTL S. 215
- { var reg1 object x = popSTACK();
- check_rational(x);
- value1 = (RA_integerp(x) ? Fixnum_1 : TheRatio(x)->rt_den); mv_count=1;
- }
-
- LISPFUN(floor,1,1,norest,nokey,0,NIL)
- # (FLOOR real [real]), CLTL S. 215
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_floor_I_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_floor_I_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(ceiling,1,1,norest,nokey,0,NIL)
- # (CEILING real [real]), CLTL S. 215
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_ceiling_I_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_ceiling_I_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(truncate,1,1,norest,nokey,0,NIL)
- # (TRUNCATE real [real]), CLTL S. 215
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_truncate_I_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_truncate_I_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(round,1,1,norest,nokey,0,NIL)
- # (ROUND real [real]), CLTL S. 215
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_round_I_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_round_I_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUNN(mod,2)
- # (MOD real real), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- check_real(y);
- value1 = R_R_mod_R(x,y); mv_count=1;
- }
-
- LISPFUNN(rem,2)
- # (REM real real), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- check_real(y);
- value1 = R_R_rem_R(x,y); mv_count=1;
- }
-
- LISPFUN(ffloor,1,1,norest,nokey,0,NIL)
- # (FFLOOR real [real]), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_ffloor_F_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_ffloor_F_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(fceiling,1,1,norest,nokey,0,NIL)
- # (FCEILING real [real]), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_fceiling_F_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_fceiling_F_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(ftruncate,1,1,norest,nokey,0,NIL)
- # (FTRUNCATE real [real]), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_ftruncate_F_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_ftruncate_F_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUN(fround,1,1,norest,nokey,0,NIL)
- # (FROUND real [real]), CLTL S. 217
- { var reg1 object y = popSTACK();
- var reg2 object x = popSTACK();
- check_real(x);
- if (eq(y,unbound) || eq(y,Fixnum_1))
- # 1 Argument oder 2. Argument =1
- { R_fround_F_R(x); }
- else
- # 2 Argumente
- { check_real(y);
- R_R_fround_F_R(x,y);
- }
- # Stackaufbau: q, r.
- value1 = STACK_1; value2 = STACK_0; skipSTACK(2); mv_count=2;
- }
-
- LISPFUNN(decode_float,1)
- # (DECODE-FLOAT float), CLTL S. 218
- { var reg1 object f = popSTACK();
- check_float(f);
- F_decode_float_F_I_F(f);
- value1 = STACK_2; value2 = STACK_1; value3 = STACK_0; skipSTACK(3);
- mv_count=3;
- }
-
- LISPFUNN(scale_float,2)
- # (SCALE-FLOAT float integer), CLTL S. 218
- { var reg1 object f = STACK_1;
- var reg1 object i = STACK_0;
- check_float(f); check_integer(i); skipSTACK(2);
- value1 = F_I_scale_float_F(f,i); mv_count=1;
- }
-
- LISPFUNN(float_radix,1)
- # (FLOAT-RADIX float), CLTL S. 218
- { var reg1 object f = popSTACK();
- check_float(f);
- value1 = F_float_radix_I(f); mv_count=1;
- }
-
- LISPFUN(float_sign,1,1,norest,nokey,0,NIL)
- # (FLOAT-SIGN float [float]), CLTL S. 218
- { var reg2 object arg2 = popSTACK();
- var reg1 object arg1 = popSTACK();
- check_float(arg1);
- if (eq(arg2,unbound))
- # 1 Argument
- { value1 = F_float_sign_F(arg1); }
- else
- # 2 Argumente
- { check_float(arg2);
- value1 = F_F_float_sign_F(arg1,arg2);
- }
- }
-
- LISPFUN(float_digits,1,1,norest,nokey,0,NIL)
- # (FLOAT-DIGITS number [digits]), CLTL S. 218
- { var reg2 object arg2 = popSTACK();
- var reg3 object arg1 = popSTACK();
- if (eq(arg2,unbound))
- # 1 Argument: (FLOAT-DIGITS float)
- { check_float(arg1);
- value1 = F_float_digits_I(arg1);
- }
- else
- # 2 Argumente: (FLOAT-DIGITS number digits)
- { if (!posfixnump(arg2)) { fehler_digits(arg2); } # nicht notwendig Fixnum!??
- {var reg1 uintL d = posfixnum_to_L(arg2); # = I_to_UL(arg2); ??
- if (d==0) { fehler_digits(arg2); } # sollte >0 sein
- check_real(arg1);
- # arg1 in ein Float mit mindestens d Bits umwandeln:
- if (d > DF_mant_len+1)
- # -> Long-Float
- { d = ceiling(d,intDsize);
- if ((intCsize<32) && (d > (bitc(intCsize)-1))) { fehler_LF_toolong(); }
- value1 = R_to_LF(arg1,d);
- }
- else
- # ein Double-Float reicht
- if (d > FF_mant_len+1)
- # -> Double-Float
- { value1 = R_to_DF(arg1); }
- else
- # ein Single-Float reicht
- if (d > SF_mant_len+1)
- # -> Single-Float
- { value1 = R_to_FF(arg1); }
- else
- # ein Short-Float reicht
- { value1 = R_to_SF(arg1); }
- }}
- mv_count=1;
- }
-
- LISPFUNN(float_precision,1)
- # (FLOAT-PRECISION float), CLTL S. 218
- { var reg1 object f = popSTACK();
- check_float(f);
- value1 = F_float_precision_I(f); mv_count=1;
- }
-
- LISPFUNN(integer_decode_float,1)
- # (INTEGER-DECODE-FLOAT float), CLTL S. 218
- { var reg1 object f = popSTACK();
- check_float(f);
- F_integer_decode_float_I_I_I(f);
- value1 = STACK_2; value2 = STACK_1; value3 = STACK_0; skipSTACK(3);
- mv_count=3;
- }
-
- LISPFUN(complex,1,1,norest,nokey,0,NIL)
- # (COMPLEX real [real]), CLTL S. 220
- # Abweichung von CLTL:
- # Bei uns ist für reelle x stets (COMPLEX x) = x.
- # Grund: Daß (COMPLEX 1) = 1 sein soll, zeigt, daß (COMPLEX x) als (COMPLEX x 0)
- # zu interpretieren ist. Bei uns können komplexe Zahlen einen Realteil
- # und einen Imaginärteil verschiedenen Typs haben (vgl. CLTL, Seite 19),
- # und es ist dann (COMPLEX x 0) = x.
- { var reg1 object arg2 = popSTACK();
- var reg2 object arg1 = popSTACK();
- check_real(arg1);
- if (eq(arg2,unbound))
- # 1 Argument
- { value1 = arg1; }
- else
- # 2 Argumente
- { check_real(arg2);
- value1 = R_R_complex_N(arg1,arg2);
- }
- mv_count=1;
- }
-
- LISPFUNN(realpart,1)
- # (REALPART number), CLTL S. 220
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_realpart_R(x); mv_count=1;
- }
-
- LISPFUNN(imagpart,1)
- # (IMAGPART number), CLTL S. 220
- { var reg1 object x = popSTACK();
- check_number(x);
- value1 = N_imagpart_R(x); mv_count=1;
- }
-
- LISPFUN(logior,0,0,rest,nokey,0,NIL)
- # (LOGIOR {integer}), CLTL S. 221
- # Methode:
- # (logior) = 0
- # (logior x1 x2 x3 ... xn) = (logior ...(logior (logior x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_0; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := logior(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Oder
- dotimesC(argcount,argcount, { x = I_I_logior_I(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUN(logxor,0,0,rest,nokey,0,NIL)
- # (LOGXOR {integer}), CLTL S. 221
- # Methode:
- # (logxor) = 0
- # (logxor x1 x2 x3 ... xn) = (logxor ...(logxor (logxor x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_0; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := logxor(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Xor
- dotimesC(argcount,argcount, { x = I_I_logxor_I(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUN(logand,0,0,rest,nokey,0,NIL)
- # (LOGAND {integer}), CLTL S. 221
- # Methode:
- # (logand) = -1
- # (logand x1 x2 x3 ... xn) = (logand ...(logand (logand x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_minus1; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := logand(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges And
- dotimesC(argcount,argcount, { x = I_I_logand_I(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUN(logeqv,0,0,rest,nokey,0,NIL)
- # (LOGEQV {integer}), CLTL S. 221
- # Methode:
- # (logeqv) = -1
- # (logeqv x1 x2 x3 ... xn) = (logeqv ...(logeqv (logeqv x1 x2) x3)... xn)
- { if (argcount==0) { value1 = Fixnum_minus1; mv_count=1; return; }
- argcount--;
- test_integer_args(argcount,rest_args_pointer); # Alle Argumente ganze Zahlen?
- # Methode:
- # n+1 Argumente Arg[0..n].
- # x:=Arg[0], for i:=1 to n do ( x := logeqv(x,Arg[i]) ), return(x).
- { var reg1 object* arg_i_ptr = rest_args_pointer;
- var reg2 object x = NEXT(arg_i_ptr); # bisheriges Zwischen-EQV
- dotimesC(argcount,argcount, { x = I_I_logeqv_I(x,NEXT(arg_i_ptr)); } );
- value1 = x; mv_count=1; set_args_end_pointer(rest_args_pointer);
- } }
-
- LISPFUNN(lognand,2)
- # (LOGNAND integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_lognand_I(x,y); mv_count=1;
- }
-
- LISPFUNN(lognor,2)
- # (LOGNOR integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_lognor_I(x,y); mv_count=1;
- }
-
- LISPFUNN(logandc1,2)
- # (LOGANDC1 integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_logandc1_I(x,y); mv_count=1;
- }
-
- LISPFUNN(logandc2,2)
- # (LOGANDC2 integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_logandc2_I(x,y); mv_count=1;
- }
-
- LISPFUNN(logorc1,2)
- # (LOGORC1 integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_logorc1_I(x,y); mv_count=1;
- }
-
- LISPFUNN(logorc2,2)
- # (LOGORC2 integer integer), CLTL S. 221
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_logorc2_I(x,y); mv_count=1;
- }
-
- LISPFUNN(boole,3)
- # (BOOLE op integer integer), CLTL S. 222
- { var reg3 object op = STACK_2; # Operator, kein Typtest
- var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(3);
- value1 = OP_I_I_boole_I(op,x,y); mv_count=1;
- }
-
- LISPFUNN(lognot,1)
- # (LOGNOT integer), CLTL S. 223
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = I_lognot_I(x); mv_count=1;
- }
-
- LISPFUNN(logtest,2)
- # (LOGTEST integer integer), CLTL S. 223
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = (I_I_logtest(x,y) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(logbitp,2)
- # (LOGBITP integer integer), CLTL S. 224
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = (I_I_logbitp(x,y) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(ash,2)
- # (ASH integer integer), CLTL S. 224
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_ash_I(x,y); mv_count=1;
- }
-
- LISPFUNN(logcount,1)
- # (LOGCOUNT integer), CLTL S. 224
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = I_logcount_I(x); mv_count=1;
- }
-
- LISPFUNN(integer_length,1)
- # (INTEGER-LENGTH integer), CLTL S. 224
- { var reg1 object x = popSTACK();
- check_integer(x);
- value1 = I_integer_length_I(x); mv_count=1;
- }
-
- LISPFUNN(byte,2)
- # (BYTE size position), CLTL S. 225
- { var reg2 object s = STACK_1;
- var reg1 object p = STACK_0;
- skipSTACK(2);
- value1 = I_I_Byte(s,p); mv_count=1; # Typprüfungen dort. Wieso Fixnums??
- }
-
- LISPFUNN(bytesize,1)
- # (BYTE-SIZE bytespec), CLTL S. 226
- { var reg1 object b = popSTACK();
- value1 = Byte_size(b); mv_count=1; # Typprüfung dort
- }
-
- LISPFUNN(byteposition,1)
- # (BYTE-POSITION bytespec), CLTL S. 226
- { var reg1 object b = popSTACK();
- value1 = Byte_position(b); mv_count=1; # Typprüfung dort
- }
-
- LISPFUNN(ldb,2)
- # (LDB bytespec integer), CLTL S. 226
- { var reg2 object b = STACK_1; # Typprüfung erfolgt später
- var reg1 object x = STACK_0;
- check_integer(x); skipSTACK(2);
- value1 = I_Byte_ldb_I(x,b); mv_count=1;
- }
-
- LISPFUNN(ldb_test,2)
- # (LDB-TEST bytespec integer), CLTL S. 226
- { var reg2 object b = STACK_1; # Typprüfung erfolgt später
- var reg1 object x = STACK_0;
- check_integer(x); skipSTACK(2);
- value1 = (I_Byte_ldb_test(x,b) ? T : NIL); mv_count=1;
- }
-
- LISPFUNN(mask_field,2)
- # (MASK_FIELD bytespec integer), CLTL S. 226
- { var reg2 object b = STACK_1; # Typprüfung erfolgt später
- var reg1 object x = STACK_0;
- check_integer(x); skipSTACK(2);
- value1 = I_Byte_mask_field_I(x,b); mv_count=1;
- }
-
- LISPFUNN(dpb,3)
- # (DPB integer bytespec integer), CLTL S. 227
- { var reg2 object x = STACK_2;
- var reg3 object b = STACK_1; # Typprüfung erfolgt später
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(3);
- value1 = I_I_Byte_dpb_I(x,y,b); mv_count=1;
- }
-
- LISPFUNN(deposit_field,3)
- # (DEPOSIT-FIELD integer bytespec integer), CLTL S. 227
- { var reg2 object x = STACK_2;
- var reg3 object b = STACK_1; # Typprüfung erfolgt später
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(3);
- value1 = I_I_Byte_deposit_field_I(x,y,b); mv_count=1;
- }
-
- # Überprüft ein optionales Random-State-Argument obj.
- # check_random_state(obj)
- # > obj: optionales Random-State-Argument
- # > subr_self: Aufrufer (ein SUBR)
- # < ergebnis: das gemeinte Random-State
- local object check_random_state (object obj);
- local object check_random_state(obj)
- var reg1 object obj;
- { if (!eq(obj,unbound))
- # angegeben -> muß Random-State sein:
- { if (random_state_p(obj))
- { return obj; }
- else
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(random_state)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Argument muß ein Random-State sein, nicht ~"
- //: ENGLISH "~: argument should be a random-state, not ~"
- //: FRANCAIS "~ : L'argument doit être un «random-state» et non ~."
- fehler(type_error, GETTEXT("~: argument should be a random-state, not ~"));
- } }
- else
- # nicht angegeben -> Default aus *RANDOM-STATE*
- { obj = Symbol_value(S(random_state_stern)); # Wert von *RANDOM-STATE*
- if (random_state_p(obj))
- { return obj; }
- else
- { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(S(random_state)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(obj);
- pushSTACK(S(random_state_stern));
- pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~: Der Wert von ~ sollte ein Random-State sein, nicht ~"
- //: ENGLISH "~: the value of ~ should be a random-state, not ~"
- //: FRANCAIS "~ : La valeur de ~ devrait être un «random-state» et non ~."
- fehler(type_error, GETTEXT("~: the value of ~ should be a random-state, not ~"));
- } }
- }
-
- LISPFUN(random,1,1,norest,nokey,0,NIL)
- # (RANDOM number [state]), CLTL S. 228
- { var reg1 object x = STACK_1;
- var reg2 object r = check_random_state(STACK_0);
- skipSTACK(2);
- check_real(x); # x muß eine reelle Zahl sein, >0 und Float oder Integer
- if (R_plusp(x))
- { if (R_floatp(x)) { value1 = F_random_F(r,x); mv_count=1; return; }
- elif (RA_integerp(x)) { value1 = I_random_I(r,x); mv_count=1; return; }
- }
- pushSTACK(x); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(O(type_random_arg)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(x); pushSTACK(S(random));
- //: DEUTSCH "~: Argument muß positiv und Integer oder Float sein, nicht ~"
- //: ENGLISH "~: argument should be positive and an integer or float, not ~"
- //: FRANCAIS "~ : L'argument doit être positif et de type entier ou flottant et non ~."
- fehler(type_error, GETTEXT("~: argument should be positive and an integer or float, not ~"));
- }
-
- # make_random_state(r) liefert ein neues Random-State mit Initialzustand
- # - zufällig, falls r=T,
- # - aus Random-State *RANDOM-STATE*, falls r=NIL oder r=unbound,
- # - aus Random-State r selbst, sonst.
- # kann GC auslösen
- local object make_random_state (object r);
- local object make_random_state(r)
- var reg2 object r;
- { var reg4 uint32 seed_hi;
- var reg5 uint32 seed_lo;
- if (eq(r,T))
- # mit Random-Bits vom Betriebssystem initialisieren:
- {
- #if defined(AMIGAOS)
- seed_lo = get_real_time(); # Uhrzeit
- seed_hi = FindTask(NULL); # Pointer auf eigene Task
- #elif defined(MSDOS) || defined(RISCOS)
- # Keine Zufallszahlen, keine PID, nichts Zufälliges da.
- seed_lo = get_real_time(); # Uhrzeit, 100 Hz
- begin_system_call(); seed_hi = time(NULL); end_system_call(); # Uhrzeit, 1 Hz
- #elif defined(UNIX) || defined(WIN32_UNIX)
- #if defined(TIME_UNIX) || defined(TIME_WIN32)
- var reg1 internal_time* real_time = get_real_time(); # Uhrzeit
- seed_lo = highlow32(real_time->tv_sec,real_time->tv_usec); # 16+16 zufällige Bits
- #endif
- #ifdef TIME_UNIX_TIMES
- seed_lo = get_real_time(); # Uhrzeit, CLK_TCK Hz
- #endif
- seed_hi = (rand() # zufällige 31 Bit (bei UNIX_BSD) bzw. 16 Bit (bei UNIX_SYSV)
- << 8) ^ (uintL)(getpid()); # ca. 8 Bit von der Process ID
- #else
- #error "make_random_state() anpassen!"
- #endif
- }
- else
- { # Random-State überprüfen:
- r = check_random_state( (eq(r,NIL) ? unbound : r) );
- # dessen Zustand herausholen:
- {var reg3 object seed = The_Random_state(r)->random_state_seed;
- var reg1 uintD* seedMSDptr = (uintD*)(&TheSbvector(seed)->data[0]);
- seed_hi = get_32_Dptr(seedMSDptr);
- seed_lo = get_32_Dptr(&seedMSDptr[32/intDsize]);
- }}
- # neuen Zustands-Bitvektor holen und füllen:
- {var reg3 object seed = allocate_bit_vector(64);
- var reg1 uintD* seedMSDptr = (uintD*)(&TheSbvector(seed)->data[0]);
- set_32_Dptr(seedMSDptr,seed_hi);
- set_32_Dptr(&seedMSDptr[32/intDsize],seed_lo);
- pushSTACK(seed);
- }
- {var reg1 object state = allocate_random_state(); # neuen Random-State
- The_Random_state(state)->random_state_seed = popSTACK(); # mit Bit-Vektor füllen
- return state;
- } }
-
- LISPFUN(make_random_state,0,1,norest,nokey,0,NIL)
- # (MAKE-RANDOM-STATE [state]), CLTL S. 230
- { value1 = make_random_state(popSTACK()); mv_count=1; }
-
- LISPFUNN(fakultaet,1)
- # (! integer)
- { var reg1 object x = popSTACK();
- check_integer(x);
- if (!posfixnump(x))
- { pushSTACK(x); # Wert für Slot DATUM von TYPE-ERROR
- pushSTACK(O(type_posfixnum)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
- pushSTACK(x); pushSTACK(TheSubr(subr_self)->name);
- //: DEUTSCH "~ : Argument muß ein Fixnum >=0 sein, nicht ~"
- //: ENGLISH "~ : argument should be a fixnum >=0, not ~"
- //: FRANCAIS "~ : L'argument doit être de type FIXNUM positif ou zéro et non ~."
- fehler(type_error, GETTEXT("~ : argument should be a fixnum >=0, not ~"));
- }
- # x ist ein Fixnum >=0.
- value1 = FN_fak_I(x); mv_count=1;
- }
-
- LISPFUNN(exquo,2)
- # (EXQUO integer integer) dividiert zwei Integers. Die Division muß aufgehen.
- # (EXQUO x y) == (THE INTEGER (/ (THE INTEGER x) (THE INTEGER y)))
- { var reg2 object x = STACK_1;
- var reg1 object y = STACK_0;
- check_integer(x); check_integer(y); skipSTACK(2);
- value1 = I_I_exquo_I(x,y); mv_count=1;
- }
-
- LISPFUNN(long_float_digits,0)
- # (LONG-FLOAT-DIGITS) liefert die Default-Bitzahl von Long-Floats.
- { value1 = UL_to_I(intDsize * I_to_UL(O(LF_digits))); mv_count=1; }
-
- # Setzt die Default-Long-Float-Länge auf den Wert len (>= LF_minlen).
- # set_lf_digits(len);
- # kann GC auslösen
- local void set_lf_digits (uintC len);
- local void set_lf_digits(len)
- var reg3 uintC len;
- { O(LF_digits) = UL_to_I(len);
- # MOST-POSITIVE-LONG-FLOAT und MOST-NEGATIVE-LONG-FLOAT :
- { # Exponent so groß wie möglich, Mantisse 1...1
- var reg1 object x = allocate_lfloat(len,LF_exp_high,0);
- fill_loop_up(&TheLfloat(x)->data[0],len,~(uintD)0);
- define_variable(S(most_positive_long_float),x);
- x = LF_minus_LF(x);
- define_variable(S(most_negative_long_float),x);
- }
- # LEAST-POSITIVE-LONG-FLOAT und LEAST-NEGATIVE-LONG-FLOAT :
- { # Exponent so klein wie möglich, Mantisse 10...0
- var reg2 object x = allocate_lfloat(len,LF_exp_low,0);
- var reg1 uintD* ptr = &TheLfloat(x)->data[0];
- *ptr++ = bit(intDsize-1);
- clear_loop_up(ptr,len-1);
- define_variable(S(least_positive_long_float),x);
- x = LF_minus_LF(x);
- define_variable(S(least_negative_long_float),x);
- }
- # LONG-FLOAT-EPSILON = 2^-16n*(1+2^(1-16n)) :
- { # Exponent 1-16n, Mantisse 10...01
- var reg2 object x = allocate_lfloat(len,LF_exp_mid+1-intDsize*(uintL)len,0);
- var reg1 uintD* ptr = &TheLfloat(x)->data[0];
- *ptr++ = bit(intDsize-1);
- ptr = clear_loop_up(ptr,len-2);
- *ptr = bit(0);
- define_variable(S(long_float_epsilon),x);
- }
- # LONG-FLOAT-NEGATIVE-EPSILON = 2^(-16n-1)*(1+2^(1-16n)) :
- { # Exponent -16n, Mantisse 10...01
- var reg2 object x = allocate_lfloat(len,LF_exp_mid-intDsize*(uintL)len,0);
- var reg1 uintD* ptr = &TheLfloat(x)->data[0];
- *ptr++ = bit(intDsize-1);
- ptr = clear_loop_up(ptr,len-2);
- *ptr = bit(0);
- define_variable(S(long_float_negative_epsilon),x);
- # PI :
- x = O(pi) = pi_F_float_F(x);
- define_variable(S(pi),x);
- # SYS::*INHIBIT-FLOATING-POINT-UNDERFLOW* := NIL
- define_variable(S(inhibit_floating_point_underflow),NIL);
- }
- }
-
- LISPFUNN(set_long_float_digits,1)
- # (SETF (LONG-FLOAT-DIGITS) digits) = (SYS::%SET-LONG-FLOAT-DIGITS digits)
- { var reg2 object arg = STACK_0;
- if (!posfixnump(arg)) { fehler_digits(arg); } # nicht notwendig Fixnum!??
- {var reg1 uintL d = posfixnum_to_L(arg); # = I_to_UL(arg); ??
- if (d==0) { fehler_digits(arg); } # sollte >0 sein
- d = ceiling(d,intDsize);
- if ((intCsize<32) && (d > (bitc(intCsize)-1))) { fehler_LF_toolong(); }
- if (d < LF_minlen) { d = LF_minlen; } # d>=LF_minlen erzwingen
- set_lf_digits(d);
- value1 = popSTACK(); mv_count=1; # digits als Wert
- }}
-
- # UP für LOG2 und LOG10: Logarithmus des Fixnums x mit mindestens digits
- # Bits berechnen und - wenn nötig - den Wert in *objptr aktualisieren.
- local object log_digits (object x, object digits, object* objptr);
- local object log_digits(x,digits,objptr)
- var reg1 object x;
- var reg1 object digits;
- var reg1 object* objptr;
- { # digits-Argument überprüfen:
- if (!posfixnump(digits)) { fehler_digits(digits); } # nicht notwendig Fixnum!??
- {var reg1 uintL d = posfixnum_to_L(digits); # = I_to_UL(digits); ??
- if (d==0) { fehler_digits(digits); } # sollte >0 sein
- # bisher bekannten Wert holen:
- { var reg1 object ln_x = *objptr;
- # ln_x in ein Float mit mindestens d Bits umwandeln:
- if (d > DF_mant_len+1)
- # -> Long-Float
- { d = ceiling(d,intDsize);
- if ((intCsize<32) && (d > (bitc(intCsize)-1))) { fehler_LF_toolong(); }
- {var reg1 uintC oldlen = TheLfloat(ln_x)->len; # vorhandene Länge
- if (d < oldlen) { return LF_shorten_LF(ln_x,d); }
- if (d == oldlen) { return ln_x; }
- # gewünschte > vorhandene Länge -> muß nachberechnen:
- # TheLfloat(ln_x)->len um mindestens einen konstanten Faktor
- # > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird:
- oldlen += floor(oldlen,2); # oldlen * 3/2
- {var reg1 uintC newlen = (d < oldlen ? oldlen : d);
- ln_x = *objptr = R_ln_R(I_to_LF(x,newlen)); # (ln x) als LF mit newlen Digits berechnen
- return (d < newlen ? LF_shorten_LF(ln_x,d) : ln_x);
- }}}
- else
- # ein Double-Float reicht
- if (d > FF_mant_len+1)
- # -> Double-Float
- { return LF_to_DF(ln_x); }
- else
- # ein Single-Float reicht
- if (d > SF_mant_len+1)
- # -> Single-Float
- { return LF_to_FF(ln_x); }
- else
- # ein Short-Float reicht
- { return LF_to_SF(ln_x); }
- }}}
-
- LISPFUNN(log2,1)
- # (SYS::LOG2 digits) liefert ln(2) mit mindestens digits Bits.
- { value1 = log_digits(fixnum(2),popSTACK(),&O(LF_ln2));
- mv_count=1;
- }
-
- LISPFUNN(log10,1)
- # (SYS::LOG10 digits) liefert ln(10) mit mindestens digits Bits.
- { value1 = log_digits(fixnum(10),popSTACK(),&O(LF_ln10));
- mv_count=1;
- }
-
-
- # ============================================================================ #
- # Initialisierung
-
- #define D_(a,b,c,d) D(a,b,c,d,_EMA_)
-
- # Mantisse von pi :
- local uintD pi_mantisse [2048/intDsize] =
- { D_(0xC9,0x0F,0xDA,0xA2) D_(0x21,0x68,0xC2,0x34) D_(0xC4,0xC6,0x62,0x8B)
- D_(0x80,0xDC,0x1C,0xD1) D_(0x29,0x02,0x4E,0x08) D_(0x8A,0x67,0xCC,0x74)
- D_(0x02,0x0B,0xBE,0xA6) D_(0x3B,0x13,0x9B,0x22) D_(0x51,0x4A,0x08,0x79)
- D_(0x8E,0x34,0x04,0xDD) D_(0xEF,0x95,0x19,0xB3) D_(0xCD,0x3A,0x43,0x1B)
- D_(0x30,0x2B,0x0A,0x6D) D_(0xF2,0x5F,0x14,0x37) D_(0x4F,0xE1,0x35,0x6D)
- D_(0x6D,0x51,0xC2,0x45) D_(0xE4,0x85,0xB5,0x76) D_(0x62,0x5E,0x7E,0xC6)
- D_(0xF4,0x4C,0x42,0xE9) D_(0xA6,0x37,0xED,0x6B) D_(0x0B,0xFF,0x5C,0xB6)
- D_(0xF4,0x06,0xB7,0xED) D_(0xEE,0x38,0x6B,0xFB) D_(0x5A,0x89,0x9F,0xA5)
- D_(0xAE,0x9F,0x24,0x11) D_(0x7C,0x4B,0x1F,0xE6) D_(0x49,0x28,0x66,0x51)
- D_(0xEC,0xE4,0x5B,0x3D) D_(0xC2,0x00,0x7C,0xB8) D_(0xA1,0x63,0xBF,0x05)
- D_(0x98,0xDA,0x48,0x36) D_(0x1C,0x55,0xD3,0x9A) D_(0x69,0x16,0x3F,0xA8)
- D_(0xFD,0x24,0xCF,0x5F) D_(0x83,0x65,0x5D,0x23) D_(0xDC,0xA3,0xAD,0x96)
- D_(0x1C,0x62,0xF3,0x56) D_(0x20,0x85,0x52,0xBB) D_(0x9E,0xD5,0x29,0x07)
- D_(0x70,0x96,0x96,0x6D) D_(0x67,0x0C,0x35,0x4E) D_(0x4A,0xBC,0x98,0x04)
- D_(0xF1,0x74,0x6C,0x08) D_(0xCA,0x18,0x21,0x7C) D_(0x32,0x90,0x5E,0x46)
- D_(0x2E,0x36,0xCE,0x3B) D_(0xE3,0x9E,0x77,0x2C) D_(0x18,0x0E,0x86,0x03)
- D_(0x9B,0x27,0x83,0xA2) D_(0xEC,0x07,0xA2,0x8F) D_(0xB5,0xC5,0x5D,0xF0)
- D_(0x6F,0x4C,0x52,0xC9) D_(0xDE,0x2B,0xCB,0xF6) D_(0x95,0x58,0x17,0x18)
- D_(0x39,0x95,0x49,0x7C) D_(0xEA,0x95,0x6A,0xE5) D_(0x15,0xD2,0x26,0x18)
- D_(0x98,0xFA,0x05,0x10) D_(0x15,0x72,0x8E,0x5A) D_(0x8A,0xAA,0xC4,0x2D)
- D_(0xAD,0x33,0x17,0x0D) D_(0x04,0x50,0x7A,0x33) D_(0xA8,0x55,0x21,0xAB)
- D_(0xDF,0x1C,0xBA,0x65) } ;
-
- # Mantisse von ln(2) :
- local uintD ln2_mantisse [64/intDsize] =
- { D_(0xB1,0x72,0x17,0xF7) D_(0xD1,0xCF,0x79,0xAC) } ;
-
- # Mantisse von ln(10) :
- local uintD ln10_mantisse [64/intDsize] =
- { D_(0x93,0x5D,0x8D,0xDD) D_(0xAA,0xA8,0xAC,0x17) } ;
-
- #undef D_
-
- # UP: Initialisiert die Arithmetik.
- # init_arith();
- # kann GC auslösen
- global void init_arith (void);
- global void init_arith()
- { # verschiedene konstante Zahlen:
- #ifndef WIDE
- O(FF_zero) = allocate_ffloat(0); # 0.0F0
- # encode_FF(0,1,bit(FF_mant_len), O(FF_one)=); # 1.0F0
- # encode_FF(-1,1,bit(FF_mant_len), O(FF_minusone)=); # -1.0F0
- #endif
- #ifdef intQsize
- O(DF_zero) = allocate_dfloat(0); # 0.0D0
- # encode_DF(0,1,bit(DF_mant_len), O(DF_one)=); # 1.0D0
- # encode_DF(-1,1,bit(DF_mant_len), O(DF_minusone)=); # -1.0D0
- #else
- O(DF_zero) = allocate_dfloat(0,0); # 0.0D0
- # encode2_DF(0,1,bit(DF_mant_len-32),0, O(DF_one)=); # 1.0D0
- # encode2_DF(-1,1,bit(DF_mant_len-32),0, O(DF_minusone)=); # -1.0D0
- #endif
- # variable Long-Floats:
- encode_LF(0,2,&pi_mantisse[0],2048/intDsize, O(LF_pi)=); # pi auf 2048 Bits
- encode_LF(0,0,&ln2_mantisse[0],64/intDsize, O(LF_ln2)=); # ln(2) auf 64 Bits
- encode_LF(0,2,&ln10_mantisse[0],64/intDsize, O(LF_ln10)=); # ln(10) auf 64 Bits
- # Defaultlänge von Long-Floats so klein wie möglich:
- set_lf_digits(LF_minlen);
- # pi als Short-, Single-, Double-Float:
- O(SF_pi) = LF_to_SF(O(pi));
- O(FF_pi) = LF_to_FF(O(pi));
- O(DF_pi) = LF_to_DF(O(pi));
- # MOST-POSITIVE-FIXNUM, MOST-NEGATIVE-FIXNUM :
- define_constant(S(most_positive_fixnum),Fixnum_mpos);
- define_constant(S(most_negative_fixnum),Fixnum_mneg);
- # MOST/LEAST-POSITIVE/NEGATIVE-SHORT-FLOAT:
- define_constant(S(most_positive_short_float),make_SF(0,SF_exp_high,bit(SF_mant_len+1)-1));
- define_constant(S(least_positive_short_float),make_SF(0,SF_exp_low,bit(SF_mant_len)));
- define_constant(S(least_negative_short_float),make_SF(-1,SF_exp_low,bit(SF_mant_len)));
- define_constant(S(most_negative_short_float),make_SF(-1,SF_exp_high,bit(SF_mant_len+1)-1));
- # MOST/LEAST-POSITIVE/NEGATIVE-SINGLE-FLOAT:
- {var reg1 object obj; encode_FF(0,FF_exp_high-FF_exp_mid,bit(FF_mant_len+1)-1, obj=);
- define_constant(S(most_positive_single_float),obj); }
- {var reg1 object obj; encode_FF(0,FF_exp_low-FF_exp_mid,bit(FF_mant_len), obj=);
- define_constant(S(least_positive_single_float),obj); }
- {var reg1 object obj; encode_FF(-1,FF_exp_low-FF_exp_mid,bit(FF_mant_len), obj=);
- define_constant(S(least_negative_single_float),obj); }
- {var reg1 object obj; encode_FF(-1,FF_exp_high-FF_exp_mid,bit(FF_mant_len+1)-1, obj=);
- define_constant(S(most_negative_single_float),obj); }
- # MOST/LEAST-POSITIVE/NEGATIVE-DOUBLE-FLOAT:
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(0,DF_exp_high-DF_exp_mid,bit(DF_mant_len+1)-1, obj=);
- #else
- encode2_DF(0,DF_exp_high-DF_exp_mid,bit(DF_mant_len-32+1)-1,bitm(32)-1, obj=);
- #endif
- define_constant(S(most_positive_double_float),obj); }
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(0,DF_exp_low-DF_exp_mid,bit(DF_mant_len), obj=);
- #else
- encode2_DF(0,DF_exp_low-DF_exp_mid,bit(DF_mant_len-32),0, obj=);
- #endif
- define_constant(S(least_positive_double_float),obj); }
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(-1,DF_exp_low-DF_exp_mid,bit(DF_mant_len), obj=);
- #else
- encode2_DF(-1,DF_exp_low-DF_exp_mid,bit(DF_mant_len-32),0, obj=);
- #endif
- define_constant(S(least_negative_double_float),obj); }
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(-1,DF_exp_high-DF_exp_mid,bit(DF_mant_len+1)-1, obj=);
- #else
- encode2_DF(-1,DF_exp_high-DF_exp_mid,bit(DF_mant_len-32+1)-1,bitm(32)-1, obj=);
- #endif
- define_constant(S(most_negative_double_float),obj); }
- # Bei Floats mit d Bits (incl. Hiddem Bit, also d = ?F_mant_len+1)
- # ist ...-FLOAT-EPSILON = 2^-d*(1+2^(1-d))
- # und ...-FLOAT-NEGATIVE-EPSILON = 2^(-d-1)*(1+2^(1-d)) .
- define_constant(S(short_float_epsilon),make_SF(0,SF_exp_mid-SF_mant_len,bit(SF_mant_len)+1));
- define_constant(S(short_float_negative_epsilon),make_SF(0,SF_exp_mid-SF_mant_len-1,bit(SF_mant_len)+1));
- {var reg1 object obj; encode_FF(0,-FF_mant_len,bit(FF_mant_len)+1, obj=);
- define_constant(S(single_float_epsilon),obj); }
- {var reg1 object obj; encode_FF(0,-FF_mant_len-1,bit(FF_mant_len)+1, obj=);
- define_constant(S(single_float_negative_epsilon),obj); }
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(0,-DF_mant_len,bit(DF_mant_len)+1, obj=);
- #else
- encode2_DF(0,-DF_mant_len,bit(DF_mant_len-32),1, obj=);
- #endif
- define_constant(S(double_float_epsilon),obj); }
- {var reg1 object obj;
- #ifdef intQsize
- encode_DF(0,-DF_mant_len-1,bit(DF_mant_len)+1, obj=);
- #else
- encode2_DF(0,-DF_mant_len-1,bit(DF_mant_len-32),1, obj=);
- #endif
- define_constant(S(double_float_negative_epsilon),obj); }
- # weitere Variablen:
- define_variable(S(default_float_format),S(single_float)); # *DEFAULT-FLOAT-FORMAT* := 'SINGLE-FLOAT
- define_variable(S(read_default_float_format),S(single_float)); # *READ-DEFAULT-FLOAT-FORMAT* := 'SINGLE-FLOAT
- {var reg1 object obj = make_random_state(T); # neuer zufälliger Random-State
- define_variable(S(random_state_stern),obj); } # =: *RANDOM-STATE*
- }
-
-