3

Is there any sort of guarantee - either in the C++ standard or in some other document - that C++ code computing cos(x) will produce identical values when compiled with g++, clang, MSVC, etc., assuming those implementations are using IEEE-754 64-bit doubles and the input value x is exactly equal? My assumption is "yes," but I'd like to confirm that before relying on this behavior.

Context: I'm teaching a course in which students may need to compute trigonometric functions of inputs. I can assure that those inputs are identical when fed into the functions. I'm aware that equality-testing doubles is not a good idea, but in this specific case I was wondering if it was safe to do so.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Why not try it yourself? – Just another Java programmer Sep 29 '21 at 16:58
  • 4
    @JustanotherJavaprogrammer Please note that the OP is asking for *"guarantee - either in the C++ standard or in some other document"* not for some (limited) anecdotal evidences. – Bob__ Sep 29 '21 at 17:02
  • This [answer](https://stackoverflow.com/questions/20137105/c-sqrt-function-precision-for-full-squares/20137304#20137304) implies that *"An implementation conforming to the IEEE-754 standard on allowed errors for basic operations [...] requires that values be correctly rounded. This means that the error will less than 1/2 ULP (unit in the last place) or basically as close as possible to the actual answer. [...] Note: this is not guaranteed by the C++ standard but by the IEEE-754 standard*. You may want to check IEEE-754 documentation. – Bob__ Sep 29 '21 at 17:08
  • Maybe a duplicate (mutatis mutandis) of https://stackoverflow.com/questions/22259537/guaranteed-precision-of-sqrt-function-in-c-c – Bob__ Sep 29 '21 at 17:14
  • 2
    @Bob__: But that only applies to "basic operations" and not to trig functions. – Ben Voigt Sep 29 '21 at 18:02
  • @Bob__ Thanks for surfacing that one! Surprisingly, looks like the answer here is different than for the linked question. – templatetypedef Sep 29 '21 at 18:11
  • FYI, the IEEE-754 committee voted for a lesser specification than “correctly rounded” for these functions. It was changed after the final committee draft, in the IEEE balloting process, without committee involvement (although individual members of the committee may have been involved). Nobody has implemented all of the transcendental functions with both correct rounding and known-bounded execution time, so the standard recommends a practice that does not exist. – Eric Postpischil Sep 29 '21 at 20:27
  • In the context of teaching students, the theoretical goal of the standard is irrelevant. The ordinary libraries they will be using—the GNU C Library, Apple’s, and Microsoft’s—do not provide results identical to each other, let alone correctly rounded. (If you use Apple’s `cos`, you will be using mine, and I guarantee it is not correctly rounded. Results may be off by several ULP.) – Eric Postpischil Sep 29 '21 at 20:31
  • @EricPostpischil- Oh, I definitely wouldn’t tell students to do this. :-) This would be for the backend autograder that evaluates student work. I figured that if I could check for bitwise equality it would be a lot easier to code up than if I needed to check for an answer within some epsilon of accurate. :-) – templatetypedef Sep 30 '21 at 02:19

1 Answers1

6

cos is a transcendental function. Transcendental functions are subject to the table-maker's dilemma. Informally, what this means is: let's say you come up with some iterative algorithm for approximating the cosine of an input value: for example, a Taylor series. When you run this iterative algorithm, you have to decide how much extra precision to keep at the intermediate stages (rounding too early may reduce the accuracy of the final result). But because the function is transcendental, it's very difficult to determine how many extra bits must be carried during the calculation in order to yield a correctly rounded final result, and for some input values, the number of extra bits required might be very large.

For this reason, it is generally not practical to design hardware that guarantees correctly rounded results for transcendental functions such as cos (where "correctly rounded" means that the resulting floating point value is the one that's closest to the true real value of the function). Instead, the hardware designers will implement a calculation technique that performs reasonably well and that, for most practical input values, will yield a result that is within 1 bit of the exact real result. (If you absolutely need a cosine function that always yields a correctly rounded result, then apparently it's possible to implement one: GNU MPFR claims to have done it. But this will perform much worse than hardware.)

IEEE 754 (2008) lists cos as one of the "recommended correctly rounded functions", which means that if you implement IEEE 754's version of cos, then you have to yield a correctly rounded result. But these functions are only "recommended" to be provided, and not required. Therefore, a conforming implementation of IEEE 754 might not provide a correctly rounded cos function, and might instead provide a "practical" cos function as described in the previous paragraph. Therefore, in practice, two implementations of C++ which both claim to be IEEE 754 compliant may not yield the exact same value for a transcendental function such as cos when applied to the same argument.

(Note that IEEE 754 requires implementations to provide a square root function that is correctly rounded. This is not a transcendental function, so correctly rounding it is not nearly as difficult.)

cigien
  • 57,834
  • 11
  • 73
  • 112
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • You already answered OP's question but for completeness, does IEEE-754 state maximum error bounds for these functions in addition to the "recommended" bound of 0.5 ULP which would apply to practical-not-recommended implementations in order to be considered conformant? Or is the "practical" approach to say "we don't provide a IEEE-754 `cos()`, but that function is optional so we still have IEEE-754 conformance" ? – Ben Voigt Sep 29 '21 at 18:07
  • @BenVoigt I don't think IEEE 754 has a maximum error bound. Looking at it again, I see the wording "the preferred quantum is language-defined", and I'm not sure what that means. Maybe it means that the function conforms to IEEE 754 if there's any stated guaranteed bound (by the implementation)? I'm not sure. – Brian Bi Sep 29 '21 at 18:27
  • @BrianBi: The “preferred quantum” alludes to the fact that numbers may have multiple representations in decimal floating-point formats (e.g., 1.230•10^5 and 12.3•10^4), and those representations differ in the exponent and hence have a different ULP, a.k.a. the quantum. – Eric Postpischil Sep 29 '21 at 20:35
  • @EricPostpischil Thanks for the clarification. I don't know what that has to do with specific functions like cos, but it does seem like it's not saying that implementations have to document the error bound. – Brian Bi Sep 29 '21 at 20:47