xref: /plan9-contrib/sys/src/libmp/port/mpextendedgcd.c (revision 59c21d95eabd8f0704c9b4a4cb647ed908ae2da6)
17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier 
47dd7cddfSDavid du Colombier #define iseven(a)	(((a)->p[0] & 1) == 0)
57dd7cddfSDavid du Colombier 
69a747e4fSDavid du Colombier // extended binary gcd
79a747e4fSDavid du Colombier //
89a747e4fSDavid du Colombier // For a anv b it solves, v = gcd(a,b) and finds x and y s.t.
97dd7cddfSDavid du Colombier // ax + by = v
109a747e4fSDavid du Colombier //
119a747e4fSDavid du Colombier // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608.
127dd7cddfSDavid du Colombier void
mpextendedgcd(mpint * a,mpint * b,mpint * v,mpint * x,mpint * y)137dd7cddfSDavid du Colombier mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y)
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier 	mpint *u, *A, *B, *C, *D;
167dd7cddfSDavid du Colombier 	int g;
177dd7cddfSDavid du Colombier 
18*59c21d95SDavid du Colombier 	if(a->sign < 0 || b->sign < 0){
19*59c21d95SDavid du Colombier 		mpassign(mpzero, v);
20*59c21d95SDavid du Colombier 		mpassign(mpzero, y);
21*59c21d95SDavid du Colombier 		mpassign(mpzero, x);
22*59c21d95SDavid du Colombier 		return;
23*59c21d95SDavid du Colombier 	}
24*59c21d95SDavid du Colombier 
257dd7cddfSDavid du Colombier 	if(a->top == 0){
267dd7cddfSDavid du Colombier 		mpassign(b, v);
277dd7cddfSDavid du Colombier 		mpassign(mpone, y);
287dd7cddfSDavid du Colombier 		mpassign(mpzero, x);
297dd7cddfSDavid du Colombier 		return;
307dd7cddfSDavid du Colombier 	}
317dd7cddfSDavid du Colombier 	if(b->top == 0){
327dd7cddfSDavid du Colombier 		mpassign(a, v);
337dd7cddfSDavid du Colombier 		mpassign(mpone, x);
347dd7cddfSDavid du Colombier 		mpassign(mpzero, y);
357dd7cddfSDavid du Colombier 		return;
367dd7cddfSDavid du Colombier 	}
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier 	g = 0;
397dd7cddfSDavid du Colombier 	a = mpcopy(a);
407dd7cddfSDavid du Colombier 	b = mpcopy(b);
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 	while(iseven(a) && iseven(b)){
437dd7cddfSDavid du Colombier 		mpright(a, 1, a);
447dd7cddfSDavid du Colombier 		mpright(b, 1, b);
457dd7cddfSDavid du Colombier 		g++;
467dd7cddfSDavid du Colombier 	}
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier 	u = mpcopy(a);
497dd7cddfSDavid du Colombier 	mpassign(b, v);
507dd7cddfSDavid du Colombier 	A = mpcopy(mpone);
517dd7cddfSDavid du Colombier 	B = mpcopy(mpzero);
527dd7cddfSDavid du Colombier 	C = mpcopy(mpzero);
537dd7cddfSDavid du Colombier 	D = mpcopy(mpone);
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	for(;;) {
567dd7cddfSDavid du Colombier //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
577dd7cddfSDavid du Colombier 		while(iseven(u)){
587dd7cddfSDavid du Colombier 			mpright(u, 1, u);
597dd7cddfSDavid du Colombier 			if(!iseven(A) || !iseven(B)) {
607dd7cddfSDavid du Colombier 				mpadd(A, b, A);
617dd7cddfSDavid du Colombier 				mpsub(B, a, B);
627dd7cddfSDavid du Colombier 			}
637dd7cddfSDavid du Colombier 			mpright(A, 1, A);
647dd7cddfSDavid du Colombier 			mpright(B, 1, B);
657dd7cddfSDavid du Colombier 		}
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
687dd7cddfSDavid du Colombier 		while(iseven(v)){
697dd7cddfSDavid du Colombier 			mpright(v, 1, v);
707dd7cddfSDavid du Colombier 			if(!iseven(C) || !iseven(D)) {
717dd7cddfSDavid du Colombier 				mpadd(C, b, C);
727dd7cddfSDavid du Colombier 				mpsub(D, a, D);
737dd7cddfSDavid du Colombier 			}
747dd7cddfSDavid du Colombier 			mpright(C, 1, C);
757dd7cddfSDavid du Colombier 			mpright(D, 1, D);
767dd7cddfSDavid du Colombier 		}
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier //		print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
797dd7cddfSDavid du Colombier 		if(mpcmp(u, v) >= 0){
807dd7cddfSDavid du Colombier 			mpsub(u, v, u);
817dd7cddfSDavid du Colombier 			mpsub(A, C, A);
827dd7cddfSDavid du Colombier 			mpsub(B, D, B);
837dd7cddfSDavid du Colombier 		} else {
847dd7cddfSDavid du Colombier 			mpsub(v, u, v);
857dd7cddfSDavid du Colombier 			mpsub(C, A, C);
867dd7cddfSDavid du Colombier 			mpsub(D, B, D);
877dd7cddfSDavid du Colombier 		}
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 		if(u->top == 0)
907dd7cddfSDavid du Colombier 			break;
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier 	}
937dd7cddfSDavid du Colombier 	mpassign(C, x);
947dd7cddfSDavid du Colombier 	mpassign(D, y);
957dd7cddfSDavid du Colombier 	mpleft(v, g, v);
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	mpfree(A);
987dd7cddfSDavid du Colombier 	mpfree(B);
997dd7cddfSDavid du Colombier 	mpfree(C);
1007dd7cddfSDavid du Colombier 	mpfree(D);
1017dd7cddfSDavid du Colombier 	mpfree(u);
1027dd7cddfSDavid du Colombier 	mpfree(a);
1037dd7cddfSDavid du Colombier 	mpfree(b);
104*59c21d95SDavid du Colombier 
105*59c21d95SDavid du Colombier 	return;
1067dd7cddfSDavid du Colombier }
107