Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,113 +0,0 @@
|
|||
with Ada.Numerics.Generic_Elementary_Functions;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with GNATCOLL.GMP.Integers;
|
||||
with GNATCOLL.GMP.Lib;
|
||||
|
||||
procedure Hamming is
|
||||
|
||||
type Log_Type is new Long_Long_Float;
|
||||
package Funcs is new Ada.Numerics.Generic_Elementary_Functions (Log_Type);
|
||||
|
||||
type Factors_Array is array (Positive range <>) of Positive;
|
||||
|
||||
generic
|
||||
Factors : Factors_Array := (2, 3, 5);
|
||||
-- The factors for smooth numbers. Hamming numbers are 5-smooth.
|
||||
package Smooth_Numbers is
|
||||
type Number is private;
|
||||
function Compute (Nth : Positive) return Number;
|
||||
function Image (N : Number) return String;
|
||||
|
||||
private
|
||||
type Exponent_Type is new Natural;
|
||||
type Exponents_Array is array (Factors'Range) of Exponent_Type;
|
||||
-- Numbers are stored as the exponents of the prime factors.
|
||||
|
||||
type Number is record
|
||||
Exponents : Exponents_Array;
|
||||
Log : Log_Type;
|
||||
-- The log of the value, used to ease sorting.
|
||||
end record;
|
||||
|
||||
function "=" (N1, N2 : Number) return Boolean
|
||||
is (for all F in Factors'Range => N1.Exponents (F) = N2.Exponents (F));
|
||||
end Smooth_Numbers;
|
||||
|
||||
package body Smooth_Numbers is
|
||||
One : constant Number := (Exponents => (others => 0), Log => 0.0);
|
||||
Factors_Log : array (Factors'Range) of Log_Type;
|
||||
|
||||
function Image (N : Number) return String is
|
||||
use GNATCOLL.GMP.Integers, GNATCOLL.GMP.Lib;
|
||||
R, Tmp : Big_Integer;
|
||||
begin
|
||||
Set (R, "1");
|
||||
for F in Factors'Range loop
|
||||
Set (Tmp, Factors (F)'Image);
|
||||
Raise_To_N (Tmp, GNATCOLL.GMP.Unsigned_Long (N.Exponents (F)));
|
||||
Multiply (R, Tmp);
|
||||
end loop;
|
||||
return Image (R);
|
||||
end Image;
|
||||
|
||||
function Compute (Nth : Positive) return Number is
|
||||
Candidates : array (Factors'Range) of Number;
|
||||
|
||||
Values : array (1 .. Nth) of Number;
|
||||
-- Will result in Storage_Error for very large values of Nth
|
||||
|
||||
Indices : array (Factors'Range) of Natural :=
|
||||
(others => Values'First);
|
||||
Current : Number;
|
||||
Tmp : Number;
|
||||
begin
|
||||
for F in Factors'Range loop
|
||||
Factors_Log (F) := Funcs.Log (Log_Type (Factors (F)));
|
||||
Candidates (F) := One;
|
||||
Candidates (F).Exponents (F) := 1;
|
||||
Candidates (F).Log := Factors_Log (F);
|
||||
end loop;
|
||||
|
||||
Values (1) := One;
|
||||
|
||||
for Count in 2 .. Nth loop
|
||||
-- Find next value (the lowest of the candidates)
|
||||
Current := Candidates (Factors'First);
|
||||
for F in Factors'First + 1 .. Factors'Last loop
|
||||
if Candidates (F).Log < Current.Log then
|
||||
Current := Candidates (F);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
Values (Count) := Current;
|
||||
|
||||
-- Update the candidates. There might be several candidates with
|
||||
-- the same value
|
||||
for F in Factors'Range loop
|
||||
if Candidates (F) = Current then
|
||||
Indices (F) := Indices (F) + 1;
|
||||
|
||||
Tmp := Values (Indices (F));
|
||||
Tmp.Exponents (F) := Tmp.Exponents (F) + 1;
|
||||
Tmp.Log := Tmp.Log + Factors_Log (F);
|
||||
|
||||
Candidates (F) := Tmp;
|
||||
end if;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
return Values (Nth);
|
||||
end Compute;
|
||||
end Smooth_Numbers;
|
||||
|
||||
package Hamming is new Smooth_Numbers ((2, 3, 5));
|
||||
|
||||
begin
|
||||
for N in 1 .. 20 loop
|
||||
Put (" " & Hamming.Image (Hamming.Compute (N)));
|
||||
end loop;
|
||||
New_Line;
|
||||
|
||||
Put_Line (Hamming.Image (Hamming.Compute (1691)));
|
||||
Put_Line (Hamming.Image (Hamming.Compute (1_000_000)));
|
||||
end Hamming;
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
use BigInteger; use Time;
|
||||
|
||||
// Chapel doesn't have closure functions that can capture variables from
|
||||
// outside scope, so we use a class to emulate them for this special case;
|
||||
// the member fields mult, mrglst, and mltlst, emulate "captured" variables
|
||||
// that would normally be captured by the `next` continuation closure...
|
||||
class HammingsList {
|
||||
const head: bigint;
|
||||
const mult: uint(8);
|
||||
var mrglst: shared HammingsList?;
|
||||
var mltlst: shared HammingsList?;
|
||||
var tail: shared HammingsList? = nil;
|
||||
proc init(hd: bigint, mlt: uint(8), mrgl: shared HammingsList?,
|
||||
mltl: shared HammingsList?) {
|
||||
head = hd; mult = mlt; mrglst = mrgl; mltlst = mltl; }
|
||||
proc next(): shared HammingsList {
|
||||
if tail != nil then return tail: shared HammingsList;
|
||||
const nhd: bigint = mltlst!.head * mult;
|
||||
if mrglst == nil then {
|
||||
tail = new shared HammingsList(nhd, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mltlst = mltlst!.next();
|
||||
tail!.mltlst <=> mltlst;
|
||||
}
|
||||
else {
|
||||
if mrglst!.head < nhd then {
|
||||
tail = new shared HammingsList(mrglst!.head, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mrglst = mrglst!.next(); mrglst <=> tail!.mrglst;
|
||||
mltlst <=> tail!.mltlst;
|
||||
}
|
||||
else {
|
||||
tail = new shared HammingsList(nhd, mult,
|
||||
nil: shared HammingsList?,
|
||||
nil: shared HammingsList?);
|
||||
mltlst = mltlst!.next(); mltlst <=> tail!.mltlst;
|
||||
mrglst <=> tail!.mrglst;
|
||||
}
|
||||
}
|
||||
return tail: shared HammingsList;
|
||||
}
|
||||
}
|
||||
|
||||
proc u(n: uint(8), s: shared HammingsList?): shared HammingsList {
|
||||
var r = new shared HammingsList(1: bigint, n, s,
|
||||
nil: shared HammingsList?);
|
||||
r.mltlst = r; // lazy recursion!
|
||||
return r.next();
|
||||
}
|
||||
|
||||
iter hammings(): bigint {
|
||||
var nxt: shared HammingsList? = nil: shared HammingsList?;
|
||||
const mlts: [ 0 .. 2 ] int = [ 5, 3, 2 ];
|
||||
for m in mlts do nxt = u(m: uint(8), nxt);
|
||||
yield 1 : bigint;
|
||||
while true { yield nxt!.head; nxt = nxt!.next(); }
|
||||
}
|
||||
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
var cnt: int = 0;
|
||||
for h in hammings() { write(" ", h); cnt += 1; if cnt >= 20 then break; }
|
||||
write(".\nThe 1691st Hamming number is ");
|
||||
cnt = 0;
|
||||
for h in hammings() { cnt += 1; if cnt < 1691 then continue; write(h); break; }
|
||||
writeln(".\nThe millionth Hamming number is ");
|
||||
var timer: Timer; timer.start(); cnt = 0;
|
||||
for h in hammings() { cnt += 1; if cnt < 1000000 then continue; write(h); break; }
|
||||
timer.stop(); writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
use BigInteger; use Time;
|
||||
|
||||
iter nodupsHamming(): bigint {
|
||||
var s2dom = { 0 .. 1023 }; var s2: [s2dom] bigint; // init so can double!
|
||||
var s3dom = { 0 .. 1023 }; var s3: [s3dom] bigint; // init so can double!
|
||||
s2[0] = 1: bigint; s3[0] = 3: bigint;
|
||||
var x5 = 5: bigint; var mrg = 3: bigint;
|
||||
var s2hdi, s2tli, s3hdi, s3tli: int;
|
||||
while true {
|
||||
s2tli += 1;
|
||||
if s2hdi + s2hdi >= s2tli { // move in place to avoid allocation!
|
||||
s2[0 .. s2tli - s2hdi - 1] = s2[s2hdi .. s2tli - 1];
|
||||
s2tli -= s2hdi; s2hdi = 0; }
|
||||
const s2sz = s2.size;
|
||||
if s2tli >= s2sz then s2dom = { 0 .. s2sz + s2sz - 1 };
|
||||
var rslt: bigint; const s2hd = s2[s2hdi];
|
||||
if s2hd < mrg { rslt = s2hd; s2hdi += 1; }
|
||||
else {
|
||||
s3tli += 1;
|
||||
if s3hdi + s3hdi >= s2tli { // move in place to avoid allocation!
|
||||
s3[0 .. s3tli - s3hdi - 1] = s3[s3hdi .. s3tli - 1];
|
||||
s3tli -= s3hdi; s3hdi = 0; }
|
||||
const s3sz = s3.size;
|
||||
if s3tli >= s3sz then s3dom = { 0 .. s3sz + s3sz - 1 };
|
||||
rslt = mrg; s3[s3tli] = rslt * 3;
|
||||
s3hdi += 1; const s3hd = s3[s3hdi];
|
||||
if s3hd < x5 { mrg = s3hd; }
|
||||
else { mrg = x5; x5 = x5 * 5; s3hdi -= 1; }
|
||||
}
|
||||
s2[s2tli] = rslt * 2;
|
||||
yield rslt;
|
||||
}
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 hamming numbers are: ");
|
||||
var cnt = 0: uint(64);
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 20 then break; cnt += 1; write(" ", h); }
|
||||
|
||||
write("\nThe 1691st hamming number is "); cnt = 1;
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 1691 { writeln(h); break; } cnt += 1; }
|
||||
|
||||
write("The millionth hamming number is ");
|
||||
var timer: Timer; cnt = 1;
|
||||
timer.start(); var rslt: bigint;
|
||||
for h in nodupsHamming() {
|
||||
if cnt >= 1000000 { rslt = h; break; } cnt += 1; }
|
||||
timer.stop();
|
||||
write(rslt);
|
||||
writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
use BigInteger; use Math; use Time;
|
||||
|
||||
config const nth: uint(64) = 1000000;
|
||||
|
||||
const lb2 = 1: real(64); // log base 2 of 2!
|
||||
const lb3 = log2(3: real(64)); const lb5 = log2(5: real(64));
|
||||
record LogRep {
|
||||
var lg: real(64); var x2: uint(32);
|
||||
var x3: uint(32); var x5: uint(32);
|
||||
inline proc mul2(): LogRep {
|
||||
return new LogRep(this.lg + lb2, this.x2 + 1, this.x3, this.x5); }
|
||||
inline proc mul3(): LogRep {
|
||||
return new LogRep(this.lg + lb3, this.x2, this.x3 + 1, this.x5); }
|
||||
inline proc mul5(): LogRep {
|
||||
return new LogRep(this.lg + lb5, this.x2, this.x3, this.x5 + 1); }
|
||||
proc lr2bigint(): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
return xpnd(2: uint, this.x2) *
|
||||
xpnd(3: uint, this.x3) * xpnd(5: uint, this.x5);
|
||||
}
|
||||
proc writeThis(lr) throws {
|
||||
lr <~> this.lr2bigint();
|
||||
}
|
||||
}
|
||||
operator <(const ref a: LogRep, const ref b: LogRep): bool { return a.lg < b.lg; }
|
||||
const one = new LogRep(0, 0, 0, 0);
|
||||
|
||||
iter nodupsHammingLog(): LogRep {
|
||||
var s2dom = { 0 .. 1023 }; var s2: [s2dom] LogRep; // init so can double!
|
||||
var s3dom = { 0 .. 1023 }; var s3: [s3dom] LogRep; // init so can double!
|
||||
s2[0] = one; s3[0] = one.mul3();
|
||||
var x5 = one.mul5(); var mrg = one.mul3();
|
||||
var s2hdi, s2tli, s3hdi, s3tli: int;
|
||||
while true {
|
||||
s2tli += 1;
|
||||
if s2hdi + s2hdi >= s2tli { // move in place to avoid allocation!
|
||||
s2[0 .. s2tli - s2hdi - 1] = s2[s2hdi .. s2tli - 1];
|
||||
s2tli -= s2hdi; s2hdi = 0; }
|
||||
const s2sz = s2.size;
|
||||
if s2tli >= s2sz then s2dom = { 0 .. s2sz + s2sz - 1 };
|
||||
var rslt: LogRep; const s2hd = s2[s2hdi];
|
||||
if s2hd.lg < mrg.lg { rslt = s2hd; s2hdi += 1; }
|
||||
else {
|
||||
s3tli += 1;
|
||||
if s3hdi + s3hdi >= s2tli { // move in place to avoid allocation!
|
||||
s3[0 .. s3tli - s3hdi - 1] = s3[s3hdi .. s3tli - 1];
|
||||
s3tli -= s3hdi; s3hdi = 0; }
|
||||
const s3sz = s3.size;
|
||||
if s3tli >= s3sz then s3dom = { 0 .. s3sz + s3sz - 1 };
|
||||
rslt = mrg; s3[s3tli] = mrg.mul3(); s3hdi += 1;
|
||||
const s3hd = s3[s3hdi];
|
||||
if s3hd.lg < x5.lg { mrg = s3hd; }
|
||||
else { mrg = x5; x5 = x5.mul5(); s3hdi -= 1; }
|
||||
}
|
||||
s2[s2tli] = rslt.mul2();
|
||||
yield rslt;
|
||||
}
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 hamming numbers are: ");
|
||||
var cnt = 0: uint(64);
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= 20 then break; cnt += 1; write(" ", h); }
|
||||
|
||||
write("\nThe 1691st hamming number is "); cnt = 1;
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= 1691 { writeln(h); break; } cnt += 1; }
|
||||
|
||||
write("The ", nth, "th hamming number is ");
|
||||
var timer: Timer; cnt = 1;
|
||||
timer.start(); var rslt: LogRep;
|
||||
for h in nodupsHammingLog() {
|
||||
if cnt >= nth { rslt = h; break; } cnt += 1; }
|
||||
timer.stop();
|
||||
write(rslt);
|
||||
writeln(".\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
use BigInteger; use Math; use Sort; use Time;
|
||||
|
||||
config const nth = 1000000: uint(64);
|
||||
|
||||
type TriVal = 3*uint(32);
|
||||
|
||||
proc trival2bigint(x: TriVal): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
const (x2, x3, x5) = x;
|
||||
return xpnd(2: uint, x2) * xpnd(3: uint, x3) * xpnd(5: uint, x5);
|
||||
}
|
||||
|
||||
proc nthHamming(n: uint(64)): TriVal {
|
||||
if n < 1 {
|
||||
writeln("nthHamming - argument must be at least one!"); exit(1); }
|
||||
if n < 2 then return (0: uint(32), 0: uint(32), 0: uint(32)); // TriVal for 1
|
||||
|
||||
type LogRep = (real(64), uint(32), uint(32), uint(32));
|
||||
record Comparator {} // used for sorting in reverse order!
|
||||
proc Comparator.compare(a: LogRep, b: LogRep): real(64) {
|
||||
return b[0] - a[0]; }
|
||||
var logrepComp: Comparator;
|
||||
|
||||
const lb3 = log2(3.0: real(64)); const lb5 = log2(5.0: real(64));
|
||||
const fctr = 6.0: real(64) * lb3 * lb5;
|
||||
const crctn = log2(sqrt(30.0: real(64))); // log base 2 of sqrt 30
|
||||
// from Wikipedia Regular Numbers formula...
|
||||
const lgest = (fctr * n: real(64))**(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const frctn = if n < 1000000000 then 0.509: real(64) else 0.105: real(64);
|
||||
const lghi = (fctr * (n: real(64) + frctn * lgest))**
|
||||
(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const lglo = 2.0: real(64) * lgest - lghi; // lower limit of the upper "band"
|
||||
var count = 0: uint(64); // need to use extended precision, might go over
|
||||
var bndi = 0; var dombnd = { 0 .. bndi }; // one value so doubling size works!
|
||||
var bnd: [dombnd] LogRep; const klmt = (lghi / lb5): uint(32);
|
||||
for k in 0 .. klmt { // i, j, k values can be just uint(32) values!
|
||||
const p = k: real(64) * lb5; const jlmt = ((lghi - p) / lb3): uint(32);
|
||||
for j in 0 .. jlmt {
|
||||
const q = p + j: real(64) * lb3;
|
||||
const ir = lghi - q; const lg = q + floor(ir); // current log value (est)
|
||||
count += ir: uint(64) + 1;
|
||||
if lg >= lglo {
|
||||
const sz = dombnd.size; if bndi >= sz then dombnd = { 0..sz + sz - 1 };
|
||||
bnd[bndi] = (lg, ir: uint(32), j, k); bndi += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if n > count {
|
||||
writeln("nth_hamming: band high estimate is too low!"); exit(1); }
|
||||
dombnd = { 0 .. bndi - 1 }; const ndx = (count - n): int;
|
||||
if ndx >= dombnd.size {
|
||||
writeln("nth_hamming: band low estimate is too high!"); exit(1); }
|
||||
sort(bnd, comparator = logrepComp); // descending order leaves zeros at end!
|
||||
|
||||
const rslt = bnd[ndx]; return (rslt[1], rslt[2], rslt[3]);
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
for i in 1 .. 20 do write(" ", trival2bigint(nthHamming(i: uint(64))));
|
||||
|
||||
writeln("\nThe 1691st hamming number is ",
|
||||
trival2bigint(nthHamming(1691: uint(64))));
|
||||
|
||||
var timer: Timer;
|
||||
timer.start();
|
||||
const answr = nthHamming(nth);
|
||||
timer.stop();
|
||||
write("The ", nth, "th Hamming number is 2**",
|
||||
answr[0], " * 3**", answr[1], " * 5**", answr[2]);
|
||||
const lgrslt = (answr[0]: real(64) + answr[1]: real(64) * log2(3: real(64)) +
|
||||
answr[2]: real(64) * log2(5: real(64))) * log10(2: real(64));
|
||||
const whl = lgrslt: uint(64); const frac = lgrslt - whl: real(64);
|
||||
write(",\nwhich is approximately ", 10: real(64)**frac, "E+", whl);
|
||||
const bganswr = trival2bigint(answr);
|
||||
const answrstr = bganswr: string; const asz = answrstr.size;
|
||||
writeln(" and has ", asz, " digits.");
|
||||
if asz <= 2000 then write("Can be printed as: ", answrstr);
|
||||
else write("It's too long to print");
|
||||
writeln("!\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
use BigInteger; use Math; use Sort; use Time;
|
||||
|
||||
config const nth = 1000000: uint(64);
|
||||
|
||||
type TriVal = 3*uint(32);
|
||||
|
||||
proc trival2bigint(x: TriVal): bigint {
|
||||
proc xpnd(bs: uint, v: uint(32)): bigint {
|
||||
var rslt = 1: bigint; var bsm = bs: bigint; var vm = v: uint;
|
||||
while vm > 0 { if vm & 1 then rslt *= bsm; bsm *= bsm; vm >>= 1; }
|
||||
return rslt;
|
||||
}
|
||||
const (x2, x3, x5) = x;
|
||||
return xpnd(2: uint, x2) * xpnd(3: uint, x3) * xpnd(5: uint, x5);
|
||||
}
|
||||
|
||||
proc nthHamming(n: uint(64)): TriVal {
|
||||
if n < 1 {
|
||||
writeln("nthHamming - argument must be at least one!"); exit(1); }
|
||||
if n < 2 then return (0: uint(32), 0: uint(32), 0: uint(32)); // TriVal for 1
|
||||
|
||||
type LogRep = (bigint, uint(32), uint(32), uint(32));
|
||||
record Comparator {} // used for sorting in reverse order!
|
||||
proc Comparator.compare(a: LogRep, b: LogRep): int {
|
||||
return (b[0] - a[0]): int; }
|
||||
var logrepComp: Comparator;
|
||||
|
||||
const lb3 = log2(3.0: real(64)); const lb5 = log2(5.0: real(64));
|
||||
const bglb2 = "1267650600228229401496703205376": bigint;
|
||||
const bglb3 = "2009178665378409109047848542368": bigint;
|
||||
const bglb5 = "2943393543170754072109742145491": bigint;
|
||||
const fctr = 6.0: real(64) * lb3 * lb5;
|
||||
const crctn = log2(sqrt(30.0: real(64))); // log base 2 of sqrt 30
|
||||
// from Wikipedia Regular Numbers formula...
|
||||
const lgest = (fctr * n: real(64))**(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const frctn = if n < 1000000000 then 0.509: real(64) else 0.105: real(64);
|
||||
const lghi = (fctr * (n: real(64) + frctn * lgest))**
|
||||
(1.0: real(64) / 3.0: real(64)) - crctn;
|
||||
const lglo = 2.0: real(64) * lgest - lghi; // lower limit of the upper "band"
|
||||
var count = 0: uint(64); // need to use extended precision, might go over
|
||||
var bndi = 0; var dombnd = { 0 .. bndi }; // one value so doubling size works!
|
||||
var bnd: [dombnd] LogRep; const klmt = (lghi / lb5): uint(32);
|
||||
for k in 0 .. klmt { // i, j, k values can be just uint(32) values!
|
||||
const p = k: real(64) * lb5; const jlmt = ((lghi - p) / lb3): uint(32);
|
||||
for j in 0 .. jlmt {
|
||||
const q = p + j: real(64) * lb3;
|
||||
const ir = lghi - q; const lg = q + floor(ir); // current log value (est)
|
||||
count += ir: uint(64) + 1;
|
||||
if lg >= lglo {
|
||||
const sz = dombnd.size; if bndi >= sz then dombnd = { 0..sz + sz - 1 };
|
||||
const bglg =
|
||||
bglb2 * ir: int(64) + bglb3 * j: int(64) + bglb5 * k: int(64);
|
||||
bnd[bndi] = (bglg, ir: uint(32), j, k); bndi += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if n > count {
|
||||
writeln("nth_hamming: band high estimate is too low!"); exit(1); }
|
||||
dombnd = { 0 .. bndi - 1 }; const ndx = (count - n): int;
|
||||
if ndx >= dombnd.size {
|
||||
writeln("nth_hamming: band low estimate is too high!"); exit(1); }
|
||||
sort(bnd, comparator = logrepComp); // descending order leaves zeros at end!
|
||||
|
||||
const rslt = bnd[ndx]; return (rslt[1], rslt[2], rslt[3]);
|
||||
}
|
||||
|
||||
// test it...
|
||||
write("The first 20 Hamming numbers are: ");
|
||||
for i in 1 .. 20 do write(" ", trival2bigint(nthHamming(i: uint(64))));
|
||||
|
||||
writeln("\nThe 1691st hamming number is ",
|
||||
trival2bigint(nthHamming(1691: uint(64))));
|
||||
|
||||
var timer: Timer;
|
||||
timer.start();
|
||||
const answr = nthHamming(nth);
|
||||
timer.stop();
|
||||
write("The ", nth, "th Hamming number is 2**",
|
||||
answr[0], " * 3**", answr[1], " * 5**", answr[2]);
|
||||
const lgrslt = (answr[0]: real(64) + answr[1]: real(64) * log2(3: real(64)) +
|
||||
answr[2]: real(64) * log2(5: real(64))) * log10(2: real(64));
|
||||
const whl = lgrslt: uint(64); const frac = lgrslt - whl: real(64);
|
||||
write(",\nwhich is approximately ", 10: real(64)**frac, "E+", whl);
|
||||
const bganswr = trival2bigint(answr);
|
||||
const answrstr = bganswr: string; const asz = answrstr.size;
|
||||
writeln(" and has ", asz, " digits.");
|
||||
if asz <= 2000 then write("Can be printed as: ", answrstr);
|
||||
else write("It's too long to print");
|
||||
writeln("!\nThis last took ",
|
||||
timer.elapsed(TimeUnits.milliseconds), " milliseconds.");
|
||||
|
|
@ -1,61 +1,61 @@
|
|||
from collections.vector import (DynamicVector, CollectionElement)
|
||||
from math import (log2, trunc, pow)
|
||||
from memory import memset_zero #, memcpy)
|
||||
from time import now
|
||||
# HammingsLogImp.mojo - uses queue instead of frequent draining...
|
||||
# compile with: mojo build --march=native Hammings.mojo
|
||||
|
||||
# import bigints, std/math # no big ints
|
||||
from math import (log2, trunc)
|
||||
from memory import (memset_zero) #, memcpy)
|
||||
from time import (monotonic)
|
||||
|
||||
alias cCOUNT: Int = 1_000_000
|
||||
|
||||
struct BigNat(Stringable): # enough just to support conversion and printing
|
||||
struct BigNat(Movable, ImplicitlyCopyable, Stringable): # enough just to support conversion and printing
|
||||
''' Enough "infinite" precision to support as required here - multiply and
|
||||
divide by 10 conversion to string...
|
||||
'''
|
||||
var contents: DynamicVector[UInt32]
|
||||
fn __init__(inout self):
|
||||
self.contents = DynamicVector[UInt32]()
|
||||
fn __init__(inout self, val: UInt32):
|
||||
self.contents = DynamicVector[UInt32](4)
|
||||
self.contents.resize(1, val)
|
||||
fn __copyinit__(inout self, existing: Self):
|
||||
self.contents = existing.contents
|
||||
fn __moveinit__(inout self, owned existing: Self):
|
||||
self.contents = existing.contents^
|
||||
var contents: List[UInt32]
|
||||
fn __init__(out self):
|
||||
self.contents = List[UInt32]()
|
||||
fn __init__(out self, val: UInt32):
|
||||
self.contents = List[UInt32](length=1, fill=val)
|
||||
fn __copyinit__(out self, existing: Self):
|
||||
self.contents = List[UInt32](existing.contents)
|
||||
fn __str__(self) -> String:
|
||||
var rslt: String = ""
|
||||
var v = self.contents
|
||||
var v = List[UInt32](self.contents)
|
||||
while len(v) > 0:
|
||||
var t: UInt64 = 0
|
||||
for i in range(len(v) - 1, -1, -1):
|
||||
t = ((t << 32) + v[i].to_int())
|
||||
v[i] = (t // 10).to_int(); t -= v[i].to_int() * 10
|
||||
t = (t << 32) + Int(v[i])
|
||||
v[i] = Int(t // 10); t -= Int(v[i]) * 10
|
||||
var sz = len(v) - 1
|
||||
while sz >= 0 and v[sz] == 0: sz -= 1
|
||||
v.resize(sz + 1, 0)
|
||||
rslt = str(t) + rslt
|
||||
rslt = String(t) + rslt
|
||||
return rslt
|
||||
fn mult(inout self, mltplr: Self):
|
||||
var rslt = DynamicVector[UInt32]()
|
||||
rslt.resize(len(self.contents) + len(mltplr.contents), 0)
|
||||
for i in range(len(mltplr.contents)):
|
||||
fn __imul__(mut self, rhs: Self):
|
||||
var lenl = len(self.contents); var lenr = len(rhs.contents)
|
||||
var rslt = List[UInt32](length = lenl + lenr, fill = 0)
|
||||
for i in range(lenr):
|
||||
var t: UInt64 = 0
|
||||
for j in range(len(self.contents)):
|
||||
t += self.contents[j].to_int() * mltplr.contents[i].to_int() + rslt[i + j].to_int()
|
||||
rslt[i + j] = (t & 0xFFFFFFFF).to_int(); t >>= 32
|
||||
rslt[i + len(self.contents)] += t.to_int()
|
||||
for j in range(lenl):
|
||||
t += Int(self.contents[j]) * Int(rhs.contents[i]) + Int(rslt[i + j])
|
||||
rslt[i + j] = Int(t & 0xFFFFFFFF); t >>= 32
|
||||
rslt[i + lenl] += Int(t)
|
||||
var sz = len(rslt) - 1
|
||||
while sz >= 0 and rslt[sz] == 0: sz -= 1
|
||||
rslt.resize(sz + 1, 0); self.contents = rslt
|
||||
rslt.resize(sz + 1, 0); self.contents = rslt^
|
||||
|
||||
alias lb2: Float64 = 1.0
|
||||
alias lb3: Float64 = log2[DType.float64, 1](3.0)
|
||||
alias lb5: Float64 = log2[DType.float64, 1](5.0)
|
||||
alias lb3: Float64 = log2(Float64(3.0))
|
||||
alias lb5: Float64 = log2(Float64(5.0))
|
||||
|
||||
@value
|
||||
struct LogRep(CollectionElement, Stringable):
|
||||
@fieldwise_init
|
||||
struct LogRep(ImplicitlyCopyable, Movable, Stringable):
|
||||
var logrep: Float64
|
||||
var x2: UInt32
|
||||
var x3: UInt32
|
||||
var x5: UInt32
|
||||
fn __del__(owned self): return
|
||||
fn __del__(deinit self): return
|
||||
@always_inline
|
||||
fn mul2(self) -> Self:
|
||||
return LogRep(self.logrep + lb2, self.x2 + 1, self.x3, self.x5)
|
||||
|
|
@ -66,91 +66,122 @@ struct LogRep(CollectionElement, Stringable):
|
|||
fn mul5(self) -> Self:
|
||||
return LogRep(self.logrep + lb5, self.x2, self.x3, self.x5 + 1)
|
||||
fn __str__(self) -> String:
|
||||
# return "( " + String(self.x2) + ", " + String(self.x3) + ", " + String(self.x5) + " )"
|
||||
var rslt = BigNat(1)
|
||||
fn expnd(inout rslt: BigNat, bs: UInt32, n: UInt32):
|
||||
fn expnd(mut rslt: BigNat, bs: UInt32, n: UInt32):
|
||||
var bsm = BigNat(bs); var nm = n
|
||||
while nm > 0:
|
||||
if (nm & 1) != 0: rslt.mult(bsm)
|
||||
bsm.mult(bsm); nm >>= 1
|
||||
if (nm & 1) != 0: rslt *= bsm
|
||||
tmp = bsm; bsm *= tmp; nm >>= 1
|
||||
expnd(rslt, 2, self.x2); expnd(rslt, 3, self.x3); expnd(rslt, 5, self.x5)
|
||||
return str(rslt)
|
||||
return String(rslt)
|
||||
|
||||
alias oneLR: LogRep = LogRep(0.0, 0, 0, 0)
|
||||
|
||||
alias LogRepThunk = fn() escaping -> LogRep
|
||||
|
||||
fn hammingsLogImp() -> LogRepThunk:
|
||||
var s2 = DynamicVector[LogRep](); var s3 = DynamicVector[LogRep](); var s5 = oneLR; var mrg = oneLR
|
||||
s2.resize(512, oneLR); s2[0] = oneLR.mul2(); s3.resize(1, oneLR); s3[0] = oneLR.mul3()
|
||||
# var s2p = s2.steal_data(); var s3p = s3.steal_data()
|
||||
var s2hdi = 0; var s2tli = -1; var s3hdi = 0; var s3tli = -1
|
||||
@always_inline
|
||||
fn next() escaping -> LogRep:
|
||||
var rslt = s2[s2hdi]
|
||||
var s2len = len(s2)
|
||||
s2tli += 1;
|
||||
if s2tli >= s2len:
|
||||
s2tli = 0
|
||||
if s2hdi == s2tli:
|
||||
# Since an escaping closure doesn't currently move even for last used captures, and
|
||||
# List's can't be copied into closures, we could write a minimal List to do the job, or
|
||||
# probably easier is to just use a Mojo Iterator struct....
|
||||
struct _HammingsLogImpIter(ImplicitlyCopyable, Movable, Iterator):
|
||||
alias __copyinit__is_trivial = False
|
||||
alias __moveinit__is_trivial = False
|
||||
alias __del__is_trivial = False
|
||||
alias Element = LogRep
|
||||
var s2: List[LogRep]; var s3: List[LogRep]; var s5: LogRep; var mrg: LogRep
|
||||
# var s2p: UnsafePointer[LogRep]; var s3p: UnsafePointer[LogRep]
|
||||
var s2hdi: Int; var s2tli: Int; var s3hdi: Int; var s3tli: Int
|
||||
fn __init__(out self: Self):
|
||||
self.s2 = List[LogRep](length=512, fill=oneLR); self.s2[0] = oneLR.mul2()
|
||||
self.s3 = List[LogRep](length=1, fill=oneLR); self.s3[0] = oneLR.mul3()
|
||||
self.s5 = oneLR.mul5(); self.mrg = oneLR
|
||||
# self.s2p = self.s2.steal_data(); self.s3p = self.s3.steal_data()
|
||||
self.s2hdi = 0; self.s2tli = -1; self.s3hdi = 0; self.s3tli = -1
|
||||
fn __copyinit__(out self: Self, existing: Self, /):
|
||||
self.s2 = existing.s2.copy(); self.s3 = existing.s3.copy()
|
||||
self.s5 = existing.s5; self.mrg = existing.mrg
|
||||
# self.s2p = existing.s2p; self.s3p = existing.s3p
|
||||
self.s2hdi = existing.s2hdi; self.s2tli = existing.s2tli
|
||||
self.s3hdi = existing.s3hdi; self.s3tli = existing.s3tli
|
||||
# fn __moveinit__(out self: Self, var existing: Self, /):
|
||||
# self = existing^
|
||||
fn __has_next__(self: Self) -> Bool:
|
||||
return True # "infinite" series!
|
||||
fn __next__(mut self: Self) -> Self.Element:
|
||||
var rslt = self.s2.unsafe_get(self.s2hdi)
|
||||
var s2len = len(self.s2)
|
||||
self.s2tli += 1;
|
||||
if self.s2tli >= s2len:
|
||||
self.s2tli = 0
|
||||
if self.s2hdi == self.s2tli:
|
||||
if s2len < 1024:
|
||||
s2.resize(1024, oneLR)
|
||||
self.s2.resize(1024, oneLR) # ; self.s2p = self.s2.steal_data()
|
||||
else:
|
||||
s2.resize(s2len + s2len, oneLR) # ; s2p = s2.steal_data()
|
||||
for i in range(s2hdi):
|
||||
s2[s2len + i] = s2[i]
|
||||
self.s2.resize(s2len + s2len, oneLR) # ; self.s2p = self.s2.steal_data()
|
||||
for i in range(self.s2hdi):
|
||||
self.s2.unsafe_set(s2len + i, self.s2.unsafe_get(i))
|
||||
# memcpy[UInt8, 0](s2p + s2len, s2p, sizeof[LogRep]() * s2hdi)
|
||||
s2tli += s2len; s2len += s2len
|
||||
if rslt.logrep < mrg.logrep:
|
||||
s2hdi += 1
|
||||
if s2hdi >= s2len:
|
||||
s2hdi = 0
|
||||
self.s2tli += s2len; s2len += s2len
|
||||
if rslt.logrep < self.mrg.logrep:
|
||||
self.s2hdi += 1
|
||||
if self.s2hdi >= s2len:
|
||||
self.s2hdi = 0
|
||||
else:
|
||||
rslt = mrg
|
||||
var s3len = len(s3)
|
||||
s3tli += 1;
|
||||
if s3tli >= s3len:
|
||||
s3tli = 0
|
||||
if s3hdi == s3tli:
|
||||
rslt = self.mrg
|
||||
var s3len = len(self.s3)
|
||||
self.s3tli += 1;
|
||||
if self.s3tli >= s3len:
|
||||
self.s3tli = 0
|
||||
if self.s3hdi == self.s3tli:
|
||||
if s3len < 1024:
|
||||
s3.resize(1024, oneLR)
|
||||
self.s3.resize(1024, oneLR) # ; self.s3p = self.s3.steal_data()
|
||||
else:
|
||||
s3.resize(s3len + s3len, oneLR) # ; s3p = s3.steal_data()
|
||||
for i in range(s3hdi):
|
||||
s3[s3len + i] = s3[i]
|
||||
self.s3.resize(s3len + s3len, oneLR) # ; self.s3p = self.s3.steal_data()
|
||||
for i in range(self.s3hdi):
|
||||
self.s3.unsafe_set(s3len + i, self.s3.unsafe_get(i))
|
||||
# memcpy[UInt8, 0](s3p + s3len, s3p, sizeof[LogRep]() * s3hdi)
|
||||
s3tli += s3len; s3len += s3len
|
||||
if mrg.logrep < s5.logrep:
|
||||
s3hdi += 1
|
||||
if s3hdi >= s3len:
|
||||
s3hdi = 0
|
||||
self.s3tli += s3len; s3len += s3len
|
||||
if self.mrg.logrep < self.s5.logrep:
|
||||
self.s3hdi += 1
|
||||
if self.s3hdi >= s3len:
|
||||
self.s3hdi = 0
|
||||
else:
|
||||
s5 = s5.mul5()
|
||||
s3[s3tli] = rslt.mul3(); let t = s3[s3hdi];
|
||||
mrg = t if t.logrep < s5.logrep else s5
|
||||
s2[s2tli] = rslt.mul2(); return rslt
|
||||
return next
|
||||
self.s5 = self.s5.mul5()
|
||||
self.s3[self.s3tli] = rslt.mul3(); var t = self.s3[self.s3hdi];
|
||||
self.mrg = t if t.logrep < self.s5.logrep else self.s5
|
||||
self.s2.unsafe_set(self.s2tli, rslt.mul2()); return rslt
|
||||
|
||||
@fieldwise_init
|
||||
struct HammingsLogImp(ImplicitlyCopyable, Movable, Iterable):
|
||||
alias __del__is_trivial = True
|
||||
alias IteratorType[
|
||||
iterable_mut: Bool, //, iterable_origin: Origin[iterable_mut]
|
||||
]: Iterator = _HammingsLogImpIter
|
||||
fn __iter__(ref self: Self) -> _HammingsLogImpIter:
|
||||
return _HammingsLogImpIter()
|
||||
|
||||
fn main():
|
||||
print("The first 20 Hamming numbers are:")
|
||||
var f = hammingsLogImp();
|
||||
for i in range(20): print_no_newline(f(), " ")
|
||||
for i, h in enumerate(HammingsLogImp()):
|
||||
print(String(h) + " ", end='')
|
||||
if i >= 19: break
|
||||
print()
|
||||
f = hammingsLogImp(); var h: LogRep = oneLR
|
||||
for i in range(1691): h = f()
|
||||
print("The 1691st Hamming number is", h)
|
||||
let strt: Int = now()
|
||||
f = hammingsLogImp()
|
||||
for i in range(cCOUNT): h = f()
|
||||
let elpsd = (now() - strt) / 1000
|
||||
for i, h in enumerate(HammingsLogImp()):
|
||||
if i >= 1691 - 1: print("The 1691st Hamming number is " + String(h)); break
|
||||
var strt: Int = monotonic()
|
||||
var ham = oneLR
|
||||
for i, h in enumerate(HammingsLogImp()):
|
||||
if i >= cCOUNT - 1: ham = h; break
|
||||
var elpsd = (monotonic() - strt) / 1000
|
||||
|
||||
print("The " + str(cCOUNT) + "th Hamming number is:")
|
||||
print("2**" + str(h.x2) + " * 3**" + str(h.x3) + " * 5**" + str(h.x5))
|
||||
let lg2 = lb2 * Float64(h.x2.to_int()) + lb3 * Float64(h.x3.to_int()) + lb5 * Float64(h.x5.to_int())
|
||||
let lg10 = lg2 / log2(Float64(10))
|
||||
let expnt = trunc(lg10); let num = pow(Float64(10.0), lg10 - expnt)
|
||||
let apprxstr = str(num) + "E+" + str(expnt.to_int())
|
||||
print("The " + String(cCOUNT) + "th Hamming number is:")
|
||||
print("2**" + String(ham.x2) + " * 3**" + String(ham.x3) + " * 5**" + String(ham.x5))
|
||||
var lg2 = lb2 * Float64(Int(ham.x2)) + lb3 * Float64(Int(ham.x3)) + lb5 * Float64(Int(ham.x5))
|
||||
var lg10 = lg2 / log2(Float64(10))
|
||||
var expnt = trunc(lg10); var num = Float64(10.0)**(lg10 - expnt)
|
||||
var apprxstr = String(num) + "E+" + String(Int(expnt))
|
||||
print("Approximately: ", apprxstr)
|
||||
let answrstr = str(h)
|
||||
var answrstr = String(ham)
|
||||
print("The result has", len(answrstr), "digits.")
|
||||
print(answrstr)
|
||||
print("This took " + str(elpsd) + " microseconds.")
|
||||
print("This took " + String(elpsd) + " microseconds.")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-- 22 Mar 2025
|
||||
include Settings
|
||||
-- 23 Aug 2025
|
||||
include Setting
|
||||
|
||||
say 'HAMMING NUMBERS'
|
||||
say version
|
||||
|
|
@ -14,12 +14,12 @@ say Time('e')/1 'seconds'
|
|||
exit
|
||||
|
||||
ShowFirstN:
|
||||
procedure expose hamm.
|
||||
procedure expose Hamm.
|
||||
arg xx
|
||||
xx = xx/1
|
||||
say 'First' xx 'Hamming numbers are'
|
||||
do i = 1 to xx
|
||||
call Charout ,Right(hamm.i,5)
|
||||
call Charout ,Right(Hamm.i,5)
|
||||
if i//10 = 0 then
|
||||
say
|
||||
end
|
||||
|
|
@ -27,14 +27,12 @@ say
|
|||
return
|
||||
|
||||
ShowNth:
|
||||
procedure expose hamm.
|
||||
procedure expose Hamm.
|
||||
arg xx
|
||||
xx = xx/1
|
||||
say xx'th Hamming number is'
|
||||
say hamm.xx '('Length(hamm.xx) 'digits)'
|
||||
say Hamm.xx '('Length(Hamm.xx) 'digits)'
|
||||
say
|
||||
return
|
||||
|
||||
include Sequences
|
||||
include Functions
|
||||
include Abend
|
||||
include Math
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
For h = 1 To 20
|
||||
WScript.StdOut.Write "H(" & h & ") = " & Hamming(h)
|
||||
WScript.StdOut.WriteLine
|
||||
Next
|
||||
WScript.StdOut.Write "H(" & 1691 & ") = " & Hamming(1691)
|
||||
WScript.StdOut.WriteLine
|
||||
|
||||
Function Hamming(l)
|
||||
Dim h() : Redim h(l) : h(0) = 1
|
||||
i = 0 : j = 0 : k = 0
|
||||
x2 = 2 : x3 = 3 : x5 = 5
|
||||
For n = 1 To l-1
|
||||
m = x2
|
||||
If m > x3 Then m = x3 End If
|
||||
If m > x5 Then m = x5 End If
|
||||
h(n) = m
|
||||
If m = x2 Then i = i + 1 : x2 = 2 * h(i) End If
|
||||
If m = x3 Then j = j + 1 : x3 = 3 * h(j) End If
|
||||
If m = x5 Then k = k + 1 : x5 = 5 * h(k) End If
|
||||
Next
|
||||
Hamming = h(l-1)
|
||||
End Function
|
||||
Loading…
Add table
Add a link
Reference in a new issue