operator assignment fortran

Tutorial OOP(III): Constructors and Destructors

Casting Keynotes: The Virtual Lab

Nov 02 2019

Tutorial OOP(IV) : Operator and Assignment Overloading

  • Filed under blog

November 2, 2019

In the previous tutorial , we created a constructor and destructor for our TTimer class.  Next, we extend our class with overloaded operators. Depending on the type of object your class represents, you may want to define an addition/subtraction/multiplication/… operator. In addition, the assignment operator deserves some extra attention as you may want to have a clear control over this operation  ( e.g. ,  deep copy vs shallow copy ). The full source of this tutorial and the previous, can be downloaded from my github-page .

Let us start with the latter: the assignment operator . As with all other operators, it is possible to overload the assignment operator in modern fortran.

1. Assignment (=) operator overloading

When dealing with objects and classes—or extended data-structures in general—, their properties often are (implicit) pointers to the actual data-structure. This brings an interesting source of possible bugs due to shallow copies being made while deep copies are expected (although the problem may be less pronounced in Fortran than it is in Python).

In a fortran object, the assignment of a pointer component ( i.e., an explicit pointer variable, or a component which is an object itself) happens via a shallow copy (or pointer assignment). In contrast, for an allocatable component , the assignment operation performs by default a deep copy ( i.e. , space is allocated, and values are copied ). Shallow copies are very useful with regard to quickly creating new handles to the same data-structure. However, if you want to make a true copy, which you can modify without changing the original, then a deep copy is what you want. By implementing assignment overloading for your own classes, you have more control over the actual copying process, and you can make sure you are creating deep copies if those are preferred.

The implementation of overloading for the assignment operator is not too complicated. It requires two lines in your class definition:

First, you need to define a class method which performs a copy-operation—which in a fit or original though we decided to call “ copy ” ;-).  As you can see this function is private, so it will not be accessible to the user of your class via a call like :

Secondly, you link this class method via the “ => ” to the assignment-operator .  It is a generic interface , which means the assignment operator could be linked to different functions, of which the relevant one will be determined and used during run-time. This generic is also public  (otherwise you would not be able to use it).

The implementation of the class method follows the standard rules of any class method and could look like

The “this” object which we passed to our class method is the object on the left side of the assignment operator, while the “from” object is the one on the right side. Note that both objects are defined as “class” and not as “type”. Within the body of this method you are in charge of copying the data from the “from”-object to the “this”-object, giving you control over deep/shallow copying.

In practice the overloaded operator is used as:

2. Operator (+,-,*,/,…) overloading

Just as you can overload the assignment operator above, you can also overload all other fortran operators. However, be careful to keep things intuitive.  For example, an addition operation on our TTimer class is strange. What would it mean to add one timer to another? How would you subtract one chronometer from another? In contrast, inside our TTimer class we have a list of TTime objects which can be used to represent a date and time, as-well-as a time interval. [1]   For the remainder of this tutorial, we will assume the TTime class only represents time-intervals. For such a class, it makes sense to be able to add and subtract time intervals.

Let us start with the basic definition of our TTime-class:

The TTime class has a constructor and destructor, implemented as we discussed before. The assignment operator is over-loaded as well. The overloading of the “ + ” and “ – ” operator follows the same setup as for the assignment operator. First, you define a class method where you will implement the addition or subtraction. Second, you link this class method to the operator as a generic. The main difference with overloading the assignment operator is that you need to use the keyword operator instead of assignment , during the second step. The class methods are private, while the generic link is public. The only thing left to do is to implement the class methods. In case of operator overloading, the class methods are functions .

The returned object need to be defined as a type, and the further implementation of the function follows the standard fortran rules. It is important to note that for a function-header like this one, the object to the left of the operator will be the one calling the overloaded operator function, so:

This may not seem this important, as we are adding two objects of the same class, but that is not necessarily always the case. Imagine that you want to overload the multiplication operator, such that you could multiply your time-interval with any possible real value. On paper

but for the compiler in the left product “this” would be a TTime object and “that” would be a real, while in the right product “this” is the real, and “that” is the TTime object. To deal with such a situation, you need to implement two class methods, which in practice only differ in their header:

In the class definition both functions are linked to the operator as

With this in mind, we could also expand our implementation of the “ + ” and “ – ” operator, by adding functionality that allows for the addition and subtraction of reals representing time-intervals. Also here, the left and right versions would need to be implemented.

As you can see, modern object oriented fortran provides you all the tools you need to create powerful classes capable of operator overloading using simple and straightforward implementations.

In our next Tutorial, we’ll look into data-hiding and private/public options in fortran classes.

[1] You could argue that this is not an ideal choice and that it would be better to keep these two concepts ( absolute and relative time) separate through the use of different classes. 

  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • fortran , Object Oriented Programming , scientific programming

' src=

Vanpoucke Danny

Permanent link to this article: https://dannyvanpoucke.be/oop-fortran-tut5-en/

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed .

Recent Posts

  • DigiLignin: Consortium Meeting
  • First-principles investigation of hydrogen-related reactions on (100)–(2×1)∶H diamond surfaces
  • Cover Nature Reviews Physics
  • Materiomics Chronicles: week 13 & 14
  • How to verify the precision of density-functional-theory implementations via reproducible and universal workflows

© 2014-2024 The Delocalized Physicist.

Made with by Graphene Themes .

previous episode

Object oriented programming with fortran, next episode, operator overloading.

Overview Teaching: 10 min Exercises: 5 min Questions What is operator overloading? Objectives Overload the ‘+’ operator.

Previously in the Interface Blocks episode, we saw how interfaces can be used to map one procedure name onto different underlying procedures based on the number, order, and type or arguments passed to the procedure. However, these interface blocks can be used with more than just procedures they can also be used for operators already defined in Fortran such as + , - , * , / , == , /= , and also operators such as .gt. , .le. etc.

Lets add a + operator which appends one of our t_vector objects to another creating a new t_vector .

operators.f90

In the main program you can see how the operator is used, exactly as if we were adding two numbers together, however in this case we are adding our two vectors together. Lets try it out.

Here you can see that the two vectors have been combined into numbers_all with the left hand t_vector object added first followed by the right hand t_vector object added second. So the way we have implemented our operator(+) the results are order dependent.

Which side of an operator? Our main program above looks like so: 111 program main 112 use m_vector 113 implicit none 114 type(t_vector) numbers_some,numbers_less,numbers_all 115 type(t_vector_3) location 116 117 numbers_some=t_vector(4) 118 numbers_some%elements(1)=1 119 numbers_some%elements(2)=2 120 numbers_some%elements(3)=3 121 numbers_some%elements(4)=4 122 print*, "numbers_some" 123 call numbers_some%display() 124 125 numbers_less=t_vector(2) 126 numbers_less%elements(1)=5 127 numbers_less%elements(2)=6 128 print*, "numbers_less" 129 call numbers_less%display() 130 131 numbers_all=numbers_some+numbers_less 132 print*, "numbers_all" 133 call numbers_all%display() 134 135 end program Line 131 is numbers_all=numbers_some+numbers_less what would line 133, call numbers_all%display() print out if line 131 where numbers_all=numbers_less+numbers_some instead? t_vector: num_elements= 6 elements= 1.00000000 2.00000000 3.00000000 4.00000000 5.00000000 6.00000000 the same as before, the + operator is commutative, in other words the order doesn’t matter. t_vector: num_elements= 6 elements= 5.00000000 6.00000000 1.00000000 2.00000000 3.00000000 4.00000000 the contents of numbers_less has been added to the new vector first followed by the contents of numbers_some . Solution NO : while it is true that for the mathematical + operator the order doesn’t matter this is not true for in general for operators. The implementation of the operator must be written in a way that it is order independent and that is now how we wrote it in this case. YES : In our case the order does matter as we first copy the data in the object left side, passed first as left , then the object on the right, passed second as right to the function.
Key Points Common Fortran operators can be overloaded to work with your custom derived types.

Fortran 90: Overloaded Operators

  • Previous : ASSIGN
  • Next : AUTOMATIC

The assignment statement assigns a value to a variable, substring, array element, record, or record field.

Parameter 

Description 

Variable, substring, array element, record, or record field  

Expression giving the value to be assigned 

Description

The value can be a constant or the result of an expression. The kinds of assignment statements: are arithmetic, logical, character, and record assignments.

Arithmetic Assignment

v is of numeric type and is the name of a variable, array element, or record field.

e is an arithmetic expression, a character constant, or a logical expression. Assigning logicals to numerics is nonstandard, and may not be portable; the resultant data type is, of course, the data type of v . @

Type of

Type of

,

(SPARC only)

(SPARC only)

(SPARC only)

(SPARC only)

Compiling with any of the options -i2 , -dbl , -r8 , or -xtypemap can alter the default data size of variables and expressions. This is discussed in Chapter 2. See also the Fortran User's Guide for a description of these options.

Example: An assignment statement:        REAL A, B        DOUBLE PRECISION V        V = A * B

The above code is compiled exactly as if it were the following:        REAL A, B        DOUBLE PRECISION V        V = DBLE( A * B )

Logical Assignment

v is the name of a variable, array element, or record field of type logical.

e is a logical expression, or an integer between -128 and 127, or a single character constant.

Execution of a logical assignment statement causes evaluation of the logical expression e and assignment of the resulting value to v . If e is a logical expression (rather than an integer between -128 and 127, or a single character constant), then e must have a value of either true or false.

Logical expressions of any size can be assigned to logical variables of any size. The section on the LOGICAL statement provides more details on the size of logical variables.

Character Assignment

The constant can be a Hollerith constant or a string of characters delimited by apostrophes (') or quotes ("). The character string cannot include the control characters Control-A, Control-B, or Control-C; that is, you cannot hold down the Control key and press the A, B, or C keys. If you need those control characters, use the char() function.

If you use quotes to delimit a character constant, then you cannot compile with the -xl option, because, in that case, a quote introduces an octal constant. The characters are transferred to the variables without any conversion of data, and may not be portable.

Character expressions which include the // operator can be assigned only to items of type CHARACTER . Here, the v is the name of a variable, substring, array element, or record field of type CHARACTER ; e is a character expression.

Execution of a character assignment statement causes evaluation of the character expression and assignment of the resulting value to v . If the length of e is more than that of v , characters on the right are truncated. If the length of e is less than that of v , blank characters are padded on the right.

Record Assignment

v and e are each a record or record field. @

The e and v must have the same structure. They have the same structure if any of the following occur:

Both e and v are fields with the same elementary data type.

Both e and v are records with the same number of fields such that corresponding fields are the same elementary data type.

Both e and v are records with the same number of fields such that corresponding fields are substructures with the same structure as defined in 2, above.

The sections on the RECORD and STRUCTURE statements have more details on the structure of records.

Example 1: Arithmetic assignment:        INTEGER I2*2, J2*2, I4*4        REAL R1, QP*16 ! ( REAL*16 is SPARC only )        DOUBLE PRECISION DP        COMPLEX C8, C16*16, QC*32 ! (COMPLEX*32 is SPARC only)        J2 = 29002        I2 = J2        I4 = (I2 * 2) + 1        DP = 6.4D9        QP = 6.4Q9        R1 = DP        C8 = R1        C8 = ( 3.0, 5.0 )        I2 = C8        C16 = C8        C32 = C8

Example 2: Logical assignment:        LOGICAL B1*1, B2*1        LOGICAL L3, L4        L4 = .TRUE.        B1 = L4        B2 = B1

Example 3: Hollerith assignment:        CHARACTER S*4        INTEGER I2*2, I4*4        REAL R        S = 4Hwxyz        I2 = 2Hyz        I4 = 4Hwxyz        R = 4Hwxyz

Example 4: Character assignment:        CHARACTER BELL*1, C2*2, C3*3, C5*5, C6*6        REAL Z        C2 = 'z'        C3 = 'uvwxyz'        C5 = 'vwxyz'        C5(1:2) = 'AB'        C6 = C5 // C2        BELL = CHAR(7)     Control Character (^G)

'

'

07 hex

Example 5: Record assignment and record field assignment:        STRUCTURE /PRODUCT/               INTEGER*4 ID               CHARACTER*16 NAME               CHARACTER*8 MODEL               REAL*4 COST               REAL*4 PRICE        END STRUCTURE        RECORD /PRODUCT/ CURRENT, PRIOR, NEXT, LINE(10)        ...        CURRENT = NEXT Record to record        LINE(1) = CURRENT Record to array element        WRITE ( 9 ) CURRENT Write whole record        NEXT.ID = 82 Assign a value to a field

  • © 2010, Oracle Corporation and/or its affiliates

Operator Overloading

  • First Online: 01 January 2015

Cite this chapter

operator assignment fortran

  • Ian Chivers 3 &
  • Jane Sleightholme 4  

The aims of this chapter are to look at operator overloading in Fortran.

All the persons in this book are real and none is fictitious even in part. Flann O’Brien, The Hard Life

This is a preview of subscription content, log in via an institution to check access.

Access this chapter

Subscribe and save.

  • Get 10 units per month
  • Download Article/Chapter or eBook
  • 1 Unit = 1 Article or 1 Chapter
  • Cancel anytime
  • Available as PDF
  • Read on any device
  • Instant download
  • Own it forever
  • Available as EPUB and PDF

Tax calculation will be finalised at checkout

Purchases are for personal use only

Institutional subscriptions

Author information

Authors and affiliations.

Rhymney Consulting, London, UK

Ian Chivers

Fortranplus, London, UK

Jane Sleightholme

You can also search for this author in PubMed   Google Scholar

Corresponding author

Correspondence to Ian Chivers .

Rights and permissions

Reprints and permissions

Copyright information

© 2015 Springer International Publishing Switzerland

About this chapter

Chivers, I., Sleightholme, J. (2015). Operator Overloading. In: Introduction to Programming with Fortran. Springer, Cham. https://doi.org/10.1007/978-3-319-17701-4_24

Download citation

DOI : https://doi.org/10.1007/978-3-319-17701-4_24

Published : 08 August 2015

Publisher Name : Springer, Cham

Print ISBN : 978-3-319-17700-7

Online ISBN : 978-3-319-17701-4

eBook Packages : Computer Science Computer Science (R0)

Share this chapter

Anyone you share the following link with will be able to read this content:

Sorry, a shareable link is not currently available for this article.

Provided by the Springer Nature SharedIt content-sharing initiative

  • Publish with us

Policies and ethics

  • Find a journal
  • Track your research

Fortran Tutorial

  • Fortran Tutorial
  • Fortran - Home
  • Fortran - Overview
  • Fortran - Environment Setup
  • Fortran - Basic Syntax
  • Fortran - Data Types
  • Fortran - Variables
  • Fortran - Constants

Fortran - Operators

  • Fortran - Decisions
  • Fortran - Loops
  • Fortran - Numbers
  • Fortran - Characters
  • Fortran - Strings
  • Fortran - Arrays
  • Fortran - Dynamic Arrays
  • Fortran - Derived Data Types
  • Fortran - Pointers
  • Fortran - Basic Input Output
  • Fortran - File Input Output
  • Fortran - Procedures
  • Fortran - Modules
  • Fortran - Intrinsic Functions
  • Fortran - Numeric Precision
  • Fortran - Program Libraries
  • Fortran - Programming Style
  • Fortran - Debugging Program
  • Fortran Resources
  • Fortran - Quick Guide
  • Fortran - Useful Resources
  • Fortran - Discussion
  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer's Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary

An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. Fortran provides the following types of operators −

Arithmetic Operators

Relational operators, logical operators.

Let us look at all these types of operators one by one.

Following table shows all the arithmetic operators supported by Fortran. Assume variable A holds 5 and variable B holds 3 then −

Show Examples

Operator Description Example
+ Addition Operator, adds two operands. A + B will give 8
- Subtraction Operator, subtracts second operand from the first. A - B will give 2
* Multiplication Operator, multiplies both operands. A * B will give 15
/ Division Operator, divides numerator by de-numerator. A / B will give 1
** Exponentiation Operator, raises one operand to the power of the other. A ** B will give 125

Following table shows all the relational operators supported by Fortran. Assume variable A holds 10 and variable B holds 20, then −

Operator Equivalent Description Example
== .eq. Checks if the values of two operands are equal or not, if yes then condition becomes true. (A == B) is not true.
/= .ne. Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. (A != B) is true.
> .gt. Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. (A > B) is not true.
< .lt. Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. (A < B) is true.
>= .ge. Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. (A >= B) is not true.
<= .le. Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. (A <= B) is true.

Logical operators in Fortran work only on logical values .true. and .false.

The following table shows all the logical operators supported by Fortran. Assume variable A holds .true. and variable B holds .false. , then −

Operator Description Example
.and. Called Logical AND operator. If both the operands are non-zero, then condition becomes true. (A .and. B) is false.
.or. Called Logical OR Operator. If any of the two operands is non-zero, then condition becomes true. (A .or. B) is true.
.not. Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false. !(A .and. B) is true.
.eqv. Called Logical EQUIVALENT Operator. Used to check equivalence of two logical values. (A .eqv. B) is false.
.neqv. Called Logical NON-EQUIVALENT Operator. Used to check non-equivalence of two logical values. (A .neqv. B) is true.

Operators Precedence in Fortran

Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.

For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

Category Operator Associativity
Logical NOT and negative sign .not. (-) Left to right
Exponentiation ** Left to right
Multiplicative * / Left to right
Additive + - Left to right
Relational < <= > >= Left to right
Equality == /= Left to right
Logical AND .and. Left to right
Logical OR .or. Left to right
Assignment = Right to left

10 Overloading operators for derived types

This chapter covers:.

  • Overloading operators in a minimal countdown app
  • Validating user input
  • Synchronization on assignment in the tsunami simulator

Almost any app working with real-world data, or any program more complex than a toy model, will use derived types (classes) to handle abstract data. Fortran’s intrinsic operators for arithmetic ( + , - , * , / , ** ) and comparison ( == , /= , >= , ⇐ , > , < ) are available out of the box for intrinsic numeric ( integer , real , complex ) but not for derived types. For example, to keep track of calendar date and time in an app, you’d need to compare, add, and subtract datetime instances (data structures that represent date and time). This is where derived types (Chapter 6) and generic procedures and custom operators (Chapter 7) come together to form a powerful feature of the language: Overloading intrinsic operators for derived types. This will allow you to define what the intrinsic (and custom) operators mean for any derived type, and in a way extend the syntax of the language.

10.1  Happy Birthday! A countdown app

10.1.1  some basic specification, 10.1.2  implementation strategy, 10.2  getting user input and current time, 10.2.1  your first datetime class, 10.2.2  reading user input, 10.2.3  getting current date and time, 10.3  calculating the difference between two times, 10.3.1  modeling a time interval, 10.3.2  overloading the subtraction operator, 10.3.3  time difference algorithm, 10.3.4  the complete program, 10.4  overloading operators in the tsunami simulator, 10.4.1  a refresher on the field class, 10.4.2  implementing the arithmetic for the field class, 10.4.3   syncing parallel images on assignment, 10.5  answer key, 10.5.1  exercise 1: validating user input, 10.7  summary.

operator assignment fortran

Fortran Wiki opover

category: code

operator assignment fortran

Overloading and Generic Programming

Overloading is when a procedure or operator is able to work on multiple types. Most languages overload at least basic arithmetic operators to work on all numerical types. In modern Fortran the mathematical intrinsics are overloaded to work at least on real and double precision, and when appropriate complex. For example, in older Fortran there were three versions of every trigonometric function when defined for complex numbers. Cosine was COS for real number, DCOS for doubles, and CCOS for complex. In modern Fortran COS works for all three. This is an example of generic programming.

Overloading can be more general than just numerical types. In some languages, sort is an intrinsic and works on any types for which relational operators (<,<=,>,>=) are defined.

Programmers can overload their own procedures in Fortran. To make a generic procedure, an interface is required. In this case the interface block has a name, which will be the generic name, and only the specific procedures should be included.

In all the examples below, our new generic diag for computing the diagonal of a matrix, will accept either real or double precision arrays. The extension to complex should be obvious if it is needed.

Explicit Interface Block

We can use an explicit interface block in a non-module program unit.

Module Procedure

Overloaded procedures are usually and most appropriately defined in a module. Since procedures in modules already have an implicit interface, we cannot use the explicit interface above. We still use a named interface block with MODULE PROCEDURE

The body of the functions would be in the module.

Generic in Type-Bound Procedures

If we wanted to define something with various linear-algebra functions defined on it, we would use the GENERIC keyword. Note that the specific functions must be written so that their signatures , the number and types of their arguments, are differ, or the compiler will not be able to distinguish them.

Operator Overloading

The arithmetic operators + , - , * ,and / can be overloaded to work on programmer-defined derived types. Assignment (=) can also be overloaded when copying can be defined for the type.

Module Procedures

The arithmetic operators are overloaded with a generic interface, but rather than the name of the generic function, the keyword OPERATOR is used, followed by the symbol in parentheses for operators, or ASSIGNMENT(=) for copying.

The procedures that define the operator must be functions , must have two arguments, and must declare those arguments INTENT(IN). For example, suppose we wished to define adder for an Atom type to add the atomic masses:

For assignment, the procedure must be a subroutine with two arguments. The first argument must represent the left-hand side and be INTENT(OUT), while the second represents the right-hand side and is INTENT(IN).

Type-Bound Operators

Operators may be overloaded to work on class members. The syntax is somewhat different than for separate types in modules. Here is a snippet from a module defining a Fraction class. The rules for the arguments are the same as for modules, but of course the instance variable must be declared CLASS.

Last updated on Jan 1, 0001

fortran.cat

A few bits of Fortran

  • English , fortran , language , llenguatge

Operator (+) overload in a class

' data-src=

Overloading a subroutine means to redefine its internal functionality for a customized behavior. Overall it adapts the class new characteristics to already wide-spread Fortran functionalities (==, =, + ,-, …).

Specifically, this post only focus on the operators (+,-,*,/).

In the following example, m ynumber is generic class to hold any type of an integer number. For that reason, it seems interesting enough to be able to directly operate with its data.

The main program shows what is meant to do:

In short, mynumber type can directly operate with:

  • mynumber + mynumber
  • mynumber + scalar int
  • scalar int + mynumber

Therefore, there must be an implementation for each type of operation. Check below how to do it:

For each desired operation, it requires its own implementation. In order to include subtraction, division or multiplication, you only need to apply the same principle but with the following signs: -, *, /.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

Recent Posts

  • Memory alignment for multidimensional arrays
  • Edge cases when implementing scientific equations
  • Mapping namelists from a derived type
  • How to profile a Fortran binary with the ‘perf’ tool
  • Parametrized derived types (PDT)
  • What is Fortran
  • February 2024
  • November 2023
  • September 2023
  • December 2022
  • February 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • Performance

Proudly Powered By WordPress

Assigning a derived type variable to itself

I would like to know if anyone knows

  • How should we handle the assignment of a derived type variable to itself when the assignment operator for the derived type is overloaded in a subroutine?
  • How is such a situation mentioned in the Fortran Standard?

Such a situation arises when extending stdlib_sorting to support sorting arrays of bitset_large type. The procedure assign_large overloading assignment operator for the bitset_large type is as follows:

and when the same array element is put on both sides of the assignment operator, an error occurs with the message Fortran runtime error: Allocatable argument 'set2' is not allocated . Here, the stdlib is built with gfortran 11.2.0 on Windows 11 and set2 is defined as the variable on the right-hand side of the assignment operator. The error may be due to the deallocation of the component blocks of set2 caused by the intent(out) attribute for set1 since set1 and set2 are the same variable.

I am trying to resolve this problem by removing assign_large and using Fortran’s intrinsic assignment operation.

For more details, please see the issue #726 and pull-requests #723 and #727 .

Using the intrinsic Fortran assignment without overloading should do, as the derived type doesn’t contain any pointer. However the question still holds for cases where overloading is required (whatever the reason why it is required).

a = a with overloading means that the same variable is passed as the two actual argument of the subroutine, in other words the two dummy arguments get aliased. Argument aliasing is normally not authorized: are there some exceptions?

@tomohirodegawa ,

As mentioned at the stdlib issue thread, argument aliasing is something the author is disallowed and it makes the program nonconforming while the processor is not required to detect and report the nonconformance. Nonetheless, in this case, the processor appears rather kind to do so - is that being overruled ?

There are a couple of options you may want to consider with your colleagues working on stdlib , if that suits you:

  • Consider making the specific procedure of the generic interface accessible and invoke it directly:

I was preparing a similar example to @FortranFan one

The component %n is set to 999 before either calling the assignement routine or the overloaded assignement. In the routine it is first set to zero before being set to what it should be. On output we would like the component to be 999

With gfortran 13.1, the argument aliasing results in the component to be zero in both cases. We can check that the arguments are aliased in the routine.

ifx 2023.1 however can sort it out when using the overloaded assignment. And we can see that it makes a copy-in of b before calling the routine:

I don’t know if ifx is going beyond the standard or if the standard requires this behavior.

EDIT: I can even check that with a = b (b being different from a), ifx is doing a copy-in of b before calling the assign routine. It seems that ifx always considers the RHS as an expression that has to be evaluated with a temporary allocation for the result.

Another option is to implement a setter method for the type that allows you to what you seek: shown below is a clone procedure.

This seems like a general aliasing problem involving assignment. What does a compiler do when it sees an expression like a=a with intrinsic assignment. Does it treat it as a noop, or does it make a copy of the RHS and go through the memory copy process?

With a defined assignment, the programmer could test for the alias (e.g. with c_loc() ), and then do a quick return if necessary. Is that what the fortran standard expects programmers to do?

Or a compiler could always make a copy of the RHS before invoking the assignment function, which could basically double (or more) the effort for complicated derived types – that doesn’t seem optimal either.

Is it the programmer’s responsibility to avoid the a=a situation, or is it the programmer’s responsibility to account for the alias when necessary, or should the compiler avoid the alias by making a RHS copy?

I tend to think the latter is the right one (and possibly optimizing by doing nothing in case of a = a ?), as the first two ones look weird. But I don’t really know.

Upon a bit of further thought, my read is you can change the assignment to explicitly reference an expression on the right-hand side to make the program conform:

And then file another report with GCC Bugzilla for that processor.

This might satisfy the principle of least change for stdlib while enhancing that one processor if the support request is worked on promptly.

The only exceptions are when the aliased arguments are not modified. That is, it is allowed to reference the same actual argument through multiple dummy arguments, so long as none of those dummy arguments are modified. Aliases can also occur for module entities and dummy arguments, but I don’t think that applies to this defined assignment situation.

By the time the assign_large( set1, set2 ) subroutine is invoked, the programmer has already effectively told the compiler that set1 and set2 are not aliased. If this subroutine were invoked in the normal way, then the programmer could place parentheses around the actual argument, making it an expression rather than a variable, and the compiler would then make a copy. That would avoid the aliasing problem, but it would be inefficient when, for example, the argument is a complicated derived type with many levels of allocatable arrays. Then the subsequent assignments within the subroutine might be inefficient when a large amount of memory is copied back to the original derived type variable. The VALUE attribute could also be added to the set2 declaration, and that would also force the compiler to make a copy and avoid the alias problem, but it would have the same efficiency problems for complicated derived types. I don’t think making copies is really the right approach to solve this problem.

It seems like the “best” solution is for the standard to be changed so that the a=a special case is required to be identified by the compiler and to treat it as a noop special case for defined assignment.

I think defined assignment is the only place where this alias issue arises. All the other cases I can think of are already under the programmer’s control (or all arguments are unmodified, so aliases are irrelevant); this is the only one that isn’t. Is that correct?

Is it not an option to make the intent of the left-side argument to inout (rather than out ), so that no auto-initialization (or deallocation) will occur? (Possibly, the need for “pure” makes it not suitable?)

If intent(out) is needed, we might use a separate routine, like

(I guess this is related to the topic of “self-assignment guard (or protection)”, and these pages seem to recommend such a guard in the case of C++ (though other languages may be different.)

  • C++ Tutorial => Self-assignment Protection
  • Self assignment check in assignment operator - GeeksforGeeks
  • https://www.learncpp.com/cpp-tutorial/overloading-the-assignment-operator/

There is no aliasing issue with defined assignment. 10.2.1.5 Note 1 helpfully summarizes:

The rules of defined assignment (15.4.3.4.3), procedure references (15.5), subroutine references (15.5.4), and elemental subroutine arguments (15.8.3) ensure that the defined assignment has the same effect as if the evaluation of all operations in x2 and x1 occurs before any portion of x1 is defined. If an elemental assignment is defined by a pure elemental subroutine, the element assignments can be performed simultaneously or in any order.

Actually the standard defines an assignment as:

R1032 assignment-stmt is variable = expr

A possible interpretation is hence that a compiler is required to process th RHS as an expression, i.e. a = a is actually a = (a) . If so, ifx gets it right and this is a bug in gfortran

The standards document ( https://j3-fortran.org/doc/year/23/23-007r1.pdf ) says:

10.2.1.4 Defined assignment statement (page 191) A subroutine defines the defined assignment x_1 = x_2 if …
10.2.1.5 Interpretation of defined assignment statements** (page 192) … NOTE The rules of defined assignment (15.4.3.4.3) , procedure references (15.5), subroutine references (15.5.4), and elemental subroutine arguments (15.9.3) ensure that the defined assignment has the same effect as if the evaluation of all operations in x_2 and x_1 occurs before any portion of x_1 is defined. If an elemental assignment is defined by a pure elemental subroutine, the element assignments can be performed simultaneously or in any order.
15.4.3.4.3 Defined assignments (page 329) If ASSIGNMENT ( = ) is specified in a generic specification, all the procedures in the generic interface shall be subroutines that can be referenced as defined assignments (10.2.1.4, 10.2.1.5). Defined assignment may, as with generic names, apply to more than one subroutine, in which case it is generic in exact analogy to generic procedure names. Each of these subroutines shall have exactly two dummy arguments. The dummy arguments shall be nonoptional dummy data objects. The first argument shall have INTENT (OUT) or INTENT (INOUT) and the second argument shall have the INTENT (IN) or VALUE attribute. Either the second argument shall be an array whose rank differs from that of the first argument, the declared types and kind type parameters of the arguments shall not conform as specified in Table 10.8, or the first argument shall be of derived type. A defined assignment is treated as a reference to the subroutine, with the left-hand side as the first argument and the right-hand side enclosed in parentheses as the second argument. All restrictions and constraints that apply to actual arguments in a reference to the subroutine also apply to the left-hand-side and to the right-hand-side enclosed in parentheses as if they were used as actual arguments. The ASSIGNMENT generic specification specifies that assignment is extended or redefined. (… bold font by me…)

Here, I am wondering:

[Q1] what happens if x_1 (= the first dummy argument corresponding to the left-side of assignment) is a derived type with an allocatable component and has intent(out) ? Does the standard mean that all the information necessary for evaluating the subroutine will be retrieved by the compiler from x_1 before any re-initialization caused by intent(out) ?

(I imagined that intent(out) causes the re-initialization of x_1 (= resetting to its initial state) by the compiler (like deallocation of allocatable components) immediately after entering the subroutine. It seems to be what is happening in various code snippets above, because segmentation fault happens if intent(out) is used. Is my interpretation above not correct…?)

[Q2] Does the section 15.4.3.4.3 (Defined assignments) above mean that

should be interpreted as equivalent to a subroutine call like

That is the way I read the above text. However, in the x1=x1 case, or an equivalent situation, it seems like this could result in a lot of redundant and unnecessary effort. Is a compiler allowed to recognize this situation and treat it as a special case? Should a processor be required to recognize this special case and avoid that unnecessary effort?

Even in the case of x1 /= x2 , if the compiler sends (x2) as a temporary variable (after making a deep copy of x2 ), I guess it would need a lot of unnecessary effort… But maybe as an optimization, ifx possibly examines the address of actual arguments on the caller side and determines which of assign( x1, x2 ) and assign( x1, (x2) ) to use internally…?

Apart from that, my concern is that even when a temporary variable like (a) is created, direct translation of a = a to assign( a, (a) ) might give a wrong result (unless it is converted to “no op”). One such case may be when a is a derived-type variable and has a pointer component that points to another allocatable component in the same type. When entering the assign() routine, a temporary variable of RHS is created (e.g. via bitwise copy), while allocatable components of LHS could be deallocated via intent(out) , so the original pointer can become ill-defined… (something like the following).

(To avoid this kind of trouble, the [Q1] above comes into play…? (like getting the value of right% val first when entering assign() …?)

To me, definitely yes.

Thank you for the information from various perspectives and helpful discussion.

I understand there are four ways to avoid self-assignment a=a using overloaded assignment operations for derived types.

  • Use the intrinsic assignment operation for derived types.
  • Set the intent(inout) attribute to the argument on the left-hand side of the assignment operator and introduce the self-assignment guard (in the context of C++) using c_loc .
  • Set the value attribute to the argument on the right-hand side of the assignment operator.
  • Explicitly refer to the variable on the right-hand side of the assignment operator using () .

I’m currently trying to support the sorting procedures in stdlib to the bitset_large type. 4 requires modifications, verifications, and performance measurements of the sorting procedures, even for already supported types. 1 is considered to be the most realistic way for the bitset_large type because bitset_large type doesn’t have pointer component.

I have zero experience with the bitset type up to now (so cannot imagine what is best for library implementation), but personally in my codes, I stick to intrinsic assignment when a given composite type is planned to have no pointers inside. If some class has a pointer, I explicitly call a custom subroutine, partly because I am still not sure what happens under the hood for defined assignment… (I will ask about this later). Also, if the second argument is internally passed with (...) , it may be meaningless to take its address for self-assignment guard.

One more problem may be that one cannot forbid the inclusion of pointer components into a derived type. So, we may need to make sure that future people will not inadvertently add pointers if intrinsic assignment is used throughout.

:sweat_smile:

And also because the allocatable component has a default lower bound. In the case of an allocatable component with non-default lower bound, the intrinsic assignement would not be able to correctly transfer the bounds to the assigned object.

Related Topics

Topic Replies Views Activity
Help 8 1113 March 14, 2022
20 254 July 15, 2024
5 1038 October 30, 2020
34 4087 January 22, 2022
Help 7 252 March 18, 2024

7. Logical expressions

Logical expressions can only have the value .TRUE. or .FALSE. . A logical expression can be formed by comparing arithmetic expressions using the following relational operators :

So you cannot use symbols like Logical expressions can be combined by the logical operators .AND. .OR. .NOT. which have the obvious meaning.

Logical variables and assignment

Truth values can be stored in logical variables . The assignment is analogous to the arithmetic assignment. Example:

The order of precedence is important, as the last example shows. The rule is that arithmetic expressions are evaluated first, then relational operators, and finally logical operators. Hence b will be assigned .FALSE. in the example above. Among the logical operators the precedence (in the absence of parenthesis) is that .NOT. is done first, then .AND. , then .OR. is done last.

Logical variables are seldom used in Fortran. But logical expressions are frequently used in conditional statements like the if statement.

Copyright © 1995-7 by Stanford University. All rights reserved.

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Using user-defined derived type assignments in subroutine calls [duplicate]

I want to overcome the lousy and non-intuitive string handling in fortran by writing a more pythonic string type, but I stumpled across a mean issue with derived-type (overloaded) assignment. The main type should look like

with its power in the derived-type procedures. Of course the new string type should be as indistinguishable from the intrinsic CHARACTER(len=*) type as possible. Especially I want to use intrinsic routines (which use the character type) without any extra type conversions. Therefore I defined an assignment operator between CLASS(t_string) and CHARACTER(len=*) . E.g. open ing a file with the new type should look like this:

Since there is an assignment file=filename between t_string and CHARACTER(len=*) there should be no problem in the call to open . But I get an error due to mismatch in types.

I guess the problem is, that the assignment in the subroutine call is not really an assignment but just some syntax convention.

  • Any ideas how to fix this?
  • What is the reason (in term of design of the fortran language) for the "subroutine assignment" not to be a real assignment?
  • I do not want to call open(file = filename%str, ...)

Here is a mwe:

  • assignment-operator
  • derived-types

Jonathan Hall's user avatar

  • Although the linked question talks about iostat specifier the same holds for file : this is a specifier, not an argument keyword and certainly not an assignment process. –  francescalus Commented Apr 30, 2021 at 10:03
  • 1 @francescalus I am not convinced this is really a duplicate. –  Vladimir F Героям слава Commented Apr 30, 2021 at 10:27
  • 1 @VladimirF, the question has "assignment in the subroutine call is not really an assignment but just some syntax convention", and the linked question is the same (mis-)conception. (There are other questions covering keyword arguments also.) If the question was directly about "how can I use a non-character type for the filename?" then I agree that would be a different question. Naturally you can reopen this question, but the scope of your answer doesn't convince me to do that. –  francescalus Commented Apr 30, 2021 at 10:39
Since there is an assignment file=filename between t_string and CHARACTER(len=*) there should be no problem in the call to open.

No such assignment is present. You are only using the specifier name to specify which argument of the statement you are passing (similar to keyword/named arguments in Python, but not the same). open is in fact not a procedure, it is a statement, but it also has its "arguments" (specifiers) distinguished by their names.

Hence no derived assignment shall be invoked. You must convert to character yourself.

francescalus's user avatar

  • 1 I thought so. What a pitty. Do you have any ideas of how to fix this keeping the effort of using this string class low? Could this theoretically be added in future standards or are there side effects of making the "subroutine assignment"/"subroutine name identification" a real assignment? –  zufall Commented Apr 30, 2021 at 10:05
  • There's talk of adding generics to fortran at some point see e.g. this post , which could fix this problem (and a host of others). But don't expect this to be accepted into the standard any time soon, or to see compiler support for a long time after that... –  veryreverie Commented Apr 30, 2021 at 14:18
  • 1 Gonestly, I do not see how generics would help in this particular problem. –  Vladimir F Героям слава Commented Apr 30, 2021 at 14:33
  • @VladimirF I was making the (in hindsight overly optimistic) assumption that if and when generics are added, the intrinsic statements will be updated to make use of them. So the file argument of open would accept any type which extends character(*) or has the character(*) trait or somesuch. –  veryreverie Commented Apr 30, 2021 at 14:51
  • @veryreverie open is not a function. You can overload intrinsic functions in Fortran 90 and later already. But open is a statement. –  Vladimir F Героям слава Commented Apr 30, 2021 at 14:54

Not the answer you're looking for? Browse other questions tagged fortran assignment-operator subroutine derived-types or ask your own question .

  • The Overflow Blog
  • From PHP to JavaScript to Kubernetes: how one backend engineer evolved over time
  • Where does Postgres fit in a world of GenAI and vector databases?
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • What does a new user need in a homepage experience on Stack Overflow?
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • Can I retain the ordinal nature of a predictor while answering a question about it that is inherently binary?
  • add images in \longtable and remove justification
  • Order of connection using digital multimeter wall outlet
  • Can I use "historically" to mean "for a long time" in "Historically, the Japanese were almost vegetarian"?
  • How to assess whether it is imposter syndrome or actual low quality work during Ph.D.?
  • Does a MySQL replication slave need to be as powerful as the master?
  • High CPU usage by process with obfuscated name on Linux server – Potential attack?
  • Is 2'6" within the size constraints of small, and what would the weight of a fairy that size be?
  • Is it possible to create a board position where White must make the move that leads to stalemating Black to avoid Black stalemating White?
  • What is the name of the book about a boy dressed in layers of clothes who is actually a mouse?
  • Repeating zsh brace expansion values in zsh to download multiple files using wget2
  • What is the spiritual difference between hungering and thirsting? (Matthew 5:6)
  • Flight left while checked in passenger queued for boarding
  • Certificate/key revocation
  • Why doesn't the world fill with time travelers?
  • Not confident about going for PCB production
  • Trying to find an old book (fantasy or scifi?) in which the protagonist and their romantic partner live in opposite directions in time
  • How can I draw water level in a cylinder like this?
  • Is it possible to do physics without mathematics?
  • What does "garb" mean in this passage?
  • My enemy sent me this puzzle!
  • Why are volumes of revolution typically taught in Calculus 2 and not Calculus 3?
  • What are the risks of a compromised top tube and of attempts to repair it?
  • How do you hide an investigation of alien ruins on the moon during Apollo 11?

operator assignment fortran

IMAGES

  1. Operators in FORTRAN

    operator assignment fortran

  2. [ForTran 14]Logical Operators in ForTran

    operator assignment fortran

  3. PPT

    operator assignment fortran

  4. Fortran Programming Tutorials (Revised) : 006 : Fortran Operators and Operator Precedence

    operator assignment fortran

  5. 6. Programming with modern FORTRAN. Variables and assignment operator(part 2 demo)

    operator assignment fortran

  6. Operators, Functions and Parameters in FORTRAN

    operator assignment fortran

COMMENTS

  1. Tutorial OOP(IV) : Operator and Assignment Overloading

    1. Assignment (=) operator overloading When dealing with objects and classes—or extended data-structures in general—, their properties often are (implicit) pointers to the actual data-structure. This brings an interesting source of possible bugs due to shallow copies being made while deep copies are expected (although the problem may be less pronounced in Fortran than it is in Python).

  2. oop

    10 = is not an operator, it is an assignment in Fortran and they are very different beasts. To the classical possibility found in Fortran 90 and explained well in other answers, Fortran 2003 added a better possibility to bind the overloaded operators and assignments with the derived type.

  3. Operator Overloading

    What is operator overloading? Objectives. Overload the '+' operator. Previously in the Interface Blocks episode, we saw how interfaces can be used to map one procedure name onto different underlying procedures based on the number, order, and type or arguments passed to the procedure. However, these interface blocks can be used with more ...

  4. Fortran Operators

    Assignment Operator The assignment operator is = Example: double precision r r = 3.14; Unlike C/C++ , the assignment operation of Fortran does NOT cascade double precision r1, r2 r2 = r1 = 3.14 ! Illegal Arithmetic Operators Fortran Arithmentic Operators listed in order of precidence: ** exponentation * , / multiply, divide + , - add, subtract ...

  5. Fortran 90: Overloaded Operators

    Note the use of array operations end function vadd. The following code will add two vectors. type (vector) a,b,c a = vadd (b,c) Now using operator overloading, we can call the vadd function by using "+". interface operator (+) function vadd (v1,v2) result (v3) include "matvec.p" type (vector), intent (in) :: v1,v2 type (vector), :: v3 end ...

  6. How to overload assignment (=) in a class

    How to overload assignment (=) in a class. Overloading a subroutine means to redefine its internal functionality for a customized behavior. Overall it adapts the class new characteristics to already wide-spread Fortran functionalities (==, =, + ,-, …). Specifically, this post only focus on assignment (=). In the following example, Mynumber is ...

  7. Assignment (FORTRAN 77 Language Reference)

    Logical Assignment v is the name of a variable, array element, or record field of type logical. e is a logical expression, or an integer between -128 and 127, or a single character constant. Execution of a logical assignment statement causes evaluation of the logical expression e and assignment of the resulting value to v.

  8. PDF Chapter 24 Operator Overloading

    ing is defined by the language. In For-tran for example, the addition + operator invokes quite different code when used with support for user defined types. Fortran introduced support for operator and assignment o

  9. Fortran

    Fortran - Operators - An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. Fortran provides the following types of operators ?

  10. 10 Overloading operators for derived types

    Almost any app working with real-world data, or any program more complex than a toy model, will use derived types (classes) to handle abstract data. Fortran's intrinsic operators for arithmetic ( +, -, *, /, **) and comparison ( ==, /=, >=, ⇐, >, <) are available out of the box for intrinsic numeric ( integer, real, complex) but not for derived types. For example, to keep track of calendar ...

  11. opover in Fortran Wiki

    opover in Fortran Wiki. @(#) Example of overloading operators in Fortran ! ! The following MODULE allows for using the syntax ! L1 == L2 ! where L1 and L2 are LOGICAL ! as an alternative to ! L1 .EQV. L2 ! (or the function call ! BOOLEAN_EQUAL (L1, L2)) ! or ! L1 .BOOLEAN_EQUAL. L2 ! for that matter); and likewise allows !

  12. Overloading and Generic Programming

    Overloading is when a procedure or operator is able to work on multiple types. Most languages overload at least basic arithmetic operators to work on all numerical types. In modern Fortran the mathematical intrinsics are overloaded to work at least on real and double precision, and when appropriate complex.

  13. Operator (+) overload in a class

    Operator (+) overload in a class. Overloading a subroutine means to redefine its internal functionality for a customized behavior. Overall it adapts the class new characteristics to already wide-spread Fortran functionalities (==, =, + ,-, …). Specifically, this post only focus on the operators (+,-,*,/). In the following example, m ynumber ...

  14. Updating assignment operators

    If Fortran eventually adds these operators, just curious how to implement:

  15. Assigning a derived type variable to itself

    How should we handle the assignment of a derived type variable to itself when the assignment operator for the derived type is overloaded in a subroutine? How is such a situation mentioned in the Fortran Standard?

  16. Operator functions in F90

    Operator functions in F90 Operator functions Operator functions are functions that are invoked when the compiler encounter an expression of the following forms : value OPERATOR value (binary operator) OPERATOR value (uniary operator) Important restriction : Input parameters of operator functionsmust be declaredINTENT (IN) I.e., operator functionscannot modify their input operands Fortran ...

  17. Fortran 77 Tutorial

    Among the logical operators the precedence (in the absence of parenthesis) is that .NOT. is done first, then .AND. , then .OR. is done last. Logical variables are seldom used in Fortran.

  18. Fortran derived types: Overloaded assignment operator not working with

    The assignment of real to complex is handled intrinsically by Fortran. This method works well when used on "typical" bicomplex variables, but breaks when I want to assign a real*8 to a bicomplex which has the PARAMETER attribute:

  19. fortran

    I want to overcome the lousy and non-intuitive string handling in fortran by writing a more pythonic string type, but I stumpled across a mean issue with derived-type (overloaded) assignment. The m...