Posts

A Trait worse than death

Going back many a year before C++ was in general circulation I had occasion to write a graphics library. It would need to be able to use a couple of different screen based APIs and also assorted pen plotters. To this end the individual drivers populated a virtual function table that would be called by the API layer. In effect a manual implementation of a C++ class system with "virtual" methods. The need for languages to have these sorts of mechanisms is clear. Of late languages have broken away from C++ classes. Golang has instead the idea of an interface, the definition of an interface specifies what functions (no variables) that interface has. At that point any struct that contains all those functions can call a function that wants the interface as a parameter. It's a great concept, very flexible, a struct might satisfy any number of different interfaces without the need for inheritance. Rust decides to change the game again and has traits which are like interfaces but

A Rust Iterator example

The idea of having an iterator type allowing you to navigate containers in a standard fashion has become common in many languages including Rust. Sadly I think the documentation makes a mess of it. I seem to come across two examples on which gives out Fibonacci  sequence numbers and is not really what I'd call an iterator, you can't reiterate it again and so it's plain confusing to post it as an example. The other I come across is a structure with a Vec in it and that just returns the iterator for the Vec which does not exactly help you in coding a real iterator. So let's start off with what an iterator essentially is an go from there. When we have a structure which we want to iterate an iterator has two pieces of information it needs, it needs a reference to the structure itself and it needs to know where we are in indexing that structure. We can't store that position index in the structure itself as if we had a nested loop or even multiple threads it could be over

Getting Rusty

Over the years I have written in many programming languages and even written a few. They all have pros and cons, things where they are ahead of the game and sometimes places where I feel they are going backwards. Really folks writing languages, why leave out  the c preprocessor or an equivalent? It's enormously useful and powerful. The last few years have been mainly golang which I have been very impressed with. Concise, secure and many innovative features. Not giving it full marks out of ten as I took a big dislike to it's "linter" that imposes styles that are pointlessly strict and actually unsuitable for some projects. Golang uses a "garbage collection" system for memory which is both a blessing and a curse. It makes things safe and secure for sure, but it means you never know quite what's going on. Plunging back into C/C++ for these tutorials though has reminded me of just how dangerous c can be, the potential to access beyond the end of arrays and l

Let's unroll a loop

 Loop unrolling is an optimisation that has had a small place in my heart, ever since I was working at a Dilbertesque company with so many management layers that on one project I was a couple of years into it before hearing that some guy I had never heard of and who had never bothered to meet the troops was actually in charge! But I digress, it was on that sort of project where they had made promises to a client as to how fast a mathematical model was going to work and obviously it didn't and they thought they we going to need to lose a significant amount of dosh to buy better kit for the client. I profiled the code, found the hotspot in a loop and having looked at the assembler generated saw that  no unrolling was done, duly unrolled the code was at least in the speed regard up to spec. Some time later a man in a grey suit actually deigned to find me in my cubicle and awkwardly say thanks.  This was extremely novel at the time. So here's an example which isn't to far off w

Array Intersections - part 4

 In our last visit to array intersections we looked at using "simd" instructions to speed up the process of array intersections. It's a quite well documented technique and one I have used successfully myself. Things didn't go quite to plan. The code worked but was slower than the basic technique of scanning two arrays. Now admittedly I had simplified ever so slightly I used: if (( mask & 1 ) > 0 ) { array3 [ count ++] = y [ posy ]; } if (( mask & 2 ) > 0 ) { array3 [ count ++] = y [ posy + 1 ]; } if (( mask & 4 ) > 0 ) { array3 [ count ++] = y [ posy + 2 ]; } if (( mask & 8 ) > 0 ) { array3 [ count ++] = y [ posy + 3 ]; } to copy the elements into the output array when they match according to the mask we found using the simd instructions. The real world implementations I have seen use mor