File : fz_qshft.adb


   1 ------------------------------------------------------------------------------
   2 ------------------------------------------------------------------------------
   3 -- This file is part of 'Finite Field Arithmetic', aka 'FFA'.               --
   4 --                                                                          --
   5 -- (C) 2018 Stanislav Datskovskiy ( www.loper-os.org )                      --
   6 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html     --
   7 --                                                                          --
   8 -- You do not have, nor can you ever acquire the right to use, copy or      --
   9 -- distribute this software ; Should you use this software for any purpose, --
  10 -- or copy and distribute it to anyone or in any manner, you are breaking   --
  11 -- the laws of whatever soi-disant jurisdiction, and you promise to         --
  12 -- continue doing so for the indefinite future. In any case, please         --
  13 -- always : read and understand any software ; verify any PGP signatures    --
  14 -- that you use - for any purpose.                                          --
  15 --                                                                          --
  16 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm .     --
  17 ------------------------------------------------------------------------------
  18 ------------------------------------------------------------------------------
  19 
  20 with Iron;     use Iron;
  21 with Word_Ops; use Word_Ops;
  22 with W_Pred;   use W_Pred;
  23 with W_Shifts; use W_Shifts;
  24 with FZ_Basic; use FZ_Basic;
  25 with FZ_Shift; use FZ_Shift;
  26 
  27 
  28 package body FZ_QShft is
  29    
  30    -- Constant-time subword shift, for where there is no barrel shifter
  31    procedure FZ_Quiet_ShiftRight_SubW_Soft(N        : in FZ;
  32                                            ShiftedN : in out FZ;
  33                                            Count    : in WBit_Index) is
  34       Nw  : constant Word  := Word(Count);
  35       nC  : constant WBool := W_ZeroP(Nw); -- 'no carry' for Count == 0 case
  36       Ni  : Word := 0; -- Current word
  37       C   : Word := 0; -- Current carry
  38       S   : Positive;  -- Current shiftness level
  39       B   : Word;      -- Quantity of shift (bitwalked over)
  40       CB  : Word;      -- Quantity of carry counter-shift (bitwalked over)
  41       St  : Word;      -- Temporary word shift candidate
  42       Ct  : Word;      -- Temporary carry counter-shift candidate
  43    begin
  44       for i in reverse N'Range loop
  45          Ni          := N(i);
  46          ShiftedN(i) := C;
  47          C           := W_Mux(Ni, 0, nC);
  48          S           := 1;
  49          B           := Nw;
  50          CB          := Word(Bitness) - B;
  51          -- For each shift level (of the subword shiftvalue width) :
  52          for j in 1 .. BitnessLog2 loop
  53             -- Shift and mux the current word
  54             St := Shift_Right(Ni, S);
  55             Ni := W_Mux(Ni, St, B and 1);
  56             -- Shift and mux the current carry
  57             Ct := Shift_Left(C, S);
  58             C  := W_Mux(C,  Ct, CB and 1);
  59             -- Go to the next shiftness level
  60             S  := S * 2;
  61             B  := Shift_Right(B,  1);
  62             CB := Shift_Right(CB, 1);
  63          end loop;
  64          -- Slide in the carry from the previous shift
  65          ShiftedN(i) := ShiftedN(i) or Ni;
  66       end loop;
  67    end FZ_Quiet_ShiftRight_SubW_Soft;
  68    
  69    
  70    -- Constant-time subword shift, for where there is no barrel shifter
  71    procedure FZ_Quiet_ShiftLeft_SubW_Soft(N        : in FZ;
  72                                           ShiftedN : in out FZ;
  73                                           Count    : in WBit_Index) is
  74       Nw  : constant Word  := Word(Count);
  75       nC  : constant WBool := W_ZeroP(Nw); -- 'no carry' for Count == 0 case
  76       Ni  : Word := 0; -- Current word
  77       C   : Word := 0; -- Current carry
  78       S   : Positive;  -- Current shiftness level
  79       B   : Word;      -- Quantity of shift (bitwalked over)
  80       CB  : Word;      -- Quantity of carry counter-shift (bitwalked over)
  81       St  : Word;      -- Temporary word shift candidate
  82       Ct  : Word;      -- Temporary carry counter-shift candidate
  83    begin
  84       for i in N'Range loop
  85          Ni          := N(i);
  86          ShiftedN(i) := C;
  87          C           := W_Mux(Ni, 0, nC);
  88          S           := 1;
  89          B           := Nw;
  90          CB          := Word(Bitness) - B;
  91          -- For each shift level (of the subword shiftvalue width) :
  92          for j in 1 .. BitnessLog2 loop
  93             -- Shift and mux the current word
  94             St := Shift_Left(Ni, S);
  95             Ni := W_Mux(Ni, St, B and 1);
  96             -- Shift and mux the current carry
  97             Ct := Shift_Right(C, S);
  98             C  := W_Mux(C,  Ct, CB and 1);
  99             -- Go to the next shiftness level
 100             S  := S * 2;
 101             B  := Shift_Right(B,  1);
 102             CB := Shift_Right(CB, 1);
 103          end loop;
 104          -- Slide in the carry from the previous shift
 105          ShiftedN(i) := ShiftedN(i) or Ni;
 106       end loop;
 107    end FZ_Quiet_ShiftLeft_SubW_Soft;
 108    
 109    
 110    -- Constant-time arbitrary Right-Shift.
 111    procedure FZ_Quiet_ShiftRight(N        : in     FZ;
 112                                  ShiftedN : in out FZ;
 113                                  Count    : in     FZBit_Index) is
 114       
 115       -- Total number of bit positions to shift by
 116       C     : constant Word     := Word(Count);
 117       
 118       -- Number of sub-Word bit positions to shift by
 119       Bits  : constant Natural  := Natural(C and (2**BitnessLog2 - 1));
 120       
 121       -- The Bitness of N's Length
 122       Wb    : constant Positive := FZ_Bitness_Log2(N);
 123       
 124       -- Number of whole-Word bitnesses to shift by
 125       Words : Word              := Shift_Right(C, BitnessLog2);
 126       
 127       -- Current 'shiftness level'
 128       S     : Indices           := 1;
 129       
 130    begin
 131       
 132       -- Subword shift first:
 133       if HaveBarrelShifter then
 134          -- If permitted, use iron shifter:
 135          FZ_ShiftRight(N, ShiftedN, Bits);
 136       else
 137          -- Otherwise, use the soft subword shifter:
 138          FZ_Quiet_ShiftRight_SubW_Soft(N, ShiftedN, Bits);
 139       end if;
 140       
 141       -- Then whole-Word shift:
 142       for i in 1 .. Wb loop
 143          
 144          declare
 145             
 146             -- Current bit of Words
 147             WordsBit : constant WBool := Words and 1;
 148             
 149          begin
 150             
 151             -- Shift at the current shiftness
 152             for i in ShiftedN'First        .. ShiftedN'Last - S loop
 153                ShiftedN(i) := W_Mux(ShiftedN(i), ShiftedN(i + S), WordsBit);
 154             end loop;
 155             
 156             -- Fill the emptiness
 157             for i in ShiftedN'Last - S + 1 .. ShiftedN'Last loop
 158                ShiftedN(i) := W_Mux(ShiftedN(i), 0,               WordsBit);
 159             end loop;
 160             
 161             -- Go to the next shiftness level
 162             S     := S * 2;
 163             Words := Shift_Right(Words, 1);
 164             
 165          end;
 166          
 167       end loop;
 168       
 169    end FZ_Quiet_ShiftRight;
 170    
 171    
 172    -- Constant-time arbitrary Left-Shift.
 173    procedure FZ_Quiet_ShiftLeft(N        : in     FZ;
 174                                 ShiftedN : in out FZ;
 175                                 Count    : in     FZBit_Index) is
 176       
 177       -- Total number of bit positions to shift by
 178       C     : constant Word     := Word(Count);
 179       
 180       -- Number of sub-Word bit positions to shift by
 181       Bits  : constant Natural  := Natural(C and (2**BitnessLog2 - 1));
 182       
 183       -- The Bitness of N's Length
 184       Wb    : constant Positive := FZ_Bitness_Log2(N);
 185       
 186       -- Number of whole-Word bitnesses to shift by
 187       Words : Word              := Shift_Right(C, BitnessLog2);
 188       
 189       -- Current 'shiftness level'
 190       S     : Indices           := 1;
 191       
 192    begin
 193       
 194       -- Subword shift first:
 195       if HaveBarrelShifter then
 196          -- If permitted, use iron shifter:
 197          FZ_ShiftLeft(N, ShiftedN, Bits);
 198       else
 199          -- Otherwise, use the soft subword shifter:
 200          FZ_Quiet_ShiftLeft_SubW_Soft(N, ShiftedN, Bits);
 201       end if;
 202       
 203       -- Then whole-Word shift:
 204       for i in 1 .. Wb loop
 205          
 206          declare
 207             
 208             -- Current bit of Words
 209             WordsBit : constant WBool := Words and 1;
 210             
 211          begin
 212             
 213             -- Shift at the current shiftness
 214             for i in reverse ShiftedN'First + S .. ShiftedN'Last loop
 215                ShiftedN(i) := W_Mux(ShiftedN(i), ShiftedN(i - S), WordsBit);
 216             end loop;
 217             
 218             -- Fill the emptiness
 219             for i in ShiftedN'First             .. ShiftedN'First + S - 1 loop
 220                ShiftedN(i) := W_Mux(ShiftedN(i), 0,               WordsBit);
 221             end loop;
 222             
 223             -- Go to the next shiftness level
 224             S     := S * 2;
 225             Words := Shift_Right(Words, 1);
 226             
 227          end;
 228          
 229       end loop;
 230       
 231    end FZ_Quiet_ShiftLeft;
 232    
 233 end FZ_QShft;