Fortran's WHERE statement

Oct 24, 2013 at 7:59am
Is there a way to realize Fortran's WHERE statement in C++? I have an array and would like to set negative array elements to zero, as in this Fortran code:
WHERE(array<0.0) array=0.0
Oct 24, 2013 at 8:21am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

template< typename T, std::size_t N, typename PREDICATE >
void WHERE( T(&a)[N], PREDICATE fn, const T& v )
{ for( auto& e : a ) if( fn(e) ) e = v ; }

int main()
{
    int a[10] { 0, 1, -2, 3, -4, -5, 6, 7, -8, 9 };

    const auto negative = []( int i ) { return i<0 ; } ;
    WHERE( a, negative, 25 ) ;

    for( int i : a ) std::cout << i << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/ed7d46314983f78a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>

template< typename T, std::size_t N, typename PREDICATE, typename FN >
void WHERE( T(&a)[N], PREDICATE if_, FN fn )
{ for( auto& e : a ) if( if_(e) ) e = fn(e) ; }

int main()
{
    int a[10] { 0, 1, -2, 3, -4, -5, 6, 7, -8, 9 };

    const auto print = [&a]
    { for( int i : a ) std::cout << i << ' ' ; std::cout << '\n' ; } ;
    using boost::phoenix::arg_names::arg1 ;

    WHERE( a, arg1<0, arg1=25 ) ; print() ;

    WHERE( a, arg1%3 == 0, arg1+=30 ) ; print() ;
}

http://coliru.stacked-crooked.com/a/d002c686f8341327
Last edited on Oct 24, 2013 at 8:40am
Oct 24, 2013 at 10:00am
Iterate over the array, check the condition, and do your work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
float array[300];

// .. you put data into the array
std::mt19937 en(std::time(nullptr));
std::uniform_real_distribution<float> dist(-100.f, 100.f);
for (std::size_t i(0); i < std::extent<decltype(array), 0>::value; ++i)
{
    array[i] = dist(en);
}
// ^^ sample

for (std::size_t i(0); i < std::extent<decltype(array), 0>::value; ++i)
{
    if (array[i] < 0.f)
    {
        array[i] = 0.f;
    }
}



You can also use a more compact version which is part of the standard library, called std::replace_if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
float array[300];

        // .. you put data into the array
        std::mt19937 en(std::time(nullptr));
        std::uniform_real_distribution<float> dist(-100.f, 100.f);
        for (std::size_t i(0); i < std::extent<decltype(array), 0>::value; ++i)
        {
            array[i] = dist(en);
        }
        // ^^ sample

        std::replace_if(array, array + 300, [](const float &r)-> bool {return r < 0.f;}, 0.f);

        for (float &r : array)
        {
            std::cout << r << std::endl;
        }

Topic archived. No new replies allowed.