commit 4f71509b3fa283cf7564fa31f64da9c03bf36c2e
parent 2cbc26b44bf11e8416a40ca39366d42ef53ae1f3
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date: Wed, 9 Nov 2016 10:34:13 +0300
Refactor operators.hpp
Diffstat:
5 files changed, 268 insertions(+), 197 deletions(-)
diff --git a/include/kfr/base.hpp b/include/kfr/base.hpp
@@ -35,6 +35,7 @@
#include "base/function.hpp"
#include "base/gamma.hpp"
#include "base/generators.hpp"
+#include "base/horizontal.hpp"
#include "base/hyperbolic.hpp"
#include "base/log_exp.hpp"
#include "base/logical.hpp"
diff --git a/include/kfr/base/bitwise.hpp b/include/kfr/base/bitwise.hpp
@@ -0,0 +1,136 @@
+/** @addtogroup math
+ * @{
+ */
+/*
+ Copyright (C) 2016 D Levin (https://www.kfrlib.com)
+ This file is part of KFR
+
+ KFR is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ KFR 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with KFR.
+
+ If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
+ Buying a commercial license is mandatory as soon as you develop commercial activities without
+ disclosing the source code of your own applications.
+ See https://www.kfrlib.com for details.
+ */
+#pragma once
+
+#include "constants.hpp"
+#include "vec.hpp"
+
+namespace kfr
+{
+
+CMT_INLINE float bitwisenot(float x) { return fbitcast(~ubitcast(x)); }
+CMT_INLINE float bitwiseor(float x, float y) { return fbitcast(ubitcast(x) | ubitcast(y)); }
+CMT_INLINE float bitwiseand(float x, float y) { return fbitcast(ubitcast(x) & ubitcast(y)); }
+CMT_INLINE float bitwiseandnot(float x, float y) { return fbitcast(ubitcast(x) & ~ubitcast(y)); }
+CMT_INLINE float bitwisexor(float x, float y) { return fbitcast(ubitcast(x) ^ ubitcast(y)); }
+CMT_INLINE double bitwisenot(double x) { return fbitcast(~ubitcast(x)); }
+CMT_INLINE double bitwiseor(double x, double y) { return fbitcast(ubitcast(x) | ubitcast(y)); }
+CMT_INLINE double bitwiseand(double x, double y) { return fbitcast(ubitcast(x) & ubitcast(y)); }
+CMT_INLINE double bitwiseandnot(double x, double y) { return fbitcast(ubitcast(x) & ~ubitcast(y)); }
+CMT_INLINE double bitwisexor(double x, double y) { return fbitcast(ubitcast(x) ^ ubitcast(y)); }
+
+/// Bitwise Not
+template <typename T1>
+CMT_INLINE T1 bitwisenot(const T1& x)
+{
+ return ~x;
+}
+KFR_FN(bitwisenot)
+
+/// Bitwise And
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> bitwiseand(const T1& x, const T2& y)
+{
+ return x & y;
+}
+template <typename T>
+constexpr CMT_INLINE T bitwiseand(initialvalue<T>)
+{
+ return constants<T>::allones();
+}
+KFR_FN(bitwiseand)
+
+/// Bitwise And-Not
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> bitwiseandnot(const T1& x, const T2& y)
+{
+ return x & ~y;
+}
+template <typename T>
+constexpr inline T bitwiseandnot(initialvalue<T>)
+{
+ return constants<T>::allones();
+}
+KFR_FN(bitwiseandnot)
+
+/// Bitwise Or
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> bitwiseor(const T1& x, const T2& y)
+{
+ return x | y;
+}
+template <typename T>
+constexpr CMT_INLINE T bitwiseor(initialvalue<T>)
+{
+ return subtype<T>(0);
+}
+KFR_FN(bitwiseor)
+
+/// Bitwise Xor (Exclusive Or)
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> bitwisexor(const T1& x, const T2& y)
+{
+ return x ^ y;
+}
+template <typename T>
+constexpr CMT_INLINE T bitwisexor(initialvalue<T>)
+{
+ return subtype<T>();
+}
+KFR_FN(bitwisexor)
+
+/// Bitwise Left shift
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> shl(const T1& left, const T2& right)
+{
+ return left << right;
+}
+KFR_FN(shl)
+
+/// Bitwise Right shift
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> shr(const T1& left, const T2& right)
+{
+ return left >> right;
+}
+KFR_FN(shr)
+
+/// Bitwise Left Rotate
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> rol(const T1& left, const T2& right)
+{
+ return shl(left, right) | shr(left, (static_cast<subtype<T1>>(typebits<T1>::bits) - right));
+}
+KFR_FN(rol)
+
+/// Bitwise Right Rotate
+template <typename T1, typename T2>
+CMT_INLINE common_type<T1, T2> ror(const T1& left, const T2& right)
+{
+ return shr(left, right) | shl(left, (static_cast<subtype<T1>>(typebits<T1>::bits) - right));
+}
+KFR_FN(ror)
+}
diff --git a/include/kfr/base/horizontal.hpp b/include/kfr/base/horizontal.hpp
@@ -0,0 +1,119 @@
+/** @addtogroup math
+ * @{
+ */
+/*
+ Copyright (C) 2016 D Levin (https://www.kfrlib.com)
+ This file is part of KFR
+
+ KFR is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ KFR 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with KFR.
+
+ If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
+ Buying a commercial license is mandatory as soon as you develop commercial activities without
+ disclosing the source code of your own applications.
+ See https://www.kfrlib.com for details.
+ */
+#pragma once
+
+#include "operators.hpp"
+
+namespace kfr
+{
+
+namespace internal
+{
+
+template <typename T, typename ReduceFn>
+CMT_INLINE T horizontal_impl(const vec<T, 1>& value, ReduceFn&&)
+{
+ return T(value[0]);
+}
+
+template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && is_poweroftwo(N))>
+CMT_INLINE T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
+{
+ return horizontal_impl(reduce(low(value), high(value)), std::forward<ReduceFn>(reduce));
+}
+template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && !is_poweroftwo(N))>
+CMT_INLINE T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
+{
+ const T initial = reduce(initialvalue<T>());
+ return horizontal_impl(widen<next_poweroftwo(N)>(value, initial), std::forward<ReduceFn>(reduce));
+}
+}
+
+template <typename T, size_t N, typename ReduceFn>
+CMT_INLINE T horizontal(const vec<T, N>& value, ReduceFn&& reduce)
+{
+ return internal::horizontal_impl(value, std::forward<ReduceFn>(reduce));
+}
+
+/// @brief Sum all elements of the vector
+template <typename T, size_t N>
+CMT_INLINE T hadd(const vec<T, N>& value)
+{
+ return horizontal(value, fn::add());
+}
+KFR_FN(hadd)
+
+/// @brief Multiply all elements of the vector
+template <typename T, size_t N>
+CMT_INLINE T hmul(const vec<T, N>& value)
+{
+ return horizontal(value, fn::mul());
+}
+KFR_FN(hmul)
+
+template <typename T, size_t N>
+CMT_INLINE T hbitwiseand(const vec<T, N>& value)
+{
+ return horizontal(value, fn::bitwiseand());
+}
+KFR_FN(hbitwiseand)
+template <typename T, size_t N>
+CMT_INLINE T hbitwiseor(const vec<T, N>& value)
+{
+ return horizontal(value, fn::bitwiseor());
+}
+KFR_FN(hbitwiseor)
+template <typename T, size_t N>
+CMT_INLINE T hbitwisexor(const vec<T, N>& value)
+{
+ return horizontal(value, fn::bitwisexor());
+}
+KFR_FN(hbitwisexor)
+
+/// @brief Calculate the Dot-Product of two vectors
+template <typename T, size_t N>
+CMT_INLINE T dot(const vec<T, N>& x, const vec<T, N>& y)
+{
+ return hadd(x * y);
+}
+KFR_FN(dot)
+
+/// @brief Calculate the Arithmetic mean of all elements in the vector
+template <typename T, size_t N>
+CMT_INLINE T avg(const vec<T, N>& value)
+{
+ return hadd(value) / N;
+}
+KFR_FN(avg)
+
+/// @brief Calculate the RMS of all elements in the vector
+template <typename T, size_t N>
+CMT_INLINE T rms(const vec<T, N>& value)
+{
+ return internal::builtin_sqrt(hadd(value * value) / N);
+}
+KFR_FN(rms)
+}
diff --git a/include/kfr/base/operators.hpp b/include/kfr/base/operators.hpp
@@ -25,39 +25,13 @@
*/
#pragma once
+#include "bitwise.hpp"
#include "function.hpp"
#include <algorithm>
#include <utility>
namespace kfr
{
-namespace internal
-{
-
-template <typename T, typename ReduceFn>
-CMT_INLINE T horizontal_impl(const vec<T, 1>& value, ReduceFn&&)
-{
- return T(value[0]);
-}
-
-template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && is_poweroftwo(N))>
-CMT_INLINE T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
-{
- return horizontal_impl(reduce(low(value), high(value)), std::forward<ReduceFn>(reduce));
-}
-template <typename T, size_t N, typename ReduceFn, KFR_ENABLE_IF(N > 1 && !is_poweroftwo(N))>
-CMT_INLINE T horizontal_impl(const vec<T, N>& value, ReduceFn&& reduce)
-{
- const T initial = reduce(initialvalue<T>());
- return horizontal_impl(widen<next_poweroftwo(N)>(value, initial), std::forward<ReduceFn>(reduce));
-}
-}
-
-template <typename T, size_t N, typename ReduceFn>
-CMT_INLINE T horizontal(const vec<T, N>& value, ReduceFn&& reduce)
-{
- return internal::horizontal_impl(value, std::forward<ReduceFn>(reduce));
-}
template <typename T>
constexpr inline T add(const T& x)
@@ -177,25 +151,25 @@ CMT_INLINE internal::expression_function<fn::cub, E1> cub(E1&& x)
}
template <typename T, KFR_ENABLE_IF(is_numeric_args<T>::value)>
-constexpr inline T pow2(const T& x)
+constexpr CMT_INLINE T pow2(const T& x)
{
return sqr(x);
}
template <typename T, KFR_ENABLE_IF(is_numeric_args<T>::value)>
-constexpr inline T pow3(const T& x)
+constexpr CMT_INLINE T pow3(const T& x)
{
return cub(x);
}
template <typename T, KFR_ENABLE_IF(is_numeric_args<T>::value)>
-constexpr inline T pow4(const T& x)
+constexpr CMT_INLINE T pow4(const T& x)
{
return sqr(sqr(x));
}
template <typename T, KFR_ENABLE_IF(is_numeric_args<T>::value)>
-constexpr inline T pow5(const T& x)
+constexpr CMT_INLINE T pow5(const T& x)
{
return pow4(x) * x;
}
@@ -233,13 +207,14 @@ CMT_INLINE internal::expression_function<fn::pow5, E1> pow5(E1&& x)
template <typename T>
constexpr inline T ipow(const T& x, int base)
{
+ T xx = x;
T result = T(1);
while (base)
{
if (base & 1)
- result *= x;
+ result *= xx;
base >>= 1;
- x *= x;
+ xx *= xx;
}
return result;
}
@@ -271,7 +246,7 @@ KFR_FN(sqrdiff)
/// Division
template <typename T1, typename T2, typename Tout = common_type<T1, T2>>
-inline Tout div(const T1& x, const T2& y)
+CMT_INLINE Tout div(const T1& x, const T2& y)
{
return static_cast<Tout>(x) / static_cast<Tout>(y);
}
@@ -279,7 +254,7 @@ KFR_FN(div)
/// Remainder
template <typename T1, typename T2, typename Tout = common_type<T1, T2>>
-inline Tout rem(const T1& x, const T2& y)
+CMT_INLINE Tout rem(const T1& x, const T2& y)
{
return static_cast<Tout>(x) % static_cast<Tout>(y);
}
@@ -293,109 +268,6 @@ inline T1 neg(const T1& x)
}
KFR_FN(neg)
-inline float bitwisenot(const float& x) { return fbitcast(~ubitcast(x)); }
-inline float bitwiseor(const float& x, const float& y) { return fbitcast(ubitcast(x) | ubitcast(y)); }
-inline float bitwiseand(const float& x, const float& y) { return fbitcast(ubitcast(x) & ubitcast(y)); }
-inline float bitwiseandnot(const float& x, const float& y) { return fbitcast(ubitcast(x) & ~ubitcast(y)); }
-inline float bitwisexor(const float& x, const float& y) { return fbitcast(ubitcast(x) ^ ubitcast(y)); }
-inline double bitwisenot(const double& x) { return fbitcast(~ubitcast(x)); }
-inline double bitwiseor(const double& x, const double& y) { return fbitcast(ubitcast(x) | ubitcast(y)); }
-inline double bitwiseand(const double& x, const double& y) { return fbitcast(ubitcast(x) & ubitcast(y)); }
-inline double bitwiseandnot(const double& x, const double& y) { return fbitcast(ubitcast(x) & ~ubitcast(y)); }
-inline double bitwisexor(const double& x, const double& y) { return fbitcast(ubitcast(x) ^ ubitcast(y)); }
-
-/// Bitwise Not
-template <typename T1>
-inline T1 bitwisenot(const T1& x)
-{
- return ~x;
-}
-KFR_FN(bitwisenot)
-
-/// Bitwise And
-template <typename T1, typename T2>
-inline common_type<T1, T2> bitwiseand(const T1& x, const T2& y)
-{
- return x & y;
-}
-template <typename T>
-constexpr inline T bitwiseand(initialvalue<T>)
-{
- return constants<T>::allones();
-}
-KFR_FN(bitwiseand)
-
-/// Bitwise And-Not
-template <typename T1, typename T2>
-inline common_type<T1, T2> bitwiseandnot(const T1& x, const T2& y)
-{
- return x & ~y;
-}
-template <typename T>
-constexpr inline T bitwiseandnot(initialvalue<T>)
-{
- return constants<T>::allones();
-}
-KFR_FN(bitwiseandnot)
-
-/// Bitwise Or
-template <typename T1, typename T2>
-inline common_type<T1, T2> bitwiseor(const T1& x, const T2& y)
-{
- return x | y;
-}
-template <typename T>
-constexpr inline T bitwiseor(initialvalue<T>)
-{
- return subtype<T>(0);
-}
-KFR_FN(bitwiseor)
-
-/// Bitwise Xor (Exclusive Or)
-template <typename T1, typename T2>
-inline common_type<T1, T2> bitwisexor(const T1& x, const T2& y)
-{
- return x ^ y;
-}
-template <typename T>
-constexpr inline T bitwisexor(initialvalue<T>)
-{
- return subtype<T>();
-}
-KFR_FN(bitwisexor)
-
-/// Bitwise Left shift
-template <typename T1, typename T2>
-inline common_type<T1, T2> shl(const T1& left, const T2& right)
-{
- return left << right;
-}
-KFR_FN(shl)
-
-/// Bitwise Right shift
-template <typename T1, typename T2>
-inline common_type<T1, T2> shr(const T1& left, const T2& right)
-{
- return left >> right;
-}
-KFR_FN(shr)
-
-/// Bitwise Left Rotate
-template <typename T1, typename T2>
-inline common_type<T1, T2> rol(const T1& left, const T2& right)
-{
- return shl(left, right) | shr(left, (static_cast<subtype<T1>>(typebits<T1>::bits) - right));
-}
-KFR_FN(rol)
-
-/// Bitwise Right Rotate
-template <typename T1, typename T2>
-inline common_type<T1, T2> ror(const T1& left, const T2& right)
-{
- return shr(left, right) | shl(left, (static_cast<subtype<T1>>(typebits<T1>::bits) - right));
-}
-KFR_FN(ror)
-
template <typename T1, typename T2>
inline maskfor<common_type<T1, T2>> equal(const T1& x, const T2& y)
{
@@ -658,65 +530,6 @@ CMT_INLINE T swapbyteorder(const T& x)
}
KFR_FN(swapbyteorder)
-/// @brief Sum all elements of the vector
-template <typename T, size_t N>
-CMT_INLINE T hadd(const vec<T, N>& value)
-{
- return horizontal(value, fn::add());
-}
-KFR_FN(hadd)
-
-/// @brief Multiply all elements of the vector
-template <typename T, size_t N>
-CMT_INLINE T hmul(const vec<T, N>& value)
-{
- return horizontal(value, fn::mul());
-}
-KFR_FN(hmul)
-
-template <typename T, size_t N>
-CMT_INLINE T hbitwiseand(const vec<T, N>& value)
-{
- return horizontal(value, fn::bitwiseand());
-}
-KFR_FN(hbitwiseand)
-template <typename T, size_t N>
-CMT_INLINE T hbitwiseor(const vec<T, N>& value)
-{
- return horizontal(value, fn::bitwiseor());
-}
-KFR_FN(hbitwiseor)
-template <typename T, size_t N>
-CMT_INLINE T hbitwisexor(const vec<T, N>& value)
-{
- return horizontal(value, fn::bitwisexor());
-}
-KFR_FN(hbitwisexor)
-
-/// @brief Calculate the Dot-Product of two vectors
-template <typename T, size_t N>
-CMT_INLINE T dot(const vec<T, N>& x, const vec<T, N>& y)
-{
- return hadd(x * y);
-}
-KFR_FN(dot)
-
-/// @brief Calculate the Arithmetic mean of all elements in the vector
-template <typename T, size_t N>
-CMT_INLINE T avg(const vec<T, N>& value)
-{
- return hadd(value) / N;
-}
-KFR_FN(avg)
-
-/// @brief Calculate the RMS of all elements in the vector
-template <typename T, size_t N>
-CMT_INLINE T rms(const vec<T, N>& value)
-{
- return internal::builtin_sqrt(hadd(value * value) / N);
-}
-KFR_FN(rms)
-
template <typename T, size_t N, KFR_ENABLE_IF(N >= 2)>
CMT_INLINE vec<T, N> subadd(const vec<T, N>& a, const vec<T, N>& b)
{
diff --git a/sources.cmake b/sources.cmake
@@ -18,6 +18,7 @@ set(
${PROJECT_SOURCE_DIR}/include/kfr/base/asin_acos.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/atan.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/basic_expressions.hpp
+ ${PROJECT_SOURCE_DIR}/include/kfr/base/bitwise.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/clamp.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/compiletime.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/complex.hpp
@@ -27,6 +28,7 @@ set(
${PROJECT_SOURCE_DIR}/include/kfr/base/function.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/gamma.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/generators.hpp
+ ${PROJECT_SOURCE_DIR}/include/kfr/base/horizontal.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/hyperbolic.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/logical.hpp
${PROJECT_SOURCE_DIR}/include/kfr/base/log_exp.hpp