Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
7983 leency 4
    Copyright (c) 2018-2020, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE ARITH;
9
 
7693 akron1 10
IMPORT AVLTREES, STRINGS, UTILS;
7597 akron1 11
 
12
 
13
CONST
14
 
15
    tINTEGER* = 1;  tREAL* = 2;  tSET*    = 3;
16
    tBOOLEAN* = 4;  tCHAR* = 5;  tWCHAR*  = 6;
17
    tSTRING*  = 7;
18
 
8097 maxcodehac 19
    opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5;
20
    opIN* = 6; opIS* = 7;
7597 akron1 21
 
8097 maxcodehac 22
 
7597 akron1 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
 
7696 akron1 50
    CASE v.typ OF
51
    |tINTEGER, tCHAR, tWCHAR:
7597 akron1 52
        res := v.int
7696 akron1 53
    |tSET:
7693 akron1 54
        res := UTILS.Long(ORD(v.set))
7696 akron1 55
    |tBOOLEAN:
7597 akron1 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
 
7983 leency 79
PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
80
    RETURN (a <= i.int) & (i.int <= b)
81
END range;
82
 
83
 
7597 akron1 84
PROCEDURE check* (v: VALUE): BOOLEAN;
85
VAR
7696 akron1 86
    res: BOOLEAN;
7597 akron1 87
 
88
BEGIN
7696 akron1 89
    CASE v.typ OF
7983 leency 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)
7696 akron1 93
    |tREAL:    res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
7597 akron1 94
    END
95
 
7696 akron1 96
    RETURN res
7597 akron1 97
END check;
98
 
99
 
100
PROCEDURE isZero* (v: VALUE): BOOLEAN;
101
VAR
102
    res: BOOLEAN;
7696 akron1 103
 
7597 akron1 104
BEGIN
7696 akron1 105
    CASE v.typ OF
106
    |tINTEGER: res := v.int = 0
107
    |tREAL:    res := v.float = 0.0
7597 akron1 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
 
7693 akron1 168
        IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
7597 akron1 169
            error := 2
170
        ELSE
171
            value := value * 16 + d;
172
            INC(i)
173
        END
174
 
175
    END;
176
 
7693 akron1 177
    value := UTILS.Long(value);
7597 akron1 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
7983 leency 207
    |"+": a := a + b
208
    |"-": a := a - b
209
    |"*": a := a * b
210
    |"/": a := a / b
7597 akron1 211
    END
212
 
7983 leency 213
    RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
7597 akron1 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
 
7983 leency 370
    n := UTILS.Log2(x);
371
    IF n = -1 THEN
7597 akron1 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;
7693 akron1 414
    RETURN ASR(UTILS.Long(x), n)
7597 akron1 415
END _ASR;
416
 
417
 
418
PROCEDURE _LSR (x, n: INTEGER): INTEGER;
7693 akron1 419
    RETURN UTILS.Long(LSR(UTILS.Short(x), n))
7597 akron1 420
END _LSR;
421
 
422
 
423
PROCEDURE _LSL (x, n: INTEGER): INTEGER;
7693 akron1 424
    RETURN UTILS.Long(LSL(x, n))
7597 akron1 425
END _LSL;
426
 
427
 
428
PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
429
BEGIN
7693 akron1 430
    x := UTILS.Short(x);
7597 akron1 431
    x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
7693 akron1 432
    RETURN UTILS.Long(x)
7597 akron1 433
END _ROR1_32;
434
 
435
 
7693 akron1 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
 
7597 akron1 444
PROCEDURE _ROR (x, n: INTEGER): INTEGER;
445
BEGIN
7693 akron1 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:
7597 akron1 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
7983 leency 479
    |"D": a.int := a.int DIV b.int
7597 akron1 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)
7693 akron1 525
    |tSET:     v.int := UTILS.Long(ORD(v.set))
7597 akron1 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
7693 akron1 550
    res := FALSE;
7597 akron1 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
7693 akron1 561
    END
562
 
7597 akron1 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
 
8097 maxcodehac 676
PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
7597 akron1 677
VAR
678
    res: BOOLEAN;
679
 
680
BEGIN
681
    error := 0;
682
 
683
    res := FALSE;
684
 
8097 maxcodehac 685
    CASE op OF
7597 akron1 686
 
8097 maxcodehac 687
    |opEQ:
7597 akron1 688
        res := equal(v, v2, error)
689
 
8097 maxcodehac 690
    |opNE:
7597 akron1 691
        res := ~equal(v, v2, error)
692
 
8097 maxcodehac 693
    |opLT:
694
        res := less(v, v2, error)
7597 akron1 695
 
8097 maxcodehac 696
    |opLE:
697
        res := less(v, v2, error);
698
        IF error = 0 THEN
699
            res := equal(v, v2, error) OR res
7597 akron1 700
        END
701
 
8097 maxcodehac 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:
7597 akron1 713
        IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
7693 akron1 714
            IF range(v, 0, UTILS.target.maxSet) THEN
7597 akron1 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
 
8097 maxcodehac 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
 
7597 akron1 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
7983 leency 799
END ARITH.