Skip to content

Fixed point sqrt#286

Open
immrsd wants to merge 8 commits intomainfrom
fixed-point-sqrt
Open

Fixed point sqrt#286
immrsd wants to merge 8 commits intomainfrom
fixed-point-sqrt

Conversation

@immrsd
Copy link
Copy Markdown
Collaborator

@immrsd immrsd commented Apr 1, 2026

Resolves #90

Summary by CodeRabbit

Release Notes

  • New Features

    • Added square root operations for fixed-point number types
    • Extended API documentation for fixed-point arithmetic operations and casting routes
  • Tests

    • Added comprehensive test coverage for square root functionality

@immrsd immrsd self-assigned this Apr 1, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e8b687a9-530d-43c9-bd09-114f3c981d73

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Added square root functionality to the fixed-point math library by introducing a shared fp_helpers module containing a sqrt_floor helper function implementing Newton's method, implementing sqrt for both SD29x9 and UD30x9 types, updating API documentation, and providing comprehensive test suites for both implementations.

Changes

Cohort / File(s) Summary
Documentation
math/fixed_point/README.md
Expanded API documentation to list additional arithmetic operations (abs, ceil, div, floor, mul, pow, sqrt) and added new casting/helper routes between types and constructor methods.
Core Implementation
math/fixed_point/sources/fp_helpers.move, math/fixed_point/sources/sd29x9/sd29x9_base.move, math/fixed_point/sources/ud30x9/ud30x9_base.move
Introduced shared sqrt_floor(a: u256) helper using Newton's method for floor square root computation, implemented sqrt(x: SD29x9) with sign validation and magnitude scaling, and implemented sqrt(x: UD30x9) with raw value unwrapping and re-wrapping.
Public API Re-exports
math/fixed_point/sources/sd29x9/sd29x9.move, math/fixed_point/sources/ud30x9/ud30x9.move
Added public re-exports mapping sqrt functions from base modules to top-level type namespaces for API consistency.
Test Coverage
math/fixed_point/tests/sd29x9_tests/sqrt_tests.move, math/fixed_point/tests/ud30x9_tests/sqrt_tests.move
Added comprehensive test suites covering zero/one/perfect squares, fractional inputs, irrational truncation, floor property verification, roundtrip correctness, edge cases (max/min values), and monotonicity for both types; SD29x9 tests also verify negative input rejection.

Sequence Diagram(s)

sequenceDiagram
    participant UD30x9 as UD30x9::sqrt()
    participant SD29x9 as SD29x9::sqrt()
    participant Helper as fp_helpers::sqrt_floor()
    participant Newton as Newton Iteration
    
    rect rgba(100, 150, 255, 0.5)
    UD30x9->>Helper: sqrt_floor(raw * SCALE)
    end
    
    rect rgba(100, 200, 100, 0.5)
    SD29x9->>Helper: sqrt_floor(magnitude * SCALE)
    end
    
    rect rgba(200, 100, 100, 0.5)
    Helper->>Newton: Initial approximation + iterations
    Newton->>Newton: (xn + a/xn) >> 1
    Newton->>Helper: Refined result
    end
    
    Helper-->>UD30x9: floor(sqrt(a))
    Helper-->>SD29x9: floor(sqrt(a))
    UD30x9->>UD30x9: wrap(result)
    SD29x9->>SD29x9: wrap(result as SD29x9)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • 0xNeshi
  • bidzyyys
  • ericnordelo

Poem

🐰 A rabbit hops through numbered fields so bright,
Where square roots bloom with Newton's guiding light,
From sqrt_floor to SD29x9,
Fixed-point math now feels so divine,
Tests and helpers dancing—oh what a sight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description only contains 'Resolves #90' and is missing required checklist items (Tests, Documentation, Changelog) that should be marked as complete or pending. Complete the PR description by adding the checklist with status updates for Tests, Documentation, and Changelog items to indicate what was done.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fixed point sqrt' is concise and clearly describes the main change: implementing square root functionality for fixed-point types.
Linked Issues check ✅ Passed The PR successfully implements square root for fixed-point math, as requested in issue #90. Multiple commits add sqrt helper functions, implementations for SD29x9 and UD30x9, comprehensive tests, and documentation updates.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing sqrt functionality: helper functions, implementations for both fixed-point types, tests, and README documentation. No out-of-scope changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fixed-point-sqrt

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

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 95.65217% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.01%. Comparing base (63a864e) to head (cedb015).

Files with missing lines Patch % Lines
math/fixed_point/sources/fp_helpers.move 93.93% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #286      +/-   ##
==========================================
+ Coverage   89.88%   90.01%   +0.12%     
==========================================
  Files          19       20       +1     
  Lines        1790     1833      +43     
  Branches      484      503      +19     
==========================================
+ Hits         1609     1650      +41     
  Misses        168      168              
- Partials       13       15       +2     
Flag Coverage Δ
contracts/access 44.87% <ø> (ø)
math/core 86.12% <ø> (ø)
math/fixed_point 61.39% <95.65%> (+2.67%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

public fun sqrt(x: UD30x9): UD30x9 {
let raw = x.unwrap() as u256;
if (raw == 0) {
return wrap(0)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Use zero()

if (mag == 0) {
return zero()
};
let result = fp_helpers::sqrt_floor(mag * SCALE);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add comment explaining why * SCALE is necessary

if (raw == 0) {
return wrap(0)
};
let result = fp_helpers::sqrt_floor(raw * SCALE_U256);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add comment explaining why * SCALE_U256 is necessary

public fun sqrt(x: SD29x9): SD29x9 {
let Components { neg, mag } = decompose(x.unwrap());
assert!(!neg, ENegativeSqrt);
if (mag == 0) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Zero-check is redundant, as sqrt_floor performs it in the first line


#[test]
fun sqrt_of_zero_is_zero() {
expect(fixed(0).sqrt(), fixed(0));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
expect(fixed(0).sqrt(), fixed(0));
expect(ud30x9::zero().sqrt(), ud30x9::zero());

values.destroy!(|x| {
let result = x.sqrt();
// Result is non-negative: raw bits should not have sign bit set
assert!(result.unwrap() <= 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It would be useful to have something like sd29x9::is_positive & sd29x9::is_negative, so this assertion would become:

assert!(!result.is_negative());

Comment on lines +77 to +78
#[test]
fun sqrt_result_is_always_non_negative() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#[test]
fun sqrt_result_is_always_non_negative() {
#[random_test]
fun sqrt_result_is_always_non_negative(raw: u128) {

Perfect candidate for a prop test

Comment on lines +62 to +63
assert!(r * r <= scaled);
assert!((r + 1) * (r + 1) > scaled);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These assertions are invariants on all non-negative values, making this a good candidate for a proptest.

Alternatively, these invariant assertions could be incorporated into sqrt_result_is_always_non_negative.

Comment on lines +95 to +96
#[test]
fun sqrt_floor_property_for_non_perfect_squares() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  • these invariants hold for all valid values, not just non-perfect squares
  • therefore, candidate for prop. test

Comment on lines +142 to +143
#[test]
fun sqrt_monotonicity() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#[test]
fun sqrt_monotonicity() {
#[random_test]
fun sqrt_monotonicity(x: u128, y: u128) {

good candidate for a prop. test

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.

[Feature]: sqrt for fixed-point math lib

2 participants