Subversion Repositories Kolibri OS

Rev

Rev 8859 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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