Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is floating point expression contraction allowed in C++?

Floating point expressions can sometimes be contracted on the processing hardware, e.g. using fused multiply-and-add as a single hardware operation.

Apparently, using these this isn't merely an implementation detail but governed by programming language specification. Specifically, the C89 standard does not allow such contractions, while in C99 they are allowed provided that some macro is defined. See details in this SO answer.

But what about C++? Are floating-point contractions not allowed? Allowed in some standards? Allowed universally?

like image 363
einpoklum Avatar asked Mar 14 '18 12:03

einpoklum


People also ask

What is a positive floating point constant in C?

Floating-point constants are positive unless they are preceded by a minus sign ( - ). In this case, the minus sign is treated as a unary arithmetic negation operator. Floating-point constants have type float, double, or long double. A floating-point constant without an f, F, l, or L suffix has type double.

How do you contract a floating point expression?

Show activity on this post. Floating point expressions can sometimes be contracted on the processing hardware, e.g. using fused multiply-and-add as a single hardware operation. Apparently, using these this isn't merely an implementation detail but governed by programming language specification.

What are floating-point types in C programming?

Floating-point types in C support most of the same arithmetic and relational operators as integer types; x > y, x / y, x + y all make sense when x and y are float s.

How do floating expressions change the types of floating expressions?

The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby.


2 Answers

Summary

Contractions are permitted, but a facility is provided for the user to disable them. Unclear language in the standard clouds the issue of whether disabling them will provide desired results.

I investigated this in the official C++ 2003 standard and the 2017 n4659 draft. C++ citations are from 2003 unless otherwise indicated.

Extra Precision and Range

The text “contract” does not appear in either document. However, clause 5 Expressions [expr] paragraph 10 (same text in 2017’s 8 [expr] 13) says:

The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby.

I would prefer this statement explicitly stated whether this extra precision and range could be used freely (the implementation may use it in some expressions, including subexpressions, while not using it in others) or had to be used uniformly (if the implementation uses extra precision, it must use it in every floating-point expression) or according to some other rules (such as it may use one precision for float, another for double).

If we interpret it permissively, it means that, in a*b+c, a*b could be evaluated with infinite precision and range, and then the addition could be evaluated with whatever precision and range is normal for the implementation. This is mathematically equivalent to contraction, as it has the same result as evaluating a*b+c with a fused multiply-add instruction.

Hence, with this interpretation, implementations may contract expressions.

Contractions Inherited From C

17.4.1.2 [lib.headers] 3 (similar text in 2017’s 20.5.1.2 [headers] 3) says:

The facilities of the Standard C Library are provided in 18 additional headers, as shown in Table 12…

Table 12 includes <cmath>, and paragraph 4 indicates this corresponds to math.h. Technically, the C++ 2003 standard refers to the C 1990 standard, but I do not have it in electronic form and do not know where my paper copy is, so I will use the C 2011 standard (but unofficial draft N1570), which the C++ 2017 draft refers to.

The C standard defines, in <math.h>, a pragma FP_CONTRACT:

#pragma STDC FP_CONTRACT on-off-switch

where on-off-switch is on to allow contraction of expressions or off to disallow them. It also says the default state for the pragma is implementation-defined.

The C++ standard does not define “facility” or “facilities.” A dictionary definition of “facility” is “a place, amenity, or piece of equipment provided for a particular purpose” (New Oxford American Dictionary, Apple Dictionary application version 2.2.2 (203)). An amenity is “a desirable or useful feature or facility of a building or place.” A pragma is a useful feature provided for a particular purpose, so it seems to be a facility, so it is included in <cmath>.

Hence, using this pragma should permit or disallow contractions.

Conclusions

  • Contractions are permitted when FP_CONTRACT is on, and it may be on by default.

  • The text of 8 [expr] 13 can be interpreted to effectively allow contractions even if FP_CONTRACT is off but is insufficiently clear for definitive interpretation.

like image 88
Eric Postpischil Avatar answered Sep 20 '22 17:09

Eric Postpischil


Yes, it is allowed.

For example in Visual Studio Compiler, by default, fp_contract is on. This tells the compiler to use floating-point contraction instructions where possible. Set fp_contract to off to preserve individual floating-point instructions.

// pragma_directive_fp_contract.cpp
// on x86 and x64 compile with: /O2 /fp:fast /arch:AVX2
// other platforms compile with: /O2

#include <stdio.h>

// remove the following line to enable FP contractions
#pragma fp_contract (off)

int main() {
   double z, b, t;

   for (int i = 0; i < 10; i++) {
      b = i * 5.5;
      t = i * 56.025;

      z = t * i + b;
      printf("out = %.15e\n", z);
   }
}

Detailed information about Specify Floating-Point Behavior.

Using the GNU Compiler Collection (GCC):

The default state for the FP_CONTRACT pragma (C99 and C11 7.12.2). This pragma is not implemented. Expressions are currently only contracted if -ffp-contract=fast, -funsafe-math-optimizations or -ffast-math are used.

like image 34
Smit Ycyken Avatar answered Sep 22 '22 17:09

Smit Ycyken