| 3050 | |
| 3051 | template <typename T> |
| 3052 | void Transpose(const TransposeParams& params, |
| 3053 | const RuntimeShape& unextended_input_shape, const T* input_data, |
| 3054 | const RuntimeShape& unextended_output_shape, T* output_data) { |
| 3055 | const int unextended_output_size = unextended_output_shape.DimensionsCount(); |
| 3056 | TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); |
| 3057 | TFLITE_DCHECK_LE(unextended_output_size, 4); |
| 3058 | TFLITE_DCHECK_EQ(unextended_output_size, params.perm_count); |
| 3059 | const RuntimeShape input_shape = |
| 3060 | RuntimeShape::ExtendedShape(4, unextended_input_shape); |
| 3061 | const RuntimeShape output_shape = |
| 3062 | RuntimeShape::ExtendedShape(4, unextended_output_shape); |
| 3063 | const int input_ext_size = 4 - unextended_input_shape.DimensionsCount(); |
| 3064 | const int output_ext_size = 4 - unextended_output_size; |
| 3065 | |
| 3066 | // The perm data is extended to match the output, each index incremented by |
| 3067 | // the amount of front padding of the input shape. |
| 3068 | int extended_perm[4]; |
| 3069 | for (int i = 0; i < output_ext_size; ++i) { |
| 3070 | extended_perm[i] = i; |
| 3071 | } |
| 3072 | for (int i = 0; i < unextended_output_size; ++i) { |
| 3073 | extended_perm[i + output_ext_size] = params.perm[i] + input_ext_size; |
| 3074 | } |
| 3075 | |
| 3076 | int out_sizes[4]; |
| 3077 | // Compute the inverse permutation array so we can do an output centered |
| 3078 | // transpose. Also, check to make sure output_dims is matching input_dims. |
| 3079 | for (int k = 0; k < 4; k++) { |
| 3080 | out_sizes[k] = MatchingDim(input_shape, extended_perm[k], output_shape, k); |
| 3081 | } |
| 3082 | |
| 3083 | // Naive transpose loop (iterate on output index and compute input index). |
| 3084 | int o[4]; // loop index (on output). |
| 3085 | int i[4]; |
| 3086 | for (o[3] = 0; o[3] < out_sizes[3]; o[3]++) { |
| 3087 | i[extended_perm[3]] = o[3]; |
| 3088 | for (o[2] = 0; o[2] < out_sizes[2]; o[2]++) { |
| 3089 | i[extended_perm[2]] = o[2]; |
| 3090 | for (o[1] = 0; o[1] < out_sizes[1]; o[1]++) { |
| 3091 | i[extended_perm[1]] = o[1]; |
| 3092 | for (o[0] = 0; o[0] < out_sizes[0]; o[0]++) { |
| 3093 | i[extended_perm[0]] = o[0]; |
| 3094 | output_data[Offset(output_shape, o)] = |
| 3095 | input_data[Offset(input_shape, i)]; |
| 3096 | } |
| 3097 | } |
| 3098 | } |
| 3099 | } |
| 3100 | } |
| 3101 | |
| 3102 | inline void TransposeConv( |
| 3103 | const ConvParams& params, const RuntimeShape& input_shape, |
no test coverage detected