Skip to content

JustNothingJay/mobius-integer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MöbiusInteger

DOI

Every systems language gets this wrong:

i64::MAX + 1 = i64::MIN    // Rust (wrapping)
2147483647 + 1 = -2147483648  // C, Java, Go

The Ariane 5 rocket exploded because of it. YouTube broke because of it. Boeing issued emergency reboots because of it.

MöbiusInteger fixes it:

use mobius_integer::Mi;

let max = Mi::new(i64::MAX);
let result = max + Mi::new(1);

assert_eq!(result.machine(), i64::MIN);  // machine wrapped — this is what hardware does
assert!(result.is_corrupted());           // but now you KNOW it wrapped
assert_eq!(result.collapse().to_string(), "9223372036854775808"); // truth

How it works

Every MöbiusInteger stores two strands:

  • Machine strand (i64): hardware-fast, uses wrapping arithmetic — behaves exactly like C/Java/Go
  • Exact strand (BigInt): arbitrary precision, never overflows — carries the truth

Arithmetic propagates both strands simultaneously. Comparison and collapse always use the exact strand. The overflow still happens on the machine strand, but it's never consulted for truth.

The name comes from the Möbius strip — one surface, no front or back. The number and its correction are the same object.

The disasters, all caught

Ariane 5 — June 4, 1996

A 64-bit float was narrowed to a 16-bit signed integer. The value exceeded 32,767. The conversion overflowed silently. The rocket self-destructed 37 seconds after launch. $370 million payload lost.

let velocity = Mi::new(32_768);

// Old way: silent truncation, rocket explodes
// MöbiusInteger way:
assert!(velocity.narrow_i16().is_err());  // caught. rocket lives.

YouTube / Gangnam Style — December 2014

PSY's video exceeded 2,147,483,647 views. YouTube's 32-bit counter couldn't hold it.

let views = Mi::new(2_147_483_648);
assert!(views.narrow_i32().is_err());  // caught before the counter breaks

Boeing 787 — April 2015

A 32-bit centisecond counter overflowed after 248 days of continuous operation. The FAA ordered periodic reboots.

let timer = Mi::new(100 * 60 * 60 * 24 * 249);  // 249 days in centiseconds
assert!(timer.narrow_i32().is_err());  // caught. no reboot needed.

The corruption detector

let a = Mi::new(i64::MAX);
let b = Mi::new(i64::MAX);
let result = a + b;

println!("{}", result);
// Output: 18446744073709551614 (machine: -2, CORRUPTED)

result.is_corrupted()  // true — the machine strand is lying
result.collapse()      // BigInt: 18446744073709551614 — the truth
result.machine()       // -2 — what C would have given you

API

Method Returns Description
Mi::new(i64) MobiusInteger Create from i64, both strands agree
Mi::from_big(BigInt) MobiusInteger Create from BigInt, machine saturates
.machine() i64 The fast strand (may have wrapped)
.exact() &BigInt The truth strand (never overflows)
.collapse() BigInt Möbius traversal — returns exact
.is_corrupted() bool True if machine ≠ exact
.narrow_i16() Result<i16, OverflowError> Safe narrowing (Ariane 5 fix)
.narrow_i32() Result<i32, OverflowError> Safe narrowing (Gangnam Style fix)
.narrow_i64() Result<i64, OverflowError> Safe narrowing
+ - * / % - MobiusInteger All propagate both strands
== != < > <= >= bool All use exact strand

Install

[dependencies]
mobius-integer = "0.1"

Part of the Möbius family

  • mobius-number — fixes IEEE 754 floating point (0.1 + 0.2 = 0.3)
  • mobius-integer — fixes integer overflow (this crate)

Same pattern. Same anatomy. Same fix. Different domain.

License

MIT

About

A dual-strand integer: machine i64 (fast, wraps) + exact BigInt (never overflows). The Ariane 5 would have landed.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages