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 pl1->get_scale(),
pl1->get_offset());
198 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
200 pr1->get_scale(),
pr1->get_offset());
206 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
208 pl2->get_num_columns(),
209 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
210 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
211 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
213 pr2->get_num_columns(),
214 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
215 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
219 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
223 pr2->get_num_columns(),
224 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
225 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
226 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
230 pr2->get_num_columns(),
231 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
232 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
233 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
237 pl2->get_num_columns(),
238 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
239 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
240 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
244 pl2->get_num_columns(),
245 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
246 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
250 if (this->
left->is_match(
this->right)) {
251 return 2.0*this->
left;
262 rm->get_left()->is_constant() &&
263 rm->get_left()->evaluate().is_negative()) {
265 }
else if (
rm.get() &&
266 rm->get_left()->is_constant() &&
267 rm->get_left()->evaluate().is_negative()) {
274 return fma(
lm->get_left(),
lm->get_right(),
this->right);
275 }
else if (
rm.get()) {
276 return fma(
rm->get_left(),
rm->get_right(),
this->left);
291 if ((
rd->get_left()->is_constant() &&
292 rd->get_left()->evaluate().is_negative()) ||
294 (
rdlm->get_left()->is_constant() &&
295 rdlm->get_left()->evaluate().is_negative()))) {
296 return this->
left - (-
rd->get_left())/
rd->get_right();
298 }
else if (
ld.get()) {
300 if ((
ld->get_left()->is_constant() &&
301 ld->get_left()->evaluate().is_negative()) ||
303 (
ldlm->get_left()->is_constant() &&
304 ldlm->get_left()->evaluate().is_negative()))) {
305 return this->
right - (-
ld->get_left())/
ld->get_right();
309 if (
ld.get() &&
rd.get()) {
310 if (
ld->get_right()->is_match(
rd->get_right())) {
311 return (
ld->get_left() +
rd->get_left())/
ld->get_right();
321 if (
ld->get_left()->is_match(
rdlm->get_left())) {
322 return (1.0/
ld->get_right() +
323 rdlm->get_right()/
rd->get_right())*
rdlm->get_left();
324 }
else if (
ld->get_left()->is_match(
rdlm->get_right())) {
325 return (1.0/
ld->get_right() +
326 rdlm->get_left()/
rd->get_right())*
rdlm->get_right();
328 }
else if (
ldlm.get()) {
329 if (
rd->get_left()->is_match(
ldlm->get_left())) {
330 return (
ldlm->get_right()/
ld->get_right() +
331 1.0/
rd->get_right())*
ldlm->get_left();
332 }
else if (
rd->get_left()->is_match(
ldlm->get_right())) {
333 return (
ldlm->get_left()/
ld->get_right() +
334 1.0/
rd->get_right())*
ldlm->get_right();
346 !
ldlm->get_right()->is_match(
rdlm->get_right())) {
347 return (
ldlm->get_right()/
ld->get_right() +
349 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
352 if (
ldlm->get_right()->is_match(
rdlm->get_right())) {
353 return (
ldlm->get_left()/
ld->get_right() +
354 rdlm->get_left()/
rd->get_right())*
ldlm->get_right();
355 }
else if (
ldlm->get_right()->is_match(
rdlm->get_left())) {
356 return (
ldlm->get_left()/
ld->get_right() +
357 rdlm->get_right()/
rd->get_right())*
ldlm->get_right();
358 }
else if (
ldlm->get_left()->is_match(
rdlm->get_right())) {
359 return (
ldlm->get_right()/
ld->get_right() +
360 rdlm->get_left()/
rd->get_right())*
ldlm->get_left();
361 }
else if (
ldlm->get_left()->is_match(
rdlm->get_left())) {
362 return (
ldlm->get_right()/
ld->get_right() +
363 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
374 if (
ldrm->get_right()->is_match(
rdrm->get_right())) {
375 return (
ld->get_left()/
ldrm->get_left() +
376 rd->get_left()/
rdrm->get_left())/
ldrm->get_right();
377 }
else if (
ldrm->get_right()->is_match(
rdrm->get_left())) {
378 return (
ld->get_left()/
ldrm->get_left() +
379 rd->get_left()/
rdrm->get_right())/
ldrm->get_right();
380 }
else if (
ldrm->get_left()->is_match(
rdrm->get_right())) {
381 return (
ld->get_left()/
ldrm->get_right() +
382 rd->get_left()/
rdrm->get_left())/
ldrm->get_left();
383 }
else if (
ldrm->get_left()->is_match(
rdrm->get_left())) {
384 return (
ld->get_left()/
ldrm->get_right() +
385 rd->get_left()/
rdrm->get_right())/
ldrm->get_left();
394 if (
ld->get_right()->is_match(
rdrm->get_left())) {
395 return fma(
ld->get_left(),
399 }
else if (
ld->get_right()->is_match(
rdrm->get_right())) {
400 return fma(
ld->get_left(),
405 }
else if (
ldrm.get()) {
406 if (
rd->get_right()->is_match(
ldrm->get_left())) {
407 return fma(
rd->get_left(),
411 }
else if (
rd->get_right()->is_match(
ldrm->get_right())) {
412 return fma(
rd->get_left(),
427 if (this->
right->is_match(
la->get_left())) {
428 return fma(2.0, this->
right,
la->get_right());
429 }
else if (this->
right->is_match(
la->get_right())) {
435 if (this->
left->is_match(
ra->get_left())) {
436 return fma(2.0, this->
left,
ra->get_right());
437 }
else if (this->
left->is_match(
ra->get_right())) {
438 return fma(2.0, this->
left,
ra->get_left());
448 return la->get_left() + (
la->get_right() + this->
right);
453 return ls->get_left() + (this->
right -
ls->get_right());
464 }
else if (
rfma.get()) {
476 if (
lfma->get_middle()->is_match(
rfma->get_middle())) {
478 lfma->get_left() +
rfma->get_left(),
479 lfma->get_right() +
rfma->get_right());
480 }
else if (
lfma->get_left()->is_match(
rfma->get_middle())) {
482 lfma->get_middle() +
rfma->get_left(),
483 lfma->get_right() +
rfma->get_right());
484 }
else if (
lfma->get_middle()->is_match(
rfma->get_left())) {
486 lfma->get_left() +
rfma->get_middle(),
487 lfma->get_right() +
rfma->get_right());
488 }
else if (
lfma->get_left()->is_match(
rfma->get_left())) {
490 lfma->get_middle() +
rfma->get_middle(),
491 lfma->get_right() +
rfma->get_right());
502 if (
pl.get() &&
pr.get() &&
503 pl->get_right()->is_match(
pr->get_right())) {
506 if (
plm.get() &&
prm.get()) {
507 if (
plm->get_left()->is_match(
prm->get_left())) {
508 return pow(
plm->get_left(),
pl->get_right())*
509 (
pow(
plm->get_right(),
pl->get_right()) +
510 pow(
prm->get_right(),
pl->get_right()));
511 }
else if (
plm->get_left()->is_match(
prm->get_right())) {
512 return pow(
plm->get_left(),
pl->get_right())*
513 (
pow(
plm->get_right(),
pl->get_right()) +
514 pow(
prm->get_left(),
pl->get_right()));
515 }
else if (
plm->get_right()->is_match(
prm->get_left())) {
516 return pow(
plm->get_right(),
pl->get_right())*
517 (
pow(
plm->get_left(),
pl->get_right()) +
518 pow(
prm->get_right(),
pl->get_right()));
519 }
else if (
plm->get_right()->is_match(
prm->get_right())) {
520 return pow(
plm->get_right(),
pl->get_right())*
521 (
pow(
plm->get_left(),
pl->get_right()) +
522 pow(
prm->get_left(),
pl->get_right()));
529 if (
plrc.get() &&
plrc->is(
static_cast<T
> (2.0))) {
534 if ((
pls.get() &&
prc.get() &&
pls->get_arg()->is_match(
prc->get_arg())) ||
535 (
plc.get() &&
prs.get() &&
plc->get_arg()->is_match(
prs->get_arg()))) {
544 if (
pl.get() &&
rd.get()) {
546 if (
rdp.get() &&
pl->get_right()->is_match(
rdp->get_right())) {
549 rdp->get_left()->is_match(
plld->get_right())) {
550 return (
pow(
plld->get_left(),
pl->get_right()) +
552 pow(
rdp->get_left(),
pl->get_right());
555 }
else if (
pr.get() &&
ld.get()) {
557 if (
ldp.get() &&
pr->get_right()->is_match(
ldp->get_right())) {
560 ldp->get_left()->is_match(
prld->get_right())) {
561 return (
pow(
prld->get_left(),
pr->get_right()) +
563 pow(
ldp->get_left(),
pr->get_right());
566 }
else if (
pl.get() &&
pr.get()) {
567 if (
pl->get_right()->is_match(
pr->get_right())) {
570 if (
pld.get() &&
prd.get() &&
571 pld->get_right()->is_match(
prd->get_right())) {
572 return (
pow(
pld->get_left(),
pl->get_right()) +
573 pow(
prd->get_left(),
pl->get_right())) /
574 pow(
pld->get_right(),
pl->get_right());
596 const size_t hash =
reinterpret_cast<size_t> (x.get());
617 if (registers.find(
this) == registers.end()) {
629 jit::add_type<T> (stream);
630 stream <<
" " << registers[
this] <<
" = "
631 << registers[
l.get()] <<
" + "
632 << registers[
r.get()];
646 if (
this == x.get()) {
653 if ((this->
left->is_match(
x_cast->get_left()) &&
654 this->right->is_match(
x_cast->get_right())) ||
673 std::cout <<
"\\left(";
675 this->
left->to_latex();
677 std::cout <<
"\\right)";
681 std::cout <<
"\\left(";
683 this->
right->to_latex();
685 std::cout <<
"\\right)";
696 return this->
left->remove_pseudo() +
697 this->
right->remove_pseudo();
711 if (registers.find(
this) == registers.end()) {
713 registers[
this] =
name;
714 stream <<
" " <<
name
715 <<
" [label = \"+\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
717 auto l = this->
left->to_vizgraph(stream, registers);
718 stream <<
" " <<
name <<
" -- " << registers[
l.get()] <<
";" << std::endl;
719 auto r = this->
right->to_vizgraph(stream, registers);
720 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
739 template<jit::
float_scalar T,
bool SAFE_MATH=false>
742 auto temp = std::make_shared<add_node<T, SAFE_MATH>> (
l,
r)->reduce();
744 for (
size_t i =
temp->get_hash();
754#if defined(__clang__) || defined(__GNUC__)
757 assert(
false &&
"Should never reach.");
773 template<jit::
float_scalar T,
bool SAFE_MATH=false>
792 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
811 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
818 template<jit::
float_scalar T,
bool SAFE_MATH=false>
830 template<jit::
float_scalar T,
bool SAFE_MATH=false>
832 return std::dynamic_pointer_cast<add_node<T, SAFE_MATH>> (x);
846 template<jit::
float_scalar T,
bool SAFE_MATH=false>
895 if (this->
left->is_match(
this->right)) {
896 if (l.get() &&
l->is(0)) {
906 if (l.get() &&
l->is(0)) {
908 }
else if (r.get() &&
r->is(0)) {
910 }
else if (l.get() &&
r.get()) {
912 }
else if (r.get() &&
r->
evaluate().is_negative()) {
919 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
921 pl1->get_scale(),
pl1->get_offset());
922 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
924 pr1->get_scale(),
pr1->get_offset());
930 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
932 pl2->get_num_columns(),
933 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
934 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
935 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
937 pr2->get_num_columns(),
938 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
939 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
943 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
947 pr2->get_num_columns(),
948 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
949 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
950 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
954 pr2->get_num_columns(),
955 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
956 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
957 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
961 pl2->get_num_columns(),
962 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
963 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
964 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
968 pl2->get_num_columns(),
969 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
970 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
977 return (
la->get_left() -
this->right) +
la->get_right();
983 return (this->
left -
ra->get_left()) +
ra->get_right();
992 return (
ls->get_left() -
this->right) -
ls->get_right();
995 return -(
ls->get_right() + this->
right) -
ls->get_left();
1003 return (this->
left -
rs->get_left()) -
rs->get_right();
1005 return (this->
left +
rs->get_right()) -
rs->get_left();
1019 lmra->get_left()) &&
1022 return fma(
lm->get_left(),
1024 lm->get_left()*
lmra->get_left() -
this->right);
1031 lmrs->get_left()) &&
1034 return lm->get_left()*
lmrs->get_left() - this->
right -
1035 lm->get_left()*
lmrs->get_right();
1043 rm->get_left()->is_constant() &&
1044 rm->get_left()->evaluate().is_negative()) {
1052 if (
lmc.get() &&
lmc->is(-1)) {
1053 return lm->get_left()*(
lm->get_right() + this->
right);
1058 if (this->
right->is_match(
lm->get_right())) {
1059 return (
lm->get_left() - 1.0)*this->
right;
1060 }
else if (this->
right->is_match(
lm->get_left())) {
1061 return (
lm->get_right() - 1.0)*this->
right;
1067 if (this->
left->is_match(
rm->get_right())) {
1068 return (1.0 -
rm->get_left())*this->
left;
1069 }
else if (this->
left->is_match(
rm->get_left())) {
1070 return (1.0 -
rm->get_right())*this->
left;
1074 if (
lm.get() &&
rm.get()) {
1075 if (
lm->get_left()->is_match(
rm->get_left())) {
1077 return lm->get_left()*(
lm->get_right() -
rm->get_right());
1078 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
1080 return lm->get_left()*(
lm->get_right() -
rm->get_left());
1081 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
1083 return lm->get_right()*(
lm->get_left() -
rm->get_right());
1084 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
1086 return lm->get_right()*(
lm->get_left() -
rm->get_left());
1091 if (
lm->get_left()->is_constant() &&
1092 rm->get_left()->is_constant() &&
1093 !
lm->get_left()->has_constant_zero()) {
1094 return lm->get_left()*(
lm->get_right() -
1095 (
rm->get_left()/
lm->get_left())*
rm->get_right());
1102 if (
lm->get_right()->is_match(
rmrm->get_right())) {
1103 return (
lm->get_left() -
rm->get_left()*
rmrm->get_left())*
lm->get_right();
1106 if (
lm->get_right()->is_match(
rmrm->get_left())) {
1107 return (
lm->get_left() -
rm->get_left()*
rmrm->get_right())*
lm->get_right();
1110 if (
lm->get_left()->is_match(
rmrm->get_right())) {
1111 return (
lm->get_right() -
rm->get_left()*
rmrm->get_left())*
lm->get_left();
1114 if (
lm->get_left()->is_match(
rmrm->get_left())) {
1115 return (
lm->get_right() -
rm->get_left()*
rmrm->get_right())*
lm->get_left();
1121 if (
rm->get_right()->is_match(
lmrm->get_right())) {
1122 return (
lm->get_left()*
lmrm->get_left() -
rm->get_left())*
rm->get_right();
1125 if (
rm->get_right()->is_match(
lmrm->get_left())) {
1126 return (
lm->get_left()*
lmrm->get_right() -
rm->get_left())*
rm->get_right();
1129 if (
rm->get_left()->is_match(
lmrm->get_right())) {
1130 return (
lm->get_left()*
lmrm->get_left() -
rm->get_right())*
rm->get_left();
1133 if (
rm->get_left()->is_match(
lmrm->get_left())) {
1134 return (
lm->get_left()*
lmrm->get_right() -
rm->get_right())*
rm->get_left();
1147 lmld->get_right()->is_match(
rmld->get_right())) {
1148 return (
lmld->get_left()*
lm->get_right() -
1149 rmld->get_left()*
rm->get_right())/
lmld->get_right();
1150 }
else if (
lmld.get() &&
rmrd.get() &&
1151 lmld->get_right()->is_match(
rmrd->get_right())) {
1152 return (
lmld->get_left()*
lm->get_right() -
1153 rmrd->get_left()*
rm->get_left())/
lmld->get_right();
1154 }
else if (
lmrd.get() &&
rmld.get() &&
1155 lmrd->get_right()->is_match(
rmld->get_right())) {
1156 return (
lmrd->get_left()*
lm->get_left() -
1157 rmld->get_left()*
rm->get_right())/
lmrd->get_right();
1158 }
else if (
lmrd.get() &&
rmrd.get() &&
1159 lmrd->get_right()->is_match(
rmrd->get_right())) {
1160 return (
lmrd->get_left()*
lm->get_left() -
1161 rmrd->get_left()*
rm->get_left())/
lmrd->get_right();
1168 if (
lrm.get() &&
rm.get()) {
1169 if (
lrm->get_left()->is_match(
rm->get_left())) {
1171 return ls->get_left() -
1173 rm->get_right())*
rm->get_left();
1174 }
else if (
lrm->get_left()->is_match(
rm->get_right())) {
1176 return ls->get_left() -
1178 rm->get_left())*
rm->get_right();
1179 }
else if (
lrm->get_right()->is_match(
rm->get_left())) {
1181 return ls->get_left() -
1183 rm->get_right())*
rm->get_left();
1184 }
else if (
lrm->get_right()->is_match(
rm->get_right())) {
1186 return ls->get_left() -
1188 rm->get_left())*
rm->get_right();
1205 if ((
rd->get_left()->is_constant() &&
1206 rd->get_left()->evaluate().is_negative()) ||
1208 (
rdlm->get_left()->is_constant() &&
1209 rdlm->get_left()->evaluate().is_negative()))) {
1212 }
else if (
ld.get()) {
1214 if ((
ld->get_left()->is_constant() &&
1215 ld->get_left()->evaluate().is_negative()) ||
1217 (
ldlm->get_left()->is_constant() &&
1218 ldlm->get_left()->evaluate().is_negative()))) {
1223 if (
ld.get() &&
rd.get()) {
1224 if (
ld->get_right()->is_match(
rd->get_right())) {
1225 return (
ld->get_left() -
rd->get_left())/
ld->get_right();
1235 if (
ld->get_left()->is_match(
rdlm->get_left())) {
1236 return (1.0/
ld->get_right() -
1237 rdlm->get_right()/
rd->get_right())*
rdlm->get_left();
1238 }
else if (
ld->get_left()->is_match(
rdlm->get_right())) {
1239 return (1.0/
ld->get_right() -
1240 rdlm->get_left()/
rd->get_right())*
rdlm->get_right();
1242 }
else if (
ldlm.get()) {
1243 if (
rd->get_left()->is_match(
ldlm->get_left())) {
1244 return (
ldlm->get_right()/
ld->get_right() -
1245 1.0/
rd->get_right())*
ldlm->get_left();
1246 }
else if (
rd->get_left()->is_match(
ldlm->get_right())) {
1247 return (
ldlm->get_left()/
ld->get_right() -
1248 1.0/
rd->get_right())*
ldlm->get_right();
1259 rdlm->get_left()) &&
1260 !
ldlm->get_right()->is_match(
rdlm->get_right())) {
1261 return (
ldlm->get_right()/
ld->get_right() -
1262 rdlm->get_left()/
ldlm->get_left() *
1263 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
1266 if (
ldlm->get_right()->is_match(
rdlm->get_right())) {
1267 return (
ldlm->get_left()/
ld->get_right() -
1268 rdlm->get_left()/
rd->get_right())*
ldlm->get_right();
1269 }
else if (
ldlm->get_right()->is_match(
rdlm->get_left())) {
1270 return (
ldlm->get_left()/
ld->get_right() -
1271 rdlm->get_right()/
rd->get_right())*
ldlm->get_right();
1272 }
else if (
ldlm->get_left()->is_match(
rdlm->get_right())) {
1273 return (
ldlm->get_right()/
ld->get_right() -
1274 rdlm->get_left()/
rd->get_right())*
ldlm->get_left();
1275 }
else if (
ldlm->get_left()->is_match(
rdlm->get_left())) {
1276 return (
ldlm->get_right()/
ld->get_right() -
1277 rdlm->get_right()/
rd->get_right())*
ldlm->get_left();
1288 if (
ldrm->get_right()->is_match(
rdrm->get_right())) {
1289 return (
ld->get_left()/
ldrm->get_left() -
1290 rd->get_left()/
rdrm->get_left())/
ldrm->get_right();
1291 }
else if (
ldrm->get_right()->is_match(
rdrm->get_left())) {
1292 return (
ld->get_left()/
ldrm->get_left() -
1293 rd->get_left()/
rdrm->get_right())/
ldrm->get_right();
1294 }
else if (
ldrm->get_left()->is_match(
rdrm->get_right())) {
1295 return (
ld->get_left()/
ldrm->get_right() -
1296 rd->get_left()/
rdrm->get_left())/
ldrm->get_left();
1297 }
else if (
ldrm->get_left()->is_match(
rdrm->get_left())) {
1298 return (
ld->get_left()/
ldrm->get_right() -
1299 rd->get_left()/
rdrm->get_right())/
ldrm->get_left();
1308 if (
ld->get_right()->is_match(
rdrm->get_left())) {
1309 return (
ld->get_left()*
rdrm->get_right() -
rd->get_left()) /
1311 }
else if (
ld->get_right()->is_match(
rdrm->get_right())) {
1312 return (
ld->get_left()*
rdrm->get_left() -
rd->get_left()) /
1315 }
else if (
ldrm.get()) {
1316 if (
rd->get_right()->is_match(
ldrm->get_left())) {
1317 return (
ld->get_left() -
rd->get_left()*
ldrm->get_right()) /
1319 }
else if (
rd->get_right()->is_match(
ldrm->get_right())) {
1320 return (
ld->get_left() -
rd->get_left()*
ldrm->get_left()) /
1333 return la->get_left() + (
la->get_right() - this->
right);
1335 return ls->get_left() - (this->
right +
ls->get_right());
1345 if (
pl.get() &&
rd.get()) {
1347 if (
rdp.get() &&
pl->get_right()->is_match(
rdp->get_right())) {
1350 rdp->get_left()->is_match(
plld->get_right())) {
1351 return (
pow(
plld->get_left(),
pl->get_right()) -
1353 pow(
rdp->get_left(),
pl->get_right());
1356 }
else if (
pr.get() &&
ld.get()) {
1358 if (
ldp.get() &&
pr->get_right()->is_match(
ldp->get_right())) {
1361 ldp->get_left()->is_match(
prld->get_right())) {
1362 return (
pow(
prld->get_left(),
pr->get_right()) -
1364 pow(
ldp->get_left(),
pr->get_right());
1367 }
else if (
pl.get() &&
pr.get()) {
1368 if (
pl->get_right()->is_match(
pr->get_right())) {
1371 if (
pld.get() &&
prd.get() &&
1372 pld->get_right()->is_match(
prd->get_right())) {
1373 return (
pow(
pld->get_left(),
pl->get_right()) -
1374 pow(
prd->get_left(),
pl->get_right())) /
1375 pow(
pld->get_right(),
pl->get_right());
1384 if (
lfma->get_middle()->is_match(
rfma->get_middle())) {
1387 lfma->get_right() -
rfma->get_right());
1392 if (
lfma.get() && !
this->right->is_all_variables()) {
1405 return ls->get_left() - (
ls->get_right() + this->
right);
1426 const size_t hash =
reinterpret_cast<size_t> (x.get());
1447 if (registers.find(
this) == registers.end()) {
1458 stream <<
" const ";
1459 jit::add_type<T> (stream);
1460 stream <<
" " << registers[
this] <<
" = "
1461 << registers[
l.get()] <<
" - "
1462 << registers[
r.get()];
1476 if (
this == x.get()) {
1482 return this->
left->is_match(
x_cast->get_left()) &&
1498 std::cout <<
"\\left(";
1500 this->
left->to_latex();
1502 std::cout <<
"\\right)";
1506 std::cout <<
"\\left(";
1508 this->
right->to_latex();
1510 std::cout <<
"\\right)";
1521 return this->
left->remove_pseudo() -
1522 this->
right->remove_pseudo();
1536 if (registers.find(
this) == registers.end()) {
1538 registers[
this] =
name;
1539 stream <<
" " <<
name
1540 <<
" [label = \"-\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
1542 auto l = this->
left->to_vizgraph(stream, registers);
1543 stream <<
" " <<
name <<
" -- " << registers[
l.get()] <<
";" << std::endl;
1544 auto r = this->
right->to_vizgraph(stream, registers);
1545 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
1562 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1565 auto temp = std::make_shared<subtract_node<T, SAFE_MATH>> (
l,
r)->reduce();
1567 for (
size_t i =
temp->get_hash();
1577#if defined(__clang__) || defined(__GNUC__)
1580 assert(
false &&
"Should never reach.");
1597 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1617 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
1637 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
1655 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1661 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1673 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1675 return std::dynamic_pointer_cast<subtract_node<T, SAFE_MATH>> (x);
1687 template<jit::
float_scalar T,
bool SAFE_MATH=false>
1708 auto temp2 = reduce_nested_fma_times_constant(
temp->get_left());
1733 if (
add->get_right()->is_match(
temp->get_middle()) &&
1735 auto temp2 = expand_nested_fma_times_add2(
temp->get_left(),
1740 temp->get_right()*
add->get_left());
1744 add->get_left()*
temp->get_left() +
temp->get_right()),
1746 temp->get_right()*
add->get_left());
1771 if (
add->get_right()->is_match(
temp->get_middle()) &&
1777 add->get_left()*
temp->get_left() +
1780 add->get_left()*
temp->get_right() +
1781 temp2->get_right());
1783 auto temp3 = expand_nested_fma_times_add2(
temp->get_left(),
1788 add->get_left()*
temp->get_right() +
1789 temp2->get_right());
1832 if (this->
left.get() ==
this->right.get()) {
1856 if (l.get() &&
l->is(1)) {
1858 }
else if (l.get() &&
l->is(0)) {
1860 }
else if (r.get() &&
r->is(1)) {
1862 }
else if (r.get() &&
r->is(0)) {
1864 }
else if (l.get() &&
r.get()) {
1871 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
1873 pl1->get_scale(),
pl1->get_offset());
1874 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
1876 pr1->get_scale(),
pr1->get_offset());
1882 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
1884 pl2->get_num_columns(),
1885 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
1886 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
1887 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
1889 pr2->get_num_columns(),
1890 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
1891 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
1895 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
1899 pr2->get_num_columns(),
1900 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
1901 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
1902 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
1906 pr2->get_num_columns(),
1907 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
1908 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
1909 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
1913 pl2->get_num_columns(),
1914 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
1915 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
1916 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
1920 pl2->get_num_columns(),
1921 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
1922 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
1938 if ((
cl.get() && !
this->right->is_power_like() &&
1939 !
this->right->is_all_variables() &&
1941 (
sl.get() && !
this->right->is_power_like() &&
1942 !
this->right->is_all_variables()) ||
1948 if (this->
left->is_match(
this->right)) {
1959 return lm->get_left()*(
lm->get_right()*this->
right);
1965 return (this->
right*
lm->get_left())*
lm->get_right();
1967 return (this->
right*
lm->get_right())*
lm->get_left();
1974 return (
lm->get_left()*this->
right)*
lm->get_right();
1987 this->right->get_power_exponent());
1999 if (
temp->is_normal()) {
2000 return temp*
rm->get_right();
2007 return (this->
left*
rm->get_left())*
rm->get_right();
2009 return (this->
left*
rm->get_right())*
rm->get_left();
2015 return (this->
left*
rm->get_left())*
rm->get_right();
2022 auto temp = this->reduce_nested_fma_times_constant(
rm->get_left());
2024 return temp*
rm->get_right();
2031 return rm->get_left()*(this->
left*
rm->get_right());
2043 !this->
right->is_power_like()) {
2044 return (
lm->get_left()*this->
right)*
lm->get_right();
2045 }
else if (
rm.get() &&
2048 !this->
left->is_constant()) {
2049 return (this->
left*
rm->get_left())*
rm->get_right();
2054 if (
lm.get() &&
rm.get()) {
2057 auto temp =
lm->get_left()*
rm->get_left();
2058 if (
temp->is_normal()) {
2059 return temp*(
lm->get_right()*
rm->get_right());
2063 auto temp =
lm->get_left()*
rm->get_right();
2064 if (
temp->is_normal()) {
2065 return temp*(
lm->get_right()*
rm->get_left());
2069 auto temp =
lm->get_right()*
rm->get_left();
2070 if (
temp->is_normal()) {
2071 return temp*(
lm->get_left()*
rm->get_right());
2075 auto temp =
lm->get_right()*
rm->get_right();
2076 if (
temp->is_normal()) {
2077 return temp*(
lm->get_left()*
rm->get_left());
2082 if (
lm->get_left()->is_match(
rm->get_left())) {
2083 return (
lm->get_left()*
rm->get_left()) *
2084 (
lm->get_right()*
rm->get_right());
2085 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
2086 return (
lm->get_right()*
rm->get_left()) *
2087 (
lm->get_left()*
rm->get_right());
2088 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
2089 return (
lm->get_left()*
rm->get_right()) *
2090 (
lm->get_right()*
rm->get_left());
2091 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
2092 return (
lm->get_right()*
rm->get_right()) *
2093 (
lm->get_left()*
rm->get_left());
2104 return (this->
left*
rd->get_left())/
rd->get_right();
2105 }
else if (
ld.get()) {
2106 return (
ld->get_left()*
this->right)/
ld->get_right();
2111 if (
ld.get() &&
rd.get()) {
2112 if (
ld->get_left()->is_match(
rd->get_right())) {
2113 return rd->get_left()/
ld->get_right();
2114 }
else if (
ld->get_right()->is_match(
rd->get_left())) {
2115 return ld->get_left()/
rd->get_right();
2120 return (
ld->get_left()*
rd->get_left()) /
2121 (
ld->get_right()*
rd->get_right());
2126 return pow(this->
left->get_power_base(),
2127 this->left->get_power_exponent() +
2128 this->right->get_power_exponent());
2136 return this->
left/
pow(
rp->get_left(), -
rp->get_right());
2144 return this->
right/
pow(
lp->get_left(), -
lp->get_right());
2148 if (
lp.get() &&
rp.get()) {
2149 if (
lp->get_right()->is_match(
rp->get_right())) {
2150 return pow(
lp->get_left()*
rp->get_left(),
lp->get_right());
2157 if (
lm.get() &&
rp.get()) {
2161 if (
lmrp->get_right()->is_match(
rp->get_right())) {
2162 return lm->get_left()*
pow(
lmrp->get_left()*
rp->get_left(),
2165 }
else if (
lmlp.get()) {
2166 if (
lmlp->get_right()->is_match(
rp->get_right())) {
2167 return lm->get_right()*
pow(
lmlp->get_left()*
rp->get_left(),
2171 }
else if (
rm.get() &&
lp.get()) {
2175 if (
rmrp->get_right()->is_match(
lp->get_right())) {
2176 return rm->get_left()*
pow(
lp->get_left()*
rmrp->get_left(),
2179 }
else if (
rmlp.get()) {
2180 if (
rmlp->get_right()->is_match(
lp->get_right())) {
2181 return rm->get_right()*
pow(
lp->get_left()*
rmlp->get_left(),
2191 if (
lp.get() &&
rp.get()) {
2197 return pow(
lplm->get_left()->get_power_base(),
2198 this->left->get_power_exponent())*
2200 this->left->get_power_exponent() +
2201 this->right->get_power_exponent());
2204 return pow(
lplm->get_right()->get_power_base(),
2205 this->left->get_power_exponent())*
2207 this->left->get_power_exponent() +
2208 this->right->get_power_exponent());
2215 return pow(
rplm->get_left()->get_power_base(),
2216 this->right->get_power_exponent())*
2217 pow(this->
left->get_power_base(),
2218 this->left->get_power_exponent() +
2219 this->right->get_power_exponent());
2222 return pow(
rplm->get_right()->get_power_base(),
2223 this->right->get_power_exponent())*
2224 pow(this->
left->get_power_base(),
2225 this->left->get_power_exponent() +
2226 this->right->get_power_exponent());
2236 return pow(
lpd->get_left(),
this->left->get_power_exponent()) *
2238 this->right->get_power_exponent() -
2239 this->left->get_power_exponent()*
lpd->get_right()->get_power_exponent());
2243 return pow(this->
right->get_power_base(),
2244 this->right->get_power_exponent() +
2245 this->left->get_power_exponent()*
lpd->get_left()->get_power_exponent()) /
2246 pow(
lpd->get_right(),
this->left->get_power_exponent());
2254 return pow(
rpd->get_left(),
this->right->get_power_exponent()) *
2255 pow(this->
left->get_power_base(),
2256 this->left->get_power_exponent() -
2257 this->right->get_power_exponent()*
rpd->get_right()->get_power_exponent());
2262 return pow(this->
right->get_power_base(),
2263 this->right->get_power_exponent() +
2264 this->right->get_power_exponent()*
rpd->get_left()->get_power_exponent()) /
2265 pow(
rpd->get_right(),
this->right->get_power_exponent());
2272 if (
le.get() &&
re.get()) {
2273 return exp(
le->get_arg() +
re->get_arg());
2278 if (
le.get() &&
rm.get()) {
2281 return rm->get_right()*(this->
left*
rm->get_left());
2285 return rm->get_left()*(this->
left*
rm->get_right());
2290 if (
re.get() &&
lm.get()) {
2293 return lm->get_right()*(this->
right*
lm->get_left());
2297 return lm->get_left()*(this->
right*
lm->get_right());
2304 if (
lm.get() &&
rm.get()) {
2309 return (
lm->get_right()*
rm->get_right()) *
2310 (
lm->get_left()*
rm->get_left());
2314 return (
lm->get_right()*
rm->get_left()) *
2315 (
lm->get_left()*
rm->get_right());
2322 return (
lm->get_left()*
rm->get_right()) *
2323 (
lm->get_right()*
rm->get_left());
2327 return (
lm->get_left()*
rm->get_left()) *
2328 (
lm->get_right()*
rm->get_right());
2333 if (
ld.get() &&
re.get()) {
2337 return ld->get_left()*(this->
right/
ld->get_right());
2342 return (
ld->get_left()*
this->right)/
ld->get_right();
2345 if (
rd.get() &&
le.get()) {
2349 return rd->get_left()*(this->
left/
rd->get_right());
2354 return (this->
left*
rd->get_left())/
rd->get_right();
2358 if (
ld.get() &&
rm.get()) {
2364 return (
ld->get_left()*
rm->get_right()) *
2365 (
rm->get_left()/
ld->get_right());
2370 return (
rm->get_right()/
ld->get_right()) *
2371 (
ld->get_left()*
rm->get_left());
2379 return (
ld->get_left()*
rm->get_left()) *
2380 (
rm->get_right()/
ld->get_right());
2385 return (
rm->get_left()/
ld->get_right()) *
2386 (
ld->get_left()*
rm->get_right());
2389 }
else if (
rd.get() &&
lm.get()) {
2395 return (
lm->get_left()/
rd->get_right()) *
2396 (
lm->get_right()*
rd->get_left());
2401 return (
lm->get_left()*
rd->get_left()) *
2402 (
lm->get_right()/
rd->get_right());
2410 return (
lm->get_right()*
rd->get_left()) *
2411 (
lm->get_left()/
rd->get_right());
2416 return (
lm->get_right()/
rd->get_right()) *
2417 (
lm->get_left()*
rd->get_left());
2426 auto fma_reduce = this->reduce_nested_fma_times_constant(this->
right);
2466 const size_t hash =
reinterpret_cast<size_t> (x.get());
2488 if (registers.find(
this) == registers.end()) {
2499 stream <<
" const ";
2500 jit::add_type<T> (stream);
2501 stream <<
" " << registers[
this] <<
" = ";
2503 stream <<
"(" << registers[
l.get()] <<
" == ";
2505 jit::add_type<T> (stream);
2510 stream <<
" || " << registers[
r.get()] <<
" == ";
2512 jit::add_type<T> (stream);
2519 jit::add_type<T> (stream);
2526 stream << registers[
l.get()] <<
"*"
2527 << registers[
r.get()];
2541 if (
this == x.get()) {
2548 if ((this->
left->is_match(
x_cast->get_left()) &&
2549 this->right->is_match(
x_cast->get_right())) ||
2550 (
this->right->is_match(
x_cast->get_left()) &&
2551 this->left->is_match(
x_cast->get_right()))) {
2566 std::cout <<
"\\left(";
2567 this->
left->to_latex();
2568 std::cout <<
"\\right)";
2570 this->
left->to_latex();
2576 std::cout <<
"\\left(";
2577 this->
right->to_latex();
2578 std::cout <<
"\\right)";
2580 this->
right->to_latex();
2591 return this->
left->remove_pseudo() *
2592 this->
right->remove_pseudo();
2606 if (registers.find(
this) == registers.end()) {
2608 registers[
this] =
name;
2609 stream <<
" " <<
name
2610 <<
" [label = \"⨉\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
2612 auto l = this->
left->to_vizgraph(stream, registers);
2613 stream <<
" " <<
name <<
" -- " << registers[
l.get()] <<
";" << std::endl;
2614 auto r = this->
right->to_vizgraph(stream, registers);
2615 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
2631 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2634 auto temp = std::make_shared<multiply_node<T, SAFE_MATH>> (
l,
r)->reduce();
2636 for (
size_t i =
temp->get_hash();
2646#if defined(__clang__) || defined(__GNUC__)
2649 assert(
false &&
"Should never reach.");
2665 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2684 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
2703 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
2710 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2722 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2724 return std::dynamic_pointer_cast<multiply_node<T, SAFE_MATH>> (x);
2736 template<jit::
float_scalar T,
bool SAFE_MATH=false>
2795 if ((l.get() &&
l->is(0)) ||
2796 (
r.get() &&
r->is(1))) {
2798 }
else if (l.get() &&
r.get()) {
2805 if (
pl1.get() && (r.get() ||
pl1->is_arg_match(
this->right))) {
2807 pl1->get_scale(),
pl1->get_offset());
2808 }
else if (
pr1.get() && (l.get() ||
pr1->is_arg_match(
this->left))) {
2810 pr1->get_scale(),
pr1->get_offset());
2816 if (
pl2.get() && (r.get() ||
pl2->is_arg_match(
this->right))) {
2818 pl2->get_num_columns(),
2819 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
2820 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
2821 }
else if (
pr2.get() && (l.get() ||
pr2->is_arg_match(
this->left))) {
2823 pr2->get_num_columns(),
2824 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
2825 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
2829 if (
pr2.get() &&
pr2->is_row_match(
this->left)) {
2833 pr2->get_num_columns(),
2834 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
2835 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
2836 }
else if (
pr2.get() &&
pr2->is_col_match(
this->left)) {
2840 pr2->get_num_columns(),
2841 pr2->get_left(),
pr2->get_x_scale(),
pr2->get_x_offset(),
2842 pr2->get_right(),
pr2->get_y_scale(),
pr2->get_y_offset());
2843 }
else if (
pl2.get() &&
pl2->is_row_match(
this->right)) {
2847 pl2->get_num_columns(),
2848 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
2849 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
2850 }
else if (
pl2.get() &&
pl2->is_col_match(
this->right)) {
2854 pl2->get_num_columns(),
2855 pl2->get_left(),
pl2->get_x_scale(),
pl2->get_x_offset(),
2856 pl2->get_right(),
pl2->get_y_scale(),
pl2->get_y_offset());
2859 if (this->
left->is_match(
this->right)) {
2864 if (this->
right->is_constant()) {
2875 return this->
left*
rald->get_right() /
2879 }
else if (
rard.get()) {
2880 return this->
left*
rard->get_right() /
2894 return this->
left*
rsld->get_right() /
2896 rsld->get_right()*
rs->get_right());
2897 }
else if (
rsrd.get()) {
2898 return this->
left*
rsrd->get_right() /
2899 (
rsrd->get_right()*
rs->get_left() -
2912 if (
lfma->get_middle()->is_match(
this->right) &&
2913 fmarm->get_right()->is_match(
this->right)) {
2914 return lfma->get_left() +
fmarm->get_left();
2915 }
else if (
lfma->get_middle()->is_match(
this->right) &&
2916 fmarm->get_left()->is_match(
this->right)) {
2917 return lfma->get_left() +
fmarm->get_right();
2918 }
else if (
lfma->get_left()->is_match(
this->right) &&
2919 fmarm->get_right()->is_match(
this->right)) {
2920 return lfma->get_middle() +
fmarm->get_left();
2921 }
else if (
lfma->get_left()->is_match(
this->right) &&
2922 fmarm->get_left()->is_match(
this->right)) {
2923 return lfma->get_middle() +
fmarm->get_right();
2932 if (
lm.get() &&
rm.get()) {
2937 return (
lm->get_left()/
rm->get_left()) *
2938 (
lm->get_right()/
rm->get_right());
2943 return (
lm->get_left()/
rm->get_right()) *
2944 (
lm->get_right()/
rm->get_left());
2952 if (
rm->get_left()->is_constant() &&
2953 rm->get_left()->is_normal()) {
2954 return ((1.0/
rm->get_left())*this->
left)/
rm->get_right();
2955 }
else if (
rm->get_right()->is_constant() &&
2956 rm->get_right()->is_normal()) {
2957 return ((1.0/
rm->get_right())*this->
left)/
rm->get_left();
2973 rmlald->get_left())*
rm->get_right());
2974 }
else if (
rmlard.get()) {
2978 rmlard->get_left())*
rm->get_right());
2988 rmrald->get_left())*
rm->get_left());
2989 }
else if (
rmrard.get()) {
2993 rmrard->get_left())*
rm->get_left());
3009 rmlsld->get_right()*
rmls->get_right())*
rm->get_right());
3010 }
else if (
rmlsrd.get()) {
3013 rmlsrd->get_left())*
rm->get_right());
3022 rmrsld->get_right()*
rmrs->get_right())*
rm->get_left());
3023 }
else if (
rmrsrd.get()) {
3026 rmrsrd->get_left())*
rm->get_left());
3031 if (
lm.get() &&
rm.get()) {
3036 if (
lm->get_left()->is_match(
rm->get_left())) {
3037 return lm->get_right()/
rm->get_right();
3038 }
else if (
lm->get_left()->is_match(
rm->get_right())) {
3039 return lm->get_right()/
rm->get_left();
3040 }
else if (
lm->get_right()->is_match(
rm->get_left())) {
3041 return lm->get_left()/
rm->get_right();
3042 }
else if (
lm->get_right()->is_match(
rm->get_right())) {
3043 return lm->get_left()/
rm->get_left();
3050 if (
lm->get_left()->is_match(this->
right)) {
3051 return lm->get_right();
3052 }
else if (
lm->get_right()->is_match(this->
right)) {
3053 return lm->get_left();
3060 return lm->get_right()*(
lm->get_left()/this->
right);
3063 return lm->get_left()*(
lm->get_right()/this->
right);
3072 return ld->get_left()/(
ld->get_right()*this->
right);
3075 return this->
left*
rd->get_right()/
rd->get_left();
3081 return pow(this->
left->get_power_base(),
3082 this->left->get_power_exponent() -
3083 this->right->get_power_exponent());
3091 return this->
left*
pow(
rp->get_left(), -
rp->get_right());
3101 if (
lpm->get_left()->is_match(
this->right->get_power_base())) {
3102 return pow(this->
right->get_power_base(),
3103 this->left->get_power_exponent() -
3104 this->right->get_power_exponent()) *
3106 this->left->get_power_exponent());
3107 }
else if (
lpm->get_right()->is_match(
this->right->get_power_base())) {
3108 return pow(this->
right->get_power_base(),
3109 this->left->get_power_exponent() -
3110 this->right->get_power_exponent()) *
3112 this->left->get_power_exponent());
3118 if (
lp.get() &&
rp.get()) {
3119 if (
lp->get_right()->is_match(
rp->get_right())) {
3120 return pow(
lp->get_left()/
rp->get_left(),
lp->get_right());
3128 if (
lp.get() &&
rm.get()) {
3131 if (
lpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3132 return (
pow(
rm->get_left()->get_power_base(),
3133 this->left->get_power_exponent() -
3134 rm->get_left()->get_power_exponent()) *
3136 this->left->get_power_exponent())) /
3138 }
else if (
lpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3139 return (
pow(
rm->get_left()->get_power_base(),
3140 this->left->get_power_exponent() -
3141 rm->get_left()->get_power_exponent()) *
3143 this->left->get_power_exponent())) /
3145 }
else if (
lpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3146 return (
pow(
rm->get_right()->get_power_base(),
3147 this->left->get_power_exponent() -
3148 rm->get_right()->get_power_exponent()) *
3150 this->left->get_power_exponent())) /
3152 }
else if (
lpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3153 return (
pow(
rm->get_right()->get_power_base(),
3154 this->left->get_power_exponent() -
3155 rm->get_right()->get_power_exponent()) *
3157 this->left->get_power_exponent())) /
3173 return lm->get_left()*
lmrm->get_left() *
3177 return lm->get_left()*
lmrm->get_right() *
3180 }
else if (
lmlm.get()) {
3183 return lm->get_right()*
lmlm->get_left() *
3187 return lm->get_right()*
lmlm->get_right() *
3201 if (
lmlpm->get_left()->is_match(
this->right->get_power_base())) {
3202 return lm->get_right() *
3204 lmlp->get_power_exponent() -
3205 this->right->get_power_exponent()) *
3207 lmlp->get_power_exponent());
3208 }
else if (
lmlpm->get_right()->is_match(
this->right->get_power_base())) {
3209 return lm->get_right() *
3211 lmlp->get_power_exponent() -
3212 this->right->get_power_exponent()) *
3214 lmlp->get_power_exponent());
3217 }
else if (
lmrp.get()) {
3220 if (
lmrpm->get_left()->is_match(
this->right->get_power_base())) {
3221 return lm->get_left() *
3223 lmrp->get_power_exponent() -
3224 this->right->get_power_exponent()) *
3226 lmrp->get_power_exponent());
3227 }
else if (
lmrpm->get_right()->is_match(
this->right->get_power_base())) {
3228 return lm->get_left() *
3230 lmrp->get_power_exponent() -
3231 this->right->get_power_exponent()) *
3233 lmrp->get_power_exponent());
3247 if (
lm.get() &&
rm.get()) {
3253 if (
lmlpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3254 return lm->get_right() *
3255 (
pow(
rm->get_left()->get_power_base(),
3256 lmlp->get_power_exponent() -
3257 rm->get_left()->get_power_exponent())) *
3259 lmlp->get_power_exponent()) /
3261 }
else if (
lmlpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3262 return lm->get_right() *
3263 (
pow(
rm->get_left()->get_power_base(),
3264 lmlp->get_power_exponent() -
3265 rm->get_left()->get_power_exponent())) *
3267 lmlp->get_power_exponent()) /
3269 }
else if (
lmlpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3270 return lm->get_right() *
3271 (
pow(
rm->get_left()->get_power_base(),
3272 lmlp->get_power_exponent() -
3273 rm->get_right()->get_power_exponent())) *
3275 lmlp->get_power_exponent()) /
3277 }
else if (
lmlpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3278 return lm->get_right() *
3279 (
pow(
rm->get_left()->get_power_base(),
3280 lmlp->get_power_exponent() -
3281 rm->get_right()->get_power_exponent())) *
3283 lmlp->get_power_exponent()) /
3287 }
else if (
lmrp.get()) {
3290 if (
lmrpm->get_left()->is_match(
rm->get_left()->get_power_base())) {
3291 return lm->get_left() *
3292 (
pow(
rm->get_left()->get_power_base(),
3293 lmrp->get_power_exponent() -
3294 rm->get_left()->get_power_exponent())) *
3296 lmrp->get_power_exponent()) /
3298 }
else if (
lmrpm->get_right()->is_match(
rm->get_left()->get_power_base())) {
3299 return lm->get_left() *
3300 (
pow(
rm->get_left()->get_power_base(),
3301 lmrp->get_power_exponent() -
3302 rm->get_left()->get_power_exponent())) *
3304 lmrp->get_power_exponent()) /
3306 }
else if (
lmrpm->get_left()->is_match(
rm->get_right()->get_power_base())) {
3307 return lm->get_left() *
3308 (
pow(
rm->get_left()->get_power_base(),
3309 lmrp->get_power_exponent() -
3310 rm->get_right()->get_power_exponent())) *
3312 lmrp->get_power_exponent()) /
3314 }
else if (
lmrpm->get_right()->is_match(
rm->get_right()->get_power_base())) {
3315 return lm->get_left() *
3316 (
pow(
rm->get_left()->get_power_base(),
3317 lmrp->get_power_exponent() -
3318 rm->get_right()->get_power_exponent())) *
3320 lmrp->get_power_exponent()) /
3336 if (
rexp.get() &&
lm.get()) {
3339 return lm->get_left()*(
lm->get_right()/this->
right);
3343 return lm->get_right()*(
lm->get_left()/this->
right);
3350 if (
rexp.get() &&
lm.get()) {
3356 return lmlm->get_left()*
lm->get_right() *
3359 return lmlm->get_right()*
lm->get_right() *
3362 }
else if (
lmrm.get()) {
3364 return lmrm->get_left()*
lm->get_left() *
3367 return lmrm->get_right()*
lm->get_left() *
3375 if (
lexp.get() &&
rm.get()) {
3378 return (this->
left/
rm->get_right())/
rm->get_left();
3382 return (this->
left/
rm->get_left())/
rm->get_right();
3390 if (
lm.get() &&
rm.get()) {
3395 return (
lm->get_left()/
rm->get_left()) *
3396 (
lm->get_right()/
rm->get_right());
3400 return (
lm->get_left()/
rm->get_right()) *
3401 (
lm->get_right()/
rm->get_left());
3408 return (
lm->get_right()/
rm->get_left()) *
3409 (
lm->get_left()/
rm->get_right());
3413 return (
lm->get_right()/
rm->get_right()) *
3414 (
lm->get_left()/
rm->get_left());
3421 if (
rd.get() &&
lexp.get()) {
3424 return (this->
left*
rd->get_right())/
rd->get_left();
3428 return rd->get_right()*(this->
left/
rd->get_left());
3458 const size_t hash =
reinterpret_cast<size_t> (x.get());
3480 if (registers.find(
this) == registers.end()) {
3491 stream <<
" const ";
3492 jit::add_type<T> (stream);
3493 stream <<
" " << registers[
this] <<
" = ";
3495 stream << registers[
l.get()] <<
" == ";
3497 jit::add_type<T> (stream);
3504 jit::add_type<T> (stream);
3511 stream << registers[
l.get()] <<
"/"
3512 << registers[
r.get()];
3525 if (
this == x.get()) {
3531 return this->
left->is_match(
x_cast->get_left()) &&
3542 std::cout <<
"\\frac{";
3543 this->
left->to_latex();
3545 this->
right->to_latex();
3556 return this->
left->remove_pseudo() /
3557 this->
right->remove_pseudo();
3571 if (registers.find(
this) == registers.end()) {
3573 registers[
this] =
name;
3574 stream <<
" " <<
name
3575 <<
" [label = \"\\\\\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
3577 auto l = this->
left->to_vizgraph(stream, registers);
3578 stream <<
" " <<
name <<
" -- " << registers[
l.get()] <<
";" << std::endl;
3579 auto r = this->
right->to_vizgraph(stream, registers);
3580 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
3596 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3599 auto temp = std::make_shared<divide_node<T, SAFE_MATH>> (
l,
r)->reduce();
3601 for (
size_t i =
temp->get_hash();
3611#if defined(__clang__) || defined(__GNUC__)
3614 assert(
false &&
"Should never reach.");
3630 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3649 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
3668 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
3675 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3687 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3689 return std::dynamic_pointer_cast<divide_node<T, SAFE_MATH>> (x);
3703 template<jit::
float_scalar T,
bool SAFE_MATH=false>
3721 temp->get_middle()->is_match(sub->get_left())) {
3724 temp->get_right() -
temp->get_left()*sub->get_right()),
3726 this->right -
temp->get_right()*sub->get_right());
3728 if (
temp->get_middle()->is_match(sub->get_left()) &&
3730 auto temp2 =
temp->reduce_nested_fma(sub);
3734 this->right -
temp->get_right()*sub->get_right());
3804 if ((l.get() &&
l->is(0)) ||
3805 (
m.get() &&
m->is(0))) {
3807 }
else if (r.get() &&
r->is(0)) {
3809 }
else if (l.get() &&
m.get() &&
r.get()) {
3811 }
else if (l.get() &&
m.get()) {
3813 }
else if (l.get() &&
l->is(-1)) {
3815 }
else if (m.get() &&
m->is(-1)) {
3817 }
else if (l.get() &&
l->is(1)) {
3819 }
else if (m.get() &&
m->is(1)) {
3838 if (this->
left->is_match(
this->right)) {
3840 }
else if (this->
middle->is_match(
this->right)) {
3861 return fma(-this->
left,
ms->get_right(),
3869 auto temp = this->reduce_nested_fma(
ms);
3870 if (
temp.get() !=
this) {
3881 if (
rm->get_left()->is_match(
this->left)) {
3883 }
else if (
rm->get_left()->is_match(this->
middle)) {
3885 }
else if (
rm->get_right()->is_match(this->
left)) {
3887 }
else if (
rm->get_right()->is_match(this->
middle)) {
3894 if (
rmlc.get() &&
rmlc->evaluate().is_negative()) {
3896 (-1.0*
rm->get_left())*
rm->get_right();
3906 !this->
left->has_constant_zero()) {
3908 if (
temp->is_normal()) {
3916 !
this->middle->has_constant_zero()) {
3918 if (
temp->is_normal()) {
3926 !
this->left->has_constant_zero()) {
3928 if (
temp->is_normal()) {
3936 !
this->middle->has_constant_zero()) {
3938 if (
temp->is_normal()) {
3950 if (
mm->get_left()->is_match(
rm->get_left())) {
3954 }
else if (
mm->get_left()->is_match(
rm->get_right())) {
3958 }
else if (
mm->get_right()->is_match(
rm->get_left())) {
3962 }
else if (
mm->get_right()->is_match(
rm->get_right())) {
3971 if ((
lm.get() ||
mm.get()) &&
3972 (
this->left->get_complexity() +
this->middle->get_complexity() >
3973 this->right->get_complexity())) {
3974 return fma(
rm->get_left(),
rm->get_right(),
3984 if (
lm.get() &&
rm.get()) {
3987 !
lm->get_left()->has_constant_zero()) {
3988 auto temp =
rm->get_left()/
lm->get_left();
3989 if (
temp->is_normal()){
3990 return lm->get_left()*
fma(
lm->get_right(),
3997 !
lm->get_right()->has_constant_zero()) {
3998 auto temp =
rm->get_left()/
lm->get_right();
3999 if (
temp->is_normal()){
4000 return lm->get_right()*
fma(
lm->get_left(),
4007 !
lm->get_left()->has_constant_zero()) {
4008 auto temp =
rm->get_right()/
lm->get_left();
4009 if (
temp->is_normal()) {
4010 return lm->get_left()*
fma(
lm->get_right(),
4017 !
lm->get_right()->has_constant_zero()) {
4018 auto temp =
rm->get_right()/
lm->get_right();
4019 if (
temp->is_normal()) {
4020 return lm->get_right()*
fma(
lm->get_left(),
4032 return fma(
lm->get_left(),
4033 lm->get_right()*
this->middle,
4036 }
else if (
mm.get()) {
4043 if (
temp->is_normal()) {
4052 if (
temp->is_normal()) {
4060 return fma(
mm->get_left(),
4061 this->left*
mm->get_right(),
4068 if (
mm->get_left()->is_match(
this->right)) {
4072 }
else if (
mm->get_right()->is_match(
this->right)) {
4085 !
this->left->has_constant_zero()) {
4087 if (
temp->is_normal()) {
4094 !this->
middle->has_constant_zero()) {
4096 if (
temp->is_normal()) {
4106 if (
ld.get() &&
ld->get_right()->is_match(
this->middle)) {
4107 return ld->get_left() + this->
right;
4110 if (
md.get() &&
md->get_right()->is_match(
this->left)) {
4111 return md->get_left() + this->
right;
4115 if (
ld.get() &&
rd.get()) {
4117 if (
ld->get_left()->is_match(
rd->get_left())) {
4118 return ld->get_left()*(this->
middle/
ld->get_right() +
4119 1.0/
rd->get_right());
4130 if (
ldrm->get_right()->is_match(
rd->get_right())) {
4131 return fma(
ld->get_left(),
this->middle,
4132 rd->get_left()*
ldrm->get_left()) /
4134 }
else if (
ldrm->get_left()->is_match(
rd->get_right())) {
4135 return fma(
ld->get_left(),
this->middle,
4136 rd->get_left()*
ldrm->get_right()) /
4139 }
else if (
rdrm.get()) {
4140 if (
rdrm->get_right()->is_match(
ld->get_right())) {
4141 return fma(
ld->get_left()*
rdrm->get_left(),
4142 this->middle,
rd->get_left()) /
4144 }
else if (
rdrm->get_left()->is_match(
ld->get_right())) {
4145 return fma(
ld->get_left()*
rdrm->get_right(),
4146 this->middle,
rd->get_left()) /
4150 }
else if (
md.get() &&
rd.get()) {
4159 if (
mdrm->get_right()->is_match(
rd->get_right())) {
4161 rd->get_left()*
mdrm->get_left()) /
4163 }
else if (
mdrm->get_left()->is_match(
rd->get_right())) {
4165 rd->get_left()*
mdrm->get_right()) /
4168 }
else if (
rdrm.get()) {
4169 if (
rdrm->get_right()->is_match(
md->get_right())) {
4173 }
else if (
rdrm->get_left()->is_match(
md->get_right())) {
4188 if (this->
middle->is_match(
rfma->get_middle())) {
4192 }
else if (this->
left->is_match(
rfma->get_middle())) {
4196 }
else if (this->
middle->is_match(
rfma->get_left())) {
4200 }
else if (this->
left->is_match(
rfma->get_left())) {
4211 if (
mm->get_right()->is_match(
rfma->get_middle())) {
4212 return fma(
mm->get_right(),
4217 }
else if (
mm->get_left()->is_match(
rfma->get_middle())) {
4218 return fma(
mm->get_left(),
4223 }
else if (
mm->get_right()->is_match(
rfma->get_left())) {
4224 return fma(
mm->get_right(),
4227 rfma->get_middle()),
4229 }
else if (
mm->get_left()->is_match(
rfma->get_left())) {
4230 return fma(
mm->get_left(),
4233 rfma->get_middle()),
4236 }
else if (
lm.get()) {
4241 if (
lm->get_right()->is_match(
rfma->get_middle())) {
4242 return fma(
lm->get_right(),
4247 }
else if (
lm->get_left()->is_match(
rfma->get_middle())) {
4248 return fma(
lm->get_left(),
4253 }
else if (
lm->get_right()->is_match(
rfma->get_left())) {
4254 return fma(
lm->get_right(),
4257 rfma->get_middle()),
4259 }
else if (
lm->get_left()->is_match(
rfma->get_left())) {
4260 return fma(
lm->get_left(),
4263 rfma->get_middle()),
4275 if (
rfmamm->get_right()->is_match(
this->middle)) {
4281 }
else if (
rfmamm->get_right()->is_match(
this->left)) {
4287 }
else if (
rfmamm->get_left()->is_match(
this->middle)) {
4293 }
else if (
rfmamm->get_left()->is_match(
this->left)) {
4300 }
else if (
rfmalm.get()) {
4305 if (
rfmalm->get_right()->is_match(
this->middle)) {
4311 }
else if (
rfmalm->get_right()->is_match(
this->left)) {
4317 }
else if (
rfmalm->get_left()->is_match(
this->middle)) {
4323 }
else if (
rfmalm->get_left()->is_match(
this->left)) {
4337 if (
mm->get_right()->is_match(
rfmamm->get_right())) {
4338 return fma(
mm->get_right(),
4343 }
else if (
mm->get_left()->is_match(
rfmamm->get_right())) {
4344 return fma(
mm->get_left(),
4349 }
else if (
mm->get_right()->is_match(
rfmamm->get_left())) {
4350 return fma(
mm->get_right(),
4355 }
else if (
mm->get_left()->is_match(
rfmamm->get_left())) {
4356 return fma(
mm->get_left(),
4362 }
else if (
lm.get() &&
rfmamm.get()) {
4367 if (
lm->get_right()->is_match(
rfmamm->get_right())) {
4368 return fma(
lm->get_right(),
4373 }
else if (
lm->get_left()->is_match(
rfmamm->get_right())) {
4374 return fma(
lm->get_left(),
4379 }
else if (
lm->get_right()->is_match(
rfmamm->get_left())) {
4380 return fma(
lm->get_right(),
4385 }
else if (
lm->get_left()->is_match(
rfmamm->get_left())) {
4386 return fma(
lm->get_left(),
4392 }
else if (
mm.get() &&
rfmalm.get()) {
4397 if (
mm->get_right()->is_match(
rfmalm->get_right())) {
4398 return fma(
mm->get_right(),
4403 }
else if (
mm->get_left()->is_match(
rfmalm->get_right())) {
4404 return fma(
mm->get_left(),
4409 }
else if (
mm->get_right()->is_match(
rfmalm->get_left())) {
4410 return fma(
mm->get_right(),
4415 }
else if (
mm->get_left()->is_match(
rfmalm->get_left())) {
4416 return fma(
mm->get_left(),
4422 }
else if (
lm.get() &&
rfmalm.get()) {
4427 if (
lm->get_right()->is_match(
rfmalm->get_right())) {
4428 return fma(
lm->get_right(),
4433 }
else if (
lm->get_left()->is_match(
rfmalm->get_right())) {
4434 return fma(
lm->get_left(),
4439 }
else if (
lm->get_right()->is_match(
rfmalm->get_left())) {
4440 return fma(
lm->get_right(),
4445 }
else if (
lm->get_left()->is_match(
rfmalm->get_left())) {
4446 return fma(
lm->get_left(),
4457 return fma(
rfma->get_middle(),
4473 return fma(
rfma->get_middle(),
4492 rfma->get_middle()),
4508 rfma->get_middle()),
4522 if (this->
left->is_match(
rfma->get_left()) &&
4523 this->middle->is_match(
rfma->get_middle())) {
4525 }
else if (this->
left->is_match(
rfma->get_middle()) &&
4526 this->middle->is_match(
rfma->get_left())) {
4537 if (
fmald.get() &&
ld->get_right()->is_match(
fmald->get_right())) {
4538 return (
ld->get_left()*
this->middle +
4539 fmald->get_left()*
rfma->get_middle())/
ld->get_right() +
4541 }
else if (
fmamd.get() &&
ld->get_right()->is_match(
fmamd->get_right())) {
4542 return (
ld->get_left()*
this->middle +
4543 fmamd->get_left()*
rfma->get_left())/
ld->get_right() +
4546 }
else if (
md.get()) {
4547 if (
fmald.get() &&
md->get_right()->is_match(
fmald->get_right())) {
4548 return (
md->get_left()*
this->left +
4549 fmald->get_left()*
rfma->get_middle())/
md->get_right() +
4551 }
else if (
fmamd.get() &&
md->get_right()->is_match(
fmamd->get_right())) {
4552 return (
md->get_left()*
this->left +
4553 fmamd->get_left()*
rfma->get_left())/
md->get_right() +
4562 if (this->
left->is_all_variables()) {
4564 if (
rdl->get_complexity() <
this->left->get_complexity() +
4565 this->right->get_complexity()) {
4568 }
else if (this->
middle->is_all_variables()) {
4571 if ((
rdm->get_complexity() <
this->middle->get_complexity() +
4572 this->right->get_complexity()) &&
4573 !(
rdmc.get() &&
rdmc->evaluate().is_negative())) {
4593 return this->
left/
pow(
mp->get_left(), -
mp->get_right()) +
4612 if (
lp.get() &&
mp.get()) {
4613 if (
lp->get_right()->is_match(
mp->get_right())) {
4614 return pow(
lp->get_left()*
mp->get_left(),
4621 if (
rm.get() &&
mp.get()) {
4642 if (
rfma.get() &&
mp.get()) {
4646 rfma->get_left())) {
4652 rfma->get_middle()),
4655 rfma->get_left())) {
4661 rfma->get_middle()),
4676 rfma->get_right()));
4684 if (
md.get() &&
rd.get()) {
4685 if (
md->get_left()->is_match(
rd->get_left())) {
4686 return md->get_left()*(this->
left/
md->get_right() +
4687 1.0/
rd->get_right());
4688 }
else if (
md->get_right()->is_match(
rd->get_right())) {
4689 return (this->
left*
md->get_left() +
4690 rd->get_left())/
md->get_right();
4695 if (
ld.get() &&
rd.get()) {
4696 if (
ld->get_left()->is_match(
rd->get_left())) {
4697 return ld->get_left()*(this->
middle/
ld->get_right() +
4698 1.0/
rd->get_right());
4699 }
else if (
ld->get_right()->is_match(
rd->get_right())) {
4700 return (this->
middle*
ld->get_left() +
4701 rd->get_left())/
ld->get_right();
4707 if (
rm.get() &&
ld.get()) {
4709 if (
rmld.get() &&
ld->get_right()->is_match(
rmld->get_right())) {
4710 return fma(
ld->get_left(),
this->middle,
rmld->get_left()*
rm->get_right())/
ld->get_right();
4713 if (
rmrd.get() &&
ld->get_right()->is_match(
rmrd->get_right())) {
4714 return fma(
ld->get_left(),
this->middle,
rmrd->get_left()*
rm->get_left())/
ld->get_right();
4719 if (
rm.get() &&
md.get()) {
4721 if (
rmld.get() &&
md->get_right()->is_match(
rmld->get_right())) {
4722 return fma(this->
left,
md->get_left(),
rmld->get_left()*
rm->get_right())/
md->get_right();
4725 if (
rmrd.get() &&
md->get_right()->is_match(
rmrd->get_right())) {
4726 return fma(this->
left,
md->get_left(),
rmrd->get_left()*
rm->get_left())/
md->get_right();
4732 if (
rd.get() &&
lm.get()) {
4734 if (
lmld.get() &&
rd->get_right()->is_match(
lmld->get_right())) {
4735 return fma(
lmld->get_left()*
lm->get_right(),
this->middle,
rd->get_left())/
rd->get_right();
4738 if (
lmrd.get() &&
rd->get_right()->is_match(
lmrd->get_right())) {
4739 return fma(
lmld->get_left()*
lm->get_left(),
this->middle,
rd->get_left())/
rd->get_right();
4744 if (
rd.get() &&
mm.get()) {
4746 if (
mmld.get() &&
rd->get_right()->is_match(
mmld->get_right())) {
4747 return fma(this->
left,
mmld->get_left()*
mm->get_right(),
rd->get_left())/
rd->get_right();
4750 if (
mmrd.get() &&
rd->get_right()->is_match(
mmrd->get_right())) {
4751 return fma(this->
left,
mmrd->get_left()*
mm->get_left(),
rd->get_left())/
rd->get_right();
4763 if (
md.get() &&
rm.get()) {
4767 if (
rmlmld.get() &&
rmlmld->get_right()->is_match(
md->get_right())) {
4769 rmlmld->get_left()*
rmlm->get_right()*
rm->get_right())/
md->get_right();
4772 if (
rmlmrd.get() &&
rmlmrd->get_right()->is_match(
md->get_right())) {
4774 rmlmrd->get_left()*
rmlm->get_left()*
rm->get_right())/
md->get_right();
4780 if (
rmrmld.get() &&
rmrmld->get_right()->is_match(
md->get_right())) {
4782 rmrmld->get_left()*
rmrm->get_right()*
rm->get_left())/
md->get_right();
4785 if (
rmrmrd.get() &&
rmrmrd->get_right()->is_match(
md->get_right())) {
4787 rmrmrd->get_left()*
rmrm->get_left()*
rm->get_left())/
md->get_right();
4790 }
else if (
ld.get() &&
rm.get()) {
4794 if (
rmlmld.get() &&
rmlmld->get_right()->is_match(
ld->get_right())) {
4795 return fma(
ld->get_left(),
this->middle,
4796 rmlmld->get_left()*
rmlm->get_right()*
rm->get_right())/
ld->get_right();
4799 if (
rmlmrd.get() &&
rmlmrd->get_right()->is_match(
ld->get_right())) {
4800 return fma(
ld->get_left(),
this->middle,
4801 rmlmrd->get_left()*
rmlm->get_right()*
rm->get_right())/
ld->get_right();
4807 if (
rmrmld.get() &&
rmrmld->get_right()->is_match(
ld->get_right())) {
4808 return fma(
ld->get_left(),
this->middle,
4809 rmrmld->get_left()*
rmrm->get_right()*
rm->get_left())/
ld->get_right();
4812 if (
rmrmrd.get() &&
rmrmrd->get_right()->is_match(
ld->get_right())) {
4813 return fma(
ld->get_left(),
this->middle,
4814 rmrmrd->get_left()*
rmrm->get_left()*
rm->get_left())/
ld->get_right();
4822 if (
le.get() && me.get()) {
4823 return exp(
le->get_arg() + me->get_arg()) + this->
right;
4828 if (
mm.get() &&
le.get()) {
4844 if (
lm.get() && me.get()) {
4853 return fma(
lm->get_right()*
this->middle,
4863 if (
lm.get() &&
mm.get()) {
4868 return fma(
lm->get_left()*
mm->get_left(),
4869 lm->get_right()*
mm->get_right(),
4874 return fma(
lm->get_left()*
mm->get_right(),
4875 lm->get_right()*
mm->get_left(),
4883 return fma(
lm->get_right()*
mm->get_left(),
4884 lm->get_left()*
mm->get_right(),
4889 return fma(
lm->get_right()*
mm->get_right(),
4890 lm->get_left()*
mm->get_left(),
4900 if (
lm.get() &&
md.get()) {
4905 return fma(
lm->get_left()*
md->get_left(),
4906 lm->get_right()/
md->get_right(),
4911 return fma(
lm->get_left()/
md->get_right(),
4912 lm->get_right()*
md->get_left(),
4920 return fma(
lm->get_right()*
md->get_left(),
4921 lm->get_left()/
md->get_right(),
4926 return fma(
lm->get_right()/
md->get_right(),
4927 lm->get_left()*
md->get_left(),
4937 if (
ld.get() &&
mm.get()) {
4942 return fma(
ld->get_left()*
mm->get_left(),
4943 mm->get_right()/
ld->get_right(),
4948 return fma(
ld->get_left()*
mm->get_right(),
4949 mm->get_left()/
ld->get_right(),
4957 return fma(
mm->get_left()/
ld->get_right(),
4958 ld->get_left()*
mm->get_right(),
4963 return fma(
mm->get_right()/
ld->get_right(),
4964 ld->get_left()*
mm->get_left(),
4974 if (
ld.get() &&
md.get()) {
4979 return ((
ld->get_left()*
md->get_left()) /
4980 (
ld->get_right()*
md->get_right())) +
4985 return fma(
ld->get_left()/
md->get_right(),
4986 md->get_left()/
ld->get_right(),
4994 return fma(
md->get_left()/
ld->get_right(),
4995 ld->get_left()/
md->get_right(),
5000 return ((
ld->get_left()*
md->get_left()) /
5001 (
ld->get_right()*
md->get_right())) +
5024 const size_t hash =
reinterpret_cast<size_t> (x.get());
5028 this->right->df(x));
5051 if (registers.find(
this) == registers.end()) {
5066 stream <<
" const ";
5067 jit::add_type<T> (stream);
5068 stream <<
" " << registers[
this] <<
" = ";
5070 stream <<
"(" << registers[
l.get()] <<
" == ";
5072 jit::add_type<T> (stream);
5077 stream <<
" || " << registers[
m.get()] <<
" == ";
5079 jit::add_type<T> (stream);
5084 stream <<
") ? " << registers[
r.get()] <<
" : ";
5087 stream << registers[
l.get()] <<
"*"
5088 << registers[
m.get()] <<
" + "
5089 << registers[
r.get()];
5092 << registers[
l.get()] <<
", "
5093 << registers[
m.get()] <<
", "
5094 << registers[
r.get()] <<
")";
5109 if (
this == x.get()) {
5115 return this->
left->is_match(
x_cast->get_left()) &&
5127 std::cout <<
"\\left(";
5130 std::cout <<
"\\left(";
5131 this->
left->to_latex();
5132 std::cout <<
"\\right)";
5134 this->
left->to_latex();
5139 std::cout <<
"\\left(";
5140 this->
middle->to_latex();
5141 std::cout <<
"\\right)";
5143 this->
middle->to_latex();
5146 this->
right->to_latex();
5147 std::cout <<
"\\right)";
5157 return fma(this->
left->remove_pseudo(),
5158 this->middle->remove_pseudo(),
5159 this->right->remove_pseudo());
5173 if (registers.find(
this) == registers.end()) {
5175 registers[
this] =
name;
5176 stream <<
" " <<
name
5177 <<
" [label = \"fma\", shape = oval, style = filled, fillcolor = blue, fontcolor = white];" << std::endl;
5179 auto l = this->
left->to_vizgraph(stream, registers);
5180 stream <<
" " <<
name <<
" -- " << registers[
l.get()] <<
";" << std::endl;
5181 auto m = this->
middle->to_vizgraph(stream, registers);
5182 stream <<
" " <<
name <<
" -- " << registers[
m.get()] <<
";" << std::endl;
5183 auto r = this->
right->to_vizgraph(stream, registers);
5184 stream <<
" " <<
name <<
" -- " << registers[
r.get()] <<
";" << std::endl;
5201 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5205 auto temp = std::make_shared<fma_node<T, SAFE_MATH>> (
l,
m,
r)->reduce();
5207 for (
size_t i =
temp->get_hash();
5217#if defined(__clang__) || defined(__GNUC__)
5220 assert(
false &&
"Should never reach.");
5238 template<jit::
float_scalar T, jit::
float_scalar L,
bool SAFE_MATH=false>
5259 template<jit::
float_scalar T, jit::
float_scalar M,
bool SAFE_MATH=false>
5280 template<jit::
float_scalar T, jit::
float_scalar R,
bool SAFE_MATH=false>
5302 template<jit::
float_scalar T, jit::
float_scalar L, jit::
float_scalar M,
bool SAFE_MATH=false>
5325 template<jit::
float_scalar T, jit::
float_scalar M, jit::
float_scalar R,
bool SAFE_MATH=false>
5348 template<jit::
float_scalar T, jit::
float_scalar L, jit::
float_scalar R,
bool SAFE_MATH=false>
5357 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5369 template<jit::
float_scalar T,
bool SAFE_MATH=false>
5371 return std::dynamic_pointer_cast<fma_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:375
void multiply_row(const buffer< T > &x)
Multiply row operation.
Definition backend.hpp:447
void add_col(const buffer< T > &x)
Add col operation.
Definition backend.hpp:339
void divide_col(const buffer< T > &x)
Divide col operation.
Definition backend.hpp:555
void add_row(const buffer< T > &x)
Add row operation.
Definition backend.hpp:303
void subtract_col(const buffer< T > &x)
Subtract col operation.
Definition backend.hpp:411
void multiply_col(const buffer< T > &x)
Multiply col operation.
Definition backend.hpp:483
void divide_row(const buffer< T > &x)
Divide row operation.
Definition backend.hpp:519
bool is_zero() const
Is every element zero.
Definition backend.hpp:141
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:709
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:591
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Querey if the nodes match.
Definition arithmetic.hpp:645
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:694
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, jit::register_map &indices, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:613
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:667
Class representing a branch node.
Definition node.hpp:1173
shared_leaf< T, SAFE_MATH > right
Right branch of the tree.
Definition node.hpp:1178
shared_leaf< T, SAFE_MATH > left
Left branch of the tree.
Definition node.hpp:1176
A division node.
Definition arithmetic.hpp:2737
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an division node.
Definition arithmetic.hpp:2790
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:3554
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, jit::register_map &indices, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:3476
divide_node(shared_leaf< T, SAFE_MATH > n, shared_leaf< T, SAFE_MATH > d)
Construct an addition node.
Definition arithmetic.hpp:2759
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Querey if the nodes match.
Definition arithmetic.hpp:3524
virtual backend::buffer< T > evaluate()
Evaluate the results of division.
Definition arithmetic.hpp:2771
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:3569
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:3541
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:3453
A fused multiply add node.
Definition arithmetic.hpp:3704
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:5155
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:5019
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, jit::register_map &indices, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:5047
virtual backend::buffer< T > evaluate()
Evaluate the results of fused multiply add.
Definition arithmetic.hpp:3780
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:5171
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:3766
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:5126
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce a fused multiply add node.
Definition arithmetic.hpp:3799
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Querey if the nodes match.
Definition arithmetic.hpp:5108
Class representing a node leaf.
Definition node.hpp:364
virtual void endline(std::ostringstream &stream, const jit::register_usage &usage) const final
End a line in the kernel source.
Definition node.hpp:637
virtual backend::buffer< T > evaluate()=0
Evaluate method.
std::map< size_t, std::shared_ptr< leaf_node< T, SAFE_MATH > > > df_cache
Cache derivative terms.
Definition node.hpp:371
virtual bool has_pseudo() const
Query if the node contains pseudo variables.
Definition node.hpp:618
const size_t hash
Hash for node.
Definition node.hpp:367
A multiplcation node.
Definition arithmetic.hpp:1688
virtual backend::buffer< T > evaluate()
Evaluate the results of multiplcation.
Definition arithmetic.hpp:1827
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:2461
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:2589
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an multiplcation node.
Definition arithmetic.hpp:1852
multiply_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Consruct a multiplcation node.
Definition arithmetic.hpp:1816
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Querey if the nodes match.
Definition arithmetic.hpp:2540
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, jit::register_map &indices, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:2484
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:2604
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:2562
A subtraction node.
Definition arithmetic.hpp:847
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map ®isters, jit::register_map &indices, const jit::register_usage &usage)
Compile the node.
Definition arithmetic.hpp:1443
subtract_node(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Consruct a subtraction node.
Definition arithmetic.hpp:869
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition arithmetic.hpp:1421
virtual shared_leaf< T, SAFE_MATH > remove_pseudo()
Remove pseudo variable nodes.
Definition arithmetic.hpp:1519
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Querey if the nodes match.
Definition arithmetic.hpp:1475
virtual shared_leaf< T, SAFE_MATH > reduce()
Reduce an subtraction node.
Definition arithmetic.hpp:892
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map ®isters)
Convert the node to vizgraph.
Definition arithmetic.hpp:1534
virtual backend::buffer< T > evaluate()
Evaluate the results of subtraction.
Definition arithmetic.hpp:881
virtual void to_latex() const
Convert the node to latex.
Definition arithmetic.hpp:1492
Class representing a triple branch node.
Definition node.hpp:1297
shared_leaf< T, SAFE_MATH > middle
Middle branch of the tree.
Definition node.hpp:1300
Complex scalar concept.
Definition register.hpp:24
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:918
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:1323
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:2666
bool is_variable_combineable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if the variable is combinable.
Definition arithmetic.hpp:75
std::shared_ptr< add_node< T, SAFE_MATH > > shared_add
Convenience type alias for shared add nodes.
Definition arithmetic.hpp:819
shared_pow< T, SAFE_MATH > pow_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a power node.
Definition math.hpp:1416
shared_subtract< T, SAFE_MATH > subtract_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a subtract node.
Definition arithmetic.hpp:1674
constexpr shared_leaf< T, SAFE_MATH > zero()
Forward declare for zero.
Definition node.hpp:994
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:3631
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:2632
shared_add< T, SAFE_MATH > add_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a add node.
Definition arithmetic.hpp:831
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:774
std::shared_ptr< divide_node< T, SAFE_MATH > > shared_divide
Convenience type alias for shared divide nodes.
Definition arithmetic.hpp:3676
shared_leaf< T, SAFE_MATH > pow(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build power node.
Definition math.hpp:1352
shared_sine< T, SAFE_MATH > sin_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a sine node.
Definition trigonometry.hpp:262
shared_divide< T, SAFE_MATH > divide_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a divide node.
Definition arithmetic.hpp:3688
shared_piecewise_1D< T, SAFE_MATH > piecewise_1D_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a piecewise 1D node.
Definition piecewise.hpp:601
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:1598
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:3597
shared_multiply< T, SAFE_MATH > multiply_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a multiply node.
Definition arithmetic.hpp:2723
shared_leaf< T, SAFE_MATH > exp(shared_leaf< T, SAFE_MATH > x)
Define exp convience function.
Definition math.hpp:544
shared_exp< T, SAFE_MATH > exp_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a exp node.
Definition math.hpp:578
bool is_constant_combineable(shared_leaf< T, SAFE_MATH > a, shared_leaf< T, SAFE_MATH > b)
Check if nodes are constant combineable.
Definition arithmetic.hpp:25
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:5202
shared_constant< T, SAFE_MATH > constant_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a constant node.
Definition node.hpp:1042
constexpr T i
Convinece type for imaginary constant.
Definition node.hpp:1026
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:1563
std::shared_ptr< fma_node< T, SAFE_MATH > > shared_fma
Convenience type alias for shared add nodes.
Definition arithmetic.hpp:5358
std::shared_ptr< leaf_node< T, SAFE_MATH > > shared_leaf
Convenience type alias for shared leaf nodes.
Definition node.hpp:673
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:2711
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:740
shared_fma< T, SAFE_MATH > fma_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a fma node.
Definition arithmetic.hpp:5370
shared_cosine< T, SAFE_MATH > cos_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a cosine node.
Definition trigonometry.hpp:514
std::shared_ptr< subtract_node< T, SAFE_MATH > > shared_subtract
Convenience type alias for shared subtract nodes.
Definition arithmetic.hpp:1662
std::string format_to_string(const T value)
Convert a value to a string while avoiding locale.
Definition register.hpp:211
std::map< void *, size_t > register_usage
Type alias for counting register usage.
Definition register.hpp:258
std::map< void *, std::string > register_map
Type alias for mapping node pointers to register names.
Definition register.hpp:256
std::string to_string(const char prefix, const NODE *pointer)
Convert a graph::leaf_node pointer to a string.
Definition register.hpp:245
Base nodes of graph computation framework.
void piecewise_1D()
Tests for 1D piecewise nodes.
Definition piecewise_test.cpp:80
void piecewise_2D()
Tests for 2D piecewise nodes.
Definition piecewise_test.cpp:283