Skip to content
This repository has been archived by the owner on Jun 21, 2022. It is now read-only.

Commit

Permalink
- experimenting with std::valarray
Browse files Browse the repository at this point in the history
- related to #156
  • Loading branch information
duynht committed Jul 10, 2019
1 parent c224c36 commit 327c833
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 47 deletions.
161 changes: 116 additions & 45 deletions awkward-cpp/awkward/cpp/array/_table.cpp
Original file line number Diff line number Diff line change
@@ -1,100 +1,171 @@
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <cinttypes>
#include <stdexcept>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <valarray>
#include "any.h"

namespace py = pybind11;

using T = std::int64_t;

// template <typename T>
class Table {
py::object _view;
std::shared_ptr<Table> _base;
std::string rowname;
ssize_t rowstart;
std::map<py::str, py::handle> _contents;
std::map<std::string, std::valarray<T>> _contents;

ssize_t length() {
return _contents.size();
}

// py::dict vs py::array????
public:
public:
// Table.Row
class Row {
// Table* _table;
std::shared_ptr<Table> _table;
ssize_t _index;

public:
public:
Row(const Table& table, ssize_t index) {
_table = std::make_shared<Table>(table);
_index = index;
}


};

// class Table


Table(py::object columns1, py::args columns2, py::kwargs columns3) {
_view = py::none();
_base = NULL;
rowname = "Row";
rowstart = 0;

std::set<std::string> seen;
if (py::isinstance<py::dict>(columns1)) {
auto columns = columns1.cast<py::dict>();
for (auto item : columns) {
std::string key = item.first.cast<std::string>();
if (seen.find(key) != seen.end()){
throw std::invalid_argument("column "+key+" occurs more than once");
auto key = item.first.cast<std::string>();
if (seen.find(key) != seen.end()) {
throw std::invalid_argument("column " + key +
" occurs more than once");
}
seen.insert(key);


_contents.emplace(key, item.second);
auto value = item.second.cast<std::valarray<T>>();
_contents.emplace(key, value);
}
if (py::len(columns2) != 0) {
throw std::invalid_argument("only one positional argument when first argument is a dict");
throw std::invalid_argument(
"only one positional argument when first argument is a "
"dict");
}
} else {
ssize_t i = 0;
auto value = columns1.cast<std::valarray<T>>();
_contents.emplace(std::to_string(i++), value);
for (auto item : columns2) {
value = item.cast<std::valarray<T>>();
_contents.emplace(std::to_string(i), value);
seen.insert(std::to_string(i));
i++;
}
}
else {
ssize_t i = 0;
_contents.emplace(std::to_string(i++),columns1);
for (auto item : columns2){
_contents.emplace(std::to_string(i),item);
seen.insert(std::to_string(i));
i++;
}
}
if (columns3){
if (columns3) {
for (auto item : columns3) {
std::string key = item.first.cast<std::string>();
if (seen.find(key) != seen.end()) {
throw std::invalid_argument("column "+key+" occurs more than once");
throw std::invalid_argument("column " + key +
" occurs more than once");
}
_contents.emplace(key,item.second);
auto value = item.second.cast<std::valarray<T>>();
_contents.emplace(key, value);
seen.insert(key);
}
}

}

};
}

// No need to consider view anymore
std::slice _index() {
if (py::isinstance<py::none>(_view)) {
return std::slice(0, 1, length());

} else if (py::isinstance<py::tuple>(_view)) {
auto myview = _view.cast<std::tuple<T,T,T>>();
auto start = std::get<0>(myview);
auto step = std::get<1>(myview);
auto length = std::get<2>(myview);
auto stop = start + step * length;
// std::vector<T> ret(length / step + 1);
// for (auto i = start; i < length; i += step) {
// ret.push_back(i);
// }

return std::slice(start, stop, step);

} else {
auto myview = _view.cast<ssize_t>();
return std::slice(myview, 1, 1);
}
}

ssize_t length() {
ssize_t ret = 0;
if (py::isinstance<py::none>(_view)) {
if (_contents.size() != 0) {
for (auto item : _contents) {
ret = std::min((size_t)ret, item.second.size());
}
}
} else if (py::isinstance<py::tuple>(_view)) {
auto myview = _view.cast<std::tuple<T,T,T>>();
ret = std::get<2>(myview);
} else {
ret = _view.cast<ssize_t>();
}
return ret;
}

// void setitem(std::string where, py::handle whats) {
// if (!py::isinstance<py::none>(_view)) {
// throw std::domain_error(
// "new columns can only be attached to the original Table, not
// a " "view (try table.base['col'] = array");
// }
// }

std::valarray<T> getitem(std::string where) {
// string, not string slice
if (py::isinstance<py::none>(_view)) {
if (_contents.find(where) == _contents.end()) {
throw std::invalid_argument("no column named " + where);
}
return _contents[where];
} else {
auto index = _index();
if (_contents.find(where) == _contents.end()) {
throw std::invalid_argument("no column named " + where);
}
return _contents[where][index];
}
}

// Row getitem(ssize_t where) {
// return Row(*this, where);
// }

// std::valarray<T> getitem(std::tuple<ssize_t> where) {
// if
// }
};

PYBIND11_MODULE(_table, m) {

py::class_<Table>(m, "Table")
.def(py::init<py::object, py::args, py::kwargs>(), py::arg("columns3") = py::dict())
;

.def(py::init<py::object, py::args, py::kwargs>(),
py::arg("columns3") = py::dict())
.def("__len__", &Table::length)
.def("__getitem__", &Table::getitem);

py::class_<Table::Row>(m,"Table.Row")
.def(py::init<const Table&, ssize_t>(),py::arg("table"), py::arg("index"))
;
py::class_<Table::Row>(m, "Table.Row")
.def(py::init<const Table&, ssize_t>(), py::arg("table"),
py::arg("index"));
}
3 changes: 1 addition & 2 deletions tests/test_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
import pytest

import awkward
import awkward.cpp as awkward_cpp
# awkward_cpp = pytest.importorskip("awkward.cpp")
awkward_cpp = pytest.importorskip("awkward.cpp")

class Test(unittest.TestCase):
def runTest(self):
Expand Down
3 changes: 3 additions & 0 deletions tests/test_cpp_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ def test_cpp_table_init(self):
t1 = awkward_cpp.Table(a)
t2 = awkward_cpp.Table({'column1' : a, 'column2' : b, 'column3' : c})
t3 = awkward_cpp.Table(column1 = a, column2 = b)
print(t1["0"])
print(t2["column1"])
print(t3["column1"])
pass
# def test_table_nbytes(self):
# assert isinstance(Table([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9]).nbytes, int)
Expand Down

0 comments on commit 327c833

Please sign in to comment.