aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/kernels/ops_util.cc
blob: ca2925128e8492a11c1da5f9261c6c1459901641 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <cmath>

#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/util/padding.h"

namespace tensorflow {

void RequireDefaultOps() {
// TODO(opensource): Use a more generic sounding preprocessor name than
// GOOGLE_CUDA (maybe SUPPORT_CUDA?)
#if GOOGLE_CUDA
  void RequireGPUDevice();
  RequireGPUDevice();
#endif
}

Status Get2dOutputSize(const int in_height, const int in_width,
                       int filter_height, int filter_width, int row_stride,
                       int col_stride, Padding padding, int* new_height,
                       int* new_width, int* pad_rows, int* pad_cols) {
  int pad_bottom_unused, pad_right_unused;
  return Get2dOutputSizeVerbose(
      in_height, in_width, filter_height, filter_width, row_stride, col_stride,
      padding, new_height, new_width, pad_rows, &pad_bottom_unused, pad_cols,
      &pad_right_unused);
}

Status Get2dOutputSizeVerbose(const int in_height, const int in_width,
                              int filter_height, int filter_width,
                              int row_stride, int col_stride, Padding padding,
                              int* new_height, int* new_width, int* pad_top,
                              int* pad_bottom, int* pad_left, int* pad_right) {
  // Cannot have strides larger than the patch size.
  if (row_stride > filter_height || col_stride > filter_width) {
    return errors::InvalidArgument(
        "stride must be less than or equal to kernel size");
  }
  switch (padding) {
    case Padding::VALID:
      *new_height = ceil((in_height - filter_height + 1.f) /
                         static_cast<float>(row_stride));
      *new_width = ceil((in_width - filter_width + 1.f) /
                        static_cast<float>(col_stride));
      *pad_top = 0;
      *pad_bottom = 0;
      *pad_left = 0;
      *pad_right = 0;
      break;
    case Padding::SAME:
      *new_height = ceil(in_height / static_cast<float>(row_stride));
      *new_width = ceil(in_width / static_cast<float>(col_stride));
      // Calculate padding for top/bottom/left/right, spilling any excess
      // padding to bottom and right.
      const int pad_needed_height =
          (*new_height - 1) * row_stride + filter_height - in_height;
      *pad_top = pad_needed_height / 2;
      CHECK_GE(pad_needed_height, 0);
      *pad_bottom = pad_needed_height - *pad_top;

      const int pad_needed_width =
          (*new_width - 1) * col_stride + filter_width - in_width;
      *pad_left = pad_needed_width / 2;
      CHECK_GE(pad_needed_width, 0);
      *pad_right = pad_needed_width - *pad_left;
      break;
  }
  if (*new_height < 0 || *new_width < 0) {
    return errors::InvalidArgument("computed output size would be negative");
  }
  return Status::OK();
}

Eigen::PaddingType BrainPadding2EigenPadding(Padding padding) {
  switch (padding) {
    case Padding::VALID:
      return Eigen::PADDING_VALID;
    case Padding::SAME:
      return Eigen::PADDING_SAME;
  }
  return Eigen::PADDING_SAME;  // Prevent compiler warning about missing return
}

Status GetBroadcastSize(const int index, const int in_size,
                             const int ksize, const int stride,
                             const int pad_size, int* bindex, int* bsize) {
  // Cannot have strides larger than the patch size.
  if (stride > ksize) {
    return errors::InvalidArgument(
        "stride must be less than or equal to kernel size");
  }
  // Cannot have index beyond the input size.
  if (index * stride > in_size) {
    return errors::InvalidArgument(
        "index * stride must be less than or equal to input size");
  }
  *bindex = index * stride;
  *bsize = ksize;
  if (*bindex < pad_size) {
    // If the current index is in the padding area, start broadcast  from index
    // 0 with broadcast size reduced by padding size.
    *bsize = ksize + *bindex - pad_size;
    *bindex = 0;
  } else {
    // Otherwise, start broadcast from current index reduced by padding size.
    *bindex -= pad_size;
  }
  if (*bindex + ksize > in_size) {
    *bsize = std::min((in_size - *bindex), ksize);
  }
  return Status::OK();
}
}  // namespace tensorflow