0

区分関数のハンドラーによって Maple CodeGeneration[C] を拡張したいと考えています (なぜ含まれていないのかわかりません)。この目的のために、私は次のことを行いました:

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)
);

意図的に case ステートメントを優先して if else ステートメントを使用していることに注意してください。翻訳するコードの例を次に示します。

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

出力は

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};
    ;
}

有効な C ルーチンの場合、明らかに中かっこを次のように置き換える必要があります

{x}

のようなもので

{result=x;}

他のものも同様です。上記の AddFunction ステートメントの文字列を変更することで、手動でこれを行うことができます。ただし、変数名の結果はコード ジェネレーターには認識されないため、宣言は行われず、必要に応じて結果の値が返されず、ルーチン myp や、piecewise の結果が代入される可能性のあるより複雑な手順に一致することもありません。他の変数に、または計算で使用されます。では、CodeGeneration ルーチンでこれを適切に処理するにはどうすればよいでしょうか。つまり、有効な変数名などを取得するにはどうすればよいですか?

4

1 に答える 1

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);
}

[編集、以下の資料を追加]

CodeGeneration[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(){..}その一時的なものは、piecewise呼び出しが Maple プロシージャ内に存在する場所で使用されます。そして、一時が宣言されます。素敵で自動。の使用にはそれで十分かもしれませんpiecewise

また、独自の拡張機能でそのような一時変数を導入して宣言する方法も尋ねました (私が正しく理解している場合)。上記の同じ Maple セッションを続けて、これらの線に沿ったいくつかのアイデアを次に示します。割り当てられていないグローバル名が生成されます。プロシージャはmypinert 形式になり、そこに新しいローカル変数が追加されます。そして、その変更された不活性フォームが実際の手順に戻されます。例として、元の拡張機能の修正版を使用して を処理しpiecewiseました。これにより、許容範囲に近いものが生成されます。唯一の問題は、代入ステートメント、

result = temporary_variable;

場違いです!piecewise翻訳ブロックの前にあります。メソッドでそれを修復する方法はまだわかりません。

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);
}

上記の最後の 3 つのステートメント (への代入から呼び出しまで) を再実行するとTTranslates0 などの新しい一時変数が使用されていることがわかります。そして、もう一度繰り返される場合は s1 。等々。

おそらく、これにより、作業するためのいくつかのアイデアが得られるでしょう。乾杯。

于 2012-04-10T05:41:09.330 に答える