Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
98bb938
Move ExprPtr related things to expr_ptr.cpp
Krzmbrzl Aug 12, 2026
788c8ba
Also separate impl of Constant to dedicated file
Krzmbrzl Aug 12, 2026
516504d
Remove in-place arithmetic operators from Expr interface
Krzmbrzl Aug 12, 2026
7c0211d
Make certain Expr API functions pure virtual
Krzmbrzl Aug 12, 2026
0f7724a
Fix error message assembly
Krzmbrzl Aug 12, 2026
926eca9
Clean up Variable impl
Krzmbrzl Aug 12, 2026
5279d12
Clean up Power impl
Krzmbrzl Aug 12, 2026
8e476fc
Add declaration of specialization of NormalOperator::labels()
Krzmbrzl Aug 12, 2026
873e0f1
Remove outdated comments
Krzmbrzl Aug 17, 2026
0bb04be
Make Product::operator* non-virtual
Krzmbrzl Aug 17, 2026
06c0b93
Reset memoized hash after modification
Krzmbrzl Aug 17, 2026
e37010c
Remove declaration of non-existent function
Krzmbrzl Aug 17, 2026
6ac7b1a
Separate Product impl
Krzmbrzl Aug 17, 2026
0fb64e5
Cleanly separate public and private interface
Krzmbrzl Aug 17, 2026
6e6b625
Cleanly separate (N)CProduct impl
Krzmbrzl Aug 17, 2026
6120935
Move some headers to impl file
Krzmbrzl Aug 17, 2026
94b967e
Remove redundant swap function
Krzmbrzl Aug 17, 2026
1dd0734
Add missing header
Krzmbrzl Aug 17, 2026
2d90288
Separate Sum impl
Krzmbrzl Aug 17, 2026
8f2f145
Remove redundant headers
Krzmbrzl Aug 17, 2026
92c8eeb
Add back missing header
Krzmbrzl Aug 17, 2026
92354e0
Replace virtual clone with virtual unique_copy
Krzmbrzl Aug 17, 2026
4e150e4
Add more arithmetic operators for Constants
Krzmbrzl Aug 17, 2026
0f5a767
Fix unused variable warning
Krzmbrzl Aug 17, 2026
09cace5
Add and use Expr & overloads
Krzmbrzl Aug 17, 2026
93dda4a
Deprecate {shared,weak}_from_this
Krzmbrzl Aug 17, 2026
d644b7a
Implement ExprContainer
Krzmbrzl Aug 17, 2026
08b1d51
Suppress deprecated warnings
Krzmbrzl Aug 18, 2026
c5fcbbd
Implement support for non-commuting product for ExprContainer
Krzmbrzl Aug 18, 2026
146f4d6
Allow unique_ptr to be moved out of ExprContainer
Krzmbrzl Aug 18, 2026
5496e24
Add ExprContainer::operator* dereferencing to Expr &&
Krzmbrzl Aug 18, 2026
4a651e7
Make ExprContainer iterable
Krzmbrzl Aug 18, 2026
a1d0df0
Ensure specialized arithmetic operators only apply to ExprPtr ignorin…
Krzmbrzl Aug 18, 2026
30fed00
Disambiguate arithmetic ops involving ExprContainer
Krzmbrzl Aug 18, 2026
22feea5
Enable conversions from ExprContainer to ExprPtr
Krzmbrzl Aug 18, 2026
6c2a524
Fix deprecation warning in test_expr
Krzmbrzl Aug 18, 2026
a0c1701
Add ExprContainer to fwd declarations
Krzmbrzl Aug 18, 2026
a65e1ba
Enable ExprPtr -> ExprContainer conversion
Krzmbrzl Aug 18, 2026
0b58236
Include supporting header
Krzmbrzl Aug 18, 2026
1abcf20
Consistently use operator->
Krzmbrzl Aug 18, 2026
9a3bd74
Add expr_holder concept
Krzmbrzl Aug 18, 2026
4bbeede
Make ExprContainer comparable with ExprPtr
Krzmbrzl Aug 18, 2026
de2ef0a
Add not-null assertion
Krzmbrzl Aug 18, 2026
6f96a42
Switch Power to using ExprContainer
Krzmbrzl Aug 18, 2026
2d2a994
Get rid of unnecessary heap allocations
Krzmbrzl Aug 18, 2026
7955bbd
Use C++ templating facilities
Krzmbrzl Aug 18, 2026
726ab37
Change Sum::filter to use predicate on cosnt Expr &
Krzmbrzl Aug 18, 2026
96d4c94
Use Catch2 sections instead of comments
Krzmbrzl Aug 18, 2026
aec0a07
Add Expr::proportional_to(const Expr &, const Expr &) overload
Krzmbrzl Aug 20, 2026
07db221
Move begin/end impl to cpp file (and fix it)
Krzmbrzl Aug 20, 2026
52aede3
Use fwd decl of Expr
Krzmbrzl Aug 20, 2026
d5ecd7f
Define ExprContainerList
Krzmbrzl Aug 20, 2026
09828aa
Add free-standing adjoint() overload for ExprContainer
Krzmbrzl Aug 20, 2026
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
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -306,16 +306,30 @@ set(SeQuant_symb_src
SeQuant/core/context.hpp
SeQuant/core/expressions/abstract_tensor.cpp
SeQuant/core/expressions/abstract_tensor.hpp
SeQuant/core/expressions/constant.cpp
SeQuant/core/expressions/constant.hpp
SeQuant/core/expressions/expr.cpp
SeQuant/core/expressions/expr.hpp
SeQuant/core/expressions/expr_algorithms.cpp
SeQuant/core/expressions/expr_algorithms.hpp
SeQuant/core/expressions/expr_container.cpp
SeQuant/core/expressions/expr_container.hpp
SeQuant/core/expressions/expr_operators.hpp
SeQuant/core/expressions/expr_ptr.cpp
SeQuant/core/expressions/expr_ptr.hpp
SeQuant/core/expressions/expr_range.hpp
SeQuant/core/expressions/power.cpp
SeQuant/core/expressions/power.hpp
SeQuant/core/expressions/product.cpp
SeQuant/core/expressions/product.hpp
SeQuant/core/expressions/result_expr.cpp
SeQuant/core/expressions/result_expr.hpp
SeQuant/core/expressions/sum.cpp
SeQuant/core/expressions/sum.hpp
SeQuant/core/expressions/tensor.cpp
SeQuant/core/expressions/tensor.hpp
SeQuant/core/expressions/variable.cpp
SeQuant/core/expressions/variable.hpp
SeQuant/core/hash.cpp
SeQuant/core/hash.hpp
SeQuant/core/hugenholtz.hpp
Expand Down
24 changes: 12 additions & 12 deletions SeQuant/core/export/export.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,10 +539,10 @@ void track_usage(const EvalNode<T> &node, PreprocessResult &result) {
handle_variable(expr.as<Variable>());
} else if (expr.is<Power>()) {
const Power &power = expr.as<Power>();
if (power.base().is<Tensor>()) {
handle_tensor(power.base().as<Tensor>());
} else if (power.base().is<Variable>()) {
handle_variable(power.base().as<Variable>());
if (power.base()->is<Tensor>()) {
handle_tensor(power.base()->as<Tensor>());
} else if (power.base()->is<Variable>()) {
handle_variable(power.base()->as<Variable>());
}
}
}
Expand Down Expand Up @@ -762,10 +762,10 @@ class PreprocessVisitor {
handle_variable(node.left()->as_variable());
} else if (node.left()->is_power()) {
const Power &power = node.left()->as_power();
if (power.base().is<Tensor>()) {
handle_tensor(power.base().as<Tensor>());
} else if (power.base().is<Variable>()) {
handle_variable(power.base().as<Variable>());
if (power.base()->is<Tensor>()) {
handle_tensor(power.base()->as<Tensor>());
} else if (power.base()->is<Variable>()) {
handle_variable(power.base()->as<Variable>());
}
}

Expand All @@ -775,10 +775,10 @@ class PreprocessVisitor {
handle_variable(node.right()->as_variable());
} else if (node.right()->is_power()) {
const Power &power = node.right()->as_power();
if (power.base().is<Tensor>()) {
handle_tensor(power.base().as<Tensor>());
} else if (power.base().is<Variable>()) {
handle_variable(power.base().as<Variable>());
if (power.base()->is<Tensor>()) {
handle_tensor(power.base()->as<Tensor>());
} else if (power.base()->is<Variable>()) {
handle_variable(power.base()->as<Variable>());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion SeQuant/core/export/itf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class ItfGenerator : public Generator<Context> {
}

std::string represent(const Power &power, const Context &ctx) const override {
const ExprPtr &base = power.base();
const ExprContainer &base = power.base();
// ITF can only express powers of Constants
if (!base->is<Constant>()) {
throw Exception(
Expand Down
2 changes: 1 addition & 1 deletion SeQuant/core/export/julia_tensor_operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class JuliaTensorOperationsGenerator : public Generator<Context> {
}

std::string represent(const Power &power, const Context &ctx) const override {
const ExprPtr &base = power.base();
const ExprContainer &base = power.base();
std::string base_str = to_julia_expr(*base, ctx);
if (base->is<Variable>() && base->as<Variable>().conjugated()) {
base_str = wrap_conj(std::move(base_str));
Expand Down
2 changes: 1 addition & 1 deletion SeQuant/core/export/python_einsum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class PythonEinsumGeneratorBase : public Generator<Context> {
}

std::string represent(const Power &power, const Context &ctx) const override {
const ExprPtr &base = power.base();
const ExprContainer &base = power.base();
std::string base_str = stringify_scalar(*base, ctx);
if (base->is<Variable>() && base->as<Variable>().conjugated()) {
base_str = wrap_conj(std::move(base_str));
Expand Down
2 changes: 1 addition & 1 deletion SeQuant/core/export/text_generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class TextGenerator : public Generator<Context> {
}

std::string represent(const Power &power, const Context &ctx) const override {
const ExprPtr &base = power.base();
const ExprContainer &base = power.base();
std::string base_str = stringify(*base, ctx);
if (base->is<Variable>() && base->as<Variable>().conjugated()) {
base_str = wrap_conj(std::move(base_str));
Expand Down
5 changes: 2 additions & 3 deletions SeQuant/core/export/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

#include <SeQuant/core/export/utils.hpp>

#include <SeQuant/core/expressions/constant.hpp>
#include <SeQuant/core/expressions/expr.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/rational.hpp>

#include <sstream>
Expand All @@ -30,7 +29,7 @@ std::string format_power_exponent(const Power::exponent_type &exponent,
return ss.str();
}

std::string format_power_base(const ExprPtr &base, std::string base_str) {
std::string format_power_base(const ExprContainer &base, std::string base_str) {
if (base->is<Constant>()) {
const auto &v = base->as<Constant>().value();
if (v.imag() == 0 &&
Expand Down
6 changes: 2 additions & 4 deletions SeQuant/core/export/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#ifndef SEQUANT_CORE_EXPORT_UTILS_HPP
#define SEQUANT_CORE_EXPORT_UTILS_HPP

#include <SeQuant/core/expr_fwd.hpp>
#include <SeQuant/core/expressions/expr_ptr.hpp>
#include <SeQuant/core/expressions/power.hpp>
#include <SeQuant/core/expr.hpp>

#include <string>

Expand All @@ -27,7 +25,7 @@ std::string format_power_exponent(const Power::exponent_type &exponent,
/// @param base_str @p base already rendered to a string by the caller
/// @return @p base_str, wrapped in parens iff @p base is a Constant whose
/// value is a non-integer or negative real
std::string format_power_base(const ExprPtr &base, std::string base_str);
std::string format_power_base(const ExprContainer &base, std::string base_str);

} // namespace sequant::detail

Expand Down
1 change: 1 addition & 0 deletions SeQuant/core/expr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <SeQuant/core/expressions/constant.hpp>
#include <SeQuant/core/expressions/expr.hpp>
#include <SeQuant/core/expressions/expr_algorithms.hpp>
#include <SeQuant/core/expressions/expr_container.hpp>
#include <SeQuant/core/expressions/expr_iterator.hpp>
#include <SeQuant/core/expressions/expr_operators.hpp>
#include <SeQuant/core/expressions/expr_ptr.hpp>
Expand Down
1 change: 1 addition & 0 deletions SeQuant/core/expr_fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace sequant {
class Expr;
class ResultExpr;
class ExprPtr;
class ExprContainer;

class Labeled;
class Constant;
Expand Down
117 changes: 117 additions & 0 deletions SeQuant/core/expressions/constant.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include <SeQuant/core/expressions/constant.hpp>
#include <SeQuant/core/expressions/expr_ptr.hpp>
#include <SeQuant/core/io/latex/latex.hpp>
#include <SeQuant/core/utility/exception.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <memory>

namespace sequant {

std::wstring Constant::to_latex() const {
return L"{" + io::latex::to_string(value()) + L"}";
}

Expr::type_id_type Constant::type_id() const { return get_type_id<Constant>(); }

bool Constant::is_scalar() const { return true; }

void Constant::adjoint() {
value_ = conj(value_);
reset_hash_value();
}

Constant &Constant::operator*=(const Constant &that) {
value_ *= that.value();

reset_hash_value();

return *this;
}

Constant &Constant::operator*=(const Expr &that) {
if (!that.is<Constant>()) {
throw Exception("Constant::operator*=(that): not valid for that");
}

return *this *= that.as<Constant>();
}

Constant &Constant::operator+=(const Constant &that) {
value_ += that.value();

reset_hash_value();

return *this;
}

Constant &Constant::operator+=(const Expr &that) {
if (!that.is<Constant>()) {
throw Exception("Constant::operator+=(that): not valid for that");
}

return *this += that.as<Constant>();
}

Constant &Constant::operator-=(const Constant &that) {
value_ -= that.value();

reset_hash_value();

return *this;
}

Constant &Constant::operator-=(const Expr &that) {
if (!that.is<Constant>()) {
throw Exception("Constant::operator-=(that): not valid for that");
}

return *this -= that.as<Constant>();
}

bool Constant::is_zero(scalar_type v) { return v.is_zero(); }

bool Constant::is_zero() const { return is_zero(this->value()); }

std::unique_ptr<Expr> Constant::unique_copy() const {
return std::make_unique<Constant>(this->value());
}

Expr::hash_type Constant::memoizing_hash() const {
if (!hash_value_) {
hash_value_ = hash::value(value_);
} else {
SEQUANT_ASSERT(*hash_value_ == hash::value(value_));
}
return *hash_value_;
}

bool Constant::static_equal(const Expr &that) const {
return value() == static_cast<const Constant &>(that).value();
}

Constant operator*(const Constant &lhs, const Constant &rhs) {
Constant result(lhs);

result *= rhs;

return result;
}

Constant operator+(const Constant &lhs, const Constant &rhs) {
Constant result(lhs);

result += rhs;

return result;
}

Constant operator-(const Constant &lhs, const Constant &rhs) {
Constant result(lhs);

result -= rhs;

return result;
}

} // namespace sequant
70 changes: 24 additions & 46 deletions SeQuant/core/expressions/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@

#include <SeQuant/core/complex.hpp>
#include <SeQuant/core/expressions/expr.hpp>
#include <SeQuant/core/expressions/expr_ptr.hpp>
#include <SeQuant/core/io/latex/latex.hpp>
#include <SeQuant/core/rational.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <boost/numeric/conversion/cast.hpp>

#include <memory>
#include <string>

namespace sequant {

class ExprPtr;

// implementation details of Constant; prefer sequant::detail over an unnamed
// namespace in a header (see CppCoreGuidelines SF.21)
namespace detail {
Expand Down Expand Up @@ -67,70 +68,47 @@ class Constant : public Expr {
throw Exception("Constant::value<T>: cannot convert value to type T");
}

std::wstring to_latex() const override {
return L"{" + io::latex::to_string(value()) + L"}";
}

type_id_type type_id() const override { return get_type_id<Constant>(); }
std::wstring to_latex() const override;

bool is_scalar() const override { return true; }
type_id_type type_id() const override;

ExprPtr clone() const override { return ex<Constant>(this->value()); }
bool is_scalar() const override;

/// @brief adjoint of a Constant is its complex conjugate
virtual void adjoint() override;

virtual Expr &operator*=(const Expr &that) override {
if (that.is<Constant>()) {
value_ *= that.as<Constant>().value();
} else {
throw Exception("Constant::operator*=(that): not valid for that");
}
return *this;
}
Constant &operator*=(const Constant &that);
Constant &operator*=(const Expr &that);

virtual Expr &operator+=(const Expr &that) override {
if (that.is<Constant>()) {
value_ += that.as<Constant>().value();
} else {
throw Exception("Constant::operator+=(that): not valid for that");
}
return *this;
}
Constant &operator+=(const Constant &that);
Constant &operator+=(const Expr &that);

virtual Expr &operator-=(const Expr &that) override {
if (that.is<Constant>()) {
value_ -= that.as<Constant>().value();
} else {
throw Exception("Constant::operator-=(that): not valid for that");
}
return *this;
}
Constant &operator-=(const Constant &that);
Constant &operator-=(const Expr &that);

/// @param[in] v a scalar
/// @return true if this is zero
static bool is_zero(scalar_type v) { return v.is_zero(); }
static bool is_zero(scalar_type v);

/// @return `Constant::is_zero(this->value())`
bool is_zero() const final { return is_zero(this->value()); }
bool is_zero() const final;

protected:
std::unique_ptr<Expr> unique_copy() const override;

private:
scalar_type value_;

hash_type memoizing_hash() const override {
if (!hash_value_) {
hash_value_ = hash::value(value_);
} else {
SEQUANT_ASSERT(*hash_value_ == hash::value(value_));
}
return *hash_value_;
}
hash_type memoizing_hash() const override;

bool static_equal(const Expr &that) const override;

bool static_equal(const Expr &that) const override {
return value() == static_cast<const Constant &>(that).value();
}
}; // class Constant

Constant operator*(const Constant &lhs, const Constant &rhs);
Constant operator+(const Constant &lhs, const Constant &rhs);
Constant operator-(const Constant &lhs, const Constant &rhs);

} // namespace sequant

#endif // SEQUANT_EXPRESSIONS_CONSTANT_HPP
Loading
Loading