source: comparacioncriptosistemas/reescrituraDeCodigo/polynomial.H

interfaz
Last change on this file was 7576857, checked in by Fundación CENDITEL <cenditel@…>, 8 years ago

Se mueven archivos de reescritura al directorio reescrituraDeCodigo

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*
2  Copyright (C) 2015
3  Alejandro Mujica (amujica en cenditel.gob.ve)
4  José Angel Contreras (jancontreras en cenditel.gob.ve)
5  Antonio Araujo (aaraujo en cenditel.gob.ve)
6  Pedro Buitrago (pbuitrago en cenditel.gob.ve)
7 
8  CENDITEL Fundación Centro Nacional de Desarrollo e Investigación en
9  Tecnologías Libres
10 
11  Este programa es software libre; Usted puede usarlo bajo los términos de la
12  licencia de software GPL versión 2.0 de la Free Software Foundation.
13 
14  Este programa se distribuye con la esperanza de que sea útil, pero SIN
15  NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o
16  ADECUACIÓN A UN PROPÓSITO PARTICULAR.
17  Consulte la licencia GPL para más detalles. Usted debe recibir una copia
18  de la GPL junto con este programa; si no, escriba a la Free Software
19  Foundation Inc. 51 Franklin Street,5 Piso, Boston, MA 02110-1301, USA.
20*/
21
22/*
23  Este archivo contiene la definición e implementación de una plantilla de clase
24  para representar polinomios.
25
26  Creado por:        Alejandro J. Mujica
27  Fecha de creación:
28*/
29
30
31# ifndef POLYNOMIAL_H
32# define POLYNOMIAL_H
33
34# include <stdexcept>
35# include <sstream>
36# include <vector>
37# include <limits>
38
39# include<iostream>
40
41/**
42 *  Plantilla para representar polinomios de una variable.
43 *
44 *  @tparam NumberT Tipo de dato para los coeficientes.
45 *
46 *  @author Alejandro Mujica     (amujica en cenditel punto gob punto ve).
47 *  @author José Angel Contreras (jancontreras en cenditel punto gob punto ve).
48 */
49template <typename NumberT = double>
50class Polynomial
51{
52public:
53  /// Tipo de conjunto para el polinomio.
54  using PolynomialType = std::vector<NumberT>;
55  /// Tipo de número para el grado.
56  using DegreeType = typename PolynomialType::size_type;
57  /// Tipo de número para los coeficientes.
58  using NumberType = typename PolynomialType::value_type;
59
60private:
61  DegreeType     deg;
62  PolynomialType pol;
63
64public:
65  /// Construcción de un polinomio dado un grado.
66  Polynomial(const DegreeType & _deg = DegreeType(0));
67
68  /// Construcción por medio de una lista de inicialización.
69  Polynomial(const std::initializer_list<NumberType> &);
70
71  /// Constructor copia
72  Polynomial(const Polynomial &);
73
74  /// Constructor de movimiento (move semantic)
75  Polynomial(Polynomial &&);
76
77  /// Retorna el grado del polinomio.
78  const DegreeType & degree() const
79  {
80    return deg;
81  }
82
83  /**
84   *  Retorna el coeficiente de la posición dada.
85   *
86   *  @param exp Grado del coeficiente deseado.
87   *  @return Coeficiente de la posición dada.
88   *  @throw overflow_error si el exponente es mayor que el grado del polinomio.
89   */
90  const NumberType & get_coefficient(const DegreeType & exp) const
91  {
92    if (exp > deg)
93      throw std::overflow_error("exp is greater than polynomial degree");
94
95    return pol.at(deg - exp);
96  }
97
98  /**
99   *  Asigna valor al coeficiente de la posición dada.
100   *
101   *  @param exp Grado del coeficiente deseado.
102   *  @param value Valor que se asignará al coeficiente.
103   *  @throw overflow_error si el exponente es mayor que el grado del polinomio.
104   */
105  void set_coefficient(const DegreeType & exp, const NumberType & value)
106  {
107    if (exp > deg)
108      throw std::overflow_error("exp is greater than polynomial degree");
109
110    pol.at(deg - exp) = value;
111  }
112
113  /// Determina si el polinomio es nulo.
114  bool is_null() const;
115
116  bool operator ! () const;
117
118  Polynomial operator + (const Polynomial &);
119
120  Polynomial & operator += (const Polynomial &);
121
122  Polynomial operator - (const Polynomial &);
123
124  Polynomial & operator -= (const Polynomial &);
125
126  Polynomial operator * (const Polynomial &);
127
128  Polynomial operator / (const Polynomial &);
129
130  Polynomial operator % (const Polynomial &);
131
132  Polynomial & operator = (const Polynomial &);
133
134  Polynomial & operator = (Polynomial &&);
135
136  bool operator == (const Polynomial &) const;
137
138  bool operator != (const Polynomial &) const;
139
140  /// Retorna una representación del polinomio en cadena.
141  std::string to_string(const char & var = 'x');
142};
143
144/**
145 *  Constructor que funge de paramétrico y por omisión al mismo tiempo.
146 *
147 *  @param _deg Grado del polinomio. Por omisión es 0.
148 */
149template <typename NumberT>
150Polynomial<NumberT>::Polynomial(const Polynomial::DegreeType & _deg)
151  : deg(_deg), pol(deg + DegreeType(1), NumberType(0))
152{
153  // Empty
154}
155
156/**
157 *  Construye un polinomio dada una lista de inicialización.
158 *
159 *  Para inicializar el polinomio se deben pasar los valores de los coeficientes
160 *  entre llaves y separados por coma (,). Debe escribirse el polinomio
161 *  completo.
162 *
163 *  Por ejemplo, si se quiere construir el polinomio
164 *  @f$p(x) = x^5 + 2x^4 + 3x^3 + 4x^2 + 5x + 6;@f$
165 *  la instanciación debe realizarse de la siguiente manera:
166 *  @code{.cpp}Polynomial<> p = { 1, 2, 3, 4, 5, 6 };@endcode
167 *
168 *  @param l Lista de inicialización del polinomio.
169 */
170template <typename NumberT>
171Polynomial<NumberT>::Polynomial(const std::initializer_list<NumberType> & l)
172  : deg(DegreeType(l.size()) - DegreeType(1)), pol(l)
173{
174  // Empty
175}
176
177template <typename NumberT>
178Polynomial<NumberT>::Polynomial(const Polynomial & p)
179  : deg(p.deg), pol(p.pol)
180{
181  // Empty
182}
183
184template <typename NumberT>
185Polynomial<NumberT>::Polynomial(Polynomial && p)
186  : deg(DegreeType(0)), pol(deg + DegreeType(1), NumberType(0))
187{
188  std::swap(deg, p.deg);
189  std::swap(pol, p.pol);
190}
191
192
193/**.
194 *  Un polinomio es nulo si todos sus coeficientes son cero.
195 *
196 *  @return <code>true</code> si el polinomio es nulo y <code>false</code> en
197 *          caso contrario.
198 */
199template <typename NumberT>
200bool Polynomial<NumberT>::is_null() const
201{
202  for (const NumberType & c : pol)
203    if (c != NumberType(0))
204      return false;
205  return true;
206}
207
208template <typename NumberT>
209bool Polynomial<NumberT>::operator ! () const
210{
211  return is_null();
212}
213
214template <typename NumberT>
215Polynomial<NumberT>
216Polynomial<NumberT>::operator + (const Polynomial & p)
217{
218  const DegreeType & min_degree = std::min(deg, p.deg);
219  const DegreeType & max_degree = std::max(deg, p.deg);
220
221  Polynomial ret(max_degree);
222
223  for (DegreeType i = DegreeType(0); i <= min_degree; ++i)
224    ret.set_coefficient(i, get_coefficient(i) + p.get_coefficient(i));
225
226  const Polynomial & max_degree_pol = deg > p.deg ? *this : p;
227
228  for (DegreeType i = min_degree + DegreeType(1); i <= max_degree; ++i)
229    ret.set_coefficient(i, max_degree_pol.get_coefficient(i));
230
231  return ret;
232}
233
234template <typename NumberT>
235Polynomial<NumberT> &
236Polynomial<NumberT>::operator += (const Polynomial & p)
237{
238  *this = *this + p;
239  return *this;
240}
241
242template <typename NumberT>
243Polynomial<NumberT>
244Polynomial<NumberT>::operator - (const Polynomial & p)
245{
246  const DegreeType & min_degree = std::min(deg, p.deg);
247  const DegreeType & max_degree = std::max(deg, p.deg);
248
249  Polynomial ret(max_degree);
250
251  for (DegreeType i = DegreeType(0); i <= min_degree; ++i)
252    ret.set_coefficient(i, get_coefficient(i) - p.get_coefficient(i));
253
254  Polynomial & max_degree_pol = deg > p.deg ? *this : p;
255
256  char sign = &max_degree_pol == this ? 1 : -1;
257
258  for (DegreeType i = min_degree + DegreeType(1); i <= max_degree; ++i)
259    ret.set_coefficient(i, sign * max_degree_pol.get_coefficient(i));
260
261  return ret;
262}
263
264template <typename NumberT>
265Polynomial<NumberT> &
266Polynomial<NumberT>::operator -= (const Polynomial & p)
267{
268  *this = *this - p;
269  return *this;
270}
271
272template <typename NumberT>
273Polynomial<NumberT>
274Polynomial<NumberT>::operator * (const Polynomial & p)
275{
276  Polynomial ret(deg + p.deg);
277
278  for (DegreeType i = DegreeType(0); i <= deg; ++i)
279    for (DegreeType j = DegreeType(0); j < p.deg; ++j)
280      ret.set_coefficient(i + j,
281        ret.get_coefficient(i + j) + get_coefficient(i) * p.get_coefficient(j));
282       
283
284  return ret;
285}
286
287template <typename NumberT>
288Polynomial<NumberT>
289Polynomial<NumberT>::operator / (const Polynomial & p)
290{
291  if (p.is_null())
292    throw std::logic_error("Polynomial devision by 0");
293
294  if (p.deg > deg)
295    return Polynomial();
296
297  Polynomial ret(deg - p.deg);
298
299  NumberType inv = NumberType(0);
300
301  if (p.deg > 0)
302    {
303      Polynomial tmp = *this;
304
305      DegreeType last = p.deg;
306
307      while (last > DegreeType(0) and p.get_coefficient(last) == NumberType(0))
308        --last;
309
310      inv = NumberType(1) / p.get_coefficient(last);
311
312      for (DegreeType i = tmp.deg; i >= p.deg; --i)
313        {
314          ret.set_coefficient(i - p.deg, tmp.get_coefficient(i) * inv);
315
316          for (DegreeType j = DegreeType(0); j <= p.deg; ++j) 
317            tmp.set_coefficient(i - j,
318              tmp.get_coefficient(i - j) - p.get_coefficient(p.deg - j) *
319              ret.get_coefficient(i - p.deg));
320        }
321
322      return ret;
323    }
324
325  DegreeType first = DegreeType(0);
326
327  while (first <= p.deg and p.get_coefficient(first) == NumberType(0))
328    ++first;
329
330  inv = NumberType(1) / p.get_coefficient(first);
331
332  for (NumberType & c : ret.pol)
333    c *= inv;
334
335  return ret;
336}
337
338template <typename NumberT>
339Polynomial<NumberT>
340Polynomial<NumberT>::operator % (const Polynomial & p)
341{
342  if (p.is_null()) 
343    throw std::logic_error("Polynomial denominator = 0");
344
345  if (p.deg == DegreeType(0))
346    return Polynomial();
347
348  Polynomial ret = *this;
349
350  DegreeType last = p.deg;
351
352    while (last > DegreeType(0) and p.get_coefficient(last) == NumberType(0))
353      --last;   
354
355  NumberType inv = NumberType(1) / p.get_coefficient(last);
356
357  for (DegreeType i = ret.deg; i >= p.deg; --i)
358    {
359      NumberType q = ret.get_coefficient(i) * inv;
360
361      for (DegreeType j = DegreeType(0); j <= p.deg; ++j) 
362        ret.set_coefficient(i - j, ret.get_coefficient(i - j) -
363          p.get_coefficient(p.deg - j) * q);
364    }
365
366  while (ret.deg > DegreeType(0) and ret.get_coefficient(ret.deg) == NumberType(0))
367    --ret.deg;
368
369  return ret;
370}
371
372template <typename NumberT>
373Polynomial<NumberT> &
374Polynomial<NumberT>::operator = (const Polynomial & p)
375{
376  if (&p == this)
377    return *this;
378
379  deg = p.deg;
380  pol = p.pol;
381
382  return *this;
383}
384
385template <typename NumberT>
386Polynomial<NumberT> &
387Polynomial<NumberT>::operator = (Polynomial && p)
388{
389  std::swap(deg, p.deg);
390  std::swap(pol, p.pol);
391
392  return *this;
393}
394
395template <typename NumberT>
396bool Polynomial<NumberT>::operator == (const Polynomial & p) const
397{
398  if (deg != p.deg)
399    return false;
400
401  for (DegreeType i = DegreeType(0); i <= deg; ++i)
402    if (pol.at(i) != p.pol.at(i))
403      return false;
404
405  return true;
406}
407
408template <typename NumberT>
409bool Polynomial<NumberT>::operator != (const Polynomial & p) const
410{
411  return not (*this == p);
412}
413
414template <typename NumberT>
415std::string Polynomial<NumberT>::to_string(const char & var)
416{
417  std::stringstream sstr;
418
419  if (deg > DegreeType(1))
420    for (DegreeType i = DegreeType(0); i < deg - DegreeType(1); ++i)
421      sstr << pol.at(i) << var << '^' << deg - i << " + ";
422
423  if (deg > DegreeType(0))
424    sstr << pol.at(deg - DegreeType(1)) << var << " + ";
425
426  sstr << pol.at(deg);
427
428  return sstr.str();
429}
430
431# endif // POLYNOMIAL_H
432
Note: See TracBrowser for help on using the repository browser.