FGInt.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068
  1. {License, info, etc
  2. ------------------
  3. This implementation is made by Walied Othman, to contact me
  4. mail to Walied.Othman@Student.KULeuven.ac.be or
  5. Triade@ace.Ulyssis.Student.KULeuven.ac.be,
  6. always mention wether it 's about the FGInt for Delphi or for
  7. FreePascal, or wether it 's about the 6xs, preferably in the subject line.
  8. If you 're going to use these implementations, at least mention my
  9. name or something and notify me so I may even put a link on my page.
  10. This implementation is freeware and according to the coderpunks'
  11. manifesto it should remain so, so don 't use these implementations
  12. in commercial software. Encryption, as a tool to ensure privacy
  13. should be free and accessible for anyone. If you plan to use these
  14. implementations in a commercial application, contact me before
  15. doing so, that way you can license the software to use it in commercial
  16. Software. If any algorithm is patented in your country, you should
  17. acquire a license before using this software. Modified versions of this
  18. software must contain an acknowledgement of the original author (=me).
  19. This implementaion is available at
  20. http://ace.ulyssis.student.kuleuven.ac.be/~triade/
  21. copyright 2000, Walied Othman
  22. This header may not be removed.
  23. }
  24. Unit FGInt;
  25. Interface
  26. Uses Windows, SysUtils, Controls, Math;
  27. Type
  28. TCompare = (Lt, St, Eq, Er);
  29. TSign = (negative, positive);
  30. TFGInt = Record
  31. Sign : TSign;
  32. Number : Array Of int64;
  33. End;
  34. Procedure zeronetochar8(Var g : char; Const x : String);
  35. Procedure zeronetochar6(Var g : integer; Const x : String);
  36. Procedure initialize8(Var trans : Array Of String);
  37. Procedure initialize6(Var trans : Array Of String);
  38. Procedure initialize6PGP(Var trans : Array Of String);
  39. Procedure ConvertBase256to64(Const str256 : String; Var str64 : String);
  40. Procedure ConvertBase64to256(Const str64 : String; Var str256 : String);
  41. Procedure ConvertBase256to2(Const str256 : String; Var str2 : String);
  42. Procedure ConvertBase64to2(Const str64 : String; Var str2 : String);
  43. Procedure ConvertBase2to256(str2 : String; Var str256 : String);
  44. Procedure ConvertBase2to64(str2 : String; Var str64 : String);
  45. Procedure ConvertBase256StringToHexString(Str256 : String; Var HexStr : String);
  46. Procedure ConvertHexStringToBase256String(HexStr : String; Var Str256 : String);
  47. Procedure PGPConvertBase256to64(Var str256, str64 : String);
  48. Procedure PGPConvertBase64to256(str64 : String; Var str256 : String);
  49. Procedure PGPConvertBase64to2(str64 : String; Var str2 : String);
  50. Procedure Base10StringToFGInt(Base10 : String; Var FGInt : TFGInt);
  51. Procedure FGIntToBase10String(Const FGInt : TFGInt; Var Base10 : String);
  52. Procedure FGIntDestroy(Var FGInt : TFGInt);
  53. Function FGIntCompareAbs(Const FGInt1, FGInt2 : TFGInt) : TCompare;
  54. Procedure FGIntAdd(Const FGInt1, FGInt2 : TFGInt; Var Sum : TFGInt);
  55. Procedure FGIntChangeSign(Var FGInt : TFGInt);
  56. Procedure FGIntSub(Var FGInt1, FGInt2, dif : TFGInt);
  57. Procedure FGIntMulByInt(Const FGInt : TFGInt; Var res : TFGInt; by : int64);
  58. Procedure FGIntMulByIntbis(Var FGInt : TFGInt; by : int64);
  59. Procedure FGIntDivByInt(Const FGInt : TFGInt; Var res : TFGInt; by : int64; Var modres : int64);
  60. Procedure FGIntDivByIntBis(Var FGInt : TFGInt; by : int64; Var modres : int64);
  61. Procedure FGIntModByInt(Const FGInt : TFGInt; by : int64; Var modres : int64);
  62. Procedure FGIntAbs(Var FGInt : TFGInt);
  63. Procedure FGIntCopy(Const FGInt1 : TFGInt; Var FGInt2 : TFGInt);
  64. Procedure FGIntShiftLeft(Var FGInt : TFGInt);
  65. Procedure FGIntShiftRight(Var FGInt : TFGInt);
  66. Procedure FGIntShiftRightBy31(Var FGInt : TFGInt);
  67. Procedure FGIntAddBis(Var FGInt1 : TFGInt; Const FGInt2 : TFGInt);
  68. Procedure FGIntSubBis(Var FGInt1 : TFGInt; Const FGInt2 : TFGInt);
  69. Procedure FGIntMul(Const FGInt1, FGInt2 : TFGInt; Var Prod : TFGInt);
  70. Procedure FGIntSquare(Const FGInt : TFGInt; Var Square : TFGInt);
  71. Procedure FGIntToBase2String(Const FGInt : TFGInt; Var S : String);
  72. Procedure Base2StringToFGInt(S : String; Var FGInt : TFGInt);
  73. Procedure FGIntToBase256String(Const FGInt : TFGInt; Var str256 : String);
  74. Procedure Base256StringToFGInt(str256 : String; Var FGInt : TFGInt);
  75. Procedure PGPMPIToFGInt(PGPMPI : String; Var FGInt : TFGInt);
  76. Procedure FGIntToPGPMPI(FGInt : TFGInt; Var PGPMPI : String);
  77. Procedure FGIntExp(Const FGInt, exp : TFGInt; Var res : TFGInt);
  78. Procedure FGIntFac(Const FGInt : TFGInt; Var res : TFGInt);
  79. Procedure FGIntShiftLeftBy31(Var FGInt : TFGInt);
  80. Procedure FGIntDivMod(Var FGInt1, FGInt2, QFGInt, MFGInt : TFGInt);
  81. Procedure FGIntDiv(Var FGInt1, FGInt2, QFGInt : TFGInt);
  82. Procedure FGIntMod(Var FGInt1, FGInt2, MFGInt : TFGInt);
  83. Procedure FGIntSquareMod(Var FGInt, Modb, FGIntSM : TFGInt);
  84. Procedure FGIntAddMod(Var FGInt1, FGInt2, base, FGIntres : TFGInt);
  85. Procedure FGIntMulMod(Var FGInt1, FGInt2, base, FGIntres : TFGInt);
  86. Procedure FGIntModExp(Var FGInt, exp, modb, res : TFGInt);
  87. Procedure FGIntModBis(Const FGInt : TFGInt; Var FGIntOut : TFGInt; b : longint; head : int64);
  88. Procedure FGIntMulModBis(Const FGInt1, FGInt2 : TFGInt; Var Prod : TFGInt; b : longint; head : int64);
  89. Procedure FGIntMontgomeryMod(Const GInt, base, baseInv : TFGInt; Var MGInt : TFGInt; b : longint; head : int64);
  90. Procedure FGIntMontgomeryModExp(Var FGInt, exp, modb, res : TFGInt);
  91. Procedure FGIntGCD(Const FGInt1, FGInt2 : TFGInt; Var GCD : TFGInt);
  92. Procedure FGIntLCM(Const FGInt1, FGInt2 : TFGInt; Var LCM : TFGInt);
  93. Procedure FGIntTrialDiv9999(Const FGInt : TFGInt; Var ok : boolean);
  94. Procedure FGIntRandom1(Var Seed, RandomFGInt : TFGInt);
  95. Procedure FGIntRabinMiller(Var FGIntp : TFGInt; nrtest : integer; Var ok : boolean);
  96. Procedure FGIntBezoutBachet(Var FGInt1, FGInt2, a, b : TFGInt);
  97. Procedure FGIntModInv(Const FGInt1, base : TFGInt; Var Inverse : TFGInt);
  98. Procedure FGIntPrimetest(Var FGIntp : TFGInt; nrRMtests : integer; Var ok : boolean);
  99. Procedure FGIntLegendreSymbol(Var a, p : TFGInt; Var L : integer);
  100. Procedure FGIntSquareRootModP(Square, Prime : TFGInt; Var SquareRoot : TFGInt);
  101. Implementation
  102. Var
  103. primes : Array[1..1228] Of integer =
  104. (3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
  105. 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
  106. 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
  107. 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
  108. 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677,
  109. 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
  110. 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009,
  111. 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123,
  112. 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
  113. 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429,
  114. 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553,
  115. 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
  116. 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847,
  117. 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
  118. 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131,
  119. 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
  120. 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417,
  121. 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593,
  122. 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719,
  123. 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
  124. 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037,
  125. 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
  126. 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359,
  127. 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527,
  128. 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659,
  129. 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
  130. 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967,
  131. 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129,
  132. 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273,
  133. 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
  134. 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637,
  135. 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789,
  136. 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957,
  137. 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
  138. 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281,
  139. 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
  140. 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623,
  141. 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779,
  142. 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903,
  143. 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101,
  144. 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269,
  145. 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397,
  146. 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599,
  147. 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779,
  148. 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947,
  149. 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
  150. 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283,
  151. 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487,
  152. 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607,
  153. 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789,
  154. 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951,
  155. 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
  156. 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311,
  157. 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521,
  158. 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681,
  159. 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
  160. 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007,
  161. 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181,
  162. 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343,
  163. 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491,
  164. 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679,
  165. 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839,
  166. 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973);
  167. chr64 : Array[1..64] Of char = ('a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F',
  168. 'g', 'G', 'h', 'H', 'i', 'I', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'o', 'O', 'p',
  169. 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y',
  170. 'z', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '=');
  171. PGPchr64 : Array[1..64] Of char = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  172. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  173. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
  174. 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/');
  175. {$H+}
  176. Procedure zeronetochar8(Var g : char; Const x : String);
  177. Var
  178. i : Integer;
  179. b : byte;
  180. Begin
  181. b := 0;
  182. For i := 1 To 8 Do
  183. Begin
  184. If copy(x, i, 1) = '1' Then
  185. b := b Or (1 Shl (8 - I));
  186. End;
  187. g := chr(b);
  188. End;
  189. Procedure zeronetochar6(Var g : integer; Const x : String);
  190. Var
  191. I : Integer;
  192. Begin
  193. G := 0;
  194. For I := 1 To Length(X) Do
  195. Begin
  196. If I > 6 Then
  197. Break;
  198. If X[I] <> '0' Then
  199. G := G Or (1 Shl (6 - I));
  200. End;
  201. Inc(G);
  202. End;
  203. Procedure initialize8(Var trans : Array Of String);
  204. Var
  205. c1, c2, c3, c4, c5, c6, c7, c8 : integer;
  206. x : String;
  207. g : char;
  208. Begin
  209. For c1 := 0 To 1 Do
  210. For c2 := 0 To 1 Do
  211. For c3 := 0 To 1 Do
  212. For c4 := 0 To 1 Do
  213. For c5 := 0 To 1 Do
  214. For c6 := 0 To 1 Do
  215. For c7 := 0 To 1 Do
  216. For c8 := 0 To 1 Do
  217. Begin
  218. x := '';
  219. x := inttostr(c1) + inttostr(c2) + inttostr(c3) + inttostr(c4) + inttostr(c5) + inttostr(c6) + inttostr(c7) + inttostr(c8);
  220. zeronetochar8(g, x);
  221. trans[ord(g)] := x;
  222. End;
  223. End;
  224. Procedure initialize6(Var trans : Array Of String);
  225. Var
  226. c1, c2, c3, c4, c5, c6 : integer;
  227. x : String;
  228. g : integer;
  229. Begin
  230. For c1 := 0 To 1 Do
  231. For c2 := 0 To 1 Do
  232. For c3 := 0 To 1 Do
  233. For c4 := 0 To 1 Do
  234. For c5 := 0 To 1 Do
  235. For c6 := 0 To 1 Do
  236. Begin
  237. x := '';
  238. x := inttostr(c1) + inttostr(c2) + inttostr(c3) + inttostr(c4) + inttostr(c5) + inttostr(c6);
  239. zeronetochar6(g, x);
  240. trans[ord(chr64[g])] := x;
  241. End;
  242. End;
  243. Procedure initialize6PGP(Var trans : Array Of String);
  244. Var
  245. c1, c2, c3, c4, c5, c6 : integer;
  246. x : String;
  247. g : integer;
  248. Begin
  249. For c1 := 0 To 1 Do
  250. For c2 := 0 To 1 Do
  251. For c3 := 0 To 1 Do
  252. For c4 := 0 To 1 Do
  253. For c5 := 0 To 1 Do
  254. For c6 := 0 To 1 Do
  255. Begin
  256. x := '';
  257. x := inttostr(c1) + inttostr(c2) + inttostr(c3) + inttostr(c4) + inttostr(c5) + inttostr(c6);
  258. zeronetochar6(g, x);
  259. trans[ord(PGPchr64[g])] := x;
  260. End;
  261. End;
  262. // Convert base 8 strings to base 6 strings and visa versa
  263. Procedure ConvertBase256to64(Const str256 : String; Var str64 : String);
  264. Var
  265. temp : String;
  266. trans : Array[0..255] Of String;
  267. i, len6 : longint;
  268. g : integer;
  269. Begin
  270. initialize8(trans);
  271. temp := '';
  272. For i := 1 To length(str256) Do temp := temp + trans[ord(str256[i])];
  273. While (length(temp) Mod 6) <> 0 Do temp := temp + '0';
  274. len6 := length(temp) Div 6;
  275. str64 := '';
  276. For i := 1 To len6 Do
  277. Begin
  278. zeronetochar6(g, copy(temp, 1, 6));
  279. str64 := str64 + chr64[g];
  280. delete(temp, 1, 6);
  281. End;
  282. End;
  283. Procedure ConvertBase64to256(Const str64 : String; Var str256 : String);
  284. Var
  285. temp : String;
  286. trans : Array[0..255] Of String;
  287. i, len8 : longint;
  288. g : char;
  289. Begin
  290. initialize6(trans);
  291. temp := '';
  292. For i := 1 To length(str64) Do temp := temp + trans[ord(str64[i])];
  293. str256 := '';
  294. len8 := length(temp) Div 8;
  295. For i := 1 To len8 Do
  296. Begin
  297. zeronetochar8(g, copy(temp, 1, 8));
  298. str256 := str256 + g;
  299. delete(temp, 1, 8);
  300. End;
  301. End;
  302. // Convert base 8 & 6 bit strings to base 2 strings and visa versa
  303. Procedure ConvertBase256to2(Const str256 : String; Var str2 : String);
  304. Var
  305. trans : Array[0..255] Of String;
  306. i : longint;
  307. Begin
  308. str2 := '';
  309. initialize8(trans);
  310. For i := 1 To length(str256) Do str2 := str2 + trans[ord(str256[i])];
  311. End;
  312. Procedure ConvertBase64to2(Const str64 : String; Var str2 : String);
  313. Var
  314. trans : Array[0..255] Of String;
  315. i : longint;
  316. Begin
  317. str2 := '';
  318. initialize6(trans);
  319. For i := 1 To length(str64) Do str2 := str2 + trans[ord(str64[i])];
  320. End;
  321. Procedure ConvertBase2to256(str2 : String; Var str256 : String);
  322. Var
  323. i, len8 : longint;
  324. g : char;
  325. Begin
  326. str256 := '';
  327. While (length(str2) Mod 8) <> 0 Do str2 := '0' + str2;
  328. len8 := length(str2) Div 8;
  329. For i := 1 To len8 Do
  330. Begin
  331. zeronetochar8(g, copy(str2, 1, 8));
  332. str256 := str256 + g;
  333. delete(str2, 1, 8);
  334. End;
  335. End;
  336. Procedure ConvertBase2to64(str2 : String; Var str64 : String);
  337. Var
  338. i, len6 : longint;
  339. g : integer;
  340. Begin
  341. str64 := '';
  342. While (length(str2) Mod 6) <> 0 Do str2 := '0' + str2;
  343. len6 := length(str2) Div 6;
  344. For i := 1 To len6 Do
  345. Begin
  346. zeronetochar6(g, copy(str2, 1, 6));
  347. str64 := str64 + chr64[g];
  348. delete(str2, 1, 6);
  349. End;
  350. End;
  351. // Convert base 256 strings to base 16 (HexaDecimal) strings and visa versa
  352. Procedure ConvertBase256StringToHexString(Str256 : String; Var HexStr : String);
  353. Var
  354. i : longint;
  355. b : byte;
  356. Begin
  357. HexStr := '';
  358. For i := 1 To length(str256) Do
  359. Begin
  360. b := ord(str256[i]);
  361. If (b Shr 4) < 10 Then HexStr := HexStr + chr(48 + (b Shr 4))
  362. Else HexStr := HexStr + chr(55 + (b Shr 4));
  363. If (b And 15) < 10 Then HexStr := HexStr + chr(48 + (b And 15))
  364. Else HexStr := HexStr + chr(55 + (b And 15));
  365. End;
  366. End;
  367. Procedure ConvertHexStringToBase256String(HexStr : String; Var Str256 : String);
  368. Var
  369. i : longint;
  370. b, h1, h2 : byte;
  371. Begin
  372. Str256 := '';
  373. For i := 1 To (length(Hexstr) Div 2) Do
  374. Begin
  375. h2 := ord(HexStr[2 * i]);
  376. h1 := ord(HexStr[2 * i - 1]);
  377. If h1 < 58 Then b := ((h1 - 48) Shl 4) Else b := ((h1 - 55) Shl 4);
  378. If h2 < 58 Then b := (b Or (h2 - 48)) Else b := (b Or (h2 - 55));
  379. Str256 := Str256 + chr(b);
  380. End;
  381. End;
  382. // Convert base 256 strings to base 64 strings and visa versa, PGP style
  383. Procedure PGPConvertBase256to64(Var str256, str64 : String);
  384. Var
  385. temp, x, a : String;
  386. i, len6 : longint;
  387. g : integer;
  388. trans : Array[0..255] Of String;
  389. Begin
  390. initialize8(trans);
  391. temp := '';
  392. For i := 1 To length(str256) Do temp := temp + trans[ord(str256[i])];
  393. If (length(temp) Mod 6) = 0 Then a := '' Else
  394. If (length(temp) Mod 6) = 4 Then
  395. Begin
  396. temp := temp + '00';
  397. a := '='
  398. End
  399. Else
  400. Begin
  401. temp := temp + '0000';
  402. a := '=='
  403. End;
  404. str64 := '';
  405. len6 := length(temp) Div 6;
  406. For i := 1 To len6 Do
  407. Begin
  408. x := copy(temp, 1, 6);
  409. zeronetochar6(g, x);
  410. str64 := str64 + PGPchr64[g];
  411. delete(temp, 1, 6);
  412. End;
  413. str64 := str64 + a;
  414. End;
  415. Procedure PGPConvertBase64to256(str64 : String; Var str256 : String);
  416. Var
  417. temp, x : String;
  418. i, j, len8 : longint;
  419. g : char;
  420. trans : Array[0..255] Of String;
  421. Begin
  422. initialize6PGP(trans);
  423. temp := '';
  424. str256 := '';
  425. If str64[length(str64) - 1] = '=' Then j := 2 Else
  426. If str64[length(str64)] = '=' Then j := 1 Else j := 0;
  427. For i := 1 To (length(str64) - j) Do temp := temp + trans[ord(str64[i])];
  428. If j <> 0 Then delete(temp, length(temp) - 2 * j + 1, 2 * j);
  429. len8 := length(temp) Div 8;
  430. For i := 1 To len8 Do
  431. Begin
  432. x := copy(temp, 1, 8);
  433. zeronetochar8(g, x);
  434. str256 := str256 + g;
  435. delete(temp, 1, 8);
  436. End;
  437. End;
  438. // Convert base 64 strings to base 2 strings, PGP style
  439. Procedure PGPConvertBase64to2(str64 : String; Var str2 : String);
  440. Var
  441. i, j : longint;
  442. trans : Array[0..255] Of String;
  443. Begin
  444. str2 := '';
  445. initialize6(trans);
  446. If str64[length(str64) - 1] = '=' Then j := 2 Else
  447. If str64[length(str64)] = '=' Then j := 1 Else j := 0;
  448. For i := 1 To (length(str64) - j) Do str2 := str2 + trans[ord(str64[i])];
  449. delete(str2, length(str2) - 2 * j + 1, 2 * j);
  450. End;
  451. // Convert a base 10 string to a FGInt
  452. Procedure Base10StringToFGInt(Base10 : String; Var FGInt : TFGInt);
  453. Var
  454. i, size : longint;
  455. j : int64;
  456. S : String;
  457. sign : TSign;
  458. Procedure GIntDivByIntBis1(Var GInt : TFGInt; by : int64; Var modres : int64);
  459. Var
  460. i, size : longint;
  461. rest : int64;
  462. Begin
  463. size := GInt.Number[0];
  464. modres := 0;
  465. For i := size Downto 1 Do
  466. Begin
  467. modres := modres * 1000000000;
  468. rest := modres + GInt.Number[i];
  469. GInt.Number[i] := rest Div by;
  470. modres := rest Mod by;
  471. End;
  472. While (GInt.Number[size] = 0) And (size > 1) Do size := size - 1;
  473. If size <> GInt.Number[0] Then
  474. Begin
  475. SetLength(GInt.Number, size + 1);
  476. GInt.Number[0] := size;
  477. End;
  478. End;
  479. Begin
  480. While (Not (Base10[1] In ['-', '0'..'9'])) And (length(Base10) > 1) Do
  481. delete(Base10, 1, 1);
  482. If copy(Base10, 1, 1) = '-' Then
  483. Begin
  484. Sign := negative;
  485. delete(Base10, 1, 1);
  486. End
  487. Else Sign := positive;
  488. While (length(Base10) > 1) And (copy(Base10, 1, 1) = '0') Do delete(Base10, 1, 1);
  489. size := length(Base10) Div 9;
  490. If (length(Base10) Mod 9) <> 0 Then size := size + 1;
  491. SetLength(FGInt.Number, size + 1);
  492. FGInt.Number[0] := size;
  493. For i := 1 To size - 1 Do
  494. Begin
  495. FGInt.Number[i] := StrToInt(copy(Base10, length(Base10) - 8, 9));
  496. delete(Base10, length(Base10) - 8, 9);
  497. End;
  498. FGInt.Number[size] := StrToInt(Base10);
  499. S := '';
  500. While (FGInt.Number[0] <> 1) Or (FGInt.Number[1] <> 0) Do
  501. Begin
  502. GIntDivByIntBis1(FGInt, 2, j);
  503. S := inttostr(j) + S;
  504. End;
  505. S := '0' + S;
  506. FGIntDestroy(FGInt);
  507. Base2StringToFGInt(S, FGInt);
  508. FGInt.Sign := sign;
  509. End;
  510. // Convert a FGInt to a base 10 string
  511. Procedure FGIntToBase10String(Const FGInt : TFGInt; Var Base10 : String);
  512. Var
  513. S : String;
  514. j : int64;
  515. temp : TFGInt;
  516. Begin
  517. FGIntCopy(FGInt, temp);
  518. Base10 := '';
  519. While (temp.Number[0] > 1) Or (temp.Number[1] > 0) Do
  520. Begin
  521. FGIntDivByIntBis(temp, 1000000000, j);
  522. S := IntToStr(j);
  523. While Length(S) < 9 Do S := '0' + S;
  524. Base10 := S + Base10;
  525. End;
  526. Base10 := '0' + Base10;
  527. While (length(Base10) > 1) And (Base10[1] = '0') Do delete(Base10, 1, 1);
  528. If FGInt.Sign = negative Then Base10 := '-' + Base10;
  529. End;
  530. // Destroy a FGInt to free memory
  531. Procedure FGIntDestroy(Var FGInt : TFGInt);
  532. Begin
  533. FGInt.Number := Nil;
  534. End;
  535. // Compare 2 FGInts in absolute value, returns
  536. // Lt if FGInt1 > FGInt2, St if FGInt1 < FGInt2, Eq if FGInt1 = FGInt2,
  537. // Er otherwise
  538. Function FGIntCompareAbs(Const FGInt1, FGInt2 : TFGInt) : TCompare;
  539. Var
  540. size1, size2, i : longint;
  541. Begin
  542. FGIntCompareAbs := Er;
  543. size1 := FGInt1.Number[0];
  544. size2 := FGInt2.Number[0];
  545. If size1 > size2 Then FGIntCompareAbs := Lt Else
  546. If size1 < size2 Then FGIntCompareAbs := St Else
  547. Begin
  548. i := size2;
  549. While (FGInt1.Number[i] = FGInt2.Number[i]) And (i > 1) Do i := i - 1;
  550. If FGInt1.Number[i] = FGInt2.Number[i] Then FGIntCompareAbs := Eq Else
  551. If FGInt1.Number[i] < FGInt2.Number[i] Then FGIntCompareAbs := St Else
  552. If FGInt1.Number[i] > FGInt2.Number[i] Then FGIntCompareAbs := Lt;
  553. End;
  554. End;
  555. // Add 2 FGInts, FGInt1 + FGInt2 = Sum
  556. Procedure FGIntAdd(Const FGInt1, FGInt2 : TFGInt; Var Sum : TFGInt);
  557. Var
  558. i, size1, size2, size : longint;
  559. rest : integer;
  560. Trest : int64;
  561. Begin
  562. size1 := FGInt1.Number[0];
  563. size2 := FGInt2.Number[0];
  564. If size1 < size2 Then FGIntAdd(FGInt2, FGInt1, Sum) Else
  565. Begin
  566. If FGInt1.Sign = FGInt2.Sign Then
  567. Begin
  568. Sum.Sign := FGInt1.Sign;
  569. SetLength(Sum.Number, size1 + 2);
  570. rest := 0;
  571. For i := 1 To size2 Do
  572. Begin
  573. Trest := FGInt1.Number[i] + FGInt2.Number[i] + rest;
  574. Sum.Number[i] := Trest And 2147483647;
  575. rest := Trest Shr 31;
  576. End;
  577. For i := (size2 + 1) To size1 Do
  578. Begin
  579. Trest := FGInt1.Number[i] + rest;
  580. Sum.Number[i] := Trest And 2147483647;
  581. rest := Trest Shr 31;
  582. End;
  583. size := size1 + 1;
  584. Sum.Number[0] := size;
  585. Sum.Number[size] := rest;
  586. While (Sum.Number[size] = 0) And (size > 1) Do size := size - 1;
  587. If Sum.Number[0] > size Then SetLength(Sum.Number, size + 1);
  588. Sum.Number[0] := size;
  589. End
  590. Else
  591. Begin
  592. If FGIntCompareAbs(FGInt2, FGInt1) = Lt Then FGIntAdd(FGInt2, FGInt1, Sum)
  593. Else
  594. Begin
  595. SetLength(Sum.Number, size1 + 1);
  596. rest := 0;
  597. For i := 1 To size2 Do
  598. Begin
  599. Trest := 2147483648 + FGInt1.Number[i] - FGInt2.Number[i] + rest;
  600. Sum.Number[i] := Trest And 2147483647;
  601. If (Trest > 2147483647) Then rest := 0 Else rest := -1;
  602. End;
  603. For i := (size2 + 1) To size1 Do
  604. Begin
  605. Trest := 2147483648 + FGInt1.Number[i] + rest;
  606. Sum.Number[i] := Trest And 2147483647;
  607. If (Trest > 2147483647) Then rest := 0 Else rest := -1;
  608. End;
  609. size := size1;
  610. While (Sum.Number[size] = 0) And (size > 1) Do size := size - 1;
  611. If size < size1 Then
  612. Begin
  613. SetLength(Sum.Number, size + 1);
  614. End;
  615. Sum.Number[0] := size;
  616. Sum.Sign := FGInt1.Sign;
  617. End;
  618. End;
  619. End;
  620. End;
  621. Procedure FGIntChangeSign(Var FGInt : TFGInt);
  622. Begin
  623. If FGInt.Sign = negative Then FGInt.Sign := positive Else FGInt.Sign := negative;
  624. End;
  625. // Substract 2 FGInts, FGInt1 - FGInt2 = dif
  626. Procedure FGIntSub(Var FGInt1, FGInt2, dif : TFGInt);
  627. Begin
  628. FGIntChangeSign(FGInt2);
  629. FGIntAdd(FGInt1, FGInt2, dif);
  630. FGIntChangeSign(FGInt2);
  631. End;
  632. // multiply a FGInt by an integer, FGInt * by = res, by < 1000000000
  633. Procedure FGIntMulByInt(Const FGInt : TFGInt; Var res : TFGInt; by : int64);
  634. Var
  635. i, size : longint;
  636. Trest, rest : int64;
  637. Begin
  638. size := FGInt.Number[0];
  639. SetLength(res.Number, size + 2);
  640. rest := 0;
  641. For i := 1 To size Do
  642. Begin
  643. Trest := FGInt.Number[i] * by + rest;
  644. res.Number[i] := Trest And 2147483647;
  645. rest := Trest Shr 31;
  646. End;
  647. If rest <> 0 Then
  648. Begin
  649. size := size + 1;
  650. Res.Number[size] := rest;
  651. End
  652. Else SetLength(Res.Number, size + 1);
  653. Res.Number[0] := size;
  654. Res.Sign := FGInt.Sign;
  655. End;
  656. // multiply a FGInt by an integer, FGInt * by = res, by < 1000000000
  657. Procedure FGIntMulByIntbis(Var FGInt : TFGInt; by : int64);
  658. Var
  659. i, size : longint;
  660. Trest, rest : int64;
  661. Begin
  662. size := FGInt.Number[0];
  663. SetLength(FGInt.Number, size + 2);
  664. rest := 0;
  665. For i := 1 To size Do
  666. Begin
  667. Trest := FGInt.Number[i] * by + rest;
  668. FGInt.Number[i] := Trest And 2147483647;
  669. rest := Trest Shr 31;
  670. End;
  671. If rest <> 0 Then
  672. Begin
  673. size := size + 1;
  674. FGInt.Number[size] := rest;
  675. End
  676. Else SetLength(FGInt.Number, size + 1);
  677. FGInt.Number[0] := size;
  678. End;
  679. // divide a FGInt by an integer, FGInt = res * by + modres
  680. Procedure FGIntDivByInt(Const FGInt : TFGInt; Var res : TFGInt; by : int64; Var modres : int64);
  681. Var
  682. i, size : longint;
  683. rest : int64;
  684. Begin
  685. size := FGInt.Number[0];
  686. SetLength(res.Number, size + 1);
  687. modres := 0;
  688. For i := size Downto 1 Do
  689. Begin
  690. modres := modres Shl 31;
  691. rest := modres Or FGInt.Number[i];
  692. res.Number[i] := rest Div by;
  693. modres := rest Mod by;
  694. End;
  695. While (res.Number[size] = 0) And (size > 1) Do size := size - 1;
  696. SetLength(res.Number, size + 1);
  697. res.Number[0] := size;
  698. Res.Sign := FGInt.Sign;
  699. End;
  700. // divide a FGInt by an integer, FGInt = FGInt * by + modres
  701. Procedure FGIntDivByIntBis(Var FGInt : TFGInt; by : int64; Var modres : int64);
  702. Var
  703. i, size : longint;
  704. rest : int64;
  705. Begin
  706. size := FGInt.Number[0];
  707. modres := 0;
  708. For i := size Downto 1 Do
  709. Begin
  710. modres := modres Shl 31;
  711. rest := modres Or FGInt.Number[i];
  712. FGInt.Number[i] := rest Div by;
  713. modres := rest Mod by;
  714. End;
  715. While (FGInt.Number[size] = 0) And (size > 1) Do size := size - 1;
  716. If size <> FGInt.Number[0] Then
  717. Begin
  718. SetLength(FGInt.Number, size + 1);
  719. FGInt.Number[0] := size;
  720. End;
  721. End;
  722. // Reduce a FGInt modulo by (=an integer), FGInt mod by = modres
  723. Procedure FGIntModByInt(Const FGInt : TFGInt; by : int64; Var modres : int64);
  724. Var
  725. i, size : longint;
  726. rest : int64;
  727. Begin
  728. size := FGInt.Number[0];
  729. modres := 0;
  730. For i := size Downto 1 Do
  731. Begin
  732. modres := modres Shl 31;
  733. rest := modres + FGInt.Number[i];
  734. modres := rest Mod by;
  735. End;
  736. End;
  737. // Returns the FGInt in absolute value
  738. Procedure FGIntAbs(Var FGInt : TFGInt);
  739. Begin
  740. FGInt.Sign := positive;
  741. End;
  742. // Copy a FGInt1 into FGInt2
  743. Procedure FGIntCopy(Const FGInt1 : TFGInt; Var FGInt2 : TFGInt);
  744. Begin
  745. FGInt2.Sign := FGInt1.Sign;
  746. FGInt2.Number := Nil;
  747. FGInt2.Number := Copy(FGInt1.Number, 0, FGInt1.Number[0] + 1);
  748. End;
  749. // Shift the FGInt to the left in base 2 notation, ie FGInt = FGInt * 2
  750. Procedure FGIntShiftLeft(Var FGInt : TFGInt);
  751. Var
  752. l, m : int64;
  753. i, size : longint;
  754. Begin
  755. size := FGInt.Number[0];
  756. l := 0;
  757. For i := 1 To Size Do
  758. Begin
  759. m := FGInt.Number[i] Shr 30;
  760. FGInt.Number[i] := ((FGInt.Number[i] Shl 1) Or l) And 2147483647;
  761. l := m;
  762. End;
  763. If l <> 0 Then
  764. Begin
  765. setlength(FGInt.Number, size + 2);
  766. FGInt.Number[size + 1] := l;
  767. FGInt.Number[0] := size + 1;
  768. End;
  769. End;
  770. // Shift the FGInt to the right in base 2 notation, ie FGInt = FGInt div 2
  771. Procedure FGIntShiftRight(Var FGInt : TFGInt);
  772. Var
  773. l, m : int64;
  774. i, size : longint;
  775. Begin
  776. size := FGInt.Number[0];
  777. l := 0;
  778. For i := size Downto 1 Do
  779. Begin
  780. m := FGInt.Number[i] And 1;
  781. FGInt.Number[i] := (FGInt.Number[i] Shr 1) Or l;
  782. l := m Shl 30;
  783. End;
  784. If (FGInt.Number[size] = 0) And (size > 1) Then
  785. Begin
  786. setlength(FGInt.Number, size);
  787. FGInt.Number[0] := size - 1;
  788. End;
  789. End;
  790. // FGInt = FGInt / 2147483648
  791. Procedure FGIntShiftRightBy31(Var FGInt : TFGInt);
  792. Var
  793. size : longint;
  794. Begin
  795. size := FGInt.Number[0];
  796. If size > 1 Then
  797. Begin
  798. FGInt.Number := Copy(FGInt.Number, 1, Size);
  799. FGInt.Number[0] := size - 1;
  800. End
  801. Else FGInt.Number[1] := 0;
  802. End;
  803. // FGInt1 = FGInt1 + FGInt2, FGInt1 > FGInt2
  804. Procedure FGIntAddBis(Var FGInt1 : TFGInt; Const FGInt2 : TFGInt);
  805. Var
  806. i, size1, size2 : longint;
  807. rest : integer;
  808. Trest : int64;
  809. Begin
  810. size1 := FGInt1.Number[0];
  811. size2 := FGInt2.Number[0];
  812. rest := 0;
  813. For i := 1 To size2 Do
  814. Begin
  815. Trest := FGInt1.Number[i] + FGInt2.Number[i] + rest;
  816. rest := Trest Shr 31;
  817. FGInt1.Number[i] := Trest And 2147483647;
  818. End;
  819. For i := size2 + 1 To size1 Do
  820. Begin
  821. Trest := FGInt1.Number[i] + rest;
  822. rest := Trest Shr 31;
  823. FGInt1.Number[i] := Trest And 2147483647;
  824. End;
  825. If rest <> 0 Then
  826. Begin
  827. SetLength(FGInt1.Number, size1 + 2);
  828. FGInt1.Number[0] := size1 + 1;
  829. FGInt1.Number[size1 + 1] := rest;
  830. End;
  831. End;
  832. // FGInt1 = FGInt1 - FGInt2, use only when 0 < FGInt2 < FGInt1
  833. Procedure FGIntSubBis(Var FGInt1 : TFGInt; Const FGInt2 : TFGInt);
  834. Var
  835. i, size1, size2 : longint;
  836. rest : integer;
  837. Trest : int64;
  838. Begin
  839. size1 := FGInt1.Number[0];
  840. size2 := FGInt2.Number[0];
  841. rest := 0;
  842. For i := 1 To size2 Do
  843. Begin
  844. Trest := 2147483648 + FGInt1.Number[i] - FGInt2.Number[i] + rest;
  845. If (Trest > 2147483647) Then rest := 0 Else rest := -1;
  846. FGInt1.Number[i] := Trest And 2147483647;
  847. End;
  848. For i := size2 + 1 To size1 Do
  849. Begin
  850. Trest := 2147483648 + FGInt1.Number[i] + rest;
  851. If (Trest > 2147483647) Then rest := 0 Else rest := -1;
  852. FGInt1.Number[i] := Trest And 2147483647;
  853. End;
  854. i := size1;
  855. While (FGInt1.Number[i] = 0) And (i > 1) Do i := i - 1;
  856. If i < size1 Then
  857. Begin
  858. SetLength(FGInt1.Number, i + 1);
  859. FGInt1.Number[0] := i;
  860. End;
  861. End;
  862. // Multiply 2 FGInts, FGInt1 * FGInt2 = Prod
  863. Procedure FGIntMul(Const FGInt1, FGInt2 : TFGInt; Var Prod : TFGInt);
  864. Var
  865. i, j, size, size1, size2 : longint;
  866. rest, Trest : int64;
  867. Begin
  868. size1 := FGInt1.Number[0];
  869. size2 := FGInt2.Number[0];
  870. size := size1 + size2;
  871. SetLength(Prod.Number, size + 1);
  872. For i := 1 To size Do Prod.Number[i] := 0;
  873. For i := 1 To size2 Do
  874. Begin
  875. rest := 0;
  876. For j := 1 To size1 Do
  877. Begin
  878. Trest := Prod.Number[j + i - 1] + FGInt1.Number[j] * FGInt2.Number[i] + rest;
  879. Prod.Number[j + i - 1] := Trest And 2147483647;
  880. rest := Trest Shr 31;
  881. End;
  882. Prod.Number[i + size1] := rest;
  883. End;
  884. Prod.Number[0] := size;
  885. While (Prod.Number[size] = 0) And (size > 1) Do size := size - 1;
  886. If size < Prod.Number[0] Then
  887. Begin
  888. SetLength(Prod.Number, size + 1);
  889. Prod.Number[0] := size;
  890. End;
  891. If FGInt1.Sign = FGInt2.Sign Then Prod.Sign := Positive Else prod.Sign := negative;
  892. End;
  893. // Square a FGInt, FGInt² = Square
  894. Procedure FGIntSquare(Const FGInt : TFGInt; Var Square : TFGInt);
  895. Var
  896. size, size1, i, j : longint;
  897. rest, Trest : int64;
  898. Begin
  899. size1 := FGInt.Number[0];
  900. size := 2 * size1;
  901. SetLength(Square.Number, size + 1);
  902. Square.Number[0] := size;
  903. For i := 1 To size Do Square.Number[i] := 0;
  904. For i := 1 To size1 Do
  905. Begin
  906. Trest := Square.Number[2 * i - 1] + FGInt.Number[i] * FGInt.Number[i];
  907. Square.Number[2 * i - 1] := Trest And 2147483647;
  908. rest := Trest Shr 31;
  909. For j := i + 1 To size1 Do
  910. Begin
  911. Trest := Square.Number[i + j - 1] + 2 * FGInt.Number[i] * FGInt.Number[j] + rest;
  912. Square.Number[i + j - 1] := Trest And 2147483647;
  913. rest := Trest Shr 31;
  914. End;
  915. Square.Number[i + size1] := rest;
  916. End;
  917. Square.Sign := positive;
  918. While (Square.Number[size] = 0) And (size > 1) Do size := size - 1;
  919. If size < 2 * size1 Then
  920. Begin
  921. SetLength(Square.Number, size + 1);
  922. Square.Number[0] := size;
  923. End;
  924. End;
  925. // Convert a FGInt to a binary string (base 2) & visa versa
  926. Procedure FGIntToBase2String(Const FGInt : TFGInt; Var S : String);
  927. Var
  928. i : longint;
  929. j : integer;
  930. Begin
  931. S := '';
  932. For i := 1 To FGInt.Number[0] Do
  933. Begin
  934. For j := 0 To 30 Do S := inttostr(1 And (FGInt.Number[i] Shr j)) + S;
  935. End;
  936. While (length(S) > 1) And (S[1] = '0') Do delete(S, 1, 1);
  937. If S = '' Then S := '0';
  938. End;
  939. Procedure Base2StringToFGInt(S : String; Var FGInt : TFGInt);
  940. Var
  941. i, j, size : longint;
  942. Begin
  943. size := length(S) Div 31;
  944. If (length(S) Mod 31) <> 0 Then size := size + 1;
  945. SetLength(FGInt.Number, size + 1);
  946. FGInt.Number[0] := size;
  947. j := 1;
  948. FGInt.Number[j] := 0;
  949. i := 0;
  950. While length(S) > 0 Do
  951. Begin
  952. If S[length(S)] = '1' Then
  953. FGInt.Number[j] := FGInt.Number[j] Or (1 Shl i);
  954. i := i + 1;
  955. If i = 31 Then
  956. Begin
  957. i := 0;
  958. j := j + 1;
  959. If j <= size Then FGInt.Number[j] := 0;
  960. End;
  961. delete(S, length(S), 1);
  962. End;
  963. FGInt.Sign := positive;
  964. End;
  965. // Convert a FGInt to an base 256 string & visa versa
  966. Procedure FGIntToBase256String(Const FGInt : TFGInt; Var str256 : String);
  967. Var
  968. temp1 : String;
  969. i, len8 : longint;
  970. g : char;
  971. Begin
  972. FGIntToBase2String(FGInt, temp1);
  973. While (length(temp1) Mod 8) <> 0 Do temp1 := '0' + temp1;
  974. len8 := length(temp1) Div 8;
  975. str256 := '';
  976. For i := 1 To len8 Do
  977. Begin
  978. zeronetochar8(g, copy(temp1, 1, 8));
  979. str256 := str256 + g;
  980. delete(temp1, 1, 8);
  981. End;
  982. End;
  983. Procedure Base256StringToFGInt(str256 : String; Var FGInt : TFGInt);
  984. Var
  985. temp1 : String;
  986. i : longint;
  987. trans : Array[0..255] Of String;
  988. Begin
  989. temp1 := '';
  990. initialize8(trans);
  991. For i := 1 To length(str256) Do temp1 := temp1 + trans[ord(str256[i])];
  992. While (temp1[1] = '0') And (temp1 <> '0') Do delete(temp1, 1, 1);
  993. Base2StringToFGInt(temp1, FGInt);
  994. End;
  995. // Convert an MPI (Multiple Precision Integer, PGP style) to an FGInt &
  996. // visa versa
  997. Procedure PGPMPIToFGInt(PGPMPI : String; Var FGInt : TFGInt);
  998. Var
  999. temp : String;
  1000. Begin
  1001. temp := PGPMPI;
  1002. delete(temp, 1, 2);
  1003. Base256StringToFGInt(temp, FGInt);
  1004. End;
  1005. Procedure FGIntToPGPMPI(FGInt : TFGInt; Var PGPMPI : String);
  1006. Var
  1007. len, i : word;
  1008. c : char;
  1009. b : byte;
  1010. Begin
  1011. FGIntToBase256String(FGInt, PGPMPI);
  1012. len := length(PGPMPI) * 8;
  1013. c := PGPMPI[1];
  1014. For i := 7 Downto 0 Do If (ord(c) Shr i) = 0 Then len := len - 1 Else break;
  1015. b := len Mod 256;
  1016. PGPMPI := chr(b) + PGPMPI;
  1017. b := len Div 256;
  1018. PGPMPI := chr(b) + PGPMPI;
  1019. End;
  1020. // Exponentiate a FGInt, FGInt^exp = res
  1021. Procedure FGIntExp(Const FGInt, exp : TFGInt; Var res : TFGInt);
  1022. Var
  1023. temp2, temp3 : TFGInt;
  1024. S : String;
  1025. i : longint;
  1026. Begin
  1027. FGIntToBase2String(exp, S);
  1028. If S[length(S)] = '0' Then Base10StringToFGInt('1', res) Else FGIntCopy(FGInt, res);
  1029. FGIntCopy(FGInt, temp2);
  1030. If length(S) > 1 Then
  1031. For i := (length(S) - 1) Downto 1 Do
  1032. Begin
  1033. FGIntSquare(temp2, temp3);
  1034. FGIntCopy(temp3, temp2);
  1035. If S[i] = '1' Then
  1036. Begin
  1037. FGIntMul(res, temp2, temp3);
  1038. FGIntCopy(temp3, res);
  1039. End;
  1040. End;
  1041. End;
  1042. // Compute FGInt! = FGInt * (FGInt - 1) * (FGInt - 2) * ... * 3 * 2 * 1
  1043. Procedure FGIntFac(Const FGInt : TFGInt; Var res : TFGInt);
  1044. Var
  1045. one, temp, temp1 : TFGInt;
  1046. Begin
  1047. FGIntCopy(FGInt, temp);
  1048. Base10StringToFGInt('1', res);
  1049. Base10StringToFGInt('1', one);
  1050. While Not (FGIntCompareAbs(temp, one) = Eq) Do
  1051. Begin
  1052. FGIntMul(temp, res, temp1);
  1053. FGIntCopy(temp1, res);
  1054. FGIntSubBis(temp, one);
  1055. End;
  1056. FGIntDestroy(one);
  1057. FGIntDestroy(temp);
  1058. End;
  1059. // FGInt = FGInt * 2147483648
  1060. Procedure FGIntShiftLeftBy31(Var FGInt : TFGInt);
  1061. Var
  1062. f1, f2 : int64;
  1063. i, size : longint;
  1064. Begin
  1065. size := FGInt.Number[0];
  1066. SetLength(FGInt.Number, size + 2);
  1067. f1 := 0;
  1068. For i := 1 To (size + 1) Do
  1069. Begin
  1070. f2 := FGInt.Number[i];
  1071. FGInt.Number[i] := f1;
  1072. f1 := f2;
  1073. End;
  1074. FGInt.Number[0] := size + 1;
  1075. End;
  1076. // Divide 2 FGInts, FGInt1 = FGInt2 * QFGInt + MFGInt, MFGInt is always positive
  1077. Procedure FGIntDivMod(Var FGInt1, FGInt2, QFGInt, MFGInt : TFGInt);
  1078. Var
  1079. one, zero, temp1, temp2 : TFGInt;
  1080. s1, s2 : TSign;
  1081. i, j, s, t : longint;
  1082. Begin
  1083. s1 := FGInt1.Sign;
  1084. s2 := FGInt2.Sign;
  1085. FGIntAbs(FGInt1);
  1086. FGIntAbs(FGInt2);
  1087. FGIntCopy(FGInt1, MFGInt);
  1088. FGIntCopy(FGInt2, temp1);
  1089. If FGIntCompareAbs(FGInt1, FGInt2) <> St Then
  1090. Begin
  1091. s := FGInt1.Number[0] - FGInt2.Number[0];
  1092. setlength(QFGInt.Number, s + 2);
  1093. QFGInt.Number[0] := s + 1;
  1094. For t := 1 To s Do
  1095. Begin
  1096. FGIntShiftLeftBy31(temp1);
  1097. QFGInt.Number[t] := 0;
  1098. End;
  1099. j := s + 1;
  1100. QFGInt.Number[j] := 0;
  1101. While FGIntCompareAbs(MFGInt, FGInt2) <> St Do
  1102. Begin
  1103. While FGIntCompareAbs(MFGInt, temp1) <> St Do
  1104. Begin
  1105. If MFGInt.Number[0] > temp1.Number[0] Then
  1106. i := (2147483648 * MFGInt.Number[MFGInt.Number[0]] + MFGInt.Number[MFGInt.Number[0] - 1]) Div (temp1.Number[temp1.Number[0]] + 1)
  1107. Else i := MFGInt.Number[MFGInt.Number[0]] Div (temp1.Number[temp1.Number[0]] + 1);
  1108. If (i <> 0) Then
  1109. Begin
  1110. FGIntCopy(temp1, temp2);
  1111. FGIntMulByIntBis(temp2, i);
  1112. FGIntSubBis(MFGInt, temp2);
  1113. QFGInt.Number[j] := QFGInt.Number[j] + i;
  1114. If FGIntCompareAbs(MFGInt, temp2) <> St Then
  1115. Begin
  1116. QFGInt.Number[j] := QFGInt.Number[j] + i;
  1117. FGIntSubBis(MFGInt, temp2);
  1118. End;
  1119. End Else
  1120. Begin
  1121. QFGInt.Number[j] := QFGInt.Number[j] + 1;
  1122. FGIntSubBis(MFGInt, temp1);
  1123. End;
  1124. End;
  1125. If MFGInt.Number[0] <= temp1.Number[0] Then
  1126. If FGIntCompareAbs(temp1, FGInt2) <> Eq Then
  1127. Begin
  1128. FGIntShiftRightBy31(temp1);
  1129. j := j - 1;
  1130. End;
  1131. End;
  1132. End
  1133. Else Base10StringToFGInt('0', QFGInt);
  1134. s := QFGInt.Number[0];
  1135. While (s > 1) And (QFGInt.Number[s] = 0) Do s := s - 1;
  1136. If s < QFGInt.Number[0] Then
  1137. Begin
  1138. setlength(QFGInt.Number, s + 1);
  1139. QFGInt.Number[0] := s;
  1140. End;
  1141. QFGInt.Sign := positive;
  1142. FGIntDestroy(temp1);
  1143. Base10StringToFGInt('0', zero);
  1144. Base10StringToFGInt('1', one);
  1145. If s1 = negative Then
  1146. Begin
  1147. If FGIntCompareAbs(MFGInt, zero) <> Eq Then
  1148. Begin
  1149. FGIntadd(QFGInt, one, temp1);
  1150. FGIntCopy(temp1, QFGInt);
  1151. FGIntDestroy(temp1);
  1152. FGIntsub(FGInt2, MFGInt, temp1);
  1153. FGIntCopy(temp1, MFGInt);
  1154. End;
  1155. If s2 = positive Then QFGInt.Sign := negative;
  1156. End
  1157. Else QFGInt.Sign := s2;
  1158. FGIntDestroy(one);
  1159. FGIntDestroy(zero);
  1160. FGInt1.Sign := s1;
  1161. FGInt2.Sign := s2;
  1162. End;
  1163. // Same as above but doesn 't compute MFGInt
  1164. Procedure FGIntDiv(Var FGInt1, FGInt2, QFGInt : TFGInt);
  1165. Var
  1166. one, zero, temp1, temp2, MFGInt : TFGInt;
  1167. s1, s2 : TSign;
  1168. i, j, s, t : longint;
  1169. Begin
  1170. s1 := FGInt1.Sign;
  1171. s2 := FGInt2.Sign;
  1172. FGIntAbs(FGInt1);
  1173. FGIntAbs(FGInt2);
  1174. FGIntCopy(FGInt1, MFGInt);
  1175. FGIntCopy(FGInt2, temp1);
  1176. If FGIntCompareAbs(FGInt1, FGInt2) <> St Then
  1177. Begin
  1178. s := FGInt1.Number[0] - FGInt2.Number[0];
  1179. setlength(QFGInt.Number, s + 2);
  1180. QFGInt.Number[0] := s + 1;
  1181. For t := 1 To s Do
  1182. Begin
  1183. FGIntShiftLeftBy31(temp1);
  1184. QFGInt.Number[t] := 0;
  1185. End;
  1186. j := s + 1;
  1187. QFGInt.Number[j] := 0;
  1188. While FGIntCompareAbs(MFGInt, FGInt2) <> St Do
  1189. Begin
  1190. While FGIntCompareAbs(MFGInt, temp1) <> St Do
  1191. Begin
  1192. If MFGInt.Number[0] > temp1.Number[0] Then
  1193. i := (2147483648 * MFGInt.Number[MFGInt.Number[0]] + MFGInt.Number[MFGInt.Number[0] - 1]) Div (temp1.Number[temp1.Number[0]] + 1)
  1194. Else i := MFGInt.Number[MFGInt.Number[0]] Div (temp1.Number[temp1.Number[0]] + 1);
  1195. If (i <> 0) Then
  1196. Begin
  1197. FGIntCopy(temp1, temp2);
  1198. FGIntMulByIntBis(temp2, i);
  1199. FGIntSubBis(MFGInt, temp2);
  1200. QFGInt.Number[j] := QFGInt.Number[j] + i;
  1201. If FGIntCompareAbs(MFGInt, temp2) <> St Then
  1202. Begin
  1203. QFGInt.Number[j] := QFGInt.Number[j] + i;
  1204. FGIntSubBis(MFGInt, temp2);
  1205. End;
  1206. End Else
  1207. Begin
  1208. QFGInt.Number[j] := QFGInt.Number[j] + 1;
  1209. FGIntSubBis(MFGInt, temp1);
  1210. End;
  1211. End;
  1212. If MFGInt.Number[0] <= temp1.Number[0] Then
  1213. If FGIntCompareAbs(temp1, FGInt2) <> Eq Then
  1214. Begin
  1215. FGIntShiftRightBy31(temp1);
  1216. j := j - 1;
  1217. End;
  1218. End;
  1219. End
  1220. Else Base10StringToFGInt('0', QFGInt);
  1221. s := QFGInt.Number[0];
  1222. While (s > 1) And (QFGInt.Number[s] = 0) Do s := s - 1;
  1223. If s < QFGInt.Number[0] Then
  1224. Begin
  1225. setlength(QFGInt.Number, s + 1);
  1226. QFGInt.Number[0] := s;
  1227. End;
  1228. QFGInt.Sign := positive;
  1229. FGIntDestroy(temp1);
  1230. Base10StringToFGInt('0', zero);
  1231. Base10StringToFGInt('1', one);
  1232. If s1 = negative Then
  1233. Begin
  1234. If FGIntCompareAbs(MFGInt, zero) <> Eq Then
  1235. Begin
  1236. FGIntadd(QFGInt, one, temp1);
  1237. FGIntCopy(temp1, QFGInt);
  1238. FGIntDestroy(temp1);
  1239. FGIntsub(FGInt2, MFGInt, temp1);
  1240. FGIntCopy(temp1, MFGInt);
  1241. End;
  1242. If s2 = positive Then QFGInt.Sign := negative;
  1243. End
  1244. Else QFGInt.Sign := s2;
  1245. FGIntDestroy(one);
  1246. FGIntDestroy(zero);
  1247. FGIntDestroy(MFGInt);
  1248. FGInt1.Sign := s1;
  1249. FGInt2.Sign := s2;
  1250. End;
  1251. // Same as above but this computes MFGInt in stead of QFGInt
  1252. // MFGInt = FGInt1 mod FGInt2
  1253. Procedure FGIntMod(Var FGInt1, FGInt2, MFGInt : TFGInt);
  1254. Var
  1255. one, zero, temp1, temp2 : TFGInt;
  1256. s1, s2 : TSign;
  1257. i : int64;
  1258. s, t : longint;
  1259. Begin
  1260. s1 := FGInt1.Sign;
  1261. s2 := FGInt2.Sign;
  1262. FGIntAbs(FGInt1);
  1263. FGIntAbs(FGInt2);
  1264. FGIntCopy(FGInt1, MFGInt);
  1265. FGIntCopy(FGInt2, temp1);
  1266. If FGIntCompareAbs(FGInt1, FGInt2) <> St Then
  1267. Begin
  1268. s := FGInt1.Number[0] - FGInt2.Number[0];
  1269. For t := 1 To s Do FGIntShiftLeftBy31(temp1);
  1270. While FGIntCompareAbs(MFGInt, FGInt2) <> St Do
  1271. Begin
  1272. While FGIntCompareAbs(MFGInt, temp1) <> St Do
  1273. Begin
  1274. If MFGInt.Number[0] > temp1.Number[0] Then
  1275. i := (2147483648 * MFGInt.Number[MFGInt.Number[0]] + MFGInt.Number[MFGInt.Number[0] - 1]) Div (temp1.Number[temp1.Number[0]] + 1)
  1276. Else i := MFGInt.Number[MFGInt.Number[0]] Div (temp1.Number[temp1.Number[0]] + 1);
  1277. If (i <> 0) Then
  1278. Begin
  1279. FGIntCopy(temp1, temp2);
  1280. FGIntMulByIntBis(temp2, i);
  1281. FGIntSubBis(MFGInt, temp2);
  1282. If FGIntCompareAbs(MFGInt, temp2) <> St Then FGIntSubBis(MFGInt, temp2);
  1283. End Else FGIntSubBis(MFGInt, temp1);
  1284. // If FGIntCompareAbs(MFGInt, temp1) <> St Then FGIntSubBis(MFGInt,temp1);
  1285. End;
  1286. If MFGInt.Number[0] <= temp1.Number[0] Then
  1287. If FGIntCompareAbs(temp1, FGInt2) <> Eq Then FGIntShiftRightBy31(temp1);
  1288. End;
  1289. End;
  1290. FGIntDestroy(temp1);
  1291. Base10StringToFGInt('0', zero);
  1292. Base10StringToFGInt('1', one);
  1293. If s1 = negative Then
  1294. Begin
  1295. If FGIntCompareAbs(MFGInt, zero) <> Eq Then
  1296. Begin
  1297. FGIntSub(FGInt2, MFGInt, temp1);
  1298. FGIntCopy(temp1, MFGInt);
  1299. End;
  1300. End;
  1301. FGIntDestroy(one);
  1302. FGIntDestroy(zero);
  1303. FGInt1.Sign := s1;
  1304. FGInt2.Sign := s2;
  1305. End;
  1306. // Square a FGInt modulo Modb, FGInt^2 mod Modb = FGIntSM
  1307. Procedure FGIntSquareMod(Var FGInt, Modb, FGIntSM : TFGInt);
  1308. Var
  1309. temp : TFGInt;
  1310. Begin
  1311. FGIntSquare(FGInt, temp);
  1312. FGIntMod(temp, Modb, FGIntSM);
  1313. FGIntDestroy(temp);
  1314. End;
  1315. // Add 2 FGInts modulo base, (FGInt1 + FGInt2) mod base = FGIntres
  1316. Procedure FGIntAddMod(Var FGInt1, FGInt2, base, FGIntres : TFGInt);
  1317. Var
  1318. temp : TFGInt;
  1319. Begin
  1320. FGIntadd(FGInt1, FGInt2, temp);
  1321. FGIntMod(temp, base, FGIntres);
  1322. FGIntDestroy(temp);
  1323. End;
  1324. // Multiply 2 FGInts modulo base, (FGInt1 * FGInt2) mod base = FGIntres
  1325. Procedure FGIntMulMod(Var FGInt1, FGInt2, base, FGIntres : TFGInt);
  1326. Var
  1327. temp : TFGInt;
  1328. Begin
  1329. FGIntMul(FGInt1, FGInt2, temp);
  1330. FGIntMod(temp, base, FGIntres);
  1331. FGIntDestroy(temp);
  1332. End;
  1333. // Exponentiate 2 FGInts modulo base, (FGInt1 ^ FGInt2) mod modb = res
  1334. Procedure FGIntModExp(Var FGInt, exp, modb, res : TFGInt);
  1335. Var
  1336. temp2, temp3 : TFGInt;
  1337. i : longint;
  1338. S : String;
  1339. Begin
  1340. If (Modb.Number[1] Mod 2) = 1 Then
  1341. Begin
  1342. FGIntMontgomeryModExp(FGInt, exp, modb, res);
  1343. exit;
  1344. End;
  1345. FGIntToBase2String(exp, S);
  1346. Base10StringToFGInt('1', res);
  1347. FGIntcopy(FGInt, temp2);
  1348. For i := length(S) Downto 1 Do
  1349. Begin
  1350. If S[i] = '1' Then
  1351. Begin
  1352. FGIntmulMod(res, temp2, modb, temp3);
  1353. FGIntCopy(temp3, res);
  1354. End;
  1355. FGIntSquareMod(temp2, Modb, temp3);
  1356. FGIntCopy(temp3, temp2);
  1357. End;
  1358. FGIntDestroy(temp2);
  1359. End;
  1360. // Procedures for Montgomery Exponentiation
  1361. Procedure FGIntModBis(Const FGInt : TFGInt; Var FGIntOut : TFGInt; b : longint; head : int64);
  1362. Var
  1363. i : longint;
  1364. Begin
  1365. If b <= FGInt.Number[0] Then
  1366. Begin
  1367. FGIntOut.Number := Copy(FGInt.Number, 0, b + 1);
  1368. FGIntOut.Number[b] := FGIntOut.Number[b] And head;
  1369. i := b;
  1370. While (FGIntOut.Number[i] = 0) And (i > 1) Do i := i - 1;
  1371. If i < b Then SetLength(FGIntOut.Number, i + 1);
  1372. FGIntOut.Number[0] := i;
  1373. FGIntOut.Sign := positive;
  1374. End Else FGIntCopy(FGInt, FGIntOut);
  1375. End;
  1376. Procedure FGIntMulModBis(Const FGInt1, FGInt2 : TFGInt; Var Prod : TFGInt; b : longint; head : int64);
  1377. Var
  1378. i, j, size, size1, size2, t : longint;
  1379. rest, Trest : int64;
  1380. Begin
  1381. size1 := FGInt1.Number[0];
  1382. size2 := FGInt2.Number[0];
  1383. size := min(b, size1 + size2);
  1384. SetLength(Prod.Number, size + 1);
  1385. For i := 1 To size Do Prod.Number[i] := 0;
  1386. For i := 1 To size2 Do
  1387. Begin
  1388. rest := 0;
  1389. t := min(size1, b - i + 1);
  1390. For j := 1 To t Do
  1391. Begin
  1392. Trest := Prod.Number[j + i - 1] + FGInt1.Number[j] * FGInt2.Number[i] + rest;
  1393. Prod.Number[j + i - 1] := Trest And 2147483647;
  1394. rest := Trest Shr 31;
  1395. End;
  1396. If (i + size1) <= b Then Prod.Number[i + size1] := rest;
  1397. End;
  1398. Prod.Number[0] := size;
  1399. If size = b Then Prod.Number[b] := Prod.Number[b] And head;
  1400. While (Prod.Number[size] = 0) And (size > 1) Do size := size - 1;
  1401. If size < Prod.Number[0] Then
  1402. Begin
  1403. SetLength(Prod.Number, size + 1);
  1404. Prod.Number[0] := size;
  1405. End;
  1406. If FGInt1.Sign = FGInt2.Sign Then Prod.Sign := Positive Else prod.Sign := negative;
  1407. End;
  1408. Procedure FGIntMontgomeryMod(Const GInt, base, baseInv : TFGInt; Var MGInt : TFGInt; b : longint; head : int64);
  1409. Var
  1410. m, temp, temp1 : TFGInt;
  1411. r : int64;
  1412. Begin
  1413. FGIntModBis(GInt, temp, b, head);
  1414. FGIntMulModBis(temp, baseInv, m, b, head);
  1415. FGIntMul(m, base, temp1);
  1416. FGIntDestroy(temp);
  1417. FGIntAdd(temp1, GInt, temp);
  1418. FGIntDestroy(temp1);
  1419. MGInt.Number := copy(temp.Number, b - 1, temp.Number[0] - b + 2);
  1420. MGInt.Sign := positive;
  1421. MGInt.Number[0] := temp.Number[0] - b + 1;
  1422. FGIntDestroy(temp);
  1423. If (head Shr 30) = 0 Then FGIntDivByIntBis(MGInt, head + 1, r)
  1424. Else FGIntShiftRightBy31(MGInt);
  1425. If FGIntCompareAbs(MGInt, base) <> St Then FGIntSubBis(MGInt, base);
  1426. FGIntDestroy(temp);
  1427. FGIntDestroy(m);
  1428. End;
  1429. Procedure FGIntMontgomeryModExp(Var FGInt, exp, modb, res : TFGInt);
  1430. Var
  1431. temp2, temp3, baseInv, r : TFGInt;
  1432. i, j, t, b : longint;
  1433. S : String;
  1434. head : int64;
  1435. Begin
  1436. FGIntToBase2String(exp, S);
  1437. t := modb.Number[0];
  1438. b := t;
  1439. If (modb.Number[t] Shr 30) = 1 Then t := t + 1;
  1440. setlength(r.Number, t + 1);
  1441. r.Number[0] := t;
  1442. r.Sign := positive;
  1443. For i := 1 To t Do r.Number[i] := 0;
  1444. If t = modb.Number[0] Then
  1445. Begin
  1446. head := 2147483647;
  1447. For j := 29 Downto 0 Do
  1448. Begin
  1449. head := head Shr 1;
  1450. If (modb.Number[t] Shr j) = 1 Then
  1451. Begin
  1452. r.Number[t] := 1 Shl (j + 1);
  1453. break;
  1454. End;
  1455. End;
  1456. End
  1457. Else
  1458. Begin
  1459. r.Number[t] := 1;
  1460. head := 2147483647;
  1461. End;
  1462. FGIntModInv(modb, r, temp2);
  1463. If temp2.Sign = negative Then FGIntCopy(temp2, BaseInv)
  1464. Else
  1465. Begin
  1466. FGIntCopy(r, BaseInv);
  1467. FGIntSubBis(BaseInv, temp2);
  1468. End;
  1469. // FGIntBezoutBachet(r, modb, temp2, BaseInv);
  1470. FGIntAbs(BaseInv);
  1471. FGIntDestroy(temp2);
  1472. FGIntMod(r, modb, res);
  1473. FGIntMulMod(FGInt, res, modb, temp2);
  1474. FGIntDestroy(r);
  1475. For i := length(S) Downto 1 Do
  1476. Begin
  1477. If S[i] = '1' Then
  1478. Begin
  1479. FGIntmul(res, temp2, temp3);
  1480. FGIntDestroy(res);
  1481. FGIntMontgomeryMod(temp3, modb, baseinv, res, b, head);
  1482. FGIntDestroy(temp3);
  1483. End;
  1484. FGIntSquare(temp2, temp3);
  1485. FGIntDestroy(temp2);
  1486. FGIntMontgomeryMod(temp3, modb, baseinv, temp2, b, head);
  1487. FGIntDestroy(temp3);
  1488. End;
  1489. FGIntDestroy(temp2);
  1490. FGIntMontgomeryMod(res, modb, baseinv, temp3, b, head);
  1491. FGIntCopy(temp3, res);
  1492. FGIntDestroy(temp3);
  1493. FGIntDestroy(baseinv);
  1494. End;
  1495. // Compute the Greatest Common Divisor of 2 FGInts
  1496. Procedure FGIntGCD(Const FGInt1, FGInt2 : TFGInt; Var GCD : TFGInt);
  1497. Var
  1498. k : TCompare;
  1499. zero, temp1, temp2, temp3 : TFGInt;
  1500. Begin
  1501. k := FGIntCompareAbs(FGInt1, FGInt2);
  1502. If (k = Eq) Then FGIntCopy(FGInt1, GCD) Else
  1503. If (k = St) Then FGIntGCD(FGInt2, FGInt1, GCD) Else
  1504. Begin
  1505. Base10StringToFGInt('0', zero);
  1506. FGIntCopy(FGInt1, temp1);
  1507. FGIntCopy(FGInt2, temp2);
  1508. While (temp2.Number[0] <> 1) Or (temp2.Number[1] <> 0) Do
  1509. Begin
  1510. FGIntMod(temp1, temp2, temp3);
  1511. FGIntCopy(temp2, temp1);
  1512. FGIntCopy(temp3, temp2);
  1513. FGIntDestroy(temp3);
  1514. End;
  1515. FGIntCopy(temp1, GCD);
  1516. FGIntDestroy(temp2);
  1517. FGIntDestroy(zero);
  1518. End;
  1519. End;
  1520. // Compute the Least Common Multiple of 2 FGInts
  1521. Procedure FGIntLCM(Const FGInt1, FGInt2 : TFGInt; Var LCM : TFGInt);
  1522. Var
  1523. temp1, temp2 : TFGInt;
  1524. Begin
  1525. FGIntGCD(FGInt1, FGInt2, temp1);
  1526. FGIntmul(FGInt1, FGInt2, temp2);
  1527. FGIntdiv(temp2, temp1, LCM);
  1528. FGIntDestroy(temp1);
  1529. FGIntDestroy(temp2);
  1530. End;
  1531. // Trialdivision of a FGInt upto 9999 and stopping when a divisor is found, returning ok=false
  1532. Procedure FGIntTrialDiv9999(Const FGInt : TFGInt; Var ok : boolean);
  1533. Var
  1534. j : int64;
  1535. i : integer;
  1536. Begin
  1537. If ((FGInt.Number[1] Mod 2) = 0) Then ok := false
  1538. Else
  1539. Begin
  1540. i := 0;
  1541. ok := true;
  1542. While ok And (i < 1228) Do
  1543. Begin
  1544. i := i + 1;
  1545. FGIntmodbyint(FGInt, primes[i], j);
  1546. If j = 0 Then ok := false;
  1547. End;
  1548. End;
  1549. End;
  1550. // A prng
  1551. Procedure FGIntRandom1(Var Seed, RandomFGInt : TFGInt);
  1552. Var
  1553. temp, base : TFGInt;
  1554. Begin
  1555. Base10StringToFGInt('281474976710656', base);
  1556. Base10StringToFGInt('44485709377909', temp);
  1557. FGIntMulMod(seed, temp, base, RandomFGInt);
  1558. FGIntDestroy(temp);
  1559. FGIntDestroy(base);
  1560. End;
  1561. // Perform a Rabin Miller Primality Test nrtest times on FGIntp, returns ok=true when FGIntp passes the test
  1562. Procedure FGIntRabinMiller(Var FGIntp : TFGInt; nrtest : integer; Var ok : boolean);
  1563. Var
  1564. j, b, i : int64;
  1565. m, z, temp1, temp2, temp3, zero, one, two, pmin1 : TFGInt;
  1566. ok1, ok2 : boolean;
  1567. Begin
  1568. randomize;
  1569. j := 0;
  1570. Base10StringToFGInt('0', zero);
  1571. Base10StringToFGInt('1', one);
  1572. Base10StringToFGInt('2', two);
  1573. FGIntsub(FGIntp, one, temp1);
  1574. FGIntsub(FGIntp, one, pmin1);
  1575. b := 0;
  1576. While (temp1.Number[1] Mod 2) = 0 Do
  1577. Begin
  1578. b := b + 1;
  1579. FGIntShiftRight(temp1);
  1580. End;
  1581. m := temp1;
  1582. i := 0;
  1583. ok := true;
  1584. Randomize;
  1585. While (i < nrtest) And ok Do
  1586. Begin
  1587. i := i + 1;
  1588. Base10StringToFGInt(inttostr(Primes[Random(1227) + 1]), temp2);
  1589. FGIntMontGomeryModExp(temp2, m, FGIntp, z);
  1590. FGIntDestroy(temp2);
  1591. ok1 := (FGIntCompareAbs(z, one) = Eq);
  1592. ok2 := (FGIntCompareAbs(z, pmin1) = Eq);
  1593. If Not (ok1 Or ok2) Then
  1594. Begin
  1595. While (ok And (j < b)) Do
  1596. Begin
  1597. If (j > 0) And ok1 Then ok := false
  1598. Else
  1599. Begin
  1600. j := j + 1;
  1601. If (j < b) And (Not ok2) Then
  1602. Begin
  1603. FGIntSquaremod(z, FGIntp, temp3);
  1604. FGIntCopy(temp3, z);
  1605. ok1 := (FGIntCompareAbs(z, one) = Eq);
  1606. ok2 := (FGIntCompareAbs(z, pmin1) = Eq);
  1607. If ok2 Then j := b;
  1608. End
  1609. Else If (Not ok2) And (j >= b) Then ok := false;
  1610. End;
  1611. End;
  1612. End
  1613. End;
  1614. FGIntDestroy(zero);
  1615. FGIntDestroy(one);
  1616. FGIntDestroy(two);
  1617. FGIntDestroy(m);
  1618. FGIntDestroy(z);
  1619. FGIntDestroy(pmin1);
  1620. End;
  1621. // Compute the coefficients from the Bezout Bachet theorem, FGInt1 * a + FGInt2 * b = GCD(FGInt1, FGInt2)
  1622. Procedure FGIntBezoutBachet(Var FGInt1, FGInt2, a, b : TFGInt);
  1623. Var
  1624. zero, r1, r2, r3, ta, gcd, temp, temp1, temp2 : TFGInt;
  1625. Begin
  1626. If FGIntCompareAbs(FGInt1, FGInt2) <> St Then
  1627. Begin
  1628. FGIntcopy(FGInt1, r1);
  1629. FGIntcopy(FGInt2, r2);
  1630. Base10StringToFGInt('0', zero);
  1631. Base10StringToFGInt('1', a);
  1632. Base10StringToFGInt('0', ta);
  1633. Repeat
  1634. FGIntdivmod(r1, r2, temp, r3);
  1635. FGIntDestroy(r1);
  1636. r1 := r2;
  1637. r2 := r3;
  1638. FGIntmul(ta, temp, temp1);
  1639. FGIntsub(a, temp1, temp2);
  1640. FGIntCopy(ta, a);
  1641. FGIntCopy(temp2, ta);
  1642. FGIntDestroy(temp1);
  1643. FGIntDestroy(temp);
  1644. Until FGIntCompareAbs(r3, zero) = Eq;
  1645. FGIntGCD(FGInt1, FGInt2, gcd);
  1646. FGIntmul(a, FGInt1, temp1);
  1647. FGIntsub(gcd, temp1, temp2);
  1648. FGIntDestroy(temp1);
  1649. FGIntdiv(temp2, FGInt2, b);
  1650. FGIntDestroy(temp2);
  1651. FGIntDestroy(ta);
  1652. FGIntDestroy(r1);
  1653. FGIntDestroy(r2);
  1654. FGIntDestroy(gcd);
  1655. End
  1656. Else FGIntBezoutBachet(FGInt2, FGInt1, b, a);
  1657. End;
  1658. // Find the (multiplicative) Modular inverse of a FGInt in a finite ring
  1659. // of additive order base
  1660. Procedure FGIntModInv(Const FGInt1, base : TFGInt; Var Inverse : TFGInt);
  1661. Var
  1662. zero, one, r1, r2, r3, tb, gcd, temp, temp1, temp2 : TFGInt;
  1663. Begin
  1664. Base10StringToFGInt('1', one);
  1665. FGIntGCD(FGInt1, base, gcd);
  1666. If FGIntCompareAbs(one, gcd) = Eq Then
  1667. Begin
  1668. FGIntcopy(base, r1);
  1669. FGIntcopy(FGInt1, r2);
  1670. Base10StringToFGInt('0', zero);
  1671. Base10StringToFGInt('0', inverse);
  1672. Base10StringToFGInt('1', tb);
  1673. Repeat
  1674. FGIntDestroy(r3);
  1675. FGIntdivmod(r1, r2, temp, r3);
  1676. FGIntCopy(r2, r1);
  1677. FGIntCopy(r3, r2);
  1678. FGIntmul(tb, temp, temp1);
  1679. FGIntsub(inverse, temp1, temp2);
  1680. FGIntDestroy(inverse);
  1681. FGIntDestroy(temp1);
  1682. FGIntCopy(tb, inverse);
  1683. FGIntCopy(temp2, tb);
  1684. FGIntDestroy(temp);
  1685. Until FGIntCompareAbs(r3, zero) = Eq;
  1686. If inverse.Sign = negative Then
  1687. Begin
  1688. FGIntadd(base, inverse, temp);
  1689. FGIntCopy(temp, inverse);
  1690. End;
  1691. FGIntDestroy(tb);
  1692. FGIntDestroy(r1);
  1693. FGIntDestroy(r2);
  1694. End;
  1695. FGIntDestroy(gcd);
  1696. FGIntDestroy(one);
  1697. End;
  1698. // Perform a (combined) primality test on FGIntp consisting of a trialdivision upto 8192,
  1699. // if the FGInt passes perform nrRMtests Rabin Miller primality tests, returns ok when a
  1700. // FGInt is probably prime
  1701. Procedure FGIntPrimetest(Var FGIntp : TFGInt; nrRMtests : integer; Var ok : boolean);
  1702. Begin
  1703. FGIntTrialdiv9999(FGIntp, ok);
  1704. If ok Then FGIntRabinMiller(FGIntp, nrRMtests, ok);
  1705. End;
  1706. // Computes the Legendre symbol for a any number and
  1707. // p a prime, returns 0 if p divides a, 1 if a is a
  1708. // quadratic residu mod p, -1 if a is a quadratic
  1709. // nonresidu mod p
  1710. Procedure FGIntLegendreSymbol(Var a, p : TFGInt; Var L : integer);
  1711. Var
  1712. temp1, temp2, temp3, temp4, temp5, zero, one : TFGInt;
  1713. i : int64;
  1714. ok1, ok2 : boolean;
  1715. Begin
  1716. Base10StringToFGInt('0', zero);
  1717. Base10StringToFGInt('1', one);
  1718. FGIntMod(a, p, temp1);
  1719. If FGIntCompareAbs(zero, temp1) = Eq Then
  1720. Begin
  1721. FGIntDestroy(temp1);
  1722. L := 0;
  1723. End
  1724. Else
  1725. Begin
  1726. FGIntDestroy(temp1);
  1727. FGIntCopy(p, temp1);
  1728. FGIntCopy(a, temp2);
  1729. L := 1;
  1730. While FGIntCompareAbs(temp2, one) <> Eq Do
  1731. Begin
  1732. If (temp2.Number[1] Mod 2) = 0 Then
  1733. Begin
  1734. FGIntSquare(temp1, temp3);
  1735. FGIntSub(temp3, one, temp4);
  1736. FGIntDestroy(temp3);
  1737. FGIntDivByInt(temp4, temp3, 8, i);
  1738. If (temp3.Number[1] Mod 2) = 0 Then ok1 := false Else ok1 := true;
  1739. FGIntDestroy(temp3);
  1740. FGIntDestroy(temp4);
  1741. If ok1 = true Then L := L * (-1);
  1742. FGIntDivByIntBis(temp2, 2, i);
  1743. End
  1744. Else
  1745. Begin
  1746. FGIntSub(temp1, one, temp3);
  1747. FGIntSub(temp2, one, temp4);
  1748. FGIntMul(temp3, temp4, temp5);
  1749. FGIntDestroy(temp3);
  1750. FGIntDestroy(temp4);
  1751. FGIntDivByInt(temp5, temp3, 4, i);
  1752. If (temp3.Number[1] Mod 2) = 0 Then ok2 := false Else ok2 := true;
  1753. FGIntDestroy(temp5);
  1754. FGIntDestroy(temp3);
  1755. If ok2 = true Then L := L * (-1);
  1756. FGIntMod(temp1, temp2, temp3);
  1757. FGIntCopy(temp2, temp1);
  1758. FGIntCopy(temp3, temp2);
  1759. End;
  1760. End;
  1761. FGIntDestroy(temp1);
  1762. FGIntDestroy(temp2);
  1763. End;
  1764. FGIntDestroy(zero);
  1765. FGIntDestroy(one);
  1766. End;
  1767. // Compute a square root modulo a prime number
  1768. // SquareRoot^2 mod Prime = Square
  1769. Procedure FGIntSquareRootModP(Square, Prime : TFGInt; Var SquareRoot : TFGInt);
  1770. Var
  1771. one, n, b, s, r, temp, temp1, temp2, temp3 : TFGInt;
  1772. a, L, i, j : longint;
  1773. Begin
  1774. Base2StringToFGInt('1', one);
  1775. Base2StringToFGInt('2', n);
  1776. a := 0;
  1777. FGIntLegendreSymbol(n, Prime, L);
  1778. While L <> -1 Do
  1779. Begin
  1780. FGIntAddBis(n, one);
  1781. FGIntLegendreSymbol(n, Prime, L);
  1782. End;
  1783. FGIntCopy(Prime, s);
  1784. s.Number[1] := s.Number[1] - 1;
  1785. While (s.Number[1] Mod 2) = 0 Do
  1786. Begin
  1787. FGIntShiftRight(s);
  1788. a := a + 1;
  1789. End;
  1790. FGIntMontgomeryModExp(n, s, Prime, b);
  1791. FGIntAdd(s, one, temp);
  1792. FGIntShiftRight(temp);
  1793. FGIntMontgomeryModExp(Square, temp, Prime, r);
  1794. FGIntDestroy(temp);
  1795. FGIntModInv(Square, Prime, temp1);
  1796. For i := 0 To (a - 2) Do
  1797. Begin
  1798. FGIntSquareMod(r, Prime, temp2);
  1799. FGIntMulMod(temp1, temp2, Prime, temp);
  1800. FGIntDestroy(temp2);
  1801. For j := 1 To (a - i - 2) Do
  1802. Begin
  1803. FGIntSquareMod(temp, Prime, temp2);
  1804. FGIntDestroy(temp);
  1805. FGIntCopy(temp2, temp);
  1806. FGIntDestroy(temp2);
  1807. End;
  1808. If FGIntCompareAbs(temp, one) <> Eq Then
  1809. Begin
  1810. FGIntMulMod(r, b, Prime, temp3);
  1811. FGIntDestroy(r);
  1812. FGIntCopy(temp3, r);
  1813. FGIntDestroy(temp3);
  1814. End;
  1815. FGIntDestroy(temp);
  1816. FGIntDestroy(temp2);
  1817. If i = (a - 2) Then break;
  1818. FGIntSquareMod(b, Prime, temp3);
  1819. FGIntDestroy(b);
  1820. FGIntCopy(temp3, b);
  1821. FGIntDestroy(temp3);
  1822. End;
  1823. FGIntCopy(r, SquareRoot);
  1824. FGIntDestroy(r);
  1825. FGIntDestroy(s);
  1826. FGIntDestroy(b);
  1827. FGIntDestroy(temp1);
  1828. FGIntDestroy(one);
  1829. FGIntDestroy(n);
  1830. End;
  1831. End.