ARITH.ob07 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2022, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE ARITH;
  7. IMPORT STRINGS, UTILS, LISTS;
  8. CONST
  9. tINTEGER* = 1; tREAL* = 2; tSET* = 3;
  10. tBOOLEAN* = 4; tCHAR* = 5; tWCHAR* = 6;
  11. tSTRING* = 7;
  12. opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5;
  13. opIN* = 6; opIS* = 7;
  14. TYPE
  15. VALUE* = RECORD
  16. typ*: INTEGER;
  17. int: INTEGER;
  18. float: REAL;
  19. set: SET;
  20. bool: BOOLEAN;
  21. string*: LISTS.ITEM
  22. END;
  23. VAR
  24. digit: ARRAY 256 OF INTEGER;
  25. PROCEDURE Int* (v: VALUE): INTEGER;
  26. VAR
  27. res: INTEGER;
  28. BEGIN
  29. CASE v.typ OF
  30. |tINTEGER, tCHAR, tWCHAR:
  31. res := v.int
  32. |tSET:
  33. res := UTILS.Long(ORD(v.set))
  34. |tBOOLEAN:
  35. res := ORD(v.bool)
  36. END
  37. RETURN res
  38. END Int;
  39. PROCEDURE getBool* (v: VALUE): BOOLEAN;
  40. BEGIN
  41. ASSERT(v.typ = tBOOLEAN);
  42. RETURN v.bool
  43. END getBool;
  44. PROCEDURE Float* (v: VALUE): REAL;
  45. BEGIN
  46. ASSERT(v.typ = tREAL);
  47. RETURN v.float
  48. END Float;
  49. PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
  50. RETURN (a <= i.int) & (i.int <= b)
  51. END range;
  52. PROCEDURE check* (v: VALUE): BOOLEAN;
  53. VAR
  54. res: BOOLEAN;
  55. BEGIN
  56. CASE v.typ OF
  57. |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt)
  58. |tCHAR: res := range(v, 0, 255)
  59. |tWCHAR: res := range(v, 0, 65535)
  60. |tREAL: res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
  61. END
  62. RETURN res
  63. END check;
  64. PROCEDURE isZero* (v: VALUE): BOOLEAN;
  65. VAR
  66. res: BOOLEAN;
  67. BEGIN
  68. CASE v.typ OF
  69. |tINTEGER: res := v.int = 0
  70. |tREAL: res := v.float = 0.0
  71. END
  72. RETURN res
  73. END isZero;
  74. PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  75. VAR
  76. value: INTEGER;
  77. i: INTEGER;
  78. d: INTEGER;
  79. BEGIN
  80. error := 0;
  81. value := 0;
  82. i := 0;
  83. WHILE STRINGS.digit(s[i]) & (error = 0) DO
  84. d := digit[ORD(s[i])];
  85. IF value <= (UTILS.maxint - d) DIV 10 THEN
  86. value := value * 10 + d;
  87. INC(i)
  88. ELSE
  89. error := 1
  90. END
  91. END;
  92. IF error = 0 THEN
  93. v.int := value;
  94. v.typ := tINTEGER;
  95. IF ~check(v) THEN
  96. error := 1
  97. END
  98. END
  99. END iconv;
  100. PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  101. VAR
  102. value: INTEGER;
  103. i: INTEGER;
  104. n: INTEGER;
  105. d: INTEGER;
  106. BEGIN
  107. ASSERT(STRINGS.digit(s[0]));
  108. error := 0;
  109. value := 0;
  110. n := -1;
  111. i := 0;
  112. WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO
  113. d := digit[ORD(s[i])];
  114. IF (n = -1) & (d # 0) THEN
  115. n := i
  116. END;
  117. IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
  118. error := 2
  119. ELSE
  120. value := value * 16 + d;
  121. INC(i)
  122. END
  123. END;
  124. value := UTILS.Long(value);
  125. IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN
  126. error := 3
  127. END;
  128. IF error = 0 THEN
  129. v.int := value;
  130. IF (s[i] = "X") OR (s[i] = "x") THEN
  131. v.typ := tCHAR;
  132. IF ~check(v) THEN
  133. v.typ := tWCHAR;
  134. IF ~check(v) THEN
  135. error := 3
  136. END
  137. END
  138. ELSE
  139. v.typ := tINTEGER;
  140. IF ~check(v) THEN
  141. error := 2
  142. END
  143. END
  144. END
  145. END hconv;
  146. PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN;
  147. BEGIN
  148. CASE op OF
  149. |"+": a := a + b
  150. |"-": a := a - b
  151. |"*": a := a * b
  152. |"/": a := a / b
  153. END
  154. RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
  155. END opFloat2;
  156. PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  157. VAR
  158. value: REAL;
  159. exp10: REAL;
  160. i, n, d: INTEGER;
  161. minus: BOOLEAN;
  162. BEGIN
  163. error := 0;
  164. value := 0.0;
  165. minus := FALSE;
  166. n := 0;
  167. exp10 := 0.0;
  168. WHILE (error = 0) & (STRINGS.digit(s[i]) OR (s[i] = ".")) DO
  169. IF s[i] = "." THEN
  170. exp10 := 1.0;
  171. INC(i)
  172. ELSE
  173. IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") & opFloat2(exp10, 10.0, "*") THEN
  174. INC(i)
  175. ELSE
  176. error := 4
  177. END
  178. END
  179. END;
  180. IF ~opFloat2(value, exp10, "/") THEN
  181. error := 4
  182. END;
  183. IF (s[i] = "E") OR (s[i] = "e") THEN
  184. INC(i)
  185. END;
  186. IF (s[i] = "-") OR (s[i] = "+") THEN
  187. minus := s[i] = "-";
  188. INC(i)
  189. END;
  190. WHILE (error = 0) & STRINGS.digit(s[i]) DO
  191. d := digit[ORD(s[i])];
  192. IF n <= (UTILS.maxint - d) DIV 10 THEN
  193. n := n * 10 + d;
  194. INC(i)
  195. ELSE
  196. error := 5
  197. END
  198. END;
  199. exp10 := 1.0;
  200. WHILE (error = 0) & (n > 0) DO
  201. IF opFloat2(exp10, 10.0, "*") THEN
  202. DEC(n)
  203. ELSE
  204. error := 4
  205. END
  206. END;
  207. IF error = 0 THEN
  208. IF minus THEN
  209. IF ~opFloat2(value, exp10, "/") THEN
  210. error := 4
  211. END
  212. ELSE
  213. IF ~opFloat2(value, exp10, "*") THEN
  214. error := 4
  215. END
  216. END
  217. END;
  218. IF error = 0 THEN
  219. v.float := value;
  220. v.typ := tREAL;
  221. IF ~check(v) THEN
  222. error := 4
  223. END
  224. END
  225. END fconv;
  226. PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
  227. BEGIN
  228. v.typ := tCHAR;
  229. v.int := ord
  230. END setChar;
  231. PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
  232. BEGIN
  233. v.typ := tWCHAR;
  234. v.int := ord
  235. END setWChar;
  236. PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  237. VAR
  238. error: BOOLEAN;
  239. BEGIN
  240. IF (a > 0) & (b > 0) THEN
  241. error := a > UTILS.maxint - b
  242. ELSIF (a < 0) & (b < 0) THEN
  243. error := a < UTILS.minint - b
  244. ELSE
  245. error := FALSE
  246. END;
  247. IF ~error THEN
  248. a := a + b
  249. ELSE
  250. a := 0
  251. END
  252. RETURN ~error
  253. END addInt;
  254. PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  255. VAR
  256. error: BOOLEAN;
  257. BEGIN
  258. IF (a > 0) & (b < 0) THEN
  259. error := a > UTILS.maxint + b
  260. ELSIF (a < 0) & (b > 0) THEN
  261. error := a < UTILS.minint + b
  262. ELSIF (a = 0) & (b < 0) THEN
  263. error := b = UTILS.minint
  264. ELSE
  265. error := FALSE
  266. END;
  267. IF ~error THEN
  268. a := a - b
  269. ELSE
  270. a := 0
  271. END
  272. RETURN ~error
  273. END subInt;
  274. PROCEDURE lg2 (x: INTEGER): INTEGER;
  275. VAR
  276. n: INTEGER;
  277. BEGIN
  278. ASSERT(x > 0);
  279. n := UTILS.Log2(x);
  280. IF n = -1 THEN
  281. n := 255
  282. END
  283. RETURN n
  284. END lg2;
  285. PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  286. VAR
  287. error: BOOLEAN;
  288. min, max: INTEGER;
  289. BEGIN
  290. min := UTILS.minint;
  291. max := UTILS.maxint;
  292. IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
  293. error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
  294. ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
  295. error := (a = min) OR (b = min);
  296. IF ~error THEN
  297. IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
  298. error := ABS(a) > max DIV ABS(b)
  299. END
  300. END
  301. ELSE
  302. error := FALSE
  303. END;
  304. IF ~error THEN
  305. a := a * b
  306. ELSE
  307. a := 0
  308. END
  309. RETURN ~error
  310. END mulInt;
  311. PROCEDURE _ASR (x, n: INTEGER): INTEGER;
  312. RETURN ASR(UTILS.Long(x), n)
  313. END _ASR;
  314. PROCEDURE _LSR (x, n: INTEGER): INTEGER;
  315. RETURN UTILS.Long(LSR(UTILS.Short(x), n))
  316. END _LSR;
  317. PROCEDURE _LSL (x, n: INTEGER): INTEGER;
  318. RETURN UTILS.Long(LSL(x, n))
  319. END _LSL;
  320. PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
  321. BEGIN
  322. x := UTILS.Short(x);
  323. x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
  324. RETURN UTILS.Long(x)
  325. END _ROR1_32;
  326. PROCEDURE _ROR1_16 (x: INTEGER): INTEGER;
  327. BEGIN
  328. x := x MOD 65536;
  329. x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
  330. RETURN UTILS.Long(x)
  331. END _ROR1_16;
  332. PROCEDURE _ROR (x, n: INTEGER): INTEGER;
  333. BEGIN
  334. CASE UTILS.bit_diff OF
  335. |0: x := ROR(x, n)
  336. |16, 48:
  337. n := n MOD 16;
  338. WHILE n > 0 DO
  339. x := _ROR1_16(x);
  340. DEC(n)
  341. END
  342. |32:
  343. n := n MOD 32;
  344. WHILE n > 0 DO
  345. x := _ROR1_32(x);
  346. DEC(n)
  347. END
  348. END
  349. RETURN x
  350. END _ROR;
  351. PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  352. VAR
  353. success: BOOLEAN;
  354. BEGIN
  355. success := TRUE;
  356. CASE op OF
  357. |"+": success := addInt(a.int, b.int)
  358. |"-": success := subInt(a.int, b.int)
  359. |"*": success := mulInt(a.int, b.int)
  360. |"/": success := FALSE
  361. |"D": a.int := a.int DIV b.int
  362. |"M": a.int := a.int MOD b.int
  363. |"L": a.int := _LSL(a.int, b.int)
  364. |"A": a.int := _ASR(a.int, b.int)
  365. |"O": a.int := _ROR(a.int, b.int)
  366. |"R": a.int := _LSR(a.int, b.int)
  367. |"m": a.int := MIN(a.int, b.int)
  368. |"x": a.int := MAX(a.int, b.int)
  369. END;
  370. a.typ := tINTEGER
  371. RETURN success & check(a)
  372. END opInt;
  373. PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
  374. BEGIN
  375. s[0] := CHR(c.int);
  376. s[1] := 0X
  377. END charToStr;
  378. PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
  379. BEGIN
  380. CASE op OF
  381. |"+": a.set := a.set + b.set
  382. |"-": a.set := a.set - b.set
  383. |"*": a.set := a.set * b.set
  384. |"/": a.set := a.set / b.set
  385. END;
  386. a.typ := tSET
  387. END opSet;
  388. PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  389. BEGIN
  390. a.typ := tREAL
  391. RETURN opFloat2(a.float, b.float, op) & check(a)
  392. END opFloat;
  393. PROCEDURE ord* (VAR v: VALUE);
  394. BEGIN
  395. CASE v.typ OF
  396. |tCHAR, tWCHAR:
  397. |tBOOLEAN: v.int := ORD(v.bool)
  398. |tSET: v.int := UTILS.Long(ORD(v.set))
  399. END;
  400. v.typ := tINTEGER
  401. END ord;
  402. PROCEDURE odd* (VAR v: VALUE);
  403. BEGIN
  404. v.typ := tBOOLEAN;
  405. v.bool := ODD(v.int)
  406. END odd;
  407. PROCEDURE bits* (VAR v: VALUE);
  408. BEGIN
  409. v.typ := tSET;
  410. v.set := BITS(v.int)
  411. END bits;
  412. PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
  413. VAR
  414. res: BOOLEAN;
  415. BEGIN
  416. res := FALSE;
  417. CASE v.typ OF
  418. |tREAL:
  419. v.float := ABS(v.float);
  420. res := TRUE
  421. |tINTEGER:
  422. IF v.int # UTILS.minint THEN
  423. v.int := ABS(v.int);
  424. res := TRUE
  425. END
  426. END
  427. RETURN res
  428. END abs;
  429. PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
  430. VAR
  431. res: BOOLEAN;
  432. BEGIN
  433. v.typ := tINTEGER;
  434. res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
  435. IF res THEN
  436. v.int := FLOOR(v.float)
  437. END
  438. RETURN res
  439. END floor;
  440. PROCEDURE flt* (VAR v: VALUE);
  441. BEGIN
  442. v.typ := tREAL;
  443. v.float := FLT(v.int)
  444. END flt;
  445. PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
  446. VAR
  447. z: VALUE;
  448. res: BOOLEAN;
  449. BEGIN
  450. res := TRUE;
  451. z.typ := tINTEGER;
  452. z.int := 0;
  453. CASE v.typ OF
  454. |tREAL: v.float := -v.float
  455. |tSET: v.set := -v.set
  456. |tINTEGER: res := opInt(z, v, "-"); v := z
  457. |tBOOLEAN: v.bool := ~v.bool
  458. END
  459. RETURN res
  460. END neg;
  461. PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
  462. BEGIN
  463. v.bool := b;
  464. v.typ := tBOOLEAN
  465. END setbool;
  466. PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
  467. BEGIN
  468. CASE op OF
  469. |"&": a.bool := a.bool & b.bool
  470. |"|": a.bool := a.bool OR b.bool
  471. END;
  472. a.typ := tBOOLEAN
  473. END opBoolean;
  474. PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  475. VAR
  476. res: BOOLEAN;
  477. BEGIN
  478. res := FALSE;
  479. IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  480. CASE v.typ OF
  481. |tINTEGER,
  482. tWCHAR,
  483. tCHAR: res := v.int < v2.int
  484. |tREAL: res := v.float < v2.float
  485. |tBOOLEAN,
  486. tSET: error := 1
  487. END
  488. ELSE
  489. error := 1
  490. END
  491. RETURN res
  492. END less;
  493. PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  494. VAR
  495. res: BOOLEAN;
  496. BEGIN
  497. res := FALSE;
  498. IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  499. CASE v.typ OF
  500. |tINTEGER,
  501. tWCHAR,
  502. tCHAR: res := v.int = v2.int
  503. |tREAL: res := v.float = v2.float
  504. |tBOOLEAN: res := v.bool = v2.bool
  505. |tSET: res := v.set = v2.set
  506. END
  507. ELSE
  508. error := 1
  509. END
  510. RETURN res
  511. END equal;
  512. PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
  513. VAR
  514. res: BOOLEAN;
  515. BEGIN
  516. error := 0;
  517. res := FALSE;
  518. CASE op OF
  519. |opEQ:
  520. res := equal(v, v2, error)
  521. |opNE:
  522. res := ~equal(v, v2, error)
  523. |opLT:
  524. res := less(v, v2, error)
  525. |opLE:
  526. res := less(v, v2, error);
  527. IF error = 0 THEN
  528. res := equal(v, v2, error) OR res
  529. END
  530. |opGE:
  531. res := ~less(v, v2, error)
  532. |opGT:
  533. res := less(v, v2, error);
  534. IF error = 0 THEN
  535. res := equal(v, v2, error) OR res
  536. END;
  537. res := ~res
  538. |opIN:
  539. IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
  540. IF range(v, 0, UTILS.target.maxSet) THEN
  541. res := v.int IN v2.set
  542. ELSE
  543. error := 2
  544. END
  545. ELSE
  546. error := 1
  547. END
  548. END;
  549. IF error = 0 THEN
  550. v.bool := res;
  551. v.typ := tBOOLEAN
  552. END
  553. END relation;
  554. PROCEDURE emptySet* (VAR v: VALUE);
  555. BEGIN
  556. v.typ := tSET;
  557. v.set := {}
  558. END emptySet;
  559. PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
  560. BEGIN
  561. v.typ := tSET;
  562. v.set := {a.int .. b.int}
  563. END constrSet;
  564. PROCEDURE getInt* (v: VALUE): INTEGER;
  565. BEGIN
  566. ASSERT(check(v))
  567. RETURN v.int
  568. END getInt;
  569. PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
  570. BEGIN
  571. v.int := i;
  572. v.typ := tINTEGER
  573. RETURN check(v)
  574. END setInt;
  575. PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN;
  576. VAR
  577. res: BOOLEAN;
  578. BEGIN
  579. res := LENGTH(s) + LENGTH(s1) < LEN(s);
  580. IF res THEN
  581. STRINGS.append(s, s1)
  582. END
  583. RETURN res
  584. END concat;
  585. PROCEDURE init;
  586. VAR
  587. i: INTEGER;
  588. BEGIN
  589. FOR i := 0 TO LEN(digit) - 1 DO
  590. digit[i] := -1
  591. END;
  592. FOR i := ORD("0") TO ORD("9") DO
  593. digit[i] := i - ORD("0")
  594. END;
  595. FOR i := ORD("A") TO ORD("F") DO
  596. digit[i] := i - ORD("A") + 10
  597. END
  598. END init;
  599. BEGIN
  600. init
  601. END ARITH.