James Tursa
See the gfortran documentation for information concerning its
implementation of these constructs.
--
steve
These came with VAX (yes VAX, not VMS) that tried to define standard
calling conventions. They defined call by value, reference, and
descriptor. Each compiler would use the appropriate method, with
%val(), %ref(), and %descr() allowing one to override the default.
(Especially useful for interlanguage calling).
With assumed shape arrays, Fortran needs a call by descriptor method
to pass the array information. Fortran 2003 added call by value,
possibly related to the C interoperability feature to be able
to call C routines expecting call by value. C interoperability
also adds C_LOC(), which gives a C pointer to a data item.
Compilers with some connection to DEC, or trying to be compatible
with programs written for VAX might implement %LOC() and %VAL().
-- glen
> On Nov 24, 10:30 am, James Tursa <aclassyguywithakno...@hotmail.com>
> wrote:
> > The non-standard %LOC() and %VAL() constructs are available in the
> > Intel Fortran and Compaq Fortran compilers that I have (32-bit,
> > WinXP). Are these constructs available in other compilers such as
> > gfortran, f95, etc? What about linux, mac, etc.? If not, is there a
> > workaround for this functionality? I am writing a package for others
> > to use and would like it to run in other environments out of the box
> > if possible. Thanks.
>
> See the gfortran documentation for information concerning its
> implementation of these constructs.
I don't have any kind of handy list, but there are certainly plenty of
compilers that do not accept these constructs. I've used many such in
the past. How many of those compilers are current ones or ones that your
particular users are likely to run into I couldn't say. I haven't kept
track, largely because I've never considered those constructs portable
enough to use in my own code.
As for "workarounds", I'd suggest looking at the f2003 C interop
facilities. Those are implemented in many f95 compilers. I'd personally
tend to consider the %loc and %val stuff as more like workarounds for
lack of f2003 C interop support in some compilers. You might keep in
mind my guess that the prevalance of support for the f2003 C interop
features is likely to increase with time, while support for %loc and
%val is likely to decrease.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Did you check the comparison pages at the Polyhedron site? IIRC it has
an "extensions supported" category for most compilers...
<www.polyhedron.com.uk> (otomh, I _think_ that's home page)
--
Thanks. What I am doing is turning separate items, a raw address and
shape information, into a Fortran pointer. I know it is non standard,
but it works beautifully for the target (please excuse the pun)
audience, MATLAB. The supplied MATLAB functions for getting at a
MATLAB variable return (in separate functions) a raw address and shape
information. I discovered a way to get these separate items all
packaged up into a single Fortran pointer by using a combination of
explicit and implicit interface routines, but I need the %VAL( ) and
%LOC( ) constructs. e.g., here is an example from my code:
function fpGetPr2Double( mx ) result(fp)
implicit none
real(8), pointer :: fp(:,:)
!-ARG
mwPointer, intent(in) :: mx
!-COM
real(8), pointer :: Apx2(:,:)
common /MatlabAPI_COMA2/ Apx2
!-LOC
mwSize, parameter :: stride = 1
mwPointer :: pr
mwSize, pointer :: dims(:)
!-----
if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. &
& mxGetNumberOfDimensions(mx) == 2 ) then
pr = mxGetPr( mx )
dims => fpGetDimensions( mx )
call MatlabAPI_COM_Apx2( %VAL(pr), stride, dims )
fp => Apx2
else
nullify( fp )
endif
return
end function fpGetPr2Double
!----------------------------------------------------------------------
subroutine MatlabAPI_COM_Apx2( A, stride, DIMS )
implicit none
!-ARG
mwSize, intent(in) :: stride, DIMS(2)
real(8), target, intent(in) :: A(stride,DIMS(1),DIMS(2))
!-COM
real(8), pointer :: Apx2(:,:)
common /MatlabAPI_COMA2/ Apx2
!-----
Apx2 => A(1,:,:)
return
end subroutine MatlabAPI_COM_Apx2
In the above code, mx is an address of a MATLAB variable, the mxGetPr
returns the raw address of the data of the MATLAB variable, and dims
will contain the dimensions of the MATLAB variable (in this case a 2D
object). So I have a raw address in pr (the mwSize is just an
integer(4) or integer(8) to contain the address) and the shape in
separate pieces. The fpGetPr2Double routine has an explicit interface,
of course. Then I call the implicit interface routine
MatlabAPI_COM_Apx2 to get the raw pieces passed down and interpreted
as a regular Fortran array, which can then be pointed to with a
Fortran pointer. The end result up the chain is a Fortran pointer that
has the correct shape of the original data. Having all of the
dimensions & shape packaged in the Fortran pointer has obvious
advantages in the calling routine because I can now access the raw
data area just like it was a regular Fortran array. Also, a variation
of this can use MATLAB memory allocation functions to allocate target
memory (which gets garbage collected by the MATLAB memory manager if
necessary) instead of the Fortran allocate function. And I have a
reshape function that returns a pointer to the original data without
copying ... an advantage one might want if working with very large
arrays. This all works great, but only if the compiler supports the
%VAL( ) and %LOC( ) constructs. I will look into the C_LOC function
to see if that will help me.
James Tursa
(snip)
For use with Fortran pointers, C_LOC() and C_F_POINTER() are
part of the Fortran 2003 standard implemented by many current
compilers. That might be a better way to go.
-- glen
James Tursa schrieb:
[...]
>
> function fpGetPr2Double( mx ) result(fp)
> implicit none
> real(8), pointer :: fp(:,:)
> !-ARG
> mwPointer, intent(in) :: mx
the above line (among others) does not seem to be a Fortran statement - do you
run this through a preprocessor before compiling?
> !-COM
> real(8), pointer :: Apx2(:,:)
> common /MatlabAPI_COMA2/ Apx2
> !-LOC
> mwSize, parameter :: stride = 1
> mwPointer :: pr
> mwSize, pointer :: dims(:)
> !-----
> if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. &
> & mxGetNumberOfDimensions(mx) == 2 ) then
> pr = mxGetPr( mx )
> dims => fpGetDimensions( mx )
> call MatlabAPI_COM_Apx2( %VAL(pr), stride, dims )
For this case, the VALUE attribute might be appropriate. If you specify an explicit interface
interface
subroutine MatlabAPI_COM_Apx2( %VAL(pr), stride, dims )
mwPointer, value :: pr ! let's hope the preprocessor doesn't mangle this ...
mwSize, intent(in) :: stride
mwSize :: dims(*)
end subroutine
end interface
in the declaration section of your function then you should be able to dispense with
specifying %VAL() on the call.
> fp => Apx2
> else
> nullify( fp )
> endif
> return
> end function fpGetPr2Double
Regards
Reinhold
Good thought. I looked here but they don't list LOC or VAL:
http://www.polyhedron.com/pb05-win32-language0html
http://www.polyhedron.com/pb05-linux-language0html
James Tursa
>> mwPointer, intent(in) :: mx
>
>the above line (among others) does not seem to be a Fortran statement - do you
>run this through a preprocessor before compiling?
>
Yes. mwPointer and mwSize are token replaced by a pre-processor with
integer*4 or integer*8 as appropriate for the installation.
James Tursa
Short: gfortran supports %LOC(), %VAL() and %REF(), see
http://gcc.gnu.org/onlinedocs/gfortran/Argument-list-functions.html and
GCC/gfortran runs on a large variety of systems (Sparc, x86, arm, mips,
PowerPC, ia64, x86-64, s390, ...) and operating systems (FreeBSD, Linux,
Windows, Darwin (Mac), AIX, Solaris, HPUX, ...). [And the Intel compiler
you mention also runs on (x86 and x86-64) Windows, Linux and Mac.] Note,
however, that those are only supported as arguments in procedure calls
and not on their own (cf. "LOC()"). Note further that these all are
vendor extensions, which are relatively common but by far not supported
by all compilers.
As others have pointed out before, using the C binding support is the
better alternative. See, e.g.,
http://gcc.gnu.org/onlinedocs/gfortran/Interoperability-with-C.html and
especially
http://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Subroutines-and-Functions.html
for an introduction, which should be relatively vendor agnostic.
The C binding support - as defined in the Fortran 2003 standard - is
present is a number of recent compilers, but older ones do not have it.
It depends on your users whether it is more likely that they have
compilers with %LOC, %VAL or with C binding support. But if you have the
choice, I would go for the latter. Advantages: (a) C bindings are well
defined (Fortran standard; vendor extensions tend to differ slightly
between vendors and even different versions). (b) I think the syntax is
also easier: You define what the procedure wants to get (e.g. a
pass-by-value argument) and then you simply pass the variable in the
call without having to care whether it should be a %VAL or a %REF or
%LOC. (c) The market share of older compilers is decreasing thus C
binding support should become more and more common.
Example for compilers not supporting %VAL: NAG f95. Example for not
supporting C bindings: Open64, g77. Examples for supporting both: ifort,
gfortran, sunf95, g95.
Tobias
When I look at the above, the first thing that comes to my mind is:
function fpGetPr2Double( mx ) result(fp)
use ISO_C_BINDING
implicit none
real(C_DOUBLE), pointer :: fp(:,:)
!-ARG
type(C_PTR), intent(in) :: mx ! Or we could use integer(C_INTPTR_T)
!-LOC
integer(C_SIZE_T), parameter :: stride = 1
type(C_PTR) :: pr
integer(C_SIZE_T), pointer :: dims(:)
real(C_DOUBLE), pointer :: A(:,:,:)
!-FUN
interface
function mxGetPr(mx) bind(C,name='mxGetPr')
use ISO_C_BINDING
implicit none
type(C_PTR) mxGetPr
type(C_PTR), value :: mx
end function mxGetPr
function mxIsDouble(mx) bind(C,name='mxIsDouble')
use ISO_C_BINDING
implicit none
integer(C_INT) mxIsDouble
type(C_PTR), value :: mx
end function mxIsDouble
function mxIsSparse(mx) bind(C,name='mxIsSparse')
use ISO_C_BINDING
implicit none
integer(C_INT) mxIsSparse
type(C_PTR), value :: mx
end function mxIsSparse
function mxGetNumberOfDimensions(mx) bind(C,name= &
'mxGetNumberOfDimensions')
use ISO_C_BINDING
implicit none
integer(C_SIZE_T) mxGetNumberOfDimensions
type(C_PTR), value :: mx
end function mxGetNumberOfDimensions
function mxGetDimensions(mx) bind(C,name='mxGetDimensions')
use ISO_C_BINDING
implicit none
type(C_PTR) mxGetDimensions
type(C_PTR), value :: mx
end function mxGetDimensions
end interface
!-----
if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. &
& mxGetNumberOfDimensions(mx) == 2 ) then
pr = mxGetPr( mx )
call C_F_POINTER(mxGetDimensions( mx ), dims, [2])
call C_F_POINTER(pr, A, [stride,dims(1),dims(2)])
fp => A(1,:,:)
nullify(A)
else
nullify( fp )
endif
return
end function fpGetPr2Double
Read Section 15 of N1601.pdf. It makes a real difference when you
face interoperability issues.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
(snip)
> end function fpGetPr2Double
>
>Read Section 15 of N1601.pdf. It makes a real difference when you
>face interoperability issues.
Wow ... that's the *first* thing that comes to your mind? It's going
to take me awhile to digest all of that! Thanks for the post. Bottom
line for me is I want to support people with older compilers as well
as newer compilers, so I will look into creating another version of my
package using the C interop facilities, particularly the C_LOC and
C_F_POINTER routines. But I don't have the latest Intel compiler, so I
will have to look into getting an upgrade or getting another compiler
that supports this.
James Tursa
If you want to work with Matlab, C-interop is the way to go. It's
pretty easy to read the documentation/header files for the (more
capable) C interface api and write out the relevant interface blocks.
Supplement those with a few parameters for kinds and some utility
functions (like your specific pointer example) whack it all into a
module or two and away you go.
So much cleaner and simpler than the non-standard, archaic, preprocessor
based interface that the Mathworks provides for working with Fortran code.
:( would be better if matlab didn't treat Fortran as a second class
citizen and created a proper binding.
Glen, I surprised you would try to make such a distinction
between VAX and VMS. They were, after all, developed together,
one for the other, so to speak. And were it me, I'd have made
the opposite claim, that it was VMS (or more correctly VAX/VMS
as it was know at the time), the software, not VAX, the hardware,
that made %LOC, %VAL and %DESCR available (and useful). The
hardware could pretty much care less, except for the mapping of
various addressing/indirection modes, etc., in VAX Macro (Macro-32).
But in Macro, those %xxxx names weren't present.
So VAX/VMS (and all subsequent versions of VMS on VAX, Alpha
and IA64), or just VMS. Not just VAX.
-Ken
>> These came with VAX (yes VAX, not VMS) that tried to define standard
>> calling conventions. ?[...]
> Glen, I surprised you would try to make such a distinction
> between VAX and VMS. They were, after all, developed together,
> one for the other, so to speak. And were it me, I'd have made
> the opposite claim, that it was VMS (or more correctly VAX/VMS
> as it was know at the time), the software, not VAX, the hardware,
> that made %LOC, %VAL and %DESCR available (and useful).
I once got it wrong, but now don't have the reference. I believe
I asked once on comp.os.vms and was told that it was VAX.
I have "VAX Architecture Reference Manual" by Timothy Leonard,
and it isn't in there.
> The hardware could pretty much care less, except for the mapping of
> various addressing/indirection modes, etc., in VAX Macro (Macro-32).
> But in Macro, those %xxxx names weren't present.
> So VAX/VMS (and all subsequent versions of VMS on VAX, Alpha
> and IA64), or just VMS. Not just VAX.
As I don't have a reference, it is hard to say. If the idea of
having a language independent call convention came from the hardware
people, it is possible. I never used VAX/Unix, and don't know
how they did calls there. Even if it was a VAX standard,
used by VMS, subsequent ports of VMS would have to support
them for software porting purposes.
Defining it with the hardware would make assembly code more
portable between different OS.
-- glen
OK, it is in "VAX11/780 Architecture Handbook", copyright 1977.
Appendix C, "Procedure Calling and Condition Handling"
The description of the calling convention says "VAX-11" thoughout.
For Condition Handling it says VAX/VMS. It looks to me like someone
wanted the calling convention to be OS independent, but realized
that condition handling was VMS dependent.
Though the % prefix will conflict with the PL/I preprocessor
if one tries to do it for PL/I.
-- glen
Well, yes, there is that. If you look at their Fortran doc some of it
isn't even syntactically correct for F77. And the Fortran example they
give in the doc for linking to their BLAS and LAPACK routines does not
work at all for the Intel Fortran compiler, their only officially
supported Fortran compiler, because their libraries still use the old
name mangling of @number_of_argument_bytes at the end while the Intel
Fortran compiler does not do that by default. So if you copy & paste
their exact example from the doc and use their exact compile commands
it will not work (need to add the /Gm compile flag to get that
behavior and get it to link ... took me awhile to figure that one
out). But overall, I am not complaining much about it since at least
they *do* offer Fortran support. Mostly I write Fortran code that the
MATLAB folks left out of their official product or other helpful
Fortran code (like the code that spawned this thread) and post it to
their file sharing system for others to download and use.
James Tursa
The %VAL, %DESC and %REF keywords were not used for all languages.
They are simply Fortran's way of supporting the argument passing
mechanisms supported by the OpenVMS Calling Standard.
I have my VAX Architecture Handbook out too and it simply notes
the Fortran built-ins as an example. For BASIC there is the
BY keyword that can be followed by DESC, REF or VALUE to indicate
the mechanism. Pascal has %IMMED, $REF and %DESC (I think).
BLISS passes by value by default (like C). There is a %REF( )
built-in, but no %DESC as it is expected that BLISS programmers
will build descriptors themselves (again, the same as C). PL/I
provides DESCRIPTOR, REFERENCE and VALUE built-in functions.
As for %LOC...well, Pascal has IADDRESS and BASIC has LOC. In
BLISS everything is an address that has to be explicitly
de-referenced with a '.'. C has the '&' operator and PL/I has
ADDR().
Of course there is nothing like that for MACRO-32 where it is
expected that the programmer will load the stack with the
relevant values, whether they be values, references or
references to descriptors.
Tim.
> The %VAL, %DESC and %REF keywords were not used for all languages.
> They are simply Fortran's way of supporting the argument passing
> mechanisms supported by the OpenVMS Calling Standard.
All VMS languages were pretty much required to have some syntax for
specifying the passing mechanism. The spellings shown here were used
for VAX FORTRAN, but as Tim says, other languages had their own syntax,
which was not always something that looked like a function call
(ignoring the percent). VAX PASCAL, for example, used attributes in
square brackets, if I recall correctly.
It was a wonderful thing - an operating system designed from the start
to have a rich multi-language environment and a single set of calling
conventions. I've never seen such a thing since.
I'll comment that other Fortran vendors adopted LOC(), without the %,
and the DEC compilers eventually supported that too. Unlike %LOC, which
could be used anywhere, %VAL, %REF and %DESC were usable only in actual
argument lists.
--
Steve Lionel
Developer Products Division
Intel Corporation
Nashua, NH
For email address, replace "invalid" with "com"
User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran
"Goals for the VAX-11 calling standard are:
1. The standard must be applicable to all of the intermodule
CALLable interfaces in the VAX-11 software system.
Specifically, the standard considers the requirements of
BASIC, COBOL, FORTRAN, BLISS, assembler, and CALLs to
the operating system."
(and later)
... "Each language is augmented to provide the following
compile-time intrinsic functions:
%VAL(arg) -- Corresponding argument list entry is the actual
32 bit value of the argument arg, as defined in
the language."
(continuing on for %REF and %DESCR. No mention of %LOC)
-- glen
why do the words "tempest" and "teapot" seem to come to my mind I
wonder??? ;)
--
I wonder how different things would be if Intel had the idea
of a system independent calling convention. VAX and 8086 came
out at about the same time, though presumably they were in
development for some years before.
Mabye even no need for C interoperability in Fortran!
(Assume other processors also followed along.)
-- glen
Have you EVER been in a project to design such a thing? I have.
>Mabye even no need for C interoperability in Fortran!
>(Assume other processors also followed along.)
%deity preserve me :-(
The thing that kills you is semantic incompatibility, especially
conceptual incompatibility. E.g. Cobol requires integer overflow
to the trapped, and Java forbids it. Fortran finalisers are
called in different places from C++ destructors. And so on.
Regards,
Nick Maclaren.
AFAIK Intel never wrote an OS and only implemented a few language
compilers on their hardware.
I really was wondering about the insistence on an argument of VAX vis a
vis VMS -- it seems to me moot as one didn't exist w/o the other and VMS
simply came at a time the various languages already existed in a place
where folks recognized there was a need/market/opportunity to support
them all and had a new product to incorporate that support into.
--
>>I wonder how different things would be if Intel had the idea
>>of a system independent calling convention. VAX and 8086 came
>>out at about the same time, though presumably they were in
>>development for some years before.
> Have you EVER been in a project to design such a thing? I have.
>>Mabye even no need for C interoperability in Fortran!
>>(Assume other processors also followed along.)
> %deity preserve me :-(
> The thing that kills you is semantic incompatibility, especially
> conceptual incompatibility. E.g. Cobol requires integer overflow
> to the trapped, and Java forbids it. Fortran finalisers are
> called in different places from C++ destructors. And so on.
VAX CALL instructions also push the trap enable bits onto
the stack, and RET restores them. If the COBOL routines
enable overflow at entry, that would fix that problem.
Though since neither C++ nor Java existed in 1978, you
can't blame VAX for that. COBOL did exist, and was considered.
Mixed language programming will always have some problems.
The IA32 stdcall vs. cdecl conventions didn't help at all.
Also, the S/360 BALR saves the mask bits along with the return
address, but BR doesn't restore them.
-- glen
| Also, the S/360 BALR saves the mask bits along with the return
| address, but BR doesn't restore them.
The called program could - if it wanted - change them, and if it did,
it used SPM to restore them.
That has nothing to do with the price of fish.
In any case, PL/I has ADDR etc builtins.
| I really was wondering about the insistence on an argument of VAX vis a
| vis VMS -- it seems to me moot as one didn't exist w/o the other and VMS
| simply came at a time the various languages already existed in a place
| where folks recognized there was a need/market/opportunity to support
| them all and had a new product to incorporate that support into.
"Various languages" existed from the 1950s, and continued
to exist though the 1960s -- including the time when the IBM S/360 was designed
and built.
CDC NOS VE.
Pr1me, etc, Burroughs had it before.
Nice to see that you still hang out here, Steve.
> All VMS languages were pretty much required to have some syntax for
> specifying the passing mechanism. The spellings shown here were used
> for VAX FORTRAN, but as Tim says, other languages had their own syntax,
> which was not always something that looked like a function call
> (ignoring the percent). VAX PASCAL, for example, used attributes in
> square brackets, if I recall correctly.
>
> It was a wonderful thing - an operating system designed from the start
> to have a rich multi-language environment and a single set of calling
> conventions. I've never seen such a thing since.
Please don't use the past tense! I'm still using VMS at home and at
work.
It would be nice if there were a Fortran compiler for VMS which supports
the new standard. Not that I personally need many of the features, but
I could compile newer code and of course in general it is sad the
Fortran on VMS is now taking a back seat, whereas for many years it was
the gold standard.
I agree. When discussing computer architectures and most software,
present tense makes sense to me. The architecture still exists even
if no instances (machines) exist, though usually there will still
be at least one. There are still plenty of VMS machines, including VAX,
running.
> It would be nice if there were a Fortran compiler for VMS which supports
> the new standard. Not that I personally need many of the features, but
> I could compile newer code and of course in general it is sad the
> Fortran on VMS is now taking a back seat, whereas for many years it was
> the gold standard.
I believe VAX/VMS stopped at Fortran 77, but that Fortran 95
compilers exist for Alpha/VMS, and I believe also Itanium/VMS.
I don't know at all about Fortran 2003 compilers for those systems.
-- glen
Well, DOH...
--
> Well, DOH...
I think you may not know what this word means. We all remember "duh."
"DOH" has its origins from the Simpson's and is said by the world's least
curious man when his simple machinations blow up in his face. Though
they might both be interjections, they wouldn't be used in the same
situations.
--
frank
"Guns: yes, they are harmful."
> I believe VAX/VMS stopped at Fortran 77,
Right. (It did have many extensions, though, which were incorporated
into Fortran 90.)
> but that Fortran 95
> compilers exist for Alpha/VMS, and I believe also Itanium/VMS.
Right.
> I don't know at all about Fortran 2003 compilers for those systems.
I don't think there is one on ANY VMS platform.
Not necessarily. That's what "non-standard" means.
Choosing one or the other can be done automatically without a preprocessor,
using standard Fortran.
Much of your code is non-standard.
The pre-processor stuff was not my choice ... that is how The
Mathworks has designed the interface for connecting Fortran with
MATLAB. As a programmer, if you want to make sure you are using the
correct types when calling MATLAB Fortran routines, then you use the
supplied macros for mwPointer, mwSize, etc.
>Much of your code is non-standard.
>
I have acknowledged that. The pre-processor stuff is necessary per the
previous paragraph. The LOC and VAL stuff is necessary as an
alternative to C_LOC and C_F_POINTER for compilers that do not have C
interop capability. For these compilers, I would gladly code using
only standard constructs, but I have no idea how to get a Fortran
pointer constructed from seperate C pointer and size info other than
what I have previously shown (calling an implicit routine using %VAL
and then returning the Fortran pointer via a COMMON block). In fact, I
was rather pleased that I was able to do it at all for those
compilers. That being said, I will probably develop another package
of similar code using C_LOC and C_F_POINTER for later compilers per
suggestions from this group.
James Tursa
Thanks. I already knew the "not necessarily" and "non-standard" per my
original post. Since I didn't have these other compilers installed I
was hoping someone with those compilers could answer the question
quickly. I got what I needed from Tobias.
James Tursa