-- |
-- Module      : PolOperaciones
-- Description : Operaciones con el TAD de los polinomios.
-- License     : Creative Commons
-- Maintainer  : José A. Alonso
-- 
-- En este módulo se definen operaciones con el TAD (tipo abstracto de
-- datos) de los polinomios estudiado en el 
-- <http://bit.ly/1WYZJuC tema 21> del curso. 
-- 
-- En los ejemplos se usarán los siguientes polinomios:
--
-- > ejPol1, ejPol2, ejPol3, ejTerm:: Polinomio Int
-- > ejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))
-- > ejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))
-- > ejPol3 = consPol 4 6 (consPol 1 2 polCero)
-- > ejTerm = consPol 1 4 polCero

module I1M.PolOperaciones
  ( module I1M.Pol
  -- * Funciones sobre términos
  , creaTermino
  , termLider
  -- * Suma de polinomios
  , sumaPol
  -- * Producto de polinomios
  , multPorTerm 
  , multPol 
  , polUnidad
  -- * Valor de un polinomio en un punto
  , valor
  -- * Verificación de raices de polinomios
  , esRaiz
  -- * Derivación de polinomios
  , derivada 
  -- * Resta de polinomios
  , restaPol
  ) where

-- ---------------------------------------------------------------------
-- Importación de librerías                                           --
-- ---------------------------------------------------------------------

import I1M.Pol

-- ---------------------------------------------------------------------
-- Ejemplos                                                           --
-- ---------------------------------------------------------------------

-- Ejemplos de polinomios con coeficientes enteros:
-- ejPol1, ejPol2, ejPol3, ejTerm:: Polinomio Int
-- ejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))
-- ejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))
-- ejPol3 = consPol 4 6 (consPol 1 2 polCero)
-- ejTerm = consPol 1 4 polCero

-- ---------------------------------------------------------------------
-- Funciones sobre términos
-- ---------------------------------------------------------------------

-- | (creaTermino n a) es el término a*x^n. Por ejemplo, 
-- 
-- > creaTermino 2 5  ==  5*x^2
creaTermino :: (Num t, Eq t) => Int -> t -> Polinomio t
creaTermino :: Int -> t -> Polinomio t
creaTermino Int
n t
a = Int -> t -> Polinomio t -> Polinomio t
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol Int
n t
a Polinomio t
forall a. Polinomio a
polCero

-- | (termLider p) es el término líder del polinomio p. Por ejemplo,
-- 
-- > ejPol2            ==  x^5 + 5*x^2 + 4*x
-- > termLider ejPol2  ==  x^5
termLider :: (Num t, Eq t) => Polinomio t -> Polinomio t
termLider :: Polinomio t -> Polinomio t
termLider Polinomio t
p = Int -> t -> Polinomio t
forall t. (Num t, Eq t) => Int -> t -> Polinomio t
creaTermino (Polinomio t -> Int
forall a. Polinomio a -> Int
grado Polinomio t
p) (Polinomio t -> t
forall t. Num t => Polinomio t -> t
coefLider Polinomio t
p)

-- ---------------------------------------------------------------------
-- Suma de polinomios                                                 --
-- ---------------------------------------------------------------------

-- | (sumaPol p q) es la suma de los polinomios p y q. Por ejemplo, 
-- 
-- > ejPol1                 ==  3*x^4 + -5*x^2 + 3
-- > ejPol2                 ==  x^5 + 5*x^2 + 4*x
-- > sumaPol ejPol1 ejPol2  ==  x^5 + 3*x^4 + 4*x + 3
sumaPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a
sumaPol :: Polinomio a -> Polinomio a -> Polinomio a
sumaPol Polinomio a
p Polinomio a
q 
  | Polinomio a -> Bool
forall a. Polinomio a -> Bool
esPolCero Polinomio a
p = Polinomio a
q
  | Polinomio a -> Bool
forall a. Polinomio a -> Bool
esPolCero Polinomio a
q = Polinomio a
p
  | Int
n1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n2      = Int -> a -> Polinomio a -> Polinomio a
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol Int
n1 a
a1 (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
sumaPol Polinomio a
r1 Polinomio a
q)
  | Int
n1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n2      = Int -> a -> Polinomio a -> Polinomio a
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol Int
n2 a
a2 (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
sumaPol Polinomio a
p Polinomio a
r2)
  | Bool
otherwise    = Int -> a -> Polinomio a -> Polinomio a
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol Int
n1 (a
a1a -> a -> a
forall a. Num a => a -> a -> a
+a
a2) (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
sumaPol Polinomio a
r1 Polinomio a
r2)
  where n1 :: Int
n1 = Polinomio a -> Int
forall a. Polinomio a -> Int
grado Polinomio a
p
        a1 :: a
a1 = Polinomio a -> a
forall t. Num t => Polinomio t -> t
coefLider Polinomio a
p
        r1 :: Polinomio a
r1 = Polinomio a -> Polinomio a
forall t. Polinomio t -> Polinomio t
restoPol Polinomio a
p
        n2 :: Int
n2 = Polinomio a -> Int
forall a. Polinomio a -> Int
grado Polinomio a
q
        a2 :: a
a2 = Polinomio a -> a
forall t. Num t => Polinomio t -> t
coefLider Polinomio a
q
        r2 :: Polinomio a
r2 = Polinomio a -> Polinomio a
forall t. Polinomio t -> Polinomio t
restoPol Polinomio a
q

-- ---------------------------------------------------------------------
-- Producto de polinomios                                             --
-- ---------------------------------------------------------------------

-- | (multPorTerm t p) es el producto del término t por el polinomio
-- p. Por ejemplo,
-- 
-- > ejTerm                     ==  4*x
-- > ejPol2                     ==  x^5 + 5*x^2 + 4*x
-- > multPorTerm ejTerm ejPol2  ==  4*x^6 + 20*x^3 + 16*x^2
multPorTerm :: (Num t, Eq t) => Polinomio t -> Polinomio t -> Polinomio t
multPorTerm :: Polinomio t -> Polinomio t -> Polinomio t
multPorTerm Polinomio t
term Polinomio t
pol 
  | Polinomio t -> Bool
forall a. Polinomio a -> Bool
esPolCero Polinomio t
pol = Polinomio t
forall a. Polinomio a
polCero
  | Bool
otherwise     = Int -> t -> Polinomio t -> Polinomio t
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
m) (t
at -> t -> t
forall a. Num a => a -> a -> a
*t
b) (Polinomio t -> Polinomio t -> Polinomio t
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
multPorTerm Polinomio t
term Polinomio t
r)
  where n :: Int
n = Polinomio t -> Int
forall a. Polinomio a -> Int
grado Polinomio t
term
        a :: t
a = Polinomio t -> t
forall t. Num t => Polinomio t -> t
coefLider Polinomio t
term
        m :: Int
m = Polinomio t -> Int
forall a. Polinomio a -> Int
grado Polinomio t
pol
        b :: t
b = Polinomio t -> t
forall t. Num t => Polinomio t -> t
coefLider Polinomio t
pol
        r :: Polinomio t
r = Polinomio t -> Polinomio t
forall t. Polinomio t -> Polinomio t
restoPol Polinomio t
pol    

-- | (multPol p q) es el producto de los polinomios p y q. Por
-- ejemplo,
-- 
-- > ghci> ejPol1
-- > 3*x^4 + -5*x^2 + 3
-- > ghci> ejPol2
-- > x^5 + 5*x^2 + 4*x
-- > ghci> multPol ejPol1 ejPol2
-- > 3*x^9 + -5*x^7 + 15*x^6 + 15*x^5 + -25*x^4 + -20*x^3 + 15*x^2 + 12*x
multPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a
multPol :: Polinomio a -> Polinomio a -> Polinomio a
multPol Polinomio a
p Polinomio a
q
  | Polinomio a -> Bool
forall a. Polinomio a -> Bool
esPolCero Polinomio a
p = Polinomio a
forall a. Polinomio a
polCero
  | Bool
otherwise    = Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
sumaPol (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
multPorTerm (Polinomio a -> Polinomio a
forall t. (Num t, Eq t) => Polinomio t -> Polinomio t
termLider Polinomio a
p) Polinomio a
q)
                           (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
multPol (Polinomio a -> Polinomio a
forall t. Polinomio t -> Polinomio t
restoPol Polinomio a
p) Polinomio a
q)

-- | polUnidad es el polinomio unidad. Por ejemplo, 
-- 
-- > ghci> polUnidad
-- > 1
polUnidad:: (Num t, Eq t) => Polinomio t
polUnidad :: Polinomio t
polUnidad = Int -> t -> Polinomio t -> Polinomio t
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol Int
0 t
1 Polinomio t
forall a. Polinomio a
polCero

-- ---------------------------------------------------------------------
-- Valor de un polinomio en un punto                                  --
-- ---------------------------------------------------------------------

-- | (valor p c) es el valor del polinomio p al sustituir su variable por
-- c. Por ejemplo, 
-- 
-- > ejPol1             ==  3*x^4 + -5*x^2 + 3
-- > valor ejPol1 0     ==  3
-- > valor ejPol1 1     ==  1
-- > valor ejPol1 (-2)  ==  31
valor :: (Num a, Eq a) => Polinomio a -> a -> a
valor :: Polinomio a -> a -> a
valor Polinomio a
p a
c 
  | Polinomio a -> Bool
forall a. Polinomio a -> Bool
esPolCero Polinomio a
p = a
0
  | Bool
otherwise   =  a
ba -> a -> a
forall a. Num a => a -> a -> a
*a
ca -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Int
n a -> a -> a
forall a. Num a => a -> a -> a
+ Polinomio a -> a -> a
forall a. (Num a, Eq a) => Polinomio a -> a -> a
valor Polinomio a
r a
c
  where n :: Int
n = Polinomio a -> Int
forall a. Polinomio a -> Int
grado Polinomio a
p
        b :: a
b = Polinomio a -> a
forall t. Num t => Polinomio t -> t
coefLider Polinomio a
p
        r :: Polinomio a
r = Polinomio a -> Polinomio a
forall t. Polinomio t -> Polinomio t
restoPol Polinomio a
p

-- ---------------------------------------------------------------------
-- Verificación de raices de polinomios                               --
-- ---------------------------------------------------------------------

-- | (esRaiz c p) se verifica si c es una raiz del polinomio p. Por
-- ejemplo, 
-- 
-- > ejPol3           ==  6*x^4 + 2*x
-- > esRaiz 1 ejPol3  ==  False
-- > esRaiz 0 ejPol3  ==  True
esRaiz :: (Num a, Eq a) => a -> Polinomio a -> Bool
esRaiz :: a -> Polinomio a -> Bool
esRaiz a
c Polinomio a
p = Polinomio a -> a -> a
forall a. (Num a, Eq a) => Polinomio a -> a -> a
valor Polinomio a
p a
c a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0

-- ---------------------------------------------------------------------
-- Derivación de polinomios                                           --
-- ---------------------------------------------------------------------

-- | (derivada p) es la derivada del polinomio p. Por ejemplo, 
-- 
-- > ejPol2           ==  x^5 + 5*x^2 + 4*x
-- > derivada ejPol2  ==  5*x^4 + 10*x + 4
derivada :: (Eq a, Num a) => Polinomio a -> Polinomio a
derivada :: Polinomio a -> Polinomio a
derivada Polinomio a
p 
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0     = Polinomio a
forall a. Polinomio a
polCero
  | Bool
otherwise  = Int -> a -> Polinomio a -> Polinomio a
forall a. (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a
consPol (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (a
b a -> a -> a
forall a. Num a => a -> a -> a
* Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) (Polinomio a -> Polinomio a
forall a. (Eq a, Num a) => Polinomio a -> Polinomio a
derivada Polinomio a
r)
  where n :: Int
n = Polinomio a -> Int
forall a. Polinomio a -> Int
grado Polinomio a
p
        b :: a
b = Polinomio a -> a
forall t. Num t => Polinomio t -> t
coefLider Polinomio a
p
        r :: Polinomio a
r = Polinomio a -> Polinomio a
forall t. Polinomio t -> Polinomio t
restoPol Polinomio a
p

-- ---------------------------------------------------------------------
-- Resta de polinomios                                                --
-- ---------------------------------------------------------------------

-- | (resta p q) es el polinomio obtenido restándole a p el q. Por
-- ejemplo, 
-- 
-- > ejPol1                  ==  3*x^4 + -5*x^2 + 3
-- > ejPol2                  ==  x^5 + 5*x^2 + 4*x
-- > restaPol ejPol1 ejPol2  ==  -1*x^5 + 3*x^4 + -10*x^2 + -4*x + 3
restaPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a
restaPol :: Polinomio a -> Polinomio a -> Polinomio a
restaPol Polinomio a
p Polinomio a
q  = 
  Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
sumaPol Polinomio a
p (Polinomio a -> Polinomio a -> Polinomio a
forall a.
(Num a, Eq a) =>
Polinomio a -> Polinomio a -> Polinomio a
multPorTerm (Int -> a -> Polinomio a
forall t. (Num t, Eq t) => Int -> t -> Polinomio t
creaTermino Int
0 (-a
1)) Polinomio a
q)