Skip to content

Commit

Permalink
document and export widen. closes #6169
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Mar 15, 2014
1 parent 4bb7e7e commit a953172
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 14 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ Library improvements
* Ranges and arrays with the same elements are now unequal. This allows hashing
and comparing ranges to be faster. ([#5778])

* New function `widen` for widening numeric types and values ([#6169])

Deprecated or removed
---------------------

Expand Down Expand Up @@ -322,6 +324,7 @@ Deprecated or removed
[#5737]: https://github.com/JuliaLang/julia/issues/5737
[#6073]: https://github.com/JuliaLang/julia/issues/6073
[#5778]: https://github.com/JuliaLang/julia/issues/5778
[#6169]: https://github.com/JuliaLang/julia/issues/6169

Julia v0.2.0 Release Notes
==========================
Expand Down
4 changes: 2 additions & 2 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ function nextprod(a::Vector{Int}, x)
v = ones(Int, k) # current value of each counter
mx = [nextpow(ai,x) for ai in a] # maximum value of each counter
v[1] = mx[1] # start at first case that is >= x
p::morebits(Int) = mx[1] # initial value of product in this case
p::widen(Int) = mx[1] # initial value of product in this case
best = p
icarry = 1

Expand Down Expand Up @@ -573,7 +573,7 @@ function prevprod(a::Vector{Int}, x)
mx = [nextpow(ai,x) for ai in a] # allow each counter to exceed p (sentinel)
first = int(prevpow(a[1], x)) # start at best case in first factor
v[1] = first
p::morebits(Int) = first
p::widen(Int) = first
best = p
icarry = 1

Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,7 @@ export
super,
typeintersect,
typejoin,
widen,

# syntax
esc,
Expand Down
4 changes: 2 additions & 2 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ promote_rule(::Type{Float32}, ::Type{Float16}) = Float32
promote_rule(::Type{Float64}, ::Type{Float16}) = Float64
promote_rule(::Type{Float64}, ::Type{Float32}) = Float64

morebits(::Type{Float16}) = Float32
morebits(::Type{Float32}) = Float64
widen(::Type{Float16}) = Float32
widen(::Type{Float32}) = Float64

## floating point arithmetic ##

Expand Down
6 changes: 5 additions & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), ($),
ndigits, promote_rule, rem, show, isqrt, string, isprime, powermod,
widemul, sum, trailing_zeros, trailing_ones, count_ones, base, parseint,
serialize, deserialize, bin, oct, dec, hex, isequal, invmod,
prevpow2, nextpow2, ndigits0z
prevpow2, nextpow2, ndigits0z, widen

type BigInt <: Integer
alloc::Cint
Expand All @@ -34,6 +34,10 @@ function __init__()
cglobal(:jl_gc_counted_free))
end

widen(::Type{Int128}) = BigInt
widen(::Type{Uint128}) = BigInt
widen(::Type{BigInt}) = BigInt

BigInt(x::BigInt) = x
BigInt(s::String) = parseint(BigInt,s)

Expand Down
16 changes: 8 additions & 8 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,14 @@ sizeof(::Type{Uint64}) = 8
sizeof(::Type{Int128}) = 16
sizeof(::Type{Uint128}) = 16

morebits(::Type{Int8}) = Int16
morebits(::Type{Int16}) = Int32
morebits(::Type{Int32}) = Int64
morebits(::Type{Int64}) = Int128
morebits(::Type{Uint8}) = Uint16
morebits(::Type{Uint16}) = Uint32
morebits(::Type{Uint32}) = Uint64
morebits(::Type{Uint64}) = Uint128
widen(::Type{Int8}) = Int
widen(::Type{Int16}) = Int
widen(::Type{Int32}) = Int64
widen(::Type{Int64}) = Int128
widen(::Type{Uint8}) = Uint
widen(::Type{Uint16}) = Uint
widen(::Type{Uint32}) = Uint64
widen(::Type{Uint64}) = Uint128

## float to integer coercion ##

Expand Down
5 changes: 4 additions & 1 deletion base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import
itrunc, eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2,
serialize, deserialize, inf, nan, hash, cbrt, typemax, typemin,
realmin, realmax, get_rounding, set_rounding, maxintfloat
realmin, realmax, get_rounding, set_rounding, maxintfloat, widen

import Base.Math.lgamma_r

Expand All @@ -44,6 +44,9 @@ type BigFloat <: FloatingPoint
end
end

widen(::Type{Float64}) = BigFloat
widen(::Type{BigFloat}) = BigFloat

BigFloat(x::BigFloat) = x

for (fJ, fC) in ((:si,:Clong), (:ui,:Culong), (:d,:Float64))
Expand Down
2 changes: 2 additions & 0 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ oftype{T}(x::T,c) = convert(T,c)
zero(x) = oftype(x,0)
one(x) = oftype(x,1)

widen{T<:Number}(x::T) = convert(widen(T), x)

sizeof(T::Type) = error(string("size of type ",T," unknown"))
sizeof(T::DataType) = if isleaftype(T) T.size else error("type does not have a native size") end
sizeof(::Type{Symbol}) = error("type does not have a native size")
Expand Down
9 changes: 9 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,15 @@ All Objects

Convert ``y`` to the type of ``x``.

.. function:: widen(type | x)

If the argument is a type, return a "larger" type (for numeric types, this will be
a type with at least as much range and precision as the argument, and usually more).
Otherwise the argument ``x`` is converted to ``widen(typeof(x))``.

**Example**: ``widen(Int32) === Int64``
**Example**: ``widen(1.5f0) === 1.5``

.. function:: identity(x)

The identity function. Returns its argument.
Expand Down
9 changes: 9 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1763,3 +1763,12 @@ end
let g(x) = sqrt(x)
@test g(NaN) === NaN
end

# widen
@test widen(1.5f0) === 1.5
@test widen(int32(42)) === int64(42)
@test widen(Int8) === Int
@test widen(Float32) === Float64
## Note: this should change to e.g. Float128 at some point
@test widen(Float64) === BigFloat
@test widen(BigInt) === BigInt

3 comments on commit a953172

@StefanKarpinski
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make a stronger guarantee on this? If we had Int65 would it really be reasonable to return that as the widened type of Int64? A less ridiculous example would be if we had Float80, would it be reasonable to have widen(Float64) = Float80 even though you lose precision when multiplying two Float64 values as Float80?

@JeffBezanson
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I'd like a stronger guarantee, but I wasn't sure exactly what it'd be so I hedged :)

@StefanKarpinski
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that being able to multiply two values without losing any significant bits would be a good guarantee and the current rules do guarantee that as far as I can tell. For integers, guaranteeing that addition doesn't lose bits is easier, but of course for floating-point, addition is harder. My gut feeling is that wanting to do multiplication without losing bits is more common though.

Please sign in to comment.