|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "edge-impulse-sdk/tensorflow/lite/c/common.h" |
|
|
#include "edge-impulse-sdk/tensorflow/lite/kernels/internal/reference/binary_function.h" |
|
|
#include "edge-impulse-sdk/tensorflow/lite/kernels/internal/tensor_ctypes.h" |
|
|
#include "edge-impulse-sdk/tensorflow/lite/kernels/op_macros.h" |
|
|
#include "edge-impulse-sdk/tensorflow/lite/micro/kernels/kernel_util.h" |
|
|
|
|
|
namespace tflite { |
|
|
namespace ops { |
|
|
namespace micro { |
|
|
namespace logical { |
|
|
namespace { |
|
|
|
|
|
|
|
|
constexpr int kInputTensor1 = 0; |
|
|
constexpr int kInputTensor2 = 1; |
|
|
constexpr int kOutputTensor = 0; |
|
|
|
|
|
TfLiteStatus LogicalImpl(TfLiteContext* context, TfLiteNode* node, |
|
|
bool (*func)(bool, bool)) { |
|
|
const TfLiteEvalTensor* input1 = |
|
|
tflite::micro::GetEvalInput(context, node, kInputTensor1); |
|
|
const TfLiteEvalTensor* input2 = |
|
|
tflite::micro::GetEvalInput(context, node, kInputTensor2); |
|
|
TfLiteEvalTensor* output = |
|
|
tflite::micro::GetEvalOutput(context, node, kOutputTensor); |
|
|
|
|
|
if (tflite::micro::HaveSameShapes(input1, input2)) { |
|
|
reference_ops::BinaryFunction<bool, bool, bool>( |
|
|
tflite::micro::GetTensorShape(input1), |
|
|
tflite::micro::GetTensorData<bool>(input1), |
|
|
tflite::micro::GetTensorShape(input2), |
|
|
tflite::micro::GetTensorData<bool>(input2), |
|
|
tflite::micro::GetTensorShape(output), |
|
|
tflite::micro::GetTensorData<bool>(output), func); |
|
|
} else { |
|
|
reference_ops::BroadcastBinaryFunction4DSlow<bool, bool, bool>( |
|
|
tflite::micro::GetTensorShape(input1), |
|
|
tflite::micro::GetTensorData<bool>(input1), |
|
|
tflite::micro::GetTensorShape(input2), |
|
|
tflite::micro::GetTensorData<bool>(input2), |
|
|
tflite::micro::GetTensorShape(output), |
|
|
tflite::micro::GetTensorData<bool>(output), func); |
|
|
} |
|
|
|
|
|
return kTfLiteOk; |
|
|
} |
|
|
|
|
|
bool LogicalOr(bool x, bool y) { return x || y; } |
|
|
|
|
|
TfLiteStatus LogicalOrEval(TfLiteContext* context, TfLiteNode* node) { |
|
|
return LogicalImpl(context, node, LogicalOr); |
|
|
} |
|
|
|
|
|
bool LogicalAnd(bool x, bool y) { return x && y; } |
|
|
|
|
|
TfLiteStatus LogicalAndEval(TfLiteContext* context, TfLiteNode* node) { |
|
|
return LogicalImpl(context, node, LogicalAnd); |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
TfLiteRegistration Register_LOGICAL_OR() { |
|
|
|
|
|
|
|
|
return {nullptr, |
|
|
nullptr, |
|
|
nullptr, |
|
|
logical::LogicalOrEval, |
|
|
nullptr, |
|
|
0, |
|
|
nullptr, |
|
|
0}; |
|
|
} |
|
|
|
|
|
TfLiteRegistration Register_LOGICAL_AND() { |
|
|
|
|
|
|
|
|
return {nullptr, |
|
|
nullptr, |
|
|
nullptr, |
|
|
logical::LogicalAndEval, |
|
|
nullptr, |
|
|
0, |
|
|
nullptr, |
|
|
0}; |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|