Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2020, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE FPU;
  9.  
  10.  
  11. CONST
  12.  
  13.     INF  = 07F800000H;
  14.     NINF = 0FF800000H;
  15.     NAN  = 07FC00000H;
  16.  
  17.  
  18. PROCEDURE div2 (b, a: INTEGER): INTEGER;
  19. VAR
  20.     n, e, r, s: INTEGER;
  21.  
  22. BEGIN
  23.     s := ORD(BITS(a) / BITS(b) - {0..30});
  24.     e := (a DIV 800000H) MOD 256 - (b DIV 800000H) MOD 256 + 127;
  25.  
  26.     a := a MOD 800000H + 800000H;
  27.     b := b MOD 800000H + 800000H;
  28.  
  29.     n := 800000H;
  30.     r := 0;
  31.  
  32.     IF a < b THEN
  33.         a := a * 2;
  34.         DEC(e)
  35.     END;
  36.  
  37.     WHILE (a > 0) & (n > 0) DO
  38.         IF a >= b THEN
  39.             INC(r, n);
  40.             DEC(a, b)
  41.         END;
  42.         a := a * 2;
  43.         n := n DIV 2
  44.     END;
  45.  
  46.     IF e <= 0 THEN
  47.         e := 0;
  48.         r := 800000H;
  49.         s := 0
  50.     ELSIF e >= 255 THEN
  51.         e := 255;
  52.         r := 800000H
  53.     END
  54.  
  55.     RETURN (r - 800000H) + e * 800000H + s
  56. END div2;
  57.  
  58.  
  59. PROCEDURE mul2 (b, a: INTEGER): INTEGER;
  60. VAR
  61.     e, r, s: INTEGER;
  62.  
  63. BEGIN
  64.     s := ORD(BITS(a) / BITS(b) - {0..30});
  65.     e := (a DIV 800000H) MOD 256 + (b DIV 800000H) MOD 256 - 127;
  66.  
  67.     a := a MOD 800000H + 800000H;
  68.     b := b MOD 800000H + 800000H;
  69.  
  70.     r := a * (b MOD 256);
  71.     b := b DIV 256;
  72.     r := LSR(r, 8);
  73.  
  74.     INC(r, a * (b MOD 256));
  75.     b := b DIV 256;
  76.     r := LSR(r, 8);
  77.  
  78.     INC(r, a * (b MOD 256));
  79.     r := LSR(r, 7);
  80.  
  81.     IF r >= 1000000H THEN
  82.         r := r DIV 2;
  83.         INC(e)
  84.     END;
  85.  
  86.     IF e <= 0 THEN
  87.         e := 0;
  88.         r := 800000H;
  89.         s := 0
  90.     ELSIF e >= 255 THEN
  91.         e := 255;
  92.         r := 800000H
  93.     END
  94.  
  95.     RETURN (r - 800000H) + e * 800000H + s
  96. END mul2;
  97.  
  98.  
  99. PROCEDURE add2 (b, a: INTEGER): INTEGER;
  100. VAR
  101.     ea, eb, e, d, r: INTEGER;
  102.  
  103. BEGIN
  104.     ea := (a DIV 800000H) MOD 256;
  105.     eb := (b DIV 800000H) MOD 256;
  106.     d  := ea - eb;
  107.  
  108.     a := a MOD 800000H + 800000H;
  109.     b := b MOD 800000H + 800000H;
  110.  
  111.     IF d > 0 THEN
  112.         IF d < 24 THEN
  113.             b := LSR(b, d)
  114.         ELSE
  115.             b := 0
  116.         END;
  117.         e := ea
  118.     ELSIF d < 0 THEN
  119.         IF d > -24 THEN
  120.             a := LSR(a, -d)
  121.         ELSE
  122.             a := 0
  123.         END;
  124.         e := eb
  125.     ELSE
  126.         e := ea
  127.     END;
  128.  
  129.     r := a + b;
  130.  
  131.     IF r >= 1000000H THEN
  132.         r := r DIV 2;
  133.         INC(e)
  134.     END;
  135.  
  136.     IF e >= 255 THEN
  137.         e := 255;
  138.         r := 800000H
  139.     END
  140.  
  141.     RETURN (r - 800000H) + e * 800000H
  142. END add2;
  143.  
  144.  
  145. PROCEDURE sub2 (b, a: INTEGER): INTEGER;
  146. VAR
  147.     ea, eb, e, d, r, s: INTEGER;
  148.  
  149. BEGIN
  150.     ea := (a DIV 800000H) MOD 256;
  151.     eb := (b DIV 800000H) MOD 256;
  152.  
  153.     a := a MOD 800000H + 800000H;
  154.     b := b MOD 800000H + 800000H;
  155.  
  156.     d := ea - eb;
  157.  
  158.     IF (d > 0) OR (d = 0) & (a >= b) THEN
  159.         s := 0
  160.     ELSE
  161.         ea := eb;
  162.         d := -d;
  163.         r := a;
  164.         a := b;
  165.         b := r;
  166.         s := 80000000H
  167.     END;
  168.  
  169.     e := ea;
  170.  
  171.     IF d > 0 THEN
  172.         IF d < 24 THEN
  173.             b := LSR(b, d)
  174.         ELSE
  175.             b := 0
  176.         END
  177.     END;
  178.  
  179.     r := a - b;
  180.  
  181.     IF r = 0 THEN
  182.         e := 0;
  183.         r := 800000H;
  184.         s := 0
  185.     ELSE
  186.         WHILE r < 800000H DO
  187.             r := r * 2;
  188.             DEC(e)
  189.         END
  190.     END;
  191.  
  192.     IF e <= 0 THEN
  193.         e := 0;
  194.         r := 800000H;
  195.         s := 0
  196.     END
  197.  
  198.     RETURN (r - 800000H) + e * 800000H + s
  199. END sub2;
  200.  
  201.  
  202. PROCEDURE zero (VAR x: INTEGER);
  203. BEGIN
  204.     IF BITS(x) * {23..30} = {} THEN
  205.         x := 0
  206.     END
  207. END zero;
  208.  
  209.  
  210. PROCEDURE isNaN (a: INTEGER): BOOLEAN;
  211.     RETURN (a > INF) OR (a < 0) & (a > NINF)
  212. END isNaN;
  213.  
  214.  
  215. PROCEDURE isInf (a: INTEGER): BOOLEAN;
  216.     RETURN (a = INF) OR (a = NINF)
  217. END isInf;
  218.  
  219.  
  220. PROCEDURE isNormal (a: INTEGER): BOOLEAN;
  221.     RETURN (BITS(a) * {23..30} # {23..30}) & (BITS(a) * {23..30} # {})
  222. END isNormal;
  223.  
  224.  
  225. PROCEDURE add* (b, a: INTEGER): INTEGER;
  226. VAR
  227.     r: INTEGER;
  228.  
  229. BEGIN
  230.     zero(a); zero(b);
  231.  
  232.     IF isNormal(a) & isNormal(b) THEN
  233.  
  234.         IF (a > 0) & (b > 0) THEN
  235.             r := add2(b, a)
  236.         ELSIF (a < 0) & (b < 0) THEN
  237.             r := add2(b, a) + 80000000H
  238.         ELSIF (a > 0) & (b < 0) THEN
  239.             r := sub2(b, a)
  240.         ELSIF (a < 0) & (b > 0) THEN
  241.             r := sub2(a, b)
  242.         END
  243.  
  244.     ELSIF isNaN(a) OR isNaN(b) THEN
  245.         r := NAN
  246.     ELSIF isInf(a) & isInf(b) THEN
  247.         IF a = b THEN
  248.             r := a
  249.         ELSE
  250.             r := NAN
  251.         END
  252.     ELSIF isInf(a) THEN
  253.         r := a
  254.     ELSIF isInf(b) THEN
  255.         r := b
  256.     ELSIF a = 0 THEN
  257.         r := b
  258.     ELSIF b = 0 THEN
  259.         r := a
  260.     END
  261.  
  262.     RETURN r
  263. END add;
  264.  
  265.  
  266. PROCEDURE sub* (b, a: INTEGER): INTEGER;
  267. VAR
  268.     r: INTEGER;
  269.  
  270. BEGIN
  271.     zero(a); zero(b);
  272.  
  273.     IF isNormal(a) & isNormal(b) THEN
  274.  
  275.         IF (a > 0) & (b > 0) THEN
  276.             r := sub2(b, a)
  277.         ELSIF (a < 0) & (b < 0) THEN
  278.             r := sub2(a, b)
  279.         ELSIF (a > 0) & (b < 0) THEN
  280.             r := add2(b, a)
  281.         ELSIF (a < 0) & (b > 0) THEN
  282.             r := add2(b, a) + 80000000H
  283.         END
  284.  
  285.     ELSIF isNaN(a) OR isNaN(b) THEN
  286.         r := NAN
  287.     ELSIF isInf(a) & isInf(b) THEN
  288.         IF a # b THEN
  289.             r := a
  290.         ELSE
  291.             r := NAN
  292.         END
  293.     ELSIF isInf(a) THEN
  294.         r := a
  295.     ELSIF isInf(b) THEN
  296.         r := INF + ORD(BITS(b) / {31} - {0..30})
  297.     ELSIF (a = 0) & (b = 0) THEN
  298.         r := 0
  299.     ELSIF a = 0 THEN
  300.         r := ORD(BITS(b) / {31})
  301.     ELSIF b = 0 THEN
  302.         r := a
  303.     END
  304.  
  305.     RETURN r
  306. END sub;
  307.  
  308.  
  309. PROCEDURE mul* (b, a: INTEGER): INTEGER;
  310. VAR
  311.     r: INTEGER;
  312.  
  313. BEGIN
  314.     zero(a); zero(b);
  315.  
  316.     IF isNormal(a) & isNormal(b) THEN
  317.         r := mul2(b, a)
  318.     ELSIF isNaN(a) OR isNaN(b) THEN
  319.         r := NAN
  320.     ELSIF (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN
  321.         r := NAN
  322.     ELSIF isInf(a) OR isInf(b) THEN
  323.         r := INF + ORD(BITS(a) / BITS(b) - {0..30})
  324.     ELSIF (a = 0) OR (b = 0) THEN
  325.         r := 0
  326.     END
  327.  
  328.     RETURN r
  329. END mul;
  330.  
  331.  
  332. PROCEDURE _div* (b, a: INTEGER): INTEGER;
  333. VAR
  334.     r: INTEGER;
  335.  
  336. BEGIN
  337.     zero(a); zero(b);
  338.  
  339.     IF isNormal(a) & isNormal(b) THEN
  340.         r := div2(b, a)
  341.     ELSIF isNaN(a) OR isNaN(b) THEN
  342.         r := NAN
  343.     ELSIF isInf(a) & isInf(b) THEN
  344.         r := NAN
  345.     ELSIF isInf(a) THEN
  346.         r := INF + ORD(BITS(a) / BITS(b) - {0..30})
  347.     ELSIF isInf(b) THEN
  348.         r := 0
  349.     ELSIF a = 0 THEN
  350.         IF b = 0 THEN
  351.             r := NAN
  352.         ELSE
  353.             r := 0
  354.         END
  355.     ELSIF b = 0 THEN
  356.         IF a > 0 THEN
  357.             r := INF
  358.         ELSE
  359.             r := NINF
  360.         END
  361.     END
  362.  
  363.     RETURN r
  364. END _div;
  365.  
  366.  
  367. PROCEDURE cmp* (op, b, a: INTEGER): BOOLEAN;
  368. VAR
  369.     res: BOOLEAN;
  370.  
  371. BEGIN
  372.     zero(a); zero(b);
  373.  
  374.     IF isNaN(a) OR isNaN(b) THEN
  375.         res := op = 1
  376.     ELSIF (a < 0) & (b < 0) THEN
  377.         CASE op OF
  378.         |0: res := a = b
  379.         |1: res := a # b
  380.         |2: res := a > b
  381.         |3: res := a >= b
  382.         |4: res := a < b
  383.         |5: res := a <= b
  384.         END
  385.     ELSE
  386.         CASE op OF
  387.         |0: res := a = b
  388.         |1: res := a # b
  389.         |2: res := a < b
  390.         |3: res := a <= b
  391.         |4: res := a > b
  392.         |5: res := a >= b
  393.         END
  394.     END
  395.  
  396.     RETURN res
  397. END cmp;
  398.  
  399.  
  400. PROCEDURE flt* (x: INTEGER): INTEGER;
  401. VAR
  402.     n, y, r, s: INTEGER;
  403.  
  404. BEGIN
  405.     IF x = 0 THEN
  406.         s := 0;
  407.         r := 800000H;
  408.         n := -126
  409.     ELSIF x = 80000000H THEN
  410.         s := 80000000H;
  411.         r := 800000H;
  412.         n := 32
  413.     ELSE
  414.         IF x < 0 THEN
  415.             s := 80000000H
  416.         ELSE
  417.             s := 0
  418.         END;
  419.         n := 0;
  420.         y := ABS(x);
  421.         r := y;
  422.         WHILE y > 0 DO
  423.             y := y DIV 2;
  424.             INC(n)
  425.         END;
  426.         IF n > 24 THEN
  427.             r := LSR(r, n - 24)
  428.         ELSE
  429.             r := LSL(r, 24 - n)
  430.         END
  431.     END
  432.  
  433.     RETURN (r - 800000H) + (n + 126) * 800000H + s
  434. END flt;
  435.  
  436.  
  437. PROCEDURE floor* (x: INTEGER): INTEGER;
  438. VAR
  439.     r, e: INTEGER;
  440.  
  441. BEGIN
  442.     zero(x);
  443.  
  444.     e := (x DIV 800000H) MOD 256 - 127;
  445.     r := x MOD 800000H + 800000H;
  446.  
  447.     IF (0 <= e) & (e <= 22) THEN
  448.         r := LSR(r, 23 - e) + ORD((x < 0) & (LSL(r, e + 9) # 0))
  449.     ELSIF (23 <= e) & (e <= 54) THEN
  450.         r := LSL(r, e - 23)
  451.     ELSIF (e < 0) & (x < 0) THEN
  452.         r := 1
  453.     ELSE
  454.         r := 0
  455.     END;
  456.  
  457.     IF x < 0 THEN
  458.         r := -r
  459.     END
  460.  
  461.     RETURN r
  462. END floor;
  463.  
  464.  
  465. END FPU.