How to define "complex Float64" variable in Julia? - julia

I have a module, say, called Constants,
module Constants
const zero = 0.0 :: Float64
const czero = 0.0 + 0.0im :: Complex
end
I know like I can define like zero as Float64. But How do I define a "Complex" and "Float64" variable such as czero? Currently I use Complex, but I want to be more specific. If I use ComplexF64
const czero = 0.0 + 0.0im :: ComplexF64
it gives me an error,
ERROR: LoadError: TypeError: in typeassert, expected Complex{Float64}, got a value of type Complex{Bool}
So what concrete type of Complex should I use?
I give each variable a concrete type is because I heard that if the code looks like Fortran it can run like Fortran, because I define the type first so Julia do not have to convert the type which can be very slow.

This question is not quite clear, but perhpas what you need is zero:
julia> zero(ComplexF64)
0.0 + 0.0im
julia> dump(zero(ComplexF64))
ComplexF64
re: Float64 0.0
im: Float64 0.0
Other options include using the constructor such as ComplexF64(0.0) or ComplexF64(0.0,0.0) or using the complex(0.0) function. These are all type stable.

::
With the ::-operator type annotations are attached to expressions and variables in programs. See the manual section on Type Declarations.
Outside of declarations :: is used to assert that expressions and variables in programs have a given type.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> (1+2)::AbstractFloat
ERROR: TypeError: typeassert: expected AbstractFloat, got a value of type Int64
julia> (1+2)::Int
3
With this in mind, obviously julia considers the declaration invalid because of operator precedence, so just put parentheses if you want to do the declaration this way
const czero = (0.0 + 0.0im) ::ComplexF64
I also second the opinion above: if you're just trying to declare zeros then what you need is zero

Related

Parametric constructors

I am having some issues understanding the concept of parametric constructors in Julia. I am looking at the standard example in the Julia docs:
struct Point{T<:Real}
x::T
y::T
end
To my understanding, this means I can generate a Point-datatype with an input that is subtype of Real, i.e., AbstractFloat, AbstractIrrational, ..., Integer, Rational, ..., StatsBase.TestStat.
However, both of the examples below result in errors:
Point(Integer(12))
Point(Rational(12))
Why does the above fail given that both integer and rational are subtypes of real?
The type parameter goes inside the curly braces in the constructor call, just like it does in the struct definition:
julia> Point{Integer}(12, 12)
Point{Integer}(12, 12)
julia> Point{Rational}(12, 10//3)
Point{Rational}(12//1, 10//3)
The arguments supplied are the values for the fields of the struct i.e. x and y. If the arguments are already of the type you want, you can leave out explicitly specifying the type parameter:
julia> Point(12, 6)
Point{Int64}(12, 6)
julia> Point(12.0, 6.0)
Point{Float64}(12.0, 6.0)
julia> Point(12, 6.0) #no automatic type promotion happens though
ERROR: MethodError: no method matching Point(::Int64, ::Float64)
Closest candidates are:
Point(::T, ::T) where T<:Real at REPL[1]:2
Stacktrace:
[1] top-level scope
# REPL[9]:1
julia> Point{Float64}(12, 6.0) #unless you explicitly specify the type
Point{Float64}(12.0, 6.0)

Julia: Even-number datatype for functions

I have about 50 functions which should consume only even positive numbers. Right now I am checking each time with an "if" whether the number put in is zero or not:
function grof(x::Int)
if (x % 2) == 0
println("good")
else
throw("x is not an even number!!!!!!!!!!!!! Stupid programmer!")
end
end
Ideally, I would like to have a datatype which produces this automatically, i.e.
function grof(x::EvenInt)
println("good")
end
However, I am not able to produce this datatype by my own since I am unable to understand the documentary. Thanks for your help!
Best, v.
I don't think creating a type is warranted in such a situation: I would simply #assert that the condition is verified at the beginning of the function(s). (Funnily enough, checking the whether a number is even is the example that was chosen in the documentation to illustrate the effect of #assert)
For example:
julia> function grof(x::Int)
#assert iseven(x) "Stupid programmer!"
println("good")
end
grof (generic function with 1 method)
julia> grof(2)
good
julia> grof(3)
ERROR: AssertionError: Stupid programmer!
Stacktrace:
[1] grof(::Int64) at ./REPL[5]:2
[2] top-level scope at REPL[7]:1
EDIT: If you really want to create a type enforcing such a constraint, it is possible. The way to do this would be to
create a type (possibly subtyping one of the Number abstract types; maybe Signed)
define an inner constructor ensuring that such a type cannot hold an odd value
A very simple example to build upon would be along the lines of:
# A wrapper around an even integer value
struct EvenInt
val :: Int
# inner constructor
function EvenInt(val)
#assert iseven(val)
new(val)
end
end
# Accessor to the value of an EvenInt
val(x::EvenInt) = x.val
# A method working only on even numbers
grof(x::EvenInt) = println("good: $(val(x)) is even")
You'd use this like so:
julia> x = EvenInt(42)
EvenInt(42)
julia> grof(x)
good: 42 is even
julia> y = EvenInt(1)
ERROR: AssertionError: iseven(val)
Stacktrace:
[1] EvenInt(::Int64) at ./REPL[1]:5
[2] top-level scope at REPL[6]:1
but note that you can't do anything on EvenInts yet: you need to either unwrap them (using val() in this case), or define operations on them (a task which can be vastly simplified if you make EvenInt a subtype of one of the abstract number types and follow the relevant interface).
All integers multiplied by two are even, so redefine your function to take half the number it currently takes.
function grof2(halfx::Int)
x=2*halfx
println("good")
end

Parametric functors in Julia

Starting 0.6 it is possible to create parametric methods in Julia using where syntax. According to the release notes of 0.6 version, where syntax
can be used anywhere a type is accepted
Now consider the following contrived example:
function (rng::R)() where {R <: Range}
return first(rng)
end
which, when I attempt to compile it, gives the following error:
ERROR: function type in method definition is not a type
So my question is what is the proper way to create parametric functors in Julia 0.6+?
Ohkay, I get what you are trying to do basically. To understand functors here is a short example code.
julia> struct Student
name::String
end
julia> function (::Student)()
println("Callable of Student Type!")
end
julia> object = Student("JuliaLang")
Student("JuliaLang")
julia> object()
Callable of Student Type!
but when I try to create the parametric functors, it throws out the error similar to yours!
julia> function (::T)() where {T <: Student}
println("Callable of Student Type!")
end
ERROR: function type in method definition is not a type
This problem is actually still OPEN as a issue as #gnimuc rightly pointed out.
You mix up two things
parametric methods e.q. julia> same_type(x::T, y::T) where {T} = true
function-like objects e.g. julia> function (p::Polynomial)(x) ... end
To my knowledge there is no "parametric function-like objects"
However, the following code should be the same of what you intend.
Julia> function (rng::Range)()
return first(rng)
end
cannot add methods to an abstract type
The current docu does not mention any limitation of function-like objects to concrete type, but unfortunately Julia doesn't accept it anyway.

How to use type using parametric typing

I am trying to use type using parametric typing But I get an Error. My julia version is 0.6.
Code:
type BasicRBC{T <: Real}
a::T
b::T
vce::Matrix{T}
matrix1::Matrix{T}
c::T
output::T
cons::T
vG::Vector{T}
end
Error:
invalid redefinition of constant BasicRBC
a,b,c,output and cons are Float64
matrix1 is Matrix
vG is Array
vce is [ 0.9 0.8 0.1]
You cannot modify a type in the same Julia session because Julia compiles things using the information about the exact type layout in order to make functions fast. Thus if you want to change type definitions, you need to refresh your workspace or restart Julia as #TasosPapastylianou said.– Chris Rackauckas

How to create an object like `()` in user space

In Julia the empty tuple is both a type and an instance of that type. So isa((),()) is true. Is it possible to create a similar object myself?
I don't believe so. In fact, in Julia 0.4 isa((),()) is no longer true. The type of () is now Tuple{}:
julia> VERSION
v"0.4.0-dev+5441"
julia> typeof(())
Tuple{}
julia> isa((),()) # Throws an error since () is no longer considered a Type
ERROR: TypeError: isa: expected Type{T}, got Tuple{}
I think the only remaining objects that are an instance of themselves are Any, Type and DataType.

Resources