Out.ob07 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. (*
  2. Copyright 2016, 2018 Anton Krotov
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. *)
  14. MODULE Out;
  15. IMPORT ConsoleLib, sys := SYSTEM;
  16. CONST
  17. d = 1.0 - 5.0E-12;
  18. VAR
  19. Realp: PROCEDURE (x: REAL; width: INTEGER);
  20. PROCEDURE Char*(c: CHAR);
  21. BEGIN
  22. ConsoleLib.write_string(sys.ADR(c), 1)
  23. END Char;
  24. PROCEDURE String*(s: ARRAY OF CHAR);
  25. BEGIN
  26. ConsoleLib.write_string(sys.ADR(s[0]), LENGTH(s))
  27. END String;
  28. PROCEDURE WriteInt(x, n: INTEGER);
  29. VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN;
  30. BEGIN
  31. i := 0;
  32. IF n < 1 THEN
  33. n := 1
  34. END;
  35. IF x < 0 THEN
  36. x := -x;
  37. DEC(n);
  38. neg := TRUE
  39. END;
  40. REPEAT
  41. a[i] := CHR(x MOD 10 + ORD("0"));
  42. x := x DIV 10;
  43. INC(i)
  44. UNTIL x = 0;
  45. WHILE n > i DO
  46. Char(" ");
  47. DEC(n)
  48. END;
  49. IF neg THEN
  50. Char("-")
  51. END;
  52. REPEAT
  53. DEC(i);
  54. Char(a[i])
  55. UNTIL i = 0
  56. END WriteInt;
  57. PROCEDURE IsNan(AValue: REAL): BOOLEAN;
  58. VAR h, l: SET;
  59. BEGIN
  60. sys.GET(sys.ADR(AValue), l);
  61. sys.GET(sys.ADR(AValue) + 4, h)
  62. RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {}))
  63. END IsNan;
  64. PROCEDURE IsInf(x: REAL): BOOLEAN;
  65. RETURN ABS(x) = sys.INF()
  66. END IsInf;
  67. PROCEDURE Int*(x, width: INTEGER);
  68. VAR i: INTEGER;
  69. BEGIN
  70. IF x # 80000000H THEN
  71. WriteInt(x, width)
  72. ELSE
  73. FOR i := 12 TO width DO
  74. Char(20X)
  75. END;
  76. String("-2147483648")
  77. END
  78. END Int;
  79. PROCEDURE OutInf(x: REAL; width: INTEGER);
  80. VAR s: ARRAY 5 OF CHAR; i: INTEGER;
  81. BEGIN
  82. IF IsNan(x) THEN
  83. s := "Nan";
  84. INC(width)
  85. ELSIF IsInf(x) & (x > 0.0) THEN
  86. s := "+Inf"
  87. ELSIF IsInf(x) & (x < 0.0) THEN
  88. s := "-Inf"
  89. END;
  90. FOR i := 1 TO width - 4 DO
  91. Char(" ")
  92. END;
  93. String(s)
  94. END OutInf;
  95. PROCEDURE Ln*;
  96. BEGIN
  97. Char(0DX);
  98. Char(0AX)
  99. END Ln;
  100. PROCEDURE _FixReal(x: REAL; width, p: INTEGER);
  101. VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN;
  102. BEGIN
  103. IF IsNan(x) OR IsInf(x) THEN
  104. OutInf(x, width)
  105. ELSIF p < 0 THEN
  106. Realp(x, width)
  107. ELSE
  108. len := 0;
  109. minus := FALSE;
  110. IF x < 0.0 THEN
  111. minus := TRUE;
  112. INC(len);
  113. x := ABS(x)
  114. END;
  115. e := 0;
  116. WHILE x >= 10.0 DO
  117. x := x / 10.0;
  118. INC(e)
  119. END;
  120. IF e >= 0 THEN
  121. len := len + e + p + 1;
  122. IF x > 9.0 + d THEN
  123. INC(len)
  124. END;
  125. IF p > 0 THEN
  126. INC(len)
  127. END
  128. ELSE
  129. len := len + p + 2
  130. END;
  131. FOR i := 1 TO width - len DO
  132. Char(" ")
  133. END;
  134. IF minus THEN
  135. Char("-")
  136. END;
  137. y := x;
  138. WHILE (y < 1.0) & (y # 0.0) DO
  139. y := y * 10.0;
  140. DEC(e)
  141. END;
  142. IF e < 0 THEN
  143. IF x - FLT(FLOOR(x)) > d THEN
  144. Char("1");
  145. x := 0.0
  146. ELSE
  147. Char("0");
  148. x := x * 10.0
  149. END
  150. ELSE
  151. WHILE e >= 0 DO
  152. IF x - FLT(FLOOR(x)) > d THEN
  153. IF x > 9.0 THEN
  154. String("10")
  155. ELSE
  156. Char(CHR(FLOOR(x) + ORD("0") + 1))
  157. END;
  158. x := 0.0
  159. ELSE
  160. Char(CHR(FLOOR(x) + ORD("0")));
  161. x := (x - FLT(FLOOR(x))) * 10.0
  162. END;
  163. DEC(e)
  164. END
  165. END;
  166. IF p > 0 THEN
  167. Char(".")
  168. END;
  169. WHILE p > 0 DO
  170. IF x - FLT(FLOOR(x)) > d THEN
  171. Char(CHR(FLOOR(x) + ORD("0") + 1));
  172. x := 0.0
  173. ELSE
  174. Char(CHR(FLOOR(x) + ORD("0")));
  175. x := (x - FLT(FLOOR(x))) * 10.0
  176. END;
  177. DEC(p)
  178. END
  179. END
  180. END _FixReal;
  181. PROCEDURE Real*(x: REAL; width: INTEGER);
  182. VAR e, n, i: INTEGER; minus: BOOLEAN;
  183. BEGIN
  184. IF IsNan(x) OR IsInf(x) THEN
  185. OutInf(x, width)
  186. ELSE
  187. e := 0;
  188. n := 0;
  189. IF width > 23 THEN
  190. n := width - 23;
  191. width := 23
  192. ELSIF width < 9 THEN
  193. width := 9
  194. END;
  195. width := width - 5;
  196. IF x < 0.0 THEN
  197. x := -x;
  198. minus := TRUE
  199. ELSE
  200. minus := FALSE
  201. END;
  202. WHILE x >= 10.0 DO
  203. x := x / 10.0;
  204. INC(e)
  205. END;
  206. WHILE (x < 1.0) & (x # 0.0) DO
  207. x := x * 10.0;
  208. DEC(e)
  209. END;
  210. IF x > 9.0 + d THEN
  211. x := 1.0;
  212. INC(e)
  213. END;
  214. FOR i := 1 TO n DO
  215. Char(" ")
  216. END;
  217. IF minus THEN
  218. x := -x
  219. END;
  220. Realp := Real;
  221. _FixReal(x, width, width - 3);
  222. Char("E");
  223. IF e >= 0 THEN
  224. Char("+")
  225. ELSE
  226. Char("-");
  227. e := ABS(e)
  228. END;
  229. IF e < 100 THEN
  230. Char("0")
  231. END;
  232. IF e < 10 THEN
  233. Char("0")
  234. END;
  235. Int(e, 0)
  236. END
  237. END Real;
  238. PROCEDURE FixReal*(x: REAL; width, p: INTEGER);
  239. BEGIN
  240. Realp := Real;
  241. _FixReal(x, width, p)
  242. END FixReal;
  243. PROCEDURE Open*;
  244. END Open;
  245. END Out.