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

Fortran alternative to C modf

202 views
Skip to first unread message

Thomas Jahns

unread,
Nov 12, 2015, 11:08:52 AM11/12/15
to
What's the Fortran way to return the fractional part f of a REAL variable x?

One expensive option is certainly

f = mod(x, 1.0)

Another slightly more verbose would be

f = x - aint(x)

C has modf which gives slightly more than desired. But does Fortran have a
similar construct? The FRACTION intrinsic returns what's C's frexp would return
it seems.

Thomas

Dick Hendrickson

unread,
Nov 12, 2015, 12:51:57 PM11/12/15
to
On 11/12/15 10:08 AM, Thomas Jahns wrote:
> What's the Fortran way to return the fractional part f of a REAL
> variable x?
>
> One expensive option is certainly
>
> f = mod(x, 1.0)

Why do you think this is expensive? I'd think almost any level of
optimization would do the right thing with the 1.0 value.

>
> Another slightly more verbose would be
>
> f = x - aint(x)

This is the standard's explanation of what MOD is equivalent to
A - INT (A/P) * P
with P special cased.

There's also the MODULO function which, I think, does things differently
for some combinations of negative values.

Dick Hendrickson

robin....@gmail.com

unread,
Nov 13, 2015, 2:37:56 AM11/13/15
to
On Friday, November 13, 2015 at 3:08:52 AM UTC+11, Thomas Jahns wrote:
> What's the Fortran way to return the fractional part f of a REAL variable x?

Use the FRACTION intrinsic.

Thomas Jahns

unread,
Nov 13, 2015, 3:55:33 AM11/13/15
to
On 11/12/15 18:51, Dick Hendrickson wrote:
> On 11/12/15 10:08 AM, Thomas Jahns wrote:
>> What's the Fortran way to return the fractional part f of a REAL
>> variable x?
>>
>> One expensive option is certainly
>>
>> f = mod(x, 1.0)
>
> Why do you think this is expensive? I'd think almost any level of optimization
> would do the right thing with the 1.0 value.

that's possibly true, but I like to use constructs that map to efficient
operations for those compilers which for some reason get the optimization wrong.
That also helps with the execution speed of debug builds.

>>
>> Another slightly more verbose would be
>>
>> f = x - aint(x)
>
> This is the standard's explanation of what MOD is equivalent to
> A - INT (A/P) * P
> with P special cased.
>
> There's also the MODULO function which, I think, does things differently for
> some combinations of negative values.

The idea behind the question is for a table lookup combined with interpolation
of the non-integral part, so while interesting to some, I'm not concerned with
negative values here.

Thomas

JB

unread,
Nov 13, 2015, 4:27:34 AM11/13/15
to
On 2015-11-13, Thomas Jahns <ja...@idontlikespam.dkrz.de> wrote:
> On 11/12/15 18:51, Dick Hendrickson wrote:
>> On 11/12/15 10:08 AM, Thomas Jahns wrote:
>>> What's the Fortran way to return the fractional part f of a REAL
>>> variable x?
>>>
>>> One expensive option is certainly
>>>
>>> f = mod(x, 1.0)
>>
>> Why do you think this is expensive? I'd think almost any level of optimization
>> would do the right thing with the 1.0 value.
>
> that's possibly true, but I like to use constructs that map to efficient
> operations for those compilers which for some reason get the optimization wrong.
> That also helps with the execution speed of debug builds.

For some implementation details, gfortran maps the mod intrinsic for
real arguments directly to the C fmod{f,,l}() functions. If both
arguments are constant, it's evaluated at compile time, otherwise
depending on the compilation options (-ffast-math) it's either
expanded inline or a call to the C library function is made. At least
when expanded inline it should be reasonably fast.

It seems there is no special casing for when the second argument is 1.

>>> Another slightly more verbose would be
>>>
>>> f = x - aint(x)
>>
>> This is the standard's explanation of what MOD is equivalent to
>> A - INT (A/P) * P
>> with P special cased.

This might be faster than the library call, but there are some corner
cases like large arguments, signed zeros, the second argument equal to
zero, etc. See

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24518

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49010



--
JB

robin....@gmail.com

unread,
Nov 13, 2015, 4:47:38 AM11/13/15
to
On Friday, November 13, 2015 at 3:08:52 AM UTC+11, Thomas Jahns wrote:
> What's the Fortran way to return the fractional part f of a REAL variable x?
>
> One expensive option is certainly
>
> f = mod(x, 1.0)
>
> Another slightly more verbose would be
>
> f = x - aint(x)

By subtracting the whole number part from x, you get the
fractional part.

Thus, if x = 9.876, you have aint(x) = 9.0, and you get 0.876.

FRACTION delivers something entirely different.

Ron Shepard

unread,
Nov 13, 2015, 10:33:17 AM11/13/15
to
On 11/13/15 3:47 AM, robin....@gmail.com wrote:
>> Another slightly more verbose would be
>> >
>> >f = x - aint(x)
> By subtracting the whole number part from x, you get the
> fractional part.
>
> Thus, if x = 9.876, you have aint(x) = 9.0, and you get 0.876.
>
> FRACTION delivers something entirely different.

I think this is probably the best approach in fortran. Yes, FRACTION()
returns the binary fraction from the internal floating point
representation, not the decimal fraction which is desired here.

A possible alternative is to use FLOOR(x) rather than AINT(x). The
former always rounds down (toward negative infinity), while the latter
rounds toward zero, so the correct choice depends on what you want to do
with negative values of x.

If you happen to want to always round up (toward positive infinity),
then you would need the CEILING() intrinsic, and if you want to round
toward the nearest integer then you would need the ANINT() intrinsic. I
just point out these options to show that fortran does indeed cover all
possibilities for rounding.

I just did a quick search on these intrinsics while writing this reply,
and I noticed that the gfortran documentation incorrectly uses the term
"whole number" to describe the function result of AINT() and ANINT().
That term usually means a nonnegative integer (0 or positive), which is
not correct for either of these intrinsics. I have not looked at the
standard to see what term is used there. In any case, what is returned
is a floating point number (REAL) that approximates the appropriate
integer value, and there is an optional KIND argument that allows
different KIND values to be returned. That argument may be important for
INTEGER values that are too large to be represented in the default real
kind.

$.02 -Ron Shepard

robert....@oracle.com

unread,
Nov 18, 2015, 1:21:30 AM11/18/15
to
On Thursday, November 12, 2015 at 9:51:57 AM UTC-8, Dick Hendrickson wrote:
> On 11/12/15 10:08 AM, Thomas Jahns wrote:
> > What's the Fortran way to return the fractional part f of a REAL
> > variable x?
> >
> > One expensive option is certainly
> >
> > f = mod(x, 1.0)
>
> Why do you think this is expensive? I'd think almost any level of
> optimization would do the right thing with the 1.0 value.

I do not know of a compiler that does that optimization. I proposed adding it to Oracle Solaris Studio Fortran years ago, but it has never approached the top of our list of things to do.

Bob Corbett

kargl

unread,
Nov 18, 2015, 11:49:38 AM11/18/15
to
cat g.f90

kargl

unread,
Nov 18, 2015, 11:51:26 AM11/18/15
to
Agh. Ignore. I hit send before I finished composing a message in
another editor.

--
steve
0 new messages