Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul polynomial type #172

Merged
merged 28 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e9de16a
Add polynomial type support to generics
inakleinbottle Nov 26, 2024
4a1d8a3
Merge branch 'main' into overhaul-polynomial-type
inakleinbottle Nov 26, 2024
224f845
Update Monomial class with operator overloads and functions
inakleinbottle Nov 26, 2024
2aac4db
Fix typo in monomial.cpp header comment
inakleinbottle Nov 26, 2024
734f500
Remove extraneous characters from comment header
inakleinbottle Nov 26, 2024
a0d71fd
Add mpq string representation and hash functions
inakleinbottle Nov 26, 2024
2b8559d
Add Polynomial class with arithmetic operations
inakleinbottle Nov 26, 2024
03bd13b
Refactor index method and add monomial tests
inakleinbottle Nov 26, 2024
28584e1
Add unit tests for `Indeterminate` and `Polynomial` classes
inakleinbottle Nov 26, 2024
bda7337
Add degree method and various enhancements to Polynomial
inakleinbottle Nov 27, 2024
9bff9aa
Add constructor and empty check to Monomial class
inakleinbottle Nov 27, 2024
ed84985
Add unit tests for polynomial operations
inakleinbottle Nov 27, 2024
89d0fc5
Add constructors and stream operator to Polynomial class
inakleinbottle Nov 27, 2024
8732501
Refactor polynomial multiplication test logic.
inakleinbottle Nov 27, 2024
940cd95
Add tests for polynomial equality and hashing
inakleinbottle Nov 27, 2024
743a52a
Add polynomial type handling files
inakleinbottle Nov 27, 2024
c53443a
Refactor `poly_div_inplace` to use `mpq_srcptr`
inakleinbottle Nov 27, 2024
d14f473
Extend PolynomialArithmetic with ArithmeticTrait methods
inakleinbottle Nov 27, 2024
c1192c2
Add polynomial_types.cpp to the build configuration
inakleinbottle Nov 27, 2024
3e7c311
Refactor `polynomial_type.cpp` for improved readability.
inakleinbottle Nov 27, 2024
a9a6c70
Update test assertions in `test_polynomial_type.cpp`.
inakleinbottle Nov 27, 2024
aae2ca8
Implement PolynomialType constructor and specialized traits
inakleinbottle Nov 27, 2024
0ab768b
Update tests for PolynomialType operations and functions
inakleinbottle Nov 27, 2024
d1710c4
Add ctre and fmt dependencies
inakleinbottle Nov 27, 2024
2fdb4e3
Change base_type to uint64_t and enhance parser functionality.
inakleinbottle Nov 27, 2024
feb999d
Change base_type to uint64_t and enhance parser functionality.
inakleinbottle Nov 27, 2024
4792aab
Add test for parsing mixed monomial with powers
inakleinbottle Nov 27, 2024
af091fe
Add missing <numeric> include and remove unused <iostream>
inakleinbottle Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ find_package(PCGRandom REQUIRED)
find_package(GMP REQUIRED)
find_package(MPFR REQUIRED)
find_package(range-v3 CONFIG REQUIRED)
find_package(ctre CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)

message(STATUS "Target architecture ${RPY_ARCH}")

Expand Down
82 changes: 38 additions & 44 deletions platform/include/roughpy/generics/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ namespace rpy::generics {
* includes methods and attributes which can be leveraged to manage and
* manipulate these properties efficiently and effectively.
*/
struct BasicProperties {
bool standard_layout : 1;
bool trivially_copyable : 1;
bool trivially_constructible : 1;
bool trivially_default_constructible : 1;
bool trivially_copy_constructible : 1;
bool trivially_copy_assignable : 1;
bool trivially_destructible : 1;
bool polymorphic : 1;
bool is_signed : 1;
bool is_floating_point : 1;
bool is_integral : 1;
struct BasicProperties
{
bool standard_layout: 1;
bool trivially_copyable: 1;
bool trivially_constructible: 1;
bool trivially_default_constructible: 1;
bool trivially_copy_constructible: 1;
bool trivially_copy_assignable: 1;
bool trivially_destructible: 1;
bool polymorphic: 1;
bool is_signed: 1;
bool is_floating_point: 1;
bool is_integral: 1;
};

template <typename T>
Expand All @@ -60,6 +61,7 @@ constexpr BasicProperties basic_properties_of() noexcept;

template <typename T>
TypePtr get_type() noexcept;

//{
// static_assert(false, "There is no Type associated with T");
// RPY_UNREACHABLE_RETURN(nullptr);
Expand All @@ -78,7 +80,6 @@ class ROUGHPY_PLATFORM_EXPORT Type : public mem::PolymorphicRefCounted
friend class Value;

public:

/**
* @brief Returns the type information of the current instance.
*
Expand Down Expand Up @@ -164,7 +165,6 @@ class ROUGHPY_PLATFORM_EXPORT Type : public mem::PolymorphicRefCounted
virtual void free_object(void* ptr) const = 0;

public:

virtual bool parse_from_string(void* data, string_view str) const noexcept;

/**
Expand All @@ -183,7 +183,7 @@ class ROUGHPY_PLATFORM_EXPORT Type : public mem::PolymorphicRefCounted
*/
virtual void
copy_or_move(void* dst, const void* src, size_t count, bool move) const
= 0;
= 0;

virtual void
destroy_range(void* data, size_t count) const = 0;
Expand Down Expand Up @@ -273,10 +273,7 @@ class ROUGHPY_PLATFORM_EXPORT Type : public mem::PolymorphicRefCounted
*
* @return A TypePtr representing the specific type.
*/
static TypePtr of() noexcept
{
return get_type<decay_t<T>>();
}
static TypePtr of() noexcept { return get_type<decay_t<T> >(); }

};

Expand Down Expand Up @@ -314,8 +311,8 @@ const BuiltinTypes& get_builtin_types() noexcept;
class ROUGHPY_PLATFORM_EXPORT MultiPrecisionTypes
{
MultiPrecisionTypes();
public:

public:
TypePtr integer_type;
TypePtr rational_type;

Expand All @@ -326,6 +323,9 @@ class ROUGHPY_PLATFORM_EXPORT MultiPrecisionTypes
static const MultiPrecisionTypes& get() noexcept;
};

RPY_NO_DISCARD
ROUGHPY_PLATFORM_EXPORT
TypePtr get_polynomial_type() noexcept;


template <typename T>
Expand All @@ -338,18 +338,18 @@ constexpr BasicProperties basic_properties_of() noexcept
{
using base_t = remove_cvref_t<T>;
return {
is_standard_layout_v<base_t>,
is_trivially_copyable_v<base_t>,
is_trivially_constructible_v<base_t>,
is_trivially_default_constructible_v<base_t>,
is_trivially_copy_constructible_v<base_t>,
is_trivially_copy_assignable_v<base_t>,
is_trivially_destructible_v<base_t>,
is_polymorphic_v<base_t>,
is_signed_v<base_t>,
is_floating_point_v<base_t>,
is_integral_v<base_t>,
};
is_standard_layout_v<base_t>,
is_trivially_copyable_v<base_t>,
is_trivially_constructible_v<base_t>,
is_trivially_default_constructible_v<base_t>,
is_trivially_copy_constructible_v<base_t>,
is_trivially_copy_assignable_v<base_t>,
is_trivially_destructible_v<base_t>,
is_polymorphic_v<base_t>,
is_signed_v<base_t>,
is_floating_point_v<base_t>,
is_integral_v<base_t>,
};
}

/**
Expand All @@ -366,7 +366,9 @@ constexpr BasicProperties basic_properties_of() noexcept
* @return The promoted type based on the provided `lhs` and `rhs` types.
* If neither type can be promoted to the other, `nullptr` is returned.
*/
RPY_NO_DISCARD TypePtr ROUGHPY_PLATFORM_EXPORT compute_promotion(const Type* lhs, const Type* rhs) noexcept;
RPY_NO_DISCARD TypePtr ROUGHPY_PLATFORM_EXPORT compute_promotion(
const Type* lhs,
const Type* rhs) noexcept;

/**
* @brief Computes the hash value of a given Type object.
Expand All @@ -386,16 +388,10 @@ inline hash_t hash_value(const Type& value) noexcept
}

RPY_NO_DISCARD constexpr bool
operator==(const Type& lhs, const Type& rhs) noexcept
{
return &lhs == &rhs;
}
operator==(const Type& lhs, const Type& rhs) noexcept { return &lhs == &rhs; }

RPY_NO_DISCARD constexpr bool
operator!=(const Type& lhs, const Type& rhs) noexcept
{
return !(lhs == rhs);
}
operator!=(const Type& lhs, const Type& rhs) noexcept { return !(lhs == rhs); }

/**
* @brief Retrieves the size of an object of the specified type.
Expand All @@ -411,7 +407,6 @@ inline size_t size_of(const Type& type) noexcept { return type.object_size(); }
namespace concepts {



/**
* @brief Check if the given type has standard layout
* @param type A reference to the Type object
Expand Down Expand Up @@ -550,7 +545,6 @@ inline bool is_arithmetic(Type const& type)
}// namespace concepts



template <>
inline TypePtr get_type<float>() noexcept
{
Expand Down Expand Up @@ -614,4 +608,4 @@ inline TypePtr get_type<uint64_t>() noexcept

}// namespace rpy::generics

#endif// ROUGHPY_GENERICS_TYPE_H
#endif// ROUGHPY_GENERICS_TYPE_H
2 changes: 2 additions & 0 deletions platform/src/generics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ target_sources(RoughPy_Platform PRIVATE
conversion_trait.cpp
multiprecision_types.cpp
number_trait.cpp
polynomial_types.cpp
type.cpp
type_builtin.cpp
type_promotion.cpp
Expand All @@ -29,6 +30,7 @@ target_sources(RoughPy_Platform PRIVATE

add_subdirectory(builtin_types)
add_subdirectory(multiprecision_types)
add_subdirectory(polynomial_type)



Expand Down
32 changes: 32 additions & 0 deletions platform/src/generics/multiprecision_types/mpq_string_rep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Created by sam on 26/11/24.
//

#ifndef ROUGHPY_GENERICS_INTERNAL_MPQ_STRING_REP_H
#define ROUGHPY_GENERICS_INTERNAL_MPQ_STRING_REP_H


#include <gmp.h>

#include "roughpy/core/types.h"


namespace rpy::generics {

inline void mpq_display_rep(string& buffer, mpq_srcptr value) noexcept
{
// The GMP docs describe the size of a mpq string representation in the
// documentation https://gmplib.org/manual/Rational-Conversions
auto num_size = mpz_sizeinbase(mpq_numref(value), 10);
auto denom_size = mpz_sizeinbase(mpq_denref(value), 10);
buffer.resize(num_size + denom_size + 3);

mpq_get_str(buffer.data(), 10, value);

// The buffer has at least one null byte at the end, cut these off
while (buffer.back() == '\0') { buffer.pop_back(); }
}

}

#endif //ROUGHPY_GENERICS_INTERNAL_MPQ_STRING_REP_H
9 changes: 9 additions & 0 deletions platform/src/generics/multiprecision_types/mpz_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ inline hash_t mpz_hash(mpz_srcptr integer) noexcept
return result;
}

inline hash_t mpq_hash(mpq_srcptr integer) noexcept
{
auto num_hash = mpz_hash(mpq_numref(integer));
const auto denom_hash = mpz_hash(mpq_denref(integer));

hash_combine(num_hash, denom_hash);
return num_hash;
}


}

Expand Down
18 changes: 3 additions & 15 deletions platform/src/generics/multiprecision_types/rational_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <roughpy/platform/alloc.h>

#include "mpz_hash.h"
#include "mpq_string_rep.h"

using namespace rpy;
using namespace rpy::generics;
Expand Down Expand Up @@ -145,18 +146,9 @@ RationalType::display(std::ostream& os, const void* value) const

const auto* rat = static_cast<mpq_srcptr>(value);

// The GMP docs describe the size of a mpq string representation in the
// documentation https://gmplib.org/manual/Rational-Conversions
auto num_size = mpz_sizeinbase(mpq_numref(rat), 10);
auto denom_size = mpz_sizeinbase(mpq_denref(rat), 10);

string buffer;
buffer.resize(num_size + denom_size + 3);

mpq_get_str(buffer.data(), 10, rat);
mpq_display_rep(buffer, rat);

// The buffer has at least one null byte at the end, cut these off
while (buffer.back() == '\0') { buffer.pop_back(); }
return os << buffer;
}

Expand All @@ -165,11 +157,7 @@ hash_t RationalType::hash_of(const void* value) const noexcept
if (value == nullptr) { return 0; }

auto* rat = static_cast<mpq_srcptr>(value);
auto num_hash = mpz_hash(mpq_numref(rat));
const auto denom_hash = mpz_hash(mpq_denref(rat));

hash_combine(num_hash, denom_hash);
return num_hash;
return mpq_hash(rat);
}

TypePtr RationalType::get() noexcept
Expand Down
60 changes: 60 additions & 0 deletions platform/src/generics/polynomial_type/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@




target_sources(RoughPy_Platform PRIVATE
indeterminate.h
indeterminate.cpp
monomial.cpp
monomial.h
polynomial.cpp
polynomial.h
polynomial_arithmetic.cpp
polynomial_arithmetic.h
polynomial_comparison.cpp
polynomial_comparison.h
polynomial_number.cpp
polynomial_number.h
polynomial_type.cpp
polynomial_type.h
)

target_link_libraries(RoughPy_Platform PRIVATE
ctre::ctre)

if (ROUGHPY_BUILD_TESTS)

add_executable(test_polynomial
test_indeterminate.cpp
test_monomial.cpp
test_polynomial.cpp
indeterminate.cpp
indeterminate.h
monomial.cpp
monomial.h
polynomial.cpp
polynomial.h
)

target_include_directories(test_polynomial PRIVATE
${ROUGHPY_PLATFORM_SOURCE}
)

target_link_libraries(test_polynomial PRIVATE
RoughPy::Core
Boost::headers
GMP::GMP
GTest::gtest
)

setup_roughpy_cpp_tests(test_polynomial)

add_executable(test_polynomial_type
test_polynomial_type.cpp
)

target_link_libraries(test_polynomial_type PRIVATE RoughPy::Platform GTest::gtest)

setup_roughpy_cpp_tests(test_polynomial_type)

endif ()
15 changes: 15 additions & 0 deletions platform/src/generics/polynomial_type/indeterminate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Created by sam on 26/11/24.
//

#include "indeterminate.h"

#include <ostream>

using namespace rpy;
using namespace rpy::generics;


std::ostream& generics::operator<<(std::ostream& os, const Indeterminate& value) {
return os << value.prefix() << value.index();
}
Loading