Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
35
Task/Hamming-numbers/Nim/hamming-numbers-1.nim
Normal file
35
Task/Hamming-numbers/Nim/hamming-numbers-1.nim
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import bigints
|
||||
|
||||
proc min(a: varargs[BigInt]): BigInt =
|
||||
result = a[0]
|
||||
for i in 1..a.high:
|
||||
if a[i] < result: result = a[i]
|
||||
|
||||
proc hamming(limit: int): BigInt =
|
||||
var
|
||||
h = newSeq[BigInt](limit)
|
||||
x2 = initBigInt(2)
|
||||
x3 = initBigInt(3)
|
||||
x5 = initBigInt(5)
|
||||
i, j, k = 0
|
||||
for i in 0..h.high: h[i] = initBigInt(1)
|
||||
|
||||
for n in 1 ..< limit:
|
||||
h[n] = min(x2, x3, x5)
|
||||
if x2 == h[n]:
|
||||
inc i
|
||||
x2 = h[i] * 2
|
||||
if x3 == h[n]:
|
||||
inc j
|
||||
x3 = h[j] * 3
|
||||
if x5 == h[n]:
|
||||
inc k
|
||||
x5 = h[k] * 5
|
||||
|
||||
result = h[h.high]
|
||||
|
||||
for i in 1 .. 20:
|
||||
stdout.write hamming(i), " "
|
||||
echo ""
|
||||
echo hamming(1691)
|
||||
echo hamming(1_000_000)
|
||||
39
Task/Hamming-numbers/Nim/hamming-numbers-2.nim
Normal file
39
Task/Hamming-numbers/Nim/hamming-numbers-2.nim
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import bigints, times
|
||||
|
||||
proc hamming(limit: int): BigInt =
|
||||
doAssert limit > 0
|
||||
var
|
||||
h = newSeq[BigInt](limit)
|
||||
x2 = initBigInt(2)
|
||||
x3 = initBigInt(3)
|
||||
x5 = initBigInt(5)
|
||||
i, j, k = 0
|
||||
h[0] = initBigInt(1)
|
||||
|
||||
# BigInt comparisons are expensive, reduce them...
|
||||
proc min3(x, y, z: BigInt): (int, BigInt) =
|
||||
let (cs, r1) = if y == z: (6, y)
|
||||
elif y < z: (2, y) else: (4, z)
|
||||
if x == r1: (cs or 1, x)
|
||||
elif x < r1: (1, x) else: (cs, r1)
|
||||
|
||||
for n in 1 ..< limit:
|
||||
let (cs, e1) = min3(x2, x3, x5)
|
||||
h[n] = e1
|
||||
if (cs and 1) != 0: i += 1; x2 = h[i] * 2
|
||||
if (cs and 2) != 0: j += 1; x3 = h[j] * 3
|
||||
if (cs and 4) != 0: k += 1; x5 = h[k] * 5
|
||||
|
||||
h[h.high]
|
||||
|
||||
for i in 1 .. 20:
|
||||
stdout.write hamming(i), " "
|
||||
echo ""
|
||||
echo hamming(1691)
|
||||
|
||||
let strt = epochTime()
|
||||
let rslt = hamming(1_000_000)
|
||||
let stop = epochTime()
|
||||
|
||||
echo rslt
|
||||
echo "This last took ", (stop - strt)*1000, " milliseconds."
|
||||
64
Task/Hamming-numbers/Nim/hamming-numbers-3.nim
Normal file
64
Task/Hamming-numbers/Nim/hamming-numbers-3.nim
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import bigints, times
|
||||
|
||||
iterator func_hamming() : BigInt =
|
||||
type Thunk[T] = proc(): T {.closure.}
|
||||
type Lazy[T] = ref object of RootObj # tuple[val: T, thnk: Thunk[T]]
|
||||
val: T
|
||||
thnk: Thunk[T]
|
||||
proc force[T](me: var Lazy[T]): T = # not thread-safe; needs lock on thunk
|
||||
if me.thnk != nil: me.val = me.thnk(); me.thnk = nil
|
||||
me.val
|
||||
type LazyList[T] = ref object of RootObj # tuple[hd: T, tl: Lazy[LazyList[T]]]
|
||||
hd: T
|
||||
tl: Lazy[LazyList[T]]
|
||||
type Mytype = LazyList[BigInt]
|
||||
proc merge(x, y: Mytype): Mytype =
|
||||
let xh = x.hd; let yh = y.hd
|
||||
if xh < yh:
|
||||
let mthnk = proc(): Mytype = merge x.tl.force, y
|
||||
let mlzy = Lazy[Mytype](thnk: mthnk)
|
||||
Mytype(hd: xh, tl: mlzy)
|
||||
else:
|
||||
let mthnk = proc(): Mytype = merge x, y.tl.force
|
||||
let mlzy = Lazy[Mytype](thnk: mthnk)
|
||||
Mytype(hd: yh, tl: mlzy)
|
||||
proc smult(m: int32, s: Mytype): Mytype =
|
||||
proc smults(ss: Mytype): Mytype =
|
||||
let mthnk = proc(): Mytype = ss.tl.force.smults
|
||||
let mlzy = Lazy[Mytype](thnk: mthnk)
|
||||
Mytype(hd: ss.hd * m, tl: mlzy)
|
||||
s.smults
|
||||
proc u(s: Mytype, n: int32): Mytype =
|
||||
var r: Mytype
|
||||
let mthnk = proc(): Mytype = r
|
||||
let mlzy = Lazy[Mytype](thnk: mthnk)
|
||||
let frst = Mytype(hd: initBigInt 1, tl: mlzy)
|
||||
if s == nil: r = smult(n, frst) else: r = merge(s, smult(n, frst))
|
||||
r
|
||||
var hmg: Mytype = nil
|
||||
for p in [5i32, 3i32, 2i32]: hmg = u(hmg, p)
|
||||
yield initBigInt 1
|
||||
while true: # loop almost forever
|
||||
yield initBigInt hmg.hd
|
||||
hmg = hmg.tl.force
|
||||
|
||||
var cnt = 1
|
||||
for h in func_hamming():
|
||||
if cnt > 20: break
|
||||
write stdout, h, " "; cnt += 1
|
||||
echo ""
|
||||
cnt = 1
|
||||
for h in func_hamming():
|
||||
if cnt < 1691: cnt += 1; continue
|
||||
else: echo h; break
|
||||
|
||||
let strt = epochTime()
|
||||
var rslt: BigInt
|
||||
cnt = 1
|
||||
for h in func_hamming():
|
||||
if cnt < 1000000: cnt += 1; continue
|
||||
else: rslt = h; break
|
||||
let stop = epochTime()
|
||||
|
||||
echo rslt
|
||||
echo "This last took ", (stop - strt)*1000, " milliseconds."
|
||||
82
Task/Hamming-numbers/Nim/hamming-numbers-4.nim
Normal file
82
Task/Hamming-numbers/Nim/hamming-numbers-4.nim
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
from times import inMilliseconds
|
||||
import std/monotimes, bigints
|
||||
from math import log2
|
||||
|
||||
type TriVal = (uint32, uint32, uint32)
|
||||
type LogRep = (float64, TriVal)
|
||||
type LogRepf = proc(x: LogRep): LogRep
|
||||
const one: LogRep = (0.0f64, (0'u32, 0'u32, 0'u32))
|
||||
proc `<`(me: LogRep, othr: LogRep): bool = me[0] < othr[0]
|
||||
|
||||
proc convertTrival2BigInt(tv: TriVal): BigInt =
|
||||
proc xpnd(bs: uint, v: uint32): BigInt =
|
||||
result = initBigInt 1;
|
||||
var bsm = initBigInt bs;
|
||||
var vm = v.uint
|
||||
while vm > 0:
|
||||
if (vm and 1) != 0: result *= bsm
|
||||
bsm = bsm * bsm # bsm *= bsm crashes.
|
||||
vm = vm shr 1
|
||||
result = (2.xpnd tv[0]) * (3.xpnd tv[1]) * (5.xpnd tv[2])
|
||||
|
||||
const lb2 = 1.0'f64
|
||||
const lb3 = 3.0'f64.log2
|
||||
const lb5 = 5.0'f64.log2
|
||||
|
||||
proc mul2(me: LogRep): LogRep =
|
||||
let (lr, tpl) = me; let (x2, x3, x5) = tpl
|
||||
(lr + lb2, (x2 + 1, x3, x5))
|
||||
|
||||
proc mul3(me: LogRep): LogRep =
|
||||
let (lr, tpl) = me; let (x2, x3, x5) = tpl
|
||||
(lr + lb3, (x2, x3 + 1, x5))
|
||||
|
||||
proc mul5(me: LogRep): LogRep =
|
||||
let (lr, tpl) = me; let (x2, x3, x5) = tpl
|
||||
(lr + lb5, (x2, x3, x5 + 1))
|
||||
|
||||
type
|
||||
LazyList = ref object
|
||||
hd: LogRep
|
||||
tlf: proc(): LazyList {.closure.}
|
||||
tl: LazyList
|
||||
|
||||
proc rest(ll: LazyList): LazyList = # not thread-safe; needs lock on thunk
|
||||
if ll.tlf != nil: ll.tl = ll.tlf(); ll.tlf = nil
|
||||
ll.tl
|
||||
|
||||
iterator log_func_hammings(until: int): TriVal =
|
||||
proc merge(x, y: LazyList): LazyList =
|
||||
let xh = x.hd
|
||||
let yh = y.hd
|
||||
if xh < yh: LazyList(hd: xh, tlf: proc(): auto = merge x.rest, y)
|
||||
else: LazyList(hd: yh, tlf: proc(): auto = merge x, y.rest)
|
||||
proc smult(mltf: LogRepf; s: LazyList): LazyList =
|
||||
proc smults(ss: LazyList): LazyList =
|
||||
LazyList(hd: ss.hd.mltf, tlf: proc(): auto = ss.rest.smults)
|
||||
s.smults
|
||||
proc unnsm(s: LazyList, mltf: LogRepf): LazyList =
|
||||
var r: LazyList = nil
|
||||
let frst = LazyList(hd: one, tlf: proc(): LazyList = r)
|
||||
r = if s == nil: smult mltf, frst else: s.merge smult(mltf, frst)
|
||||
r
|
||||
yield one[1]
|
||||
var hmpll: LazyList = ((nil.unnsm mul5).unnsm mul3).unnsm mul2
|
||||
for _ in 2 .. until:
|
||||
yield hmpll.hd[1]; hmpll = hmpll.rest # almost forever
|
||||
|
||||
proc main =
|
||||
stdout.write "The first 20 hammings are: "
|
||||
for h in log_func_hammings(20): stdout.write h.convertTrival2BigInt, " "
|
||||
|
||||
var lsth: TriVal
|
||||
for h in log_func_hammings(1691): lsth = h
|
||||
echo "\r\nThe 1691st Hamming number is: ", lsth.convertTriVal2BigInt
|
||||
|
||||
let strt = getMonotime()
|
||||
for h in log_func_hammings(1000000): lsth = h
|
||||
let elpsd = (getMonotime() - strt).inMilliseconds
|
||||
echo "The millionth Hamming number is: ", lsth.convertTriVal2BigInt
|
||||
echo "This last took ", elpsd, " milliseconds."
|
||||
|
||||
main()
|
||||
58
Task/Hamming-numbers/Nim/hamming-numbers-5.nim
Normal file
58
Task/Hamming-numbers/Nim/hamming-numbers-5.nim
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import bigints, times
|
||||
|
||||
iterator nodups_hamming(): BigInt =
|
||||
var
|
||||
m = newSeq[BigInt](1) # give it two values so doubling size works
|
||||
h = newSeq[BigInt](1) # reasonably size
|
||||
x5 = initBigInt 5
|
||||
mrg = initBigInt 3
|
||||
x53 = initBigInt 9 # already advanced one step
|
||||
x532 = initBigInt 2
|
||||
ih, jm, i, j = 0
|
||||
|
||||
yield initBigInt 1 # trivial case of 1
|
||||
while true:
|
||||
let cph = h.len # move in-place to avoid allocation
|
||||
if i >= cph div 2: # move in-place to avoid allocation
|
||||
var s = i; var d = 0
|
||||
while s < ih: shallowCopy(h[d], h[s]); s += 1; d += 1
|
||||
ih -= i; i = 0
|
||||
if ih >= cph: h.setLen(2 * cph)
|
||||
if x532 < mrg: h[ih] = x532; x532 = h[i] * 2; i += 1
|
||||
else:
|
||||
h[ih] = mrg
|
||||
let cpm = m.len
|
||||
if j >= cpm div 2: # move in-place to avoid allocation
|
||||
var s = j; var d = 0
|
||||
while s < jm: shallowCopy(m[d], m[s]); s += 1; d += 1
|
||||
jm -= j; j = 0
|
||||
if jm >= cpm: m.setLen(2 * cpm)
|
||||
if x53 < x5: mrg = x53; x53 = m[j] * 3; j += 1
|
||||
else: mrg = x5; x5 = x5 * 5
|
||||
m[jm] = mrg
|
||||
jm += 1
|
||||
ih += 1
|
||||
|
||||
yield h[ih - 1]
|
||||
|
||||
|
||||
var cnt = 1
|
||||
for h in nodups_hamming():
|
||||
if cnt > 20: break
|
||||
write stdout, h, " "; cnt += 1
|
||||
echo ""
|
||||
cnt = 1
|
||||
for h in nodups_hamming():
|
||||
if cnt < 1691: cnt += 1; continue
|
||||
else: echo h; break
|
||||
|
||||
let strt = epochTime()
|
||||
var rslt: BigInt
|
||||
cnt = 1
|
||||
for h in nodups_hamming():
|
||||
if cnt < 1000000: cnt += 1; continue
|
||||
else: rslt = h; break
|
||||
let stop = epochTime()
|
||||
|
||||
echo rslt
|
||||
echo "This last took ", (stop - strt)*1000, " milliseconds."
|
||||
95
Task/Hamming-numbers/Nim/hamming-numbers-6.nim
Normal file
95
Task/Hamming-numbers/Nim/hamming-numbers-6.nim
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# HammingsLogImp.nim
|
||||
# compile with: nim c -d:danger -t:-march=native -d:LTO --gc:arc HammingsLogImp
|
||||
|
||||
import bigints, std/math
|
||||
from std/times import inMicroseconds
|
||||
from std/monotimes import getMonoTime, `-`
|
||||
|
||||
type LogRep = (float64, uint32, uint32, uint32)
|
||||
|
||||
let one: LogRep = (0.0, 0'u32, 0'u32, 0'u32)
|
||||
|
||||
let lb2 = 1.0'f64; let lb3 = 3.0.log2; let lb5 = 5.0.log2
|
||||
proc mul2(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb2, me[1] + 1, me[2], me[3])
|
||||
proc mul3(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb3, me[1], me[2] + 1, me[3])
|
||||
proc mul5(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb5, me[1], me[2], me[3] + 1)
|
||||
|
||||
proc lr2BigInt(lr: Logrep): BigInt =
|
||||
proc xpnd(bs: uint, v: uint32): BigInt =
|
||||
result = initBigInt 1
|
||||
var bsm = initBigInt bs;
|
||||
var vm = v.uint
|
||||
while vm > 0:
|
||||
if (vm and 1) != 0: result *= bsm
|
||||
bsm *= bsm; vm = vm shr 1
|
||||
xpnd(2, lr[1]) * xpnd(3, lr[2]) * xpnd(5, lr[3])
|
||||
|
||||
iterator hammingsLogImp(): LogRep =
|
||||
var
|
||||
s2 = newSeq[Logrep](1024) # give it size one so doubling size works
|
||||
s3 = newSeq[Logrep](1024) # reasonably sized
|
||||
s5 = one.mul5 # initBigInt 5
|
||||
mrg = one.mul3 # initBigInt 3
|
||||
s2hdi, s2tli, s3hdi, s3tli = 0
|
||||
|
||||
yield one
|
||||
s2[0] = one.mul2; s3[0] = one.mul3
|
||||
while true:
|
||||
s2tli += 1
|
||||
if s2hdi + s2hdi >= s2tli: # move in-place to avoid allocation
|
||||
copyMem(addr(s2[0]), addr(s2[s2hdi]), sizeof(LogRep) * (s2tli - s2hdi))
|
||||
s2tli -= s2hdi; s2hdi = 0
|
||||
let cps2 = s2.len # move in-place to avoid allocation
|
||||
if s2tli >= cps2: s2.setLen(cps2 + cps2)
|
||||
var rsltp = addr(s2[s2hdi])
|
||||
if rsltp[][0] < mrg[0]: s2[s2tli] = rsltp[].mul2; s2hdi += 1; yield rsltp[]
|
||||
else:
|
||||
s3tli += 1
|
||||
if s3hdi + s3hdi >= s3tli: # move in-place to avoid allocation
|
||||
copyMem(addr(s3[0]), addr(s3[s3hdi]), sizeof(LogRep) * (s3tli - s3hdi))
|
||||
s3tli -= s3hdi; s3hdi = 0
|
||||
let cps3 = s3.len
|
||||
if s3tli >= cps3: s3.setLen(cps3 + cps3)
|
||||
s2[s2tli] = mrg.mul2; s3[s3tli] = mrg.mul3; s3hdi += 1
|
||||
let arsltp = addr(s3[s3hdi])
|
||||
let rslt = mrg
|
||||
if arsltp[][0] < s5[0]: mrg = arsltp[]
|
||||
else: mrg = s5; s5 = s5.mul5; s3hdi -= 1
|
||||
yield rslt
|
||||
|
||||
var cnt = 0
|
||||
for h in hammingsLogImp():
|
||||
write stdout, h.lr2BigInt, " "; cnt += 1
|
||||
if cnt >= 20: break
|
||||
echo ""
|
||||
cnt = 0
|
||||
for h in hammingsLogImp():
|
||||
cnt += 1
|
||||
if cnt >= 1691: echo h.lr2BigInt; break
|
||||
|
||||
let strt = getMonoTime()
|
||||
var rslt: LogRep
|
||||
cnt = 0
|
||||
for h in hammingsLogImp():
|
||||
cnt += 1
|
||||
if cnt >= 1_000_000: rslt = h; break # """
|
||||
let elpsd = (getMonoTime() - strt).inMicroseconds
|
||||
|
||||
let (_, x2, x3, x5) = rslt
|
||||
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
|
||||
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
|
||||
x5.float64 * 5.0f64.log2) * 2.0f64.log10
|
||||
let (whl, frac) = lgrslt.splitDecimal
|
||||
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
|
||||
let brslt = rslt.lr2BigInt()
|
||||
let s = brslt.to_string
|
||||
let ls = s.len
|
||||
echo "Number of digits: ", ls
|
||||
if ls <= 2000:
|
||||
for i in countup(0, ls - 1, 100):
|
||||
if i + 100 < ls: echo s[i .. i + 99]
|
||||
else: echo s[i .. ls - 1]
|
||||
echo "This last took ", elpsd, " microseconds."
|
||||
96
Task/Hamming-numbers/Nim/hamming-numbers-7.nim
Normal file
96
Task/Hamming-numbers/Nim/hamming-numbers-7.nim
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# HammingsLogDQ.nim
|
||||
# compile with: nim c -d:danger -t:-march=native -d:LTO --gc:arc HammingsImpLogQ
|
||||
|
||||
import bigints, std/math
|
||||
from std/times import inMicroseconds
|
||||
from std/monotimes import getMonoTime, `-`
|
||||
|
||||
type LogRep = (float64, uint32, uint32, uint32)
|
||||
|
||||
let one: LogRep = (0.0, 0'u32, 0'u32, 0'u32)
|
||||
|
||||
let lb2 = 1.0'f64; let lb3 = 3.0.log2; let lb5 = 5.0.log2
|
||||
proc mul2(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb2, me[1] + 1, me[2], me[3])
|
||||
proc mul3(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb3, me[1], me[2] + 1, me[3])
|
||||
proc mul5(me: Logrep): Logrep {.inline.} =
|
||||
(me[0] + lb5, me[1], me[2], me[3] + 1)
|
||||
|
||||
proc lr2BigInt(lr: Logrep): BigInt =
|
||||
proc xpnd(bs: uint, v: uint32): BigInt =
|
||||
result = initBigInt 1
|
||||
var bsm = initBigInt bs;
|
||||
var vm = v.uint
|
||||
while vm > 0:
|
||||
if (vm and 1) != 0: result *= bsm
|
||||
bsm *= bsm; vm = vm shr 1
|
||||
xpnd(2, lr[1]) * xpnd(3, lr[2]) * xpnd(5, lr[3])
|
||||
|
||||
proc `$`(lr: LogRep): string {.inline.} = $lr2BigInt(lr)
|
||||
|
||||
iterator hammingsLogQ(): LogRep =
|
||||
var s2msk, s3msk = 1024
|
||||
var s2 = newSeq[LogRep] s2msk; var s3 = newSeq[LogRep] s3msk
|
||||
s2msk -= 1; s3msk -= 1; s2[0] = one; var s2nxti = 1
|
||||
var s2hdi, s3hdi, s3nxti = 0
|
||||
var s5 = one.mul5; var mrg = one.mul3
|
||||
while true:
|
||||
let s2hdp = addr(s2[s2hdi])
|
||||
if s2hdp[][0] < mrg[0]:
|
||||
s2[s2nxti] = s2hdp[].mul2; s2hdi += 1; s2hdi = s2hdi and s2msk
|
||||
yield s2hdp[]
|
||||
else:
|
||||
s2[s2nxti] = mrg.mul2; s3[s3nxti] = mrg.mul3; yield mrg
|
||||
let s3hdp = addr(s3[s3hdi])
|
||||
if s3hdp[0] < s5[0]:
|
||||
mrg = s3hdp[]; s3hdi += 1; s3hdi = s3hdi and s3msk
|
||||
else: mrg = s5; s5 = s5.mul5
|
||||
s3nxti += 1; s3nxti = s3nxti and s3msk
|
||||
if s3nxti == s3hdi: # buffer full - expand...
|
||||
let sz = s3msk + 1; s3msk = sz + sz; s3.setLen(s3msk); s3msk -= 1
|
||||
if s3hdi == 0: s3nxti = sz
|
||||
else: # put extra space between next and head...
|
||||
copyMem(addr(s3[s3hdi + sz]), addr(s3[s3hdi]),
|
||||
sizeof(LogRep) * (sz - s3hdi)); s3hdi += sz
|
||||
s2nxti += 1; s2nxti = s2nxti and s2msk
|
||||
if s2nxti == s2hdi: # buffer full - expand...
|
||||
let sz = s2msk + 1; s2msk = sz + sz; s2.setLen s2msk; s2msk -= 1
|
||||
if s2hdi == 0: s2nxti = sz # copy all in a single block...
|
||||
else: # make extra space between next and head...
|
||||
copyMem(addr(s2[s2hdi + sz]), addr(s2[s2hdi]),
|
||||
sizeof(LogRep) * (sz - s2hdi)); s2hdi += sz
|
||||
|
||||
# testing it...
|
||||
var cnt = 0
|
||||
for h in hammingsLogQ():
|
||||
write stdout, h, " "; cnt += 1
|
||||
if cnt >= 20: break
|
||||
echo ""
|
||||
cnt = 0
|
||||
for h in hammingsLogQ():
|
||||
cnt += 1
|
||||
if cnt >= 1691: echo h; break
|
||||
|
||||
let strt = getMonoTime()
|
||||
var rslt: LogRep
|
||||
cnt = 0
|
||||
for h in hammingsLogQ():
|
||||
cnt += 1
|
||||
if cnt >= 1_000_000: rslt = h; break # """
|
||||
let elpsd = (getMonoTime() - strt).inMicroseconds
|
||||
|
||||
let (_, x2, x3, x5) = rslt
|
||||
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
|
||||
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
|
||||
x5.float64 * 5.0f64.log2) * 2.0f64.log10
|
||||
let (whl, frac) = lgrslt.splitDecimal
|
||||
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
|
||||
let s = $rslt
|
||||
let ls = s.len
|
||||
echo "Number of digits: ", ls
|
||||
if ls <= 2000:
|
||||
for i in countup(0, ls - 1, 100):
|
||||
if i + 100 < ls: echo s[i .. i + 99]
|
||||
else: echo s[i .. ls - 1]
|
||||
echo "This last took ", elpsd, " microseconds."
|
||||
72
Task/Hamming-numbers/Nim/hamming-numbers-8.nim
Normal file
72
Task/Hamming-numbers/Nim/hamming-numbers-8.nim
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import bigints, math, algorithm, times
|
||||
|
||||
type TriVal = (uint32, uint32, uint32)
|
||||
|
||||
proc convertTrival2BigInt(tv: TriVal): BigInt =
|
||||
|
||||
proc xpnd(bs: uint, v: uint32): BigInt =
|
||||
result = initBigInt 1
|
||||
var bsm = initBigInt bs
|
||||
var vm = v.uint
|
||||
while vm > 0:
|
||||
if (vm and 1) != 0: result *= bsm
|
||||
bsm = bsm * bsm # bsm *= bsm causes a crash.
|
||||
vm = vm shr 1
|
||||
|
||||
result = (2.xpnd tv[0]) * (3.xpnd tv[1]) * (5.xpnd tv[2])
|
||||
|
||||
proc nth_hamming(n: uint64): TriVal =
|
||||
doAssert n > 0u64
|
||||
if n < 2: return (0'u32, 0'u32, 0'u32) # trivial case for 1
|
||||
|
||||
type LogRep = (float64, uint32, uint32, uint32)
|
||||
|
||||
let lb3 = 3.0'f64.log2; let lb5 = 5.0'f64.log2; let fctr = 6.0'f64*lb3*lb5
|
||||
let
|
||||
crctn = 30.0'f64.sqrt().log2 # log base 2 of sqrt 30
|
||||
lgest = (fctr * n.float64).pow(1.0'f64/3.0'f64) - crctn # from WP formula
|
||||
frctn = if n < 1000000000: 0.509'f64 else: 0.105'f64
|
||||
lghi = (fctr * (n.float64 + frctn * lgest)).pow(1.0'f64/3.0'f64) - crctn
|
||||
lglo = 2.0'f64 * lgest - lghi # and a lower limit of the upper "band"
|
||||
var count = 0'u64 # need to use extended precision, might go over
|
||||
var bnd = newSeq[LogRep](1) # give itone value so doubling size works
|
||||
let klmt = (lghi / lb5).uint32 + 1
|
||||
for k in 0 ..< klmt: # i, j, k values can be just u32 values
|
||||
let p = k.float64 * lb5; let jlmt = ((lghi - p) / lb3).uint32 + 1
|
||||
for j in 0 ..< jlmt:
|
||||
let q = p + j.float64 * lb3
|
||||
let ir = lghi - q; let lg = q + ir.floor # current log value (estimated)
|
||||
count += ir.uint64 + 1;
|
||||
if lg >= lglo: bnd.add((lg, ir.uint32, j, k))
|
||||
if n > count: raise newException(Exception, "nth_hamming: band high estimate is too low!")
|
||||
let ndx = (count - n).int
|
||||
if ndx >= bnd.len: raise newException(Exception, "nth_hamming: band low estimate is too high!")
|
||||
bnd.sort((proc (a, b: LogRep): int = a[0].cmp b[0]), SortOrder.Descending)
|
||||
|
||||
let rslt = bnd[ndx]; (rslt[1], rslt[2], rslt[3])
|
||||
|
||||
for i in 1 .. 20:
|
||||
write stdout, nth_hamming(i.uint64).convertTrival2BigInt, " "
|
||||
echo ""
|
||||
echo nth_hamming(1691).convertTrival2BigInt
|
||||
|
||||
let strt = epochTime()
|
||||
let rslt = nth_hamming(1_000_000'u64)
|
||||
let stop = epochTime()
|
||||
|
||||
let (x2, x3, x5) = rslt
|
||||
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
|
||||
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
|
||||
x5.float64 * 5.0f64.log2) * 2.0f64.log10
|
||||
let (whl, frac) = lgrslt.splitDecimal
|
||||
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
|
||||
let brslt = rslt.convertTrival2BigInt()
|
||||
let s = brslt.to_string
|
||||
let ls = s.len
|
||||
echo "Number of digits: ", ls
|
||||
if ls <= 2000:
|
||||
for i in countup(0, ls - 1, 100):
|
||||
if i + 100 < ls: echo s[i .. i + 99]
|
||||
else: echo s[i .. ls - 1]
|
||||
|
||||
echo "This last took ", (stop - strt) * 1000, " milliseconds."
|
||||
79
Task/Hamming-numbers/Nim/hamming-numbers-9.nim
Normal file
79
Task/Hamming-numbers/Nim/hamming-numbers-9.nim
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import bigints, math, algorithm, times
|
||||
|
||||
type TriVal = (uint32, uint32, uint32)
|
||||
|
||||
proc convertTrival2BigInt(tv: TriVal): BigInt =
|
||||
|
||||
proc xpnd(bs: uint, v: uint32): BigInt =
|
||||
result = initBigInt 1
|
||||
var bsm = initBigInt bs
|
||||
var vm = v.uint
|
||||
while vm > 0:
|
||||
if (vm and 1) != 0: result *= bsm
|
||||
bsm = bsm * bsm # bsm *= bsm causes a crash.
|
||||
vm = vm shr 1
|
||||
|
||||
result = (2.xpnd tv[0]) * (3.xpnd tv[1]) * (5.xpnd tv[2])
|
||||
|
||||
proc nth_hamming(n: uint64): TriVal =
|
||||
doAssert n > 0u64
|
||||
if n < 2: return (0'u32, 0'u32, 0'u32) # trivial case for 1
|
||||
|
||||
type LogRep = (BigInt, uint32, uint32, uint32)
|
||||
|
||||
let lb3 = 3.0'f64.log2; let lb5 = 5.0'f64.log2; let fctr = 6.0'f64*lb3*lb5
|
||||
let # manually produce the BigInt "limb's"!
|
||||
bglb2 = initBigInt @[0'u32, 0, 0, 16] # 1267650600228229401496703205376
|
||||
# 2009178665378409109047848542368
|
||||
bglb3 = initBigInt @[11608224'u32, 3177740794'u32, 1543611295, 25]
|
||||
# 2943393543170754072109742145491
|
||||
bglb5 = initBigInt @[1258143699'u32, 1189265298, 647893747, 37]
|
||||
crctn = 30.0'f64.sqrt().log2 # log base 2 of sqrt 30
|
||||
lgest = (fctr * n.float64).pow(1.0'f64/3.0'f64) - crctn # from WP formula
|
||||
frctn = if n < 1000000000: 0.509'f64 else: 0.105'f64
|
||||
lghi = (fctr * (n.float64 + frctn * lgest)).pow(1.0'f64/3.0'f64) - crctn
|
||||
lglo = 2.0'f64 * lgest - lghi # and a lower limit of the upper "band"
|
||||
var count = 0'u64 # need to use extended precision, might go over
|
||||
var bnd = newSeq[LogRep](1) # give it one value so doubling size works
|
||||
let klmt = (lghi / lb5).uint32 + 1
|
||||
for k in 0 ..< klmt: # i, j, k values can be just u32 values
|
||||
let p = k.float64 * lb5; let jlmt = ((lghi - p) / lb3).uint32 + 1
|
||||
for j in 0 ..< jlmt:
|
||||
let q = p + j.float64 * lb3
|
||||
let ir = lghi - q; let lg = q + ir.floor # current log value (estimated)
|
||||
count += ir.uint64 + 1;
|
||||
if lg >= lglo:
|
||||
let bglg = bglb2 * ir.int32 + bglb3 * j.int32 + bglb5 * k.int32
|
||||
bnd.add((bglg, ir.uint32, j, k))
|
||||
if n > count: raise newException(Exception, "nth_hamming: band high estimate is too low!")
|
||||
let ndx = (count - n).int
|
||||
if ndx >= bnd.len: raise newException(Exception, "nth_hamming: band low estimate is too high!")
|
||||
bnd.sort((proc (a, b: LogRep): int = (a[0].cmp b[0]).int), SortOrder.Descending)
|
||||
|
||||
let rslt = bnd[ndx]; (rslt[1], rslt[2], rslt[3])
|
||||
|
||||
for i in 1 .. 20:
|
||||
write stdout, nth_hamming(i.uint64).convertTrival2BigInt, " "
|
||||
echo ""
|
||||
echo nth_hamming(1691).convertTrival2BigInt
|
||||
|
||||
let strt = epochTime()
|
||||
let rslt = nth_hamming(1_000_000'u64)
|
||||
let stop = epochTime()
|
||||
|
||||
let (x2, x3, x5) = rslt
|
||||
writeLine stdout, "2^", x2, " + 3^", x3, " + 5^", x5
|
||||
let lgrslt = (x2.float64 + x3.float64 * 3.0f64.log2 +
|
||||
x5.float64 * 5.0f64.log2) * 2.0f64.log10
|
||||
let (whl, frac) = lgrslt.splitDecimal
|
||||
echo "Approximately: ", 10.0f64.pow(frac), "E+", whl.uint64
|
||||
let brslt = rslt.convertTrival2BigInt()
|
||||
let s = brslt.to_string
|
||||
let ls = s.len
|
||||
echo "Number of digits: ", ls
|
||||
if ls <= 2000:
|
||||
for i in countup(0, ls - 1, 100):
|
||||
if i + 100 < ls: echo s[i .. i + 99]
|
||||
else: echo s[i .. ls - 1]
|
||||
|
||||
echo "This last took ", (stop - strt) * 1000, " milliseconds."
|
||||
Loading…
Add table
Add a link
Reference in a new issue