| 81 | } |
| 82 | |
| 83 | TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { |
| 84 | auto* params = |
| 85 | reinterpret_cast<TfLiteDepthwiseConvParams*>(node->builtin_data); |
| 86 | OpData* data = reinterpret_cast<OpData*>(node->user_data); |
| 87 | |
| 88 | // TODO(ahentz): use could use GetOptionalInputTensor() here, but we need to |
| 89 | // decide whether we are OK with optional tensors being completely absent, as |
| 90 | // opposed to having -1 as their index. |
| 91 | bool hasBias = NumInputs(node) == 3; |
| 92 | |
| 93 | TF_LITE_ENSURE(context, hasBias || NumInputs(node) == 2); |
| 94 | const TfLiteTensor* input = GetInput(context, node, kInputTensor); |
| 95 | const TfLiteTensor* filter = GetInput(context, node, kFilterTensor); |
| 96 | const TfLiteTensor* bias = nullptr; |
| 97 | |
| 98 | TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); |
| 99 | TfLiteTensor* output = GetOutput(context, node, kOutputTensor); |
| 100 | |
| 101 | TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4); |
| 102 | TF_LITE_ENSURE_EQ(context, NumDimensions(filter), 4); |
| 103 | TF_LITE_ENSURE(context, params->dilation_height_factor > 0); |
| 104 | TF_LITE_ENSURE(context, params->dilation_width_factor > 0); |
| 105 | |
| 106 | // The parameter 'depth_multiplier' is redundant, so we check here to make |
| 107 | // sure it is consistent with the given dimensions. |
| 108 | TF_LITE_ENSURE_EQ(context, |
| 109 | params->depth_multiplier * SizeOfDimension(input, 3), |
| 110 | SizeOfDimension(filter, 3)); |
| 111 | |
| 112 | const TfLiteType data_type = input->type; |
| 113 | TF_LITE_ENSURE(context, data_type == kTfLiteFloat32 || |
| 114 | data_type == kTfLiteUInt8 || |
| 115 | data_type == kTfLiteInt8); |
| 116 | TF_LITE_ENSURE_EQ(context, output->type, data_type); |
| 117 | TF_LITE_ENSURE_EQ(context, filter->type, data_type); |
| 118 | // Filter in DepthwiseConv is expected to be [1, H, W, O]. |
| 119 | TF_LITE_ENSURE_EQ(context, SizeOfDimension(filter, 0), 1); |
| 120 | |
| 121 | if (hasBias) { |
| 122 | bias = GetInput(context, node, kBiasTensor); |
| 123 | if (data_type == kTfLiteUInt8 || data_type == kTfLiteInt8) { |
| 124 | TF_LITE_ENSURE_EQ(context, bias->type, kTfLiteInt32); |
| 125 | TF_LITE_ENSURE_EQ(context, bias->params.zero_point, 0); |
| 126 | } else { |
| 127 | TF_LITE_ENSURE_EQ(context, bias->type, data_type); |
| 128 | } |
| 129 | TF_LITE_ENSURE_EQ(context, NumDimensions(bias), 1); |
| 130 | TF_LITE_ENSURE_EQ(context, SizeOfDimension(filter, 3), |
| 131 | SizeOfDimension(bias, 0)); |
| 132 | } |
| 133 | |
| 134 | int channels_out = SizeOfDimension(filter, 3); |
| 135 | int width = SizeOfDimension(input, 2); |
| 136 | int height = SizeOfDimension(input, 1); |
| 137 | int filter_width = SizeOfDimension(filter, 2); |
| 138 | int filter_height = SizeOfDimension(filter, 1); |
| 139 | int batches = SizeOfDimension(input, 0); |
| 140 |
nothing calls this directly
no test coverage detected