Here is the problem. I want to write a convolution for two simple signals x[n]=0.2^n*u[n] and h[n]=u[n+2] for some values of n. This is how I implement it:
using Plots, DSP
x(n) = if n<0 0 else 0.2^n end
h(n) = if n<-2 0 else 1 end
n = -10:10
conv(h.(n),x.(n))
It doesn't work. Here is the error:
`float` not defined on abstractly-typed arrays; please convert to a more specific type
Any idea how may I fix it?
I ran it fine with a fresh REPL session:
julia> using Plots, DSP
[ Info: Precompiling Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]
[ Info: Precompiling DSP [717857b8-e6f2-59f4-9121-6e50c889abd2]
julia> x(n) = if n<0 0 else 2^n end
x (generic function with 1 method)
julia> h(n) = if n<-2 0 else 1 end
h (generic function with 1 method)
julia> n = -10:10
-10:10
julia> conv(h.(n),x.(n))
41-element Array{Int64,1}:
0
0
(etc)
1984
1920
1792
1536
1024
julia> plot(conv(h.(n),x.(n)))
(plots ok)
If you change the 2 in 2^n to a float you need to specify Float64:
julia> x(n) = if n<0 0 else 0.2^n end
x (generic function with 1 method)
julia> conv(h.(n),Float64.(x.(n)))
41-element Array{Float64,1}:
0.0
8.458842092382145e-17
2.5376526277146434e-16
4.229421046191072e-17
2.1147105230955362e-16
(etc)
7.997440000004915e-5
1.597440000003685e-5
3.1744000002024485e-6
6.144000000924524e-7
1.0240000015600833e-7
Related
I want to evaluate a set of vectors (or tuples) in a function $f$ but Julia says me that is imposible.
For example: If I have an array of tuples p=[(1,1), (1,-1), (-1,1), (-1,-1)] and a function f(x,y)=x+y. I would like to calculate f(p[1]) = f(1,1)= 2. But Julia says me that the types are incompatible.
Can you help me please?
You have to splat a tuple like this:
julia> p=[(1,1), (1,-1), (-1,1), (-1,-1)]
4-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(1, -1)
(-1, 1)
(-1, -1)
julia> f(x,y)=x+y
f (generic function with 1 method)
julia> f(p[1]...)
2
you could also define a higher order function splat that would conveniently wrap any function and perform splatting. It is useful as then you can e.g. broadcast such function:
julia> splat(f) = x -> f(x...)
splat (generic function with 1 method)
julia> splat(f)(p[1])
2
julia> splat(f).(p)
4-element Array{Int64,1}:
2
0
0
-2
Alternatively you can define your function f like this:
julia> f((x,y),)=x+y
f (generic function with 1 method)
julia> f(p[1])
2
and now you do not have to do splatting.
Just use the ... operator to unpack the tuple as parameters:
julia> f(p[1]...)
2
In addition to other answers, if your task allows you, you can just define
julia> f(x) = f(x...)
and use it as
julia> f.(p)
4-element Vector{Int64}:
2
0
0
-2
Why does this happen in Julia?
My input is
A = []
for i = 17:21
t = 1/(10^(i))
push!(A, t)
end
return(A)
And the output was:
5-element Array{Any,1}:
1.0e-17
1.0e-18
-1.1838881245526248e-19
1.2876178137472069e-19
2.5800991659088344e-19
I observed that
A[3]>0
false
I want to find the number which act to 0 of Julia, but I found this and don’t understand.
The reason for this problem is when you have i = 19, note that then:
julia> 10^19
-8446744073709551616
and it is unrelated to floating point numbers, but is caused by Int64 overflow.
Here is the code that will work as you expect. Either use 10.0 instead of 10 as 10.0 is a Float64 value:
julia> A=[]
Any[]
julia> for i=17:21
t=1/(10.0^(i))
push!(A,t)
end
julia> A
5-element Array{Any,1}:
1.0e-17
1.0e-18
1.0e-19
1.0e-20
1.0e-21
or using high precision BigInt type that is created using big(10)
julia> A=[]
Any[]
julia> for i=17:21
t=1/(big(10)^(i))
push!(A,t)
end
julia> A
5-element Array{Any,1}:
9.999999999999999999999999999999999999999999999999999999999999999999999999999967e-18
9.999999999999999999999999999999999999999999999999999999999999999999999999999997e-19
9.999999999999999999999999999999999999999999999999999999999999999999999999999997e-20
1.000000000000000000000000000000000000000000000000000000000000000000000000000004e-20
9.999999999999999999999999999999999999999999999999999999999999999999999999999927e-22
You can find more discussion of this here https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#Overflow-behavior.
For example notice that (which you might find surprising not knowing about the overflow):
julia> x = typemin(Int64)
-9223372036854775808
julia> x^2
0
julia> y = typemax(Int64)
9223372036854775807
julia> y^2
1
Finally to find smallest positive Float64 number use:
julia> nextfloat(0.0)
5.0e-324
or
julia> eps(0.0)
5.0e-324
Say I have a lot of different very simple functions called f1, f2, ....
I would like to store all of the f functions in a fStruct and pass one of the f functions to e.g. g, when I need itin my code.
But when I pass the function f to g, the evaluation of the function g() is much slower.
Is there a workaround?
My ugly solution is to use an overall function which selects the right f() function by if-else statements.
Below is a minimal example of the slow computation.
using BenchmarkTools
struct fFunction
f1
f2
end
f() = return 1
fStruct = fFunction(f, f)
g = fStruct.f1
#btime f() --> 0.001 ns (0 allocations: 0 bytes)
#btime g() --> 9.591 ns (0 allocations: 0 bytes)
EDIT1:
I could also ask why the function g is slower or how to make it as fast as f in the following minimal example
using BenchmarkTools
f() = return 1
func = "f"
g = eval(Meta.parse(func))
f == g -->true
#btime f() --> 0.001 ns (0 allocations: 0 bytes)
#btime g() --> 11.907 ns (0 allocations: 0 bytes)
EDIT2:
Thank you for your answers.
I update the post with a solution.
using BenchmarkTools
f() = return 1
function g(x)
h = f
h()
end
const g2 = f
#btime f()
#btime g(f)
#btime g2()
f, g and g2 give you the same speed.
struct fFunctionAmbigiousType{F}
f1::F
f2::F
end
struct fFunctionDeclaredType{F}
f1::F
f2::F
end
fStructAmbigiousType = fFunctionAmbigiousType(f, f)
fStructDeclaredType = fFunctionDeclaredType(f, f)
fTuple = (f1 = f, f2 = f)
#btime $fStructAmbigiousType.f1
#btime $fStructDeclaredType.f1
#btime $fTuple.f1
fStructAmbigiousTypeFunctionPassed = fStructAmbigiousType.f1
fStructDeclaredTypeFunctionPassed = fStructDeclaredType.f1
fTupleFunctionPassed = fTuple.f1
#btime $fStructAmbigiousTypeFunctionPassed()
#btime $fStructDeclaredTypeFunctionPassed()
#btime $fTupleFunctionPassed()
fFunctionAmbigiousType, fFunctionDeclaredType and fTuple give you the same speed.
Declaring the type of a function to a struct does not change anything. Julia understands in both cases typeof{f}.
A paramteric struct or a parametric NamedTuple is possible, but is of course slower, if you apply the function often. If you apply the funcion f often you should pass it first to g or something like that to avoid the indexing every time.
Kind regards,
Till
There are several issues in your question.
How to do benchmarks
Actually in your code both functions are equally fast. The problem is that g is not const in global scope which introduces a penalty. To see this declare g as const or use $g in #btime call to see that there is no difference:
julia> using BenchmarkTools
julia> struct fFunction
f1
f2
end
julia> f() = return 1
f (generic function with 1 method)
julia> fStruct = fFunction(f, f)
fFunction(f, f)
julia> const g = fStruct.f1
f (generic function with 1 method)
julia> #btime f()
0.001 ns (0 allocations: 0 bytes)
1
julia> #btime g()
0.001 ns (0 allocations: 0 bytes)
1
and
julia> using BenchmarkTools
julia> struct fFunction
f1
f2
end
julia> f() = return 1
f (generic function with 1 method)
julia> fStruct = fFunction(f, f)
fFunction(f, f)
julia> g = fStruct.f1
f (generic function with 1 method)
julia> #btime f()
0.001 ns (0 allocations: 0 bytes)
1
julia> #btime $g()
0.001 ns (0 allocations: 0 bytes)
1
How to analyze your code
However, this equivalence is artificial, because you extract g from fStruct in global scope thus it is evaluated before a call to #btime. A more proper test would be:
julia> using BenchmarkTools
julia> struct fFunction
f1
f2
end
julia> f() = return 1
f (generic function with 1 method)
julia> fStruct = fFunction(f, f)
fFunction(f, f)
julia> test1() = f()
test1 (generic function with 1 method)
julia> test2(fStruct) = fStruct.f1()
test2 (generic function with 1 method)
julia> #btime test1()
0.001 ns (0 allocations: 0 bytes)
1
julia> #btime test2($fStruct)
14.462 ns (0 allocations: 0 bytes)
1
julia> #code_warntype test1()
Body::Int64
1 1 ─ return 1 │
julia> #code_warntype test2(fStruct)
Body::Any
1 1 ─ %1 = (Base.getfield)(fStruct, :f1)::Any │╻ getproperty
│ %2 = (%1)()::Any │
└── return %2
And you see that using fFunction struct is not efficient because its f1 and f2 fields have abstract type (Any to be specific).
How to write an efficient struct that holds functions
Use either a Tuple, a NamedTuple or struct with parameters as they all provide type information. A tuple would be simply defined as (f,f), a NamedTuple would be (f1=f, f2=f). The most complex case is parametric struct, which I show you here (code for Tuple and NamedTuple would be even simpler):
julia> using BenchmarkTools
julia> struct fFunction{F1,F2}
f1::F1
f2::F2
end
julia> f() = return 1
f (generic function with 1 method)
julia> fStruct = fFunction(f, f)
fFunction{typeof(f),typeof(f)}(f, f)
julia> test1() = f()
test1 (generic function with 1 method)
julia> test2(fStruct) = fStruct.f1()
test2 (generic function with 1 method)
julia> #btime test1()
0.001 ns (0 allocations: 0 bytes)
1
julia> #btime test2($fStruct)
1.866 ns (0 allocations: 0 bytes)
1
julia> #code_warntype test1()
Body::Int64
1 1 ─ return 1 │
julia> #code_warntype test2(fStruct)
Body::Int64
1 1 ─ (Base.getfield)(fStruct, :f1) │╻ getproperty
└── return 1
And you can see that using fFunction defined as parametric type has almost no overhead (the only cost you pay is field extraction).
If something is not clear please let me know and I can elaborate more on it.
If you know ahead of time what kind of function you will be passing, one thing I found to make things much faster is to manually transform the closure you need into a struct. So, if for example you will always be passing functions of the form
f(x) = x + a
for different a, you can transform this into
struct Adder
a::Int
end
(adder::Adder)(x) = x + adder.a
and then use it in fFunction like
fFunction(f::Adder, g::Adder) = rand() < 0.5 ? f(10) : g(10)
That way, you have a concrete type for f and g and manual control over your closures, entirely avoiding all the method call overhead except for the overloaded call operator. And fFunction is completely specialized and type-stable.
I was curious how quick and accurate, algorithm from Rosseta code ( https://rosettacode.org/wiki/Ackermann_function ) for (4,2) parameters, could be. But got StackOverflowError.
julia> using Memoize
#memoize ack3(m, n) =
m == 0 ? n + 1 :
n == 0 ? ack3(m-1, 1) :
ack3(m-1, ack3(m, n-1))
# WARNING! Next line has to calculate and print number with 19729 digits!
julia> ack3(4,2) # -> StackOverflowError
# has to be -> 2003529930406846464979072351560255750447825475569751419265016973710894059556311
# ...
# 4717124577965048175856395072895337539755822087777506072339445587895905719156733
EDIT:
Oscar Smith is right that trying ack3(4,2) is unrealistic. This is version translated from Rosseta's C++:
module Ackermann
function ackermann(m::UInt, n::UInt)
function ack(m::UInt, n::BigInt)
if m == 0
return n + 1
elseif m == 1
return n + 2
elseif m == 2
return 3 + 2 * n;
elseif m == 3
return 5 + 8 * (BigInt(2) ^ n - 1)
else
if n == 0
return ack(m - 1, BigInt(1))
else
return ack(m - 1, ack(m, n - 1))
end
end
end
return ack(m, BigInt(n))
end
end
julia> import Ackermann;Ackermann.ackermann(UInt(1),UInt(1));#time(a4_2 = Ackermann.ackermann(UInt(4),UInt(2)));t = "$a4_2"; println("len = $(length(t)) first_digits=$(t[1:20]) last digits=$(t[end-20:end])")
0.000041 seconds (57 allocations: 33.344 KiB)
len = 19729 first_digits=20035299304068464649 last digits=445587895905719156733
Julia itself does not have an internal limit to the stack size, but your operating system does. The exact limits here (and how to change them) will be system dependent. On my Mac (and I assume other POSIX-y systems), I can check and change the stack size of programs that get called by my shell with ulimit:
$ ulimit -s
8192
$ julia -q
julia> f(x) = x > 0 ? f(x-1) : 0 # a simpler recursive function
f (generic function with 1 method)
julia> f(523918)
0
julia> f(523919)
ERROR: StackOverflowError:
Stacktrace:
[1] f(::Int64) at ./REPL[1]:1 (repeats 80000 times)
$ ulimit -s 16384
$ julia -q
julia> f(x) = x > 0 ? f(x-1) : 0
f (generic function with 1 method)
julia> f(1048206)
0
julia> f(1048207)
ERROR: StackOverflowError:
Stacktrace:
[1] f(::Int64) at ./REPL[1]:1 (repeats 80000 times)
I believe the exact number of recursive calls that will fit on your stack will depend upon both your system and the complexity of the function itself (that is, how much each recursive call needs to store on the stack). This is the bare minimum. I have no idea how big you'd need to make the stack limit in order to compute that Ackermann function.
Note that I doubled the stack size and it more than doubled the number of recursive calls — this is because of a constant overhead:
julia> log2(523918)
18.998981503278365
julia> 2^19 - 523918
370
julia> log2(1048206)
19.99949084151746
julia> 2^20 - 1048206
370
Just fyi, even if you change the max recursion depth, you won't get the right answer as Julia uses 64 bit integers, so integer overflow with make stuff not work. To get the right answer, you will have to use big ints to have any hope. The next problem is that you probably don't want to memoize, as almost all of the computations are not repeated, and you will be computing the function more than 10^19729 different inputs, which you really do not want to store.
Is there a way to concatenate ArrayViews in Julia, that doesn't copy the underlying data? (I'd also be glad to use a SubArray, if that solves the problem.)
In the code below, for example, I want a single ArrayView that references the data in both y1 and y2.
julia> x = [1:50];
julia> using ArrayViews;
julia> y1 = view(x, 2:5);
julia> y2 = view(x, 44:48);
julia> concat(y1, y2) # I wish there were a function like this
ERROR: concat not defined
julia> [y1, y2] # This copies the data in y1 and y2, unfortunately
9-element Array{Int64,1}:
2
3
4
5
44
45
46
47
48
Not directly. But you could roll your own type with something like:
julia> type CView{A<:AbstractArray} <: AbstractArray
a::A
b::A
end
julia> import Base: size, getindex, setindex!
julia> size(c::CView) = tuple([sa+sb for (sa, sb) in zip(size(c.a), size(c.b))]...)
size (generic function with 57 methods)
julia> getindex(c::CView, i::Int) = i <= length(c.a) ? getindex(c.a, i) : getindex(c.b, i)
getindex (generic function with 180 methods)
julia> c = CView(y1, y2);
julia> size(c)
(9,)
julia> c[1]
2
julia> c[4]
5
julia> c[5]
48
These methods may not be optimal but they can certainly get you started. To be useful, more methods would probably be needed. Note that the key is simply in deciding which member array to index into. For multidimensional indexing sub2ind can be used.