Skip to content

Examples: Fix compiling issues and imports, closes #69 #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 22 additions & 39 deletions examples/elliptic.nim
Original file line number Diff line number Diff line change
@@ -1,59 +1,42 @@
# By Cyther606: http://forum.nimrod-lang.org/t/522
# By Cyther606: https://forum.nim-lang.org/t/522
# Adapted from: https://github.com/wobine/blackboard101/blob/master/EllipticCurvesPart4-PrivateKeyToPublicKey.py
import bigints, math, strutils
import bigints
import std/[math, strutils]

proc `^`(base: int; exp: int): BigInt =
let base = base.initBigInt
var exp = exp
result = 1.initBigInt
while exp > 0:
result *= base
dec(exp)
const
one = 1.initBigInt
two = 2.initBigInt
zero = 0.initBigInt

proc `^`(base: int; exp: int): BigInt = pow(base.initBigInt, exp)

# Specs of the Bitcoin's curve - secp256k1
let
Pcurve: BigInt = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
N = initBigInt("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
Acurve = 0.initBigInt
Bcurve = 7.initBigInt
primeCurve: BigInt = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - one
numberPoints = initBigInt("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
Acurve = zero # with Bcurve = 7, coefficients in the elliptic curve equation y^2 = x^3 + Acurve * x + Bcurve
Gx = initBigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240")
Gy = initBigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424")
Gpoint = (Gx, Gy)
privKey = initBigInt("A0DC65FFCA799873CBEA0AC274015B9526505DAAAED385155425F7337704883E", 16)

proc modinv(a: BigInt): BigInt =
var
lm = 1.initBigInt
hm = 0.initBigInt
lowm = a mod Pcurve
highm = Pcurve
while lowm > 1:
let
ratio = highm div lowm
nm = hm - (lm * ratio)
temp = highm - (lowm * ratio)
hm = nm
highm = temp
swap hm, lm
swap highm, lowm
result = lm mod Pcurve

proc ecAdd(a: tuple, b: tuple): (BigInt, BigInt) =
let
lamAdd = ((b[1] - a[1]) * modinv(b[0] - a[0])) mod Pcurve
x = (lamAdd * lamAdd - a[0] - b[0]) mod Pcurve
y = (lamAdd * (a[0] - x) - a[1]) mod Pcurve
lamAdd = ((b[1] - a[1]) * invmod((b[0] - a[0]), primeCurve)) mod primeCurve
x = (lamAdd * lamAdd - a[0] - b[0]) mod primeCurve
y = (lamAdd * (a[0] - x) - a[1]) mod primeCurve
result = (x, y)

proc ecDouble(a: tuple): (BigInt, BigInt) =
var
lam = ((3.initBigInt * a[0] * a[0] + Acurve) * modinv(2.initBigInt * a[1]))
x = ((lam * lam) - (2.initBigInt * a[0])) mod Pcurve
y = (lam * (a[0] - x) - a[1]) mod Pcurve
lam = lam mod Pcurve
lam = ((3.initBigInt * a[0] * a[0] + Acurve) * invmod(2.initBigInt * a[1], primeCurve))
x = ((lam * lam) - (2.initBigInt * a[0])) mod primeCurve
y = (lam * (a[0] - x) - a[1]) mod primeCurve
lam = lam mod primeCurve
result = (x, y)

proc ecMultiply(genPoint: tuple, scalarHex: BigInt): (BigInt, BigInt) =
if scalarHex == 0 or scalarHex >= N:
if scalarHex == zero or scalarHex >= numberPoints:
raise newException(Exception, "Invalid Scalar/Private Key")
var
scalarBin = scalarHex.toString(base = 2)
Expand All @@ -80,7 +63,7 @@ proc main() =
echo "04", publicKey[0].toString(base = 16).align(64, '0'), publicKey[1].toString(base = 16).align(64, '0')
echo ""
echo "the official Public Key - compressed:"
echo if publicKey[1] mod 2 == 1: "03" & publicKey[0].toString(base = 16).align(64, '0')
echo if publicKey[1] mod two == one: "03" & publicKey[0].toString(base = 16).align(64, '0')
else: "02" & publicKey[0].toString(base = 16).align(64, '0')

main()
1 change: 1 addition & 0 deletions examples/nim.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
path = "$projectPath/../src"
64 changes: 45 additions & 19 deletions examples/pidigits.nim
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# Translation of http://benchmarksgame.alioth.debian.org/u32/program.php?test=pidigits&lang=go&id=4
# This program prints as much pi digits as the user indicates
# with the first command line argument
# This program is an extension of the solution for https://rosettacode.org/wiki/Pi
# translated from former website http://benchmarksgame.alioth.debian.org

import os, strutils, unsigned, bigints
import std/[os, strutils, options]
import bigints

const
zero = 0.initBigInt
one = 1.initBigInt
two = 2.initBigInt
ten = 10.initBigInt
let
mask = (one shl 32) - one

var
tmp1, tmp2, tmp3, acc, k, dd = initBigInt(0)
den, num, k2 = initBigInt(1)
tmp1, tmp2, tmp3, acc, k = zero
den, num, k2 = one

proc extractDigit(): int32 =
if num > acc:
Expand All @@ -20,35 +32,49 @@ proc extractDigit(): int32 =
if tmp2 >= den:
return -1

result = int32(tmp1.limbs[0])
Copy link
Contributor Author

@dlesnoff dlesnoff Jan 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example can not be rewritten as long as we have not defined a way to convert a BigInt into an int, see issue #72. Type cast does not do the same thing, it interprets the BigInt as an int ! So the first limb is understood as the 2’s complement representation of another number. Thanks @konsumlamm for the explanation. Same for examples/rc_pidigits.nim

result = get(toSignedInt[int32](tmp1 and mask))

proc eliminateDigit(d: int32) =
acc -= den * d
acc *= 10
num *= 10
acc -= den * d.initBigInt
acc *= ten
num *= ten

proc nextTerm() =
k += 1
k2 += 2
k += one
k2 += two
tmp1 = num shl 1
acc += tmp1
acc *= k2
den *= k2
num *= k

let n = parseInt(paramStr(1))
proc findPiDigit(): int32 =
result = -1
while result < 0:
nextTerm()
result = extractDigit()

var i = 0
if paramCount() == 0:
# prints an infinite amount of pi digits
while true:
var d: int32 = findPiDigit()
stdout.write chr(ord('0') + d)
inc i
if i == 40:
echo ""
i = 0
eliminateDigit(d)

while i < n:
var d: int32 = -1
while d < 0:
nextTerm()
d = extractDigit()
let n = parseInt(paramStr(1))

if n <= 0:
quit("The number you entered is negative. Please specify a strictly positive number")

while i < n:
var d: int32 = findPiDigit()
stdout.write(chr(ord('0') + d))
inc(i)
if i mod 10 == 0:
if i mod 40 == 0:
echo "\t:", i
if i >= n:
break
eliminateDigit(d)
12 changes: 6 additions & 6 deletions examples/rc_combperm.nim
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Solution for http://rosettacode.org/wiki/Combinations_and_permutations
# Solution for https://rosettacode.org/wiki/Combinations_and_permutations
import bigints

proc perm(n, k: int32): BigInt =
result = initBigInt 1
result = initBigInt(1)
var
k = n - k
n = n
k = initBigInt(n - k)
n = initBigInt(n)
while n > k:
result *= n
dec n

proc comb(n, k: int32): BigInt =
result = perm(n, k)
var k = k
while k > 0:
var k = initBigInt(k)
while k > 0.initBigInt:
result = result div k
dec k

Expand Down
7 changes: 4 additions & 3 deletions examples/rc_godtheinteger.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Solution for http://rosettacode.org/wiki/9_billion_names_of_God_the_integer#Python
# Solution for https://rosettacode.org/wiki/9_billion_names_of_God_the_integer#Python
import bigints

var cache = @[@[1.initBigInt]]
Expand All @@ -14,14 +14,15 @@ proc cumu(n: int): seq[BigInt] =
proc row(n: int): seq[BigInt] =
let r = cumu n
result = @[]
for i in 0 .. <n:
for i in 0 ..< n:
result.add r[i+1] - r[i]

echo "rows:"
for x in 1..10:
echo row x

echo "sums:"
for x in [23, 123, 1234, 12345]:
# for 12345 this implementation is too slow, for a faster implementation see rc_godtheinteger2.nim
for x in [23, 123, 1234]:
let c = cumu(x)
echo x, " ", c[c.high]
2 changes: 1 addition & 1 deletion examples/rc_godtheinteger2.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Solution for http://rosettacode.org/wiki/9_billion_names_of_God_the_integer#Python
# Solution for https://rosettacode.org/wiki/9_billion_names_of_God_the_integer#Python
import bigints

var p = @[1.initBigInt]
Expand Down
22 changes: 13 additions & 9 deletions examples/rc_hammingnumbers.nim
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
# Translation of http://rosettacode.org/wiki/Hamming_numbers#Another_implementation_of_same_approach
# Translation of https://rosettacode.org/wiki/Hamming_numbers#Another_implementation_of_same_approach
import bigints

import bigints, math
const
two = initBigInt(2)
three = initBigInt(3)
five = initBigInt(5)

proc hamming(limit: int): BigInt =
var
h = newSeq[BigInt](limit)
x2 = initBigInt(2)
x3 = initBigInt(3)
x5 = initBigInt(5)
x2 = two
x3 = three
x5 = five
i, j, k = 0
for i in 0..h.high: h[i] = initBigInt(1)

for n in 1 .. < limit:
for n in 1 ..< limit:
h[n] = min([x2, x3, x5])
if x2 == h[n]:
inc i
x2 = h[i] * 2
x2 = h[i] * two
if x3 == h[n]:
inc j
x3 = h[j] * 3
x3 = h[j] * three
if x5 == h[n]:
inc k
x5 = h[k] * 5
x5 = h[k] * five

result = h[h.high]

Expand Down
4 changes: 3 additions & 1 deletion examples/rc_integersequence.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# This example includes an infinite loop that has to be interrupted by Ctrl+C
import bigints

const one = 1.initBigInt
var i = 0.initBigInt
while true:
i += 1
i += one
echo i
55 changes: 33 additions & 22 deletions examples/rc_leftfactorials.nim
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import iterutils, bigints
import bigints

proc lfact: iterator: BigInt =
result = iterator: BigInt =
yield 0.initBigInt
var
fact = 1.initBigInt
sum = 0.initBigInt
n = 1.initBigInt
while true:
sum += fact
fact *= n
n += 1
yield sum
const
one = 1.initBigInt
zero = 0.initBigInt

echo "first 11:"
for i in lfact().slice(last = 10):
echo " ", i
iterator lfact: BigInt =
yield zero
var
fact = one
sum = zero
n = one
while true:
sum += fact
fact *= n
n += one
yield sum

echo "20 through 110 (inclusive) by tens:"
for i in lfact().slice(20, 110, 10):
echo " ", i
var i = 0
for n in lfact():
if i == 0:
echo "first 11:"
if i == 20:
echo "20 through 110 (inclusive) by tens:"
if i == 1000:
echo "Digits in 1,000 through 10,000 (inclusive) by thousands:"

if i <= 10:
echo i, ": ", n
elif i <= 110 and i mod 10 == 0:
echo i, ": ", n
elif i >= 1000 and i <= 10_000 and i mod 1000 == 0:
echo i, ": ", ($n).len
elif i > 10_000:
break
inc i

echo "Digits in 1,000 through 10,000 (inclusive) by thousands:"
for i in lfact().slice(1_000, 10_000, 1_000):
echo " ", ($i).len
21 changes: 13 additions & 8 deletions examples/rc_paraffins.nim
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
# Solution for http://rosettacode.org/wiki/Paraffins
# Solution for https://rosettacode.org/wiki/Paraffins
import bigints

const
nMax: int32 = 250
nBranches: int32 = 4

const
one = 1.initBigInt
zero = 0.initBigInt

var rooted, unrooted: array[nMax + 1, BigInt]
rooted[0..1] = [1.initBigInt, 1.initBigInt]
unrooted[0..1] = [1.initBigInt, 1.initBigInt]
rooted[0..1] = [one, one]
unrooted[0..1] = [one, one]
for i in 2 .. nMax:
rooted[i] = 0.initBigInt
unrooted[i] = 0.initBigInt
rooted[i] = zero
unrooted[i] = zero

proc choose(m: BigInt, k: int32): BigInt =
result = m
if k == 1: return
for i in 1 .. < k:
result = result * (m + i) div (i + 1)
for i in 1 ..< k:
result = result * (m + i.initBigInt) div (i + 1).initBigInt

proc tree(br, n, l, sum: int32, cnt: BigInt) =
var s: int32 = 0
Expand All @@ -33,8 +37,9 @@ proc tree(br, n, l, sum: int32, cnt: BigInt) =
tree b, m, l, s, c

proc bicenter(s: int32) =
var s = s
if (s and 1) == 0:
unrooted[s] += rooted[s div 2] * (rooted[s div 2] + 1) div 2
unrooted[s] += rooted[s div 2] * (rooted[s div 2] + 1.initBigInt) div 2.initBigInt

for n in 1 .. nMax:
tree 0, n, n, 1, 1.initBigInt
Expand Down
Loading