Home > Software engineering >  Is there any equivalent of Python range() in C ?
Is there any equivalent of Python range() in C ?

Time:04-01

I want to use std::for_each to iterate over vector indexes in range [a, b) in parallel, calculate the value of the Weierstrass function and write it to the std::vector:

std::vector<std::array<float, 2>> values(1000);
auto range = /** equivalent of Pyhthon range(0, values.size()) **/;

std::for_each(std::execution::par, range.begin(), range.end(), [&](auto &&i) {
    values[i][0] = static_cast<float>(i) / resolution;
    values[i][1] = weierstrass(a, b, static_cast<float>(i) / resolution);
});

// a, b, and resolution are some constants defined before
// weierstrass() is the Weierstrass function

I have found some solutions in the internet, but all of them requires to include some third-party libraries or create my own range class. Is there any standard solution for this?

CodePudding user response:

You can use std::views::iota(), its use is identical to Python's range(). With help of std::ranges::for_each(). Both are available in C 20.

Try it online!

#include <algorithm>
#include <ranges>
#include <iostream>

int main() {
    std::ranges::for_each(std::views::iota(1, 10), [](int i) {
        std::cout << i << ' ';
    });
}

Output:

1 2 3 4 5 6 7 8 9 

As noted by @Afshin, in code mentioned above std::ranges::for_each() doesn't support std::execution::par for multi-threaded execution.

To overcome this issue you may use iota with regular std::for_each() as following:

Try it online!

#include <algorithm>
#include <ranges>
#include <iostream>
#include <execution>

int main() {
    auto range = std::views::iota(1, 10);
    std::for_each(std::execution::par, range.begin(), range.end(),
        [](int i) {
            std::cout << i << ' ';
        });
}

Output:

1 2 3 4 5 6 7 8 9 

CodePudding user response:

If the problem is in creating range similar to python's range() you can look through https://en.cppreference.com/w/cpp/iterator/iterator and use it's example:

#include <iostream>
#include <algorithm>
 
template<long FROM, long TO>
class Range {
public:
    // member typedefs provided through inheriting from std::iterator
    class iterator: public std::iterator<
                        std::input_iterator_tag,   // iterator_category
                        long,                      // value_type
                        long,                      // difference_type
                        const long*,               // pointer
                        long                       // reference
                                      >{
        long num = FROM;
    public:
        explicit iterator(long _num = 0) : num(_num) {}
        iterator& operator  () {num = TO >= FROM ? num   1: num - 1; return *this;}
        iterator operator  (int) {iterator retval = *this;   (*this); return retval;}
        bool operator==(iterator other) const {return num == other.num;}
        bool operator!=(iterator other) const {return !(*this == other);}
        reference operator*() const {return num;}
    };
    iterator begin() {return iterator(FROM);}
    iterator end() {return iterator(TO >= FROM? TO 1 : TO-1);}
};
 
int main() {
    // std::find requires an input iterator
    auto range = Range<15, 25>();
    auto itr = std::find(range.begin(), range.end(), 18);
    std::cout << *itr << '\n'; // 18
 
    // Range::iterator also satisfies range-based for requirements
    for(long l : Range<3, 5>()) {
        std::cout << l << ' '; // 3 4 5
    }
    std::cout << '\n';
}

CodePudding user response:

Just as an alternative, you could make each work package carry the necessary information by adding the index you need.

Example:

std::vector<std::pair<size_t, std::array<float, 2>>> values(1000);
for(size_t i = 0; i < values.size();   i) values[i].first = i;

std::for_each(std::execution::par, values.begin(), values.end(),
    [&](auto& p) {
        p.second[0] = static_cast<float>(p.first) / resolution;
        p.second[1] = weierstrass(a, b, static_cast<float>(p.first) / resolution);
    });
  • Related