>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      Fixed-point
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

      Fixed point je geniální způsob, jak se vyhnout zdlouhavým operacím v
      plovoucí  čárce.  Jde  v  podstatě  o to, vynásobit číslo, se kterým
      budeme  pracovat  dostatečně  velkou konstantou tak, aby poskytovala
      dostatek námi požadované desetinné přesnosti, poté s ním pracujeme a
      pak,  když  potřebujeme použít reálnou hodnotu, vydělíme ho zase tou
      konstantou.  V  praxi se pak pro násobení používají SHL a pro dělení
      SHR.

      Zkusím  příklad  -  klasický interpolovací algoritmus barev po lajně
      (Gouraud):

      Floating-point
      ^^^^^^^^^^^^^^
            procedure Interpoluj (X1,X2,Y,Barva1,Barva2:nejakej_typ)
             var step:real;
                 actua:real;
                 ofs,i:word;
              {
               step  = (Barva2-Barva1)/(X2-X1);
               actua = Barva1;
               ofs   =  (Y << 8) + (Y << 6);
               for i = X1 to X2 do
                {
                  mem[seg:ofs+i] = round(actua);
                  actua = actua + step;
                }
              }

      Fixed-point
      ^^^^^^^^^^^
            procedure Interpoluj (X1,X2,Y,Barva1,Barva2:nejakej_typ)
              var step:word nebo longint;
                    actua:        - " -           ;
                    ofs,i:word;
              {
               step := ((Barva2-Barva1)*256) DIV (X2-X1);
                                           /*A je to fixed point !*/
               actua := Barva1;
               ofs :=  (Y << 8) + (Y << 6);
               for i = X1 to X2 do
                {
                  mem[seg:ofs] := actua DIV 256;
                  actua := actua + step;
                }
              }

      Fixed-point-more-optimised
      ^^^^^^^^^^^^^^^^^^^^^^^^^^
            procedure Interpoluj (X1,X2,Y,Barva1,Barva2:nejakej_celoc_typ)
             var step:word nebo longint;
                 actua:        - " -            ;
                 ofs,i:word;
              {
               step := ((Barva2-Barva1) << 8) DIV (X2-X1);
                                        /*rychleji a rychleji :)*/
               actua := Barva1;
               ofs :=  (Y << 8) + (Y << 6);
               for i = X1 to X2 do
                {
                  mem[seg:ofs+i] := actua >> 8;
                  actua := actua + step;
                }
              }

      A  teď  ASM  -  algoritmus  je  optimalizován POUZE na fixed-point a
      párování instrukcí pro CPU Pentáč :

          In :    BX = X1
                  CX = X2
                  AH = C2         // barva v bode X2
                  AL = C1         // barva v bode X1
                  DI  = Y
           Code:
                 ...
                 Sub     cx, bx
                 Mov     si, ax         ; v pohodě

                 Sub     ah, al
                 Xor     dx,dx          ; taky

                 Xor     al, al
                 Div     cx             ; ne - div neni jednoduchá
                                          instrukce
                 Xchg    ax, dx
                 Mov     ax, di         ; Ne - čtení po zápisu (nelze)
                 Shl     ax, 8
                 Shl     di, 6          ; pohoda

                 Add     ax, bx
                 Mov     bx, si         ; o5 párujeme

                 Add     di, ax
                 Mov     bx, si         ; není problém

                 Shl     bx, 8          ; hmmm ? zbyla sama ? možná, že
                                          tam kompiler (nebo my) hodí
                                          NOP :-)

                 @loop:
                    Mov     al,bh
                    Mov     [di],al     ; párkujeme

                    Inc     di
                    Add     bx,dx       ; znova

                    Dec     cx
                 jnz short @loop        ; a zase

      Tyto  algoritmy  jsou pouze ukázkové - nezaručuji funkčnost, protože
      bylo  použito  fixed-point  8.8  a  Xové  souřadnice  by mohly hravě
      "přetéct" (a navíc jsem ten algoritmus nezkoušel :-] ).

      V praxi se nejčastěji používají tyto kombinace fixed-point :

   +------+-----------+-----------+---------+-------------+---------------+
   |typ   |   Celá    |   Deset.  |         |             |               |
   |FixPnt|   část    |   část    | 22/7 ** |   Přesnost  |   Odchylka    |
   +------+-----------+-----------+---------+-------------+---------------+
   | 8.8  |       256 |       256 |     805 | 3.14453125  | -0.001674107 *|
   |10.6  |     1 024 |        64 |     201 | 3.140625    |  0.002232142  |
   |6.10  |        64 |      1024 |    3218 | 3.142578125 |  0.000279017  |
   |16.16 |    65 536 |    65 536 |  205970 | 3.142852783 |  0.000004359  |
   |24.8  |16 777 216 |       256 |     805 | 3.14453125  | -0.001674107 *|
   |8.24  |       256 |16 777 216 |52728393 | 3.142857134 |  8.85 x 10-3  |
   +------+-----------+-----------+---------+-------------+---------------+

      *  Hodnota  je větší v důsledku zaokrouhlování při převádění real na
         fixed
      ** Pro  příklad  bylo   použito  "náhodného"  zlomku  22/7,  což  je
         3.142857143.  Tento  sloupec  ukazuje,  jak  vypadá  zlomek  22/7
         ve fixed-point.

      Samozřejmě  Vám nikdo nezakazuje více exotické kombinace jako 2.30 ,
      nebo  22.10  a  tak.  Záleží  čistě  na  tom,  jak  velkou  přesnost
      potřebujete,  ale  je třeba odhadnout rozsah celé části tak, aby vám
      ta celá část "nepřetekla" (overflow).


            výheň