Fix uses of std::nextafter on Android
authorMarcus Holland-Moritz <mhx@fb.com>
Fri, 24 Jun 2016 18:23:42 +0000 (11:23 -0700)
committerFacebook Github Bot 8 <facebook-github-bot-8-bot@fb.com>
Fri, 24 Jun 2016 18:38:26 +0000 (11:38 -0700)
Summary:
On Android, std::nextafter isn't implemented. However, the C functions and
compiler builtins are still provided.

This change adds a portability abstraction as folly::nextafter.

Reviewed By: mzlee, yfeldblum

Differential Revision: D3478081

fbshipit-source-id: 54fec1ca8bdec24ba45d51e07020259fdbae61b4

folly/Conv.h
folly/Makefile.am
folly/portability/Math.h [new file with mode: 0644]

index 08628a0e44018b943f0a07cfa59f739d8281dc68..8c03e28f47f5ae4450a67fa8e7725ab433342173 100644 (file)
@@ -41,6 +41,7 @@
 #include <folly/Likely.h>
 #include <folly/Preprocessor.h>
 #include <folly/Range.h>
+#include <folly/portability/Math.h>
 
 #define FOLLY_RANGE_CHECK_STRINGIZE(x) #x
 #define FOLLY_RANGE_CHECK_STRINGIZE2(x) FOLLY_RANGE_CHECK_STRINGIZE(x)
@@ -1172,7 +1173,7 @@ checkConversion(const Src& value) {
     if (value > tgtMaxAsSrc) {
       return false;
     }
-    const Src mmax = std::nextafter(tgtMaxAsSrc, Src());
+    const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
     if (static_cast<Tgt>(value - mmax) >
         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
       return false;
@@ -1181,7 +1182,7 @@ checkConversion(const Src& value) {
     if (value < tgtMinAsSrc) {
       return false;
     }
-    const Src mmin = std::nextafter(tgtMinAsSrc, Src());
+    const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
     if (static_cast<Tgt>(value - mmin) <
         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
       return false;
index 08ce2f23a30d1b23e3a9d94bfb447058e3501caf..212c0a170e677aac11e64b730de7b082bc9d5b32 100644 (file)
@@ -257,6 +257,7 @@ nobase_follyinclude_HEADERS = \
        portability/IOVec.h \
        portability/Libgen.h \
        portability/Malloc.h \
+       portability/Math.h \
        portability/Memory.h \
        portability/PThread.h \
        portability/Sockets.h \
diff --git a/folly/portability/Math.h b/folly/portability/Math.h
new file mode 100644 (file)
index 0000000..c9bdd51
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cmath>
+
+namespace folly {
+
+#ifndef __ANDROID__
+
+/**
+ * Most platforms hopefully provide std::nextafter.
+ */
+
+/* using override */ using std::nextafter;
+
+#else // !__ANDROID__
+
+/**
+ * On Android, std::nextafter isn't implemented. However, the C functions and
+ * compiler builtins are still provided. Using the GCC builtin is actually
+ * slightly faster, as they're constexpr and the use cases within folly are in
+ * constexpr context.
+ */
+
+#if defined(__GNUC__) && !defined(__clang__)
+
+constexpr float nextafter(float x, float y) {
+  return __builtin_nextafterf(x, y);
+}
+
+constexpr double nextafter(double x, double y) {
+  return __builtin_nextafter(x, y);
+}
+
+constexpr long double nextafter(long double x, long double y) {
+  return __builtin_nextafterl(x, y);
+}
+
+#else // __GNUC__
+
+inline float nextafter(float x, float y) {
+  return ::nextafterf(x, y);
+}
+
+inline double nextafter(double x, double y) {
+  return ::nextafter(x, y);
+}
+
+inline long double nextafter(long double x, long double y) {
+  return ::nextafterl(x, y);
+}
+
+#endif // __GNUC__
+
+#endif // __ANDROID__
+}