I'm on Windows 10 Mathematica 12.1.1.

I would expect allocating a big ConstantArray and comparing would be slower but apparently it is not:

RepeatedTiming[RandomReal[1, 10000] == ConstantArray[0, 10000]]
(* {0.0000589, False} *)
RepeatedTiming[ContainsOnly[RandomReal[1, 10000], {0}]]
(* {0.00309, False} *)

This becomes even worse if I add SameTest->Equal which the documentation states allows some numerical tolerance:

RepeatedTiming[ContainsOnly[RandomReal[1, 10000], {0}, SameTest -> Equal]]
(* {7.92, False} *)

Why is the above more than ~100,000 times slower than the code that allocates a ConstantArray with a large ByteCount?! What is going on behind the scenes in ContainsOnly that's more expensive than allocation?

Admittedly, in this much bigger case involving sparse arrays ContainsOnly is faster, so I'd guess the allocation overhead eventually catches up:

RepeatedTiming[SparseArray[999999 -> 1] == ConstantArray[0, 1000000]]
(* {0.00212, False} *)
RepeatedTiming[ContainsOnly[SparseArray[999999 -> 1, 1000000], {0}]]
(* {0.0000169, False} *)
  • $\begingroup$ Look at the timing of Complement[RandomReal[1, 10000], {0}] $\endgroup$ – Jason B. Aug 7 at 14:18
  • $\begingroup$ @JasonB. Thanks. Complement would have to construct a list though so I'd expect it to be a little slow. ContainsOnly simply has to return True or False. $\endgroup$ – flinty Aug 7 at 14:30
  • 1
    $\begingroup$ I agree that ContainsOnly should be able to short circuit and return False at the first mismatch, and not continue with the remaining comparisons that Complement does. But it doesn't appear to be implemented that way. $\endgroup$ – Jason B. Aug 7 at 16:27
  • 1
    $\begingroup$ What @JasonB said. That function is on my to-improve list, though not at the top. $\endgroup$ – Daniel Lichtblau Aug 9 at 14:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.