@@ -965,7 +965,7 @@ FormElement* make_and_compact_math_op(Form* arg0,
965
965
/* !
966
966
* Update a two-argument form that uses two floats.
967
967
* This is for operations like * and + that can be nested
968
- * (* (* a b)) -> (* a b c)
968
+ * (* (* a b) c ) -> (* a b c)
969
969
* Note that we only apply this to the _first_ argument to keep the order of operations the same.
970
970
*/
971
971
void SimpleExpressionElement::update_from_stack_float_2_nestable (const Env& env,
@@ -2603,6 +2603,9 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
2603
2603
ASSERT (x->parent_form == m_src);
2604
2604
}
2605
2605
2606
+ if (auto test0 = m_src->to_string (env) == " (* 0.00024414062 (-> arg0 y))" ) {
2607
+ printf (" " );
2608
+ }
2606
2609
if (m_src->is_single_element ()) {
2607
2610
auto src_as_se = dynamic_cast <SimpleExpressionElement*>(m_src->back ());
2608
2611
if (src_as_se) {
@@ -2624,6 +2627,71 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
2624
2627
}
2625
2628
}
2626
2629
}
2630
+
2631
+ // (* 0.125 b) -> (/ b 8)
2632
+ // adds explicit cast b to float if necessary
2633
+ auto src_as_ge = dynamic_cast <GenericElement*>(m_src->back ());
2634
+ if (src_as_ge) {
2635
+ auto mr = match (Matcher::op_fixed (FixedOperatorKind::MULTIPLICATION,
2636
+ {Matcher::any_single (0 ), Matcher::any (1 )}),
2637
+ m_src);
2638
+ if (mr.matched && std::abs (mr.maps .floats .at (0 )) < 1 && mr.maps .floats .at (0 ) != 0 ) {
2639
+ auto inverse_mult = mr.maps .floats .at (0 );
2640
+ float divisor_num = 1 .0f / inverse_mult;
2641
+
2642
+ // note: float inaccuracies lead to convergent values, so we can do this safely
2643
+ if ((int )divisor_num != divisor_num && 1 .0f / std::roundf (divisor_num) == inverse_mult) {
2644
+ lg::debug (" managed to round divisor - cool !! {} -> {} ({})" , divisor_num,
2645
+ std::roundf (divisor_num), inverse_mult);
2646
+ divisor_num = std::roundf (divisor_num);
2647
+ }
2648
+
2649
+ int divisor_int = (int )divisor_num;
2650
+ bool integer = divisor_int == divisor_num;
2651
+ if (integer) {
2652
+ auto elt = mr.maps .forms .at (1 )->try_as_single_element ();
2653
+ auto b_as_simple = dynamic_cast <SimpleExpressionElement*>(elt);
2654
+ // WARNING : there is an assumption here that derefs DO NOT have implicit casts!
2655
+ auto b_as_deref = dynamic_cast <DerefElement*>(elt);
2656
+ if (b_as_deref ||
2657
+ (b_as_simple && b_as_simple->expr ().kind () == SimpleExpression::Kind::IDENTITY)) {
2658
+ // TODO check if op is float, cast if so
2659
+ Form* divisor = nullptr ;
2660
+ if (divisor_num == 4096 .0f ) {
2661
+ divisor = pool.form <ConstantTokenElement>(" METER_LENGTH" );
2662
+ } else if (integer && divisor_int % 4096 == 0 ) {
2663
+ divisor = pool.form <GenericElement>(
2664
+ GenericOperator::make_function (pool.form <ConstantTokenElement>(" meters" )),
2665
+ pool.form <SimpleAtomElement>(divisor_int / 4096 , true ));
2666
+ } else if (integer && divisor_int % 2048 == 0 ) {
2667
+ divisor = pool.form <GenericElement>(
2668
+ GenericOperator::make_function (pool.form <ConstantTokenElement>(" meters" )),
2669
+ pool.form <ConstantFloatElement>(divisor_num / (float )METER_LENGTH));
2670
+ } else if (integer) {
2671
+ divisor = pool.form <SimpleAtomElement>(divisor_int, true );
2672
+ } else {
2673
+ // this shouldn't run because of the checks before.
2674
+ divisor = pool.form <ConstantFloatElement>(divisor_num);
2675
+ }
2676
+ if (divisor) {
2677
+ if (b_as_deref || (b_as_simple->expr ().is_var () &&
2678
+ env.get_types_before_op (b_as_simple->expr ().var ().idx ())
2679
+ .get (b_as_simple->expr ().var ().reg ())
2680
+ .typespec () == TypeSpec (" float" ))) {
2681
+ *m_src->back_ref () = pool.alloc_element <GenericElement>(
2682
+ GenericOperator::make_fixed (FixedOperatorKind::DIVISION), mr.maps .forms .at (1 ),
2683
+ divisor);
2684
+ } else {
2685
+ *m_src->back_ref () = pool.alloc_element <GenericElement>(
2686
+ GenericOperator::make_fixed (FixedOperatorKind::DIVISION),
2687
+ pool.form <CastElement>(TypeSpec (" float" ), mr.maps .forms .at (1 ), true ), divisor);
2688
+ }
2689
+ m_src->back ()->parent_form = m_src;
2690
+ }
2691
+ }
2692
+ }
2693
+ }
2694
+ }
2627
2695
}
2628
2696
2629
2697
stack.push_value_to_reg (m_dst, m_src, true , m_src_type, m_var_info);
0 commit comments