1 | // Copyright 2019 Glen Joseph Fernandes |
2 | // (glenjofe@gmail.com) |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. |
5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #include <boost/core/lightweight_test.hpp> |
9 | #include <boost/multi_array.hpp> |
10 | #include <algorithm> |
11 | |
12 | template<class T> |
13 | class creator { |
14 | public: |
15 | typedef T value_type; |
16 | typedef T* pointer; |
17 | typedef std::size_t size_type; |
18 | typedef std::ptrdiff_t difference_type; |
19 | |
20 | template<class U> |
21 | struct rebind { |
22 | typedef creator<U> other; |
23 | }; |
24 | |
25 | creator(int state) |
26 | : state_(state) { } |
27 | |
28 | template<class U> |
29 | creator(const creator<U>& other) |
30 | : state_(other.state()) { } |
31 | |
32 | T* allocate(std::size_t size) { |
33 | return static_cast<T*>(::operator new(sizeof(T) * size)); |
34 | } |
35 | |
36 | void deallocate(T* ptr, std::size_t) { |
37 | ::operator delete(ptr); |
38 | } |
39 | |
40 | int state() const { |
41 | return state_; |
42 | } |
43 | |
44 | private: |
45 | int state_; |
46 | }; |
47 | |
48 | template<class T, class U> |
49 | inline bool |
50 | operator==(const creator<T>& a, const creator<U>& b) |
51 | { |
52 | return a.state() == b.state(); |
53 | } |
54 | |
55 | template<class T, class U> |
56 | inline bool |
57 | operator!=(const creator<T>& a, const creator<U>& b) |
58 | { |
59 | return !(a == b); |
60 | } |
61 | |
62 | void test(const double&, std::size_t*, int*, unsigned) |
63 | { |
64 | } |
65 | |
66 | template<class Array> |
67 | void test(const Array& array, std::size_t* sizes, int* strides, |
68 | unsigned elements) |
69 | { |
70 | BOOST_TEST(array.num_elements() == elements); |
71 | BOOST_TEST(array.size() == *sizes); |
72 | BOOST_TEST(std::equal(sizes, sizes + array.num_dimensions(), array.shape())); |
73 | BOOST_TEST(std::equal(strides, strides + array.num_dimensions(), |
74 | array.strides())); |
75 | test(array[0], ++sizes, ++strides, elements / array.size()); |
76 | } |
77 | |
78 | bool test(const double& a, const double& b) |
79 | { |
80 | return a == b; |
81 | } |
82 | |
83 | template<class A1, class A2> |
84 | bool test(const A1& a1, const A2& a2) |
85 | { |
86 | typename A1::const_iterator i1 = a1.begin(); |
87 | typename A2::const_iterator i2 = a2.begin(); |
88 | for (; i1 != a1.end(); ++i1, ++i2) { |
89 | if (!test(*i1, *i2)) { |
90 | return false; |
91 | } |
92 | } |
93 | return true; |
94 | } |
95 | |
96 | int main() |
97 | { |
98 | typedef boost::multi_array<double, 3, creator<double> > type; |
99 | creator<double> state(1); |
100 | { |
101 | type array(state); |
102 | } |
103 | boost::array<type::size_type, 3> sizes = { .elems: { 3, 3, 3 } }; |
104 | type::size_type elements = 27; |
105 | { |
106 | int strides[] = { 9, 3, 1 }; |
107 | type array(sizes, state); |
108 | test(array, sizes: &sizes[0], strides, elements); |
109 | } |
110 | { |
111 | int strides[] = { 1, 3, 9 }; |
112 | type array(sizes, boost::fortran_storage_order(), state); |
113 | test(array, sizes: &sizes[0], strides, elements); |
114 | } |
115 | { |
116 | int strides[] = { 9, 3, 1 }; |
117 | type::extent_gen extents; |
118 | type array(extents[3][3][3], state); |
119 | test(array, sizes: &sizes[0], strides, elements); |
120 | } |
121 | { |
122 | type array1(sizes, state); |
123 | std::vector<double> values(elements, 4.5); |
124 | array1.assign(begin: values.begin(), end: values.end()); |
125 | type array2(array1); |
126 | int strides[] = { 9, 3, 1 }; |
127 | test(array: array2, sizes: &sizes[0], strides, elements); |
128 | BOOST_TEST(test(array1, array2)); |
129 | } |
130 | { |
131 | type array1(sizes, state); |
132 | type array2(sizes, state); |
133 | std::vector<double> values(elements, 4.5); |
134 | array1.assign(begin: values.begin(), end: values.end()); |
135 | array2 = array1; |
136 | int strides[] = { 9, 3, 1 }; |
137 | test(array: array2, sizes: &sizes[0], strides, elements); |
138 | BOOST_TEST(test(array1, array2)); |
139 | } |
140 | { |
141 | type array1(sizes, state); |
142 | std::vector<double> values(elements, 4.5); |
143 | array1.assign(begin: values.begin(), end: values.end()); |
144 | typedef type::subarray<2>::type other; |
145 | other array2 = array1[1]; |
146 | other::value_type value = array2[0]; |
147 | BOOST_TEST(test(array1[1][0], value)); |
148 | BOOST_TEST(test(array2[0], value)); |
149 | } |
150 | return boost::report_errors(); |
151 | } |
152 | |