24 template<jit::
float_scalar T,
bool SAFE_MATH=false>
27 if (
a->is_constant() &&
b->is_constant()) {
34 (
a1.get() &&
a1->is_arg_match(
b)) ||
35 (
a2.get() &&
a2->is_arg_match(
b)) ||
36 (
a2.get() && (
a2->is_row_match(
b) ||
a2->is_col_match(
b))) ||
37 (
b2.get() && (
b2->is_row_match(
a) ||
b2->is_col_match(
a)));
52 template<jit::
float_scalar T,
bool SAFE_MATH=false>
58 return a->is_constant() &&
74 template<jit::
float_scalar T,
bool SAFE_MATH=false>
77 return a->is_power_base_match(
b);
90 template<jit::
float_scalar T,
bool SAFE_MATH=false>
93 return !
b->is_constant() &&
94 (
a->is_all_variables() &&
95 (!
b->is_all_variables() ||
96 (
b->is_all_variables() &&
97 a->get_complexity() <
b->get_complexity())));
110 template<jit::
float_scalar T,
bool SAFE_MATH=false>
116 return ae.get() &&
be.get() &&
117 std::abs(
ae->evaluate().at(0)) > std::abs(
be->evaluate().at(0));
131 template<jit::
float_scalar T,
bool SAFE_MATH=false>
182 if (l.get() && l->is(0)) {
184 }
else if (r.get() &&
r->is(0)) {
186 }
else if (l.get() &&
r.get()) {
188 }
else if (r.get() && !l.get()) {
195 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
197 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
204 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
206 pl2->get_num_columns(),
209 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
211 pr2->get_num_columns(),
217 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
221 pr2->get_num_columns(),
224 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
228 pr2->get_num_columns(),
231 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
235 pl2->get_num_columns(),
238 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
242 pl2->get_num_columns(),
248 if (this->
left->is_match(
this->right)) {
249 return 2.0*this->
left;
260 rm->get_left()->is_constant() &&
261 rm->get_left()->evaluate().is_negative()) {
263 }
else if (
rm.get() &&
264 rm->get_left()->is_constant() &&
265 rm->get_left()->evaluate().is_negative()) {
272 return fma(
lm->get_left(),
lm->get_right(),
this->right);
273 }
else if (
rm.get()) {
274 return fma(
rm->get_left(),
rm->get_right(),
this->left);
289 if ((
rd->get_left()->is_constant() &&
290 rd->get_left()->evaluate().is_negative()) ||
292 (
rdlm->get_left()->is_constant() &&
293 rdlm->get_left()->evaluate().is_negative()))) {
294 return this->
left - (-
rd->get_left())/
rd->get_right();
296 }
else if (
ld.get()) {
298 if ((
ld->get_left()->is_constant() &&
299 ld->get_left()->evaluate().is_negative()) ||
301 (
ldlm->get_left()->is_constant() &&
302 ldlm->get_left()->evaluate().is_negative()))) {
303 return this->
right - (-
ld->get_left())/
ld->get_right();
307 if (
ld.get() &&
rd.get()) {
308 if (
ld->get_right()->is_match(
rd->get_right())) {
309 return (
ld->get_left() +
rd->get_left())/
ld->get_right();
319 if (
ld->get_left()->is_match(
rdlm->get_left())) {
320 return (1.0/
ld->get_right() +
321 rdlm->get_right()/
rd->get_right())*
rdlm->get_left();
322 }
else if (
ld->get_left()->is_match(
rdlm->get_right())) {
323 return (1.0/
ld->get_right() +
324 rdlm->get_left()/
rd->get_right())*
rdlm->get_right();
326 }
else if (
ldlm.get()) {
327 if (
rd->get_left()->is_match(
ldlm->get_left())) {
328 return (
ldlm->get_right()/
ld->get_right() +
329 1.0/
rd->get_right())*
ldlm->get_left();
330 }
else if (
rd->get_left()->is_match(
ldlm->get_right())) {
331 return (
ldlm->get_left()/
ld->get_right() +
332 1.0/
rd->get_right())*
ldlm->get_right();
344 !
ldlm->get_right()->is_match(
rdlm->get_right())) {
345 return (
ldlm->get_right()/
ld->get_right() +
347 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
350 if (
ldlm->get_right()->is_match(
rdlm->get_right())) {
351 return (
ldlm->get_left()/
ld->get_right() +
352 rdlm->get_left()/
rd->get_right())*
ldlm->get_right();
353 }
else if (
ldlm->get_right()->is_match(
rdlm->get_left())) {
354 return (
ldlm->get_left()/
ld->get_right() +
355 rdlm->get_right()/
rd->get_right())*
ldlm->get_right();
356 }
else if (
ldlm->get_left()->is_match(
rdlm->get_right())) {
357 return (
ldlm->get_right()/
ld->get_right() +
358 rdlm->get_left()/
rd->get_right())*
ldlm->get_left();
359 }
else if (
ldlm->get_left()->is_match(
rdlm->get_left())) {
360 return (
ldlm->get_right()/
ld->get_right() +
361 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
372 if (
ldrm->get_right()->is_match(
rdrm->get_right())) {
373 return (
ld->get_left()/
ldrm->get_left() +
374 rd->get_left()/
rdrm->get_left())/
ldrm->get_right();
375 }
else if (
ldrm->get_right()->is_match(
rdrm->get_left())) {
376 return (
ld->get_left()/
ldrm->get_left() +
377 rd->get_left()/
rdrm->get_right())/
ldrm->get_right();
378 }
else if (
ldrm->get_left()->is_match(
rdrm->get_right())) {
379 return (
ld->get_left()/
ldrm->get_right() +
380 rd->get_left()/
rdrm->get_left())/
ldrm->get_left();
381 }
else if (
ldrm->get_left()->is_match(
rdrm->get_left())) {
382 return (
ld->get_left()/
ldrm->get_right() +
383 rd->get_left()/
rdrm->get_right())/
ldrm->get_left();
392 if (
ld->get_right()->is_match(
rdrm->get_left())) {
393 return fma(
ld->get_left(),
397 }
else if (
ld->get_right()->is_match(
rdrm->get_right())) {
398 return fma(
ld->get_left(),
403 }
else if (
ldrm.get()) {
404 if (
rd->get_right()->is_match(
ldrm->get_left())) {
405 return fma(
rd->get_left(),
409 }
else if (
rd->get_right()->is_match(
ldrm->get_right())) {
410 return fma(
rd->get_left(),
425 if (this->
right->is_match(
la->get_left())) {
426 return fma(2.0, this->
right,
la->get_right());
427 }
else if (this->
right->is_match(
la->get_right())) {
433 if (this->
left->is_match(
ra->get_left())) {
434 return fma(2.0, this->
left,
ra->get_right());
435 }
else if (this->
left->is_match(
ra->get_right())) {
436 return fma(2.0, this->
left,
ra->get_left());
448 if (
ls->get_left()->is_match(
this->right)) {
449 return static_cast<T
> (2.0)*this->
right -
ls->get_right();
450 }
else if (
ls->get_right()->is_match(this->
right)) {
451 return ls->get_left();
462 return (this->
left +
rs->get_left()) -
rs->get_right();
464 return (this->
left -
rs->get_right()) +
rs->get_left();
465 }
else if (this->
left->is_match(
rs->get_left())) {
466 return static_cast<T
> (2.0)*this->
left -
rs->get_right();
467 }
else if (this->
left->is_match(
rs->get_right())) {
468 return rs->get_left();
478 return la->get_left() + (
la->get_right() + this->
right);
483 return ls->get_left() + (this->
right -
ls->get_right());
494 }
else if (
rfma.get()) {
506 if (
lfma->get_middle()->is_match(
rfma->get_middle())) {
508 lfma->get_left() +
rfma->get_left(),
509 lfma->get_right() +
rfma->get_right());
510 }
else if (
lfma->get_left()->is_match(
rfma->get_middle())) {
512 lfma->get_middle() +
rfma->get_left(),
513 lfma->get_right() +
rfma->get_right());
514 }
else if (
lfma->get_middle()->is_match(
rfma->get_left())) {
516 lfma->get_left() +
rfma->get_middle(),
517 lfma->get_right() +
rfma->get_right());
518 }
else if (
lfma->get_left()->is_match(
rfma->get_left())) {
520 lfma->get_middle() +
rfma->get_middle(),
521 lfma->get_right() +
rfma->get_right());
532 if (
pl.get() &&
pr.get() &&
533 pl->get_right()->is_match(
pr->get_right())) {
536 if (
plm.get() &&
prm.get()) {
537 if (
plm->get_left()->is_match(
prm->get_left())) {
538 return pow(
plm->get_left(),
pl->get_right())*
539 (
pow(
plm->get_right(),
pl->get_right()) +
540 pow(
prm->get_right(),
pl->get_right()));
541 }
else if (
plm->get_left()->is_match(
prm->get_right())) {
542 return pow(
plm->get_left(),
pl->get_right())*
543 (
pow(
plm->get_right(),
pl->get_right()) +
544 pow(
prm->get_left(),
pl->get_right()));
545 }
else if (
plm->get_right()->is_match(
prm->get_left())) {
546 return pow(
plm->get_right(),
pl->get_right())*
547 (
pow(
plm->get_left(),
pl->get_right()) +
548 pow(
prm->get_right(),
pl->get_right()));
549 }
else if (
plm->get_right()->is_match(
prm->get_right())) {
550 return pow(
plm->get_right(),
pl->get_right())*
551 (
pow(
plm->get_left(),
pl->get_right()) +
552 pow(
prm->get_left(),
pl->get_right()));
559 if (
plrc.get() &&
plrc->is(
static_cast<T
> (2.0))) {
564 if ((
pls.get() &&
prc.get() &&
pls->get_arg()->is_match(
prc->get_arg())) ||
565 (
plc.get() &&
prs.get() &&
plc->get_arg()->is_match(
prs->get_arg()))) {
574 if (
pl.get() &&
rd.get()) {
576 if (
rdp.get() &&
pl->get_right()->is_match(
rdp->get_right())) {
579 rdp->get_left()->is_match(
plld->get_right())) {
580 return (
pow(
plld->get_left(),
pl->get_right()) +
582 pow(
rdp->get_left(),
pl->get_right());
585 }
else if (
pr.get() &&
ld.get()) {
587 if (
ldp.get() &&
pr->get_right()->is_match(
ldp->get_right())) {
590 ldp->get_left()->is_match(
prld->get_right())) {
591 return (
pow(
prld->get_left(),
pr->get_right()) +
593 pow(
ldp->get_left(),
pr->get_right());
596 }
else if (
pl.get() &&
pr.get()) {
597 if (
pl->get_right()->is_match(
pr->get_right())) {
600 if (
pld.get() &&
prd.get() &&
601 pld->get_right()->is_match(
prd->get_right())) {
602 return (
pow(
pld->get_left(),
pl->get_right()) +
603 pow(
prd->get_left(),
pl->get_right())) /
604 pow(
pld->get_right(),
pl->get_right());
626 const size_t hash =
reinterpret_cast<size_t> (x.get());
647 if (registers.find(
this) == registers.end()) {
650 auto r = this->
right->compile(stream, registers,
655 jit::add_type<T> (stream);
656 stream <<
" " << registers[
this] <<
" = "
657 << registers[l.get()] <<
" + "
658 << registers[
r.get()];
672 if (
this == x.get()) {
679 return (this->
left->is_match(
x_cast->get_left()) &&
680 this->right->is_match(
x_cast->get_right())) ||
697 std::cout <<
"\\left(";
699 this->
left->to_latex();
701 std::cout <<
"\\right)";
705 std::cout <<
"\\left(";
707 this->
right->to_latex();
709 std::cout <<
"\\right)";
720 return this->
left->remove_pseudo() +
721 this->
right->remove_pseudo();
735 if (registers.find(
this) == registers.end()) {
737 registers[
this] =
name;
738 stream <<
" " <<
name
739 <<
" [label = \"+\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
742 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
743 auto r = this->
right->to_vizgraph(stream, registers);
744 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
763 template<jit::
float_scalar T,
bool SAFE_MATH=false>
766 auto temp = std::make_shared<add_node<T, SAFE_MATH>> (l,
r)->reduce();
768 for (
size_t i =
temp->get_hash();
778#if defined(__clang__) || defined(__GNUC__)
781 assert(
false &&
"Should never reach.");
797 template<jit::
float_scalar T,
bool SAFE_MATH=false>
816 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
835 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
842 template<jit::
float_scalar T,
bool SAFE_MATH=false>
854 template<jit::
float_scalar T,
bool SAFE_MATH=false>
856 return std::dynamic_pointer_cast<add_node<T, SAFE_MATH>> (x);
870 template<jit::
float_scalar T,
bool SAFE_MATH=false>
919 if (this->
left->is_match(
this->right)) {
920 if (l.get() && l->is(0)) {
930 if (l.get() && l->is(0)) {
932 }
else if (r.get() &&
r->is(0)) {
934 }
else if (l.get() &&
r.get()) {
936 }
else if (r.get() &&
r->
evaluate().is_negative()) {
943 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
945 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
952 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
954 pl2->get_num_columns(),
957 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
959 pl2->get_num_columns(),
965 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
969 pl2->get_num_columns(),
972 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
976 pl2->get_num_columns(),
979 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
983 pl2->get_num_columns(),
986 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
990 pl2->get_num_columns(),
999 return (
la->get_left() -
this->right) +
la->get_right();
1005 return (this->
left -
ra->get_left()) -
ra->get_right();
1014 return (
ls->get_left() -
this->right) -
ls->get_right();
1017 return -(
ls->get_right() + this->
right) -
ls->get_left();
1025 return (this->
left -
rs->get_left()) +
rs->get_right();
1027 return (this->
left +
rs->get_right()) -
rs->get_left();
1041 lmra->get_left()) &&
1044 return fma(
lm->get_left(),
1046 lm->get_left()*
lmra->get_left() -
this->right);
1053 lmrs->get_left()) &&
1056 return lm->get_left()*
lmrs->get_left() - this->
right -
1057 lm->get_left()*
lmrs->get_right();
1067 if (
la->get_left()->is_match(
this->right)) {
1068 return la->get_right();
1069 }
else if (
la->get_right()->is_match(
this->right)) {
1070 return la->get_left();
1072 }
else if (
ra.get()) {
1073 if (
ra->get_left()->is_match(
this->left)) {
1075 }
else if (
ra->get_right()->is_match(
this->left)) {
1083 rm->get_left()->is_constant() &&
1084 rm->get_left()->evaluate().is_negative()) {
1092 if (
lmc.get() &&
lmc->is(-1)) {
1093 return lm->get_left()*(
lm->get_right() + this->
right);
1098 if (this->
right->is_match(
lm->get_right())) {
1099 return (
lm->get_left() - 1.0)*this->
right;
1100 }
else if (this->
right->is_match(
lm->get_left())) {
1101 return (
lm->get_right() - 1.0)*this->
right;
1107 if (this->
left->is_match(
rm->get_right())) {
1108 return (1.0 -
rm->get_left())*this->
left;
1109 }
else if (this->
left->is_match(
rm->get_left())) {
1110 return (1.0 -
rm->get_right())*this->
left;
1114 if (
lm.get() &&
rm.get()) {
1115 if (
lm->get_left()->is_match(
rm->get_left())) {
1117 return lm->get_left()*(
lm->get_right() -
rm->get_right());
1118 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
1120 return lm->get_left()*(
lm->get_right() -
rm->get_left());
1121 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
1123 return lm->get_right()*(
lm->get_left() -
rm->get_right());
1124 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
1126 return lm->get_right()*(
lm->get_left() -
rm->get_left());
1131 if (
lm->get_left()->is_constant() &&
1132 rm->get_left()->is_constant() &&
1133 !
lm->get_left()->has_constant_zero()) {
1134 return lm->get_left()*(
lm->get_right() -
1135 (
rm->get_left()/
lm->get_left())*
rm->get_right());
1142 if (
lm->get_right()->is_match(
rmrm->get_right())) {
1143 return (
lm->get_left() -
rm->get_left()*
rmrm->get_left())*
lm->get_right();
1146 if (
lm->get_right()->is_match(
rmrm->get_left())) {
1147 return (
lm->get_left() -
rm->get_left()*
rmrm->get_right())*
lm->get_right();
1150 if (
lm->get_left()->is_match(
rmrm->get_right())) {
1151 return (
lm->get_right() -
rm->get_left()*
rmrm->get_left())*
lm->get_left();
1154 if (
lm->get_left()->is_match(
rmrm->get_left())) {
1155 return (
lm->get_right() -
rm->get_left()*
rmrm->get_right())*
lm->get_left();
1161 if (
rm->get_right()->is_match(
lmrm->get_right())) {
1162 return (
lm->get_left()*
lmrm->get_left() -
rm->get_left())*
rm->get_right();
1165 if (
rm->get_right()->is_match(
lmrm->get_left())) {
1166 return (
lm->get_left()*
lmrm->get_right() -
rm->get_left())*
rm->get_right();
1169 if (
rm->get_left()->is_match(
lmrm->get_right())) {
1170 return (
lm->get_left()*
lmrm->get_left() -
rm->get_right())*
rm->get_left();
1173 if (
rm->get_left()->is_match(
lmrm->get_left())) {
1174 return (
lm->get_left()*
lmrm->get_right() -
rm->get_right())*
rm->get_left();
1187 lmld->get_right()->is_match(
rmld->get_right())) {
1188 return (
lmld->get_left()*
lm->get_right() -
1189 rmld->get_left()*
rm->get_right())/
lmld->get_right();
1190 }
else if (
lmld.get() &&
rmrd.get() &&
1191 lmld->get_right()->is_match(
rmrd->get_right())) {
1192 return (
lmld->get_left()*
lm->get_right() -
1193 rmrd->get_left()*
rm->get_left())/
lmld->get_right();
1194 }
else if (
lmrd.get() &&
rmld.get() &&
1195 lmrd->get_right()->is_match(
rmld->get_right())) {
1196 return (
lmrd->get_left()*
lm->get_left() -
1197 rmld->get_left()*
rm->get_right())/
lmrd->get_right();
1198 }
else if (
lmrd.get() &&
rmrd.get() &&
1199 lmrd->get_right()->is_match(
rmrd->get_right())) {
1200 return (
lmrd->get_left()*
lm->get_left() -
1201 rmrd->get_left()*
rm->get_left())/
lmrd->get_right();
1208 if (
lrm.get() &&
rm.get()) {
1209 if (
lrm->get_left()->is_match(
rm->get_left())) {
1211 return ls->get_left() -
1213 rm->get_right())*
rm->get_left();
1214 }
else if (
lrm->get_left()->is_match(
rm->get_right())) {
1216 return ls->get_left() -
1218 rm->get_left())*
rm->get_right();
1219 }
else if (
lrm->get_right()->is_match(
rm->get_left())) {
1221 return ls->get_left() -
1223 rm->get_right())*
rm->get_left();
1224 }
else if (
lrm->get_right()->is_match(
rm->get_right())) {
1226 return ls->get_left() -
1228 rm->get_left())*
rm->get_right();
1245 if ((
rd->get_left()->is_constant() &&
1246 rd->get_left()->evaluate().is_negative()) ||
1248 (
rdlm->get_left()->is_constant() &&
1249 rdlm->get_left()->evaluate().is_negative()))) {
1252 }
else if (
ld.get()) {
1254 if ((
ld->get_left()->is_constant() &&
1255 ld->get_left()->evaluate().is_negative()) ||
1257 (
ldlm->get_left()->is_constant() &&
1258 ldlm->get_left()->evaluate().is_negative()))) {
1263 if (
ld.get() &&
rd.get()) {
1264 if (
ld->get_right()->is_match(
rd->get_right())) {
1265 return (
ld->get_left() -
rd->get_left())/
ld->get_right();
1275 if (
ld->get_left()->is_match(
rdlm->get_left())) {
1276 return (1.0/
ld->get_right() -
1277 rdlm->get_right()/
rd->get_right())*
rdlm->get_left();
1278 }
else if (
ld->get_left()->is_match(
rdlm->get_right())) {
1279 return (1.0/
ld->get_right() -
1280 rdlm->get_left()/
rd->get_right())*
rdlm->get_right();
1282 }
else if (
ldlm.get()) {
1283 if (
rd->get_left()->is_match(
ldlm->get_left())) {
1284 return (
ldlm->get_right()/
ld->get_right() -
1285 1.0/
rd->get_right())*
ldlm->get_left();
1286 }
else if (
rd->get_left()->is_match(
ldlm->get_right())) {
1287 return (
ldlm->get_left()/
ld->get_right() -
1288 1.0/
rd->get_right())*
ldlm->get_right();
1299 rdlm->get_left()) &&
1300 !
ldlm->get_right()->is_match(
rdlm->get_right())) {
1301 return (
ldlm->get_right()/
ld->get_right() -
1302 rdlm->get_left()/
ldlm->get_left() *
1303 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
1306 if (
ldlm->get_right()->is_match(
rdlm->get_right())) {
1307 return (
ldlm->get_left()/
ld->get_right() -
1308 rdlm->get_left()/
rd->get_right())*
ldlm->get_right();
1309 }
else if (
ldlm->get_right()->is_match(
rdlm->get_left())) {
1310 return (
ldlm->get_left()/
ld->get_right() -
1311 rdlm->get_right()/
rd->get_right())*
ldlm->get_right();
1312 }
else if (
ldlm->get_left()->is_match(
rdlm->get_right())) {
1313 return (
ldlm->get_right()/
ld->get_right() -
1314 rdlm->get_left()/
rd->get_right())*
ldlm->get_left();
1315 }
else if (
ldlm->get_left()->is_match(
rdlm->get_left())) {
1316 return (
ldlm->get_right()/
ld->get_right() -
1317 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
1328 if (
ldrm->get_right()->is_match(
rdrm->get_right())) {
1329 return (
ld->get_left()/
ldrm->get_left() -
1330 rd->get_left()/
rdrm->get_left())/
ldrm->get_right();
1331 }
else if (
ldrm->get_right()->is_match(
rdrm->get_left())) {
1332 return (
ld->get_left()/
ldrm->get_left() -
1333 rd->get_left()/
rdrm->get_right())/
ldrm->get_right();
1334 }
else if (
ldrm->get_left()->is_match(
rdrm->get_right())) {
1335 return (
ld->get_left()/
ldrm->get_right() -
1336 rd->get_left()/
rdrm->get_left())/
ldrm->get_left();
1337 }
else if (
ldrm->get_left()->is_match(
rdrm->get_left())) {
1338 return (
ld->get_left()/
ldrm->get_right() -
1339 rd->get_left()/
rdrm->get_right())/
ldrm->get_left();
1348 if (
ld->get_right()->is_match(
rdrm->get_left())) {
1349 return (
ld->get_left()*
rdrm->get_right() -
rd->get_left()) /
1351 }
else if (
ld->get_right()->is_match(
rdrm->get_right())) {
1352 return (
ld->get_left()*
rdrm->get_left() -
rd->get_left()) /
1355 }
else if (
ldrm.get()) {
1356 if (
rd->get_right()->is_match(
ldrm->get_left())) {
1357 return (
ld->get_left() -
rd->get_left()*
ldrm->get_right()) /
1359 }
else if (
rd->get_right()->is_match(
ldrm->get_right())) {
1360 return (
ld->get_left() -
rd->get_left()*
ldrm->get_left()) /
1373 return la->get_left() + (
la->get_right() - this->
right);
1375 return ls->get_left() - (this->
right +
ls->get_right());
1385 if (
pl.get() &&
rd.get()) {
1387 if (
rdp.get() &&
pl->get_right()->is_match(
rdp->get_right())) {
1390 rdp->get_left()->is_match(
plld->get_right())) {
1391 return (
pow(
plld->get_left(),
pl->get_right()) -
1393 pow(
rdp->get_left(),
pl->get_right());
1396 }
else if (
pr.get() &&
ld.get()) {
1398 if (
ldp.get() &&
pr->get_right()->is_match(
ldp->get_right())) {
1401 ldp->get_left()->is_match(
prld->get_right())) {
1402 return (
pow(
prld->get_left(),
pr->get_right()) -
1404 pow(
ldp->get_left(),
pr->get_right());
1407 }
else if (
pl.get() &&
pr.get()) {
1408 if (
pl->get_right()->is_match(
pr->get_right())) {
1411 if (
pld.get() &&
prd.get() &&
1412 pld->get_right()->is_match(
prd->get_right())) {
1413 return (
pow(
pld->get_left(),
pl->get_right()) -
1414 pow(
prd->get_left(),
pl->get_right())) /
1415 pow(
pld->get_right(),
pl->get_right());
1424 if (
lfma->get_middle()->is_match(
rfma->get_middle())) {
1427 lfma->get_right() -
rfma->get_right());
1432 if (
lfma.get() && !
this->right->is_all_variables()) {
1445 return ls->get_left() - (
ls->get_right() + this->
right);
1466 const size_t hash =
reinterpret_cast<size_t> (x.get());
1487 if (registers.find(
this) == registers.end()) {
1490 auto r = this->
right->compile(stream, registers,
1494 stream <<
" const ";
1495 jit::add_type<T> (stream);
1496 stream <<
" " << registers[
this] <<
" = "
1497 << registers[l.get()] <<
" - "
1498 << registers[
r.get()];
1512 if (
this == x.get()) {
1518 return this->
left->is_match(
x_cast->get_left()) &&
1534 std::cout <<
"\\left(";
1536 this->
left->to_latex();
1538 std::cout <<
"\\right)";
1542 std::cout <<
"\\left(";
1544 this->
right->to_latex();
1546 std::cout <<
"\\right)";
1557 return this->
left->remove_pseudo() -
1558 this->
right->remove_pseudo();
1572 if (registers.find(
this) == registers.end()) {
1574 registers[
this] =
name;
1575 stream <<
" " <<
name
1576 <<
" [label = \"-\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
1579 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
1580 auto r = this->
right->to_vizgraph(stream, registers);
1581 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
1598 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1601 auto temp = std::make_shared<subtract_node<T, SAFE_MATH>> (l,
r)->reduce();
1603 for (
size_t i =
temp->get_hash();
1613#if defined(__clang__) || defined(__GNUC__)
1616 assert(
false &&
"Should never reach.");
1633 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1653 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
1673 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
1691 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1697 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1709 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1711 return std::dynamic_pointer_cast<subtract_node<T, SAFE_MATH>> (x);
1723 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1744 auto temp2 = reduce_nested_fma_times_constant(
temp->get_left());
1769 if (
add->get_right()->is_match(
temp->get_middle()) &&
1771 auto temp2 = expand_nested_fma_times_add2(
temp->get_left(),
1776 temp->get_right()*
add->get_left());
1780 add->get_left()*
temp->get_left() +
temp->get_right()),
1782 temp->get_right()*
add->get_left());
1807 if (
add->get_right()->is_match(
temp->get_middle()) &&
1813 add->get_left()*
temp->get_left() +
1816 add->get_left()*
temp->get_right() +
1817 temp2->get_right());
1819 auto temp3 = expand_nested_fma_times_add2(
temp->get_left(),
1824 add->get_left()*
temp->get_right() +
1825 temp2->get_right());
1868 if (this->
left.get() ==
this->right.get()) {
1892 if (l.get() && l->is(1)) {
1894 }
else if (l.get() && l->is(0)) {
1896 }
else if (r.get() &&
r->is(1)) {
1898 }
else if (r.get() &&
r->is(0)) {
1900 }
else if (l.get() &&
r.get()) {
1907 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
1909 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
1916 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
1918 pl2->get_num_columns(),
1921 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
1923 pr2->get_num_columns(),
1929 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
1933 pr2->get_num_columns(),
1936 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
1940 pr2->get_num_columns(),
1943 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
1947 pl2->get_num_columns(),
1950 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
1954 pl2->get_num_columns(),
1972 if ((
cl.get() && !
this->right->is_power_like() &&
1973 !
this->right->is_all_variables() &&
1975 (
sl.get() && !
this->right->is_power_like() &&
1976 !
this->right->is_all_variables()) ||
1982 if (this->
left->is_match(
this->right)) {
1993 return lm->get_left()*(
lm->get_right()*this->
right);
1999 return (this->
right*
lm->get_left())*
lm->get_right();
2001 return (this->
right*
lm->get_right())*
lm->get_left();
2008 return (
lm->get_left()*this->
right)*
lm->get_right();
2021 this->right->get_power_exponent());
2033 if (
temp->is_normal()) {
2034 return temp*
rm->get_right();
2041 return (this->
left*
rm->get_left())*
rm->get_right();
2043 return (this->
left*
rm->get_right())*
rm->get_left();
2049 return (this->
left*
rm->get_left())*
rm->get_right();
2056 auto temp = this->reduce_nested_fma_times_constant(
rm->get_left());
2058 return temp*
rm->get_right();
2065 return rm->get_left()*(this->
left*
rm->get_right());
2077 !this->
right->is_power_like()) {
2078 return (
lm->get_left()*this->
right)*
lm->get_right();
2079 }
else if (
rm.get() &&
2082 !this->
left->is_constant()) {
2083 return (this->
left*
rm->get_left())*
rm->get_right();
2088 if (
lm.get() &&
rm.get()) {
2091 auto temp =
lm->get_left()*
rm->get_left();
2092 if (
temp->is_normal()) {
2093 return temp*(
lm->get_right()*
rm->get_right());
2097 auto temp =
lm->get_left()*
rm->get_right();
2098 if (
temp->is_normal()) {
2099 return temp*(
lm->get_right()*
rm->get_left());
2103 auto temp =
lm->get_right()*
rm->get_left();
2104 if (
temp->is_normal()) {
2105 return temp*(
lm->get_left()*
rm->get_right());
2109 auto temp =
lm->get_right()*
rm->get_right();
2110 if (
temp->is_normal()) {
2111 return temp*(
lm->get_left()*
rm->get_left());
2116 if (
lm->get_left()->is_match(
rm->get_left())) {
2117 return (
lm->get_left()*
rm->get_left()) *
2118 (
lm->get_right()*
rm->get_right());
2119 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
2120 return (
lm->get_right()*
rm->get_left()) *
2121 (
lm->get_left()*
rm->get_right());
2122 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
2123 return (
lm->get_left()*
rm->get_right()) *
2124 (
lm->get_right()*
rm->get_left());
2125 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
2126 return (
lm->get_right()*
rm->get_right()) *
2127 (
lm->get_left()*
rm->get_left());
2138 return (this->
left*
rd->get_left())/
rd->get_right();
2139 }
else if (
ld.get()) {
2140 return (
ld->get_left()*
this->right)/
ld->get_right();
2145 if (
ld.get() &&
rd.get()) {
2146 if (
ld->get_left()->is_match(
rd->get_right())) {
2147 return rd->get_left()/
ld->get_right();
2148 }
else if (
ld->get_right()->is_match(
rd->get_left())) {
2149 return ld->get_left()/
rd->get_right();
2154 return (
ld->get_left()*
rd->get_left()) /
2155 (
ld->get_right()*
rd->get_right());
2160 return pow(this->
left->get_power_base(),
2161 this->left->get_power_exponent() +
2162 this->right->get_power_exponent());
2170 return this->
left/
pow(
rp->get_left(), -
rp->get_right());
2178 return this->
right/
pow(
lp->get_left(), -
lp->get_right());
2182 if (
lp.get() &&
rp.get()) {
2183 if (
lp->get_right()->is_match(
rp->get_right())) {
2184 return pow(
lp->get_left()*
rp->get_left(),
lp->get_right());
2191 if (
lm.get() &&
rp.get()) {
2195 if (
lmrp->get_right()->is_match(
rp->get_right())) {
2196 return lm->get_left()*
pow(
lmrp->get_left()*
rp->get_left(),
2199 }
else if (
lmlp.get()) {
2200 if (
lmlp->get_right()->is_match(
rp->get_right())) {
2201 return lm->get_right()*
pow(
lmlp->get_left()*
rp->get_left(),
2205 }
else if (
rm.get() &&
lp.get()) {
2209 if (
rmrp->get_right()->is_match(
lp->get_right())) {
2210 return rm->get_left()*
pow(
lp->get_left()*
rmrp->get_left(),
2213 }
else if (
rmlp.get()) {
2214 if (
rmlp->get_right()->is_match(
lp->get_right())) {
2215 return rm->get_right()*
pow(
lp->get_left()*
rmlp->get_left(),
2225 if (
lp.get() &&
rp.get()) {
2231 return pow(
lplm->get_left()->get_power_base(),
2232 this->left->get_power_exponent())*
2234 this->left->get_power_exponent() +
2235 this->right->get_power_exponent());
2238 return pow(
lplm->get_right()->get_power_base(),
2239 this->left->get_power_exponent())*
2241 this->left->get_power_exponent() +
2242 this->right->get_power_exponent());
2249 return pow(
rplm->get_left()->get_power_base(),
2250 this->right->get_power_exponent())*
2251 pow(this->
left->get_power_base(),
2252 this->left->get_power_exponent() +
2253 this->right->get_power_exponent());
2256 return pow(
rplm->get_right()->get_power_base(),
2257 this->right->get_power_exponent())*
2258 pow(this->
left->get_power_base(),
2259 this->left->get_power_exponent() +
2260 this->right->get_power_exponent());
2270 return pow(
lpd->get_left(),
this->left->get_power_exponent()) *
2272 this->right->get_power_exponent() -
2273 this->left->get_power_exponent()*
lpd->get_right()->get_power_exponent());
2277 return pow(this->
right->get_power_base(),
2278 this->right->get_power_exponent() +
2279 this->left->get_power_exponent()*
lpd->get_left()->get_power_exponent()) /
2280 pow(
lpd->get_right(),
this->left->get_power_exponent());
2288 return pow(
rpd->get_left(),
this->right->get_power_exponent()) *
2289 pow(this->
left->get_power_base(),
2290 this->left->get_power_exponent() -
2291 this->right->get_power_exponent()*
rpd->get_right()->get_power_exponent());
2296 return pow(this->
right->get_power_base(),
2297 this->right->get_power_exponent() +
2298 this->right->get_power_exponent()*
rpd->get_left()->get_power_exponent()) /
2299 pow(
rpd->get_right(),
this->right->get_power_exponent());
2306 if (
le.get() &&
re.get()) {
2307 return exp(
le->get_arg() +
re->get_arg());
2312 if (
le.get() &&
rm.get()) {
2315 return rm->get_right()*(this->
left*
rm->get_left());
2319 return rm->get_left()*(this->
left*
rm->get_right());
2324 if (
re.get() &&
lm.get()) {
2327 return lm->get_right()*(this->
right*
lm->get_left());
2331 return lm->get_left()*(this->
right*
lm->get_right());
2338 if (
lm.get() &&
rm.get()) {
2343 return (
lm->get_right()*
rm->get_right()) *
2344 (
lm->get_left()*
rm->get_left());
2348 return (
lm->get_right()*
rm->get_left()) *
2349 (
lm->get_left()*
rm->get_right());
2356 return (
lm->get_left()*
rm->get_right()) *
2357 (
lm->get_right()*
rm->get_left());
2361 return (
lm->get_left()*
rm->get_left()) *
2362 (
lm->get_right()*
rm->get_right());
2367 if (
ld.get() &&
re.get()) {
2371 return ld->get_left()*(this->
right/
ld->get_right());
2376 return (
ld->get_left()*
this->right)/
ld->get_right();
2379 if (
rd.get() &&
le.get()) {
2383 return rd->get_left()*(this->
left/
rd->get_right());
2388 return (this->
left*
rd->get_left())/
rd->get_right();
2392 if (
ld.get() &&
rm.get()) {
2398 return (
ld->get_left()*
rm->get_right()) *
2399 (
rm->get_left()/
ld->get_right());
2404 return (
rm->get_right()/
ld->get_right()) *
2405 (
ld->get_left()*
rm->get_left());
2413 return (
ld->get_left()*
rm->get_left()) *
2414 (
rm->get_right()/
ld->get_right());
2419 return (
rm->get_left()/
ld->get_right()) *
2420 (
ld->get_left()*
rm->get_right());
2423 }
else if (
rd.get() &&
lm.get()) {
2429 return (
lm->get_left()/
rd->get_right()) *
2430 (
lm->get_right()*
rd->get_left());
2435 return (
lm->get_left()*
rd->get_left()) *
2436 (
lm->get_right()/
rd->get_right());
2444 return (
lm->get_right()*
rd->get_left()) *
2445 (
lm->get_left()/
rd->get_right());
2450 return (
lm->get_right()/
rd->get_right()) *
2451 (
lm->get_left()*
rd->get_left());
2460 auto fma_reduce = this->reduce_nested_fma_times_constant(this->
right);
2484 if constexpr (std::floating_point<T>) {
2491 pow(
lhypot->get_right(),
static_cast<T
> (2))) *
2495 pow(
rhypot->get_right(),
static_cast<T
> (2))) *
2507 lsqrpc->get_left()->is_match(
rcsc->get_right())) {
2508 return rcsc->get_right();
2510 }
else if (
lcsc.get() &&
rsqr.get()) {
2514 rsqrpc->get_left()->is_match(
lcsc->get_right())) {
2515 return lcsc->get_right();
2528 if (
lald.get() &&
lald->get_right()->is_match(
this->right)) {
2530 }
else if (
lard.get() &&
lard->get_right()->is_match(
this->right)) {
2533 }
else if (
ra.get()) {
2536 if (
rald.get() &&
rald->get_right()->is_match(
this->left)) {
2538 }
else if (
rard.get() &&
rard->get_right()->is_match(
this->left)) {
2552 if (
lsld.get() &&
lsld->get_right()->is_match(
this->right)) {
2553 return lsld->get_left() -
ls->get_right()*this->
right;
2554 }
else if (
lsrd.get() &&
lsrd->get_right()->is_match(
this->right)) {
2555 return ls->get_left()*this->
right -
lsrd->get_left();
2557 }
else if (
rs.get()) {
2560 if (
rsld.get() &&
rsld->get_right()->is_match(
this->left)) {
2561 return rsld->get_right() -
rs->get_right()*this->
left;
2562 }
else if (
rsrd.get() &&
rsrd->get_right()->is_match(
this->left)) {
2563 return rs->get_left()*this->
left -
rsld->get_left();
2590 const size_t hash =
reinterpret_cast<size_t> (x.get());
2612 if (registers.find(
this) == registers.end()) {
2615 auto r = this->
right->compile(stream, registers,
2619 stream <<
" const ";
2620 jit::add_type<T> (stream);
2621 stream <<
" " << registers[
this] <<
" = ";
2623 stream <<
"(" << registers[l.get()] <<
" == ";
2625 jit::add_type<T> (stream);
2630 stream <<
" || " << registers[
r.get()] <<
" == ";
2632 jit::add_type<T> (stream);
2639 jit::add_type<T> (stream);
2646 stream << registers[l.get()] <<
"*"
2647 << registers[
r.get()];
2661 if (
this == x.get()) {
2668 if ((this->
left->is_match(
x_cast->get_left()) &&
2669 this->right->is_match(
x_cast->get_right())) ||
2670 (
this->right->is_match(
x_cast->get_left()) &&
2671 this->left->is_match(
x_cast->get_right()))) {
2686 std::cout <<
"\\left(";
2687 this->
left->to_latex();
2688 std::cout <<
"\\right)";
2690 this->
left->to_latex();
2696 std::cout <<
"\\left(";
2697 this->
right->to_latex();
2698 std::cout <<
"\\right)";
2700 this->
right->to_latex();
2711 return this->
left->remove_pseudo() *
2712 this->
right->remove_pseudo();
2726 if (registers.find(
this) == registers.end()) {
2728 registers[
this] =
name;
2729 stream <<
" " <<
name
2730 <<
" [label = \"⨉\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
2733 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
2734 auto r = this->
right->to_vizgraph(stream, registers);
2735 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
2751 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2754 auto temp = std::make_shared<multiply_node<T, SAFE_MATH>> (l,
r)->reduce();
2756 for (
size_t i =
temp->get_hash();
2766#if defined(__clang__) || defined(__GNUC__)
2769 assert(
false &&
"Should never reach.");
2785 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2804 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
2823 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
2830 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2842 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2844 return std::dynamic_pointer_cast<multiply_node<T, SAFE_MATH>> (x);
2856 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2915 if ((l.get() && l->is(0)) ||
2916 (
r.get() &&
r->is(1))) {
2918 }
else if (l.get() &&
r.get()) {
2925 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
2927 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
2934 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
2936 pl2->get_num_columns(),
2939 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
2941 pr2->get_num_columns(),
2947 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
2951 pr2->get_num_columns(),
2954 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
2958 pr2->get_num_columns(),
2961 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
2965 pl2->get_num_columns(),
2968 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
2972 pl2->get_num_columns(),
2977 if (this->
left->is_match(
this->right)) {
2982 if (this->
right->is_constant()) {
2993 return this->
left*
rald->get_right() /
2997 }
else if (
rard.get()) {
2998 return this->
left*
rard->get_right() /
3012 return this->
left*
rsld->get_right() /
3014 rsld->get_right()*
rs->get_right());
3015 }
else if (
rsrd.get()) {
3016 return this->
left*
rsrd->get_right() /
3017 (
rsrd->get_right()*
rs->get_left() -
3030 if (
lfma->get_middle()->is_match(
this->right) &&
3031 fmarm->get_right()->is_match(
this->right)) {
3032 return lfma->get_left() +
fmarm->get_left();
3033 }
else if (
lfma->get_middle()->is_match(
this->right) &&
3034 fmarm->get_left()->is_match(
this->right)) {
3035 return lfma->get_left() +
fmarm->get_right();
3036 }
else if (
lfma->get_left()->is_match(
this->right) &&
3037 fmarm->get_right()->is_match(
this->right)) {
3038 return lfma->get_middle() +
fmarm->get_left();
3039 }
else if (
lfma->get_left()->is_match(
this->right) &&
3040 fmarm->get_left()->is_match(
this->right)) {
3041 return lfma->get_middle() +
fmarm->get_right();
3050 if (
lm.get() &&
rm.get()) {
3055 return (
lm->get_left()/
rm->get_left()) *
3056 (
lm->get_right()/
rm->get_right());
3061 return (
lm->get_left()/
rm->get_right()) *
3062 (
lm->get_right()/
rm->get_left());
3070 if (
rm->get_left()->is_constant() &&
3071 rm->get_left()->is_normal()) {
3072 return ((1.0/
rm->get_left())*this->
left)/
rm->get_right();
3073 }
else if (
rm->get_right()->is_constant() &&
3074 rm->get_right()->is_normal()) {
3075 return ((1.0/
rm->get_right())*this->
left)/
rm->get_left();
3091 rmlald->get_left())*
rm->get_right());
3092 }
else if (
rmlard.get()) {
3096 rmlard->get_left())*
rm->get_right());
3106 rmrald->get_left())*
rm->get_left());
3107 }
else if (
rmrard.get()) {
3111 rmrard->get_left())*
rm->get_left());
3127 rmlsld->get_right()*
rmls->get_right())*
rm->get_right());
3128 }
else if (
rmlsrd.get()) {
3131 rmlsrd->get_left())*
rm->get_right());
3140 rmrsld->get_right()*
rmrs->get_right())*
rm->get_left());
3141 }
else if (
rmrsrd.get()) {
3144 rmrsrd->get_left())*
rm->get_left());
3149 if (
lm.get() &&
rm.get()) {
3154 if (
lm->get_left()->is_match(
rm->get_left())) {
3155 return lm->get_right()/
rm->get_right();
3156 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
3157 return lm->get_right()/
rm->get_left();
3158 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
3159 return lm->get_left()/
rm->get_right();
3160 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
3161 return lm->get_left()/
rm->get_left();
3168 if (
lm->get_left()->is_match(this->
right)) {
3169 return lm->get_right();
3170 }
else if (
lm->get_right()->is_match(this->
right)) {
3171 return lm->get_left();
3178 return lm->get_right()*(
lm->get_left()/this->
right);
3181 return lm->get_left()*(
lm->get_right()/this->
right);
3190 return ld->get_left()/(
ld->get_right()*this->
right);
3193 return this->
left*
rd->get_right()/
rd->get_left();
3199 return pow(this->
left->get_power_base(),
3200 this->left->get_power_exponent() -
3201 this->right->get_power_exponent());
3209 return this->
left*
pow(
rp->get_left(), -
rp->get_right());
3219 if (
lpm->get_left()->is_match(
this->right->get_power_base())) {
3220 return pow(this->
right->get_power_base(),
3221 this->left->get_power_exponent() -
3222 this->right->get_power_exponent()) *
3224 this->left->get_power_exponent());
3225 }
else if (
lpm->get_right()->is_match(
this->right->get_power_base())) {
3226 return pow(this->
right->get_power_base(),
3227 this->left->get_power_exponent() -
3228 this->right->get_power_exponent()) *
3230 this->left->get_power_exponent());
3236 if (
lp.get() &&
rp.get()) {
3237 if (
lp->get_right()->is_match(
rp->get_right())) {
3238 return pow(
lp->get_left()/
rp->get_left(),
lp->get_right());
3246 if (
lp.get() &&
rm.get()) {
3249 if (
lpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3250 return (
pow(
rm->get_left()->get_power_base(),
3251 this->left->get_power_exponent() -
3252 rm->get_left()->get_power_exponent()) *
3254 this->left->get_power_exponent())) /
3256 }
else if (
lpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3257 return (
pow(
rm->get_left()->get_power_base(),
3258 this->left->get_power_exponent() -
3259 rm->get_left()->get_power_exponent()) *
3261 this->left->get_power_exponent())) /
3263 }
else if (
lpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3264 return (
pow(
rm->get_right()->get_power_base(),
3265 this->left->get_power_exponent() -
3266 rm->get_right()->get_power_exponent()) *
3268 this->left->get_power_exponent())) /
3270 }
else if (
lpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3271 return (
pow(
rm->get_right()->get_power_base(),
3272 this->left->get_power_exponent() -
3273 rm->get_right()->get_power_exponent()) *
3275 this->left->get_power_exponent())) /
3291 return lm->get_left()*
lmrm->get_left() *
3295 return lm->get_left()*
lmrm->get_right() *
3298 }
else if (
lmlm.get()) {
3301 return lm->get_right()*
lmlm->get_left() *
3305 return lm->get_right()*
lmlm->get_right() *
3319 if (
lmlpm->get_left()->is_match(
this->right->get_power_base())) {
3320 return lm->get_right() *
3322 lmlp->get_power_exponent() -
3323 this->right->get_power_exponent()) *
3325 lmlp->get_power_exponent());
3326 }
else if (
lmlpm->get_right()->is_match(
this->right->get_power_base())) {
3327 return lm->get_right() *
3329 lmlp->get_power_exponent() -
3330 this->right->get_power_exponent()) *
3332 lmlp->get_power_exponent());
3335 }
else if (
lmrp.get()) {
3338 if (
lmrpm->get_left()->is_match(
this->right->get_power_base())) {
3339 return lm->get_left() *
3341 lmrp->get_power_exponent() -
3342 this->right->get_power_exponent()) *
3344 lmrp->get_power_exponent());
3345 }
else if (
lmrpm->get_right()->is_match(
this->right->get_power_base())) {
3346 return lm->get_left() *
3348 lmrp->get_power_exponent() -
3349 this->right->get_power_exponent()) *
3351 lmrp->get_power_exponent());
3365 if (
lm.get() &&
rm.get()) {
3371 if (
lmlpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3372 return lm->get_right() *
3373 (
pow(
rm->get_left()->get_power_base(),
3374 lmlp->get_power_exponent() -
3375 rm->get_left()->get_power_exponent())) *
3377 lmlp->get_power_exponent()) /
3379 }
else if (
lmlpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3380 return lm->get_right() *
3381 (
pow(
rm->get_left()->get_power_base(),
3382 lmlp->get_power_exponent() -
3383 rm->get_left()->get_power_exponent())) *
3385 lmlp->get_power_exponent()) /
3387 }
else if (
lmlpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3388 return lm->get_right() *
3389 (
pow(
rm->get_left()->get_power_base(),
3390 lmlp->get_power_exponent() -
3391 rm->get_right()->get_power_exponent())) *
3393 lmlp->get_power_exponent()) /
3395 }
else if (
lmlpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3396 return lm->get_right() *
3397 (
pow(
rm->get_left()->get_power_base(),
3398 lmlp->get_power_exponent() -
3399 rm->get_right()->get_power_exponent())) *
3401 lmlp->get_power_exponent()) /
3405 }
else if (
lmrp.get()) {
3408 if (
lmrpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3409 return lm->get_left() *
3410 (
pow(
rm->get_left()->get_power_base(),
3411 lmrp->get_power_exponent() -
3412 rm->get_left()->get_power_exponent())) *
3414 lmrp->get_power_exponent()) /
3416 }
else if (
lmrpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3417 return lm->get_left() *
3418 (
pow(
rm->get_left()->get_power_base(),
3419 lmrp->get_power_exponent() -
3420 rm->get_left()->get_power_exponent())) *
3422 lmrp->get_power_exponent()) /
3424 }
else if (
lmrpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3425 return lm->get_left() *
3426 (
pow(
rm->get_left()->get_power_base(),
3427 lmrp->get_power_exponent() -
3428 rm->get_right()->get_power_exponent())) *
3430 lmrp->get_power_exponent()) /
3432 }
else if (
lmrpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3433 return lm->get_left() *
3434 (
pow(
rm->get_left()->get_power_base(),
3435 lmrp->get_power_exponent() -
3436 rm->get_right()->get_power_exponent())) *
3438 lmrp->get_power_exponent()) /
3454 if (
rexp.get() &&
lm.get()) {
3457 return lm->get_left()*(
lm->get_right()/this->
right);
3461 return lm->get_right()*(
lm->get_left()/this->
right);
3468 if (
rexp.get() &&
lm.get()) {
3474 return lmlm->get_left()*
lm->get_right() *
3477 return lmlm->get_right()*
lm->get_right() *
3480 }
else if (
lmrm.get()) {
3482 return lmrm->get_left()*
lm->get_left() *
3485 return lmrm->get_right()*
lm->get_left() *
3493 if (
lexp.get() &&
rm.get()) {
3496 return (this->
left/
rm->get_right())/
rm->get_left();
3500 return (this->
left/
rm->get_left())/
rm->get_right();
3508 if (
lm.get() &&
rm.get()) {
3513 return (
lm->get_left()/
rm->get_left()) *
3514 (
lm->get_right()/
rm->get_right());
3518 return (
lm->get_left()/
rm->get_right()) *
3519 (
lm->get_right()/
rm->get_left());
3526 return (
lm->get_right()/
rm->get_left()) *
3527 (
lm->get_left()/
rm->get_right());
3531 return (
lm->get_right()/
rm->get_right()) *
3532 (
lm->get_left()/
rm->get_left());
3539 if (
rd.get() &&
lexp.get()) {
3542 return (this->
left*
rd->get_right())/
rd->get_left();
3546 return rd->get_right()*(this->
left/
rd->get_left());
3576 const size_t hash =
reinterpret_cast<size_t> (x.get());
3598 if (registers.find(
this) == registers.end()) {
3601 auto r = this->
right->compile(stream, registers,
3605 stream <<
" const ";
3606 jit::add_type<T> (stream);
3607 stream <<
" " << registers[
this] <<
" = ";
3609 stream << registers[l.get()] <<
" == ";
3611 jit::add_type<T> (stream);
3618 jit::add_type<T> (stream);
3625 stream << registers[l.get()] <<
"/"
3626 << registers[
r.get()];
3639 if (
this == x.get()) {
3645 return this->
left->is_match(
x_cast->get_left()) &&
3656 std::cout <<
"\\frac{";
3657 this->
left->to_latex();
3659 this->
right->to_latex();
3670 return this->
left->remove_pseudo() /
3671 this->
right->remove_pseudo();
3685 if (registers.find(
this) == registers.end()) {
3687 registers[
this] =
name;
3688 stream <<
" " <<
name
3689 <<
" [label = \"\\\\\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
3692 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
3693 auto r = this->
right->to_vizgraph(stream, registers);
3694 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
3710 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3713 auto temp = std::make_shared<divide_node<T, SAFE_MATH>> (l,
r)->reduce();
3715 for (
size_t i =
temp->get_hash();
3725#if defined(__clang__) || defined(__GNUC__)
3728 assert(
false &&
"Should never reach.");
3744 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3763 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
3782 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
3789 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3801 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3803 return std::dynamic_pointer_cast<divide_node<T, SAFE_MATH>> (x);
3817 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3835 temp->get_middle()->is_match(sub->get_left())) {
3838 temp->get_right() -
temp->get_left()*sub->get_right()),
3840 this->right -
temp->get_right()*sub->get_right());
3842 if (
temp->get_middle()->is_match(sub->get_left()) &&
3844 auto temp2 =
temp->reduce_nested_fma(sub);
3848 this->right -
temp->get_right()*sub->get_right());
3918 if ((l.get() && l->is(0)) ||
3919 (m.get() && m->is(0))) {
3921 }
else if (r.get() &&
r->is(0)) {
3923 }
else if (l.get() && m.get() &&
r.get()) {
3925 }
else if (l.get() && m.get()) {
3927 }
else if (l.get() && l->is(-1)) {
3929 }
else if (m.get() && m->is(-1)) {
3931 }
else if (l.get() && l->is(1)) {
3933 }
else if (m.get() && m->is(1)) {
3952 if (this->
left->is_match(
this->right)) {
3954 }
else if (this->
middle->is_match(
this->right)) {
3975 return fma(-this->
left,
ms->get_right(),
3983 auto temp = this->reduce_nested_fma(
ms);
3984 if (
temp.get() !=
this) {
3995 if (
rm->get_left()->is_match(
this->left)) {
3997 }
else if (
rm->get_left()->is_match(this->
middle)) {
3999 }
else if (
rm->get_right()->is_match(this->
left)) {
4001 }
else if (
rm->get_right()->is_match(this->
middle)) {
4008 if (
rmlc.get() &&
rmlc->evaluate().is_negative()) {
4010 (-1.0*
rm->get_left())*
rm->get_right();
4020 !this->
left->has_constant_zero()) {
4022 if (
temp->is_normal()) {
4030 !
this->middle->has_constant_zero()) {
4032 if (
temp->is_normal()) {
4040 !
this->left->has_constant_zero()) {
4042 if (
temp->is_normal()) {
4050 !
this->middle->has_constant_zero()) {
4052 if (
temp->is_normal()) {
4064 if (
mm->get_left()->is_match(
rm->get_left())) {
4068 }
else if (
mm->get_left()->is_match(
rm->get_right())) {
4072 }
else if (
mm->get_right()->is_match(
rm->get_left())) {
4076 }
else if (
mm->get_right()->is_match(
rm->get_right())) {
4085 if ((
lm.get() ||
mm.get()) &&
4086 (
this->left->get_complexity() +
this->middle->get_complexity() >
4087 this->right->get_complexity())) {
4088 return fma(
rm->get_left(),
rm->get_right(),
4098 if (
lm.get() &&
rm.get()) {
4101 !
lm->get_left()->has_constant_zero()) {
4102 auto temp =
rm->get_left()/
lm->get_left();
4103 if (
temp->is_normal()){
4104 return lm->get_left()*
fma(
lm->get_right(),
4111 !
lm->get_right()->has_constant_zero()) {
4112 auto temp =
rm->get_left()/
lm->get_right();
4113 if (
temp->is_normal()){
4114 return lm->get_right()*
fma(
lm->get_left(),
4121 !
lm->get_left()->has_constant_zero()) {
4122 auto temp =
rm->get_right()/
lm->get_left();
4123 if (
temp->is_normal()) {
4124 return lm->get_left()*
fma(
lm->get_right(),
4131 !
lm->get_right()->has_constant_zero()) {
4132 auto temp =
rm->get_right()/
lm->get_right();
4133 if (
temp->is_normal()) {
4134 return lm->get_right()*
fma(
lm->get_left(),
4146 return fma(
lm->get_left(),
4147 lm->get_right()*
this->middle,
4150 }
else if (
mm.get()) {
4157 if (
temp->is_normal()) {
4166 if (
temp->is_normal()) {
4174 return fma(
mm->get_left(),
4175 this->left*
mm->get_right(),
4182 if (
mm->get_left()->is_match(
this->right)) {
4186 }
else if (
mm->get_right()->is_match(
this->right)) {
4199 !
this->left->has_constant_zero()) {
4201 if (
temp->is_normal()) {
4208 !this->
middle->has_constant_zero()) {
4210 if (
temp->is_normal()) {
4220 if (
ld.get() &&
ld->get_right()->is_match(
this->middle)) {
4221 return ld->get_left() + this->
right;
4224 if (
md.get() &&
md->get_right()->is_match(
this->left)) {
4225 return md->get_left() + this->
right;
4229 if (
ld.get() &&
rd.get()) {
4231 if (
ld->get_left()->is_match(
rd->get_left())) {
4232 return ld->get_left()*(this->
middle/
ld->get_right() +
4233 1.0/
rd->get_right());
4244 if (
ldrm->get_right()->is_match(
rd->get_right())) {
4245 return fma(
ld->get_left(),
this->middle,
4246 rd->get_left()*
ldrm->get_left()) /
4248 }
else if (
ldrm->get_left()->is_match(
rd->get_right())) {
4249 return fma(
ld->get_left(),
this->middle,
4250 rd->get_left()*
ldrm->get_right()) /
4253 }
else if (
rdrm.get()) {
4254 if (
rdrm->get_right()->is_match(
ld->get_right())) {
4255 return fma(
ld->get_left()*
rdrm->get_left(),
4256 this->middle,
rd->get_left()) /
4258 }
else if (
rdrm->get_left()->is_match(
ld->get_right())) {
4259 return fma(
ld->get_left()*
rdrm->get_right(),
4260 this->middle,
rd->get_left()) /
4264 }
else if (
md.get() &&
rd.get()) {
4273 if (
mdrm->get_right()->is_match(
rd->get_right())) {
4275 rd->get_left()*
mdrm->get_left()) /
4277 }
else if (
mdrm->get_left()->is_match(
rd->get_right())) {
4279 rd->get_left()*
mdrm->get_right()) /
4282 }
else if (
rdrm.get()) {
4283 if (
rdrm->get_right()->is_match(
md->get_right())) {
4287 }
else if (
rdrm->get_left()->is_match(
md->get_right())) {
4302 if (this->
middle->is_match(
rfma->get_middle())) {
4306 }
else if (this->
left->is_match(
rfma->get_middle())) {
4310 }
else if (this->
middle->is_match(
rfma->get_left())) {
4314 }
else if (this->
left->is_match(
rfma->get_left())) {
4325 if (
mm->get_right()->is_match(
rfma->get_middle())) {
4326 return fma(
mm->get_right(),
4331 }
else if (
mm->get_left()->is_match(
rfma->get_middle())) {
4332 return fma(
mm->get_left(),
4337 }
else if (
mm->get_right()->is_match(
rfma->get_left())) {
4338 return fma(
mm->get_right(),
4341 rfma->get_middle()),
4343 }
else if (
mm->get_left()->is_match(
rfma->get_left())) {
4344 return fma(
mm->get_left(),
4347 rfma->get_middle()),
4350 }
else if (
lm.get()) {
4355 if (
lm->get_right()->is_match(
rfma->get_middle())) {
4356 return fma(
lm->get_right(),
4361 }
else if (
lm->get_left()->is_match(
rfma->get_middle())) {
4362 return fma(
lm->get_left(),
4367 }
else if (
lm->get_right()->is_match(
rfma->get_left())) {
4368 return fma(
lm->get_right(),
4371 rfma->get_middle()),
4373 }
else if (
lm->get_left()->is_match(
rfma->get_left())) {
4374 return fma(
lm->get_left(),
4377 rfma->get_middle()),
4389 if (
rfmamm->get_right()->is_match(
this->middle)) {
4395 }
else if (
rfmamm->get_right()->is_match(
this->left)) {
4401 }
else if (
rfmamm->get_left()->is_match(
this->middle)) {
4407 }
else if (
rfmamm->get_left()->is_match(
this->left)) {
4414 }
else if (
rfmalm.get()) {
4419 if (
rfmalm->get_right()->is_match(
this->middle)) {
4425 }
else if (
rfmalm->get_right()->is_match(
this->left)) {
4431 }
else if (
rfmalm->get_left()->is_match(
this->middle)) {
4437 }
else if (
rfmalm->get_left()->is_match(
this->left)) {
4451 if (
mm->get_right()->is_match(
rfmamm->get_right())) {
4452 return fma(
mm->get_right(),
4457 }
else if (
mm->get_left()->is_match(
rfmamm->get_right())) {
4458 return fma(
mm->get_left(),
4463 }
else if (
mm->get_right()->is_match(
rfmamm->get_left())) {
4464 return fma(
mm->get_right(),
4469 }
else if (
mm->get_left()->is_match(
rfmamm->get_left())) {
4470 return fma(
mm->get_left(),
4476 }
else if (
lm.get() &&
rfmamm.get()) {
4481 if (
lm->get_right()->is_match(
rfmamm->get_right())) {
4482 return fma(
lm->get_right(),
4487 }
else if (
lm->get_left()->is_match(
rfmamm->get_right())) {
4488 return fma(
lm->get_left(),
4493 }
else if (
lm->get_right()->is_match(
rfmamm->get_left())) {
4494 return fma(
lm->get_right(),
4499 }
else if (
lm->get_left()->is_match(
rfmamm->get_left())) {
4500 return fma(
lm->get_left(),
4506 }
else if (
mm.get() &&
rfmalm.get()) {
4511 if (
mm->get_right()->is_match(
rfmalm->get_right())) {
4512 return fma(
mm->get_right(),
4517 }
else if (
mm->get_left()->is_match(
rfmalm->get_right())) {
4518 return fma(
mm->get_left(),
4523 }
else if (
mm->get_right()->is_match(
rfmalm->get_left())) {
4524 return fma(
mm->get_right(),
4529 }
else if (
mm->get_left()->is_match(
rfmalm->get_left())) {
4530 return fma(
mm->get_left(),
4536 }
else if (
lm.get() &&
rfmalm.get()) {
4541 if (
lm->get_right()->is_match(
rfmalm->get_right())) {
4542 return fma(
lm->get_right(),
4547 }
else if (
lm->get_left()->is_match(
rfmalm->get_right())) {
4548 return fma(
lm->get_left(),
4553 }
else if (
lm->get_right()->is_match(
rfmalm->get_left())) {
4554 return fma(
lm->get_right(),
4559 }
else if (
lm->get_left()->is_match(
rfmalm->get_left())) {
4560 return fma(
lm->get_left(),
4571 return fma(
rfma->get_middle(),
4587 return fma(
rfma->get_middle(),
4606 rfma->get_middle()),
4622 rfma->get_middle()),
4636 if (this->
left->is_match(
rfma->get_left()) &&
4637 this->middle->is_match(
rfma->get_middle())) {
4639 }
else if (this->
left->is_match(
rfma->get_middle()) &&
4640 this->middle->is_match(
rfma->get_left())) {
4651 if (
fmald.get() &&
ld->get_right()->is_match(
fmald->get_right())) {
4652 return (
ld->get_left()*
this->middle +
4653 fmald->get_left()*
rfma->get_middle())/
ld->get_right() +
4655 }
else if (
fmamd.get() &&
ld->get_right()->is_match(
fmamd->get_right())) {
4656 return (
ld->get_left()*
this->middle +
4657 fmamd->get_left()*
rfma->get_left())/
ld->get_right() +
4660 }
else if (
md.get()) {
4661 if (
fmald.get() &&
md->get_right()->is_match(
fmald->get_right())) {
4662 return (
md->get_left()*
this->left +
4663 fmald->get_left()*
rfma->get_middle())/
md->get_right() +
4665 }
else if (
fmamd.get() &&
md->get_right()->is_match(
fmamd->get_right())) {
4666 return (
md->get_left()*
this->left +
4667 fmamd->get_left()*
rfma->get_left())/
md->get_right() +
4676 if (this->
left->is_all_variables()) {
4678 if (
rdl->get_complexity() <
this->left->get_complexity() +
4679 this->right->get_complexity()) {
4682 }
else if (this->
middle->is_all_variables()) {
4685 if ((
rdm->get_complexity() <
this->middle->get_complexity() +
4686 this->right->get_complexity()) &&
4687 !(
rdmc.get() &&
rdmc->evaluate().is_negative())) {
4707 return this->
left/
pow(
mp->get_left(), -
mp->get_right()) +
4726 if (
lp.get() &&
mp.get()) {
4727 if (
lp->get_right()->is_match(
mp->get_right())) {
4728 return pow(
lp->get_left()*
mp->get_left(),
4735 if (
rm.get() &&
mp.get()) {
4756 if (
rfma.get() &&
mp.get()) {
4760 rfma->get_left())) {
4766 rfma->get_middle()),
4769 rfma->get_left())) {
4775 rfma->get_middle()),
4790 rfma->get_right()));
4798 if (
md.get() &&
rd.get()) {
4799 if (
md->get_left()->is_match(
rd->get_left())) {
4800 return md->get_left()*(this->
left/
md->get_right() +
4801 1.0/
rd->get_right());
4802 }
else if (
md->get_right()->is_match(
rd->get_right())) {
4803 return (this->
left*
md->get_left() +
4804 rd->get_left())/
md->get_right();
4809 if (
ld.get() &&
rd.get()) {
4810 if (
ld->get_left()->is_match(
rd->get_left())) {
4811 return ld->get_left()*(this->
middle/
ld->get_right() +
4812 1.0/
rd->get_right());
4813 }
else if (
ld->get_right()->is_match(
rd->get_right())) {
4814 return (this->
middle*
ld->get_left() +
4815 rd->get_left())/
ld->get_right();
4821 if (
rm.get() &&
ld.get()) {
4823 if (
rmld.get() &&
ld->get_right()->is_match(
rmld->get_right())) {
4824 return fma(
ld->get_left(),
this->middle,
rmld->get_left()*
rm->get_right())/
ld->get_right();
4827 if (
rmrd.get() &&
ld->get_right()->is_match(
rmrd->get_right())) {
4828 return fma(
ld->get_left(),
this->middle,
rmrd->get_left()*
rm->get_left())/
ld->get_right();
4833 if (
rm.get() &&
md.get()) {
4835 if (
rmld.get() &&
md->get_right()->is_match(
rmld->get_right())) {
4836 return fma(this->
left,
md->get_left(),
rmld->get_left()*
rm->get_right())/
md->get_right();
4839 if (
rmrd.get() &&
md->get_right()->is_match(
rmrd->get_right())) {
4840 return fma(this->
left,
md->get_left(),
rmrd->get_left()*
rm->get_left())/
md->get_right();
4846 if (
rd.get() &&
lm.get()) {
4848 if (
lmld.get() &&
rd->get_right()->is_match(
lmld->get_right())) {
4849 return fma(
lmld->get_left()*
lm->get_right(),
this->middle,
rd->get_left())/
rd->get_right();
4852 if (
lmrd.get() &&
rd->get_right()->is_match(
lmrd->get_right())) {
4853 return fma(
lmld->get_left()*
lm->get_left(),
this->middle,
rd->get_left())/
rd->get_right();
4858 if (
rd.get() &&
mm.get()) {
4860 if (
mmld.get() &&
rd->get_right()->is_match(
mmld->get_right())) {
4861 return fma(this->
left,
mmld->get_left()*
mm->get_right(),
rd->get_left())/
rd->get_right();
4864 if (
mmrd.get() &&
rd->get_right()->is_match(
mmrd->get_right())) {
4865 return fma(this->
left,
mmrd->get_left()*
mm->get_left(),
rd->get_left())/
rd->get_right();
4877 if (
md.get() &&
rm.get()) {
4881 if (
rmlmld.get() &&
rmlmld->get_right()->is_match(
md->get_right())) {
4883 rmlmld->get_left()*
rmlm->get_right()*
rm->get_right())/
md->get_right();
4886 if (
rmlmrd.get() &&
rmlmrd->get_right()->is_match(
md->get_right())) {
4888 rmlmrd->get_left()*
rmlm->get_left()*
rm->get_right())/
md->get_right();
4894 if (
rmrmld.get() &&
rmrmld->get_right()->is_match(
md->get_right())) {
4896 rmrmld->get_left()*
rmrm->get_right()*
rm->get_left())/
md->get_right();
4899 if (
rmrmrd.get() &&
rmrmrd->get_right()->is_match(
md->get_right())) {
4901 rmrmrd->get_left()*
rmrm->get_left()*
rm->get_left())/
md->get_right();
4904 }
else if (
ld.get() &&
rm.get()) {
4908 if (
rmlmld.get() &&
rmlmld->get_right()->is_match(
ld->get_right())) {
4909 return fma(
ld->get_left(),
this->middle,
4910 rmlmld->get_left()*
rmlm->get_right()*
rm->get_right())/
ld->get_right();
4913 if (
rmlmrd.get() &&
rmlmrd->get_right()->is_match(
ld->get_right())) {
4914 return fma(
ld->get_left(),
this->middle,
4915 rmlmrd->get_left()*
rmlm->get_right()*
rm->get_right())/
ld->get_right();
4921 if (
rmrmld.get() &&
rmrmld->get_right()->is_match(
ld->get_right())) {
4922 return fma(
ld->get_left(),
this->middle,
4923 rmrmld->get_left()*
rmrm->get_right()*
rm->get_left())/
ld->get_right();
4926 if (
rmrmrd.get() &&
rmrmrd->get_right()->is_match(
ld->get_right())) {
4927 return fma(
ld->get_left(),
this->middle,
4928 rmrmrd->get_left()*
rmrm->get_left()*
rm->get_left())/
ld->get_right();
4936 if (
le.get() && me.get()) {
4937 return exp(
le->get_arg() + me->get_arg()) + this->
right;
4942 if (
mm.get() &&
le.get()) {
4958 if (
lm.get() && me.get()) {
4967 return fma(
lm->get_right()*
this->middle,
4977 if (
lm.get() &&
mm.get()) {
4982 return fma(
lm->get_left()*
mm->get_left(),
4983 lm->get_right()*
mm->get_right(),
4988 return fma(
lm->get_left()*
mm->get_right(),
4989 lm->get_right()*
mm->get_left(),
4997 return fma(
lm->get_right()*
mm->get_left(),
4998 lm->get_left()*
mm->get_right(),
5003 return fma(
lm->get_right()*
mm->get_right(),
5004 lm->get_left()*
mm->get_left(),
5014 if (
lm.get() &&
md.get()) {
5019 return fma(
lm->get_left()*
md->get_left(),
5020 lm->get_right()/
md->get_right(),
5025 return fma(
lm->get_left()/
md->get_right(),
5026 lm->get_right()*
md->get_left(),
5034 return fma(
lm->get_right()*
md->get_left(),
5035 lm->get_left()/
md->get_right(),
5040 return fma(
lm->get_right()/
md->get_right(),
5041 lm->get_left()*
md->get_left(),
5051 if (
ld.get() &&
mm.get()) {
5056 return fma(
ld->get_left()*
mm->get_left(),
5057 mm->get_right()/
ld->get_right(),
5062 return fma(
ld->get_left()*
mm->get_right(),
5063 mm->get_left()/
ld->get_right(),
5071 return fma(
mm->get_left()/
ld->get_right(),
5072 ld->get_left()*
mm->get_right(),
5077 return fma(
mm->get_right()/
ld->get_right(),
5078 ld->get_left()*
mm->get_left(),
5088 if (
ld.get() &&
md.get()) {
5093 return ((
ld->get_left()*
md->get_left()) /
5094 (
ld->get_right()*
md->get_right())) +
5099 return fma(
ld->get_left()/
md->get_right(),
5100 md->get_left()/
ld->get_right(),
5108 return fma(
md->get_left()/
ld->get_right(),
5109 ld->get_left()/
md->get_right(),
5114 return ((
ld->get_left()*
md->get_left()) /
5115 (
ld->get_right()*
md->get_right())) +
5128 if constexpr (std::floating_point<T>) {
5135 pow(
lhypot->get_right(),
static_cast<T
> (2))) *
5139 pow(
mhypot->get_right(),
static_cast<T
> (2))) *
5151 lsqrpc->get_left()->is_match(
mcsc->get_right())) {
5154 }
else if (
lcsc.get() &&
msqr.get()) {
5158 msqrpc->get_left()->is_match(
lcsc->get_right())) {
5181 const size_t hash =
reinterpret_cast<size_t> (x.get());
5185 this->right->df(x));
5208 if (registers.find(
this) == registers.end()) {
5213 auto r = this->
right->compile(stream, registers,
5217 stream <<
" const ";
5218 jit::add_type<T> (stream);
5219 stream <<
" " << registers[
this] <<
" = ";
5221 stream <<
"(" << registers[l.get()] <<
" == ";
5223 jit::add_type<T> (stream);
5228 stream <<
" || " << registers[m.get()] <<
" == ";
5230 jit::add_type<T> (stream);
5235 stream <<
") ? " << registers[
r.get()] <<
" : ";
5238 stream << registers[l.get()] <<
"*"
5239 << registers[m.get()] <<
" + "
5240 << registers[
r.get()];
5243 << registers[l.get()] <<
", "
5244 << registers[m.get()] <<
", "
5245 << registers[
r.get()] <<
")";
5260 if (
this == x.get()) {
5266 return this->
left->is_match(
x_cast->get_left()) &&
5278 std::cout <<
"\\left(";
5281 std::cout <<
"\\left(";
5282 this->
left->to_latex();
5283 std::cout <<
"\\right)";
5285 this->
left->to_latex();
5290 std::cout <<
"\\left(";
5291 this->
middle->to_latex();
5292 std::cout <<
"\\right)";
5294 this->
middle->to_latex();
5297 this->
right->to_latex();
5298 std::cout <<
"\\right)";
5308 return fma(this->
left->remove_pseudo(),
5309 this->middle->remove_pseudo(),
5310 this->right->remove_pseudo());
5324 if (registers.find(
this) == registers.end()) {
5326 registers[
this] =
name;
5327 stream <<
" " <<
name
5328 <<
" [label = \"fma\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
5331 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
5333 stream <<
" " <<
name <<
" -- " << registers[m.get()] <<
";" << std::endl;
5334 auto r = this->
right->to_vizgraph(stream, registers);
5335 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
5352 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5356 auto temp = std::make_shared<fma_node<T, SAFE_MATH>> (l, m,
r)->reduce();
5358 for (
size_t i =
temp->get_hash();
5368#if defined(__clang__) || defined(__GNUC__)
5371 assert(
false &&
"Should never reach.");
5389 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
5410 template<jit::
float_scalar T, jit::
float_scalar M,
bool SAFE_MATH=false>
5431 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
5453 template<jit::
float_scalar T, jit::
float_scalar L, jit::
float_scalar M,
bool SAFE_MATH=false>
5476 template<jit::
float_scalar T, jit::
float_scalar M, jit::
float_scalar R,
bool SAFE_MATH=false>
5499 template<jit::
float_scalar T, jit::
float_scalar L, jit::
float_scalar R,
bool SAFE_MATH=false>
5508 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5520 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5522 return std::dynamic_pointer_cast<fma_node<T, SAFE_MATH>> (x);
5536 template<std::
floating_po
int T,
bool SAFE_MATH=false>
5589 if (l.get() &&
r.get()) {
5610 if (registers.find(
this) == registers.end()) {
5611 auto l = this->left->
compile(stream, registers,
5613 auto r = this->right->compile(stream, registers,
5617 stream <<
" const ";
5618 jit::add_type<T> (stream);
5619 stream <<
" " << registers[
this] <<
" = fmod("
5620 << registers[l.get()] <<
","
5621 << registers[
r.get()] <<
")";
5637 std::cout <<
"\\left(";
5639 this->left->to_latex();
5641 std::cout <<
"\\right)";
5645 std::cout <<
"\\left(";
5647 this->right->to_latex();
5649 std::cout <<
"\\right)";
5662 if (registers.find(
this) == registers.end()) {
5664 registers[
this] =
name;
5665 stream <<
" " <<
name
5666 <<
" [label = \"%\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
5668 auto l = this->left->
to_vizgraph(stream, registers);
5669 stream <<
" " <<
name <<
" -- " << registers[l.get()] <<
";" << std::endl;
5670 auto r = this->right->to_vizgraph(stream, registers);
5671 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
5687 template<std::
floating_po
int T,
bool SAFE_MATH=false>
5690 auto temp = std::make_shared<modulo_node<T, SAFE_MATH>> (l,
r)->reduce();
5692 for (
size_t i =
temp->get_hash();
5702#if defined(__clang__) || defined(__GNUC__)
5705 assert(
false &&
"Should never reach.");
5721 template<std::
floating_po
int T,
bool SAFE_MATH=false>
5740 template<std::
floating_po
int T, std::
floating_po
int L,
bool SAFE_MATH=false>
5759 template<std::
floating_po
int T, std::
floating_po
int R,
bool SAFE_MATH=false>
5766 template<std::
floating_po
int T,
bool SAFE_MATH=false>
5778 template<std::
floating_po
int T,
bool SAFE_MATH=false>
5780 return std::dynamic_pointer_cast<modulo_node<T, SAFE_MATH>> (x);
Class representing a generic buffer.
Definition backend.hpp:29
void subtract_row(const buffer< T > &x)
Subtract row operation.
Definition backend.hpp:413
void multiply_row(const buffer< T > &x)
Multiply row operation.
Definition backend.hpp:437
void add_col(const buffer< T > &x)
Add col operation.
Definition backend.hpp:401
void divide_col(const buffer< T > &x)
Divide col operation.
Definition backend.hpp:473
void add_row(const buffer< T > &x)
Add row operation.
Definition backend.hpp:356
void subtract_col(const buffer< T > &x)
Subtract col operation.
Definition backend.hpp:425
void multiply_col(const buffer< T > &x)
Multiply col operation.
Definition backend.hpp:449
void divide_row(const buffer< T > &x)
Divide row operation.
Definition backend.hpp:461
bool is_zero() const
Is every element zero.
Definition backend.hpp:126
An addition node.
Definition arithmetic.hpp:132
virtual backend::buffer< T > evaluate()
Evaluate the results of addition.
Definition arithmetic.hpp:166
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:733
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:621
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition arithmetic.hpp:671
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:718
add_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Construct an addition node.
Definition arithmetic.hpp:154
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an addition node.
Definition arithmetic.hpp:177
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:691
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:643
Class representing a branch node.
Definition node.hpp:1337
shared_leaf< T, SAFE_MATH > right
Right branch of the tree.
Definition node.hpp:1342
shared_leaf< T, SAFE_MATH > left
Left branch of the tree.
Definition node.hpp:1340
A division node.
Definition arithmetic.hpp:2857
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an division node.
Definition arithmetic.hpp:2910
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:3668
divide_node(shared_leaf< T, SAFE_MATH > n, shared_leaf< T, SAFE_MATH > d)
Construct an addition node.
Definition arithmetic.hpp:2879
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition arithmetic.hpp:3638
virtual backend::buffer< T > evaluate()
Evaluate the results of division.
Definition arithmetic.hpp:2891
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:3683
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:3655
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:3594
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:3571
A fused multiply add node.
Definition arithmetic.hpp:3818
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:5306
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:5176
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:5204
virtual backend::buffer< T > evaluate()
Evaluate the results of fused multiply add.
Definition arithmetic.hpp:3894
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:5322
fma_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > m, shared_leaf< T, SAFE_MATH > r)
Construct a fused multiply add node.
Definition arithmetic.hpp:3880
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:5277
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce a fused multiply add node.
Definition arithmetic.hpp:3913
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition arithmetic.hpp:5259
Class representing a node leaf.
Definition node.hpp:371
virtual std::shared_ptr< leaf_node< T, SAFE_MATH > > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)=0
Compile the node.
virtual void endline(std::ostringstream &stream, const jit::register_usage &usage, const char end=';') const
End a line in the kernel source.
Definition node.hpp:653
virtual std::shared_ptr< leaf_node< T, SAFE_MATH > > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)=0
Convert the node to vizgraph.
virtual backend::buffer< T > evaluate()=0
Evaluate method.
virtual bool has_pseudo() const
Query if the node contains pseudo variables.
Definition node.hpp:633
const size_t hash
Hash for node.
Definition node.hpp:374
std::unordered_map< size_t, std::shared_ptr< leaf_node< T, SAFE_MATH > > > df_cache
Cache derivative terms.
Definition node.hpp:378
An Modulo node.
Definition arithmetic.hpp:5537
modulo_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Construct an modulo node.
Definition arithmetic.hpp:5559
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:5631
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:5660
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:5606
virtual backend::buffer< T > evaluate()
Evaluate the results of modulo.
Definition arithmetic.hpp:5573
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an modulo node.
Definition arithmetic.hpp:5584
A multiplication node.
Definition arithmetic.hpp:1724
virtual backend::buffer< T > evaluate()
Evaluate the results of multiplication.
Definition arithmetic.hpp:1863
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:2608
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:2585
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:2709
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an multiplication node.
Definition arithmetic.hpp:1888
multiply_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Construct a multiplication node.
Definition arithmetic.hpp:1852
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition arithmetic.hpp:2660
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:2724
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:2682
Nodes without derivatives.
Definition node.hpp:1713
A subtraction node.
Definition arithmetic.hpp:871
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:1483
subtract_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Construct a subtraction node.
Definition arithmetic.hpp:893
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:1461
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:1555
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition arithmetic.hpp:1511
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an subtraction node.
Definition arithmetic.hpp:916
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:1570
virtual backend::buffer< T > evaluate()
Evaluate the results of subtraction.
Definition arithmetic.hpp:905
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:1528
Class representing a triple branch node.
Definition node.hpp:1467
shared_leaf< T, SAFE_MATH > middle
Middle branch of the tree.
Definition node.hpp:1470
Complex scalar concept.
Definition register.hpp:25
subroutine assert(test, message)
Assert check.
Definition f_binding_test.f90:38
buffer< T > fma(buffer< T > &a, buffer< T > &b, buffer< T > &c)
Fused multiply add operation.
Definition backend.hpp:1219
Name space for graph nodes.
Definition arithmetic.hpp:13
shared_piecewise_2D< T, SAFE_MATH > piecewise_2D_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a piecewise 2D node.
Definition piecewise.hpp:1508
shared_leaf< T, SAFE_MATH > operator*(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build multiply node from two leaves.
Definition arithmetic.hpp:2786
std::shared_ptr< add_node< T, SAFE_MATH > > shared_add
Convenience type alias for shared add nodes.
Definition arithmetic.hpp:843
shared_pow< T, SAFE_MATH > pow_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a power node.
Definition math.hpp:1448
shared_subtract< T, SAFE_MATH > subtract_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a subtract node.
Definition arithmetic.hpp:1710
shared_leaf< T, SAFE_MATH > modulo(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build modulo node from two leaves.
Definition arithmetic.hpp:5688
constexpr shared_leaf< T, SAFE_MATH > zero()
Forward declare for zero.
Definition node.hpp:1154
shared_leaf< T, SAFE_MATH > operator/(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build divide node from two leaves.
Definition arithmetic.hpp:3745
shared_sqrt< T, SAFE_MATH > sqrt_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a sqrt node.
Definition math.hpp:331
shared_leaf< T, SAFE_MATH > multiply(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build multiply node from two leaves.
Definition arithmetic.hpp:2752
shared_add< T, SAFE_MATH > add_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a add node.
Definition arithmetic.hpp:855
bool is_greater_exponent(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if the exponent is greater than the other.
Definition arithmetic.hpp:111
shared_leaf< T, SAFE_MATH > operator+(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build add node from two leaves.
Definition arithmetic.hpp:798
std::shared_ptr< divide_node< T, SAFE_MATH > > shared_divide
Convenience type alias for shared divide nodes.
Definition arithmetic.hpp:3790
shared_leaf< T, SAFE_MATH > pow(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build power node.
Definition math.hpp:1384
shared_sine< T, SAFE_MATH > sin_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a sine node.
Definition trigonometry.hpp:258
shared_divide< T, SAFE_MATH > divide_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a divide node.
Definition arithmetic.hpp:3802
shared_piecewise_1D< T, SAFE_MATH > piecewise_1D_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a piecewise 1D node.
Definition piecewise.hpp:849
shared_leaf< T, SAFE_MATH > operator-(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build subtract node from two leaves.
Definition arithmetic.hpp:1634
shared_leaf< T, SAFE_MATH > divide(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build divide node from two leaves.
Definition arithmetic.hpp:3711
shared_multiply< T, SAFE_MATH > multiply_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a multiply node.
Definition arithmetic.hpp:2843
std::shared_ptr< modulo_node< T, SAFE_MATH > > shared_modulo
Convenience type alias for shared modulo nodes.
Definition arithmetic.hpp:5767
shared_modulo< T, SAFE_MATH > modulo_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a modulo node.
Definition arithmetic.hpp:5779
shared_leaf< T, SAFE_MATH > exp(shared_leaf< T, SAFE_MATH > x)
Define exp convenience function.
Definition math.hpp:558
shared_exp< T, SAFE_MATH > exp_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a exp node.
Definition math.hpp:592
bool is_constant_promotable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if the constants are promotable.
Definition arithmetic.hpp:53
shared_leaf< T, SAFE_MATH > fma(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > m, shared_leaf< T, SAFE_MATH > r)
Build fused multiply add node.
Definition arithmetic.hpp:5353
shared_constant< T, SAFE_MATH > constant_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a constant node.
Definition node.hpp:1202
bool is_variable_combinable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if the variable is combinable.
Definition arithmetic.hpp:75
constexpr T i
Convenience type for imaginary constant.
Definition node.hpp:1186
shared_leaf< T, SAFE_MATH > subtract(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build subtract node from two leaves.
Definition arithmetic.hpp:1599
std::shared_ptr< fma_node< T, SAFE_MATH > > shared_fma
Convenience type alias for shared add nodes.
Definition arithmetic.hpp:5509
shared_leaf< T, SAFE_MATH > sqrt(shared_leaf< T, SAFE_MATH > x)
Define sqrt convenience function.
Definition math.hpp:297
std::shared_ptr< leaf_node< T, SAFE_MATH > > shared_leaf
Convenience type alias for shared leaf nodes.
Definition node.hpp:691
shared_hypot< T, SAFE_MATH > hypot_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a hypot node.
Definition math.hpp:2287
shared_leaf< T, SAFE_MATH > operator%(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build modulo node from two leaves.
Definition arithmetic.hpp:5722
bool is_variable_promotable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if the variable is variable is promotable.
Definition arithmetic.hpp:91
std::shared_ptr< multiply_node< T, SAFE_MATH > > shared_multiply
Convenience type alias for shared multiply nodes.
Definition arithmetic.hpp:2831
shared_leaf< T, SAFE_MATH > add(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build add node from two leaves.
Definition arithmetic.hpp:764
shared_fma< T, SAFE_MATH > fma_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a fma node.
Definition arithmetic.hpp:5521
shared_copysign< T, SAFE_MATH > copysign_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a copysign node.
Definition math.hpp:2597
shared_cosine< T, SAFE_MATH > cos_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a cosine node.
Definition trigonometry.hpp:512
bool is_constant_combinable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if nodes are constant combinable.
Definition arithmetic.hpp:25
std::shared_ptr< subtract_node< T, SAFE_MATH > > shared_subtract
Convenience type alias for shared subtract nodes.
Definition arithmetic.hpp:1698
std::string format_to_string(const T value)
Convert a value to a string while avoiding locale.
Definition register.hpp:213
std::unordered_map< void *, size_t > register_usage
Type alias for counting register usage.
Definition register.hpp:261
std::unordered_map< void *, std::string > register_map
Type alias for mapping node pointers to register names.
Definition register.hpp:259
std::string to_string(const char prefix, const NODE *pointer)
Convert a graph::leaf_node pointer to a string.
Definition register.hpp:247
Base nodes of graph computation framework.
void piecewise_1D()
Tests for 1D piecewise nodes.
Definition piecewise_test.cpp:82
void piecewise_2D()
Tests for 2D piecewise nodes.
Definition piecewise_test.cpp:321