1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2014-2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#include "main.h"
11
12#include <Eigen/CXX11/Tensor>
13
14
15void test_signed_32bit()
16{
17  // Divide by one
18  const Eigen::internal::TensorIntDivisor<int32_t, false> div_by_one(1);
19
20  for (int32_t j = 0; j < 25000; ++j) {
21    const int32_t fast_div = j / div_by_one;
22    const int32_t slow_div = j / 1;
23    VERIFY_IS_EQUAL(fast_div, slow_div);
24  }
25
26  // Standard divide by 2 or more
27  for (int32_t i = 2; i < 25000; ++i) {
28    const Eigen::internal::TensorIntDivisor<int32_t, false> div(i);
29
30    for (int32_t j = 0; j < 25000; ++j) {
31      const int32_t fast_div = j / div;
32      const int32_t slow_div = j / i;
33      VERIFY_IS_EQUAL(fast_div, slow_div);
34    }
35  }
36
37  // Optimized divide by 2 or more
38  for (int32_t i = 2; i < 25000; ++i) {
39    const Eigen::internal::TensorIntDivisor<int32_t, true> div(i);
40
41    for (int32_t j = 0; j < 25000; ++j) {
42      const int32_t fast_div = j / div;
43      const int32_t slow_div = j / i;
44      VERIFY_IS_EQUAL(fast_div, slow_div);
45    }
46  }
47}
48
49
50void test_unsigned_32bit()
51{
52  for (uint32_t i = 1; i < 25000; ++i) {
53    const Eigen::internal::TensorIntDivisor<uint32_t> div(i);
54
55    for (uint32_t j = 0; j < 25000; ++j) {
56      const uint32_t fast_div = j / div;
57      const uint32_t slow_div = j / i;
58      VERIFY_IS_EQUAL(fast_div, slow_div);
59    }
60  }
61}
62
63
64void test_signed_64bit()
65{
66  for (int64_t i = 1; i < 25000; ++i) {
67    const Eigen::internal::TensorIntDivisor<int64_t> div(i);
68
69    for (int64_t j = 0; j < 25000; ++j) {
70      const int64_t fast_div = j / div;
71      const int64_t slow_div = j / i;
72      VERIFY_IS_EQUAL(fast_div, slow_div);
73    }
74  }
75}
76
77
78void test_unsigned_64bit()
79{
80  for (uint64_t i = 1; i < 25000; ++i) {
81    const Eigen::internal::TensorIntDivisor<uint64_t> div(i);
82
83    for (uint64_t j = 0; j < 25000; ++j) {
84      const uint64_t fast_div = j / div;
85      const uint64_t slow_div = j / i;
86      VERIFY_IS_EQUAL(fast_div, slow_div);
87    }
88  }
89}
90
91void test_powers_32bit() {
92  for (int expon = 1; expon < 31; expon++) {
93    int32_t div = (1 << expon);
94    for (int num_expon = 0; num_expon < 32; num_expon++) {
95      int32_t start_num = (1 << num_expon) - 100;
96      int32_t end_num = (1 << num_expon) + 100;
97      if (start_num < 0)
98        start_num = 0;
99      for (int32_t num = start_num; num < end_num; num++) {
100        Eigen::internal::TensorIntDivisor<int32_t> divider =
101          Eigen::internal::TensorIntDivisor<int32_t>(div);
102        int32_t result = num/div;
103        int32_t result_op = divider.divide(num);
104        VERIFY_IS_EQUAL(result_op, result);
105      }
106    }
107  }
108}
109
110void test_powers_64bit() {
111  for (int expon = 0; expon < 63; expon++) {
112    int64_t div = (1ull << expon);
113    for (int num_expon = 0; num_expon < 63; num_expon++) {
114      int64_t start_num = (1ull << num_expon) - 10;
115      int64_t end_num = (1ull << num_expon) + 10;
116      if (start_num < 0)
117        start_num = 0;
118      for (int64_t num = start_num; num < end_num; num++) {
119        Eigen::internal::TensorIntDivisor<int64_t> divider(div);
120        int64_t result = num/div;
121        int64_t result_op = divider.divide(num);
122        VERIFY_IS_EQUAL(result_op, result);
123      }
124    }
125  }
126}
127
128void test_specific() {
129  // A particular combination that was previously failing
130  int64_t div = 209715200;
131  int64_t num = 3238002688ll;
132  Eigen::internal::TensorIntDivisor<int64_t> divider(div);
133  int64_t result = num/div;
134  int64_t result_op = divider.divide(num);
135  VERIFY_IS_EQUAL(result, result_op);
136}
137
138void test_cxx11_tensor_intdiv()
139{
140  CALL_SUBTEST_1(test_signed_32bit());
141  CALL_SUBTEST_2(test_unsigned_32bit());
142  CALL_SUBTEST_3(test_signed_64bit());
143  CALL_SUBTEST_4(test_unsigned_64bit());
144  CALL_SUBTEST_5(test_powers_32bit());
145  CALL_SUBTEST_6(test_powers_64bit());
146  CALL_SUBTEST_7(test_specific());
147}
148