- Fixed Documentation for Consistency
- Added more documentation, predominantly in the Math Library
This commit is contained in:
@@ -16,19 +16,31 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file bits.h
|
||||
/// \brief bit-wise operations
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
#ifndef FENNEC_LANG_BITS_H
|
||||
#define FENNEC_LANG_BITS_H
|
||||
|
||||
#include <fennec/lang/intrinsics.h>
|
||||
#include <fennec/memory/memory.h>
|
||||
#include <fennec/lang/detail/__bits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \fn fennec::bit_cast(const FromT&)
|
||||
/// \brief
|
||||
/// \brief perform a bitcast of FromT to ToT
|
||||
/// \tparam ToT Type to cast to
|
||||
/// \tparam FromT Type of the value
|
||||
/// \param from Value to bit cast
|
||||
@@ -41,25 +53,110 @@ constexpr ToT bit_cast(const FromT& from)
|
||||
else
|
||||
{
|
||||
ToT to;
|
||||
memcpy(&to, &from, sizeof(ToT));
|
||||
fennec::memcpy(&to, &from, sizeof(ToT));
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void* bitmask(void* arr, const void* mask, size_t n)
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief perform a bit-wise and over an array of bytes
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to and against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_and(void* arr, const void* mask, size_t n)
|
||||
{
|
||||
if (arr == mask) return arr;
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
|
||||
while (n >= 8) { detail::__bitmask_64(d, s); d += 8; s += 8; n -= 8; }
|
||||
while (n >= 4) { detail::__bitmask_32(d, s); d += 4; s += 4; n -= 4; }
|
||||
while (n >= 2) { detail::__bitmask_16(d, s); d += 2; s += 2; n -= 2; }
|
||||
while (n >= 1) { *d++ = *s++; --n; }
|
||||
while (n > 0)
|
||||
{
|
||||
size_t step = detail::__bit_and(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief safe version of fennec::bit_and
|
||||
/// \copydoc fennec::bit_and
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param n1 the size of mask in bytes
|
||||
constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)
|
||||
{ return bit_and(arr, mask, n0 < n1 ? n0 : n1); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief perform a bit-wise or over an array of bytes
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_or(void* arr, const void* mask, size_t n)
|
||||
{
|
||||
if (arr == mask) return arr;
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
size_t step = detail::__bit_or(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief safe version of fennec::bit_or
|
||||
/// \copydoc fennec::bit_or
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param n1 the size of mask in bytes
|
||||
constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)
|
||||
{ return bit_or(arr, mask, n0 < n1 ? n0 : n1); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief perform a bit-wise or over an array of bytes
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to or against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer arr
|
||||
constexpr void* bit_xor(void* arr, const void* mask, size_t n)
|
||||
{
|
||||
if (arr == mask) return arr;
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
size_t step = detail::__bit_xor(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief safe version of fennec::bit_xor
|
||||
/// \copydoc fennec::bit_xor
|
||||
/// \param n0 the size of arr in bytes
|
||||
/// \param n1 the size of mask in bytes
|
||||
constexpr void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1)
|
||||
{ return bit_xor(arr, mask, n0 < n1 ? n0 : n1); }
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_BITS_H
|
||||
|
||||
@@ -88,6 +88,13 @@ struct detect
|
||||
static constexpr bool is_detected = false;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
using detect_t
|
||||
= typename detect<DefaultT, DetectT, ArgsT...>::type;
|
||||
|
||||
|
||||
// true case
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
requires requires { typename DetectT<ArgsT...>; }
|
||||
@@ -97,13 +104,6 @@ struct detect<DefaultT, DetectT, ArgsT...>
|
||||
static constexpr bool is_detected = true;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
using detect_t
|
||||
= typename detect<DefaultT, DetectT, ArgsT...>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_CONDITIONAL_TYPES_H
|
||||
|
||||
@@ -48,7 +48,6 @@ template<typename T, T V> struct integral_constant
|
||||
/// \brief value of the constant
|
||||
inline static constexpr T value = V;
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief cast operator to allow for braced initialization
|
||||
/// \returns the value of the constant
|
||||
@@ -56,7 +55,6 @@ template<typename T, T V> struct integral_constant
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief metaprogramming boolean constant
|
||||
///
|
||||
@@ -67,14 +65,12 @@ struct bool_constant
|
||||
: integral_constant<bool_t, V> {};
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief metaprogramming true constant
|
||||
struct true_type
|
||||
: bool_constant<true> {};
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief metaprogramming false constant
|
||||
struct false_type
|
||||
|
||||
@@ -27,17 +27,109 @@ namespace fennec
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// helper for copying 2 bytes at once
|
||||
constexpr size_t __bitmask_16(void* dst, const void* src)
|
||||
{ *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; }
|
||||
// helper for bitwise and for 1 byte
|
||||
constexpr size_t __bit_and_8(void* dst, const void* src)
|
||||
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1; }
|
||||
|
||||
// helper for copying 4 bytes at once
|
||||
constexpr size_t __bitmask_32(void* dst, const void* src)
|
||||
{ *static_cast<uint32_t*>(dst) = *static_cast<const uint32_t*>(src); return 4; }
|
||||
// helper for bitwise and 2 bytes at once
|
||||
constexpr size_t __bit_and_16(void* dst, const void* src)
|
||||
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2; }
|
||||
|
||||
// helper for copying 8 bytes at once
|
||||
constexpr size_t __bitmask_64(void* dst, const void* src)
|
||||
{ *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; }
|
||||
// helper for bitwise and 4 bytes at once
|
||||
constexpr size_t __bit_and_32(void* dst, const void* src)
|
||||
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4; }
|
||||
|
||||
// helper for bitwise and 8 bytes at once
|
||||
constexpr size_t __bit_and_64(void* dst, const void* src)
|
||||
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8; }
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_and(void* dst, const void* src, size_t n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_and_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_and_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_and_32(dst, src);
|
||||
default:
|
||||
return __bit_and_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise or for 1 byte
|
||||
constexpr size_t __bit_or_8(void* dst, const void* src)
|
||||
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1; }
|
||||
|
||||
// helper for bitwise or 2 bytes at once
|
||||
constexpr size_t __bit_or_16(void* dst, const void* src)
|
||||
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2; }
|
||||
|
||||
// helper for bitwise or 4 bytes at once
|
||||
constexpr size_t __bit_or_32(void* dst, const void* src)
|
||||
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4; }
|
||||
|
||||
// helper for bitwise or 8 bytes at once
|
||||
constexpr size_t __bit_or_64(void* dst, const void* src)
|
||||
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8; }
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_or(void* dst, const void* src, size_t n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_or_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_or_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_or_32(dst, src);
|
||||
default:
|
||||
return __bit_or_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise and 1 byte
|
||||
constexpr size_t __bit_xor_8(void* dst, const void* src)
|
||||
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1; }
|
||||
|
||||
// helper for bitwise xor 2 bytes at once
|
||||
constexpr size_t __bit_xor_16(void* dst, const void* src)
|
||||
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2; }
|
||||
|
||||
// helper for bitwise xor 4 bytes at once
|
||||
constexpr size_t __bit_xor_32(void* dst, const void* src)
|
||||
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4; }
|
||||
|
||||
// helper for bitwise xor 8 bytes at once
|
||||
constexpr size_t __bit_xor_64(void* dst, const void* src)
|
||||
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8; }
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_xor(void* dst, const void* src, size_t n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_xor_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_xor_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_xor_32(dst, src);
|
||||
default:
|
||||
return __bit_xor_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#define FENNEC_LANG_H
|
||||
|
||||
///
|
||||
/// \page page_fennec_lang C++ Language Library
|
||||
/// \page fennec_lang C++ Language Library
|
||||
///
|
||||
/// This library implements the parts of the C++ stdlib that relate to built-in types and metaprogramming.
|
||||
///
|
||||
/// \subpage
|
||||
///
|
||||
///
|
||||
|
||||
#endif // FENNEC_LANG_H
|
||||
|
||||
@@ -44,41 +44,40 @@ enum float_round_style
|
||||
/// \tparam TypeT Numeric types, may be overloaded for custom types
|
||||
template<typename TypeT> struct numeric_limits
|
||||
{
|
||||
static constexpr bool is_specialized = false;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = false;
|
||||
static constexpr bool is_modulo = false;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = false;
|
||||
static constexpr bool is_specialized = false; ///< Check if the template is specialized for TypeT
|
||||
static constexpr bool is_signed = false; ///< Check if TypeT is signed
|
||||
static constexpr bool is_integer = false; ///< Check if TypeT is of an integral type
|
||||
static constexpr bool is_exact = false; ///< Check if TypeT is exact in its precision
|
||||
static constexpr bool has_infinity = false; ///< Check if TypeT can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; ///< Check if TypeT can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; ///< Check if TypeT can hold a signaling nan
|
||||
static constexpr bool is_iec559 = false; ///< Check if a TypeT representing a float is IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = false; ///< Check if TypeT represents a finite set of values
|
||||
static constexpr bool is_modulo = false; ///< Check if TypeT can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; ///< Check if TypeT checks for tinyness before rounding
|
||||
static constexpr bool traps = false; ///< Check if TypeT can cause operations to trap
|
||||
|
||||
static constexpr int digits = 0;
|
||||
static constexpr int digits10 = 0;
|
||||
static constexpr int max_digits10 = 0;
|
||||
static constexpr int radix = 0;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int radix = 0; ///< Get the base representation of the type
|
||||
static constexpr int digits = 0; ///< Get the number of radix digits TypeT represents
|
||||
static constexpr int digits10 = 0; ///< Get the number of decimal digits TypeT represents
|
||||
static constexpr int max_digits10 = 0; ///< Get the maximum number of decimal digits TypeT represents
|
||||
static constexpr int min_exponent = 0; ///< Get the minimum number of radix digits that represent the exponent of TypeT
|
||||
static constexpr int min_exponent10 = 0; ///< Get the minimum number of decimal digits that represent the exponent of TypeT
|
||||
static constexpr int max_exponent = 0; ///< Get the maximum number of radix digits that represent the exponent of TypeT
|
||||
static constexpr int max_exponent10 = 0; ///< Get the maximum number of decimal digits that represent the exponent of TypeT
|
||||
|
||||
static constexpr float_round_style rounding_style = round_indeterminate;
|
||||
static constexpr float_round_style rounding_style = round_indeterminate; ///< The rounding style of TypeT
|
||||
|
||||
static constexpr TypeT min() { return TypeT(); }
|
||||
static constexpr TypeT max() { return TypeT(); }
|
||||
static constexpr TypeT lowest() { return TypeT(); }
|
||||
static constexpr TypeT epsilon() { return TypeT(); }
|
||||
static constexpr TypeT round_error() { return TypeT(); }
|
||||
static constexpr TypeT infinity() { return TypeT(); }
|
||||
static constexpr TypeT quiet_NaN() { return TypeT(); }
|
||||
static constexpr TypeT signaling_NaN() { return TypeT(); }
|
||||
static constexpr TypeT denorm_min() { return TypeT(); }
|
||||
// This is very poorly named and defined in the C++ Standard so these functions differ
|
||||
static constexpr TypeT min() { return TypeT(); } ///< The minimum finite value of TypeT
|
||||
static constexpr TypeT max() { return TypeT(); } ///< The maximum finite value of TypeT
|
||||
static constexpr TypeT lowest() { return TypeT(); } ///< The smallest positive value of TypeT
|
||||
static constexpr TypeT epsilon() { return TypeT(); } ///< Returns the difference between 1.0 and the next representable value
|
||||
static constexpr TypeT round_error() { return TypeT(); } ///< Returns the max rounding error of TypeT
|
||||
static constexpr TypeT infinity() { return TypeT(); } ///< Returns a value of TypeT holding a positive infinity
|
||||
static constexpr TypeT quiet_NaN() { return TypeT(); } ///< Returns a value of TypeT holding a quiet NaN
|
||||
static constexpr TypeT signaling_NaN() { return TypeT(); } ///< Returns a value of TypeT holding a signaling NaN
|
||||
static constexpr TypeT denorm_min() { return TypeT(); } ///< Returns a value of TypeT holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin floating point type
|
||||
|
||||
@@ -33,12 +33,18 @@
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
#include <fennec/lang/detail/__numeric_transforms.h>
|
||||
|
||||
// TODO: Document
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Get the corresponding signed integral type of TypeT
|
||||
/// \tparam TypeT the integral type to transform
|
||||
template<typename TypeT> struct make_signed : detail::__make_signed<remove_cv_t<TypeT>> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Get the corresponding unsigned integral type of TypeT
|
||||
/// \tparam TypeT the integral type to transform
|
||||
template<typename TypeT> struct make_unsigned : detail::__make_unsigned<remove_cv_t<TypeT>> {};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ template<typename...TypesT> using first_element_t = typename first_element<Types
|
||||
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
||||
template<typename ClassT, typename SubT> struct replace_first_element { };
|
||||
|
||||
Reference in New Issue
Block a user