GithubHelp home page GithubHelp logo

bigints's People

Contributors

ab95 avatar andreaferretti avatar araq avatar bung87 avatar def- avatar dependabot[bot] avatar dlesnoff avatar domosokrat avatar ehmry avatar konsumlamm avatar markspanbroek avatar markus-oberhumer avatar msmith491 avatar narimiran avatar pietroppeter avatar ringabout avatar rotu avatar solitudesf avatar vil02 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bigints's Issues

Design of internal functions taking out parameters (`addition`, `additionInt`, etc.)

The internal functions currently take a var BigInt argument as first parameter, which is used to store the result (essentially an out parameter). I suppose that is so that a buffer can be preallocated, however, that's never done afaict. In this light, it would be more ergonomic to just return a new BigInt (using the result variable).

Another possibility is instead of defining functions like func addition(a: var BigInt, b, c: BigInt) to do a = b + c, use func addition(a: var BigInt, b: BigInt) to do a += b. That would avoid copying the first argument for +=. a + b would then be implemented as result = a; result += b, but I'm not sure if that avoids a copy (I think it should, at least with ARC/ORC). (I'm just using addition as an example, the same applies to other operations).

If there is no flaw in my analysis, I'd prefer the last possibility, as I think it's the most efficient and ergonomic.

cc @narimiran @mratsim

Off by one error in division

Nim:
image

Wolfram Alpha:
image

Python:
image

Nim v0.13.0
Bigints downloaded earlier today, so also up to date

The calculation is 40!/(20!*20!)

Consider extracting the first limb into a separate field

Currently, BigInt is defined as follows:

type
  BigInt* = object
    limbs: seq[uint32]
    isNegative: bool

It has the invariant that limbs.len >= 1.

It might be worth it changing that to

type
  BigInt* = object
    limbs: seq[uint32]
    first: uint32
    isNegative: bool

This has several advantages:

  • The invariant is now always satisfied (the first limb always exists).
  • Small BigInts require no allocation & pointer indirection.
  • It would avoid special casing 0 (see #26).

Disadvantages:

  • A bit more special handling is needed.
  • The first limb not being next to the other limbs in memory may make a difference (but I doubt it would be noticable).

Negative BigInt

It seems that bigints, as implemented here, are unsigned. I tried to do

let x = -initBigInt(1)

but it does not compile. Implementing unary negation as

proc `-`*(a: BigInt): BigInt = initBigInt(0) - a

leads to SIGSEGV: Illegal storage access.

Is there any reason why BigInts are implemented as positive numbers?

roadmap for next versions of BigInts (>=0.6.0)

It has been almost a year since last release of BigInts. I would like to prioritize issues, and know which features are expected for the next release (next tag) of BigInt. There are no labels put on issues right now.

I noticed there is almost no information for new developer to know what the developers are currently working on. I fear we might be multiple people working on the same thing in the future.

Here I will manage a list, that presents some features in other multiprecision libraries that is not yet implemented here, and I will try to link the current issues to that list. Please add a comment if the list is not up-to-date or you want another feature to implement (in addition to a new issue concerning that feature). Could you tell me which one you expect to see in BigInts 0.6.0, in BigInts 0.7.0, or in BigInts 1.0.0 ?

  • Karatsuba multiplication (for 0.6.0 ?)
  • Other fast multiplication : Tom-Cook, Schönhage-Strassen, FFT (for 0.7.0 ?)
  • more string formatting #52 (for 0.6.0, this should not take too much time)
  • another type representation of BigInt #43 (This might break a lot of things, and should quickly be considered in my opinion).
  • type casts : signed and unsigned int #72, float and double (for 0.6.0)
  • examples : for a new release, I think examples at least should work #73
  • bitwise not
  • arithmetic functions : is(Probab)Prime(n) (No issue yet), legendre & jacobi symbol, binomial coefficient, fibonnaci, factorial (These might be the object of another library of course).
  • gcd (PR #75), lcm (for 0.6.0)
  • sqrt, isSqrt (for 0.7.0)
  • a benchmark folder, might be considered, in addition to the examples.
  • Montgomery multiplication : squaring is faster than multiplying
  • fast Division
  • integrate examples in the CI

Tests of invmod fail with arc & orc GC

The latest commit does not pass due to to an error with the arc garbage collector and the modular inverse function invmod.
It fails at the very first test of the function line 388.

How can I debug the invmod function to fix it ?

[Feature Request] Random BigInt

I would like a function to generate a uniformly (as much as possible) random BigInt inferior to some upper bound.
This would enable to randomize tests.

Division causes assert failure

import bigints

var a = initBigint("6277101735386680763835789123314955362437298222279840143829")
var b = initBigint("1461501637330902918203684832716283019655932313743")
var r = a.div(b)

Output:

Error: unhandled exception: /home/jhg/.nimble/pkgs/bigints-1.0.0/bigints.nim(652, 14) `q1 <= uint32.high`

Using latest repository version of bigints, Nim 1.6.10 on Linux x64.

Add probabilistic and deterministic primality tests

Miller-Rabin test is a polynomial probabilistic test to determine wheter an integer is prime. It is way faster than deterministic algorithm (even if they are polynomial) primality test.

Here are some implementations of what I would like :
Miller-Rabin test in Nim, by @mratsim :
https://github.com/mratsim/nim-project-euler/blob/master/src/lib/primes.nim
GMP optimized version :
https://gmplib.org/repo/gmp/file/tip/mpz/millerrabin.c

A primality test can then lead to algorithms for factoring integers, finding the next prime, improve prime sieving …
Another question this issue raises, is what do we want from this library to do ? Should it also be an arithmetic library ?
Since the limbs attribute of BigInt type is private, it might be complex to make another arithmetic library on top of this one (less optimizations on big integers due to less access to the internal representation).

Base multiplication returns wrong results for some big numbers

when isMainModule:
  a = "1780983279228119273110576463639172624".initBigInt
  b = "1843917749452418885995463656480858321".initBigInt
  echo a.limbs.len
  echo b.limbs.len
  echo a*b

outputs :

4
4
3283986680046702618742503890385314117448805445290098330749803441805804304

It should output :

4
4
3171901440890145063107180402349133639481893332927709969425239467271045376

Result obtained with SageMath, with Pari/GP and Wolfram/Alpha.
There are no tests for multiplication with more than two or three limbs.

Compound assignment operators shouldn't use `template`s

Currently, e.g. += is defined as

template `+=`*(a: var BigInt, b: BigInt) =
  a = a + b

This causes a to be evaluated twice, which can produce unexpected results, when it's an expression that can cause side effects. For example

proc lol(x: var BigInt): var BigInt =
  echo "hello ", x
  x

var a = 42.initBigInt
lol(a) += 1.initBigInt

prints hello 42 twice, instead of just once.

The solution would be to just make it a func instead. The same applies to -= and *=.

nimdocs.com going away

Hello, I wanted to give this repo a quick heads-up that nimdocs.com, which @treeform and I have been running, is going away in favor of using Github Actions + Github Pages.

nimdocs.com is currently linked to from this repo's readme for documentation.

My suggestion:

Add this Github Actions workflow file: https://github.com/treeform/nimtemplate/blob/master/.github/workflows/docs.yml (no need to change anything) to automatically generate docs in a branch called gh-pages. This branch will have the Docs content updated each push.

In the repo settings Page tab, you can then select that branch to serve (once the job has run once).

After that, https://nim-lang.github.io/bigints/ should be serving the most recently generated docs.

This is simpler than us running a server and all of that stuff and just as easy for repo maintainers so I think it is a better model.

I'll keep the server up for a bit yet but it is going away.

More functions for working with `SomeInteger`s

Currently, there are inc, dec, succ, pred for adding/subtracting an int. Internally, there are also functions for comparing with int32.

We should add more functions for working with BigInts and SomeIntegers, to avoid having to construct BigInts (and thus allocating) for small numbers. This would make sense for at least ==, <, +, -, *, div (in the second argument), mod (in the second argument).

CircleCI builds are broken

Apparently CircleCI no longer supports projects with a 1.0 configuration.

Service alert: Your project references CircleCI 1.0 or it has no configuration. CircleCI 1.0 and projects without configuration files are no longer supported. You must update your project to use CircleCI 2.0 configuration to continue.

Range of BigInt not supported?

For reasons to do with investigating testing Nim code I am writing factorial with a number of different algorithms. For the external iterative version, I have the statement:

  for i in two .. n:
    result *= i

where two and n are BigInt values, but the compiler tells me:

factorial.nim(13, 15) Info: template/generic instantiation from here
lib/system.nim(1581, 4) Error: type mismatch: got (BigInt)
but expected one of:
system.inc(x: var T, y: int)

the for statement is line 13. Does this mean ranges of BigInt are not supported out of the box?

Problem with multiple multiplications

Hi, thanks for this library, its great!
While playing with factorials though, I think I've found an odd bug. Here's the reduced case:

import bigints

let nums = [ "68855123440532288245010625",
             "201850901852714536181760000",
             "435980903974422631450250625",
             "824199001261152424427520000",
             "11527258048987096618327125",
             "18960243520191483654144000" ]


var total = 1.initBigInt

for e in items(nums):
  let bigInt = e.initBigInt
  stdout.write bigInt, " * ", total
  total *= bigInt
  echo " = ", total

output:

68855123440532288245010625 * 1 = 68855123440532288245010625
201850901852714536181760000 * 68855123440532288245010625 = 13898468763651426950178424411236763123358131200000000
435980903974422631450250625 * 13898468763651426950178424411236763123358131200000000 = 6059466975437025204783660349002445834010410572229490978416137871632000000000000
824199001261152424427520000 * 6059466975437025204783660349002445834010410572229490978416137871632000000000000 = 0
11527258048987096618327125 * 0 = 0
18960243520191483654144000 * 0 = 0

Obviously multiplying two positive integers shouldn't result in zero. The following works fine:

echo "824199001261152424427520000".initBigInt * "6059466975437025204783660349002445834010410572229490978416137871632000000000000".initBigInt

So i assume this is the result of consecutive mutations to total.

Add benchmarks

It would be useful to add some benchmarks, so that we can measure performance improvements/degradations for changes.

Some functions are not being imported

The compiler doesn't seem to be able to find some functions such as invmod, toInt or powmod.

An example from the documentation:

import pkg/"bigints"
assert invmod(3.initBigInt, 7.initBigInt) == 5.initBigInt

Throws an error when compiling...

Error: undeclared identifier: 'invmod'

Everything looks fine in the source , does anybody knows what is going on?

[Feature Request] Implement fast multiplication (Karatsuba, Tom-Cook, FFT)

As written in the Readme.md file, we need to implement fast multiplication to improve many different algorithms (at once).
I prefer to write a Github issue, as it is easier to gather good implementations and documentation of fast multiplication algorithms and issue enables to track progress with PRs.

The gmp section 15 algorithms describes fast multiplication algorithms : https://gmplib.org/gmp-man-6.2.1.pdf
I guess we might want to it differently than gmp and take into account other multi-precision arithmetic library . Especially the tresholds at which we switch from one algorithm to another might be different than GMP (because internal representation is different).

Squaring is faster than generic multiplication. We might want to take this into account for pow and powmod multiplication (e.g. montgomery squaring algorithm).

I am also surprised in-place multiplication is realized with a = a * b. Can we optimize this case as to reduce memory and copy operations ?

[Bug] `toSignedInt[int64]` produces wrong results in certain cases

Example:

import bigints

echo toSignedInt[int64](-initBigInt(0xFFFFFFFF_00000000'u64))

This currently prints some(-9223372036854775808), but the expected result is none(int64).

The reason is the following lines:

bigints/src/bigints.nim

Lines 817 to 819 in 18e3899

if x.limbs[1] > uint32.high shr 1:
if x.isNegative and x.limbs[0] == 0:
result = some(T(int64.low))

This is only correct if x.limbs[1] == uint32.high shr 1 + 1, otherwise x is out of range.

SIGSEGV when used with `const`.

Hi,
Thanks for a great library. I'm running into the following issue:

import bigints

proc factorial(accum: BigInt, i : int) : BigInt =
  if i == 1: accum
  else: factorial(accum * initBigInt(i), i - 1)

const fact1000 = factorial(initBigInt(1),1000)

echo fact1000

generates the following compilation error:

  Verifying dependencies for [email protected]
    Reading official package list
   Checking for bigints@>= 0.4.1
      Info: Dependency on bigints@>= 0.4.1 already satisfied
  Verifying dependencies for [email protected]
   Building factorial/main using c backend
     Error: Build failed for package: factorial
        ... Details:
        ... Execution failed with exit code 1
        ... Command: "/home/deech/Downloads/Nim/bin/nim" c --noBabelPath  --path:"/home/deech/.nimble/pkgs/bigints-0.4.1"  -o:"/home/deech/Nim/factorial/main" "/home/deech/Nim/factorial/main.nim"
        ... Output: Hint: used config file '/home/deech/Downloads/Nim/config/nim.cfg' [Conf]
        ... Hint: system [Processing]
        ... Hint: main [Processing]
        ... Hint: bigints [Processing]
        ... Hint: strutils [Processing]
        ... Hint: parseutils [Processing]
        ... Hint: math [Processing]
        ... Hint: algorithm [Processing]
        ... SIGSEGV: Illegal storage access. (Attempt to read from nil?)

But change the const to a var and everything works fine. Is compile time evaluation with this library supported?
Thanks!

Type conversion for small BigInts into integers

Since BigInt's limb parameter has become private, thus we can not easily cast BigInts with absolute value less than 2^32 to an int or even a uint32.
The only workaround yet is to use the keyword cast[int]. But this does not always do what we want.
To get only the smallest limb, we also have to define a mask like 2^32 - 1 and to apply an ineffective and.
Can we implement some functions like … ?:

  • toUint32(a: BigInt): uint32 returns the only limb for BigInts between 1-2^32 and +2^32-1 (small BigInts).
  • toInt(a: BigInt): int cast the BigInt if it is small enough, into an int, according to the sign of BigInt, with correct representation (2's complement) and raises a ValueError if the cast can not be done (if int is stored on 32 bits, it may not fit if the heavy weight bit of the uint32 corresponding to first limb is 1).
  • toUint64(a: BigInt): uint64 returns the uint64 made up of one to two limbs, if the BigInt is small enough.
  • toFloat like described in the similar issue #34.

Feature request: toBiggestInt

I need to convert BigInt to float64 and I'm not sure I'm qualified to implement it.

I'm using this:

proc toBiggestFloat(a: BigInt): BiggestFloat =
  for i in countdown(a.limbs.high, 0):
    result = result * BiggestFloat(1 shl 32) + a.limbs[i].BiggestFloat
  if Negative in a.flags:
    result = - result

But it gives me different results from a Haskell implementation as it get close to saturating the float at 179769313486231560835325876058105298516207002341652166261661174625869553267292326574530099287946549246750631490335877017522087105926987962906277604735569213290190919152394180476217125334960946356387261286640198029037799514183602981511756283727771403830521483963923935633133642802139091669457927874464075218945.

Turn `proc`s into `func`s

As far as I can tell, all procs could be turned into funcs, providing the guarantee that they don't have side effects. Is there anything or anyone opposing this?

Some examples do not compile

I have tested the examples but could not compile some of them probably due to some optional dependencies like unsigned in the pidigits example.
Is it an old file of the library that has been removed, or an external library ?
In the latter case, it should be added to nimble optional dependencies list if nimble has such an option.

Furthermore, some syntax has become obsolete like .. < that is now ..<.

Add significant bits/fastLog2 operation for BigInts

In order to improve modular exponentiation or to write other higher-order functions (functions that do not rely on BigInts internal representation), we might want to count the number of significant bits (bits after leading zeros, without the sign bit in complement representation of signed integers) or at least the logarithm in base 2 of the number.

We can determine the number of significant bits from the logarithm in base 2 as:
significantBits(n) = floor(log_2(n)) + 1

func significantBits*(n: BigInt): int =
  if n < 0:
    return significantBits(-n)
  fastLog2(n.limbs.high) + 32*(n.limbs.len-1)

How would you optimize the negative case ? Can we just take the two’s complement of the highest limb and then compute the fastLog2(n.limbs.high) ?

func significantBits*(n: BigInt): int =
  var highest_limb = n.limbs.high
  if n < 0:
    highest_limb = not n.limbs.high + 1
  fastLog2(highest_limb) + 32*(n.limbs.len-1)

JS backend

I experimented a bit with running the tests on the JS backend, but I came to the conclusion that this is currently not viable. The problem is nim-lang/Nim#4714: 64 bit integers are broken on the JS backend, since they're implemented as floating point values.

We could use std/jsbigints on the JS backend, but I'd rather not do that, since it has a different API, which means we'd have to implement some functions twice. Apart from that, this library wouldn't be a pure Nim implementation anymore then.

Are `BigInt`s always normalized?

It seems to me that BigInts are always normalized (i.e. the highest limb is never 0, except if the number is 0), however, this isn't documented.

If this is the case, I think at least isZero(n) could be optimized to just check n.limbs.len == 1 and n.limbs[0] (it currently uses a loop).

Bitwise `not`

In the README, there is a mention about a bitwise not operator. I would like to understand the use case of such an operator.
Is it not sufficient to just invert the bits of each limb ?
Should it modify the sign of the BigInt ? The previously implemented operators raises an exception if at least one of the inputs is negative.

Here is how I would code the operator not:

func `not`*(a : BigInt): BigInt =
  ## Bitwise `not` for `BigInt`s.
  runnableExamples:
  let
    a = 7.initBigInt
    assert not a == 8.initBigInt
  assert (not a.isNegative)
  result.limbs.setLen(a.limbs.len)
  for i in 0 ..< a.limbs.len:
    result.limbs[i] = not result.limbs[i]

avoid unnecessary copy in setXLen

the fix for #27 done in #35 introduced a copy in setXLen that has some impact in the performance in some cases (see benchmark on chainAddition in this comment).
In principle it is possible to fix the issue in self addition without introducing a new copy but it requires more effort.

Note that legacy usage of setXLen remains accessible through a compile time switch bigintsLegacySetXLen.

`div`/`mod` behaviour

The behaviour of div and mod is currently inconsistent with the respective operators for ints. For example:

import bigints

func divmod(a, b: int): tuple[q, r: int] =
    (q: a div b, r: a mod b)

echo "int:"
echo "  divmod(1, 2): ", divmod(1, 2)
echo "  divmod(1, -2): ", divmod(1, -2)
echo "  divmod(-1, 2): ", divmod(-1, 2)
echo "  divmod(-1, -2): ", divmod(-1, -2)
echo "BigInt:"
echo "  divmod(1, 2): ", divmod(1'bi, 2'bi)
echo "  divmod(1, -2): ", divmod(1'bi, -2'bi)
echo "  divmod(-1, 2): ", divmod(-1'bi, 2'bi)
echo "  divmod(-1, -2): ", divmod(-1'bi, -2'bi)

prints the following:

int:
  divmod(1, 2): (q: 0, r: 1)
  divmod(1, -2): (q: 0, r: 1)
  divmod(-1, 2): (q: 0, r: -1)
  divmod(-1, -2): (q: 0, r: -1)
BigInt:
  divmod(1, 2): (q: 0, r: 1)
  divmod(1, -2): (q: -1, r: -1)
  divmod(-1, 2): (q: -1, r: 1)
  divmod(-1, -2): (q: 0, r: -1)

For ints, division rounds towards 0 and the sign of a mod b is the sign of a. Meanwhile, for BigInts, division rounds towards negative infinity and the sign of a mod b is the sign of b.

I suggest we change the behavior of BigInts to match that of ints.

@def- since you implemented this, did you have a specific reason for implementing it this way?

suport for and, or

is there a reason and and or are not implemented? If this library is fast enough, I have a use-case, but I would need those operations.

Error encountered while using the `toInt` function

Hello,

I encountered a problem while using the bigints library. When I tried to use the toInt function to convert a value of type BigInt to type int, the following error message appeared:

template/generic instantiation of `toInt` from here
Error: cannot instantiate: 'T'

Here is my code snippet:

# 示例
var charset = "abc"
let length = 2
let startFrom = "ab"
let endAt = "bc"
let startNumber: BigInt = getStartNumber(startFrom, charset, length)
let endNumber: BigInt = getEndNumber(endAt, charset, length)

for i in startNumber..endNumber:
  echo fromDecimal(charset, i.toInt, length)

My Nim version is nim-1.6.4 and the bigints library version is bigints-1.1.0.

How can this problem be solved? Thank you!

Zero result from subtraction always has Negative flags

Hi Dennis,

Forgive me if I have misunderstood a reason for this, but I noticed when using subtraction to zero (or addition on equal magnitude but opposite signed BigInts), the resulting zero value always has Negative flags. EDIT: I added an example using multiplication, as I also noticed the same behaviour.

My expectation was that a zero value would normally be given as a positive zero by default, as that is typically how I would expect a native integer type to behave.

The negative flag can be worked around if you are aware of it, but I am not sure it is obvious or expected behaviour for the end user.

For example:

var 
  a = initBigInt("828478292990482")
  b = initBigInt(9283)
  c = initBigInt("-828478292990482")
  d = initBigInt(-9283)
  e = initBigInt(0)


echo b + d
echo a + c

echo d + b
echo c + a

echo b - b
echo d - d

echo d * e

# Outputs:

-0
-0
-0
-0
-0
-0
-0

Is there any reason for the result to always be given a negative sign, or are you happy for this to default to positive (un-flagged) zero?

Thank you

IndexError with a = a +b

expected to work:

import bigints

var
  a = 0.initBigInt
  b = "359097073186387306".initBigInt

a = a + b  # Error: unhandled exception: index out of bounds, the container is empty [IndexError]

The above seems to work if b < uint32.high.

With a temporary variable it works:

import bigints

var
  a = 0.initBigInt
  b = "359097073186387306".initBigInt
  t: BigInt

# with a temporary variable t it works
t = a + b
a = t
echo a

for context where this came from, see https://forum.nim-lang.org/t/6327

Rational numbers

BigInt objects don't work with the rationals module, because initRational expects SomeInteger which BigInt isn't. Looking through the code for rationals, it looks like the only function it needs that bigints doesn't have is lcd. What would be the best way to go about using bigints with rational numbers? Could BigInt be marked as SomeInteger with some tweaking?

LICENSE for bigints

We wanted to use this library in a project, but it doesn't have a LICENSE.

Bitwise operators for negative numbers

Currently, the bitwise operators (and, or, xor) only work for non-negative numbers. I suggest also supporting negative numbers, treating them as if they were represented using 2's complement (the standard representation for signed integers). This would also allow implementing not x, by simply doing -x - 1.

Empty limbs when uninitialized

Consider the following:

var
    a: BigInt
    b: BigInt = 12.initBigInt

echo a*b

This results in the following stack trace:

[...]/scratch.nim(7) scratch
[...].nimble/pkgs/bigints-0.4.3/bigints.nim(484) *
[...].nimble/pkgs/bigints-0.4.3/bigints.nim(394) multiplication
[...].choosenim/toolchains/nim-#devel/lib/system/fatal.nim(39) sysFatal
Error: unhandled exception: index out of bounds, the container is empty [IndexError]

This is because a.limbs is @[]. Would it be possible for an uninitialized BigInt to default to limbs = @[0], to be consistent with nim integers? Otherwise, maybe there could be a flag initialized that is checked before trying to operate on a BigInt, so we get slightly more readable errors. I'm not super proud about it, but tbh this took me a while to debug. To be fair, my actual code was slightly more complex and resulted in a zero BigInt not being initialized in a corner case.

RangeErrors on nim 0.20.2

Running nimble test using nim 0.20.2 results in multiple RangeErrors.

Hint: /Users/me/Development/mpc/nim-bigints/tests/tester  [Exec]
/Users/me/Development/mpc/nim-bigints/tests/tester.nim(43) tester
/Users/me/Development/mpc/nim-bigints/tests/tester.nim(32) chk
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(30) initBigInt
/Users/me/.choosenim/toolchains/nim-0.20.2/lib/system/fatal.nim(39) sysFatal

Unhandled exception: value out of range [RangeError]
[FAILED] initBigInt
[OK] range of bigint (https://github.com/def-/nim-bigints/issues/1)
[OK] multiple multiplications (https://github.com/def-/nim-bigints/issues/3)
[OK] negative bigint (https://github.com/def-/nim-bigints/issues/4)
/Users/me/.choosenim/toolchains/nim-0.20.2/lib/pure/unittest.nim(622) tester
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(742) div
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(681) division
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(636) unsignedDivRem
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(308) addition
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(249) unsignedSubtraction
/Users/me/.choosenim/toolchains/nim-0.20.2/lib/system/fatal.nim(39) sysFatal

Unhandled exception: value out of range [RangeError]
[FAILED] off by one in division (https://github.com/def-/nim-bigints/issues/5)
/Users/me/.choosenim/toolchains/nim-0.20.2/lib/pure/unittest.nim(622) tester
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(321) +
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(311) addition
/Users/me/Development/mpc/nim-bigints/src/bigints.nim(249) unsignedSubtraction
/Users/me/.choosenim/toolchains/nim-0.20.2/lib/system/fatal.nim(39) sysFatal

Unhandled exception: value out of range [RangeError]
[FAILED] negative zero flags (https://github.com/def-/nim-bigints/issues/16)

[Feature request] Add more examples : factorization, find modular square-root

To showcase what can be done with the library, as well to benchmark it, I propose to add examples for factorization with simple exponential algorithms like rho-pollard, p-1 or p+1.
We would need for these gcd and powmod algorithms currently in PR #65 and #66.

We could also improve/adapt the algorithm published on Rosetta Code for Shanks-Tonelli . Some examples could not be computed with only nim's integer native library and have a need for multi-precision arithmetic.

Too much examples might make the library size big, but they help to define a good API, to understand which feature are essential and which one needs optimization.

[Feature request] `powmod`

Description

Provide a powmod(base, exponent, modulus) function that computes (base ^ exponent) % modulus, but more efficiently than the naive computation. In particular, it should avoid building up BigInts that are substantially larger than modulus.

Related work

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.