Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial checkin for a module for tolerant comparison of reals #353

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/specs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This is and index/directory of the specifications (specs) for each new module/fe
- [stats](./stdlib_stats.html) - Descriptive Statistics
- [stats_distribution_PRNG](./stdlib_stats_distribution_PRNG.html) - Probability Distributions random number generator
- [string\_type](./stdlib_string_type.html) - Basic string support
- [tolerant](./stdlib_tolerant.html) - Tolerant comparisons of reals

## Missing specs

Expand Down
85 changes: 85 additions & 0 deletions doc/specs/stdlib_tolerant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: tolerant
---

# Tolerant comparison of reals

[TOC]

## Introduction

The age-old adagium is that you should never compare real variables directly, as rounding/truncation errors can
give false results. This module provides the means to allow a certain tolerance with such comparisons. In addition
it provides tolerant versions of the `floor`, `ceil` and `round` functions. The operation is in most respects
simple, in that a margin is used which is based on the "epsilon" value for the given kind of reals.


## Procedures and operators provided

The module's procedures and operators work on ordinary single-precision and double-precision reals.

### `teq`, `tne`, `tgt`, `tge`, `tlt`, `tle` - Tolerant relational operators

#### Description

Compare two reals with a tolerance based on a small margin (set to three times the epsilon value).
The implementation is such that if `x .teq. y` is true, then `x .tne. y` is never true and vice versa.
Similarly for the pairs `.tlt.` and `.tge.`, `.tle.` and `.tgt.`.

#### Syntax

`if ( x .teq. y ) write(*,*) 'x and y are equal'`

#### Status

Experimental

#### Class

Operator.

#### Arguments

`x`, `y`: Two reals (of the same kind) to be compared
Copy link
Member

Choose a reason for hiding this comment

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

Are they scalar? Or are arrays also possible (and then the function should be elemental?


#### Result value

A logical indicating whether the two operands are different enough or not.


### `tfloor`, `tceil`, `tround` - Tolerant versions of the `floor`, `ceil` and `round` functions

#### Description

Provide tolerant versions of the `floor`, `ceil` and `round` functions that take a small interval into account.
While the actual interval can be set, the advised default is three times epsilon(). Note that the implementation
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
While the actual interval can be set, the advised default is three times epsilon(). Note that the implementation
While the actual interval can be set, the advised default is three times `epsilon()`. Note that the implementation

is actually much more involved than would seem necessary. It is the result of extensive research.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
is actually much more involved than would seem necessary. It is the result of extensive research.
is actually much more involved than would seem necessary. It is the result of extensive research.



#### Syntax

```fortran
fl = [[stdlib_tolerant(module):tfloor(interface)]](x) ! Or: tfloor( x, ct ) if you want control over the interval
cl = [[stdlib_tolerant(module):tfceil(interface)]](x) ! Or: tceil( x, ct )
rnd = [[stdlib_tolerant(module):tround(interface)]](x) ! Or: tround( x, ct )
```

#### Status

Experimental

#### Class

Elemental function

#### Arguments

`x`: The real number that is to be truncated or rounded
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
`x`: The real number that is to be truncated or rounded
`x`: The real number that is to be truncated or rounded. It is an `intent(in)` argument.


`ct`: Tolearance for comparison (optional, defaults to 3*epsilon)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
`ct`: Tolearance for comparison (optional, defaults to 3*epsilon)
`ct`: Tolerance for comparison. It is an `intent(in)` and `optional` argument. The default is 3*`epsilon().


#### Return value

A real value of the same kind as the argument but with proper truncation or rounding in accordance
with the function.

1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ set(SRC
stdlib_logger.f90
stdlib_string_type.f90
stdlib_system.F90
stdlib_tolerant.f90
${outFiles}
)

Expand Down
Loading