diff --git a/onnxruntime/contrib_ops/cpu/signal/dft.cc b/onnxruntime/contrib_ops/cpu/signal/dft.cc index 70aa7e2deb..4a90243da6 100644 --- a/onnxruntime/contrib_ops/cpu/signal/dft.cc +++ b/onnxruntime/contrib_ops/cpu/signal/dft.cc @@ -278,17 +278,22 @@ static Status discrete_fourier_transform(OpKernelContext* ctx, const Tensor* X, auto batch_and_signal_rank = X->Shape().NumDimensions(); auto total_dfts = static_cast(X->Shape().Size() / X->Shape()[axis]); + + auto is_input_real = X->Shape().NumDimensions() == 2 || X->Shape()[X->Shape().NumDimensions() - 1] == 1; + auto compex_input_factor = is_input_real ? 1 : 2; if (X->Shape().NumDimensions() > 2) { total_dfts /= X->Shape()[X->Shape().NumDimensions() - 1]; batch_and_signal_rank -= 1; } + + // Calculate x/y offsets/strides for (size_t i = 0; i < total_dfts; i++) { size_t X_offset = 0; - size_t X_stride = X_shape.SizeFromDimension(axis+1); + size_t X_stride = X_shape.SizeFromDimension(axis+1) / compex_input_factor; size_t cumulative_packed_stride = total_dfts; size_t temp = i; for (size_t r = 0; r < batch_and_signal_rank; r++) { @@ -299,7 +304,7 @@ static Status discrete_fourier_transform(OpKernelContext* ctx, const Tensor* X, cumulative_packed_stride /= X_shape[r]; auto index = temp / cumulative_packed_stride; temp -= (index * cumulative_packed_stride); - X_offset += index * X_shape.SizeFromDimension(r + 1); + X_offset += index * X_shape.SizeFromDimension(r + 1) / compex_input_factor; } size_t Y_offset = 0; diff --git a/winml/test/api/LearningModelSessionAPITest.cpp b/winml/test/api/LearningModelSessionAPITest.cpp index 219c74525f..4e872a46c4 100644 --- a/winml/test/api/LearningModelSessionAPITest.cpp +++ b/winml/test/api/LearningModelSessionAPITest.cpp @@ -944,40 +944,80 @@ static void ModelBuilding_DiscreteFourierTransform() { #endif } -static void ModelBuilding_DiscreteFourierTransformInverseIdentity() { #if !defined(BUILD_INBOX) && defined(BUILD_MS_EXPERIMENTAL_OPS) - std::vector shape = {1, 5}; - std::vector output_shape = {1, shape[1], 2}; +static void DiscreteFourierTransformInverse(size_t axis) { + std::vector shape = {2, 5, 8, 1}; + std::vector output_shape = {2, 5, 8, 2}; auto model = LearningModelBuilder::Create(13) .Inputs().Add(LearningModelBuilder::CreateTensorFeatureDescriptor(L"Input.TimeSignal", TensorKind::Float, shape)) .Outputs().Add(LearningModelBuilder::CreateTensorFeatureDescriptor(L"Output.Spectra", TensorKind::Float, output_shape)) + .Outputs().Add(LearningModelBuilder::CreateTensorFeatureDescriptor(L"Output.Inverse", TensorKind::Float, output_shape)) .Operators().Add(Operator(L"DFT", MS_EXPERIMENTAL_DOMAIN) .SetInput(L"input", L"Input.TimeSignal") - .SetOutput(L"output", L"DFTOutput")) - .Operators().Add(Operator(L"IDFT", MS_EXPERIMENTAL_DOMAIN) - .SetInput(L"input", L"DFTOutput") + .SetAttribute(L"axis", TensorInt64Bit::CreateFromArray({}, {INT64(axis)})) .SetOutput(L"output", L"Output.Spectra")) + .Operators().Add(Operator(L"IDFT", MS_EXPERIMENTAL_DOMAIN) + .SetInput(L"input", L"Output.Spectra") + .SetAttribute(L"axis", TensorInt64Bit::CreateFromArray({}, {INT64(axis)})) + .SetOutput(L"output", L"Output.Inverse")) .CreateModel(); LearningModelSession session(model); LearningModelBinding binding(session); + auto input_vector = + std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + + 2, 4, 6, 8, 10, 12, 14, 16, + 2, 4, 6, 8, 10, 12, 14, 16, + 2, 4, 6, 8, 10, 12, 14, 16, + 2, 4, 6, 8, 10, 12, 14, 16, + 2, 4, 6, 8, 10, 12, 14, 16, + }; // Populate binding - binding.Bind(L"Input.TimeSignal", TensorFloat::CreateFromArray(shape, {1, 2, 3, 4, 5})); + binding.Bind( + L"Input.TimeSignal", + TensorFloat::CreateFromArray( + shape, + input_vector)); // Evaluate auto result = session.Evaluate(binding, L""); - + // Check results - printf("Output.Spectra\n"); - auto y_tensor = result.Outputs().Lookup(L"Output.Spectra").as(); + auto y_tensor = result.Outputs().Lookup(L"Output.Inverse").as(); auto y_ivv = y_tensor.GetAsVectorView(); - for (int i = 0; i < output_shape[0] * output_shape[1] * 2; i += 2) { - printf("(%f + %fi), ", y_ivv.GetAt(i), y_ivv.GetAt(i + 1)); + for (uint32_t i = 0; i < y_ivv.Size(); i += 2) { + WINML_EXPECT_TRUE(abs(y_ivv.GetAt(i) - input_vector[i / 2]) < .001); + WINML_EXPECT_TRUE(abs(y_ivv.GetAt(i + 1) - 0) < .001); } - printf("\n"); + + //printf("Output.Spectra\n"); + //auto y_tensor = result.Outputs().Lookup(L"Output.Spectra").as(); + //auto y_ivv = y_tensor.GetAsVectorView(); + //for (uint32_t i = 0; i < y_ivv.Size(); i+=2) { + // auto format_size = 16; + // if (i % format_size == 0 && i != 0) { + // printf("\n"); + // } + // printf("(%.2f + %.2fi), ", y_ivv.GetAt(i), y_ivv.GetAt(i + 1)); + //} + //printf("\n"); + +} +#endif + +static void ModelBuilding_DiscreteFourierTransformInverseIdentity() { +#if !defined(BUILD_INBOX) && defined(BUILD_MS_EXPERIMENTAL_OPS) + DiscreteFourierTransformInverse(0); + DiscreteFourierTransformInverse(1); #endif }