summaryrefslogtreecommitdiffstats
path: root/src/include/math.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/math.h')
-rw-r--r--src/include/math.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/include/math.h b/src/include/math.h
new file mode 100644
index 0000000..dc7b197
--- /dev/null
+++ b/src/include/math.h
@@ -0,0 +1,161 @@
+#pragma once
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Various miscellaneous utility functions
+ *
+ * @file src/lib/util/misc.h
+ *
+ * @copyright 2000,2006 The FreeRADIUS server project
+ */
+RCSIDH(math_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+/** Find the highest order high bit in an unsigned 64 bit integer
+ *
+ * @return 0-64 indicating the position of the highest bit,
+ * with 0 indicating no high bits, 1 indicating the 1st
+ * bit and 64 indicating the last bit.
+ */
+static inline uint8_t fr_high_bit_pos(uint64_t num)
+{
+ if (num == 0) return 0; /* num being zero is undefined behaviour for __builtin_clzll */
+
+#ifdef HAVE_BUILTIN_CLZLL
+ return (64 - __builtin_clzll(num));
+#else
+ uint8_t ret = 1;
+ while (num >>= 1) ret++;
+ return ret;
+#endif
+}
+
+/** Find the lowest order high bit in an unsigned 64 bit integer
+ *
+ * @return 0-64 indicating the position of the lowest bit,
+ * with 0 indicating no high bits, 1 indicating the 1st
+ * bit and 64 indicating the last bit.
+ */
+static inline uint8_t fr_low_bit_pos(uint64_t num)
+{
+ if (num == 0) return 0;
+
+#ifdef HAVE_BUILTIN_CLZLL
+ return __builtin_ctzll(num) + 1;
+#else
+ uint8_t ret = 1;
+
+ do {
+ if (num & 0x01) break;
+ ret++;
+ } while (num >>= 1);
+
+ return ret;
+#endif
+}
+
+/** Efficient calculation of log10 of a unsigned 64bit integer
+ *
+ * @param[in] num to calculate log10 of.
+ * @return log10 of the integer
+ */
+static inline uint8_t fr_log10(uint64_t num)
+{
+ static uint64_t const pow_of_10[] =
+ {
+ 1ULL,
+ 10ULL,
+ 100ULL,
+ 1000ULL,
+ 10000ULL,
+ 100000ULL,
+ 1000000ULL,
+ 10000000ULL,
+ 100000000ULL,
+ 1000000000ULL,
+ 10000000000ULL,
+ 100000000000ULL,
+ 1000000000000ULL,
+ 10000000000000ULL,
+ 100000000000000ULL,
+ 1000000000000000ULL,
+ 10000000000000000ULL,
+ 100000000000000000ULL,
+ 1000000000000000000ULL,
+ 10000000000000000000ULL
+ };
+ uint64_t tmp;
+
+ tmp = (fr_high_bit_pos(num) * 1233) >> 12;
+ return tmp - (num < pow_of_10[tmp]);
+}
+
+/** Multiplies two integers together
+ *
+ * @param[in] _out Where to store the result.
+ * @param[in] _a first argument to multiply.
+ * @param[in] _b second argument to multiply.
+ * @return
+ * - false on overflow.
+ * - true if there was no overflow.
+ */
+#define fr_multiply(_out, _a, _b) !__builtin_mul_overflow(_a, _b, _out)
+
+/** Adds two integers
+ *
+ * @param[in] _out Where to store the result.
+ * @param[in] _a first argument to add.
+ * @param[in] _b second argument to add.
+ * @return
+ * - false on overflow.
+ * - true if there was no overflow.
+ */
+#define fr_add(_out, _a, _b) !__builtin_add_overflow(_a, _b, _out)
+
+/** Subtracts two integers
+ *
+ * @param[in] _out Where to store the result.
+ * @param[in] _a first argument to subtract.
+ * @param[in] _b second argument to subtract.
+ * @return
+ * - false on overflow.
+ * - true if there was no overflow.
+ */
+#define fr_sub(_out, _a, _b) !__builtin_sub_overflow(_a, _b, _out)
+
+/** Round up - Only works if _mul is a power of 2 but avoids division
+ */
+#define ROUND_UP_POW2(_num, _mul) (((_num) + ((_mul) - 1)) & ~((_mul) - 1))
+
+/** Round up - Works in all cases, but is slower
+ */
+#define ROUND_UP(_num, _mul) (((((_num) + ((_mul) - 1))) / (_mul)) * (_mul))
+
+/** Get the ceiling value of integer division
+ *
+ */
+#define ROUND_UP_DIV(_x, _y) (1 + (((_x) - 1) / (_y)))
+
+#ifdef __cplusplus
+}
+#endif