1 #ifndef CASM_DataFormatterTools
2 #define CASM_DataFormatterTools
3 #include <boost/algorithm/string.hpp>
4 #include <boost/regex.hpp>
29 template <
typename ValueType,
typename ArgType,
typename DataObject>
33 using Evaluator = std::function<ValueType(
const std::vector<ArgType> &)>;
42 std::unique_ptr<DataFormatterOperator>
clone()
const {
43 return std::unique_ptr<DataFormatterOperator>(this->
_clone());
56 bool parse_args(
const std::string &_args)
override;
59 Index pass_index)
const override {
68 Index pass_index)
const override {
69 _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
103 template <
typename DataObject>
106 "add",
"Add two or more numbers",
107 [](
const std::vector<double> &vec) ->
double {
108 return std::accumulate(vec.cbegin(), vec.cend(), 0.0);
116 template <
typename DataObject>
119 "sub",
"Subtract two numbers",
120 [](
const std::vector<double> &vec) ->
double {
122 throw std::runtime_error(
123 "Subtraction operator must receive exactly two values!");
124 return vec[0] - vec[1];
133 template <
typename DataObject>
136 "mult",
"Multiply two or more numbers",
137 [](
const std::vector<double> &vec) ->
double {
138 return std::accumulate(
139 vec.cbegin(), vec.cend(), 1.0,
140 [](
double a,
double b) ->
double { return a * b; });
148 template <
typename DataObject>
151 "div",
"Divide two numbers",
152 [](
const std::vector<double> &vec) ->
double {
154 throw std::runtime_error(
155 "Division operator must receive exactly two values!");
156 return vec[0] / vec[1];
165 template <
typename DataObject>
168 "rms",
"Root mean square of 0 or more numerical values",
169 [](
const std::vector<double> &vec) ->
double {
170 return sqrt(std::accumulate(
171 vec.cbegin(), vec.cend(), 0.0,
172 [](
double a,
double b) ->
double { return a + b * b; }));
181 template <
typename DataObject>
185 "Vector p-norm of zero or more elements Ex: 'pnorm(p, elem1, elem2)' "
186 "evaluates (elem1^p+elem2^p)^(1/p)",
187 [](
const std::vector<double> &vec) ->
double {
189 throw std::runtime_error(
190 "pnorm query operator must receive at least one value!");
192 return pow(std::accumulate(++vec.cbegin(), vec.cend(), 0.0,
193 [p](
double a,
double b) ->
double {
194 return a + pow(b, p);
205 template <
typename DataObject>
208 "max",
"Max value of two or more numbers",
209 [](
const std::vector<double> &vec) ->
double {
210 return (*std::max_element(vec.cbegin(), vec.cend()));
219 template <
typename DataObject>
222 "min",
"Min value of two or more numbers",
223 [](
const std::vector<double> &vec) ->
double {
224 return (*std::min_element(vec.cbegin(), vec.cend()));
233 template <
typename DataObject>
236 "imax",
"Index (from 0) of max value in array of two or more numbers",
237 [](
const std::vector<double> &vec) ->
long {
238 auto it = std::max_element(vec.cbegin(), vec.cend());
239 return std::distance(vec.cbegin(), it);
248 template <
typename DataObject>
251 "imin",
"Index (from 0) of min value in array of two or more numbers",
252 [](
const std::vector<double> &vec) ->
long {
253 auto it = std::min_element(vec.cbegin(), vec.cend());
254 return std::distance(vec.cbegin(), it);
263 template <
typename DataObject>
266 "exp",
"Exponential function",
267 [](
const std::vector<double> &vec) ->
double {
269 throw std::runtime_error(
270 "Exponent operator must receive exactly one value!");
282 template <
typename DataObject>
286 "Check if string matches regular expression. Ex: "
287 "re('input_string','regex_pattern')",
288 [](
const std::vector<std::string> &vec) ->
bool {
290 throw std::runtime_error(
291 "Operator re('input_string','regex_pattern') must receive "
292 "exactly 2 values!");
293 boost::regex e(boost::trim_copy_if(vec[1], boost::is_any_of(
" '")));
294 return boost::regex_match(vec[0], e);
305 template <
typename DataObject>
309 "Check if string contains regular expression. Ex: "
310 "rs('input_string','regex_pattern')",
311 [](
const std::vector<std::string> &vec) ->
bool {
313 throw std::runtime_error(
314 "Operator re('input_string','regex_pattern') must receive "
315 "exactly 2 values!");
316 boost::regex e(boost::trim_copy_if(vec[1], boost::is_any_of(
" '")));
317 return boost::regex_search(vec[0], e);
325 template <
typename DataObject>
328 "sq",
"Square of a number", [](
const std::vector<double> &vec) ->
double {
330 throw std::runtime_error(
331 "Square operator must receive exactly one value!");
332 return vec[0] * vec[0];
341 template <
typename DataObject>
344 "sqrt",
"Square root of a number",
345 [](
const std::vector<double> &vec) ->
double {
347 throw std::runtime_error(
348 "Square-root operator must receive exactly one value!");
357 template <
typename DataObject>
360 "neg",
"Negative of a number",
361 [](
const std::vector<double> &vec) ->
double {
363 throw std::runtime_error(
364 "Negation operator must receive exactly one value!");
374 template <
typename DataObject>
377 "and",
"Boolean AND for sequence of boolean values",
378 [](
const std::vector<bool> &vec) ->
bool {
379 return std::accumulate(vec.cbegin(), vec.cend(),
true,
380 [](
bool a,
bool b) ->
bool { return a && b; });
389 template <
typename DataObject>
392 "or",
"Boolean OR for sequence of boolean values",
393 [](
const std::vector<bool> &vec) ->
bool {
394 return std::accumulate(vec.cbegin(), vec.cend(),
false,
395 [](
bool a,
bool b) ->
bool { return a || b; });
404 template <
typename DataObject>
407 "xor",
"Boolean XOR for for two boolean values",
408 [](
const std::vector<bool> &vec) ->
bool {
410 throw std::runtime_error(
411 "Boolean XOR operator expects exactly two values!");
412 return (vec[0] && !vec[1]) || (!vec[0] && vec[1]);
416 template <
typename DataObject>
419 "not",
"Boolean NOT for a single boolean value",
420 [](
const std::vector<bool> &vec) ->
bool {
422 throw std::runtime_error(
423 "Boolean NOT operator must receive exactly one value!");
432 template <
typename DataObject>
435 "eq",
"Equality comparison for two values",
436 [](
const std::vector<double> &vec) ->
bool {
438 throw std::runtime_error(
439 "Equality operator must receive exactly two values!");
448 template <
typename DataObject>
451 "lt",
"Less-than comparison for two values",
452 [](
const std::vector<double> &vec) ->
bool {
454 throw std::runtime_error(
455 "Less-than operator must receive exactly two values!");
456 return vec[0] < vec[1];
465 template <
typename DataObject>
468 "le",
"Less-than-or-equal comparison for two values",
469 [](
const std::vector<double> &vec) ->
bool {
471 throw std::runtime_error(
472 "Less-than-or-equal operator must receive exactly two values!");
473 return vec[0] <= vec[1];
482 template <
typename DataObject>
485 "gt",
"Greater-than comparison for two values",
486 [](
const std::vector<double> &vec) ->
bool {
488 throw std::runtime_error(
489 "Greater-than operator must receive exactly two values!");
490 return vec[0] > vec[1];
499 template <
typename DataObject>
502 "ge",
"Greater-than-or-equal comparison for two values",
503 [](
const std::vector<double> &vec) ->
bool {
505 throw std::runtime_error(
506 "Greater-than-or-equal operator must receive exactly two "
508 return vec[0] >= vec[1];
513 template <
typename DataObject>
518 format_operator_add<DataObject>(), format_operator_sub<DataObject>(),
519 format_operator_mult<DataObject>(), format_operator_div<DataObject>(),
520 format_operator_exp<DataObject>(), format_operator_sq<DataObject>(),
521 format_operator_sqrt<DataObject>(), format_operator_neg<DataObject>(),
522 format_operator_and<DataObject>(), format_operator_or<DataObject>(),
523 format_operator_not<DataObject>(), format_operator_min<DataObject>(),
524 format_operator_max<DataObject>(), format_operator_imin<DataObject>(),
525 format_operator_imax<DataObject>(), format_operator_eq<DataObject>(),
526 format_operator_lt<DataObject>(), format_operator_le<DataObject>(),
527 format_operator_gt<DataObject>(), format_operator_ge<DataObject>(),
528 format_operator_re<DataObject>(), format_operator_rs<DataObject>());
541 template <
typename DataObject>
548 const std::string &_help =
"")
550 _name, _help.empty() ?
"User-specified alias for '" + _command +
"'"
554 throw std::runtime_error(
555 "Expression '" + _command +
556 "' is either empty or consists of multiple expressions.\n");
562 const std::string &_help =
"")
565 ?
"User-specified alias for '" + _rhs.
name() +
"'"
573 std::unique_ptr<DatumFormatterAlias>
clone()
const {
574 return std::unique_ptr<DatumFormatterAlias>(this->
_clone());
590 const DataObject &_template_obj)
const override {
591 std::vector<std::string> _col;
594 if (tcount.
count() == 1) {
595 _col.push_back(
name());
600 std::stringstream t_ss;
601 t_ss <<
name() <<
'(' << i <<
')';
602 _col.push_back(t_ss.str());
627 Index pass_index = 0)
const override {
628 m_formatter->print(_data_obj, _stream, pass_index);
635 Index pass_index = 0)
const override {
636 m_formatter->inject(_data_obj, _stream, pass_index);
660 throw std::runtime_error(
"ERROR: DataFormatterAlias has no formatter");
666 throw std::runtime_error(
668 "'. Cannot accept expression '" +
m_subexprs[0] +
"'\n");
671 return args.size() == 0;
691 template <
typename DataObject>
693 const std::string &_name,
const std::string &_command,
695 const std::string &_help =
"") {
703 template <
typename DataObject>
706 const std::string &_help =
"") {
718 template <
typename ValueType,
typename DataObject>
724 bool _print_json =
false)
726 _header,
"Constant value that will be printed on each line"),
730 std::unique_ptr<ConstantValueFormatter>
clone()
const {
731 return std::unique_ptr<ConstantValueFormatter>(this->
_clone());
735 Index pass_index)
const override {
740 Index pass_index)
const override {
787 template <
typename ValueType,
typename DataObject>
797 std::unique_ptr<BaseValueFormatter>
clone()
const {
798 return std::unique_ptr<BaseValueFormatter>(this->
_clone());
805 throw std::runtime_error(std::string(
"Invalid DataObject in ") +
822 Index pass_index = 0)
const override {
826 _stream << this->
evaluate(_data_obj);
834 Index pass_index = 0)
const override {
835 _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
836 _stream.precision(8);
838 _stream << this->
evaluate(_data_obj);
840 _stream <<
"unknown";
867 template <
typename ValueType,
typename DataObject>
883 Validator _validator = always_true<DataObject>)
900 std::unique_ptr<GenericDatumFormatter>
clone()
const {
901 return std::unique_ptr<GenericDatumFormatter>(this->
_clone());
923 template <
typename DataObject>
927 [](
const DataObject &obj) -> std::string {
return obj.name(); });
930 template <
typename DataObject>
934 [](
const DataObject &obj) -> std::string {
935 std::string
alias = obj.alias();
943 template <
typename DataObject>
948 [](
const DataObject &obj) -> std::string {
949 std::string
alias = obj.alias();
1001 template <
typename Container,
typename DataObject>
1017 std::unique_ptr<Base1DDatumFormatter>
clone()
const {
1018 return std::unique_ptr<Base1DDatumFormatter>(this->
_clone());
1028 if (!this->
validate(_template_obj))
return false;
1032 for (
Index i = 0; i < size; i++) {
1042 const DataObject &_template_obj)
const override {
1043 std::vector<std::string> _col;
1046 for (; it != end_it; ++it) {
1047 std::stringstream t_ss;
1048 t_ss << std::string(
s,
' ') << this->
name() <<
'(' << (*it)[0] <<
')';
1049 _col.push_back(t_ss.str());
1064 Index pass_index = 0)
const override {
1070 Container val = this->
evaluate(_data_obj);
1074 for (; it != end_it; ++it) {
1078 for (; it != end_it; ++it) {
1079 _stream << Access::at(val, (*it)[0]);
1088 Index pass_index = 0)
const override {
1094 _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
1095 _stream.precision(8);
1096 bool known = this->
validate(_data_obj);
1098 if (known) val = this->
evaluate(_data_obj);
1100 for (; it != end_it; ++it) {
1102 _stream <<
" " << Access::at(val, (*it)[0]);
1104 _stream <<
" unknown";
1124 template <
typename Container,
typename DataObject>
1141 Validator _validator = always_true<DataObject>)
1155 std::unique_ptr<Generic1DDatumFormatter>
clone()
const {
1156 return std::unique_ptr<Generic1DDatumFormatter>(this->
_clone());
1181 template <
typename DataObject>
1185 dict.
insert(make_string_dictionary<DataObject>(),
1186 make_boolean_dictionary<DataObject>(),
1187 make_integer_dictionary<DataObject>(),
1188 make_scalar_dictionary<DataObject>(),
1189 make_vectorxi_dictionary<DataObject>(),
1190 make_vectorxd_dictionary<DataObject>(),
1191 make_matrixxd_dictionary<DataObject>(),
1192 make_json_dictionary<DataObject>());
1206 template <
typename Container,
typename DataObject>
1224 std::unique_ptr<Base2DDatumFormatter>
clone()
const {
1225 return std::unique_ptr<Base2DDatumFormatter>(this->
_clone());
1257 const DataObject &_template_obj)
const override {
1258 std::vector<std::string> _col;
1259 init(_template_obj);
1266 std::stringstream t_ss;
1267 t_ss << std::string(
s,
' ') << this->
name() <<
'(';
1274 t_ss << a <<
":" << b;
1276 _col.push_back(t_ss.str());
1291 Index pass_index = 0)
const override {
1297 Index i = pass_index;
1299 Index *row_ptr = &row;
1308 row_ptr = &pass_index;
1314 for (
Index j = 0; j < cols; ++j) {
1327 Index pass_index = 0)
const override {
1331 _stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
1332 _stream.precision(8);
1334 Index i = pass_index;
1336 Index *row_ptr = &row;
1345 row_ptr = &pass_index;
1352 for (
Index j = 0; j < cols; ++j) {
1358 _stream <<
" unknown";
1385 if (bounds.first.empty() && bounds.second.empty())
return;
1387 if (bounds.first.size() != 2 || bounds.second.size() != 2) {
1388 throw std::runtime_error(
1389 "Attempted to initialize 2D DatumFormatter with incompatible index "
1395 for (
difference_type i = bounds.first[0]; i < bounds.second[0]; ++i, ++r) {
1396 for (
difference_type j = bounds.first[1]; j < bounds.second[1]; ++j) {
1425 for (
Index j = 0; j < cols; j++) {
1445 template <
typename Container,
typename DataObject>
1462 Validator _validator = always_true<DataObject>)
1476 std::unique_ptr<Generic2DDatumFormatter>
clone()
const {
1477 return std::unique_ptr<Generic2DDatumFormatter>(this->
_clone());
1499 template <
typename DataObject>
std::set< std::string > & s
const std::vector< T > & vector() const
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
std::pair< std::vector< long >, std::vector< long > > index_expression_to_bounds(const std::string &_expr)
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
GenericDatumFormatter< std::string, DataObject > alias()
GenericDatumFormatter< std::string, DataObject > alias_or_name()
DataFormatterOperator< bool, bool, DataObject > format_operator_not()
DataFormatterDictionary< DataObject > make_operator_dictionary()
Dictionary of all DatumFormatterOperator.
void split_formatter_expression(const std::string &input_expr, std::vector< std::string > &tag_names, std::vector< std::string > &sub_exprs)
GenericDatumFormatter< std::string, DataObject > name()
bool valid_index(Index i)
DataFormatterDictionary< DataObject > make_attribute_dictionary()
Dictionary of all AttributeFormatter (i.e. BaseValueFormatter<V, DataObject>)
INDEX_TYPE Index
For long integer indexing:
T max(const T &A, const T &B)
Specialize container traits Expects:
Shortcut for multidimensional vector (std::vector< std::vector< ...)