-- Copyright (C) 2015 Daniel Otte -- -- 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 . 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;