Skip to content

Commit

Permalink
Extended tensor operations (#61)
Browse files Browse the repository at this point in the history
* Added reverse method to PyTensorKey

* Add concatenation operator for tensor keys

* Add new header for hash functor

* add hash_value method to basis objects.

* Add hash method to PyTensorKey

* added context method to algebra types.

* added coeff lookup by key type.

* Implemented intermediate keytype lookup for lie keys

* Oops missed virtual

* Actually declare friend function in namespace

* Added basis to pytensorkey python interface

* Fixed an issue with type deduction in basis interface

* Added to_letters method to tensorkey python interface

* Added arithmetic between scalars and ints/doubles

* Moved error macros and support to platform

This allows use to have fairly complex code for producing error messages because it is hidden away in a shared library.

* add boost stacktrace to dependencies

* pass backtrace as argument to get the locality right.

* Fixed need to call function to get pointer

* Fixed a potential bug caused by trivial bytes 0

* No address of for array.

* is_mutable convenience function

* Fixed bug not assigning zero trivial bytes

* debug assertion

* Formatting

* Switch to dst_info to avoid needing a new constructor

* short circuit if lhs is zero.

* add borrowed scalar test

* Fixed argument order for r operators

* Fixed cause of segfault in scalar repr

* Add debug assertions

* Add more debug assertions

* Fix a bug that leads to unset type after copy zero

* More tests for scalars

* Adding tensor functions

* Changed implementation of eq operator for basis objects

* Added richcompare function to pycontext

* allow assigning of scalars in constructors

* Fixed a bug in is_pointer_zero

* Add test for Log

* Handle scalar arg in check_and_set_dtype

* More intelligent handling for copying from opaque pointer

* Implement assignment for owned pointers

* oops missed part

* copy interfaces as if they were opaque pointers

* use enumeration aware function

* perform a true copy on assignment from opaque pointer

* remove unused define

* formatting

* fixed semantics of assigment move operator

* Implemented ScalarMeta_call

* Raw python pointer st-pst

* preparations for moving static python scalar type

* extended tests for scalars

* finish test for adjoint

* remove print

* change type and packed pointer access

* formatting

* remove some compiler warnings

* implemented type promotion for scalars

* formatting

* update CMakeLists.txt

* various updates for debugging

* implement operators by hand

* remove debug print

* remove debug print

* Fix the implementation of divide to use type promotion

* fill out the missing promotion modes

* remove debug format function

* added docstrings

* update changelog

* Fixed incorrect type promotion in float

* relative import for init
  • Loading branch information
inakleinbottle authored Jan 22, 2024
1 parent 5ba347b commit 2e41f59
Show file tree
Hide file tree
Showing 55 changed files with 2,449 additions and 624 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Version 0.1.1:
- Fixed type promotions in scalar arithmetic - left hand types are now promoted when appropriate.
- Added "tensor_functions" module for implementing additional functions on tensors. Currently only Log is implemented.



Version 0.1.0:
- Added framework for integrating device support and redesigned scalars module to accommodate the changes.
- Made changes to type deduction in constructors to avoid exceptions when providing lists of python ints/floats.
Expand Down
1 change: 1 addition & 0 deletions algebra/include/roughpy/algebra/algebra_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <roughpy/core/macros.h>
#include <roughpy/core/types.h>
#include <roughpy/platform/errors.h>

#include <memory>
#include "roughpy_algebra_export.h"
Expand Down
205 changes: 112 additions & 93 deletions algebra/include/roughpy/algebra/basis.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <roughpy/core/hash.h>

#include <roughpy/core/traits.h>

Expand All @@ -54,15 +55,17 @@ class BasisInterface
template <typename T>
using impl_t = dtl::BasisImplementation<T, Derived>;

using base_interface_t = BasisInterface;

using mixin_t = void;

virtual ~BasisInterface() = default;

RPY_NO_DISCARD
virtual string key_to_string(const key_type& key) const = 0;
RPY_NO_DISCARD virtual string key_to_string(const key_type& key) const = 0;

RPY_NO_DISCARD virtual dimn_t dimension() const noexcept = 0;

RPY_NO_DISCARD
virtual dimn_t dimension() const noexcept = 0;
RPY_NO_DISCARD virtual bool are_same(const BasisInterface &other) const noexcept = 0;
};

namespace dtl {
Expand All @@ -85,14 +88,14 @@ class OrderedBasisInterface : public void_or_base<Base>

template <typename T>
using impl_t = dtl::OrderedBasisImplementationMixin<
T, Derived, typename Base::template impl_t<T>>;
T,
Derived,
typename Base::template impl_t<T>>;

virtual ~OrderedBasisInterface() = default;

RPY_NO_DISCARD
virtual key_type index_to_key(dimn_t index) const = 0;
RPY_NO_DISCARD
virtual dimn_t key_to_index(const key_type& key) const = 0;
RPY_NO_DISCARD virtual key_type index_to_key(dimn_t index) const = 0;
RPY_NO_DISCARD virtual dimn_t key_to_index(const key_type& key) const = 0;
};

namespace dtl {
Expand All @@ -114,40 +117,39 @@ class WordLikeBasisInterface : public void_or_base<Base>

template <typename T>
using impl_t = dtl::WordLikeBasisImplementationMixin<
T, Derived, typename Base::template impl_t<T>>;

RPY_NO_DISCARD
virtual deg_t width() const noexcept = 0;
RPY_NO_DISCARD
virtual deg_t depth() const noexcept = 0;
RPY_NO_DISCARD
virtual deg_t degree(const key_type& key) const noexcept = 0;
RPY_NO_DISCARD
virtual deg_t size(deg_t degree) const noexcept = 0;
RPY_NO_DISCARD
virtual let_t first_letter(const key_type& key) const noexcept = 0;
RPY_NO_DISCARD
virtual let_t to_letter(const key_type& key) const noexcept = 0;

RPY_NO_DISCARD
virtual dimn_t start_of_degree(deg_t degree) const noexcept = 0;
RPY_NO_DISCARD
virtual pair<optional<key_type>, optional<key_type>>
T,
Derived,
typename Base::template impl_t<T>>;

RPY_NO_DISCARD virtual deg_t width() const noexcept = 0;
RPY_NO_DISCARD virtual deg_t depth() const noexcept = 0;
RPY_NO_DISCARD virtual deg_t degree(const key_type& key) const noexcept = 0;
RPY_NO_DISCARD virtual deg_t size(deg_t degree) const noexcept = 0;
RPY_NO_DISCARD virtual let_t first_letter(const key_type& key
) const noexcept
= 0;
RPY_NO_DISCARD virtual let_t to_letter(const key_type& key) const noexcept
= 0;

RPY_NO_DISCARD virtual dimn_t start_of_degree(deg_t degree) const noexcept
= 0;
RPY_NO_DISCARD virtual pair<optional<key_type>, optional<key_type>>
parents(const key_type& key) const = 0;
RPY_NO_DISCARD
optional<key_type> lparent(const key_type& key) const
RPY_NO_DISCARD optional<key_type> lparent(const key_type& key) const
{
return parents(key).first;
}
RPY_NO_DISCARD
optional<key_type> rparent(const key_type& key) const
RPY_NO_DISCARD optional<key_type> rparent(const key_type& key) const
{
return parents(key).second;
}
RPY_NO_DISCARD
virtual key_type key_of_letter(let_t letter) const noexcept = 0;
RPY_NO_DISCARD
virtual bool letter(const key_type& key) const = 0;

RPY_NO_DISCARD virtual optional<key_type>
child(const key_type& lparent, const key_type& rparent) const = 0;

RPY_NO_DISCARD virtual key_type key_of_letter(let_t letter) const noexcept
= 0;
RPY_NO_DISCARD virtual bool letter(const key_type& key) const = 0;
};

template <typename PrimaryInterface>
Expand Down Expand Up @@ -182,78 +184,88 @@ class Basis : public PrimaryInterface::mixin_t
Basis(const Basis&) = default;
Basis(Basis&&) noexcept = default;

RPY_NO_UBSAN
~Basis() = default;
RPY_NO_UBSAN ~Basis() = default;

Basis& operator=(const Basis&) = default;
Basis& operator=(Basis&&) noexcept = default;

RPY_NO_DISCARD
const basis_interface& instance() const noexcept { return *p_impl; }
RPY_NO_DISCARD const basis_interface& instance() const noexcept
{
return *p_impl;
}

RPY_NO_DISCARD
constexpr operator bool() const noexcept { return static_cast<bool>(p_impl); }
RPY_NO_DISCARD constexpr operator bool() const noexcept
{
return static_cast<bool>(p_impl);
}

RPY_NO_DISCARD
string key_to_string(const key_type& key) const noexcept
RPY_NO_DISCARD string key_to_string(const key_type& key) const noexcept
{
return instance().key_to_string(key);
}

RPY_NO_DISCARD
dimn_t dimension() const noexcept { return instance().dimension(); }

RPY_NO_DISCARD dimn_t dimension() const noexcept
{
return instance().dimension();
}

friend bool operator==(const Basis& left, const Basis& right) noexcept
{
return left.p_impl == right.p_impl;
if (left.p_impl == right.p_impl) {
return true;
}

return left.p_impl->are_same(*right.p_impl);
}

friend bool operator!=(const Basis& left, const Basis& right) noexcept
{
return left.p_impl != right.p_impl;
return !operator==(left, right);
}

friend hash_t hash_value(const Basis& basis) noexcept
{
return hash_value(basis.p_impl);
}
};



namespace dtl {
template <
typename Derived, typename KeyType,
template <typename, typename> class... Interfaces>
typename Derived,
typename KeyType,
template <typename, typename>
class... Interfaces>
struct make_basis_interface_impl;
}

template <
typename Derived, typename KeyType,
template <typename, typename> class... Interfaces>
using make_basis_interface = typename dtl::make_basis_interface_impl<
Derived, KeyType, Interfaces...>::type;
typename Derived,
typename KeyType,
template <typename, typename>
class... Interfaces>
using make_basis_interface = typename dtl::
make_basis_interface_impl<Derived, KeyType, Interfaces...>::type;

namespace dtl {

template <typename Derived, typename Base>
class OrderedBasisMixin : public Base
{

RPY_NO_DISCARD
const Derived& instance() const noexcept
RPY_NO_DISCARD const Derived& instance() const noexcept
{
return static_cast<const Basis<Derived>*>(this)->instance();
}

public:
using key_type = typename Derived::key_type;

RPY_NO_DISCARD
key_type index_to_key(dimn_t index) const
RPY_NO_DISCARD key_type index_to_key(dimn_t index) const
{
return instance().index_to_key(index);
}

RPY_NO_DISCARD
dimn_t key_to_index(const key_type& key) const
RPY_NO_DISCARD dimn_t key_to_index(const key_type& key) const
{
return instance().key_to_index(key);
}
Expand All @@ -263,70 +275,77 @@ template <typename Derived, typename Base>
class WordLikeBasisMixin
{

RPY_NO_DISCARD
const Derived& instance() const noexcept
RPY_NO_DISCARD const Derived& instance() const noexcept
{
return static_cast<const Basis<Derived>*>(this)->instance();
}

public:
using key_type = typename Derived::key_type;

RPY_NO_DISCARD
deg_t width() const noexcept { return instance().width(); }
RPY_NO_DISCARD
deg_t depth() const noexcept { return instance().depth(); }
RPY_NO_DISCARD
deg_t degree(const key_type& key) const noexcept
RPY_NO_DISCARD deg_t width() const noexcept { return instance().width(); }
RPY_NO_DISCARD deg_t depth() const noexcept { return instance().depth(); }
RPY_NO_DISCARD deg_t degree(const key_type& key) const noexcept
{
return instance().degree(key);
}
RPY_NO_DISCARD
deg_t size(deg_t degree) const noexcept { return instance().size(degree); }
RPY_NO_DISCARD
let_t first_letter(const key_type& key) const noexcept
RPY_NO_DISCARD deg_t size(deg_t degree) const noexcept
{
return instance().size(degree);
}
RPY_NO_DISCARD let_t first_letter(const key_type& key) const noexcept
{
return instance().first_letter(key);
}
RPY_NO_DISCARD let_t to_letter(const key_type& key) const noexcept {
RPY_NO_DISCARD let_t to_letter(const key_type& key) const noexcept
{
return instance().to_letter(key);
}
RPY_NO_DISCARD
dimn_t start_of_degree(deg_t degree) const noexcept
RPY_NO_DISCARD dimn_t start_of_degree(deg_t degree) const noexcept
{
return instance().start_of_degree(degree);
}
RPY_NO_DISCARD
pair<optional<key_type>, optional<key_type>> parents(const key_type& key
) const
RPY_NO_DISCARD pair<optional<key_type>, optional<key_type>>
parents(const key_type& key) const
{
return instance().parents(key);
}
RPY_NO_DISCARD
optional<key_type> lparent(const key_type& key) const
RPY_NO_DISCARD optional<key_type> lparent(const key_type& key) const
{
return instance().lparent(key);
}
RPY_NO_DISCARD
optional<key_type> rparent(const key_type& key) const
RPY_NO_DISCARD optional<key_type> rparent(const key_type& key) const
{
return instance().rparent(key);
}
RPY_NO_DISCARD
key_type key_of_letter(let_t letter) const noexcept
RPY_NO_DISCARD optional<key_type>
child(const key_type& lparent, const key_type& rparent) const
{
return instance().child(lparent, rparent);
}

RPY_NO_DISCARD key_type key_of_letter(let_t letter) const noexcept
{
return instance().key_of_letter(letter);
}
RPY_NO_DISCARD
bool letter(const key_type& key) const { return instance().letter(key); }
RPY_NO_DISCARD bool letter(const key_type& key) const
{
return instance().letter(key);
}
};

template <
typename Derived, typename KeyType,
template <typename, typename> class FirstInterface,
template <typename, typename> class... Interfaces>
typename Derived,
typename KeyType,
template <typename, typename>
class FirstInterface,
template <typename, typename>
class... Interfaces>
struct make_basis_interface_impl<
Derived, KeyType, FirstInterface, Interfaces...> {
Derived,
KeyType,
FirstInterface,
Interfaces...> {
using next_t = make_basis_interface_impl<Derived, KeyType, Interfaces...>;
using type = FirstInterface<Derived, typename next_t::type>;
};
Expand Down
Loading

0 comments on commit 2e41f59

Please sign in to comment.