3

I need to create an array of data which resembles to something like this

Table[{i, Sin[j^2*i]}, {j, 2000}, {i, 0., Pi, Pi/10000.}]

where each "row" of the array contains a list of tuples for varying values of the 'j' parameter. The time required for this computation can be calculated by the AbsoluteTiming function, giving

{15.1485, Null}

I succeeded in using functional programming at the first level. This speeds things up. For example, the following code does the same thing as the initial one:

Table[{#1, Sin[j^2 #1]} & /@ Range[0, Pi, Pi/10000.], {j, 2000}]

but is 5 times as fast as the original one. AbsoluteTiming returns

{3.71441, Null}

The size of these tables roughly represents the size of the data that I am currently manipulating (lots of it). Since I noticed that Table is not the most "time-efficient" option, I would like to learn how to construct this kind of table with things like pure functions and slots (which I naively assume leads to faster code).

Meclassic
  • 1,005
  • 1
  • 9
  • 15
  • Table[{i, Sin[j^2 i]}, {j, 2}, {i, 0., Pi, Pi/100.}]; : Table can take multiple iterators. – Syed Sep 17 '22 at 03:43
  • @Syed You are right and I do not know why but I was evaluating a Table with the iterators in the wrong order, which of course was not giving the desired result: Table[{i, Sin[j*i]}, {i, 0., 4 Pi, 4 Pi/100.},{j,2}]. Nevertheless, I have modified the title and updated my question accordingly. – Meclassic Sep 17 '22 at 03:48
  • t1 = Chop@Table[{i, Sin[j*i]}, {j, 2}, {i, 0., 4 Pi, 4 Pi/100.}]; and t2 = Chop@ Outer[{#2, Sin[#1 #2]} & , {1, 2}, Range[0., 4 Pi, 4 Pi/100.]]; are almost identical in timing. – Syed Sep 17 '22 at 04:01
  • 1
    Table is functional programming. If what you are looking for is to speed up this code, then please edit the question and make that the main topic. – Szabolcs Sep 17 '22 at 07:47
  • @Szabolcs I got confused with what functional programming means. You are right, speed is what I am looking for. The question has been edited accordingly. – Meclassic Sep 17 '22 at 14:35
  • Thanks for the edit, upvoted. – Szabolcs Sep 17 '22 at 14:46

1 Answers1

6

Set

A=N[Range[2000]];
B=N[Range[0,Pi,Pi/10000.]];

I will compare

method1:=Outer[{#2,Sin[#1^2*#2]}&,A,B];
method2:=Transpose[{ConstantArray[B,Length[A]],
                    Sin[Outer[Times,A^2,B]]},{3,1,2}];

To check that they give the same output, run

Max[Abs[Flatten[method1-method2]]]

Timing

RepeatedTiming[method1;]
(* about 27 seconds *)

RepeatedTiming[method2;] (* about 0.7 seconds *)

So method2 is quite a bit faster. The reason is that it uses packed arrays and certain simple constructs such as Outer[Times,...] that are fast.

Comment. Perhaps there is some room for further improvement, but I would think that one limitation is Sin. Therefore, I would be surprised if there was a solution faster than

temp=RandomReal[{-1,1},Length[A]*Length[B]];
RepeatedTiming[Sin[temp];]
(* about 0.1 seconds *)
user293787
  • 11,833
  • 10
  • 28
  • 1
    Nice answer, but you have a wrong square: A^2. It should only be: A – Daniel Huber Sep 17 '22 at 07:57
  • @DanielHuber Thanks for your feedback. OPs question contains both versions, one without square and one with square, and I thought I take the one with square. – user293787 Sep 17 '22 at 08:12