Skip to content

Instantly share code, notes, and snippets.

@timholy
Created January 15, 2020 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timholy/569475b24763d1fbd36a42634192cb74 to your computer and use it in GitHub Desktop.
Save timholy/569475b24763d1fbd36a42634192cb74 to your computer and use it in GitHub Desktop.
Prototype of NaNIntegers
module NaNIntegers
import Base: <, <=, +, -, *, ~, &, |, <<, >>, >>>, xor
export NInt16, NInt32, NInt64, NInt128, NInt
export NaNI16, NaNI32, NaNI64, NaNI128
abstract type NSigned <: Signed end
primitive type NInt16 <: NSigned 16 end
primitive type NInt32 <: NSigned 32 end
primitive type NInt64 <: NSigned 64 end
primitive type NInt128 <: NSigned 128 end
if Sys.WORD_SIZE == 32
const NInt = NInt32
else
const NInt = NInt64
end
## Traits
itype(::Type{NSigned}) = Signed
itype(::Type{NInt16}) = Int16
itype(::Type{NInt32}) = Int32
itype(::Type{NInt64}) = Int64
itype(::Type{NInt128}) = Int128
itype(x::NSigned) = itype(typeof(x))
ntype(::Type{Signed}) = NSigned
ntype(::Type{Int16}) = NInt16
ntype(::Type{Int32}) = NInt32
ntype(::Type{Int64}) = NInt64
ntype(::Type{Int128}) = NInt128
ntype(x::Signed) = rtype(typeof(x))
nanmask(::Type{NInt16}) = 0x4000
nanmask(::Type{NInt32}) = 0x40000000
nanmask(::Type{NInt64}) = 0x4000000000000000
nanmask(::Type{NInt128}) = 0x40000000000000000000000000000000
nanmask(::Type{S}) where S<:Signed = nanmask(ntype(S))
nanmask(x::Integer) = nanmask(typeof(x))
## Constructors
checknan(x) = (x & nanmask(x)) == zero(nanmask(x)) || throw(DomainError(x, "NaN bit must not be set"))
NInt16(x::Int16) = (checknan(x); reinterpret(NInt16, x))
NInt32(x::Int32) = (checknan(x); reinterpret(NInt32, x))
NInt64(x::Int64) = (checknan(x); reinterpret(NInt64, x))
NInt128(x::Int128) = (checknan(x); reinterpret(NInt128, x))
(::Type{N})(x) where N<:NSigned = N(convert(itype(N), x))
Base.rem(x::Int16, ::Type{NInt16}) = reinterpret(NInt16, x)
Base.rem(x::Int32, ::Type{NInt32}) = reinterpret(NInt32, x)
Base.rem(x::Int64, ::Type{NInt64}) = reinterpret(NInt64, x)
Base.rem(x::Int128, ::Type{NInt128}) = reinterpret(NInt128, x)
const NaNI16 = Int16(nanmask(NInt16)) % NInt16
const NaNI32 = Int32(nanmask(NInt32)) % NInt32
const NaNI64 = Int64(nanmask(NInt64)) % NInt64
const NaNI128 = Int128(nanmask(NInt128)) % NInt128
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment