libnum: some additional functions
This commit is contained in:
parent
36a21e3261
commit
a7529430dd
|
@ -97,7 +97,8 @@ if(Azur_FOUND)
|
|||
set_target_properties(Azur::Azur PROPERTIES
|
||||
IMPORTED_LOCATION "${AZUR_LIB}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${AZUR_INCLUDE}"
|
||||
INTERFACE_COMPILE_OPTIONS "-DAZUR_PLATFORM=${AZUR_PLATFORM}")
|
||||
INTERFACE_COMPILE_OPTIONS "-DAZUR_PLATFORM=${AZUR_PLATFORM}"
|
||||
INTERFACE_LINK_LIBRARIES -lnum)
|
||||
|
||||
if(AZUR_PLATFORM STREQUAL linux)
|
||||
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
include(CTest)
|
||||
|
||||
add_library(num STATIC
|
||||
src/num.cpp
|
||||
src/str.cpp)
|
||||
|
||||
target_include_directories(num PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
|
|
|
@ -117,9 +117,15 @@ struct num8
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr num8 ifloor() {
|
||||
return 0;
|
||||
}
|
||||
inline constexpr num8 floor() {
|
||||
return num8(0);
|
||||
}
|
||||
inline constexpr num8 iceil() {
|
||||
return v != 0;
|
||||
}
|
||||
/* Warning: num8::ceil() always overflows! */
|
||||
inline constexpr num8 ceil() {
|
||||
return num8(0);
|
||||
|
@ -195,6 +201,9 @@ struct num16
|
|||
/* num16 x num16 -> num32 multiplication
|
||||
This is efficiently implemented with a muls.w instruction. */
|
||||
static constexpr num32 dmul(num16 const &x, num16 const &y);
|
||||
/* num16 / num16 -> num16 division for positive numbers
|
||||
This bypasses some sign tests, which saves a bit of time. */
|
||||
static constexpr num16 div_positive(num16 const &x, num16 const &y);
|
||||
|
||||
/* Basic arithmetic */
|
||||
|
||||
|
@ -218,11 +227,17 @@ struct num16
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 8;
|
||||
}
|
||||
inline constexpr num16 floor() {
|
||||
num16 x;
|
||||
x.v = v & 0xff00;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v + 0xff) >> 8;
|
||||
}
|
||||
inline constexpr num16 ceil() {
|
||||
num16 x;
|
||||
x.v = ((v - 1) | 0xff) + 1;
|
||||
|
@ -330,11 +345,17 @@ struct num32
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 16;
|
||||
}
|
||||
inline constexpr num32 floor() {
|
||||
num32 x;
|
||||
x.v = v & 0xffff0000;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v + 0xffff) >> 16;
|
||||
}
|
||||
inline constexpr num32 ceil() {
|
||||
num32 x;
|
||||
x.v = ((v - 1) | 0xffff) + 1;
|
||||
|
@ -345,6 +366,7 @@ struct num32
|
|||
x.v = v & 0xffff;
|
||||
return x;
|
||||
}
|
||||
num32 sqrt() const;
|
||||
|
||||
/* Comparisons with int */
|
||||
|
||||
|
@ -447,11 +469,17 @@ struct num64
|
|||
v %= other.v;
|
||||
return *this;
|
||||
}
|
||||
inline constexpr int ifloor() {
|
||||
return v >> 32;
|
||||
}
|
||||
inline constexpr num64 floor() {
|
||||
num64 x;
|
||||
x.v = v & 0xffffffff00000000ull;
|
||||
return x;
|
||||
}
|
||||
inline constexpr int iceil() {
|
||||
return (v >> 32) + ((uint32_t)v != 0);
|
||||
}
|
||||
inline constexpr num64 ceil() {
|
||||
num64 x;
|
||||
x.v = ((v - 1) | 0xffffffffull) + 1;
|
||||
|
@ -569,6 +597,26 @@ inline constexpr T operator-(T const &op) {
|
|||
return T(0) - op;
|
||||
}
|
||||
|
||||
/* Internal minima, maxima and clamp */
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T min(T const &left, T const &right)
|
||||
{
|
||||
return (left < right) ? left : right;
|
||||
}
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T max(T const &left, T const &right)
|
||||
{
|
||||
return (left > right) ? left : right;
|
||||
}
|
||||
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T clamp(T const &val, T const &lower, T const &upper)
|
||||
{
|
||||
return max(lower, min(val, upper));
|
||||
}
|
||||
|
||||
/* Other specific operations */
|
||||
|
||||
inline constexpr num32 num16::dmul(num16 const &x, num16 const &y)
|
||||
|
@ -578,6 +626,13 @@ inline constexpr num32 num16::dmul(num16 const &x, num16 const &y)
|
|||
return n;
|
||||
}
|
||||
|
||||
inline constexpr num16 num16::div_positive(num16 const &x, num16 const &y)
|
||||
{
|
||||
num16 r;
|
||||
r.v = ((uint32_t)(uint16_t)x.v << 8) / (uint16_t)y.v;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline constexpr num64 num32::dmul(num32 const &x, num32 const &y)
|
||||
{
|
||||
num64 n;
|
||||
|
@ -585,4 +640,12 @@ inline constexpr num64 num32::dmul(num32 const &x, num32 const &y)
|
|||
return n;
|
||||
}
|
||||
|
||||
/* Floor modulo. We provide an optimized version for constants, which optimizes
|
||||
away the main condition. */
|
||||
template<typename T> requires(is_num<T>)
|
||||
inline constexpr T modf(T const &x, T const &y) {
|
||||
T r = x % y;
|
||||
return (r.v && (r.v ^ y.v) < 0) ? r + y : r;
|
||||
}
|
||||
|
||||
} /* namespace libnum */
|
||||
|
|
|
@ -189,6 +189,10 @@ inline constexpr vec<T,N> operator*(T const &lhs, vec<T,N> rhs) {
|
|||
rhs[i] *= lhs;
|
||||
return rhs;
|
||||
}
|
||||
template<typename T, int N>
|
||||
inline constexpr vec<T,N> operator/(vec<T,N> lhs, T const &rhs) {
|
||||
return lhs /= rhs;
|
||||
}
|
||||
|
||||
/* Comparisons */
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#include <num/num.h>
|
||||
using namespace libnum;
|
||||
|
||||
/* Integer square root (rather slow) */
|
||||
static int64_t sqrtll(int64_t n)
|
||||
{
|
||||
if(n < 4)
|
||||
return (n > 0);
|
||||
|
||||
int64_t low_bound = sqrtll(n / 4) * 2;
|
||||
int64_t high_bound = low_bound + 1;
|
||||
|
||||
return (high_bound * high_bound <= n) ? high_bound : low_bound;
|
||||
}
|
||||
|
||||
num32 num32::sqrt() const
|
||||
{
|
||||
num32 r;
|
||||
r.v = sqrtll((int64_t)v << 16);
|
||||
return r;
|
||||
}
|
|
@ -306,7 +306,7 @@ class ExprParser:
|
|||
return decorate
|
||||
|
||||
def binaryOpsRight(ctor, ops):
|
||||
return binaryOpsRight(ctor, ops, rassoc=True)
|
||||
return binaryOps(ctor, ops, rassoc=True)
|
||||
|
||||
def unaryOps(ctor, ops, assoc=True):
|
||||
def decorate(f):
|
||||
|
|
Loading…
Reference in New Issue