Skip to content

Commit

Permalink
优化 Huffman 编码实现,重构分数类构造函数,添加内存对齐分配功能,更新异常处理,增强 Any 类的类型安全性
Browse files Browse the repository at this point in the history
  • Loading branch information
AstroAir committed Nov 14, 2024
1 parent 7ac7ad7 commit 32e4f67
Show file tree
Hide file tree
Showing 19 changed files with 1,481 additions and 799 deletions.
12 changes: 3 additions & 9 deletions src/atom/algorithm/fraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Description: Implementation of Fraction class

#include "fraction.hpp"

#include <numeric>
#include <sstream>

namespace atom::algorithm {

/* ------------------------ Private Methods ------------------------ */
Expand All @@ -39,15 +42,6 @@ void Fraction::reduce() noexcept {
denominator /= divisor;
}

/* ------------------------ Constructors ------------------------ */

constexpr Fraction::Fraction(int n, int d) : numerator(n), denominator(d) {
if (denominator == 0) {
throw FractionException("Denominator cannot be zero.");
}
reduce();
}

/* ------------------------ Arithmetic Operators ------------------------ */

auto Fraction::operator+=(const Fraction& other) -> Fraction& {
Expand Down
27 changes: 19 additions & 8 deletions src/atom/algorithm/fraction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ Description: Implementation of Fraction class

#include <cmath>
#include <compare>
#include <exception>
#include <functional>
#include <iostream>
#include <numeric>
#include <sstream>
#include <stdexcept>
#include <string>

Expand Down Expand Up @@ -65,7 +61,23 @@ class Fraction {
* @param d The denominator (default is 1).
* @throws FractionException if the denominator is zero.
*/
explicit constexpr Fraction(int n = 0, int d = 1);
explicit constexpr Fraction(int n, int d) : numerator(n), denominator(d) {
if (denominator == 0) {
throw FractionException("Denominator cannot be zero.");
}
reduce();
}

/**
* @brief Constructs a new Fraction object with the given integer value.
* @param value The integer value.
*/
explicit constexpr Fraction(int value) : numerator(value), denominator(1) {}

/**
* @brief Default constructor. Initializes the fraction as 0/1.
*/
constexpr Fraction() : Fraction(0, 1) {}

/**
* @brief Adds another fraction to this fraction.
Expand Down Expand Up @@ -229,7 +241,7 @@ class Fraction {
* @param value The integer value.
* @return A Fraction representing the integer.
*/
inline auto makeFraction(int value) -> Fraction;
auto makeFraction(int value) -> Fraction;

/**
* @brief Creates a Fraction from a double by approximating it.
Expand All @@ -238,8 +250,7 @@ inline auto makeFraction(int value) -> Fraction;
* approximation.
* @return A Fraction approximating the double value.
*/
inline auto makeFraction(double value,
int max_denominator = 1000000) -> Fraction;
auto makeFraction(double value, int max_denominator = 1000000) -> Fraction;

} // namespace atom::algorithm

Expand Down
1 change: 1 addition & 0 deletions src/atom/algorithm/huffman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Description: Enhanced implementation of Huffman encoding
#include "huffman.hpp"
#include <bitset>
#include <functional>
#include <iostream>
#include <queue>
#include <sstream>

Expand Down
2 changes: 0 additions & 2 deletions src/atom/algorithm/huffman.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ Description: Enhanced implementation of Huffman encoding
#ifndef ATOM_ALGORITHM_HUFFMAN_HPP
#define ATOM_ALGORITHM_HUFFMAN_HPP

#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
Expand Down
8 changes: 8 additions & 0 deletions src/atom/function/any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <utility>
#include <vector>

#include "atom/error/exception.hpp"
#include "atom/function/proxy.hpp"
#include "atom/macro.hpp"
#include "type_info.hpp"

Expand Down Expand Up @@ -252,6 +254,12 @@ class BoxedValue {
}
}

template <typename T>
auto isType() const -> bool {
std::shared_lock lock(m_mutex_);
return m_data_->mTypeInfo == userType<T>();
}

/*!
* \brief Check if the value is undefined.
* \return True if the value is undefined, false otherwise.
Expand Down
205 changes: 134 additions & 71 deletions src/atom/function/field_count.hpp
Original file line number Diff line number Diff line change
@@ -1,97 +1,160 @@
/*!
* \file field_count.hpp
* \brief Field Count
* \author Max Qian <lightapt.com>
* \date 2024-05-25
* \copyright Copyright (C) 2023-2024 Max Qian <lightapt.com>
*/
#ifndef ATOMMETA_FIELD_COUNT_HPP
#define ATOMMETA_FIELD_COUNT_HPP

#ifndef ATOM_META_FIELD_COUNT_HPP
#define ATOM_META_FIELD_COUNT_HPP
#include <array>
namespace atom::meta::details {
struct Any;

#include <type_traits>
#include <utility>
struct Any {
constexpr Any(int) {}

namespace atom::meta {
template <typename T>
requires std::is_copy_constructible_v<T>
operator T&();

/*!
* \brief A struct that can be converted to any type.
*/
struct Any {
/*!
* \brief Constexpr conversion operator to any type.
* \tparam T The type to convert to.
* \return An instance of type T.
*/
template <typename T>
explicit consteval operator T() const noexcept;
requires std::is_move_constructible_v<T>
operator T&&();

struct Empty {};

template <typename T>
requires(!std::is_copy_constructible_v<T> &&
!std::is_move_constructible_v<T> &&
!std::is_constructible_v<T, Empty>)
operator T();
};

/*!
* \brief Checks if a type T is constructible with braces.
* \tparam T The type to check.
* \tparam I The index sequence.
* \param[in] indices The index sequence.
* \return True if T is constructible with braces, false otherwise.
*/
template <typename T, std::size_t... I>
consteval auto isBracesConstructible(
std::index_sequence<I...> /*indices*/) noexcept -> bool {
return requires { T{((void)I, std::declval<Any>())...}; };
template <typename T, std::size_t N>
consteval auto tryInitializeWithN() -> std::size_t {
return []<std::size_t... Is>(std::index_sequence<Is...>) {
return requires { T{Any(Is)...}; };
}(std::make_index_sequence<N>{});
}

/*!
* \brief Recursively counts the number of fields in a type T.
* \tparam T The type to count fields in.
* \tparam N The current count of fields.
* \return The number of fields in type T.
*/
template <typename T, std::size_t N = 0>
consteval auto fieldCount() noexcept -> std::size_t {
if constexpr (!isBracesConstructible<T>(
std::make_index_sequence<N + 1>{})) {
consteval auto totalCountOfFields() -> std::size_t {
if constexpr (tryInitializeWithN<T, N>() &&
!tryInitializeWithN<T, N + 1>()) {
return N;
} else {
return fieldCount<T, N + 1>();
return totalCountOfFields<T, N + 1>();
}
}
} // namespace atom::meta::details

/*!
* \brief A template struct to hold type information.
* \tparam T The type to hold information for.
*/
template <typename T>
struct TypeInfo;
namespace atom::meta::details {

template <typename T, std::size_t N1, std::size_t N2, std::size_t N3>
consteval auto tryInitializeWithThreeParts() -> std::size_t {
return []<std::size_t... I1, std::size_t... I2, std::size_t... I3>(
std::index_sequence<I1...>, std::index_sequence<I2...>,
std::index_sequence<I3...>) {
return requires { T{Any(I1)..., {Any(I2)...}, Any(I3)...}; };
}(std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{},
std::make_index_sequence<N3>{});
}

template <typename T, std::size_t position, std::size_t N>
constexpr auto tryPlaceNInPos() -> bool {
constexpr auto Total = totalCountOfFields<T>();
if constexpr (N == 0) {
return true;
} else if constexpr (position + N <= Total) {
return tryInitializeWithThreeParts<T, position, N,
Total - position - N>();
} else {
return false;
}
}

template <typename T, std::size_t pos, std::size_t N = 0, std::size_t Max = 10>
constexpr auto hasExtraElements() -> bool {
constexpr auto Total = totalCountOfFields<T>();
if constexpr (tryInitializeWithThreeParts<T, pos, N, Total - pos - 1>()) {
return false;
} else if constexpr (N + 1 <= Max) {
return hasExtraElements<T, pos, N + 1>();
} else {
return true;
}
}

template <typename T, std::size_t pos>
constexpr auto searchMaxInPos() -> std::size_t {
constexpr auto Total = totalCountOfFields<T>();
if constexpr (!hasExtraElements<T, pos>()) {
return 1;
} else {
std::size_t result = 0;
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
((tryPlaceNInPos<T, pos, Is>() ? result = Is : 0), ...);
}(std::make_index_sequence<Total + 1>());
return result;
}
}

template <typename T, std::size_t N = 0>
constexpr auto searchAllExtraIndex(auto&& array) {
constexpr auto total = totalCountOfFields<T>();
constexpr auto value = std::max<std::size_t>(searchMaxInPos<T, N>(), 1);
array[N] = value;
if constexpr (N + value < total) {
searchAllExtraIndex<T, N + value>(array);
}
}

/*!
* \brief Gets the number of fields in a type T.
* \tparam T The type to get the field count for.
* \return The number of fields in type T.
*/
template <typename T>
consteval auto fieldCountOf() noexcept -> std::size_t {
if constexpr (std::is_aggregate_v<T>) {
if constexpr (requires { TypeInfo<T>::count; }) {
return TypeInfo<T>::count;
} else {
return fieldCount<T>();
}
constexpr auto trueCountOfFields() {
constexpr auto max = totalCountOfFields<T>();
if constexpr (max == 0) {
return 0;
} else {
return 0; // Non-aggregate types are considered to have 0 fields
std::array<std::size_t, max> indices = {1};
searchAllExtraIndex<T>(indices);
std::size_t result = max;
std::size_t index = 0;
while (index < max) {
auto n = indices[index];
result -= n - 1;
index += n;
}
return result;
}
}
} // namespace atom::meta::details

namespace atom::meta {
template <typename T>
struct type_info;

/*!
* \brief Gets the number of elements in an array.
* \tparam T The type of the array elements.
* \tparam N The number of elements in the array.
* \return The number of elements in the array.
/**
* @brief Retrieve the count of fields of a struct
* @warning cannot get the count of fields of a struct which has reference
* type member in gcc 13 because the internal error occurs in below occasion
* @code
* struct Number { operator int&(); };
* int& x = { Number{} };
*
* internal compiler error: in reference_binding, at cp/call.cc:2020
* @endcode
*
*/
template <typename T, std::size_t N>
consteval auto fieldCountOf() noexcept -> std::size_t {
return N;
template <typename T>
requires std::is_aggregate_v<T>
consteval auto fieldCountOf() {
if constexpr (requires { type_info<T>::count; }) {
return type_info<T>::count;
} else {
return details::trueCountOfFields<T>();
}
}

template <typename T>
requires(!std::is_aggregate_v<T>)
consteval auto fieldCountOf() {
return 0;
}
} // namespace atom::meta

#endif // ATOM_META_FIELD_COUNT_HPP
#endif // ATOMMETA_FIELD_COUNT_HPP
22 changes: 20 additions & 2 deletions src/atom/function/proxy_params.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ inline void to_json(nlohmann::json& j, const std::any& a) {
j = std::any_cast<std::string>(a);
} else if (a.type() == typeid(std::string_view)) {
j = std::any_cast<std::string_view>(a);
} else if (a.type() == typeid(const char *)) {
j = std::any_cast<const char *>(a);
} else if (a.type() == typeid(const char*)) {
j = std::any_cast<const char*>(a);
} else {
throw std::runtime_error("Unsupported type");
}
Expand Down Expand Up @@ -293,6 +293,24 @@ class FunctionParams {
params_[index] = arg;
}

template <typename T>
[[nodiscard]] auto getValueAs(size_t index) const -> std::optional<T> {
if (index >= params_.size()) {
return std::nullopt;
}

const auto& value = params_[index].getDefaultValue();
if (!value.has_value()) {
return std::nullopt;
}

try {
return std::any_cast<T>(value.value());
} catch (const std::bad_any_cast&) {
return std::nullopt;
}
}

private:
std::vector<Arg> params_; ///< The vector of Arg objects.
};
Expand Down
Loading

0 comments on commit 32e4f67

Please sign in to comment.