Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2020, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE ARITH;
  9.  
  10. IMPORT AVLTREES, STRINGS, UTILS;
  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*:   AVLTREES.DATA
  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") & (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") & (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" 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.     exp10 := 10.0;
  228.     minus := FALSE;
  229.     n := 0;
  230.  
  231.     i := 0;
  232.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  233.         IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") THEN
  234.             INC(i)
  235.         ELSE
  236.             error := 4
  237.         END
  238.     END;
  239.  
  240.     INC(i);
  241.  
  242.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  243.         IF opFloat2(value, FLT(digit[ORD(s[i])]) / exp10, "+") & opFloat2(exp10, 10.0, "*") THEN
  244.             INC(i)
  245.         ELSE
  246.             error := 4
  247.         END
  248.     END;
  249.  
  250.     IF s[i] = "E" THEN
  251.         INC(i)
  252.     END;
  253.  
  254.     IF (s[i] = "-") OR (s[i] = "+") THEN
  255.         minus := s[i] = "-";
  256.         INC(i)
  257.     END;
  258.  
  259.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  260.         d := digit[ORD(s[i])];
  261.         IF n <= (UTILS.maxint - d) DIV 10 THEN
  262.             n := n * 10 + d;
  263.             INC(i)
  264.         ELSE
  265.             error := 5
  266.         END
  267.     END;
  268.  
  269.     exp10 := 1.0;
  270.     WHILE (error = 0) & (n > 0) DO
  271.         IF opFloat2(exp10, 10.0, "*") THEN
  272.             DEC(n)
  273.         ELSE
  274.             error := 4
  275.         END
  276.     END;
  277.  
  278.     IF error = 0 THEN
  279.         IF minus THEN
  280.             IF ~opFloat2(value, exp10, "/") THEN
  281.                 error := 4
  282.             END
  283.         ELSE
  284.             IF ~opFloat2(value, exp10, "*") THEN
  285.                 error := 4
  286.             END
  287.         END
  288.     END;
  289.  
  290.     IF error = 0 THEN
  291.         v.float := value;
  292.         v.typ := tREAL;
  293.         IF ~check(v) THEN
  294.             error := 4
  295.         END
  296.     END
  297.  
  298. END fconv;
  299.  
  300.  
  301. PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
  302. BEGIN
  303.     v.typ := tCHAR;
  304.     v.int := ord
  305. END setChar;
  306.  
  307.  
  308. PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
  309. BEGIN
  310.     v.typ := tWCHAR;
  311.     v.int := ord
  312. END setWChar;
  313.  
  314.  
  315. PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  316. VAR
  317.     error: BOOLEAN;
  318.  
  319. BEGIN
  320.     IF (a > 0) & (b > 0) THEN
  321.         error := a > UTILS.maxint - b
  322.     ELSIF (a < 0) & (b < 0) THEN
  323.         error := a < UTILS.minint - b
  324.     ELSE
  325.         error := FALSE
  326.     END;
  327.  
  328.     IF ~error THEN
  329.         a := a + b
  330.     ELSE
  331.         a := 0
  332.     END
  333.  
  334.     RETURN ~error
  335. END addInt;
  336.  
  337.  
  338. PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  339. VAR
  340.     error: BOOLEAN;
  341.  
  342. BEGIN
  343.     IF (a > 0) & (b < 0) THEN
  344.         error := a > UTILS.maxint + b
  345.     ELSIF (a < 0) & (b > 0) THEN
  346.         error := a < UTILS.minint + b
  347.     ELSIF (a = 0) & (b < 0) THEN
  348.         error := b = UTILS.minint
  349.     ELSE
  350.         error := FALSE
  351.     END;
  352.  
  353.     IF ~error THEN
  354.         a := a - b
  355.     ELSE
  356.         a := 0
  357.     END
  358.  
  359.     RETURN ~error
  360. END subInt;
  361.  
  362.  
  363. PROCEDURE lg2 (x: INTEGER): INTEGER;
  364. VAR
  365.     n: INTEGER;
  366.  
  367. BEGIN
  368.     ASSERT(x > 0);
  369.  
  370.     n := UTILS.Log2(x);
  371.     IF n = -1 THEN
  372.         n := 255
  373.     END
  374.  
  375.     RETURN n
  376. END lg2;
  377.  
  378.  
  379. PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  380. VAR
  381.     error:    BOOLEAN;
  382.     min, max: INTEGER;
  383.  
  384. BEGIN
  385.     min := UTILS.minint;
  386.     max := UTILS.maxint;
  387.  
  388.     IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
  389.         error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
  390.  
  391.     ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
  392.         error := (a = min) OR (b = min);
  393.         IF ~error THEN
  394.             IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
  395.                 error := ABS(a) > max DIV ABS(b)
  396.             END
  397.         END
  398.  
  399.     ELSE
  400.         error := FALSE
  401.     END;
  402.  
  403.     IF ~error THEN
  404.         a := a * b
  405.     ELSE
  406.         a := 0
  407.     END
  408.  
  409.     RETURN ~error
  410. END mulInt;
  411.  
  412.  
  413. PROCEDURE _ASR (x, n: INTEGER): INTEGER;
  414.     RETURN ASR(UTILS.Long(x), n)
  415. END _ASR;
  416.  
  417.  
  418. PROCEDURE _LSR (x, n: INTEGER): INTEGER;
  419.     RETURN UTILS.Long(LSR(UTILS.Short(x), n))
  420. END _LSR;
  421.  
  422.  
  423. PROCEDURE _LSL (x, n: INTEGER): INTEGER;
  424.     RETURN UTILS.Long(LSL(x, n))
  425. END _LSL;
  426.  
  427.  
  428. PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
  429. BEGIN
  430.     x := UTILS.Short(x);
  431.     x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
  432.     RETURN UTILS.Long(x)
  433. END _ROR1_32;
  434.  
  435.  
  436. PROCEDURE _ROR1_16 (x: INTEGER): INTEGER;
  437. BEGIN
  438.     x := x MOD 65536;
  439.     x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
  440.     RETURN UTILS.Long(x)
  441. END _ROR1_16;
  442.  
  443.  
  444. PROCEDURE _ROR (x, n: INTEGER): INTEGER;
  445. BEGIN
  446.  
  447.     CASE UTILS.bit_diff OF
  448.     |0: x := ROR(x, n)
  449.     |16, 48:
  450.         n := n MOD 16;
  451.         WHILE n > 0 DO
  452.             x := _ROR1_16(x);
  453.             DEC(n)
  454.         END
  455.     |32:
  456.         n := n MOD 32;
  457.         WHILE n > 0 DO
  458.             x := _ROR1_32(x);
  459.             DEC(n)
  460.         END
  461.     END
  462.  
  463.     RETURN x
  464. END _ROR;
  465.  
  466.  
  467. PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  468. VAR
  469.     success: BOOLEAN;
  470.  
  471. BEGIN
  472.     success := TRUE;
  473.  
  474.     CASE op OF
  475.     |"+": success := addInt(a.int, b.int)
  476.     |"-": success := subInt(a.int, b.int)
  477.     |"*": success := mulInt(a.int, b.int)
  478.     |"/": success := FALSE
  479.     |"D": a.int := a.int DIV b.int
  480.     |"M": a.int := a.int MOD b.int
  481.     |"L": a.int := _LSL(a.int, b.int)
  482.     |"A": a.int := _ASR(a.int, b.int)
  483.     |"O": a.int := _ROR(a.int, b.int)
  484.     |"R": a.int := _LSR(a.int, b.int)
  485.     |"m": a.int := MIN(a.int, b.int)
  486.     |"x": a.int := MAX(a.int, b.int)
  487.     END;
  488.     a.typ := tINTEGER
  489.  
  490.     RETURN success & check(a)
  491. END opInt;
  492.  
  493.  
  494. PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
  495. BEGIN
  496.     s[0] := CHR(c.int);
  497.     s[1] := 0X
  498. END charToStr;
  499.  
  500.  
  501. PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
  502. BEGIN
  503.     CASE op OF
  504.     |"+": a.set := a.set + b.set
  505.     |"-": a.set := a.set - b.set
  506.     |"*": a.set := a.set * b.set
  507.     |"/": a.set := a.set / b.set
  508.     END;
  509.     a.typ := tSET
  510. END opSet;
  511.  
  512.  
  513. PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  514. BEGIN
  515.     a.typ := tREAL
  516.     RETURN opFloat2(a.float, b.float, op) & check(a)
  517. END opFloat;
  518.  
  519.  
  520. PROCEDURE ord* (VAR v: VALUE);
  521. BEGIN
  522.     CASE v.typ OF
  523.     |tCHAR, tWCHAR:
  524.     |tBOOLEAN: v.int := ORD(v.bool)
  525.     |tSET:     v.int := UTILS.Long(ORD(v.set))
  526.     END;
  527.     v.typ := tINTEGER
  528. END ord;
  529.  
  530.  
  531. PROCEDURE odd* (VAR v: VALUE);
  532. BEGIN
  533.     v.typ := tBOOLEAN;
  534.     v.bool := ODD(v.int)
  535. END odd;
  536.  
  537.  
  538. PROCEDURE bits* (VAR v: VALUE);
  539. BEGIN
  540.     v.typ := tSET;
  541.     v.set := BITS(v.int)
  542. END bits;
  543.  
  544.  
  545. PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
  546. VAR
  547.     res: BOOLEAN;
  548.  
  549. BEGIN
  550.     res := FALSE;
  551.  
  552.     CASE v.typ OF
  553.     |tREAL:
  554.         v.float := ABS(v.float);
  555.         res := TRUE
  556.     |tINTEGER:
  557.         IF v.int # UTILS.minint THEN
  558.             v.int := ABS(v.int);
  559.             res := TRUE
  560.         END
  561.     END
  562.  
  563.     RETURN res
  564. END abs;
  565.  
  566.  
  567. PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
  568. VAR
  569.     res: BOOLEAN;
  570.  
  571. BEGIN
  572.     v.typ := tINTEGER;
  573.     res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
  574.     IF res THEN
  575.         v.int := FLOOR(v.float)
  576.     END
  577.  
  578.     RETURN res
  579. END floor;
  580.  
  581.  
  582. PROCEDURE flt* (VAR v: VALUE);
  583. BEGIN
  584.     v.typ := tREAL;
  585.     v.float := FLT(v.int)
  586. END flt;
  587.  
  588.  
  589. PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
  590. VAR
  591.     z: VALUE;
  592.     res: BOOLEAN;
  593.  
  594. BEGIN
  595.     res := TRUE;
  596.  
  597.     z.typ := tINTEGER;
  598.     z.int := 0;
  599.  
  600.     CASE v.typ OF
  601.     |tREAL:     v.float := -v.float
  602.     |tSET:      v.set := -v.set
  603.     |tINTEGER:  res := opInt(z, v, "-"); v := z
  604.     |tBOOLEAN:  v.bool := ~v.bool
  605.     END
  606.  
  607.     RETURN res
  608. END neg;
  609.  
  610.  
  611. PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
  612. BEGIN
  613.     v.bool := b;
  614.     v.typ := tBOOLEAN
  615. END setbool;
  616.  
  617.  
  618. PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
  619. BEGIN
  620.     CASE op OF
  621.     |"&": a.bool := a.bool & b.bool
  622.     |"|": a.bool := a.bool OR b.bool
  623.     END;
  624.     a.typ := tBOOLEAN
  625. END opBoolean;
  626.  
  627.  
  628. PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  629. VAR
  630.     res: BOOLEAN;
  631.  
  632. BEGIN
  633.     res := FALSE;
  634.  
  635.     IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  636.         CASE v.typ OF
  637.         |tINTEGER,
  638.          tWCHAR,
  639.          tCHAR:     res := v.int < v2.int
  640.         |tREAL:     res := v.float < v2.float
  641.         |tBOOLEAN,
  642.          tSET:      error := 1
  643.         END
  644.     ELSE
  645.         error := 1
  646.     END
  647.  
  648.     RETURN res
  649. END less;
  650.  
  651.  
  652. PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  653. VAR
  654.     res: BOOLEAN;
  655.  
  656. BEGIN
  657.     res := FALSE;
  658.  
  659.     IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  660.         CASE v.typ OF
  661.         |tINTEGER,
  662.          tWCHAR,
  663.          tCHAR:     res := v.int = v2.int
  664.         |tREAL:     res := v.float = v2.float
  665.         |tBOOLEAN:  res := v.bool = v2.bool
  666.         |tSET:      res := v.set = v2.set
  667.         END
  668.     ELSE
  669.         error := 1
  670.     END
  671.  
  672.     RETURN res
  673. END equal;
  674.  
  675.  
  676. PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
  677. VAR
  678.     res: BOOLEAN;
  679.  
  680. BEGIN
  681.     error := 0;
  682.  
  683.     res := FALSE;
  684.  
  685.     CASE op OF
  686.  
  687.     |opEQ:
  688.         res := equal(v, v2, error)
  689.  
  690.     |opNE:
  691.         res := ~equal(v, v2, error)
  692.  
  693.     |opLT:
  694.         res := less(v, v2, error)
  695.  
  696.     |opLE:
  697.         res := less(v, v2, error);
  698.         IF error = 0 THEN
  699.             res := equal(v, v2, error) OR res
  700.         END
  701.  
  702.     |opGE:
  703.         res := ~less(v, v2, error)
  704.  
  705.     |opGT:
  706.         res := less(v, v2, error);
  707.         IF error = 0 THEN
  708.             res := equal(v, v2, error) OR res
  709.         END;
  710.         res := ~res
  711.  
  712.     |opIN:
  713.         IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
  714.             IF range(v, 0, UTILS.target.maxSet) THEN
  715.                 res := v.int IN v2.set
  716.             ELSE
  717.                 error := 2
  718.             END
  719.         ELSE
  720.             error := 1
  721.         END
  722.  
  723.     END;
  724.  
  725.     IF error = 0 THEN
  726.         v.bool := res;
  727.         v.typ  := tBOOLEAN
  728.     END
  729.  
  730. END relation;
  731.  
  732.  
  733. PROCEDURE emptySet* (VAR v: VALUE);
  734. BEGIN
  735.     v.typ := tSET;
  736.     v.set := {}
  737. END emptySet;
  738.  
  739.  
  740. PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
  741. BEGIN
  742.     v.typ := tSET;
  743.     v.set := {a.int .. b.int}
  744. END constrSet;
  745.  
  746.  
  747. PROCEDURE getInt* (v: VALUE): INTEGER;
  748. BEGIN
  749.     ASSERT(check(v))
  750.  
  751.     RETURN v.int
  752. END getInt;
  753.  
  754.  
  755. PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
  756. BEGIN
  757.     v.int := i;
  758.     v.typ := tINTEGER
  759.  
  760.     RETURN check(v)
  761. END setInt;
  762.  
  763.  
  764. PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN;
  765. VAR
  766.     res: BOOLEAN;
  767.  
  768. BEGIN
  769.     res := LENGTH(s) + LENGTH(s1) < LEN(s);
  770.     IF res THEN
  771.         STRINGS.append(s, s1)
  772.     END
  773.  
  774.     RETURN res
  775. END concat;
  776.  
  777.  
  778. PROCEDURE init;
  779. VAR
  780.     i: INTEGER;
  781.  
  782. BEGIN
  783.     FOR i := 0 TO LEN(digit) - 1 DO
  784.         digit[i] := -1
  785.     END;
  786.  
  787.     FOR i := ORD("0") TO ORD("9") DO
  788.         digit[i] := i - ORD("0")
  789.     END;
  790.  
  791.     FOR i := ORD("A") TO ORD("F") DO
  792.         digit[i] := i - ORD("A") + 10
  793.     END
  794. END init;
  795.  
  796.  
  797. BEGIN
  798.     init
  799. END ARITH.