Stéphane Laurent 2024-04-25

*Fractions of multivariate polynomials with rational coefficients.*

The **qspray** package allows arithmetic (and more) on multivariate polynomials with rational coefficients. Based on this one, the **ratioOfQsprays** package allows to manipulate *fractions* of multivariate polynomials with rational coefficients.

These notes about the **ratioOfQsprays** package assume that the reader is a bit familiar with the **qspray** package.

`ratioOfQsprays`

A `ratioOfQsprays`

object represents a fraction of two multivariate polynomial with rational coefficients. Such polynomials are represented by `qspray`

objects. The easiest way to create a `ratioOfQsprays`

is to introduce the variables of the polynomials with the `qlone`

function (from the **qspray** package), and then to build a `qspray`

numerator and a `qspray`

denominator with the arithmetic operations. For example:

```
library(ratioOfQsprays)
f <- function(x1, x2, x3) {
(2*x1^2 + x2*x3) / (4*x1 - 3*x3 + 1)
}
# variables:
x1 <- qlone(1)
x2 <- qlone(2)
x3 <- qlone(3)
# the 'ratioOfQsprays':
( roq <- f(x1, x2, x3) )
## [ 2*x^2 + y.z ] %//% [ 4*x - 3*z + 1 ]
```

Arithmetic on `ratioOfQsprays`

objects is available:

```
roq^2
## [ 4*x^4 + 4*x^2.y.z + y^2.z^2 ] %//% [ 16*x^2 - 24*x.z + 8*x + 9*z^2 - 6*z + 1 ]
roq - roq
## [ 0 ]
1 / roq
## [ 4*x - 3*z + 1 ] %//% [ 2*x^2 + y.z ]
2*roq + (x2 + x3)/x1
## [ 4*x^3 + 2*x.y.z + 4*x.y + 4*x.z - 3*y.z + y - 3*z^2 + z ] %//% [ 4*x^2 - 3*x.z + x ]
```

You don’t like my quotient bar `%//%`

? Be patient, we will see how to change it later. I adopted this large quotient bar because it is more easy to find it than a single slash `/`

in a `ratioOfQsprays`

having a long expression.

Rational numbers and `qspray`

polynomials are coercible to `ratioOfQsprays`

objects, and then you can also perform arithmetic operations between a `ratioOfQsprays`

and such an object:

```
2 * roq
## [ 4*x^2 + 2*y.z ] %//% [ 4*x - 3*z + 1 ]
"1/2" * roq
## [ x^2 + 1/2*y.z ] %//% [ 4*x - 3*z + 1 ]
roq + gmp::as.bigq("7/3")
## [ 2*x^2 + 28/3*x + y.z - 7*z + 7/3 ] %//% [ 4*x - 3*z + 1 ]
x1 + roq + x3^2
## [ 6*x^2 + 4*x.z^2 - 3*x.z + x + y.z - 3*z^3 + z^2 ] %//% [ 4*x - 3*z + 1 ]
```

The result of an arithmetic operation is always an irreducible fraction. To perform this step, the C++ library **CGAL** is used to compute a greatest common divisor of the numerator and the denominator of the possibly non-reduced fraction resulting from the arithmetic operation, and then to divide both of them by this greatest common divisor. This is very efficient in general.

`ratioOfQsprays`

Use `evalRatioOfQsprays`

to evaluate a `ratioOfQsprays`

. This function returns a `bigq`

number:

```
library(gmp) # rational numbers
x <- c("4", "3", "2/5")
evalRatioOfQsprays(roq, x)
## Big Rational ('bigq') :
## [1] 166/79
x <- as.bigq(x)
evalRatioOfQsprays(roq, x)
## Big Rational ('bigq') :
## [1] 166/79
f(x[1], x[2], x[3])
## Big Rational ('bigq') :
## [1] 166/79
```

It is also possible to substitute some values to only a subset of the variables, with the help of the function `substituteRatioOfQsprays`

. You have to indicate the variables you don’t want to replace with `NA`

:

```
x <- c(NA, "3", "2/5")
substituteRatioOfQsprays(roq, x)
## [ 2*x^2 + 6/5 ] %//% [ 4*x - 1/5 ]
x <- as.bigq(x)
f(x1, x[2], x[3])
## [ 2*x^2 + 6/5 ] %//% [ 4*x - 1/5 ]
```

And it is possible to convert a `ratioOfQsprays`

to a function which is evaluated by **Ryacas**:

```
fyac <- as.function(roq)
fyac("4", "3", "2/5") # = evalRatioOfQsprays(roq, c("4", "3", "2/5"))
## [1] "166/79"
```

Actually you can pass some literal variables to this function:

```
fyac("x", "3", "2/5") # = substituteRatioOfQsprays(roq, c(NA, "3", "2/5"))
## [1] "(2*(5*x^2+3))/(20*x-1)"
fyac("x", "y", "z") # = roq
## [1] "(y*z+2*x^2)/(4*x-3*z+1)"
fyac("x", "x", "x")
## [1] "(3*x^2)/(x+1)"
```

Complex numbers and allowed; the imaginary unit is denoted by `I`

. See the **Yacas** documentation for more information.

You can get numerical approximations by setting the option `N=TRUE`

in `as.function`

:

```
fyacN <- as.function(roq, N = TRUE)
fyacN("4", "3", "2/5")
## [1] 2.101266
fyacN("x", "3", "2/5")
## expression((2 * (5 * x^2 + 3))/(20 * x - 1))
fyacN("Sqrt(2)", "2 + 2*I", "3")
## [1] -4.267767-2.56066i
```

`ratioOfQsprays`

A couple of functions to query a `ratioOfQsprays`

are available:

```
getNumerator(roq)
## 2*x^2 + y.z
getDenominator(roq)
## 4*x - 3*z + 1
numberOfVariables(roq)
## [1] 3
isConstant(roq)
## [1] FALSE
isConstant(roq / roq)
## [1] TRUE
isUnivariate(roq)
## [1] FALSE
isUnivariate(x1 / (x1^2 + 1))
## [1] TRUE
isPolynomial(roq)
## [1] FALSE
isPolynomial((x1^2 - x2^2) / (x1 - x2))
## [1] TRUE
```

`ratioOfQsprays`

As you have seen, the variables of `roq`

are denoted by `x`

, `y`

, `z`

. This is the default way of printing a `ratioOfQsprays`

which has no more than three variables. If it has more than three variables, then they are denoted by `x1`

, `x2`

, `x3`

, …:

It is possible to control the way a `ratioOfQsprays`

is printed. For example, let’s say you want to print `roq`

by using `a1`

, `a2`

, `a3`

for the variables and you want to change the symbol for the quotient bar:

```
showRatioOfQspraysOption(roq, "x") <- "a"
showRatioOfQspraysOption(roq, "quotientBar") <- " / "
roq
## [ 2*a1^2 + a2.a3 ] / [ 4*a1 - 3*a3 + 1 ]
```

Now, if you perform an arithmetic operation between `roq`

*at first position* and an another `ratioOfQsprays`

, these show options are passed to the result if possible:

```
roq + (x1 + 1)/x2
## [ 2*a1^2.a2 + 4*a1^2 - 3*a1.a3 + 5*a1 + a2^2.a3 - 3*a3 + 1 ] / [ 4*a1.a2 - 3*a2.a3 + a2 ]
```

If you perform an arithmetic operation between `roq`

and an object coercible to a `ratioOfQsprays`

object but which is not a `ratioOfQsprays`

object, such as a `bigq`

number or a `qspray`

object, the show options of `roq`

are passed to the result, even if `roq`

is not at the first position:

An obvious example of a situation in which it is not always possible to transfer the show options is when you use three letters for the variables, e.g.

```
showRatioOfQspraysOption(roq, "showQspray") <- showQsprayXYZ(c("A", "B", "C"))
roq
## [ 2*A^2 + B.C ] / [ 4*A - 3*C + 1 ]
```

but then you add to `roq`

a `ratioOfQsprays`

containing the fourth variable:

```
roq + x4/(x4 + 1)
## [ 2*A1^2.A4 + 2*A1^2 + 4*A1.A4 + A2.A3.A4 + A2.A3 - 3*A3.A4 + A4 ] / [ 4*A1.A4 + 4*A1 - 3*A3.A4 - 3*A3 + A4 + 1 ]
```

Obviously it is not possible to denote the resulting fraction of polynomials with the letters `A`

, `B`

and `C`

. The solution I adopted consists in taking the first of these letters and to index it. The same method is used for the `qspray`

polynomials.

`ratioOfQsprays`

Let’s take a `ratioOfQsprays`

fraction of polynomials:

```
f <- function(x, y, z) {
(2*x^2 + y*z) / (4*x - 3*z + 1)
}
x <- qlone(1); y <- qlone(2); z <- qlone(3)
roq <- f(x, y, z)
```

You can differentiate it:

You can permute its variables:

You can perform some polynomial changes of its variables: