141 lines
3.6 KiB
Ada
141 lines
3.6 KiB
Ada
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
|
|
--
|
|
-- This program is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package body Spritz is
|
|
|
|
procedure Initialize (ctx : out Context) is
|
|
begin
|
|
ctx.i := 0;
|
|
ctx.j := 0;
|
|
ctx.k := 0;
|
|
ctx.z := 0;
|
|
ctx.a := 0;
|
|
ctx.w := 1;
|
|
for i in ctx.S'Range loop
|
|
ctx.S(i) := u8(i);
|
|
end loop;
|
|
end Initialize;
|
|
|
|
procedure Output (ctx : in out Context; z : out u8) is
|
|
begin
|
|
ctx.z := ctx.S(ctx.j + ctx.S(ctx.i + ctx.S(ctx.z + ctx.k)));
|
|
z := ctx.z;
|
|
end Output;
|
|
|
|
procedure Update (ctx : in out Context) is
|
|
begin
|
|
ctx.i := ctx.i + ctx.w;
|
|
ctx.j := ctx.k + ctx.S(ctx.j + ctx.S(ctx.i));
|
|
ctx.k := ctx.i + ctx.k + ctx.S(ctx.j);
|
|
Swap(ctx.S(ctx.i), ctx.S(ctx.j));
|
|
end Update;
|
|
|
|
procedure Crush (ctx : in out Context) is
|
|
begin
|
|
for v in u8 range 0 .. u8(N / 2 - 1) loop
|
|
if ctx.S(v) > ctx.S(u8(N - 1) - v) then
|
|
Swap(ctx.S(v), ctx.S(u8(N - 1) - v));
|
|
end if;
|
|
end loop;
|
|
end Crush;
|
|
|
|
procedure Whip (ctx : in out Context) is
|
|
begin
|
|
for i in 1 .. 2 * N loop
|
|
Update(ctx);
|
|
end loop;
|
|
ctx.w := ctx.w + 2;
|
|
end Whip;
|
|
|
|
procedure Shuffle (ctx : in out Context) is
|
|
begin
|
|
Whip(ctx);
|
|
Crush(ctx);
|
|
Whip(ctx);
|
|
Crush(ctx);
|
|
Whip(ctx);
|
|
ctx.a := 0;
|
|
end Shuffle;
|
|
|
|
procedure Drip (ctx : in out Context; z : out u8) is
|
|
begin
|
|
if ctx.a > 0 then
|
|
Shuffle(ctx);
|
|
end if;
|
|
Update(ctx);
|
|
Output(ctx, z);
|
|
end Drip;
|
|
|
|
procedure Squeeze (ctx : in out Context; P : out u8_Array) is
|
|
z : u8;
|
|
begin
|
|
for i in P'Range loop
|
|
Drip(ctx, z);
|
|
P(i) := z;
|
|
end loop;
|
|
end Squeeze;
|
|
|
|
procedure AbsorbStop (ctx : in out Context) is
|
|
begin
|
|
if ctx.a = u8(N / 2) then
|
|
Shuffle(ctx);
|
|
end if;
|
|
ctx.a := ctx.a + 1;
|
|
end AbsorbStop;
|
|
|
|
procedure AbsorbNibble (ctx : in out Context; x : in u8) is
|
|
begin
|
|
if ctx.a = u8(N / 2) then
|
|
Shuffle(ctx);
|
|
end if;
|
|
Swap(ctx.S(ctx.a), ctx.S(u8(N / 2) + x));
|
|
ctx.a := ctx.a + 1;
|
|
end AbsorbNibble;
|
|
|
|
procedure Absorb (ctx : in out Context; x : in u8) is
|
|
begin
|
|
AbsorbNibble(ctx, x and 15);
|
|
AbsorbNibble(ctx, Shift_Right(x, 4));
|
|
end Absorb;
|
|
|
|
procedure Absorb (ctx : in out Context; x : in u8_Array) is
|
|
begin
|
|
for i in x'Range loop
|
|
Absorb(ctx, x(i));
|
|
end loop;
|
|
end Absorb;
|
|
|
|
procedure Absorb (ctx : in out Context; x : in String) is
|
|
begin
|
|
for i in x'Range loop
|
|
Absorb(ctx, u8(Character'Pos(x(i))));
|
|
end loop;
|
|
end Absorb;
|
|
|
|
procedure Absorb (ctx : in out Context; x : in Natural) is
|
|
buf : u8_Array (1 .. Integer'Size / 8);
|
|
c : Integer := 1 + Integer'Size / 8;
|
|
t : Natural := x;
|
|
begin
|
|
while t > 0 loop
|
|
c := c - 1;
|
|
buf(c) := u8(t rem 256);
|
|
t := t / 256;
|
|
end loop;
|
|
Absorb(ctx, buf(c .. buf'Last));
|
|
end Absorb;
|
|
|
|
end Spritz;
|