Features of the mql5 language, subtleties and tricks - page 313

 

Calculator for approximate integer division by a constant.

uint Div1000( const uint Value ) { return((Value >> 10) + (Value >> 16) + (Value >> 17)); }
constdivmul
  • www.golovchenko.org
Background Source Code and Builds
 

I just looked-up this and it is already called  "shift and add".

For certain multipliers like multiply by 10, the result is exact.

 (x << 3) + (x << 1) # Here 10*x is computed as x*2^3 + x*2

https://www.wikiwand.com/en/articles/Multiplication_algorithm#Usage_in_computers

In base two, long multiplication is sometimes called "shift and add", because the algorithm simplifies and just consists of shifting left (multiplying by powers of two) and adding.

Multiplication algorithm - Wikiwand
  • www.wikiwand.com
A multiplication algorithm is an algorithm to multiply two numbers. Depending on the size of the numbers, different algorithms are more efficient than others. N...
 
amrali #:

I just looked-up this and it is already called  "shift and add".

For certain multipliers like multiply by 10, the result is exact.

https://www.wikiwand.com/en/articles/Multiplication_algorithm#Usage_in_computers

In base two, long multiplication is sometimes called "shift and add", because the algorithm simplifies and just consists of shifting left (multiplying by powers of two) and adding.


Aren't CPUs underlying architectures anyways implementing such techniques in hardware already?

Maybe this would require some benchmarking.
 
This method gives approximate results for multiplication with a compile-time constant (on basic hardware). Nowadays compilers use more advanced optimizations for exact multiplications, see https://www.wikiwand.com/en/articles/Division_algorithm#Division_by_a_constant
Also here:

https://www.mql5.com/en/forum/393227/page280#comment_55325243

There is also a library optimizing integer division with compile-time constants, see https://libdivide.com/

it basically converts the divisor to approximate multiplier: 

fast_d = libdivide_s32_gen(divisor);

Division algorithm - Wikiwand
  • www.wikiwand.com
A division algorithm is an algorithm which, given two integers N and D, computes their quotient and/or remainder, the result of Euclidean division. Some are app...
 
Тест AVX512
Тест AVX512
  • 2025.09.19
  • www.mql5.com
Требуются добровольцы с avx512 Нужно скомпилировать и запустить скрипт в 4 режимах Поделиться результатами Дефолтные значения оптимальные можно SIZ...
 
About multiply shift:


About at minute 34.

Compilers actually apply this method if they can.
 

A minimal implementation of the fastdiv algorithm (described here https://www.wikiwand.com/en/articles/Division_algorithm?ai=topQs#Division_by_a_constant)

This demonstrates how a compiler can optimize divsion by a compile-time constant (to multiplication and shift).

Compiler Version: 5283, X64 Regular
13th Gen Intel Core i3-1305U, AVX2 + FMA3
 2.48 ns/call, checksum = 516274437   // div_test
 0.53 ns/call, checksum = 516274437   // fastdiv_test
NB: this fastdiv optimization cannot be applied for divisors that are unkown at compile-time (e.g., division by a runtime variable).
Division algorithm - Wikiwand
  • www.wikiwand.com
A division algorithm is an algorithm which, given two integers N and D, computes their quotient and/or remainder, the result of Euclidean division. Some are app...
Files:
fastdiv.mq5  8 kb
 

Is there any way to choose which loop to use depending on the value of the bool variable? Inside the loops everything is the same, so I want to select the loop itself 1 time.

There is a bool variable Up. If its value is true, we need the LOOP_Up loop, if false LOOP_Down.

#define  LOOP_Up   for(i = 21;    i >= start; i--)
#define  LOOP_Down for(i = start; i <  22;    i++)
if(Up)  LOOP_Up   else LOOP_Down {

This option causes an error:

illegal 'else' without matching 'if'

It doesn't work this way either:

if(Up) LOOP_Up if(!Up) LOOP_Down {
 
Andrei Iakovlev #:
  int start = 0;
  int end = 21;
  bool up = false;
  
  for (int i = up ? end : start; up ? i >= start : i < end; up ? i-- : i++) {
    Print(i);
  }