Skip to main content

1674. gopy float and complex

What we are porting

  • Objects/floatobject.c (~2400 lines): boxed IEEE-754 binary64. Numeric protocol, repr (shortest-roundtrip via dtoa), hash, __format__, parsing.
  • Objects/complexobject.c (~1400 lines): complex built on two float64 fields. Same numeric protocol shape with explicit real/imag.

floatobject.c lands in v0.2 (it gates the v0.2 repr corpus). complexobject.c lands in v0.6 (no upstream user before then).

Go shape

// Float mirrors PyFloatObject.
type Float struct {
Header
Value float64
}

// Complex mirrors PyComplexObject.
type Complex struct {
Header
Real float64
Imag float64
}

Both store values directly. No NaN-canonicalisation: float('nan') is one specific bit pattern (0x7ff8000000000000), the same one CPython uses.

Hashing

float.__hash__ runs the modular-reduction algorithm from Objects/object.c:_Py_HashDouble. Reuses the hash package (1661) which already exposes Double.

complex.__hash__ combines the real and imag hashes: hash(z) == hash(z.real) + 1000003 * hash(z.imag) (mod 2**61 - 1), matching CPython.

Repr / str

Shortest-roundtrip via pystrtod.FormatFloat (1660). Special cases:

  • inf / -inf / nan repr verbatim.
  • Integer-valued floats render as 1.0, not 1.
  • Negative zero renders as -0.0.

File mapping

C sourceGo target
Objects/floatobject.cobjects/float.go
arithmetic + richcompareobjects/float_arith.go
repr / str / formatobjects/float_repr.go
parsingobjects/float_parse.go
Objects/complexobject.cobjects/complex.go (v0.6)

Checklist

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

Files (float, v0.2)

  • [~] objects/float.go: Float struct, FromFloat64, AsFloat64. v0.2 placeholder landed; richcompare panel pending.
  • objects/float_arith.go: Add, Sub, Mul, TrueDiv, FloorDiv, Mod, DivMod, Pow, Negative, Abs, Bool.
  • objects/float_repr.go: Repr (shortest roundtrip), Str, Format (mini-language with f/e/g/F/E/G/%), Hash via hash.Double.
  • objects/float_parse.go: FromString with whitespace trimming, underscore PEP 515, signed inf/nan parsing.
  • objects/float_test.go: repr corpus, hash corpus, parsing corner cases, NaN comparisons.

Files (complex, v0.6)

  • objects/complex.go: Complex struct, real/imag accessors, numeric protocol, __format__.
  • objects/complex_test.go: hash combine, division, abs, __format__.

Surface guarantees

  • repr(float) matches CPython on the compat/repr/floats.txt corpus (subnormals, denormals, exact powers of two, near-roundoff cases).
  • hash(float) matches CPython on every value in compat/hash/floats.txt.
  • float('inf'), float('nan') produce the exact bit patterns CPython produces.
  • 0.1 + 0.2 == 0.30000000000000004 (no silent rounding).
  • int(float('inf')) raises OverflowError with the CPython text.
  • Division by zero raises ZeroDivisionError; modulo with NaN returns NaN.
  • complex(1, 2) ** 2 == complex(-3, 4) (panel pinned).

Cross-references

  • pystrtod parsing / formatting: 1660.
  • Hash key: 1661.
  • Format mini-language: 1660.

Out of scope

  • decimal.Decimal. Stdlib effort.
  • fractions.Fraction. Stdlib.
  • Long-double / _Float128. Not exposed in CPython 3.14 either.