R/trigonometry.r

Defines functions arccotangent arccosecant arcsecant arctangent arccosine arcsine cotangent cosecant secant tangent cosine sine

Documented in arccosecant arccosine arccotangent arcsecant arcsine arctangent cosecant cosine cotangent secant sine tangent

#' Angle vector aware trigonometric functions
#'
#' `sine()`, `cosine()`, `tangent()`, `secant()`, `cosecant()`, and `cotangent()` are
#' [angle()] aware trigonometric functions that allow for a user chosen angular unit.
#'
#' @inheritParams angle
#' @return A numeric vector
#'
#' @examples
#' sine(pi, "radians")
#' cosine(180, "degrees")
#' tangent(0.5, "turns")
#'
#' a <- angle(0.5, "turns")
#' secant(a)
#' cosecant(a)
#' cotangent(a)
#' @name trigonometric-functions
NULL

#' @rdname trigonometric-functions
#' @export
sine <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    sin.angle(x)
}

#' @rdname trigonometric-functions
#' @export
cosine <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    cos.angle(x)
}

#' @rdname trigonometric-functions
#' @export
tangent <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    tan.angle(x)
}

#' @rdname trigonometric-functions
#' @export
secant <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    1 / sin.angle(x)
}

#' @rdname trigonometric-functions
#' @export
cosecant <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    1 / cos.angle(x)
}

#' @rdname trigonometric-functions
#' @export
cotangent <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    if (!is_angle(x))
        x <- as_angle(x, unit = unit)
    1 / tan.angle(x)
}

#' Angle vector aware inverse trigonometric functions
#'
#' `arcsine()`, `arccosine()`, `arctangent()`,
#' `arcsecant()`, `arccosecant()`, and `arccotangent()` are
#' inverse trigonometric functions that return [angle()] vectors
#' with a user chosen angular unit.
#'
#' @inheritParams angle
#' @param x A numeric vector
#' @return An [angle()] vector
#'
#' @examples
#' arccosine(-1, "degrees")
#' arcsine(0, "turns")
#' arctangent(0, "gradians")
#' arccosecant(-1, "degrees")
#' arcsecant(1, "degrees")
#' arccotangent(1, "half-turns")
#'
#' # `base::atan2(y, x)` computes the angle of the vector from origin to (x, y)
#' as_angle(as_coord2d(x = 1, y = 1), "degrees")
#' @name inverse-trigonometric-functions
NULL

#' @rdname inverse-trigonometric-functions
#' @param tolerance If `x` greater than 1 (or less than -1) but is within a `tolerance`
#'                  of 1 (or -1) then it will be treated as 1 (or -1)
#' @export
arcsine <- function(x, unit = getOption("affiner_angular_unit", "degrees"),
                    tolerance = sqrt(.Machine$double.eps)) {
    idp1 <- which(x > 1 & x < 1 + tolerance)
    x[idp1] <- 1
    idn1 <- which(x < -1 & x > -1 - tolerance)
    x[idn1] <- -1
    unit <- standardize_angular_unit(unit)
    new_angle(from_radians(asin(x), unit), unit)
}

#' @rdname inverse-trigonometric-functions
#' @export
arccosine <- function(x, unit = getOption("affiner_angular_unit", "degrees"),
                      tolerance = sqrt(.Machine$double.eps)) {
    idp1 <- which(x > 1 & x < 1 + tolerance)
    x[idp1] <- 1
    idn1 <- which(x < -1 & x > -1 - tolerance)
    x[idn1] <- -1
    unit <- standardize_angular_unit(unit)
    new_angle(from_radians(acos(x), unit), unit)
}

#' @rdname inverse-trigonometric-functions
#' @param y A numeric vector or `NULL`.
#'          If `NULL` (default) we compute the 1-argument arctangent
#'          else we compute the 2-argument arctangent.
#'          For positive coordinates `(x, y)` then `arctangent(x = y/x) == arctangent(x = x, y = y)`.
#' @export
arctangent <- function(x, unit = getOption("affiner_angular_unit", "degrees"),
                       y = NULL) {
    unit <- standardize_angular_unit(unit)
    if (is.null(y))
        a <- from_radians(atan(x), unit)
    else
        a <- from_radians(atan2(y, x), unit)
    new_angle(a, unit)
}

#' @rdname inverse-trigonometric-functions
#' @export
arcsecant <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    arcsine(1 / x, unit)
}

#' @rdname inverse-trigonometric-functions
#' @export
arccosecant <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    arccosine(1 / x, unit)
}

#' @rdname inverse-trigonometric-functions
#' @export
arccotangent <- function(x, unit = getOption("affiner_angular_unit", "degrees")) {
    arctangent(1 / x, unit)
}

Try the affiner package in your browser

Any scripts or data that you put into this service are public.

affiner documentation built on April 4, 2025, 4:42 a.m.