2
$\begingroup$

I actually need two things:

  1. A square wave function that allows me to control its duty cycle, period and phase.
  2. It must work fast enough to be evaluated at least a million times per second.

For the first problem, I found a number of solutions. Some of them may be found here: How to create a rectangle wave (duty cycle $\ne$ 50 %)?

The best one that I tried yet is as follows:

squareWave[period_, duty_, phase_,  x_] := Sign[TriangleWave[x/period - phase] - 1 + 2 duty]

Unfortunately, on my current machine it takes about 34 seconds to evaluate it 10^6 times. To compare with, Sin[x] evaluates 10^6 times in 0.09 seconds.

Is it even possible to achieve my goal? And how?

$\endgroup$
  • $\begingroup$ Try squareWave[x_, period_: 1, duty_: (1/2), phase_: 0] := Sign[Mod[x + phase period, period] - (1 - duty) period] $\endgroup$ – J. M. will be back soon Nov 9 '17 at 17:20
  • $\begingroup$ The test that gives 34 seconds is actually AbsoluteTiming[Do[squareWave[1, 0.5, 0, 0.3], 10^6]] with the definition of squareWave provided above. Some insignificant details were omitted to simplify the question. I have a PC that can handle the same task in 7 seconds but it's still too slow. I tried your definition with the test AbsoluteTiming[Do[squareWave[0.3], 10^6]] on a good PC and it just took 8 seconds instead of 7. $\endgroup$ – Helyrk Nov 9 '17 at 19:57
  • $\begingroup$ Btw, the good PC evaluates AbsoluteTiming[Do[Sin[1], 10^6]] in 0.038 seconds. $\endgroup$ – Helyrk Nov 9 '17 at 20:19
  • $\begingroup$ Maybe you could use Compile? $\endgroup$ – anderstood Nov 9 '17 at 20:41
  • 1
    $\begingroup$ Have you tried compiling J.M.'s version? It uses only low level functions, I guess, so should be fast. $\endgroup$ – anderstood Nov 9 '17 at 21:08
1
$\begingroup$

The following maps directly to the List of values:

x = RandomReal[1, 10^6];
squareWave[x_, period_: 1, duty_: (1/2), phase_: 0] := 
       Sign[Mod[x + phase period, period] - (1 - duty) period] (* J.M.'s def. *)
squareWave[x, 1, .5, 0]; // AbsoluteTiming
(* 0.0078 *)

If you want to evaluate with multiple period, duty and phase values, stack all values in Lists as in:

x = RandomReal[2, 10^6];
period = RandomReal[1, 10^6];
duty = RandomReal[.7, 10^6];
phase = RandomReal[.5, 10^6];
squareWave[x, period, duty, phase]; // AbsoluteTiming
(* 0.061 *)

This is 150 times faster than the sequential approach Table[squareWave[x[[i]], period[[i]], duty[[i]], phase[[i]]], {i, 10^6}], however it assumes that you know the list of values before running the calculation, which seems to be the case.

$\endgroup$
  • $\begingroup$ Well this is a very interesting and useful result. I will definitely try to apply it to the real task and mark the answer accepted if it helps. As of now, a quick test shows about 10x improvement in speed so on a good PC it may be enough. $\endgroup$ – Helyrk Nov 9 '17 at 21:45
  • $\begingroup$ Somehow I figured that something wonky was going on with either the OP's computer or with how the function I proposed is being applied for it to be "slower" than Sin[], but lost interest in trying to diagnose it. $\endgroup$ – J. M. will be back soon Nov 10 '17 at 3:22

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.