From: Alberto Bertogli Date: Tue, 4 Oct 2005 04:32:59 +0000 (+0000) Subject: Agregar karatsuba() y pot_ko(). X-Git-Tag: Entrega_1~40 X-Git-Url: https://git.llucax.com/z.facultad/75.29/dale.git/commitdiff_plain/57edd8276b149ac99cc685e4691294bec413f0cb?ds=inline;hp=cbfd67d82e0913165b67283f702b00b781e7b3ae Agregar karatsuba() y pot_ko(). 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. --- diff --git a/src/number.h b/src/number.h index 2c2d281..3d64955 100644 --- a/src/number.h +++ b/src/number.h @@ -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; +}