Skip to content

9. Precision ​

probe has computed in double precision so far. VecFor has the same vector in single, double and quadruple precision; probe measures the edge from p2 to p3, of length 2, in each of them.

f90
program probe
!< Tutorial, chapter 9: the same edge in single, double and quadruple precision.
use, intrinsic :: iso_fortran_env, only : real128
use penf, only : R4P, R8P, R16P
use vecfor, only : ex_R4P, ey_R4P, ex_R8P, ey_R8P, ex_R16P, ey_R16P, normL2_R4P, vector, vector_R4P, vector_R8P, &
                   vector_R16P
implicit none
type(vector_R4P)  :: a4  ! single precision
type(vector_R8P)  :: a8  ! double precision
type(vector_R16P) :: a16 ! quadruple precision, if the library is built for it
type(vector)      :: a   ! the default: double precision
real(real128)     :: l   ! the exact length, sqrt(2), to 33 digits

l = sqrt(2._real128)
a4  = ey_R4P  - ex_R4P                       ! each kind has its own versors
a8  = ey_R8P  - ex_R8P
a16 = ey_R16P - ex_R16P
print '(A,I3,A,ES10.2)', 'R4P : digits', precision(a4%x),  ', error of the length', &
                         abs(a4%normL2()  - l)
print '(A,I3,A,ES10.2)', 'R8P : digits', precision(a8%x),  ', error of the length', &
                         abs(a8%normL2()  - l)
print '(A,I3,A,ES10.2)', 'R16P: digits', precision(a16%x), ', error of the length', &
                         abs(a16%normL2() - l)
print '(A,I3)',          'vector: digits', precision(a%x)
a4 = a4 * 0.1_R8P                            ! a scalar of another kind is converted to the kind of the vector
print '(A,ES16.8)', 'x of a4 * 0.1    ', a4%x
print '(A,ES16.8)', 'length, function ', normL2_R4P(a4)
a8%x = real(a4%x, R8P)                       ! from one kind to another: component by component
a8%y = real(a4%y, R8P)
a8%z = real(a4%z, R8P)
print '(A,ES24.16)', 'x of a8          ', a8%x
endprogram probe

With VecFor built as by its FoBiS modes:

console
$ probe
R4P : digits  6, error of the length  2.42E-08
R8P : digits 15, error of the length  9.67E-17
R16P: digits 15, error of the length  9.67E-17
vector: digits 15
x of a4 * 0.1     -1.00000001E-01
length, function   1.41421363E-01
x of a8           -1.0000000149011612E-01

With VecFor built with -DPENF_R16P:

console
$ probe
R4P : digits  6, error of the length  2.42E-08
R8P : digits 15, error of the length  9.67E-17
R16P: digits 33, error of the length  0.00E+00
vector: digits 15
x of a4 * 0.1     -1.00000001E-01
length, function   1.41421363E-01
x of a8           -1.0000000149011612E-01

Three precisions, one module ​

use vecfor exports a vector type for each real kind of PENF: vector_R4P (single precision), vector_R8P (double) and vector_R16P (quadruple), each with its versors (ex_R4P, ey_R8P, ez_R16P, ...) and its free functions (normL2_R4P, angle_R16P, ...). The type-bound methods and the operators have the same names for every kind: a4%normL2(), a16 .cross. b16. vector is the default kind, double precision, with ex, ey, ez and the unsuffixed functions.

A single precision vector has 6 significant digits: its length is off by 2.4×10−8. A double precision one has 15, and is off by 9.7×10−17, less than half a unit in the last place: correctly rounded.

True quadruple precision ​

vector_R16P is as precise as the kind R16P of PENF, and PENF makes R16P a true quadruple precision kind only when it is compiled with -DPENF_R16P. The FoBiS modes of VecFor do not define it, so in their builds R16P is double precision and vector_R16P has 15 digits, as the first run shows. Built with -DPENF_R16P (library and program alike, see Precision and kinds), vector_R16P has 33 digits and the length is exact to all the digits printed, as the second run shows. The reference here is real128 of iso_fortran_env, which does not depend on PENF.

Scalars of other kinds, vectors of other kinds ​

A scalar of any kind can meet a vector of any kind: a4 * 0.1_R8P converts 0.1 to single precision first, and the result is a single precision vector, with the error of single precision (-1.00000001E-01).

Two vectors of different kinds cannot: there is no a4 + a8, nor a8 = a4. Convert component by component, with real(a4%x, R8P): the result carries the error of the single precision value (-1.0000000149011612E-01), digits cannot be recovered. Note that vector and vector_R8P are two different types too, although both are double precision: vector comes from its own module, so a vector_R8P is not assigned to a vector either (see Vectors of each precision).

What you learned

vector_R4P, vector_R8P, vector_R16P and their versors and functions; true quadruple precision with -DPENF_R16P; scalars of any kind, vectors converted by components. Reference: Precision and kinds.

Next: 10. Printing and files.

Released under the GPL v3, BSD 2-Clause, BSD 3-Clause or MIT License.