File: polybase.R

package info (click to toggle)
r-cran-polynom 1.4-1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 212 kB
  • sloc: makefile: 2
file content (164 lines) | stat: -rw-r--r-- 5,294 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
polynomial <- function(coef = c(0, 1)) {
  a <- as.numeric(coef)
  while ((la <- length(a)) > 1 && a[la] == 0) a <- a[-la]
  structure(a, class = "polynomial")
}

as.polynomial <- function(p) {
  if (is.polynomial(p)) p else polynomial(p)
}

is.polynomial <- function(p) {
  inherits(p, "polynomial")
}

Ops.polynomial <- function(e1, e2) {
  if (missing(e2))
    return(switch(.Generic,
                  `+` = e1,
                  `-` = polynomial(NextMethod(.Generic)),
                  stop("unsupported unary operation")))
  e1 <- unclass(e1)
  e2 <- unclass(e2)
  l1 <- length(e1)
  l2 <- length(e2)
  e1.op.e2 <- switch(.Generic,
                     `+` = , `-` = {
                       e1 <- c(e1, rep.int(0, max(0, l2 - l1)))
                       e2 <- c(e2, rep.int(0, max(0, l1 - l2)))
                       NextMethod(.Generic)
                     },
                     `*` = if (l1 == 1 || l2 == 1) {
                       e1 * e2
                     } else {
                       m <- outer(e1, e2)
                       as.vector(tapply(m, row(m) + col(m), sum))
                     },
                     `/` = {
                       if (l2 == 0) stop("unsupported polynomial division")
                       if (l2 == 1) e1/e2 else {
                         p <- rev(e1)
                         q <- rev(e2)
                         r <- rep.int(0, length(p))
                         i <- 0
                         while (length(p) >= l2) {
                           i <- i + 1
                           d <- p[1]/q[1]
                           r[i] <- d
                           p[1:l2] <- p[1:l2] - d * q
                           p <- p[-1]
                         }
                         if (i == 0) 0 else r[i:1]
                       }
                     },
                     `^` = {
                       if (l2 != 1 || e2 < 0 || e2%%1 != 0) stop("unsupported polynomial power")
                       switch(as.character(e2), `0` = 1, `1` = e1, {
                         p <- q <- polynomial(e1)
                         for (i in 2:e2) p <- p * q
                         as.numeric(p)
                       })
                     },
                     `%%` = {
                       if (l2 == 1) 0 else {
                         p <- rev(e1)
                         q <- rev(e2)
                         while (length(p) >= l2) {
                           d <- p[1]/q[1]
                           p[1:l2] <- p[1:l2] - d * q
                           p <- p[-1]
                         }
                         if (length(p) == 0) 0 else rev(p)
                       }
                     },
                     `==` = return(l1 == l2 && all(e1 == e2)),
                     `!=` = return(l1 != l2 || any(e1 != e2)),
                     stop("unsupported operation on polynomials"))
  polynomial(e1.op.e2)
}

Summary.polynomial <- function(..., na.rm = FALSE) {
  ok <- switch(.Generic,
               sum = , prod = TRUE,
               FALSE)
  if (!ok)
    stop(gettextf("Generic '%s' not defined for \"%s\" objects.", .Generic, .Class))
  switch(.Generic,
         sum = accumulate("+", as.polynomial(0), polylist(...)),
         prod = accumulate("*", as.polynomial(1), polylist(...)))
}

Math.polynomial <- function(x, ...) {
  switch(.Generic,
         round = , signif = , floor = , ceiling = , trunc = polynomial(NextMethod(.Generic)),
         stop(paste(.Generic, "unsupported for polynomials")))
}

as.character.polynomial <- function(x, decreasing = FALSE, ...) {
  p <- unclass(x)
  lp <- length(p) - 1
  names(p) <- 0:lp
  p <- p[p != 0]
  if (length(p) == 0)
    return("0")
  if (decreasing)
    p <- rev(p)
  signs <- ifelse(p < 0, "- ", "+ ")
  signs[1] <- if (signs[1] == "- ")
    "-" else ""
  np <- names(p)
  p <- as.character(abs(p))
  p[p == "1" & np != "0"] <- ""
  pow <- paste("x^", np, sep = "")
  pow[np == "0"] <- ""
  pow[np == "1"] <- "x"
  stars <- rep.int("*", length(p))
  stars[p == "" | pow == ""] <- ""
  paste(signs, p, stars, pow, sep = "", collapse = " ")
}

print.polynomial <- function(x, digits = getOption("digits"), decreasing = FALSE, ...) {
  p <- as.character.polynomial(signif(x, digits = digits), decreasing = decreasing)
  pc <- nchar(p)
  ow <- max(35, getOption("width"))
  m2 <- 0
  while (m2 < pc) {
    m1 <- m2 + 1
    m2 <- min(pc, m2 + ow)
    if (m2 < pc)
      while (substring(p, m2, m2) != " " && m2 > m1 + 1) m2 <- m2 - 1
    cat(substring(p, m1, m2), "\n")
  }
  invisible(x)
}

as.function.polynomial <- function(x, ...) {
  a <- rev(coef(x))
  w <- as.name("w")
  v <- as.name("x")
  ex <- call("{", call("<-", w, 0))
  for (i in seq_along(a)) {
    ex[[i + 2]] <- call("<-", w, call("+", a[1], call("*", v, w)))
    a <- a[-1]
  }
  ex[[length(ex) + 1]] <- w
  f <- function(x) NULL
  body(f) <- ex
  f
}

poly.orth <- function(x, degree = length(unique(x)) - 1, norm = TRUE) {
  at <- attr(poly(x, degree), "coefs")
  a <- at$alpha
  N <- at$norm2
  x <- polynomial()
  p <- list(polynomial(0), polynomial(1))
  for (j in 1:degree) p[[j + 2]] <- (x - a[j]) * p[[j + 1]] - N[j + 1]/N[j] * p[[j]]
  p <- p[-1]
  if (norm) {
    sqrtN <- sqrt(N[-1])
    for (j in 1 + 0:degree) p[[j]] <- p[[j]]/sqrtN[j]
  }
  class(p) <- "polylist"
  p
}