xref: /plan9/sys/src/libmp/port/mpeuclid.c (revision 39734e7ed1eb944f5e7b41936007d0d38b560d7f)
17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier 
49a747e4fSDavid du Colombier // extended euclid
59a747e4fSDavid du Colombier //
69a747e4fSDavid du Colombier // For a and b it solves, d = gcd(a,b) and finds x and y s.t.
77dd7cddfSDavid du Colombier // ax + by = d
89a747e4fSDavid du Colombier //
99a747e4fSDavid du Colombier // Handbook of Applied Cryptography, Menezes et al, 1997, pg 67
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier void
mpeuclid(mpint * a,mpint * b,mpint * d,mpint * x,mpint * y)127dd7cddfSDavid du Colombier mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier 	mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r;
157dd7cddfSDavid du Colombier 
16*39734e7eSDavid du Colombier 	if(a->sign<0 || b->sign<0)
17*39734e7eSDavid du Colombier 		sysfatal("mpeuclid: negative arg");
18*39734e7eSDavid du Colombier 
197dd7cddfSDavid du Colombier 	if(mpcmp(a, b) < 0){
207dd7cddfSDavid du Colombier 		tmp = a;
217dd7cddfSDavid du Colombier 		a = b;
227dd7cddfSDavid du Colombier 		b = tmp;
237dd7cddfSDavid du Colombier 		tmp = x;
247dd7cddfSDavid du Colombier 		x = y;
257dd7cddfSDavid du Colombier 		y = tmp;
267dd7cddfSDavid du Colombier 	}
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier 	if(b->top == 0){
297dd7cddfSDavid du Colombier 		mpassign(a, d);
307dd7cddfSDavid du Colombier 		mpassign(mpone, x);
317dd7cddfSDavid du Colombier 		mpassign(mpzero, y);
327dd7cddfSDavid du Colombier 		return;
337dd7cddfSDavid du Colombier 	}
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier 	a = mpcopy(a);
367dd7cddfSDavid du Colombier 	b = mpcopy(b);
377dd7cddfSDavid du Colombier 	x0 = mpnew(0);
387dd7cddfSDavid du Colombier 	x1 = mpcopy(mpzero);
397dd7cddfSDavid du Colombier 	x2 = mpcopy(mpone);
407dd7cddfSDavid du Colombier 	y0 = mpnew(0);
417dd7cddfSDavid du Colombier 	y1 = mpcopy(mpone);
427dd7cddfSDavid du Colombier 	y2 = mpcopy(mpzero);
437dd7cddfSDavid du Colombier 	q = mpnew(0);
447dd7cddfSDavid du Colombier 	r = mpnew(0);
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier 	while(b->top != 0 && b->sign > 0){
477dd7cddfSDavid du Colombier 		// q = a/b
487dd7cddfSDavid du Colombier 		// r = a mod b
497dd7cddfSDavid du Colombier 		mpdiv(a, b, q, r);
507dd7cddfSDavid du Colombier 		// x0 = x2 - qx1
517dd7cddfSDavid du Colombier 		mpmul(q, x1, x0);
527dd7cddfSDavid du Colombier 		mpsub(x2, x0, x0);
537dd7cddfSDavid du Colombier 		// y0 = y2 - qy1
547dd7cddfSDavid du Colombier 		mpmul(q, y1, y0);
557dd7cddfSDavid du Colombier 		mpsub(y2, y0, y0);
567dd7cddfSDavid du Colombier 		// rotate values
577dd7cddfSDavid du Colombier 		tmp = a;
587dd7cddfSDavid du Colombier 		a = b;
597dd7cddfSDavid du Colombier 		b = r;
607dd7cddfSDavid du Colombier 		r = tmp;
617dd7cddfSDavid du Colombier 		tmp = x2;
627dd7cddfSDavid du Colombier 		x2 = x1;
637dd7cddfSDavid du Colombier 		x1 = x0;
647dd7cddfSDavid du Colombier 		x0 = tmp;
657dd7cddfSDavid du Colombier 		tmp = y2;
667dd7cddfSDavid du Colombier 		y2 = y1;
677dd7cddfSDavid du Colombier 		y1 = y0;
687dd7cddfSDavid du Colombier 		y0 = tmp;
697dd7cddfSDavid du Colombier 	}
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	mpassign(a, d);
727dd7cddfSDavid du Colombier 	mpassign(x2, x);
737dd7cddfSDavid du Colombier 	mpassign(y2, y);
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier 	mpfree(x0);
767dd7cddfSDavid du Colombier 	mpfree(x1);
777dd7cddfSDavid du Colombier 	mpfree(x2);
787dd7cddfSDavid du Colombier 	mpfree(y0);
797dd7cddfSDavid du Colombier 	mpfree(y1);
807dd7cddfSDavid du Colombier 	mpfree(y2);
817dd7cddfSDavid du Colombier 	mpfree(q);
827dd7cddfSDavid du Colombier 	mpfree(r);
837dd7cddfSDavid du Colombier 	mpfree(a);
847dd7cddfSDavid du Colombier 	mpfree(b);
857dd7cddfSDavid du Colombier }
86