BigInt

← Reference
Io

C implementation of arbitrary-precision integers. Each BigInt is an IoObject whose dataPointer is an IoBigIntData that owns a libtommath mp_int (variable-size digit array on the heap). Unlike Number, BigInt has a real payload: rawClone allocates and mp_init's a fresh mp_int, and the tag's freeFunc must call mp_clear before freeing the wrapper. Operands must both be BigInts — there is no silent coercion from Number (matching JavaScript's BigInt rules), which is enforced by the IoBigInt_argData helper that raises an error on non-BigInt args. Every arithmetic method follows the same mp_init/op/mp_copy-into-new- BigInt/mp_clear pattern to keep libtommath's ownership discipline correct even in the face of GC-driven allocation.

IoBigInt_argData(self, locals, m, argIndex)

Pulls the n-th argument and returns its IoBigIntData, or NULL after raising an error if the argument is not a BigInt. Used at the top of every binary operation — centralizes the "no implicit coercion" rule so BigInt + Number, etc. fails rather than silently losing precision. Also propagates any prior errorRaised flag.

IoBigInt_free(self)

Registered as the tag's freeFunc. mp_clear releases libtommath's heap digit buffer before the wrapper struct is freed — omitting this would leak digits for every reclaimed BigInt.

IoBigInt_isBigInt(self)

Type check by tag-name comparison. Used by argData and by external bindings that need to distinguish BigInt from Number before calling IoBigInt_mp. Name comparison (rather than tag pointer equality) is chosen so the check keeps working across VM state restarts.

IoBigInt_mp(self)

Returns a borrowed pointer to the internal mp_int. Caller must not mp_clear it — the wrapper still owns the digits. Used by helpers that want to call libtommath functions directly without going back through the Io method dispatch path.

IoBigInt_new(state)

Convenience constructor: look up the proto and IOCLONE. rawClone provides a zeroed mp_int, so the caller typically follows up with mp_copy or mp_set_double to seed the value.

IoBigInt_newFromCString(state, str)

Parses a C string as a base-10 integer. Unlike the Io-level from method, this silently ignores parse errors — intended for callers that have already validated the input.

IoBigInt_newResult(state, result)

Mints a fresh BigInt and copies the caller's scratch mp_int into it. The caller retains ownership of their temporary and must mp_clear it after — see every arithmetic method for the canonical init/op/copy/ clear sequence. Deep copy is required because the wrapper's mp_int is freed independently from the caller's.

IoBigInt_newTag(state)

Builds the BigInt tag with clone and free hooks. No compareFunc is set — comparison goes through the explicit compare / <, > Io methods so mismatched-type comparisons raise instead of silently ordering.

IoBigInt_newWithMpInt(state, src)

Constructs a BigInt from an existing libtommath mp_int. Deep-copies via mp_copy so the caller's mp_int can be cleared independently — this is the safe bridge from C code that already owns an mp_int.

IoBigInt_proto(state)

Creates the BigInt proto. Allocates an IoBigIntData payload initialized to zero, attaches the tag, registers the proto on the state, and installs the full arithmetic/comparison/conversion method table. All BigInts are clones of this proto.

IoBigInt_rawClone(proto)

Registered as the tag's cloneFunc. Allocates a fresh IoBigIntData and mp_init's its mp_int so the clone owns an independent digit buffer. The value is NOT copied from proto — callers seed the result themselves (e.g. IoBigInt_newWithMpInt, arithmetic methods). The explicit tag set preserves tag identity across clones when the proto chain is shared.

IoObject_BigInt_abs(self, locals, m)

Absolute value via mp_abs. Always allocates a fresh BigInt even when self is already non-negative — BigInts are immutable from Io.

IoObject_BigInt_add(self, locals, m)

Sum of two BigInts. Exemplar of the add/sub/mul shape: stack-allocated scratch mp_int, mp_init, mp_op, copy into a fresh IoBigInt, mp_clear. Returns nil on argument-type error raised by IoBigInt_argData.

IoObject_BigInt_asNumber(self, locals, m)

Lossy conversion to a Number. Values beyond 2^53 or below -2^53 lose integer precision through the double; Infinity is returned for out-of-range magnitudes per mp_get_double.

IoObject_BigInt_asString(self, locals, m)

Decimal string form. Queries libtommath for the needed buffer size via mp_radix_size, allocates, renders with mp_to_radix, and interns the result as a Symbol so repeated large values share storage.

IoObject_BigInt_compare(self, locals, m)

Three-way compare returning -1/0/1 as a Number. Translates libtommath's MP_LT/MP_EQ/MP_GT enum into the Io-standard integer ordering used by sort predicates.

IoObject_BigInt_div(self, locals, m)

Quotient of two BigInts (truncated toward zero, matching mp_div). Passes NULL for the remainder out-param since only the quotient is returned; callers needing both should use div and mod separately. Raises on divide-by-zero before calling mp_div.

IoObject_BigInt_from(self, locals, m)

Construction entry point accepting a Number, a Sequence (parsed as decimal), or another BigInt (copy). Number path uses mp_set_double, which truncates the fractional component; Sequence path routes errors from mp_read_radix back through IoState_error_ so malformed literals surface as an Io exception.

IoObject_BigInt_mod(self, locals, m)

Remainder of two BigInts. Uses mp_mod, which gives a non-negative result for positive modulus (Euclidean), distinct from C's trunc-toward- zero fmod semantics. Raises on divide-by-zero before calling mp_mod.

IoObject_BigInt_mul(self, locals, m)

Product of two BigInts. libtommath may allocate additional digits for the result buffer during mp_mul; ownership transfers to the new wrapper via mp_copy.

IoObject_BigInt_negate(self, locals, m)

Unary minus. Same init/op/copy/clear pattern as the binary ops, with mp_neg writing into a scratch mp_int.

IoObject_BigInt_pow(self, locals, m)

Integer power. Exponent comes as a Number (not a BigInt) because mp_expt_n takes a C int; negative or non-integral exponents are rejected up front since BigInt has no fractional representation.

IoObject_BigInt_sub(self, locals, m)

Difference of two BigInts. Same init/op/copy/clear pattern as add.