Helper function for comparing two literals for nearness. Handles tuple-shapes via recursion. shape_index is the ShapeIndex of expected (or actual) currently being compared.
| 772 | // via recursion. shape_index is the ShapeIndex of expected (or actual) |
| 773 | // currently being compared. |
| 774 | Status NearHelper(const LiteralSlice& expected, const LiteralSlice& actual, |
| 775 | const ShapeIndex& shape_index, const ErrorSpec& error, |
| 776 | absl::optional<bool> detailed_message, |
| 777 | const MiscompareCallback& miscompare_callback) { |
| 778 | TF_RETURN_IF_ERROR(EqualShapes(expected.shape(), actual.shape())); |
| 779 | |
| 780 | if (expected.shape().IsTuple()) { |
| 781 | Status return_status; |
| 782 | for (int64 i = 0; i < ShapeUtil::TupleElementCount(expected.shape()); ++i) { |
| 783 | const auto expected_element = LiteralSlice(expected, {i}); |
| 784 | const auto actual_element = LiteralSlice(actual, {i}); |
| 785 | ShapeIndex element_index = shape_index; |
| 786 | element_index.push_back(i); |
| 787 | Status element_result = |
| 788 | NearHelper(expected_element, actual_element, element_index, error, |
| 789 | detailed_message, miscompare_callback); |
| 790 | if (!element_result.ok()) { |
| 791 | element_result = InvalidArgument("Array at shape index %s, %s", |
| 792 | element_index.ToString(), |
| 793 | element_result.error_message()); |
| 794 | if (return_status.ok()) { |
| 795 | return_status = element_result; |
| 796 | } else { |
| 797 | return_status = |
| 798 | AppendStatus(return_status, element_result.error_message()); |
| 799 | } |
| 800 | } |
| 801 | } |
| 802 | if (!return_status.ok() && shape_index.empty()) { |
| 803 | // Emit a top-level error message containing the top-level shape in case |
| 804 | // of mismatch. |
| 805 | int64 total_elements = RecursiveElementCount(actual.shape()); |
| 806 | return_status = |
| 807 | InvalidArgument("\nMismatches in shape %s (%d elements):\n%s", |
| 808 | ShapeUtil::HumanString(actual.shape()), |
| 809 | total_elements, return_status.error_message()); |
| 810 | } |
| 811 | return return_status; |
| 812 | } |
| 813 | |
| 814 | if (ShapeUtil::ElementIsFloating(expected.shape()) || |
| 815 | ShapeUtil::ElementIsComplex(expected.shape())) { |
| 816 | bool use_detailed_message = detailed_message.value_or( |
| 817 | ShapeUtil::ElementsIn(expected.shape()) >= 64); |
| 818 | switch (expected.shape().element_type()) { |
| 819 | case BF16: |
| 820 | return NearComparator<bfloat16>::Compare(expected, actual, shape_index, |
| 821 | error, use_detailed_message, |
| 822 | miscompare_callback); |
| 823 | break; |
| 824 | case F16: |
| 825 | return NearComparator<half>::Compare(expected, actual, shape_index, |
| 826 | error, use_detailed_message, |
| 827 | miscompare_callback); |
| 828 | break; |
| 829 | case F32: |
| 830 | return NearComparator<float>::Compare(expected, actual, shape_index, |
| 831 | error, use_detailed_message, |
no test coverage detected