array_utils.h 4.78 KB
Newer Older
André Anjos's avatar
André Anjos committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * @date Tue Nov 8 15:34:31 2011 +0100
 * @author Andre Anjos <andre.anjos@idiap.ch>
 *
 * @brief Utilities for converting data to-from blitz::Arrays and other
 * goodies.
 *
 * Copyright (C) Idiap Research Institute, Martigny, Switzerland
 */

#ifndef BOB_IO_BASE_ARRAY_UTILS_H
#define BOB_IO_BASE_ARRAY_UTILS_H

#include <blitz/array.h>
#include <stdint.h>
#include <stdexcept>
#include <boost/format.hpp>

#include <bob.core/cast.h>
#include <bob.io.base/array.h>

namespace bob { namespace io { namespace base { namespace array {

  /**
25
   * @brief Fills in shape and stride starting from a typeinfo object
André Anjos's avatar
André Anjos committed
26
   */
27
  template <int N> void set_shape_and_stride(const typeinfo& info,
André Anjos's avatar
André Anjos committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
      blitz::TinyVector<int,N>& shape, blitz::TinyVector<int,N>& stride) {
    for (int k=0; k<N; ++k) {
      shape[k] = info.shape[k];
      stride[k] = info.stride[k];
    }
  }


  /**
   * @brief Takes a data pointer and assumes it is a C-style array for the
   * defined type. Creates a wrapper as a blitz::Array<T,N> with the same
   * number of dimensions and type. Notice that the blitz::Array<> created
   * will have its memory tied to the passed buffer. In other words you have
   * to make sure that the buffer outlives the returned blitz::Array<>.
   */
  template <typename T, int N>
    blitz::Array<T,N> wrap(const interface& buf) {

46
      const typeinfo& type = buf.type();
André Anjos's avatar
André Anjos committed
47
48
49

      if (!buf.ptr()) throw std::runtime_error("empty buffer");

50
      if (type.dtype != bob::io::base::array::getElementType<T>()) {
André Anjos's avatar
André Anjos committed
51
        boost::format m("cannot efficiently retrieve blitz::Array<%s,%d> from buffer of type '%s'");
52
        m % stringize<T>() % N % type.str();
André Anjos's avatar
André Anjos committed
53
54
55
56
57
        throw std::runtime_error(m.str());
      }

      if (type.nd != N) {
        boost::format m("cannot retrieve blitz::Array<%s,%d> from buffer of type '%s'");
58
        m % stringize<T>() % N % type.str();
André Anjos's avatar
André Anjos committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
        throw std::runtime_error(m.str());
      }

      blitz::TinyVector<int,N> shape;
      blitz::TinyVector<int,N> stride;
      set_shape_and_stride(type, shape, stride);

      return blitz::Array<T,N>((T*)buf.ptr(),
          shape, stride, blitz::neverDeleteData);
    }


  /**
   * @brief Takes a data pointer and assumes it is a C-style array for the
   * defined type. Creates a copy as a blitz::Array<T,N> with the same number
   * of dimensions, but with a type as specified by you. If the type does not
   * match the type of the original C-style array, a cast will happen.
   *
   * If a certain type cast is not supported. An appropriate exception will
   * be raised.
   */
  template <typename T, int N>
    blitz::Array<T,N> cast(const interface& buf) {

83
      const typeinfo& type = buf.type();
André Anjos's avatar
André Anjos committed
84
85
86

      if (type.nd != N) {
        boost::format m("cannot cast blitz::Array<%s,%d> from buffer of type '%s'");
87
        m % stringize<T>() % N % type.str();
André Anjos's avatar
André Anjos committed
88
89
90
91
        throw std::runtime_error(m.str());
      }

      switch (type.dtype) {
92
        case bob::io::base::array::t_bool:
André Anjos's avatar
André Anjos committed
93
          return bob::core::array::cast<T>(wrap<bool,N>(buf));
94
        case bob::io::base::array::t_int8:
André Anjos's avatar
André Anjos committed
95
          return bob::core::array::cast<T>(wrap<int8_t,N>(buf));
96
        case bob::io::base::array::t_int16:
André Anjos's avatar
André Anjos committed
97
          return bob::core::array::cast<T>(wrap<int16_t,N>(buf));
98
        case bob::io::base::array::t_int32:
André Anjos's avatar
André Anjos committed
99
          return bob::core::array::cast<T>(wrap<int32_t,N>(buf));
100
        case bob::io::base::array::t_int64:
André Anjos's avatar
André Anjos committed
101
          return bob::core::array::cast<T>(wrap<int64_t,N>(buf));
102
        case bob::io::base::array::t_uint8:
André Anjos's avatar
André Anjos committed
103
          return bob::core::array::cast<T>(wrap<uint8_t,N>(buf));
104
        case bob::io::base::array::t_uint16:
André Anjos's avatar
André Anjos committed
105
          return bob::core::array::cast<T>(wrap<uint16_t,N>(buf));
106
        case bob::io::base::array::t_uint32:
André Anjos's avatar
André Anjos committed
107
          return bob::core::array::cast<T>(wrap<uint32_t,N>(buf));
108
        case bob::io::base::array::t_uint64:
André Anjos's avatar
André Anjos committed
109
          return bob::core::array::cast<T>(wrap<uint64_t,N>(buf));
110
        case bob::io::base::array::t_float32:
André Anjos's avatar
André Anjos committed
111
          return bob::core::array::cast<T>(wrap<float,N>(buf));
112
        case bob::io::base::array::t_float64:
André Anjos's avatar
André Anjos committed
113
          return bob::core::array::cast<T>(wrap<double,N>(buf));
114
        case bob::io::base::array::t_float128:
André Anjos's avatar
André Anjos committed
115
          return bob::core::array::cast<T>(wrap<long double,N>(buf));
116
        case bob::io::base::array::t_complex64:
André Anjos's avatar
André Anjos committed
117
          return bob::core::array::cast<T>(wrap<std::complex<float>,N>(buf));
118
        case bob::io::base::array::t_complex128:
André Anjos's avatar
André Anjos committed
119
          return bob::core::array::cast<T>(wrap<std::complex<double>,N>(buf));
120
        case bob::io::base::array::t_complex256:
André Anjos's avatar
André Anjos committed
121
122
123
124
125
126
127
128
129
130
131
132
133
          return bob::core::array::cast<T>(wrap<std::complex<long double>,N>(buf));
        default:
          break;
      }

      //if we get to this point, there is nothing much we can do...
      throw std::runtime_error("invalid type on blitz buffer array casting -- debug me");

    }

}}}}

#endif /* BOB_IO_BASE_ARRAY_UTILS_H */