Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Range-v3 operator overloading to write shorter code

For my matrix class I want to do some sort of operator overloading (probably using expression templates) on range-v3 views for + - / * % . For example if I want to get a view of the sum of two columns, I want to write

col_1 + col_2

instead of

rv::zip_with([](auto c1, auto c2) {return c1 + c2;}, col_1, col_2);

Probably some ideas from this paper can be used to avoid constructing too many temporaries. Here is the code that I want to write:

//simple example
//what I want to write
auto rangeview =    col_1 + col_2;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2) {
                        return c1 + c2;
                    }, col_1, col_2);


//itermediate
//what I want to write
auto rangeview =    col_1 + col_2 + col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return c1 + c2 + c3;
                    }, col_1, col_2, col_3);


//advanced
//what I want to write
auto rangeview =    10*col_1 + 20*col_2 - 30*col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return 10.0*c1 + 20.0*c2 - 30.0*c3;
                    }, col_1, col_2, col_3);


//more advanced with elementwise multiplication
//what I want to write
auto rangeview =    10*col_1 + 20*col_2 - col_2 % col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return 10.0*c1 + 20.0*c2 - c2*c3;
                    }, col_1, col_2, col_3);
like image 267
Porsche9II Avatar asked Sep 11 '25 11:09

Porsche9II


1 Answers

Range views are supposedly lazy; Is it not why they are called views in the first place? So why not to return the resulting view in a user defined operand of your own? They'll ideally get evaluated, once the final range is iterated in a for loop or an algorithm.

IMHO not everything can be provided by the std or any other general purpose library. Some little tweaks are necessary using any tool:

decltype(auto) operator+(column const& col_1, column const& col_2){
    return rv::zip_transform( [] (auto c1, auto c2)
                                 {return c1 + c2;},
                             rv::all(col_1),
                             rv::all(col_2) );
};

A scalar * vector multiplication operator can be separately defined in a similar manor too. Then the linear combination of columns is written just as it is mathematically written. The actual calculations will wait till a for loop or an algorithm like std::fold or std::foreach traverses the range.


Lazy scalar * vector product becomes:

decltype(auto) operator*(range_value_t<column> const coef, column& col) {
    return rv::transform(rv::all(col),[=,coef](auto x){return coef*x});
};
like image 118
Red.Wave Avatar answered Sep 14 '25 00:09

Red.Wave