Module

Data.Sparse.Polynomial

Package
purescript-sparse-polynomials
Repository
Ebmtranceboy/purescript-sparse-polynomials

#Polynomial Source

newtype Polynomial a

Represents a non-null polynomial by the discrete list of its non-zero terms, stored in a map

  • from Int (type of the degree of a term)
  • to a (type of the coefficient of a term: integer, real, complex, polynomic ...).

and a null polynomial by the empty map.

> -- Working with Sparse Polynomials
> import Data.Sparse.Polynomial 
 
> -- Defining univariate polynomial
> -- ------------------------------
>
> --  * by concat / reset with (<>) [see Semigroup instance note] or
> --  * by summation with (+) and (-)
>
> -- of terms (monoms). Each term has the form: coef ^ degree.
> -- For instance
>
> display ["x"] $ 2.0 ^ 3 <> (-4.0) ^ 0
"(2.0)×x^3+(-4.0)"
>
> 2.0 ^ 3 <> (-4.0) ^ 0
(2.0)×x^3+(-4.0)
>
> display ["z"] $ 2.0 ^ 3 + (-4.0) ^ 0
"(2.0)×z^3+(-4.0)"
>
> -- displays (with variable "x" by default) the polynomial 
> -- that subtract 4 from the double of the cube, 
> -- so evaluated at 5 with the (:.) evaluation operator:
>
> (2.0 ^ 3 <> (-4.0) ^ 0) :. 5.0
246.0
>
> -- or with `xpose`, its flipped version:
>
> 5.0 `xpose` (2.0 ^ 3 <> (-4.0) ^ 0)
246.0
>
> -- without having to specify the variable name.


> -- Polynomials constitute a Ring, so usual mathematical operations can 
> -- be performed:
> 
> a = 1 ^ 2 <> 4 ^ 0 -- working with Int as the underlying structure
>                    -- here 
> b = 1 ^ 1 <> 1 ^ 0
> 
> a
(1)×x^2+4
> 
> b
(1)×x+1
> 
> a+b
(1)×x^2+(1)×x+5
>
> a-b
(1)×x^2+(-1)×x+3
>
> a*b
(1)×x^3+(1)×x^2+(4)×x+4

> -- Composition is using the (.-) substitution operator:
>
> aAfterB = a .- b
> aAfterB
(1)×x^2+(2)×x+5
>
> b .- a
(1)×x^2+5
>
> -- or `xpand`, its flipped version:
>
> bThenA = b `xpand` a
> bThenA
(1)×x^2+(2)×x+5
>
> a `xpand` b
(1)×x^2+5


> -- Coefficients can be extracted with the (!) query operator :
> a ! 0
4


> -- When the underlying structure is a Division ring (Rationals, Reals, 
> -- Complex, or any other field), we can divide too. (Technically, when
> -- the underlying structure is only a Euclidean ring -- like  Int --,
> -- the algorithm works when the rest is null and occasionnally loops
> -- forever if not.)
>
> import Data.Ratio
> r = (1%9) ^ 2 <> (2%1) ^ 0 -- meaning x↦(1/9) x^2 + 2
> s = (4%1) ^ 1 -- meaning x↦4x
>
> r / s
(1 % 36)×x
>
> r `mod` s
2 % 1
>
> gcd r s
32 % 1
>
> -- [WARNING] the implemented gcd is designed to be useful 
> -- for non-constant polynomials modulo some scaling factor.
> -- This has 2 major consequences :
>
> -- 1) `Prelude.gcd a b` is generally _different_ from 
> --    `Data.Sparse.Polynomial.gcd (a^0) (b^0)`
> --    because the scaling factor is left unchanged 
> --    at the end of the algorithm (see gcd's comment)
> -- 2) Little Bézout's theorem doesn't hold : for any two multivariate
> --    polynomials P and Q, it's _not_ always possible to find two
> --    polynomials U and V, and a ring element r such that
> --    U×P + V×Q = r GCD(P,Q).
> --    [Consider P(X,Y)=X, Q(X,Y)=Y then no (U,V) possible
> --    since GCD(P,Q)=1]


> -- No surprise with differentiation:
> diff $ (2%1)^3<>(-4%1)^1
(6 % 1)×x^2+(-4 % 1)


> -- There is also a useful tool in case of univariate real polynomials:
>
> pol = 1.0 ^ 2 <> 7.0 ^ 1 <> 12.0 ^ 0
> roots pol
[-2.9999999996605635-3.769201527786494e-10i,
-4.000000000339432+3.769201528752112e-10i]
>
> -- which gives the approximative values of all the complex roots of the 
> -- polynomial.
> -- Thanks to the sparse nature of the lib, any abuse is permitted :-)
> -- but best results are given when there is no multiple roots
> 
> roots $ 1.0 ^ 16 <> (-1.0) ^ 0
[1.0+0.0i,0.3826834323650897+0.9238795325112867i,
-0.7071067811865476+0.7071067811865476i,
-0.9238795325112871-0.3826834323650901i,
-2.5434386919291434e-12-1.0000000000025875i,
0.9238795325108287-0.382683432364685i,
0.7071067811865476+0.7071067811865476i,
-0.9238795325112867+0.3826834323650898i,
-0.707106781186544-0.7071067811865521i,
0.382683432330398-0.9238795325016941i,
0.7071067812242033-0.7071067811940133i,
2.825247823205539e-19+1.0i,-0.3826834323650898+0.9238795325112867i,
-1.0-1.7156434035577625e-17i,-0.3826834323650554-0.9238795325112262i,
0.9238795325112867+0.3826834323650898i]
 

> ------------------------------------
> --                                --
> -- ABOUT MULTIVARIATE POLYNOMIALS --
> --                                --
> --           -------              --
> --          |  API  |             --
> --           -------              --
> ------------------------------------

> --    This set of notes shows several uses of the functions
> --    performing  multivariate polynomial manipulation provided 
> --    by this library, along with (^) and (!) : 
> --
> --     * `set`,  for evaluation and arity decrease, more efficient 
> --               but demanding than
> --     * `fill`, for substitution (or `full` for full evaluation)
> --               where arity is conserved.
> --
> --    Then, two functions are provided to increase arity :
> --     * `pad`,  rather coarse, useful in particular
> --               with numerical constants, and
> --     * `nest`, for more specific uses.
> --
> --    The inverse of `pad`  :
> --     * `unpad`, carelessly decreases arity.
> --
> --    Finally, one function makes variable changes :
> --     * the `swap` function,
> --
> --    and one function extracts the constant coefficient
> --    of any polynomial :
> --     * the `peel` function.
> --
> --    See documentation of each function for more specifications. 


> -- 1) DEFINITION : There are (at least) three possible 
> --    ----------   and equivalent ways to define multivariate
> --                 polynomials with this library:

> --    a) By using a sum of terms where each term is defined with 
> --       the enumerative representation "n ^ ... ^ e_Z ^ e_Y ^ e_X",
> --       generalizing the construction seen with univariate polynomials
> --       where n is an element of the underlying structure and the e_i, 
> --       of type Int, correspond to respective variable's degrees.
>
> 3^0^2
(3)×x^2
>
> 4^1^1^0
((4)×z)×y
>
> 3^0^0^0^2 + 4^0^1^1^0 + 5^1^0^0^0
(3)×x^2+((4)×z)×y+(5)×t

> --    b) By using
> --       * the basis axes where each axis (aka term that embodies
> --         a variable) is defined with the enumerative representation,
> --         and
> --       * a wrapping function that lifts the constant numeric values
> --         (refered as n in a))  to the required (multivariate) 
> --         polynomial type (see the `axes`  function).
> --        
>
> -- For instance, with arity = 4 and Int as the underlying structure :
>
> x = 1^0^0^0^1
> y = 1^0^0^1^0
> z = 1^0^1^0^0
> t = 1^1^0^0^0
> kst v = v^0^0^0^0 
>
> kst 3*x*x + kst 4*y*z + kst 5*t 
(3)×x^2+((4)×z)×y+(5)×t

> --    Note that, in the enumerative representation of a term, the 
> --    positions of the exponents listed from left to right were 
> --    designed to be of decreasing proximity (i.e of decreasing 
> --    technical accessibility) so that the righter the position 
> --    of a 1, the more remote and more difficult to access.
> --    In other words, if an integer is associated with the proximity of
> --    a term, and if `@` is the function returning that integer,
> --    
> --    @(x) < @(y) < ... < @(nearest) < @(kst one).
> --
> --    In addition, this library has been built, for any arity,
> --    following these four principles : 
> --
> --     * the proximity of two consecutive axes defer by 1,
> --     * the proximity of the most remote axis ("x") is set to 0,
> --     * thus, the proximity of the most accessible (aka nearest) axis
> --       is set to arity-1,
> --     * and the constant terms (like `kst one`) are more accessible 
> --       than any other axis.

> --    This leads to the preferred third option:

> --    c) By using 
> --     * proximity of axes, 
> --     * `one^1`, the _univariate_ axis, and
> --     * `pad` and `swap` functions : 
>
> --========= DEFINING SCHEME FOR ANY ARITY > 1 (arity=4 here) ==========
>              ---------------------------------                                                 
>
>                     -- *) Keep the 0, 1, .., arity-1 sequence in mind
>                           as the x, y, .., t sequence of axes.
>
> kst = pad @3        -- *) Define the wrapping function = pad @(arity-1)
>
>                     -- *) Choose a underlying structure to define `one`
>                     --    then :
> t = pad @2 (1^1)    --    Nearest axis = pad @(arity-2) $ one^1
>
>                     -- *) Other axis =
> x = swap @0 @3 t    --      swap @self @(arity-1) $ nearest axis
> y = swap @1 @3 t    --    ...
> z = swap @2 @3 t    --    ...
> ...                 --    ...
> --=====================================================================
>
> kst 3*x*x + kst 4*y*z + kst 5*t          
(3)×x^2+((4)×z)×y+(5)×t

> --     ------------------------------
> --    | Using `pad` increases arity. |
> --     ------------------------------

> -- Note that, for arity=1, `kst = pad @0` and `x = one^1`.

> -- 2) DISPLAY : By defaut, the first 4 variables are printed with the 
> --    -------
> --    "x","y","z" and "t" strings in that order, but, for five
> --    or more variables, the variables names are proximity-indexed
> --    versions of "x".
> --    So,
>
> display ["a","b","c"] $ 2^0^0^0 + 4^0^1^0
> --    returns
"(4)×b+2"
> --    whereas
> 2^0^0^0 + 4^0^1^0
> --    displays
(4)×y+2
> --    and
> 2^0^0^0^0^0 + 4^0^0^0^1^0
> --    displays
(4)×x1+2


> -- 3) EVALUATION : A multivariate polynomial, say with arity = 4 
> --    ----------   for instance, like
>
> p = kst 2 * x - y * y + z * z * t - z * t * t
> p
(2)×x+((-1))×y^2+((1)×t)×z^2+((-1)×t^2)×z
>
> --    has been modeled in this library as
> --    a polynomial in x whose coefficients are
> --    polynomials in y whose coefficients are
> --    polynomials in z whose coefficients are
> --    polynomials in t whose coefficients are numbers
> --    (in other words, polynomials in the most accessible variable
> --    are univariate polynomials).

> --    As a consequence, if we evaluate (`set`) the t-component of p
> --    at a constant value,
> 
> 4 `set @3` p
(2)×x+((-1))×y^2+(4)×z^2+(-16)×z
>
> :t 4 `set @3` p
Polynomial (Polynomial (Polynomial Int))
>
> --    we get the same 3-variate polynomial as if we substitute (`fill`)
> --    the t variable with the corresponding constant polynomial :
> 
> kst 4 `fill @3` p
(2)×x+((-1))×y^2+(4)×z^2+((-16))×z
>
> --    However, with `fill`, the result is in the same scope 
> --    as p (where arity = 4).
>
> :t kst 4 `fill @3` p
Polynomial (Polynomial (Polynomial (Polynomial Int)))

> --     -------------------------------------
> --    | Using `set` _does_ decrement arity, |
> --    | using `fill` does not change arity. |
> --     -------------------------------------

> --    This is a desired behavior because `set` consumes all occurrences 
> --    of a variable so the loss of one unit of arity only reflects
> --    the saved space. On the other hand, with `fill`, all occurrences 
> --    of the replaced variable are consumed as well but replacements 
> --    variables  may include the replaced variable itself (which is
> --    not possible with `set`), so arity is not expected to be 
> --    decreased mecanically in this case.

> --    Here are all the ways to define
> --
> --             q(x,y) = p(x,y,3,4) = (2)×x+(-1)×y^2+(-12)
> --
> --    from p(x,y,z,t) :
>
> --    (xtend = pad @0 : convert a number
> --    to the corresponding univariate constant polynomial)
>
> 3 `set @2` (4 `set @3` p)                -- output arity = 2
> 4 `set @2` (xtend 3 `set @2` p)          -- output arity = 2
> xtend 3 `set @2` (kst 4 `fill @3` p)     -- output arity = 3
> 4 `set @3` (kst 3 `fill @2` p)           -- output arity = 3
> pad @2 3 `fill @2` (4 `set @3` p)        -- output arity = 3
> pad @2 4 `fill @2` (xtend 3 `set @2` p)  -- output arity = 3
> kst 3 `fill @2` (kst 4 `fill @3` p)      -- output arity = 4
> kst 4 `fill @3` (kst 3 `fill @2` p)      -- output arity = 4


> --    Notice that using `set` requires to be careful about the types of 
> --    the provided arguments. This is the first reason `set` is
> --    more demanding to use than `fill`.

> --    Ultimately, the easiest ways to fully evaluate a polynomial 
> --    (numerical result of q(1,2) with arity 0 after all partial 
> --    partial evaluations performed), are either with `set`,
> --    providing the values _in_order_

> set @0 1 $ set @1 2 $ set @2 3 $ set @3 4 p
-14

> --    or with `fill`, providing constant polynomials in any order 
> --    (techically, the result is still a polynomial whose constant 
> --    value can be extracted with `peel`) :

> fill @3 (kst 4) $ fill @0 (kst 1) $ fill @2 (kst 3) $ fill @1 (kst 2) p
-14

> --    or with `full`, a 'saturated' version of `fill` where values have
> --    to be provided in order, this time :

> peel $ map kst [1,2,3,4] `full` p
-14


> --    Similarly, when evaluating the z-component of p at a non-constant
> --    univariate polynomial, it is implicitely expressed in t, 
> --    in respect of the type of the coefficients of the z-component :
>
> pz = (2^1-5^0) `set @2` p
> pz
(2)×x+((-1))×y^2+(2)×z^3+(-15)×z^2+(25)×z
>
> --    Even if any t doesn't seem to be introduced, this expression is 
> --    expected because of the way `set` works : after having been 
> --    replaced with a t expression, each occurrence of z in p has 
> --    vanished. The empty z-slot is vacant, and since t follows z 
> --    by order of proximity, t-content earns an order
> --    of remoteness and everything looks like t has been renamed z. 
> --    As a check, the fact that the same polynomial is obtained when  
> --    filling z with the corresponding polynomial in t should
> --    convince that the expression of pz is right :
> --    
> 
> pt = (kst 2 * t - kst 5) `fill @2` p
> pt
(2)×x+((-1))×y^2+(2)×t^3+(-15)×t^2+(25)×t

> --    This odd process is the second reason `set` is more demanding
> --    than `fill`. In addition, note that, with `fill`, the replacement 
> --    polynomial can include any variable, unlike with `set` where
> --    replacement variables are always stricly more accessible 
> --    than the replaced one :
> 
> (kst 2 * z - kst 5 * y ) `fill @2` p
(2)×x+((25)×t+(-1))×y^2+(((-20)×t)×z+(5)×t^2)×y+((4)×t)×z^2+((-2)×t^2)×z


> --    When needed, it is possible to change pt to pz by evaluating 
> --    the z-component of pt at any polynomial with right arity (say  
> --    zero). Indeed, the empty content associated with z gets removed
> --    since `set` decrements arity and the content associated with t
> --    is shifted one step more remote and gets associated with z,
> --    as already stated.
> 
> zero `set @2` pt
(2)×x+((-1))×y^2+(2)×z^3+(-15)×z^2+(25)×z

> --    It is conceptually easier to change pz to pt, by substituting z 
> --    with t, as long as we use a version of pz with arity at least 4 
> --    because the use of `fill` requires its two arguments of the same
> --    arity :
> --    Note that the `pad` function can't be used to change arity here
> --    since it shifts all the axes several times, unlike the `nest` 
> --    function which shifts several chosen axes once  : 
> --    
> 
> t `fill @2` (nest @2 pz)
(2)×x+((-1))×y^2+(2)×t^3+(-15)×t^2+(25)×t
>
> --     --------------------------------
> --    | Using `nest` increments arity. |
> --     --------------------------------

> --    This method can be used to change pt to pz as well
> --    (arity won't match though, `set @3 zero` would fix that)

> z `fill @3` pt
(2)×x+((-1))×y^2+(2)×z^3+((-15))×z^2+(25)×z


> --    There is another way to change pt to pz using 
> --    a function that unconditionnally swaps two axes
> --    (and keeps scope).
>
> swap @2 @3 pt
(2)×x+((-1))×y^2+(2)×z^3+((-15))×z^2+(25)×z

> --     --------------------------------------
> --    | Using `swap` does not change arity. |
> --     --------------------------------------

> --    Finally, it is possible to `swap` pz to pt too, but
> --    pz's arity is only 3, so swaping z and t requires to `nest`
> --    a t-slot beforehand just like in one of the preceeding examples
>
> swap @2 @3 $ nest @3 pz
(2)×x+((-1))×y^2+(2)×t^3+(-15)×t^2+(25)×t
>
> --    and a simpler way is to just `nest` a z-slot, thanks to the fact
> --    that `nest` shifts all previous z content on step nearer, to t:
>
> nest @2 pz
(2)×x+((-1))×y^2+(2)×t^3+(-15)×t^2+(25)×t


> --    Notation used in the documentation of the manipulation functions
> --    ----------------------------------------------------------------
> --    P : natural number reflecting the arity of the polynomial
> --    P = 0 for the elements of the underlying structure
> --    P = 1 for univariate polynomials
> --    P = 2 for bivariate polynomials and more generally,
> --          multivariate polynomials are P-variate.


> -- 4) COEFFICIENT EXTRACTION :
> --    ----------------------
> --
> -- coefficient of zt², beware, orders ...
> let p = 10^0^0^1^2 + 20^1^2^0^0 + 42^2^1^0^0 in p ! 0 ! 0 ! 1 ! 2
42

Constructors

Instances

#monoPol Source

monoPol :: forall a. a -> Int -> Polynomial a

Monoterm polynomial

#(^) Source

Operator alias for Data.Sparse.Polynomial.monoPol (left-associative / precedence 8)

Monoterm polynomial infix notation

#NextAxis Source

class NextAxis :: Int -> Int -> Constraintclass NextAxis a n | a -> n, n -> a where

Members

Instances

#Pad Source

class Pad :: Int -> Type -> Type -> Constraintclass Pad n a b | n a -> b where
> --     ---------------------------------------------------
> --    | PAD : the lifting function that introduces        |
> --    | ---                                               |
> --    | in a polynomial as many new variables as 1 + the  |
> --    | provided size, shifting the content of each       |
> --    | of the initial variables as many orders nearer.   |
> --     ---------------------------------------------------
> --    | input : polynomial |
> --     ----------------------------------------------------
> --    |                            |    arity  |  arity    |
> --    |           usage            |    input  |  output   |
> --    |                            |           |           |
> --     ====================================================
> --    |         pad @size          |    P>=0   |  P+size+1 |
> --     ----------------------------------------------------

> pad @0 5
5

> pad @0 (5^0)
5

> pad @0 (5^1)
(5)×y

> pad @1 (5^0)
5

> pad @1 (5^1)
(5)×z

> pad @1 (5^1^1)
((5)×t)×z

Members

Instances

#pad Source

pad :: forall @n a b. Pad n a b => a -> b

#Unpad Source

class Unpad :: Int -> Type -> Type -> Constraintclass Unpad n a b | n b -> a where
> --     -----------------------------------------------------
> --    | UNPAD : the inverse of `pad` that decreases the     |
> --    | -----                                               |
> --    | arity of a polynomial of 1 + the                    |
> --    | provided size, shifting the content of each         |
> --    | of the initial variables to a more remote position. |
> --     -----------------------------------------------------
> --    | input : polynomial |
> --     ------------------------------------------------------
> --    |                            |    arity    |  arity    |
> --    |             usage          |    input    | output    |
> --    |                            |             |           |
> --     ======================================================
> --    |          unpad @size       | P >= 2+size | P-size-1  |
> --     ------------------------------------------------------

> unpad @0 (5^1^1 + 6^1^0)
(6)×x

> unpad @1 (5^1^1^0 + 6^1^0^0 + 7^0^0^0)
(6)×x+7

Members

Instances

#unpad Source

unpad :: forall @n a b. Unpad n a b => b -> a

#query Source

query :: forall a. Semiring a => Polynomial a -> Int -> a

Coefficient extraction

#(!) Source

Operator alias for Data.Sparse.Polynomial.query (left-associative / precedence 8)

Coefficient extraction infix notation

#pow Source

pow :: forall a. Semiring a => a -> Int -> a

Integer power

#evaluate Source

evaluate :: forall a. Semiring a => Polynomial a -> a -> a

Univariate polynomial evaluation

#(:.) Source

Operator alias for Data.Sparse.Polynomial.evaluate (left-associative / precedence 5)

Univariate polynomial evaluation infix notation

#Set Source

class Set :: Int -> Type -> Type -> Constraintclass Set n a b | n b -> a where
> --     ---------------------------------------------------------
> --    | SET : the evaluating function that removes the variable |
> --    | ---                                                     |
> --    | at focus in a polynomial by setting it to the provided  |
> --    | value, and shifts the content of each of the other      |      
> --    | nearer variables and associates it to the variable      |
> --    | one order more remote.                                  |
> --     ---------------------------------------------------------
> --    | input1 : value || input2 : polynomial |
> --     ---------------------------------------------------
> --    |    arity    |               |    arity   |  arity |
> --    |    input1   |     `usage`   |   input2   = output |
> --    |             |               |            |        |
> --     ===================================================
> --    | P-(focus+1) |  `set @focus` |   P>focus  =   P-1  |
> --     ----------------------------------------------------

> 1^0^0^1 + 2^1^3^0
(1)×x+((2)×z)×y^3

> (5^0^0) `set @0` (1^0^0^1 + 2^1^3^0)
((2)×y)×x^3+5

> (5^1^3) `set @0` (1^0^0^1 + 2^1^3^0)
((7)×y)×x^3

> (5^0) `set @1` (1^0^0^1 + 2^1^3^0) 
(1)×x+(250)×y

> (5) `set @2` (1^0^0^1 + 2^1^3^0) 
(1)×x+(10)×y^3

Members

Instances

#set Source

set :: forall @n a b. Set n a b => a -> Polynomial b -> b

#down Source

down :: forall f a c d. Functor f => Semiring a => (a -> c -> d) -> a -> f c -> f d

#xpose Source

xpose :: forall a. Semiring a => a -> Polynomial a -> a

#flipXpand Source

flipXpand :: forall a. Eq a => Semiring a => Polynomial a -> Polynomial a -> Polynomial a

Multivariate polynomial substitution

#(.-) Source

Operator alias for Data.Sparse.Polynomial.flipXpand (left-associative / precedence 5)

Multivariate polynomial substitution infix notation

#FillValid Source

class FillValid :: Int -> Type -> Constraintclass FillValid n a  where

Members

Instances

#deep Source

deep :: forall f a c d. Functor f => Semiring a => (a -> c -> d) -> Polynomial a -> f c -> f d

#xpand Source

xpand :: forall a. Eq a => Semiring a => Polynomial a -> Polynomial a -> Polynomial a

#_fill Source

_fill :: forall a v w. Eq a => Semiring a => NextAxis v w => GoSwap 0 w a => Proxy v -> Polynomial a -> Polynomial a -> Polynomial a
> --     ------------------------------------------------
> --    | FILL : the substitution function that replaces |
> --    | ----                                           |
> --    | each occurrence of the focus in a polynomial   |
> --    | by the provided value.                         |
> --     ------------------------------------------------
> --    | input1 : value || input2 : polynomial |
> --     -------------------------------------------------
> --    |    arity  |                |    arity  |  arity |
> --    |   input1  |     `usage`    |   input2  = output |
> --    |           |                |           |        |
> --     =================================================
> --    |      P    | `fill @focus`  |  P>focus  =    P   |
> --     -------------------------------------------------

> 1^0^0^1 + 2^1^3^0
(1)×x+((2)×z)×y^3

> 1^0^0^1 + 1^0^1^0
(1)×x+(1)×y

> (1^0^0^1 + 1^0^1^0) `fill @0` (1^0^0^1 + 2^1^3^0)
(1)×x+((2)×z)×y^3+(1)×y

> (1^0^0^1 + 1^0^1^0) `fill @1` (1^0^0^1 + 2^1^3^0)
((2)×z)×x^3+(((6)×z)×y)×x^2+(((6)×z)×y^2+1)×x+((2)×z)×y^3

> (1^0^0^1 + 1^0^1^0) `fill @2` (1^0^0^1 + 2^1^3^0) 
((2)×y^3+1)×x+(2)×y^4

#fill Source

fill :: forall a @v w. Eq a => Semiring a => NextAxis v w => GoSwap 0 w a => Polynomial a -> Polynomial a -> Polynomial a

#Full Source

class Full :: Int -> Type -> Constraintclass Full n a  where

Members

Instances

#full Source

full :: forall a n m. Full n a => Add n 1 m => Arity (Polynomial a) m => Array (Polynomial a) -> Polynomial a -> Polynomial a

Saturated version of fill where array values have to be provided in order of proximity : value at index i is set to axis of proximity <i>.

#sortedMonoms Source

sortedMonoms :: forall a. Polynomial a -> Array (Tuple Int a)

Dispatches the terms of a polynomial with respect to its first variable in list of tuples (degree, coefficient) and order it by decreasing degree

#monoms Source

monoms :: forall a. Polynomial a -> Array (Tuple Int a)

Terms of a polynomial with respect to its first variable in list of tuples (degree, coefficient)

#dominantMonom Source

dominantMonom :: forall a. Eq a => Semiring a => Polynomial a -> Tuple Int a

Leading term of a polynomial with respect to its first variable

#Leadable Source

class (Semiring a) <= Leadable a  where

Leading term of an expanded multivariate polynomial

Members

Instances

#Divisible Source

class Divisible a  where

Divisibility between two leaders

Members

Instances

#division Source

division :: forall a. Ring a => Eq a => Divisible a => Leadable a => Polynomial a -> Polynomial a -> { div :: Polynomial a, mod :: Polynomial a }

Euclidean division between two multivariate polynomials over an Euclidean ring

#degreeAccordingToFirstVariable Source

degreeAccordingToFirstVariable :: forall a. Eq a => Semiring a => Polynomial a -> Int

Degree

#gcds Source

gcds :: forall a. Ord a => Divisible a => Leadable a => EuclideanRing a => Primitivable a => Array (Polynomial a) -> Polynomial a

#gcd Source

gcd :: forall a. Ord a => Divisible a => CommutativeRing a => Leadable a => Primitivable a => Polynomial a -> Polynomial a -> Polynomial a

Greatest common divisor of 2 multvariate polynomials The final constant scaling factor is nothing but arbitrary For instance gcd (2xyz) (3yz) gives 2yz

#cont Source

cont :: forall a. Ord a => EuclideanRing a => Divisible a => Leadable a => Primitivable a => Polynomial (Polynomial a) -> Polynomial a

#bezout Source

bezout :: forall a. Eq a => Ord a => CommutativeRing a => Divisible a => Leadable a => Univariate (Polynomial a) => Polynomial a -> Polynomial a -> Maybe { u :: Polynomial a, v :: Polynomial a }

Find 2 univariate polynomials u and v such that u(x) p1(x) + v(x) p2(x) == g(x) where g = gcd (p1,p2)

#unity Source

unity :: forall a. Eq a => Semiring a => Polynomial a -> Polynomial a

Gets the right representation of unity in the context of the provided multivariate polynomial

#Univariate Source

class Univariate a  where

Members

Instances

#Arity Source

class Arity :: Type -> Int -> Constraintclass Arity a n | a -> n where

Members

Instances

#Peel Source

class Peel a b | a -> b where
> --     -------------------------------------------------
> --    | PEEL : the extracting function that returns     |
> --    | ----                                            |
> --    | the constant term (in the underlying structure) |
> --    | of a polynomial.                                |
> --     -------------------------------------------------
> --    | input : polynomial |
> --     ----------------------------------
> --    |            |    arity  |  arity  |
> --    |     usage  |    input  = output  |
> --    |            |           |         |
> --     ==================================
> --    |     peel   |    P>0    =   0     |
> --     ----------------------------------

> peel $ (1^1+3^0) * (1^1-3^0)
-9

> peel $ (4^2^2 - 12^1^1) / 2^1^1
-6

Members

Instances

#Axed Source

class Axed a r  where

Gets the right representation of each of the variables in the context of the provided multivariate unity

Members

Instances

#Nest Source

class Nest :: Int -> Type -> Constraintclass Nest n a  where
> --     -------------------------------------------------
> --    | NEST : the extension function that introduces a |
> --    | ----                                            |
> --    | new variable before the focus of a polynomial   |
> --    | and shifts each of the other nearer variables   |
> --    | (focus included) one order nearer.              |
> --     -------------------------------------------------
> --    | input : polynomial |
> --     ---------------------------------------
> --    |                |    arity    |  arity |
> --    |      usage     |    input    = output |
> --    |                |             |        |
> --     =======================================
> --    |   nest @focus  |  P >= focus =   P+1  |
> --     ---------------------------------------

> nest @0 $ 5^0
5

> nest @0 $ 8^0^1
(8)×y

> nest @0 $ 21^1^1
((21)×z)×y

> nest @1 $ 5^0^0
5

> nest @1 $ 8^0^0^1
(8)×x

> nest @1 $ 13^0^1^0
(13)×z

> nest @1 $ 34^1^1^1
(((34)×t)×z)×x

> nest @2 $ 5^0^0
5

> nest @2 $ 34^1^1^1
(((34)×t)×y)×x

Members

Instances

#nest Source

nest :: forall @n a. Nest n a => a -> Polynomial a

#xtend Source

xtend :: forall a. a -> Polynomial a

#SwapAdjacent Source

class SwapAdjacent :: Int -> Type -> Constraintclass SwapAdjacent n a  where
> --     --------------------------------------------
> --    | SWAP : the swapping function that permutes |
> --    | ----                                       |
> --    | two axes in a polynomial.                  |
> --     --------------------------------------------
> --    | input : polynomial |
> --     ----------------------------------------
> --    |                     |  arity  |  arity |
> --    |         usage       |  input  = output |
> --    |                     |         |        |
> --     ========================================
> --    |   swap @ax1 @ax2    |  P>=2   =     P  |
> --     ----------------------------------------

> f = 3^0^0^0^2 + 4^0^1^3^0 + 5^1^0^0^0
> f
(3)×x^2+((4)×z)×y^3+(5)×t
>
> swap @0 @1 f
((4)×z)×x^3+(3)×y^2+(5)×t

> swap @3 @1 f
(3)×x^2+(5)×y+((4)×t^3)×z

Members

Instances

#xchng Source

xchng :: forall a. Eq a => Semiring a => Polynomial (Polynomial a) -> Polynomial (Polynomial a)

#Swap Source

class Swap :: Int -> Int -> Type -> Constraintclass Swap m n a  where

Members

Instances

#swap Source

swap :: forall @m @n a. Swap m n a => Polynomial (Polynomial a) -> Polynomial (Polynomial a)

#SwapSort Source

class SwapSort :: Ordering -> Int -> Int -> Type -> Constraintclass SwapSort o m n a  where

Members

Instances

#SwapInOrder Source

class SwapInOrder :: Int -> Int -> Type -> Constraintclass SwapInOrder m n a  where

Members

Instances

#GoSwap Source

class GoSwap :: Int -> Int -> Type -> Constraintclass GoSwap from delta a  where

Members

Instances

#liftC Source

liftC :: Polynomial Number -> Polynomial (Cartesian Number)

Transforms a univariate polynomial with real arguments into a univariate polynomial with complex arguments

#roots Source

roots :: Polynomial Number -> Array (Cartesian Number)

Returns the n approximative roots of a univariate polynomial of degree n

#Display Source

class Display a  where

Displays a multivariate polynomial with respect to the provided list of names. Whatever the arity, the zero polynomial is displayed as the empty string.

Members

Instances

#derivative Source

derivative :: forall a. Eq a => Semiring a => (Int -> a) -> Polynomial a -> Polynomial a

#diff Source

diff :: forall a. Eq a => Ord a => Semiring a => EuclideanRing a => IntLiftable a => Polynomial a -> Polynomial a

Univariate polynomial differentiation

#interpolate Source

interpolate :: forall a. Eq a => Semiring a => EuclideanRing a => Array (a /\ a) -> Polynomial a

Polynomial such that the second element of each tuple is the image of the first element.

#isPrime Source

isPrime :: forall a. Ord a => Semiring a => EuclideanRing a => a -> Boolean

True if n is < 2 or prime

#nextPrime Source

nextPrime :: forall a. Ord a => Semiring a => EuclideanRing a => a -> a

Ad infinitum

#primeFactor Source

primeFactor :: forall a. Ord a => Eq a => EuclideanRing a => a -> Boolean /\ a

If n is prime, returns true /\ n, otherwise, false /\ d if d | n with d > 1

#primeFactorization Source

primeFactorization :: forall base exp. Ord base => Eq base => Semiring base => EuclideanRing base => Semiring exp => base -> Array (base /\ exp)

Factorizes a number > 1 in an array (divider /\ multiplicity)

#divisors Source

divisors :: forall a. Semiring a => EuclideanRing a => Eq a => Ord a => a -> Array a

All the divisors of a positive integer

#factor Source

factor :: forall a. Eq a => Ord a => EuclideanRing a => IntLiftable a => Divisible a => Leadable a => Polynomial (Ratio a) -> Array (Polynomial (Ratio a))

At least one non-constant polynomial factor if the univariate input, with rational coefficients, is not irreductible, empty array if it is.

#factorOnZ Source

factorOnZ :: forall a. Ord a => Ring a => EuclideanRing a => Divisible a => IntLiftable a => Leadable a => Polynomial a -> Array (Polynomial a)

At least one non-constant polynomial factor if the univariate input, with integer coefficients, is not irreductible, empty array if it is.

#eisenstein Source

eisenstein :: forall a. Eq a => Divisible a => Leadable a => CommutativeRing a => EuclideanRing a => Polynomial a -> a -> Boolean
Eisenstein criterium of irreductibility of f = anx^n + ... + a1x + a0:
                           _
Exists prime p,             |
p   not | an                | => f  irreductible over Q
p       | ai for i=0..n-1   | 
p^2 not | a0                |