# Tonight I hated julia, REPL and overflows

**URL:** https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884
**Category:** New to Julia
**Tags:** integer-overflow
**Created:** [February 20, 2020, 2:10am UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884 "2020-02-20T02:10:21Z")
**Posts on this page:** 5
**Page:** 4

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [March 11, 2020, 5:09pm UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884/61 "2020-03-11T17:09:29Z")

</div>

The error is at a place where it isn’t even using rtype (it fails for both SometimesBigInt and my SBig types).

Here is the code I used to test:

> using BenchmarkTools  
> using Strs
> 
> using Base: mul\_with\_overflow  
> import Base: //, promote\_type, convert
> 
> struct SometimesBigInt \<: Integer  
> value::Union{Int, Base.RefValue{BigInt}}  
> end
> 
> SometimesBigInt(x::BigInt) = SometimesBigInt(Ref(x))
> 
> function Base.show(io::IO, x::SometimesBigInt)  
> print(io, “SometimesBigInt(”, value(x), “)”)  
> end
> 
> function value(x::SometimesBigInt)::Union{Int, BigInt}  
> x.value  
> end
> 
> //(x::SometimesBigInt, y) = value(x)//y  
> //(x::SometimesBigInt, y::Integer) = value(x)//y
> 
> function Base.:(\*)(x::SometimesBigInt, y::SometimesBigInt)  
> xv, yv = value(x), value(y)  
> if xv isa Int && yv isa Int  
> zv, overflowed = mul\_with\_overflow(xv, yv)  
> if overflowed  
> zv = big(xv) \* big(yv)  
> end  
> else  
> zv = xv \* yv  
> end  
> SometimesBigInt(zv)  
> end
> 
> convert(::Type{BigInt}, v::SometimesBigInt) = BigInt(value(v))
> 
> promote\_type(SometimesBigInt, Int) = SometimesBigInt  
> promote\_type(SometimesBigInt, BigInt) = BigInt
> 
> const b0 = big"0"
> 
> struct SBig \<: Integer  
> v::Int  
> b::BigInt  
> end
> 
> value(x::SBig) = isint(x) ? x.v : x.b
> 
> //(x::SBig, y) = value(x)//y  
> //(x::SBig, y::Integer) = value(x)//y
> 
> fitint(x) = typemin(Int) \<= x \<= typemax(Int)  
> isint(x::SBig) = (x.b === b0)  
> SBig(x::Int) = SBig(x, b0)  
> SBig(x) = fitint(x) ? SBig(convert(Int, x)) : SBig(0, x)  
> SBig(x::BigInt) = fitint(x) ? SBig(x % Int, b0) : SBig(0, convert(BigInt, x))
> 
> convert(::Type{BigInt}, v::SBig) = isint(v) ? BigInt(v.v) : v.b  
> convert(::Type{SBig}, v::BigInt) = fitint(v)isint(v) ? BigInt(v.v) : v.b
> 
> promote\_type(SBig, Int) = SBig  
> promote\_type(SBig, BigInt) = BigInt
> 
> Base.show(io::IO, x::SBig) = print(io, “SBig(”, value(x), “)”)
> 
> function Base.:(\*)(x::SBig, y::SBig)  
> if isint(x)  
> isint(y) ? SBig(widemul(x.v, y.v)) : SBig(0, x.v \* y.b)  
> else  
> isint(y) ? SBig(0, x.b \* y.v) : SBig(0, x.b \* y.b)  
> end  
> end
> 
> function out(s, t)  
> m0 = minimum(t).time / 1000  
> md = median(t).time / 1000  
> pr"%-25s(s)min=%10.3f(m0) μs, median=%10.3f(md) μs\n"  
> m0  
> end
> 
> function bench(p, nums)  
> xs = rand(nums, 1000)  
> ys = rand(nums, 1000)
> 
> ```
> pr"\n\%d(p)% chance of overflow\n"
> t1 = out("Int mul:", @benchmark $xs .* $ys)
> 
> bigxs = big.(xs)
> bigys = big.(ys)
> t2 = out("BigInt mul:", @benchmark $bigxs .* $bigys)
> pr"\%8.3f(t2/t1)x BigInt/Int\n"
> pr"\%8.3f(t1/t2)x Int/BigInt\n"
> 
> sbigxs = SometimesBigInt.(xs)
> sbigys = SometimesBigInt.(ys)
> t3 = out("SometimesBigInt mul:", @benchmark $sbigxs .* $sbigys)
> pr"\%8.3f(t3/t1)x SBI/Int\n"
> pr"\%8.3f(t1/t2)x Int/SBI\n"
> pr"\%8.3f(t3/t2)x SBI/BigInt\n"
> pr"\%8.3f(t2/t3)x BigInt/SBI\n"
> 
> xbigxs = SBig.(xs)
> xbigys = SBig.(ys)
> t4 = out("SBig mul:", @benchmark $xbigxs .* $xbigys)
> pr"\%8.3f(t4/t1)x SBig/Int\n"
> pr"\%8.3f(t1/t2)x Int/SBig\n"
> pr"\%8.3f(t4/t2)x SBig/BigInt\n"
> pr"\%8.3f(t2/t4)x BigInt/SBig\n"
> pr"\%8.3f(t4/t3)x SBig/SometimesBigInt\n"
> pr"\%8.3f(t3/t4)x SometimesBigInt/SBig\n"
> 
> nothing
> 
> ```
> 
> end
> 
> bench(1, (1:9…, 10^10))  
> bench(0, (1:10…,))  
> bench(100, ((10^10 .+ (1:10))…,))
> 
> function test\_hm(rtype,rank)  
> mr = [rtype(1) // (i + j) for i in 1:rank, j in 1:rank]  
> one(mr) == mr \* inv(mr)  
> end
> 
> println(“test\_hm(SometimesBigInt”)  
> @btime test\_hm(SometimesBigInt, 45)
> 
> println(“test\_hm(SBig”)  
> @btime test\_hm(SBig, 45)

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 11, 2020, 6:09pm UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884/62 "2020-03-11T18:09:55Z")

</div>

Dear Scott,  
there were quite a few wrong things with your code:  
a missing convert function, an error in the arguments of promote\_type (I replaced with promote\_rule  
which is better), and the main thing is that // must build a Rational{SometimesBigInt} if you want rational operations to be protected from overflows.

You also need to define all the arithmetic for SometimesBigInts. I put “dummy” definitions for -, rem, div  
just so one can build a Rational. Dummy since they don’t check for overflow!  
I did not finish, but with a few more definitions you should be able to make the example run…

```julia
using BenchmarkTools
using Strs
using Statistics

using Base: mul_with_overflow
import Base: //, promote_type, convert

struct SometimesBigInt <: Integer
value::Union{Int, Base.RefValue{BigInt}}
end

SometimesBigInt(x::BigInt) = SometimesBigInt(Ref(x))

function Base.show(io::IO, x::SometimesBigInt)
print(io, "SometimesBigInt(", value(x), ")")
end

function value(x::SometimesBigInt)::Union{Int, BigInt}
x.value
end

Base.signbit(x::SometimesBigInt)=signbit(x.value)

//(x::SometimesBigInt, y) = Rational{SometimesBigInt}(x,1)//y
//(x::SometimesBigInt, y::Integer) = Rational{SometimesBigInt}(x,y)

function Base.:(*)(x::SometimesBigInt, y::SometimesBigInt)
  xv, yv = value(x), value(y)
  if xv isa Int && yv isa Int
    zv, overflowed = mul_with_overflow(xv, yv)
    if overflowed
    zv = big(xv) * big(yv)
    end
  else
    zv = xv * yv
  end
  SometimesBigInt(zv)
end

Base.:-(x::SometimesBigInt, y::SometimesBigInt)=x.value-y.value
Base.rem(x::SometimesBigInt, y::SometimesBigInt)=rem(x.value,y.value)
Base.div(x::SometimesBigInt, y::SometimesBigInt)=div(x.value,y.value)

convert(::Type{BigInt}, v::SometimesBigInt) = BigInt(value(v))
convert(::Type{SometimesBigInt}, a::Int)=SometimesBigInt(a)

Base.promote_rule(::Type{SometimesBigInt}, ::Type{Int}) = SometimesBigInt
Base.promote_rule(::Type{SometimesBigInt}, ::Type{BigInt}) = BigInt

const b0 = big"0"

struct SBig <: Integer
v::Int
b::BigInt
end

value(x::SBig) = isint(x) ? x.v : x.b

//(x::SBig, y) = value(x)//y
//(x::SBig, y::Integer) = value(x)//y

fitint(x) = typemin(Int) <= x <= typemax(Int)
isint(x::SBig) = (x.b === b0)
SBig(x::Int) = SBig(x, b0)
SBig(x) = fitint(x) ? SBig(convert(Int, x)) : SBig(0, x)
SBig(x::BigInt) = fitint(x) ? SBig(x % Int, b0) : SBig(0, convert(BigInt, x))

convert(::Type{BigInt}, v::SBig) = isint(v) ? BigInt(v.v) : v.b
convert(::Type{SBig}, v::BigInt) = fitint(v)isint(v) ? BigInt(v.v) : v.b

promote_type(SBig, Int) = SBig
promote_type(SBig, BigInt) = BigInt

Base.show(io::IO, x::SBig) = print(io, "SBig(", value(x), ")")

function Base.:(*)(x::SBig, y::SBig)
if isint(x)
isint(y) ? SBig(widemul(x.v, y.v)) : SBig(0, x.v * y.b)
else
isint(y) ? SBig(0, x.b * y.v) : SBig(0, x.b * y.b)
end
end

function out(s, t)
m0 = minimum(t).time / 1000
md = median(t).time / 1000
pr"%-25s(s)min=%10.3f(m0) μs, median=%10.3f(md) μs\n"
m0
end

function bench(p, nums)
xs = rand(nums, 1000)
ys = rand(nums, 1000)

pr"\n\%d(p)% chance of overflow\n"
t1 = out("Int mul:", @benchmark $xs .* $ys)

bigxs = big.(xs)
bigys = big.(ys)
t2 = out("BigInt mul:", @benchmark $bigxs .* $bigys)
pr"\%8.3f(t2/t1)x BigInt/Int\n"
pr"\%8.3f(t1/t2)x Int/BigInt\n"

sbigxs = SometimesBigInt.(xs)
sbigys = SometimesBigInt.(ys)
t3 = out("SometimesBigInt mul:", @benchmark $sbigxs .* $sbigys)
pr"\%8.3f(t3/t1)x SBI/Int\n"
pr"\%8.3f(t1/t2)x Int/SBI\n"
pr"\%8.3f(t3/t2)x SBI/BigInt\n"
pr"\%8.3f(t2/t3)x BigInt/SBI\n"

xbigxs = SBig.(xs)
xbigys = SBig.(ys)
t4 = out("SBig mul:", @benchmark $xbigxs .* $xbigys)
pr"\%8.3f(t4/t1)x SBig/Int\n"
pr"\%8.3f(t1/t2)x Int/SBig\n"
pr"\%8.3f(t4/t2)x SBig/BigInt\n"
pr"\%8.3f(t2/t4)x BigInt/SBig\n"
pr"\%8.3f(t4/t3)x SBig/SometimesBigInt\n"
pr"\%8.3f(t3/t4)x SometimesBigInt/SBig\n"

nothing

end

bench(1, (1:9..., 10^10))
bench(0, (1:10...,))
bench(100, ((10^10 .+ (1:10))...,))

function test_hm(rtype,rank)
mr = [rtype(1) // (i + j) for i in 1:rank, j in 1:rank]
one(mr) == mr * inv(mr)
end

println("test_hm(SometimesBigInt")
@btime test_hm(SometimesBigInt, 45)

println("test_hm(SBig")
@btime test_hm(SBig, 45)

```

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [March 14, 2020, 6:26pm UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884/63 "2020-03-14T18:26:27Z")

</div>

I was just trying to quickly test that code snippet as you asked me to do, I didn’t have time to add all of the stuff (that wasn’t in the code you had posted either)

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [March 14, 2020, 6:28pm UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884/64 "2020-03-14T18:28:58Z")

</div>

Also - you were the one who had `promote_type`, and I copied the code you gave exactly - so if there was an error, it was in that.

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2020, 8:43pm UTC](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884/65 "2020-03-14T20:43:58Z")

</div>

Sorry if I did not give the impression, but do I appreciate your code. That’s why I tried to debug it. Just realized that more work was required than I had time to do. I hope that someone more knowledgeable than us continues the work (this could be myself some months from now…). Anyway thanks a lot for your contribution to the discussion.

[Previous page](https://discourse.julialang.org/t/tonight-i-hated-julia-repl-and-overflows/34884.md?page=3)
