| /* REQUIRED_ARGS: -O -release -inline |
| This compares two different ways to do a for loop. The range |
| version should SROA the VecRange struct into two register variables. |
| */ |
| |
| extern (C): |
| |
| nothrow: |
| @nogc: |
| @safe: |
| |
| alias vec_base_t = size_t; // base type of vector |
| alias vec_t = vec_base_t*; |
| |
| @trusted |
| pure |
| size_t vec_index(size_t b, const vec_t vec); |
| |
| @trusted |
| pure ref inout(vec_base_t) vec_numbits(inout vec_t v) { return v[-1]; } |
| @trusted |
| pure ref inout(vec_base_t) vec_dim(inout vec_t v) { return v[-2]; } |
| |
| struct VecRange |
| { |
| size_t i; |
| const vec_t v; |
| |
| @nogc @safe nothrow pure: |
| this(const vec_t v) { this.v = v; i = vec_index(0, v); } |
| bool empty() const { return i == vec_numbits(v); } |
| size_t front() const { return i; } |
| void popFront() { i = vec_index(i + 1, v); } |
| } |
| |
| @safe |
| pure |
| uint vec_numBitsSet(const vec_t vec) |
| { |
| uint n = 0; |
| size_t length = vec_numbits(vec); |
| for (size_t i = 0; (i = vec_index(i, vec)) < length; ++i) |
| ++n; |
| return n; |
| } |
| |
| @safe |
| pure |
| uint vec_numBitsSet2(const vec_t vec) |
| { |
| uint n = 0; |
| foreach (j; VecRange(vec)) |
| ++n; |
| return n; |
| } |