---
title: Correctly rounded floating-point maths functions
document: P3864R1
date: 2026-02-22
audience: SG6
reply-to:
  - "Guy Davidson < <gd@6it.dev>"
paper-type: proposal
---

This paper proposes adding five overload sets to the standard library for addition, subtraction, multiplication, division, and square root calculation, correctly rounded as specified in ISO/IEC 60559:2020.



### Related papers

Proposal [[P3375R3]](https://wg21%2elink/p3375r3) seeks to introduce reliable reproducibility to floating-point operations regardless of platform. This proposal partially addresses this problem by reducing the places where implementations can diverge. However, it does not necessarily solve the divergence introduced by inlining or optimization choices, which are declared per translation unit.

This can be mitigated, at the cost of performance, by creating a `struct` which contains a value of the appropriate type as a single member, and implementing the arithmetic operators in a separate library, linked at runtime, in terms of the correctly rounded functions. In this way, a client can mix correctly rounded and optimized operations in a single translation unit.

This author currently believes that more performant reproducibility can only be achieved by introducing a new type which is defined to be immune to the floating-point optimizations specified in [[60559:2020]](https://www%2eiso%2eorg/standard/80985%2ehtml).

## Design considerations

### Error handling

The error handling for the proposed functions should match that of the existing mathematical functions. That is:

- NaN is propagated.
- A range errors occur on overflow.
- Infinity may be propagated without error.
- A pole error occurs when dividing by zero.
- Underflow or denormalization is ignored.
- A domain error occurs when the result is not mathematically defined.

### cr_sqrt for -0 arguments

If the argument to `cr_sqrt` is negative zero, the result should also be negative zero. This matches the behavior of `sqrt` in typical implementations (although this behavior is not mandated by the C standard), and it matches the behavior specified for **squareRoot**(-0) in [[60559:2020]](https://www%2eiso%2eorg/standard/80985%2ehtml).

## Wording

The proposed changes are based on [[N5014]](https://wg21%2elink/n5014).

### [version.syn]

In [[version.syn]](https://eel.is/c++draft/version.syn), insert a feature-test macro as follows:

#define __cpp_lib_math_cr_functions 20XXXXL

//

also in

<cmath>

The name is based on `__cpp_lib_math_special_functions`.

### [cmath.syn]

In [[cmath.syn]](https://eel.is/c++draft/cmath.syn), prior to the declaration of the mathematical special functions, insert the following:

//

[c.math.crfunc], correctly rounded functions

constexpr

iec-559-type

cr_add

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

constexpr

iec-559-type

cr_sub

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

constexpr

iec-559-type

cr_mul

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

constexpr

iec-559-type

cr_div

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

constexpr

iec-559-type

cr_sqrt

(

iec-559-type

x

)

noexcept

;

Amend [[cmath.syn] paragraph 1](https://eel.is/c++draft/cmath.syn#1) to read:

The contents and meaning of the header <cmath> are a subset of the C standard library header <math.h> and only the declarations shown in the synopsis above are present, with the addition of

- a three-dimensional hypotenuse function ([[c.math.hypot3]](https://eel.is/c++draft/c.math.hypot3)),
- a linear interpolation function ([[c.math.lerp]](https://eel.is/c++draft/c.math.lerp)), <del>and</del>
- <ins>the correctly rounded functions ([[c.math.crfunc]](https://eel.is/c++draft/c.math.crfunc)), and</ins>
- the mathematical special functions described in [[sf.cmath]](https://eel.is/c++draft/sf.cmath).

The use of bullets is added here.

Amend [[cmath.syn] paragraph 2](https://eel.is/c++draft/cmath.syn#2) to read:

For each function with at least one parameter of type `*floating-point-type*`, the implementation provides an overload for each cv-unqualified floating-point type ([[basic.fundamental]](https://eel.is/c++draft/basic.fundamental))<ins>; for each function with at least one parameter of type `*iec-559-type*`, the implementation provides an overload for each cv-unqualified floating-point type `T` for which `numeric_limits<T>::is_iec559` is `true`.</ins> <del>where all</del> <ins>All</ins> uses of `*floating-point-type*` <ins>or `*iec-559-type*`</ins> in the function signature are replaced with <del>that</del> <ins>the provided</ins> floating-point type.

### [c.math.crfunc]

Immediately preceding [[cf.cmath]](https://eel.is/c++draft/cf.cmath), introduce a new subclause:

### Correctly rounded functions [c.math.crfunc]

¶ The correctly rounded functions correctly round the result of an operation, meaning that the result is calculated as if using infinite precision, then rounded using roundTiesToEven, as specified in ISO/IEC 60559:2020.

¶ If any argument value to any of the functions below is a NaN (Not a Number), the function shall return a NaN but it shall not report a domain error. A range error occurs if all arguments are finite and the result is too large in magnitude to be represented in the destination type.

¶ Unless otherwise specified, each function is defined for all finite values, for negative infinity, and for positive infinity.

constexpr

iec-559-type

cr_add

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

¶ *Returns*: x+y correctly rounded.

constexpr

iec-559-type

cr_sub

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

¶ *Returns*: x−y correctly rounded.

constexpr

iec-559-type

cr_mul

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

¶ *Returns*: x×y correctly rounded.

constexpr

iec-559-type

cr_div

(

iec-559-type

x

,

iec-559-type

y

)

noexcept

;

¶ *Returns*: xy correctly rounded.

¶ *Remarks*: A pole error occurs if `y` equals zero.

constexpr

iec-559-type

cr_sqrt

(

iec-559-type

x

)

noexcept

;

¶ *Returns*: x correctly rounded. If `x` is −0, the result is also −0.

¶ *Remarks*: A domain error occurs if `x` < 0.

The introductory wording is loosely inspired by [[sf.cmath.general]](https://eel.is/c++draft/sf.cmath.general).

## References and bibliography

[N5014]

Thomas Köppe.

Working Draft, Programming Languages — C++

2025-08-05

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5014.pdf

[60559:2020]

ISO.

ISO/IEC 60559:2020 — Information technology — Microprocessor Systems — Floating-Point arithmetic

2025-05

https://www.iso.org/standard/80985.html

[P3375R3]

Guy Davidson.

Reproducible floating-point results

2025-05-12

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3375r3.html
