Skip to content

Commit

Permalink
Merge pull request #743 from jalvesz/master
Browse files Browse the repository at this point in the history
Proposal for a reference string to number conversion facility in stdlib
  • Loading branch information
jvdp1 authored Jan 17, 2024
2 parents 9582167 + 3b50f6a commit 8c7461d
Show file tree
Hide file tree
Showing 10 changed files with 884 additions and 1 deletion.
9 changes: 8 additions & 1 deletion ci/fpm-deployment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ destdir="${DESTDIR:-stdlib-fpm}"
fypp="${FYPP:-$(which fypp)}"

# Arguments for the fypp preprocessor
fyflags="${FYFLAGS:--DMAXRANK=4}"
maxrank=4
fyflags="${FYFLAGS:--DMAXRANK=$maxrank}"

# Number of parallel jobs for preprocessing
if [ $(uname) = "Darwin" ]; then
Expand Down Expand Up @@ -44,6 +45,12 @@ mkdir -p "$destdir/src" "$destdir/test" "$destdir/example"
find src -maxdepth 1 -iname "*.fypp" \
| cut -f1 -d. | xargs -P "$njob" -I{} "$fypp" "{}.fypp" "$destdir/{}.f90" $fyflags

find test -name "test_*.fypp" -exec cp {} "$destdir/test/" \;
fyflags="${fyflags} -I src"
find $destdir/test -maxdepth 1 -iname "*.fypp" \
| cut -f1 -d. | xargs -P "$njob" -I{} "$fypp" "{}.fypp" "{}.f90" $fyflags
find $destdir/test -name "test_*.fypp" -exec rm {} \;

# Collect stdlib source files
find src -maxdepth 1 -iname "*.f90" -exec cp {} "$destdir/src/" \;
find test -name "test_*.f90" -exec cp {} "$destdir/test/" \;
Expand Down
82 changes: 82 additions & 0 deletions doc/specs/stdlib_str2num.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: str2num
---

# The `stdlib_str2num` module

This module proposes a function-style interface for string-to-number conversion. It also profits from Fortran's interfaces to implement precision-dependant algorithms to maximize runtime efficiency.

[TOC]

## `to_num` - conversion of strings to numbers

### Status

Experimental

### Description

Convert a string or an array of strings to numerical types.

### Syntax

`number = [[stdlib_str2num(module):to_num(interface)]](string, mold)`

### Arguments

`string`: argument has `intent(in)` and is of type `character(*)`.

`mold`: argument has `intent(in)` and is of numerical type (that is of `integer` or of `real`). **Note**: The type of the `mold` argument defines the type of the result.

### Return value

Return a scalar of numerical type (i.e., `integer`, or `real`).

### Example

```fortran
{!example/strings/example_string_to_number.f90!}
```

## `to_num_from_stream` - conversion of a stream of values in a string to numbers

### Status

Experimental

### Description

Convert a stream of values in a string to an array of values.

### Syntax

`number = [[stdlib_str2num(module):to_num_from_stream(interface)]](string, mold)`

### Arguments

`string`: argument has `intent(in)` and is of type `character(:), pointer`.

`mold`: argument has `intent(in)` and is of numerical type (currently of `integer` or `real`). **Note**: The type of the `mold` argument defines the type of the result.

### Return value

Return a scalar of numerical type (i.e., `integer` or `real`).

### Example

```fortran
{!example/strings/example_stream_of_strings_to_numbers.f90!}
```

## Note
The accuracy of the conversion is implementation dependent; it is recommended that implementers guarantee precision down to the last 3 bits.

**The current implementation has been tested to provide for** :

`sp` : exact match

`dp` : precision up-to epsilon(0.0_dp)

`qp` : precision around 200*epsilon(0.0_qp)

Where precision refers to the relative difference between `to_num` and `read`. On the other hand, `to_num` provides speed-ups ranging from 4x to >10x compared to the intrinsic `read`.
2 changes: 2 additions & 0 deletions example/strings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ ADD_EXAMPLE(starts_with)
ADD_EXAMPLE(strip)
ADD_EXAMPLE(to_string)
ADD_EXAMPLE(zfill)
ADD_EXAMPLE(string_to_number)
ADD_EXAMPLE(stream_of_strings_to_numbers)
22 changes: 22 additions & 0 deletions example/strings/example_stream_of_strings_to_numbers.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
program example_stream_of_strings_to_numbers
use stdlib_kinds, only: dp
use stdlib_str2num, only: to_num_from_stream
character(:), allocatable, target :: chain
character(len=:), pointer :: cptr
real(dp), allocatable :: r(:), p(:)
integer :: i

chain = " 1.234 1.E1 1e0 0.1234E0 12.21e+001 -34.5E1"
allocate( r(6), p(6) )
!> Example for streamline conversion using `to_num_from_stream`
cptr => chain
do i =1, 6
r(i) = to_num_from_stream( cptr , r(i) ) !> the pointer is shifted within the function
end do
read(chain,*) p
print *, "Reading with to_num_from_stream"
print *, r
print *, "Reading with formatted read"
print *, p

end program example_stream_of_strings_to_numbers
10 changes: 10 additions & 0 deletions example/strings/example_string_to_number.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
program example_string_to_number
use stdlib_kinds, only: dp
use stdlib_str2num, only: to_num
implicit none
character(:), allocatable :: txt
real(dp) :: x

txt = ' 8.8541878128e−12 '
x = to_num( txt , x )
end program example_string_to_number
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ set(fppFiles
stdlib_math_is_close.fypp
stdlib_math_all_close.fypp
stdlib_math_diff.fypp
stdlib_str2num.fypp
stdlib_string_type.fypp
stdlib_string_type_constructor.fypp
stdlib_strings_to_string.fypp
Expand Down
Loading

0 comments on commit 8c7461d

Please sign in to comment.