]> git.llucax.com Git - z.facultad/75.29/dale.git/commitdiff
Agregar karatsuba() y pot_ko().
authorAlberto Bertogli <albertogli@telpin.com.ar>
Tue, 4 Oct 2005 04:32:59 +0000 (04:32 +0000)
committerAlberto Bertogli <albertogli@telpin.com.ar>
Tue, 4 Oct 2005 04:32:59 +0000 (04:32 +0000)
En este patch se reintroduce karatsuba() (todavia no probado porque falta la
resta, pero no deberia distar mucho de su implementacion final) y pot_ko(),
tampoco probada. Soy un loco barbaro.

src/number.h

index 2c2d281b1e7a1c8947ce3654c3e69b5d6415494a..3d64955b9cfbedf2d13e9e6d4531afe4829eeee4 100644 (file)
@@ -460,4 +460,70 @@ number < N, E > naif(const number< N, E > &u, const number< N, E > &v)
 }
 
 
 }
 
 
+/* Algoritmo de multiplicacion de Karatsuba-Ofman
+ * Ver los comentarios del algoritmo naif, es practicamente identico salvo en
+ * los calculos numericos que se especifican debajo.
+ */
+template < typename N, typename E >
+number < N, E > karatsuba(const number< N, E > &u, const number< N, E > &v)
+{
+       typedef number< N, E > num_type;
+
+       typename num_type::size_type chunk_size = u.chunk.size();
+
+       sign_type sign;
+
+       if ( (u.sign == positive && v.sign == positive) ||
+                       (u.sign == negative && v.sign == negative) ) {
+               sign = positive;
+       } else {
+               sign = negative;
+       }
+
+       if (chunk_size == 1) {
+               E tmp;
+               tmp = static_cast< E >(u.chunk[0]) * static_cast< E >(v.chunk[0]);
+               num_type tnum = num_type(static_cast< N* >(&tmp), 2, sign);
+               return tnum;
+       }
+
+       std::pair< num_type, num_type > u12 = u.split();
+       std::pair< num_type, num_type > v12 = v.split();
+
+       // Los nombres M, D y H los puso Rosita en clase, cambiar si se les
+       // ocurren algunos mejores!
+       // m = u1*v1
+       // d = u2*v2
+       // h = (u1+v1)*(u2+v2) = u1*u2+u1*v2+u2*v1+u2*v2
+       num_type m = karastuba(u12.second, v12.second);
+       num_type d = karastuba(u12.first, v12.first);
+       num_type h = karastuba(u12.second + v12.second,
+                       u12.first + v12.first);
+
+       // H-D-M = u1*u2+u1*v2+u2*v1+u2*v2 - u2*v2 - u1*v1 = u1*v2+u2*v1
+       // u1*v1 << base^N + u1*v2+u2*v1 << base^N/2 + u2*v2
+       num_type res;
+       res = (m << chunk_size) + ((h - d - m) << (chunk_size / 2) ) + h;
+       res.sign = sign;
+       return res;
+}
+
+
+/* Potenciacion usando multiplicaciones sucesivas.
+ * Toma dos parametros u y v, devuelve u^v; asume v positivo.
+ */
+template < typename N, typename E >
+number < N, E > pot_ko(const number< N, E > &u, const number< N, E > &v)
+{
+       number< N, E > res, i;
+
+       res = u;
+       res.sign = u.sign;
+
+       for (i = 1; i < v; i++) {
+               res *= u;
+       }
+
+       return res;
+}