2012-04-08 7 views
0

Maple CodeGeneration [C]をpiecewise関数用のハンドラで拡張したいのですが(含まれていない理由はありません)。私はpuroposeのcase文の賛成であればelseステートメントを使用していますMapleコード生成を拡張する際の変数名

with(CodeGeneration): 
with(LanguageDefinition): 

LanguageDefinition:-Define("NewC", extend="C", 
    AddFunction("piecewise", anything::numeric, 
     proc() 
      local i; 
      Printer:-Print("if(",_passed[1],"){",_passed[2],"}"); 
      for i from 3 to _npassed-2 by 2 do 
       Printer:-Print("else if(",_passed[i],"){",_passed[i+1],"}"); 
      end do; 
      Printer:-Print("else{",_passed[_npassed],"}"); 
     end proc, 
    numeric=double) 
); 

注:私はこの目的のために 。ここ は、変換するサンプルコードです:

myp:=proc(x::numeric) 
    piecewise(x>1,1*x,x>2,2*x,x>3,3*x,0); 
end proc: 
Translate(myp, language="NewC"); 

出力は、私は明らかに何かに

{x} 

ような中括弧を交換する必要があり、有効なC-ルーチンの

void myp (double x) 
{ 
    if(0.1e1 < x){x}else if(0.2e1 < x){0.2e1 * x}else if(0.3e1 < x){0.3e1 * x}else{0}; 
    ; 
} 

ですlike

{result=x;} 

であり、他のものと類似している。上記のAddFunction文の文字列を変更することで、私はこれを手で行うことができます。しかし、変数名の結果はコードジェネレータには知られていないので、宣言もルーチンのmypやpiecewiseの結果を代入することができるより複雑な手続きと一致するように、結果の値は必要に応じて返されません他の変数に変換したり、計算に使用することができます。ですから、私はCodeGenerationルーチンでこれを適切に扱うにはどうすればよいですか?私。有効な変数名などを取得するにはどうすればいいですか?

答えて

1

どうしてこういうのですか?

restart: 

with(CodeGeneration): 
with(LanguageDefinition): 

LanguageDefinition:-Define("NewC", extend="C", 
    AddFunction("piecewise", anything::numeric, 
     proc() 
      local i; 
      Printer:-Print("((",_passed[1],") ? ",_passed[2]); 
      for i from 3 to _npassed-2 by 2 do 
       Printer:-Print(" : (",_passed[i],") ? ",_passed[i+1]); 
      end do; 
      Printer:-Print(" : ",_passed[_npassed],") "); 
     end proc, 
    numeric=double) 
); 

myp:=proc(x::numeric) local result::numeric; 
    result := piecewise(x>3,3*x,x>2,2*x,x>1,1*x,0); 
end proc: 

Translate(myp, language="NewC"); 

double myp (double x) 
{ 
    double result; 
    result = ((0.3e1 < x) ? 0.3e1 * x : (0.2e1 < x) ? 0.2e1 * x : (0.1e1 < x) ? x : 0) ; 
    return(result); 
} 

これは、コード生成[C]がpiecewiseを処理していることが判明したが、optimizeオプションが提供されている場合のみ、[編集さは、下記の材料を追加します]。 (私はそれがデフォルトで扱われるべきであること、バグレポートを提出します。)

restart: 

with(CodeGeneration): 
with(LanguageDefinition): 
myp:=proc(x::numeric) local result::numeric; 
    result:=piecewise(x>3,3*x,x>2,2*x,x>1,1*x,0); 
end proc; 

     myp := proc(x::numeric) 
     local result::numeric; 
      result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0) 
     end proc; 

Translate(myp, language="C", optimize); 

double myp (double x) 
{ 
    double result; 
    double s1; 
    if (0.3e1 < x) 
    s1 = 0.3e1 * x; 
    else if (0.2e1 < x) 
    s1 = 0.2e1 * x; 
    else if (0.1e1 < x) 
    s1 = x; 
    else 
    s1 = 0.0e0; 
    result = s1; 
    return(result); 
} 

をあなたが見ることができるように、piecewiseを導入し、一時変数に代入して、別のif(){..}ブロックに翻訳することにより、上記処理されます。その一時的な使用は、Mapleプロシージャ内にpiecewiseコールが存在していた場合はいつでも使用されます。一時的に宣言されます。ニースと自動。したがって、piecewiseの使用には十分です。

また、自分の拡張子でこのような一時変数をどのように導入し宣言することができるかを尋ねました(私があなたのことを正しく理解していれば)。上のメイプルセッションと同じように、これらの行に沿ったアイディアがいくつかあります。割り当てられていないグローバル名が生成されます。 mypプロシージャは新しいローカル変数が追加された不活性型になります。そして、その変更された不活性形態は、実際の手順に戻される。例として、元の拡張機能の修正版を使用してpiecewiseを処理しました。これはすべて受け入れられるものの近くに何かを生み出します。唯一の問題は、割り当てステートメントが、

result = temporary_variable; 

であることです。それはpiecewise翻訳ブロックの前にあります。私はまだ方法でそれを修復する方法を見ていない。あなたは上記の最後の3つの文を再実行した場合

LanguageDefinition:-Define("NewC", extend="C", 
    AddFunction("piecewise", anything::numeric, 
     proc() 
      global T; 
      local i, t; 
      t:=convert(T,string); 
      Printer:-Print(t,";\n"); 
      Printer:-Print(" if (",_passed[1], 
          ")\n { ",t," = ",_passed[2],"; }\n"); 
      for i from 3 to _npassed-2 by 2 do 
       Printer:-Print(" else if (",_passed[i],")\n { ", 
           t," = ",_passed[i+1],"; }\n"); 
      end do; 
      Printer:-Print(" else { ",t," = ",_passed[_npassed],"; }"); 
     end proc, 
    numeric=double) 
): 

T:=`tools/genglobal`('s'): 

newmyp := FromInert(subsindets(ToInert(eval(myp)),'specfunc(anything,_Inert_LOCALSEQ)', 
      z->_Inert_LOCALSEQ(op(z), 
           _Inert_DCOLON(_Inert_NAME(convert(T,string)), 
              _Inert_NAME("numeric", 
               _Inert_ATTRIBUTE(_Inert_NAME("protected", 
               _Inert_ATTRIBUTE(_Inert_NAME("protected") 
     )))))))); 

      newmyp := proc(x::numeric) 
      local result::numeric, s::numeric; 
       result := piecewise(3 < x, 3*x, 2 < x, 2*x, 1 < x, x, 0) 
      end proc; 

Translate(newmyp, language="NewC"); 

double newmyp (double x) 
{ 
    double result; 
    double s; 
    result = s; 
    if (0.3e1 < x) 
    { s = 0.3e1 * x; } 
    else if (0.2e1 < x) 
    { s = 0.2e1 * x; } 
    else if (0.1e1 < x) 
    { s = x; } 
    else { s = 0; }; 
    return(result); 
} 

は(割り当てからTに、Translate呼び出しに至るまで)、あなたは、S0として、新たに一時変数が使用されるはずです。そしてもう一度繰り返すならばs1。等々。

おそらく、これはあなたにはもっと多くのアイデアを提供します。乾杯。

+0

これは当然のことながら、おそらく区分的機能のための最良の解決策です。しかし、C言語で関数を評価するために中間計算を行う必要がある一般的なケースでは、私は何ができますか?有効な変数名を取得するにはどうすればよいですか? – highsciguy

関連する問題