Apply slicing to array valued function in Fortran [duplicate] - arrays

How does one access an element of an array that is returned from a function? For example, shape() returns an array of integers. How does one compare an element of that array to an integer? The following does not compile:
integer :: a
integer, dimension(5) :: b
a = 5
if (a .eq. shape(b)) then
print *, 'equal'
end if
The error is:
if (a .eq. shape(c)) then
1
Error: IF clause at (1) requires a scalar LOGICAL expression
I understand that this is because shape(c) returns an array. However, accessing an element of the array does not appear to be possible like so: shape(c)(1)
Now if I add these two lines:
integer, dimension(1) :: c
c = shape(b)
...and change the if clause to this:
if (a .eq. c(1)) then
... then it works. But do I really have to declare an extra array variable to hold the return value of shape(), or is there some other way to do it?

Further to the answers that deal with SHAPE and logical expressions etc, the general answer to your question "How does one access an element of an array that is returned from a function?" is
you assign the expression that has the function reference to an array variable, and then index that array variable.
you use the expression that has the function reference as an actual argument to a procedure that takes a dummy array argument, and does the indexing for you.
Consequently, the general answer to your last questions "But do I really have to declare an extra array variable to hold the return value of shape(), or is there some other way to do it?" is "Yes, you do need to declare another array variable" and hence "No, there is no other way".
(Note that reasonable optimising compilers will avoid the need for any additional memory operations/allocations etc once they have the result of the array function, it's really just a syntax issue.)
The rationale for this particular aspect of language design is sometimes ascribed to a need to avoid syntax ambiguity and confusion for array function results that are of character type (they could potentially be indexed and/or substringed - how do you tell what was intended?). Others think it was done this way just to annoy C programmers.

Instead of using shape(array), I would use size(array).
Note that this will return an integer indicating how many elements there are in ALL dimensions, unless you specify the DIM attribute, in which case it will return only the number of elements in the specified dimension.
Take a look at the gfortran documentation:
http://gcc.gnu.org/onlinedocs/gfortran/SIZE.html.
Also, look up lbound and ubound.

Note that the expression
a == shape(b)
returns a rank-1 array of logicals and the if statement requires that the condition reduce to a scalar logical expression. You could reduce the rank-1 array to a scalar like this:
if (all(a == shape(b)))
This is certainly not a general replacement for the syntactically-invalid application of array indexing to an array-returning function such as shape(b)(1).

It is possible even without the intermediate variable using ASSOCIATE:
real c(3,3)
associate (x=>shape(c))
print *,x(1),x(2)
end associate
end

Related

How to Compare two arrays and its elements in visual foxpro?

I Am having two arrays named atest and NEWARRAY,I have tried to compare the elements of two arrays with simple if()and this is comparing only the first element of an array , how to compare all the array values at once,here's my code
IF (Alltrim(atest)== Alltrim(NEWARRAY))
Messagebox('Success',64,'Status')
Else
Messagebox('MisMatch',16,'Status')
ENDIF
Fox has a few functions that operate on whole arrays - like acopy, ascan and asort - but there is no built-in function that compares whole arrays. So you'll have to do the comparison element per element, for example with a for loop.
And yes, if you use an array name as an expression - including passing it by value - then you'll get the value of the first array element instead. There is one exception, though: when you pass an array to a built-in function in a place where an array parameter is expected then the compiler will automatically emit a reference token under the hood in order to arrange pass-by-reference instead of pass-by-value.
So, if you have a user-defined function f() to which you want to pass an array a then you need to call it like this: f(#m.a) but you can call built-in functions taking arrays like this: alen(a) (since the m. can be left off in this situation as well). In fact, Fox would complain if you coded something like alen(#m.a) or alen(#a), and older Foxen could even crash in such situations.
Conversely, if an array is the target of an assignment like a = 42 or store 42 to a then the value will be assigned to all array elements. This is convenient for initialising arrays to something like 0, '' or .null..
Hence, if you have two arrays a and b then a = b will assign the first value of b to all elements of a, and if a == b will compare the respective first cells only.
Sidenote: should you ever have to compare records from tables with equal or equivalent structure then you should remember to look up compobj(). It does for objects and scatter records what Fox won't do for arrays: it compares them whole-sale. That is, it compares the values of properties with matching names and tells you if there's a mismatch, and it does so much faster than hand-crafted code could do it.
Theoretically you could gather an array into a table/cursor record and then use scatter name Walther to produce a scatter record, which could then be compared to a scatter record named Herbert that was produced in a similar fashion from the contents of the other array: compobj(m.Walther, m.Herbert) would tell you whether the original arrays were equal or not. However, I'd be hard pressed to imagine circumstances where one might use something like that in production code...
You could create a simple procedure like this for comparison:
Procedure CompareArrays(ta1, ta2)
If Alen(ta1) != Alen(ta2)
Return .F.
EndIf
Local ix
For ix=1 to Alen(ta1)
If (Type('ta1[m.ix]') != Type('ta2[m.ix]') or ta1[m.ix] != ta2[m.ix])
Return .F.
endif
endfor
endproc
And pass your arrays by reference. ie:
isIdentical = CompareArrays(#laArr1, #laArr2)
If array members could hold objects, you should use compobj for comparison of array elements.

Why [1:2] != Array[1:2]

I am learning Julia following the Wikibook, but I don't understand why the following two commands give different results:
julia> [1:2]
1-element Array{UnitRange{Int64},1}:
1:2
julia> Array[1:2]
1-element Array{Array,1}:
[1,2]
Apologies if there is an explanation I haven't seen in the Wikibook, I have looked briefly but didn't find one.
Type[a] runs convert on the elements, and there is a simple conversion between a Range to an Array (collect). So Array[1:2] converts 1:2 to an array, and then makes an array of objects like that. This is the same thing as why Float64[1;2;3] is an array of Float64.
These previous parts answer answered the wrong thing. Oops...
a:b is not an array, it's a UnitRange. Why would you create an array for A = a:b? It only takes two numbers to store it, and you can calculate A[i] basically for free for any i. Using an array would take an amount of memory which is proportional to the b-a, and thus for larger arrays would take a lot of time to allocate, whereas allocation for UnitRange is essentially free.
These kinds of types in Julia are known as lazy iterators. LinSpace is another. Another interesting set of types are the special matrix types: why use more than an array to store a Diagonal? The UniformScaling operator acts as the identity matrix while only storing one value (it's scale) to make A-kI efficient.
Since Julia has a robust type system, there is no reason to make all of these things arrays. Instead, you can make them a specialized type which will act (*, +, etc.) and index like an array, but actually aren't. This will make them take less memory and be faster. If you ever need the array, just call collect(A) or full(A).
I realized that you posted something a little more specific. The reason here is that Array[1:2] calls the getindex function for an array. This getindex function has a special dispatch on a Range so that way it "acts like it's indexed by an array" (see the discussion from earlier). So that's "special-cased", but in actuality it just has dispatches to act like an array just like it does with every other function. [A] gives an array of typeof(A) no matter what A is, so there's no magic here.

Array with specific indices

Is it possible to have an array with custom allocatable indices in Fortran?
For example
integer a(3:7)
will create following elements: a(3), a(4), a(5), a(6), and a(7).
Is there any way to create, say, only a(3), a(5), and a(7) to save memory, as other elements will never be used?
If that is possible for static case, can we have similar thing for dynamic case?
Edit:
say I have a complicated expression with various a(i,j,k). Now depending on i,j,k, a(i,j,k) can be assigned some external function "F" with different arguments. Here i,j,k can non-uniformly go up to 1000, i.e, say, 'i' takes values 12,16,34,...,999 etc only.But in my code if I declare "integer a(1000,1000,1000)" that will be a waste of memory.
COMMON/I/i1,i2,i3,i4,i5,i6
a(i1,i2,i3)=F(1)
a(i3,i2,i4)=F(2)
a(i1+i4,i5,i3)=F(3)
function=a(i1,i2,i3) *(...) + a(i3,i2,i4) *(...) + ...
Now changing all the instances of a(i,j,k) in the expression by the external function would be a solution, but I don't want to modify the expression. That is why, I was wondering whether there is any alternative without wasting lot of memory.

MATLAB sum over all elements of array valued expression

So I've been wondering about this for a while now. Summing up over some array variable A is as easy as
sum(A(:))
% or
sum(...sum(sum(A,n),n-2)...,1) % where n is the dimension of A
However once it gets to expressions the (:) doesn't work anymore, like
sum((A-2*A)(:))
is no valid matlab syntax, instead we need to write
foo = A-2*A;
sum(foo(:))
%or the one liner
sum(sum(...sum(A-2*A,n)...,2),1) % n is the dimension of A
The one liner above will only work, if the dimension of A is fixed which, depending on what you are doing, may not necessary be the case. The downside of the two lines is, that foo will be kept in memory until you run clear foo or may not even be possible depending on the size of A and what else is in your workspace.
Is there a general way to circumvent this issue and sum up all elements of an array valued expression in a single line / without creating temporal variables? Something like sum(A-2*A,'-all')?
Edit: It differes from How can I index a MATLAB array returned by a function without first assigning it to a local variable?, as it doesn't concern general (nor specific) indexing of array valued expressions or return values, but rather the summation over each possible index.
While it is possible to solve my problem with the answer given in the link, gnovice says himself that using subref is a rather ugly solution. Further Andras Deak posted a much cleaner way of doing this in the comments below.
While the answers to the linked duplicate can indeed be applied to your problem, the narrower scope of your question allows us to give a much simpler solution than the answers provided there.
You can sum all the elements in an expression (including the return value of a function) by reshaping your array first to 1d:
sum(reshape(A-2*A,1,[]))
%or even sum(reshape(magic(3),1,[]))
This will reshape your array-valued expression to size [1, N] where N is inferred from the size of the array, i.e. numel(A-2*A) (but the above syntax of reshape will compute the missing dimension for you, no need to evaluate your expression twice). Then a single call to sum will sum all the elements, as needed.
The actual case where you have to resort to something like this is when a function returns an array with an unknown number of dimensions, and you want to use its sum in an anonymous function (making temporary variables unavailable):
fun = #() rand(2*ones(1,randi(10))); %function returning random 2 x 2 x ... x 2 array with randi(10) dimensions
sumfun = #(A) sum(reshape(A,1,[]));
sumfun(fun()) %use it

In Matlab, can I access an element of an array, which is in turn a value of a container.Map?

Here is a code snippet, that shows what I want and the error, that follows:
a = [1, 2];
m = containers.Map('KeyType','char', 'ValueType','any');
m('stackoverflow.com') = a;
pull_the_first_element_of_the_stored_array = m('stackoverflow.com')(1);
??? Error: ()-indexing must appear last in an index expression.
How do I access an element of the array, which is in turn a value of a map object?
I could have done this:
temp = m('stackoverflow.com');
pull_the_first_element_of_the_stored_array = temp(1);
But I do not want to create an intermediate array only to pull a single value out of it.
EDIT : This is a duplicate of How can I index a MATLAB array returned by a function without first assigning it to a local variable? The answer is there.
This is another case where you can get around syntax limitations with small helper functions. EG:
getFirst = #(x)x(1);
pull_the_first_element_of_the_stored_array = getFirst(m('stackoverflow.com'));
This still needs two lines, but you can often reuse the function definition. More generally, you could write:
getNth = #(x, n) x(n);
And then use:
getNth (m('stackoverflow.com'),1);
Although this question is a duplicate of this previous question, I feel compelled to point out one small difference between the problems they are addressing, and how my previous answer could be adapted slightly...
The previous question dealt with how to get around the syntax issue involved in having a function call immediately followed by an indexing operation on the same line. This question instead deals with two indexing operations immediately following one another on the same line. The two solutions from my other answer (using SUBSREF or a helper function) also apply, but there is actually an alternative way to use SUBSREF that combines the two indexing operations, like so:
value = subsref(m,struct('type','()','subs',{'stackoverflow.com',{1}}));
Note how the sequential index subscripts 'stackoverflow.com' and 1 are combined into a cell array to create a 1-by-2 structure array to pass to SUBSREF. It's still an ugly one-liner, and I would still advocate using the temporary variable solution for the sake of readability.

Resources