2012-04-08 9 views
0

Ich möchte die Maple CodeGeneration [C] von einem Handler für die stückweise Funktion (keine Ahnung, warum es nicht enthalten ist) zu erweitern. Zu diesem Zweck hat mich:Variablennamen in erweiternde Maple-Code-Generation

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

Bitte beachte, dass ich, wenn sonst Aussagen über puropose für Case-Anweisungen verwenden. Hier ist ein Beispiel-Code zu übersetzen:

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

Der Ausgang

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

Für eine gültige C-Routine, die ich natürlich müssen die geschweiften Klammern wie

{x} 

durch etwas ersetzen, wie

{result=x;} 

und analog für die anderen. Ich könnte dies manuell tun, indem ich die Strings in der obigen AddFunction-Anweisung ändere. Aber dann ist das Ergebnis des Variablennamens dem Codegenerator nicht bekannt, daher gibt es keine Deklaration, noch wird der Wert von result zurückgegeben, um der Routine myp oder einer komplizierteren Prozedur, in der das Ergebnis stückweise zugewiesen werden kann, zu entsprechen zu einer anderen Variablen oder in Berechnungen verwendet. Wie behandle ich das in den CodeGeneration Routinen richtig? I.e. Wie kann ich einen gültigen Variablennamen usw. erhalten?

Antwort

1

Wie wäre es mit so etwas?

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

Es stellt sich heraus, dass Codegenerierung [C] [bearbeitet, um das Material zum hinzufügen] piecewise tut verarbeiten, aber nur, wenn die optimize Option geliefert wird. (Ich werde einen Fehlerbericht einreichen, dass sie standardmäßig behandelt werden soll.)

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

Wie Sie sehen können, ist piecewise behandelt oben durch Übersetzung in einen separaten if(){..} Block, mit Zuordnung zu einem eingeführt temporären Variable. Dieses Temporär wird anschließend überall dort verwendet, wo der Aufruf piecewise in der Maple-Prozedur existiert. Und das temporäre wird erklärt. Nett und automatisch. So könnte das für Ihre Verwendung von piecewise ausreichen.

Sie haben auch gefragt, wie Sie solche temporären Variablen in Ihren eigenen Erweiterungen einführen und deklarieren könnten (wenn ich Sie richtig verstehe). In der gleichen Maple-Session von oben fortgefahren, hier sind einige Ideen in dieser Richtung. Ein nicht zugewiesener globaler Name wird generiert. Die Prozedur myp wird in eine inerte Form gebracht, zu der die neue lokale Variable hinzugefügt wird. Und dann wird diese veränderte inerte Form wieder zu einem tatsächlichen Vorgang gemacht. Zur Veranschaulichung habe ich eine modifizierte Version Ihrer ursprünglichen Erweiterung verwendet, um piecewise zu behandeln. Dies alles erzeugt etwas, das nahezu akzeptabel ist. Der einzige Haken ist, dass die Zuweisungsanweisung,

result = temporary_variable; 

ist fehl am Platz! Es liegt vor dem piecewise Übersetzungsblock. Ich sehe noch nicht, wie ich das in der Methode reparieren kann.

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

Wenn Sie die letzten drei Aussagen über (aus der Zuordnung zu T, bis zum Translate Anruf) erneut ausführen, dann sollten Sie eine neue temporäre Variable verwendet, wie s0 sehen. Und dann s1 wenn noch einmal wiederholt. Und so weiter.

Vielleicht gibt Ihnen das mehr Ideen, mit denen Sie arbeiten können. Prost.

+0

Dies funktioniert natürlich und ist wahrscheinlich die beste Lösung für die stückweise Funktion. Aber was kann ich im allgemeinen Fall tun, wo ich einige Zwischenberechnungen machen muss, um eine Funktion in der C-Sprache zu bewerten? Wie kann ich gültige Variablennamen erhalten? – highsciguy