LIBINT 2.9.0
algebra.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint compiler.
5 *
6 * Libint compiler is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint compiler is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Libint compiler. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef _libint2_src_bin_libint_algebra_h_
22#define _libint2_src_bin_libint_algebra_h_
23
24#include <class_registry.h>
25#include <dgvertex.h>
26#include <exception.h>
27#include <global_macros.h>
28#include <rr.h>
29#include <smart_ptr.h>
30
31namespace libint2 {
32
33namespace algebra {
35 typedef enum { Plus, Minus, Times, Divide } OperatorType;
36};
37static const char OperatorSymbol[][2] = {"+", "-", "*", "/"};
38}; // namespace algebra
39
46template <class T>
48 public:
50 typedef algebra::OperatorTypes::OperatorType OperatorType;
51
52 AlgebraicOperator(OperatorType OT, const std::shared_ptr<T>& left,
53 const std::shared_ptr<T>& right)
55 OT_(OT),
56 left_(left),
57 right_(right),
58 label_(algebra::OperatorSymbol[OT_]) {}
59 virtual ~AlgebraicOperator() {}
60
62 AlgebraicOperator(const std::shared_ptr<AlgebraicOperator>& A,
63 const std::shared_ptr<T>& left,
64 const std::shared_ptr<T>& right)
65 : DGVertex(static_cast<DGVertex&>(*A)),
66 OT_(A->OT_),
67 left_(left),
68 right_(right),
69 label_(A->label_) {
70#if DEBUG
71 if (num_exit_arcs() != 2)
72 std::cout << "AlgebraicOperator<DGVertex> copy constructor: number of "
73 "children != 2"
74 << std::endl;
75 else {
76 typedef DGVertex::ArcSetType::const_iterator aciter;
77 aciter a = this->first_exit_arc();
78 auto left_arg = (*a)->dest();
79 ++a;
80 auto right_arg = (*a)->dest();
81
82 if (left_ != left_arg && left_ != right_arg)
83 std::cout << "AlgebraicOperator<DGVertex> copy constructor: invalid "
84 "left operand given"
85 << std::endl;
86 if (right_ != left_arg && right_ != right_arg)
87 std::cout << "AlgebraicOperator<DGVertex> copy constructor: invalid "
88 "right operand given"
89 << std::endl;
90 }
91#endif
92 }
93
95 OperatorType type() const { return OT_; }
97 const std::shared_ptr<T>& left() const { return left_; }
99 const std::shared_ptr<T>& right() const { return right_; }
100
103 void add_exit_arc(const std::shared_ptr<DGArc>& a) override;
105 unsigned int size() const override { return 1; }
107 bool equiv(const std::shared_ptr<DGVertex>& a) const override {
108 if (typeid_ == a->typeid_) {
109#if ALGEBRAICOPERATOR_USE_KEY_TO_COMPARE
110#if USE_INT_KEY_TO_COMPARE
111 if (key() == a->key())
112 return *this ==
113 std::static_pointer_cast<AlgebraicOperator, DGVertex>(a);
114 else
115 return false;
116#else
117 return description() == a->description();
118#endif
119#else
120 return *this == std::static_pointer_cast<AlgebraicOperator, DGVertex>(a);
121#endif
122 } else
123 return false;
124 }
125
127 bool operator==(const std::shared_ptr<AlgebraicOperator>& a) const {
128#if ALGEBRAICOPERATOR_USE_SHAREDPTR
129 // Find out why sometimes equivalent left_ and a->left_ have non-equivalent
130 // pointers
131 if (left_->equiv(a->left()) && left_ != a->left_) {
132 std::cout << "Left arguments are equivalent but pointers differ!"
133 << std::endl;
134 std::cout << left_->description() << std::endl;
135 std::cout << a->left_->description() << std::endl;
136 }
137 // Find out why sometimes equivalent right_ and a->right_ have
138 // non-equivalent pointers
139 if (right_->equiv(a->right()) && right_ != a->right_) {
140 std::cout << "Left arguments are equivalent but pointers differ!"
141 << std::endl;
142 std::cout << right_->description() << std::endl;
143 std::cout << a->right_->description() << std::endl;
144 }
145#endif
146 if (OT_ == a->OT_) {
147#if ALGEBRAICOPERATOR_USE_SHAREDPTR
148 if (left_ == a->left_ && right_ == a->right_)
149#else
150 if (left_->equiv(a->left()) && right_->equiv(a->right()))
151#endif
152 return true;
153 else
154 return false;
155 } else
156 return false;
157 }
158
160 const std::string& label() const override { return label_; }
162 const std::string& id() const override { return label(); }
164 std::string description() const override {
165 std::ostringstream os;
166 os << "( ( " << left_->description() << " ) "
167 << algebra::OperatorSymbol[OT_] << " ( " << right_->description()
168 << " ) )";
169 const std::string descr = os.str();
170 return descr;
171 }
172
174 void del_exit_arcs() override {
175 throw CannotAddArc(
176 "AlgebraicOperator::del_exit_arcs() -- cannot safely use del_exit_arcs "
177 "on operator vertices.");
178 }
179
181 typename DGVertex::KeyReturnType key() const override { return 0; }
182
183 void print(std::ostream& os) const override {
184 DGVertex::print(os);
185 std::string prefix("AlgebraicOperator::print: ");
186 os << prefix << "this = " << this << std::endl;
187 os << prefix << "left_ = " << left_ << std::endl;
188 os << prefix << "right_ = " << right_ << std::endl;
189 }
190
191 private:
192 OperatorType OT_;
193 std::shared_ptr<T> left_;
194 std::shared_ptr<T> right_;
195
197 bool this_precomputed() const override { return false; }
198
199 std::string label_;
200};
201
202/*
203template <>
204 void
205 AlgebraicOperator<DGVertex>::add_exit_arc(const std::shared_ptr<DGArc>& a)
206 {
207 DGVertex::add_exit_arc(a);
208 if (left_->equiv(a->dest()))
209 left_ = a->dest();
210 else if (right_->equiv(a->dest()))
211 right_ = a->dest();
212 else
213 throw std::runtime_error("AlgebraicOperator<DGVertex>::add_exit_arc --
214trying to add an arc to a vertex not equivalent to either argument.");
215 }
216*/
217
221template <class C, class T>
223 public:
224 typedef std::pair<C, T> term_t;
225 typedef std::vector<term_t> data_t;
226
228 // shallow copy constructor -- used by operator^
229 LinearCombination(data_t* data) {
230 swap(*data, data_);
231 delete data;
232 }
233
234 LinearCombination& operator+=(const term_t& t) {
235 data_.push_back(t);
236 return *this;
237 }
238 size_t size() const { return data_.size(); }
239 const term_t& operator[](unsigned int i) const { return data_[i]; }
240
241 private:
242 data_t data_;
243};
244
245namespace algebra {
247template <class L, class R>
248struct Wedge {
249 Wedge(const L& l, const R& r) : left(l), right(r) {}
250 L left;
251 R right;
252};
253template <class L, class R>
254Wedge<L, R> make_wedge(const L& l, const R& r) {
255 return Wedge<L, R>(l, r);
256}
257
259template <class C, class Tl, class Tr>
260typename LinearCombination<C, Wedge<Tl, Tr> >::term_t wedge(
261 const std::pair<C, Tl>& L, const std::pair<C, Tr>& R) {
262 return make_pair(L.first * R.first, L.second ^ R.second);
263}
264} // namespace algebra
265
266template <class C, class Tl, class Tr>
267typename LinearCombination<C, algebra::Wedge<Tl, Tr> >::data_t* operator^(
268 const LinearCombination<C, Tl>& L, const LinearCombination<C, Tr>& R) {
269 typedef typename LinearCombination<C, algebra::Wedge<Tl, Tr> >::data_t data_t;
270 data_t* result = new data_t;
271 const size_t nL = L.size();
272 const size_t nR = R.size();
273 for (unsigned int l = 0; l < nL; ++l)
274 for (unsigned int r = 0; r < nR; ++r) {
275 result->push_back(algebra::wedge(L[l], R[r]));
276 }
277 return result;
278}
279
280template <class C, class Tl, class Tr>
281typename LinearCombination<C, algebra::Wedge<Tl, Tr> >::data_t* operator^(
282 const Tl& L, const LinearCombination<C, Tr>& R) {
283 typedef typename LinearCombination<C, algebra::Wedge<Tl, Tr> >::data_t data_t;
284 data_t* result = new data_t;
285 const size_t nR = R.size();
286 for (unsigned int r = 0; r < nR; ++r) {
287 result->push_back(L ^ R[r]);
288 }
289 return result;
290}
291
292}; // namespace libint2
293
294#endif
AlgebraicOperator is an algebraic operator that acts on objects of type T.
Definition algebra.h:47
const std::string & id() const override
Implements DGVertex::id()
Definition algebra.h:162
bool equiv(const std::shared_ptr< DGVertex > &a) const override
Implements DGVertex::equiv()
Definition algebra.h:107
const std::string & label() const override
Implements DGVertex::label()
Definition algebra.h:160
void del_exit_arcs() override
Overloads DGVertex::del_exit_arcs()
Definition algebra.h:174
bool operator==(const std::shared_ptr< AlgebraicOperator > &a) const
laboriously compare 2 operators element by element
Definition algebra.h:127
const std::shared_ptr< T > & right() const
Returns the right argument.
Definition algebra.h:99
std::string description() const override
Implements DGVertex::description()
Definition algebra.h:164
unsigned int size() const override
Implements DGVertex::size()
Definition algebra.h:105
void add_exit_arc(const std::shared_ptr< DGArc > &a) override
Overloads DGVertex::add_exit_arc().
const std::shared_ptr< T > & left() const
Returns the left argument.
Definition algebra.h:97
OperatorType type() const
Returns the OperatorType.
Definition algebra.h:95
void print(std::ostream &os) const override
print(os) prints vertex info to os
Definition algebra.h:183
DGVertex::KeyReturnType key() const override
Implements Hashable::key()
Definition algebra.h:181
AlgebraicOperator(const std::shared_ptr< AlgebraicOperator > &A, const std::shared_ptr< T > &left, const std::shared_ptr< T > &right)
Clone A but replace operands with left and right.
Definition algebra.h:62
Definition exception.h:37
Objects of this type provide limited information about the class at runtime.
Definition class_registry.h:46
This is a vertex of a Directed Graph (DG)
Definition dgvertex.h:44
ClassID typeid_
typeid stores the ClassID of the concrete type.
Definition dgvertex.h:71
unsigned int num_exit_arcs() const
returns the number of children
Definition dgvertex.cc:254
DGVertex(ClassID tid)
Sets typeid to tid.
Definition dgvertex.cc:32
ArcSetType::const_iterator first_exit_arc() const
returns children::begin()
Definition dgvertex.h:124
virtual void print(std::ostream &os) const
print(os) prints vertex info to os
Definition dgvertex.cc:433
represents linear combination of objects of type T with coefficients of type C
Definition algebra.h:222
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
Definition algebra.h:34
Wedge is a typeholder for the result of a wedge product.
Definition algebra.h:248