SXEval 1.0.3
A generic s-expression interpreter library.
Loading...
Searching...
No Matches
OperationsFactory.hpp
Go to the documentation of this file.
1
2#ifndef SXEVAL_OPERATIONS_HPP
3#define SXEVAL_OPERATIONS_HPP
4
60#include <memory>
61#include <unordered_map>
62#include <string>
63#include <stdexcept>
64#include <functional>
65#include <sstream>
66
67
68/* DEFINITIONS */
69
70namespace sxeval {
71namespace operations {
72
80template <typename T>
82public:
87
95 template <typename OP>
96 typename std::enable_if<std::is_base_of<sxeval::AOperation<T>, OP>::value>
97 ::type
98 add();
99
109 std::unique_ptr<AOperation<T>> create(const std::string& key,
110 const std::vector<IInstruction<T>*> args);
111
121 T compute(const std::string& key, const std::vector<IInstruction<T>*> args)
122 const;
123
124private:
125 std::unordered_map<std::string,
126 const std::function<std::unique_ptr<AOperation<T>>(
127 const std::vector<IInstruction<T>*>&)>> _operations;
128
129};
130
131} /* namespace operations */
132} /* namespace sxeval */
133
134
135/* IMPLEMENTATIONS */
136
137template <typename T>
139 add<Addition<T>>();
140 add<Subtraction<T>>();
141 add<Multiplication<T>>();
142 add<Division<T>>();
143 add<Modulo<T>>();
144 add<Exponentiation<T>>();
145 add<Equal<T>>();
146 add<NotEqual<T>>();
147 add<Less<T>>();
148 add<Greater<T>>();
149 add<LessOrEqual<T>>();
150 add<GreaterOrEqual<T>>();
151 add<LogicalAnd<T>>();
152 add<LogicalOr<T>>();
153 add<LogicalNot<T>>();
154 add<LogicalXor<T>>();
155 add<LogicalXnor<T>>();
156 add<LogicalNand<T>>();
157 add<LogicalNor<T>>();
158 add<AbsoluteValue<T>>();
159 add<Average<T>>();
160 add<Ceiling<T>>();
161 add<Expm1<T>>();
162 add<Exp<T>>();
163 add<Floor<T>>();
164 add<Hypotenuse<T>>();
165 add<NaturalLogarithm<T>>();
166 add<Logarithm<T>>();
167 add<Logarithm10<T>>();
168 add<Logarithm1p<T>>();
169 add<Logarithm2<T>>();
170 add<LogarithmB<T>>();
171 add<Maximum<T>>();
172 add<Minimum<T>>();
173 add<Round<T>>();
174 add<SquareRoot<T>>();
175 add<Truncate<T>>();
176 add<ArcCosine<T>>();
177 add<ArcCosh<T>>();
178 add<ArcSine<T>>();
179 add<ArcSinh<T>>();
180 add<ArcTangent<T>>();
181 add<ArcTangent2<T>>();
182 add<ArcTanh<T>>();
183 add<Cosine<T>>();
184 add<Cosh<T>>();
185 add<Sine<T>>();
186 add<Sinh<T>>();
187 add<Tangent<T>>();
188 add<Tanh<T>>();
189 add<DegreesToRadians<T>>();
190 add<RadiansToDegrees<T>>();
191 add<DegreesToGradians<T>>();
192 add<GradiansToDegrees<T>>();
193}
194
195template <typename T>
196template <typename OP>
197typename std::enable_if<std::is_base_of<sxeval::AOperation<T>, OP>::value>::type
199 if (_operations.find(OP::KEY) != _operations.end()) {
200 _operations.erase(OP::KEY);
201 }
202 const std::function<std::unique_ptr<AOperation<T>>(
203 const std::vector<IInstruction<T>*>&)> f =
204 [](const std::vector<IInstruction<T>*>& args) {
205 const auto nargs = static_cast<int>(args.size());
206 if (nargs < OP::ARITY_MIN) {
207 std::ostringstream oss;
208 oss << "Operation " << OP::KEY << " requires at least "
209 << OP::ARITY_MIN << " arguments";
210 throw std::invalid_argument(oss.str());
211 }
212 if (OP::ARITY_MAX != AOperation<T>::UNLIMITED_ARITY
213 && nargs > OP::ARITY_MAX)
214 {
215 std::ostringstream oss;
216 oss << "Operation " << OP::KEY << " requires at most "
217 << OP::ARITY_MAX << " arguments";
218 throw std::invalid_argument(oss.str());
219 }
220 return std::unique_ptr<AOperation<T>>(new OP(args));
221 };
222 _operations.insert(std::make_pair(OP::KEY, f));
223}
224
225template <typename T>
226std::unique_ptr<sxeval::AOperation<T>>
228 const std::string& key, const std::vector<sxeval::IInstruction<T>*> args)
229{
230 const auto it = _operations.find(key);
231 if (it == _operations.end()) {
232 throw std::invalid_argument("Unknown operation key: " + key);
233 }
234 return it->second(args);
235}
236
237template <typename T>
239 const std::string& key, const std::vector<sxeval::IInstruction<T>*> args
240) const {
241 const auto it = _operations.find(key);
242 if (it == _operations.end()) {
243 throw std::invalid_argument("Unknown operation key: " + key);
244 }
245 const auto op = it->second(args);
246 op->execute();
247 return op->getResult();
248}
249
250#endif /* SXEVAL_OPERATIONS_HPP */
The AOperation class is an abstract base class for operations in the SXEval library.
Definition AOperation.hpp:22
The IInstruction class is an interface for any instructions.
Definition IInstruction.hpp:21
The OperationsFactory class is used to manage operations.
Definition OperationsFactory.hpp:81
T compute(const std::string &key, const std::vector< IInstruction< T > * > args) const
Compute the result of an operation from its key and arguments.
Definition OperationsFactory.hpp:238
std::unique_ptr< AOperation< T > > create(const std::string &key, const std::vector< IInstruction< T > * > args)
Instantiate an operation from its key and arguments.
Definition OperationsFactory.hpp:227
OperationsFactory()
Default constructor.
Definition OperationsFactory.hpp:138
std::enable_if< std::is_base_of< sxeval::AOperation< T >, OP >::value >::type add()
Register an operation.
Definition OperationsFactory.hpp:198
Definition AOperation.hpp:8
std::enable_if< std::is_unsigned< T >::value, T >::type Absolute(const T &a)
Perform an absolute value operation on types T.
Definition utils.hpp:262