def simplex_table_to_assumptions(table, symbols_used): common_assumps, new_assumps_by_pot = table.pots.get_common_and_not_assumptions() ret = '' common_assumpt_text = list() for a in common_assumps: process_expr_on_symbols(a.exp, symbols_used) common_assumpt_text.append('(' + ccode( a.exp) + ' ' + a.sign + ' 0 )') pots_assumpt_text = list() for pot in new_assumps_by_pot: pot_assumpt_text = list() for a in pot: process_expr_on_symbols(a.exp, symbols_used) pot_assumpt_text.append('(' + ccode( a.exp) + ' ' + a.sign + ' 0 )') pots_assumpt_text.append( '(' + " && ".join(pot_assumpt_text) + ')' ) ret = " && ".join(common_assumpt_text) if len(pots_assumpt_text) > 0: if len(common_assumps): ret += ' && ' ret += '(' + " || ".join(pots_assumpt_text) + ')' process_table_on_symbols(table, symbols_used) return ret
def test_ccode_reserved_words(): x, y = symbols('x, if') with raises(ValueError): ccode(y**2, error_on_reserved=True, standard='C99') assert ccode(y**2) == 'pow(if_, 2)' assert ccode(x * y**2, dereference=[y]) == 'pow((*if_), 2)*x' assert ccode(y**2, reserved_word_suffix='_unreserved') == 'pow(if_unreserved, 2)'
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*g(x), -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)'
def test_ccode_Piecewise_deep(): p = ccode(2*Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True))) assert p == ( "2*((x < 1) ? (\n" " x\n" ")\n" ": ((x < 2) ? (\n" " x + 1\n" ")\n" ": (\n" " pow(x, 2)\n" ")))") expr = x*y*z + x**2 + y**2 + Piecewise((0, x < 0.5), (1, True)) + cos(z) - 1 assert ccode(expr) == ( "pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" " 0\n" ")\n" ": (\n" " 1\n" ")) + cos(z) - 1") assert ccode(expr, assign_to='c') == ( "c = pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" " 0\n" ")\n" ": (\n" " 1\n" ")) + cos(z) - 1;")
def test_ccode_Indexed(): from sympy.tensor import IndexedBase, Idx from sympy import symbols s, n, m, o = symbols('s n m o', integer=True) i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) x = IndexedBase('x')[j] A = IndexedBase('A')[i, j] B = IndexedBase('B')[i, j, k] with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=SymPyDeprecationWarning) p = CCodePrinter() p._not_c = set() assert p._print_Indexed(x) == 'x[j]' assert p._print_Indexed(A) == 'A[%s]' % (m*i+j) assert p._print_Indexed(B) == 'B[%s]' % (i*o*m+j*o+k) assert p._not_c == set() A = IndexedBase('A', shape=(5,3))[i, j] assert p._print_Indexed(A) == 'A[%s]' % (3*i + j) A = IndexedBase('A', shape=(5,3), strides='F')[i, j] assert ccode(A) == 'A[%s]' % (i + 5*j) A = IndexedBase('A', shape=(29,29), strides=(1, s), offset=o)[i, j] assert ccode(A) == 'A[o + s*j + i]' Abase = IndexedBase('A', strides=(s, m, n), offset=o) assert ccode(Abase[i, j, k]) == 'A[m*j + n*k + o + s*i]' assert ccode(Abase[2, 3, k]) == 'A[3*m + n*k + o + 2*s]'
def test_ccode_sign(): expr1, ref1 = sign(x) * y, 'y*(((x) > 0) - ((x) < 0))' expr2, ref2 = sign(cos(x)), '(((cos(x)) > 0) - ((cos(x)) < 0))' expr3, ref3 = sign(2 * x + x**2) * x + x**2, 'pow(x, 2) + x*(((pow(x, 2) + 2*x) > 0) - ((pow(x, 2) + 2*x) < 0))' assert ccode(expr1) == ref1 assert ccode(expr1, 'z') == 'z = %s;' % ref1 assert ccode(expr2) == ref2 assert ccode(expr3) == ref3
def main(): # GENERATES WITHOUT ARGUMENTS: rev_unary_1.tex rev_unary_rate.tex rev_unary_k_b.c rev_unary_K_eq.c from sympy.printing.latex import latex open('rev_unary_1.tex', 'wt').write(as_align_env(eqs)) open('rev_unary_rate.tex', 'wt').write(latex(rate_expr)) open('rev_unary_k_b.c', 'wt').write('return_val = {};'.format(ccode(alt_expl_in_t))) open('rev_unary_K_eq.c', 'wt').write('return_val = {};'.format( ccode(alt_expl_in_t.subs({k_b: k_f/K_eq}))))
def __init__(self, model, tspan, integrator='vode', **integrator_options): pysb.bng.generate_equations(model) code_eqs = '\n'.join(['ydot[%d] = %s;' % (i, sympy.ccode(model.odes[i])) for i in range(len(model.odes))]) code_eqs = re.sub(r's(\d+)', lambda m: 'y[%s]' % (int(m.group(1))), code_eqs) for e in model.expressions: code_eqs = re.sub(r'\b(%s)\b' % e.name, sympy.ccode(e.expand_expr()), code_eqs) for i, p in enumerate(model.parameters): code_eqs = re.sub(r'\b(%s)\b' % p.name, 'p[%d]' % i, code_eqs) Solver._test_inline() # If we can't use weave.inline to run the C code, compile it as Python code instead for use with # exec. Note: C code with array indexing, basic math operations, and pow() just happens to also # be valid Python. If the equations ever have more complex things in them, this might fail. if not Solver._use_inline: code_eqs_py = compile(code_eqs, '<%s odes>' % model.name, 'exec') else: for arr_name in ('ydot', 'y', 'p'): macro = arr_name.upper() + '1' code_eqs = re.sub(r'\b%s\[(\d+)\]' % arr_name, '%s(\\1)' % macro, code_eqs) def rhs(t, y, p): ydot = self.ydot # note that the evaluated code sets ydot as a side effect if Solver._use_inline: inline(code_eqs, ['ydot', 't', 'y', 'p']); else: exec code_eqs_py in locals() return ydot # build integrator options list from our defaults and any kwargs passed to this function options = {} try: options.update(default_integrator_options[integrator]) except KeyError as e: pass options.update(integrator_options) self.model = model self.tspan = tspan self.y = numpy.ndarray((len(tspan), len(model.species))) self.ydot = numpy.ndarray(len(model.species)) if len(model.observables): self.yobs = numpy.ndarray(len(tspan), zip(model.observables.keys(), itertools.repeat(float))) else: self.yobs = numpy.ndarray((len(tspan), 0)) exprs = model.expressions_dynamic() if len(exprs): self.yexpr = numpy.ndarray(len(tspan), zip(exprs.keys(), itertools.repeat(float))) else: self.yexpr = numpy.ndarray((len(tspan), 0)) self.yobs_view = self.yobs.view(float).reshape(len(self.yobs), -1) self.integrator = ode(rhs).set_integrator(integrator, **options)
def main(): # GENERATES WITHOUT ARGUMENTS: irrev_binary_1.tex irrev_binary_2.tex irrev_binary_rate.tex irrev_binary_k_b.c irrev_binary_K_eq.c from sympy.printing.latex import latex open("irrev_binary_1.tex", "wt").write(as_align_env(eqs[:2])) open("irrev_binary_2.tex", "wt").write(as_align_env(eqs[2:])) open("irrev_binary_rate.tex", "wt").write(latex(rate_expr)) open("irrev_binary_k_b.c", "wt").write("return_val = {};".format(ccode(alt_expl_in_t))) open("irrev_binary_K_eq.c", "wt").write("return_val = {};".format(ccode(alt_expl_in_t.subs({k_b: k_f / K_eq}))))
def test_ccode_user_functions(): x = symbols('x', integer=False) n = symbols('n', integer=True) custom_functions = { "ceiling": "ceil", "Abs": [(lambda x: not x.is_integer, "fabs"), (lambda x: x.is_integer, "abs")], } assert ccode(ceiling(x), user_functions=custom_functions) == "ceil(x)" assert ccode(Abs(x), user_functions=custom_functions) == "fabs(x)" assert ccode(Abs(n), user_functions=custom_functions) == "abs(n)"
def test_MatrixElement_printing(): # test cases for issue #11821 A = MatrixSymbol("A", 1, 3) B = MatrixSymbol("B", 1, 3) C = MatrixSymbol("C", 1, 3) assert(ccode(A[0, 0]) == "A[0]") assert(ccode(3 * A[0, 0]) == "3*A[0]") F = C[0, 0].subs(C, A - B) assert(ccode(F) == "(-B + A)[0]")
def test_ccode_sign(): expr = sign(x) * y assert ccode(expr) == 'y*(((x) > 0) - ((x) < 0))' assert ccode(expr, 'z') == 'z = y*(((x) > 0) - ((x) < 0));' assert ccode(sign(2 * x + x**2) * x + x**2) == \ 'pow(x, 2) + x*(((pow(x, 2) + 2*x) > 0) - ((pow(x, 2) + 2*x) < 0))' expr = sign(cos(x)) assert ccode(expr) == '(((cos(x)) > 0) - ((cos(x)) < 0))'
def test_ccode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert ccode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert ccode(g(x)) == "double const Catalan = %s;\n2*x/Catalan" %Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert ccode(g(A[i]), assign_to=A[i]) == ( "for (int i=0; i<n; i++){\n" " A[i] = (1 + A[i])*(2 + A[i])*A[i];\n" "}" )
def eval_str(self, dom, idx_str="i", qd_pt_str="QUAD_PTS"): qd_id_str = "(%(jac)f*%(qd_pt_str)s[%(idx_str)s]+%(shift)f)" % \ {"qd_pt_str":qd_pt_str, "idx_str":idx_str, "jac":(dom.args[2] - dom.args[1]) / 2.0 , "shift":(dom.args[2] + dom.args[1]) / 2.0 } return ccode(self.args[0]).replace(str(self.args[1]), qd_id_str)
def _ccode(expr, ): code = sympy.ccode(expr) if options['unroll_square']: code = re.sub(r'pow\(([^,]*), 2\)', r'((\1)*(\1))', code) if options['custom_sign_func']: code = re.sub(r'\(\(([^,]*)\) > 0\) - \(\(([^,]*)\) < 0\)', r'Sign(\1)', code) return code
def test_ccode_loops_multiple_contractions(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m, o, p = symbols('n m o p', integer=True) a = IndexedBase('a') b = IndexedBase('b') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) k = Idx('k', o) l = Idx('l', p) s = ( 'for (int i=0; i<m; i++){\n' ' y[i] = 0;\n' '}\n' 'for (int i=0; i<m; i++){\n' ' for (int j=0; j<n; j++){\n' ' for (int k=0; k<o; k++){\n' ' for (int l=0; l<p; l++){\n' ' y[i] = a[%s]*b[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ ' }\n' ' }\n' ' }\n' '}' ) assert ccode(b[j, k, l]*a[i, j, k, l], assign_to=y[i]) == s
def run(model): output = StringIO() pysb.bng.generate_equations(model) ic_values = [0] * len(model.odes) for cp, ic_param in model.initial_conditions: ic_values[model.get_species_index(cp)] = ic_param.value # list of "dynamic variables" pw_x = ["m = pwAddX(m, 's%d', %e);" % (i, ic_values[i]) for i in range(len(model.odes))] # parameters pw_k = ["m = pwAddK(m, '%s', %e);" % (p.name, p.value) for p in model.parameters] # equations (one for each dynamic variable) # Note that we just generate C code, which for basic math expressions # is identical to matlab. We just have to change 'pow' to 'power'. # Ideally there would be a matlab formatter for sympy. pw_ode = ["m = pwAddODE(m, 's%d', '%s');" % (i, sympy.ccode(model.odes[i])) for i in range(len(model.odes))] pw_ode = [re.sub(r'pow(?=\()', 'power', s) for s in pw_ode] # observables pw_y = ["m = pwAddY(m, '%s', '%s');" % (obs.name, ' + '.join('%f * s%s' % t for t in zip(obs.coefficients, obs.species))) for obs in model.observables] output.write('% PottersWheel model definition file\n') output.write('%% save as %s.m\n' % model_name) output.write('function m = %s()\n' % model_name) output.write('\n') output.write('m = pwGetEmptyModel();\n') output.write('\n') output.write('% meta information\n') output.write("m.ID = '%s';\n" % model_name) output.write("m.name = '%s';\n" % model_name) output.write("m.description = '';\n") output.write("m.authors = {''};\n") output.write("m.dates = {''};\n") output.write("m.type = 'PW-1-5';\n") output.write('\n') output.write('% dynamic variables\n') for x in pw_x: output.write(x) output.write('\n') output.write('\n') output.write('% dynamic parameters\n') for k in pw_k: output.write(k) output.write('\n') output.write('\n') output.write('% ODEs\n') for ode in pw_ode: output.write(ode) output.write('\n') output.write('\n') output.write('% observables\n') for y in pw_y: output.write(y) output.write('\n') output.write('\n') output.write('%% end of PottersWheel model %s\n' % model_name) return output.getvalue()
def test_ccode_loops_addfactor(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m, o, p = symbols('n m o p', integer=True) a = IndexedBase('a') b = IndexedBase('b') c = IndexedBase('c') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) k = Idx('k', o) l = Idx('l', p) s = ( 'for (int i=0; i<m; i++){\n' ' y[i] = 0;\n' '}\n' 'for (int i=0; i<m; i++){\n' ' for (int j=0; j<n; j++){\n' ' for (int k=0; k<o; k++){\n' ' for (int l=0; l<p; l++){\n' ' y[i] = (a[%s] + b[%s])*c[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ ' }\n' ' }\n' ' }\n' '}' ) c = ccode((a[i, j, k, l] + b[i, j, k, l])*c[j, k, l], assign_to=y[i]) assert c == s
def run(model): output = StringIO() pysb.bng.generate_equations(model) output.write("% MATLAB model definition file\n") output.write('%% save as %s_odes.m\n' % model_name) output.write('function out = %s_odes(t, input, param)' % model_name) output.write("\n\n") c_code_consts = '\n'.join(['param(%d) = %s %% %s;' % (i+1, p.value, p.name) for i, p in enumerate(model.parameters)]) c_code_eqs = '\n'.join(['out(%d,1) = %s;' % (i+1, sympy.ccode(model.odes[i])) for i in range(len(model.odes))]) c_code_eqs = re.sub(r's(\d+)', lambda m: 'input(%s)' % (int(m.group(1))+1), c_code_eqs) c_code_eqs = re.sub(r'pow\(', 'power(', c_code_eqs) c_code = c_code_eqs c_code_species = '\n'.join(['%% input(%d) = %s;' % (i+1, s) for i, s in enumerate(model.species)]) for i, p in enumerate(model.parameters): c_code = re.sub(r'\b(%s)\b' % p.name, 'param(%d)' % (i+1), c_code) output.write(c_code_consts + "\n\n") output.write(c_code_species + "\n\n") output.write(c_code + "\n\n") output.write("end\n") return output.getvalue()
def eqn_substitutions(eqns): """String substitutions on the sympy C code for the ODE RHS and Jacobian functions to use appropriate terms for variables and parameters.""" # Substitute expanded parameter formulas for any named expressions for e in self.model.expressions: eqns = re.sub(r'\b(%s)\b' % e.name, '('+sympy.ccode( e.expand_expr())+')', eqns) # Substitute sums of observable species that could've been added # by expressions for obs in self.model.observables: obs_string = '' for i in range(len(obs.coefficients)): if i > 0: obs_string += "+" if obs.coefficients[i] > 1: obs_string += str(obs.coefficients[i])+"*" obs_string += "__s"+str(obs.species[i]) if len(obs.coefficients) > 1: obs_string = '(' + obs_string + ')' eqns = re.sub(r'\b(%s)\b' % obs.name, obs_string, eqns) # Substitute 'y[i]' for 'si' eqns = re.sub(r'_*s(\d+)', lambda m: 'y[%s]' % (int(m.group(1))), eqns) # Substitute 'p[i]' for any named parameters for i, p in enumerate(self.model.parameters): eqns = re.sub(r'\b(%s)\b' % p.name, 'p[%d]' % i, eqns) return eqns
def test_RealFunction_and_ImageFunction(): x = sympy.Symbol('x') f = RealFunction('f')(x) assert f.is_real assert RealFunction('f')(x) == f ref_ccode = sympy.ccode(sympy.Function('f')(x)) assert sympy.ccode(f) == ref_ccode y = sympy.Symbol('y', real=False) g = ImagFunction('g')(y) assert g.is_real is False assert f.is_real assert ImagFunction('g')(y) == g assert g != f assert RealFunction('f')(x) == f assert sympy.ccode(f) == sympy.ccode(sympy.Function('f')(x))
def test_ccode_exceptions(): assert ccode(gamma(x), standard='C99') == "tgamma(x)" gamma_c89 = ccode(gamma(x), standard='C89') assert 'not supported in c' in gamma_c89.lower() gamma_c89 = ccode(gamma(x), standard='C89', allow_unknown_functions=False) assert 'not supported in c' in gamma_c89.lower() gamma_c89 = ccode(gamma(x), standard='C89', allow_unknown_functions=True) assert not 'not supported in c' in gamma_c89.lower() assert ccode(ceiling(x)) == "ceil(x)" assert ccode(Abs(x)) == "fabs(x)" assert ccode(gamma(x)) == "tgamma(x)" r, s = symbols('r,s', real=True) assert ccode(Mod(ceiling(r), ceiling(s))) == "((ceil(r)) % (ceil(s)))" assert ccode(Mod(r, s)) == "fmod(r, s)"
def body(): U = self.solution_scaled(x,a,b,c,d,e) dU = self.solution_gradient(x,a,b,c,d,e) if True: decl, statements = self.residual_code(x,U,dU) return decl + statements else: V,dV = self.residual(x,U,dU) return [ccode(V[i] - divergence(row,x), assign_to=self.ffieldname(i)) for i,row in enumerate(rows(dV))]
def test_ccode_ITE(): expr = ITE(x < 1, x, x**2) assert ccode(expr) == ( "((x < 1) ? (\n" " x\n" ")\n" ": (\n" " pow(x, 2)\n" "))")
def test_ccode_ITE(): expr = ITE(x < 1, y, z) assert ccode(expr) == ( "((x < 1) ? (\n" " y\n" ")\n" ": (\n" " z\n" "))")
def test_ccode_Indexed_without_looking_for_contraction(): len_y = 5 y = IndexedBase('y', shape=(len_y,)) x = IndexedBase('x', shape=(len_y,)) Dy = IndexedBase('Dy', shape=(len_y-1,)) i = Idx('i', len_y-1) e=Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) code0 = ccode(e.rhs, assign_to=e.lhs, contract=False) assert code0 == 'Dy[i] = (y[%s] - y[i])/(x[%s] - x[i]);' % (i + 1, i + 1)
def ccode(self, **args): from sympy import ccode, N#, horner if self.fundamental: return str(self) if hasattr(self.substitution, '__iter__'): # Check only for __iter__ so that strings don't get caught return '{' + ', '.join([ccode(x, **args) for x in self.substitution]) + '}' if isinstance(self.substitution, basestring): return self.substitution code = self.substitution try: code=N(code) except: pass # try: # code=horner(code, wrt=args.pop('wrt', None)) # except: # pass return ccode(code, **args)
def test_ccode_boolean(): assert ccode(x & y) == "x && y" assert ccode(x | y) == "x || y" assert ccode(~x) == "!x" assert ccode(x & y & z) == "x && y && z" assert ccode(x | y | z) == "x || y || z" assert ccode((x & y) | z) == "z || x && y" assert ccode((x | y) & z) == "z && (x || y)"
def test_ccode_constants_mathh(): assert ccode(exp(1)) == "M_E" assert ccode(pi) == "M_PI" assert ccode(oo, standard='c89') == "HUGE_VAL" assert ccode(-oo, standard='c89') == "-HUGE_VAL" assert ccode(oo) == "INFINITY" assert ccode(-oo, standard='c99') == "-INFINITY" assert ccode(pi, type_aliases={real: float80}) == "M_PIl"
def test_ccode_sinc(): from sympy import sinc expr = sinc(x) assert ccode(expr) == ( "((x != 0) ? (\n" " sin(x)/x\n" ")\n" ": (\n" " 1\n" "))")
def test_ccode_For(): f = For(x, Range(0, 10, 2), [aug_assign(y, '*', x)]) assert ccode(f) == ("for (x = 0; x < 10; x += 2) {\n" " y *= x;\n" "}")
def test_ccode_UnevaluatedExpr(): assert ccode(UnevaluatedExpr(y * x) + z) == "z + x*y" assert ccode(UnevaluatedExpr(y + x) + z) == "z + (x + y)" # gh-21955 w = symbols('w') assert ccode(UnevaluatedExpr(y + x) + UnevaluatedExpr(z + w)) == "(w + z) + (x + y)"
def _ccode(expr, ): code = sympy.ccode(expr) if options['unroll_square']: return re.sub(r'pow\(([^,]*), 2\)', r'((\1)*(\1))', code) else: return code
def test_ccode_standard(): assert ccode(expm1(x), standard="c99") == "expm1(x)" assert ccode(nan, standard="c99") == "NAN" assert ccode(float("nan"), standard="c99") == "NAN"
def test_ccode_math_macros(): assert ccode(z + exp(1)) == "z + M_E" assert ccode(z + log2(exp(1))) == "z + M_LOG2E" assert ccode(z + 1 / log(2)) == "z + M_LOG2E" assert ccode(z + log(2)) == "z + M_LN2" assert ccode(z + log(10)) == "z + M_LN10" assert ccode(z + pi) == "z + M_PI" assert ccode(z + pi / 2) == "z + M_PI_2" assert ccode(z + pi / 4) == "z + M_PI_4" assert ccode(z + 1 / pi) == "z + M_1_PI" assert ccode(z + 2 / pi) == "z + M_2_PI" assert ccode(z + 2 / sqrt(pi)) == "z + M_2_SQRTPI" assert ccode(z + 2 / Sqrt(pi)) == "z + M_2_SQRTPI" assert ccode(z + sqrt(2)) == "z + M_SQRT2" assert ccode(z + Sqrt(2)) == "z + M_SQRT2" assert ccode(z + 1 / sqrt(2)) == "z + M_SQRT1_2" assert ccode(z + 1 / Sqrt(2)) == "z + M_SQRT1_2"
def myCCode(A): return sy.ccode(A).replace('M_PI', 'pi')
def outputC(sympyexpr, output_varname_str, filename="stdout", params="", prestring="", poststring=""): outCparams = parse_outCparams_string(params) preindent = outCparams.preindent TYPE = par.parval_from_str("PRECISION") if outCparams.enable_TYPE == "False": TYPE = "" # Step 0: Initialize # commentblock: comment block containing the input SymPy string, # set only if outCverbose==True # outstring: the output C code string commentblock = "" outstring = "" # Step 1: If SIMD_enable==True, then check if TYPE=="double". If not, error out. # Otherwise set TYPE="REAL_SIMD_ARRAY", which should be #define'd # within the C code. For example for AVX-256, the C code should have # #define REAL_SIMD_ARRAY __m256d if outCparams.SIMD_enable == "True": if not (TYPE == "double" or TYPE == ""): print( "SIMD output currently only supports double precision or typeless. Sorry!" ) exit(1) if TYPE == "double": TYPE = "REAL_SIMD_ARRAY" else: TYPE = "" # Step 2a: Apply sanity checks when either sympyexpr or # output_varname_str is a list. if type(output_varname_str) is list and type(sympyexpr) is not list: print( "Error: Provided a list of output variable names, but only one SymPy expression." ) exit(1) if type(sympyexpr) is list: if type(output_varname_str) is not list: print( "Error: Provided a list of SymPy expressions, but no corresponding list of output variable names" ) exit(1) elif len(output_varname_str) != len(sympyexpr): print("Error: Length of SymPy expressions list (" + str(len(sympyexpr)) + ") != Length of corresponding output variable name list (" + str(len(output_varname_str)) + ")") exit(1) # Step 2b: If sympyexpr and output_varname_str are not lists, # convert them to lists of one element each, to # simplify proceeding code. if type(output_varname_str) is not list and type(sympyexpr) is not list: output_varname_strtmp = [output_varname_str] output_varname_str = output_varname_strtmp sympyexprtmp = [sympyexpr] sympyexpr = sympyexprtmp # Step 3: If outCparams.verbose = True, then output the original SymPy # expression(s) in code comments prior to actual C code if outCparams.outCverbose == "True": commentblock += preindent + "/*\n" + preindent + " * Original SymPy expression" if len(output_varname_str) > 1: commentblock += "s" commentblock += ":\n" for i in range(len(output_varname_str)): if i == 0: if len(output_varname_str) != 1: commentblock += preindent + " * \"[" else: commentblock += preindent + " * \"" else: commentblock += preindent + " * " commentblock += output_varname_str[i] + " = " + str(sympyexpr[i]) if i == len(output_varname_str) - 1: if len(output_varname_str) != 1: commentblock += "]\"\n" else: commentblock += "\"\n" else: commentblock += ",\n" commentblock += preindent + " */\n" # Step 4: Add proper indentation of C code: if outCparams.includebraces == "True": indent = outCparams.preindent + " " else: indent = outCparams.preindent + "" # Step 5: Should the output variable, e.g., outvar, be declared? # If so, start output line with e.g., "double outvar " outtypestring = "" if outCparams.declareoutputvars == "True": outtypestring = outCparams.preindent + indent + TYPE + " " else: outtypestring = outCparams.preindent + indent # Step 6a: If common subexpression elimination (CSE) disabled, then # just output the SymPy string in the most boring way, # nearly consistent with SymPy's ccode() function, # though with support for float & long double types # as well. SIMD_decls = "" if outCparams.CSE_enable == "False": # If CSE is disabled: for i in range(len(sympyexpr)): outstring += outtypestring + ccode_postproc( sp.ccode(sympyexpr[i], output_varname_str[i])) + "\n" # Step 6b: If CSE enabled, then perform CSE using SymPy and then # resulting C code. else: # If CSE is enabled: SIMD_const_varnms = [] SIMD_const_values = [] CSE_results = sp.cse(sympyexpr, sp.numbered_symbols(outCparams.CSE_varprefix), order='canonical') for commonsubexpression in CSE_results[0]: FULLTYPESTRING = "const " + TYPE + " " if outCparams.enable_TYPE == "False": FULLTYPESTRING = "" if outCparams.SIMD_enable == "True": outstring += outCparams.preindent + indent + FULLTYPESTRING + str(commonsubexpression[0]) + " = " + \ str(expr_convert_to_SIMD_intrins(commonsubexpression[1],SIMD_const_varnms,SIMD_const_values,outCparams.SIMD_debug)) + ";\n" else: outstring += outCparams.preindent + indent + FULLTYPESTRING + ccode_postproc( sp.ccode(commonsubexpression[1], commonsubexpression[0])) + "\n" for i, result in enumerate(CSE_results[1]): if outCparams.SIMD_enable == "True": outstring += outtypestring + output_varname_str[i] + " = " + \ str(expr_convert_to_SIMD_intrins(result,SIMD_const_varnms,SIMD_const_values,outCparams.SIMD_debug)) + ";\n" else: outstring += outtypestring + ccode_postproc( sp.ccode(result, output_varname_str[i])) + "\n" # Step 6b.i: If SIMD_enable == True , and # there is at least one SIMD const variable, # then declare the SIMD_const_varnms and SIMD_const_values arrays if outCparams.SIMD_enable == "True" and len(SIMD_const_varnms) != 0: # Step 6a) Sort the list of definitions. Idea from: # https://stackoverflow.com/questions/9764298/is-it-possible-to-sort-two-listswhich-reference-each-other-in-the-exact-same-w SIMD_const_varnms, SIMD_const_values = \ (list(t) for t in zip(*sorted(zip(SIMD_const_varnms, SIMD_const_values)))) # Step 6b) Remove duplicates uniq_varnms = superfast_uniq(SIMD_const_varnms) uniq_values = superfast_uniq(SIMD_const_values) SIMD_const_varnms = uniq_varnms SIMD_const_values = uniq_values if len(SIMD_const_varnms) != len(SIMD_const_values): print( "Error: SIMD constant declaration arrays SIMD_const_varnms[] and SIMD_const_values[] have inconsistent sizes!" ) exit(1) for i in range(len(SIMD_const_varnms)): if outCparams.enable_TYPE == "False": SIMD_decls += outCparams.preindent + indent + SIMD_const_varnms[ i] + " = " + SIMD_const_values[i] + ";" else: SIMD_decls += outCparams.preindent + indent + "const double " + outCparams.CSE_varprefix + SIMD_const_varnms[ i] + " = " + SIMD_const_values[i] + ";\n" SIMD_decls += outCparams.preindent + indent + "const REAL_SIMD_ARRAY " + SIMD_const_varnms[ i] + " = ConstSIMD(" + outCparams.CSE_varprefix + SIMD_const_varnms[ i] + ");\n" SIMD_decls += "\n" # Step 7: Construct final output string final_Ccode_output_str = commentblock # Step 7a: Output C code in indented curly brackets if # outCparams.includebraces = True if outCparams.includebraces == "True": final_Ccode_output_str += outCparams.preindent + "{\n" final_Ccode_output_str += prestring + SIMD_decls + outstring + poststring if outCparams.includebraces == "True": final_Ccode_output_str += outCparams.preindent + "}\n" # Step 8: If filename == "stdout", then output # C code to standard out (useful for copy-paste or interactive # mode). Otherwise output to file specified in variable name. if filename == "stdout": # Output to standard out (stdout; "the screen") print(final_Ccode_output_str) elif filename == "returnstring": return final_Ccode_output_str else: # Output to the file specified by the function input parameter string 'filename': with open(filename, outCparams.outCfileaccess) as file: file.write(final_Ccode_output_str) successstr = "" if outCparams.outCfileaccess == "a": successstr = "Appended " elif outCparams.outCfileaccess == "w": successstr = "Wrote " print(successstr + "to file \"" + filename + "\"")
def test_Element(): assert ccode(Element('x', 'ij')) == 'x[i][j]' assert ccode(Element('x', 'ij', strides='kl', offset='o')) == 'x[i*k + j*l + o]' assert ccode(Element('x', (3,))) == 'x[3]' assert ccode(Element('x', (3,4,5))) == 'x[3][4][5]'
def test_printmethod(): class fabs(Abs): def _ccode(self, printer): return "fabs(%s)" % printer._print(self.args[0]) assert ccode(fabs(x)) == "fabs(x)"
def test_ccode_settings(): raises(TypeError, lambda: ccode(sin(x), method="garbage"))
def test_ccode_boolean(): assert ccode(True) == "true" assert ccode(S.true) == "true" assert ccode(False) == "false" assert ccode(S.false) == "false" assert ccode(x & y) == "x && y" assert ccode(x | y) == "x || y" assert ccode(~x) == "!x" assert ccode(x & y & z) == "x && y && z" assert ccode(x | y | z) == "x || y || z" assert ccode((x & y) | z) == "z || x && y" assert ccode((x | y) & z) == "z && (x || y)"
def test_ccode_functions(): assert ccode(sin(x) ** cos(x)) == "pow(sin(x), cos(x))"
def test_ccode_Max_Min(): assert ccode(Max(x, 0), standard='C89') == '((0 > x) ? 0 : x)' assert ccode(Max(x, 0), standard='C99') == 'fmax(0, x)' assert ccode(Min(x, 0, sqrt(x)), standard='c89') == ( '((0 < ((x < sqrt(x)) ? x : sqrt(x))) ? 0 : ((x < sqrt(x)) ? x : sqrt(x)))' )
def test_ccode_Min_performance(): #Shouldn't take more than a few seconds big_min = Min(*symbols('a[0:50]')) for curr_standard in ('c89', 'c99', 'c11'): output = ccode(big_min, standard=curr_standard) assert output.count('(') == output.count(')')
def test_ccode_Rational(): assert ccode(Rational(3, 7)) == "3.0/7.0" assert ccode(Rational(3, 7), type_aliases={real: float80}) == "3.0L/7.0L" assert ccode(Rational(18, 9)) == "2" assert ccode(Rational(3, -7)) == "-3.0/7.0" assert ccode(Rational(3, -7), type_aliases={real: float80}) == "-3.0L/7.0L" assert ccode(Rational(-3, -7)) == "3.0/7.0" assert ccode(Rational(-3, -7), type_aliases={real: float80}) == "3.0L/7.0L" assert ccode(x + Rational(3, 7)) == "x + 3.0/7.0" assert ccode(x + Rational(3, 7), type_aliases={real: float80}) == "x + 3.0L/7.0L" assert ccode(Rational(3, 7) * x) == "(3.0/7.0)*x" assert ccode(Rational(3, 7) * x, type_aliases={real: float80}) == "(3.0L/7.0L)*x"
def test_ccode_Assignment(): assert ccode(Assignment(x, y + z)) == "x = y + z;" assert ccode(aug_assign(x, "+", y + z)) == "x += y + z;"
def test_ccode_Type(): assert ccode(Type("float")) == "float" assert ccode(intc) == "int"
def outputC(sympyexpr, output_varname_str, filename = "stdout", params = "", prestring = "", poststring = ""): outCparams = parse_outCparams_string(params) preindent = outCparams.preindent TYPE = par.parval_from_str("PRECISION") if outCparams.enable_TYPE == "False": TYPE = "" # Step 0: Initialize # commentblock: comment block containing the input SymPy string, # set only if outCverbose==True # outstring: the output C code string commentblock = "" outstring = "" # Step 1: If enable_SIMD==True, then check if TYPE=="double". If not, error out. # Otherwise set TYPE="REAL_SIMD_ARRAY", which should be #define'd # within the C code. For example for AVX-256, the C code should have # #define REAL_SIMD_ARRAY __m256d if outCparams.enable_SIMD == "True": if TYPE not in ('double', ''): print("SIMD output currently only supports double precision or typeless. Sorry!") sys.exit(1) if TYPE == "double": TYPE = "REAL_SIMD_ARRAY" # Step 2a: Apply sanity checks when either sympyexpr or # output_varname_str is a list. if isinstance(output_varname_str, list) and not isinstance(sympyexpr, list): print("Error: Provided a list of output variable names, but only one SymPy expression.") sys.exit(1) if isinstance(sympyexpr, list): if not isinstance(output_varname_str, list): print("Error: Provided a list of SymPy expressions, but no corresponding list of output variable names") sys.exit(1) elif len(output_varname_str) != len(sympyexpr): print("Error: Length of SymPy expressions list ("+str(len(sympyexpr))+ ") != Length of corresponding output variable name list ("+str(len(output_varname_str))+")") sys.exit(1) # Step 2b: If sympyexpr and output_varname_str are not lists, # convert them to lists of one element each, to # simplify proceeding code. if not isinstance(output_varname_str, list) and not isinstance(sympyexpr, list): output_varname_strtmp = [output_varname_str] output_varname_str = output_varname_strtmp sympyexprtmp = [sympyexpr] sympyexpr = sympyexprtmp sympyexpr = sympyexpr[:] # pass-by-value (copy list) # Step 3: If outCparams.verbose = True, then output the original SymPy # expression(s) in code comments prior to actual C code if outCparams.outCverbose == "True": commentblock += preindent+"/*\n"+preindent+" * Original SymPy expression" if len(output_varname_str)>1: commentblock += "s" commentblock += ":\n" for i, varname in enumerate(output_varname_str): if i == 0: if len(output_varname_str) != 1: commentblock += preindent+" * \"[" else: commentblock += preindent+" * \"" else: commentblock += preindent+" * " commentblock += varname + " = " + str(sympyexpr[i]) if i == len(output_varname_str)-1: if len(output_varname_str) != 1: commentblock += "]\"\n" else: commentblock += "\"\n" else: commentblock += ",\n" commentblock += preindent+" */\n" # Step 4: Add proper indentation of C code: if outCparams.includebraces == "True": indent = outCparams.preindent+" " else: indent = outCparams.preindent+"" # Step 5: Should the output variable, e.g., outvar, be declared? # If so, start output line with e.g., "double outvar " outtypestring = "" if outCparams.declareoutputvars == "True": outtypestring = indent+TYPE + " " else: outtypestring = indent # Step 6a: If common subexpression elimination (CSE) disabled, then # just output the SymPy string in the most boring way, # nearly consistent with SymPy's ccode() function, # though with support for float & long double types # as well. SIMD_RATIONAL_decls = RATIONAL_decls = "" if outCparams.CSE_enable == "False": # If CSE is disabled: for i in range(len(sympyexpr)): outstring += outtypestring + ccode_postproc(sp.ccode(sympyexpr[i], output_varname_str[i], user_functions=custom_functions_for_SymPy_ccode))+"\n" # Step 6b: If CSE enabled, then perform CSE using SymPy and then # resulting C code. else: # If CSE is enabled: SIMD_const_varnms = [] SIMD_const_values = [] varprefix = '' if outCparams.CSE_varprefix == 'tmp' else outCparams.CSE_varprefix if outCparams.CSE_preprocess == "True" or outCparams.enable_SIMD == "True": # If CSE_preprocess == True, then perform partial factorization # If enable_SIMD == True, then declare _NegativeOne_ in preprocessing factor_negative = eval(outCparams.enable_SIMD) and eval(outCparams.SIMD_find_more_subs) sympyexpr, map_sym_to_rat = cse_preprocess(sympyexpr, prefix=varprefix, declare=eval(outCparams.enable_SIMD), negative=factor_negative, factor=eval(outCparams.CSE_preprocess)) for v in map_sym_to_rat: p, q = float(map_sym_to_rat[v].p), float(map_sym_to_rat[v].q) if outCparams.enable_SIMD == "False": RATIONAL_decls += indent + 'const double ' + str(v) + ' = ' # Since Integer is a subclass of Rational in SymPy, we need only check whether # the denominator q = 1 to determine if a rational is an integer. if q != 1: RATIONAL_decls += str(p) + '/' + str(q) + ';\n' else: RATIONAL_decls += str(p) + ';\n' sympy_version = sp.__version__.replace('rc', '...').replace('b', '...') sympy_major_version = int(sympy_version.split(".")[0]) sympy_minor_version = int(sympy_version.split(".")[1]) if sympy_major_version < 1 or (sympy_major_version == 1 and sympy_minor_version < 3): print('Warning: SymPy version', sympy_version, 'does not support CSE postprocessing.') CSE_results = sp.cse(sympyexpr, sp.numbered_symbols(outCparams.CSE_varprefix + '_'), order=outCparams.CSE_sorting) else: CSE_results = cse_postprocess(sp.cse(sympyexpr, sp.numbered_symbols(outCparams.CSE_varprefix + '_'), order=outCparams.CSE_sorting)) for commonsubexpression in CSE_results[0]: FULLTYPESTRING = "const " + TYPE + " " if outCparams.enable_TYPE == "False": FULLTYPESTRING = "" if outCparams.enable_SIMD == "True": outstring += indent + FULLTYPESTRING + str(commonsubexpression[0]) + " = " + \ str(expr_convert_to_SIMD_intrins(commonsubexpression[1],map_sym_to_rat,varprefix,outCparams.SIMD_find_more_FMAsFMSs)) + ";\n" else: outstring += indent + FULLTYPESTRING + ccode_postproc(sp.ccode(commonsubexpression[1], commonsubexpression[0], user_functions=custom_functions_for_SymPy_ccode)) + "\n" for i, result in enumerate(CSE_results[1]): if outCparams.enable_SIMD == "True": outstring += outtypestring + output_varname_str[i] + " = " + \ str(expr_convert_to_SIMD_intrins(result,map_sym_to_rat,varprefix,outCparams.SIMD_find_more_FMAsFMSs)) + ";\n" else: outstring += outtypestring+ccode_postproc(sp.ccode(result,output_varname_str[i], user_functions=custom_functions_for_SymPy_ccode))+"\n" # Complication: SIMD functions require numerical constants to be stored in SIMD arrays # Resolution: This function extends lists "SIMD_const_varnms" and "SIMD_const_values", # which store the name of each constant SIMD array (e.g., _Integer_1) and # the value of each variable (e.g., 1.0). if outCparams.enable_SIMD == "True": for v in map_sym_to_rat: p, q = float(map_sym_to_rat[v].p), float(map_sym_to_rat[v].q) SIMD_const_varnms.extend([str(v)]) if q != 1: SIMD_const_values.extend([str(p) + '/' + str(q)]) else: SIMD_const_values.extend([str(p)]) # Step 6b.i: If enable_SIMD == True , and # there is at least one SIMD const variable, # then declare the SIMD_const_varnms and SIMD_const_values arrays if outCparams.enable_SIMD == "True" and len(SIMD_const_varnms) != 0: # Step 6a) Sort the list of definitions. Idea from: # https://stackoverflow.com/questions/9764298/is-it-possible-to-sort-two-listswhich-reference-each-other-in-the-exact-same-w SIMD_const_varnms, SIMD_const_values = \ (list(t) for t in zip(*sorted(zip(SIMD_const_varnms, SIMD_const_values)))) # Step 6b) Remove duplicates uniq_varnms = superfast_uniq(SIMD_const_varnms) uniq_values = superfast_uniq(SIMD_const_values) SIMD_const_varnms = uniq_varnms SIMD_const_values = uniq_values if len(SIMD_const_varnms) != len(SIMD_const_values): print("Error: SIMD constant declaration arrays SIMD_const_varnms[] and SIMD_const_values[] have inconsistent sizes!") sys.exit(1) for i in range(len(SIMD_const_varnms)): if outCparams.enable_TYPE == "False": SIMD_RATIONAL_decls += indent + SIMD_const_varnms[i] + " = " + SIMD_const_values[i]+";" else: SIMD_RATIONAL_decls += indent + "const double " + "tmp" + SIMD_const_varnms[i] + " = " + SIMD_const_values[i] + ";\n" SIMD_RATIONAL_decls += indent + "const REAL_SIMD_ARRAY " + SIMD_const_varnms[i] + " = ConstSIMD(" + "tmp" + SIMD_const_varnms[i] + ");\n" SIMD_RATIONAL_decls += "\n" # Step 7: Construct final output string final_Ccode_output_str = commentblock # Step 7a: Output C code in indented curly brackets if # outCparams.includebraces = True if outCparams.includebraces == "True": final_Ccode_output_str += outCparams.preindent+"{\n" final_Ccode_output_str += prestring + RATIONAL_decls + SIMD_RATIONAL_decls + outstring + poststring if outCparams.includebraces == "True": final_Ccode_output_str += outCparams.preindent+"}\n" # Step 8: If filename == "stdout", then output # C code to standard out (useful for copy-paste or interactive # mode). Otherwise output to file specified in variable name. if filename == "stdout": # Output to standard out (stdout; "the screen") print(final_Ccode_output_str) elif filename == "returnstring": return final_Ccode_output_str else: # Output to the file specified by the function input parameter string 'filename': with open(filename, outCparams.outCfileaccess) as file: file.write(final_Ccode_output_str) successstr = "" if outCparams.outCfileaccess == "a": successstr = "Appended " elif outCparams.outCfileaccess == "w": successstr = "Wrote " print(successstr + "to file \"" + filename + "\"")
def test_ccode_standard(): assert ccode(expm1(x), standard='c99') == 'expm1(x)' assert ccode(nan, standard='c99') == 'NAN' assert ccode(float('nan'), standard='c99') == 'NAN'
def test_ccode_Type(): assert ccode(Type('float')) == 'float' assert ccode(intc) == 'int'
def test_ccode_sqrt(): assert ccode(sqrt(x)) == "sqrt(x)" assert ccode(x**0.5) == "sqrt(x)" assert ccode(sqrt(x)) == "sqrt(x)"
def __str__(self): return sym.ccode(self.sym_func)
def test_ccode_Max_Min(): assert ccode(Max(x, 0), standard="C89") == "((0 > x) ? 0 : x)" assert ccode(Max(x, 0), standard="C99") == "fmax(0, x)" assert ccode(Min(x, 0, sqrt(x)), standard="c89") == ( "((0 < ((x < sqrt(x)) ? x : sqrt(x))) ? 0 : ((x < sqrt(x)) ? x : sqrt(x)))" )
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2*x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0/3.0)' assert ccode(x**Rational(2, 3), type_aliases={real: float80}) == 'powl(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**0.5, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 0.5)' assert ccode(x**Rational(16, 5), user_functions={'Pow': _cond_cfunc}) == 'pow(x, 16.0/5.0)' _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: 'exp2(%s)' % exp), (lambda base, exp: base != 2, 'pow')] # Related to gh-11353 assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)' # For issue 14160 assert ccode(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x/(y*y)'
def test_Element(): assert ccode(Element("x", "ij")) == "x[i][j]" assert ccode(Element("x", "ij", strides="kl", offset="o")) == "x[i*k + j*l + o]" assert ccode(Element("x", (3,))) == "x[3]" assert ccode(Element("x", (3, 4, 5))) == "x[3][4][5]"
def test_dereference_printing(): expr = x + y + sin(z) + z assert ccode(expr, dereference=[z]) == "x + y + (*z) + sin((*z))"
def test_sparse_matrix(): # gh-15791 assert 'Not supported in C' in ccode(SparseMatrix([[1, 2, 3]]))
def test_ccode_Assignment(): assert ccode(Assignment(x, y + z)) == 'x = y + z;' assert ccode(aug_assign(x, '+', y + z)) == 'x += y + z;'
def test_ccode_Integer(): assert ccode(Integer(67)) == "67" assert ccode(Integer(-1)) == "-1"
def test_ccode_math_macros(): assert ccode(z + exp(1)) == 'z + M_E' assert ccode(z + log2(exp(1))) == 'z + M_LOG2E' assert ccode(z + 1 / log(2)) == 'z + M_LOG2E' assert ccode(z + log(2)) == 'z + M_LN2' assert ccode(z + log(10)) == 'z + M_LN10' assert ccode(z + pi) == 'z + M_PI' assert ccode(z + pi / 2) == 'z + M_PI_2' assert ccode(z + pi / 4) == 'z + M_PI_4' assert ccode(z + 1 / pi) == 'z + M_1_PI' assert ccode(z + 2 / pi) == 'z + M_2_PI' assert ccode(z + 2 / sqrt(pi)) == 'z + M_2_SQRTPI' assert ccode(z + 2 / Sqrt(pi)) == 'z + M_2_SQRTPI' assert ccode(z + sqrt(2)) == 'z + M_SQRT2' assert ccode(z + Sqrt(2)) == 'z + M_SQRT2' assert ccode(z + 1 / sqrt(2)) == 'z + M_SQRT1_2' assert ccode(z + 1 / Sqrt(2)) == 'z + M_SQRT1_2'