代码生成codegen
代碼生成codegen
該模塊提供了從SymPy表達式生成直接可編譯代碼的功能。該codegen功能是SymPy中代碼生成功能的用戶界面。下面為可能希望直接使用框架的高級用戶提供了一些實現(xiàn)細(xì)節(jié)。
注意
該codegen調(diào)用是不是自動在sympy命名空間,必須首先執(zhí)行才能使用
Run code block in SymPy Live
from sympy.utilities.codegen import codegen
實現(xiàn)細(xì)則Implementation Details
介紹了內(nèi)部結(jié)構(gòu)中最重要的部分,因為高級用戶可能希望直接使用。例如,通過為專用應(yīng)用程序?qū)⒋a生成器子類化。 優(yōu)先使用上面記錄的codegen()函數(shù)。
基本假設(shè):
? 常規(guī)數(shù)據(jù)結(jié)構(gòu)描述了必須轉(zhuǎn)換為C / Fortran /…代碼的示例。此數(shù)據(jù)結(jié)構(gòu)涵蓋以一種或多種支持的語言提供的所有功能。
? CodeGen類的擴展將多個Routine實例轉(zhuǎn)換為可編譯代碼。每個派生的類都翻譯成一種特定的語言。
? 在許多情況下,人們想要一個簡單的工作流程。最后一部分中的友函數(shù)是Routine / CodeGen之上的簡單api。它們更易于使用,但功能不那么強大。
示例
Routine類是codegen模塊的重要組成部分。Routine實例將codegen實用程序視為將數(shù)學(xué)表達式轉(zhuǎn)換為編程語言中的一組語句的工具,負(fù)責(zé)提取和存儲有關(guān)如何將數(shù)學(xué)封裝在函數(shù)調(diào)用中的信息。因此,由Routine構(gòu)造函數(shù)決定示例,將需要哪些參數(shù)以及是否應(yīng)該有返回值。
API參考
用于生成計算sympy表達式的C,C ++,Fortran77,Fortran90,Julia,Rust和Octave / Matlab示例的模塊。該模塊正在進行中。以下列表中只有帶有“ +”字符的里程碑已完成。
— sympy.utilities.codegen與sympy.printing.ccode有何不同?—
以擴展Sympy函數(shù)的打印示例的方式來打印完整的可編譯代碼,這會導(dǎo)致一些無法解決的問題,只有使用專用代碼生成器才能解決:
? 對于C語言,需要代碼和頭文件,而打印示例僅生成一個字符串。可以擴展此代碼生成器以支持f2py的.pyf文件。
? SymPy函數(shù)與編程技術(shù)問題無關(guān),例如輸入,輸出和輸入輸出自變量。其它示例是連續(xù)或不連續(xù)的數(shù)組,包括其它庫(例如gsl或其它庫)的including headers。
? 在一個C示例中評估幾個sympy函數(shù),最終在cse示例的幫助下共享共同的中間結(jié)果,這是非常有趣的。這不僅僅是打印。
? 從編程的角度來看,應(yīng)在代碼生成器中盡可能多地評估具有常量的表達式。這與打印不同。
-基本假設(shè)-
? 常規(guī)示例數(shù)據(jù)結(jié)構(gòu)描述了必須轉(zhuǎn)換為C / Fortran /…代碼的示例。此數(shù)據(jù)結(jié)構(gòu)涵蓋以一種或多種支持的語言提供的所有功能。
? CodeGen類的擴展將多個Routine實例轉(zhuǎn)換為可編譯代碼。每個派生的類都翻譯成一種特定的語言。
? 在許多情況下,需要一個簡單的工作流程。最后一部分中的友函數(shù)是Routine / CodeGen之上的簡單api。它們更易于使用,但功能不那么強大。
—里程碑—
? 具有標(biāo)量輸入?yún)?shù)的第一個工作版本,生成C代碼,進行測試
? 友好的功能比嚴(yán)格的Routine / CodeGen工作流程更易于使用。
? 整數(shù)和實數(shù)作為輸入和輸出
? 輸出參數(shù)
? Input Output參數(shù)
? 正確排序輸入/輸出參數(shù)
? 連續(xù)數(shù)組參數(shù)(numpy矩陣)
? 同時為f2py生成.pyf代碼(在自動包裝模塊中)
? 隔離常數(shù)并事先以雙精度對其求值
? Fortran 90
? Octave/Matlab
? 常見子表達消除
? 用戶定義的注釋在生成的代碼中
? 可選的依賴包含行,可以評估特殊功能的庫/對象
? 測試其它C編譯器和庫:gcc,tcc,libtcc,gcc + gsl等
? 連續(xù)數(shù)組參數(shù)(對稱矩陣)
? 非連續(xù)數(shù)組參數(shù)(對稱矩陣)
? 當(dāng)ccode遇到無法翻譯為c的內(nèi)容時,必須引發(fā)錯誤。ccode(integrate(sin(x)/ x,x))沒有意義。
? 復(fù)數(shù)作為輸入和輸出
? 默認(rèn)的復(fù)雜數(shù)據(jù)類型
? Include中包含其它信息:日期,用戶,主機名,sha1哈希,…
? Fortran 77
? C ++
? Python
? Julia
? Rust
? …
class sympy.utilities.codegen.Argument(name, datatype=None, dimensions=None, precision=None)
抽象的Argument數(shù)據(jù)結(jié)構(gòu):名稱和數(shù)據(jù)類型。
下面的擴展對這種結(jié)構(gòu)進行了改進。
class sympy.utilities.codegen.CCodeGen(project=‘project’, printer=None, preprocessor_statements=None, cse=False)
C代碼生成器。
從CodeGen繼承的.write()方法,將分別輸出代碼文件和接口文件 .c和 .h。
dump_c(routines, f, prefix, header=True, empty=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
dump_h(routines, f, prefix, header=True, empty=True)
寫入C頭文件。
該文件包含所有函數(shù)聲明。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于構(gòu)造包含include guards保護。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
get_prototype(常規(guī))
返回該示例的函數(shù)原型的字符串。
如果示例具有多個結(jié)果對象,則會引發(fā)CodeGenError。
請參閱:https://en.wikipedia.org/wiki/Function_prototype
class sympy.utilities.codegen.CodeGen(project=‘project’, cse=False)
代碼生成器的抽象類。
dump_code(routines, f, prefix, header=True, empty=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
routine(name, expr, argument_sequence=None, global_vars=None)
創(chuàng)建適合該語言的Routine對象。
此實現(xiàn)至少適用于C / Fortran。如有必要,子類可以覆蓋此方法。
假設(shè)最多有一個返回值(l值),必須是標(biāo)量。其它輸出是OutputArguments(例如,右側(cè)的指針或通過引用的指針)。矩陣始終通過OutputArguments返回。如果argument_sequence為None,則參數(shù)將按字母順序排序,但所有InputArguments排第一,然后是OutputArgument和InOutArguments。
write(routines, prefix, to_files=False, header=True, empty=True)
編寫給定示例的所有源代碼文件。
生成的源作為(文件名,內(nèi)容)元組的列表返回,或?qū)懭胛募?#xff08;請參見下文)。每個文件名都由給定的前綴組成,并附加適當(dāng)?shù)臄U展名。
參量
示例:列表
要編寫的示例實例列表
前綴:字符串
輸出文件的前綴
to_files:布爾值,可選
為True時,輸出將寫入文件。否則,將返回(文件名,內(nèi)容)元組的列表。[默認(rèn)值:False]
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn)值:True]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn)值:True]
class sympy.utilities.codegen.DataType(cname, fname, pyname, jlname, octname, rsname)
以不同的語言保存某個數(shù)據(jù)類型的字符串。
class sympy.utilities.codegen.FCodeGen(project=‘project’, printer=None)
Fortran 95代碼生成器
從CodeGen繼承的.write()方法將分別輸出代碼文件和接口文件 .f90和 .h。
dump_f95(routines, f, prefix, header=True, empty=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
dump_h(routines, f, prefix, header=True, empty=True)
將接口寫入頭文件。
該文件包含所有函數(shù)聲明。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
get_interface(常規(guī))
返回函數(shù)接口的字符串。
該示例應(yīng)具有單個結(jié)果對象,該對象可以為None。如果示例具有多個結(jié)果對象,則會引發(fā)CodeGenError。
請參閱:https://en.wikipedia.org/wiki/Function_prototype
class sympy.utilities.codegen.JuliaCodeGen(project=‘project’, printer=None)
從CodeGen繼承的.write()方法將輸出代碼文件 .jl。
dump_jl(routines, f, prefix, header=True, empty=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
routine(name, expr, argument_sequence, global_vars)
專為Julia創(chuàng)建例行程序。
class sympy.utilities.codegen.OctaveCodeGen(project=‘project’, printer=None)
從CodeGen繼承的.write()方法將輸出代碼文件 .m。
octave.m文件通常包含一個功能。該函數(shù)名稱應(yīng)與文件名(prefix)相匹配。如果傳遞多個name_expr對,則假定后者是由主函數(shù)訪問的私有函數(shù)。
只應(yīng)將輸入傳遞給argument_sequence:輸出按照name_expr中的順序排列。
dump_m(routines, f, prefix, header=True, empty=True, inline=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
routine(name, expr, argument_sequence, global_vars)
octave的專業(yè)示例創(chuàng)建。
class sympy.utilities.codegen.OutputArgument(name, result_var, expr, datatype=None, dimensions=None, precision=None)
OutputArgument總是在示例中初始化。
class sympy.utilities.codegen.Result(expr, name=None, result_var=None, datatype=None, dimensions=None, precision=None)
返回值的表達式。
名稱結(jié)果用于避免與python語言中的保留字“ return”發(fā)生沖突。也比ReturnValue短。
可能在目標(biāo)中也可能不需要名稱(例如,“ return(x * y)”可能會返回一個值而無需命名)。
class sympy.utilities.codegen.Routine(name, arguments, results, local_vars, global_vars)
表達式集的評估示例的一般描述。
CodeGen類可以將此類的實例轉(zhuǎn)換為特定語言的代碼。常規(guī)規(guī)范涵蓋了這些語言中存在的所有功能。當(dāng)目標(biāo)語言中不存在某些功能時,CodeGen部分必須引發(fā)異常。例如,在Python中可能有多個返回值,但在C或Fortran中卻沒有。另一個示例:Fortran和Python支持復(fù)數(shù),而C不支持。
屬性result_variables
返回OutputArgument,InOutArgument和Result的列表。
如果存在返回值,則它們將位于列表的末尾。
屬性variables
返回示例中可能使用的所有變量的集合。
對于具有未命名返回值的示例,可能使用或可能不使用的虛擬變量將包括在該集合中。
class sympy.utilities.codegen.RustCodeGen(project=‘project’, printer=None)
Rust代碼生成器。
從CodeGen繼承的.write()方法將輸出代碼文件 .rs
dump_rs(routines, f, prefix, header=True, empty=True)
通過調(diào)用特定于語言的方法來編寫代碼。
生成的文件以低級代碼包含示例的所有定義,并在適當(dāng)時引用頭文件。
參量
示例:列表
示例實例列表。
f:類似文件
在哪里寫文件。
前綴:字符串
文件名前綴,用于引用正確的頭文件。僅使用前綴的基本名稱。
header頭:布爾值,可選
如果為True,則在每個源文件的頂部包含標(biāo)題注釋。[默認(rèn):正確]
空:布爾值,可選
如果為True,則包含空行以構(gòu)造源文件。[默認(rèn):正確]
get_prototype(常規(guī))
返回該示例的函數(shù)原型的字符串。
如果示例具有多個結(jié)果對象,則會引發(fā)CodeGenError。
請參閱:https://en.wikipedia.org/wiki/Function_prototype
routine(name, expr, argument_sequence, global_vars)[source]
Rust的常規(guī)程序創(chuàng)建。
sympy.utilities.codegen.codegen(name_expr, language=None, prefix=None, project=‘project’, to_files=False, header=True, empty=True, argument_sequence=None, global_vars=None, standard=None, code_gen=None, printer=None)
為給定語言的表達式生成源代碼。
參量
name_expr:元組或元組列表
一個(名稱,表達式)元組或(名稱,表達式)元組列表。每個元組對應(yīng)一個示例。如果表達式是等式(Equal類的實例),則將左側(cè)視為輸出參數(shù)。如果expression是可迭代的,則該示例將具有多個輸出。
語言:字符串,
指示源代碼語言的字符串。這是不區(qū)分大小寫的。當(dāng)前,支持“ C”,“ F95”和“Octave”。“ Octave”生成與Octave和Matlab兼容的代碼。
prefix:字符串,可選
包含源代碼的文件名的前綴。與語言相關(guān)的后綴將被附加。如果省略,則使用第一個name_expr元組的名稱。
項目:字符串,可選
項目名稱,用于制作唯一的預(yù)處理程序指令。[默認(rèn):“項目”]
to_files:布爾值,可選
當(dāng)為True時,代碼將被寫入具有給定前綴的一個或多個文件,否則返回具有這些文件的名稱和內(nèi)容的字符串。[默認(rèn)值:False]
標(biāo)頭:布爾值,可選
如果為True,則將標(biāo)頭寫入每個源文件的頂部。[默認(rèn)值:True]
空:布爾值,可選
如果為True,則使用空行來構(gòu)造代碼。[默認(rèn)值:True]
arguments_sequence:可迭代,可選
示例的參數(shù)序列按首選順序排列。如果缺少必需的參數(shù),則會引發(fā)CodeGenError。使用冗余參數(shù)時不會發(fā)出警告。如果省略,則參數(shù)將按字母順序排序,但所有輸入?yún)?shù)都將首先排列,然后是輸出或輸入-輸出參數(shù)。
global_vars:可迭代,可選
示例使用的全局變量序列。此處列出的變量不會顯示為函數(shù)參數(shù)。
標(biāo)準(zhǔn):字符串
code_gen:CodeGen實例
CodeGen子類的實例。覆蓋language。
示例
Run code block in SymPy Livefrom sympy.utilities.codegen import codegen
from sympy.abc import x, y, z
[(c_name, c_code), (h_name, c_header)] = codegen(
… (“f”, x+y*z), “C89”, “test”, header=False, empty=False)print(c_name)
test.cprint(c_code)
#include “test.h”
#include <math.h>
double f(double x, double y, double z) {
double f_result;
f_result = x + y*z;
return f_result;
}
print(h_name)
test.hprint(c_header)
#ifndef PROJECT__TEST__H
#define PROJECT__TEST__H
double f(double x, double y, double z);
#endif
使用Equality對象提供命名輸出的另一個示例。這里的文件名(前綴)取自first (name, expr)。
Run code block in SymPy Livefrom sympy.abc import f, g
from sympy import Eq
[(c_name, c_code), (h_name, c_header)] = codegen(
… [(“myfcn”, x + y), (“fcn2”, [Eq(f, 2*x), Eq(g, y)])],
… “C99”, header=False, empty=False)print(c_name)
myfcn.cprint(c_code)
#include “myfcn.h”
#include <math.h>
double myfcn(double x, double y) {
double myfcn_result;
myfcn_result = x + y;
return myfcn_result;
}
void fcn2(double x, double y, double *f, double *g) {
(f) = 2x;
(*g) = y;
}
如果生成的函數(shù)將是已定義各種全局變量的較大項目的一部分,則可以使用’global_vars’選項從函數(shù)簽名中刪除指定的變量
Run code block in SymPy Livefrom sympy.utilities.codegen import codegen
from sympy.abc import x, y, z
[(f_name, f_code), header] = codegen(
… (“f”, x+y*z), “F95”, header=False, empty=False,
… argument_sequence=(x, y), global_vars=(z,))print(f_code)
REAL8 function f(x, y)
implicit none
REAL8, intent(in) :: x
REAL8, intent(in) :: y
f = x + yz
end function
sympy.utilities.codegen.get_default_datatype(expr, complex_allowed=None)
根據(jù)表達式得出適當(dāng)?shù)臄?shù)據(jù)類型。
sympy.utilities.codegen.make_routine(name, expr, argument_sequence=None, global_vars=None, language=‘F95’)
通過表達式生成適當(dāng)示例的factory。
參量
名稱:字符串
生成的代碼中此示例的名稱。
expr:表達式或表達式列表/元組
Routine實例將代表的SymPy表達式。如果給定表達式列表或元組,則該示例將被視為具有多個返回值和/或輸出參數(shù)。
arguments_sequence:列表或元組,可選
以首選順序列出示例的參數(shù)。如果省略,則結(jié)果取決于語言,例如,字母順序或與給定表達式相同的順序。
global_vars:可迭代,可選
示例使用的全局變量序列。此處列出的變量不會顯示為函數(shù)參數(shù)。
語言:字符串,可選
指定目標(biāo)語言。示例本身應(yīng)該與語言無關(guān),但是創(chuàng)建示例的確切方式,錯誤檢查等取決于語言。[默認(rèn)值:“ F95”]。
決定是否使用輸出參數(shù)或返回值
取決于語言和特定的數(shù)學(xué)表達式。
對于Equality類型的表達式,通常制作左側(cè)
放入一個OutputArgument(或一個InOutArgument,如果合適的話)。
否則,通常使計算出的表達式的返回值為
routine程序。
示例
Run code block in SymPy Livefrom sympy.utilities.codegen import make_routine
from sympy.abc import x, y, f, g
from sympy import Eq
r = make_routine(‘test’, [Eq(f, 2*x), Eq(g, x + y)])
[arg.result_var for arg in r.results]
[][arg.name for arg in r.arguments]
[x, y, f, g][arg.name for arg in r.result_variables]
[f, g]r.local_vars
set()
另一個更復(fù)雜的示例,其中包含指定名稱和自動分配的名稱。還具有矩陣輸出。
Run code block in SymPy Livefrom sympy import Matrix
r = make_routine(‘fcn’, [x*y, Eq(f, 1), Eq(g, x + g), Matrix([[x, 2]])])
[arg.result_var for arg in r.results]
[result_5397460570204848505][arg.expr for arg in r.results]
[x*y][arg.name for arg in r.arguments]
[x, y, f, g, out_8598435338387848786]
可以更仔細(xì)地研究各種論點:
Run code block in SymPy Livefrom sympy.utilities.codegen import (InputArgument, OutputArgument,
… InOutArgument)[a.name for a in r.arguments if isinstance(a, InputArgument)]
[x, y]
Run code block in SymPy Live[a.name for a in r.arguments if isinstance(a, OutputArgument)]
[f, out_8598435338387848786][a.expr for a in r.arguments if isinstance(a, OutputArgument)]
[1, Matrix([[x, 2]])]
Run code block in SymPy Live[a.name for a in r.arguments if isinstance(a, InOutArgument)]
[g][a.expr for a in r.arguments if isinstance(a, InOutArgument)]
[g + x]
總結(jié)
以上是生活随笔為你收集整理的代码生成codegen的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Tensorize评估硬件内部特性
- 下一篇: nvGRAPH原理概述