Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can you avoid temporary storage when overloading operators?

Status
Not open for further replies.

Steve77088

Programmer
Apr 6, 2017
2
US
I was using operator overloading for a vector class

--------- cut here ---------
[pre]

interface operator(+)
module procedure :: vec_add_sv !< scalar + vector
module procedure :: vec_add_vs !< vector + scalar
module procedure :: vec_add_vv !< vector + vector
end interface operator(+)
:
:
function vec_add_sv( s, v1 ) result( v2 )
type(Vector) :: v2
real(dp), intent(in) :: s
type(Vector), intent(in) :: v1
integer :: i, n
n = v1%size()
call v2%resize(n)
do i=1,n
V2%q(i) = s + V1%q(i)
end do
end function vec_add_sv
:
:
v2 = s + v1

[/pre]

--------- cut here ---------

works just fine. However when I implemented:

[pre]

interface assignment(=)
module procedure vector_assign
end interface assignment(=)

[/pre]

and put a print statement in the subroutine vector_assign I noticed that when I used

[pre]
vec2 = scalar + vector
[/pre]

it called both the vec_add_sv function and the vector_assign subroutine. This indicates that the vec_add_sv function created a temporary vector for its return and then passed that temporary to the vector_assign subroutine. The result is that I am looping through my vector elements twice.

Is there a way to implement binary operators with out creating temporary storage?
I recognize that a temporary is needed if you do something like A = B + ( C * D ) then (C * D) crates a temporary that is used in B + temp.
But if I am just doing a single operation A = B + C

I would like something equivalent to

[pre]
interface add
subroutine vec_add( A, B, C )
type(vector), intent(out) :: A
type(vector), intent(in) :: B
type(vector), intent(in) :: C
end subroutine vec_add
end interface add
[/pre]

interface operator(+) requires the module procedure to be a function not a subroutine



 
hhhmmm, operator overloading is not something I do often; but, first...I am curious, why are you implementing something Fortran already does? I guess there is more to 'vector' type, but you don't show it. Is it more than just an array? And size and resize does not count! That can be done natively, too.
 
This was just a simple demonstration to generate the temporary object. In other languages such as C++ the operator overload does not create a temporary object unless you explicitly build it that way. To answer you question there is a lot more to matrix and vector interaction than you can get with that intrinsic array functions. What I am actually working with is a multidimensional structure known as a tensor. 1D & 2D tensors are the familiar vectors and matrices from linear algebra. A math library with higher order tensors is what I am after.
 
Operators are just for convenience, readability and elegance but they are not necessarily efficient. You pay for the convenience. You are back to quads or triplets (compiler code generation terminology) if you want efficiency.

eg instead of A = B + ( C * D ) convert to reverse Polish and write something like
Code:
call mult(D, C, A)
call add(B, A)
It is not pretty but it may be faster than creating temp objects. Creation of temp objects doesn't matter if you have a fast machine or are running the operations a few times but if you have a slow machine or are doing the computation millions of times, then you really need to optimize.

Also with temp objects, if they are on the stack, they just get deleted when they are out of scope - that is quite fast. If they are on the heap, you could get a memory leak, memory fragmentation or all sorts of weird and wonderful things that fascinate computer scientists. I just fixed a massive build up of temp objects in C# (don't believe all you read about C#) which was causing the machine to reboot after 30 minutes because the temp objects weren't being cleared out.
 
just a comment regarding the loop in the function above;

this:
Code:
do i=1,n
    V2%q(i) = s + V1%q(i)
end do
can be more efficiently written like this:
Code:
V2%q(1:n) = s + V1%q(1:n)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top