Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -0,0 +1,89 @@
//
// How to compile:
// patscc -DATS_MEMALLOC_LIBC -o hamming hamming.dats
//
#include
"share/atspre_staload.hats"
fun
min3
(
A: arrayref(int, 3)
) : natLt(3) = i where
{
var x: int = A[0]
var i: natLt(3) = 0
val () = if A[1] < x then (x := A[1]; i := 1)
val () = if A[2] < x then (x := A[2]; i := 2)
} (* end of [min3] *)
fun
hamming
{n:pos}
(
n: int(n)
) : int = let
//
var A = @[int](2, 3, 5)
val A = $UNSAFE.cast{arrayref(int, 3)}(addr@A)
var I = @[int](1, 1, 1)
val I = $UNSAFE.cast{arrayref(int, 3)}(addr@I)
val H = arrayref_make_elt<int> (i2sz(succ(n)), 0)
val () = H[0] := 1
//
fun
loop{k:pos}
(k: int(k)) : void =
(
//
if
k < n
then let
val i = min3(A)
val k =
(
if A[i] > H[k-1] then (H[k] := A[i]; k+1) else k
) : intBtwe(k, k+1)
val ii = I[i]
val () = I[i] := ii+1
val ii = $UNSAFE.cast{natLte(n)}(ii)
val () = if i = 0 then A[i] := 2*H[ii]
val () = if i = 1 then A[i] := 3*H[ii]
val () = if i = 2 then A[i] := 5*H[ii]
in
loop(k)
end // end of [then]
else () // end of [else]
//
) (* end of [loop] *)
//
in
loop (1); H[n-1]
end (* end of [hamming] *)
implement
main0 () =
{
val () =
loop(1) where
{
fun
loop
{n:pos}
(
n: int(n)
) : void =
if
n <= 20
then let
val () =
println! ("hamming(",n,") = ", hamming(n))
in
loop(n+1)
end // end of [then]
// end of [if]
} (* end of [val] *)
val n = 1691
val () = println! ("hamming(",n,") = ", hamming(n))
//
} (* end of [main0] *)

View file

@ -9,11 +9,9 @@
:else [x (rest xs) (rest ys)])]
(cons z (smerge xs* ys*)))))
(defn smerge3 [xs ys zs]
(smerge xs (smerge ys zs)))
(defn map*n [n ks] (map #(*' n %) ks))
(def hamming
(lazy-seq
(cons 1 (smerge3 (map*n 2 hamming) (map*n 3 hamming) (map*n 5 hamming)))))
(->> (map #(*' 5 %) hamming)
(smerge (map #(*' 3 %) hamming))
(smerge (map #(*' 2 %) hamming))
(cons 1))))

View file

@ -1,13 +1,13 @@
import std.stdio, std.bigint, std.algorithm, std.range, core.memory;
auto hamming(in int n) {
BigInt two = 2, three = 3, five = 5;
auto hamming(in uint n) pure nothrow /*@safe*/ {
immutable BigInt two = 2, three = 3, five = 5;
auto h = new BigInt[n];
h[0] = 1;
BigInt x2 = 2, x3 = 3, x5 = 5;
int i, j, k;
size_t i, j, k;
foreach (ref el; h[1 .. $]) {
foreach (ref el; h.dropOne) {
el = min(x2, x3, x5);
if (el == x2) x2 = two * h[++i];
if (el == x3) x3 = three * h[++j];

View file

@ -3,6 +3,7 @@ import std.bigint: BigInt;
import std.conv: text;
import std.numeric: gcd;
import std.algorithm: copy, map;
import std.array: array;
import core.stdc.stdlib: calloc;
import std.math: log; // ^^
@ -20,18 +21,10 @@ struct Hamming {
double v; // Log of the number, for convenience.
ushort[NK] e; // Exponents of each factor.
// log can't be used in CTFE yet.
//public static __gshared immutable double[factors.length] inc =
// factors[].map!log.array;
public static __gshared immutable double[factors.length] inc;
public static __gshared immutable double[factors.length] inc =
factors[].map!log.array;
nothrow pure static this() {
//factors[].map!log.copy(inc[]); // Not nothrow, not const.
foreach (immutable i, immutable f; factors)
inc[i] = f.log;
}
bool opEquals(in ref Hamming y) const pure nothrow {
bool opEquals(in ref Hamming y) const pure nothrow @nogc {
//return this.e == y.e; // Too much slow.
foreach (immutable i; 0 .. this.e.length)
if (this.e[i] != y.e[i])
@ -39,7 +32,7 @@ struct Hamming {
return true;
}
void update() pure nothrow {
void update() pure nothrow @nogc {
//this.v = dotProduct(inc, this.e); // Too much slow.
this.v = 0.0;
foreach (immutable i; 0 .. this.e.length)
@ -58,13 +51,14 @@ struct Hamming {
__gshared Hamming[] hams;
__gshared Hamming[NK] values;
nothrow static this() {
nothrow @nogc static this() {
// Slower than calloc if you don't use all the MAX_HAM items.
//hams = new Hamming[MAX_HAM];
auto ptr = cast(Hamming*)calloc(MAX_HAM, Hamming.sizeof);
static const err = new Error("Not enough memory.");
if (!ptr)
throw new Error("Not enough memory.");
throw err;
hams = ptr[0 .. MAX_HAM];
foreach (immutable i, ref v; values) {
@ -74,7 +68,7 @@ nothrow static this() {
}
ref Hamming getHam(in size_t n) nothrow
ref Hamming getHam(in size_t n) nothrow @nogc
in {
assert(n <= MAX_HAM);
} body {

View file

@ -0,0 +1,154 @@
import std.stdio: writefln;
import std.bigint: BigInt;
import std.conv: text;
import std.algorithm: map;
import std.array: array;
import core.stdc.stdlib: malloc, calloc, free;
import std.math: log; // ^^
// Number of factors.
enum NK = 3;
__gshared immutable int[NK] primes = [2, 3, 5];
__gshared immutable double[NK] lnPrimes = primes[].map!log.array;
/// K-smooth numbers (stored as their exponents of each factor).
struct Hamming {
double ln; // Log of the number.
ushort[NK] e; // Exponents of each factor.
Hamming* next;
size_t n;
// Recompute the logarithm from the exponents.
void recalculate() pure nothrow @safe @nogc {
this.ln = 0.0;
foreach (immutable i, immutable ei; this.e)
this.ln += lnPrimes[i] * ei;
}
string toString() const {
BigInt result = 1;
foreach (immutable i, immutable f; primes)
result *= f.BigInt ^^ this.e[i];
return result.text;
}
}
Hamming getHam(in size_t n) nothrow @nogc
in {
assert(n && n != size_t.max);
} body {
static struct Candidate {
typeof(Hamming.ln) ln;
typeof(Hamming.e) e;
void increment(in size_t n) pure nothrow @safe @nogc {
e[n] += 1;
ln += lnPrimes[n];
}
bool opEquals(T)(in ref T y) const pure nothrow @safe @nogc {
// return this.e == y.e; // Slow.
return !((this.e[0] ^ y.e[0]) |
(this.e[1] ^ y.e[1]) |
(this.e[2] ^ y.e[2]));
}
int opCmp(T)(in ref T y) const pure nothrow @safe @nogc {
return (ln > y.ln) ? 1 : (ln < y.ln ? -1 : 0);
}
}
static struct HammingIterator { // Not a Range.
Candidate cand;
Hamming* base;
size_t primeIdx;
this(in size_t i, Hamming* b) pure nothrow @safe @nogc {
primeIdx = i;
base = b;
cand.e = base.e;
cand.ln = base.ln;
cand.increment(primeIdx);
}
void next() pure nothrow @safe @nogc {
base = base.next;
cand.e = base.e;
cand.ln = base.ln;
cand.increment(primeIdx);
}
}
HammingIterator[NK] its;
Hamming* head = cast(Hamming*)calloc(Hamming.sizeof, 1);
Hamming* freeList, cur = head;
Candidate next;
foreach (immutable i, ref it; its)
it = HammingIterator(i, cur);
for (size_t i = cur.n = 1; i < n; ) {
auto leastReferenced = size_t.max;
next.ln = double.max;
foreach (ref it; its) {
if (it.cand == *cur)
it.next;
if (it.base.n < leastReferenced)
leastReferenced = it.base.n;
if (it.cand < next)
next = it.cand;
}
// Collect unferenced numbers.
while (head.n < leastReferenced) {
auto tmp = head;
head = head.next;
tmp.next = freeList;
freeList = tmp;
}
if (!freeList) {
cur.next = cast(Hamming*)malloc(Hamming.sizeof);
} else {
cur.next = freeList;
freeList = freeList.next;
}
cur = cur.next;
version (fastmath) {
cur.ln = next.ln;
cur.e = next.e;
} else {
cur.e = next.e;
cur.recalculate; // Prevent FP error accumulation.
}
cur.n = i++;
cur.next = null;
}
auto result = *cur;
version (leak) {}
else {
while (head) {
auto tmp = head;
head = head.next;
tmp.free;
}
while (freeList) {
auto tmp = freeList;
freeList = freeList.next;
tmp.free;
}
}
return result;
}
void main() {
foreach (immutable n; [1691, 10 ^^ 6, 10_000_000])
writefln("%8d: %s", n, n.getHam);
}

View file

@ -1,99 +1,93 @@
package main
import (
"flag"
"fmt"
"math"
"math/big"
"os"
"flag"
"fmt"
"log"
"math"
"math/big"
"os"
)
var ordinal int // ordinal of last sequence element to compute
var sequenceMode bool // print the whole sequence or just one element?
var (
// print the whole sequence or just one element?
var lg3, lg5 float64 // precomputed base-2 logarithms for 3 and 5
seqMode = flag.Bool("s", false, "sequence mode")
// precomputed base-2 logarithms for 3 and 5
lg3, lg5 float64 = math.Log2(3), math.Log2(5)
var table [][3]int16 // table for dynamic-programming stored results
var front [3]cursor // state of the three multiplied sequences
// state of the three multiplied sequences
front = [3]cursor{
{0, 0, 1}, // 2
{1, 0, lg3}, // 3
{2, 0, lg5}, // 5
}
// table for dynamic-programming stored results
table [][3]int16
)
type cursor struct {
f int // index (0, 1, 2) corresponding to factor (2, 3, 5)
i int // index into table for the entry being multiplied
lg float64 // base-2 logarithm of the multiple (for ordering)
f int // index (0, 1, 2) corresponding to factor (2, 3, 5)
i int // index into table for the entry being multiplied
lg float64 // base-2 logarithm of the multiple (for ordering)
}
func (c *cursor) value() [3]int16 {
x := table[c.i]
x[c.f]++ // multiply by incrementing the exponent
return x
func (c *cursor) val() [3]int16 {
x := table[c.i]
x[c.f]++ // multiply by incrementing the exponent
return x
}
func (c *cursor) advance() {
c.i++
// skip entries that would produce duplicates
for (c.f < 2 && table[c.i][2] > 0) || (c.f < 1 && table[c.i][1] > 0) {
c.i++
}
x := c.value()
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
c.i++
// skip entries that would produce duplicates
for (c.f < 2 && table[c.i][2] > 0) || (c.f < 1 && table[c.i][1] > 0) {
c.i++
}
x := c.val()
c.lg = float64(x[0]) + lg3*float64(x[1]) + lg5*float64(x[2])
}
func step() {
table = append(table, front[0].value())
front[0].advance()
// re-establish sorted order
if front[0].lg > front[1].lg {
front[0], front[1] = front[1], front[0]
if front[1].lg > front[2].lg {
front[1], front[2] = front[2], front[1]
}
}
table = append(table, front[0].val())
front[0].advance()
// re-establish sorted order
if front[0].lg > front[1].lg {
front[0], front[1] = front[1], front[0]
if front[1].lg > front[2].lg {
front[1], front[2] = front[2], front[1]
}
}
}
func show(elem [3]int16) {
z := big.NewInt(1)
for i, base := range []int64{2, 3, 5} {
b := big.NewInt(base)
x := big.NewInt(int64(elem[i]))
z.Mul(z, b.Exp(b, x, nil))
}
fmt.Println(z)
}
func fail(msg string) {
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], msg)
os.Exit(1)
}
func parse() {
flag.Parse()
if flag.NArg() != 1 {
fail("need one argument")
}
_, err := fmt.Sscan(flag.Arg(0), &ordinal)
if err != nil || ordinal <= 0 {
fail("argument must be a positive integer")
}
}
func init() {
flag.BoolVar(&sequenceMode, "s", false, "sequence mode")
lg3 = math.Log2(3)
lg5 = math.Log2(5)
front = [3]cursor{
{0, 0, 1}, // 2
{1, 0, lg3}, // 3
{2, 0, lg5}, // 5
}
z := big.NewInt(1)
for i, base := range []int64{2, 3, 5} {
b := big.NewInt(base)
x := big.NewInt(int64(elem[i]))
z.Mul(z, b.Exp(b, x, nil))
}
fmt.Println(z)
}
func main() {
parse()
table = make([][3]int16, 1, ordinal)
for i, n := 1, ordinal; i < n; i++ {
if sequenceMode {
show(table[i-1])
}
step()
}
show(table[ordinal-1])
log.SetPrefix(os.Args[0] + ": ")
log.SetOutput(os.Stderr)
flag.Parse()
if flag.NArg() != 1 {
log.Fatalln("need one positive integer argument")
}
var ordinal int // ordinal of last sequence element to compute
_, err := fmt.Sscan(flag.Arg(0), &ordinal)
if err != nil || ordinal <= 0 {
log.Fatalln("argument must be a positive integer")
}
table = make([][3]int16, 1, ordinal)
for i, n := 1, ordinal; i < n; i++ {
if *seqMode {
show(table[i-1])
}
step()
}
show(table[ordinal-1])
}

View file

@ -21,10 +21,10 @@ rngval n
nthHam :: Int -> (Double, (Int, Int, Int))
nthHam n -- n: 1-based: 1,2,3...
| w >= 1 = error $ "Breach of contract: (w < 1): " ++ show w
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
| True = res
| w >= 1 = error $ "Breach of contract: (w < 1): " ++ show w
| m < 0 = error $ "Not enough triples generated: " ++ show (c,n)
| m >= nb = error $ "Generated band is too narrow: " ++ show (m,nb)
| otherwise = res
where
(d,w) = rngval n -- correction dist, width
hi = estval n - d -- hi > logval > hi-w

View file

@ -1 +1 @@
hamming=: {. (/:~@~.@], 2 3 5 * {)/ @ (1x,~i.@-)
hamming=: {. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)

View file

@ -1 +1 @@
(1x,~i.@-)
(1x ,~ i.@-)

View file

@ -1,2 +1,2 @@
({. (/:~@~.@], 2 3 5 * {)/ @ (1x,~i.@-)) 7
({. (/:~@~.@] , 2 3 5 * {)/@(1x ,~ i.@-)) 7
1 2 3 4 5 6 8

View file

@ -1,2 +1,2 @@
(1x,~i.@-) 7
(1x ,~ i.@-) 7
6 5 4 3 2 1 0 1

View file

@ -1,2 +1,2 @@
6(/:~@~.@], 2 3 5 * {) 5(/:~@~.@], 2 3 5 * {) 4(/:~@~.@], 2 3 5 * {) 3(/:~@~.@], 2 3 5 * {) 2(/:~@~.@], 2 3 5 * {) 1(/:~@~.@], 2 3 5 * {) 0(/:~@~.@], 2 3 5 * {) 1
6(/:~@~.@] , 2 3 5 * {) 5(/:~@~.@] , 2 3 5 * {) 4(/:~@~.@] , 2 3 5 * {) 3(/:~@~.@] , 2 3 5 * {) 2(/:~@~.@] , 2 3 5 * {) 1(/:~@~.@] , 2 3 5 * {) 0(/:~@~.@] , 2 3 5 * {) 1
1 2 3 4 5 6 8 9 10 12 15 18 20 25 30 16 24 40

View file

@ -0,0 +1,110 @@
import java.math.BigInteger;
public class Hamming
{
public static void main(String args[])
{
Stream hamming = makeHamming();
System.out.print("H[1..20] ");
for (int i=0; i<20; i++) {
System.out.print(hamming.value());
System.out.print(" ");
hamming = hamming.advance();
}
System.out.println();
System.out.print("H[1691] ");
hamming = makeHamming();
for (int i=1; i<1691; i++) {
hamming = hamming.advance();
}
System.out.println(hamming.value());
hamming = makeHamming();
System.out.print("H[10^6] ");
for (int i=1; i<1000000; i++) {
hamming = hamming.advance();
}
System.out.println(hamming.value());
}
public interface Stream
{
BigInteger value();
Stream advance();
}
public static class MultStream implements Stream
{
MultStream(int mult)
{ m_mult = BigInteger.valueOf(mult); }
MultStream setBase(Stream s)
{ m_base = s; return this; }
public BigInteger value()
{ return m_mult.multiply(m_base.value()); }
public Stream advance()
{ return setBase(m_base.advance()); }
private final BigInteger m_mult;
private Stream m_base;
}
private final static class RegularStream implements Stream
{
RegularStream(Stream[] streams, BigInteger val)
{
m_streams = streams;
m_val = val;
}
public BigInteger value()
{ return m_val; }
public Stream advance()
{
// memoized value for the next stream instance.
if (m_advance != null) { return m_advance; }
int minidx = 0 ;
BigInteger next = nextStreamValue(0);
for (int i=1; i<m_streams.length; i++) {
BigInteger v = nextStreamValue(i);
if (v.compareTo(next) < 0) {
next = v;
minidx = i;
}
}
RegularStream ret = new RegularStream(m_streams, next);
// memoize the value!
m_advance = ret;
m_streams[minidx].advance();
return ret;
}
private BigInteger nextStreamValue(int streamidx)
{
// skip past duplicates in the streams we're merging.
BigInteger ret = m_streams[streamidx].value();
while (ret.equals(m_val)) {
m_streams[streamidx] = m_streams[streamidx].advance();
ret = m_streams[streamidx].value();
}
return ret;
}
private final Stream[] m_streams;
private final BigInteger m_val;
private RegularStream m_advance = null;
}
private final static Stream makeHamming()
{
MultStream nums[] = new MultStream[] {
new MultStream(2),
new MultStream(3),
new MultStream(5)
};
Stream ret = new RegularStream(nums, BigInteger.ONE);
for (int i=0; i<nums.length; i++) {
nums[i].setBase(ret);
}
return ret;
}
}

View file

@ -0,0 +1,19 @@
n = 40
powers_2 = 2.^[0:n-1]
powers_3 = 3.^[0:n-1]
powers_5 = 5.^[0:n-1]
matrix = powers_2 * powers_3'
powers_23 = sort(reshape(matrix,length(matrix),1),1)
matrix = powers_23 * powers_5'
powers_235 = sort(reshape(matrix,length(matrix),1),1)
#
# Remove the integer overflow values.
#
powers_235 = powers_235[powers_235 .> 0]
println(powers_235[1:20])
println(powers_235[1691])

View file

@ -0,0 +1,20 @@
n = 40;
powers_2 = 2.^[0:n-1];
powers_3 = 3.^[0:n-1];
powers_5 = 5.^[0:n-1];
matrix = powers_2' * powers_3;
powers_23 = sort(reshape(matrix,n*n,1));
matrix = powers_23 * powers_5;
powers_235 = sort(reshape(matrix,n*n*n,1));
%
% Remove the integer overflow values.
%
powers_235 = powers_235(powers_235 > 0);
disp(powers_235(1:20))
disp(powers_235(1691))

View file

@ -0,0 +1,163 @@
functor
import
Application
System
define
class Multiplier
attr lst
factor
current
meth init(Factor Lst)
lst := Lst
factor := Factor
{self next}
end
meth next
local
A
AS
in
A|AS = @lst
current := A*@factor
lst := AS
end
end
meth peek(?X)
X = @current
end
meth dump
{System.showInfo "DUMP"}
{System.showInfo "Factor: "#@factor}
{System.showInfo "current: "#@current}
end
end
% a priority queue of multipliers. The one which currently holds the smallest value is put on front
class PriorityQueue
attr mults
current % for duplicate detection
meth init(Mults)
mults := Mults
current := 0
end
meth insert(Mult)
local
fun {Insert M Lst}
local
Av
Mv
in
case Lst of
nil then M|Lst
[] A|AS then {A peek(Av)}
{M peek(Mv)}
if Av < Mv then
A|{Insert M AS}
else M|A|AS
end
end
end
end
in
mults := {Insert Mult @mults}
end
end
meth next(Tail NextTail)
local
M
Ms
X
Curr
in
M|Ms = @mults
{M peek(X)} % gets value of lowest iterator
Curr = @current
if Curr == X then
skip
else
Tail = X|NextTail % if we found a new value: append
end
{M next}
mults := Ms
{self insert(M)}
if Curr == X then
{self next(Tail NextTail)}
else
current := X
end
end
end
end
local
% Sieve of erasthothenes, adapted from http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Oz
fun {Sieve N}
S = {Array.new 2 N true}
M = {Float.toInt {Sqrt {Int.toFloat N}}}
in
for I in 2..M do
if S.I then
for J in I*I..N;I do
S.J := false
end
end
end
S
end
fun {Primes N}
S = {Sieve N}
in
for I in 2..N collect:C do
if S.I then {C I} end
end
end
% help method to extract args
proc {GetNK ArgList N K}
case ArgList of
A|B|_ then
N={StringToInt A}
K={StringToInt B}
end
end
proc {Generate N PriorQ Tail}
local
NewTail
in
if N == 0 then
Tail = nil
else
{PriorQ next(Tail NewTail)}
{Generate (N-1) PriorQ NewTail}
end
end
end
K = 3
PrimeFactors
Lst
Tail
in
ArgList = {Application.getArgs plain}
Lst = 1|Tail
PrimeFactors = {List.take {Primes K*K} K}
Mults = {List.map PrimeFactors fun {$ A} {New Multiplier init(A Lst) } end}
PriorQ = {New PriorityQueue init(Mults)}
{Generate 20 PriorQ Tail}
{ForAll Lst System.showInfo}
{Application.exit 0}
end
end

View file

@ -0,0 +1,75 @@
program HammNumb;
{$IFDEF FPC}
{$MODE DELPHI}
{$OPTIMIZATION ON}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
{
type
NativeUInt = longWord;
}
var
pot : array[0..2] of NativeUInt;
function NextHammNumb(n:NativeUInt):NativeUInt;
var
q,p,nr : NativeUInt;
begin
repeat
nr := n+1;
n := nr;
p := 0;
while NOT(ODD(nr)) do
begin
inc(p);
nr := nr div 2;
end;
Pot[0]:= p;
p := 0;
q := nr div 3;
while q*3=nr do
Begin
inc(P);
nr := q;
q := nr div 3;
end;
Pot[1] := p;
p := 0;
q := nr div 5;
while q*5=nr do
Begin
inc(P);
nr := q;
q := nr div 5;
end;
Pot[2] := p;
until nr = 1;
result:= n;
end;
procedure Check;
var
i,n: NativeUint;
begin
n := 1;
for i := 1 to 20 do
begin
n := NextHammNumb(n);
write(n,' ');
end;
writeln;
writeln;
n := 1;
for i := 1 to 1690 do
n := NextHammNumb(n);
writeln('No ',i:4,' | ',n,' = 2^',Pot[0],' 3^',Pot[1],' 5^',Pot[2]);
end;
Begin
Check;
End.

View file

@ -0,0 +1,329 @@
program hammNumb;
{$IFDEF FPC}
{$MODE DELPHI}
{$OPTIMIZATION ON,ASMCSE,CSE,PEEPHOLE}
{$ALIGN 16}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
sysutils;
const
maxPrimFakCnt = 3;//3 or 3+8 if tNumber= double, else -1 for extended to keep data aligned
minElemCnt = 10;
type
tPrimList = array of NativeUint;
tnumber = double;
tpNumber= ^tnumber;
tElem = record
n : tnumber;//ln(prime[0]^Pots[0]*...
Pots: array[0..maxPrimFakCnt] of word;
end;
tpElem = ^tElem;
tElems = array of tElem;
tElemArr = array [0..0] of tElem;
tpElemArr = ^tElemArr;
tpFaktorRec = ^tFaktorRec;
tFaktorRec = record
frElems : tElems;
frInsElems: tElems;
frAktIdx : NativeUint;
frMaxIdx : NativeUint;
frPotNo : NativeUint;
frActPot : NativeUint;
frNextFr : tpFaktorRec;
frActNumb: tElem;
frLnPrime: tnumber;
end;
tArrFR = array of tFaktorRec;
var
Pl : tPrimList;
ActIndex : NativeUint;
ArrInsert : tElems;
procedure PlInit(n: integer);
const
cPl : array[0..11] of byte=(2,3,5,7,11,13,17,19,23,29,31,37);
var
i : integer;
Begin
IF n>High(cPl)+1 then
n := High(cPl)
else
IF n < 0 then
n := 1;
setlength(Pl,n);
dec(n);
For i := 0 to n do
Pl[i] := cPl[i];
end;
procedure AusgabeElem(pElem: tElem);
var
i : integer;
Begin
with pElem do
Begin
IF n < 23 then
write(round(exp(n)):16)
else
write('ln ',n:13:7);
For i := 0 to maxPrimFakCnt do
write(' ',PL[i]:2,'^',Pots[i]);
end;
writeln
end;
//LoE == List of Elements
function LoEGetNextNumber(pFR :tpFaktorRec):tElem;forward;
procedure LoECreate(const Pl: tPrimList;var FA:tArrFR);
var
i : integer;
Begin
setlength(ArrInsert,100);
setlength(FA,Length(PL));
For i := 0 to High(PL) do
with FA[i] do
Begin
//automatic zeroing
IF i < High(PL) then
Begin
setlength(frElems,minElemCnt);
setlength(frInsElems,minElemCnt);
frNextFr := @FA[i+1]
end
else
Begin
setlength(frElems,2);
setlength(frInsElems,0);
frNextFr := NIL;
end;
frPotNo := i;
frLnPrime:= ln(PL[i]);
frMaxIdx := 0;
frAktIdx := 0;
frActPot := 1;
With frElems[0] do
Begin
n := frLnPrime;
Pots[i]:= 1;
end;
frActNumb := frElems[0];
end;
end;
procedure LoEFree(var FA:tArrFR);
var
i : integer;
Begin
For i := High(FA) downto Low(FA) do
setlength(FA[i].frElems,0);
setLength(FA,0);
end;
function LoEGetActElem(pFr:tpFaktorRec):tElem;
Begin
with pFr^ do
result := frElems[frAktIdx];
end;
function LoEGetActLstNumber(pFr:tpFaktorRec):tpNumber;
Begin
with pFr^ do
result := @frElems[frAktIdx].n;
end;
procedure LoEIncInsArr(var a:tElems);
Begin
setlength(a,Length(a)*8 div 5);
end;
procedure LoEIncreaseElems(pFr:tpFaktorRec;minCnt:NativeUint);
var
newLen: NativeUint;
Begin
with pFR^ do
begin
newLen := Length(frElems);
minCnt := minCnt+frMaxIdx;
repeat
newLen := newLen*8 div 5 +1;
until newLen > minCnt;
setlength(frElems,newLen);
end;
end;
procedure LoEInsertNext(pFr:tpFaktorRec;Limit:tnumber);
var
pNum : tpNumber;
pElems : tpElemArr;
cnt,i,u : NativeInt;
begin
with pFr^ do
Begin
//collect numbers of heigher primes
cnt := 0;
pNum := LoEGetActLstNumber(frNextFr);
while Limit > pNum^ do
Begin
frInsElems[cnt] := LoEGetNextNumber(frNextFr);
// writeln( 'Ins ',frInsElems[cnt].n:10:8,' < ',pNum^:10:8);
inc(cnt);
IF cnt > High(frInsElems) then
LoEIncInsArr(frInsElems);
pNum := LoEGetActLstNumber(frNextFr);
end;
if cnt = 0 then
EXIT;
i := frMaxIdx;
u := frMaxIdx+cnt+1;
IF u > High(frElems) then
LoEIncreaseElems(pFr,cnt);
IF frPotNo = 0 then
inc(ActIndex,u);
//Merge
pElems := @frElems[0];
dec(cnt);
dec(u);
frMaxIdx:= u;
repeat
// writeln(i:10,cnt:10,u:10); writeln( pElems^[i].n:10:8,' < ',frInsElems[cnt].n:10:8);
IF pElems^[i].n < frInsElems[cnt].n then
Begin
pElems^[u] := frInsElems[cnt];
dec(cnt);
end
else
Begin
pElems^[u] := pElems^[i];
dec(i);
end;
dec(u);
until (i<0) or (cnt<0);
IF i < 0 then
For u := cnt downto 0 do
pElems^[u] := frInsElems[u];
end;
end;
procedure LoEAppendNext(pFr:tpFaktorRec;Limit:tnumber);
var
pNum : tpNumber;
pElems : tpElemArr;
i : NativeInt;
begin
with pFr^ do
Begin
i := frMaxIdx+1;
pElems := @frElems[0];
pNum := LoEGetActLstNumber(frNextFr);
while Limit > pNum^ do
Begin
IF i > High(frElems) then
Begin
LoEIncreaseElems(pFr,10);
pElems := @frElems[0];
end;
pElems^[i] := LoEGetNextNumber(frNextFr);
inc(i);
pNum := LoEGetActLstNumber(frNextFr);
end;
inc(ActIndex,i);
frMaxIdx:= i-1;
end;
end;
procedure LoENextList(pFr:tpFaktorRec);
var
pElems : tpElemArr;
j : NativeUint;
begin
with pFR^ do
Begin
//increase Elements by factor
pElems := @frElems[0];
for j := frMaxIdx Downto 0 do
with pElems^[j] do
Begin
n := n+frLnPrime;
inc(Pots[frPotNo]);
end;
//x^j -> x^(j+1)
j := frActPot+1;
with frActNumb do
begin
n:= j*frLnPrime;
Pots[frPotNo]:= j;
end;
frActPot := j;
//if something follows
IF frNextFr <> NIL then
LoEInsertNext(pFR,frActNumb.n);
frAktIdx := 0;
end;
end;
function LoEGetNextNumber(pFR :tpFaktorRec):tElem;
Begin
with pFr^ do
Begin
result := frElems[frAktIdx];
inc(frAktIdx);
IF frMaxIdx < frAktIdx then
LoENextList(pFr);
end;
end;
procedure LoEGetNumber(pFR :tpFaktorRec;no:NativeUint);
Begin
dec(no);
while ActIndex < no do
LoENextList(pFR);
with pFr^ do
frAktIdx := (no-(ActIndex-frMaxIdx)-1);
end;
var
T1,T0: tDateTime;
FA: tArrFR;
i : integer;
Begin
PlInit(3);// 3 -> 2,3,5
LoECreate(Pl,FA);
i := 1;
i := 1;
T0 := time;
For i := 1 to 20 do
AusgabeElem(LoEGetNextNumber(@FA[0]));
LoEGetNumber(@FA[0],1691);
AusgabeElem(LoEGetNextNumber(@FA[0]));
LoEGetNumber(@FA[0],1000*1000);
AusgabeElem(LoEGetNextNumber(@FA[0]));
LoEGetNumber(@FA[0],100*1000*1000);
T1 := time;
AusgabeElem(LoEGetNextNumber(@FA[0]));
Writeln('Timed 100*1000*1000 in ',FormatDateTime('HH:NN:SS.ZZZ',T1-T0));
Writeln('Actual Index ',ActIndex );
AusgabeElem(LoEGetNextNumber(@FA[0]));
For i := 0 to High(FA) do
writeln(pL[i]:2,
' elemcount ',FA[i].frMaxIdx+1:7,' out of',length(FA[i].frElems):7);
LoEFree(FA);
End.

View file

@ -1,11 +1,15 @@
use List::Util 'min';
# If you want the large output, uncomment either the one line
# marked (1) or the two lines marked (2)
#use Math::GMP qw/:constant/; # (1) uncomment this to use Math::GMP
#use Math::GMPz; # (2) uncomment this plus later line for Math::GMPz
sub ham_gen {
my @s = ([1], [1], [1]);
my @m = (2, 3, 5);
#@m = map { Math::GMPz->new($_) } @m; # (2) uncomment for Math::GMPz
return sub {
# use bigint;
my $n = min($s[0][0], $s[1][0], $s[2][0]);
for (0 .. 2) {
shift @{$s[$_]} if $s[$_][0] == $n;
@ -23,3 +27,7 @@ print "...\n";
++$i, $h->() until $i == 1690;
print ++$i, "-th: ", $h->(), "\n";
# You will need to pick one of the bigint choices
#++$i, $h->() until $i == 999999;
#print ++$i, "-th: ", $h->(), "\n";

View file

@ -9,4 +9,6 @@ hamming=function(hamms,limit) {
}
hamms
}
sort(hamming(1,limit=2^31)[-1])
h <- sort(hamming(1,limit=2^31-1))
print(h[1:20])
print(h[length(h)])

View file

@ -1,14 +1,12 @@
require 'generator'
# the Hamming number generator
hamming = Generator.new do |generator|
hamming = Enumerator.new do |yielder|
next_ham = 1
queues = { 2 => [], 3 => [], 5 => [] }
loop do
generator.yield next_ham
queues = [[ 2, []], [3, []], [5, []] ]
[2,3,5].each {|m| queues[m] << (next_ham * m)}
next_ham = [2,3,5].collect {|m| queues[m][0]}.min
[2,3,5].each {|m| queues[m].shift if queues[m][0] == next_ham}
loop do
yielder << next_ham # or: yielder.yield(next_ham)
queues.each {|m,queue| queue << next_ham * m}
next_ham = queues.collect{|m,queue| queue.first}.min
queues.each {|m,queue| queue.shift if queue.first==next_ham}
end
end

View file

@ -1,12 +1,13 @@
hamming = Enumerator.new do |yielder|
next_ham = 1
queues = { 2 => [], 3 => [], 5 => [] }
start = Time.now
loop do
yielder << next_ham # or: yielder.yield(next_ham)
[2,3,5].each {|m| queues[m]<< (next_ham * m)}
next_ham = [2,3,5].collect {|m| queues[m][0]}.min
[2,3,5].each {|m| queues[m].shift if queues[m][0]== next_ham}
hamming.each.with_index(1) do |ham, idx|
case idx
when (1..20), 1691
puts "#{idx} => #{ham}"
when 1_000_000
puts "#{idx} => #{ham}"
break
end
end
puts "elapsed: #{Time.now - start} seconds"

View file

@ -0,0 +1,36 @@
typeset -a hamming=(1)
function nextHamming {
typeset -Sa q2 q3 q5
integer h=${hamming[${#hamming[@]}-1]}
q2+=( $(( h*2 )) )
q3+=( $(( h*3 )) )
q5+=( $(( h*5 )) )
h=$( min3 ${q2[0]} ${q3[0]} ${q5[0]} )
(( ${q2[0]} == h )) && ashift q2 >/dev/null
(( ${q3[0]} == h )) && ashift q3 >/dev/null
(( ${q5[0]} == h )) && ashift q5 >/dev/null
hamming+=($h)
}
function ashift {
nameref ary=$1
print -- "${ary[0]}"
ary=( "${ary[@]:1}" )
}
function min3 {
if (( $1 < $2 )); then
(( $1 < $3 )) && print -- $1 || print -- $3
else
(( $2 < $3 )) && print -- $2 || print -- $3
fi
}
for ((i=1; i<=20; i++)); do
nextHamming
printf "%d\t%d\n" $i ${hamming[i-1]}
done
for ((; i<=1690; i++)); do nextHamming; done
nextHamming
printf "%d\t%d\n" $i ${hamming[i-1]}
print "elapsed: $SECONDS"