diff --git a/base/abstractarray.jl b/base/abstractarray.jl index f946b1458a776..116053c11897a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -3405,7 +3405,7 @@ pushfirst!(A, a, b, c...) = pushfirst!(pushfirst!(A, c...), a, b) const hash_abstractarray_seed = UInt === UInt64 ? 0x7e2d6fb6448beb77 : 0xd4514ce5 function hash(A::AbstractArray, h::UInt) - h += hash_abstractarray_seed + h +%= hash_abstractarray_seed # Axes are themselves AbstractArrays, so hashing them directly would stack overflow # Instead hash the tuple of firsts and lasts along each dimension h = hash(map(first, axes(A)), h) diff --git a/base/abstractset.jl b/base/abstractset.jl index 5d0d65dad2de6..fe8f015254d43 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -93,7 +93,9 @@ max_values(T::Union{map(X -> Type{X}, BitIntegerSmall_types)...}) = 1 << (8*size function max_values(T::Union) a = max_values(T.a)::Int b = max_values(T.b)::Int - return max(a, b, a + b) + r, o = add_with_overflow(a, b) + o && return typemax(Int) + return r end max_values(::Type{Bool}) = 2 max_values(::Type{Nothing}) = 1 diff --git a/base/bool.jl b/base/bool.jl index d7dcf76caa91b..fdfde93e8dd7c 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -160,12 +160,17 @@ isone(x::Bool) = x ## do arithmetic as Int ## -+(x::Bool) = Int(x) --(x::Bool) = -Int(x) - -+(x::Bool, y::Bool) = Int(x) + Int(y) --(x::Bool, y::Bool) = Int(x) - Int(y) ++(x::Bool) = Int(x) ++%(x::Bool) = Int(x) +-(x::Bool) = -%(Int(x)) +-%(x::Bool) = -%(Int(x)) + ++(x::Bool, y::Bool) = Int(x) +% Int(y) +-(x::Bool, y::Bool) = Int(x) -% Int(y) ++%(x::Bool, y::Bool) = Int(x) +% Int(y) +-%(x::Bool, y::Bool) = Int(x) -% Int(y) *(x::Bool, y::Bool) = x & y +*%(x::Bool, y::Bool) = x & y ^(x::Bool, y::Bool) = x | !y ^(x::Integer, y::Bool) = ifelse(y, x, one(x)) diff --git a/base/char.jl b/base/char.jl index 08d661c41de56..6ff2b86a734ec 100644 --- a/base/char.jl +++ b/base/char.jl @@ -223,8 +223,9 @@ isless(x::AbstractChar, y::AbstractChar) = isless(Char(x), Char(y)) hash(x::AbstractChar, h::UInt) = hash(Char(x), h) widen(::Type{T}) where {T<:AbstractChar} = T +@inline -%(x::AbstractChar, y::AbstractChar) = Int(x) -% Int(y) @inline -(x::AbstractChar, y::AbstractChar) = Int(x) - Int(y) -@inline function -(x::T, y::Integer) where {T<:AbstractChar} +@inline function -%(x::T, y::Integer) where {T<:AbstractChar} if x isa Char u = Int32((bitcast(UInt32, x) >> 24) % Int8) if u >= 0 # inline the runtime fast path @@ -234,7 +235,7 @@ widen(::Type{T}) where {T<:AbstractChar} = T end return T(Int32(x) - Int32(y)) end -@inline function +(x::T, y::Integer) where {T<:AbstractChar} +@inline function +%(x::T, y::Integer) where {T<:AbstractChar} if x isa Char u = Int32((bitcast(UInt32, x) >> 24) % Int8) if u >= 0 # inline the runtime fast path @@ -244,7 +245,11 @@ end end return T(Int32(x) + Int32(y)) end -@inline +(x::Integer, y::AbstractChar) = y + x +@inline +%(x::Integer, y::AbstractChar) = y + x + +-(x::AbstractChar, y::Integer) = x -% y ++(x::AbstractChar, y::Integer) = x +% y ++(x::Integer, y::AbstractChar) = x +% y # `print` should output UTF-8 by default for all AbstractChar types. # (Packages may implement other IO subtypes to specify different encodings.) diff --git a/base/checked.jl b/base/checked.jl index d5b4112397e84..5fa9c9fd019fa 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -21,7 +21,7 @@ import Core.Intrinsics: checked_srem_int, checked_uadd_int, checked_usub_int, checked_umul_int, checked_udiv_int, checked_urem_int -import ..no_op_err, ..@inline, ..@noinline, ..checked_length +import ..no_op_err, ..@inline, ..@noinline, ..checked_length, ..BitInteger # define promotion behavior for checked operations checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...) @@ -98,7 +98,7 @@ throw_overflowerr_negation(x) = (@noinline; throw(OverflowError(Base.invokelatest(string, "checked arithmetic: cannot compute -x for x = ", x, "::", typeof(x))))) if BrokenSignedInt != Union{} function checked_neg(x::BrokenSignedInt) - r = -x + r = -%(x) (x<0) & (r<0) && throw_overflowerr_negation(x) r end @@ -140,11 +140,11 @@ Calculates `r = x+y`, with the flag `f` indicating whether overflow has occurred function add_with_overflow end add_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_sadd_int(x, y) add_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_uadd_int(x, y) -add_with_overflow(x::Bool, y::Bool) = (x+y, false) +add_with_overflow(x::Bool, y::Bool) = (x +% y, false) if BrokenSignedInt != Union{} function add_with_overflow(x::T, y::T) where T<:BrokenSignedInt - r = x + y + r = x +% y # x and y have the same sign, and the result has a different sign f = (x<0) == (y<0) != (r<0) r, f @@ -154,7 +154,7 @@ if BrokenUnsignedInt != Union{} function add_with_overflow(x::T, y::T) where T<:BrokenUnsignedInt # x + y > typemax(T) # Note: ~y == -y-1 - x + y, x > ~y + x +% y, x > ~y end end @@ -171,7 +171,11 @@ The overflow protection may impose a perceptible performance penalty. """ function checked_add(x::T, y::T) where T<:Integer @inline - z, b = add_with_overflow(x, y) + zb = add_with_overflow(x, y) + # Avoid use of tuple destructuring, which uses aritmetic internally, + # so that this can be used as a replacement for + + z = getfield(zb, 1) + b = getfield(zb, 2) b && throw_overflowerr_binaryop(:+, x, y) z end @@ -206,7 +210,7 @@ sub_with_overflow(x::Bool, y::Bool) = (x-y, false) if BrokenSignedInt != Union{} function sub_with_overflow(x::T, y::T) where T<:BrokenSignedInt - r = x - y + r = x -% y # x and y have different signs, and the result has a different sign than x f = (x<0) != (y<0) == (r<0) r, f @@ -215,7 +219,7 @@ end if BrokenUnsignedInt != Union{} function sub_with_overflow(x::T, y::T) where T<:BrokenUnsignedInt # x - y < 0 - x - y, x < y + x -% y, x < y end end @@ -242,7 +246,7 @@ Calculates `r = x*y`, with the flag `f` indicating whether overflow has occurred function mul_with_overflow end mul_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_smul_int(x, y) mul_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_umul_int(x, y) -mul_with_overflow(x::Bool, y::Bool) = (x*y, false) +mul_with_overflow(x::Bool, y::Bool) = (x *% y, false) if BrokenSignedIntMul != Union{} && BrokenSignedIntMul != Int128 function mul_with_overflow(x::T, y::T) where T<:BrokenSignedIntMul @@ -273,14 +277,14 @@ if Int128 <: BrokenSignedIntMul else false end - x*y, f + x *% y, f end end if UInt128 <: BrokenUnsignedIntMul # Avoid BigInt function mul_with_overflow(x::T, y::T) where T<:UInt128 # x * y > typemax(T) - x * y, y > 0 && x > fld(typemax(T), y) + x *% y, y > 0 && x > fld(typemax(T), y) end end diff --git a/base/deprecated.jl b/base/deprecated.jl index 1b661716cc2d9..29dec793d980b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -384,3 +384,14 @@ macro pure(ex) end # END 1.10 deprecations + +# BEGIN 1.11 deprecations + +# These operators are new in 1.11, but these fallback methods are added for +# compatibility while packages adjust to defining both operators, to allow +# Base and other packages to start using these. +*%(a::T, b::T) where {T} = *(a, b) ++%(a::T, b::T) where {T} = +(a, b) +-%(a::T, b::T) where {T} = -(a, b) + +# END 1.11 deprecations diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index fd8c35a5fdf76..21b947c8c9faf 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -2644,6 +2644,30 @@ julia> +(1, 20, 4) """ (+)(x, y...) +""" + +%(x::Integer, y::Integer...) + +Addition operator with semantic wrapping. In the default Julia environment, this +is equivalent to the regular addition operator `+`. However, some users may choose to overwrite +`+` in their local environment to perform checked arithmetic instead (e.g. using +[`Experimental.@make_all_arithmetic_checked`](@ref)). The `+%` operator may be used to indicate +that wrapping behavior is semantically expected and correct and should thus be exempted from +any opt-in overflow checking. + +# Examples +```jldoctest +julia> 1 +% 20 +% 4 +25 + +julia> +%(1, 20, 4) +25 + +julia> typemax(Int) +% 1 +-9223372036854775808 +``` +""" +(+%)(x, y...) + """ -(x) @@ -2683,6 +2707,27 @@ julia> -(2, 4.5) """ -(x, y) +""" + -%(x::Integer, y::Integer...) + +Subtraction operator with semantic wrapping. In the default Julia environment, this +is equivalent to the regular subtraction operator `-`. However, some users may choose to overwrite +`-` in their local environment to perform checked arithmetic instead (e.g. using +[`Experimental.@make_all_arithmetic_checked`](@ref)). The `-%` operator may be used to indicate +that wrapping behavior is semantically expected and correct and should thus be exempted from +any opt-in overflow checking. + +# Examples +```jldoctest +julia> 2 -% 3 +-1 + +julia> -(typemin(Int)) +-9223372036854775808 +``` +""" +(-%)(x, y...) + """ *(x, y...) @@ -2699,6 +2744,30 @@ julia> *(2, 7, 8) """ (*)(x, y...) +""" + *%(x::Integer, y::Integer, z::Integer...) + +Multiplication operator with semantic wrapping. In the default Julia environment, this +is equivalent to the regular multiplication operator `*`. However, some users may choose to overwrite +`*` in their local environment to perform checked arithmetic instead (e.g. using +[`Experimental.@make_all_arithmetic_checked`](@ref)). The `*%` operator may be used to indicate +that wrapping behavior is semantically expected and correct and should thus be exempted from +any opt-in overflow checking. + +# Examples +```jldoctest +julia> 2 *% 7 *% 8 +112 + +julia> *(2, 7, 8) +112 + +julia> 0xff *% 0xff +0x01 +``` +""" +(*%)(x, y, z...) + """ /(x, y) diff --git a/base/experimental.jl b/base/experimental.jl index cc8d368023b49..cef0b1bbc4fb6 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -368,4 +368,25 @@ adding them to the global method table. """ :@MethodTable +""" + Experimental.@make_all_arithmetic_checked() + +This macro defines methods that overwrite the base definition of basic arithmetic (+,-,*), +to use their checked variants instead. Explicitly overflowing arithmetic operators (+%,-%,*%) +are not affected. + +!!! warning + This macro is temporary and will likely be replaced by a more complete mechanism in the + future. It is subject to change or removal without notice. +""" +macro make_all_arithmetic_checked() + esc(quote + Base.:(-)(x::BitInteger) = Base.Checked.checked_neg(x) + Base.:(-)(x::T, y::T) where {T<:BitInteger} = Base.Checked.checked_sub(x, y) + Base.:(+)(x::T, y::T) where {T<:BitInteger} = Base.Checked.checked_add(x, y) + Base.:(*)(x::T, y::T) where {T<:BitInteger} = Base.Checked.checked_mul(x, y) + Base.:(-)(x::AbstractChar, y::AbstractChar) = Int(x) - Int(y) + end) +end + end diff --git a/base/exports.jl b/base/exports.jl index 0959fa1c391e2..14bf86a8247c7 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -183,8 +183,11 @@ export ÷, &, *, + *%, +, + +%, -, + -%, /, //, <, diff --git a/base/filesystem.jl b/base/filesystem.jl index d291dd3b31630..61f506d5c508e 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -200,9 +200,10 @@ end function read(f::File, ::Type{Char}) b0 = read(f, UInt8) - l = 0x08 * (0x04 - UInt8(leading_ones(b0))) + lo = UInt8(leading_ones(b0)) c = UInt32(b0) << 24 - if l ≤ 0x10 + if 0x02 ≤ lo ≤ 0x04 + l = 0x08 * (0x04 - lo) s = 16 while s ≥ l && !eof(f) # this works around lack of peek(::File) diff --git a/base/float.jl b/base/float.jl index fc4cef09b48ad..f2a27e7a6dcf1 100644 --- a/base/float.jl +++ b/base/float.jl @@ -650,7 +650,7 @@ function hash(x::Float64, h::UInt) elseif isnan(x) return hx_NaN ⊻ h # NaN does not have a stable bit pattern end - return hash_uint64(bitcast(UInt64, x)) - 3h + return hash_uint64(bitcast(UInt64, x)) -% (3 *% h) end hash(x::Float32, h::UInt) = hash(Float64(x), h) @@ -665,7 +665,7 @@ function hash(x::Float16, h::UInt) elseif isnan(x) return hx_NaN ⊻ h # NaN does not have a stable bit pattern end - return hash_uint64(bitcast(UInt64, Float64(x))) - 3h + return hash_uint64(bitcast(UInt64, Float64(x))) - (3 *% h) end ## generic hashing for rational values ## diff --git a/base/gmp.jl b/base/gmp.jl index 8a1451be7a590..6699362f98973 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -4,7 +4,7 @@ module GMP export BigInt -import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, nand, nor, +import .Base: *, *%, +, +%, -, -%, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, nand, nor, binomial, cmp, convert, div, divrem, factorial, cld, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, prod, trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal, @@ -334,7 +334,7 @@ function BigInt(x::Integer) isbits(x) && typemin(Clong) <= x <= typemax(Clong) && return BigInt((x % Clong)::Clong) nd = ndigits(x, base=2) z = MPZ.realloc2(nd) - ux = unsigned(x < 0 ? -x : x) + ux = unsigned(x < 0 ? -%(x) : x) size = 0 limbnbits = sizeof(Limb) << 3 while nd > 0 @@ -494,6 +494,7 @@ big(n::Integer) = convert(BigInt, n) # Binary ops for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul), + (:+%, :add), (:-%,:sub), (:*%, :mul), (:mod, :fdiv_r), (:rem, :tdiv_r), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @@ -552,10 +553,10 @@ end -(x::BigInt, c::CulongMax) = MPZ.sub_ui(x, c) -(c::CulongMax, x::BigInt) = MPZ.ui_sub(c, x) -+(x::BigInt, c::ClongMax) = c < 0 ? -(x, -(c % Culong)) : x + convert(Culong, c) -+(c::ClongMax, x::BigInt) = c < 0 ? -(x, -(c % Culong)) : x + convert(Culong, c) --(x::BigInt, c::ClongMax) = c < 0 ? +(x, -(c % Culong)) : -(x, convert(Culong, c)) --(c::ClongMax, x::BigInt) = c < 0 ? -(x + -(c % Culong)) : -(convert(Culong, c), x) ++(x::BigInt, c::ClongMax) = c < 0 ? -(x, -%(c % Culong)) : x + convert(Culong, c) ++(c::ClongMax, x::BigInt) = c < 0 ? -(x, -%(c % Culong)) : x + convert(Culong, c) +-(x::BigInt, c::ClongMax) = c < 0 ? +(x, -%(c % Culong)) : -(x, convert(Culong, c)) +-(c::ClongMax, x::BigInt) = c < 0 ? -(x + -%(c % Culong)) : -(convert(Culong, c), x) *(x::BigInt, c::CulongMax) = MPZ.mul_ui(x, c) *(c::CulongMax, x::BigInt) = x * c @@ -873,7 +874,7 @@ if Limb === UInt64 === UInt return hash(unsafe_load(ptr), h) elseif sz == -1 limb = unsafe_load(ptr) - limb <= typemin(Int) % UInt && return hash(-(limb % Int), h) + limb <= typemin(Int) % UInt && return hash(-%(limb % Int), h) end pow = trailing_zeros(x) nd = Base.ndigits0z(x, 2) diff --git a/base/hashing.jl b/base/hashing.jl index 5dbae09123bd6..d325b30034140 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -29,11 +29,11 @@ See also: [`objectid`](@ref), [`Dict`](@ref), [`Set`](@ref). """ hash(x::Any) = hash(x, zero(UInt)) hash(w::WeakRef, h::UInt) = hash(w.value, h) -hash(T::Type, h::UInt) = hash_uint(3h - ccall(:jl_type_hash, UInt, (Any,), T)) +hash(T::Type, h::UInt) = hash_uint(3 *% h -% ccall(:jl_type_hash, UInt, (Any,), T)) ## hashing general objects ## -hash(@nospecialize(x), h::UInt) = hash_uint(3h - objectid(x)) +hash(@nospecialize(x), h::UInt) = hash_uint(3 *% h -% objectid(x)) hash(x::Symbol) = objectid(x) @@ -41,34 +41,34 @@ hash(x::Symbol) = objectid(x) function hash_64_64(n::UInt64) a::UInt64 = n - a = ~a + a << 21 + a = ~a +% a << 21 a = a ⊻ a >> 24 - a = a + a << 3 + a << 8 + a = a +% a << 3 +% a << 8 a = a ⊻ a >> 14 - a = a + a << 2 + a << 4 + a = a +% a << 2 +% a << 4 a = a ⊻ a >> 28 - a = a + a << 31 + a = a +% a << 31 return a end function hash_64_32(n::UInt64) a::UInt64 = n - a = ~a + a << 18 + a = ~a +% a << 18 a = a ⊻ a >> 31 a = a * 21 a = a ⊻ a >> 11 - a = a + a << 6 + a = a +% a << 6 a = a ⊻ a >> 22 return a % UInt32 end function hash_32_32(n::UInt32) a::UInt32 = n - a = a + 0x7ed55d16 + a << 12 + a = a +% 0x7ed55d16 +% a << 12 a = a ⊻ 0xc761c23c ⊻ a >> 19 - a = a + 0x165667b1 + a << 5 - a = a + 0xd3a2646c ⊻ a << 9 - a = a + 0xfd7046c5 + a << 3 + a = a +% 0x165667b1 +% a << 5 + a = a +% 0xd3a2646c ⊻ a << 9 + a = a +% 0xfd7046c5 +% a << 3 a = a ⊻ 0xb55a4f09 ⊻ a >> 16 return a end @@ -83,8 +83,8 @@ end ## efficient value-based hashing of integers ## -hash(x::Int64, h::UInt) = hash_uint64(bitcast(UInt64, x)) - 3h -hash(x::UInt64, h::UInt) = hash_uint64(x) - 3h +hash(x::Int64, h::UInt) = hash_uint64(bitcast(UInt64, x)) -% (3 *% h) +hash(x::UInt64, h::UInt) = hash_uint64(x) -% (3 *% h) hash(x::Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32}, h::UInt) = hash(Int64(x), h) function hash_integer(n::Integer, h::UInt) @@ -101,11 +101,11 @@ end ## symbol & expression hashing ## if UInt === UInt64 - hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x83c7900696d26dc6)) - hash(x::QuoteNode, h::UInt) = hash(x.value, h + 0x2c97bf8b3de87020) + hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h +% 0x83c7900696d26dc6)) + hash(x::QuoteNode, h::UInt) = hash(x.value, h +% 0x2c97bf8b3de87020) else - hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x96d26dc6)) - hash(x::QuoteNode, h::UInt) = hash(x.value, h + 0x469d72af) + hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h +% 0x96d26dc6)) + hash(x::QuoteNode, h::UInt) = hash(x.value, h +% 0x469d72af) end ## hashing strings ## @@ -114,6 +114,6 @@ const memhash = UInt === UInt64 ? :memhash_seed : :memhash32_seed const memhash_seed = UInt === UInt64 ? 0x71e729fd56419c81 : 0x56419c81 @assume_effects :total function hash(s::String, h::UInt) - h += memhash_seed - ccall(memhash, UInt, (Ptr{UInt8}, Csize_t, UInt32), s, sizeof(s), h % UInt32) + h + h +%= memhash_seed + ccall(memhash, UInt, (Ptr{UInt8}, Csize_t, UInt32), s, sizeof(s), h % UInt32) +% h end diff --git a/base/int.jl b/base/int.jl index 4b2f542bba788..17cba868a0385 100644 --- a/base/int.jl +++ b/base/int.jl @@ -87,6 +87,11 @@ signed(::Type{T}) where {T<:Signed} = T (+)(x::T, y::T) where {T<:BitInteger} = add_int(x, y) (*)(x::T, y::T) where {T<:BitInteger} = mul_int(x, y) +(-%)(x::BitInteger) = neg_int(x) +(-%)(x::T, y::T) where {T<:BitInteger} = sub_int(x, y) +(+%)(x::T, y::T) where {T<:BitInteger} = add_int(x, y) +(*%)(x::T, y::T) where {T<:BitInteger} = mul_int(x, y) + negate(x) = -x negate(x::Unsigned) = -convert(Signed, x) #widenegate(x) = -convert(widen(signed(typeof(x))), x) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 1b007700f4331..711cf12c22a12 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -272,7 +272,7 @@ to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x) "\nMake x a float matrix by adding a zero decimal ", "(e.g., [2.0 1.0;1.0 0.0]^", p, " instead of [2 1;1 0]^", p, ")", "or write float(x)^", p, " or Rational.(x)^", p, "."))) -@assume_effects :terminates_locally function power_by_squaring(x_, p::Integer) +@assume_effects :terminates_locally function power_by_squaring(*, x_, p::Integer) x = to_power_type(x_) if p == 1 return copy(x) @@ -301,6 +301,7 @@ to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x) end return y end +power_by_squaring(x_, p::Integer) = power_by_squaring(*, x_, p) power_by_squaring(x::Bool, p::Unsigned) = ((p==0) | x) function power_by_squaring(x::Bool, p::Integer) p < 0 && !x && throw_domerr_powbysq(x, p) @@ -711,7 +712,7 @@ function bin(x::Unsigned, pad::Int, neg::Bool) i = n @inbounds while i >= 4 b = UInt32((x % UInt8)::UInt8) - d = 0x30303030 + ((b * 0x08040201) >> 0x3) & 0x01010101 + d = 0x30303030 +% ((b *% 0x08040201) >> 0x3) & 0x01010101 a[i-3] = (d >> 0x00) % UInt8 a[i-2] = (d >> 0x08) % UInt8 a[i-1] = (d >> 0x10) % UInt8 @@ -874,7 +875,7 @@ function bitstring(x::T) where {T} i = sz @inbounds while i >= 4 b = UInt32(sizeof(T) == 1 ? bitcast(UInt8, x) : trunc_int(UInt8, x)) - d = 0x30303030 + ((b * 0x08040201) >> 0x3) & 0x01010101 + d = 0x30303030 +% ((b *% 0x08040201) >> 0x3) & 0x01010101 str[i-3] = (d >> 0x00) % UInt8 str[i-2] = (d >> 0x08) % UInt8 str[i-1] = (d >> 0x10) % UInt8 diff --git a/base/io.jl b/base/io.jl index be43a954c621e..ddcb4377f9194 100644 --- a/base/io.jl +++ b/base/io.jl @@ -884,9 +884,10 @@ end function read(io::IO, ::Type{Char}) b0 = read(io, UInt8)::UInt8 - l = 0x08 * (0x04 - UInt8(leading_ones(b0))) + lo = UInt8(leading_ones(b0)) c = UInt32(b0) << 24 - if l ≤ 0x10 + if 0x02 ≤ lo ≤ 0x04 + l = 0x08 * (0x04 - lo) s = 16 while s ≥ l && !eof(io)::Bool peek(io) & 0xc0 == 0x80 || break diff --git a/base/multidimensional.jl b/base/multidimensional.jl index f793df068ec5a..dc8c1e9559f45 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -138,7 +138,7 @@ module IteratorsMD # hashing const cartindexhash_seed = UInt == UInt64 ? 0xd60ca92f8284b8b0 : 0xf2ea7c2e function Base.hash(ci::CartesianIndex, h::UInt) - h += cartindexhash_seed + h +%= cartindexhash_seed for i in ci.I h = hash(i, h) end diff --git a/base/number.jl b/base/number.jl index 923fc907d4038..c4dfb8997f9f1 100644 --- a/base/number.jl +++ b/base/number.jl @@ -202,7 +202,7 @@ julia> flipsign(5, -3) -5 ``` """ -flipsign(x::Real, y::Real) = ifelse(signbit(y), -x, +x) # the + is for type-stability on Bool +flipsign(x::Real, y::Real) = signbit(y) ? -x : +x # the + is for type-stability on Bool """ copysign(x, y) -> z @@ -218,7 +218,7 @@ julia> copysign(-1, 2) 1 ``` """ -copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, +x) +copysign(x::Real, y::Real) = signbit(x)!=signbit(y) ? -x : +x conj(x::Real) = x transpose(x::Number) = x diff --git a/base/operators.jl b/base/operators.jl index 3f0f8bc49b164..08af5d4de81c8 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -579,7 +579,7 @@ function afoldl(op, a, bs...) end setfield!(typeof(afoldl).name.mt, :max_args, 34, :monotonic) -for op in (:+, :*, :&, :|, :xor, :min, :max, :kron) +for op in (:+, :(+%), :*, :(*%), :&, :|, :xor, :min, :max, :kron) @eval begin # note: these definitions must not cause a dispatch loop when +(a,b) is # not defined, and must only try to call 2-argument definitions, so diff --git a/base/pkgid.jl b/base/pkgid.jl index 20d9de559b334..495af7f971e6d 100644 --- a/base/pkgid.jl +++ b/base/pkgid.jl @@ -17,7 +17,7 @@ end ==(a::PkgId, b::PkgId) = a.uuid == b.uuid && a.name == b.name function hash(pkg::PkgId, h::UInt) - h += 0xc9f248583a0ca36c % UInt + h +%= 0xc9f248583a0ca36c % UInt h = hash(pkg.uuid, h) h = hash(pkg.name, h) return h diff --git a/base/pointer.jl b/base/pointer.jl index a47f1e38edb9b..fb8a41c3ae2ab 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -278,6 +278,7 @@ isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y ==(x::Ptr, y::Ptr) = UInt(x) == UInt(y) <(x::Ptr, y::Ptr) = UInt(x) < UInt(y) -(x::Ptr, y::Ptr) = UInt(x) - UInt(y) +-%(x::Ptr, y::Ptr) = UInt(x) -% UInt(y) +(x::Ptr, y::Integer) = oftype(x, add_ptr(UInt(x), (y % UInt) % UInt)) -(x::Ptr, y::Integer) = oftype(x, sub_ptr(UInt(x), (y % UInt) % UInt)) diff --git a/base/promotion.jl b/base/promotion.jl index 6e32bd7a42efa..aa252aac4fe42 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -424,6 +424,10 @@ end -(x::Number, y::Number) = -(promote(x,y)...) /(x::Number, y::Number) = /(promote(x,y)...) ++%(x::Number, y::Number) = +%(promote(x,y)...) +*%(x::Number, y::Number) = *%(promote(x,y)...) +-%(x::Number, y::Number) = -%(promote(x,y)...) + """ ^(x, y) diff --git a/base/range.jl b/base/range.jl index e8ffe10e2ba7f..2c7f8f82f5e65 100644 --- a/base/range.jl +++ b/base/range.jl @@ -345,7 +345,7 @@ function steprange_last(start, step, stop)::typeof(stop) else # Compute absolute value of difference between `start` and `stop` # (to simplify handling both signed and unsigned T and checking for signed overflow): - absdiff, absstep = stop > start ? (stop - start, step) : (start - stop, -step) + absdiff, absstep = stop > start ? (stop -% start, step) : (start -% stop, -step) # Compute remainder as a nonnegative number: if absdiff isa Signed && absdiff < zero(absdiff) @@ -997,7 +997,7 @@ function getindex(r::AbstractUnitRange, s::AbstractUnitRange{T}) where {T<:Integ f = first(r) start = oftype(f, f + first(s) - firstindex(r)) len = length(s) - stop = oftype(f, start + (len - oneunit(len))) + stop = start + oftype(f, len - oneunit(len)) return range(start, stop) end end diff --git a/base/rational.jl b/base/rational.jl index 5b9ff99ea7a6c..f4e2bc4158834 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -317,7 +317,16 @@ function +(x::Rational, y::Rational) return xp end xd, yd = divgcd(promote(x.den, y.den)...) - Rational(checked_add(checked_mul(x.num,yd), checked_mul(y.num,xd)), checked_mul(x.den,yd)) + Rational(checked_add(checked_mul(x.num, yd), checked_mul(y.num, xd)), checked_mul(x.den, yd)) +end + +function +%(x::Rational, y::Rational) + xp, yp = promote(x, y)::NTuple{2,Rational} + if isinf(x) && x == y + return xp + end + xd, yd = divgcd(promote(x.den, y.den)...) + Rational(+%(+*(x.num,yd), +*(y.num,xd)), +*(x.den,yd)) end function -(x::Rational, y::Rational) @@ -326,7 +335,16 @@ function -(x::Rational, y::Rational) return xp end xd, yd = divgcd(promote(x.den, y.den)...) - Rational(checked_sub(checked_mul(x.num,yd), checked_mul(y.num,xd)), checked_mul(x.den,yd)) + Rational(checked_sub(checked_mul(x.num, yd), checked_mul(y.num, xd)), checked_mul(x.den, yd)) +end + +function -%(x::Rational, y::Rational) + xp, yp = promote(x, y)::NTuple{2,Rational} + if isinf(x) && x == -y + return xp + end + xd, yd = divgcd(promote(x.den, y.den)...) + Rational(-%(*%(x.num, yd), *%(y.num, xd)), *%(x.den, yd)) end for (op,chop) in ((:rem,:rem), (:mod,:mod)) diff --git a/base/regex.jl b/base/regex.jl index 109724903823f..b9bcba8490b64 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -417,7 +417,7 @@ function match(re::Regex, str::Union{SubString{String}, String}, idx::Integer, cap = Union{Nothing,SubString{String}}[unsafe_load(p,2i+1) == PCRE.UNSET ? nothing : SubString(str, unsafe_load(p,2i+1)+1, prevind(str, unsafe_load(p,2i+2)+1)) for i=1:n] - off = Int[ unsafe_load(p,2i+1)+1 for i=1:n ] + off = Int[ unsafe_load(p,2i+1) == PCRE.UNSET ? 0 : unsafe_load(p,2i+1)+1 for i=1:n ] result = RegexMatch(mat, cap, unsafe_load(p,1)+1, off, re) PCRE.free_match_data(data) return result diff --git a/base/ryu/shortest.jl b/base/ryu/shortest.jl index aaa62ba33c703..ad945abf0304d 100644 --- a/base/ryu/shortest.jl +++ b/base/ryu/shortest.jl @@ -14,7 +14,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. # mf * 2^ef == f mf = (one(U) << significand_bits(T)) | m ef = e - exponent_bias(T) - significand_bits(T) - f_isinteger = mf & ((one(U) << -ef) - one(U)) == 0 + f_isinteger = mf & ((one(U) << -ef) -% one(U)) == 0 if ef > 0 || ef < -Base.significand_bits(T) || !f_isinteger # fixup subnormals @@ -56,7 +56,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. end end if q <= qinvbound(T) - if ((v % UInt32) - 5 * div(v, 5)) == 0 + if ((v % UInt32) -% 5 * div(v, 5)) == 0 b_allzero = pow5(v, q) elseif mf_iseven a_allzero = pow5(u, q) @@ -99,9 +99,9 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. if c_div10 <= a_div10 break end - a_mod10 = (a % UInt32) - UInt32(10) * (a_div10 % UInt32) + a_mod10 = (a % UInt32) -% UInt32(10) *% (a_div10 % UInt32) b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) a_allzero &= a_mod10 == 0 b_allzero &= b_lastdigit == 0 b_lastdigit = b_mod10 % UInt8 @@ -113,13 +113,13 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. if a_allzero while true a_div10 = div(a, 10) - a_mod10 = (a % UInt32) - UInt32(10) * (a_div10 % UInt32) + a_mod10 = (a % UInt32) -% UInt32(10) *% (a_div10 % UInt32) if a_mod10 != 0 && (maxsignif === nothing || b < maxsignif) break end c_div10 = div(c, 10) b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) b_allzero &= b_lastdigit == 0 b_lastdigit = b_mod10 % UInt8 b = b_div10 @@ -139,7 +139,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. a_div100 = div(a, 100) if c_div100 > a_div100 b_div100 = div(b, 100) - b_mod100 = (b % UInt32) - UInt32(100) * (b_div100 % UInt32) + b_mod100 = (b % UInt32) -% UInt32(100) *% (b_div100 % UInt32) roundup = b_mod100 >= 50 b = b_div100 c = c_div100 @@ -153,7 +153,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. break end b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) roundup = b_mod10 >= 5 b = b_div10 c = c_div10 @@ -166,7 +166,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. # reduce to max significant digits while true b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) if b <= maxsignif break end @@ -180,7 +180,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. # remove trailing zeros while true b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) if b_mod10 != 0 break end @@ -200,7 +200,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. # reduce to max significant digits while true b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) if b <= maxsignif break end @@ -213,7 +213,7 @@ integer. If a `maxsignif` argument is provided, then `b < maxsignif`. end while true b_div10 = div(b, 10) - b_mod10 = (b % UInt32) - UInt32(10) * (b_div10 % UInt32) + b_mod10 = (b % UInt32) -% UInt32(10) *% (b_div10 % UInt32) if b_mod10 != 0 break end @@ -353,7 +353,7 @@ function writeshortest(buf::Vector{UInt8}, pos, x::T, ptr2 = pointer(DIGIT_TABLE) if (output >> 32) != 0 q = output ÷ 100000000 - output2 = (output % UInt32) - UInt32(100000000) * (q % UInt32) + output2 = (output % UInt32) -% UInt32(100000000) *% (q % UInt32) output = q c = output2 % UInt32(10000) diff --git a/base/ryu/utils.jl b/base/ryu/utils.jl index f5a88c057e2b3..fd2909e3167bf 100644 --- a/base/ryu/utils.jl +++ b/base/ryu/utils.jl @@ -61,7 +61,23 @@ lengthforindex(idx) = div(((Int64(16 * idx) * 1292913986) >> 32) + 1 + 16 + 8, 9 Return `true` if `5^p` is a divisor of `x`. """ -pow5(x, p) = x % (UInt64(5)^p) == 0 +function pow5(x, p) + # Assumptions: + # 0 < x < (1 << 53) + # 0 <= p <= 308 + wrapped_pow = Base.power_by_squaring(*%, UInt64(5), p) + + # We are using wrapping arithmetic here, which can overflow, but we get the right answer anyway + # by the following argument (#47511): + # 1. False Negative + # No overflow occurs unless big(5)^p > typemax(UInt64), but typemax(UInt64) > (1 << 53), so + # z is never divisible by big(5)^p. QED. + # 2. False Positive + # We ask ∃ m2, p s.t. big(5)^p && m2 % wrapped_pow == 0. + # By exhaustive checking `all(p->UInt64(5)^p > 1<<53, 28:308)`, so there does not exist any such + # `m2` that satiesfies our assumptions above. QED. + x % wrapped_pow == 0 +end """ Ryu.pow2(x, p) @@ -166,6 +182,14 @@ Compute `pHi = (a*b)>>128` where `b = bLo + bHi<<64`. """ umul256_hi(a, bHi, bLo) = umul256(a, bHi, bLo)[2] +function mod1e9(v::UInt128) + # TODO: Fix LLVM to perform this optimization itself on 128 bit integers + # return (v % 10^9) % UInt32 + multiplied = umul256_hi(v, 0x89705F4136B4A597, 0x31680A88F8953031) + shifted = (multiplied >> 29) % UInt32 + return (v % UInt32) -% UInt32(1000000000) *% shifted +end + """ Ryu.mulshiftmod1e9(m, mula, mulb, mulc, j)::UInt32 @@ -178,9 +202,7 @@ function mulshiftmod1e9(m, mula, mulb, mulc, j) mid = b1 + ((b0 >> 64) % UInt64) s1 = b2 + ((mid >> 64) % UInt64) v = s1 >> (j - 128) - multiplied = umul256_hi(v, 0x89705F4136B4A597, 0x31680A88F8953031) - shifted = (multiplied >> 29) % UInt32 - return (v % UInt32) - UInt32(1000000000) * shifted + return mod1e9(v) end function append_sign(x, plus, space, buf, pos) diff --git a/base/special/log.jl b/base/special/log.jl index 5d7f1c8118724..6219e344418f9 100644 --- a/base/special/log.jl +++ b/base/special/log.jl @@ -566,9 +566,9 @@ function _log_ext(xu) # x = 2^k z; where z is in range [0x1.69555p-1,0x1.69555p-0) and exact. # The range is split into N subintervals. # The ith subinterval contains z and c is near the center of the interval. - tmp = reinterpret(Int64, xu - 0x3fe6955500000000) #0x1.69555p-1 + tmp = reinterpret(Int64, xu -% 0x3fe6955500000000) #0x1.69555p-1 i = (tmp >> 45) & 127 - z = reinterpret(Float64, xu - (tmp & 0xfff0000000000000)) + z = reinterpret(Float64, xu -% (tmp & 0xfff0000000000000)) k = Float64(tmp >> 52) # log(x) = k*Ln2 + log(c) + log1p(z/c-1). # getfield instead of getindex to satisfy effect analysis not knowing whether this is inbounds diff --git a/base/special/rem_pio2.jl b/base/special/rem_pio2.jl index de5c4151df2d0..c37f31f88d671 100644 --- a/base/special/rem_pio2.jl +++ b/base/special/rem_pio2.jl @@ -188,9 +188,9 @@ Base.@assume_effects :consistent function paynehanek(x::Float64) # # (i.e. ignoring integer and lowest bit parts of result) - w1 = UInt128(X*a1) << 64 # overflow becomes integer - w2 = widemul(X,a2) - w3 = widemul(X,a3) >> 64 + w1 = UInt128(X *% a1) << 64 # overflow becomes integer + w2 = widemul(X, a2) + w3 = widemul(X, a3) >> 64 w = w1 + w2 + w3 # quotient fraction after division by 2π # adjust for sign of x diff --git a/base/special/trig.jl b/base/special/trig.jl index 6463560caa3e5..23d240327dc64 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -634,7 +634,7 @@ function atan(y::T, x::T) where T<:Union{Float32, Float64} ypw = poshighword(y) xpw = poshighword(x) # compute y/x for Float32 - k = reinterpret(Int32, ypw-xpw)>>ATAN2_RATIO_BIT_SHIFT(T) + k = reinterpret(Int32, ypw -% xpw)>>ATAN2_RATIO_BIT_SHIFT(T) if k > ATAN2_RATIO_THRESHOLD(T) # |y/x| > threshold z=T(pi)/2+T(0.5)*ATAN2_PI_LO(T) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 792925f24b12b..6f062686aa559 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -127,8 +127,8 @@ pointer(x::SubString{String}) = pointer(x.string) + x.offset pointer(x::SubString{String}, i::Integer) = pointer(x.string) + x.offset + (i-1) function hash(s::SubString{String}, h::UInt) - h += memhash_seed - ccall(memhash, UInt, (Ptr{UInt8}, Csize_t, UInt32), s, sizeof(s), h % UInt32) + h + h +%= memhash_seed + ccall(memhash, UInt, (Ptr{UInt8}, Csize_t, UInt32), s, sizeof(s), h % UInt32) +% h end """ diff --git a/base/tuple.jl b/base/tuple.jl index 59fe2c1e531e1..a1cd53c6d6c85 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -514,10 +514,10 @@ function _eq(t1::Any32, t2::Any32) end const tuplehash_seed = UInt === UInt64 ? 0x77cfa1eef01bca90 : 0xf01bca90 -hash(::Tuple{}, h::UInt) = h + tuplehash_seed +hash(::Tuple{}, h::UInt) = h +% tuplehash_seed hash(t::Tuple, h::UInt) = hash(t[1], hash(tail(t), h)) function hash(t::Any32, h::UInt) - out = h + tuplehash_seed + out = h +% tuplehash_seed for i = length(t):-1:1 out = hash(t[i], out) end diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 210ba8f0ae07b..1f684474ffe6e 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -4,7 +4,7 @@ (define (add-dots ops) (append! ops (map (lambda (op) (symbol (string "." op))) ops))) (define prec-assignment - (append! (add-dots '(= += -= −= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕)) + (append! (add-dots '(= += +%= -= −%= *= *%= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕)) (add-dots '(~)) '(:= $=))) ;; comma - higher than assignment outside parentheses, lower when inside @@ -20,8 +20,8 @@ (define prec-pipe> '(|.\|>| |\|>|)) (define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) (define prec-plus (append! '($) - (add-dots '(+ - − ¦ |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⟇ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) -(define prec-times (add-dots '(* / ⌿ ÷ % & · · ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ ⨟))) + (add-dots '(+ +% - -% − ¦ |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⟇ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) +(define prec-times (add-dots '(* *% / ⌿ ÷ % & · · ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗ ⨟))) (define prec-rational (add-dots '(//))) (define prec-bitshift (add-dots '(<< >> >>>))) ;; `where` @@ -927,8 +927,8 @@ (else (loop (list 'call t ex (down s)))))))))) -(define (parse-expr s) (parse-with-chains s parse-term is-prec-plus? '(+ ++))) -(define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(*))) +(define (parse-expr s) (parse-with-chains s parse-term is-prec-plus? '(+ +% ++))) +(define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(* *%))) (define (parse-rational s) (parse-LtoR s parse-shift is-prec-rational?)) (define (parse-shift s) (parse-LtoR s parse-unary-subtype is-prec-bitshift?)) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 59f0662e61018..feaf585cceec9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2749,8 +2749,11 @@ '& (lambda (e) (error (string "invalid syntax " (deparse e)))) '+= lower-update-op + '+%= lower-update-op '-= lower-update-op + '-%= lower-update-op '*= lower-update-op + '*%= lower-update-op '.*= lower-update-op '/= lower-update-op './= lower-update-op diff --git a/stdlib/FileWatching/test/pidfile.jl b/stdlib/FileWatching/test/pidfile.jl index c2cb0c88a1b1e..31662e7f72b20 100644 --- a/stdlib/FileWatching/test/pidfile.jl +++ b/stdlib/FileWatching/test/pidfile.jl @@ -43,7 +43,7 @@ try if !iswindows() @test isvalidpid("", 1 % Cuint) @test !isvalidpid("", -1 % Cuint) - @test !isvalidpid("", -mypid) + @test !isvalidpid("", -getpid() % Cuint) end end diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index cb336a8d9c18b..ba72cf2e8330f 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -184,8 +184,8 @@ function Format(f::AbstractString) b = bytes[pos] pos += 1 else - while b - UInt8('0') < 0x0a - width = 10 * width + (b - UInt8('0')) + while UInt8('0') <= b <= UInt8('9') + width = 10 * width + (b - UInt8('0')) b = bytes[pos] pos += 1 pos > len && break @@ -208,7 +208,7 @@ function Format(f::AbstractString) pos += 1 else precision = 0 - while b - UInt8('0') < 0x0a + while UInt8('0') <= b <= UInt8('9') precision = 10precision + (b - UInt8('0')) b = bytes[pos] pos += 1 diff --git a/stdlib/Random/src/Xoshiro.jl b/stdlib/Random/src/Xoshiro.jl index 3be276ad23754..b5820ae59e3af 100644 --- a/stdlib/Random/src/Xoshiro.jl +++ b/stdlib/Random/src/Xoshiro.jl @@ -116,7 +116,7 @@ rng_native_52(::TaskLocalRNG) = UInt64 function setstate!( x::TaskLocalRNG, s0::UInt64, s1::UInt64, s2::UInt64, s3::UInt64, # xoshiro256 state - s4::UInt64 = 1s0 + 3s1 + 5s2 + 7s3, # internal splitmix state + s4::UInt64 = s0 +% (3 *% s1) +% (5 *% s2) +% (7 *% s3), # internal splitmix state ) t = current_task() t.rngState0 = s0 @@ -130,8 +130,8 @@ end @inline function rand(::TaskLocalRNG, ::SamplerType{UInt64}) task = current_task() s0, s1, s2, s3 = task.rngState0, task.rngState1, task.rngState2, task.rngState3 - tmp = s0 + s3 - res = ((tmp << 23) | (tmp >> 41)) + s0 + tmp = s0 +% s3 + res = ((tmp << 23) | (tmp >> 41)) +% s0 t = s1 << 17 s2 ⊻= s0 s3 ⊻= s1 diff --git a/stdlib/Random/src/XoshiroSimd.jl b/stdlib/Random/src/XoshiroSimd.jl index 1a16baa4bce28..9980c8dfef698 100644 --- a/stdlib/Random/src/XoshiroSimd.jl +++ b/stdlib/Random/src/XoshiroSimd.jl @@ -17,7 +17,7 @@ simdThreshold(::Type{Bool}) = 640 @inline _rotl45(x::UInt64) = (x<<45)|(x>>19) @inline _shl17(x::UInt64) = x<<17 @inline _rotl23(x::UInt64) = (x<<23)|(x>>41) -@inline _plus(x::UInt64,y::UInt64) = x+y +@inline _plus(x::UInt64,y::UInt64) = x +% y @inline _xor(x::UInt64,y::UInt64) = xor(x,y) @inline _and(x::UInt64, y::UInt64) = x & y @inline _or(x::UInt64, y::UInt64) = x | y @@ -128,10 +128,10 @@ function forkRand(rng::Union{TaskLocalRNG, Xoshiro}, ::Val{N}) where N # 0x5a94851fb48a6e05 == hash(UInt(2))|0x01 # 0x3688cf5d48899fa7 == hash(UInt(3))|0x01 # 0x867b4bb4c42e5661 == hash(UInt(4))|0x01 - s0 = ntuple(i->VecElement(0x02011ce34bce797f * rand(rng, UInt64)), Val(N)) - s1 = ntuple(i->VecElement(0x5a94851fb48a6e05 * rand(rng, UInt64)), Val(N)) - s2 = ntuple(i->VecElement(0x3688cf5d48899fa7 * rand(rng, UInt64)), Val(N)) - s3 = ntuple(i->VecElement(0x867b4bb4c42e5661 * rand(rng, UInt64)), Val(N)) + s0 = ntuple(i->VecElement(0x02011ce34bce797f *% rand(rng, UInt64)), Val(N)) + s1 = ntuple(i->VecElement(0x5a94851fb48a6e05 *% rand(rng, UInt64)), Val(N)) + s2 = ntuple(i->VecElement(0x3688cf5d48899fa7 *% rand(rng, UInt64)), Val(N)) + s3 = ntuple(i->VecElement(0x867b4bb4c42e5661 *% rand(rng, UInt64)), Val(N)) (s0, s1, s2, s3) end diff --git a/stdlib/Random/src/generation.jl b/stdlib/Random/src/generation.jl index cc9840f678413..7c4ce40616c28 100644 --- a/stdlib/Random/src/generation.jl +++ b/stdlib/Random/src/generation.jl @@ -345,7 +345,7 @@ function rand(rng::AbstractRNG, sp::SamplerRangeNDL{U,T}) where {U,T} m = x * s l = m % U if l < s - t = mod(-s, s) # as s is unsigned, -s is equal to 2^L - s in the paper + t = mod(-%(s), s) # as s is unsigned, -s is equal to 2^L - s in the paper while l < t x = widen(rand(rng, U)) m = x * s diff --git a/stdlib/SHA.version b/stdlib/SHA.version index f2242a336c6fe..56b5e12f11cbd 100644 --- a/stdlib/SHA.version +++ b/stdlib/SHA.version @@ -1,4 +1,4 @@ SHA_BRANCH = master -SHA_SHA1 = 2d1f84e6f8417a1a368de48318640d948b023e7a +SHA_SHA1 = d44b32222edc233f3f4f2bf30ef43275841356b5 SHA_GIT_URL := https://github.com/JuliaCrypto/SHA.jl.git SHA_TAR_URL = https://api.github.com/repos/JuliaCrypto/SHA.jl/tarball/$1 diff --git a/test/arrayops.jl b/test/arrayops.jl index 770cec3705038..d80c88ce3f59d 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2533,7 +2533,7 @@ end @test cumsum(Any[1, 2.3]) == [1, 3.3] == cumsum(Real[1, 2.3])::Vector{Real} @test cumsum([true,true,true]) == [1,2,3] @test cumsum(0x00:0xff)[end] === UInt(255*(255+1)÷2) # no overflow - @test accumulate(+, 0x00:0xff)[end] === 0x80 # overflow + @test accumulate(+%, 0x00:0xff)[end] === 0x80 # overflow @test_throws InexactError cumsum!(similar(0x00:0xff), 0x00:0xff) # overflow @test cumsum([[true], [true], [false]])::Vector{Vector{Int}} == [[1], [2], [2]] diff --git a/test/intfuncs.jl b/test/intfuncs.jl index ceaac235a3da9..1f31ed240c7a0 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -53,14 +53,15 @@ is_effect_free(args...) = Core.Compiler.is_effect_free(Base.infer_effects(args.. @test_throws OverflowError gcd(typemin(T), T(0)) @test_throws OverflowError gcd(T(0), typemin(T)) else + negtmax = one(T) # For Unsigned Integer types, -typemax(T) == 1. - @test gcd(-typemax(T), T(1)) === T(1) - @test gcd(T(1), -typemax(T)) === T(1) - @test gcd(-typemax(T), T(0)) === T(1) - @test gcd(T(0), -typemax(T)) === T(1) - @test gcd(-typemax(T), -typemax(T)) === T(1) - @test gcd(-typemax(T), typemax(T)) === T(1) - @test gcd(typemax(T), -typemax(T)) === T(1) + @test gcd(negtmax, T(1)) === T(1) + @test gcd(T(1), negtmax) === T(1) + @test gcd(negtmax, T(0)) === T(1) + @test gcd(T(0), negtmax) === T(1) + @test gcd(negtmax, negtmax) === T(1) + @test gcd(negtmax, typemax(T)) === T(1) + @test gcd(typemax(T), negtmax) === T(1) # For Unsigned Integer types, typemin(T) == 0. @test gcd(typemin(T), T(1)) === T(1) @@ -126,14 +127,15 @@ is_effect_free(args...) = Core.Compiler.is_effect_free(Base.infer_effects(args.. @test_throws OverflowError lcm(typemin(T), typemin(T)+T(1)) # lcm(n, n+1) = n*(n+1). @test_throws OverflowError lcm(typemin(T), typemin(T)) else + negtmax = one(T) # For Unsigned Integer types, -typemax(T) == 1. - @test lcm(-typemax(T), T(1)) === T(1) - @test lcm(T(1), -typemax(T)) === T(1) - @test lcm(-typemax(T), T(0)) === T(0) - @test lcm(T(0), -typemax(T)) === T(0) - @test lcm(-typemax(T), -typemax(T)) === T(1) - @test lcm(-typemax(T), typemax(T)) === typemax(T) - @test lcm(typemax(T), -typemax(T)) === typemax(T) + @test lcm(negtmax, T(1)) === T(1) + @test lcm(T(1), negtmax) === T(1) + @test lcm(negtmax, T(0)) === T(0) + @test lcm(T(0), negtmax) === T(0) + @test lcm(negtmax, negtmax) === T(1) + @test lcm(negtmax, typemax(T)) === typemax(T) + @test lcm(typemax(T), negtmax) === typemax(T) # For Unsigned Integer types, typemin(T) == 0. @test lcm(typemin(T), T(1)) === lcm(T(0), T(1)) === T(0) diff --git a/test/ryu.jl b/test/ryu.jl index 0b10bd7e49ba5..031c98a670df1 100644 --- a/test/ryu.jl +++ b/test/ryu.jl @@ -52,7 +52,7 @@ end @test "2.305843009213694e40" == Ryu.writeshortest(Core.bitcast(Float64, 0x4850F0CF064DD592)) end -@testset "pow5 overflow (#47464)" begin +@testset "pow5 overflow (#46764/#47511)" begin @test "4.6458339e+63" == Ryu.writeexp(4.645833859177319e63, 7) @test "4.190673780e+40" == Ryu.writeexp(4.190673779576499e40, 9) end diff --git a/test/testhelpers/Furlongs.jl b/test/testhelpers/Furlongs.jl index f63b5460c7c16..6f8ff255f64e4 100644 --- a/test/testhelpers/Furlongs.jl +++ b/test/testhelpers/Furlongs.jl @@ -66,8 +66,8 @@ for f in (:real,:imag,:complex,:+,:-) @eval Base.$f(x::Furlong{p}) where {p} = Furlong{p}($f(x.val)) end -import Base: +, -, ==, !=, <, <=, isless, isequal, *, /, //, div, rem, mod, ^ -for op in (:+, :-) +import Base: +, -, +%, -%, ==, !=, <, <=, isless, isequal, *, /, //, div, rem, mod, ^ +for op in (:+, :-, :(+%), :(-%)) @eval function $op(x::Furlong{p}, y::Furlong{p}) where {p} v = $op(x.val, y.val) Furlong{p}(v)