4

How does Java find sine and cosine? I’m working on trying to make a game that is a simple platformer something like super Mario or Castlevania. I attempted to make a method that would rotate an image for me and then resize the JLabel to fit that image. I found an algorithm that worked and was able to accomplish my goal. However all I did was copy and past the algorithm any one can do that I want to understand the math behind it. So far I have figured everything out except one part. The methods sin and cos in the math class. They work and I can use them but I have no idea how Java get its numbers.

It would seem there is more then one way to solve this problem. For now I’m interested in how Java does it. I looked into the Taylor series but I’m not sure that is how java does it. But if Java does use the Taylor series I would like to know how that algorithm is right all the time (I am aware that it is an approximation). I’ve also heard of the CORDIC algorithm but I don’t know much about it as I do with the Taylor series which I have programmed into Java even though I don’t understand it. If CORDIC is how it's done, I would like to know how that algorithm is always right. It would seem it is also possible that the Java methods are system dependent meaning that the algorithm or code used would differ from system to system. If the methods are system dependent then I would like to know how Windows gets sine and cosine. However if it is the CPU itself that gets the answer I would like to know what algorithm it is using (I run an AMD Turion II Dual-Core Mobile M520 2.29GHz).

I have looked at the score code of the Math class and it points to the StrictMath class. However the StrictMath class only has a comment inside it no code. I have noticed though that the method does use the keyword native. A quick Google search suggest that this keyword enables java to work with other languages and systems supporting the idea that the methods are system dependent. I have looked at the java api for the StrictMath class (http://docs.oracle.com/javase/7/docs/api/java/lang/StrictMath.html) and it mentions something called fdlimb. The link is broken but I was able to Google it (http://www.netlib.org/fdlibm/).

It seems to be some sort of package written in C. while I know Java I have never learned C so I have been having trouble deciphering it. I started looking up some info about the C language in the hopes of getting to bottom of this but it a slow process. Of cores even if did know C I still don’t know what C file Java is using. There seems to be different version of the c methods for different systems and I can’t tell which one is being used. The API suggest it is the "IEEE 754 core function" version (residing in a file whose name begins with the letter e). But I see no sin method in the e files. I have found one that starts with a k which I think is sort for kernel and another that starts with an s which I think is sort for standard. The only e files I found that look similar to sin are e_sinh.c and e_asin.c which I think are different math functions. And that’s the story of my quest to fiend the Java algorithms for sine and cosine.

Somewhere at some point in the line an algorithm is being called upon to get these numbers and I want to know what it is and why it works(there is no way java just gets these numbers out of thin air).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user3491432
  • 91
  • 2
  • 7
  • 7
    there are assembly instructions for sine and cosine. java uses these. on x86 they are called FSIN, FCOS, and FSINCOS – Steve Cox Apr 02 '14 at 22:24
  • 1
    @SteveCox Actually, there's no obligation for Java (especially ME) to use such instructions, as embedded devices may have processors/microcontrollers that lack them, and not all JVMs will use them, even if they exist. – nanofarad Apr 02 '14 at 22:25
  • of course there is no obligation. any vm can implement java however they want. this is how the x86 vm's do it. if you are actually using java for an embedded device, i'd like to point you to https://xkcd.com/801/ – Steve Cox Apr 02 '14 at 22:26
  • 3
    http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions http://stackoverflow.com/questions/1252929/assembly-code-for-sinx – assylias Apr 02 '14 at 22:27
  • 1
    When `StrictMath` is used, the JVM probably can't use the machine instructions unless there's been some verification that they return the same results as the "fdlibm" algorithm in all cases. (Don't ask me how they would verify this.) – ajb Apr 02 '14 at 22:33
  • The do it the same way they do it [in C.](http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions?rq=1) – Hot Licks Apr 02 '14 at 23:17
  • @SteveCox It is actually unlikely that Java uses FSIN and FCOS on x86 because there are software implementations that are more accurate. glibc on Linux used to use FSIN and FCOS but they recently added a software implementation that is perfectly accurate. See this blog post I wrote for some details: https://randomascii.wordpress.com/2014/10/09/intel-underestimates-error-bounds-by-1-3-quintillion/ – Bruce Dawson Jun 18 '15 at 14:39

1 Answers1

3

The JDK is not obligated to compute sine and cosine on its own, only to provide you with an interface to some implementation via Math. So the simple answer to your question is: It doesn't; it asks something else to do it, and that something else is platform/JDK/JVM dependent.

All JDKs that I know of pass the burden off to some native code. In your case, you came across a reference to fdlibm, and you'll just have to suck it up and learn to read that code if you want to see the actual implementation there.

Some JVMs can optimize this. I believe HotSpot has the ability to spot Math.cos(), etc. calls and throw in a hardware instruction on systems where it is available, but do not quote me on that.

From the documentation for Math:

By default many of the Math methods simply call the equivalent method in StrictMath for their implementation. Code generators are encouraged to use platform-specific native libraries or microprocessor instructions, where available, to provide higher-performance implementations of Math methods. Such higher-performance implementations still must conform to the specification for Math.

The documentation for StrictMath actually mentions fdlibm (it places the constraint on StrictMath that all functions must produce the same results that fdlibm produces):

To help ensure portability of Java programs, the definitions of some of the numeric functions in this package require that they produce the same results as certain published algorithms. These algorithms are available from the well-known network library netlib as the package "Freely Distributable Math Library," fdlibm. These algorithms, which are written in the C programming language, are then to be understood as executed with all floating-point operations following the rules of Java floating-point arithmetic.

Note, however, that Math is not required to defer to StrictMath. Use StrictMath explicitly in your code if you want to guarantee consistent results across all platforms. Note also that this implies that code generators (e.g. HotSpot) are not given the freedom to optimize StrictMath calls to hardware calls unless the hardware would produce exactly the same results as fdlibm.

In any case, again, Java doesn't have to implement these on its own (it usually doesn't), and this question doesn't have a definitive answer. It depends on the platform, the JDK, and in some cases, the JVM.

As for general computational techniques, there are many; here is a potentially good starting point. C implementations are generally easy to come by. You'll have to search through hardware datasheets and documentation if you want to find out more about the hardware options available on a specific platform (if Java is even using them on that platform).

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • What is a CRT? Not familiar with that acronym. – G. Bach Apr 02 '14 at 22:55
  • @G.Bach The [C Runtime library](https://www.google.com/search?q=c+runtime+library) (e.g. in this context, the `cos()` you get from `math.h`). It frequently (but definitely not always) serves as the basis for most applications that don't explicitly use other methods. Although, given `StrictMath`s `fdlibm` restriction, and the fact that `Math` most often seems to default to `StrictMath`, I guess its unlikely that CRT `cos()` would be used in practice unless its on a system where its implementation is guaranteed to match `fdlibm`'s. – Jason C Apr 02 '14 at 22:58