- Fixed Documentation for Consistency

- Added more documentation, predominantly in the Math Library
This commit is contained in:
2025-06-16 01:48:31 -04:00
parent 096e82f47a
commit db7d52c86c
28 changed files with 861 additions and 538 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>> {};
}

View File

@@ -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 { };