Alternative implementations of standard functions/approaches - page 13

 
Реter Konow:

This is what the beginning of the block looks like:

As far as I understand you, you have created your own interpreter language.

  • you create the interface itself as a text file in that language
  • the body of the main program loads the text file and converts it to understandable "byte-code", essentially an array.
  • From this array, the interface images are generated

Like this?

Another silly question:

is each generated window with different elements one resource or many?

Although, a better analogy would probably be HTML

As I said before, your child needs a graphical constructor. Something like Andrei Barinov's.

Also your video clips are too long. You need to reduce them from 45 minutes to 5 minutes, or even better - 3 minutes.

 
A100:

Have you tried to find the answer to the question yourself?

Hint: In the google search, enter "DBL_MANT_DIG 53 52".

Yeah, thanks. Found it.

 
Nikolai Semko:

1. As far as I understand you, you have created your own interpreter language.

  • you create the interface itself as a text file in this language
  • the body of the main program loads the text file and converts it into human-readable "byte-code", essentially an array.
  • This array is used to generate interface images.

Like this?

And a silly question:

is each generated window with different elements one resource or many?

Although, perhaps a better analogy would be the HTML language.

As I said before - your brainchild needs a graphical constructor. Something like Andrei Barinov's.

Also your video clips are too long. From 45 minutes they should be reduced to 5 minutes, or even better, to 3.

1. Yes, it turns out that the definition of "interpreter" suits best what I have created (although in the process of creation I had no idea what it is).

  • Yes, that's right. The interpreter is created as a text file. More precisely, a direct initialization of the array "string SOURCE[]" inside the file connected to the indicator is performed. (The user writes the "KIB-code" and thus initializes the array). Further the indicator file is compiled by the user, and the content of the array is passed to the constructor (Expert Advisor) using the EventChartCustom().

  • Inside the constructor the adoption of the user's "KIB-code" in the form of "slicing" of strings is performed. Each passed string is a union of 128 characters. These strings are sliced and written to a copy of the SOURCE array on the Designer side. Then, the "kernel building block" is executed, which transforms the content of the "SOURCE" array into the content of the "int G_CORE[][]" array. This is the "kernel". The block converts one content into another, more than 5000 lines of code (consists of a set of functions).
  • .
  • The conversion is done using an intermediate array "int TEMPLATES[]", which collects prototypes of all elements and window platforms. Following an instruction from "SOURCE[]" (created by the user), the main kernel is assembled. Templates of elements from "TEMPLATES" are taken and transformed into "G_CORE".
  • .
  • When the core is built, the "engine" (the part of the constructor responsible for controlling the GUI mechanics) starts working with the built core. It draws kanvasses and opens windows.

2. Each formed window consists of several kanvases (resources). The first two of them are windows platform. Before, I used a different drawing method and therefore some parts were semi-transparent and you could see the graph through them. To avoid that I've added another kanvas in the background. Then the technique has improved, but the canvas stays in the background. It's grown into the technology and it's hard to get rid of it now. But eventually I'll remove it and the window platform will consist of one canvas.

Also, the "fields" (switchable image tabs), are independent canvases. They contain ready-made images and therefore switch as quickly as possible. If I were to draw everything on a single kanvas, inevitably the image switching would be slower. I would have to redraw all over again. Anyway, after thinking about it, I've come to the conclusion that this is the best option.


3. Visual Constructor was, and still is, my goal. I'm very close to the beginning of its implementation. There is an understanding of its structure. There are all the concepts necessary for its implementation. I know how to make it. All I need is time.


ZS. The peculiarity of my development is spontaneity. I wasn't familiar with interpertors or HTML language, and didn't know how they work. However, that doesn't stop me from creating and making similar things. I think if it works well, I'll keep on doing it. :)

 
Реter Konow:

At first glance, you seem to have a very wasteful use of memory. I may be wrong, though.

Ideally, your task should have only one canvas that supports transparency over the price chart.

The performance of MQL5 should be enough to form the whole interface on the fly without having ready blocks in memory, if coding is correct.

Although I don't exclude the possibility of sacrificing memory resources for increasing the performance of cumbersome interfaces.

I see one big advantage in your approach so far:

It will be easier for you to create a full-fledged graphical constructor, as it's easier to generate markup code rather than the MQL code itself.


But it's an elephantine task.
 
Nikolai Semko:

At first glance, you seem to have a very wasteful use of memory. I may be wrong, though.

Ideally, your task should have only one canvas that supports transparency over the price chart.

The performance of MQL5 should be enough to form the whole interface on the fly without having ready blocks in memory, if coding is correct.

Although I don't exclude the possibility of sacrificing memory resources for increasing the performance of cumbersome interfaces.

I see one big advantage in your approach so far:

It will be easier for you to create a full-fledged graphical constructor, as it's easier to generate markup code, not the MQL code itself.


But it's an elephantine task.

There is still a relatively small memory overrun. You're right. Element objects such as text or icon are "undeservedly" given a number of 235 properties in the kernel, while their own properties are several times less. The main element object, namely the base, should have all 235 properties, but icon and text objects have fewer properties. This creates a memory overrun.

The idea is that if I add another 60 cells to the row of main item objects, I can put text and icon properties in them. This would make the core "wider", but two thirds of the objects could be removed.

There would be excellent memory savings and a gain in kernel build speed. However, this is technically difficult to implement. There is a lot of rework to be done. So far, memory consumption and build time are quite acceptable. But there is no limit to perfection...


Using one canvas is not a good idea. It's much easier to use one canvas for each window and one canvas for each field. Generic canvas needs to be redrawn much more often. For every image switching or every window shift. On scrolling... It should be taken into account that redrawing is not always fast. It is not in the algorithms, but in the "sophistication" of the graphics. Let me explain:

If you draw a simple rectangular label (a square, for example), it's one cycle over an array of pixels with the right cells initialized with the right value (colour).

If you draw a square with a frame, it's two cycles on an array of pixels.

If you draw a square with a frame and an icon, it's three cycles.

If you draw a square with a frame that has a surface gradient and an icon that has a shadow, that's four or more cycles on the pixel array.

So, the steeper the graphic, the more you need to "iron" this array of pixels in cycles, creating the right image. Therefore, the less the need for redrawing, the better.

One canvas for all images, will make you redraw everything continuously. Therefore, it's not a good solution.


ZS. The task is certainly elephantine, but I can do it. (Although I will get some help.))

ZS. Thank you for the video, it's inspiring! :)

 
Реter Konow:


Do you resize the window with the mouse?
If so, does a red square appear?

 
Nikolai Semko:

Do you resize window with mouse?
If so, does a red square appear?

I don't understand what squares we're talking about.

The dynamic window can be resized with the mouse. How else could it be?


ZS: The dynamic window initially has a full screen size. Furthermore, it is "trimmed" to the required size. In other words, all its dynamism is realized in the maximum size of the already created bitmap.

 

To continue the topic of rounding.
I found out that modern Intel processors supporting extended SSE4.1 instruction set have rounding commandROUND{PS, PD} . I'm sure AMD has something similar.

https://ru.wikipedia.org/wiki/SSE4#SSE4a

http://o-ili-v.ru/wiki/SSE4

Does this mean that the MQL5 compiler does not use this command at CPU level? Since my Intel Kaby Lake processor supports this set.

And there's much more to it, even scalar multiplication of vectors.

SSE4 — Википедия
  • ru.wikipedia.org
SSE4 — новый набор команд микроархитектуры Intel Core, впервые реализованный в процессорах серии Penryn (не следует путать с SSE4A от AMD)[1]. Он был анонсирован 27 сентября 2006 года, однако детальное описание стало доступно только весной 2007 года. Более подробное описание новых возможностей процессоров для программистов можно найти на сайте...
 
fxsaber:

NormalizeDouble

The result is 1123275 and 1666643 in favour of MyNormalizeDouble (Optimize=1). Without optimization, it is four times faster (in memory).


Your function does not round correctly (it has round-off errors, due to division by fractions):

#define  EPSILON (1.0e-7 + 1.0e-13)
#define  HALF_PLUS  (0.5 + EPSILON)

double MyNormalizeDouble(const double Value, const int digits)
  {
   static const double Points[]= {1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8};
   return((int)((Value > 0) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);
  }

void OnStart()
  {
   Print(MyNormalizeDouble(2.026, 2) == 2.03);   // false
   Print(MyNormalizeDouble(2.03, 2) == 2.03);    // false

   Print(MyNormalizeDouble(2.256, 2) == 2.26);   // false
   Print(MyNormalizeDouble(2.26, 2) == 2.26);    // false
  }


Edit:

The correct code that avoids round-off errors should be:

#define  HALF_PLUS  (0.5 + FLT_EPSILON)

double MyNormalizeDouble(const double Value, const int digits)
  {
   static const double Powers[]= {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};
//---
   return (int)(Value * Powers[digits] + (Value > 0 ? HALF_PLUS : -HALF_PLUS)) / Powers[digits];
  }
 
amrali #:

Your function does not round correctly (it has round-off errors, due to division by fractions):


The correct code that avoids round-off errors should be:

Thanks. But this.

double f()
{
  double Res = 0;
  
  for (int i = 0; i < 1e8; i++)    
    Res = MyNormalizeDouble(Res += 0.121, 8);
    
  return(Res);  // 5.99216352 (12100000.0)
}


PS Slow.

double MyNormalizeDoubleSlow(const double Value, const int digits)
  {
   static const double Powers[]= {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};
//---
   return (int)((Value - (int)Value) * Powers[digits] + (Value > 0 ? HALF_PLUS : -HALF_PLUS)) / Powers[digits] + (int)Value;
  }
Reason: