Skip to content

Commit ea2017e

Browse files
committed
* Prototype array view interface
* Buffer slicing and copying * Test ArrayView constructors and copy/move assignment * Test ArrayView::Slice, EnsureMutable, and some array attrs Change-Id: Id4c1d7b95f958d207b443829a53078b3e7ac27f0
1 parent b982d96 commit ea2017e

26 files changed

+727
-345
lines changed

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ if (UNIX)
574574
# Full lint
575575
add_custom_target(lint ${BUILD_SUPPORT_DIR}/cpplint.py
576576
--verbose=4
577-
--filter=-whitespace/comments,-readability/todo,-build/header_guard,-build/include_order
577+
--filter=-whitespace/comments,-readability/todo,-build/header_guard,-build/include_order,-build/c++11
578578
`find ${CMAKE_CURRENT_SOURCE_DIR}/src -name \\*.cc -or -name \\*.h`)
579579
endif (UNIX)
580580

@@ -611,12 +611,12 @@ set(PANDAS_SRCS
611611
src/pandas/numpy_interop.cc
612612
src/pandas/pytypes.cc
613613
src/pandas/status.cc
614-
src/pandas/types.cc
614+
src/pandas/type.cc
615615

616616
src/pandas/types/boolean.cc
617+
src/pandas/types/common.cc
617618
src/pandas/types/category.cc
618-
src/pandas/types/integer.cc
619-
src/pandas/types/floating.cc
619+
src/pandas/types/numeric.cc
620620
)
621621

622622
add_library(pandas SHARED

src/pandas/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ install(FILES
1111

1212
set(PANDAS_TEST_LINK_LIBS pandas_test_util ${PANDAS_MIN_TEST_LIBS})
1313

14+
ADD_PANDAS_TEST(array-test)
1415
ADD_PANDAS_TEST(buffer-test)
1516
ADD_PANDAS_TEST(memory-test)
1617
ADD_PANDAS_TEST(util-test)

src/pandas/api.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66

77
#include "pandas/array.h"
88
#include "pandas/dispatch.h"
9-
#include "pandas/types.h"
9+
#include "pandas/status.h"
10+
#include "pandas/type.h"
1011

1112
#include "pandas/types/boolean.h"
1213
#include "pandas/types/category.h"
13-
#include "pandas/types/floating.h"
14-
#include "pandas/types/integer.h"
15-
16-
#include "pandas/status.h"
14+
#include "pandas/types/numeric.h"
1715

1816
#endif // PANDAS_API_H

src/pandas/array-test.cc

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// This file is a part of pandas. See LICENSE for details about reuse and
2+
// copyright holders
3+
4+
// Test non-type specific array functionality
5+
6+
#include <cstdint>
7+
#include <limits>
8+
#include <string>
9+
10+
#include "gtest/gtest.h"
11+
12+
#include "pandas/array.h"
13+
#include "pandas/buffer.h"
14+
#include "pandas/memory.h"
15+
#include "pandas/status.h"
16+
#include "pandas/test-util.h"
17+
#include "pandas/type.h"
18+
#include "pandas/types/numeric.h"
19+
20+
using std::string;
21+
22+
namespace pandas {
23+
24+
class TestArray : public ::testing::Test {
25+
public:
26+
void SetUp() {
27+
values_ = {0, 1, 2, 3, 4, 5, 6, 7};
28+
29+
auto buffer = std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(values_.data()),
30+
values_.size() * sizeof(double));
31+
32+
array_ = std::make_shared<DoubleArray>(values_.size(), buffer);
33+
}
34+
35+
protected:
36+
std::shared_ptr<Array> array_;
37+
std::vector<double> values_;
38+
};
39+
40+
TEST_F(TestArray, Attrs) {
41+
DoubleType ex_type;
42+
ASSERT_TRUE(array_->type()->Equals(ex_type));
43+
ASSERT_EQ(DataType::DOUBLE, array_->type_id());
44+
45+
ASSERT_EQ(values_.size(), array_->length());
46+
}
47+
48+
// ----------------------------------------------------------------------
49+
// Array view object
50+
51+
class TestArrayView : public ::testing::Test {
52+
public:
53+
using value_t = double;
54+
55+
void SetUp() {
56+
values_ = {0, 1, 2, 3, 4, 5, 6, 7};
57+
58+
auto buffer = std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(values_.data()),
59+
values_.size() * sizeof(value_t));
60+
61+
auto arr = std::make_shared<DoubleArray>(values_.size(), buffer);
62+
view_ = ArrayView(arr);
63+
}
64+
65+
protected:
66+
ArrayView view_;
67+
std::vector<value_t> values_;
68+
};
69+
70+
TEST_F(TestArrayView, Ctors) {
71+
ASSERT_EQ(1, view_.ref_count());
72+
ASSERT_EQ(0, view_.offset());
73+
ASSERT_EQ(values_.size(), view_.length());
74+
75+
// Copy ctor
76+
ArrayView view2(view_);
77+
ASSERT_EQ(2, view2.ref_count());
78+
ASSERT_EQ(0, view_.offset());
79+
ASSERT_EQ(values_.size(), view_.length());
80+
81+
// move ctor
82+
ArrayView view3(view_.data(), 3);
83+
ArrayView view4(std::move(view3));
84+
ASSERT_EQ(3, view4.ref_count());
85+
ASSERT_EQ(3, view3.offset());
86+
ASSERT_EQ(values_.size() - 3, view3.length());
87+
88+
// With offset and length
89+
ArrayView view5(view4.data(), 2, 4);
90+
ASSERT_EQ(2, view5.offset());
91+
ASSERT_EQ(4, view5.length());
92+
93+
// Copy assignment
94+
ArrayView view6 = view5;
95+
ASSERT_EQ(5, view4.ref_count());
96+
ASSERT_EQ(2, view5.offset());
97+
ASSERT_EQ(4, view5.length());
98+
99+
// Move assignment
100+
ArrayView view7 = std::move(view6);
101+
ASSERT_EQ(5, view4.ref_count());
102+
ASSERT_EQ(2, view5.offset());
103+
ASSERT_EQ(4, view5.length());
104+
}
105+
106+
TEST_F(TestArrayView, EnsureMutable) {
107+
// This only tests for one data type -- we will need to test more rigorously
108+
// across all data types elsewhere
109+
110+
const Array* ap = view_.data().get();
111+
112+
ASSERT_OK(view_.EnsureMutable());
113+
ASSERT_EQ(ap, view_.data().get());
114+
115+
ArrayView view2 = view_;
116+
117+
ASSERT_OK(view_.EnsureMutable());
118+
119+
// The views now have their own distinct copies of the array
120+
ASSERT_NE(ap, view_.data().get());
121+
ASSERT_EQ(ap, view2.data().get());
122+
123+
ASSERT_EQ(1, view_.ref_count());
124+
ASSERT_EQ(1, view2.ref_count());
125+
}
126+
127+
TEST_F(TestArrayView, Slice) {
128+
ArrayView s1 = view_.Slice(3);
129+
ASSERT_EQ(2, s1.ref_count());
130+
ASSERT_EQ(3, s1.offset());
131+
ASSERT_EQ(view_.length() - 3, s1.length());
132+
133+
ArrayView s2 = view_.Slice(2, 4);
134+
ASSERT_EQ(3, s2.ref_count());
135+
ASSERT_EQ(2, s2.offset());
136+
ASSERT_EQ(4, s2.length());
137+
138+
// Slice of a slice
139+
ArrayView s3 = s1.Slice(2);
140+
ASSERT_EQ(4, s3.ref_count());
141+
ASSERT_EQ(5, s3.offset());
142+
ASSERT_EQ(view_.length() - 5, s3.length());
143+
144+
ArrayView s4 = s1.Slice(1, 2);
145+
ASSERT_EQ(5, s4.ref_count());
146+
ASSERT_EQ(4, s4.offset());
147+
ASSERT_EQ(2, s4.length());
148+
}
149+
150+
} // namespace pandas

src/pandas/array.cc

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,98 @@
33

44
#include "pandas/array.h"
55
#include "pandas/status.h"
6+
#include "pandas/type.h"
7+
#include "pandas/util/logging.h"
68

79
namespace pandas {
810

11+
// ----------------------------------------------------------------------
12+
// Array
13+
14+
Array::Array(const std::shared_ptr<DataType>& type, int64_t length)
15+
: type_(type),
16+
length_(length) {}
17+
18+
Status Array::Copy(std::shared_ptr<Array>* out) const {
19+
return Copy(0, length_, out);
20+
}
21+
22+
// ----------------------------------------------------------------------
23+
// ArrayView
24+
25+
ArrayView::ArrayView(const std::shared_ptr<Array>& data)
26+
: data_(data),
27+
offset_(0),
28+
length_(data->length()) {}
29+
30+
ArrayView::ArrayView(const std::shared_ptr<Array>& data, int64_t offset)
31+
: data_(data),
32+
offset_(offset),
33+
length_(data->length() - offset) {
34+
// Debugging sanity checks
35+
PANDAS_DCHECK_GE(offset, 0);
36+
PANDAS_DCHECK_LT(offset, data->length());
37+
}
38+
39+
ArrayView::ArrayView(const std::shared_ptr<Array>& data, int64_t offset, int64_t length)
40+
: data_(data),
41+
offset_(offset),
42+
length_(length) {
43+
// Debugging sanity checks
44+
PANDAS_DCHECK_GE(offset, 0);
45+
PANDAS_DCHECK_LT(offset, data->length());
46+
PANDAS_DCHECK_GE(length, 0);
47+
PANDAS_DCHECK_LE(length, data->length() - offset);
48+
}
49+
50+
// Copy ctor
51+
ArrayView::ArrayView(const ArrayView& other)
52+
: data_(other.data_),
53+
offset_(other.offset_),
54+
length_(other.length_) {}
55+
56+
// Move ctor
57+
ArrayView::ArrayView(ArrayView&& other)
58+
: data_(std::move(other.data_)),
59+
offset_(other.offset_),
60+
length_(other.length_) {}
61+
62+
// Copy assignment
63+
ArrayView& ArrayView::operator=(const ArrayView& other) {
64+
data_ = other.data_;
65+
offset_ = other.offset_;
66+
length_ = other.length_;
67+
return *this;
68+
}
69+
70+
// Move assignment
71+
ArrayView& ArrayView::operator=(ArrayView&& other) {
72+
data_ = std::move(other.data_);
73+
offset_ = other.offset_;
74+
length_ = other.length_;
75+
return *this;
76+
}
77+
78+
Status ArrayView::EnsureMutable() {
79+
if (ref_count() > 1) {
80+
std::shared_ptr<Array> copied_data;
81+
RETURN_NOT_OK(data_->Copy(&copied_data));
82+
data_ = copied_data;
83+
}
84+
return Status::OK();
85+
}
86+
87+
ArrayView ArrayView::Slice(int64_t offset) {
88+
return ArrayView(data_, offset_ + offset, length_ - offset);
89+
}
90+
91+
ArrayView ArrayView::Slice(int64_t offset, int64_t length) {
92+
return ArrayView(data_, offset_ + offset, length);
93+
}
94+
95+
// Return the reference count for the underlying array
96+
int64_t ArrayView::ref_count() const {
97+
return data_.use_count();
98+
}
99+
9100
} // namespace pandas

0 commit comments

Comments
 (0)