Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Complex to real: DBLE, REAL, DIMAG and AIMAG.

515 views
Skip to first unread message

P Vincent

unread,
Apr 30, 2009, 2:01:01 PM4/30/09
to
It is my first post in this forum.
I am just a scientist using Fortan, not a specialist of Fortran
standards, an I want to relate a tricky bug that puzzled me recently.
I had two versions of a program giving not the same results and
searching for the divergence point, found that, at this point, the
imaginary parts of complex numbers were identical, but not the real
ones. The main difference between the two versions was that, in an
attempt to conform to the F95 norm, I had changed all the DBLE into
REAL and DIMAG into AIMAG.

Unfortunately, some previous modifications had transformed some
complex expressions into real ones and the behaviour of REAL is
different in the two cases:
* applied to a complex, it takes the real part with the same
precision,
* applied to a real double precision, it gives a real simple
precision.

All variables in my program are (and need to be) REAL(8) or COMPLEX(8)
and this was not respected by the new version.

This bug cannot occur changing DIMAG into AIMAG, because the compiler
complains if the argument is real.

In fact two different functions must have different names and taking
the real part of a complex or changing the precision of a variable
are not the same action.

Thus I think that using a name different (e.g. REAL_PART) to take the
real part of a complex can avoid this sort of bug.
What do you think of that?

glen herrmannsfeldt

unread,
Apr 30, 2009, 2:32:49 PM4/30/09
to
P Vincent <frer...@gmail.com> wrote:
(snip)

> The main difference between the two versions was that, in an
> attempt to conform to the F95 norm, I had changed all the DBLE into
> REAL and DIMAG into AIMAG.

DBLE should not be changed to REAL, but to REAL with the
appropriate second argument.

Personally, I do agree that it is confusing having two different
uses for the function REAL, but that is the way it is.

REAL(X,KIND(1.D0))

will get you the double precision KIND of REAL. (And just the
real part if it is complex.)

-- glen

Richard Maine

unread,
Apr 30, 2009, 3:06:13 PM4/30/09
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> REAL(X,KIND(1.D0))
>
> will get you the double precision KIND of REAL.

But I would never recommend that anyone actually write it that way. In
addition to looking awkward, it has the philosophical objection of
computing the same thing (the kind number) multiple times (because this
is bound to not be the only place in the program that uses that kind).

I don't know your style preferences well enough to be sure whether you
would actually recommend writing it like this or whether you were just
abbreviating, but I have some disagreement in either case.

If you actually recommend the style, then I'll just stop with saying
that I don't.

If this is just an abbreviation, I caution that readers new to f90-ish
things often don't pick up on things like that. They see examples and
take them literally, without necessarily making the immediate
translation that a more experienced f90 programmer might find obvious.
This case isn't too horribly bad, but I have seen people horrified at
how awkward things like selected_real_kind were because they thought
that you really were supposed to put it directly in each declaration
just like the example someone showed them. (Yes, selected_real_kind is a
little awkward anyway, but it have to be the horror that using it that
way would be).

Ii would write the above something more like either

real(x,kind=dp)

or

real(x,dp)

depending one one's preference for the keyword in that context (I'd
probably use it), and where dp is an appropriately defined kind
parameter, perhaps from something like

integer, parameter :: dp = kind(1.d0)

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

glen herrmannsfeldt

unread,
Apr 30, 2009, 3:25:49 PM4/30/09
to
Richard Maine <nos...@see.signature> wrote:
> glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

>> REAL(X,KIND(1.D0))

>> will get you the double precision KIND of REAL.

> But I would never recommend that anyone actually write it that way. In
> addition to looking awkward, it has the philosophical objection of
> computing the same thing (the kind number) multiple times (because this
> is bound to not be the only place in the program that uses that kind).

I agree, but for a direct replacement for DBLE, it doesn't
seem so bad. Other than problems with continuation lines,
it could easily be done as a string substitution. (Also, one
would have to be careful with parentheses.)

Getting PARAMETER statements into the right place would be
somewhat harder. If one was planning for more than just replacing
DBLE then I 100% agree that PARAMETER and SELECTED_REAL_KIND
is a better choice. Then again, DBLE isn't so bad...

-- glen

Ron Shepard

unread,
Apr 30, 2009, 7:47:00 PM4/30/09
to
In article <1iyzi5z.11bpwctohz2giN%nos...@see.signature>,
nos...@see.signature (Richard Maine) wrote:

It would surprise me if this makes any difference in efficiency.
KIND(1.0D0) would be determined at compile time, so as far as runtime
efficiency

REAL(X,KIND(1.D0))

or

real(x,dp)

would end up with the same sequence of instructions.

However, the problem with the first approach might be that you don't
really want double precision, but rather some other floating point kind.
Say you have

integer, parameter :: dp = selected_real_kind(13)

then depending on the compiler, or the options you use for your
compiler, that might or might not correspond to KIND(1.D0).

So, another way to write these types of statements in a slightly more
portable way is like

y = real(x,kind(y))

where "y" is a real variable of the correct time (however it is
declared). Again, I would expect kind(y) to be evaluated at compile
time, not runtime, so there would be no efficiency concerns. In this
case, you never get any extra, or less, precision that you need,
regardless of what the compiler defaults are or what the compiler
options are. This can be adapted in a straightforward way if the real()
function result is used in a more complicated expression, not just a
simple assignment.

I agree that this is mostly just a matter of programming style, but I
think it is at least worth considering, and there are some practical
issues involved.

$.02 -Ron Shepard

Richard Maine

unread,
Apr 30, 2009, 9:03:48 PM4/30/09
to
Ron Shepard <ron-s...@NOSPAM.comcast.net> wrote:

> In article <1iyzi5z.11bpwctohz2giN%nos...@see.signature>,
> nos...@see.signature (Richard Maine) wrote:
>
> > > REAL(X,KIND(1.D0))
> > >
> > > will get you the double precision KIND of REAL.
> >
> > But I would never recommend that anyone actually write it that way. In
> > addition to looking awkward, it has the philosophical objection of
> > computing the same thing (the kind number) multiple times (because this
> > is bound to not be the only place in the program that uses that kind).

> It would surprise me if this makes any difference in efficiency.

I wouldn't expect it to either. Efficiency is not the basis for my
objection to computing the same thing multiple times. The objection has
a lot more to do with issues such as clarity and maintainability.

Sure, the compiler computes 'em all at compile time - kind values are
like that. But the human reader has to parse each one as he reads it.
That human has to recognize that

double precision
real*8 (if you use that one)
kind(1.d0)
kind(1.0d0)
kind(0.d0)
dp (for appropriate dp)
8 (if you hard-wire that value)
real (if you have used some compiler switches)

all refer to the same thing. Yes, some of the above variants are
recommended against for other reasons. But even when you toss all those,
there are multiple options left. I think it better to go for
consistency, defining dp (or whatever you want to name it; I personally
use a bit more long-winded names) once and using it everywhere.

And if you ever want to change it, you have to catch all the different
places, including all the variations you used in different contexts.

As an aside, I see no benefit to replacing dble(x) with
real(x,kind(1.d0)). It is still specific to double precision and has
that dependency buried in the middle of the code in places not obvious
to a casual glance. That change strikes me as one of those "knee jerk"
reactions to someone explaining that one should not use specific
intrinsics such as dble. The change does avoid using dble, but
completely misses the point of avoiding dble in my opinion. Sort of like
people who heard that goto is bad, but who have no idea why, so they
eliminate their gotos with hacks that are worse than the goto because
they have all of the original problems of go to, with the extra
disadvantage of being obfuscated. If you are going to keep all the
disadvantages of dble, you might as well stick with the simpler syntax
of actually using dble. Using real(x,dp) is a different matter entirely
in that it improves the maintainability of the code.

P Vincent

unread,
May 1, 2009, 5:45:46 AM5/1/09
to
On 1 mai, 03:03, nos...@see.signature (Richard Maine) wrote:

Thanks you all for this nice discussion that gives me a better insight
of the DBLE-REAL issue. Waiting for a function really symmetrical to
AIMAG in the Fortran norm, I think I will continue to use the more
readable i.e. DBLE.
P. Vincent

robin

unread,
May 1, 2009, 9:23:26 AM5/1/09
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1iyzi5z.11bpwctohz2giN%nos...@see.signature...

> glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
>
> > REAL(X,KIND(1.D0))
> >
> > will get you the double precision KIND of REAL.
>
> But I would never recommend that anyone actually write it that way. In
> addition to looking awkward, it has the philosophical objection of
> computing the same thing (the kind number) multiple times

The kind number is determined at compile time,
not execution time, so computing "multiple times" is irrelevant.


robin

unread,
May 1, 2009, 9:23:28 AM5/1/09
to
"Ron Shepard" <ron-s...@NOSPAM.comcast.net> wrote in message
news:ron-shepard-4E9C...@news60.forteinc.com...

> So, another way to write these types of statements in a slightly more
> portable way is like
>
> y = real(x,kind(y))
>
> where "y" is a real variable of the correct time (however it is
> declared). Again, I would expect kind(y) to be evaluated at compile
> time, not runtime, so there would be no efficiency concerns.

The kind is something that is required to be
known at compile time.


robin

unread,
May 1, 2009, 9:23:27 AM5/1/09
to
"P Vincent" <frer...@gmail.com> wrote in message
news:f6d3fcf9-f051-4386...@b6g2000pre.googlegroups.com...

> It is my first post in this forum.
> I am just a scientist using Fortan, not a specialist of Fortran
> standards, an I want to relate a tricky bug that puzzled me recently.
> I had two versions of a program giving not the same results and
> searching for the divergence point, found that, at this point, the
> imaginary parts of complex numbers were identical, but not the real
> ones. The main difference between the two versions was that, in an
> attempt to conform to the F95 norm, I had changed all the DBLE into
> REAL and DIMAG into AIMAG.

You don't really need to change DBLE.


robin

unread,
May 1, 2009, 9:23:26 AM5/1/09
to
"P Vincent" <frer...@gmail.com> wrote in message
news:f6d3fcf9-f051-4386...@b6g2000pre.googlegroups.com...

> All variables in my program are (and need to be) REAL(8) or COMPLEX(8)


> and this was not respected by the new version.

REAL(8) etc is not a portable declaration.

Better is to use selected_real_kind or kind.


Dan Nagle

unread,
May 1, 2009, 10:41:28 AM5/1/09
to
Hello,

On 2009-05-01 09:23:27 -0400, "robin" <rob...@bigpond.com> said:

> You don't really need to change DBLE.

<splork!>

There are good reasons to prefer real()
with the correct type kind value rather than dble().

dble() is conversion to double precision,
which is not always the 64-bit kind.

In the face of 32-bit and 64-bit chips and compilers,
and various compiler options, it is generally better
to be explicit about the target of the intended
conversion. Especially if numeric differences,
which is what led the OP to post in the first place,
arise.

--
Cheers!

Dan Nagle

robin

unread,
May 1, 2009, 6:33:14 PM5/1/09
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1iyzyfy.1a42q741c3qyf8N%nos...@see.signature...

No they don't. REAL*8 is not standard.

8 is a number and doesn't guarantee that you get
anything. Kind numbers are arbitrary.


robin

unread,
May 5, 2009, 9:37:26 AM5/5/09
to
"Dan Nagle" <dann...@verizon.net> wrote in message news:2009050110412916807-dannagle@verizonnet...

> Hello,
>
> On 2009-05-01 09:23:27 -0400, "robin" <rob...@bigpond.com> said:
>
> > You don't really need to change DBLE.
>
> <splork!>

Is the pig speaking again!

> There are good reasons to prefer real()
> with the correct type kind value rather than dble().

Not in this case.

> dble() is conversion to double precision,
> which is not always the 64-bit kind.

It is in this case.
If it works, don't fix it.

> In the face of 32-bit and 64-bit chips and compilers,
> and various compiler options, it is generally better
> to be explicit about the target of the intended
> conversion. Especially if numeric differences,
> which is what led the OP to post in the first place,
> arise.

The reason that the OP had numeric differences
was because he used REAL to convert the double precision
values to single precision.

That was because he was NOT using DBLE !
Had he retained DBLE instead of changing it,
the problem would not have arisen.


Dan Nagle

unread,
May 9, 2009, 7:16:16 AM5/9/09
to
Hello,

On 2009-05-05 09:37:26 -0400, "robin" <rob...@bigpond.com> said:

> "Dan Nagle" <dann...@verizon.net> wrote in message
> news:2009050110412916807-dannagle@verizonnet...
>> Hello,
>>
>> On 2009-05-01 09:23:27 -0400, "robin" <rob...@bigpond.com> said:
>>
>>> You don't really need to change DBLE.
>>
>> <splork!>
>
> Is the pig speaking again!

<splork!>

robin compounds his usual Fortran foolishness by failing
to understand Usenet terminology.

http://www.faqs.org/docs/jargon/S/splork.html

(Mind you, it's funny in a "I used to be disgusted,
not I try to be amused" sort of way.")

Using kind-specific conversions is error-prone due
to differences in hardware, compilers, and compiler options.
As another thread recently explained, use the selected*
inquiries to get the right kind values.

oo

--
Cheers!

Dan Nagle

glen herrmannsfeldt

unread,
May 9, 2009, 1:51:06 PM5/9/09
to
Dan Nagle <dann...@verizon.net> wrote:

> Using kind-specific conversions is error-prone due
> to differences in hardware, compilers, and compiler options.
> As another thread recently explained, use the selected*
> inquiries to get the right kind values.

This is true, but...

Most of the time people don't really know the exact precision
needed for a calculation. If you do know, it most likely is
known only at run-time and not at compile time. One might
read in some data with associated uncertainties, where those
uncertainties could be used to select the needed precision.

Also, as hardware converges toward the IEEE standards, the
variety of precisions it decreasing. No more 60 bit CDC
machines. The 36 bit machines that started Fortran are
gone, though some DEC 36 bit machines are still running.
128 bit floating point never got so popular that it was
a serious choice for most people, though that could still
change.

-- glen

Dan Nagle

unread,
May 9, 2009, 4:48:14 PM5/9/09
to
Hello,

On 2009-05-09 13:51:06 -0400, glen herrmannsfeldt <g...@ugcs.caltech.edu> said:

> Most of the time people don't really know the exact precision
> needed for a calculation.

Yea, sure, ok, but ...

Most folks have an idea whether they want 32-bit, 64-bit, or 128-bit
real numbers. And they know what to put in the selected*()
to get the desired result.

The terms "real" and "double precision" are still rather undefined,
as they are only defined in terms of numeric storage units,
which are themselves undefined.

Surely, you're not claiming that dble() is as well defined as
real( , kind= selected_real_kind( p= 15)) ??
(And no, I don't expect to see that literally in Real Code (tm).)

And yes, the CDC/Cray (why not throw in the Univacs & DECs
and their 36/72 bit stuff, or S/360 and the hex normalized floats,
and so on) might still be around warming some dark corner. But,
as you say, it's mostly 754 these days, so you _know_ what p= to set.

But surely, that's just making the point more firmly.

--
Cheers!

Dan Nagle

robin

unread,
May 28, 2009, 11:45:46 AM5/28/09
to
"Dan Nagle" <dann...@verizon.net> wrote in message news:2009050907161816807-dannagle@verizonnet...

> Hello,
>
> On 2009-05-05 09:37:26 -0400, "robin" <rob...@bigpond.com> said:
>
> > "Dan Nagle" <dann...@verizon.net> wrote in message
> > news:2009050110412916807-dannagle@verizonnet...
> >> Hello,
> >>
> >> On 2009-05-01 09:23:27 -0400, "robin" <rob...@bigpond.com> said:
> >>
> >>> You don't really need to change DBLE.
> >>
> >> <splork!>
> >
> > Is the pig speaking again!
>
> <splork!>

Could the pig be speaking again?

> robin compounds his usual Fortran foolishness by failing
> to understand Usenet terminology.

> Using kind-specific conversions is error-prone due


> to differences in hardware, compilers, and compiler options.

It isn't - for a WORKING pre-F90 program
(which is the case here).

Dan Nagle

unread,
May 28, 2009, 3:09:08 PM5/28/09
to
Hello,

On 2009-05-28 11:45:46 -0400, "robin" <rob...@bigpond.com> said:

>> Using kind-specific conversions is error-prone due
>> to differences in hardware, compilers, and compiler options.
>
> It isn't - for a WORKING pre-F90 program
> (which is the case here).

<splork!>

http://www.faqs.org/docs/jargon/S/splork.html

WORKING pre-f90 programs didn't have kinds, they had
specific types, which were error prone when moved
to new hardware.

WORKING pre-f90 programs had problems when switching
between hardware of different numerical storage sizes.

That's *why* the kind mechanism was invented
in the first place.

0 new messages