home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / CLISP-1.LHA / CLISP960530-sr.lha / src / arilev1.d < prev    next >
Encoding:
Text File  |  1996-04-19  |  8.2 KB  |  268 lines

  1. # Arithmetik, Level 1
  2. # operiert auf Digit Sequences (DS) und Unsigned Digit Sequences (UDS).
  3.  
  4.  
  5. # Aus LISPBIBL.D importiere:
  6. # intDsize        Anzahl Bits in einem Digit
  7. # uintD, sintD    Integer-Typen für ein Digit
  8. # log2_intDsize   log2(intDsize)
  9. # HAVE_DD         Flag, das anzeigt, ob ein Integertyp für Doppel-Digits da ist
  10. # intDDsize       Anzahl Bits in einem Doppel-Digit
  11. # uintDD,sintDD   Integer-Typen für ein Doppel-Digit
  12.  
  13. #if !((32%intDsize)==0)
  14.   #error "intDsize sollte ein Teiler von 32 sein!"
  15. #endif
  16.  
  17.  
  18. # Vorzeichen eines Digit bestimmen
  19. # sign_of_sintD(wert)
  20. # > wert: ein Digit
  21. # < sintD ergebnis: 0 falls wert>=0, -1 falls wert<0.
  22.   global sint32 sign_of_sintD (sintD wert);
  23. #if (intDsize==8)
  24.   #define sign_of_sintD(x)  (sintD)(sign_of_sint16((sint16)(sint8)(x)))
  25. #endif
  26. #if (intDsize==16)
  27.   #define sign_of_sintD(x)  (sintD)(sign_of_sint16(x))
  28. #endif
  29. #if (intDsize==32)
  30.   #define sign_of_sintD(x)  (sintD)(sign_of_sint32(x))
  31. #endif
  32.  
  33. # High-Digit eines Doppel-Digit bestimmen
  34. # highD(wert)
  35. #if HAVE_DD
  36.   #if (!(intDsize==16))
  37.     #define highD(x)  ((uintD)((uintDD)(x)>>intDsize))
  38.   #else
  39.     #define highD  high16
  40.   #endif
  41. #endif
  42.  
  43. # Low-Digit eines Doppel-Digit bestimmen
  44. # lowD(wert)
  45. #if HAVE_DD
  46.   #define lowD(x)  ((uintD)(uintDD)(x))
  47. #endif
  48.  
  49. # Ein Doppel-Digit aus ihrem High-Digit und ihrem Low-Digit bestimmen:
  50. # highlowDD(uintD high, uintD low)
  51. #if HAVE_DD
  52.   #if (!(intDsize==16))
  53.     #define highlowDD(x,y)  (((uintDD)(uintD)(x)<<intDsize)|(uintDD)(uintD)(y))
  54.   #else
  55.     #define highlowDD  highlow32
  56.   #endif
  57. #endif
  58.  
  59. # Ein Doppel-Digit aus ihrem High-Digit und ihrem Low-Digit 0 bestimmen:
  60. # highlowDD_0(uintD high)
  61. #if HAVE_DD
  62.   #if (!(intDsize==16))
  63.     #define highlowDD_0(x)  ((uintDD)(uintD)(x)<<intDsize)
  64.   #else
  65.     #define highlowDD_0  highlow32_0
  66.   #endif
  67. #endif
  68.  
  69. # Zwei Digits multiplizieren:
  70. # (uintDD)hilo = muluD(uintD arg1, uintD arg2)
  71. # bzw.
  72. # muluD(uintD arg1, uintD arg2, uintD hi =, uintD lo =);
  73. #if HAVE_DD
  74.   #if (intDsize==8)
  75.     #ifdef GNU
  76.       #define muluD(arg1,arg2)  ((uintDD)((uintD)(arg1)*(uintD)(arg2)))
  77.     #else
  78.       #define muluD(arg1,arg2)  ((uintDD)(uintD)(arg1)*(uintDD)(uintD)(arg2))
  79.     #endif
  80.   #endif
  81.   #if (intDsize==16)
  82.     #define muluD  mulu16
  83.   #endif
  84.   #if (intDsize==32) && defined(HAVE_LONGLONG)
  85.     #define muluD(arg1,arg2)  ((uintDD)(uintD)(arg1)*(uintDD)(uintD)(arg2))
  86.   #endif
  87. #else
  88.   #if (intDsize==32)
  89.     #define muluD  mulu32
  90.   #endif
  91. #endif
  92.  
  93. # Zwei Digits multiplizieren, mit einem Digit als Ergebnis.
  94. # (uintD)lo = muluD_unchecked(uintD arg1, uintD arg2)
  95. # Es wird vorausgesetzt, daß arg1*arg2 < 2^intDsize.
  96.   #if (intDsize==8) || (intDsize==16)
  97.     #define muluD_unchecked(arg1,arg2)  ((uintD)((uintD)(arg1)*(uintD)(arg2)))
  98.   #endif
  99.   #if (intDsize==32)
  100.     #define muluD_unchecked(arg1,arg2)  mulu32_unchecked(arg1,arg2)
  101.   #endif
  102.  
  103. # Durch ein Digit dividieren:
  104. # divuD(uintDD x, uintD y, uintD q =, uintD r =);
  105. # bzw.
  106. # divuD(uintD xhi, uintD xlo, uintD y, uintD q =, uintD r =);
  107. # dividiert x/y und liefert q = floor(x/y) und r = (x mod y). x = q*y+r.
  108. # Es wird vorausgesetzt, daß 0 <= x < 2^intDsize*y.
  109. #if HAVE_DD
  110.   #if (intDsize==8)
  111.     #define divuD  divu_1616_1616
  112.   #endif
  113.   #if (intDsize==16)
  114.     #define divuD  divu_3216_1616
  115.   #endif
  116.   #if (intDsize==32) && defined(HAVE_LONGLONG)
  117.     #define divuD(x,y,q_zuweisung,r_zuweisung) \
  118.       { var reg1 uint64 __x = (x);                            \
  119.         var reg1 uint32 __y = (y);                            \
  120.         var reg1 uint32 __q = floor(__x,(uint64)__y);         \
  121.         q_zuweisung __q; r_zuweisung (uint32)__x - __q * __y; \
  122.       }
  123.   #endif
  124. #else
  125.   #if (intDsize==32)
  126.     #define divuD  divu_6432_3232
  127.   #endif
  128. #endif
  129.  
  130. # Durch ein Digit dividieren:
  131. # floorD(uintD x, uintD y)
  132. # dividiert x/y und liefert q = floor(x/y).
  133. # Es wird vorausgesetzt, daß y > 0.
  134.   #if (intDsize==8) || (intDsize==16)
  135.     #define floorD(arg1,arg2)  (floor((uintD)(arg1),(uintD)(arg2)))
  136.   #endif
  137.   #if (intDsize==32)
  138.     #define floorD  divu_3232_3232_
  139.   #endif
  140.  
  141. # Digit sequence (DS) - nur intern verwendet -
  142. # Zusammenhängender Speicherbereich mit n (ein uintC) Digits,
  143. # zwischen zwei Pointer MSDptr und LSDptr.
  144. #  MSDptr                  LSDptr
  145. # | MSD ............. LSW |
  146. # [abgekürzt: MSDptr/n/LSDptr ]
  147. # In 68000-Manier (vgl. ADDX, SUBX) ist das Most significant Digit an der
  148. # untersten Adresse, nämlich MSDptr. LSDptr = MSDptr + n zeigt hinter die DS.
  149. # Falls n = 0, wird die Zahl 0 dargestellt.
  150. # Falls n > 0, ist das höchstwertige Bit (nämlich  Bit (intDsize-1) von
  151. #              *MSDptr) das Vorzeichenbit. Schreibt man es noch unendlich
  152. #              oft an, so erhält man die "unendliche Bitfolge".
  153. # Normalisierte Digit sequence (NDS) ist eine solche, bei der das MSD nötig
  154. # ist, also n = 0 oder (n > 0 und nicht alle höchstwertigen intDsize+1 Bits
  155. # sind gleich).
  156. # In C:
  157. #   uintD* MSWptr und uintC len.
  158. #   MSWptr[0] ... MSWptr[(uintL)len-1] sind die Digits.
  159.  
  160. # Unsigned Digit sequence (UDS) - nur intern verwendet -
  161. # wie DS (MSD unten, LSD oben), nur ohne Vorzeichen.
  162. # Normalized Unsigned Digit sequence (NUDS):
  163. # wie UDS, nur ist entweder n=0 (Zahl 0) oder bei n>0 : *MSDptr >0.
  164. # (d.h. die Zahl >=0 kann nicht mit weniger Digits als UDS dargestellt werden).
  165. # In C:
  166. #   uintD* MSWptr und uintC len.
  167. #   MSWptr[0] ... MSWptr[(uintL)len-1] sind die Digits.
  168.  
  169. # Zur Konstruktion konstanter DS: D(byte0,byte1,byte2,byte3,dummy) liefert
  170. # die 32 Bits von {byte0,byte1,byte2,byte3} als 32/intDsize Digits.
  171.   #if (intDsize==8)
  172.     #define D(byte0,byte1,byte2,byte3,dummy)  byte0,byte1,byte2,byte3,
  173.   #endif
  174.   #if (intDsize==16)
  175.     #define D(byte0,byte1,byte2,byte3,dummy)  ((byte0<<8)|byte1),((byte2<<8)|byte3),
  176.   #endif
  177.   #if (intDsize==32)
  178.     #define D(byte0,byte1,byte2,byte3,dummy)  \
  179.       (((uintD)(byte0)<<24)|((uintD)(byte1)<<16)|((uintD)(byte2)<<8)|((uintD)(byte3))),
  180.   #endif
  181.  
  182. typedef struct { uintD* MSDptr; uintC len; uintD* LSDptr; } DS;
  183.  
  184.  
  185. # Es gibt für die innersten Schleifen vier Möglichkeiten:
  186. # LOOP_EXTERN_C     Alle Schleifen als externe C-compilierte Routinen.
  187. #                   Portabel, aber evtl. ineffizient.
  188. # LOOP_INLINE_C     Schleifen ohne Wert (mit GNU-Compiler: alle Schleifen)
  189. #                   als Macros.
  190. #                   Portabel, aber evtl. ineffizient.
  191. # LOOP_EXTERN_ASM   Alle Schleifen als externe Assembler-Routinen.
  192. #                   Effizienter, aber immer noch Function-Call-Overhead.
  193. # LOOP_INLINE_ASM   Schleifen ohne Wert (mit GNU-Compiler: alle Schleifen)
  194. #                   als macroexpandierte Assembler-Routinen inline.
  195. #                   Ganz effizient.
  196.  
  197. #if (defined(MC680X0) || defined(SPARC) || (defined(I80Z86) && !defined(WATCOM)) || defined(MIPS) || defined(VAX) || defined(ARM)) && (SAFETY < 3)
  198.   # diese Assembler beherrsche ich
  199.   #if (defined(GNU) && defined(WANT_LOOP_INLINE))
  200.     # der GNU-Compiler kann Inline-Assembler
  201.     #define LOOP_INLINE_ASM
  202.   #else
  203.     # sonst mit externen Routinen arbeiten
  204.     #define LOOP_EXTERN_ASM
  205.   #endif
  206. #else
  207.   # sonst die portable Lösung
  208.   #if (defined(DECALPHA) && defined(GNU) && (intDsize==32) && defined(HAVE_DD))
  209.     # GCC-2.7.2-Bug umgehen
  210.     #define LOOP_EXTERN_C
  211.   #else
  212.     #define LOOP_INLINE_C
  213.   #endif
  214. #endif
  215.  
  216.  
  217. #ifdef LOOP_EXTERN_C
  218.   # Die Definitionen samt portablem C-Code:
  219.   #include "arilev1c.c"
  220. #endif
  221.  
  222. # Die Inline-Macros
  223. #ifdef LOOP_INLINE_ASM
  224.   # sind momentan nicht implementiert
  225.   #define LOOP_EXTERN_ASM  # stattdessen extern in Assembler
  226. #endif
  227.  
  228. #ifdef LOOP_EXTERN_ASM
  229.   # Die Assembler-Definitionen:
  230.     #define INCLUDED_FROM_C
  231.     #if defined(MC680X0) && !defined(UNIX_LINUX)
  232.       # Scott Kolodzieski <scott@dmi.stevens-tech.edu> says this doesn't work
  233.       # on Linux/68k.
  234.       #if !defined(MC680Y0)
  235.         #include "ari68000.c"
  236.       #else
  237.         #include "ari68020.c"
  238.       #endif
  239.     #endif
  240.     #if defined(SPARC)
  241.       #include "arisparc.c"
  242.     #endif
  243.     #if defined(I80Z86)
  244.       #include "ari80386.c"
  245.     #endif
  246.     #if defined(MIPS)
  247.       #include "arimips.c"
  248.     #endif
  249.     #if defined(VAX)
  250.       #include "arivaxunix.c"
  251.     #endif
  252.     #if defined(ARM)
  253.       #include "ariarm.c"
  254.     #endif
  255.     #undef INCLUDED_FROM_C
  256.   # Die Extern-Deklarationen:
  257.     #include "arilev1e.c"
  258.   # Die nicht in Assembler geschriebenen Teile nehmen wir vom portablen C-Code:
  259.     #define LOOP_INLINE_C
  260. #endif
  261.  
  262. #ifdef LOOP_INLINE_C
  263.   # Die Definitionen samt portablem C-Code und
  264.   # - für den GNU-Compiler - Inline-Deklarationen:
  265.   #include "arilev1i.c"
  266. #endif
  267.  
  268.