1 // Copyright (c) 2017 Commissariat à l'énergie atomique et aux énergies alternatives (CEA) 2 // Copyright (c) 2017 Centre national de la recherche scientifique (CNRS) 3 // Copyright (c) 2020 Simons Foundation 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0.txt 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // Authors: Olivier Parcollet, Nils Wentzell 18 19 #pragma once 20 #include "../pyref.hpp" 21 #include "./complex.hpp" 22 23 #include <numpy/arrayobject.h> 24 25 namespace cpp2py { 26 27 // PyObject * 28 template <> struct py_converter<PyObject *> { c2pycpp2py::py_converter29 static PyObject *c2py(PyObject *ob) { return ob; } py2ccpp2py::py_converter30 static PyObject *py2c(PyObject *ob) { return ob; } is_convertiblecpp2py::py_converter31 static bool is_convertible(PyObject *ob, bool raise_exception) { return true; } 32 }; 33 34 // --- bool 35 template <> struct py_converter<bool> { c2pycpp2py::py_converter36 static PyObject *c2py(bool b) { 37 if (b) 38 Py_RETURN_TRUE; 39 else 40 Py_RETURN_FALSE; 41 } py2ccpp2py::py_converter42 static bool py2c(PyObject *ob) { return ob == Py_True; } is_convertiblecpp2py::py_converter43 static bool is_convertible(PyObject *ob, bool raise_exception) { 44 if (PyBool_Check(ob)) return true; 45 if (raise_exception) { PyErr_SetString(PyExc_TypeError, ("Cannot convert "s + to_string(ob) + " to bool"s).c_str()); } 46 return false; 47 } 48 }; 49 50 // --- long 51 52 namespace details { 53 template <typename I> struct py_converter_impl { c2pycpp2py::details::py_converter_impl54 static PyObject *c2py(I i) { return PyLong_FromLong(long(i)); } py2ccpp2py::details::py_converter_impl55 static I py2c(PyObject *ob) { 56 if (PyLong_Check(ob)) { return I(PyLong_AsLong(ob)); } 57 // Convert NPY Scalar Type to Builtin Type 58 pyref py_builtin = PyObject_CallMethod(ob, "item", NULL); 59 return I(PyLong_AsLong(py_builtin)); 60 } is_convertiblecpp2py::details::py_converter_impl61 static bool is_convertible(PyObject *ob, bool raise_exception) { 62 if (PyLong_Check(ob)) return true; 63 if (PyArray_CheckScalar(ob)) { 64 pyref py_arr = PyArray_FromScalar(ob, NULL); 65 if (PyArray_ISINTEGER((PyObject *)py_arr)) return true; 66 } 67 if (raise_exception) { PyErr_SetString(PyExc_TypeError, ("Cannot convert "s + to_string(ob) + " to integer type"s).c_str()); } 68 return false; 69 } 70 }; 71 } // namespace details 72 73 template <> struct py_converter<long> : details::py_converter_impl<long> {}; 74 template <> struct py_converter<int> : details::py_converter_impl<int> {}; 75 template <> struct py_converter<unsigned int> : details::py_converter_impl<unsigned int> {}; 76 template <> struct py_converter<unsigned long> : details::py_converter_impl<unsigned long> {}; 77 template <> struct py_converter<unsigned long long> : details::py_converter_impl<unsigned long long> {}; 78 79 // --- double 80 81 template <> struct py_converter<double> { c2pycpp2py::py_converter82 static PyObject *c2py(double x) { return PyFloat_FromDouble(x); } py2ccpp2py::py_converter83 static double py2c(PyObject *ob) { 84 if (PyFloat_Check(ob) || PyLong_Check(ob)) { return PyFloat_AsDouble(ob); } 85 // Convert NPY Scalar Type to Builtin Type 86 pyref py_builtin = PyObject_CallMethod(ob, "item", NULL); 87 return PyFloat_AsDouble(py_builtin); 88 } is_convertiblecpp2py::py_converter89 static bool is_convertible(PyObject *ob, bool raise_exception) { 90 if (PyFloat_Check(ob) || PyLong_Check(ob)) return true; 91 if (PyArray_CheckScalar(ob)) { 92 pyref py_arr = PyArray_FromScalar(ob, NULL); 93 if (PyArray_ISINTEGER((PyObject*)py_arr) or PyArray_ISFLOAT((PyObject*)py_arr)) return true; 94 } 95 if (raise_exception) { PyErr_SetString(PyExc_TypeError, ("Cannot convert "s + to_string(ob) + " to double"s).c_str()); } 96 return false; 97 } 98 }; 99 100 } // namespace cpp2py 101