def test13_templated_return_type(self): import cppyy cppyy.cppdef(""" struct RTTest_SomeStruct1 {}; template<class ...T> struct RTTest_TemplatedList {}; template<class ...T> auto rttest_make_tlist(T ... args) { return RTTest_TemplatedList<T...>{}; } namespace RTTest_SomeNamespace { struct RTTest_SomeStruct2 {}; template<class ...T> struct RTTest_TemplatedList2 {}; } template<class ...T> auto rttest_make_tlist2(T ... args) { return RTTest_SomeNamespace::RTTest_TemplatedList2<T...>{}; } """) from cppyy.gbl import rttest_make_tlist, rttest_make_tlist2, \ RTTest_SomeNamespace, RTTest_SomeStruct1 assert rttest_make_tlist(RTTest_SomeStruct1()) assert rttest_make_tlist(RTTest_SomeNamespace.RTTest_SomeStruct2()) assert rttest_make_tlist2(RTTest_SomeStruct1()) assert rttest_make_tlist2(RTTest_SomeNamespace.RTTest_SomeStruct2())
def test02_dir(self): """For the same reasons as test01_kdcraw, this used to crash.""" import cppyy, pydoc assert not '__abstractmethods__' in dir(cppyy.gbl.gInterpreter) assert '__class__' in dir(cppyy.gbl.gInterpreter) self.__class__.helpout = [] pydoc.doc(cppyy.gbl.gInterpreter) helptext = ''.join(self.__class__.helpout) assert 'TInterpreter' in helptext assert 'CPPInstance' in helptext assert 'AddIncludePath' in helptext cppyy.cppdef("namespace cppyy_regression_test { void iii() {}; }") assert not 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ assert not '__abstractmethods__' in dir(cppyy.gbl.cppyy_regression_test) assert '__class__' in dir(cppyy.gbl.cppyy_regression_test) assert 'iii' in dir(cppyy.gbl.cppyy_regression_test) assert not 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ assert cppyy.gbl.cppyy_regression_test.iii assert 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ self.__class__.helpout = [] pydoc.doc(cppyy.gbl.cppyy_regression_test) helptext = ''.join(self.__class__.helpout) assert 'CPPInstance' in helptext
def test11_templated_ctor(self): """Test templated constructors""" import cppyy cppyy.cppdef(""" template <typename T> class RTTest_SomeClassWithTCtor { public: template<typename R> RTTest_SomeClassWithTCtor(int n, R val) : m_double(n+val) {} double m_double; }; namespace RTTest_SomeNamespace { template <typename T> class RTTest_SomeClassWithTCtor { public: RTTest_SomeClassWithTCtor() : m_double(-1.) {} template<typename R> RTTest_SomeClassWithTCtor(int n, R val) : m_double(n+val) {} double m_double; }; } """) from cppyy import gbl assert round(gbl.RTTest_SomeClassWithTCtor[int](1, 3.1).m_double - 4.1, 8) == 0. RTTest2 = gbl.RTTest_SomeNamespace.RTTest_SomeClassWithTCtor assert round(RTTest2[int](1, 3.1).m_double - 4.1, 8) == 0. assert round(RTTest2[int]().m_double + 1., 8) == 0.
def test01_kdcraw(self): """Doc strings for KDcrawIface (used to crash).""" import cppyy, pydoc # TODO: run a find for these paths qtpath = "/usr/include/qt5" kdcraw_h = "/usr/include/KF5/KDCRAW/kdcraw/kdcraw.h" if not os.path.isdir(qtpath) or not os.path.exists(kdcraw_h): import warnings warnings.warn("no KDE/Qt found, skipping test01_kdcraw") return # need to resolve qt_version_tag for the incremental compiler; since # it's not otherwise used, just make something up cppyy.cppdef("int qt_version_tag = 42;") cppyy.add_include_path(qtpath) cppyy.include(kdcraw_h) from cppyy.gbl import KDcrawIface self.__class__.helpout = [] pydoc.doc(KDcrawIface.KDcraw) helptext = ''.join(self.__class__.helpout) assert 'KDcraw' in helptext assert 'CPPInstance' in helptext
def test02_non_type_template_args(self): """Use of non-types as template arguments""" import cppyy cppyy.cppdef("template<int i> int nt_templ_args() { return i; };") assert cppyy.gbl.nt_templ_args[1]() == 1 assert cppyy.gbl.nt_templ_args[256]() == 256
def test05_lambda_calls(self): """Call (global) lambdas""" import cppyy cppyy.cppdef("auto gMyLambda = [](int a) { return 40 + a; };") assert cppyy.gbl.gMyLambda assert cppyy.gbl.gMyLambda(2) == 42 assert cppyy.gbl.gMyLambda(40) == 80
def test04_type_deduction(self): import cppyy cppyy.cppdef(""" template <typename T> struct DeductTest_Wrap { static auto whatis(T t) { return t; } }; """) w = cppyy.gbl.DeductTest_Wrap[int]() three = w.whatis(3) assert three == 3
def test05_freshly_instantiated_map_type(self): """Instantiate a map from a newly defined class""" import cppyy cppyy.cppdef('template<typename T> struct Data { T fVal; };') from cppyy.gbl import std, Data results = std.map( std.string, Data(int) )() d = Data(int)(); d.fVal = 42 results['summary'] = d assert results.size() == 1 for tag, data in results: assert data.fVal == 42
def test05_lambda_calls(self): """Call (global) lambdas""" import cppyy cppyy.cppdef("auto gMyLambda = [](int a) { return 40 + a; };") assert cppyy.gbl.gMyLambda assert cppyy.gbl.gMyLambda(2) == 42 assert cppyy.gbl.gMyLambda(40) == 80 cppyy.cppdef("auto gime_a_lambda1() { return []() { return 42; }; }") l1 = cppyy.gbl.gime_a_lambda1() assert l1 assert l1() == 42 cppyy.cppdef("auto gime_a_lambda2() { int a = 4; return [a](int b) { return 42+a+b; }; }") l2 = cppyy.gbl.gime_a_lambda2() assert l2 assert l2(2) == 48 cppyy.cppdef("auto gime_a_lambda3(int a ) { return [a](int b) { return 42+a+b; }; }") l3 = cppyy.gbl.gime_a_lambda3(4) assert l3 assert l3(2) == 48
def test08_lambda_calls(self): """Call (global) lambdas""" import cppyy cppyy.cppdef("auto gMyLambda = [](int a) { return 40 + a; };") assert cppyy.gbl.gMyLambda assert cppyy.gbl.gMyLambda(2) == 42 assert cppyy.gbl.gMyLambda(40) == 80 if cppyy.gbl.gInterpreter.ProcessLine("__cplusplus;") >= 201402: cppyy.cppdef("auto gime_a_lambda1() { return []() { return 42; }; }") l1 = cppyy.gbl.gime_a_lambda1() assert l1 assert l1() == 42 cppyy.cppdef("auto gime_a_lambda2() { int a = 4; return [a](int b) { return 42+a+b; }; }") l2 = cppyy.gbl.gime_a_lambda2() assert l2 assert l2(2) == 48 cppyy.cppdef("auto gime_a_lambda3(int a ) { return [a](int b) { return 42+a+b; }; }") l3 = cppyy.gbl.gime_a_lambda3(4) assert l3 assert l3(2) == 48
def test03_replacement_of_eq(self): """A global templated function should work as a method""" import cppyy cppyy.cppdef("""template<class C> bool cont_eq(const typename C::iterator& a, const typename C::iterator& b) { return a != b; }""") a = cppyy.gbl.std.list[int]() assert a.begin() == a.end() a.begin().__class__.__eq__ = cppyy.gbl.cont_eq[cppyy.gbl.std.list[int]] assert not (a.begin() == a.end())
def test04_template_aliases(self): """Access to templates made available with 'using'""" import cppyy # through dictionary davec = cppyy.gbl.DA_vector["float"]() davec += range(10) assert davec[5] == 5 # through interpreter cppyy.cppdef("template<typename T> using IA_vector = std::vector<T>;") iavec = cppyy.gbl.IA_vector["float"]() iavec += range(10) assert iavec[5] == 5
def test18_overload(self): """Test usage of __overload__""" import cppyy cppyy.cppdef("""struct Variable { Variable(double lb, double ub, double value, bool binary, bool integer, const string& name) {} Variable(int) {} };""") for sig in [ 'double, double, double, bool, bool, const string&', 'double,double,double,bool,bool,const string&', 'double lb, double ub, double value, bool binary, bool integer, const string& name' ]: assert cppyy.gbl.Variable.__init__.__overload__(sig)
def test_builtin_arctan2(self): # space la_str = self.import_trig + """c = atan2(a, b) where a: scalar b: scalar""" func_info = self.gen_func_info(la_str) self.assertEqual(func_info.numpy_func(3, 2).c, np.arctan2(3, 2)) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " return {}(3, 2).c == atan2(3, 2);".format( func_info.eig_func_name), "}" ] cppyy.cppdef('\n'.join(func_list))
def generate_GA_setters(): DEFS = """ #include <ogdf/basic/GraphAttributes.h> #include <ogdf/cluster/ClusterGraphAttributes.h> namespace ogdf_pythonization { void GraphAttributes_set_directed(ogdf::GraphAttributes &GA, bool v) { GA.directed() = v; }""" for name, obj, val in GA_FIELDS: DEFS += ( "\n\tvoid GraphAttributes_set_{name}(ogdf::GraphAttributes &GA, {obj} o, {val} v) " "{{ GA.{name}(o) = v; }}\n".format(name=name, obj=obj, val=val)) for name, obj, val in CGA_FIELDS: DEFS += ( "\n\tvoid GraphAttributes_set_{name}(ogdf::ClusterGraphAttributes &GA, {obj} o, {val} v) " "{{ GA.{name}(o) = v; }}\n".format(name=name, obj=obj, val=val)) cppyy.cppdef(DEFS + "};")
def test_builtin_trig_power(self): # space la_str = self.import_trig + """b = asin^2(a) where a: scalar""" func_info = self.gen_func_info(la_str) self.assertEqual( func_info.numpy_func(0.4).b, np.power(np.arcsin(0.4), 2)) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " return {}(0.4).b == pow(asin(0.4), 2);".format( func_info.eig_func_name), "}" ] cppyy.cppdef('\n'.join(func_list))
def get_cpp_function(node): c_code = to_cpp(node, c_data_type="double") import cppyy cppyy.cppdef(c_code) # print(c_code) from cppyy.gbl import spn_many import numpy as np def python_eval_func(data): results = np.zeros((data.shape[0], 1)) spn_many(data, results, data.shape[0]) return results return python_eval_func
def test17_chaining(self): """Respective return values of temporaries should not go away""" import cppyy cppyy.cppdef("""namespace Lifeline { struct A1 { A1(int x) : x(x) {} int x; }; struct A2 { A2(int x) { v.emplace_back(x); } std::vector<A1> v; std::vector<A1>& get() { return v; } }; struct A3 { A3(int x) { v.emplace_back(x); } std::vector<A2> v; std::vector<A2>& get() { return v; } }; struct A4 { A4(int x) { v.emplace_back(x); } std::vector<A3> v; std::vector<A3>& get() { return v; } }; struct A5 { A5(int x) { v.emplace_back(x); } std::vector<A4> v; std::vector<A4>& get() { return v; } }; A5 gime(int i) { return A5(i); } }""") assert cppyy.gbl.Lifeline.gime(42).get()[0].get()[0].get()[0].get()[0].x == 42
def __init__(self, code_gen_results): """ Compile a system so that it can be instanciated and, hence, executed code_gen_results - the returned results of dy.generate_code Note: internally the c++ interpreter Cling C++ interpreter is used that is interfaced by Python via https://pypi.org/project/cppyy/ . """ import cppyy global system_instance_counter # # Note: # # Issue: https://bitbucket.org/wlav/cppyy/issues/295/q-reset-interpreter-or-multiple-instances # # Symbols once create in the cppyy.glb namespace cannot be deleted or overwritten. # Therefore, all code is wrapped into a namespace with a unique name that involves a # counter that increases for each call of cppyy.cppdef(src). Even if an instance of CompiledCode # is destructed, the compiled c++ module remains in the cppyy.glb namespace, hence, over time # symbols are accumulated. Hence, this is a memory leak. I do not know how to solve this. # ortd_auto_namespace_id = system_instance_counter system_instance_counter = system_instance_counter + 1 algorithm_sourcecode, manifest = code_gen_results[ 'algorithm_sourcecode'], code_gen_results['manifest'] self._manifest = manifest # wrap all classes into a unique namespace src = 'namespace ' + 'ortd_system_ns' + str( ortd_auto_namespace_id) + '{\n' + algorithm_sourcecode + '\n}' # send sourcecode to jit-compiler cppyy.cppdef(src) # load module and extract the main class 'simulation' cpp_class_of_system = getattr( cppyy.gbl, 'ortd_system_ns' + str(ortd_auto_namespace_id)).simulation # store self._cpp_class_of_system = cpp_class_of_system
def test21_initializer_list_and_temporary(self): """Conversion rules when selecting intializer_list v.s. temporary""" import cppyy cppyy.cppdef(""" namespace regression_test21 { std::string what_called = ""; class Foo { public: Foo() = default; Foo(int i) { what_called += "Foo(int)"; } Foo(std::initializer_list<uint8_t> il) { std::ostringstream os; os << "Foo(il<size=" << il.size() << ">)"; what_called += os.str(); } }; class Bar { public: Bar() = default; Bar(int i) { what_called = "Bar(int)"; } Bar(std::initializer_list<uint8_t> il) { std::ostringstream os; os << "Bar(il<size=" << il.size() << ">)"; what_called += os.str(); } Bar(Foo x) { what_called += "Bar(Foo)"; } }; }""") r21 = cppyy.gbl.regression_test21 assert len(r21.what_called) == 0 r21.Bar(1) assert r21.what_called == 'Bar(int)' r21.what_called = '' r21.Bar([1,2]) # used to call Bar(Foo x) through implicit conversion assert r21.what_called == 'Bar(il<size=2>)'
def test01_deque_byvalue_regression(self): """Return by value of a deque used to crash""" import cppyy assert cppyy.cppdef("std::deque<long double> f() { std::deque<long double> d ; return d ; }") x = cppyy.gbl.f() assert x del x
def test19_signed_char_ref(self): """Signed char executor was self-referencing""" import cppyy cppyy.cppdef(""" class SignedCharRefGetter { public: void setter(signed char sc) { m_c = sc; } signed char& getter() { return m_c; } signed char m_c; };""") obj = cppyy.gbl.SignedCharRefGetter() obj.setter('c') assert obj.getter() == 'c'
def test22_copy_constructor(self): """Copy construct an object into an empty (NULL) proxy""" import cppyy, gc cppyy.cppdef(""" namespace regression_test22 { struct Countable { static int s_count; Countable() { ++s_count; } Countable(const Countable&) { ++s_count; } Countable& operator=(const Countable&) { return *this; } ~Countable() { --s_count; } }; int Countable::s_count = 0; }""") r22 = cppyy.gbl.regression_test22 assert r22.Countable.s_count == 0 c = r22.Countable() assert r22.Countable.s_count == 1 raises(ReferenceError, c.__init__, r22.Countable()) gc.collect() assert r22.Countable.s_count == 1 c.__assign__(r22.Countable()) gc.collect() assert r22.Countable.s_count == 1 c.__destruct__() assert r22.Countable.s_count == 0 c.__init__(r22.Countable()) gc.collect() assert r22.Countable.s_count == 1 del c gc.collect() assert r22.Countable.s_count == 0 c = cppyy.bind_object(cppyy.nullptr, r22.Countable) assert r22.Countable.s_count == 0 c.__init__(r22.Countable()) gc.collect() assert r22.Countable.s_count == 1
def test_constant_pi(self): # space la_str = self.import_trig+"""A = sin(π/a) where a: scalar""" func_info = self.gen_func_info(la_str) self.assertEqual(func_info.numpy_func(2).A, 1) # MATLAB test if TEST_MATLAB: mat_func = getattr(mat_engine, func_info.mat_func_name, None) self.assertEqual(np.array(mat_func(matlab.double([2]))['A']), 1) # eigen test cppyy.include(func_info.eig_file_name) func_list = ["bool {}(){{".format(func_info.eig_test_name), " return {}(2).A == 1;".format(func_info.eig_func_name), "}"] cppyy.cppdef('\n'.join(func_list))
def get_macro(self, key): try: return getattr(self.lib, "_" + key) except AttributeError: assert cppyy.cppdef(""" auto _%s = %s; """ % (key, key)), ("%s is not a defined macro" % key) self.get_macro(key)
def test27_boolarray2cpp(self): ''' Pass an bool array to a C++ function taking a bool* Fixes ROOT-10731 ''' try: import numpy as np except: raise ImportError("Cannot import numpy") import cppyy cppyy.cppdef('int convert(bool* x) { return x[0]; }') x1 = np.array([True], '?') # bool x2 = np.array([True], 'b') # signed char, treated as bool before y1 = cppyy.gbl.convert(x1) y2 = cppyy.gbl.convert(x2) assert y1 == 1 assert y2 == 1
def test_gallery_18(self): # sequence la_str = """n = ∑_T A_T||M_T v_T - [0 -1 1 0] M_T u_T||² where v_i: ℝ^3 u_i: ℝ^3 M_i: ℝ^(2×3) A_i: ℝ""" v = np.array([[1, 2, 3], [3, 4, 5]]) u = np.array([[2, 1, 3], [5, 8, 1]]) M = np.array([[[2, 2, 1], [2, 1, 1]], [[4, 2, 3], [3, 1, 2]]]) A = np.array([2, 6]) func_info = self.gen_func_info(la_str) self.assertTrue(np.isclose(func_info.numpy_func(v, u, M, A).n, 23722)) # eigen test cppyy.include(func_info.eig_file_name) func_list = ["bool {}(){{".format(func_info.eig_test_name), " std::vector<Eigen::Matrix<double, 3, 1> > v;", " Eigen::Matrix<double, 3, 1> v1;" " v1 << 1, 2, 3;", " Eigen::Matrix<double, 3, 1> v2;" " v2 << 3, 4, 5;", " v.push_back(v1);", " v.push_back(v2);", " std::vector<Eigen::Matrix<double, 3, 1> > u;", " Eigen::Matrix<double, 3, 1> u1;" " u1 << 2, 1, 3;", " Eigen::Matrix<double, 3, 1> u2;" " u2 << 5, 8, 1;", " u.push_back(u1);", " u.push_back(u2);", " std::vector<Eigen::Matrix<double, 2, 3> > M;", " Eigen::Matrix<double, 2, 3> M1;" " M1 << 2, 2, 1, 2, 1, 1;", " Eigen::Matrix<double, 2, 3> M2;" " M2 << 4, 2, 3, 3, 1, 2;", " M.push_back(M1);", " M.push_back(M2);", " std::vector<double> A = {2, 6};", " double C = {}(v, u, M, A).n;".format(func_info.eig_func_name), " return (abs(23722 - C) < {});".format(self.eps), "}"] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test14_virtual_dtors_and_del(self): """Usage of virtual destructors and Python-side del.""" import cppyy cppyy.cppdef(""" namespace VirtualDtor { class MyClass1 {}; // no virtual dtor ... class MyClass2 { public: virtual ~MyClass2() {} }; class MyClass3 : public MyClass2 {}; template<class T> class MyClass4 { public: virtual ~MyClass4() {} }; } """) VD = cppyy.gbl.VirtualDtor try: class MyPyDerived1(VD.MyClass1): pass except TypeError: pass else: assert not "should have failed" class MyPyDerived2(VD.MyClass2): pass d = MyPyDerived2() del d # used to crash # check a few more derivations that should not fail class MyPyDerived3(VD.MyClass3): pass class MyPyDerived4(VD.MyClass4[int]): pass
def test_kronecker_product_sparse_lhs(self): la_str = """A = T ⊗ P where T: ℝ ^ (2×3) sparse P: ℝ ^ (2×3): a sequence""" func_info = self.gen_func_info(la_str) t = [(0, 1), (1, 2)] value = np.array([2, 5]) T = scipy.sparse.coo_matrix((value, np.asarray(t).T), shape=(2, 3)) P = np.array([[5, 6, 7], [7, 8, 9]]) t1 = [(0, 3), (0, 4), (0, 5), (1, 3), (1, 4), (1, 5), (2, 6), (2, 7), (2, 8), (3, 6), (3, 7), (3, 8)] value1 = np.array([10, 12, 14, 14, 16, 18, 25, 30, 35, 35, 40, 45]) A = scipy.sparse.coo_matrix((value1, np.asarray(t1).T), shape=(4, 9)) self.assertSMatrixEqual(func_info.numpy_func(T, P).A, A) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " std::vector<Eigen::Triplet<double> > t2;", " t2.push_back(Eigen::Triplet<double>(0, 1, 2));", " t2.push_back(Eigen::Triplet<double>(1, 2, 5));", " Eigen::SparseMatrix<double> T(2, 3);", " T.setFromTriplets(t2.begin(), t2.end());" " Eigen::Matrix<double, 2, 3> P;", " P << 5, 6, 7, 7, 8, 9;", " std::vector<Eigen::Triplet<double> > t1;", " t1.push_back(Eigen::Triplet<double>(0, 3, 10));", " t1.push_back(Eigen::Triplet<double>(0, 4, 12));", " t1.push_back(Eigen::Triplet<double>(0, 5, 14));", " t1.push_back(Eigen::Triplet<double>(1, 3, 14));", " t1.push_back(Eigen::Triplet<double>(1, 4, 16));", " t1.push_back(Eigen::Triplet<double>(1, 5, 18));", " t1.push_back(Eigen::Triplet<double>(2, 6, 25));", " t1.push_back(Eigen::Triplet<double>(2, 7, 30));", " t1.push_back(Eigen::Triplet<double>(2, 8, 35));", " t1.push_back(Eigen::Triplet<double>(3, 6, 35));", " t1.push_back(Eigen::Triplet<double>(3, 7, 40));", " t1.push_back(Eigen::Triplet<double>(3, 8, 45));", " Eigen::SparseMatrix<double> A(4, 9);", " A.setFromTriplets(t1.begin(), t1.end());" " Eigen::SparseMatrix<double> B = {}(T, P).A;".format( func_info.eig_func_name), " return A.isApprox(B);", "}" ] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test07_typedef_identity(self): """Nested typedefs should retain identity""" import cppyy cppyy.cppdef("""namespace PyABC { struct S1 {}; struct S2 { typedef std::vector<const PyABC::S1*> S1_coll; }; }""") from cppyy.gbl import PyABC assert PyABC.S2.S1_coll assert 'S1_coll' in dir(PyABC.S2) assert not 'vector<const PyABC::S1*>' in dir(PyABC.S2) assert PyABC.S2.S1_coll is cppyy.gbl.std.vector('const PyABC::S1*')
def test03_instance_conversion(self): """Proxy object conversions""" import cppyy cpp = cppyy.gbl API = cpp.CPyCppyy cppyy.cppdef(""" class APICheck2 { public: virtual ~APICheck2() {} };""") m = cpp.APICheck2() voidp = API.Instance_AsVoidPtr(m) m2 = API.Instance_FromVoidPtr(voidp, 'APICheck2') assert m is m2
def test15_const_in_name(self): """Make sure 'const' is not erased when part of a name""" import cppyy cppyy.cppdef(""" struct Some0Class {} myvar0; struct constSome1Class {} myvar1; struct Some2Classconst {} myvar2; struct Some_const_Class3 {} myvar3; struct SomeconstClass4 {} myvar4; """) assert cppyy.gbl.myvar0 assert cppyy.gbl.myvar1 assert cppyy.gbl.myvar2 assert cppyy.gbl.myvar3 assert cppyy.gbl.myvar4
def test08_voidptr_array(self): """Example of access to array of void ptrs""" import cppyy cppyy.cppdef(""" namespace VoidPtrArray { typedef struct _name { _name() { p[0] = (void*)0x1; p[1] = (void*)0x2; p[2] = (void*)0x3; } void* p[3]; } name; }""") n = cppyy.gbl.VoidPtrArray.name() assert n.p[0] == 0x1 assert n.p[1] == 0x2 assert n.p[2] == 0x3 assert len(n.p) == 3
def test01_deque_byvalue_regression(self): """Return by value of a deque used to crash""" import cppyy assert cppyy.cppdef("""std::deque<long double> f() { std::deque<long double> d; d.push_back(0); return d ; }""") x = cppyy.gbl.f() assert x del x
def test04_variadic_function(self): """Call a variadic function""" import cppyy std = cppyy.gbl.std s = std.ostringstream('(')#TODO: fails on PyPy, std.ios_base.ate) s.seekp(1, s.cur) # Fails; wrong overload on PyPy, none on CPython #s << "(" cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap") assert s.str() == "(1, 4, aap, NULL)" cppyy.cppdef(""" template<typename... myTypes> int test04_variadic_func() { return sizeof...(myTypes); } """) assert cppyy.gbl.test04_variadic_func['int', 'double', 'void*']() == 3
def try_cppyy(): import cppyy cppyy.add_include_path("/usr/include/eigen3") def access(cls): cls.make_std_vector cls.make_matrix3 t_start = time.time() cppyy.cppdef(code) # Access some members to try and make it even for cppyy's lazy # instantiation. ns = cppyy.gbl.ns ns.ExampleClass[int] ns.ExampleClass[float, float] dt = time.time() - t_start return dt
def test09_optional(self): """Use of optional and nullopt""" import cppyy if 201703 <= cppyy.gbl.gInterpreter.ProcessLine("__cplusplus;"): assert cppyy.gbl.std.optional assert cppyy.gbl.std.nullopt cppyy.cppdef(""" enum Enum { A = -1 }; bool callopt(std::optional<Enum>) { return true; } """) a = cppyy.gbl.std.optional[cppyy.gbl.Enum]() assert cppyy.gbl.callopt(a) c = cppyy.gbl.nullopt assert cppyy.gbl.callopt(c)
def test_builtin_trig_matrix_cot(self): # space la_str = self.import_trig + """A = cot(T) where T: ℝ ^ (2×2): a sequence""" func_info = self.gen_func_info(la_str) T = np.array([[1, 2], [3, 4]]) self.assertDMatrixEqual(func_info.numpy_func(T).A, 1 / np.tan(T)) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " Eigen::Matrix<double, 2, 2> T;", " T << 1, 2, 4, 3;", " Eigen::Matrix<double, 2, 2> B = {}(T).A;".format( func_info.eig_func_name), " return ((B - T.unaryExpr<double(*)(double)>(&std::tan).cwiseInverse()).norm() == 0);", "}" ] cppyy.cppdef('\n'.join(func_list))
def test04_variadic_function(self): """Call a variadic function""" import cppyy std = cppyy.gbl.std s = std.ostringstream('(') #TODO: fails on PyPy, std.ios_base.ate) s.seekp(1, s.cur) # Fails; wrong overload on PyPy, none on CPython #s << "(" cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap") assert s.str() == "(1, 4, aap, NULL)" cppyy.cppdef(""" template<typename... myTypes> int test04_variadic_func() { return sizeof...(myTypes); } """) assert cppyy.gbl.test04_variadic_func['int', 'double', 'void*']() == 3
def test_scalar_pow(self): la_str = """C = A^2 where A: ℝ: a scalar""" func_info = self.gen_func_info(la_str) self.assertEqual(func_info.numpy_func(2).C, 4) # MATLAB test if TEST_MATLAB: mat_func = getattr(mat_engine, func_info.mat_func_name, None) self.assertEqual(np.array(mat_func(2)['C']), 4) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " double C = {}(2).C;".format(func_info.eig_func_name), " return (C == 4);", "}" ] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test_scalar_norm(self): la_str = """A = |a| where a: scalar""" func_info = self.gen_func_info(la_str) self.assertEqual(func_info.numpy_func(-2).A, 2) # MATLAB test if TEST_MATLAB: mat_func = getattr(mat_engine, func_info.mat_func_name, None) self.assertEqual(np.array(mat_func(-2)['A']), 2) # eigen test cppyy.include(func_info.eig_file_name) func_list = [ "bool {}(){{".format(func_info.eig_test_name), " double B = {}(-2).A;".format(func_info.eig_func_name), " return (B == 2);", "}" ] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test11_vector_of_pair(self): """Use of std::vector<std::pair>""" import cppyy # after the original bug report cppyy.cppdef(""" class PairVector { public: std::vector<std::pair<double, double>> vector_pair(const std::vector<std::pair<double, double>>& a) { return a; } }; """) from cppyy.gbl import PairVector a = PairVector() ll = [[1., 2.], [2., 3.], [3., 4.], [4., 5.]] v = a.vector_pair(ll) assert len(v) == 4 i = 0 for p in v: p.first == ll[i][0] p.second == ll[i][1] i += 1 assert i == 4 # TODO: nicer error handling for the following (current: template compilation failure trying # to assign a pair with <double, string> to <double, double>) # ll2 = ll[:] # ll2[2] = ll[2][:] # ll2[2][1] = 'a' # v = a.vector_pair(ll2) ll3 = ll[:] ll3[0] = 'a' raises(TypeError, a.vector_pair, ll3) ll4 = ll[:] ll4[1] = 'a' raises(TypeError, a.vector_pair, ll4)
def test_gallery_8(self): # sequence la_str = """`n(v)` = (∑_(i for i ∈ `N₁(v)`) α_i n(T_i))/||∑_(i for i ∈ `N₁(v)`) α_i n(T_i)|| where T_i: ℝ^(3×3) α_i: ℝ `N₁(v)`: {ℤ} n: ℝ^(3×3) -> ℝ^3""" func_info = self.gen_func_info(la_str) T = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 21, 3], [4, 5, 6], [7, 8, 9]]]) α = np.array([10, 2]) N1 = [1, 2] n = lambda p: p[0] B = np.array([0.38601376, 0.79776177, 0.46321651]) self.assertDMatrixApproximateEqual(func_info.numpy_func(T, α, N1, n).n_left_parenthesis_v_right_parenthesis, B) # eigen test cppyy.include(func_info.eig_file_name) func_list = ["bool {}(){{".format(func_info.eig_test_name), " std::vector<Eigen::Matrix<double, 3, 3>> T;", " Eigen::Matrix<double, 3, 3> A1;", " A1 << 1, 2, 3, 4, 5, 6, 7, 8, 9;", " Eigen::Matrix<double, 3, 3> A2;", " A2 << 10, 21, 3, 4, 5, 6, 7, 8, 9;", " T.push_back(A1);", " T.push_back(A2);", " std::vector<double> α;", " α.push_back(10);", " α.push_back(2);", " std::set<int > N1;", " N1.insert(1);", " N1.insert(2);", " std::function<Eigen::Matrix<double, 3, 1>(Eigen::Matrix<double, 3, 3>)> n;", " n = [](Eigen::Matrix<double, 3, 3> t)->Eigen::Matrix<double, 3, 1>{", " return t.row(0);", " };", " Eigen::Matrix<double, 3, 1> B;", " B << 0.38601376, 0.79776177, 0.46321651;", " Eigen::Matrix<double, 3, 1> C = {}(T, α, N1, n).n_left_parenthesis_v_right_parenthesis;".format(func_info.eig_func_name), " return ((B - C).norm() < {});".format(self.eps), "}"] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test_gallery_12(self): # sequence la_str = """E = 1/`σ_N`²`E_I` + ∑_(j for j>1) α_j²/`σ_S`_j² + ∑_(j for j>1) β_j²/`σ_T`_j² + ∑_j (ρ_j-ρ̄_j)²/`σ_ρ`_j² where `σ_N`: ℝ `E_I`: ℝ α_i : ℝ β_i : ℝ `σ_S`_i: ℝ `σ_T`_i: ℝ ρ_i: ℝ ρ̄_i: ℝ `σ_ρ`_i: ℝ ā_i: ℝ """ func_info = self.gen_func_info(la_str) σ_N = 3 E_I = 4 α = np.array([1, 2, 3]) β = np.array([1, 3, 2]) σ_S = np.array([2, 2, 7]) σ_T = np.array([5, 7, 3]) ρ = np.array([10, 2, 3]) ρ̄ = np.array([5, 2, 7]) σ_ρ = np.array([2, 3, 5]) ā = np.array([3, 1, 8]) self.assertTrue(np.isclose(func_info.numpy_func(σ_N, E_I, α, β, σ_S, σ_T, ρ, ρ̄, σ_ρ, ā).E, 9.146235827664398)) # eigen test cppyy.include(func_info.eig_file_name) func_list = ["bool {}(){{".format(func_info.eig_test_name), " std::vector<double> α = {1, 2, 3};", " std::vector<double> β = {1, 3, 2};", " std::vector<double> σ_S = {2, 2, 7};", " std::vector<double> σ_T = {5, 7, 3};", " std::vector<double> ρ = {10, 2, 3};", " std::vector<double> ρ̄ = {5, 2, 7};", " std::vector<double> σ_ρ = {2, 3, 5};", " std::vector<double> ā = {3, 1, 8};", " double C = {}(3, 4, α, β, σ_S, σ_T, ρ, ρ̄, σ_ρ, ā).E;".format(func_info.eig_func_name), " return (abs(9.146235827664398 - C) < {});".format(self.eps), "}"] cppyy.cppdef('\n'.join(func_list)) self.assertTrue(getattr(cppyy.gbl, func_info.eig_test_name)())
def test05_default_template_arguments(self): """Calling a templated method on a templated class with all defaults used to crash.""" import cppyy cppyy.cppdef(""" template<typename T> class AllDefault { public: AllDefault(int val) : m_t(val) {} template<int aap=1, int noot=2> int do_stuff() { return m_t+aap+noot; } public: T m_t; };""") a = cppyy.gbl.AllDefault[int](24) a.m_t = 21; assert a.do_stuff() == 24
def test08_using_of_static_data(self): """Derived class using static data of base""" import cppyy # TODO: the following should live in templates.h, but currently fails # in TClass::GetListOfMethods() cppyy.cppdef(""" template <typename T> struct BaseClassWithStatic { static T const ref_value; }; template <typename T> T const BaseClassWithStatic<T>::ref_value = 42; template <typename T> struct DerivedClassUsingStatic : public BaseClassWithStatic<T> { using BaseClassWithStatic<T>::ref_value; explicit DerivedClassUsingStatic(T x) : BaseClassWithStatic<T>() { m_value = x > ref_value ? ref_value : x; } T m_value; };""") # TODO: the ref_value property is inaccessible (offset == -1) # assert cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42 b1 = cppyy.gbl.DerivedClassUsingStatic["size_t"]( 0) b2 = cppyy.gbl.DerivedClassUsingStatic["size_t"](100) # assert b1.ref_value == 42 assert b1.m_value == 0 # assert b2.ref_value == 42 assert b2.m_value == 42
def test11_template_aliases(self): """Access to templates made available with 'using'""" import cppyy # through dictionary davec = cppyy.gbl.DA_vector["float"]() davec += range(10) assert davec[5] == 5 # through interpreter cppyy.cppdef("template<typename T> using IA_vector = std::vector<T>;") iavec = cppyy.gbl.IA_vector["float"]() iavec += range(10) assert iavec[5] == 5 # with variadic template if cppyy.gbl.gInterpreter.ProcessLine("__cplusplus;") > 201402: assert cppyy.gbl.using_problem.matryoshka[int, 3].type assert cppyy.gbl.using_problem.matryoshka[int, 3, 4].type assert cppyy.gbl.using_problem.make_vector[int , 3] assert cppyy.gbl.using_problem.make_vector[int , 3]().m_val == 3 assert cppyy.gbl.using_problem.make_vector[int , 4]().m_val == 4
def test03_pyfunc_doc(self): """Help on a generated pyfunc used to crash.""" import cppyy, distutils, pydoc, sys cppyy.add_include_path(distutils.sysconfig_get_python_inc()) if sys.hexversion < 0x3000000: cppyy.cppdef("#undef _POSIX_C_SOURCE") cppyy.cppdef("#undef _XOPEN_SOURCE") else: cppyy.cppdef("#undef slots") # potentially pulled in by Qt/xapian.h cppyy.cppdef("""#include "Python.h" long py2long(PyObject* obj) { return PyLong_AsLong(obj); }""") pydoc.doc(cppyy.gbl.py2long) assert 1 == cppyy.gbl.py2long(1)
def test04_avx(self): """Test usability of AVX by default.""" import cppyy, subprocess has_avx = False try: for line in open('/proc/cpuinfo', 'r'): if 'avx' in line: has_avx = True break except Exception: try: cli_arg = subprocess.check_output(['sysctl', 'machdep.cpu.features']) has_avx = 'avx' in cli_arg.decode("utf-8").strip().lower() except Exception: pass if has_avx: assert cppyy.cppdef('int check_avx() { return (int) __AVX__; }') assert cppyy.gbl.check_avx() # attribute error if compilation failed
def setup_class(cls): import cppyy cppyy.cppdef(""" #include <cmath> #include <iostream> #include <vector> //----- unsigned int gUint = 0; //----- class Abstract { public: virtual ~Abstract() {} virtual void abstract_method() = 0; virtual void concrete_method() = 0; }; void Abstract::concrete_method() { std::cout << "called Abstract::concrete_method" << std::endl; } //----- class Concrete : Abstract { public: Concrete(int n=42) : m_int(n), m_const_int(17) {} ~Concrete() {} virtual void abstract_method() { std::cout << "called Concrete::abstract_method" << std::endl; } virtual void concrete_method() { std::cout << "called Concrete::concrete_method" << std::endl; } void array_method(int* ad, int size) { for (int i=0; i < size; ++i) std::cout << ad[i] << ' '; std::cout << std::endl; } void array_method(double* ad, int size) { for (int i=0; i < size; ++i) std::cout << ad[i] << ' '; std::cout << std::endl; } Abstract* show_autocast() { return this; } operator const char*() { return "Hello operator const char*!"; } public: double m_data[4]; int m_int; const int m_const_int; }; //----- int global_function(int) { return 42; } double global_function(double) { return std::exp(1); } //----- namespace Namespace { class Concrete { public: class NestedClass { public: std::vector<int> m_v; }; }; int global_function(int i) { return 2*::global_function(i); } double global_function(double d) { return 2*::global_function(d); } } // namespace Namespace """)
def setup_class(cls): import cppyy # touch __version__ as a test assert hasattr(cppyy, '__version__') cppyy.cppdef(""" #include <cmath> #include <iostream> #include <vector> //----- unsigned int gUint = 0; //----- class Abstract { public: virtual ~Abstract() {} virtual std::string abstract_method() = 0; virtual void concrete_method() = 0; }; void Abstract::concrete_method() { std::cout << "called Abstract::concrete_method" << std::endl; } //----- class Concrete : Abstract { public: Concrete(int n=42) : m_int(n), m_const_int(17) {} ~Concrete() {} virtual std::string abstract_method() { return "called Concrete::abstract_method"; } virtual void concrete_method() { std::cout << "called Concrete::concrete_method" << std::endl; } void array_method(int* ad, int size) { for (int i=0; i < size; ++i) std::cerr << ad[i] << ' '; std::cerr << std::endl; } void array_method(double* ad, int size) { for (int i=0; i < size; ++i) std::cerr << ad[i] << ' '; std::cerr << std::endl; } void uint_ref_assign(unsigned int& target, unsigned int value) { target = value; } Abstract* show_autocast() { return this; } operator const char*() { return "Hello operator const char*!"; } public: double m_data[4]; int m_int; const int m_const_int; static int s_int; }; typedef Concrete Concrete_t; int Concrete::s_int = 321; std::string call_abstract_method(Abstract* a) { return a->abstract_method(); } //----- int global_function(int) { return 42; } double global_function(double) { return std::exp(1); } int call_int_int(int (*f)(int, int), int i1, int i2) { return f(i1, i2); } //----- namespace Namespace { class Concrete { public: class NestedClass { public: std::vector<int> m_v; }; }; int global_function(int i) { return 2*::global_function(i); } double global_function(double d) { return 2*::global_function(d); } } // namespace Namespace """)