| // Copyright 2015 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| // Author: ericv@google.com (Eric Veach) |
| |
| #ifndef S2__FPCONTRACTOFF_H_ |
| #define S2__FPCONTRACTOFF_H_ |
| |
| // Turn off the fused multiply-add optimization ("fp-contract"). With |
| // fp-contract on, any expression of the form "a * b + c" has two possible |
| // results, and the compiler is free to choose either of them. Effectively |
| // this makes it impossible to write deterministic functions that involve |
| // floating-point math. |
| // |
| // S2 requires deterministic arithmetic for correctness. We need to turn off |
| // fp-contract for the entire compilation unit, because S2 has public inline |
| // functions, and the optimization is controlled by the setting in effect when |
| // inline functions are instantiated (not when they are defined). |
| // |
| // Note that there is a standard C pragma to turn off FP contraction: |
| // #pragma STDC FP_CONTRACT OFF |
| // but it is not implemented in GCC because the standard pragma allows control |
| // at the level of compound statements rather than entire functions. |
| // |
| // This file may be included with other files in any order, as long as it |
| // appears before the first non-inline function definition. It is |
| // named with an underscore so that it is included first among the S2 headers. |
| |
| // TODO(compiler-team): Figure out how to do this in a portable way. |
| #if defined(HAVE_ARMEABI_V7A) |
| // Some android builds use a buggy compiler that runs out of memory while |
| // parsing the pragma (--cpu=armeabi-v7a). |
| |
| #elif defined(ANDROID) |
| // Other android builds use a buggy compiler that crashes with an internal |
| // error (Android NDK R9). |
| |
| #elif defined(__clang__) |
| // Clang supports the standard C++ pragma for turning off this optimization. |
| #pragma STDC FP_CONTRACT OFF |
| |
| #elif defined(__GNUC__) |
| // GCC defines its own pragma that operates at the function level rather than |
| // the statement level. |
| #pragma GCC optimize("fp-contract=off") |
| #endif |
| |
| #endif // S2__FPCONTRACTOFF_H_ |