cxx11_tensor_block_io.cpp File Reference
#include "main.h"
#include <Eigen/CXX11/Tensor>

Macros

#define CALL_SUBTESTS(NAME)
 

Functions

template<int NumDims>
static DSizes< Index, NumDims > RandomDims (Index min, Index max)
 
static internal::TensorBlockShapeType RandomBlockShape ()
 
template<int NumDims>
static size_t RandomTargetBlockSize (const DSizes< Index, NumDims > &dims)
 
template<int Layout, int NumDims>
static Index GetInputIndex (Index output_index, const array< Index, NumDims > &output_to_input_dim_map, const array< Index, NumDims > &input_strides, const array< Index, NumDims > &output_strides)
 
template<typename T , int NumDims, int Layout>
static void test_block_io_copy_data_from_source_to_target ()
 
template<typename T , int NumDims, int Layout>
static void test_block_io_copy_using_reordered_dimensions ()
 
template<int Layout>
static void test_block_io_copy_using_reordered_dimensions_do_not_squeeze ()
 
template<int Layout>
static void test_block_io_copy_using_reordered_dimensions_squeeze ()
 
template<int Layout>
static void test_block_io_zero_stride ()
 
template<int Layout>
static void test_block_io_squeeze_ones ()
 
 EIGEN_DECLARE_TEST (cxx11_tensor_block_io)
 

Macro Definition Documentation

◆ CALL_SUBTESTS

#define CALL_SUBTESTS (   NAME)
Value:
CALL_SUBTEST((NAME<float, 1, RowMajor>())); \
CALL_SUBTEST((NAME<float, 2, RowMajor>())); \
CALL_SUBTEST((NAME<float, 4, RowMajor>())); \
CALL_SUBTEST((NAME<float, 5, RowMajor>())); \
CALL_SUBTEST((NAME<float, 1, ColMajor>())); \
CALL_SUBTEST((NAME<float, 2, ColMajor>())); \
CALL_SUBTEST((NAME<float, 4, ColMajor>())); \
CALL_SUBTEST((NAME<float, 5, ColMajor>())); \
CALL_SUBTEST((NAME<bool, 1, RowMajor>())); \
CALL_SUBTEST((NAME<bool, 2, RowMajor>())); \
CALL_SUBTEST((NAME<bool, 4, RowMajor>())); \
CALL_SUBTEST((NAME<bool, 5, RowMajor>())); \
CALL_SUBTEST((NAME<bool, 1, ColMajor>())); \
CALL_SUBTEST((NAME<bool, 2, ColMajor>())); \
CALL_SUBTEST((NAME<bool, 4, ColMajor>())); \
CALL_SUBTEST((NAME<bool, 5, ColMajor>()))
#define CALL_SUBTEST(FUNC)
Definition: main.h:382

Function Documentation

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( cxx11_tensor_block_io  )
415  {
416  // clang-format off
419 
420  CALL_SUBTEST(test_block_io_copy_using_reordered_dimensions_do_not_squeeze<RowMajor>());
421  CALL_SUBTEST(test_block_io_copy_using_reordered_dimensions_do_not_squeeze<ColMajor>());
422 
423  CALL_SUBTEST(test_block_io_copy_using_reordered_dimensions_squeeze<RowMajor>());
424  CALL_SUBTEST(test_block_io_copy_using_reordered_dimensions_squeeze<ColMajor>());
425 
426  CALL_SUBTEST(test_block_io_zero_stride<RowMajor>());
427  CALL_SUBTEST(test_block_io_zero_stride<ColMajor>());
428 
429  CALL_SUBTEST(test_block_io_squeeze_ones<RowMajor>());
430  CALL_SUBTEST(test_block_io_squeeze_ones<ColMajor>());
431  // clang-format on
432 }
static void test_block_io_copy_data_from_source_to_target()
Definition: cxx11_tensor_block_io.cpp:57
#define CALL_SUBTESTS(NAME)
Definition: cxx11_tensor_block_io.cpp:397
static void test_block_io_copy_using_reordered_dimensions()
Definition: cxx11_tensor_block_io.cpp:114

References CALL_SUBTEST, CALL_SUBTESTS, test_block_io_copy_data_from_source_to_target(), and test_block_io_copy_using_reordered_dimensions().

◆ GetInputIndex()

template<int Layout, int NumDims>
static Index GetInputIndex ( Index  output_index,
const array< Index, NumDims > &  output_to_input_dim_map,
const array< Index, NumDims > &  input_strides,
const array< Index, NumDims > &  output_strides 
)
static
37  {
38  int input_index = 0;
39  if (Layout == ColMajor) {
40  for (int i = NumDims - 1; i > 0; --i) {
41  const Index idx = output_index / output_strides[i];
42  input_index += idx * input_strides[output_to_input_dim_map[i]];
43  output_index -= idx * output_strides[i];
44  }
45  return input_index + output_index * input_strides[output_to_input_dim_map[0]];
46  } else {
47  for (int i = 0; i < NumDims - 1; ++i) {
48  const Index idx = output_index / output_strides[i];
49  input_index += idx * input_strides[output_to_input_dim_map[i]];
50  output_index -= idx * output_strides[i];
51  }
52  return input_index + output_index * input_strides[output_to_input_dim_map[NumDims - 1]];
53  }
54 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
@ ColMajor
Definition: Constants.h:318
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83

References Eigen::ColMajor, and i.

◆ RandomBlockShape()

static internal::TensorBlockShapeType RandomBlockShape ( )
static
25  {
26  return internal::random<bool>() ? internal::TensorBlockShapeType::kUniformAllDims
27  : internal::TensorBlockShapeType::kSkewedInnerDims;
28 }

Referenced by test_block_io_copy_data_from_source_to_target(), and test_block_io_copy_using_reordered_dimensions().

◆ RandomDims()

template<int NumDims>
static DSizes<Index, NumDims> RandomDims ( Index  min,
Index  max 
)
static
17  {
19  for (int i = 0; i < NumDims; ++i) {
20  dims[i] = internal::random<Index>(min, max);
21  }
22  return DSizes<Index, NumDims>(dims);
23 }
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23

References i, max, and min.

◆ RandomTargetBlockSize()

template<int NumDims>
static size_t RandomTargetBlockSize ( const DSizes< Index, NumDims > &  dims)
static
31  {
32  return internal::random<size_t>(1, dims.TotalSize());
33 }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex TotalSize() const
Definition: TensorDimensions.h:167

References Eigen::DSizes< DenseIndex, NumDims >::TotalSize().

Referenced by test_block_io_copy_data_from_source_to_target(), and test_block_io_copy_using_reordered_dimensions().

◆ test_block_io_copy_data_from_source_to_target()

template<typename T , int NumDims, int Layout>
static void test_block_io_copy_data_from_source_to_target ( )
static
57  {
58  using TensorBlockIO = internal::TensorBlockIO<T, Index, NumDims, Layout>;
59  using IODst = typename TensorBlockIO::Dst;
60  using IOSrc = typename TensorBlockIO::Src;
61 
62  // Generate a random input Tensor.
63  DSizes<Index, NumDims> dims = RandomDims<NumDims>(1, 30);
64  Tensor<T, NumDims, Layout> input(dims);
65  input.setRandom();
66 
67  // Write data to an output Tensor.
69 
70  // Construct a tensor block mapper.
71  using TensorBlockMapper = internal::TensorBlockMapper<NumDims, Layout, Index>;
72  TensorBlockMapper block_mapper(dims, {RandomBlockShape(), RandomTargetBlockSize(dims), {0, 0, 0}});
73 
74  // We will copy data from input to output through this buffer.
75  Tensor<T, NumDims, Layout> block(block_mapper.blockDimensions());
76 
77  // Precompute strides for TensorBlockIO::Copy.
78  auto input_strides = internal::strides<Layout>(dims);
79  auto output_strides = internal::strides<Layout>(dims);
80 
81  const T* input_data = input.data();
82  T* output_data = output.data();
83  T* block_data = block.data();
84 
85  for (int i = 0; i < block_mapper.blockCount(); ++i) {
86  auto desc = block_mapper.blockDescriptor(i);
87 
88  auto blk_dims = desc.dimensions();
89  auto blk_strides = internal::strides<Layout>(blk_dims);
90 
91  {
92  // Read from input into a block buffer.
93  IODst dst(blk_dims, blk_strides, block_data, 0);
94  IOSrc src(input_strides, input_data, desc.offset());
95 
96  TensorBlockIO::Copy(dst, src);
97  }
98 
99  {
100  // Write from block buffer to output.
101  IODst dst(blk_dims, output_strides, output_data, desc.offset());
102  IOSrc src(blk_strides, block_data, 0);
103 
104  TensorBlockIO::Copy(dst, src);
105  }
106  }
107 
108  for (int i = 0; i < dims.TotalSize(); ++i) {
109  VERIFY_IS_EQUAL(input_data[i], output_data[i]);
110  }
111 }
m m block(1, 0, 2, 2)<< 4
The tensor class.
Definition: Tensor.h:68
static internal::TensorBlockShapeType RandomBlockShape()
Definition: cxx11_tensor_block_io.cpp:25
static size_t RandomTargetBlockSize(const DSizes< Index, NumDims > &dims)
Definition: cxx11_tensor_block_io.cpp:31
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:367
void output(std::ostream &outfile, const unsigned &nplot)
Overload output function.
Definition: overloaded_element_body.h:490

References block(), Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), i, output(), RandomBlockShape(), RandomTargetBlockSize(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), Eigen::DSizes< DenseIndex, NumDims >::TotalSize(), and VERIFY_IS_EQUAL.

Referenced by EIGEN_DECLARE_TEST().

◆ test_block_io_copy_using_reordered_dimensions()

template<typename T , int NumDims, int Layout>
static void test_block_io_copy_using_reordered_dimensions ( )
static
114  {
115  // Generate a random input Tensor.
116  DSizes<Index, NumDims> dims = RandomDims<NumDims>(1, 30);
117  Tensor<T, NumDims, Layout> input(dims);
118  input.setRandom();
119 
120  // Create a random dimension re-ordering/shuffle.
121  std::vector<int> shuffle;
122 
123  for (int i = 0; i < NumDims; ++i) shuffle.push_back(i);
124  std::shuffle(shuffle.begin(), shuffle.end(), std::mt19937(g_seed));
125 
126  DSizes<Index, NumDims> output_tensor_dims;
127  DSizes<Index, NumDims> input_to_output_dim_map;
128  DSizes<Index, NumDims> output_to_input_dim_map;
129  for (Index i = 0; i < NumDims; ++i) {
130  output_tensor_dims[shuffle[i]] = dims[i];
131  input_to_output_dim_map[i] = shuffle[i];
132  output_to_input_dim_map[shuffle[i]] = i;
133  }
134 
135  // Write data to an output Tensor.
136  Tensor<T, NumDims, Layout> output(output_tensor_dims);
137 
138  // Construct a tensor block mapper.
139  // NOTE: Tensor block mapper works with shuffled dimensions.
140  using TensorBlockMapper = internal::TensorBlockMapper<NumDims, Layout, Index>;
141  TensorBlockMapper block_mapper(output_tensor_dims,
142  {RandomBlockShape(), RandomTargetBlockSize(output_tensor_dims), {0, 0, 0}});
143 
144  // We will copy data from input to output through this buffer.
145  Tensor<T, NumDims, Layout> block(block_mapper.blockDimensions());
146 
147  // Precompute strides for TensorBlockIO::Copy.
148  auto input_strides = internal::strides<Layout>(dims);
149  auto output_strides = internal::strides<Layout>(output_tensor_dims);
150 
151  const T* input_data = input.data();
152  T* output_data = output.data();
153  T* block_data = block.data();
154 
155  for (Index i = 0; i < block_mapper.blockCount(); ++i) {
156  auto desc = block_mapper.blockDescriptor(i);
157 
158  const Index first_coeff_index =
159  GetInputIndex<Layout, NumDims>(desc.offset(), output_to_input_dim_map, input_strides, output_strides);
160 
161  // NOTE: Block dimensions are in the same order as output dimensions.
162 
163  using TensorBlockIO = internal::TensorBlockIO<T, Index, NumDims, Layout>;
164  using IODst = typename TensorBlockIO::Dst;
165  using IOSrc = typename TensorBlockIO::Src;
166 
167  auto blk_dims = desc.dimensions();
168  auto blk_strides = internal::strides<Layout>(blk_dims);
169 
170  {
171  // Read from input into a block buffer.
172  IODst dst(blk_dims, blk_strides, block_data, 0);
173  IOSrc src(input_strides, input_data, first_coeff_index);
174 
175  // TODO(ezhulenev): Remove when fully switched to TensorBlock.
176  DSizes<int, NumDims> dim_map;
177  for (int j = 0; j < NumDims; ++j) dim_map[j] = static_cast<int>(output_to_input_dim_map[j]);
178  TensorBlockIO::Copy(dst, src, /*dst_to_src_dim_map=*/dim_map);
179  }
180 
181  {
182  // We need to convert block dimensions from output to input order.
183  auto dst_dims = blk_dims;
184  for (int out_dim = 0; out_dim < NumDims; ++out_dim) {
185  dst_dims[output_to_input_dim_map[out_dim]] = blk_dims[out_dim];
186  }
187 
188  // Write from block buffer to output.
189  IODst dst(dst_dims, input_strides, output_data, first_coeff_index);
190  IOSrc src(blk_strides, block_data, 0);
191 
192  // TODO(ezhulenev): Remove when fully switched to TensorBlock.
193  DSizes<int, NumDims> dim_map;
194  for (int j = 0; j < NumDims; ++j) dim_map[j] = static_cast<int>(input_to_output_dim_map[j]);
195  TensorBlockIO::Copy(dst, src, /*dst_to_src_dim_map=*/dim_map);
196  }
197  }
198 
199  for (Index i = 0; i < dims.TotalSize(); ++i) {
200  VERIFY_IS_EQUAL(input_data[i], output_data[i]);
201  }
202 }
EIGEN_STRONG_INLINE Packet2d shuffle(const Packet2d &m, const Packet2d &n, int mask)
Definition: LSX/PacketMath.h:150
static unsigned int g_seed
Definition: main.h:192
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References block(), Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), Eigen::g_seed, i, j, output(), RandomBlockShape(), RandomTargetBlockSize(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), Eigen::internal::shuffle(), Eigen::DSizes< DenseIndex, NumDims >::TotalSize(), and VERIFY_IS_EQUAL.

Referenced by EIGEN_DECLARE_TEST().

◆ test_block_io_copy_using_reordered_dimensions_do_not_squeeze()

template<int Layout>
static void test_block_io_copy_using_reordered_dimensions_do_not_squeeze ( )
static
208  {
209  DSizes<Index, 3> tensor_dims(7, 9, 7);
210  DSizes<Index, 3> block_dims = tensor_dims;
211 
212  DSizes<int, 3> block_to_tensor_dim;
213  block_to_tensor_dim[0] = 2;
214  block_to_tensor_dim[1] = 1;
215  block_to_tensor_dim[2] = 0;
216 
217  auto tensor_strides = internal::strides<Layout>(tensor_dims);
218  auto block_strides = internal::strides<Layout>(block_dims);
219 
220  Tensor<float, 3, Layout> block(block_dims);
221  Tensor<float, 3, Layout> tensor(tensor_dims);
222  tensor.setRandom();
223 
224  float* tensor_data = tensor.data();
225  float* block_data = block.data();
226 
227  using TensorBlockIO = internal::TensorBlockIO<float, Index, 3, Layout>;
228  using IODst = typename TensorBlockIO::Dst;
229  using IOSrc = typename TensorBlockIO::Src;
230 
231  // Read from a tensor into a block.
232  IODst dst(block_dims, block_strides, block_data, 0);
233  IOSrc src(tensor_strides, tensor_data, 0);
234 
235  TensorBlockIO::Copy(dst, src, /*dst_to_src_dim_map=*/block_to_tensor_dim);
236 
237  TensorMap<Tensor<float, 3, Layout> > block_tensor(block_data, block_dims);
238  TensorMap<Tensor<float, 3, Layout> > tensor_tensor(tensor_data, tensor_dims);
239 
240  for (Index d0 = 0; d0 < tensor_dims[0]; ++d0) {
241  for (Index d1 = 0; d1 < tensor_dims[1]; ++d1) {
242  for (Index d2 = 0; d2 < tensor_dims[2]; ++d2) {
243  float block_value = block_tensor(d2, d1, d0);
244  float tensor_value = tensor_tensor(d0, d1, d2);
245  VERIFY_IS_EQUAL(block_value, tensor_value);
246  }
247  }
248  }
249 }
A tensor expression mapping an existing array of data.
Definition: TensorMap.h:33

References block(), Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), and VERIFY_IS_EQUAL.

◆ test_block_io_copy_using_reordered_dimensions_squeeze()

template<int Layout>
static void test_block_io_copy_using_reordered_dimensions_squeeze ( )
static
255  {
256  DSizes<Index, 4> tensor_dims(7, 5, 9, 9);
257  DSizes<Index, 4> block_dims = tensor_dims;
258 
259  DSizes<int, 4> block_to_tensor_dim;
260  block_to_tensor_dim[0] = 0;
261  block_to_tensor_dim[1] = 1;
262  block_to_tensor_dim[2] = 3;
263  block_to_tensor_dim[3] = 2;
264 
265  auto tensor_strides = internal::strides<Layout>(tensor_dims);
266  auto block_strides = internal::strides<Layout>(block_dims);
267 
268  Tensor<float, 4, Layout> block(block_dims);
269  Tensor<float, 4, Layout> tensor(tensor_dims);
270  tensor.setRandom();
271 
272  float* tensor_data = tensor.data();
273  float* block_data = block.data();
274 
275  using TensorBlockIO = internal::TensorBlockIO<float, Index, 4, Layout>;
276  using IODst = typename TensorBlockIO::Dst;
277  using IOSrc = typename TensorBlockIO::Src;
278 
279  // Read from a tensor into a block.
280  IODst dst(block_dims, block_strides, block_data, 0);
281  IOSrc src(tensor_strides, tensor_data, 0);
282 
283  TensorBlockIO::Copy(dst, src, /*dst_to_src_dim_map=*/block_to_tensor_dim);
284 
285  TensorMap<Tensor<float, 4, Layout> > block_tensor(block_data, block_dims);
286  TensorMap<Tensor<float, 4, Layout> > tensor_tensor(tensor_data, tensor_dims);
287 
288  for (Index d0 = 0; d0 < tensor_dims[0]; ++d0) {
289  for (Index d1 = 0; d1 < tensor_dims[1]; ++d1) {
290  for (Index d2 = 0; d2 < tensor_dims[2]; ++d2) {
291  for (Index d3 = 0; d3 < tensor_dims[3]; ++d3) {
292  float block_value = block_tensor(d0, d1, d3, d2);
293  float tensor_value = tensor_tensor(d0, d1, d2, d3);
294  VERIFY_IS_EQUAL(block_value, tensor_value);
295  }
296  }
297  }
298  }
299 }

References block(), Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), and VERIFY_IS_EQUAL.

◆ test_block_io_squeeze_ones()

template<int Layout>
static void test_block_io_squeeze_ones ( )
static
351  {
352  using TensorBlockIO = internal::TensorBlockIO<float, Index, 5, Layout>;
353  using IODst = typename TensorBlockIO::Dst;
354  using IOSrc = typename TensorBlockIO::Src;
355 
356  // Total size > 1.
357  {
358  DSizes<Index, 5> block_sizes(1, 2, 1, 2, 1);
359  auto strides = internal::strides<Layout>(block_sizes);
360 
361  // Create a random input tensor.
362  Tensor<float, 5> input(block_sizes);
363  input.setRandom();
364 
365  Tensor<float, 5> output(block_sizes);
366 
367  IODst dst(block_sizes, strides, output.data(), 0);
368  IOSrc src(strides, input.data());
369  TensorBlockIO::Copy(dst, src);
370 
371  for (Index i = 0; i < block_sizes.TotalSize(); ++i) {
372  VERIFY_IS_EQUAL(output.data()[i], input.data()[i]);
373  }
374  }
375 
376  // Total size == 1.
377  {
378  DSizes<Index, 5> block_sizes(1, 1, 1, 1, 1);
379  auto strides = internal::strides<Layout>(block_sizes);
380 
381  // Create a random input tensor.
382  Tensor<float, 5> input(block_sizes);
383  input.setRandom();
384 
385  Tensor<float, 5> output(block_sizes);
386 
387  IODst dst(block_sizes, strides, output.data(), 0);
388  IOSrc src(strides, input.data());
389  TensorBlockIO::Copy(dst, src);
390 
391  for (Index i = 0; i < block_sizes.TotalSize(); ++i) {
392  VERIFY_IS_EQUAL(output.data()[i], input.data()[i]);
393  }
394  }
395 }
EIGEN_ALWAYS_INLINE DSizes< IndexType, NumDims > strides(const DSizes< IndexType, NumDims > &dimensions)
Definition: TensorBlock.h:29

References Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), i, output(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), Eigen::internal::strides(), Eigen::DSizes< DenseIndex, NumDims >::TotalSize(), and VERIFY_IS_EQUAL.

◆ test_block_io_zero_stride()

template<int Layout>
static void test_block_io_zero_stride ( )
static
302  {
303  DSizes<Index, 5> rnd_dims = RandomDims<5>(1, 30);
304 
305  DSizes<Index, 5> input_tensor_dims = rnd_dims;
306  input_tensor_dims[0] = 1;
307  input_tensor_dims[2] = 1;
308  input_tensor_dims[4] = 1;
309 
310  Tensor<float, 5, Layout> input(input_tensor_dims);
311  input.setRandom();
312 
313  DSizes<Index, 5> output_tensor_dims = rnd_dims;
314 
315  auto input_tensor_strides = internal::strides<Layout>(input_tensor_dims);
316  auto output_tensor_strides = internal::strides<Layout>(output_tensor_dims);
317 
318  auto input_tensor_strides_with_zeros = input_tensor_strides;
319  input_tensor_strides_with_zeros[0] = 0;
320  input_tensor_strides_with_zeros[2] = 0;
321  input_tensor_strides_with_zeros[4] = 0;
322 
323  Tensor<float, 5, Layout> output(output_tensor_dims);
324  output.setRandom();
325 
326  using TensorBlockIO = internal::TensorBlockIO<float, Index, 5, Layout>;
327  using IODst = typename TensorBlockIO::Dst;
328  using IOSrc = typename TensorBlockIO::Src;
329 
330  // Write data from input to output with broadcasting in dims [0, 2, 4].
331  IODst dst(output_tensor_dims, output_tensor_strides, output.data(), 0);
332  IOSrc src(input_tensor_strides_with_zeros, input.data(), 0);
333  TensorBlockIO::Copy(dst, src);
334 
335  for (int i = 0; i < output_tensor_dims[0]; ++i) {
336  for (int j = 0; j < output_tensor_dims[1]; ++j) {
337  for (int k = 0; k < output_tensor_dims[2]; ++k) {
338  for (int l = 0; l < output_tensor_dims[3]; ++l) {
339  for (int m = 0; m < output_tensor_dims[4]; ++m) {
340  float input_value = input(0, j, 0, l, 0);
341  float output_value = output(i, j, k, l, m);
342  VERIFY_IS_EQUAL(input_value, output_value);
343  }
344  }
345  }
346  }
347  }
348 }
int * m
Definition: level2_cplx_impl.h:294
char char char int int * k
Definition: level2_impl.h:374

References Eigen::Tensor< Scalar_, NumIndices_, Options_, IndexType_ >::data(), i, j, k, m, output(), Eigen::TensorBase< Derived, AccessLevel >::setRandom(), and VERIFY_IS_EQUAL.