Unexpected floor division with ndarrays on python 3
- Lenguaje dominante
- C++
- Estrellas
- 537
- Forks
- 223
- Merge medio
- 11 h 22 min
- PR fusionados (30 d)
- 2
Descripción
Our primarily C++ code base uses an embedded python to do computation with help from `boost::python`. We are in the process of porting to python 3. We have noticed that it appears that the `/` operator when acting on a pair of `boost::python::numpy::ndarray`'s yields floor division. That is to say the results are numerically consistent with constructing the same arrays in a python interpreter and then performing `arr1 // arr2`. We do did not see this behaviour when linking against `python27.dll`. To make my issue concrete I prepared an example based on those provided in the `examples/` folder. It was built on windows 10 using:
- MSVC 2015
- Python 2.7.16
- Python 3.6.8
- cmake 3.16
- Ninja 1.9.0
- Boost 1.70.0
`main.cpp` was:
```cpp
#include
#include
namespace p = boost::python;
namespace np = boost::python::numpy;
typedef float arr_dtype;
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
arr_dtype raw_array1[] = {1.53f, 2.53f, 3.53f, 4.53f};
np::ndarray nd_array1 = np::from_data(raw_array1, np::dtype::get_builtin(),
p::make_tuple(4),
p::make_tuple(4),
p::object());
arr_dtype raw_array2[] = {0.1f};
np::ndarray nd_array2 = np::from_data(raw_array2, np::dtype::get_builtin(),
p::make_tuple(1),
p::make_tuple(1),
p::object());
std::cout << "ndarray 1 is " << p::extract(p::str(nd_array1)) << std::endl;
std::cout << "ndarray 2 is " << p::extract(p::str(nd_array2)) << std::endl;
//
p::object result_array_div = nd_array1 / nd_array2;
std::cout << "operator/ division of arrays is " << p::extract(p::str(result_array_div)) << std::endl;
return 0;
}
```
For Python 27 the output when running `main.exe` was consistent with our expectations:
```
ndarray 1 is [1.53 2.53 3.53 4.53]
ndarray 2 is [0.1]
operator/ division of arrays is [15.299999 25.3 35.3 45.300003]
```
For Python 36 the result when running `main.exe` was not consistent with our (possibly misguided) expectations:
```
ndarray 1 is [1.53 2.53 3.53 4.53]
ndarray 2 is [0.1]
operator/ division of arrays is [15. 25. 35. 45.]
```
Is this expected behaviour? Is there any way to enforce non-floor division when using the `/` operator and python 3?
For reference the `CMakeLists.txt` was:
```
cmake_minimum_required(VERSION 3.16)
project(test_boost_numpy_division)
# version selection
if (BUILD_PY3)
set(python_package_name "Python3")
set(BOOST_ROOT "${BOOST_ROOT_PY3}")
set(py_dll_path "${Python3_ROOT_DIR}/python36.dll")
set(py_maj_min_version "36")
else()
set(python_package_name "Python2")
set(BOOST_ROOT "${BOOST_ROOT_PY2}")
set(py_dll_path "C:/Windows/System32/python27.dll")
set(py_maj_min_version "27")
endif()
set(boost_python_module_name "python${py_maj_min_version}")
set(boost_numpy_module_name "numpy${py_maj_min_version}")
# python config
find_package (${python_package_name} COMPONENTS Development REQUIRED)
# boost config
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost REQUIRED COMPONENTS ${boost_python_module_name} ${boost_numpy_module_name} unit_test_framework)
#
add_executable(main)
target_sources(main PRIVATE main.cpp)
target_link_libraries(main ${python_package_name}::Python)
target_link_libraries(main Boost::${boost_python_module_name} Boost::${boost_numpy_module_name})
set_target_properties( main
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
#
file(COPY "${Boost_LIBRARY_DIRS}/" DESTINATION "${CMAKE_BINARY_DIR}/bin")
file(COPY "${py_dll_path}" DESTINATION "${CMAKE_BINARY_DIR}/bin")
```
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Evaluación
Este issue todavía no se ha evaluado.