basic.cpp 9.16 KB
Newer Older
1
2
// Copyright (C) 2013  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
3
#include <dlib/python.h>
Davis King's avatar
Davis King committed
4
5
6
#include <dlib/matrix.h>
#include <sstream>
#include <string>
Davis King's avatar
Davis King committed
7
#include "opaque_types.h"
Davis King's avatar
Davis King committed
8
9

#include <dlib/string.h>
10
#include <pybind11/stl_bind.h>
Davis King's avatar
Davis King committed
11
12
13

using namespace std;
using namespace dlib;
14
namespace py = pybind11;
Davis King's avatar
Davis King committed
15

16
17

std::shared_ptr<std::vector<double> > array_from_object(py::object obj)
Davis King's avatar
Davis King committed
18
{
19
20
21
    try {
        long nr = obj.cast<long>();
        return std::make_shared<std::vector<double>>(nr);
Davis King's avatar
Davis King committed
22
    } catch (py::cast_error&) {
23
24
25
        py::list li = obj.cast<py::list>();
        const long nr = len(li);
        auto temp = std::make_shared<std::vector<double>>(nr);
Davis King's avatar
Davis King committed
26
27
        for ( long r = 0; r < nr; ++r)
        {
28
            (*temp)[r] = li[r].cast<double>();
Davis King's avatar
Davis King committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
        }
        return temp;
    }
}

string array__str__ (const std::vector<double>& v)
{
    std::ostringstream sout;
    for (unsigned long i = 0; i < v.size(); ++i)
    {
        sout << v[i];
        if (i+1 < v.size())
            sout << "\n";
    }
    return sout.str();
}

string array__repr__ (const std::vector<double>& v)
{
    std::ostringstream sout;
    sout << "dlib.array([";
    for (unsigned long i = 0; i < v.size(); ++i)
    {
        sout << v[i];
        if (i+1 < v.size())
            sout << ", ";
    }
    sout << "])";
    return sout.str();
}

Davis King's avatar
Davis King committed
60
61
62
string range__str__ (const std::pair<unsigned long,unsigned long>& p)
{
    std::ostringstream sout;
Davis King's avatar
Davis King committed
63
    sout << p.first << ", " << p.second;
Davis King's avatar
Davis King committed
64
65
66
67
68
69
70
71
72
73
    return sout.str();
}

string range__repr__ (const std::pair<unsigned long,unsigned long>& p)
{
    std::ostringstream sout;
    sout << "dlib.range(" << p.first << ", " << p.second << ")";
    return sout.str();
}

Davis King's avatar
Davis King committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
struct range_iter
{
    std::pair<unsigned long,unsigned long> range;
    unsigned long cur;

    unsigned long next()
    {
        if (cur < range.second)
        {
            return cur++;
        }
        else
        {
            PyErr_SetString(PyExc_StopIteration, "No more data.");
88
            throw py::error_already_set();
Davis King's avatar
Davis King committed
89
90
91
92
93
94
95
96
97
98
99
100
        }
    }
};

range_iter make_range_iterator (const std::pair<unsigned long,unsigned long>& p)
{
    range_iter temp;
    temp.range = p;
    temp.cur = p.first;
    return temp;
}

Davis King's avatar
Davis King committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
string pair__str__ (const std::pair<unsigned long,double>& p)
{
    std::ostringstream sout;
    sout << p.first << ": " << p.second;
    return sout.str();
}

string pair__repr__ (const std::pair<unsigned long,double>& p)
{
    std::ostringstream sout;
    sout << "dlib.pair(" << p.first << ", " << p.second << ")";
    return sout.str();
}

string sparse_vector__str__ (const std::vector<std::pair<unsigned long,double> >& v)
{
    std::ostringstream sout;
    for (unsigned long i = 0; i < v.size(); ++i)
    {
        sout << v[i].first << ": " << v[i].second;
        if (i+1 < v.size())
            sout << "\n";
    }
    return sout.str();
}

string sparse_vector__repr__ (const std::vector<std::pair<unsigned long,double> >& v)
{
    std::ostringstream sout;
    sout << "< dlib.sparse_vector containing: \n" << sparse_vector__str__(v) << " >";
    return sout.str();
}

134
135
136
137
138
139
140
141
unsigned long range_len(const std::pair<unsigned long, unsigned long>& r)
{
    if (r.second > r.first)
        return r.second-r.first;
    else
        return 0;
}

142
143
template <typename T>
void resize(T& v, unsigned long n) { v.resize(n); }
Davis King's avatar
Davis King committed
144

145
void bind_basic_types(py::module& m)
Davis King's avatar
Davis King committed
146
{
147
148
149
150
151
152
153
    {
    typedef double item_type;
    typedef std::vector<item_type> type;
    typedef std::shared_ptr<type> type_ptr;
    py::bind_vector<type, type_ptr >(m, "array", "This object represents a 1D array of floating point numbers. "
        "Moreover, it binds directly to the C++ type std::vector<double>.")
        .def(py::init(&array_from_object))
Davis King's avatar
Davis King committed
154
155
        .def("__str__", array__str__)
        .def("__repr__", array__repr__)
156
157
158
159
160
        .def("clear", &type::clear)
        .def("resize", resize<type>)
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
    }
Davis King's avatar
Davis King committed
161

162
163
164
165
166
167
168
169
170
    {
    typedef matrix<double,0,1> item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "vectors", "This object is an array of vector objects.")
        .def("clear", &type::clear)
        .def("resize", resize<type>)
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
    }
Davis King's avatar
Davis King committed
171

172
    {
173
174
175
    typedef std::vector<matrix<double,0,1> > item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "vectorss", "This object is an array of arrays of vector objects.")
176
177
        .def("clear", &type::clear)
        .def("resize", resize<type>)
178
179
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
180
181
    }

Davis King's avatar
Davis King committed
182
    typedef pair<unsigned long,unsigned long> range_type;
183
184
    py::class_<range_type>(m, "range", "This object is used to represent a range of elements in an array.")
        .def(py::init<unsigned long,unsigned long>())
185
        .def(py::init([](unsigned long end){return range_type(0,end); }))
186
187
        .def_readwrite("begin",&range_type::first, "The index of the first element in the range.  This is represented using an unsigned integer.")
        .def_readwrite("end",&range_type::second, "One past the index of the last element in the range.  This is represented using an unsigned integer.")
Davis King's avatar
Davis King committed
188
189
        .def("__str__", range__str__)
        .def("__repr__", range__repr__)
Davis King's avatar
Davis King committed
190
        .def("__iter__", &make_range_iterator)
191
        .def("__len__", &range_len)
192
        .def(py::pickle(&getstate<range_type>, &setstate<range_type>));
Davis King's avatar
Davis King committed
193

194
    py::class_<range_iter>(m, "_range_iter")
195
196
        .def("next", &range_iter::next)
        .def("__next__", &range_iter::next);
Davis King's avatar
Davis King committed
197

Davis King's avatar
Davis King committed
198
    {
199
200
201
    typedef std::pair<unsigned long, unsigned long> item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "ranges", "This object is an array of range objects.")
Davis King's avatar
Davis King committed
202
203
        .def("clear", &type::clear)
        .def("resize", resize<type>)
204
205
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
Davis King's avatar
Davis King committed
206
207
    }

Davis King's avatar
Davis King committed
208
    {
209
210
211
    typedef std::vector<std::pair<unsigned long, unsigned long> > item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "rangess", "This object is an array of arrays of range objects.")
Davis King's avatar
Davis King committed
212
213
        .def("clear", &type::clear)
        .def("resize", resize<type>)
214
215
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
Davis King's avatar
Davis King committed
216
217
    }

Davis King's avatar
Davis King committed
218

Davis King's avatar
Davis King committed
219
    typedef pair<unsigned long,double> pair_type;
220
221
    py::class_<pair_type>(m, "pair", "This object is used to represent the elements of a sparse_vector.")
        .def(py::init<unsigned long,double>())
Davis King's avatar
Davis King committed
222
223
224
225
        .def_readwrite("first",&pair_type::first, "This field represents the index/dimension number.")
        .def_readwrite("second",&pair_type::second, "This field contains the value in a vector at dimension specified by the first field.")
        .def("__str__", pair__str__)
        .def("__repr__", pair__repr__)
226
        .def(py::pickle(&getstate<pair_type>, &setstate<pair_type>));
Davis King's avatar
Davis King committed
227

228
229
230
    {
    typedef std::vector<pair_type> type;
    py::bind_vector<type>(m, "sparse_vector",
231
232
233
234
235
236
237
238
239
240
241
242
"This object represents the mathematical idea of a sparse column vector.  It is    \n\
simply an array of dlib.pair objects, each representing an index/value pair in    \n\
the vector.  Any elements of the vector which are missing are implicitly set to    \n\
zero.      \n\
    \n\
Unless otherwise noted, any routines taking a sparse_vector assume the sparse    \n\
vector is sorted and has unique elements.  That is, the index values of the    \n\
pairs in a sparse_vector should be listed in increasing order and there should    \n\
not be duplicates.  However, some functions work with \"unsorted\" sparse    \n\
vectors.  These are dlib.sparse_vector objects that have either duplicate    \n\
entries or non-sorted index values.  Note further that you can convert an    \n\
\"unsorted\" sparse_vector into a properly sorted sparse vector by calling    \n\
243
dlib.make_sparse_vector() on it.   "
244
        )
Davis King's avatar
Davis King committed
245
246
        .def("__str__", sparse_vector__str__)
        .def("__repr__", sparse_vector__repr__)
247
248
249
250
251
        .def("clear", &type::clear)
        .def("resize", resize<type>)
        .def("extend", extend_vector_with_python_list<pair_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
    }
Davis King's avatar
Davis King committed
252

253
    {
254
255
256
    typedef std::vector<pair_type> item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "sparse_vectors", "This object is an array of sparse_vector objects.")
257
258
        .def("clear", &type::clear)
        .def("resize", resize<type>)
259
260
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
261
262
    }

263
264
265
266
267
268
269
270
271
    {
    typedef std::vector<std::vector<pair_type> > item_type;
    typedef std::vector<item_type > type;
    py::bind_vector<type>(m, "sparse_vectorss", "This object is an array of arrays of sparse_vector objects.")
        .def("clear", &type::clear)
        .def("resize", resize<type>)
        .def("extend", extend_vector_with_python_list<item_type>)
        .def(py::pickle(&getstate<type>, &setstate<type>));
    }
Davis King's avatar
Davis King committed
272
273
}