xc
vectorZ.h
1 // -*-c++-*-
2 //----------------------------------------------------------------------------
3 // xc utils library; general purpose classes and functions.
4 //
5 // Copyright (C) Luis C. Pérez Tato
6 //
7 // XC utils is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // This software is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program.
19 // If not, see <http://www.gnu.org/licenses/>.
20 //----------------------------------------------------------------------------
21 //vectorZ.h
22 /*
23 Template para vectores cuyos elementos forman estructura de anillo
24 con las operaciones de composicion interna suma y producto.
25 */
26 
27 #ifndef VECTORZ_H
28 #define VECTORZ_H
29 
30 #include <iostream>
31 #include <cassert>
32 #include <vector>
33 #include <algorithm>
34 #include <numeric>
35 #include <list>
36 #include <cstring>
37 
38 template <class numero>
39 class vectorZ : public std::vector<numero>
40  {
41  protected:
42  typedef std::vector<numero> vector_numero;
44 
45  public:
46  //typedef vector_allocator vectorZ_allocator;
47  typedef typename std::vector<numero>::size_type size_type;
48  typedef std::list<numero> lst_numero;
49 
50  vectorZ(void) : vector_numero() {}
51  vectorZ(size_type n,const numero &value = numero()) : vector_numero(n,value) {}
52  vectorZ(const lst_numero &ln);
53  vectorZ(const vectorZ<numero> &otro) : vector_numero(otro) {}
54  vectorZ(const size_t &sz,const numero arr[]) : vector_numero(arr,arr+sz){}
55  template <class InputIterator>
56  vectorZ(InputIterator b,InputIterator e);
57  vectorZ<numero> &operator=(const vectorZ<numero> &otro)
58  {
59  vector_numero::operator=(otro);
60  return *this;
61  }
62  vectorZ<numero> &operator+=(const vectorZ<numero> &otro)
63  {
64  Suma(otro);
65  return *this;
66  }
67  vectorZ<numero> &operator-=(const vectorZ<numero> &otro)
68  {
69  Resta(otro);
70  return *this;
71  }
72  vectorZ<numero> &operator*=(const numero &n)
73  {
74  Prod(n);
75  return *this;
76  }
77  void Suma(const vectorZ<numero> &v);
78  void Resta(const vectorZ<numero> &v);
79  void Suma(const vectorZ<numero> &v1,const vectorZ<numero> &v2)
80  {
81  vectorZ::operator =(v1);
82  Suma(v2);
83  }
84  void Resta(const vectorZ<numero> &v1,const vectorZ<numero> &v2)
85  {
86  vectorZ::operator=(v1);
87  Resta(v2);
88  }
89  void Prod(const numero &n);
90  void PutSuma(size_type i,const numero &n)
91  { (*this)[i]+= n; }
92  void PutResta(size_type i,const numero &n)
93  { (*this)[i]-= n; }
94  void PutProd(size_type i,const numero &n)
95  { (*this)[i]*= n; }
96  void swap(size_type n1,size_type n2)
97  { std::swap((*this)[n1],(*this)[n2]); }
98  long Busca(const numero &n) const;
99  void Neg(void);
100  bool Nulos(const numero &tol= numero());
101  void Con(size_type n1,size_type n2,const numero &n)
102  {
103  fill(&(vector_numero::operator [](n1)),&(vector_numero::operator [](n2)),n);
104  vector_numero::operator [](n2)= n;
105  }
106  void Con(size_type n1,const numero &n)
107  { fill(&(vector_numero::operator [](n1)),this->end(),n); }
108  void Con(const numero &n)
109  { fill(this->begin(),this->end(),n); }
110  numero Sumatorio( size_type i, size_type j) const
111  //devuelve la suma de los elementos [i,j)
112  { return accumulate(this->begin()+ i,this->begin() + j,numero()); }
113  numero Productorio(size_type i, size_type j) const
114  //devuelve el producto de los elementos [i,j)
115  { return accumulate(this->begin()+ i+1,this->begin() + j,*(this->begin()+i),std::multiplies<numero>()); }
116  vectorZ<numero> Left(size_t j) const;
117  vectorZ<numero> Right(size_t j) const;
118  vectorZ<numero> Mid(size_t i,size_t j) const;
119  vectorZ<numero> GetMenor(size_t j) const;
120  vectorZ<numero> Sustituye(size_t j,const vectorZ<numero> &v) const;
121  unsigned long Distintos(const vectorZ<numero> &v) const;
122  friend vectorZ<numero> operator+( const vectorZ<numero> &v1,
123  const vectorZ<numero> &v2)
124  {
125  typename vectorZ<numero>::size_type mx= std::max(v1.size(),v2.size());
126  vectorZ<numero> suma(mx);
127  suma.Suma(v1,v2);
128  return suma;
129  }
130  friend vectorZ<numero> operator-( const vectorZ<numero> &v1,
131  const vectorZ<numero> &v2)
132  {
133  typename vectorZ<numero>::size_type mx= std::max(v1.size(),v2.size());
134  vectorZ<numero> resta(mx);
135  resta.Resta(v1,v2);
136  return resta;
137  }
138  friend vectorZ<numero> operator*( const numero &d,
139  const vectorZ<numero> &m)
140  { return m*d; }
141  friend vectorZ<numero> operator*( const vectorZ<numero> &m,
142  const numero &d)
143  {
144  vectorZ<numero> producto(m);
145  producto.Prod(d);
146  return producto;
147  }
148  friend bool operator ==(const vectorZ<numero> &x,const vectorZ<numero> &y)
149  { return ((const vector_numero &) x == (const vector_numero &) y); }
150  };
151 
153 template <class numero> template<class InputIterator>
154 vectorZ<numero>::vectorZ(InputIterator b,InputIterator e)
155  : vector_numero(b,e) {}
156 
157 template <class numero>
158 vectorZ<numero>::vectorZ(const lst_numero &ln) : vector_numero(ln.size())
159  {
160  size_type j= 0;
161  typedef typename lst_numero::const_iterator c_iterator;
162  for(c_iterator i=ln.begin();i!=ln.end();i++)
163  { (*this)[j]= *i; j++; }
164  }
165 
166 template <class numero>
167 vectorZ<numero> operator -(const vectorZ<numero> &m)
168  {
169  vectorZ<numero> neg(m);
170  neg.Neg();
171  return neg;
172  }
173 
174 template <class numero>
175 long vectorZ<numero>::Busca(const numero &n) const
176  {
177  size_type sz= this->size();
178  for(size_type i=0;i<sz;i++)
179  if ((*this)[i] == n) return i;
180  return -1;
181  }
182 
183 template <class numero>
184 void vectorZ<numero>::Neg(void)
185  {
186  size_type sz= this->size();
187  for(size_type i= 0;i<sz;i++)
188  (*this)[i] = -(*this)[i];
189  }
190 template <class numero>
191 bool vectorZ<numero>::Nulos(const numero &tol)
192  {
193  size_type sz= this->size();
194  for(size_type i= 0;i<sz;i++)
195  if(Abs((*this)[i])>tol) return false;
196  return true;
197  }
198 
199 template <class numero>
201  {
202  size_type sz= v.size();
203  for(size_type i=0;i<sz;i++) PutSuma(i,v[i]);
204  }
205 
206 template <class numero>
208  {
209  size_type sz= v.size();
210  for(size_type i=0;i<sz;i++) PutResta(i,v[i]);
211  }
212 
213 template <class numero>
214 void vectorZ<numero>::Prod(const numero &n)
215  {
216  size_type sz= this->size();
217  for(size_type i= 0;i<sz;i++)
218  PutProd(i,n);
219  }
220 
221 template <class numero>
223 //Devuelve un vector con los elementos a la izquierda de j.
224  {
225  assert(j>0);
226  vectorZ<numero> left(j);
227  for(size_t i=0;i<j;i++) left[i]= (*this)[i];
228  return left;
229  }
230 
231 template <class numero>
233 //Devuelve un vector con los elementos a la derecha de j.
234  {
235  size_type sz= this->size();
236  assert(j<sz);
237  size_type szr= sz-j-1;
238  vectorZ<numero> right(szr);
239  for(size_type i=0;i<szr;i++) right[i]= (*this)[i+j+1];
240  return right;
241  }
242 
243 template <class numero>
244 vectorZ<numero> vectorZ<numero>::Mid(size_t i,size_t j) const
245 //Devuelve un vector con los elementos entre i y j.
246  {
247  assert(j>i);
248  size_type sz= j-i-1;
249  vectorZ<numero> mid(sz);
250  for(size_type k=0;k<sz;k++) mid[k]= (*this)[k+i+1];
251  return mid;
252  }
253 
254 template <class numero>
256  {
257  if (j == 0) return Right(j);
258  if (j == (this->size() - 1)) return Left(j);
259  return Cat(Left(j),Right(j));
260  }
261 
262 template <class numero>
264  {
265  vectorZ<numero> s;
266  if (j>0)
267  s= Cat(Left(j),v);
268  else
269  s= v;
270  if (j<this->size()) s= Cat(s,Right(j));
271  return s;
272  }
273 
274 template <class numero>
275 unsigned long vectorZ<numero>::Distintos(const vectorZ<numero> &v) const
276 //Cuenta el número de elementos distintos entre los dos vectores
277  {
278  unsigned long c= this->size(),sz=v.size();
279  for(unsigned long i=0;i<sz;i++)
280  if (Busca(v[i]) < 0) c++;
281  return c;
282  }
283 
284 template <class numero>
285 std::ostream &operator << (std::ostream &os,const vectorZ<numero> &n)
286  {
287  os << '[';
288  typedef typename vectorZ<numero>::size_type sz_type;
289  sz_type sz= n.size();
290  if(sz>0) os << n[0];
291  for(sz_type i= 1;i<sz;i++) os << ',' << n[i];
292  os << ']';
293  return os;
294  }
295 
296 template <class numero>
297 std::istream &operator >> (std::istream &is, vectorZ<numero> &n)
298  {
299  char c;
300  typename vectorZ<numero>::lst_numero ln;
301  numero ni;
302  is >> c;
303  if(c != '[') is.putback(c);
304  while(!is.eof())
305  {
306  is >> ni >> c;
307  ln.push_back(ni);
308  if(c == ']')
309  {
310  n= vectorZ<numero>(ln);
311  return is;
312  }
313  }
314  n= vectorZ<numero>(ln);
315  return is;
316  }
317 
318 template <class numero>
319 vectorZ<numero> Cat(const vectorZ<numero> &v1,const vectorZ<numero> &v2)
320  {
321  size_t sz1= v1.size(), sz2= v2.size();
322  size_t szc= sz1 + sz2;
323  vectorZ<numero> cat(szc);
324  typedef typename vectorZ<numero>::size_type sz_type;
325  for(sz_type i=0;i<sz1;i++)
326  cat[i]= v1[i];
327  for(sz_type i=0;i<sz2;i++)
328  cat[i+sz1]= v2[i];
329  return cat;
330  }
331 
332 #endif
Definition: vectorZ.h:39