3
$\begingroup$

I am programming a small game (with other programming language) in which I have to use Mod function to express piecewise linear period functions.

In my case, two hard parts I think exist.

(1) The periodic function is linear in the piecewise sence, like the function below. In a full period it is NOT linear.

(2) There are NO powerful function like Piecewise function in Mathematica, and all I can use are some very basic functions including Mod, +,-, *, \, Abs, Floor, Ceiling,Exp,10^,Sin,Cos,Tan,ASin,ACos, ATan,Log and logic control commands If, If Then Else.

(3) After many times trying, I also found another challenging part is related to Mod of a negative number .My piecewise linear periodic function can thake negative integers whose Mod is so confusing to me. I can calculate the Mod of a negative number by hand, but I have no clear idea how it relates to a repeat pattern.

So is it possible to use Mathematica to find something like linear combinations of Mod functions for any periodic piecewise linear function?

For example, the periodic piecewise linear period function like this:

f[x_?IntegerQ] := 
 Piecewise[{{-10 x + 2, 1 <= x < 4}, {-5 x + 8, 4 <= x <= 10}}, True]
f[x_?IntegerQ] := f[x + 10] /; x < 1
f[x_?IntegerQ] := f[x - 10] /; x > 10
ListPlot[Table[{x, f[x]}, {x, -9, 20}]]

Any advices are highly appreciated! Thanks :)

some period piecewise linear function

$\endgroup$
6
  • $\begingroup$ What about period = 10; ListPlot[Table[{x, Mod[x, period, 0]}, {x, -9, 20}]]? $\endgroup$ Jan 24, 2022 at 13:41
  • $\begingroup$ Partly similar to this. $\endgroup$
    – Syed
    Jan 24, 2022 at 13:43
  • $\begingroup$ Thanks, but in my problem the repeated part is a combination of two different linear functions, that is the linear functions on [1,4) and [4,10] are different. $\endgroup$
    – xinxin guo
    Jan 24, 2022 at 13:47
  • 1
    $\begingroup$ Does your other programming language's mod() function work exactly like Mod[]? I doubt it: Both Mod[x, m] and Mod[x, m, x0]? Mod[x + m, m] == Mod[x, m], even when -m < x < 0? It seems necessary to know how the functions in both Mathematica and the target language work to know how to solve the problem. $\endgroup$
    – Michael E2
    Jan 24, 2022 at 17:27
  • 1
    $\begingroup$ @MichaelE2 Thanks for you answer, very inspring. Actually, my target programming language is Scratch (scratch.mit.edu), and it dosen't support Mod[x, m, x0] and Mod[x + m, m] == Mod[x, m]. My naive idea is to use a guess form of Mod linear combination to fit the data generated by original piecewise linear function. I will think more on your great answer. Thanks :) $\endgroup$
    – xinxin guo
    Jan 25, 2022 at 1:28

1 Answer 1

5
$\begingroup$

Here's a way to take advantage of Mathematica's code generation capabilities. In particular we take advantage of two internal workhorses, Simplify`PWToUnitStep and Experimental`OptimizeExpression. You should check to see if your library has a unit step function, and if so, you can just use the output of Simplify`PWToUnitStep, inserting x = Mod[y, 10] for input y, and avoid the rest of the trickery.

(* Auxiliary functions *)
ifArithmeticRules = {
   Times[z_, If[c_, a_, b_]] :> With[{i = If @@ {c, a*z, b*z}}, i /; True], 
   Plus[z_,  If[c_, a_, b_]] :> With[{i = If @@ {c, a+z, b+z}}, i /; True]};
compileToTempVars = 
  With[{c = #[[1, 1]]}, # /. 
     Thread[c -> Block[{nnn = 1}, Symbol["tmp" <> ToString[nnn++]] & /@ c]]
   ] &;

Simplify`PWToUnitStep[
      Piecewise[{{-10 x + 2, 1 <= x < 4}, {-5 x + 8, 4 <= x <= 10}}]
      ] // ReplaceAll[{
       x -> Mod[x, 10],             (* adjust if Mod[] != mod() *)
       UnitStep -> (Inactive[If][#>=0,1,0]&)  (* is translating UnitStep[] necessary? *)
       }] // 
    Experimental`OptimizeExpression //
   Activate //     (* If had to be Inactive[] for condition to be optimized *)
  compileToTempVars //              (* optional: change variable names *)
 ReplaceRepeated@ifArithmeticRules  (* not needed if you can use UnitStep[] *)
(*
  Experimental`OptimizedExpression[Block[{tmp1, tmp2, tmp3, tmp4},
    tmp1 = Mod[x, 10];
    tmp2 = -4 + tmp1;
    tmp3 = tmp2 >= 0;
    tmp4 = If[tmp3, 1, 0];
    If[10 - tmp1 >= 0,
     If[-1 + tmp1 >= 0,
      -2 (-1 + 5 tmp1) (1 - tmp4) + (8 - 5 tmp1) tmp4,
      (8 - 5 tmp1) tmp4],
     If[-1 + tmp1 >= 0, -2 (-1 + 5 tmp1) (1 - tmp4),
      0
      ]]]]
*)
$\endgroup$
1
  • $\begingroup$ You'll have to adjust Mod[x, 10] if your mod() function works differently. $\endgroup$
    – Michael E2
    Jan 24, 2022 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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