c++valarray

How to use std::valarray in if statement without redundant computation?


I have the following code with float, for example:

std::vector<float> v = {0.f, 1.f, 2.f};
for(size_t i = 0; i < v.size(); ++i)
    if(v[i] != 0) // An optimization for `v[i] != 0`.
        v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.

Now I want to replace float with std::valarray<float>:

using vfloat = std::valarray<float>;
std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.f, 0.f}};
for(size_t i = 0; i < v.size(); ++i)
    // if(v[i] != 0) // I want this optimization! ◀◀◀◄◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀◀
        v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.

Though the new code is correct logically, there are redundant computation for v[i][j] == 0.

So how to use std::valarray in if statement without the redundant computation?


Solution

  • If you want to skip elemets in v[i] use a nested loop

    using vfloat = std::valarray<float>;
    std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.f, 0.f}};
    for(size_t i = 0; i < v.size(); ++i)
        for(size_t j = 0; j < v[i].size(); ++j)
            if (v[i][j] != 0)
                v[i][j] = v[i][j] * v[i][j] * v[i][j]; // Time-consuming computation.
    

    or apply:

    using vfloat = std::valarray<float>;
    std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.f, 0.f}};
    for(size_t i = 0; i < v.size(); ++i)
        v[i] = v[i].apply([](float n) -> float {
            if (n == 0) return 0;
            return n * n * n; // Time-consuming computation.
        });
    

    If you want to skip elements in v

    using vfloat = std::valarray<float>;
    std::vector<vfloat> v = {vfloat{0.f, 0.f}, vfloat{1.f, 0.f}, vfloat{2.f, 0.f}};
    for(size_t i = 0; i < v.size(); ++i)
        if ((v[i] != 0).max() != 0)
            v[i] = v[i] * v[i] * v[i]; // Time-consuming computation.