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

gfortran: floor() function only for single precision?

326 views
Skip to first unread message

Ingo Thies

unread,
Mar 23, 2013, 5:46:01 AM3/23/13
to
Dear all,

I am quite surprised to get an error message when passing a double
precision (real(kind=8)) argument to the gfortran intrinsic function
floor (and the same should apply to ceiling):

Error: 'a' argument of 'nint' intrinsic at (1) must be REAL

Is there a specific reason to restrict this function to low-precision
arguments while most other functions automatically detect the kind, or
is there an option to use floor with double precision arguments?

BTW, I know that a custom floor function is easily made, but it is
nevertheless a convenience issue.

Best wishes,

Ingo

Daniel Feenberg

unread,
Mar 23, 2013, 6:30:11 AM3/23/13
to
Just guessing, but perhaps the reason is that the system can't represent
exactly all the integers that floor(double) might need to be correct. Note that double precision reals have a range far above the level at which every integer has an exact representation. Possibly 19999999999 doesn't have an exact binary representation, so the system doesn't want to promise to evaluate floor(19999999999.5).

daniel feenberg

Ingo Thies

unread,
Mar 23, 2013, 7:16:08 AM3/23/13
to
Am 23.03.2013 11:30, schrieb Daniel Feenberg:

> Just guessing, but perhaps the reason is that the system can't
> represent exactly all the integers that floor(double) might need to
> be correct. Note that double precision reals have a range far above
> the level at which every integer has an exact representation.
> Possibly 19999999999 doesn't have an exact binary representation, so
> the system doesn't want to promise to evaluate floor(19999999999.5).

Well, int(), nint() etc. works fine with both kind=4 and 8. And floor is
essentially the same as int for positive arguments and int-1 for
negative ones with non-zero decimal fraction. I am using this
construction frequently, since in my work I need a floor-like rounding
more often than simpla truncation.

It is clear that double precision has a larger range than integers (this
is true for single precision, which goes to about 10^38, as well), but
for those below 2^31-1 I see no reason to refuse operation. In addition,
a function which returns the floor value as double precision again would
solve the problem either.

I guess that someone has simply forgotten to implement automatic type
detection in floor/ceiling, either the developers of gfortran or of the
F95 standard itself (and gfortran simply sticks to this standard).

Best wishes,

Ingo

Thomas Koenig

unread,
Mar 23, 2013, 8:25:32 AM3/23/13
to
Ingo Thies <ingo....@gmx.de> schrieb:
> I am quite surprised to get an error message when passing a double
> precision (real(kind=8)) argument to the gfortran intrinsic function
> floor (and the same should apply to ceiling):
>
> Error: 'a' argument of 'nint' intrinsic at (1) must be REAL

Can you provide an example?

The following works as expected:

module x
contains
subroutine foo(a)
real(kind=8), intent(in) :: a
print *,nint(a),floor(a),ceiling(a)
end subroutine foo
end module x

program main
use x
real(kind=8) :: v
v = 1.4_8
call foo(v)
end program main

The output is

1 1 2

Ingo Thies

unread,
Mar 23, 2013, 10:18:15 AM3/23/13
to
Am 23.03.2013 13:25, schrieb Thomas Koenig:

Oops, the error was the argument of "nint", not "floor". I expected
floor returning a real/double and therefore wrapped an (nint) around to
avoid rounding errors (which sometimes occur even for values defined as
exact values if the code is compiled with optimization options).

However, the gfortran manual explicitely says "real" as input type.

Sorry for the confusion - it's weekend, and the coffee was perhaps not
strong enough ;-)

Best wishes,

Ingo

Richard Maine

unread,
Mar 23, 2013, 12:44:18 PM3/23/13
to
Ingo Thies <ingo....@gmx.de> wrote:

> Am 23.03.2013 13:25, schrieb Thomas Koenig:
>
> Oops, the error was the argument of "nint", not "floor". I expected
> floor returning a real/double and therefore wrapped an (nint) around to
> avoid rounding errors (which sometimes occur even for values defined as
> exact values if the code is compiled with optimization options).

I'd need to see the actual code. Answer number 1 to many, many questions
in this newsgroup is to show the code instead of trying to describe it.

> However, the gfortran manual explicitely says "real" as input type.

Note that as of f90, double precision *IS* real type. It is real type
with a specific kind. F77 was different; real and double were distinct
types then. But in 90, double precision is just an alternate syntax
(mostly for compatibility with old code) for declaring a particular kind
of real.

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

Ingo Thies

unread,
Mar 23, 2013, 1:43:42 PM3/23/13
to
Am 23.03.2013 17:44, schrieb Richard Maine:

> I'd need to see the actual code. Answer number 1 to many, many questions
> in this newsgroup is to show the code instead of trying to describe it.

Just nint(floor(a)) instead of floor(a):

program main
real(kind=8) :: a
a = 1.4_8
print *,nint(a),floor(a),ceiling(a) ! works
print *,nint(floor(a)) ! compiler error message
end program main

Again, I have mistaken the error message for nint for that with floor.
Since floor returns integer per default (which I was not aware of), but
nint expects real/double, the compiler returned an error message. And
since floor is already integer per default (so no trouble with rounding
when using -O3 etc. options), the use of nint is completely unnecessary
here, anyway. So, again, sorry for causing confusion.

Best wishes,

Ingo

glen herrmannsfeldt

unread,
Mar 23, 2013, 2:14:27 PM3/23/13
to
Richard Maine <nos...@see.signature> wrote:
> Ingo Thies <ingo....@gmx.de> wrote:

>> Am 23.03.2013 13:25, schrieb Thomas Koenig:

>> Oops, the error was the argument of "nint", not "floor". I expected
>> floor returning a real/double and therefore wrapped an (nint) around to
>> avoid rounding errors (which sometimes occur even for values defined as
>> exact values if the code is compiled with optimization options).

I would have thought FLOOR would return REAL (of appropriate KIND)
but it seems to return INTEGER.

I remember learning about FLOOR and CEIL in PL/I, long before Fortran
had them, and I believe there they return the same attributes as
the argument.

There is ANINT with REAL result, but no AFLOOR and ACEIL.

> I'd need to see the actual code. Answer number 1 to many, many questions
> in this newsgroup is to show the code instead of trying to describe it.

>> However, the gfortran manual explicitely says "real" as input type.

> Note that as of f90, double precision *IS* real type. It is real type
> with a specific kind. F77 was different; real and double were distinct
> types then. But in 90, double precision is just an alternate syntax
> (mostly for compatibility with old code) for declaring a particular kind
> of real.

Yes, but INTEGER (returned by FLOOR) is not a REAL type.

-- glen
0 new messages