• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Ankit Daftery 2011-2012.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 /**
7  *  @brief An example to demonstrate use of universal functions or ufuncs
8  *
9  *
10  * @todo Calling the overloaded () operator is in a roundabout manner, find a simpler way
11  *       None of the methods like np::add, np::multiply etc are supported as yet
12  */
13 
14 #include <boost/python/numpy.hpp>
15 #include <iostream>
16 
17 namespace p = boost::python;
18 namespace np = boost::python::numpy;
19 
20 
21 // Create the structs necessary to implement the ufuncs
22 // The typedefs *must* be made
23 
24 struct UnarySquare
25 {
26   typedef double argument_type;
27   typedef double result_type;
28 
operator ()UnarySquare29   double operator()(double r) const { return r * r;}
30 };
31 
32 struct BinarySquare
33 {
34   typedef double first_argument_type;
35   typedef double second_argument_type;
36   typedef double result_type;
37 
operator ()BinarySquare38   double operator()(double a,double b) const { return (a*a + b*b) ; }
39 };
40 
main(int argc,char ** argv)41 int main(int argc, char **argv)
42 {
43   // Initialize the Python runtime.
44   Py_Initialize();
45   // Initialize NumPy
46   np::initialize();
47   // Expose the struct UnarySquare to Python as a class, and let ud be the class object
48   p::object ud = p::class_<UnarySquare, boost::shared_ptr<UnarySquare> >("UnarySquare")
49     .def("__call__", np::unary_ufunc<UnarySquare>::make());
50   // Let inst be an instance of the class ud
51   p::object inst = ud();
52   // Use the "__call__" method to call the overloaded () operator and print the value
53   std::cout << "Square of unary scalar 1.0 is " << p::extract <char const * > (p::str(inst.attr("__call__")(1.0))) << std::endl ;
54   // Create an array in C++
55   int arr[] = {1,2,3,4} ;
56   // ..and use it to create the ndarray in Python
57   np::ndarray demo_array = np::from_data(arr, np::dtype::get_builtin<int>() , p::make_tuple(4), p::make_tuple(4), p::object());
58   // Print out the demo array
59   std::cout << "Demo array is " << p::extract <char const * > (p::str(demo_array)) << std::endl ;
60   // Call the "__call__" method to perform the operation and assign the value to result_array
61   p::object result_array = inst.attr("__call__")(demo_array) ;
62   // Print the resultant array
63   std::cout << "Square of demo array is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
64   // Lets try the same with a list
65   p::list li ;
66   li.append(3);
67   li.append(7);
68   // Print out the demo list
69   std::cout << "Demo list is " << p::extract <char const * > (p::str(li)) << std::endl ;
70   // Call the ufunc for the list
71   result_array = inst.attr("__call__")(li) ;
72   // And print the list out
73   std::cout << "Square of demo list is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
74   // Now lets try Binary ufuncs
75   // Expose the struct BinarySquare to Python as a class, and let ud be the class object
76   ud = p::class_<BinarySquare, boost::shared_ptr<BinarySquare> >("BinarySquare")
77     .def("__call__", np::binary_ufunc<BinarySquare>::make());
78   // Again initialise inst as an instance of the class ud
79   inst = ud();
80   // Print the two input listsPrint the two input lists
81   std::cout << "The two input list for binary ufunc are " << std::endl << p::extract <char const * > (p::str(demo_array)) << std::endl << p::extract <char const * > (p::str(demo_array)) << std::endl ;
82   // Call the binary ufunc taking demo_array as both inputs
83   result_array = inst.attr("__call__")(demo_array,demo_array) ;
84   std::cout << "Square of list with binary ufunc is " << p::extract <char const * > (p::str(result_array)) << std::endl ;
85 }
86 
87