2011-10-14 02:41:56 +08:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
2016-11-20 22:24:43 +08:00
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
2011-10-14 02:41:56 +08:00
|
|
|
* Atlanta, Georgia 30332-0415
|
|
|
|
* All Rights Reserved
|
|
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
|
|
|
|
* See LICENSE for the license information
|
|
|
|
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
2011-10-14 11:23:14 +08:00
|
|
|
* @file Method.ccp
|
|
|
|
* @author Frank Dellaert
|
2012-07-13 06:28:28 +08:00
|
|
|
* @author Richard Roberts
|
2011-10-14 02:41:56 +08:00
|
|
|
**/
|
|
|
|
|
2014-05-26 01:22:10 +08:00
|
|
|
#include "Method.h"
|
2016-09-10 06:37:48 +08:00
|
|
|
#include "Class.h"
|
2014-05-26 01:22:10 +08:00
|
|
|
#include "utilities.h"
|
2011-10-14 02:41:56 +08:00
|
|
|
|
2012-07-05 22:04:36 +08:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2014-05-26 01:22:10 +08:00
|
|
|
#include <boost/algorithm/string.hpp>
|
2011-10-14 02:41:56 +08:00
|
|
|
|
2014-05-26 01:22:10 +08:00
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
2011-10-14 02:41:56 +08:00
|
|
|
|
|
|
|
using namespace std;
|
2011-12-03 00:43:15 +08:00
|
|
|
using namespace wrap;
|
2011-10-14 02:41:56 +08:00
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2014-11-14 23:43:53 +08:00
|
|
|
bool Method::addOverload(Str name, const ArgumentList& args,
|
2016-11-20 22:24:43 +08:00
|
|
|
const ReturnValue& retVal, bool is_const,
|
|
|
|
boost::optional<const Qualified> instName,
|
|
|
|
bool verbose) {
|
2014-11-29 22:31:29 +08:00
|
|
|
bool first = MethodBase::addOverload(name, args, retVal, instName, verbose);
|
2014-11-14 23:43:53 +08:00
|
|
|
if (first)
|
|
|
|
is_const_ = is_const;
|
|
|
|
else if (is_const && !is_const_)
|
|
|
|
throw std::runtime_error(
|
2016-11-20 22:24:43 +08:00
|
|
|
"Method::addOverload now designated as const whereas before it was "
|
|
|
|
"not");
|
2014-11-14 23:43:53 +08:00
|
|
|
else if (!is_const && is_const_)
|
|
|
|
throw std::runtime_error(
|
2016-11-20 22:24:43 +08:00
|
|
|
"Method::addOverload now designated as non-const whereas before it "
|
|
|
|
"was");
|
2014-11-14 23:43:53 +08:00
|
|
|
return first;
|
2012-07-05 22:05:00 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 03:03:19 +08:00
|
|
|
/* ************************************************************************* */
|
2014-11-14 00:28:05 +08:00
|
|
|
void Method::proxy_header(FileWriter& proxyFile) const {
|
2014-11-14 23:43:53 +08:00
|
|
|
proxyFile.oss << " function varargout = " << matlabName()
|
2016-11-20 22:24:43 +08:00
|
|
|
<< "(this, varargin)\n";
|
2011-10-14 02:41:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2014-11-14 00:34:33 +08:00
|
|
|
string Method::wrapper_call(FileWriter& wrapperFile, Str cppClassName,
|
2016-11-20 22:24:43 +08:00
|
|
|
Str matlabUniqueName,
|
|
|
|
const ArgumentList& args) const {
|
2011-10-14 02:41:56 +08:00
|
|
|
// check arguments
|
|
|
|
// extra argument obj -> nargin-1 is passed !
|
|
|
|
// example: checkArguments("equals",nargout,nargin-1,2);
|
2014-11-30 02:34:46 +08:00
|
|
|
wrapperFile.oss << " checkArguments(\"" << matlabName()
|
2016-11-20 22:24:43 +08:00
|
|
|
<< "\",nargout,nargin-1," << args.size() << ");\n";
|
2011-10-14 02:41:56 +08:00
|
|
|
|
|
|
|
// get class pointer
|
|
|
|
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
|
2014-11-13 03:51:47 +08:00
|
|
|
wrapperFile.oss << " Shared obj = unwrap_shared_ptr<" << cppClassName
|
2016-11-20 22:24:43 +08:00
|
|
|
<< ">(in[0], \"ptr_" << matlabUniqueName << "\");" << endl;
|
2014-11-14 00:28:05 +08:00
|
|
|
|
|
|
|
// unwrap arguments, see Argument.cpp, we start at 1 as first is obj
|
2014-11-13 03:51:47 +08:00
|
|
|
args.matlab_unwrap(wrapperFile, 1);
|
2011-10-14 02:41:56 +08:00
|
|
|
|
2012-07-10 04:19:37 +08:00
|
|
|
// call method and wrap result
|
2014-11-14 00:28:05 +08:00
|
|
|
// example: out[0]=wrap<bool>(obj->return_field(t));
|
2014-11-13 19:52:41 +08:00
|
|
|
string expanded = "obj->" + name_;
|
2014-11-30 17:38:24 +08:00
|
|
|
if (templateArgValue_)
|
|
|
|
expanded += ("<" + templateArgValue_->qualifiedName("::") + ">");
|
2011-10-14 02:41:56 +08:00
|
|
|
|
2014-11-14 00:28:05 +08:00
|
|
|
return expanded;
|
2011-10-14 02:41:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2016-09-12 06:14:19 +08:00
|
|
|
void Method::emit_cython_pxd(FileWriter& file, const Class& cls) const {
|
2016-11-20 22:24:43 +08:00
|
|
|
for (size_t i = 0; i < nrOverloads(); ++i) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " ";
|
2016-12-16 13:23:45 +08:00
|
|
|
returnVals_[i].emit_cython_pxd(file, cls.pxdClassName(), cls.templateArgs);
|
2016-11-20 22:24:43 +08:00
|
|
|
file.oss << pyRename(name_) + " \"" + name_ + "\""
|
|
|
|
<< "(";
|
2016-12-16 13:23:45 +08:00
|
|
|
argumentList(i).emit_cython_pxd(file, cls.pxdClassName(), cls.templateArgs);
|
2016-09-09 19:26:11 +08:00
|
|
|
file.oss << ")";
|
2016-12-20 06:53:14 +08:00
|
|
|
// if (is_const_) file.oss << " const";
|
|
|
|
file.oss << " except +";
|
2016-09-09 19:26:11 +08:00
|
|
|
file.oss << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2016-11-20 22:24:43 +08:00
|
|
|
void Method::emit_cython_pyx_no_overload(FileWriter& file,
|
|
|
|
const Class& cls) const {
|
2016-09-14 05:11:23 +08:00
|
|
|
string funcName = pyRename(name_);
|
2016-11-20 22:24:43 +08:00
|
|
|
// leverage python's special treatment for print
|
2016-11-17 06:37:33 +08:00
|
|
|
if (funcName == "print_")
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " def __str__(self):\n self.print_('')\n return ''\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
|
|
|
|
// Function definition
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " def " << funcName;
|
2016-11-20 22:24:43 +08:00
|
|
|
// modify name of function instantiation as python doesn't allow overloads
|
|
|
|
// e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
|
2016-11-25 08:22:44 +08:00
|
|
|
if (templateArgValue_) file.oss << templateArgValue_->pyxClassName();
|
2016-11-20 22:24:43 +08:00
|
|
|
// funtion arguments
|
|
|
|
file.oss << "(self";
|
|
|
|
if (argumentList(0).size() > 0) file.oss << ", ";
|
|
|
|
argumentList(0).emit_cython_pyx(file);
|
|
|
|
file.oss << "):\n";
|
|
|
|
|
|
|
|
/// Call cython corresponding function and return
|
convert numpy input params to dtype float and order 'F' automatically
using numpy.astype(...). No copy if the params are already in the correct dtype and storage order.
For a function
f(Matrix A, Matrix B),
simply wrapping it to pyx as
f(A.astype(float, order='F', copy=False), B.astype(float, order='F', copy=False))
won't work.
It produces a strange side-effect that the content of A is overwritten by B and the two inputs are the same (data address) inside the function!
This is because Cython decreases the ref count for the temporary variable resulted from A.astype(...) before generates the wrap for B.astype(...).
Hence, the A.astype temp var is probably reused for B.astype, and they were pointing to the same data address.
For that reason, we have to go a longer route and wrap it as:
A = A.astype(float, order='F', copy=False)
B = B.astype(float, order='F', copy=False)
f(A, B)
For future ref., here is a sample of the wrongly generated code that wraps the JacobianFactor constructor:
Jacobian(Key i1, Matrix A1, Key i2, Matrix A2, Vector b, noiseModel::Diagonal model)
Wrongly wrapped pyx code:
self.shared_CJacobianFactor_ = shared_ptr[CJacobianFactor](new CJacobianFactor(i1, <MatrixXd>(Map[MatrixXd](A1.astype(float, order='F',copy=False)), i2, <MatrixXd>(Map[MatrixXd](A2.astype(float, order='F', copy=False)), <VectorXd>(Map[VectorXd](b.astype(float, order='F', copy=False))), model.shared_CnoiseModel_Diagonal_))
The problematic Cython generated CPP code with a comment on the problematic line:
/////////////////////////////////////////
// WRONG VERSION
/////////////////////////////////////////
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A1), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_14 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
///////////////////////////////////////////////
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; //<------- Problematic line!!! Killing this will result in the correct result!
///////////////////////////////////////////////
__pyx_t_13 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A2), __pyx_n_s_astype); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_15 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_12));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_16 = eigency::Map<Eigen::VectorXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
try {
__pyx_t_17 = new gtsam::JacobianFactor(__pyx_v_i1, ((Eigen::MatrixXd)__pyx_t_14), __pyx_v_i2, ((Eigen::MatrixXd)__pyx_t_15), ((Eigen::VectorXd)__pyx_t_16), __pyx_v_model->shared_CnoiseModel_Diagonal_);
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__pyx_v_self->shared_CJacobianFactor_ = boost::shared_ptr<gtsam::JacobianFactor> (__pyx_t_17);
2017-03-16 01:47:11 +08:00
|
|
|
file.oss << argumentList(0).pyx_convertEigenTypeAndStorageOrder(" ");
|
2016-11-23 01:13:33 +08:00
|
|
|
string caller = "self." + cls.shared_pxd_obj_in_pyx() + ".get()";
|
2016-11-20 22:24:43 +08:00
|
|
|
string ret = pyx_functionCall(caller, funcName, 0);
|
|
|
|
if (!returnVals_[0].isVoid()) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " cdef " << returnVals_[0].pyx_returnType()
|
2016-11-20 22:24:43 +08:00
|
|
|
<< " ret = " << ret << "\n";
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " return " << returnVals_[0].pyx_casting("ret") << "\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
} else {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " " << ret << "\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
void Method::emit_cython_pyx(FileWriter& file, const Class& cls) const {
|
|
|
|
string funcName = pyRename(name_);
|
|
|
|
// For template function: modify name of function instantiation as python
|
|
|
|
// doesn't allow overloads
|
|
|
|
// e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
|
|
|
|
string instantiatedName =
|
2016-11-25 08:22:44 +08:00
|
|
|
(templateArgValue_) ? funcName + templateArgValue_->pyxClassName() : funcName;
|
2016-11-20 22:24:43 +08:00
|
|
|
|
2016-09-10 06:37:48 +08:00
|
|
|
size_t N = nrOverloads();
|
2016-11-20 22:24:43 +08:00
|
|
|
// It's easy if there's no overload
|
|
|
|
if (N == 1) {
|
|
|
|
emit_cython_pyx_no_overload(file, cls);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dealing with overloads..
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " def " << instantiatedName << "(self, *args, **kwargs):\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
for (size_t i = 0; i < N; ++i) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " success, results = self." << instantiatedName << "_" << i
|
2016-11-20 22:24:43 +08:00
|
|
|
<< "(*args, **kwargs)\n";
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " if success:\n return results\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
}
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " raise TypeError('Could not find the correct overload')\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
|
|
|
|
for (size_t i = 0; i < N; ++i) {
|
|
|
|
ArgumentList args = argumentList(i);
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " def " + instantiatedName + "_" + to_string(i) +
|
2016-11-20 22:24:43 +08:00
|
|
|
"(self, *args, **kwargs):\n";
|
2016-11-22 06:14:30 +08:00
|
|
|
file.oss << pyx_resolveOverloadParams(args, false); // lazy: always return None even if it's a void function
|
2016-11-20 22:24:43 +08:00
|
|
|
|
|
|
|
/// Call cython corresponding function
|
convert numpy input params to dtype float and order 'F' automatically
using numpy.astype(...). No copy if the params are already in the correct dtype and storage order.
For a function
f(Matrix A, Matrix B),
simply wrapping it to pyx as
f(A.astype(float, order='F', copy=False), B.astype(float, order='F', copy=False))
won't work.
It produces a strange side-effect that the content of A is overwritten by B and the two inputs are the same (data address) inside the function!
This is because Cython decreases the ref count for the temporary variable resulted from A.astype(...) before generates the wrap for B.astype(...).
Hence, the A.astype temp var is probably reused for B.astype, and they were pointing to the same data address.
For that reason, we have to go a longer route and wrap it as:
A = A.astype(float, order='F', copy=False)
B = B.astype(float, order='F', copy=False)
f(A, B)
For future ref., here is a sample of the wrongly generated code that wraps the JacobianFactor constructor:
Jacobian(Key i1, Matrix A1, Key i2, Matrix A2, Vector b, noiseModel::Diagonal model)
Wrongly wrapped pyx code:
self.shared_CJacobianFactor_ = shared_ptr[CJacobianFactor](new CJacobianFactor(i1, <MatrixXd>(Map[MatrixXd](A1.astype(float, order='F',copy=False)), i2, <MatrixXd>(Map[MatrixXd](A2.astype(float, order='F', copy=False)), <VectorXd>(Map[VectorXd](b.astype(float, order='F', copy=False))), model.shared_CnoiseModel_Diagonal_))
The problematic Cython generated CPP code with a comment on the problematic line:
/////////////////////////////////////////
// WRONG VERSION
/////////////////////////////////////////
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A1), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_14 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
///////////////////////////////////////////////
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; //<------- Problematic line!!! Killing this will result in the correct result!
///////////////////////////////////////////////
__pyx_t_13 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A2), __pyx_n_s_astype); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_15 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_12));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_16 = eigency::Map<Eigen::VectorXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
try {
__pyx_t_17 = new gtsam::JacobianFactor(__pyx_v_i1, ((Eigen::MatrixXd)__pyx_t_14), __pyx_v_i2, ((Eigen::MatrixXd)__pyx_t_15), ((Eigen::VectorXd)__pyx_t_16), __pyx_v_model->shared_CnoiseModel_Diagonal_);
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__pyx_v_self->shared_CJacobianFactor_ = boost::shared_ptr<gtsam::JacobianFactor> (__pyx_t_17);
2017-03-16 01:47:11 +08:00
|
|
|
file.oss << argumentList(i).pyx_convertEigenTypeAndStorageOrder(" ");
|
2016-11-23 01:13:33 +08:00
|
|
|
string caller = "self." + cls.shared_pxd_obj_in_pyx() + ".get()";
|
2016-11-20 22:24:43 +08:00
|
|
|
|
|
|
|
string ret = pyx_functionCall(caller, funcName, i);
|
2016-11-22 06:14:30 +08:00
|
|
|
if (!returnVals_[i].isVoid()) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " cdef " << returnVals_[i].pyx_returnType()
|
2016-11-20 22:24:43 +08:00
|
|
|
<< " ret = " << ret << "\n";
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " return True, " << returnVals_[i].pyx_casting("ret") << "\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
} else {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " " << ret << "\n";
|
|
|
|
file.oss << " return True, None\n";
|
2016-11-20 22:24:43 +08:00
|
|
|
}
|
2016-09-10 06:37:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ************************************************************************* */
|