+#include <vector>
+#include <algorithm>
+#include <iterator>
+
+//XXX Pensado para andar con unsigned's (si anda con otra cosa es casualidad =)
+
+template < typename T >
+struct number
+{
+
+ // Tipos
+ typedef T atomic_type;
+ typedef typename std::vector< T > chunk_type;
+ typedef typename chunk_type::size_type size_type;
+ typedef typename chunk_type::iterator iterator;
+ typedef typename chunk_type::const_iterator const_iterator;
+
+ // Constructores
+ number(): chunk(1, 0) {}
+ number(atomic_type* buf, size_type len): chunk(buf, buf + len)
+ { fix_empty(); }
+ number(atomic_type* buf)
+ { while (*buf) chunk.push_back(*(buf++)); fix_empty(); }
+ number(atomic_type n): chunk(1, n) {}
+ // TODO constructor a partir de string.
+
+ // Operadores
+ number& operator++ () { if (!++chunk[0]) carry(1); return *this; }
+ number& operator+= (const number& n)
+ {
+ atomic_type c = 0;
+ size_type ini = 0;
+ size_type fin = std::min(chunk.size(), n.chunk.size());
+ for (size_type i = ini; i < fin; ++i)
+ {
+ chunk[i] += n.chunk[i] + c;
+ if (chunk[i] || (!n.chunk[i] && !c)) c = 0; // OK
+ else c = 1; // Overflow
+ }
+ if (chunk.size() >= n.chunk.size()) // No hay más
+ {
+ if (c) carry(fin); // Propago carry
+ return *this;
+ }
+ // Hay más
+ ini = fin;
+ fin = n.chunk.size();
+ for (size_type i = ini; i < fin; ++i)
+ {
+ chunk.push_back(n.chunk[i] + c); // Agrego nuevo átomo
+ if (chunk[i] || !c) c = 0; // OK
+ else c = 1; // Overflow
+ }
+ if (c) chunk.push_back(1); // Último carry
+ return *this;
+ }
+ atomic_type& operator[] (size_type i) { return chunk[i]; }
+
+ // Iteradores
+ iterator begin() { return chunk.begin(); }
+ iterator end() { return chunk.end(); }
+ const_iterator begin() const { return chunk.begin(); }
+ const_iterator end() const { return chunk.end(); }
+
+ private:
+ // Atributos
+ chunk_type chunk;
+
+ // Helpers
+ void fix_empty() { if (!chunk.size()) chunk.push_back(0); }
+ void carry(size_type i)
+ {
+ if (chunk.size() > i)
+ {
+ ++chunk[i];
+ if (!chunk[i]) carry(i+1); // Overflow
+ }
+ else chunk.push_back(1);
+ }
+};
+
+template < typename T >
+number< T > operator+ (const number< T >& n1, const number< T >& n2)
+{
+ number< T > tmp = n1;
+ tmp += n2;
+ return tmp;
+}
+
+template < typename T >
+std::ostream& operator<< (std::ostream& os, const number< T >& n)
+{
+ // FIXME sacar una salida bonita en ASCII =)
+ std::copy(n.begin(), n.end(), std::ostream_iterator< T >(os, " "));
+ return os;
+}
+