Skip to content

#853 Fix IBM single precision floating point (COMP-1) decoder to produce correct results.#854

Merged
yruslan merged 3 commits into
masterfrom
bugfix/853-fix-comp1-ibm-exponent
Jun 15, 2026
Merged

#853 Fix IBM single precision floating point (COMP-1) decoder to produce correct results.#854
yruslan merged 3 commits into
masterfrom
bugfix/853-fix-comp1-ibm-exponent

Conversation

@yruslan

@yruslan yruslan commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Closes #853

  1. Fixed exponent mask (line 131): Changed from 0x80000000 → 0x7F000000
    - The original mask was incorrect (same as sign mask)
    - Proper mask now extracts the 7-bit IBM exponent correctly
  2. Fixed exponent conversion (line 151): Changed from + 131 → - 131
    - IBM uses base-16 exponent bias of 64 vs IEEE-754's base-2 bias of 127
    - Correct formula: ieee_exp = (ibm_exp - 64) * 4 + 127 - leading_zeros
    - Simplified to: ibm_exp * 4 - 131 - leading_zeros

Test Updates

  • FloatingPointDecodersSpec.scala: Replaced incorrect test (5.045883) with comprehensive test suite covering:
    • Basic values (1.0, 1234.0, 4.5, 2.5)
    • Negative numbers (-1234.0, -3.75)
    • Edge cases (0, infinity)
    • Both big-endian and little-endian variants
  • Test03IbmFloats.scala: Updated expected value from 5.045883f → 322.93652f (the correct decoded value)

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

decodeIbmSingleBigEndian in FloatingPointDecoders is fixed by correcting the IBM32_EXPONENT_MASK constant and flipping the sign of the exponent bias offset. Unit tests and one regression test have their expected float values corrected accordingly.

Changes

IBM HFP Single-Precision Decoder Fix

Layer / File(s) Summary
Corrected exponent extraction and bias
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala
Fixes the IBM32_EXPONENT_MASK constant to the correct exponent field mask and adjusts the exponent bias offset from +131 to -131. The rest of the function flow and error handling remain unchanged.
Expanded unit tests and corrected regression assertions
cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala, spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test03IbmFloats.scala
Unit tests replace the two prior grouped assertions with per-value tests for both big-endian and little-endian formats (1.0, 1234.0, -1234.0, 4.5, -3.75, 2.5, 0, infinity). Regression test expected Float for field F is updated from 5.045883f to 322.93652f in both IBM float test methods.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 A mask was wrong, the bits astray,
The exponent copied the sign one day.
Now bytes are plucked with careful paws,
And -131 hops without a pause.
Negative floats no longer hide —
The rabbit fixed the bug inside! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: correcting the IBM32_EXPONENT_MASK to enable proper COMP-1 decoding.
Linked Issues check ✅ Passed The code changes directly fix issue #853 by correcting the IBM32_EXPONENT_MASK from 0x80000000 to 0x7F000000 and adjusting the convertedExp calculation, resolving both positive value inflation and negative value decoding failures.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #853: the decoder bug fix, corresponding test expansions, and regression test correction. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/853-fix-comp1-ibm-exponent

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

JaCoCo code coverage report - 'cobol-parser'

Overall Project 90.11% 🍏
Files changed 100% 🍏

File Coverage
FloatingPointDecoders.scala 76.89% 🍏

@github-actions

Copy link
Copy Markdown

JaCoCo code coverage report - 'spark-cobol'

Overall Project 83.4% 🍏

There is no coverage information present for the Files changed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala`:
- Around line 127-140: The byte extraction and zero-check logic (extracting b0,
b1, b2, b3 from the bytes array and checking if their combined value is zero) is
occurring before the try block, which means null or short input arrays can cause
unhandled exceptions that bypass the NonFatal exception guard. Move the byte
extraction statements and the zero-check condition into the try block so that
any potential IndexOutOfBoundsException or NullPointerException is properly
caught and handled according to the decoder's null-on-failure contract.

In
`@cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala`:
- Around line 128-131: The test for IBM single-precision little-endian infinity
is calling the wrong decoder function. In the assertion line with
decodeIbmSingleBigEndian, replace this call with decodeIbmSingleLittleEndian to
correctly test the little-endian decoder. Ensure the byte array in the test is
adjusted to represent the proper little-endian byte order for infinity so the
test exercises the intended decoder and validates the correct behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1134243f-ee11-4b06-b9ec-3e6dcdb20f15

📥 Commits

Reviewing files that changed from the base of the PR and between db6ce82 and 8aad4a8.

📒 Files selected for processing (3)
  • cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala
  • spark-cobol/src/test/scala/za/co/absa/cobrix/spark/cobol/source/regression/Test03IbmFloats.scala

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala`:
- Around line 156-157: The overflow handling in the condition `convertedExp >
254` unconditionally returns `POSITIVE_INFINITY`, discarding the sign bit that
was extracted earlier at line 136. Modify this section to preserve the sign
during overflow by checking the sign bit and returning either
`POSITIVE_INFINITY` or `NEGATIVE_INFINITY` accordingly, so that negative values
that overflow produce `NEGATIVE_INFINITY` instead of `POSITIVE_INFINITY`,
consistent with IEEE 754 behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a3e74525-fca4-4f7c-a91f-2966eead09ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8aad4a8 and 69d8325.

📒 Files selected for processing (2)
  • cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala
🚧 Files skipped from review as they are similar to previous changes (1)
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala`:
- Around line 156-157: The overflow handling in the condition `convertedExp >
254` unconditionally returns `POSITIVE_INFINITY`, discarding the sign bit that
was extracted earlier at line 136. Modify this section to preserve the sign
during overflow by checking the sign bit and returning either
`POSITIVE_INFINITY` or `NEGATIVE_INFINITY` accordingly, so that negative values
that overflow produce `NEGATIVE_INFINITY` instead of `POSITIVE_INFINITY`,
consistent with IEEE 754 behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a3e74525-fca4-4f7c-a91f-2966eead09ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8aad4a8 and 69d8325.

📒 Files selected for processing (2)
  • cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala
🚧 Files skipped from review as they are similar to previous changes (1)
  • cobol-parser/src/test/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecodersSpec.scala
🛑 Comments failed to post (1)
cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala (1)

156-157: ⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

ibm2ieee library overflow handling sign bit

💡 Result:

The ibm2ieee library handles overflow and sign bit information in accordance with IEEE 754 standards for floating-point conversion [1][2]. Regarding overflow, the library is designed to identify when a rounded converted value exceeds the representable range of the target IEEE 754 type [1][2]. In such cases, the library returns an appropriately-signed infinity, ensuring that the sign bit is preserved despite the overflow [1][2]. This handling applies to both single-precision and double-precision conversions, though the risk of overflow depends on the specific format conversion (e.g., IBM single-precision has a larger range than IEEE 754 single-precision, while IBM double-precision has a smaller range than IEEE 754 double-precision) [1][2]. Regarding the sign bit, the library explicitly preserves the sign of the value throughout the conversion process [1][2]. This includes the handling of signed zeros, which are representable in both IBM and IEEE formats; the library ensures the sign bit of a zero is correctly maintained under all conversions [1][2].

Citations:


Sign bit lost on overflow — negative overflows become POSITIVE_INFINITY.

When convertedExp > 254, the code unconditionally returns POSITIVE_INFINITY, discarding the sign extracted at line 136. A very large negative IBM HFP value will incorrectly decode as positive infinity instead of negative infinity. Per IEEE 754 and the ibm2ieee reference implementation, the sign bit must be preserved during overflow to return appropriately-signed infinity.

Proposed fix
       } else if (convertedExp > 254) {
-        java.lang.Float.POSITIVE_INFINITY
+        if (sign != 0) java.lang.Float.NEGATIVE_INFINITY else java.lang.Float.POSITIVE_INFINITY
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        } else if (convertedExp > 254) {
          if (sign != 0) java.lang.Float.NEGATIVE_INFINITY else java.lang.Float.POSITIVE_INFINITY
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@cobol-parser/src/main/scala/za/co/absa/cobrix/cobol/parser/decoders/FloatingPointDecoders.scala`
around lines 156 - 157, The overflow handling in the condition `convertedExp >
254` unconditionally returns `POSITIVE_INFINITY`, discarding the sign bit that
was extracted earlier at line 136. Modify this section to preserve the sign
during overflow by checking the sign bit and returning either
`POSITIVE_INFINITY` or `NEGATIVE_INFINITY` accordingly, so that negative values
that overflow produce `NEGATIVE_INFINITY` instead of `POSITIVE_INFINITY`,
consistent with IEEE 754 behavior.

@yruslan yruslan merged commit 5f1343e into master Jun 15, 2026
7 checks passed
@yruslan yruslan deleted the bugfix/853-fix-comp1-ibm-exponent branch June 15, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: COMP-1 (IBM HFP single precision) decodes incorrectly — IBM32_EXPONENT_MASK wrong (positive → ×4, negative → 0.0)

1 participant