Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / python / numpy / dtype.hpp
1 // Copyright Jim Bosch 2010-2012.
2 // Copyright Stefan Seefeld 2016.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef boost_python_numpy_dtype_hpp_
8 #define boost_python_numpy_dtype_hpp_
9
10 /**
11  *  @file boost/python/numpy/dtype.hpp
12  *  @brief Object manager for Python's numpy.dtype class.
13  */
14
15 #include <boost/python.hpp>
16 #include <boost/python/numpy/numpy_object_mgr_traits.hpp>
17 #include <boost/python/numpy/config.hpp>
18
19 #include <boost/mpl/for_each.hpp>
20 #include <boost/type_traits/add_pointer.hpp>
21
22 namespace boost { namespace python { namespace numpy {
23
24 /**
25  *  @brief A boost.python "object manager" (subclass of object) for numpy.dtype.
26  *
27  *  @todo This could have a lot more interesting accessors.
28  */
29 class BOOST_NUMPY_DECL dtype : public object {
30   static python::detail::new_reference convert(object::object_cref arg, bool align);
31 public:
32
33   /// @brief Convert an arbitrary Python object to a data-type descriptor object.
34   template <typename T>
35   explicit dtype(T arg, bool align=false) : object(convert(arg, align)) {}
36
37   /**
38    *  @brief Get the built-in numpy dtype associated with the given scalar template type.
39    *
40    *  This is perhaps the most useful part of the numpy API: it returns the dtype object
41    *  corresponding to a built-in C++ type.  This should work for any integer or floating point
42    *  type supported by numpy, and will also work for std::complex if 
43    *  sizeof(std::complex<T>) == 2*sizeof(T).
44    *
45    *  It can also be useful for users to add explicit specializations for POD structs
46    *  that return field-based dtypes.
47    */
48   template <typename T> static dtype get_builtin();
49
50   /// @brief Return the size of the data type in bytes.
51   int get_itemsize() const;
52
53   /**
54    *  @brief Compare two dtypes for equivalence.
55    *
56    *  This is more permissive than equality tests.  For instance, if long and int are the same
57    *  size, the dtypes corresponding to each will be equivalent, but not equal.
58    */
59   friend BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
60
61   /**
62    *  @brief Register from-Python converters for NumPy's built-in array scalar types.
63    *
64    *  This is usually called automatically by initialize(), and shouldn't be called twice
65    *  (doing so just adds unused converters to the Boost.Python registry).
66    */
67   static void register_scalar_converters();
68
69   BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dtype, object);
70
71 };
72
73 BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
74
75 namespace detail
76 {
77
78 template <int bits, bool isUnsigned> dtype get_int_dtype();
79
80 template <int bits> dtype get_float_dtype();
81
82 template <int bits> dtype get_complex_dtype();
83
84 template <typename T, bool isInt=boost::is_integral<T>::value>
85 struct builtin_dtype;
86
87 template <typename T>
88 struct builtin_dtype<T,true> {
89   static dtype get() { return get_int_dtype< 8*sizeof(T), boost::is_unsigned<T>::value >(); }
90 };
91
92 template <>
93 struct builtin_dtype<bool,true> {
94   static dtype get();
95 };
96
97 template <typename T>
98 struct builtin_dtype<T,false> {
99   static dtype get() { return get_float_dtype< 8*sizeof(T) >(); }
100 };
101
102 template <typename T>
103 struct builtin_dtype< std::complex<T>, false > {
104   static dtype get() { return get_complex_dtype< 16*sizeof(T) >(); }  
105 };
106
107 } // namespace detail
108
109 template <typename T>
110 inline dtype dtype::get_builtin() { return detail::builtin_dtype<T>::get(); }
111
112 } // namespace boost::python::numpy
113
114 namespace converter {
115 NUMPY_OBJECT_MANAGER_TRAITS(numpy::dtype);
116 }}} // namespace boost::python::converter
117
118 #endif