| Title: | Lightweight Numerical Operations |
|---|---|
| Description: | Provides dependency-free helpers for recurring numerical tasks on vectors, matrices, and arrays. Operations cover bounds, interpolation, remapping, division, Euclidean norms, normalization, and adjacent differences. Multi-input operations use strict scalar recycling, reject incompatible lengths, and preserve names, dimensions, and dimension names where applicable. Explicit handling of invalid intervals, zero denominators, and zero norms gives consistent behavior for common edge cases. |
| Authors: | Joao Claudio Macosso [aut, cre] (ORCID: <https://orcid.org/0009-0006-5051-9312>) |
| Maintainer: | Joao Claudio Macosso <[email protected]> |
| License: | GPL-3 |
| Version: | 1.0.0 |
| Built: | 2026-09-29 21:18:47 UTC |
| Source: | https://github.com/macosso/numops |
Keeps the first value and replaces every later value with its change from the preceding value.
adjacent_difference(x)adjacent_difference(x)
x |
A numeric vector in the order in which differences are required. |
For nonempty x, the result satisfies result[1] = x[1] and
result[i] = x[i] - x[i - 1] for later positions. Unlike diff(), the
first value is retained, so the input can be recovered with cumsum().
An empty input is returned unchanged.
A numeric vector with the same length and names as x.
adjacent_difference(c(10, 13, 12))adjacent_difference(c(10, 13, 12))
Replaces values below lower with lower and values above upper with
upper.
clamp(x, lower, upper)clamp(x, lower, upper)
x |
A numeric vector, matrix, or array containing values to restrict. |
lower |
A numeric lower bound giving the smallest permitted value. |
upper |
A numeric upper bound giving the greatest permitted value. |
Each result is computed as
min(max(x, lower), upper). Missing values in x are preserved. Bounds
may be infinite, but must not be missing or have lower > upper.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
x, lower, and upper must each have length one or a shared length.
Length-one inputs are recycled; other length combinations are errors.
Names, dimensions, and dimnames come from the first input with the shared
length.
clamp(c(-1, 0.5, 2), 0, 1)clamp(c(-1, 0.5, 2), 0, 1)
Replaces values below zero with zero and values above one with one.
clamp01(x)clamp01(x)
x |
A numeric vector, matrix, or array containing values to restrict. |
This is equivalent to clamp(x, 0, 1), or element-wise to
min(max(x, 0), 1). Missing values are preserved.
A numeric vector, matrix, or array with the same length, names,
dimensions, and dimnames as x.
clamp01(c(-0.2, 0.4, 1.3))clamp01(c(-0.2, 0.4, 1.3))
Divides corresponding values and substitutes a chosen result wherever the denominator is zero.
divide_or(x, y, default = NA_real_)divide_or(x, y, default = NA_real_)
x |
A numeric numerator. |
y |
A numeric denominator. |
default |
The numeric value to return where |
The result is x / y where y != 0, and default where
y == 0. Missing denominators and other non-finite results follow
ordinary R division; they do not trigger default.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
x, y, and default must each have length one or a shared length.
Length-one inputs are recycled; other length combinations are errors.
Names, dimensions, and dimnames come from the first input with the shared
length.
divide_or(c(1, 2, 0), c(1, 0, 0), default = NA_real_)divide_or(c(1, 2, 0), c(1, 0, 0), default = NA_real_)
Tests whether each value falls in the closed interval from lower to
upper.
in_range(x, lower, upper)in_range(x, lower, upper)
x |
A numeric vector, matrix, or array containing values to test. |
lower |
A numeric inclusive lower bound. |
upper |
A numeric inclusive upper bound. |
Each result is computed as x >= lower & x <= upper. Missing
values in x produce missing results. Bounds may be infinite, but must
not be missing or have lower > upper.
A logical vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
x, lower, and upper must each have length one or a shared length.
Length-one inputs are recycled; other length combinations are errors.
Names, dimensions, and dimnames come from the first input with the shared
length.
in_range(1:5, 2, 4)in_range(1:5, 2, 4)
Calculates how far x lies from a toward b.
inv_lerp(a, b, x)inv_lerp(a, b, x)
a |
A numeric endpoint corresponding to a result of zero. |
b |
A numeric endpoint corresponding to a result of one. It must differ
from |
x |
A numeric vector, matrix, or array containing values to locate. |
Each result is (x - a) / (b - a), calculated to avoid
unnecessary overflow for widely separated endpoints. Results outside
[0, 1] indicate that x lies outside the endpoints. Infinite endpoints
are not supported, and missing values are propagated.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
a, b, and x must each have length one or a shared length. Length-one
inputs are recycled; other length combinations are errors. Names,
dimensions, and dimnames come from the first input with the shared length.
inv_lerp(10, 20, c(10, 15, 20))inv_lerp(10, 20, c(10, 15, 20))
Computes Euclidean lengths for a complete object or for slices selected by
margin.
l2_norm(x, margin = NULL)l2_norm(x, margin = NULL)
x |
A numeric vector, matrix, or array. |
margin |
An integer vector naming the dimensions that index separate
slices, or |
For a slice with values x[i], the L2 norm is
sqrt(sum(x[i]^2)). The calculation is scaled to avoid unnecessary
overflow and underflow. An empty slice has norm zero, an infinite value
produces an infinite norm, and a missing value produces a missing norm.
If margin is NULL, one numeric value. Otherwise, a numeric vector
or array indexed by dim(x)[margin], with the corresponding dimnames.
l2_norm(c(3, 4)) l2_norm(matrix(1:6, nrow = 2), margin = 1)l2_norm(c(3, 4)) l2_norm(matrix(1:6, nrow = 2), margin = 1)
Computes the value a proportion t of the way from a to b.
lerp(a, b, t)lerp(a, b, t)
a |
A numeric endpoint returned when |
b |
A numeric endpoint returned when |
t |
A numeric interpolation proportion, usually between zero and one. |
Each result is computed as a + t * (b - a), using a calculation
that avoids unnecessary overflow when a and b have opposite signs.
Values of t outside [0, 1] extrapolate. The endpoints are returned
exactly when t is zero or one.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
a, b, and t must each have length one or a shared length. Length-one
inputs are recycled; other length combinations are errors. Names,
dimensions, and dimnames come from the first input with the shared length.
lerp(10, 20, c(0, 0.25, 1))lerp(10, 20, c(0, 0.25, 1))
Computes the value halfway between corresponding values in x and y.
midpoint(x, y)midpoint(x, y)
x |
The first numeric endpoint. |
y |
The second numeric endpoint. |
The mathematical result is (x + y) / 2. The implementation uses
equivalent forms chosen to avoid unnecessary overflow for finite values.
Missing and infinite values follow ordinary R arithmetic.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
x and y must each have length one or a shared length. Length-one inputs
are recycled; other length combinations are errors. Names, dimensions, and
dimnames come from the first input with the shared length.
midpoint(c(0, 10), c(10, 20))midpoint(c(0, 10), c(10, 20))
Divides a numeric object, or each selected slice, by its Euclidean norm.
normalize_l2(x, margin = NULL, zero = c("keep", "na", "error"))normalize_l2(x, margin = NULL, zero = c("keep", "na", "error"))
x |
A numeric vector, matrix, or array to normalize. |
margin |
An integer vector naming the dimensions that index separate
slices, or |
zero |
How to handle a slice whose norm is zero. |
Each slice s is transformed to s / l2_norm(s). Nonzero finite
slices therefore have an L2 norm of one. A missing value makes its entire
slice missing. Infinite values follow ordinary division by an infinite
norm.
A numeric vector, matrix, or array with the same length, names,
dimensions, and dimnames as x.
normalize_l2(c(3, 4)) normalize_l2(matrix(1:6, nrow = 2), margin = 1)normalize_l2(c(3, 4)) normalize_l2(matrix(1:6, nrow = 2), margin = 1)
Linearly maps values from the interval from to the interval to.
remap(x, from, to)remap(x, from, to)
x |
A numeric vector, matrix, or array containing values to map. |
from |
A finite numeric vector of length two giving the input endpoints. |
to |
A finite numeric vector of length two giving the output endpoints. |
The result is
to[1] + (x - from[1]) / (from[2] - from[1]) * (to[2] - to[1]).
Values outside from are extrapolated. Either interval may be reversed,
but the endpoints of from must differ.
A numeric vector, matrix, or array with the same length, names,
dimensions, and dimnames as x.
remap(c(0, 5, 10), c(0, 10), c(-1, 1))remap(c(0, 5, 10), c(0, 10), c(-1, 1))
Periodically maps values to the half-open interval [lower, upper).
wrap(x, lower, upper)wrap(x, lower, upper)
x |
A numeric vector, matrix, or array containing values to wrap. |
lower |
A finite numeric lower boundary included in the result. |
upper |
A finite numeric upper boundary excluded from the result. |
The operation is equivalent to
lower + (x - lower) %% (upper - lower), using an overflow-resistant
calculation. Bounds must be finite with lower < upper. A value equal to
upper maps to lower; infinite values in x produce NaN.
A numeric vector, matrix, or array of the shared length. It takes names, dimensions, and dimnames from the first input already having that length.
x, lower, and upper must each have length one or a shared length.
Length-one inputs are recycled; other length combinations are errors.
Names, dimensions, and dimnames come from the first input with the shared
length.
wrap(c(-10, 0, 370), 0, 360)wrap(c(-10, 0, 370), 0, 360)