I have a little problem with array.
I would like to be able to access it according to coordinates relating to a table of rank 3 AND also according to coordinates of table of rank 1.
Here is an example below:
integer, dimension(2,2,2) , target:: Int_array_xyz integer, dimension(8), pointer:: Int_array_xxx Int_array_xyz = RESHAPE((I,I=1,8),(/2,2,2/)) Int_array_xxx(1) => Int_array_xyz(1,1,1)
This approach is not accepted.
It is also not possible to do the following:
integer, dimension(2,2,2) :: Int_array_xyz integer, dimension(2) :: Int_array_xxx EQUIVALENCE (Int_array_xxx(1) , Int_array_xyz(1,1,1) )
I’m trying to improve a computational tool, and for some reason, the previous developer chose to reference some values in a 3-dimensional space, and other values in a 1-dimensional space.
When someone wishes to perform matrix operations by combining certain values, we are obliged to carry out an expensive and dangerous calculation of index matches.
If I could access to some of my table values alternately according to the two index systems (1 dimension and 3 dimensions) I would save a lot of development time.
I thought about using the RESHAPE function to be able to switch from a 3D system to a 1D system, but it is not possible to make a RESHAPE on itself!
XXX(:,:,:) = RESHAPE(XXX(:),(/2,2,2/))
So I have to create two tables. So that I double the memory space used, and also I need to synchronize the tables when one or the other is modified.
XYZ(:,:,:) = RESHAPE(XXX(:),(/2,2,2/))
Does anyone have any ideas?
Is that possible? Do I have to look further, on the side of "type" or "class"?
I have also try by using the PACK instruction, but not with any success.
Does anyone have an idea.
INTEGER, DIMENSION (10,3) :: MAT_XY INTEGER, DIMENSION (30) :: PACK_XX LOGICAL, DIMENSION (10,3) :: MASK ! PACK_XXX(:) = 0 ! for further try MASK(:,:) = .TRUE. MAT_XY=RESHAPE((/ (i,i=1,30) /),(/10,3/)) PACK(MAT_XY,MASK,PACK_XX) ! PACK(MAT_XY,.TRUE.,PACK_XX) ! I think, this is supposed to also work
Thank you for raising this query. As your query has reached inappropriate forum, I will help you in routing this topic to the correct forum for better discussion. We appreciate your patience.
Intel Developer Zone Support
S R, Arvind (Intel) wrote:
I will help you in routing this topic to the correct forum for better discussion.
Thanks Arvind !
Et voila !
PROGRAM ESSAI_POINTER !!---------------------------------------------------------------------- !! *** PROGRAM ESSAI_POINTER *** !! !! ** PURPOSE : LITTLE EXERCISE ON POINTER USES !! !!---------------------------------------------------------------------- IMPLICIT NONE INTEGER, DIMENSION (10,3) , TARGET :: MAT_I INTEGER, DIMENSION (:) , POINTER :: AD1_MAT_I MAT_I(:,:)=0 AD1_MAT_I(1:30) => MAT_I(:,:) MAT_I(:,:)=0 AD1_MAT_I(5:11)=3 print *,MAT_I(1:5 ,1) print *,MAT_I(6:10,1) print *,MAT_I(1:5 ,2) print *,MAT_I(6:10,2) print *,MAT_I(1:5 ,3) print *,MAT_I(6:10,3) MAT_I(3,:) = 2 print *,"" print *,AD1_MAT_I END PROGRAM ESSAI_POINTER
Not after the first try, but finally, I'm now able to do exactly what i need, with both method ! Pointer et EQUIVALENCE.
Thanks everyone for your support.
Thank you Dr. I really appreciate this kind of lighting! Moreover, EQUIVALENCE seems to be easier to use ...
So, I really enjoy not making bad choices in my early development.
for my knowledge, that it is the bad point of using EQUIVALENCE ?
EQUIVALENCE has been deemed obsolete in the standard. Its use can encourage errors and hard-to-maintain applications. There are almost always better ways to accomplish what EQUIVALENCE does.
But the EQUIVALENCE has deep roots in the assembler language i.e associate the same address to different variables and is very simple to understand.
The RESHAPE statement is in my opinion absolutely obscure: which other language has a similar function ?
People in charge of defining Fortran standard, who have made such a fuss with POINTER, TARGET, and so on ..., are continuing to mark as obsolete useful features and add new features uselessly complicated.
>>EQUIVALENCE has been deemed obsolete in the standard. Its use can encourage errors and hard-to-maintain applications.
Then what is the functional difference with: pointer(...) => RESHAPE(other(...)) or the ASSOCIATE equivalent?
To me, the pointer route is not only confusing, and complicated (Luigi's sentiments), but from my viewpoint is more "hard-to-maintain".
My reasoning is the EQUIVILENCE is placed with the variable declarations. Thus providing some indication that the variable/array is multi-purposed as well as how it is repurposed, whereas using a pointer hides this multi-purposes-ness from all places except where it is used. IOW pointer can tend towards being blindsided. I suppose one could argue that the foundation array having TARGET provides the heads up to some extent for pointer=> but no such heads up for ASSOCIATE.
I would say that most users of EQUIVALENCE don't understand how it works and aren't aware of the rules the compiler assumes are valid. For example, if you EQUIVALENCE an INTEGER and a REAL, and define the INTEGER, the REAL becomes undefined. The typical use of EQUIVALENCE in the past was to save storage by overlaying variables on the same memory location. It was never intended to be used for reinterpreting a value. I have seen programs misuse EQUIVALENCE and COMMON in ways that the standard prohibits and then the programmers complain when the code no longer works due to an optimization.
Pointer bounds remapping is the proper solution for this case. Some of the other substitutes for EQUIVALENCE are clunky, such as TRANSFER, but the meaning is clear and both the user and the compiler are clear as to what is happening.
I don't get the gripe about ASSOCIATE.
>>I don't get the gripe about ASSOCIATE
While ASSOCIATE does not provide for re-typing a variable/array, it does provide for repurposing the, or part of the, variable/array.
The non-portable UNION can also do the same. There are many cases in programming where it is expedient to represent the same memory location(s) as differing types. Reading data files form old systems with non-conforming data layouts.
I eliminated equivalence from all my code many tears ago, I found it had been used in some very cludgy ways and was a source of some unpredictable results. Irrespective of if you like it or not, It has been declared obsolete and thus it is not wise to be developing new code that uses it. In my world all new code should only be compiled with standards checking on. Simillarly I won't use a circular saw without the safety guard ot drive my car without a seat belt.
>>ASSOCIATE can do much more than UNION or EQUIVALENCE...
Correct, however, it cannot retype a variable/array/array section, or re-layout a record, whereas a UNION (or a "cast") can.
Thank you for all your answers, which I read with great interest.
Your opinions seem to differ. So here is how I construct my conclusion:
jimdempseyatthecove (Blackbelt) wrote:
[…] My reasoning is the EQUIVALENCE is placed with the variable declarations. […]
Steve Lionel (Ret.) (Blackbelt)
[…] if you EQUIVALENCE an INTEGER and a REAL, and define the INTEGER, the REAL becomes undefined. […]
Luigi R. wrote:
Not using EQUIVALENCE that has a deep root in the assembler language can prevents you to create efficient software architectures.
The performance of my code is a real priority.
It seems to me that efficiency and performance have more or less the same meaning.
My conclusion is that EQUIVALENCE is an excellent solution to my problem. But I'm just a paper belt... so I'm very interested in your explanations!
Thanks thanks thanks :-)
jimdempseyatthecove (Blackbelt) wrote:
>>ASSOCIATE can do much more than UNION or EQUIVALENCE...
Correct, however, it cannot retype a variable/array/array section, or re-layout a record, whereas a UNION (or a "cast") can. ..
Jim, what do you mean by "re-layout a record"?
TYPE MyRecord UNION MAP REAL(8) :: BLA END MAP MAP CHARACTER(LEN=8) :: NAME END MAP MAP INTEGER(4) :: COUNT END MAP END UNION ... ! other record items REAL(8) :: OTHER(nnn) END TYPE MyRecord
And use that type to read records from a file (as binary).
When the data file contains POD (plain old data), and when you cannot tell what the record is until after you read the record, it is useful to be able to describe the record in a manner that has a multiplicity of declarations. A similar issue when writing arbitrary POD files.
Thanks, I presumed you were referring to UNIONs but I wanted to be sure.
Would you by any chance have a fully worked out, real-life example of record processing using this non-standard UNION type along with some measure of performance you get, either in terms of speed and/or data size that you think is important to consider?
Now, one can achieve something similar to the above use case of UNIONs involving POD via polymorphiic types, TRANSFER, etc. in Fortran. But then the issue brought up often is performance. But as far as I know, there has been no objective quantification of any difference in performance with UNIONs vs some standard-conforming one, just words and references to inefficient assembler code, etc. That does not help move beyond the status quo with Fortran. With an actual example, if someone can illustrate substantial difference in non-standard UNION and what the standard offers now, that could help contemplate what to consider in a future revision to the standard - it's worth an online discussion (see below) among the interested parties.
Readers: please see this recent site at GitHub: https://github.com/j3-fortran/fortran_proposals