MathgeomGLS
1747 строк · 54.9 Кб
1{**********************************************************************}
2{ }
3{ "The contents of this file are subject to the Mozilla Public }
4{ License Version 1.1 (the "License"); you may not use this }
5{ file except in compliance with the License. You may obtain }
6{ a copy of the License at http://www.mozilla.org/MPL/ }
7{ }
8{ Software distributed under the License is distributed on an }
9{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express }
10{ or implied. See the License for the specific language }
11{ governing rights and limitations under the License. }
12{ }
13{ Copyright Creative IT. }
14{ Current maintainer: Eric Grange }
15{ }
16{**********************************************************************}
17unit dwsBigIntegerFunctions.GMP;
18
19{$I dws.inc}
20
21interface
22
23uses
24Classes, System.SysUtils,
25dwsXPlatform, dwsUtils, dwsStrings, dwsCompilerContext,
26dwsFunctions, dwsSymbols, dwsExprs, dwsCoreExprs, dwsExprList, dwsUnitSymbols,
27dwsConstExprs, dwsMagicExprs, dwsDataContext, dwsErrors, dwsRelExprs,
28dwsOperators, dwsTokenTypes, dwsCryptoXPlatform, dwsScriptSource,
29dwsMPIR;
30
31const
32SYS_BIGINTEGER = 'BigInteger';
33
34type
35
36TBaseBigIntegerSymbol = class (TBaseSymbol)
37public
38constructor Create;
39
40function IsCompatible(typSym : TTypeSymbol) : Boolean; override;
41procedure InitData(const data : TData; offset : Integer); override;
42end;
43
44IdwsBigInteger = interface
45['{93A7FA32-DE99-44AB-A5B4-861FD50E9AAB}']
46function GetValue : pmpz_t;
47procedure SetValue(const v : pmpz_t);
48property Value : pmpz_t read GetValue write SetValue;
49
50function BitLength : Integer;
51function PopCount : Integer;
52function Sign : Integer;
53
54function ToStringBase(base : Integer) : String;
55function ToHexString : String;
56
57function ToInt64 : Int64;
58
59function ToNeg : IdwsBigInteger;
60end;
61
62TdwsBigIntegerWrapperPool = class;
63
64TBigIntegerWrapper = class (TInterfacedObject, IdwsBigInteger, IGetSelf)
65private
66FNext : TBigIntegerWrapper;
67
68protected
69function _Release: Integer; stdcall;
70
71function GetValue : pmpz_t; inline;
72procedure SetValue(const v : pmpz_t); inline;
73function GetSelf : TObject;
74
75constructor CreateNewZero;
76procedure Reset;
77
78public
79Value : mpz_t;
80
81class function CreateZero : TBigIntegerWrapper; static;
82class function CreateInt64(const i : Int64) : TBigIntegerWrapper; static;
83class function CreateFloat(const f : Double) : TBigIntegerWrapper; static;
84class function CreateString(const s : String; base : Integer) : TBigIntegerWrapper; static;
85destructor Destroy; override;
86
87function BitLength : Integer;
88function PopCount : Integer;
89function Sign : Integer;
90
91function ToStringBase(base : Integer) : String;
92function ToHexString : String;
93function ToString : String; override;
94
95function ToInt64 : Int64;
96
97function ToNeg : IdwsBigInteger;
98end;
99
100TdwsBigIntegerWrapperPool = class
101private
102FLock : TMultiReadSingleWrite;
103FHead : TBigIntegerWrapper;
104FSize : Integer;
105
106public
107constructor Create;
108destructor Destroy; override;
109
110function Pop : TBigIntegerWrapper; inline;
111procedure Push(ref : TBigIntegerWrapper); inline;
112procedure Cleanup;
113end;
114
115TBigIntegerNegateExpr = class(TUnaryOpExpr)
116constructor Create(context : TdwsBaseSymbolsContext; const aScriptPos : TScriptPos; expr : TTypedExpr); override;
117procedure EvalAsVariant(exec : TdwsExecution; var result : Variant); override;
118end;
119
120TMPIRBinOpFunc = procedure (var dest: mpz_t; const src1, src2: mpz_t); cdecl;
121
122TBigIntegerBinOpExpr = class(TBinaryOpExpr)
123constructor Create(context : TdwsCompilerContext; const aScriptPos : TScriptPos;
124const anOp : TTokenType; aLeft, aRight : TTypedExpr); override;
125procedure EvalAsVariant(exec : TdwsExecution; var result : Variant); override;
126end;
127
128TBigIntegerBinOpFuncExpr = class(TBigIntegerBinOpExpr)
129protected
130FOpFunc : TMPIRBinOpFunc;
131procedure InitOpFunc; virtual; abstract;
132
133public
134constructor Create(context : TdwsCompilerContext; const aScriptPos : TScriptPos;
135const anOp : TTokenType; aLeft, aRight : TTypedExpr); override;
136
137procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override; final;
138end;
139
140TBigIntegerAddOpExpr = class(TBigIntegerBinOpFuncExpr)
141procedure InitOpFunc; override;
142end;
143TBigIntegerSubOpExpr = class(TBigIntegerBinOpFuncExpr)
144procedure InitOpFunc; override;
145end;
146TBigIntegerMultOpExpr = class(TBigIntegerBinOpFuncExpr)
147procedure InitOpFunc; override;
148end;
149TBigIntegerDivOpExpr = class(TBigIntegerBinOpFuncExpr)
150procedure InitOpFunc; override;
151end;
152TBigIntegerModOpExpr = class(TBigIntegerBinOpFuncExpr)
153procedure InitOpFunc; override;
154end;
155
156TBigIntegerAndOpExpr = class(TBigIntegerBinOpFuncExpr)
157procedure InitOpFunc; override;
158end;
159TBigIntegerOrOpExpr = class(TBigIntegerBinOpFuncExpr)
160procedure InitOpFunc; override;
161end;
162TBigIntegerXorOpExpr = class(TBigIntegerBinOpFuncExpr)
163procedure InitOpFunc; override;
164end;
165
166TBigIntegerShiftLeftExpr = class(TBigIntegerBinOpExpr)
167procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override;
168end;
169TBigIntegerShiftRightExpr = class(TBigIntegerBinOpExpr)
170procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override;
171end;
172
173TBigIntegerOpAssignExpr = class(TOpAssignExpr)
174procedure TypeCheckAssign(context : TdwsCompilerContext); override;
175end;
176
177TBigIntegerPlusAssignExpr = class(TBigIntegerOpAssignExpr)
178procedure EvalNoResult(exec : TdwsExecution); override;
179end;
180TBigIntegerPlusAssignIntExpr = class(TBigIntegerPlusAssignExpr)
181procedure EvalNoResult(exec : TdwsExecution); override;
182end;
183TBigIntegerMinusAssignExpr = class(TBigIntegerOpAssignExpr)
184procedure EvalNoResult(exec : TdwsExecution); override;
185end;
186TBigIntegerMinusAssignIntExpr = class(TBigIntegerMinusAssignExpr)
187procedure EvalNoResult(exec : TdwsExecution); override;
188end;
189TBigIntegerMultAssignExpr = class(TBigIntegerOpAssignExpr)
190procedure EvalNoResult(exec : TdwsExecution); override;
191end;
192
193TBigIntegerRelOpExpr = class(TBoolRelOpExpr)
194protected
195function InternalCompare(exec : TdwsExecution) : Integer;
196end;
197TBigIntegerRelOpExprClass = class of TBigIntegerRelOpExpr;
198
199TBigIntegerEqualOpExpr = class(TBigIntegerRelOpExpr)
200function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
201end;
202TBigIntegerNotEqualOpExpr = class(TBigIntegerRelOpExpr)
203function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
204end;
205TBigIntegerGreaterOpExpr = class(TBigIntegerRelOpExpr)
206function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
207end;
208TBigIntegerGreaterEqualOpExpr = class(TBigIntegerRelOpExpr)
209function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
210end;
211TBigIntegerLessOpExpr = class(TBigIntegerRelOpExpr)
212function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
213end;
214TBigIntegerLessEqualOpExpr = class(TBigIntegerRelOpExpr)
215function EvalAsBoolean(exec : TdwsExecution) : Boolean; override;
216end;
217
218TBigIntegerUnaryOpExpr = class (TUnaryOpExpr)
219public
220constructor Create(context : TdwsBaseSymbolsContext; const aScriptPos : TScriptPos; expr : TTypedExpr); override;
221procedure EvalAsVariant(exec : TdwsExecution; var result : Variant); override;
222end;
223
224TConvIntegerToBigIntegerExpr = class(TBigIntegerUnaryOpExpr)
225procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override;
226end;
227TConvStringToBigIntegerExpr = class(TBigIntegerUnaryOpExpr)
228procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override;
229end;
230TConvFloatToBigIntegerExpr = class(TBigIntegerUnaryOpExpr)
231procedure EvalAsInterface(exec : TdwsExecution; var result : IUnknown); override;
232end;
233TConvBigIntegerToIntegerExpr = class(TUnaryOpIntExpr)
234function EvalAsInteger(exec : TdwsExecution) : Int64; override;
235end;
236TConvBigIntegerToFloatExpr = class(TUnaryOpFloatExpr)
237function EvalAsFloat(exec : TdwsExecution) : Double; override;
238end;
239
240TBigIntegerToStringFunc = class(TInternalMagicStringFunction)
241procedure DoEvalAsString(const args : TExprBaseListExec; var Result : String); override;
242end;
243TStringToBigIntegerFunc = class(TInternalMagicVariantFunction)
244procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
245end;
246TBigIntegerToHexFunc = class(TInternalMagicStringFunction)
247procedure DoEvalAsString(const args : TExprBaseListExec; var Result : String); override;
248end;
249THexToBigIntegerFunc = class(TInternalMagicVariantFunction)
250procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
251end;
252
253TBigIntegerToBlobFunc = class(TInternalMagicVariantFunction)
254procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
255end;
256TBlobToBigIntegerFunc = class(TInternalMagicInterfaceFunction)
257procedure DoEvalAsInterface(const args : TExprBaseListExec; var result : IUnknown); override;
258end;
259
260TBigIntegerToFloatFunc = class(TInternalMagicFloatFunction)
261procedure DoEvalAsFloat(const args : TExprBaseListExec; var Result : Double); override;
262end;
263TBigIntegerToIntegerFunc = class(TInternalMagicIntFunction)
264function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
265end;
266
267TBigIntegerOddFunc = class(TInternalMagicBoolFunction)
268function DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean; override;
269end;
270TBigIntegerEvenFunc = class(TInternalMagicBoolFunction)
271function DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean; override;
272end;
273
274TBigIntegerSignFunc = class(TInternalMagicIntFunction)
275function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
276end;
277
278TBigIntegerAbsFunc = class(TInternalMagicVariantFunction)
279procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
280end;
281
282TBigIntegerBitLengthFunc = class(TInternalMagicIntFunction)
283function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
284end;
285
286TBigIntegerTestBitFunc = class(TInternalMagicBoolFunction)
287function DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean; override;
288end;
289
290TBigIntegerSetBitFunc = class(TInternalMagicProcedure)
291procedure DoEvalProc(const args : TExprBaseListExec); override;
292end;
293
294TBigIntegerSetBitValFunc = class(TInternalMagicProcedure)
295procedure DoEvalProc(const args : TExprBaseListExec); override;
296end;
297
298TBigIntegerClearBitFunc = class(TInternalMagicProcedure)
299procedure DoEvalProc(const args : TExprBaseListExec); override;
300end;
301
302TBigIntegerPopCountFunc = class(TInternalMagicIntFunction)
303function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
304end;
305
306TBigIntegerGcdFunc = class(TInternalMagicVariantFunction)
307procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
308end;
309
310TBigIntegerLcmFunc = class(TInternalMagicVariantFunction)
311procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
312end;
313
314TBigIntegerIsPrimeFunc = class(TInternalMagicBoolFunction)
315function DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean; override;
316end;
317TBigIntegerNextPrimeFunc = class(TInternalMagicVariantFunction)
318procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
319end;
320
321TBigIntegerPowerFunc = class(TInternalMagicVariantFunction)
322procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
323end;
324
325TBigIntegerSqrFunc = class(TInternalMagicVariantFunction)
326procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
327end;
328
329TBigIntegerModPowFunc = class(TInternalMagicVariantFunction)
330procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
331end;
332
333TBigIntegerModInvFunc = class(TInternalMagicVariantFunction)
334procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
335end;
336
337TBigIntegerDivModFunc = class(TInternalMagicProcedure)
338procedure DoEvalProc(const args : TExprBaseListExec); override;
339end;
340
341TBigJacobiFunc = class(TInternalMagicIntFunction)
342function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
343end;
344TBigLegendreFunc = class(TInternalMagicIntFunction)
345function DoEvalAsInteger(const args : TExprBaseListExec) : Int64; override;
346end;
347
348TBigIntegerFactorialFunc = class(TInternalMagicVariantFunction)
349procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
350end;
351TBigIntegerPrimorialFunc = class(TInternalMagicVariantFunction)
352procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
353end;
354
355TBigIntegerRandomFunc = class(TInternalMagicVariantFunction)
356procedure DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant); override;
357end;
358
359// ------------------------------------------------------------------
360// ------------------------------------------------------------------
361// ------------------------------------------------------------------
362implementation
363// ------------------------------------------------------------------
364// ------------------------------------------------------------------
365// ------------------------------------------------------------------
366
367const
368cLimbSize = SizeOf(NativeUInt);
369cPoolMaxSize = 256;
370
371type
372TLimbArray = array [0..1024*1024*1024 div cLimbSize] of NativeUInt;
373PLimbArray = ^TLimbArray;
374
375var
376vPool : TdwsBigIntegerWrapperPool;
377
378// RegisterBigIntegerType
379//
380procedure RegisterBigIntegerType(systemTable : TSystemSymbolTable; unitSyms : TUnitMainSymbols;
381unitTable : TSymbolTable);
382var
383typBigInteger : TBaseBigIntegerSymbol;
384begin
385if systemTable.FindLocal(SYS_BIGINTEGER)<>nil then exit;
386
387typBigInteger:=TBaseBigIntegerSymbol.Create;
388
389systemTable.AddSymbol(typBigInteger);
390end;
391
392// RegisterBigIntegerOperators
393//
394procedure RegisterBigIntegerOperators(systemTable : TSystemSymbolTable;
395unitTable : TSymbolTable; operators : TOperators);
396var
397typBigInteger : TBaseBigIntegerSymbol;
398
399procedure RegisterOperators(token : TTokenType; exprClass : TBinaryOpExprClass);
400begin
401operators.RegisterOperator(token, exprClass, typBigInteger, typBigInteger);
402operators.RegisterOperator(token, exprClass, systemTable.TypInteger, typBigInteger);
403operators.RegisterOperator(token, exprClass, typBigInteger, systemTable.TypInteger);
404end;
405
406begin
407typBigInteger:=systemTable.FindTypeSymbol(SYS_BIGINTEGER, cvMagic) as TBaseBigIntegerSymbol;
408
409if operators.FindCaster(typBigInteger, systemTable.TypInteger) <> nil then Exit;
410
411operators.RegisterUnaryOperator(ttMINUS, TBigIntegerNegateExpr, typBigInteger);
412
413RegisterOperators(ttPLUS, TBigIntegerAddOpExpr);
414RegisterOperators(ttMINUS, TBigIntegerSubOpExpr);
415RegisterOperators(ttTIMES, TBigIntegerMultOpExpr);
416RegisterOperators(ttDIV, TBigIntegerDivOpExpr);
417RegisterOperators(ttMOD, TBigIntegerModOpExpr);
418RegisterOperators(ttAND, TBigIntegerAndOpExpr);
419RegisterOperators(ttOR, TBigIntegerOrOpExpr);
420RegisterOperators(ttXOR, TBigIntegerXorOpExpr);
421
422operators.RegisterOperator(ttSHL, TBigIntegerShiftLeftExpr, typBigInteger, systemTable.TypInteger);
423operators.RegisterOperator(ttSAR, TBigIntegerShiftRightExpr, typBigInteger, systemTable.TypInteger);
424
425operators.RegisterOperator(ttPLUS_ASSIGN, TBigIntegerPlusAssignExpr, typBigInteger, typBigInteger);
426operators.RegisterOperator(ttPLUS_ASSIGN, TBigIntegerPlusAssignIntExpr, typBigInteger, systemTable.TypInteger);
427operators.RegisterOperator(ttMINUS_ASSIGN, TBigIntegerMinusAssignExpr, typBigInteger, typBigInteger);
428operators.RegisterOperator(ttMINUS_ASSIGN, TBigIntegerMinusAssignIntExpr, typBigInteger, systemTable.TypInteger);
429operators.RegisterOperator(ttTIMES_ASSIGN, TBigIntegerMultAssignExpr, typBigInteger, typBigInteger);
430operators.RegisterOperator(ttTIMES_ASSIGN, TBigIntegerMultAssignExpr, typBigInteger, systemTable.TypInteger);
431
432RegisterOperators(ttEQ, TBigIntegerEqualOpExpr);
433RegisterOperators(ttNOT_EQ, TBigIntegerNotEqualOpExpr);
434RegisterOperators(ttGTR, TBigIntegerGreaterOpExpr);
435RegisterOperators(ttGTR_EQ, TBigIntegerGreaterEqualOpExpr);
436RegisterOperators(ttLESS, TBigIntegerLessOpExpr);
437RegisterOperators(ttLESS_EQ, TBigIntegerLessEqualOpExpr);
438
439operators.RegisterCaster(typBigInteger, systemTable.TypInteger, TConvIntegerToBigIntegerExpr);
440operators.RegisterCaster(typBigInteger, systemTable.TypString, TConvStringToBigIntegerExpr);
441operators.RegisterCaster(typBigInteger, systemTable.TypFloat, TConvFloatToBigIntegerExpr);
442operators.RegisterCaster(systemTable.TypInteger, typBigInteger, TConvBigIntegerToIntegerExpr);
443operators.RegisterCaster(systemTable.TypFloat, typBigInteger, TConvBigIntegerToFloatExpr);
444end;
445
446type
447TTypedExprBigIntegerHelper = class helper for TTypedExpr
448function EvalAsBigInteger(exec : TdwsExecution) : IdwsBigInteger;
449end;
450
451function TTypedExprBigIntegerHelper.EvalAsBigInteger(exec : TdwsExecution) : IdwsBigInteger;
452begin
453if Typ.UnAliasedType.ClassType = TBaseBigIntegerSymbol then begin
454EvalAsInterface(exec, IUnknown(Result));
455if Result = nil then
456Result := TBigIntegerWrapper.CreateZero;
457end else Result := TBigIntegerWrapper.CreateInt64( EvalAsInteger(exec) );
458end;
459
460// ArgBigInteger
461//
462function ArgBigInteger(const args : TExprBaseListExec; index : Integer) : IdwsBigInteger;
463begin
464Result := (args.ExprBase[index] as TTypedExpr).EvalAsBigInteger(args.Exec);
465end;
466
467// ArgVarBigInteger
468//
469function ArgVarBigInteger(const args : TExprBaseListExec; index : Integer) : IdwsBigInteger;
470
471procedure Allocate(varExpr : TBaseTypeVarExpr; var result : IdwsBigInteger);
472var
473v : Variant;
474begin
475Result := TBigIntegerWrapper.CreateZero;
476v := IUnknown(Result);
477varExpr.AssignValue(args.Exec, v);
478end;
479
480var
481varExpr : TBaseTypeVarExpr;
482begin
483varExpr := (args.ExprBase[index] as TBaseTypeVarExpr);
484varExpr.EvalAsInterface(args.Exec, IUnknown(Result));
485if Result = nil then
486Allocate(varExpr, Result);
487end;
488
489// ------------------
490// ------------------ TBaseBigIntegerSymbol ------------------
491// ------------------
492
493// Create
494//
495constructor TBaseBigIntegerSymbol.Create;
496begin
497inherited Create(SYS_BIGINTEGER);
498end;
499
500// IsCompatible
501//
502function TBaseBigIntegerSymbol.IsCompatible(typSym : TTypeSymbol) : Boolean;
503begin
504Result:=(typSym<>nil) and (typSym.UnAliasedType.ClassType=TBaseBigIntegerSymbol);
505end;
506
507// InitData
508//
509procedure TBaseBigIntegerSymbol.InitData(const data : TData; offset : Integer);
510begin
511VarCopySafe(data[offset], IUnknown(nil));
512end;
513
514// ------------------
515// ------------------ TBigIntegerWrapper ------------------
516// ------------------
517
518// CreateNewZero
519//
520constructor TBigIntegerWrapper.CreateNewZero;
521begin
522Create;
523if not Bind_MPIR_DLL then
524raise Exception.Create('mpir.dll is required for BigInteger');
525
526mpz_init(Value);
527end;
528
529// Reset
530//
531procedure TBigIntegerWrapper.Reset;
532begin
533mpz_set_ui(Value, 0);
534end;
535
536// _Release
537//
538function TBigIntegerWrapper._Release: Integer;
539begin
540Result := InterlockedDecrement(FRefCount);
541if Result = 0 then
542vPool.Push(Self);
543end;
544
545// CreateZero
546//
547class function TBigIntegerWrapper.CreateZero : TBigIntegerWrapper;
548begin
549Result := vPool.Pop;
550end;
551
552// CreateInt64
553//
554class function TBigIntegerWrapper.CreateInt64(const i : Int64) : TBigIntegerWrapper;
555begin
556Result := vPool.Pop;
557mpz_set_int64(Result.Value, i);
558end;
559
560// CreateFloat
561//
562class function TBigIntegerWrapper.CreateFloat(const f : Double) : TBigIntegerWrapper;
563begin
564Result := vPool.Pop;
565mpz_set_d(Result.Value, f);
566end;
567
568// CreateString
569//
570class function TBigIntegerWrapper.CreateString(const s : String; base : Integer) : TBigIntegerWrapper;
571var
572buf : RawByteString;
573p : PAnsiChar;
574begin
575Result := vPool.Pop;
576if s <> '' then begin
577ScriptStringToRawByteString(s, buf);
578p := Pointer(buf);
579if p^ = '+' then
580Inc(p);
581mpz_set_str(Result.Value, p, base);
582end;
583end;
584
585// Destroy
586//
587destructor TBigIntegerWrapper.Destroy;
588begin
589if Value.mp_alloc <> 0 then
590mpz_clear(Value);
591inherited;
592end;
593
594// GetValue
595//
596function TBigIntegerWrapper.GetValue : pmpz_t;
597begin
598Result := @Value;
599end;
600
601// SetValue
602//
603procedure TBigIntegerWrapper.SetValue(const v : pmpz_t);
604begin
605mpz_set(Value, v^);
606end;
607
608// GetSelf
609//
610function TBigIntegerWrapper.GetSelf : TObject;
611begin
612Result := Self;
613end;
614
615// BitLength
616//
617function TBigIntegerWrapper.BitLength : Integer;
618begin
619if Value.mp_size = 0 then
620Result := 0
621else Result := mpz_sizeinbase(Value, 2);
622end;
623
624// PopCount
625//
626function TBigIntegerWrapper.PopCount : Integer;
627begin
628if Value.mp_size = 0 then
629Result := 0
630else Result := mpz_popcount(Value);
631end;
632
633// Sign
634//
635function TBigIntegerWrapper.Sign : Integer;
636begin
637Result := mpz_sgn(Value);
638end;
639
640// ToStringBase
641//
642function TBigIntegerWrapper.ToStringBase(base : Integer) : String;
643var
644size : Integer;
645buf : RawByteString;
646begin
647Assert(base in [2..62]);
648
649if Value.mp_size = 0 then Exit('0');
650
651size := mpz_sizeinbase(Value, base);
652Assert(size > 0);
653if Value.mp_size < 0 then
654Inc(size);
655SetLength(buf, size);
656mpz_get_str(Pointer(buf), base, Value);
657if (size > 1) and (buf[size] = #0) then
658SetLength(buf, size-1); // clear occasional trailing #0
659Result := RawByteStringToScriptString(buf);
660end;
661
662// ToHexString
663//
664function TBigIntegerWrapper.ToHexString : String;
665begin
666Result := ToStringBase(16);
667end;
668
669// ToString
670//
671function TBigIntegerWrapper.ToString : String;
672begin
673Result := ToStringBase(10);
674end;
675
676// ToInt64
677//
678function TBigIntegerWrapper.ToInt64 : Int64;
679var
680n : Integer;
681begin
682Result := 0;
683
684n := Abs(Value.mp_size);
685if n > 2 then n := 3;
686System.Move(Value.mp_d^, Result, n*4);
687
688if Value.mp_size < 0 then begin
689Result := -Result;
690end;
691end;
692
693// ToNeg
694//
695function TBigIntegerWrapper.ToNeg : IdwsBigInteger;
696var
697biw : TBigIntegerWrapper;
698begin
699biw := TBigIntegerWrapper.CreateZero;
700mpz_neg(biw.Value, Value);
701Result := biw;
702end;
703
704// ------------------
705// ------------------ TdwsBigIntegerWrapperPool ------------------
706// ------------------
707
708// Create
709//
710constructor TdwsBigIntegerWrapperPool.Create;
711begin
712inherited;
713FLock := TMultiReadSingleWrite.Create;
714end;
715
716// Destroy
717//
718destructor TdwsBigIntegerWrapperPool.Destroy;
719begin
720inherited;
721Cleanup;
722FLock.Free;
723end;
724
725// Pop
726//
727function TdwsBigIntegerWrapperPool.Pop : TBigIntegerWrapper;
728begin
729Result := nil;
730if Self <> nil then begin
731FLock.BeginWrite;
732try
733if FHead <> nil then begin
734Result := FHead;
735FHead := FHead.FNext;
736Result.FNext := nil;
737Dec(FSize);
738end;
739finally
740FLock.EndWrite;
741end;
742end;
743if Result = nil then
744Result := TBigIntegerWrapper.CreateNewZero
745end;
746
747// Push
748//
749procedure TdwsBigIntegerWrapperPool.Push(ref : TBigIntegerWrapper);
750begin
751if (Self = nil) or (FSize >= cPoolMaxSize) then
752ref.Free
753else begin
754FLock.BeginWrite;
755try
756ref.FNext := FHead;
757FHead := ref;
758ref.Reset;
759Inc(FSize);
760finally
761FLock.EndWrite;
762end;
763end;
764end;
765
766// Cleanup
767//
768procedure TdwsBigIntegerWrapperPool.Cleanup;
769var
770iter, next : TBigIntegerWrapper;
771begin
772FLock.BeginWrite;
773try
774iter := FHead;
775while iter <> nil do begin
776next := iter.FNext;
777iter.Free;
778iter := next;
779end;
780FHead := nil;
781FSize := 0;
782finally
783FLock.EndWrite;
784end;
785end;
786
787// ------------------
788// ------------------ TBigIntegerNegateExpr ------------------
789// ------------------
790
791// Create
792//
793constructor TBigIntegerNegateExpr.Create(context : TdwsBaseSymbolsContext; const aScriptPos : TScriptPos; expr : TTypedExpr);
794begin
795inherited;
796Typ := expr.Typ;
797end;
798
799// EvalAsVariant
800//
801procedure TBigIntegerNegateExpr.EvalAsVariant(exec : TdwsExecution; var result : Variant);
802begin
803result := Expr.EvalAsBigInteger(exec).ToNeg;
804end;
805
806// ------------------
807// ------------------ TBigIntegerBinOpExpr ------------------
808// ------------------
809
810// Create
811//
812constructor TBigIntegerBinOpExpr.Create(context : TdwsCompilerContext; const aScriptPos : TScriptPos;
813const anOp : TTokenType; aLeft, aRight : TTypedExpr);
814begin
815inherited Create(context, aScriptPos, anOp, aLeft, aRight);
816if aLeft.Typ.UnAliasedTypeIs(TBaseIntegerSymbol) then
817Typ := aRight.Typ
818else Typ := aLeft.Typ;
819end;
820
821
822// EvalAsVariant
823//
824procedure TBigIntegerBinOpExpr.EvalAsVariant(exec : TdwsExecution; var result : Variant);
825var
826intf : IUnknown;
827begin
828EvalAsInterface(exec, intf);
829result := intf;
830end;
831
832// ------------------
833// ------------------ TBigIntegerBinOpFuncExpr ------------------
834// ------------------
835
836// Create
837//
838constructor TBigIntegerBinOpFuncExpr.Create(context : TdwsCompilerContext; const aScriptPos : TScriptPos;
839const anOp : TTokenType; aLeft, aRight : TTypedExpr);
840begin
841inherited Create(context, aScriptPos, anOp, aLeft, aRight);
842InitOpFunc;
843end;
844
845// EvalAsInterface
846//
847procedure TBigIntegerBinOpFuncExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
848var
849bi : TBigIntegerWrapper;
850biLeft, biRight : IdwsBigInteger;
851begin
852biLeft := Left.EvalAsBigInteger(exec);
853biRight := Right.EvalAsBigInteger(exec);
854bi := TBigIntegerWrapper.CreateZero;
855FOpFunc(bi.Value, biLeft.Value^, biRight.Value^);
856result := bi as IdwsBigInteger;
857end;
858
859// ------------------
860// ------------------ TBigIntegerAddOpExpr ------------------
861// ------------------
862
863procedure TBigIntegerAddOpExpr.InitOpFunc;
864begin
865FOpFunc := mpz_add;
866end;
867
868// ------------------
869// ------------------ TBigIntegerSubOpExpr ------------------
870// ------------------
871
872procedure TBigIntegerSubOpExpr.InitOpFunc;
873begin
874FOpFunc := mpz_sub;
875end;
876
877// ------------------
878// ------------------ TBigIntegerMultOpExpr ------------------
879// ------------------
880
881procedure TBigIntegerMultOpExpr.InitOpFunc;
882begin
883FOpFunc := mpz_mul;
884end;
885
886// ------------------
887// ------------------ TBigIntegerDivOpExpr ------------------
888// ------------------
889
890procedure TBigIntegerDivOpExpr.InitOpFunc;
891begin
892FOpFunc := mpz_tdiv_q
893end;
894
895// ------------------
896// ------------------ TBigIntegerModOpExpr ------------------
897// ------------------
898
899procedure TBigIntegerModOpExpr.InitOpFunc;
900begin
901FOpFunc := mpz_mod;
902end;
903
904// ------------------
905// ------------------ TBigIntegerAndOpExpr ------------------
906// ------------------
907
908procedure TBigIntegerAndOpExpr.InitOpFunc;
909begin
910FOpFunc := mpz_and;
911end;
912
913// ------------------
914// ------------------ TBigIntegerOrOpExpr ------------------
915// ------------------
916
917procedure TBigIntegerOrOpExpr.InitOpFunc;
918begin
919FOpFunc := mpz_ior;
920end;
921
922// ------------------
923// ------------------ TBigIntegerXorOpExpr ------------------
924// ------------------
925
926procedure TBigIntegerXorOpExpr.InitOpFunc;
927begin
928FOpFunc := mpz_xor;
929end;
930
931// ------------------
932// ------------------ TBigIntegerRelOpExpr ------------------
933// ------------------
934
935function TBigIntegerRelOpExpr.InternalCompare(exec : TdwsExecution) : Integer;
936begin
937Result := mpz_cmp(Left.EvalAsBigInteger(exec).Value^, Right.EvalAsBigInteger(exec).Value^);
938end;
939
940// ------------------
941// ------------------ TBigIntegerEqualOpExpr ------------------
942// ------------------
943
944function TBigIntegerEqualOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
945begin
946Result := InternalCompare(exec) = 0;
947end;
948
949// ------------------
950// ------------------ TBigIntegerNotEqualOpExpr ------------------
951// ------------------
952
953function TBigIntegerNotEqualOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
954begin
955Result := InternalCompare(exec) <> 0;
956end;
957
958// ------------------
959// ------------------ TBigIntegerGreaterOpExpr ------------------
960// ------------------
961
962function TBigIntegerGreaterOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
963begin
964Result := InternalCompare(exec) > 0;
965end;
966
967// ------------------
968// ------------------ TBigIntegerGreaterEqualOpExpr ------------------
969// ------------------
970
971function TBigIntegerGreaterEqualOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
972begin
973Result := InternalCompare(exec) >= 0;
974end;
975
976// ------------------
977// ------------------ TBigIntegerLessOpExpr ------------------
978// ------------------
979
980function TBigIntegerLessOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
981begin
982Result := InternalCompare(exec) < 0;
983end;
984
985// ------------------
986// ------------------ TBigIntegerLessEqualOpExpr ------------------
987// ------------------
988
989function TBigIntegerLessEqualOpExpr.EvalAsBoolean(exec : TdwsExecution) : Boolean;
990begin
991Result := InternalCompare(exec) <= 0;
992end;
993
994// ------------------
995// ------------------ TBigIntegerUnaryOpExpr ------------------
996// ------------------
997
998constructor TBigIntegerUnaryOpExpr.Create(context : TdwsBaseSymbolsContext; const aScriptPos : TScriptPos; expr : TTypedExpr);
999begin
1000inherited Create(context, aScriptPos, expr);
1001Typ := context.FindType(SYS_BIGINTEGER);
1002end;
1003
1004procedure TBigIntegerUnaryOpExpr.EvalAsVariant(exec : TdwsExecution; var result : Variant);
1005var
1006intf : IUnknown;
1007begin
1008EvalAsInterface(exec, intf);
1009result := intf;
1010end;
1011
1012// ------------------
1013// ------------------ TConvIntegerToBigIntegerExpr ------------------
1014// ------------------
1015
1016procedure TConvIntegerToBigIntegerExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
1017begin
1018result := TBigIntegerWrapper.CreateInt64( Expr.EvalAsInteger(exec) ) as IdwsBigInteger;
1019end;
1020// ------------------
1021// ------------------ TConvStringToBigIntegerExpr ------------------
1022// ------------------
1023
1024procedure TConvStringToBigIntegerExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
1025var
1026s : String;
1027begin
1028Expr.EvalAsString(exec, s);
1029result := TBigIntegerWrapper.CreateString( s, 10 ) as IdwsBigInteger;
1030end;
1031
1032// ------------------
1033// ------------------ TConvFloatToBigIntegerExpr ------------------
1034// ------------------
1035
1036// EvalAsInterface
1037//
1038procedure TConvFloatToBigIntegerExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
1039begin
1040Result := TBigIntegerWrapper.CreateFloat(Expr.EvalAsFloat(exec)) as IdwsBigInteger;
1041end;
1042
1043// ------------------
1044// ------------------ TConvBigIntegerToIntegerExpr ------------------
1045// ------------------
1046
1047function TConvBigIntegerToIntegerExpr.EvalAsInteger(exec : TdwsExecution) : Int64;
1048begin
1049Result := Expr.EvalAsBigInteger(exec).ToInt64;
1050end;
1051
1052// ------------------
1053// ------------------ TConvBigIntegerToFloatExpr ------------------
1054// ------------------
1055
1056function TConvBigIntegerToFloatExpr.EvalAsFloat(exec : TdwsExecution) : Double;
1057begin
1058Result := mpz_get_d(Expr.EvalAsBigInteger(exec).Value^);
1059end;
1060
1061// ------------------
1062// ------------------ TBigIntegerToStringFunc ------------------
1063// ------------------
1064
1065// DoEvalAsString
1066//
1067procedure TBigIntegerToStringFunc.DoEvalAsString(const args : TExprBaseListExec; var Result : String);
1068begin
1069Result := ArgBigInteger(args, 0).ToStringBase(args.AsInteger[1]);
1070end;
1071
1072// ------------------
1073// ------------------ TStringToBigIntegerFunc ------------------
1074// ------------------
1075
1076// DoEvalAsVariant
1077//
1078procedure TStringToBigIntegerFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1079begin
1080result := TBigIntegerWrapper.CreateString( args.AsString[0], args.AsInteger[1] ) as IdwsBigInteger;
1081end;
1082
1083// ------------------
1084// ------------------ TBigIntegerToHexFunc ------------------
1085// ------------------
1086
1087// DoEvalAsString
1088//
1089procedure TBigIntegerToHexFunc.DoEvalAsString(const args : TExprBaseListExec; var Result : String);
1090begin
1091Result := ArgBigInteger(args, 0).ToStringBase(16);
1092end;
1093
1094// ------------------
1095// ------------------ THexToBigIntegerFunc ------------------
1096// ------------------
1097
1098// DoEvalAsVariant
1099//
1100procedure THexToBigIntegerFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1101begin
1102result := TBigIntegerWrapper.CreateString( args.AsString[0], 16 ) as IdwsBigInteger;
1103end;
1104
1105// ------------------
1106// ------------------ TBigIntegerToFloatFunc ------------------
1107// ------------------
1108
1109procedure TBigIntegerToFloatFunc.DoEvalAsFloat(const args : TExprBaseListExec; var result : Double);
1110begin
1111result := mpz_get_d(ArgBigInteger(args, 0).Value^);
1112end;
1113
1114// ------------------
1115// ------------------ TBigIntegerToIntegerFunc ------------------
1116// ------------------
1117
1118function TBigIntegerToIntegerFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1119begin
1120Result := ArgBigInteger(args, 0).ToInt64;
1121end;
1122
1123// ------------------
1124// ------------------ TBigIntegerOddFunc ------------------
1125// ------------------
1126
1127function TBigIntegerOddFunc.DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean;
1128begin
1129Result := mpz_odd_p(ArgBigInteger(args, 0).Value^);
1130end;
1131
1132// ------------------
1133// ------------------ TBigIntegerEvenFunc ------------------
1134// ------------------
1135
1136function TBigIntegerEvenFunc.DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean;
1137begin
1138Result := mpz_even_p(ArgBigInteger(args, 0).Value^);
1139end;
1140
1141// ------------------
1142// ------------------ TBigIntegerSignFunc ------------------
1143// ------------------
1144
1145function TBigIntegerSignFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1146begin
1147Result := ArgBigInteger(args, 0).Sign;
1148end;
1149
1150// ------------------
1151// ------------------ TBigIntegerAbsFunc ------------------
1152// ------------------
1153
1154procedure TBigIntegerAbsFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1155var
1156bi : TBigIntegerWrapper;
1157begin
1158bi := TBigIntegerWrapper.CreateZero;
1159bi.SetValue(ArgBigInteger(args, 0).Value);
1160bi.Value.mp_size := Abs(bi.Value.mp_size);
1161result := bi as IdwsBigInteger;
1162end;
1163
1164// ------------------
1165// ------------------ TBigIntegerGcdFunc ------------------
1166// ------------------
1167
1168procedure TBigIntegerGcdFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1169var
1170bi : TBigIntegerWrapper;
1171begin
1172bi := TBigIntegerWrapper.CreateZero;
1173mpz_gcd(bi.Value, ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1174result := bi as IdwsBigInteger;
1175end;
1176
1177// ------------------
1178// ------------------ TBigIntegerLcmFunc ------------------
1179// ------------------
1180
1181procedure TBigIntegerLcmFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1182var
1183bi : TBigIntegerWrapper;
1184begin
1185bi := TBigIntegerWrapper.CreateZero;
1186mpz_lcm(bi.Value, ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1187result := bi as IdwsBigInteger;
1188end;
1189
1190// ------------------
1191// ------------------ TBigIntegerIsPrimeFunc ------------------
1192// ------------------
1193
1194function TBigIntegerIsPrimeFunc.DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean;
1195var
1196state : gmp_randstate_t;
1197begin
1198gmp_randinit_mt(state);
1199try
1200Result := mpz_probable_prime_p(ArgBigInteger(args, 0).Value^, state, args.AsInteger[1], 0) > 0;
1201finally
1202gmp_randclear(state);
1203end;
1204end;
1205
1206// ------------------
1207// ------------------ TBigIntegerNextPrimeFunc ------------------
1208// ------------------
1209
1210procedure TBigIntegerNextPrimeFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1211var
1212base : IdwsBigInteger;
1213bi : TBigIntegerWrapper;
1214state : gmp_randstate_t;
1215reps : Integer;
1216begin
1217base := ArgBigInteger(args, 0);
1218reps := args.AsInteger[1];
1219
1220bi := TBigIntegerWrapper.CreateZero;
1221result := bi as IdwsBigInteger;
1222
1223if base.Value.mp_size <= 0 then begin
1224mpz_set_ui(bi.Value, 1);
1225Exit;
1226end;
1227
1228if mpz_even_p(base.Value^) then
1229mpz_add_ui(bi.Value, base.Value^, 1)
1230else mpz_add_ui(bi.Value, base.Value^, 2);
1231
1232gmp_randinit_mt(state);
1233try
1234while mpz_probable_prime_p(bi.Value, state, reps, 0) <= 0 do begin
1235if args.Exec.ProgramState = psRunningStopped then
1236raise Exception.Create('NextPrime aborted');
1237mpz_add_ui(bi.Value, bi.Value, 2);
1238end;
1239finally
1240gmp_randclear(state);
1241end;
1242end;
1243
1244// ------------------
1245// ------------------ TBigIntegerPowerFunc ------------------
1246// ------------------
1247
1248procedure TBigIntegerPowerFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1249var
1250bi : TBigIntegerWrapper;
1251begin
1252bi := TBigIntegerWrapper.CreateZero;
1253mpz_pow_ui(bi.Value, ArgBigInteger(args, 0).Value^, args.AsInteger[1]);
1254result := bi as IdwsBigInteger;
1255end;
1256
1257// ------------------
1258// ------------------ TBigIntegerSqrFunc ------------------
1259// ------------------
1260
1261procedure TBigIntegerSqrFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1262var
1263bi : TBigIntegerWrapper;
1264begin
1265bi := TBigIntegerWrapper.CreateZero;
1266mpz_pow_ui(bi.Value, ArgBigInteger(args, 0).Value^, 2);
1267result := bi as IdwsBigInteger;
1268end;
1269
1270// ------------------
1271// ------------------ TBigIntegerDivModFunc ------------------
1272// ------------------
1273
1274procedure TBigIntegerDivModFunc.DoEvalProc(const args : TExprBaseListExec);
1275var
1276biQ, biR : TBigIntegerWrapper;
1277begin
1278biQ := TBigIntegerWrapper.CreateZero;
1279biR := TBigIntegerWrapper.CreateZero;
1280
1281mpz_tdiv_qr(biQ.Value, biR.Value, ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1282
1283args.ExprBase[2].AssignValue(args.Exec, biQ as IdwsBigInteger);
1284args.ExprBase[3].AssignValue(args.Exec, biR as IdwsBigInteger);
1285end;
1286
1287// ------------------
1288// ------------------ TBigIntegerToBlobFunc ------------------
1289// ------------------
1290
1291procedure TBigIntegerToBlobFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1292var
1293bufString : RawByteString;
1294pDest, pSrc : PByte;
1295n : Integer;
1296gmp : pmpz_t;
1297begin
1298gmp := ArgBigInteger(args, 0).Value;
1299n := Abs(gmp.mp_size);
1300if n = 0 then
1301bufString := ''
1302else begin
1303SetLength(bufString, n*cLimbSize+1);
1304pDest := Pointer(bufString);
1305if gmp.mp_size < 0 then begin
1306pDest^ := $ff;
1307Inc(pDest);
1308end;
1309pSrc := @PLimbArray(gmp.mp_d)^[n-1];
1310Inc(pSrc, cLimbSize-1);
1311// skip zeroes
1312while pSrc^ = 0 do begin
1313Dec(pSrc);
1314if pSrc = PByte(gmp.mp_d) then break;
1315end;
1316if (pSrc^ = $ff) and (gmp.mp_size > 0) then begin
1317pDest^ := $00;
1318Inc(pDest);
1319end;
1320repeat
1321pDest^ := pSrc^;
1322Dec(pSrc);
1323Inc(pDest);
1324until NativeUInt(pSrc) < NativeUInt(gmp.mp_d);
1325SetLength(bufString, NativeUInt(pDest)-NativeUInt(Pointer(bufString)));
1326end;
1327Result := bufString;
1328end;
1329
1330// ------------------
1331// ------------------ TBlobToBigIntegerFunc ------------------
1332// ------------------
1333
1334// DoEvalAsInterface
1335//
1336procedure TBlobToBigIntegerFunc.DoEvalAsInterface(const args : TExprBaseListExec; var result : IUnknown);
1337var
1338bi : TBigIntegerWrapper;
1339bufString : RawByteString;
1340nbBytes, nbLimbs : Integer;
1341pSrc, pDest : PByte;
1342i : Integer;
1343begin
1344bi := TBigIntegerWrapper.CreateZero;
1345
1346bufString := args.AsDataString[0];
1347if bufString <> '' then begin
1348
1349nbBytes := Length(bufString);
1350pSrc := Pointer(bufString);
1351case Ord(bufString[1]) of
1352$00, $ff : begin
1353Inc(pSrc);
1354Dec(nbBytes);
1355end
1356end;
1357
1358nbLimbs := (nbBytes+cLimbSize-1) div cLimbSize;
1359mpz_realloc(bi.Value, nbLimbs);
1360if Ord(bufString[1]) = $ff then
1361bi.Value.mp_size := -nbLimbs
1362else bi.Value.mp_size := nbLimbs;
1363
1364PLimbArray(bi.Value.mp_d)[nbLimbs-1] := 0;
1365pDest := @PByteArray(bi.Value.mp_d)[nbBytes-1];
1366for i := 1 to nbBytes do begin
1367pDest^ := pSrc^;
1368Dec(pDest);
1369Inc(pSrc);
1370end;
1371
1372end;
1373
1374Result := bi as IdwsBigInteger;
1375end;
1376
1377// ------------------
1378// ------------------ TBigIntegerShiftLeftExpr ------------------
1379// ------------------
1380
1381procedure TBigIntegerShiftLeftExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
1382var
1383bi : TBigIntegerWrapper;
1384begin
1385bi := TBigIntegerWrapper.CreateZero;
1386mpz_mul_2exp(bi.Value, Left.EvalAsBigInteger(exec).Value^, Right.EvalAsInteger(exec));
1387result := bi as IdwsBigInteger;
1388end;
1389
1390// ------------------
1391// ------------------ TBigIntegerShiftRightExpr ------------------
1392// ------------------
1393
1394procedure TBigIntegerShiftRightExpr.EvalAsInterface(exec : TdwsExecution; var result : IUnknown);
1395var
1396bi : TBigIntegerWrapper;
1397begin
1398bi := TBigIntegerWrapper.CreateZero;
1399mpz_tdiv_q_2exp(bi.Value, Left.EvalAsBigInteger(exec).Value^, Right.EvalAsInteger(exec));
1400result := bi as IdwsBigInteger;
1401end;
1402
1403// ------------------
1404// ------------------ TBigIntegerOpAssignExpr ------------------
1405// ------------------
1406
1407procedure TBigIntegerOpAssignExpr.TypeCheckAssign(context : TdwsCompilerContext);
1408begin
1409// nothing here
1410end;
1411
1412// ------------------
1413// ------------------ TBigIntegerPlusAssignExpr ------------------
1414// ------------------
1415
1416procedure TBigIntegerPlusAssignExpr.EvalNoResult(exec : TdwsExecution);
1417var
1418bi : TBigIntegerWrapper;
1419begin
1420bi := TBigIntegerWrapper.CreateZero;
1421mpz_add(bi.Value, Left.EvalAsBigInteger(exec).Value^, Right.EvalAsBigInteger(exec).Value^);
1422FLeft.AssignValue(exec, bi as IdwsBigInteger);
1423end;
1424
1425// ------------------
1426// ------------------ TBigIntegerPlusAssignIntExpr ------------------
1427// ------------------
1428
1429procedure TBigIntegerPlusAssignIntExpr.EvalNoResult(exec : TdwsExecution);
1430var
1431bi : TBigIntegerWrapper;
1432begin
1433bi := TBigIntegerWrapper.CreateInt64(Right.EvalAsInteger(exec));
1434mpz_add(bi.Value, bi.Value, Left.EvalAsBigInteger(exec).Value^);
1435FLeft.AssignValue(exec, bi as IdwsBigInteger);
1436end;
1437
1438// ------------------
1439// ------------------ TBigIntegerMinusAssignExpr ------------------
1440// ------------------
1441
1442procedure TBigIntegerMinusAssignExpr.EvalNoResult(exec : TdwsExecution);
1443var
1444bi : TBigIntegerWrapper;
1445begin
1446bi := TBigIntegerWrapper.CreateZero;
1447mpz_sub(bi.Value, Left.EvalAsBigInteger(exec).Value^, Right.EvalAsBigInteger(exec).Value^);
1448FLeft.AssignValue(exec, bi as IdwsBigInteger);
1449end;
1450
1451// ------------------
1452// ------------------ TBigIntegerMinusAssignIntExpr ------------------
1453// ------------------
1454
1455procedure TBigIntegerMinusAssignIntExpr.EvalNoResult(exec : TdwsExecution);
1456var
1457bi : TBigIntegerWrapper;
1458begin
1459bi := TBigIntegerWrapper.CreateInt64(Right.EvalAsInteger(exec));
1460mpz_sub(bi.Value, Left.EvalAsBigInteger(exec).Value^, bi.Value);
1461FLeft.AssignValue(exec, bi as IdwsBigInteger);
1462end;
1463
1464// ------------------
1465// ------------------ TBigIntegerMultAssignExpr ------------------
1466// ------------------
1467
1468procedure TBigIntegerMultAssignExpr.EvalNoResult(exec : TdwsExecution);
1469var
1470bi : TBigIntegerWrapper;
1471begin
1472bi := TBigIntegerWrapper.CreateZero;
1473mpz_mul(bi.Value, Left.EvalAsBigInteger(exec).Value^, Right.EvalAsBigInteger(exec).Value^);
1474FLeft.AssignValue(exec, bi as IdwsBigInteger);
1475end;
1476
1477// ------------------
1478// ------------------ TBigIntegerRandomFunc ------------------
1479// ------------------
1480
1481// DoEvalAsVariant
1482//
1483procedure TBigIntegerRandomFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1484
1485function RandomBigIntegerOfBitLength(nb : Integer) : IdwsBigInteger;
1486var
1487mask : Integer;
1488bytes : TBytes;
1489bi : TBigIntegerWrapper;
1490begin
1491Assert(nb > 0);
1492
1493// adapted from BigInteger.Create(NumBits: Integer; const Random: IRandom)
1494// uses cryptographic random
1495bytes := RawByteStringToBytes(CryptographicRandom( (nb + 7) div 8 + 1 ));
1496
1497// One byte too many was allocated, to get a top byte of 0, i.e. always positive.
1498bytes[High(bytes)] := 0;
1499
1500// Set bits above required bit length to 0.
1501mask := $7F shr (7 - (nb and 7));
1502bytes[High(bytes)-1] := bytes[High(bytes)-1] and mask;
1503
1504bi := TBigIntegerWrapper.CreateZero;
1505mpz_realloc(bi.Value, (nb div (8*cLimbSize))+1);
1506FillChar(bi.Value.mp_d^, bi.Value.mp_alloc*cLimbSize, 0);
1507bi.Value.mp_size := bi.Value.mp_alloc;
1508System.Move(bytes[0], bi.Value.mp_d^, Length(bytes));
1509
1510Result := bi as IdwsBigInteger;
1511end;
1512
1513var
1514bi, limit : IdwsBigInteger;
1515bits : Integer;
1516begin
1517limit := ArgBigInteger(args, 0);
1518if mpz_cmp_ui(limit.Value^, 1) <= 0 then begin
1519result := TBigIntegerWrapper.CreateZero as IdwsBigInteger;
1520end else begin
1521bits := limit.BitLength;
1522repeat
1523bi := RandomBigIntegerOfBitLength(bits);
1524until mpz_cmp(bi.Value^, limit.Value^) < 0;
1525end;
1526result := bi;
1527end;
1528
1529// ------------------
1530// ------------------ TBigIntegerBitLengthFunc ------------------
1531// ------------------
1532
1533function TBigIntegerBitLengthFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1534begin
1535Result := ArgBigInteger(args, 0).BitLength;
1536end;
1537
1538// ------------------
1539// ------------------ TBigIntegerTestBitFunc ------------------
1540// ------------------
1541
1542// DoEvalAsBoolean
1543//
1544function TBigIntegerTestBitFunc.DoEvalAsBoolean(const args : TExprBaseListExec) : Boolean;
1545begin
1546Result := mpz_tstbit(ArgBigInteger(args, 0).Value^, Cardinal(args.AsInteger[1])) <> 0;
1547end;
1548
1549// ------------------
1550// ------------------ TBigIntegerSetBitFunc ------------------
1551// ------------------
1552
1553// DoEvalProc
1554//
1555procedure TBigIntegerSetBitFunc.DoEvalProc(const args : TExprBaseListExec);
1556begin
1557mpz_setbit(ArgVarBigInteger(args, 0).Value^, Cardinal(args.AsInteger[1]));
1558end;
1559
1560// ------------------
1561// ------------------ TBigIntegerSetBitValFunc ------------------
1562// ------------------
1563
1564// DoEvalProc
1565//
1566procedure TBigIntegerSetBitValFunc.DoEvalProc(const args : TExprBaseListExec);
1567var
1568bi : IdwsBigInteger;
1569bit : Integer;
1570begin
1571bi := ArgVarBigInteger(args, 0);
1572bit := args.AsInteger[1];
1573if args.AsBoolean[2] then
1574mpz_setbit(bi.Value^, bit)
1575else mpz_clrbit(bi.Value^, bit)
1576end;
1577
1578// ------------------
1579// ------------------ TBigIntegerClearBitFunc ------------------
1580// ------------------
1581
1582// DoEvalProc
1583//
1584procedure TBigIntegerClearBitFunc.DoEvalProc(const args : TExprBaseListExec);
1585begin
1586mpz_clrbit(ArgVarBigInteger(args, 0).Value^, args.AsInteger[1]);
1587end;
1588
1589// ------------------
1590// ------------------ TBigIntegerPopCountFunc ------------------
1591// ------------------
1592
1593function TBigIntegerPopCountFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1594begin
1595Result := ArgBigInteger(args, 0).PopCount;
1596end;
1597
1598// ------------------
1599// ------------------ TBigIntegerModPowFunc ------------------
1600// ------------------
1601
1602procedure TBigIntegerModPowFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1603var
1604bi : TBigIntegerWrapper;
1605begin
1606bi := TBigIntegerWrapper.CreateZero;
1607Result := bi as IdwsBigInteger;
1608mpz_powm(bi.Value,
1609ArgBigInteger(args, 0).Value^,
1610ArgBigInteger(args, 1).Value^,
1611ArgBigInteger(args, 2).Value^);
1612end;
1613
1614// ------------------
1615// ------------------ TBigIntegerModInvFunc ------------------
1616// ------------------
1617
1618// DoEvalAsVariant
1619//
1620procedure TBigIntegerModInvFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1621var
1622bi : TBigIntegerWrapper;
1623begin
1624bi := TBigIntegerWrapper.CreateZero;
1625Result := bi as IdwsBigInteger;
1626mpz_invert(bi.Value, ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1627end;
1628
1629// ------------------
1630// ------------------ TBigIntegerFactorialFunc ------------------
1631// ------------------
1632
1633procedure TBigIntegerFactorialFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1634var
1635bi : TBigIntegerWrapper;
1636i : Int64;
1637begin
1638i := args.AsInteger[0];
1639bi := TBigIntegerWrapper.CreateZero;
1640if i <= 1 then
1641mpz_set_uint64(bi.Value, 1)
1642else mpz_fac_ui(bi.Value, i);
1643Result := bi as IdwsBigInteger;
1644end;
1645
1646// ------------------
1647// ------------------ TBigIntegerPrimorialFunc ------------------
1648// ------------------
1649
1650procedure TBigIntegerPrimorialFunc.DoEvalAsVariant(const args : TExprBaseListExec; var result : Variant);
1651var
1652bi : TBigIntegerWrapper;
1653i : Int64;
1654begin
1655i := args.AsInteger[0];
1656bi := TBigIntegerWrapper.CreateZero;
1657if i < 1 then
1658mpz_set_uint64(bi.Value, 1)
1659else mpz_primorial_ui(bi.Value, i);
1660Result := bi as IdwsBigInteger;
1661end;
1662
1663// ------------------
1664// ------------------ TBigJacobiFunc ------------------
1665// ------------------
1666
1667function TBigJacobiFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1668begin
1669Result := mpz_jacobi(ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1670end;
1671
1672// ------------------
1673// ------------------ TBigLegendreFunc ------------------
1674// ------------------
1675
1676function TBigLegendreFunc.DoEvalAsInteger(const args : TExprBaseListExec) : Int64;
1677begin
1678Result := mpz_legendre(ArgBigInteger(args, 0).Value^, ArgBigInteger(args, 1).Value^);
1679end;
1680
1681// ------------------------------------------------------------------
1682// ------------------------------------------------------------------
1683// ------------------------------------------------------------------
1684initialization
1685// ------------------------------------------------------------------
1686// ------------------------------------------------------------------
1687// ------------------------------------------------------------------
1688
1689vPool := TdwsBigIntegerWrapperPool.Create;
1690
1691dwsInternalUnit.AddSymbolsRegistrationProc(RegisterBigIntegerType);
1692dwsInternalUnit.AddOperatorsRegistrationProc(RegisterBigIntegerOperators);
1693
1694RegisterInternalStringFunction(TBigIntegerToStringFunc, 'BigIntegerToString', ['v', SYS_BIGINTEGER, 'base=10', SYS_INTEGER], [iffStateLess], 'ToString');
1695RegisterInternalFunction(TStringToBigIntegerFunc, 'StringToBigInteger', ['s', SYS_STRING, 'base=10', SYS_INTEGER], SYS_BIGINTEGER, [iffStateLess], 'ToBigInteger');
1696RegisterInternalStringFunction(TBigIntegerToHexFunc, 'BigIntegerToHex', ['v', SYS_BIGINTEGER], [iffStateLess], 'ToHex');
1697RegisterInternalFunction(THexToBigIntegerFunc, 'HexToBigInteger', ['h', SYS_STRING], SYS_BIGINTEGER, [iffStateLess], 'HexToBigInteger');
1698
1699RegisterInternalFunction(TBigIntegerToBlobFunc, 'BigIntegerToBlobParameter', ['v', SYS_BIGINTEGER], SYS_VARIANT, [iffStateLess], 'ToBlobParameter');
1700RegisterInternalInterfaceFunction(TBlobToBigIntegerFunc, 'BlobFieldToBigInteger', ['b', SYS_STRING], SYS_BIGINTEGER, [iffStateLess]);
1701
1702RegisterInternalFloatFunction(TBigIntegerToFloatFunc, '', ['v', SYS_BIGINTEGER], [iffStateLess], 'ToFloat');
1703RegisterInternalIntFunction(TBigIntegerToIntegerFunc, '', ['v', SYS_BIGINTEGER], [iffStateLess], 'ToInteger');
1704
1705
1706RegisterInternalBoolFunction(TBigIntegerOddFunc, 'Odd', ['i', SYS_BIGINTEGER], [iffStateLess, iffOverloaded], 'IsOdd');
1707RegisterInternalBoolFunction(TBigIntegerEvenFunc, 'Even', ['i', SYS_BIGINTEGER], [iffStateLess, iffOverloaded], 'IsEven');
1708RegisterInternalIntFunction(TBigIntegerSignFunc, 'Sign', ['v', SYS_BIGINTEGER], [iffStateLess, iffOverloaded], 'Sign');
1709RegisterInternalFunction(TBigIntegerAbsFunc, 'Abs', ['v', SYS_BIGINTEGER], SYS_BIGINTEGER, [iffStateLess, iffOverloaded], 'Abs');
1710
1711RegisterInternalIntFunction(TBigIntegerBitLengthFunc, '', ['v', SYS_BIGINTEGER], [iffStateLess], 'BitLength');
1712RegisterInternalBoolFunction(TBigIntegerTestBitFunc, '', ['i', SYS_BIGINTEGER, 'bit', SYS_INTEGER], [iffStateLess], 'TestBit');
1713RegisterInternalProcedure(TBigIntegerSetBitFunc, '', ['@i', SYS_BIGINTEGER, 'bit', SYS_INTEGER], 'SetBit', [iffOverloaded]);
1714RegisterInternalProcedure(TBigIntegerSetBitValFunc, '', ['@i', SYS_BIGINTEGER, 'bit', SYS_INTEGER, 'v', SYS_BOOLEAN], 'SetBit', [iffOverloaded]);
1715RegisterInternalProcedure(TBigIntegerClearBitFunc, '', ['@i', SYS_BIGINTEGER, 'bit', SYS_INTEGER], 'ClearBit', []);
1716RegisterInternalIntFunction(TBigIntegerPopCountFunc, '', ['i', SYS_BIGINTEGER], [iffStateLess], 'PopCount');
1717
1718RegisterInternalFunction(TBigIntegerGcdFunc, 'Gcd', ['a', SYS_BIGINTEGER, 'b', SYS_BIGINTEGER], SYS_BIGINTEGER, [iffStateLess, iffOverloaded]);
1719RegisterInternalFunction(TBigIntegerLcmFunc, 'Lcm', ['a', SYS_BIGINTEGER, 'b', SYS_BIGINTEGER], SYS_BIGINTEGER, [iffStateLess, iffOverloaded]);
1720RegisterInternalBoolFunction(TBigIntegerIsPrimeFunc, 'IsPrime',['n', SYS_BIGINTEGER, 'prob=25', SYS_INTEGER], [iffStateLess, iffOverloaded], 'IsPrime');
1721RegisterInternalFunction(TBigIntegerNextPrimeFunc, '', ['n', SYS_BIGINTEGER, 'prob=25', SYS_INTEGER], SYS_BIGINTEGER, [iffStateLess], 'NextPrime');
1722
1723RegisterInternalFunction(TBigIntegerPowerFunc, 'IntPower', ['base', SYS_BIGINTEGER, 'exponent', SYS_INTEGER], SYS_BIGINTEGER, [iffStateLess, iffOverloaded], 'Power');
1724RegisterInternalFunction(TBigIntegerSqrFunc, 'Sqr', ['v', SYS_BIGINTEGER], SYS_BIGINTEGER, [iffStateLess, iffOverloaded], 'Sqr');
1725RegisterInternalProcedure(TBigIntegerDivModFunc, 'DivMod',
1726['dividend', SYS_BIGINTEGER, 'divisor', SYS_BIGINTEGER,
1727'@result', SYS_BIGINTEGER, '@remainder', SYS_BIGINTEGER], '', [iffOverloaded]);
1728RegisterInternalFunction(TBigIntegerModPowFunc, 'ModPow', ['base', SYS_BIGINTEGER, 'exponent', SYS_BIGINTEGER, 'modulus', SYS_BIGINTEGER],
1729SYS_BIGINTEGER, [iffStateLess, iffOverloaded], 'ModPow');
1730RegisterInternalFunction(TBigIntegerModPowFunc, 'ModPow', ['base', SYS_BIGINTEGER, 'exponent', SYS_INTEGER, 'modulus', SYS_BIGINTEGER],
1731SYS_BIGINTEGER, [iffStateLess, iffOverloaded], 'ModPow');
1732RegisterInternalFunction(TBigIntegerModInvFunc, 'ModInv', ['base', SYS_BIGINTEGER, 'modulus', SYS_BIGINTEGER],
1733SYS_BIGINTEGER, [iffStateLess], 'ModInv');
1734RegisterInternalFunction(TBigIntegerFactorialFunc, 'BigFactorial', ['n', SYS_INTEGER], SYS_BIGINTEGER, [iffStateLess]);
1735RegisterInternalFunction(TBigIntegerPrimorialFunc, 'BigPrimorial', ['n', SYS_INTEGER], SYS_BIGINTEGER, [iffStateLess]);
1736
1737RegisterInternalIntFunction(TBigJacobiFunc, 'BigJacobi', ['a', SYS_BIGINTEGER, 'b', SYS_BIGINTEGER], [iffStateLess], 'Jacobi');
1738RegisterInternalIntFunction(TBigLegendreFunc, 'BigLegendre', ['a', SYS_BIGINTEGER, 'b', SYS_BIGINTEGER], [iffStateLess], 'Legendre');
1739
1740RegisterInternalFunction(TBigIntegerRandomFunc, 'RandomBigInteger', ['limitPlusOne', SYS_BIGINTEGER], SYS_BIGINTEGER);
1741
1742finalization
1743
1744vPool.Cleanup;
1745FreeAndNil(vPool);
1746
1747end.
1748
1749