In order to have exact geometric computations it is necessary to avoid the issues of floating point arithmetic. CGAL can work with a range of different exact kernels, where euclid uses the Exact_predicates_exact_constructions predifined kernel. Moving values in and out of R would force a conversion to double thus destroying the exactness of computation, so euclid provides a new numeric vector class that simply maps to the underlying exact representation. While the exact numeric class generally behaves as a standard numeric there are operations that are not possible because it will loose the exactness, e.g. trigonometric functions, roots, etc. If any unsupported function is needed it is necessary to convert back to numeric (thus loosing exactness). Anywhere euclid takes a numeric input it will convert it to an exact numeric before use.

## Usage

exact_numeric(x = numeric(0))

is_exact_numeric(x)

as_exact_numeric(x)

## Arguments

x

An object coercible to numeric

## Value

An euclid_exact_numeric vector

## Note

Exact numeric only have one form of non-finite value: NA. Any other non-finite value will be converted to that.

Other non-geometry vectors: affine_transformation, bbox()

## Examples

# Standard use
exact_numeric(runif(5))
#> <exact numerics [5]>
#> [1] 0.2352080 0.6000057 0.8187621 0.3930079 0.2987804

# Non-finite numbers are all converted to NA
exact_numeric(NaN)
#> <exact numerics [1]>
#> [1] NA

# this is also true for division by zero
exact_numeric(runif(5)) / 0
#> <exact numerics [5]>
#> [1] NA NA NA NA NA

# Exact numerics are more limited on operations but doesn't have the
# weirdness of floating point arithmetic:
float <- c(1, 2, 3)
identical(float[1] + float[2], float[3])
#> [1] TRUE
float <- float / 10
identical((float[1] + float[2]) * 10, float[3] * 10)
#> [1] FALSE

exact <- exact_numeric(c(1, 2, 3))
identical(as.numeric(exact[1] + exact[2]), as.numeric(exact[3]))
#> [1] TRUE
exact <- exact / 10
identical(as.numeric((exact[1] + exact[2]) * 10), as.numeric(exact[3] * 10))
#> [1] TRUE

# This only holds if the input are exact to begin with
identical(
as.numeric(exact_numeric(1/10 + 2/10)),
as.numeric(exact_numeric(3/10))
)
#> [1] FALSE