K iAzdZddlZddlZddlZddlZddlmZddlmZm Z m Z ddl m Z ddl mZddlmZddlmZdd lmZdd lmZmZdd lmZmZdd lmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$dd l%m&Z&ddl'm(Z(ddl)m*Z*dddZ+Gdde,Z-GddZ.Gdde.Z/Gdde.Z0Gdde.Z1dddddZ2d Z3d!Z4ee*d"d d.d#Z5e*d"dd$Z6e d%Z7e d&Z8e d'Z9e d(Z:e d)Z;e d*Z<Gd+d,e.Z=ee*dd d/d-Z>y)0aR Module for compiling codegen output, and wrap the binary for use in python. .. note:: To use the autowrap module it must first be imported >>> from sympy.utilities.autowrap import autowrap This module provides a common interface for different external backends, such as f2py, fwrap, Cython, SWIG(?) etc. (Currently only f2py and Cython are implemented) The goal is to provide access to compiled binaries of acceptable performance with a one-button user interface, e.g., >>> from sympy.abc import x,y >>> expr = (x - y)**25 >>> flat = expr.expand() >>> binary_callable = autowrap(flat) >>> binary_callable(2, 3) -1.0 Although a SymPy user might primarily be interested in working with mathematical expressions and not in the details of wrapping tools needed to evaluate such expressions efficiently in numerical form, the user cannot do so without some understanding of the limits in the target language. For example, the expanded expression contains large coefficients which result in loss of precision when computing the expression: >>> binary_callable(3, 2) 0.0 >>> binary_callable(4, 5), binary_callable(5, 4) (-22925376.0, 25165824.0) Wrapping the unexpanded expression gives the expected behavior: >>> e = autowrap(expr) >>> e(4, 5), e(5, 4) (-1.0, 1.0) The callable returned from autowrap() is a binary Python function, not a SymPy object. If it is desired to use the compiled function in symbolic expressions, it is better to use binary_function() which returns a SymPy Function object. The binary callable is attached as the _imp_ attribute and invoked when a numerical evaluation is requested with evalf(), or with lambdify(). >>> from sympy.utilities.autowrap import binary_function >>> f = binary_function('f', expr) >>> 2*f(x, y) + y y + 2*f(x, y) >>> (2*f(x, y) + y).evalf(2, subs={x: 1, y:2}) 0.e-110 When is this useful? 1) For computations on large arrays, Python iterations may be too slow, and depending on the mathematical expression, it may be difficult to exploit the advanced index operations provided by NumPy. 2) For *really* long expressions that will be called repeatedly, the compiled binary should be significantly faster than SymPy's .evalf() 3) If you are generating code with the codegen utility in order to use it in another project, the automatic Python wrappers let you test the binaries immediately from within SymPy. 4) To create customized ufuncs for use with numpy arrays. See *ufuncify*. When is this module NOT the best approach? 1) If you are really concerned about speed or memory optimizations, you will probably get better results by working directly with the wrapper tools and the low level code. However, the files generated by this utility may provide a useful starting point and reference code. Temporary files will be left intact if you supply the keyword tempdir="path/to/files/". 2) If the array computation can be handled easily by numpy, and you do not need the binaries for another project. N)Path)STDOUTCalledProcessError check_output)Template)warn)cacheit)Lambda)Eq)DummySymbol)Idx IndexedBase) make_routineget_code_generatorOutputArgument InOutArgument InputArgumentCodeGenArgumentListErrorResult ResultBase C99CodeGen)iterable)implemented_function)doctest_depends_on)f2pygfortrangcc)numpy)exemodulesc eZdZy) CodeWrapErrorN)__name__ __module__ __qualname__^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/utilities/autowrap.pyr#r#msr(r#c~eZdZdZdZdZdZedZedZ dgdfd Z ed Z ed Z d Z dd ZdZy) CodeWrapperzBase Class for code wrappers wrapped_codewrapper_modulerc@|jdtjSN_) _filenamer+_module_counterselfs r)filenamezCodeWrapper.filenamews..+*E*EFFr(c@|jdtjSr/)_module_basenamer+r2r3s r) module_namezCodeWrapper.module_name{s//1L1LMMr(NFc>||_||_||_| |_y)z8 generator -- the code generator to use N) generatorfilepathflagsquiet)r4r:r;r<verboses r)__init__zCodeWrapper.__init__s"#    [ r(c,t|jSNboolr;r3s r)include_headerzCodeWrapper.include_headerDMM""r(c,t|jSrArBr3s r) include_emptyzCodeWrapper.include_emptyrEr(c|j||jj||jd|j|j yNT)appendr:writer5rDrG)r4 main_routineroutiness r)_generate_codezCodeWrapper._generate_codes< %  dmmT4+>+>    r(cv|xsg}|jr*tjj|j}nt j d}tj |tjstj|tj}tj| tjj||j|||j||j|t!|j"}tjj%|t&xj(dz c_tj||js t+j,||j1||j2S#t.$rY'wxYw#tjj%|t&xj(dz c_tj||js& t+j,|w#t.$rYwwxYwwxYw)N_sympy_compile)r;ospathabspathtempfilemkdtempaccessF_OKmkdirgetcwdchdirsysrJrN_prepare_files_process_files __import__r8remover+r2shutilrmtreeOSError_get_wrapped_functionname)r4routinehelpersworkdiroldworkmods r) wrap_codezCodeWrapper.wrap_codes-R ==ggoodmm4G&&'78Gyy"''* HHW ))+   HHOOG $    1    (    (T--.C HHOOG $  ' '1 , ' HHW ==MM'* ))#w||<<  HHOOG $  ' '1 , ' HHW ==MM'*!sD5A(F77F(( F43F47AH8H('H8( H41H83H44H8c :|j}|j|j t|t}|js t|yy#t $r>}t ddj|d|jjdd}~wwxYw)N)stderrzError while executing command:  z. Command output is: zutf-8) commandextendr<rrrr#joinoutputdecoder=print)r4rfro retoutputes r)r^zCodeWrapper._process_filess,,tzz" B$WVz-DummyWrapper._generate_code..s >)#%#r(nameless)reexprargsretvals)endfile)openr8rqresult_variablesstrrfilter argumentsrrrJ result_varrtrztemplatere) r4rfrgfresprintedrrvalas r)rNzDummyWrapper._generate_codes* 'D,,,c 2 aii*1*B*BC3SXXCEG#$+$5$57DG// 3c6*NN:.NN3>>2  3 ,''  "=13qvv;"=>99'%B3c#h%BC + A    C#>%B#  s5EE BE-E EE0E EE#cyrAr'r|s r)r^zDummyWrapper._process_filesr}r(ct||SrAgetattrclsrjres r)rdz"DummyWrapper._get_wrapped_functionsD!!r(N) r$r%r&rwrr]rNr^ classmethodrdr'r(r)rzrzs/9H*""r(rzceZdZdZdZdddiiZdZdZdZd Z fd Z e d Z e jfd Zed ZdZdZdZdZdZdZxZS)CythonCodeWrapperzWrapper that uses Cythonafrom setuptools import setup from setuptools import Extension from Cython.Build import cythonize cy_opts = {cythonize_options} {np_import} ext_mods = [Extension( {ext_args}, include_dirs={include_dirs}, library_dirs={library_dirs}, libraries={libraries}, extra_compile_args={extra_compile_args}, extra_link_args={extra_link_args} )] setup(ext_modules=cythonize(ext_mods, **cy_opts)) compiler_directiveslanguage_level3z(import numpy as np cimport numpy as np z5cdef extern from '{header_file}.h': {prototype} z1def {name}_c({arg_string}): {declarations}{body}z-std=c99c|jdg|_|jdg|_|jdg|_|jdg|_|jj |j |jdg|_|jd|j|_d|_ t|,|i|y) aInstantiates a Cython code wrapper. The following optional parameters get passed to ``setuptools.Extension`` for building the Python extension module. Read its documentation to learn more. Parameters ========== include_dirs : [list of strings] A list of directories to search for C/C++ header files (in Unix form for portability). library_dirs : [list of strings] A list of directories to search for C/C++ libraries at link time. libraries : [list of strings] A list of library names (not filenames or paths) to link against. extra_compile_args : [list of strings] Any extra platform- and compiler-specific information to use when compiling the source files in 'sources'. For platforms and compilers where "command line" makes sense, this is typically a list of command-line arguments, but for other platforms it could be anything. Note that the attribute ``std_compile_flag`` will be appended to this list. extra_link_args : [list of strings] Any extra platform- and compiler-specific information to use when linking object files together to create the extension (or to create a new static Python interpreter). Similar interpretation as for 'extra_compile_args'. cythonize_options : [dictionary] Keyword arguments passed on to cythonize. include_dirs library_dirs librariesextra_compile_argsextra_link_argscythonize_optionsFN) pop _include_dirs _library_dirs _libraries_extra_compile_argsrJstd_compile_flag_extra_link_args_cythonize_options _need_numpysuperr?)r4rkwargs __class__s r)r?zCythonCodeWrapper.__init__sB$ZZ;#ZZ; **["5#)::.BB#G    ''(=(=> & +>:{KHr(c F|jdz}|jd|jj}t t j j||d5}|j|g||jdddt|jt||gg}|jrd}|jjdnd}t|jjdd}|jj!dj||||j"|j$|j&|j(|j* } t-t j j|d j/| y#1swYxYw) Nz.pyx.rzimport numpy as np znp.get_include()rz'np.get_include()'r)ext_args np_importrrrrrrr)r8r5r:code_extensionrrRrSrqdump_pyxreprrrrJrreplacesetup_templateformatrrrrrr write_text) r4rf build_dir pyxfilename codefilenamerrrincludescodes r)r]z CythonCodeWrapper._prepare_filesBsY&&/ "&--1N1NO "'',,y+6 < 7 MM7)Q 6 7))*D+|1L,MN   .I    % %&8 9It))*223G4FH""))8,#%!////#'#;#; $ 5 5"&"9"9*; RWW\\)Z 01<z-CythonCodeWrapper.dump_pyx..s"O4#6#6s#;"Osz cdef {} = {}.shape[{}]z cdef {} z return ()z z) )re arg_string declarationsbodyN)r: get_prototyperJ pyx_headerr_partition_argsrrerqitemsr _string_varrp _declare_arg _call_argresultspyx_funcrrK pyx_imports)r4rMrprefixheaders functionsrfrpy_retspy_argspy_locpy_infrer local_decsrrprotovmatindrrargs_crretsrs` r)rzCythonCodeWrapper.dump_pyxds}  % ;G44W=I NN4??11f"E"EeSRU"VW X   SYZa}33D4E4Ea4HIZ [99Z0L+d2 YY7;L;LMaq 1MNF99H1d..qvv6HID.5llFC$;-D *1v>m+d2   T]]11t !-D2: ;I% ;P    GGD$$ %  '"#  )$%5>Z NHsJ+'J0 6J5 $"J: c g}g}g}i}|D]}t|tr#|j||j|nDt|tr#|j||j|n|j|t|ttfs|j s|j Dcgc] }|ddz }}t |D cgc]\} }t|tr| |f} } }| D]\} }|j| f||< |D]/}|j|vs|j|j||<1|D cgc] } | |vs|  }} ||||fScc}wcc}} wcc} w))Group function arguments into categories.rQ) rrrJrr dimensions enumerater rer) r4rr py_returns py_locals py_inferredrddimsisym_dimsrs r)rz!CythonCodeWrapper._partition_argssu    3C#~.!!#&  %C/!!#&s#s## }=>3>>*-..9Q!q991:43v1&q&1F33&3FQ&)hh]KN3 3" =Cxx;&#.??388#< C  =&>+)=1>>7I{:::3?s8E$E) E/E/c&d}ddd}|jd}|jrNd|_t|j}||}|j |||j |j S|d|j |j S) Nz'np.ndarray[{mtype}, ndim={ndim}] {name}z np.double_tznp.int_t)doubleintcT)mtypendimrern) get_datatyperrlenrrre)r4rmat_decnp_typestr rs r)rz CythonCodeWrapper._prototype_args;+%'   S ! >>#D s~~&DQKE>>Dt?O?OPSPXPX?Y>Z Z!1!1#((!;< .s$"V!4#3#3AaD1H#="Vs!$rz = np.empty({shape}))shapez = 0)rrrqr)r4rrrs` r)rzCythonCodeWrapper._declare_argsa##C( >>#(("Vs~~"VVVY\\E188u8EE E6> !r(c<|jr<|jd}dj||j|jSt |t r*dj|j|jS|j|jS)Nrz <{}*> {}.dataz&{})rr rrrerr)r4rrs r)rzCythonCodeWrapper._call_argsx >>  %A"))!T-=-=chh-GH H Z (<< 0 0 :; ;##CHH- -r(cR|jjj}||SrA)r:printerdoprint)r4varrs r)rzCythonCodeWrapper._string_vars!..((00s|r()r$r%r&rwrrrrrrr?rxrorRcurdirr]rrdrrrrrr __classcell__rs@r)rrs"N"01AC0HI "     "+*Z13 C<))>&@;< =".r(rcHeZdZdZfdZedZdZedZ xZ S)F2PyCodeWrapperzWrapper that uses f2pycgd}d}|D]@}||jvrt|j||j|dBt ||i|y)NrrrrrzGThe compilation option kwarg {} is not supported with the f2py backend.keysrrrrr?r4rrext_keysmsgkrs r)r?zF2PyCodeWrapper.__init__sb= AFKKM!SZZ]# JJq$  $)&)r(c|jdz|jjz}dd|j|g}tj ddg|z}|S)Nrz-cz-mz)import numpy.f2py as f2py2e;f2py2e.main())r5r:rr8r\r)r4r5rros r)rozF2PyCodeWrapper.commandsO==3&)F)FFdD,,h7>>4)TUVZZr(cyrAr'r|s r)r]zF2PyCodeWrapper._prepare_filess r(ct||SrArrs r)rdz%F2PyCodeWrapper._get_wrapped_functionrr() r$r%r&rwr?rxror]rrdrrs@r)rrs8  *  ""r(r)C99C89C)F95)CYTHONF2PYNUMPYDUMMYcttj|jd}|std|z|dS)z6For a given backend, return the top choice of languageFUnrecognized backend: r) _lang_lookupgetupper ValueError)backendlangss r)_infer_languager8s7   W]]_e 4E 1G;<< 8Or(ctj|jd}|std|z|j|vrtdj ||y)z5Throws error if backend and language are incompatibleFr1z+Backend {} and language {} are incompatibleN)r2r3r4r5r)r6languager7s r)_validate_backend_languager;sb   W]]_e 4E 1G;<<~~u$)*0&(*CE E%r()rrc  |rt|tst||n t|}t |r#t |dk7rt |dr|r|nd}n|r|gnd}t |t r t|n|}| t|d}tttd|j} | |||r|nd|fi| } g} |D](\} }}| j|j| ||*|D];\} }}|j|st!| |d} |j#|| |}= |jd ||}| j-|| S#t$$r_}g}|j&D].}t|t(s|j|j*0|jd |||z}Yd}~vd}~wwxYw) a8Generates Python callable binaries based on the math expression. Parameters ========== expr The SymPy expression that should be wrapped as a binary routine. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'f2py' [default], or 'cython'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. args : iterable, optional An ordered iterable of symbols. Specifies the argument sequence for the function. flags : iterable, optional Additional option flags that will be passed to the backend. verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : 3-tuple or iterable of 3-tuples, optional Used to define auxiliary functions needed for the main expression. Each tuple should be of the form (name, expr, args) where: - name : str, the function name - expr : sympy expression, the function - args : iterable, the function arguments (can be any iterable of symbols) code_gen : CodeGen instance An instance of a CodeGen subclass. Overrides ``language``. include_dirs : [string] A list of directories to search for C/C++ header files (in Unix form for portability). library_dirs : [string] A list of directories to search for C/C++ libraries at link time. libraries : [string] A list of library names (not filenames or paths) to link against. extra_compile_args : [string] Any extra platform- and compiler-specific information to use when compiling the source files in 'sources'. For platforms and compilers where "command line" makes sense, this is typically a list of command-line arguments, but for other platforms it could be anything. extra_link_args : [string] Any extra platform- and compiler-specific information to use when linking object files together to create the extension (or to create a new static Python interpreter). Similar interpretation as for 'extra_compile_args'. Examples ======== Basic usage: >>> from sympy.abc import x, y, z >>> from sympy.utilities.autowrap import autowrap >>> expr = ((x - y + z)**(13)).expand() >>> binary_func = autowrap(expr) >>> binary_func(1, 4, 2) -1.0 Using helper functions: >>> from sympy.abc import x, t >>> from sympy import Function >>> helper_func = Function('helper_func') # Define symbolic function >>> expr = 3*x + helper_func(t) # Main expression using helper function >>> # Define helper_func(x) = 4*x using f2py backend >>> binary_func = autowrap(expr, args=[x, t], ... helpers=('helper_func', 4*x, [x])) >>> binary_func(2, 5) # 3*2 + helper_func(5) = 6 + 20 26.0 >>> # Same example using cython backend >>> binary_func = autowrap(expr, args=[x, t], backend='cython', ... helpers=[('helper_func', 4*x, [x])]) >>> binary_func(2, 5) # 3*2 + helper_func(5) = 6 + 20 26.0 Type handling example: >>> import numpy as np >>> expr = x + y >>> f_cython = autowrap(expr, backend='cython') >>> f_cython(1, 2) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(np.array([1.0]), np.array([2.0])) array([ 3.]) rr')excludeNautowrap)r-r,r/dummy)r6autofuncrg)rtyper;r8rr setlistrrrrzr4rJrfhasbinary_functionsubsr missing_argsrrerk)rr:r6tempdirrr<r>rgcode_genrCodeWrapperClass code_wrapperhelpsname_hexpr_hargs_hrfrvnew_argsmissings r)r>r> sH(D) &w 9"7+S\Q.8GAJ3G$'"&7)B!$44:$D%h ; #mmo  $Hgu2$+7/57L E")? X%%fff=>?#*6 88F $VVWEF99VVV_5D6 F"":tT:  ! !'5 ! 99 $ F~~ *Gg~6 OOGLL ) *"":tTH_E Fs/E F=AF88F=c 2t|fi|}t||S)aMReturns a SymPy function with expr as binary implementation This is a convenience function that automates the steps needed to autowrap the SymPy expression and attaching it to a Function object with implemented_function(). Parameters ========== symfunc : SymPy Function The function to bind the callable to. expr : SymPy Expression The expression used to generate the function. kwargs : dict Any kwargs accepted by autowrap. Examples ======== >>> from sympy.abc import x, y >>> from sympy.utilities.autowrap import binary_function >>> expr = ((x - y)**(25)).expand() >>> f = binary_function('f', expr) >>> type(f) >>> 2*f(x, y) 2*f(x, y) >>> f(x, y).evalf(2, subs={x: 1, y: 2}) -1.0 )r>r)symfuncrrbinarys r)rFrFs!Bd %f %F  00r(z#include "Python.h" #include "math.h" #include "numpy/ndarraytypes.h" #include "numpy/ufuncobject.h" #include "numpy/halffloat.h" #include ${include_file} static PyMethodDef ${module}Methods[] = { {NULL, NULL, 0, NULL} };z6*((double *)out${outnum}) = ${funcname}(${call_args});aD#ifdef NPY_1_19_API_VERSION static void ${funcname}_ufunc(char **args, const npy_intp *dimensions, const npy_intp* steps, void* data) #else static void ${funcname}_ufunc(char **args, npy_intp *dimensions, npy_intp* steps, void* data) #endif { npy_intp i; npy_intp n = dimensions[0]; ${declare_args} ${declare_steps} for (i = 0; i < n; i++) { ${outcalls} ${step_increments} } } PyUFuncGenericFunction ${funcname}_funcs[1] = {&${funcname}_ufunc}; static char ${funcname}_types[${n_types}] = ${types} static void *${funcname}_data[1] = {NULL};a#if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "${module}", NULL, -1, ${module}Methods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_${module}(void) { PyObject *m, *d; ${function_creation} m = PyModule_Create(&moduledef); if (!m) { return NULL; } import_array(); import_umath(); d = PyModule_GetDict(m); ${ufunc_init} return m; } #else PyMODINIT_FUNC init${module}(void) { PyObject *m, *d; ${function_creation} m = Py_InitModule("${module}", ${module}Methods); if (m == NULL) { return; } import_array(); import_umath(); d = PyModule_GetDict(m); ${ufunc_init} } #endifaufunc${ind} = PyUFunc_FromFuncAndData(${funcname}_funcs, ${funcname}_data, ${funcname}_types, 1, ${n_in}, ${n_out}, PyUFunc_None, "${module}", ${docstring}, 0); PyDict_SetItemString(d, "${funcname}", ufunc${ind}); Py_DECREF(ufunc${ind});a(from setuptools.extension import Extension from setuptools import setup from numpy import get_include if __name__ == "__main__": setup(ext_modules=[ Extension('${module}', sources=['${module}.c', '${filename}.c'], include_dirs=[get_include()])]) cjeZdZdZfdZedZd dZdZdZ e dZ dZ d d Z d ZxZS) UfuncifyCodeWrapperzWrapper for Ufuncifycgd}d}|D]@}||jvrt|j||j|dBt ||i|y)NrzHThe compilation option kwarg {} is not supported with the numpy backend.rr!s r)r?zUfuncifyCodeWrapper.__init__Csb= AFKKM!SZZ]# JJq$  $)&)r(c.tjdddg}|Srrrs r)rozUfuncifyCodeWrapper.commandQrr(cZ||ng}dtt|t|zz}|jxstjd}t j |t jst j|t j}t j| tjj||j|||j|||j!|t#|j$}tjj'|t(xj*dz c_t j||js t-j.||j3||S#t0$rYwxYw#tjj'|t(xj*dz c_t j||js& t-j.|w#t0$rYwwxYwwxYw)Nwrapped_rPrQ)ridr;rUrVrRrWrXrYrZr[r\rSrJrNr]r^r_r8r`r+r2rarbrcrd)r4rMrgfuncnamerhrirjs r)rkzUfuncifyCodeWrapper.wrap_codeVs %0'bBxL2g;$> ??--E8#3#34D#Eyy"''* HHW ))+   HHOOG $   ' 2   ( 3    )T--.C HHOOG $  ' '1 , ' HHW ==MM'* ))#x88  HHOOG $  ' '1 , ' HHW ==MM'*!sD0A)F)3F F&%F&)AH*HH* H&#H*%H&&H*c||z}|jj||jd|j|jyrI)r:rKr5rDrG)r4 main_routineshelper_routines all_routiness r)rNz"UfuncifyCodeWrapper._generate_codews:$6   $--t/B/B    r(c|jdz}t|d5}|j|||j|dddtdd5}|j |dddy#1swY0xYw#1swYyxYw)Nz.cr)r]r)r8rdump_cr5 dump_setup)r4rMr]rrs r)r]z"UfuncifyCodeWrapper._prepare_files}s''$. , $ G KK!T]]XK F G*c " a OOA     G G  s A+A7+A47Bct||SrArrs r)rdz)UfuncifyCodeWrapper._get_wrapped_functionrr(c|tj|j|j}|j |y)N)moduler5) _ufunc_setup substituter8r5rK)r4rsetups r)rdzUfuncifyCodeWrapper.dump_setups2''t/?/?15(@ r(c |+t|dk(r|dj}n d}t|g}g}g}|j} dj |} t j | | } |} d} |j|dj\}}t|}t|}d}t|Dcgc]}|j d||}}|jt|Dcgc]}|j d |||zc}d j|}d }t|Dcgc]}|j d||}}|jt|Dcgc]}|j d |||zc}d j|}d }d jt|Dcgc]}|j |c}}d}t|Dcgc]}|j d|}}|jt|Dcgc]}|j d ||c}dj|}||z}dd jdg|zzdz}d}|jdj | tj | | |||| }|j|t|Dcgc]'}tj ||||j)} }tj | | ||||||dj|  }!|j|!dj|}!d j|}d j|}t j | ||}"| |!|"g}#|j#dj|#ycc}wcc}wcc}wcc}wcc}wcc}wcc}wcc}w)aWrite a C file with Python wrappers This file contains all the definitions of the routines in c code. Arguments --------- routines List of Routine instances f File-like object to write the file to prefix The filename prefix, used to name the imported module. funcname Name of the main function to be returned. NrQrz7funcname must be specified for multiple output routinesz"{}.h") include_filergzchar *{0}{1} = args[{2}];inoutz z"npy_intp {0}{1}_step = steps[{2}];z*(double *)in{0}rz{0}{1} += {0}{1}_step;z { NPY_DOUBLEz};z "Created in SymPy with Ufuncify"zPyObject *ufunc{};)rgr] docstringn_inn_outr)outnum call_argsr]) rgr] declare_args declare_stepsrustep_incrementsn_typestypesoutcallsz )rg ufunc_initfunction_creation)r rer5r8r _ufunc_toprirrrangerprqrJ_ufunc_init_form_ufunc_outcalls _ufunc_body _ufunc_bottomrK)$r4rMrrr]r#rr}r|rgrltoprer_indexpy_inr0rrrsformrarg_decsrv step_decsrwrru step_incsrxryrzrq init_formr{rbottomtexts$ r)rczUfuncifyCodeWrapper.dump_cs  8}!#A;++O o%  !!!((0 ##f#M'' (=(=>q5zH +5:4[ADKKa+AAe M1UAqv6MN}}X. 46;DkBT[[q!,B BuNA$++eQ$7NO i0 "IIuT{C!t{{1~CD (38;?aT[[q)? ?E%LIq$++eQ2IJ&++I6,diiw 677$>7    !5!>> from sympy.utilities.autowrap import ufuncify >>> from sympy.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) >>> f([1, 2, 3], 2) array([ 3., 6., 11.]) >>> f(np.arange(5), 3) array([ 3., 4., 7., 12., 19.]) Using helper functions: >>> from sympy import Function >>> helper_func = Function('helper_func') # Define symbolic function >>> expr = x**2 + y*helper_func(x) # Main expression using helper function >>> # Define helper_func(x) = x**3 >>> f = ufuncify((x, y), expr, helpers=[('helper_func', x**3, [x])]) >>> f([1, 2], [3, 4]) array([ 4., 36.]) Type handling with different backends: For the 'f2py' and 'cython' backends, inputs are required to be equal length 1-dimensional arrays. The 'f2py' backend will perform type conversion, but the Cython backend will error if the inputs are not of the expected type. >>> f_fortran = ufuncify((x, y), y + x**2, backend='f2py') >>> f_fortran(1, 2) array([ 3.]) >>> f_fortran(np.array([1, 2, 3]), np.array([1.0, 2.0, 3.0])) array([ 2., 6., 12.]) >>> f_cython = ufuncify((x, y), y + x**2, backend='Cython') >>> f_cython(1, 2) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(np.array([1.0]), np.array([2.0])) array([ 3.]) r'r. ufuncifyrz#Expression iterable has zero lengthzKCannot create ufunc with more than {0} total arguments: got {1} in, {2} outz autofunc{}rAymT)integerrrz%s_%d)rr tupler;r8r4rJrrWrrDr r5rrrkrr rrre dummy_indexr rr>r )rrr:r6rIr<r>rgrmaxargsrMrerLr#idxexprxrMrrrf_dummyrr indexed_argsargs_with_indicess r)rrsSN$wT{"7H5"7+ gbGEE}}'! ' 9 D$ LLdD$7 8 9*:j+A7+0'; $u .6D t9>BC C t9s4y 7 *)CSZZTCIFG G"+D/3C!!4!4S!95$G33%%h%>> c # #t $ c4(! ,* GLL':M:M+N!NPVW[]aPb c<@Aq E#a&M2A As\!QC'+78aQqT881Q4$5!677ugwJBHJ J!3B9s&&H=$I I)NrNNNFNN)NrNNFN)?rwr\rRrarUpathlibr subprocessrrrstringrwarningsrsympy.core.cacher sympy.core.functionr sympy.core.relationalr sympy.core.symbolr r sympy.tensor.indexedrrsympy.utilities.codegenrrrrrrrrrsympy.utilities.iterablesrsympy.utilities.lambdifyrsympy.utilities.decoratorr_doctest_depends_on Exceptionr#r+rzrrr2r8r;r>rFr~rrrrrhrWrr'r(r)rsPd ??$&$+1EEE/989",. I LL^'";'"Tx xv"k"F. ,!# E ,jAEI?CP:B P:f,jA!1B!1N   ST./ (++ Z     @+@F 3ZHAE04UJI UJr(