I am looking for the fastest way to test whether an n-dimensional numerical (NumericQ) array (in the ArrayQ sense) is complex or not. It is considered complex if it has at least one complex element.

It is an important requirement that this test must not unpack packed arrays.

Currently I have Not@ArrayQ[arr, _, FreeQ[#, _Complex] &], which does not unpack, but it executes the test for each element of packed arrays (can be tested using Print). Theoretically it's sufficient to test only one: all elements of a packed array are necessarily of the same type. In theory it's possible to detect whether an array is packed, and if it is, only test the first element, but this is very ugly, so I'd like to avoid it. It' also not easy to implement for an n-dimensional array.

What I am hoping for is a function which is internally special cased for packed arrays and is thus very fast.

What exactly would be a compex array? One in which every element belongs to Complexes, no matter if they are real or integers, but at least one of them is actually a complex? Or any array with at least one Complex element? Or all complex elements? Your test seems to define it as an array in which at least one of its elements has a complex subelement. Is that the idea?
–
RojoFeb 19 '13 at 4:21

@Rojo Okay, clarifications: the array is guaranteed to be numeric (as in NumericQ). If it has at least one complex element, it is considered to be complex. This is why I had Not@ ... FreeQ instead of MemberQ. Use case: need to decide how to transfer the data through MathLink so it's easy to handle in C on the other side.
–
SzabolcsFeb 19 '13 at 4:25

2 Answers
2

One potential problem with directly testing the complete list using Developer`PackedArray[arr_, type_] is that this test may fail if the whole array is not packed, but sub-arrays are. As a result, one can too easily fall through to the more general test using FreeQ (or MemberQ) and end up unpacking anyway. This can be avoided by using ReplaceAll to remove packed arrays in advance of the membership test, which is a trick I also used here.

An important difference between MemberQ and FreeQ is that the former has Heads -> False, while the latter has Heads -> True by default. Although one may of course specify Heads -> True to mimic the behavior of the example given in the question, since the intended application is to test array-like expressions, it's just as well to leave the default as it is. Furthermore, it's sufficient for the purpose of determining whether any complex values are present to test only level -1 of the structure, rather than every level as FreeQ does by default. As a result, a judicious use of MemberQ as above may perform somewhat better than Composition[Not, FreeQ] by virtue of testing fewer subexpressions.

But why not exit e.g. through exception throwing upon the first case where Developer`PackedArrayQ[l, Complex] woul d give True? It should be generally faster than either of the options you mentioned.
–
Leonid ShifrinFeb 19 '13 at 22:12

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.