Calling standard native function

  • Thread starter Screamin Lord Byron
  • Start date
S

Screamin Lord Byron

Hi,

The title might be a little confusing (or even completely wrong), so
I'll try to explain exactly what I mean.

For example, suppose you must do lots of power calculations and you can
guarantee that the x argument to Math.pow(double x, double y) will
always be positive or zero and it will never be infinity. In other
words, no special cases, so you don't need the checks that Math.pow()
provides prior to calling the native doPow() function. My question is:
is it somehow possible to call that native function directly?

Where are the implementations of such functions? Google wasn't very
helpful because it wants to teach me how to make my own native
functions. I was looking at JNA, but that's obviously not what I want
either.

If you're interested in the purpose of this it's purely curiosity.

Thanks.
 
E

Eric Sosman

Hi,

The title might be a little confusing (or even completely wrong), so
I'll try to explain exactly what I mean.

For example, suppose you must do lots of power calculations and you can
guarantee that the x argument to Math.pow(double x, double y) will
always be positive or zero and it will never be infinity. In other
words, no special cases, so you don't need the checks that Math.pow()
provides prior to calling the native doPow() function. My question is:
is it somehow possible to call that native function directly?

StrictMath.pow() is public, and in a "stock" Java it's native.
You can call it directly if you wish, exactly as you'd call any
other public static method.

I don't know what these "checks" you mention might be, nor what
doPow() is. Are you using an alternative non-Sun Java implementation
of some kind?
 
A

Arved Sandstrom

StrictMath.pow() is public, and in a "stock" Java it's native.
You can call it directly if you wish, exactly as you'd call any
other public static method.

I don't know what these "checks" you mention might be, nor what
doPow() is. Are you using an alternative non-Sun Java implementation
of some kind?
I might also add, if one looks at the API for StrictMath, it states
clearly that StrictMath.pow (which as you point out is called directly
and without adornments by Math.pow) is required to have fdlibm
semantics, and specifically the "IEEE 754 core function" definition if
there is more than one definition of a function.

This means that Math.pow semantics are required to be what is achieved
by the implementation in fdlibm's e_pow.c source file. And you'll find
that when you look at this file that it's loaded with special cases...19
of them precisely.

And I wonder how much checking you'll dispense with on any platform with
any math library. Now that I got curious I downloaded the source for
eglibc, which is what Debian/Ubuntu now use, and examined the source for
various permutations of *pow.c (e_powl.c, s_cpow.c, s_cpowf.c,
s_cpowl.c, w_pow.c, w_powf.c, w_powl.c), and there's an expected
(substantial) amount of special case checking in those too.

So if one knew that they could provide certain calling guarantees, _and_
one wanted to call a simplified C pow implementation, it seems to me
that one might extract the appropriate case out of a C math library
source file, and make it available to Java using JNI. I stand to be duly
informed otherwise, but I don't imagine there are other options.

AHS
 
S

Screamin Lord Byron

Thanks. I'll try first with StricMath.pow()

To answer your question, I don't have the source for my actual JDK
(wanted to download it, but seems that java.net is down for
maintenance), so I just inspected this:
http://www.docjar.com/html/api/java/lang/Math.java.html

and, perhaps naively, concluded that this code must be the same as the
one in the Sun's implementation (which I use).

It looks like this:

public static double pow(double x, double y) {
if (x < 0.0 && x != Double.NEGATIVE_INFINITY) {
if (y != Double.NEGATIVE_INFINITY
&& y != Double.POSITIVE_INFINITY) { // is finit
if (y == Math.ceil(y)) { // is integer
double absx = Math.abs(x);
if (y % 2 == 0.0) {
return doPow(absx, y);
}
return -1.0 * doPow(absx, y);
}
return Double.NaN;
}
}
return doPow(x, y);
}

private static native double doPow(double x, double y);


I might also add, if one looks at the API for StrictMath, it states
clearly that StrictMath.pow (which as you point out is called directly
and without adornments by Math.pow) is required to have fdlibm
semantics, and specifically the "IEEE 754 core function" definition if
there is more than one definition of a function.

This means that Math.pow semantics are required to be what is achieved
by the implementation in fdlibm's e_pow.c source file. And you'll find
that when you look at this file that it's loaded with special cases...19
of them precisely.

And I wonder how much checking you'll dispense with on any platform with
any math library. Now that I got curious I downloaded the source for
eglibc, which is what Debian/Ubuntu now use, and examined the source for
various permutations of *pow.c (e_powl.c, s_cpow.c, s_cpowf.c,
s_cpowl.c, w_pow.c, w_powf.c, w_powl.c), and there's an expected
(substantial) amount of special case checking in those too.

So if one knew that they could provide certain calling guarantees, _and_
one wanted to call a simplified C pow implementation, it seems to me
that one might extract the appropriate case out of a C math library
source file, and make it available to Java using JNI. I stand to be duly
informed otherwise, but I don't imagine there are other options.

Those informations are very useful. I'm checking out eglibc source and
will try to do as you suggest. I will then compare the results to Java's
Math and StictMath provided methods to see if this fudging was really
worth the effort at all. Considering the amount of special case checking
it just might be (but with "dragons ahead" disclaimer, of course :) ).

Thanks!
 
E

Eric Sosman

Thanks. I'll try first with StricMath.pow()

To answer your question, I don't have the source for my actual JDK
(wanted to download it, but seems that java.net is down for
maintenance), so I just inspected this:
http://www.docjar.com/html/api/java/lang/Math.java.html

and, perhaps naively, concluded that this code must be the same as the
one in the Sun's implementation (which I use).

It looks like this:

public static double pow(double x, double y) {
if (x< 0.0&& x != Double.NEGATIVE_INFINITY) {
if (y != Double.NEGATIVE_INFINITY
&& y != Double.POSITIVE_INFINITY) { // is finit
if (y == Math.ceil(y)) { // is integer
double absx = Math.abs(x);
if (y % 2 == 0.0) {
return doPow(absx, y);
}
return -1.0 * doPow(absx, y);
}
return Double.NaN;
}
}
return doPow(x, y);
}

With this implementation and under the conditions you describe,
note that the "checks" amount to one count them one comparison.

But it's moot anyhow. The reason that both Math and StrictMath
exist is to allow a trade-off of portability and efficiency. The
StrictMath methods produce bit-for-bit identical results on all Java
implementations (unless there's a bug), while the Math methods are
allowed to be just a little bit sloppy. When you call Math.foo() the
JIT compiler might use the processor's built-in DFOO instruction, even
if a few of the low-order result bits could differ from the StrictMath
"gold standard." The JIT might do this no matter what the supposed
Math.foo() source looks like -- and might do it differently on different
hardware models, and might give different results before and after a
calling method gets JITted, and so on.

With StrictMath the implementation is required to produce the
"statutory" result. Again, it might or might not use something that
looks like the purported source; it can still take liberties, as long
as it gets the right answers.

The rule of thumb, then, is to call Math.foo() when you can deal
with "close to right" answers and would like speed -- you may not *get*
the speed, but at least there's the opportunity. Call StrictMath.foo()
when you need reproducible results, or when you need to rely on the
precise numerical specification, "good to the very last bit."
 
A

Andreas Leitgeb

Eric Sosman said:
The JIT might do this no matter what the supposed
Math.foo() source looks like

You mean, if I were to modify my Java-installation's rt.jar and
replaced Math.class by an April1st-version, which implemented "pow()"
by redirecting to atan2(), then the jit could still change invocations
to the processor's "dpow"-instruction (whatever its actual name) ?
and might give different results before and after a
calling method gets JITted, and so on.

This admittedly surprises me. I was (of course) prepared to expect a
different result from StrictMath, but not a different result possibly
between two iterations of the same loop...

I naively would have expected the non-JIT-compiled version to invoke
the same math-processor opcodes, just maybe wrapped in subroutines,
which the JIT would inline.

(Just trying to make sure I wasn't misunderstanding what you said)
 
E

Eric Sosman

You mean, if I were to modify my Java-installation's rt.jar and
replaced Math.class by an April1st-version, which implemented "pow()"
by redirecting to atan2(), then the jit could still change invocations
to the processor's "dpow"-instruction (whatever its actual name) ?

That's my understanding. Besides, if you've somehow injected
foreign classes into the Java core, you're not running Java any more
but some Java-ish impostor. Java's guarantees therefore no longer
hold, and there's no telling what might happen. (Imagine a similar
redirect of System.out.println() to System.err.printf(), for example.)
This admittedly surprises me. I was (of course) prepared to expect a
different result from StrictMath, but not a different result possibly
between two iterations of the same loop...

I don't know whether this actually occurs, but I don't see anything
in the java.lang.Math Javadoc that forbids it. And it's certainly a
plausible scenario: Interpret the byte code for the first N iterations,
then get JITted to a hardware instruction with slightly different
behavior -- and then maybe get un-JITted when a new class is loaded
and the method can't be inlined quite so easily ...

Perhaps there's something in the JLS or JVMS that nails things down
more precisely; I haven't looked.
I naively would have expected the non-JIT-compiled version to invoke
the same math-processor opcodes, just maybe wrapped in subroutines,
which the JIT would inline.

(Just trying to make sure I wasn't misunderstanding what you said)

You've understood me correctly. Whether I myself am correct is
a different question! ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top