<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">Reminds me of the old way of doing *10<div><br></div><div><ul class="MailOutline"><li>T1 = INPUT << 2</li><li>T2 = INPUT << 1</li><li>Result = T1 + T1 + T2</li></ul><div><br></div><div>If you look in the OVMS v2 code (on that little 8bit PIC microcontroller), you’ll see lots of little kludges like this. Some for performance, and some to keep the calculation similar to other tiny MCUs in the car.</div><div><br></div><div>Regards, Mark.</div><div><br><blockquote type="cite"><div>On 8 Jun 2024, at 11:06 PM, Michael Geddes via OvmsDev <ovmsdev@lists.openvehicles.com> wrote:</div><br class="Apple-interchange-newline"><div><div dir="ltr">I'm really not sure if this would make enough difference to be useful - but it's kinda neat.<div>It's basically a template class that turns    y = m * x / d  into  y = (c * x) >> n</div><div>eg:    fast_int_muldiv<int, 10, 3>::op( x )  </div><div><br></div><div>it is an approximation only, and the larger PREC value you give, the more precise it is, and the larger integer it would need.  So a decent precision would probably need a 64 bit integer.</div><div><div><br></div><div>I would need to do experiments on the ESP32 to really get an idea.  One thing it does do is turn a  multiply and divide (like for imperial units) into 2 operations.</div><div><br></div><div>//.</div><div><font face="monospace"><br></font></div><div><font face="monospace">  constexpr unsigned floorlog2(unsigned x)<br>    {<br>    return x == 1 ? 0 : 1+floorlog2(x >> 1);<br>    }<br></font><span style="font-family:monospace">  constexpr un</span><span style="font-family:monospace">signed ceillog2(unsigned x)</span></div><div><font face="monospace">    {<br>    return x == 1 ? 0 : floorlog2(x - 1) + 1;<br>    }<br>  /* Use a multiple and shift (right) to approximate a multiply and divide.<br>   * T - the intermediate type used.<br>   * M - The  multiplier (1 is fine)<br>   * D - The divisor<br>   * PREC - The precision required for the operation.<br>   */<br>  template<typename T, unsigned M, unsigned D, unsigned PREC=100><br>  class fast_int_muldiv<br>    {<br>  public:<br>    static const uint8_t shift = ceillog2(D * PREC);<br>    // Gives the approx multiplier that fits with the chosen shift value .<br>    static const T mult = M* (((T(0x1) << shift)+(D>>1)) / D);<br><br>    // Perform the operation approx (val * M / D)<br>    static T op(T val)<br>      {<br>      // Make sure there is enough space (16bits) for a value.<br>      static_assert( (8 * sizeof(T)) >= (16 + shift + floorlog2(mult)),<br>          "Use a larger integer or smaller precision");<br>      return  ((val * mult) >> shift);<br>      }<br>    };<br></font><br></div></div></div>
_______________________________________________<br>OvmsDev mailing list<br>OvmsDev@lists.openvehicles.com<br>http://lists.openvehicles.com/mailman/listinfo/ovmsdev<br></div></blockquote></div><br></div></body></html>