How can I specify a type for a function argument without restricting its dimensions? - arrays

In Julia, I want to specify the type of a function argument as an array of arrays. So I have
function foo{T <: Any}(x::Array{Array{T}})
but if I set the argument x in the REPL, for example:
x = Array[[0,1],[1,2,3],[0,1,2,4]]
then it automatically gets the following type assignment (for example), which includes its dimensions:
x::Array{Array{T,N},1}
so that I get the error
ERROR: `foo` has no method matching foo(::Array{Array{T,N},1}).
I don't want to restrict the array dimensions at all, so was thinking that the solution maybe something along the lines of
function foo{T <: Any, N <: Number}(x::Array{Array{T,N},N})
but this doesn't work either.
How can I specify the argument type to be an array of arrays?

Given an array of arrays x = Array[isodd(i) ? [1i,2i] : [1.0i 2.0i] for i=1:10], Julia reports its type as Array{Array{T,N},1}. This is deceiving, as it seems to imply that there exists some T and some N for which the above type will match. But that's not the case: the odd elements will be of type Array{Int,1}, and the evens are Array{Float64,2}. So when you try to write a method for foo with the type parameters:
foo{T,N}(::Array{Array{T,N},1}) = T,N
What are T and N for x? Clearly, there is no such N — it's both 1 and 2! And the elements of these subarrays aren't of type Any — they're both Int and Float64. The same applies for Array[[0,1],[0,1,2]], even though in your example you know that T and N are consistent, Julia's type system doesn't… and you could potentially push elements that aren't Int vectors.
There are quite a few ways around this. The best approach is to try to make sure that your arrays always have concrete (or at least uniform) element types, but that's not always possible. Given your example x above, you could instead write: x = Array{Int,1}[[0,1],[1,2,3],[0,1,2,4]].
Another alternative is to change your function signature:
foo{N}(x::Array{Array,N}) = 1 # Will *only* work for arrays like x above
foo{T<:Array, N}(x::Array{T,N} = 2 # Will work for all arrays of arrays
The first will only apply if you have exactly that type due to invariance, whereas the second will work for all Arrays of Arrays, both poorly-typed and concrete.
(Edit: As a final note, N<:Number won't match literal numbers. It will match types that are a subtype of Number, like Real or Int. There's currently no way to express that a type parameter must be a value of type Int beyond the convention that N is an integer).

Related

Array of strings in Ada

So, I'm coding in Ada for the first time and have to create this pre-populated array of strings, so I can use a random method and call a different value each time.
poolOfWords: constant array(1..50) of string := ("gum","sin","for","cry","lug","bye","fly",
"ugly", "each","from","work","talk","with","self", "pizza","thing","feign","friend",
"elbow","fault", "dirty","budget","spirit","quaint","maiden","escort","pickax",
"example","tension","quinine","kidney","replica","sleeper", "triangle","kangaroo",
"mahogany","sergeant","sequence","moustache","dangerous","scientist",
"different","quiescent", "magistrate","erroneously","loudspeaker",
"phytotoxic","matrimonial","parasympathomimetic","thigmotropism");
But when I try to compile I get this error: "unconstrained element type in array declaration".
I Googled all over internet and couldn't find a solution to that. I even tried to use unbounded_string, but didn't work as well. It works fine when I pre-populate an array of integers, floats, but when it come to strings it's not working.
Can someone help me and explain what's going on and how to solve it? I really don't want to declare the array and then populate each of the 50 indexes one by one.
Your problem stems from the fact that String in Ada is an unconstrained type. This means, roughly, that you need to specify "something" in order to have a usable type. In the case of String you need to specify the string length, since a String is just an array of Character. If you say something like
X : String;
the compiler complains since it does not know the length of X and it does not know how much memory to reserve for X. You need to say something like
X : String(1..6);
or something like
X : String := "foobar";
Note that in the second case you do not need to specify the index range since the compiler is able to deduce it from the fact that you use a 6-Character string to initialize X.
This explains why it is illegal to declare an array of just String. When you declare an array the compiler needs to know the size of every entry (all the entries must share the same size, this makes access to a random entry of the array very efficient). If you declare an array of just String, the compiler would not know how much memory to allocate to every entry since the length is unspecified.
Note that this instead would work (disclaimer: I have not an Ada compiler at hand now, so I cannot check the code)
subtype ZIP_Code is String (1..5);
type ZIP_Code_Array is array(Positive range <>) of ZIP_Code;
since now the compiler knows the size of every entry of a ZIP_Code_Array (5 Character).
In your case, however, the strings have all different sizes. I can see two possible solutions
If the maximum length is known in advance you can use the subtype approach shown above and pad the strings with spaces. It depends on your context if this is a suitable solution or not
The approach that I typically use is to create an array of Unconstrained_String that I initialize as follows
function "+"(X: String) return Unbounded_String
renames To_Unbounded_String;
poolOfWords: constant array(1..50) of Unbounded_String :=
(+"gum",
+"sin",
+"for",
-- and so on...
);
Note the renames that defines the unary + as an alias for To_Unbounded_String. This is just syntactic sugar that allows you to write +"gum" instead of To_Unbounded_String("gum"). Someone cringes at this type of syntactic sugar (and I am not so keen either), but in this case I think it is worth since it makes the code "lighter." It would be nice to have the definition of unary + near its use, just for clarity.
An alternative to the use of Unbounded_String is to use the generic package Bounded_Strings and define poolOfWords as an array of Bounded_String. A Bounded_String can hold strings with variable length, as long as the length is smaller than the bound specified when instantiating the Bounded_Strings package. In order to convert back and forth String you can use the same "rename trick."
My personal preference goes to the Unbounded_String, unless I have some special reason that forces me to use the Bounded_String.
Another option is to use Ada's standard containers. For example:
Package String_Holder is new Ada.Containers.Indefinite_Holders(
"=" => Ada.Strings.Equal_Case_Insensitive,
Element_Type => String
);
Function "+"( Right : String_Holder.Holder ) return String
renames String_Holder.Element;
Function "+"( Right : String ) return String_Holder.Holder
renames String_Holder.To_Holder;
Allows you to store in the holder varying sized values of type String, so you could forego any dependence on Ada.Strings.Unbounded_String and use something like:
poolOfWords: constant array(Positive range <>) of String_Holder.Holder :=
+"gum", +"sin", +"for", +"cry", -- ...
+"Stuff"
);
Function Get_Word(Index : Positive) return String is
(+poolOfWords(Index)) with Pre => Index in poolOfWords'Range;
Alternatively, you could use Ada.Containers.Indefinite_Vectors like so:
Package String_Vector is new Ada.Containers.Indefinite_Vectors(
"=" => Ada.Strings.Equal_Case_Insensitive,
Index_Type => Positive,
Element_Type => String
);
though there is one problem with this in Ada 2012: You can't initialize such a vector directly within the declaration, but can initialize it via function-call:
Function Populate return String_Vector.Vector is
Begin
Return Result : String_Vector.Vector do
Result.Append( "some" );
Result.Append( "data" );
Result.Append( "HERE" );
End Return;
End Populate;
Being able to say X : String_Vectors.Vector := ("this", "that", "the other") is in Ada 2020 .

Can't create a 'real' type array in Verilog

I've tried creating a 'real' type value array in the following way in Icarus Verilog:
parameter width = 10;
shortreal b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181};
Gives the following error:
error: Cannot assign to array b. Did you forget a word index?
I went through the icarus verilog src code error messages and the explanation to this one is "Special case: The l-value is an entire memory, or array
slice". This is, in fact, an error in l-values. Detect the
situation by noting if the index count is less than the
array dimensions (unpacked)", which I assume means that the array index size differs from the declared one [width-1:0], which isn't true if I understand.
I've also tried:
parameter width = 10;
parameter [32:0] b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181};
but without any success.
Using Icarus Verilog with -g2012 flag (for SV support)
It is only legal to use so-called array concatenation if you fill the entire array. You array have 10 elements, but there are only 9 on the right hand side:
parameter width = 10;
shortreal b [width-1:0] = {0.0181,0.0487,0.1227,0.1967,0.2273,0.1967,0.1227,0.0487,0.0181,0.0181};

Using findmin() in data from array composed of mutable struct elements - Julia

Suppose I have the following struct:
mutable struct Car
load
locale
availability
odometer
end
And I have created an array:
fleet = Vector{Car}(undef, num_cars)
for i in 1:num_cars
a, b, c, d = rand(4)
fleet[i] = Car(a, b, c, d)
end
How can I find the smallest (with findmin or similar) or biggest (with?) value from, for example, the odometer of all the cars in my array?
Basically, I want to be able to use conditional statements with struct arrays, e.g.: For every element in my struct array, get the ones that a data satisfy a condition and, from those, get the minimum value of another data.
Thanks!
Finding the minimum value is pretty straightforward, using the minimum function, with a mapping argument:
julia> minimum(x->x.odometer, fleet)
0.08468003971220694
If you also want the index of the minimum, you can use the findmin function. Unfortunately, this does not, for some reason, support a function argument, so you have to create a temporary array, and apply findmin to that:
julia> findmin(getfield.(fleet, :odometer))
(0.08468003971220694, 1)
You can also use getproperty instead of getfield, they do the same thing for your struct, I'm not certain which is preferable. Probably, the most idiomatic solution would be to define accessor functions instead of using the field values directly. For example:
odometer(car::Car) = car.odometer
minimum(odometer, fleet)
findmin(odometer.(fleet))
For maximum values, use maximum and findmax.
Julia is about performance.
You should avoid using untyped structs hence your type definition should be:
mutable struct Car
load::Float64
locale::Float64
availability::Float64
odometer::Float64
end
The code for creating Vector can be shorter:
cars = [Car(rand(4)...) for _ in 1:5]
The most efficient way to find the index of the minimum element is:
julia> Base.isless(c1::Car,c2::Car) = c1.odometer < c2.odometer
julia> findmin(cs)
(Car(0.7623514815463603, 0.7523019237133661, 0.37422766075278413, 0.49830949323733464), 3)

Fortran Array Splice Initialization

I'm trying to initialize an array with equal spacing between 0 and 1 in fortran.
My code is :
program test
double precision :: h
double precision, dimension(:), allocatable :: x
h = 1./11
if(.not. allocated(x)) allocate(x(10))
x(1:10) = [h:(1-h):h] (*)
end program
The error I am given is "The highest data type rank permitted is INTEGER(KIND=8)" at the stared line.
I've tried to change it with
x(1:10) = h:(1-h):h
x = h:(1-h):h
x(1:10) = (/(h:(1-h):h)/)
and various other forms with no luck.
The syntax you're using is not valid Fortran and implied DO loops can't have non-integer bounds. You want something like this:
x = h * real([(i,i=1,size(x))],kind(h))
For more information, look up "array constructors" in the standard or a textbook.
Don't use (1:10) on the left side - see https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this
This expression
[h:(1-h):h]
is, from a Fortran point of view, broken. It looks a bit like an array slice, but that would require integers, not reals, and ( and ) rather than the [ and ]. And it looks a bit like an array constructor, for which [ and ] are correct, but h:(1-h):h isn't.
Try this
x = REAL([(ix,ix=1,10)],real64)/11
(having declared ix to be an integer). The expression (ix,ix=1,10) is an implied do-loop and, inside the [ and ] produces an array with integers from 1 to 10. I trust the rest is obvious.
Incidentally, since the lhs of my suggested replacement is the whole of x you don't actually need to explicitly allocate it, Fortran will automatically do that for you. This is one of the differences between a whole array section, such as your x(1:10) and the whole array, x.
And if that doesn't produce the results you want let us know.

What is the point of cell indexing in MATLAB

The point of indexing is mainly to get the value. In MATLAB,
for a cell array, there is content indexing ({}), and thus cell indexing (()) is only for selecting a subset from the cell array, right?
Is there anything other advanced usage for it? Like using it as
a pointer and pass it to a function?
There is a heavily simplified answer. {}-indexing returns you the content, ()-indexing creates a subcell with the indexed elements. Let's take a simple example:
>> a=x(2)
a =
[2]
>> class(a)
ans =
cell
>> b=x{2}
b =
2
>> class(b)
ans =
double
Now continue with non-scalar elements. For the ()-indexing everything behaves as expected, you receive a subcell with the elements:
>> a=x(2:3)
a =
[2] [3]
The thing really special to Matlab is using {}-indexing with non-scalar indices. It returns a Comma-Separated List with all the contents. Now what is happening here:
>> b=x{2:3}
b =
2
The Comma-Separated List behaves similar to a function with two return arguments. You want only one value, only one value is assigned. The second value is lost. You can also use this to assign multiple elements to individual lists at once:
>> [a,b]=x{2:3} %old MATLAB versions require deal here
a =
2
b =
3
Now finally to a very powerful use case of comma separated lists. Assume you have some stupid function foo which requires many input arguments. In your code you could write something like:
foo(a,b,c,d,e,f)
Or, assuming you have all parameters stored in a cell:
foo(a{1},a{2},a{3},a{4},a{5},a{6})
Alternatively you can call the function using a comma separated list. Assuming a has 6 elements, this line is fully equivalent to the previous:
foo(a{:}) %The : is a short cut for 1:end, index the first to the last element
The same technique demonstrated here for input arguments can also be used for output arguments.
Regarding your final question about pointers. Matlab does not use pointers and it has no supplement for it (except handle in oop Matlab), but Matlab is very strong in optimizing the memory usage. Especially using Copy-on-write makes it unnecessary to have pointers in most cases. You typically end up with functions like
M=myMatrixOperation(M,parameter,parameter2)
Where you input your data and return it.

Resources