ARM.Reals.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
  2. Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
  3. MODULE Reals; (** portable, except where noted *)
  4. (** AUTHOR "bmoesli"; PURPOSE "Real number manipulation"; *)
  5. (** Implementation of the non-portable components of IEEE REAL and
  6. LONGREAL manipulation. The routines here are required to do conversion
  7. of reals to strings and back.
  8. Implemented by Bernd Moesli, Seminar for Applied Mathematics,
  9. Swiss Federal Institute of Technology Zürich.
  10. *)
  11. (** Simple port to ARM, without platform-dependent code by Timothée Martiel *)
  12. IMPORT SYSTEM, Machine;
  13. (* Bernd Moesli
  14. Seminar for Applied Mathematics
  15. Swiss Federal Institute of Technology Zurich
  16. Copyright 1993
  17. Support module for IEEE floating-point numbers
  18. Please change constant definitions of H, L depending on byte ordering
  19. Use bm.TestReals.Do for testing the implementation.
  20. Expo, ExpoL return the shifted binary exponent (0 <= e < 256 (2048 resp.))
  21. SetExpo, SetExpoL set the shifted binary exponent
  22. Real, RealL convert hexadecimals to reals
  23. Int, IntL convert reals to hexadecimals
  24. Ten returns 10^e (e <= 308, 308 < e delivers NaN)
  25. 1993.4.22 IEEE format only, 32-bits LONGINTs only
  26. 30.8.1993 mh: changed RealX to avoid compiler warnings;
  27. 7.11.1995 jt: dynamic endianess test
  28. 22.01.97 pjm: NaN stuff (using quiet NaNs only to avoid traps)
  29. 05.01.98 prk: NaN with INF support
  30. *)
  31. VAR
  32. DefaultFCR*: SET;
  33. tene: ARRAY 23 OF LONGREAL; (* e = 0..22: exact values of 10^e *)
  34. ten: ARRAY 27 OF LONGREAL;
  35. eq, gr: ARRAY 20 OF SET;
  36. H, L: INTEGER;
  37. (** Returns the shifted binary exponent (0 <= e < 256). *)
  38. PROCEDURE Expo* (x: REAL): LONGINT;
  39. BEGIN
  40. RETURN ASH(SYSTEM.VAL(LONGINT, x), -23) MOD 256
  41. END Expo;
  42. (** Returns the shifted binary exponent (0 <= e < 2048). *)
  43. PROCEDURE ExpoL* (x: LONGREAL): LONGINT;
  44. VAR i: LONGINT;
  45. BEGIN
  46. SYSTEM.GET(ADDRESSOF(x) + H, i); RETURN ASH(i, -20) MOD 2048
  47. END ExpoL;
  48. (** Sets the shifted binary exponent. *)
  49. PROCEDURE SetExpo* (e: LONGINT; VAR x: REAL);
  50. VAR i: LONGINT;
  51. BEGIN
  52. SYSTEM.GET(ADDRESSOF(x), i);
  53. i:= ASH(ASH(ASH(i, -31), 8) + e MOD 256, 23) + i MOD ASH(1, 23);
  54. SYSTEM.PUT(ADDRESSOF(x), i)
  55. END SetExpo;
  56. (** Sets the shifted binary exponent. *)
  57. PROCEDURE SetExpoL* (e: LONGINT; VAR x: LONGREAL);
  58. VAR i: LONGINT;
  59. BEGIN
  60. SYSTEM.GET(ADDRESSOF(x) + H, i);
  61. i:= ASH(ASH(ASH(i, -31), 11) + e MOD 2048, 20) + i MOD ASH(1, 20);
  62. SYSTEM.PUT(ADDRESSOF(x) + H, i)
  63. END SetExpoL;
  64. (** Convert hexadecimal to REAL. *)
  65. PROCEDURE Real* (h: LONGINT): REAL;
  66. VAR x: REAL;
  67. BEGIN SYSTEM.PUT(ADDRESSOF(x), h); RETURN x
  68. END Real;
  69. (** Convert hexadecimal to LONGREAL. h and l are the high and low parts.*)
  70. PROCEDURE RealL* (h, l: LONGINT): LONGREAL;
  71. VAR x: LONGREAL;
  72. BEGIN SYSTEM.PUT(ADDRESSOF(x) + H, h); SYSTEM.PUT(ADDRESSOF(x) + L, l); RETURN x
  73. END RealL;
  74. (** Convert REAL to hexadecimal. *)
  75. PROCEDURE Int* (x: REAL): LONGINT;
  76. VAR i: LONGINT;
  77. BEGIN SYSTEM.PUT(ADDRESSOF(i), x); RETURN i
  78. END Int;
  79. (** Convert LONGREAL to hexadecimal. h and l are the high and low parts. *)
  80. PROCEDURE IntL* (x: LONGREAL; VAR h, l: LONGINT);
  81. BEGIN SYSTEM.GET(ADDRESSOF(x) + H, h); SYSTEM.GET(ADDRESSOF(x) + L, l)
  82. END IntL;
  83. (** Returns 10^e (e <= 308, 308 < e delivers IEEE-code +INF). *)
  84. PROCEDURE Ten* (e: LONGINT): LONGREAL;
  85. VAR E: LONGINT; r: LONGREAL;
  86. BEGIN
  87. IF e < -307 THEN RETURN 0 ELSIF 308 < e THEN RETURN RealL(2146435072, 0) END;
  88. INC(e, 307); r:= ten[e DIV 23] * tene[e MOD 23];
  89. IF e MOD 32 IN eq[e DIV 32] THEN RETURN r
  90. ELSE
  91. E:= ExpoL(r); SetExpoL(1023+52, r);
  92. IF e MOD 32 IN gr[e DIV 32] THEN r:= r-1 ELSE r:= r+1 END;
  93. SetExpoL(E, r); RETURN r
  94. END
  95. END Ten;
  96. (** Returns the NaN code (0 <= c < 8399608) or -1 if not NaN/Infinite. *)
  97. PROCEDURE NaNCode* (x: REAL): LONGINT;
  98. BEGIN
  99. IF ASH(SYSTEM.VAL(LONGINT, x), -23) MOD 256 = 255 THEN (* Infinite or NaN *)
  100. RETURN SYSTEM.VAL(LONGINT, x) MOD 800000H (* lowest 23 bits *)
  101. ELSE
  102. RETURN -1
  103. END
  104. END NaNCode;
  105. (** Returns the NaN code (0 <= h < 1048576, MIN(LONGINT) <= l <= MAX(LONGINT)) or (-1,-1) if not NaN/Infinite. *)
  106. PROCEDURE NaNCodeL* (x: LONGREAL; VAR h, l: LONGINT);
  107. BEGIN
  108. SYSTEM.GET(ADDRESSOF(x) + H, h); SYSTEM.GET(ADDRESSOF(x) + L, l);
  109. IF ASH(h, -20) MOD 2048 = 2047 THEN (* Infinite or NaN *)
  110. h := h MOD 100000H (* lowest 20 bits *)
  111. ELSE
  112. h := -1; l := -1
  113. END
  114. END NaNCodeL;
  115. (** Returns TRUE iff x is NaN/Infinite. *)
  116. PROCEDURE IsNaN* (x: REAL): BOOLEAN;
  117. BEGIN
  118. RETURN ASH(SYSTEM.VAL(LONGINT, x), -23) MOD 256 = 255
  119. END IsNaN;
  120. (** Returns TRUE iff x is NaN/Infinite. *)
  121. PROCEDURE IsNaNL* (x: LONGREAL): BOOLEAN;
  122. VAR h: LONGINT;
  123. BEGIN
  124. SYSTEM.GET(ADDRESSOF(x) + H, h);
  125. RETURN ASH(h, -20) MOD 2048 = 2047
  126. END IsNaNL;
  127. (** Returns NaN with specified code (0 <= l < 8399608). *)
  128. PROCEDURE NaN* (l: LONGINT): REAL;
  129. VAR x: REAL;
  130. BEGIN
  131. SYSTEM.PUT(ADDRESSOF(x), (l MOD 800000H) + 7F800000H);
  132. RETURN x
  133. END NaN;
  134. (** Returns NaN with specified code (0 <= h < 1048576, MIN(LONGINT) <= l <= MAX(LONGINT)). *)
  135. PROCEDURE NaNL* (h, l: LONGINT): LONGREAL;
  136. VAR x: LONGREAL;
  137. BEGIN
  138. h := (h MOD 100000H) + 7FF00000H;
  139. SYSTEM.PUT(ADDRESSOF(x) + H, h);
  140. SYSTEM.PUT(ADDRESSOF(x) + L, l);
  141. RETURN x
  142. END NaNL;
  143. (*
  144. PROCEDURE fcr(): SET;
  145. CODE {SYSTEM.i386, SYSTEM.FPU}
  146. PUSH 0
  147. FSTCW [ESP]
  148. FWAIT
  149. POP EAX
  150. END fcr;
  151. *)
  152. (** Return state of the floating-point control register. *)
  153. PROCEDURE FCR*(): SET;
  154. END FCR;
  155. (** Set state of floating-point control register. Traps reset this to the default. Note that changing the rounding mode affects rounding of imprecise results as well as the ENTIER operation. *)
  156. PROCEDURE SetFCR*(s: SET);
  157. END SetFCR;
  158. (** Round x to an integer using the current rounding mode. *)
  159. PROCEDURE Round*(x: REAL): LONGINT; (** non-portable *)
  160. END Round;
  161. (** Round x to an integer using the current rounding mode. *)
  162. PROCEDURE RoundL*(x: LONGREAL): LONGINT; (** non-portable *)
  163. END RoundL;
  164. PROCEDURE RealX (hh, hl: HUGEINT; adr: ADDRESS);
  165. VAR h,l: LONGINT;
  166. BEGIN
  167. h := SHORT(hh); l := SHORT(hl);
  168. SYSTEM.PUT(adr + H, h); SYSTEM.PUT(adr + L, l);
  169. END RealX;
  170. PROCEDURE InitHL;
  171. VAR i: ADDRESS; dmy: INTEGER; littleEndian: BOOLEAN;
  172. BEGIN
  173. DefaultFCR := Machine.fcr;
  174. dmy := 1; i := ADDRESSOF(dmy);
  175. SYSTEM.GET(i, littleEndian); (* indirection via i avoids warning on SUN cc -O *)
  176. IF littleEndian THEN H := 4; L := 0 ELSE H := 0; L := 4 END
  177. END InitHL;
  178. BEGIN InitHL;
  179. RealX(03FF00000H, 0, ADDRESSOF(tene[0]));
  180. RealX(040240000H, 0, ADDRESSOF(tene[1])); (* 1 *)
  181. RealX(040590000H, 0, ADDRESSOF(tene[2])); (* 2 *)
  182. RealX(0408F4000H, 0, ADDRESSOF(tene[3])); (* 3 *)
  183. RealX(040C38800H, 0, ADDRESSOF(tene[4])); (* 4 *)
  184. RealX(040F86A00H, 0, ADDRESSOF(tene[5])); (* 5 *)
  185. RealX(0412E8480H, 0, ADDRESSOF(tene[6])); (* 6 *)
  186. RealX(0416312D0H, 0, ADDRESSOF(tene[7])); (* 7 *)
  187. RealX(04197D784H, 0, ADDRESSOF(tene[8])); (* 8 *)
  188. RealX(041CDCD65H, 0, ADDRESSOF(tene[9])); (* 9 *)
  189. RealX(04202A05FH, 020000000H, ADDRESSOF(tene[10])); (* 10 *)
  190. RealX(042374876H, 0E8000000H, ADDRESSOF(tene[11])); (* 11 *)
  191. RealX(0426D1A94H, 0A2000000H, ADDRESSOF(tene[12])); (* 12 *)
  192. RealX(042A2309CH, 0E5400000H, ADDRESSOF(tene[13])); (* 13 *)
  193. RealX(042D6BCC4H, 01E900000H, ADDRESSOF(tene[14])); (* 14 *)
  194. RealX(0430C6BF5H, 026340000H, ADDRESSOF(tene[15])); (* 15 *)
  195. RealX(04341C379H, 037E08000H, ADDRESSOF(tene[16])); (* 16 *)
  196. RealX(043763457H, 085D8A000H, ADDRESSOF(tene[17])); (* 17 *)
  197. RealX(043ABC16DH, 0674EC800H, ADDRESSOF(tene[18])); (* 18 *)
  198. RealX(043E158E4H, 060913D00H, ADDRESSOF(tene[19])); (* 19 *)
  199. RealX(04415AF1DH, 078B58C40H, ADDRESSOF(tene[20])); (* 20 *)
  200. RealX(0444B1AE4H, 0D6E2EF50H, ADDRESSOF(tene[21])); (* 21 *)
  201. RealX(04480F0CFH, 064DD592H, ADDRESSOF(tene[22])); (* 22 *)
  202. RealX(031FA18H, 02C40C60DH, ADDRESSOF(ten[0])); (* -307 *)
  203. RealX(04F7CAD2H, 03DE82D7BH, ADDRESSOF(ten[1])); (* -284 *)
  204. RealX(09BF7D22H, 08322BAF5H, ADDRESSOF(ten[2])); (* -261 *)
  205. RealX(0E84D669H, 05B193BF8H, ADDRESSOF(ten[3])); (* -238 *)
  206. RealX(0134B9408H, 0EEFEA839H, ADDRESSOF(ten[4])); (* -215 *)
  207. RealX(018123FF0H, 06EEA847AH, ADDRESSOF(ten[5])); (* -192 *)
  208. RealX(01CD82742H, 091C6065BH, ADDRESSOF(ten[6])); (* -169 *)
  209. RealX(0219FF779H, 0FD329CB9H, ADDRESSOF(ten[7])); (* -146 *)
  210. RealX(02665275EH, 0D8D8F36CH, ADDRESSOF(ten[8])); (* -123 *)
  211. RealX(02B2BFF2EH, 0E48E0530H, ADDRESSOF(ten[9])); (* -100 *)
  212. RealX(02FF286D8H, 0EC190DCH, ADDRESSOF(ten[10])); (* -77 *)
  213. RealX(034B8851AH, 0B548EA4H, ADDRESSOF(ten[11])); (* -54 *)
  214. RealX(0398039D6H, 065896880H, ADDRESSOF(ten[12])); (* -31 *)
  215. RealX(03E45798EH, 0E2308C3AH, ADDRESSOF(ten[13])); (* -8 *)
  216. RealX(0430C6BF5H, 026340000H, ADDRESSOF(ten[14])); (* 15 *)
  217. RealX(047D2CED3H, 02A16A1B1H, ADDRESSOF(ten[15])); (* 38 *)
  218. RealX(04C98E45EH, 01DF3B015H, ADDRESSOF(ten[16])); (* 61 *)
  219. RealX(0516078E1H, 011C3556DH, ADDRESSOF(ten[17])); (* 84 *)
  220. RealX(05625CCFEH, 03D35D80EH, ADDRESSOF(ten[18])); (* 107 *)
  221. RealX(05AECDA62H, 055B2D9EH, ADDRESSOF(ten[19])); (* 130 *)
  222. RealX(05FB317E5H, 0EF3AB327H, ADDRESSOF(ten[20])); (* 153 *)
  223. RealX(064794514H, 05230B378H, ADDRESSOF(ten[21])); (* 176 *)
  224. RealX(06940B8E0H, 0ACAC4EAFH, ADDRESSOF(ten[22])); (* 199 *)
  225. RealX(06E0621B1H, 0C28AC20CH, ADDRESSOF(ten[23])); (* 222 *)
  226. RealX(072CD4A7BH, 0EBFA31ABH, ADDRESSOF(ten[24])); (* 245 *)
  227. RealX(077936214H, 09CBD3226H, ADDRESSOF(ten[25])); (* 268 *)
  228. RealX(07C59A742H, 0461887F6H, ADDRESSOF(ten[26])); (* 291 *)
  229. eq[0]:= {0, 3, 4, 5, 9, 16, 23, 25, 26, 28, 31};
  230. eq[1]:= {2, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 31};
  231. eq[2]:= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28};
  232. eq[3]:= {0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 14, 15, 16, 17, 18, 19, 20, 22, 27, 28, 29, 30, 31};
  233. eq[4]:= {0, 6, 7, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
  234. eq[5]:= {0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
  235. eq[6]:= {0, 1, 4, 5, 7, 8, 10, 14, 15, 16, 18, 20, 21, 23, 24, 25, 26, 28, 29, 30, 31};
  236. eq[7]:= {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 23, 24, 26, 28, 29, 30, 31};
  237. eq[8]:= {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 16, 17, 18, 19, 20, 21, 24, 25, 26, 29};
  238. eq[9]:= {1, 2, 4, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
  239. eq[10]:= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
  240. eq[11]:= {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 27, 28, 29, 30};
  241. eq[12]:= {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30, 31};
  242. eq[13]:= {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 27, 28, 29, 30, 31};
  243. eq[14]:= {0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
  244. eq[15]:= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28};
  245. eq[16]:= {1, 2, 4, 11, 13, 16, 17, 18, 19, 22, 24, 25, 26, 27, 28, 29, 30, 31};
  246. eq[17]:= {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 15, 18, 19, 20, 21, 23, 25, 26, 27, 28, 29, 31};
  247. eq[18]:= {0, 2, 4, 5, 6, 8, 9, 11, 12, 13, 14, 16, 17, 19, 20, 22, 23, 24, 26, 27, 28, 29};
  248. eq[19]:= {2, 3, 4, 5, 6, 7};
  249. gr[0]:= {24, 27, 29, 30};
  250. gr[1]:= {0, 1, 3, 4, 7};
  251. gr[2]:= {29, 30, 31};
  252. gr[3]:= {4, 10, 12, 13, 21, 23, 24, 25, 26};
  253. gr[4]:= {1, 2, 3, 4, 5, 8, 9, 16, 17};
  254. gr[5]:= {2, 3, 4, 18};
  255. gr[6]:= {2, 3, 6, 9, 11, 12, 13, 17, 19, 22, 27};
  256. gr[7]:= {2};
  257. gr[8]:= {7, 12, 13, 15, 22, 23, 27, 28, 30, 31};
  258. gr[9]:= {0, 3, 5, 7, 8};
  259. gr[10]:= {};
  260. gr[11]:= {};
  261. gr[12]:= {11, 13, 22, 24, 25, 28};
  262. gr[13]:= {22, 25, 26};
  263. gr[14]:= {4, 5};
  264. gr[15]:= {10, 14, 27, 29, 30, 31};
  265. gr[16]:= {0, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 20, 21, 23};
  266. gr[17]:= {0, 10, 12, 13, 16, 17, 22, 24, 30};
  267. gr[18]:= {};
  268. gr[19]:= {}
  269. END Reals.