MathgeomGLS
121 строка · 3.1 Кб
1program GenerateBaseConversionTables;
2
3{$APPTYPE CONSOLE}
4
5{$R *.res}
6
7uses
8System.SysUtils, System.Math, System.Classes;
9
10type
11TBaseInfo = record
12MaxPower: UInt64;
13MaxDigits: Integer;
14PowerOfTwo: Boolean;
15MaxFactor: UInt32;
16end;
17
18var
19BaseInfos32: array[2..36] of TBaseInfo;
20BaseInfos64: array[2..36] of TBaseInfo;
21
22MaxFactorShift: Integer;
23
24function IsPowerofTwo(I: Integer): Boolean;
25begin
26Result := (I and (I - 1)) = 0;
27end;
28
29procedure FindMaxValue(const Base, Max: UInt64; var Info: TBaseInfo);
30var
31MaxPower: UInt64;
32begin
33if (Base < 2) or (Base > 36) then
34raise EInvalidArgument.Create('Invalid base value');
35MaxPower := Max div Base;
36Write('Max = ', MaxPower, ': ');
37Info.PowerOfTwo := IsPowerofTwo(Base);
38Info.MaxPower := Base;
39Info.MaxDigits := 1;
40repeat
41Write(Info.MaxPower, ' ');
42Info.MaxPower := Info.MaxPower * Base;
43Inc(Info.MaxDigits);
44until Info.MaxPower >= MaxPower;
45Writeln(Info.MaxPower);
46Info.MaxFactor := Round((Ln(2) / Ln(Info.MaxPower)) * (1 shl MaxFactorShift));
47Writeln;
48end;
49
50const
51Bools: array[Boolean] of string = ('False', 'True');
52
53procedure WriteArray(W: TStreamWriter; const Name: string; const Bases: array of TBaseInfo; const Comment: string);
54var
55Comma: Char;
56I: Integer;
57begin
58Comma := ',';
59W.WriteLine(' // %s', [Comment]);
60W.WriteLine(' %s: array[TNumberBase] of BigInteger.TNumberBaseInfo = ', [Name]);
61W.WriteLine(' (');
62
63for I := Low(Bases) to High(Bases) do
64begin
65if I = High(Bases) then
66Comma := ' ';
67W.WriteLine(Format(' (MaxPower: %20u; MaxDigits: %2d; PowerofTwo: %5s; MaxFactor: %6u)%s // Base %d',
68[Bases[I].MaxPower, Bases[I].MaxDigits, Bools[Bases[I].PowerOfTwo], Bases[I].MaxFactor, Comma, I + 2],
69TFormatSettings.Invariant));
70end;
71
72W.WriteLine(' );');
73end;
74
75procedure WriteArrays;
76var
77W: TStreamWriter;
78begin
79W := TStreamWriter.Create('bases.inc', False, TEncoding.UTF8);
80try
81W.WriteLine('{$IF CompilerVersion < 29.0}');
82W.WriteLine(' {$IF (DEFINED(WIN32) or DEFINED(CPUX86)) AND NOT DEFINED(CPU32BITS)}');
83W.WriteLine(' {$DEFINE CPU32BITS}');
84W.WriteLine(' {$IFEND}');
85W.WriteLine(' {$IF (DEFINED(WIN64) OR DEFINED(CPUX64)) AND NOT DEFINED(CPU64BITS)}');
86W.WriteLine(' {$DEFINE CPU64BITS}');
87W.WriteLine(' {$IFEND}');
88W.WriteLine('{$IFEND}');
89W.WriteLine;
90W.WriteLine('const');
91W.WriteLine(' CMaxFactorShift = %d;', [MaxFactorShift]);
92
93W.WriteLine('{$IFDEF CPU64BITS}');
94WriteArray(W, 'CBaseInfos', BaseInfos64, 'Maximum powers of given bases that fit into UInt64');
95W.WriteLine('{$ELSE}');
96WriteArray(W, 'CBaseInfos', BaseInfos32, 'Maximum powers of given bases that fit into UInt32');
97W.WriteLine('{$ENDIF}');
98W.WriteLine;
99finally
100W.Free;
101end;
102end;
103
104var
105I: Integer;
106
107begin
108try
109MaxFactorShift := 24;
110for I := 2 to 36 do
111begin
112FindMaxValue(I, High(UInt32), BaseInfos32[I]);
113FindMaxValue(I, High(UInt64), BaseInfos64[I]);
114end;
115WriteArrays;
116except
117on E: Exception do
118Writeln(E.ClassName, ': ', E.Message);
119end;
120Readln;
121end.
122
123