# How to make a square wave function with controllable period, phase and duty cycle that can work really fast?

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?

• Try squareWave[x_, period_: 1, duty_: (1/2), phase_: 0] := Sign[Mod[x + phase period, period] - (1 - duty) period] – J. M.'s technical difficulties Nov 9 '17 at 17:20
• 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. – Helyrk Nov 9 '17 at 19:57
• Btw, the good PC evaluates AbsoluteTiming[Do[Sin, 10^6]] in 0.038 seconds. – Helyrk Nov 9 '17 at 20:19
• Maybe you could use Compile? – anderstood Nov 9 '17 at 20:41
• Have you tried compiling J.M.'s version? It uses only low level functions, I guess, so should be fast. – anderstood Nov 9 '17 at 21:08

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.

• 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. – Helyrk Nov 9 '17 at 21:45
• 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. – J. M.'s technical difficulties Nov 10 '17 at 3:22