Hack to convert [Big]Ints to any Int type

Currently there are no to_i128 and to_u128 methods for BigInts.
This causes some problems for doing math in some instances.
See e.g. Integer root algorithm · Issue #13416 · crystal-lang/crystal · GitHub and
Ruby out performs Crystal significantly on this numerical algorithm - #15 by jzakiya

A really simple (and not too ugly) way to convert a number of one type to another is as follows.

If a = "1283984894429".to_big_i can fit into a smaller Int primitive you can do

x = typeof(1i64).new(a.to_s), and x = a will now be a Int64.

Here’s an actual use case from above issue.

lib LibGMP
  fun root = __gmpz_root(rop : MPZ*, op : MPZ*, n : ULong) : Int
end

def irootgmp(val, n : Int::Primitive)
  # error handling / range check not shown
  root = BigInt.new { |mpz| LibGMP.root(mpz, val.to_big_i, n) }
  typeof(val).new(root.to_s)
end

Here LibGMP.root(mpz, val.to_big_i, n) returns the nth integer root of val.
root is returned from the function as a BigInt, but is always smaller than val, and when doing actual math in an algorithm you usually want them to be the same type.

So typeof(val).new(root.to_s) returns root as the same type as val.
This gets around the current case where you can’t do BigInt.to_(u|i)128.
This has the added benefit of converting any larger Int type to a smaller one it can fit within (and obviously vice versa) without having to do explicit to_(u|i)xint.