Skip to content

feat(stable-api): Add RB_NUM2DBL, DBL2NUM for Float conversions #668

@ianks

Description

@ianks

Summary

Add stable API methods for converting between Float VALUEs and C doubles, equivalent to RB_NUM2DBL and DBL2NUM.

Motivation

Float conversion is common in numeric Ruby extensions. The Flonum optimization (storing small floats as immediate values) makes this non-trivial. Having stable API methods ensures:

  • Correct handling of Flonum vs heap Float
  • Consistent behavior across Ruby versions
  • No need for users to understand Flonum internals

Proposed API

/// Convert a Float VALUE to a C double (akin to `RB_NUM2DBL`).
///
/// Handles both Flonum (immediate) and heap-allocated Float objects.
///
/// # Safety
/// The caller must ensure the VALUE is a Float type (use RB_FLOAT_TYPE_P first).
unsafe fn num2dbl(&self, obj: VALUE) -> c_double;

/// Convert a C double to a Float VALUE (akin to `DBL2NUM`).
///
/// May return either a Flonum (immediate) or heap-allocated Float
/// depending on the value and Ruby version/platform.
fn dbl2num(&self, val: c_double) -> VALUE;

/// Extract double from a Flonum (internal helper).
///
/// # Safety
/// Caller must ensure VALUE is actually a Flonum.
unsafe fn flonum2dbl(&self, obj: VALUE) -> c_double;

Implementation Notes

  • Flonum uses a specific bit pattern to encode doubles as immediate values
  • Not all platforms support Flonum (32-bit systems typically don't)
  • Need to check ruby_use_flonum cfg flag
  • Reference: include/ruby/internal/arithmetic/double.h

Checklist

  • Add methods to StableApiDefinition trait
  • Implement for each Ruby version
  • Handle Flonum vs non-Flonum platforms
  • Add C fallback in compiled.c
  • Add public macro wrappers in macros.rs
  • Add comprehensive tests including edge cases (NaN, Inf, etc.)
  • Add to show-asm script for performance verification

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions