diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc
index b7b54e21a9b63b3854fdbd27849b1f3b23c7f321..e9951eaa09412f152d9c30eae7fcb55f862cfb7d 100644
--- a/src/box/tuple_compare.cc
+++ b/src/box/tuple_compare.cc
@@ -90,8 +90,6 @@ static enum mp_class mp_classes[] = {
 	/* .MP_BIN     = */ MP_CLASS_BIN
 };
 
-#define COMPARE_RESULT(a, b) (a < b ? -1 : a > b)
-
 static enum mp_class
 mp_classof(enum mp_type type)
 {
@@ -137,77 +135,6 @@ mp_compare_integer_with_type(const char *field_a, enum mp_type a_type,
 	}
 }
 
-#define EXP2_53 9007199254740992.0      /* 2.0 ^ 53 */
-#define EXP2_64 1.8446744073709552e+19  /* 2.0 ^ 64 */
-
-/*
- * Compare LHS with RHS, return a value <0, 0 or >0 depending on the
- * comparison result (strcmp-style).
- * Normally, K==1. If K==-1, the result is inverted (as if LHS and RHS
- * were swapped).
- * K is needed to enable tail call optimization in Release build.
- * NOINLINE attribute was added to avoid aggressive inlining which
- * resulted in over 2Kb code size for mp_compare_number.
- */
-NOINLINE static int
-mp_compare_double_uint64(double lhs, uint64_t rhs, int k)
-{
-	assert(k==1 || k==-1);
-	/*
-	 * IEEE double represents 2^N precisely.
-	 * The value below is 2^53.  If a double exceeds this threshold,
-	 * there's no fractional part. Moreover, the "next" float is
-	 * 2^53+2, i.e. there's not enough precision to encode even some
-	 * "odd" integers.
-	 * Note: ">=" is important, see next block.
-	 */
-	if (lhs >= EXP2_53) {
-		/*
-		 * The value below is 2^64.
-		 * Note: UINT64_MAX is 2^64-1, hence ">="
-		 */
-		if (lhs >= EXP2_64)
-			return k;
-		/* Within [2^53, 2^64) double->uint64_t is lossless. */
-		assert((double)(uint64_t)lhs == lhs);
-		return k*COMPARE_RESULT((uint64_t)lhs, rhs);
-	}
-	/*
-	 * According to the IEEE 754 the double format is the
-	 * following:
-	 * +------+----------+----------+
-	 * | sign | exponent | fraction |
-	 * +------+----------+----------+
-	 *  1 bit    11 bits    52 bits
-	 * If the exponent is 0x7FF, the value is a special one.
-	 * Special value can be NaN, +inf and -inf.
-	 * If the fraction == 0, the value is inf. Sign depends on
-	 * the sign bit.
-	 * If the first bit of the fraction is 1, the value is the
-	 * quiet NaN, else the signaling NaN.
-	 */
-	if (!isnan(lhs)) {
-		/*
-		 * lhs is a number or inf.
-		 * If RHS < 2^53, uint64_t->double is lossless.
-		 * Otherwize the value may get rounded.	 It's
-		 * unspecified whether it gets rounded up or down,
-		 * i.e. the conversion may yield 2^53 for a
-		 * RHS > 2^53. Since we've aready ensured that
-		 * LHS < 2^53, the result is still correct even if
-		 * rounding happens.
-		 */
-		assert(lhs < EXP2_53);
-		assert((uint64_t)(double)rhs == rhs || rhs > (uint64_t)EXP2_53);
-		return k*COMPARE_RESULT(lhs, (double)rhs);
-	}
-	/*
-	 * Lhs is NaN. We assume all NaNs to be less than any
-	 * number.
-	 */
-	return -k;
-}
-
 static int
 mp_compare_double_any_int(double lhs, const char *rhs, enum mp_type rhs_type,
 			  int k)
@@ -215,13 +142,12 @@ mp_compare_double_any_int(double lhs, const char *rhs, enum mp_type rhs_type,
 	if (rhs_type == MP_INT) {
 		int64_t v = mp_decode_int(&rhs);
 		if (v < 0) {
-			return mp_compare_double_uint64(-lhs, (uint64_t)-v,
-							-k);
+			return double_compare_uint64(-lhs, (uint64_t)-v, -k);
 		}
-		return mp_compare_double_uint64(lhs, (uint64_t)v, k);
+		return double_compare_uint64(lhs, (uint64_t)v, k);
 	}
 	assert(rhs_type == MP_UINT);
-	return mp_compare_double_uint64(lhs, mp_decode_uint(&rhs), k);
+	return double_compare_uint64(lhs, mp_decode_uint(&rhs), k);
 }
 
 static int
diff --git a/src/lib/core/util.c b/src/lib/core/util.c
index 4ca99e177e2c0281dd32ab2c6bcddc59c3789375..ffa1d2b516dc8ee0bb0a7a3afe5d904c57b5212c 100644
--- a/src/lib/core/util.c
+++ b/src/lib/core/util.c
@@ -30,6 +30,7 @@
  */
 #include "trivia/util.h"
 
+#include <math.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -324,3 +325,65 @@ fpconv_check()
 	 */
 	assert(buf[1] == '.');
 }
+
+#define EXP2_53 9007199254740992.0      /* 2.0 ^ 53 */
+#define EXP2_64 1.8446744073709552e+19  /* 2.0 ^ 64 */
+
+int
+double_compare_uint64(double lhs, uint64_t rhs, int k)
+{
+	assert(k==1 || k==-1);
+	/*
+	 * IEEE double represents 2^N precisely.
+	 * The value below is 2^53.  If a double exceeds this threshold,
+	 * there's no fractional part. Moreover, the "next" float is
+	 * 2^53+2, i.e. there's not enough precision to encode even some
+	 * "odd" integers.
+	 * Note: ">=" is important, see next block.
+	 */
+	if (lhs >= EXP2_53) {
+		/*
+		 * The value below is 2^64.
+		 * Note: UINT64_MAX is 2^64-1, hence ">="
+		 */
+		if (lhs >= EXP2_64)
+			return k;
+		/* Within [2^53, 2^64) double->uint64_t is lossless. */
+		assert((double)(uint64_t)lhs == lhs);
+		return k*COMPARE_RESULT((uint64_t)lhs, rhs);
+	}
+	/*
+	 * According to the IEEE 754 the double format is the
+	 * following:
+	 * +------+----------+----------+
+	 * | sign | exponent | fraction |
+	 * +------+----------+----------+
+	 *  1 bit    11 bits    52 bits
+	 * If the exponent is 0x7FF, the value is a special one.
+	 * Special value can be NaN, +inf and -inf.
+	 * If the fraction == 0, the value is inf. Sign depends on
+	 * the sign bit.
+	 * If the first bit of the fraction is 1, the value is the
+	 * quiet NaN, else the signaling NaN.
+	 */
+	if (!isnan(lhs)) {
+		/*
+		 * lhs is a number or inf.
+		 * If RHS < 2^53, uint64_t->double is lossless.
+		 * Otherwize the value may get rounded.	 It's
+		 * unspecified whether it gets rounded up or down,
+		 * i.e. the conversion may yield 2^53 for a
+		 * RHS > 2^53. Since we've aready ensured that
+		 * LHS < 2^53, the result is still correct even if
+		 * rounding happens.
+		 */
+		assert(lhs < EXP2_53);
+		assert((uint64_t)(double)rhs == rhs || rhs > (uint64_t)EXP2_53);
+		return k*COMPARE_RESULT(lhs, (double)rhs);
+	}
+	/*
+	 * Lhs is NaN. We assume all NaNs to be less than any
+	 * number.
+	 */
+	return -k;
+}
diff --git a/src/trivia/util.h b/src/trivia/util.h
index 1e01013dbff9902c5d354d4d38735bdd3e960803..8a3d22b38d1e13fe09dae60b2af1d4779cb0ae07 100644
--- a/src/trivia/util.h
+++ b/src/trivia/util.h
@@ -500,6 +500,18 @@ json_escape(char *buf, int size, const char *data);
 	}									\
 } while(0)
 
+#define COMPARE_RESULT(a, b) (a < b ? -1 : a > b)
+
+/**
+ * Compare LHS with RHS, return a value <0, 0 or >0 depending on the
+ * comparison result (strcmp-style).
+ * Normally, K==1. If K==-1, the result is inverted (as if LHS and RHS
+ * were swapped).
+ * K is needed to enable tail call optimization in Release build.
+ */
+int
+double_compare_uint64(double lhs, uint64_t rhs, int k);
+
 #if !defined(__cplusplus) && !defined(static_assert)
 # define static_assert _Static_assert
 #endif