views:

253

answers:

8

can i check in C(++) if an array is all 0 (or false) without iterating/looping over every single value and without allocating a new array of the same size (to use memcmp)?

i'm abusing an array of bools to have arbitrary large bitsets at runtime and do some bitflipping on it

+3  A: 

You can use the following condition:

(myvector.end() == std::find(myvector.begin(), myvector.end(), true))

Obviously, internally, this loops over all values.

The alternative (which really should avoid looping) is to override all write-access functions, and keep track of whether true has ever been written to your vector.

UPDATE

Lie Ryan's comments below describe a more robust method of doing this, based on the same principle.

Oli Charlesworth
be aware that, while the flag can reliably tell that the array contains all false if the flag is false; if the flag is true, it cannot reliably tell if the array does contain a true. If the flag is true, you'll still need to check whether there is any true.
Lie Ryan
A more sophisticated way is to keep track of how many `true`s is in the array. If you're changing a value from true to false, you decrement this counter, and if you're changing a value from false to true, then you increment the counter. Otherwise, if you're changing from true to true or from false to false, you do nothing. You can tell if the array is all false if the counter is zero.
Lie Ryan
One thing to keep in mind though is that, if you modify the array a lot and rarely do the "is all 0" check and if the array isn't too big, you're wasting more time modifying the counter than you would be if you were to check the array.
EboMike
It's not a good idea to override std::vector<bool> . Party, because standard container implementations aren't necessarily designed to be overridden. But also, in c++0x, std::vector<bool> won't be a bitset anymore.
kotlinski
@kotlinksi: Yes, to be safe, you'd need to write your own class that wraps `std::vector`, rather than derives from it.
Oli Charlesworth
+2  A: 

If it's not sorted, no. How would you plan on accomplishing that? You would need to inspect every element to see if it's 0 or not! memcmp, of course, would also check every element. It would just be much more expensive since it reads another array as well.

Of course, you can early-out as soon as you hit a non-0 element.

Your only option would be to use SIMD (which technically still checks every element, but using fewer instructions), but you generally don't do that in a generic array.

(Btw, my answer assumes that you have a simple static C/C++ array. If you can specify what kind of array you have, we could be more specific.)

EboMike
+1. I think your only option provided you have a contiguous array of integral types would be to use SIMD instructions as mentioned to check multiple elements at once.
Wyatt Anderson
A: 

No, you can compare arrays with memcmp, but you can't compare one value against a block of memory.

What you can do is use algorithms in C++ but that still involves a loop internally.

Let_Me_Be
A: 

You don't have to iterate over the entire thing, just stop looping on the first non-zero value.

I can't think of any way to check a set of values other than inspecting them each in turn - you could play games with checking the underlying memory as something larger than bool (__int64 say) but alignment is then an issue.

EDIT: You could keep a separate count of set bits, and check that is non-zero. You'd have to be careful about maintenance of this, so that setting a set bit did not ++ it and so on.

Steve Townsend
+1  A: 

If you know that this is going to be a requirement, you could build a data structure consisting of an array (possibly dynamic) and a count or currently non-zero cells. Obviously the setting of cells must be abstracted through, but that is natural in c++ with overloading, and you can use an opaque type in c.

dmckee
A: 

Consider using boost::dynamic_bitset instead. It has a none member and several other std::bitset-like operations, but its length can be set of runtime.

larsmans
i cannot use external libraries (and don't want to either)
knittl
@knittl: then you can copy and paste the code from `boost::dynamic_bitset`.
Steve Jessop
This is a header-only library. You can just copy the `dynamic_bitset` directory into your project and include the main header in your source file.
larsmans
Good luck in just copying a single header from boost and making it compile...
kotlinski
Then I'd suggest shooting yourself. NDH syndrome is a debilitating and painful disease somewhat along the lines of Alzheimer's or brain cancer. I know that I for one at least would rather end it all than die slowly in such an awful manner.
Noah Roberts
+1  A: 

Assume that you have an array of N element, you can do a bit check against a set of base vectors.

For example, you have a 15-element array you want to test.

You can test it against an 8-element zero array, an 4-element zero array, a 2-element zero array and a 1-element zero array.

You only have to allocate these elements once given that you know the maximum size of arrays you want to test. Furthermore, the test can be done in parallel (and with assembly intrinsic if necessary).

Further improvement in term of memory allocation can be done with using only an 8-element array since a 4-element zero array is simply the first half of the 8-element zero array.

Dat Chu
A: 

knittl,

I don't suppose you have access to some fancy DMA hardware on the target computer? Sometimes DMA hardware supports exactly the operation you require, i.e. "Is this region of memory all-zero?" This sort of hardware-accelerated comparison is a common solution when dealing with large bit-buffers. For example, some RAID controllers use this mechanism for parity checking.

Andrew Cottrell