Primes.jl looks very suspicious.
(primes(999).^2).% 24
Primes.jl looks very suspicious.
(primes(999).^2).% 24
that’s correct, it is a fact for all primes >= 5
Squared Primes Modulo 24
Roger B. Nelsen
Mathematics Magazine, 93 (2020) pg 228
DOI: 10.1080/0025570X.2020.1736877
Julia and Primes.jl turned many problems on https://projecteuler.net/ into jokes
Since Julia 1.6 I think
a = 1
b = 2
c = 3
d = 4
f(a, b; c, d) = a+b+c+d
f(a, b; c = c, d = d)
# no need to name them with `=` if variable name is same as argument name
f(a, b; c, d)
That’s what I do with Emacs
When reduction operators take generators:
f(k) = sum(x^2 for x in 1:k)
even better than math notation!
seems much slower than
f(k) = sum((1:k).^2)
Unfortunately, this doesn’t work with sum
, but if we define our own:
julia> function mysum(f, r)
s = zero(f(first(r)))
for i ∈ r
s += f(i)
end
s
end
mysum (generic function with 1 method)
julia> @btime mysum(abs2, 1:$(Ref(10))[])
1.585 ns (0 allocations: 0 bytes)
385
julia> @btime mysum(abs2, 1:$(Ref(100))[])
1.586 ns (0 allocations: 0 bytes)
338350
julia> @btime mysum(abs2, 1:$(Ref(1000))[])
1.588 ns (0 allocations: 0 bytes)
333833500
julia> @btime mysum(abs2, 1:$(Ref(10000))[])
1.586 ns (0 allocations: 0 bytes)
333383335000
LLVM can optimize away the loop, so performance is independent of k
.
How so?
using BenchmarkTools, BenchmarkPlots, StatsPlots
K = 10_000
bg = BenchmarkGroup()
bg[:a] = @benchmark sum((1:$K).^2)
bg[:b] = @benchmark sum(x^2 for x in 1:$K)
bg[:c] = @benchmark sum(x -> x^2, 1:$K)
plot(bg; yscale=:log10)
The generator method is clearly much faster (but not as fast as the two argument version).
But still about 100x slower than mysum
would be at that size.
It is indeed a lot faster even than sum(f, x)
. I wonder what it is about sum
that can’t be optimized like mysum
can.
I think it’s probably harder to constant fold pairwise summation.
What about sum
is pairwise? I would expect sum
to do more or less the same thing as mysum
It’s a technique to increase floating-point accuracy : Pairwise summation - Wikipedia
pkg> add BenchmarkPlots
Updating registry at `C:\Users\Hermesr\.julia\registries\General`
Updating git-repo `https://github.com/JuliaRegistries/General.git`
ERROR: The following package names could not be resolved:
* BenchmarkPlots (not found in project, manifest or registry)
My bad, that’s an unmerged pr. You can clone it and add by directory if you want.
Another nice thing to do with end
was given by @giordano in a Slack thread:
Alexander Palvin:
I wish it was also possible to store the indexing expression in a variable.
ix = min(i, end)
x[ix] # same effect as x[min(i, end)]
@giordano , Using the package EndpointRanges.jl
solved it using:
julia> using EndpointRanges
julia> using EndpointRanges: Endpoint, IndexFunction
julia> Base.min(x::Endpoint, y::Endpoint) = IndexFunction(r->Base.min(x(r), y(r)))
julia> Base.min(x::Endpoint, y::Number) = IndexFunction(r->Base.min(x(r), y))
julia> Base.min(x::Number, y::Endpoint) = IndexFunction(r->Base.min(x, y(r)))
julia> m = min(3, iend)
IndexFunction{var"#5#6"{Int64, EndpointRanges.IEnd}}(var"#5#6"{Int64, EndpointRanges.IEnd}(3, EndpointRanges.IEnd()))
julia> (1:10)[m]
3
julia> (1:2)[m]
2
@RoyiAvital that’s more an example of missing sugar though… It’s nice that it can be implemented but it would be nice to have something like this in Base.
@times
it’s amazing
What package is that from?