Alternative implementations of standard functions/approaches - page 10

 
pavlick_:
)). This may have a place only in personal crafts with exact knowledge of the value range, but not in std library. The built-in functions are not written by fools, don't think you're the smartest. Here is a friend who also writes undefined and unspecified behavior and then is surprised that it does not work that way https://www.linux.org.ru/forum/development/14422428#comments. All these savings of a few nanoseconds won't even be visible in real algorithm (not in naked loop).

Only now I've caught up with what you were saying.
I take it back that you're not in the loop. I apologise.
Yes, you can use that variant with a proviso that number double lies in the range from -9007199254740992 to 9007199254740992 (2 to the power of 53 (number of bits in the mantissa))

 
Renat Fatkhullin:
Think about what you'll get outside the integer range.

how about this?

double Ceil (double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}

result:

2018.08.26 10:49:23.552 TestRound (Crypto.ALT,M10)      Время цикла без округления = 1.317 наносекунд, сумма = 115583114403605978808320.00000000
2018.08.26 10:49:23.556 TestRound (Crypto.ALT,M10)      Время выполнения функции ceil =  2.129 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.557 TestRound (Crypto.ALT,M10)      Время выполнения функции Ceil =  0.100 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.560 TestRound (Crypto.ALT,M10)      Время выполнения функции floor = 1.299 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.561 TestRound (Crypto.ALT,M10)      Время выполнения функции Floor = 0.120 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.564 TestRound (Crypto.ALT,M10)      Время выполнения функции round = 1.787 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Время выполнения функции Round = 0.106 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать

the test seems to show complete identity.

However, the speed of the alternative solution in this case, where there is a range check, is higher by about 2 times (rather than 3-8), but this is if the number double is in the rangefrom -9007199254740992 to 9007199254740992. But it is much higher when it is outside this range.

Files:
TestRound.mq5  9 kb
 
Nikolai Semko:


the test seems to show complete identity.

However, this variant does not take into account overflow of input variableof double type, when it takes values nan, snan.

If it has to be taken into account, you can add one more check, but still this variant will work faster than the original function

double Ceil (double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}
 
Nikolai Semko:

Write up an EA for a tester/optimiser. That is where speed in practice is important.

 
fxsaber:

Write up an EA for a tester/optimiser. That's where speed is important in practice.

As many people know, I also do smooth graphics. It is for smoothing graphics and working with each pixel that rounding functions are actively used.

Earlier I could not even imagine that rounding function is slower than the extraction of the square root of double.
It's for this reason that I've taken to choking out those nanoseconds. Because those nanoseconds on the smoothed graph can turn into milliseconds on every frame, and a frame can change every 33 milliseconds.

 
Nikolai Semko:

As many people know, I also deal with anti-aliased graphics. It is for smooth graphics and working with every pixel that rounding functions are actively used.
It is for this reason that I have engaged in smoothening those nanoseconds. Because those nanoseconds on the smoothed graphics can turn into milliseconds on every frame, and a frame can change every 33 milliseconds.

Of course, this is important for graphics. That is why algorithmic optimizations for almost all common tasks have existed there for a very long time.

 
fxsaber:

Of course, this is important for graphics. That's why algorithmic optimizations for almost all common tasks have existed there for a very long time.

You are mistaken. The field there is still not ploughed, and what is ploughed is closed. And in MQL all the more so. CCanvas class is very far from optimality and there is almost no antialiasing and what there is of antialiasing is unsatisfactory.

 

Why don't you use LONG_MAX/MIN? It would look nicer somehow. It looks nice, I think. I ran your tests with gcc (with min modification, of course, very old compiler 5.4.0, what I had at hand):

1. Compiling with -O3.

Время цикла без округления = 0.001099185 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.004310106 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.001912712 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.005283493 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.002031304 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.005308409 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.002344382 секунд, сумма = 1.15583114 e+23

2. Compiling with -Ofast

Время цикла без округления = 0.000552652 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.001720999 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.00189282 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.001430063 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.001979336 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.001698521 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.001944874 секунд, сумма = 1.15583114 e+23

Your code has a problem with time calculation - output is in milliseconds (not nano), and I still don't understand why you need minus t0.

Print("Время выполнения функции ceil =  "+DoubleToString((double)(GetMicrosecondCount()-t-t0)/1000,3)+" наносекунд, Контрольная сумма = "+string(s));
 
Nikolai Semko:

Wrong. There is still an unploughed field, and what is ploughed is closed.

I was talking about world experience. Look at algorithms on the thematic forums where they make graph demos. People are sharing their quick algorithms.

 
fxsaber:

I was talking about world experience. Look for algorithms on the thematic forums where graph demos are made. People are sharing fast algorithms.

Can you please send me the link?
Reason: