raw
ffa_ch4_ffacalc         1 ------------------------------------------------------------------------------
ffa_ch4_ffacalc 2 ------------------------------------------------------------------------------
ffa_ch4_ffacalc 3 -- This file is part of 'Finite Field Arithmetic', aka 'FFA'. --
ffa_ch4_ffacalc 4 -- --
ffa_ch4_ffacalc 5 -- (C) 2017 Stanislav Datskovskiy ( www.loper-os.org ) --
ffa_ch4_ffacalc 6 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
ffa_ch4_ffacalc 7 -- --
ffa_ch4_ffacalc 8 -- You do not have, nor can you ever acquire the right to use, copy or --
ffa_ch4_ffacalc 9 -- distribute this software ; Should you use this software for any purpose, --
ffa_ch4_ffacalc 10 -- or copy and distribute it to anyone or in any manner, you are breaking --
ffa_ch4_ffacalc 11 -- the laws of whatever soi-disant jurisdiction, and you promise to --
ffa_ch4_ffacalc 12 -- continue doing so for the indefinite future. In any case, please --
ffa_ch4_ffacalc 13 -- always : read and understand any software ; verify any PGP signatures --
ffa_ch4_ffacalc 14 -- that you use - for any purpose. --
ffa_ch4_ffacalc 15 -- --
ffa_ch4_ffacalc 16 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
ffa_ch4_ffacalc 17 ------------------------------------------------------------------------------
ffa_ch4_ffacalc 18 ------------------------------------------------------------------------------
ffa_ch4_ffacalc 19
ffa_ch4_ffacalc 20 -- Basics
ffa_ch8_randomism 21 with OS; use OS;
ffa_ch8_randomism 22 with CmdLine; use CmdLine;
ffa_ch4_ffacalc 23
ffa_ch4_ffacalc 24 -- FFA
ffa_ch4_ffacalc 25 with FZ_Lim; use FZ_Lim;
ffa_ch4_ffacalc 26 with Words; use Words;
ffa_ch4_ffacalc 27 with W_Pred; use W_Pred;
ffa_ch4_ffacalc 28 with FZ_Type; use FZ_Type;
ffa_ch4_ffacalc 29 with FZ_Basic; use FZ_Basic;
ffa_ch4_ffacalc 30 with FZ_Arith; use FZ_Arith;
ffa_ch4_ffacalc 31 with FZ_Cmp; use FZ_Cmp;
ffa_ch4_ffacalc 32 with FZ_Pred; use FZ_Pred;
ffa_ch4_ffacalc 33 with FZ_BitOp; use FZ_BitOp;
ffa_ch4_ffacalc 34 with FZ_Shift; use FZ_Shift;
ffa_ch5_egypt 35 with FZ_Divis; use FZ_Divis;
ffa_ch5_egypt 36 with FZ_Mul; use FZ_Mul;
ffa_ch6_simplest_rsa 37 with FZ_ModEx; use FZ_ModEx;
ffa_ch4_ffacalc 38
ffa_ch4_ffacalc 39 -- For Output
ffa_ch4_ffacalc 40 with FFA_IO; use FFA_IO;
ffa_ch4_ffacalc 41
ffa_ch8_randomism 42 -- For RNG:
ffa_ch8_randomism 43 with FFA_RNG; use FFA_RNG;
ffa_ch8_randomism 44
ffa_ch8_randomism 45
ffa_ch4_ffacalc 46 procedure FFA_Calc is
ffa_ch4_ffacalc 47
ffa_ch8_randomism 48 Width : Positive; -- Desired FFA Width
ffa_ch8_randomism 49 Height : Positive; -- Desired Height of Stack
ffa_ch8_randomism 50 RNG : RNG_Device; -- The active RNG device.
ffa_ch4_ffacalc 51
ffa_ch4_ffacalc 52 begin
ffa_ch8_randomism 53 if Arg_Count < 3 or Arg_Count > 4 then
ffa_ch8_randomism 54 Eggog("Usage: ./ffa_calc WIDTH HEIGHT [/dev/rng]");
ffa_ch4_ffacalc 55 end if;
ffa_ch4_ffacalc 56
ffa_ch4_ffacalc 57 declare
ffa_ch4_ffacalc 58 Arg1 : CmdLineArg;
ffa_ch4_ffacalc 59 Arg2 : CmdLineArg;
ffa_ch4_ffacalc 60 begin
ffa_ch4_ffacalc 61 -- Get commandline args:
ffa_ch4_ffacalc 62 Get_Argument(1, Arg1); -- First arg
ffa_ch4_ffacalc 63 Get_Argument(2, Arg2); -- Second arg
ffa_ch4_ffacalc 64
ffa_ch8_randomism 65 if Arg_Count = 4 then
ffa_ch8_randomism 66 -- RNG was specified:
ffa_ch8_randomism 67 declare
ffa_ch8_randomism 68 Arg3 : CmdLineArg;
ffa_ch8_randomism 69 begin
ffa_ch8_randomism 70 Get_Argument(3, Arg3); -- Third arg (optional)
ffa_ch8_randomism 71
ffa_ch8_randomism 72 -- Ada.Sequential_IO chokes on paths with trailing whitespace!
ffa_ch8_randomism 73 -- So we have to give it a trimmed path. But we can't use
ffa_ch8_randomism 74 -- Ada.Strings.Fixed.Trim, because it suffers from
ffa_ch8_randomism 75 -- SecondaryStackism-syphilis. Instead we are stuck doing this:
ffa_ch8_randomism 76 Init_RNG(RNG, Arg3(Arg3'First .. Len_Arg(3)));
ffa_ch8_randomism 77 end;
ffa_ch8_randomism 78 else
ffa_ch8_randomism 79 -- RNG was NOT specified:
ffa_ch8_randomism 80 Init_RNG(RNG); -- Use the machine default then
ffa_ch8_randomism 81 end if;
ffa_ch8_randomism 82
ffa_ch4_ffacalc 83 -- Parse into Positives:
ffa_ch4_ffacalc 84 Width := Positive'Value(Arg1);
ffa_ch4_ffacalc 85 Height := Positive'Value(Arg2);
ffa_ch4_ffacalc 86 exception
ffa_ch4_ffacalc 87 when others =>
ffa_ch4_ffacalc 88 Eggog("Invalid arguments!");
ffa_ch4_ffacalc 89 end;
ffa_ch4_ffacalc 90
ffa_ch4_ffacalc 91 -- Test if proposed Width is permissible:
ffa_ch4_ffacalc 92 if not FZ_Valid_Bitness_P(Width) then
ffa_ch4_ffacalc 93 Eggog("Invalid Width: " & FZ_Validity_Rule_Doc);
ffa_ch4_ffacalc 94 end if;
ffa_ch4_ffacalc 95
ffa_ch4_ffacalc 96 -- The Calculator itself:
ffa_ch4_ffacalc 97 declare
ffa_ch4_ffacalc 98
ffa_ch4_ffacalc 99 -- The number of Words required to make a FZ of the given Bitness.
ffa_ch4_ffacalc 100 Wordness : Indices := Indices(Width / Bitness);
ffa_ch4_ffacalc 101
ffa_ch4_ffacalc 102 --------------------------------------------------------
ffa_ch4_ffacalc 103 -- State --
ffa_ch4_ffacalc 104 --------------------------------------------------------
ffa_ch4_ffacalc 105 -- The Stack:
ffa_ch4_ffacalc 106 subtype Stack_Positions is Natural range 0 .. Height;
ffa_ch4_ffacalc 107 type Stacks is array(Stack_Positions range <>) of FZ(1 .. Wordness);
ffa_ch4_ffacalc 108 Stack : Stacks(Stack_Positions'Range);
ffa_ch4_ffacalc 109
ffa_ch4_ffacalc 110 -- Stack Pointer:
ffa_ch4_ffacalc 111 SP : Stack_Positions := Stack_Positions'First;
ffa_ch4_ffacalc 112
ffa_ch4_ffacalc 113 -- Carry/Borrow Flag:
ffa_ch4_ffacalc 114 Flag : WBool := 0;
ffa_ch4_ffacalc 115
ffa_ch4_ffacalc 116 -- Odometer:
ffa_ch4_ffacalc 117 Pos : Natural := 0;
ffa_ch4_ffacalc 118
ffa_ch4_ffacalc 119 -- The current levels of the three types of nestedness:
ffa_ch4_ffacalc 120 QuoteLevel : Natural := 0;
ffa_ch4_ffacalc 121 CommLevel : Natural := 0;
ffa_ch4_ffacalc 122 CondLevel : Natural := 0;
ffa_ch4_ffacalc 123 --------------------------------------------------------
ffa_ch4_ffacalc 124
ffa_ch4_ffacalc 125
ffa_ch4_ffacalc 126 -- Clear the stack and set SP to bottom.
ffa_ch4_ffacalc 127 procedure Zap is
ffa_ch4_ffacalc 128 begin
ffa_ch4_ffacalc 129 -- Clear the stack
ffa_ch4_ffacalc 130 for i in Stack'Range loop
ffa_ch4_ffacalc 131 FZ_Clear(Stack(i));
ffa_ch4_ffacalc 132 end loop;
ffa_ch4_ffacalc 133 -- Set SP to bottom
ffa_ch4_ffacalc 134 SP := Stack_Positions'First;
ffa_ch4_ffacalc 135 -- Clear Overflow flag
ffa_ch4_ffacalc 136 Flag := 0;
ffa_ch4_ffacalc 137 end Zap;
ffa_ch4_ffacalc 138
ffa_ch4_ffacalc 139
ffa_ch4_ffacalc 140 -- Report a fatal error condition at the current symbol
ffa_ch4_ffacalc 141 procedure E(S : in String) is
ffa_ch4_ffacalc 142 begin
ffa_ch4_ffacalc 143 Eggog("Pos:" & Natural'Image(Pos) & ": " & S);
ffa_ch4_ffacalc 144 end E;
ffa_ch4_ffacalc 145
ffa_ch4_ffacalc 146
ffa_ch4_ffacalc 147 -- Move SP up
ffa_ch4_ffacalc 148 procedure Push is
ffa_ch4_ffacalc 149 begin
ffa_ch4_ffacalc 150 if SP = Stack_Positions'Last then
ffa_ch4_ffacalc 151 E("Stack Overflow!");
ffa_ch4_ffacalc 152 else
ffa_ch4_ffacalc 153 SP := SP + 1;
ffa_ch4_ffacalc 154 end if;
ffa_ch4_ffacalc 155 end Push;
ffa_ch4_ffacalc 156
ffa_ch4_ffacalc 157
ffa_ch4_ffacalc 158 -- Discard the top of the stack
ffa_ch4_ffacalc 159 procedure Drop is
ffa_ch4_ffacalc 160 begin
ffa_ch4_ffacalc 161 FZ_Clear(Stack(SP));
ffa_ch4_ffacalc 162 SP := SP - 1;
ffa_ch4_ffacalc 163 end Drop;
ffa_ch4_ffacalc 164
ffa_ch4_ffacalc 165
ffa_ch4_ffacalc 166 -- Check if stack has the necessary N items
ffa_ch4_ffacalc 167 procedure Want(N : in Positive) is
ffa_ch4_ffacalc 168 begin
ffa_ch4_ffacalc 169 if SP < N then
ffa_ch4_ffacalc 170 E("Stack Underflow!");
ffa_ch4_ffacalc 171 end if;
ffa_ch4_ffacalc 172 end Want;
ffa_ch4_ffacalc 173
ffa_ch4_ffacalc 174
ffa_ch5_egypt 175 -- Ensure that a divisor is not zero
ffa_ch5_egypt 176 procedure MustNotZero(D : in FZ) is
ffa_ch5_egypt 177 begin
ffa_ch5_egypt 178 if FZ_ZeroP(D) = 1 then
ffa_ch5_egypt 179 E("Division by Zero!");
ffa_ch5_egypt 180 end if;
ffa_ch5_egypt 181 end MustNotZero;
ffa_ch5_egypt 182
ffa_ch5_egypt 183
ffa_ch4_ffacalc 184 -- Slide a new hex digit into the FZ on top of stack
ffa_ch4_ffacalc 185 procedure Ins_Hex_Digit(N : in out FZ;
ffa_ch4_ffacalc 186 D : in Nibble) is
ffa_ch4_ffacalc 187 Overflow : Word := 0;
ffa_ch4_ffacalc 188 begin
ffa_ch4_ffacalc 189 -- Make room in this FZ for one additional hex digit
ffa_ch4_ffacalc 190 FZ_ShiftLeft_O(N => N,
ffa_ch4_ffacalc 191 ShiftedN => N,
ffa_ch4_ffacalc 192 Count => 4,
ffa_ch4_ffacalc 193 Overflow => Overflow);
ffa_ch4_ffacalc 194
ffa_ch4_ffacalc 195 -- Constants which exceed the Width are forbidden:
ffa_ch4_ffacalc 196 if W_NZeroP(Overflow) = 1 then
ffa_ch4_ffacalc 197 E("Constant Exceeds Bitness!");
ffa_ch4_ffacalc 198 end if;
ffa_ch4_ffacalc 199
ffa_ch4_ffacalc 200 -- Set the new digit
ffa_ch4_ffacalc 201 FZ_Or_W(N, D);
ffa_ch4_ffacalc 202 end;
ffa_ch4_ffacalc 203
ffa_ch4_ffacalc 204
ffa_ch4_ffacalc 205 -- Execute a Normal Op
ffa_ch4_ffacalc 206 procedure Op_Normal(C : in Character) is
ffa_ch4_ffacalc 207
ffa_ch4_ffacalc 208 -- Over/underflow output from certain ops
ffa_ch4_ffacalc 209 F : Word;
ffa_ch4_ffacalc 210
ffa_ch4_ffacalc 211 begin
ffa_ch4_ffacalc 212
ffa_ch4_ffacalc 213 case C is
ffa_ch4_ffacalc 214
ffa_ch4_ffacalc 215 --------------
ffa_ch4_ffacalc 216 -- Stickies --
ffa_ch4_ffacalc 217 --------------
ffa_ch4_ffacalc 218 -- Enter Commented
ffa_ch4_ffacalc 219 when '(' =>
ffa_ch4_ffacalc 220 CommLevel := 1;
ffa_ch4_ffacalc 221
ffa_ch4_ffacalc 222 -- Exit Commented (but we aren't in it!)
ffa_ch4_ffacalc 223 when ')' =>
ffa_ch4_ffacalc 224 E("Mismatched close-comment parenthesis !");
ffa_ch4_ffacalc 225
ffa_ch4_ffacalc 226 -- Enter Quoted
ffa_ch4_ffacalc 227 when '[' =>
ffa_ch4_ffacalc 228 QuoteLevel := 1;
ffa_ch4_ffacalc 229
ffa_ch4_ffacalc 230 -- Exit Quoted (but we aren't in it!)
ffa_ch4_ffacalc 231 when ']' =>
ffa_ch4_ffacalc 232 E("Mismatched close-quote bracket !");
ffa_ch4_ffacalc 233
ffa_ch4_ffacalc 234 -- Enter a ~taken~ Conditional branch:
ffa_ch4_ffacalc 235 when '{' =>
ffa_ch4_ffacalc 236 Want(1);
ffa_ch4_ffacalc 237 if FZ_ZeroP(Stack(SP)) = 1 then
ffa_ch4_ffacalc 238 CondLevel := 1;
ffa_ch4_ffacalc 239 end if;
ffa_ch4_ffacalc 240 Drop;
ffa_ch4_ffacalc 241
ffa_ch4_ffacalc 242 -- Exit from a ~non-taken~ Conditional branch:
ffa_ch4_ffacalc 243 -- ... we push a 0, to suppress the 'else' clause
ffa_ch4_ffacalc 244 when '}' =>
ffa_ch4_ffacalc 245 Push;
ffa_ch4_ffacalc 246 WBool_To_FZ(0, Stack(SP));
ffa_ch4_ffacalc 247
ffa_ch4_ffacalc 248 ----------------
ffa_ch4_ffacalc 249 -- Immediates --
ffa_ch4_ffacalc 250 ----------------
ffa_ch4_ffacalc 251
ffa_ch4_ffacalc 252 -- These operate on the FZ ~currently~ at top of the stack;
ffa_ch4_ffacalc 253 -- and this means that the stack may NOT be empty.
ffa_ch4_ffacalc 254
ffa_ch4_ffacalc 255 when '0' .. '9' =>
ffa_ch4_ffacalc 256 Want(1);
ffa_ch4_ffacalc 257 Ins_Hex_Digit(Stack(SP),
ffa_ch4_ffacalc 258 Character'Pos(C) - Character'Pos('0'));
ffa_ch4_ffacalc 259
ffa_ch4_ffacalc 260 when 'A' .. 'F' =>
ffa_ch4_ffacalc 261 Want(1);
ffa_ch4_ffacalc 262 Ins_Hex_Digit(Stack(SP),
ffa_ch4_ffacalc 263 10 + Character'Pos(C) - Character'Pos('A'));
ffa_ch4_ffacalc 264
ffa_ch4_ffacalc 265 when 'a' .. 'f' =>
ffa_ch4_ffacalc 266 Want(1);
ffa_ch4_ffacalc 267 Ins_Hex_Digit(Stack(SP),
ffa_ch4_ffacalc 268 10 + Character'Pos(C) - Character'Pos('a'));
ffa_ch4_ffacalc 269
ffa_ch4_ffacalc 270 ------------------
ffa_ch4_ffacalc 271 -- Stack Motion --
ffa_ch4_ffacalc 272 ------------------
ffa_ch4_ffacalc 273
ffa_ch4_ffacalc 274 -- Push a 0 onto the stack
ffa_ch4_ffacalc 275 when '.' =>
ffa_ch4_ffacalc 276 Push;
ffa_ch4_ffacalc 277 FZ_Clear(Stack(SP));
ffa_ch4_ffacalc 278
ffa_ch4_ffacalc 279 -- Dup
ffa_ch4_ffacalc 280 when '"' =>
ffa_ch4_ffacalc 281 Want(1);
ffa_ch4_ffacalc 282 Push;
ffa_ch4_ffacalc 283 Stack(SP) := Stack(SP - 1);
ffa_ch4_ffacalc 284
ffa_ch4_ffacalc 285 -- Drop
ffa_ch4_ffacalc 286 when '_' =>
ffa_ch4_ffacalc 287 Want(1);
ffa_ch4_ffacalc 288 Drop;
ffa_ch4_ffacalc 289
ffa_ch4_ffacalc 290 -- Swap
ffa_ch4_ffacalc 291 when ''' =>
ffa_ch4_ffacalc 292 Want(2);
ffa_ch4_ffacalc 293 FZ_Swap(Stack(SP), Stack(SP - 1));
ffa_ch4_ffacalc 294
ffa_ch4_ffacalc 295 -- Over
ffa_ch4_ffacalc 296 when '`' =>
ffa_ch4_ffacalc 297 Want(2);
ffa_ch4_ffacalc 298 Push;
ffa_ch4_ffacalc 299 Stack(SP) := Stack(SP - 2);
ffa_ch4_ffacalc 300
ffa_ch4_ffacalc 301 ----------------
ffa_ch4_ffacalc 302 -- Predicates --
ffa_ch4_ffacalc 303 ----------------
ffa_ch4_ffacalc 304
ffa_ch4_ffacalc 305 -- Equality
ffa_ch4_ffacalc 306 when '=' =>
ffa_ch4_ffacalc 307 Want(2);
ffa_ch4_ffacalc 308 WBool_To_FZ(FZ_Eqp(X => Stack(SP),
ffa_ch4_ffacalc 309 Y => Stack(SP - 1)),
ffa_ch4_ffacalc 310 Stack(SP - 1));
ffa_ch4_ffacalc 311 Drop;
ffa_ch4_ffacalc 312
ffa_ch4_ffacalc 313 -- Less-Than
ffa_ch4_ffacalc 314 when '<' =>
ffa_ch4_ffacalc 315 Want(2);
ffa_ch4_ffacalc 316 WBool_To_FZ(FZ_LessThanP(X => Stack(SP - 1),
ffa_ch4_ffacalc 317 Y => Stack(SP)),
ffa_ch4_ffacalc 318 Stack(SP - 1));
ffa_ch4_ffacalc 319 Drop;
ffa_ch4_ffacalc 320
ffa_ch4_ffacalc 321 -- Greater-Than
ffa_ch4_ffacalc 322 when '>' =>
ffa_ch4_ffacalc 323 Want(2);
ffa_ch4_ffacalc 324 WBool_To_FZ(FZ_GreaterThanP(X => Stack(SP - 1),
ffa_ch4_ffacalc 325 Y => Stack(SP)),
ffa_ch4_ffacalc 326 Stack(SP - 1));
ffa_ch4_ffacalc 327 Drop;
ffa_ch4_ffacalc 328
ffa_ch4_ffacalc 329 ----------------
ffa_ch4_ffacalc 330 -- Arithmetic --
ffa_ch4_ffacalc 331 ----------------
ffa_ch4_ffacalc 332
ffa_ch4_ffacalc 333 -- Subtract
ffa_ch4_ffacalc 334 when '-' =>
ffa_ch4_ffacalc 335 Want(2);
ffa_ch4_ffacalc 336 FZ_Sub(X => Stack(SP - 1),
ffa_ch4_ffacalc 337 Y => Stack(SP),
ffa_ch4_ffacalc 338 Difference => Stack(SP - 1),
ffa_ch4_ffacalc 339 Underflow => F);
ffa_ch4_ffacalc 340 Flag := W_NZeroP(F);
ffa_ch4_ffacalc 341 Drop;
ffa_ch4_ffacalc 342
ffa_ch4_ffacalc 343 -- Add
ffa_ch4_ffacalc 344 when '+' =>
ffa_ch4_ffacalc 345 Want(2);
ffa_ch4_ffacalc 346 FZ_Add(X => Stack(SP - 1),
ffa_ch4_ffacalc 347 Y => Stack(SP),
ffa_ch4_ffacalc 348 Sum => Stack(SP - 1),
ffa_ch4_ffacalc 349 Overflow => F);
ffa_ch4_ffacalc 350 Flag := W_NZeroP(F);
ffa_ch4_ffacalc 351 Drop;
ffa_ch4_ffacalc 352
ffa_ch5_egypt 353 -- Divide and give Quotient and Remainder
ffa_ch5_egypt 354 when '\' =>
ffa_ch5_egypt 355 Want(2);
ffa_ch5_egypt 356 MustNotZero(Stack(SP));
ffa_ch5_egypt 357 FZ_IDiv(Dividend => Stack(SP - 1),
ffa_ch5_egypt 358 Divisor => Stack(SP),
ffa_ch5_egypt 359 Quotient => Stack(SP - 1),
ffa_ch5_egypt 360 Remainder => Stack(SP));
ffa_ch5_egypt 361
ffa_ch5_egypt 362 -- Divide and give Quotient only
ffa_ch5_egypt 363 when '/' =>
ffa_ch5_egypt 364 Want(2);
ffa_ch5_egypt 365 MustNotZero(Stack(SP));
ffa_ch5_egypt 366 FZ_Div(Dividend => Stack(SP - 1),
ffa_ch5_egypt 367 Divisor => Stack(SP),
ffa_ch5_egypt 368 Quotient => Stack(SP - 1));
ffa_ch5_egypt 369 Drop;
ffa_ch5_egypt 370
ffa_ch5_egypt 371 -- Divide and give Remainder only
ffa_ch5_egypt 372 when '%' =>
ffa_ch5_egypt 373 Want(2);
ffa_ch5_egypt 374 MustNotZero(Stack(SP));
ffa_ch5_egypt 375 FZ_Mod(Dividend => Stack(SP - 1),
ffa_ch5_egypt 376 Divisor => Stack(SP),
ffa_ch5_egypt 377 Remainder => Stack(SP - 1));
ffa_ch5_egypt 378 Drop;
ffa_ch5_egypt 379
ffa_ch5_egypt 380 -- Multiply, give bottom and top halves
ffa_ch5_egypt 381 when '*' =>
ffa_ch5_egypt 382 Want(2);
ffa_ch10_karatsuba 383 FZ_Mult(X => Stack(SP - 1),
ffa_ch10_karatsuba 384 Y => Stack(SP),
ffa_ch10_karatsuba 385 XY_Lo => Stack(SP - 1),
ffa_ch10_karatsuba 386 XY_Hi => Stack(SP));
ffa_ch5_egypt 387
ffa_ch6_simplest_rsa 388 -- Modular Multiplication
ffa_ch6_simplest_rsa 389 when 'M' =>
ffa_ch6_simplest_rsa 390 Want(3);
ffa_ch6_simplest_rsa 391 MustNotZero(Stack(SP));
ffa_ch6_simplest_rsa 392 FZ_Mod_Mul(X => Stack(SP - 2),
ffa_ch6_simplest_rsa 393 Y => Stack(SP - 1),
ffa_ch6_simplest_rsa 394 Modulus => Stack(SP),
ffa_ch6_simplest_rsa 395 Product => Stack(SP - 2));
ffa_ch6_simplest_rsa 396 Drop;
ffa_ch6_simplest_rsa 397 Drop;
ffa_ch6_simplest_rsa 398
ffa_ch6_simplest_rsa 399 -- Modular Exponentiation
ffa_ch6_simplest_rsa 400 when 'X' =>
ffa_ch6_simplest_rsa 401 Want(3);
ffa_ch6_simplest_rsa 402 MustNotZero(Stack(SP));
ffa_ch6_simplest_rsa 403 FZ_Mod_Exp(Base => Stack(SP - 2),
ffa_ch6_simplest_rsa 404 Exponent => Stack(SP - 1),
ffa_ch6_simplest_rsa 405 Modulus => Stack(SP),
ffa_ch6_simplest_rsa 406 Result => Stack(SP - 2));
ffa_ch6_simplest_rsa 407 Drop;
ffa_ch6_simplest_rsa 408 Drop;
ffa_ch6_simplest_rsa 409
ffa_ch4_ffacalc 410 -----------------
ffa_ch4_ffacalc 411 -- Bitwise Ops --
ffa_ch4_ffacalc 412 -----------------
ffa_ch4_ffacalc 413
ffa_ch4_ffacalc 414 -- Bitwise-And
ffa_ch4_ffacalc 415 when '&' =>
ffa_ch4_ffacalc 416 Want(2);
ffa_ch4_ffacalc 417 FZ_And(X => Stack(SP - 1),
ffa_ch4_ffacalc 418 Y => Stack(SP),
ffa_ch4_ffacalc 419 Result => Stack(SP - 1));
ffa_ch4_ffacalc 420 Drop;
ffa_ch4_ffacalc 421
ffa_ch4_ffacalc 422 -- Bitwise-Or
ffa_ch4_ffacalc 423 when '|' =>
ffa_ch4_ffacalc 424 Want(2);
ffa_ch4_ffacalc 425 FZ_Or(X => Stack(SP - 1),
ffa_ch4_ffacalc 426 Y => Stack(SP),
ffa_ch4_ffacalc 427 Result => Stack(SP - 1));
ffa_ch4_ffacalc 428 Drop;
ffa_ch4_ffacalc 429
ffa_ch4_ffacalc 430 -- Bitwise-Xor
ffa_ch4_ffacalc 431 when '^' =>
ffa_ch4_ffacalc 432 Want(2);
ffa_ch4_ffacalc 433 FZ_Xor(X => Stack(SP - 1),
ffa_ch4_ffacalc 434 Y => Stack(SP),
ffa_ch4_ffacalc 435 Result => Stack(SP - 1));
ffa_ch4_ffacalc 436 Drop;
ffa_ch4_ffacalc 437
ffa_ch4_ffacalc 438 -- Bitwise-Not (1s-Complement)
ffa_ch4_ffacalc 439 when '~' =>
ffa_ch4_ffacalc 440 Want(1);
ffa_ch4_ffacalc 441 FZ_Not(Stack(SP), Stack(SP));
ffa_ch4_ffacalc 442
ffa_ch4_ffacalc 443 -----------
ffa_ch4_ffacalc 444 -- Other --
ffa_ch4_ffacalc 445 -----------
ffa_ch4_ffacalc 446
ffa_ch8_randomism 447 -- Push a FZ of RNGolade onto the stack
ffa_ch8_randomism 448 when '?' =>
ffa_ch8_randomism 449 Push;
ffa_ch8_randomism 450 FZ_Clear(Stack(SP));
ffa_ch8_randomism 451 FZ_Random(RNG, Stack(SP));
ffa_ch8_randomism 452
ffa_ch4_ffacalc 453 -- mUx
ffa_ch4_ffacalc 454 when 'U' =>
ffa_ch4_ffacalc 455 Want(3);
ffa_ch4_ffacalc 456 FZ_Mux(X => Stack(SP - 2),
ffa_ch4_ffacalc 457 Y => Stack(SP - 1),
ffa_ch4_ffacalc 458 Result => Stack(SP - 2),
ffa_ch4_ffacalc 459 Sel => FZ_NZeroP(Stack(SP)));
ffa_ch4_ffacalc 460 Drop;
ffa_ch4_ffacalc 461 Drop;
ffa_ch4_ffacalc 462
ffa_ch4_ffacalc 463 -- Put the Overflow flag on the stack
ffa_ch4_ffacalc 464 when 'O' =>
ffa_ch4_ffacalc 465 Push;
ffa_ch4_ffacalc 466 WBool_To_FZ(Flag, Stack(SP));
ffa_ch4_ffacalc 467
ffa_ch4_ffacalc 468 -- Print the FZ on the top of the stack
ffa_ch4_ffacalc 469 when '#' =>
ffa_ch4_ffacalc 470 Want(1);
ffa_ch4_ffacalc 471 Dump(Stack(SP));
ffa_ch4_ffacalc 472 Drop;
ffa_ch4_ffacalc 473
ffa_ch4_ffacalc 474 -- Zap (reset)
ffa_ch4_ffacalc 475 when 'Z' =>
ffa_ch4_ffacalc 476 Zap;
ffa_ch4_ffacalc 477
ffa_ch4_ffacalc 478 -- Quit with Stack Trace
ffa_ch4_ffacalc 479 when 'Q' =>
ffa_ch4_ffacalc 480 for I in reverse Stack'First + 1 .. SP loop
ffa_ch4_ffacalc 481 Dump(Stack(I));
ffa_ch4_ffacalc 482 end loop;
ffa_ch4_ffacalc 483 Quit(0);
ffa_ch4_ffacalc 484
ffa_ch4_ffacalc 485 ----------
ffa_ch4_ffacalc 486 -- NOPs --
ffa_ch4_ffacalc 487 ----------
ffa_ch4_ffacalc 488
ffa_ch4_ffacalc 489 -- Ops we have not yet spoken of -- do nothing
ffa_ch4_ffacalc 490 when others =>
ffa_ch4_ffacalc 491 null;
ffa_ch4_ffacalc 492
ffa_ch4_ffacalc 493 end case;
ffa_ch4_ffacalc 494
ffa_ch4_ffacalc 495 end Op_Normal;
ffa_ch4_ffacalc 496
ffa_ch4_ffacalc 497
ffa_ch4_ffacalc 498 -- Process a Symbol
ffa_ch4_ffacalc 499 procedure Op(C : in Character) is
ffa_ch4_ffacalc 500 begin
ffa_ch4_ffacalc 501 -- First, see whether we are in a state of nestedness:
ffa_ch4_ffacalc 502
ffa_ch4_ffacalc 503 -- ... in a Comment block:
ffa_ch4_ffacalc 504 if CommLevel > 0 then
ffa_ch4_ffacalc 505 case C is
ffa_ch4_ffacalc 506 when ')' => -- Drop a nesting level:
ffa_ch4_ffacalc 507 CommLevel := CommLevel - 1;
ffa_ch4_ffacalc 508 when '(' => -- Add a nesting level:
ffa_ch4_ffacalc 509 CommLevel := CommLevel + 1;
ffa_ch4_ffacalc 510 when others =>
ffa_ch4_ffacalc 511 null; -- Other symbols have no effect at all
ffa_ch4_ffacalc 512 end case;
ffa_ch4_ffacalc 513
ffa_ch4_ffacalc 514 -- ... in a Quote block:
ffa_ch4_ffacalc 515 elsif QuoteLevel > 0 then
ffa_ch4_ffacalc 516 case C is
ffa_ch4_ffacalc 517 when ']' => -- Drop a nesting level:
ffa_ch4_ffacalc 518 QuoteLevel := QuoteLevel - 1;
ffa_ch4_ffacalc 519 when '[' => -- Add a nesting level:
ffa_ch4_ffacalc 520 QuoteLevel := QuoteLevel + 1;
ffa_ch4_ffacalc 521 when others =>
ffa_ch4_ffacalc 522 null; -- Other symbols have no effect on the level
ffa_ch4_ffacalc 523 end case;
ffa_ch4_ffacalc 524
ffa_ch4_ffacalc 525 -- If we aren't the mode-exiting ']', print current symbol:
ffa_ch4_ffacalc 526 if QuoteLevel > 0 then
ffa_ch4_ffacalc 527 Write_Char(C);
ffa_ch4_ffacalc 528 end if;
ffa_ch4_ffacalc 529
ffa_ch4_ffacalc 530 --- ... in a ~taken~ Conditional branch:
ffa_ch4_ffacalc 531 elsif CondLevel > 0 then
ffa_ch4_ffacalc 532 case C is
ffa_ch4_ffacalc 533 when '}' => -- Drop a nesting level:
ffa_ch4_ffacalc 534 CondLevel := CondLevel - 1;
ffa_ch4_ffacalc 535
ffa_ch4_ffacalc 536 -- If we exited the Conditional as a result,
ffa_ch4_ffacalc 537 -- we push a 1 to trigger the possible 'else' clause:
ffa_ch4_ffacalc 538 if CondLevel = 0 then
ffa_ch4_ffacalc 539 Push;
ffa_ch4_ffacalc 540 WBool_To_FZ(1, Stack(SP));
ffa_ch4_ffacalc 541 end if;
ffa_ch4_ffacalc 542
ffa_ch4_ffacalc 543 when '{' => -- Add a nesting level:
ffa_ch4_ffacalc 544 CondLevel := CondLevel + 1;
ffa_ch4_ffacalc 545 when others =>
ffa_ch4_ffacalc 546 null; -- Other symbols have no effect on the level
ffa_ch4_ffacalc 547 end case;
ffa_ch4_ffacalc 548 else
ffa_ch4_ffacalc 549 -- This is a Normal Op, so proceed with the normal rules.
ffa_ch4_ffacalc 550 Op_Normal(C);
ffa_ch4_ffacalc 551 end if;
ffa_ch4_ffacalc 552
ffa_ch4_ffacalc 553 end Op;
ffa_ch4_ffacalc 554
ffa_ch4_ffacalc 555
ffa_ch4_ffacalc 556 -- Current Character
ffa_ch4_ffacalc 557 C : Character;
ffa_ch4_ffacalc 558
ffa_ch4_ffacalc 559 begin
ffa_ch4_ffacalc 560 -- Reset the Calculator
ffa_ch4_ffacalc 561 Zap;
ffa_ch4_ffacalc 562 -- Process characters until EOF:
ffa_ch4_ffacalc 563 loop
ffa_ch4_ffacalc 564 if Read_Char(C) then
ffa_ch4_ffacalc 565 -- Execute Op:
ffa_ch4_ffacalc 566 Op(C);
ffa_ch4_ffacalc 567 -- Advance Odometer
ffa_ch4_ffacalc 568 Pos := Pos + 1;
ffa_ch4_ffacalc 569 else
ffa_ch4_ffacalc 570 Zap;
ffa_ch4_ffacalc 571 Quit(0); -- if EOF, we're done
ffa_ch4_ffacalc 572 end if;
ffa_ch4_ffacalc 573 end loop;
ffa_ch4_ffacalc 574 end;
ffa_ch4_ffacalc 575
ffa_ch4_ffacalc 576 end FFA_Calc;