New Quark for Arbitrary-Precision Arithmetic

Hello everyone,

I wanted to share with you a Quark I just finished developing (my first Quark, feedback much appreciated).

A class for arbitrary-precision arithmetic in SuperCollider. For some cases, it solves the limitation of doing arithmetics in only 64-bit. Link: mafalda/SCBigNumArithmetic - Codeberg.org

So far, I implemented methods for addition, subtraction, multiplication, modulo, exponentiation and comparison. Further, negative values and leading zeros are supported.

// number of states in 128 bits.
BigNum(2) ** 128 // -> 340282366920938463463374607431768211456

The Quark can be installed by executing this line:

Quarks.install("https://codeberg.org/mafalda/SCBigNumArithmetic.git")

cheers,
matt

1 Like

Looks nice!

A few queries and suggestions:

  1. Kwargs returns an array like this [\arg1, val1, \arg2, val2] if you want to iterate through it, you’d need to call asPairs. Or you could turn it into an event…
var kwargsEvent = kwargs.asEvent;
var sign = kwargsEvent[\sign] ?? {false};
  1. Does double dispatch work?
1 + BigNum(...) \\ returns a big number.

If not you should be able to get this working, but the rules around what classes implicitly coerce might be confusing!

  1. You might consider not using isNumber and instead just call asBigNum directly and use extensions to implement the switch in behaviour. This is usually the more SC/Smalltalk way of doing things. Naively, I’d expect BigNum to be a number.

  2. Nice to see someone use newCopyArgs with keywords!

Hi Jordan, thanks for your comments!

(1): I see! I was not so happy with that iteration. I like the conversion into an Event. It would then look more like this:

    kwargsEvent = kwargs.asEvent;
    digits = kwargsEvent[\digits] ?? { digits };
    sign = kwargsEvent[\sign] ?? { sign };
    length = kwargsEvent[\length] ?? { length };

(2): Yes, double dispatch works. The relevant method performBinaryOpOnSimpleNumber is quite at the end of the file. To me a little while to understand the concept :wink:

(3): Do you mean something like this?

  + { |aNumber|
    if (aNumber.class != BigNum) {
      ^BigNum.addBigNum(this, aNumber.asBigNum)
    } {
      ^BigNum.addBigNum(this, aNumber)
    }
  }

While writing it… I could also implement a asBigNum for BigNum and get rid of the switch completely.

(4) props to the documentation authors! They gave me this idea :smile:

In fact, this was a great suggestion, thanks! I got rid of a lot of lines: commit link

1 Like