1 ------------------------------------------------------------------------------ 2 ------------------------------------------------------------------------------ 3 -- This file is part of 'Finite Field Arithmetic', aka 'FFA'. -- 4 -- -- 5 -- (C) 2019 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 Words; use Words; 21 with FZ_Type; use FZ_Type; 22 23 with W_Pred; 24 25 with FZ_Lim; 26 with FZ_Basic; 27 with FZ_IO; 28 with FZ_Cmp; 29 with FZ_Pred; 30 with FZ_BitOp; 31 with FZ_Divis; 32 with FZ_ModEx; 33 with FZ_Measr; 34 with FZ_QShft; 35 with FZ_LoMul; 36 with FZ_Prime; 37 38 39 -- FFA Exports 40 package FFA is 41 42 pragma Pure; 43 44 ---------------------------------------------------------------------------- 45 --- Current 'deg. Kelvin' Version of FFA 46 ---------------------------------------------------------------------------- 47 48 FFA_K_Version : constant Natural := 199; 49 50 ---------------------------------------------------------------------------- 51 --- Fundamental Types and Sizes 52 ---------------------------------------------------------------------------- 53 54 subtype Word is Words.Word; 55 subtype WBool is Words.WBool; 56 57 subtype Nibble is Words.Nibble; 58 59 subtype FZ is FZ_Type.FZ; 60 subtype Indices is FZ_Type.Indices; 61 subtype FZBit_Index is FZ_Type.FZBit_Index; 62 63 subtype Char_Count is FZ_IO.Char_Count; 64 65 Bitness : Positive renames Words.Bitness; 66 67 ---------------------------------------------------------------------------- 68 --- Word Predicates 69 ---------------------------------------------------------------------------- 70 71 -- Return 1 if N is equal to 0; otherwise return 0. 72 function FFA_Word_ZeroP(N : in Word) return WBool 73 renames W_Pred.W_ZeroP; 74 75 -- Return 1 if N is unequal to 0; otherwise return 0. 76 function FFA_Word_NZeroP(N : in Word) return WBool 77 renames W_Pred.W_NZeroP; 78 79 -- Return WBool-complement of N. 80 function FFA_Word_Not(N : in WBool) return WBool 81 renames W_Pred.W_Not; 82 83 -- Return 1 if N is odd; otherwise return 0. 84 function FFA_Word_OddP(N : in Word) return WBool 85 renames W_Pred.W_OddP; 86 87 -- Return 1 if A is equal to B ; otherwise return 0. 88 function FFA_Word_EqP(A : in Word; B : in Word) return WBool 89 renames W_Pred.W_EqP; 90 91 ---------------------------------------------------------------------------- 92 --- FZ Limits 93 ---------------------------------------------------------------------------- 94 95 FFA_Validity_Rule_Doc : String renames FZ_Lim.FZ_Validity_Rule_Doc; 96 97 -- Determine if a proposed FFA Bitness is valid. 98 function FFA_FZ_Valid_Bitness_P(B : in Positive) return Boolean 99 renames FZ_Lim.FZ_Valid_Bitness_P; 100 101 ---------------------------------------------------------------------------- 102 --- FZ Basics 103 ---------------------------------------------------------------------------- 104 105 -- Determine the Bitness of N 106 function FFA_FZ_Bitness(N : in FZ) return Bit_Count 107 renames FZ_Basic.FZ_Bitness; 108 109 -- N := 0 110 procedure FFA_FZ_Clear(N : out FZ) 111 renames FZ_Basic.FZ_Clear; 112 113 -- Set given FZ to a given truth value 114 procedure FFA_WBool_To_FZ(V : in WBool; N : out FZ) 115 renames FZ_Basic.WBool_To_FZ; 116 117 -- First Word of N := Source 118 procedure FFA_FZ_Set_Head(N : out FZ; Source : in Word) 119 renames FZ_Basic.FZ_Set_Head; 120 121 -- First Word of N 122 function FFA_FZ_Get_Head(N : in FZ) return Word 123 renames FZ_Basic.FZ_Get_Head; 124 125 -- Exchange X and Y 126 procedure FFA_FZ_Swap(X : in out FZ; Y : in out FZ) 127 with Pre => X'Length = Y'Length; 128 129 -- Constant-time MUX: Sel = 0: Result := X; Sel = 1: Result := Y 130 procedure FFA_FZ_Mux(X : in FZ; Y : in FZ; Result : out FZ; Sel : in WBool) 131 with Pre => X'Length = Y'Length and X'Length = Result'Length; 132 133 ---------------------------------------------------------------------------- 134 --- FZ IO Operations 135 ---------------------------------------------------------------------------- 136 137 -- Expand FZ N by nibble D, and determine whether this operation overflowed 138 procedure FFA_FZ_Insert_Bottom_Nibble(N : in out FZ; 139 D : in Nibble; 140 Overflow : out WBool) 141 renames FZ_IO.FZ_Insert_Bottom_Nibble; 142 143 -- Determine the number of ASCII characters required to represent N 144 function FFA_FZ_ASCII_Length(N : in FZ) return Char_Count 145 renames FZ_IO.FZ_ASCII_Length; 146 147 -- Write an ASCII hex representation of N into existing string buffer S 148 procedure FFA_FZ_To_Hex_String(N : in FZ; S : out String) 149 renames FZ_IO.FZ_To_Hex_String; 150 151 ---------------------------------------------------------------------------- 152 --- Comparison Predicate Operations on FZ 153 ---------------------------------------------------------------------------- 154 155 -- 1 iff X == Y (branch-free); else 0 156 function FFA_FZ_EqP(X : in FZ; Y: in FZ) return WBool 157 renames FZ_Cmp.FZ_EqP; 158 159 -- 1 iff X < Y (branch-free); else 0 160 function FFA_FZ_LessThanP(X : in FZ; Y : in FZ) return WBool 161 renames FZ_Cmp.FZ_LessThanP; 162 163 -- 1 iff X > Y (branch-free); else 0 164 function FFA_FZ_GreaterThanP(X : in FZ; Y : in FZ) return WBool 165 renames FZ_Cmp.FZ_GreaterThanP; 166 167 ---------------------------------------------------------------------------- 168 --- Fundamental Predicate Operations on FZ 169 ---------------------------------------------------------------------------- 170 171 -- 1 iff N == 0 (branch-free); else 0 172 function FFA_FZ_ZeroP(N : in FZ) return WBool 173 renames FZ_Pred.FZ_ZeroP; 174 175 -- 1 iff N != 0 (branch-free); else 0 176 function FFA_FZ_NZeroP(N : in FZ) return WBool 177 renames FZ_Pred.FZ_NZeroP; 178 179 -- 1 iff N is odd 180 function FFA_FZ_OddP(N : in FZ) return WBool 181 renames FZ_Pred.FZ_OddP; 182 183 ---------------------------------------------------------------------------- 184 --- Bitwise Operations on FZ 185 ---------------------------------------------------------------------------- 186 187 -- Result := X & Y 188 procedure FFA_FZ_And(X : in FZ; Y : in FZ; Result : out FZ) 189 with Pre => X'Length = Y'Length and X'Length = Result'Length; 190 191 -- N := N & W, W is a Word 192 procedure FFA_FZ_And_W(N : in out FZ; W : in Word) 193 renames FZ_BitOp.FZ_And_W; 194 195 -- Result := X | Y 196 procedure FFA_FZ_Or(X : in FZ; Y : in FZ; Result : out FZ) 197 with Pre => X'Length = Y'Length and X'Length = Result'Length; 198 199 -- N := N | W, W is a Word 200 procedure FFA_FZ_Or_W(N : in out FZ; W : in Word) 201 renames FZ_BitOp.FZ_Or_W; 202 203 -- Result := X ^ Y 204 procedure FFA_FZ_Xor(X : in FZ; Y : in FZ; Result : out FZ) 205 with Pre => X'Length = Y'Length and X'Length = Result'Length; 206 207 -- N := N ^ W, W is a Word 208 procedure FFA_FZ_Xor_W(N : in out FZ; W : in Word) 209 renames FZ_BitOp.FZ_Xor_W; 210 211 -- NotN := ~N ('ones complement') 212 procedure FFA_FZ_Not(N : in FZ; NotN : out FZ) 213 with Pre => N'Length = NotN'Length; 214 215 ---------------------------------------------------------------------------- 216 --- Basic Arithmetic on FZ 217 ---------------------------------------------------------------------------- 218 219 -- Sum := X + Y; Overflow := Carry 220 procedure FFA_FZ_Add(X : in FZ; 221 Y : in FZ; 222 Sum : out FZ; 223 Overflow : out WBool) 224 with Pre => X'Length = Y'Length and X'Length = Sum'Length; 225 226 -- Difference := X - Y; Underflow := Borrow 227 procedure FFA_FZ_Subtract(X : in FZ; 228 Y : in FZ; 229 Difference : out FZ; 230 Underflow : out WBool) 231 with Pre => X'Length = Y'Length and X'Length = Difference'Length; 232 233 ---------------------------------------------------------------------------- 234 --- Division on FZ 235 ---------------------------------------------------------------------------- 236 237 -- Dividend is divided by Divisor, producing Quotient and Remainder. 238 -- WARNING: NO div0 test here! Caller must test. 239 procedure FFA_FZ_IDiv(Dividend : in FZ; 240 Divisor : in FZ; 241 Quotient : out FZ; 242 Remainder : out FZ) 243 renames FZ_Divis.FZ_IDiv; 244 245 -- Exactly same thing as IDiv, but keep only the Quotient 246 procedure FFA_FZ_Div(Dividend : in FZ; 247 Divisor : in FZ; 248 Quotient : out FZ) 249 renames FZ_Divis.FZ_Div; 250 251 -- Modulus. 252 procedure FFA_FZ_Mod(Dividend : in FZ; 253 Divisor : in FZ; 254 Remainder : out FZ) 255 renames FZ_Divis.FZ_Mod; 256 257 ---------------------------------------------------------------------------- 258 --- Multiplication on FZ 259 ---------------------------------------------------------------------------- 260 261 -- Multiplier. Preserves the inputs. 262 procedure FFA_FZ_Multiply(X : in FZ; 263 Y : in FZ; 264 XY_Lo : out FZ; 265 XY_Hi : out FZ) 266 with Pre => X'Length = Y'Length and 267 XY_Lo'Length = XY_Hi'Length and 268 XY_Lo'Length = ((X'Length + Y'Length) / 2); 269 270 -- Square. Preserves the inputs. 271 procedure FFA_FZ_Square(X : in FZ; 272 XX_Lo : out FZ; 273 XX_Hi : out FZ) 274 with Pre => XX_Lo'Length = X'Length and 275 XX_Hi'Length = X'Length and 276 X'Length mod 2 = 0; 277 278 -- Low-Only Multiplier. Preserves the inputs. 279 procedure FFA_FZ_Low_Multiply(X : in FZ; 280 Y : in FZ; 281 XY : out FZ) 282 renames FZ_LoMul.FZ_Low_Multiply_Buffered; 283 284 ---------------------------------------------------------------------------- 285 --- Modular Operations on FZ 286 ---------------------------------------------------------------------------- 287 288 -- Modular Multiply: Product := X*Y mod Modulus 289 procedure FFA_FZ_Modular_Multiply(X : in FZ; 290 Y : in FZ; 291 Modulus : in FZ; 292 Product : out FZ) 293 renames FZ_ModEx.FZ_Mod_Mul; 294 295 -- Modular Squaring: Product := X*X mod Modulus 296 procedure FFA_FZ_Modular_Square(X : in FZ; 297 Modulus : in FZ; 298 Product : out FZ) 299 renames FZ_ModEx.FZ_Mod_Sqr; 300 301 -- Modular Exponent: Result := Base^Exponent mod Modulus 302 procedure FFA_FZ_Modular_Exponentiate(Base : in FZ; 303 Exponent : in FZ; 304 Modulus : in FZ; 305 Result : out FZ) 306 renames FZ_ModEx.FZ_Mod_Exp; 307 308 ---------------------------------------------------------------------------- 309 --- Other Operations on FZ 310 ---------------------------------------------------------------------------- 311 312 -- Find the index of eldest nonzero bit ( 0 if none, or 1 .. FZBitness ) 313 function FFA_FZ_Measure(N : in FZ) return FZBit_Index 314 renames FZ_Measr.FZ_Measure; 315 316 -- Constant-time arbitrary right-shift. 317 procedure FFA_FZ_Quiet_ShiftRight(N : in FZ; 318 ShiftedN : in out FZ; 319 Count : in FZBit_Index) 320 renames FZ_QShft.FZ_Quiet_ShiftRight; 321 322 -- Constant-time arbitrary left-shift. 323 procedure FFA_FZ_Quiet_ShiftLeft(N : in FZ; 324 ShiftedN : in out FZ; 325 Count : in FZBit_Index) 326 renames FZ_QShft.FZ_Quiet_ShiftLeft; 327 328 -- Find Greatest Common Divisor (GCD) of X and Y. 329 procedure FFA_FZ_Greatest_Common_Divisor(X : in FZ; 330 Y : in FZ; 331 Result : out FZ) 332 with Pre => X'Length = Y'Length and X'Length = Result'Length; 333 334 -- Constant-Time Miller-Rabin Test on N using the given Witness. 335 -- Witness will be used as-is if it conforms to the valid bounds, 336 -- i.e. 2 <= Witness <= N - 2; otherwise will be transformed into a 337 -- valid Witness via modular arithmetic. 338 -- Outputs ONE if N WAS FOUND composite; ZERO if NOT FOUND. 339 -- Handles degenerate cases of N that M-R per se cannot eat: 340 -- N=0, N=1: ALWAYS 'FOUND COMPOSITE'; 2, 3 - ALWAYS 'NOT FOUND'. 341 -- If N is Even and not equal to 2, N is ALWAYS 'FOUND COMPOSITE.' 342 -- For ALL other N, the output is equal to that of the M-R test. 343 function FFA_FZ_MR_Composite_On_Witness(N : in FZ; 344 Witness : in FZ) return WBool 345 renames FZ_Prime.FZ_MR_Composite_On_Witness; 346 347 end FFA;