Skip to main content

1673. gopy long

What we are porting

Objects/longobject.c (~6500 lines). The most-used numeric type in CPython. Arbitrary precision via 30-bit digit arrays (15-bit on 32-bit builds, but gopy is 64-bit-only). Per-process cache of the small-int range (-5..256). Numeric-protocol slot table covering add, subtract, multiply, true/floor div, mod, pow, bitwise ops, shifts, negation, abs, conversion to/from float, hashing, repr, parsing from string with arbitrary base.

CPython 3.12+ stores small ints inline in a tagged-pointer style on free-threaded builds. gopy's GIL build matches the unboxed layout but does not use tagged pointers; the small-int cache is a plain [262]*Long array.

Go shape

// Long mirrors PyLongObject. Sign is encoded in size: positive
// magnitude in digits[], negative if size<0, zero if size==0.
type Long struct {
Header
digits []uint32 // 30 bits per digit, little-endian
size int // signed; sign(size) == sign(value)
}

Use int64 fast path for values that fit; spill to digit array otherwise. CPython does the same with _PyLong_IsCompact.

Small-int cache

// smallInts[i] caches the int with value i-5 for i in [0..262).
// Mirrors _Py_SmallInts in longobject.c.
var smallInts [262]*Long

-5..256 are singletons. is comparison preserves identity: x = 1; y = 1; assert x is y.

Parsing

PyLong_FromString accepts any base in [2..36] plus base 0 (autodetect from 0x/0o/0b prefix or default to 10). Underscores allowed between digits per PEP 515.

File mapping

C sourceGo target
Objects/longobject.c (struct + ctors)objects/long.go
arithmeticobjects/long_arith.go
bitwise + shiftsobjects/long_bitwise.go
parsingobjects/long_parse.go
hash, repr, formatobjects/long_misc.go
small-int cacheobjects/long_cache.go
clinic/longobject.c.hfolded into the above

Checklist

Status legend: [x] shipped, [ ] pending, [~] partial / scaffold, [n] deferred / not in scope this phase.

Files

  • [~] objects/long.go: Long struct, FromInt64, FromUint64, AsInt64, IsZero, Sign. v0.2 placeholder shipped; full digit-array spill pending.
  • objects/long_arith.go: Add, Sub, Mul, FloorDiv, TrueDiv, Mod, DivMod, Pow, Negative, Abs.
  • objects/long_bitwise.go: And, Or, Xor, Invert, Lshift, Rshift.
  • objects/long_parse.go: FromString(s, base), base-0 autodetect, underscore handling, leading/trailing whitespace rules.
  • objects/long_misc.go: Hash (compress to Py_hash_t), Repr (decimal), Str, Format (__format__ with mini-language), RichCompare, Bool, Int, Float coercions.
  • objects/long_cache.go: small-int cache initialiser, the Get(i) fast path.
  • objects/long_test.go: per-op panel + small-int identity + hash parity.

Surface guarantees

  • is identity holds for -5..256 across every constructor path.
  • hash(int) matches CPython under PYTHONHASHSEED=0 for the full -2**128 .. 2**128 corpus from compat/hash_panel.txt.
  • repr(int) matches CPython for arbitrary-precision values.
  • int("0x1_0", 0) == 16 round-trips per PEP 515.
  • int(2**1000) round-trips through digit-array path.
  • int.__pow__(b, e, m) modular reduction matches CPython bit-for-bit.
  • Division by zero raises ZeroDivisionError with the same text CPython uses.

Cross-references

  • Header / refcount: 1671.
  • Type slots: 1672.
  • Hash key: 1607 / 1661.
  • Format mini-language: 1660.

Out of scope

  • bool subtype of int. Lives in 1675.
  • SIMD-accelerated multiplication. Tracked under perf, not parity.
  • Free-threaded tagged-pointer compaction. Lands with 1671 §free threading in v0.14.