13
$\begingroup$

Here I'm not interested in accuracy (see 13614) but rather in raw speed. You'd think that for a complex machine-precision number z, calculating Abs[z]^2 should be faster than calculating Abs[z] because the latter requires a square root whereas the former does not. Yet it's not so:

s = RandomVariate[NormalDistribution[], {10^7, 2}].{1, I};
Developer`PackedArrayQ[s]
(* True *)
Abs[s]^2; // AbsoluteTiming // First
(* 0.083337 *)
Abs[s]; // AbsoluteTiming // First
(* 0.033179 *)

This indicates that Abs[z]^2 is really calculated by summing the squares of real and imaginary parts, taking a square root (for Abs[z]), and then re-squaring (for Abs[z]^2).

Is there a faster way to compute Abs[z]^2? Is there a hidden equivalent to the GSL's gsl_complex_abs2 function? The source code of this GSL function is simply to return Re[z]^2+Im[z]^2; no fancy tricks.

$\endgroup$
  • 1
    $\begingroup$ Here's an even slower way: (Re[#]^2 + Im[#]^2) & /@ s. And even slower still: Total[ReIm[#]^2] & /@ s $\endgroup$ – bill s May 10 '19 at 14:24
21
$\begingroup$

There's Internal`AbsSquare:

s = RandomVariate[NormalDistribution[], {10^7, 2}].{1, I};
foo = Internal`AbsSquare[s]; // AbsoluteTiming // First
murf = Abs[s]^2; // AbsoluteTiming // First
(*
  0.022909
  0.063441
*)

foo == murf
(*  True  *)
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Ah yes precisely what I was looking for, many thanks Michael! Is there a repository of such tricks? $\endgroup$ – Roman May 10 '19 at 14:25
  • 1
    $\begingroup$ @Roman I was just looking. I thought there was a post about useful Internal` functions, but I couldn't find it just now. The context contains some useful numerical functions like Log1p and Expm1. Statistics`Library` also contains some nice, well-programmed functions. $\endgroup$ – Michael E2 May 10 '19 at 14:31
  • 3
    $\begingroup$ @MichaelE2 mathematica.stackexchange.com/questions/805/… $\endgroup$ – Chris K May 10 '19 at 14:31
  • 1
    $\begingroup$ @ChrisK That must be it! Thanks. $\endgroup$ – Michael E2 May 10 '19 at 14:32
  • 1
    $\begingroup$ @CATrevillian I would have thought it was in the MKL (Intel Math Kernel Library), but I didn't find it there. I guess I don't know. $\endgroup$ – Michael E2 May 11 '19 at 3:10
1
$\begingroup$

for v5.2, s Conjugate[s] is fast too, ref the pic:

enter image description here

| improve this answer | |
$\endgroup$
  • 3
    $\begingroup$ On my computer, Re[s*Conjugate[s]] is about five to ten times slower than Internal`AbsSquare[s]. What is your $Version and what CPU do you have? $\endgroup$ – Roman Jul 8 at 12:27
  • 1
    $\begingroup$ Hi, people here generally like users to post code as Mathematica code instead of just images or TeX, so they can copy-paste it. It makes it convenient for them and more likely they will engage with your posts. You may find this meta Q&A helpful. -- BTW, have you seen RandomVariate[NormalDistribution[], {10^7, 2}]? It's much faster on my machine. Ditto for RandomComplex[]. $\endgroup$ – Michael E2 Jul 8 at 12:48
  • $\begingroup$ @Roman Re[] is unnecessary, though it's very fast. My version is very old, it's v5.2. So there's no Internal`AbsSquare[]. $\endgroup$ – infoage Jul 8 at 18:14
  • $\begingroup$ @MichaelE2 Thanks, man. My version is v5.2. This code is so simple that I had no motivation to paste text version at that moment. Sorry. $\endgroup$ – infoage Jul 8 at 18:18
  • 1
    $\begingroup$ Maybe it's worth adding the version info to your answer. It turns out that I don't have the Statistics`NormalDistribution package (in V12.1.1), I suppose because it's been replaced by top-level statistics functions some versions ago. $\endgroup$ – Michael E2 Jul 8 at 19:08

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.