- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I was told that the standard math operators can be extended to include user defined
variables, such as what one would set up with a TYPE statement.
How does one tell the compiler what to do in those instances?
For instance, I want to use the * to refer to a DOT product of two vectors.
Like :
--------------------------------------------
type(vector)A,B,C
C= A*B
! where A,B, and C are defined as follows:
type (vector)
integer nx
real(4) x(100)
end type
------------------------------------------
Likewise I would like the + and - operators to take the sum and difference of two vectors.
Or even one could do comparisons of absolute values:
if( A > B) go to 99
I was looking for an article about this topic, but I don't know what "lingo" is used to discuss this.
So I couldn't find it. Any suggestions?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually, I made a mistake:
C would be a regular scalar, not a vector,
unless one is referring to a CROSS product.
So S = A * B for example.
But maybe there is a way to tell the compiler to redefine another operator (ex: ** )
mean CROSS products? Or tell it what to do if one multiplies a scalar by a Vector?
Example: B = S* A
where A and B are typed vectors, and S is an ordinary real(4) scaler variable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Studying the many on-line references on Fortran operator overloading would keep you busy for a while. As you said, the suggestions are to use * for a cross product rather than a dot product, which already has a standard intrinsic.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I realise this is an example but in the case of vector operations I really would not recommend using a derived type. The simple 1D array works just fine.
[fortran]
Real(4) :: a(3), b(3), c(3)
Real(4) :: magnitude, dot
a=b-c
a=b+c
magnitude= norm2(a)
a=a/magnitude
dot=dot_product(a,b)[/fortran]
All of the above are quick, simple, understandable and portable. They use intrinsics and require no coding. The only one you need to write is a simple cross product function (or subroutine).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Oh, sure, for simple 3 element vectors I WOULD do just that.
But I wanted to address the issue of "overloaded operators"
without getting involved in something much more complicated.
For cross products, I would do something like:
real(4) A(3),B(3), C(3), Cross
C = Cross (a,b)
Where Cross is a function that returns 3 element vectors.
Would I say real(4) Cross(3) or just what is above?
Is there a good article about overloaded operators I can address?
I have some books about Fortran '90, not sure yet whether this is adequately covered.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You would define an operator .CROSS. and write:
c = a .cross. b
This is not an overloaded operator, it's a user defined operator. The problem with overloading is that you can't redefine an existing signature, so if you wanted to overload an existing operator you have to satisfy the rules for generic disambiguation and make sure you're not adding a signature that matches an existing one. For the purpose you're describing, a user-defined operator makes more sense and is also more readable (given that assigning weird meanings to existing operators would be confusing.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IMSL has an entire chapter on linear operators: Chapter 10: Linear Algebra Operators and Generic Functions. One could use the defined operators (for matrix multiplication, inversion, transpose, etc.) in this chapter as an illustration of what can be done. Of course, one does not get to see how these operators are implemented, and it can be complicated while one is defining new operators to cover all the varieties of expressions where such defined operators could be used.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Any volunteer to provide code for defining .cross. and a simple example of it's use ?
I'd be interested to see an extension where the dimension of the vectors is general and not just 3, to see how arbitrary vector sizes are provided.
John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There are several issues that I need to reply to so I'll reply in separate messages.
First, I'll reply to the second issue that John Campbell mentioned.
John Campbell wrote:
I'd be interested to see an extension where the dimension of the vectors is general and not just 3, to see how arbitrary vector sizes are provided.
John
The vector cross product is not an operation that can be generalized to an arbitrary number of dimensions. I first learned this in my second semester course in Calculus and Analytic Geometry as a freshman at UW-Madison in the spring of 1974. The vector cross product, as limited to non-trivial products with vector results, is valid only in three (3) and seven (7) dimensions. See the Wikipedia article, "Cross Product":
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
gfortran testsuite includes operator (.cross.) in gcc/testsuite/gfortran.dg/userdef_operator_1.f90
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'd like to follow up on Steve Lionel's last sentence.
Steve Lionel (Intel) wrote:
For the purpose you're describing, a user-defined operator makes more sense and is also more readable (given that assigning weird meanings to existing operators would be confusing.)
IMHO, assigning weird meanings to existing operators is not just confusing, it is atrocious programming practice. This practice violates just about all principles of good programming practice, most importantly, the Principle of Least Surprise.
You need to remember that multiplication, signified by *, is commutative. I.e., C = A * B and also C = B * A. This is not true with the vector cross product. Instead, the vector cross product is anti-commutative. I.e., if C = A .Cross. B and D = B .Cross. A, then C = -D. I.e., the vectors C and D point in opposite directions, even though they have the same length.
Thus, it is far better programming practice to create a user-defined operator such as .Cross. to signify the vector cross product.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As John Campbell asked, I was going to provide a simple example of how to define a vector cross product and how to use it. This example was going to be a shortened version of a module I wrote for vector operations in October 2011. Due to the need for brevity, I did not include some of the functionality I had in the original module
However, when I tried to post the example, I got a message, "Your submission has triggered the spam filter and will not be accepted."
If there is some other way to provide the example I tried to post, please let me know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Attaching the source file should work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The example Tim quoted is below. Personally, I think using a straight function call is more obvious /clear as this stuff isn't much used IMO.
[fortran]
- module geometry
- implicit none
- interface operator(.cross.)
- module procedure cross
- end interface
- contains
- ! Cross product between two 3d vectors.
- pure function cross(a, b)
- real, dimension(3), intent(in) :: a,b
- real, dimension(3) :: cross
- cross = (/ a(2) * b(3) - a(3) * b(2), &
- a(3) * b(1) - a(1) * b(3), &
- a(1) * b(2) - a(2) * b(1) /)
- end function cross
- end module geometry
- program opshape
- use geometry
- implicit none
- real :: t(3,3), a
- a = dot_product (t(:,1), t(:,2) .cross. t(:,3))
- end program opshape
[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As John Campbell asked, here is a simple example of how to define a vector cross product and how to use it. This example is a shortened version of a module I wrote for vector operations in October 2011. Due to the need for brevity, I will not include some of the functionality I have in the original module. The type definitions could also be done with parameterized derived types (PDTs) but not all current Fortran compilers support PDTs.
The two attachments contain source code that shows how this is done. The file Demo_Vector_3D_M.f90 shows how to define a 3-D vector and some operations, including the vector cross product. The file Demo_Vector_Cross_Product.f90 show how to use a vector cross product operator in a program.
Hope this helps.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I looked at your examples, but I don't see how you told the compiler what to do with
".cross." you use as an operator.
In other words, is there a place where the compiler associates that with the actual subroutine?
Of course you also have to make sure that the compiler does NOT treat it as a commutative operator.
so you would have to define A.cross.B as different than B . cross. A
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
but I don't see how you told the compiler what to do with
".cross." you use as an operator
The idiom
[fortran]interface
operator
(.cross.)
module procedure crossproc[/fortran]
tells the compiler to translate "term1 .cross. term2" to "call crossproc(term1,term2)".
The compiler is not expected to possess mathematical knowledge on topics such as commutativity, etc. The code for the procedure that implements the operator should satisfy the requirement that the result of the operation has the correct mathematical properties.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
billsincl wrote:
I looked at your examples, but I don't see how you told the compiler what to do with
".cross." you use as an operator.
In other words, is there a place where the compiler associates that with the actual subroutine?
Of course you also have to make sure that the compiler does NOT treat it as a commutative operator.
so you would have to define A.cross.B as different than B . cross. A
Bill,
Since you're asking very, very basic questions about enhancements to Fortran starting with the Fortran 90 standard, it may help you greatly if you study the various books which explain such topics in detail. See Steve's recent blogpost on some of the new books. I'd suggest you start with "FORTRAN 90 for Engineers and Scientists" by Nyhoff and Leestma, ISBN-13: 978-0135197295. Studying these books will give you an all-around view and a far deeper understanding of "Modern Fortran" that simply cannot be offered by such forum posts and responses.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Craig and app4619 for your examples of the coding for .cross. They give me a good indication of what is required.
Bill, as A .cross. B = - B .cross. A, the example of "t(:,2) .cross. t(:,3)" has no ambiguity of order assumed.
I have always used a subroutine dcross (a, b, c) where C = A x B, rather than using a vector function. I'm not sure if I will adopt the use of .cross. Given my recent interest in AVX performance, I wonder if adopting .cross. would have any benefit ?
Interesting topic,
John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is my impression of F2003 and F2008 that the expanded language now provides for many alternatives for coding some basic approaches, such as vector algebra or list processing.
I'm with Bill in some of these, as it becomes difficult to identify if the new alternative syntax provides any benefit for solving the basic problem. While new syntax provides alternative ways of coding, which hopefully provides ways of expanding the range of problems that can be solved, they also introduce new ways of hiding coding bugs which means that no problems are robustly solved.
I need to broaden my horizons and look for new problems to solve, rather than redefining the problems I already have.
john
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am now looking thru the various texts on this topic, so I may be able to comment more intelligently later.
But the end purpose is to be able to pose complicated operations in a mathematically intuitive format - - -
Ex:
Z = A*B + C*D - E* F as one would see in a Physics text,
instead of a long series of subroutine and function calls.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page