From the Nim manual
For reasons of simplicity of implementation the types uint and uint64 are not ordinal types.
I bumped into a case while working with uint64 that I wanted to use a uint64 in a case; obviously there weren't really that many cases and I could easily map to a smaller range, but after that bump I got curious as to why this restriction is here.
As long as I'm asking, any plans for int128/uint128?
The compiler uses int64 internally to compute type bounds, uint64's bounds do not fit this scheme. And changing it to also support uint64 or use big nums everywhere is much work.
As long as I'm asking, any plans for int128/uint128?
No, you're one of the firsts who ask for it. When we tackle the uint64 issue, we might address these too though.
Now, with the release of version 1.0 and the correction of uint64 to regular ordinal, is there any plan for Nim to support int128/uint128?
I know of the stint library, but it would be interesting for the language to support these types without the need for external packages.
Once again, congratulations on the excellent work.
int128/uint128 maps to hardware and/or compiler intrinsics and need some codegen fixes for shifts.
Or you can use the hacky approach I started in https://github.com/nim-lang/Nim/issues/7675#issuecomment-383409664, don't put that in the standard lib though.
{.emit:"""
typedef unsigned __int128 NU128;
typedef __int128 NI128;
""".}
type
int128*{.importc: "NI128".} = object
# Size missing https://github.com/nim-lang/Nim/issues/7674
do_not_use1, do_not_use2: uint64
helper128 = object
lo, hi: uint64
func `+`(x, y: int128): int128 {.magic: "AddI".}
# func `shl`(x, y: int128): int128 {.magic: "ShlI".}
# # Generates c_3kT3fyGcLUlO9cGAfoG5F0w = ()((NU128)(a_H4uaduhuKIzzvSo9a5XGckw) << (NU128)(b_s7Jde6jEzqXVu63vxBEZxg));
# # Notice how the parenthesis is empty
func `shl`(x, y: int128): int128 =
{.emit: "`result` = (NI128)((NU128)(`x`) << (NU128)(`y`));".}
# Works
var
helperA = helper128(lo: 10)
helperB = helper128(lo: 3)
let
a = (cast[ptr int128](helperA.addr))[]
b = (cast[ptr int128](helperB.addr))[]
var c = a shl b
echo (cast[ptr helper128](c.addr))[] # (lo: 80, hi: 0)
Both int128 and bignum would be nice in the standard library but while int128 have a very defined API (drop-in replacement for int64), bignum might need some API tuning and so should probably start as a package.