Skip to content
This repository
Browse code

weave: Make sure blitz converters don't issue undef code

  • Loading branch information...
commit 0912c59124cb8ea7a5469397e84b45de96fd8884 1 parent ee8744a
Travis Oliphant authored

Showing 2 changed files with 33 additions and 94 deletions. Show diff stats Hide diff stats

  1. +22 90 Lib/weave/doc/tutorial.html
  2. +11 4 Lib/weave/standard_array_spec.py
112 Lib/weave/doc/tutorial.html
@@ -1233,7 +1233,8 @@
1233 1233 <p> The example is available in <code>examples/tuple_return.py</code>.
1234 1234 It also
1235 1235 has the dubious honor of demonstrating how much <code>inline()</code>
1236   -can slow things down. The C version here is about 10 times slower than
  1236 +can slow things down. The C version here is about 7-10 times slower
  1237 +than
1237 1238 the Python
1238 1239 version. Of course, something so trivial has no reason to be written in
1239 1240 C anyway.
@@ -1285,44 +1286,7 @@
1285 1286 And here is the extension function generated by <code>inline</code>:
1286 1287 <blockquote>
1287 1288 <pre><code>
1288   - static PyObject* compiled_func(PyObject*self, PyObject* args)
1289   - {
1290   - // The Py_None needs an incref before returning
1291   - PyObject *return_val = NULL;
1292   - int exception_occured = 0;
1293   - PyObject *py__locals = NULL;
1294   - PyObject *py__globals = NULL;
1295   - PyObject *py_a;
1296   - py_a = NULL;
1297   -
1298   - if(!PyArg_ParseTuple(args,"OO:compiled_func",&amp;py__locals,&amp;py__globals))
1299   - return NULL;
1300   - try
1301   - {
1302   - PyObject* raw_locals = py_to_raw_dict(py__locals,"_locals");
1303   - PyObject* raw_globals = py_to_raw_dict(py__globals,"_globals");
1304   - int a = py_to_int (get_variable("a",raw_locals,raw_globals),"a");
1305   - /* Here is the inline code */
1306   - printf("%d\n",a);
1307   - /* I would like to fill in changed locals and globals here... */
1308   - }
1309   - catch( Py::Exception&amp; e)
1310   - {
1311   - return_val = Py::Null();
1312   - exception_occured = 1;
1313   - }
1314   - if(!return_val &amp;&amp; !exception_occured)
1315   - {
1316   -
1317   - Py_INCREF(Py_None);
1318   - return_val = Py_None;
1319   - }
1320   - /* clean up code */
1321   -
1322   - /* return */
1323   - return return_val;
1324   - }
1325   - </code></pre>
  1289 +static PyObject* compiled_func(PyObject*self, PyObject* args)<br>{<br> py::object return_val;<br> int exception_occured = 0;<br> PyObject *py__locals = NULL;<br> PyObject *py__globals = NULL;<br> PyObject *py_a;<br> py_a = NULL;<br><br> if(!PyArg_ParseTuple(args,"OO:compiled_func",&amp;py__locals,&amp;py__globals))<br> return NULL;<br> try<br> {<br> PyObject* raw_locals = py_to_raw_dict(py__locals,"_locals");<br> PyObject* raw_globals = py_to_raw_dict(py__globals,"_globals");<br> /* argument conversion code */<br> py_a = get_variable("a",raw_locals,raw_globals);<br> int a = convert_to_int(py_a,"a");<br> /* inline code */<br> /* NDARRAY API VERSION 90907 */<br> printf("%d\n",a); /*I would like to fill in changed locals and globals here...*/<br><br> }<br> catch(...)<br> {<br> return_val = py::object();<br> exception_occured = 1;<br> }<br> /* cleanup code */<br> if(!(PyObject*)return_val &amp;&amp; !exception_occured)<br> {<br><br> return_val = Py_None;<br> }<br><br> return return_val.disown();<br>}<br> </code><br></pre>
1326 1290 </blockquote>
1327 1291 Every inline function takes exactly two arguments -- the local and
1328 1292 global
@@ -1333,7 +1297,8 @@
1333 1297 variables
1334 1298 aren't found, or there is an error converting a Python variable to the
1335 1299 appropriate type in C++, an exception is raised. The C++ exception
1336   -is automatically converted to a Python exception by CXX and returned to
  1300 +is automatically converted to a Python exception by SCXX and returned
  1301 +to
1337 1302 Python.
1338 1303 The <code>py_to_int()</code> function illustrates how the conversions
1339 1304 and
@@ -1345,7 +1310,8 @@
1345 1310 calls
1346 1311 <code>handle_bad_type()</code> which gathers information about what
1347 1312 went wrong
1348   -and then raises a CXX TypeError which returns to Python as a TypeError.
  1313 +and then raises a SCXX TypeError which returns to Python as a
  1314 +TypeError.
1349 1315 <blockquote>
1350 1316 <pre><code>
1351 1317 int py_to_int(PyObject* py_obj,char* name)
@@ -1473,19 +1439,19 @@
1473 1439 </tr>
1474 1440 <tr>
1475 1441 <td>&nbsp;&nbsp; string</td>
1476   - <td>&nbsp;&nbsp; Py::String</td>
  1442 + <td>&nbsp;&nbsp; py::string</td>
1477 1443 </tr>
1478 1444 <tr>
1479 1445 <td>&nbsp;&nbsp; list</td>
1480   - <td>&nbsp;&nbsp; Py::List</td>
  1446 + <td>&nbsp;&nbsp; py::list</td>
1481 1447 </tr>
1482 1448 <tr>
1483 1449 <td>&nbsp;&nbsp; dict</td>
1484   - <td>&nbsp;&nbsp; Py::Dict</td>
  1450 + <td>&nbsp;&nbsp; py::dict</td>
1485 1451 </tr>
1486 1452 <tr>
1487 1453 <td>&nbsp;&nbsp; tuple</td>
1488   - <td>&nbsp;&nbsp; Py::Tuple</td>
  1454 + <td>&nbsp;&nbsp; py::tuple</td>
1489 1455 </tr>
1490 1456 <tr>
1491 1457 <td>&nbsp;&nbsp; file</td>
@@ -1493,14 +1459,14 @@
1493 1459 </tr>
1494 1460 <tr>
1495 1461 <td>&nbsp;&nbsp; callable</td>
1496   - <td>&nbsp;&nbsp; PyObject*</td>
  1462 + <td>&nbsp;&nbsp; py::object</td>
1497 1463 </tr>
1498 1464 <tr>
1499 1465 <td>&nbsp;&nbsp; instance</td>
1500   - <td>&nbsp;&nbsp; PyObject*</td>
  1466 + <td>&nbsp;&nbsp; py::object</td>
1501 1467 </tr>
1502 1468 <tr>
1503   - <td>&nbsp;&nbsp; NumPy.array</td>
  1469 + <td>&nbsp;&nbsp; numpy.ndarray</td>
1504 1470 <td>&nbsp;&nbsp; PyArrayObject*</td>
1505 1471 </tr>
1506 1472 <tr>
@@ -1511,8 +1477,8 @@
1511 1477 </table>
1512 1478 </center>
1513 1479 <p>
1514   -The <code>Py::</code> namespace is defined by the <a
1515   - href="http://cxx.sourceforge.net/">CXX</a> library which has C++ class
  1480 +The <code>Py::</code> namespace is defined by the SCXX library which
  1481 +has C++ class
1516 1482 equivalents for many Python types. <code>std::</code> is the namespace
1517 1483 of the
1518 1484 standard library in C++.
@@ -1534,42 +1500,7 @@
1534 1500 <code>weave.inline("")</code>. </p>
1535 1501 <blockquote>
1536 1502 <pre><code>
1537   - static PyObject* compiled_func(PyObject*self, PyObject* args)
1538   - {
1539   - PyObject *return_val = NULL;
1540   - int exception_occured = 0;
1541   - PyObject *py__locals = NULL;
1542   - PyObject *py__globals = NULL;
1543   - PyObject *py_a;
1544   - py_a = NULL;
1545   -
1546   - if(!PyArg_ParseTuple(args,"OO:compiled_func",&amp;py__locals,&amp;py__globals))
1547   - return NULL;
1548   - try
1549   - {
1550   - PyObject* raw_locals = py_to_raw_dict(py__locals,"_locals");
1551   - PyObject* raw_globals = py_to_raw_dict(py__globals,"_globals");
1552   - /* argument conversion code */
1553   - /* inline code */
1554   - /*I would like to fill in changed locals and globals here...*/
1555   -
1556   - }
1557   - catch( Py::Exception&amp; e)
1558   - {
1559   - return_val = Py::Null();
1560   - exception_occured = 1;
1561   - }
1562   - /* cleanup code */
1563   - if(!return_val &amp;&amp; !exception_occured)
1564   - {
1565   -
1566   - Py_INCREF(Py_None);
1567   - return_val = Py_None;
1568   - }
1569   -
1570   - return return_val;
1571   - }
1572   - </code></pre>
  1503 +</code></pre>
1573 1504 </blockquote>
1574 1505 The <code>/* inline code */</code> section is filled with the code
1575 1506 passed to
@@ -1627,7 +1558,7 @@
1627 1558 <a name="inline_python_argument_conversion"></a>
1628 1559 <h3> String, List, Tuple, and Dictionary Conversion </h3>
1629 1560 Strings, Lists, Tuples and Dictionary conversions are all converted to
1630   -CXX types by default.
  1561 +SCXX types by default.
1631 1562 For the following code,
1632 1563 <blockquote>
1633 1564 <pre><code>
@@ -1649,7 +1580,7 @@
1649 1580 <blockquote>
1650 1581 <pre><code> <br> static Py::List py_to_list(PyObject* py_obj,char* name)<br> {<br> if (!py_obj || !PyList_Check(py_obj))<br> handle_bad_type(py_obj,"list", name);<br> return Py::List(py_obj);<br> }<br> <br> static Py::String py_to_string(PyObject* py_obj,char* name)<br> {<br> if (!PyString_Check(py_obj))<br> handle_bad_type(py_obj,"string", name);<br> return Py::String(py_obj);<br> }<br><br> static Py::Dict py_to_dict(PyObject* py_obj,char* name)<br> {<br> if (!py_obj || !PyDict_Check(py_obj))<br> handle_bad_type(py_obj,"dict", name);<br> return Py::Dict(py_obj);<br> }<br> <br> static Py::Tuple py_to_tuple(PyObject* py_obj,char* name)<br> {<br> if (!py_obj || !PyTuple_Check(py_obj))<br> handle_bad_type(py_obj,"tuple", name);<br> return Py::Tuple(py_obj);<br> }<br> </code></pre>
1651 1582 </blockquote>
1652   -CXX handles reference counts on for strings, lists, tuples, and
  1583 +SCXX handles reference counts on for strings, lists, tuples, and
1653 1584 dictionaries,
1654 1585 so clean up code isn't necessary.
1655 1586 <a name="#inline_file_argument_conversion"></a>
@@ -2242,7 +2173,8 @@
2242 2173 <h2>The Tools</h2>
2243 2174 <code>weave.blitz</code> relies heavily on several remarkable tools. On
2244 2175 the Python side, the main facilitators are Jermey Hylton's parser
2245   -module and Jim Huginin's NumPy module. On the compiled language side,
  2176 +module and Travis Oliphant's NumPy module. On the compiled language
  2177 +side,
2246 2178 Todd Veldhuizen's blitz++ array library, written in C++ (shhhh. don't
2247 2179 tell David Beazley), does the heavy lifting. Don't assume that, because
2248 2180 it's C++, it's much slower than C or Fortran. Blitz++ uses a jaw
@@ -2330,7 +2262,7 @@
2330 2262 other than that, they are the same. Further, most of the concept and
2331 2263 capabilities of the two libraries are remarkably similar. It is
2332 2264 satisfying that two completely different implementations solved the
2333   -problem with similar basic architectures. It is also fortitous. The
  2265 +problem with similar basic architectures. It is also fortuitous. The
2334 2266 work involved in converting NumPy expressions to blitz expressions was
2335 2267 greatly diminished.
2336 2268 As an example, consider the code for slicing an array in Python with a
15 Lib/weave/standard_array_spec.py
@@ -174,12 +174,19 @@ def declaration_code(self,templatize = 0,inline=0):
174 174 'int D%(name)s = %(array_name)s->nd;\n' \
175 175 '%(num_type)s* %(name)s = (%(num_type)s*) %(array_name)s->data;\n'
176 176 code = code % res
  177 + self.__doundef=1
177 178 return code
178 179
179 180 def cleanup_code(self):
180 181 code = common_base_converter.cleanup_code(self)
181   - cap_name = self.name.upper()
182   - newcode = "#undef %(cap_name)s1\n#undef %(cap_name)s2\n"\
183   - "#undef %(cap_name)s3\n#undef %(cap_name)s4\n" % {'cap_name':cap_name}
184   - code = "%s%s" % (code, newcode)
  182 + try:
  183 + if self.__doundef != 1:
  184 + return code
  185 + cap_name = self.name.upper()
  186 + newcode = "#undef %(cap_name)s1\n#undef %(cap_name)s2\n"\
  187 + "#undef %(cap_name)s3\n#undef %(cap_name)s4\n"\
  188 + % {'cap_name':cap_name}
  189 + code = "%s%s" % (code, newcode)
  190 + except AttributeError:
  191 + pass
185 192 return code

0 comments on commit 0912c59

Please sign in to comment.
Something went wrong with that request. Please try again.