version 1.7, 2001/06/21 07:47:02 |
version 1.19, 2018/03/29 01:32:52 |
|
|
* DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE, |
* DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE, |
* PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE. |
* PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE. |
* |
* |
* $OpenXM: OpenXM_contrib2/asir2000/engine/gfs.c,v 1.6 2001/06/20 09:30:34 noro Exp $ |
* $OpenXM: OpenXM_contrib2/asir2000/engine/gfs.c,v 1.18 2017/02/27 05:14:54 noro Exp $ |
*/ |
*/ |
#include "ca.h" |
#include "ca.h" |
|
#include "inline.h" |
|
|
/* q = p^n */ |
/* q = p^n */ |
|
|
Line 59 int *current_gfs_plus1; |
|
Line 60 int *current_gfs_plus1; |
|
int *current_gfs_ntoi; |
int *current_gfs_ntoi; |
int *current_gfs_iton; |
int *current_gfs_iton; |
|
|
void chsgngfs(); |
|
void generate_defpoly_um(); |
|
|
|
struct prim_root_info { |
struct prim_root_info { |
int p; |
int p; |
int extdeg; |
int extdeg; |
int defpoly; |
int defpoly; |
int prim_root; |
int prim_root; |
}; |
}; |
|
|
|
/* if p >= SF_THRESHOLD, usual representation is used */ |
|
|
|
#define SF_THRESHOLD 16384 |
|
|
struct prim_root_info prim_root_info_tab[] = { |
struct prim_root_info prim_root_info_tab[] = { |
{2,1,0,0}, {2,2,7,2}, {2,3,11,2}, {2,4,19,2}, {2,5,37,2}, {2,6,67,2}, |
{2,1,0,0}, {2,2,7,2}, {2,3,11,2}, {2,4,19,2}, {2,5,37,2}, {2,6,67,2}, |
{2,7,131,2}, {2,8,283,3}, {2,9,515,7}, {2,10,1033,2}, {2,11,2053,2}, |
{2,7,131,2}, {2,8,283,3}, {2,9,515,7}, {2,10,1033,2}, {2,11,2053,2}, |
Line 473 struct prim_root_info prim_root_info_tab[] = { |
|
Line 475 struct prim_root_info prim_root_info_tab[] = { |
|
{16349,1,0,2}, {16361,1,0,3}, {16363,1,0,2}, {16369,1,0,7}, {16381,1,0,2}, |
{16349,1,0,2}, {16361,1,0,3}, {16363,1,0,2}, {16369,1,0,7}, {16381,1,0,2}, |
}; |
}; |
|
|
void dec_um(p,a,u) |
void dec_um(int p,int a,UM u) |
int p,a; |
|
UM u; |
|
{ |
{ |
int i; |
int i; |
|
|
for ( i = 0; a; i++, a /= p ) |
for ( i = 0; a; i++, a /= p ) |
COEF(u)[i] = a%p; |
COEF(u)[i] = a%p; |
DEG(u) = i-1; |
DEG(u) = i-1; |
} |
} |
|
|
/* |
/* |
|
|
* current_gfs_iton[p-1] = 0 |
* current_gfs_iton[p-1] = 0 |
*/ |
*/ |
|
|
void setmod_sf(p,n) |
void setmod_sf(int p,int n) |
int p,n; |
|
{ |
{ |
int r,i,q1,q,t,t1; |
int r,i,q1,q,t,t1; |
UM dp; |
UM dp; |
|
|
for ( i = 0, q = 1; i < n; i++ ) |
if ( p >= SF_THRESHOLD ) { |
q *= p; |
if ( n > 1 ) |
dp = UMALLOC(n); |
error("setmod_ff : p^n is too large"); |
r = search_defpoly_and_primitive_root(p,n,dp); |
current_gfs_p = p; |
if ( !r ) { |
current_gfs_q = p; |
generate_defpoly_um(p,n,dp); |
current_gfs_q1 = p-1; |
r = generate_primitive_root_enc(p,n,dp); |
current_gfs_ext = 0; |
} |
current_gfs_ntoi = 0; |
current_gfs_p = p; |
current_gfs_iton = 0; |
current_gfs_q = q; |
current_gfs_plus1 = 0; |
current_gfs_q1 = q1 = q-1; |
return; |
if ( n > 1 ) |
} |
umtop(CO->v,dp,¤t_gfs_ext); |
|
else |
|
current_gfs_ext = 0; |
|
current_gfs_iton = (int *)MALLOC(q1*sizeof(int)); |
|
current_gfs_iton[0] = 1; |
|
for ( i = 1; i < q1; i++ ) |
|
current_gfs_iton[i] = mulremum_enc(p,n,dp,current_gfs_iton[i-1],r); |
|
|
|
current_gfs_ntoi = (int *)MALLOC(q*sizeof(int)); |
for ( i = 0, q = 1; i < n; i++ ) |
current_gfs_ntoi[0] = -1; |
q *= p; |
for ( i = 0; i < q1; i++ ) |
if ( p == current_gfs_p && q == current_gfs_q ) return; |
current_gfs_ntoi[current_gfs_iton[i]] = i; |
dp = UMALLOC(n); |
|
r = search_defpoly_and_primitive_root(p,n,dp); |
current_gfs_plus1 = (int *)MALLOC(q*sizeof(int)); |
if ( !r ) { |
for ( i = 0; i < q1; i++ ) { |
generate_defpoly_um(p,n,dp); |
t = current_gfs_iton[i]; |
r = generate_primitive_root_enc(p,n,dp); |
/* add 1 to the constant part */ |
if ( !r ) |
t1 = (t/p)*p+((t+1)%p); |
error("setmod_sf : primitive root not found"); |
current_gfs_plus1[i] = current_gfs_ntoi[t1]; |
} |
} |
current_gfs_p = p; |
|
current_gfs_q = q; |
|
current_gfs_q1 = q1 = q-1; |
|
if ( n > 1 ) |
|
umtop(CO->v,dp,¤t_gfs_ext); |
|
else |
|
current_gfs_ext = 0; |
|
current_gfs_iton = (int *)MALLOC(q1*sizeof(int)); |
|
current_gfs_iton[0] = 1; |
|
for ( i = 1; i < q1; i++ ) |
|
current_gfs_iton[i] = mulremum_enc(p,n,dp,current_gfs_iton[i-1],r); |
|
|
|
current_gfs_ntoi = (int *)MALLOC(q*sizeof(int)); |
|
current_gfs_ntoi[0] = -1; |
|
for ( i = 0; i < q1; i++ ) |
|
current_gfs_ntoi[current_gfs_iton[i]] = i; |
|
|
|
current_gfs_plus1 = (int *)MALLOC(q*sizeof(int)); |
|
for ( i = 0; i < q1; i++ ) { |
|
t = current_gfs_iton[i]; |
|
/* add 1 to the constant part */ |
|
t1 = (t/p)*p+((t+1)%p); |
|
current_gfs_plus1[i] = current_gfs_ntoi[t1]; |
|
} |
} |
} |
|
|
int search_defpoly_and_primitive_root(p,n,dp) |
int search_defpoly_and_primitive_root(int p,int n,UM dp) |
int p,n; |
|
UM dp; |
|
{ |
{ |
int l,min,max,mid,p1,i,ind,t; |
int l,min,max,mid,p1,i,ind,t; |
|
|
l = sizeof(prim_root_info_tab)/sizeof(struct prim_root_info); |
l = sizeof(prim_root_info_tab)/sizeof(struct prim_root_info); |
min = 0; max = l-1; |
min = 0; max = l-1; |
ind = -1; |
ind = -1; |
while ( max - min > 1 ) { |
while ( max - min > 1 ) { |
mid = (max+min)/2; |
mid = (max+min)/2; |
p1 = prim_root_info_tab[mid].p; |
p1 = prim_root_info_tab[mid].p; |
if ( p1 == p ) { |
if ( p1 == p ) { |
ind = mid; break; |
ind = mid; break; |
} else if ( p1 > p ) |
} else if ( p1 > p ) |
max = mid; |
max = mid; |
else |
else |
min = mid; |
min = mid; |
} |
} |
if ( ind < 0 ) { |
if ( ind < 0 ) { |
if ( prim_root_info_tab[min].p == p ) |
if ( prim_root_info_tab[min].p == p ) |
ind = min; |
ind = min; |
else if ( prim_root_info_tab[max].p == p ) |
else if ( prim_root_info_tab[max].p == p ) |
ind = max; |
ind = max; |
else |
else |
return 0; /* XXX */ |
return 0; /* XXX */ |
} |
} |
/* now prim_root_info_tab[ind].p = p */ |
/* now prim_root_info_tab[ind].p = p */ |
t = ind - (prim_root_info_tab[ind].extdeg-1); |
t = ind - (prim_root_info_tab[ind].extdeg-1); |
/* now prim_root_info_tab[t].extdeg = 1 */ |
/* now prim_root_info_tab[t].extdeg = 1 */ |
for ( i = t; prim_root_info_tab[i].p == p; i++ ) |
for ( i = t; prim_root_info_tab[i].p == p; i++ ) |
if ( prim_root_info_tab[i].extdeg == n ) |
if ( prim_root_info_tab[i].extdeg == n ) |
break; |
break; |
if ( prim_root_info_tab[i].p != p ) |
if ( prim_root_info_tab[i].p != p ) |
return 0; |
return 0; |
dec_um(p,prim_root_info_tab[i].defpoly,dp); |
dec_um(p,prim_root_info_tab[i].defpoly,dp); |
return prim_root_info_tab[i].prim_root; |
return prim_root_info_tab[i].prim_root; |
} |
} |
|
|
void generate_defpoly_um(p,n,dp) |
void generate_defpoly_um(int p,int n,UM dp) |
int p,n; |
|
UM dp; |
|
{ |
{ |
int i,j,a,c,q; |
int i,j,a,q; |
UM wf,wdf,wgcd; |
UM wf,wdf,wgcd; |
|
|
wf = W_UMALLOC(n); |
wf = W_UMALLOC(n); |
wdf = W_UMALLOC(n); |
wdf = W_UMALLOC(n); |
wgcd = W_UMALLOC(n); |
wgcd = W_UMALLOC(n); |
COEF(dp)[n] = 1; |
COEF(dp)[n] = 1; |
DEG(dp) = n; |
DEG(dp) = n; |
for ( i = 0, q = 1; i < n; i++ ) |
for ( i = 0, q = 1; i < n; i++ ) |
q *= p; |
q *= p; |
for ( i = 0; i < q; i++ ) { |
for ( i = 0; i < q; i++ ) { |
for ( j = 0, a = i; a; j++, a /= p ) |
for ( j = 0, a = i; a; j++, a /= p ) |
COEF(dp)[j] = a%p; |
COEF(dp)[j] = a%p; |
for ( ; j < n; j++ ) |
for ( ; j < n; j++ ) |
COEF(dp)[j] = 0; |
COEF(dp)[j] = 0; |
cpyum(dp,wf); |
cpyum(dp,wf); |
diffum(p,dp,wdf); |
diffum(p,dp,wdf); |
gcdum(p,wf,wdf,wgcd); |
gcdum(p,wf,wdf,wgcd); |
if ( DEG(wgcd) >= 1 ) |
if ( DEG(wgcd) >= 1 ) |
continue; |
continue; |
mini(p,dp,wf); |
mini(p,dp,wf); |
if ( DEG(wf) <= 0 ) |
if ( DEG(wf) <= 0 ) |
return; |
return; |
} |
} |
} |
} |
|
|
int generate_primitive_root_enc(p,n,dp) |
int generate_primitive_root_enc(int p,int n,UM dp) |
int p,n; |
|
UM dp; |
|
{ |
{ |
int i,r,rj,j,q; |
int i,r,rj,j,q; |
|
|
if ( p == 2 && n == 1 ) |
if ( p == 2 && n == 1 ) |
return 1; |
return 1; |
|
|
for ( i = 0, q = 1; i < n; i++ ) |
for ( i = 0, q = 1; i < n; i++ ) |
q *= p; |
q *= p; |
for ( r = n==1?2:p; r < q; r++ ) { |
for ( r = n==1?2:p; r < q; r++ ) { |
rj = r; |
rj = r; |
for ( j = 1; j < q-1 && rj != 1; j++ ) |
for ( j = 1; j < q-1 && rj != 1; j++ ) |
rj = mulremum_enc(p,n,dp,rj,r); |
rj = mulremum_enc(p,n,dp,rj,r); |
if ( j == q-1 ) |
if ( j == q-1 ) |
return r; |
return r; |
} |
} |
|
/* not found */ |
|
return 0; |
} |
} |
|
|
/* [a(p)]*[b(p)] in GF(p^n) -> [a(x)*b(x) mod dp(x)]_{x->p} */ |
/* [a(p)]*[b(p)] in GF(p^n) -> [a(x)*b(x) mod dp(x)]_{x->p} */ |
|
|
int mulremum_enc(p,n,dp,a,b) |
int mulremum_enc(int p,int n,UM dp,int a,int b) |
int p,n; |
|
UM dp; |
|
int a,b; |
|
{ |
{ |
int i,dr,r; |
int i,dr,r; |
UM wa,wb,wc,wq; |
UM wa,wb,wc,wq; |
|
|
if ( n == 1 ) |
if ( n == 1 ) |
return (a*b)%p; |
return (a*b)%p; |
if ( !a || !b ) |
if ( !a || !b ) |
return 0; |
return 0; |
|
|
wa = W_UMALLOC(n); |
wa = W_UMALLOC(n); |
dec_um(p,a,wa); |
dec_um(p,a,wa); |
|
|
wb = W_UMALLOC(n); |
wb = W_UMALLOC(n); |
dec_um(p,b,wb); |
dec_um(p,b,wb); |
|
|
wc = W_UMALLOC(2*n); |
wc = W_UMALLOC(2*n); |
wq = W_UMALLOC(2*n); |
wq = W_UMALLOC(2*n); |
mulum(p,wa,wb,wc); |
mulum(p,wa,wb,wc); |
dr = divum(p,wc,dp,wq); |
dr = divum(p,wc,dp,wq); |
for ( i = dr, r = 0; i >= 0; i-- ) |
for ( i = dr, r = 0; i >= 0; i-- ) |
r = r*p+COEF(wc)[i]; |
r = r*p+COEF(wc)[i]; |
return r; |
return r; |
} |
} |
|
|
void gfs_galois_action(a,e,c) |
/* sigma : alpha -> alpha^q */ |
GFS a; |
|
Q e; |
void gfs_galois_action(GFS a,Q e,GFS *c) |
GFS *c; |
|
{ |
{ |
Q p; |
Q p; |
int i,k; |
int i,k; |
GFS t,s; |
GFS t,s; |
|
|
t = a; |
t = a; |
k = QTOS(e); |
k = QTOS(e); |
STOQ(current_gfs_p,p); |
STOQ(current_gfs_p,p); |
for ( i = 0; i < k; i++ ) { |
for ( i = 0; i < k; i++ ) { |
pwrgfs(t,p,&s); t = s; |
pwrgfs(t,p,&s); t = s; |
} |
} |
*c = t; |
*c = t; |
} |
} |
|
|
void qtogfs(a,c) |
/* GF(pn)={0,1,a,a^2,...} -> GF(pm)={0,1,b,b^2,...}; a->b^k */ |
Q a; |
|
GFS *c; |
void gfs_embed(GFS z,int k,int pm,GFS *c) |
{ |
{ |
int s; |
int t; |
|
|
s = QTOS(a)%current_gfs_q; |
if ( !z ) |
if ( s < 0 ) |
*c = 0; |
s += current_gfs_q; |
else { |
if ( !s ) |
t = dmar(k,CONT(z),0,pm-1); |
*c = 0; |
MKGFS(t,*c); |
else |
} |
MKGFS(current_gfs_ntoi[s],*c); |
|
} |
} |
|
|
void mqtogfs(a,c) |
/* 0 <= index <= q-1 */ |
MQ a; |
|
GFS *c; |
void indextogfs(int index, GFS *c) |
{ |
{ |
if ( !a ) |
if ( index == 0 ) |
*c = 0; |
*c = 0; |
else { |
else if ( index >= current_gfs_q ) |
MKGFS(current_gfs_ntoi[CONT(a)],*c); |
error("indextogfs : exhausted"); |
} |
else if ( !current_gfs_ntoi ) { |
|
MKGFS(index,*c); |
|
} else { |
|
MKGFS(index-1,*c); |
|
} |
} |
} |
|
|
void gfstomq(a,c) |
void itogfs(int n, GFS *c) |
GFS a; |
|
MQ *c; |
|
{ |
{ |
if ( !a ) |
n = _itosf(n); |
*c = 0; |
if ( !n ) |
else { |
*c = 0; |
UTOMQ(current_gfs_iton[CONT(a)],*c); |
else { |
} |
n = IFTOF(n); |
|
MKGFS(n,*c); |
|
} |
} |
} |
|
|
void ntogfs(a,b) |
void iftogfs(int n, GFS *c) |
Obj a; |
|
GFS *b; |
|
{ |
{ |
P t; |
if ( !n ) |
|
*c = 0; |
|
else { |
|
MKGFS(IFTOF(n),*c); |
|
} |
|
} |
|
|
if ( !current_gfs_q1 ) |
void qtogfs(Q a,GFS *c) |
error("addgfs : current_gfs_q is not set"); |
{ |
if ( !a || (OID(a)==O_N && NID(a) == N_GFS) ) |
int s; |
*b = (GFS)a; |
|
else if ( OID(a) == O_N && NID(a) == N_M ) |
if ( a && (SGN(a) < 1) ) |
mqtogfs(a,b); |
error("qtogfs : invalid argument"); |
else if ( OID(a) == O_N && NID(a) == N_Q ) { |
s = QTOS(a)%current_gfs_q; |
ptomp(current_gfs_p,(P)a,&t); mqtogfs(t,b); |
itogfs(s,c); |
} else |
|
error("ntogfs : invalid argument"); |
|
} |
} |
|
|
void addgfs(a,b,c) |
void mqtogfs(MQ a,GFS *c) |
GFS a,b; |
|
GFS *c; |
|
{ |
{ |
int ai,bi,ci; |
if ( !a ) |
GFS z; |
*c = 0; |
|
else |
|
itogfs(CONT(a),c); |
|
} |
|
|
ntogfs(a,&z); a = z; |
void gfstomq(GFS a,MQ *c) |
ntogfs(b,&z); b = z; |
{ |
if ( !a ) |
if ( !a ) |
*c = b; |
*c = 0; |
else if ( !b ) |
else if ( !current_gfs_ntoi ) { |
*c = a; |
UTOMQ(CONT(a),*c); |
else { |
} else { |
ai = CONT(a); bi = CONT(b); |
UTOMQ(current_gfs_iton[CONT(a)],*c); |
if ( ai > bi ) { |
} |
/* tab[ai]+tab[bi] = tab[bi](tab[ai-bi]+1) */ |
|
ci = current_gfs_plus1[ai-bi]; |
|
if ( ci < 0 ) |
|
*c = 0; |
|
else { |
|
ci += bi; |
|
if ( ci >= current_gfs_q1 ) |
|
ci -= current_gfs_q1; |
|
MKGFS(ci,*c); |
|
} |
|
} else { |
|
/* tab[ai]+tab[bi] = tab[ai](tab[bi-ai]+1) */ |
|
ci = current_gfs_plus1[bi-ai]; |
|
if ( ci < 0 ) |
|
*c = 0; |
|
else { |
|
ci += ai; |
|
if ( ci >= current_gfs_q1 ) |
|
ci -= current_gfs_q1; |
|
MKGFS(ci,*c); |
|
} |
|
} |
|
} |
|
} |
} |
|
|
void subgfs(a,b,c) |
void gfstopgfs(GFS a,V v,P *c) |
GFS a,b; |
|
GFS *c; |
|
{ |
{ |
GFS t,z; |
MQ t; |
|
Q q; |
|
|
ntogfs(a,&z); a = z; |
if ( !a ) |
ntogfs(b,&z); b = z; |
*c = 0; |
if ( !b ) |
else if ( !current_gfs_ntoi ) { |
*c = a; |
UTOMQ(CONT(a),t); |
else { |
STOQ(CONT(t),q); |
chsgngfs(b,&t); |
*c = (P)q; |
addgfs(a,t,c); |
} else |
} |
enc_to_p(current_gfs_p,current_gfs_iton[CONT(a)],v,c); |
} |
} |
|
|
void mulgfs(a,b,c) |
void ntogfs(Obj a,GFS *b) |
GFS a,b; |
|
GFS *c; |
|
{ |
{ |
int ai; |
P t; |
GFS z; |
|
|
|
ntogfs(a,&z); a = z; |
if ( !current_gfs_q1 ) |
ntogfs(b,&z); b = z; |
error("addgfs : current_gfs_q is not set"); |
if ( !a || !b ) |
if ( !a || (OID(a)==O_N && NID(a) == N_GFS) ) |
*c = 0; |
*b = (GFS)a; |
else { |
else if ( OID(a) == O_N && NID(a) == N_M ) |
ai = CONT(a) + CONT(b); |
mqtogfs((MQ)a,b); |
if ( ai >= current_gfs_q1 ) |
else if ( OID(a) == O_N && NID(a) == N_Q ) { |
ai -= current_gfs_q1; |
ptomp(current_gfs_p,(P)a,&t); mqtogfs((MQ)t,b); |
MKGFS(ai,*c); |
} else |
} |
error("ntogfs : invalid argument"); |
} |
} |
|
|
void divgfs(a,b,c) |
void addgfs(GFS a,GFS b,GFS *c) |
GFS a,b; |
|
GFS *c; |
|
{ |
{ |
int ai; |
int ai,bi,ci; |
GFS z; |
GFS z; |
|
|
ntogfs(a,&z); a = z; |
ntogfs((Obj)a,&z); a = z; |
ntogfs(b,&z); b = z; |
ntogfs((Obj)b,&z); b = z; |
if ( !b ) |
if ( !a ) |
error("divgfs : division by 0"); |
*c = b; |
else if ( !a ) |
else if ( !b ) |
*c = 0; |
*c = a; |
else { |
else if ( !current_gfs_ntoi ) { |
ai = CONT(a) - CONT(b); |
ai = CONT(a); bi = CONT(b); |
if ( ai < 0 ) |
ci = ai+bi-current_gfs_q; |
ai += current_gfs_q1; |
if ( ci == 0 ) |
MKGFS(ai,*c); |
*c = 0; |
} |
else { |
|
if ( ci < 0 ) |
|
ci += current_gfs_q; |
|
MKGFS(ci,*c); |
|
} |
|
} else { |
|
ai = CONT(a); bi = CONT(b); |
|
if ( ai > bi ) { |
|
/* tab[ai]+tab[bi] = tab[bi](tab[ai-bi]+1) */ |
|
ci = current_gfs_plus1[ai-bi]; |
|
if ( ci < 0 ) |
|
*c = 0; |
|
else { |
|
ci += bi; |
|
if ( ci >= current_gfs_q1 ) |
|
ci -= current_gfs_q1; |
|
MKGFS(ci,*c); |
|
} |
|
} else { |
|
/* tab[ai]+tab[bi] = tab[ai](tab[bi-ai]+1) */ |
|
ci = current_gfs_plus1[bi-ai]; |
|
if ( ci < 0 ) |
|
*c = 0; |
|
else { |
|
ci += ai; |
|
if ( ci >= current_gfs_q1 ) |
|
ci -= current_gfs_q1; |
|
MKGFS(ci,*c); |
|
} |
|
} |
|
} |
} |
} |
|
|
void chsgngfs(a,c) |
void subgfs(GFS a,GFS b,GFS *c) |
GFS a,*c; |
|
{ |
{ |
int ai; |
GFS t,z; |
GFS z; |
|
|
|
ntogfs(a,&z); a = z; |
ntogfs((Obj)a,&z); a = z; |
if ( !a ) |
ntogfs((Obj)b,&z); b = z; |
*c = 0; |
if ( !b ) |
else if ( current_gfs_q1&1 ) |
*c = a; |
*c = a; |
else { |
else { |
chsgngfs(b,&t); |
/* r^((q-1)/2) = -1 */ |
addgfs(a,t,c); |
ai = CONT(a)+(current_gfs_q1>>1); |
} |
if ( ai >= current_gfs_q1 ) |
|
ai -= current_gfs_q1; |
|
MKGFS(ai,*c); |
|
} |
|
} |
} |
|
|
void pwrgfs(a,b,c) |
void mulgfs(GFS a,GFS b,GFS *c) |
GFS a; |
|
Q b; |
|
GFS *c; |
|
{ |
{ |
N an,tn,rn; |
int ai,bi,ci; |
GFS t,s,z; |
GFS z; |
|
|
ntogfs(a,&z); a = z; |
ntogfs((Obj)a,&z); a = z; |
if ( !b ) |
ntogfs((Obj)b,&z); b = z; |
MKGFS(0,*c); |
if ( !a || !b ) |
else if ( !a ) |
*c = 0; |
*c = 0; |
else if ( !current_gfs_ntoi ) { |
else { |
ai = CONT(a); bi = CONT(b); |
STON(CONT(a),an); muln(an,NM(b),&tn); |
DMAR(ai,bi,0,current_gfs_q,ci); |
STON(current_gfs_q1,an); remn(tn,an,&rn); |
MKGFS(ci,*c); |
if ( !rn ) |
} else { |
MKGFS(0,*c); |
ai = CONT(a) + CONT(b); |
else if ( SGN(b) > 0 ) |
if ( ai >= current_gfs_q1 ) |
MKGFS(BD(rn)[0],*c); |
ai -= current_gfs_q1; |
else { |
MKGFS(ai,*c); |
MKGFS(0,t); |
} |
MKGFS(BD(rn)[0],s); |
|
divgfs(t,s,c); |
|
} |
|
} |
|
} |
} |
|
|
int cmpgfs(a,b) |
void divgfs(GFS a,GFS b,GFS *c) |
GFS a,b; |
|
{ |
{ |
GFS z; |
int ai,bi,ci; |
|
GFS z; |
|
|
ntogfs(a,&z); a = z; |
ntogfs((Obj)a,&z); a = z; |
if ( !a ) |
ntogfs((Obj)b,&z); b = z; |
return !b ? 0 : -1; |
if ( !b ) |
else |
error("divgfs : division by 0"); |
if ( !b ) |
else if ( !a ) |
return 1; |
*c = 0; |
else { |
else if ( !current_gfs_ntoi ) { |
if ( CONT(a) > CONT(b) ) |
ai = CONT(a); bi = invm(CONT(b),current_gfs_q); |
return 1; |
DMAR(ai,bi,0,current_gfs_q,ci); |
else if ( CONT(a) < CONT(b) ) |
MKGFS(ci,*c); |
return -1; |
} else { |
else |
ai = CONT(a) - CONT(b); |
return 0; |
if ( ai < 0 ) |
} |
ai += current_gfs_q1; |
|
MKGFS(ai,*c); |
|
} |
} |
} |
|
|
void randomgfs(r) |
void chsgngfs(GFS a,GFS *c) |
GFS *r; |
|
{ |
{ |
unsigned int t; |
int ai; |
|
GFS z; |
|
|
if ( !current_gfs_q1 ) |
ntogfs((Obj)a,&z); a = z; |
error("addgfs : current_gfs_q is not set"); |
if ( !a ) |
t = mt_genrand()%current_gfs_q; |
*c = 0; |
if ( !t ) |
else if ( !current_gfs_ntoi ) { |
*r = 0; |
ai = current_gfs_q - CONT(a); |
else { |
MKGFS(ai,*c); |
if ( t == current_gfs_q1 ) |
} else if ( current_gfs_q1&1 ) |
t = 0; |
*c = a; |
MKGFS(t,*r); |
else { |
} |
/* r^((q-1)/2) = -1 */ |
|
ai = CONT(a)+(current_gfs_q1>>1); |
|
if ( ai >= current_gfs_q1 ) |
|
ai -= current_gfs_q1; |
|
MKGFS(ai,*c); |
|
} |
} |
} |
|
|
|
void pwrgfs(GFS a,Q b,GFS *c) |
|
{ |
|
N an,tn,rn; |
|
GFS t,s,z; |
|
int ai; |
|
|
|
ntogfs((Obj)a,&z); a = z; |
|
if ( !b ) |
|
itogfs(1,c); |
|
else if ( !a ) |
|
*c = 0; |
|
else if ( !current_gfs_ntoi) { |
|
ai = pwrm(current_gfs_q,CONT(a),QTOS(b)); |
|
MKGFS(ai,*c); |
|
} else { |
|
STON(CONT(a),an); muln(an,NM(b),&tn); |
|
STON(current_gfs_q1,an); remn(tn,an,&rn); |
|
if ( !rn ) |
|
itogfs(1,c); |
|
else if ( SGN(b) > 0 ) |
|
MKGFS(BD(rn)[0],*c); |
|
else { |
|
itogfs(1,&t); |
|
MKGFS(BD(rn)[0],s); |
|
divgfs(t,s,c); |
|
} |
|
} |
|
} |
|
|
|
int cmpgfs(GFS a,GFS b) |
|
{ |
|
GFS z; |
|
|
|
ntogfs((Obj)a,&z); a = z; |
|
if ( !a ) |
|
return !b ? 0 : -1; |
|
else |
|
if ( !b ) |
|
return 1; |
|
else { |
|
if ( CONT(a) > CONT(b) ) |
|
return 1; |
|
else if ( CONT(a) < CONT(b) ) |
|
return -1; |
|
else |
|
return 0; |
|
} |
|
} |
|
|
|
void pthrootgfs(GFS a,GFS *b) |
|
{ |
|
Q p; |
|
int e,i; |
|
GFS t,s; |
|
|
|
STOQ(characteristic_sf(),p); |
|
e = extdeg_sf()-1; |
|
t = a; |
|
for ( i = 0; i < e; i++ ) { |
|
pwrgfs(t,p,&s); t = s; |
|
} |
|
*b = t; |
|
} |
|
|
|
void randomgfs(GFS *r) |
|
{ |
|
unsigned int t; |
|
|
|
if ( !current_gfs_q1 ) |
|
error("addgfs : current_gfs_q is not set"); |
|
t = mt_genrand()%current_gfs_q; |
|
indextogfs(t,r); |
|
} |
|
|
/* arithmetic operations for 'immediate values of GFS */ |
/* arithmetic operations for 'immediate values of GFS */ |
|
|
int _addsf(a,b) |
int _addsf(int a,int b) |
int a,b; |
|
{ |
{ |
if ( !a ) |
if ( !a ) |
return b; |
return b; |
else if ( !b ) |
else if ( !b ) |
return a; |
return a; |
|
|
a = IFTOF(a); b = IFTOF(b); |
a = IFTOF(a); b = IFTOF(b); |
if ( a > b ) { |
|
/* tab[a]+tab[b] = tab[b](tab[a-b]+1) */ |
if ( !current_gfs_ntoi ) { |
a = current_gfs_plus1[a-b]; |
a = a+b-current_gfs_q; |
if ( a < 0 ) |
if ( a == 0 ) |
return 0; |
return 0; |
else { |
else { |
a += b; |
if ( a < 0 ) |
if ( a >= current_gfs_q1 ) |
a += current_gfs_q; |
a -= current_gfs_q1; |
return FTOIF(a); |
return FTOIF(a); |
} |
} |
} |
} else { |
|
/* tab[a]+tab[b] = tab[a](tab[b-a]+1) */ |
if ( a > b ) { |
b = current_gfs_plus1[b-a]; |
/* tab[a]+tab[b] = tab[b](tab[a-b]+1) */ |
if ( b < 0 ) |
a = current_gfs_plus1[a-b]; |
return 0; |
if ( a < 0 ) |
else { |
return 0; |
b += a; |
else { |
if ( b >= current_gfs_q1 ) |
a += b; |
b -= current_gfs_q1; |
if ( a >= current_gfs_q1 ) |
return FTOIF(b); |
a -= current_gfs_q1; |
} |
return FTOIF(a); |
} |
} |
|
} else { |
|
/* tab[a]+tab[b] = tab[a](tab[b-a]+1) */ |
|
b = current_gfs_plus1[b-a]; |
|
if ( b < 0 ) |
|
return 0; |
|
else { |
|
b += a; |
|
if ( b >= current_gfs_q1 ) |
|
b -= current_gfs_q1; |
|
return FTOIF(b); |
|
} |
|
} |
} |
} |
|
|
int _chsgnsf(a) |
int _chsgnsf(int a) |
int a; |
|
{ |
{ |
if ( !a ) |
if ( !a ) |
return 0; |
return 0; |
else if ( current_gfs_q1&1 ) |
else if ( !current_gfs_ntoi ) { |
return a; |
a = current_gfs_q-IFTOF(a); |
else { |
return FTOIF(a); |
/* r^((q-1)/2) = -1 */ |
} else if ( current_gfs_q1&1 ) |
a = IFTOF(a); |
return a; |
a += (current_gfs_q1>>1); |
else { |
if ( a >= current_gfs_q1 ) |
/* r^((q-1)/2) = -1 */ |
a -= current_gfs_q1; |
a = IFTOF(a); |
return FTOIF(a); |
a += (current_gfs_q1>>1); |
} |
if ( a >= current_gfs_q1 ) |
|
a -= current_gfs_q1; |
|
return FTOIF(a); |
|
} |
} |
} |
|
|
int _subsf(a,b) |
int _subsf(int a,int b) |
int a,b; |
|
{ |
{ |
if ( !a ) |
if ( !a ) |
return _chsgnsf(b); |
return _chsgnsf(b); |
else if ( !b ) |
else if ( !b ) |
return a; |
return a; |
else |
else |
return _addsf(a,_chsgnsf(b)); |
return _addsf(a,_chsgnsf(b)); |
} |
} |
|
|
int _mulsf(a,b) |
int _mulsf(int a,int b) |
int a,b; |
|
{ |
{ |
if ( !a || !b ) |
int c; |
return 0; |
|
else { |
if ( !a || !b ) |
a = IFTOF(a) + IFTOF(b); |
return 0; |
if ( a >= current_gfs_q1 ) |
else if ( !current_gfs_ntoi ) { |
a -= current_gfs_q1; |
a = IFTOF(a); b = IFTOF(b); |
return FTOIF(a); |
DMAR(a,b,0,current_gfs_q,c); |
} |
return FTOIF(c); |
|
} else { |
|
a = IFTOF(a) + IFTOF(b); |
|
if ( a >= current_gfs_q1 ) |
|
a -= current_gfs_q1; |
|
return FTOIF(a); |
|
} |
} |
} |
|
|
int _invsf(a) |
int _invsf(int a) |
int a; |
|
{ |
{ |
if ( !a ) |
if ( !a ) { |
error("_invsf : division by 0"); |
error("_invsf : division by 0"); |
else { |
/* NOTREACHED */ |
a = current_gfs_q1 - IFTOF(a); |
return -1; |
return FTOIF(a); |
} else if ( !current_gfs_ntoi ) { |
} |
a = invm(IFTOF(a),current_gfs_q); |
|
return FTOIF(a); |
|
} else { |
|
a = current_gfs_q1 - IFTOF(a); |
|
return FTOIF(a); |
|
} |
} |
} |
|
|
int _divsf(a,b) |
int _divsf(int a,int b) |
int a,b; |
|
{ |
{ |
if ( !b ) |
int c; |
error("_divsf : division by 0"); |
|
else if ( !a ) |
if ( !b ) { |
return 0; |
error("_divsf : division by 0"); |
else { |
/* NOTREACHED */ |
a = IFTOF(a) - IFTOF(b); |
return -1; |
if ( a < 0 ) |
} else if ( !current_gfs_ntoi ) { |
a += current_gfs_q1; |
b = invm(IFTOF(b),current_gfs_q); |
return FTOIF(a); |
a = IFTOF(a); |
} |
DMAR(a,b,0,current_gfs_q,c); |
|
return FTOIF(c); |
|
} else if ( !a ) |
|
return 0; |
|
else { |
|
a = IFTOF(a) - IFTOF(b); |
|
if ( a < 0 ) |
|
a += current_gfs_q1; |
|
return FTOIF(a); |
|
} |
} |
} |
|
|
int _pwrsf(a,b) |
int _pwrsf(int a,int b) |
int a,b; |
|
{ |
{ |
GFS at,ct; |
GFS at,ct; |
Q bt; |
Q bt; |
int c; |
int c; |
|
|
if ( !b ) |
if ( !b ) |
return _onesf(); |
return _onesf(); |
else if ( !a ) |
else if ( !a ) |
return 0; |
return 0; |
else { |
if ( !current_gfs_ntoi ) { |
a = IFTOF(a); |
a = pwrm(current_gfs_q,IFTOF(a),b); |
MKGFS(a,at); |
return FTOIF(a); |
STOQ(b,bt); |
} else { |
pwrgfs(at,bt,&ct); |
iftogfs(a,&at); |
c = CONT(ct); |
STOQ(b,bt); |
return FTOIF(c); |
pwrgfs(at,bt,&ct); |
} |
c = CONT(ct); |
|
return FTOIF(c); |
|
} |
} |
} |
|
|
int _onesf() |
int _onesf() |
{ |
{ |
return FTOIF(0); |
return !current_gfs_ntoi ? FTOIF(1) : FTOIF(0); |
} |
} |
|
|
int _itosf(n) |
int _itosf(int n) |
int n; |
|
{ |
{ |
int i; |
int i; |
|
|
n %= current_gfs_p; |
/* XXX */ |
if ( !n ) |
#if 0 |
return 0; |
n %= current_gfs_p; |
i = current_gfs_ntoi[n]; |
#else |
i = FTOIF(i); |
n %= current_gfs_q; |
if ( n < 0 ) |
#endif |
i = _chsgnsf(i); |
if ( !n ) |
return i; |
return 0; |
|
i = !current_gfs_ntoi ? n : current_gfs_ntoi[n]; |
|
i = FTOIF(i); |
|
if ( n < 0 ) |
|
i = _chsgnsf(i); |
|
return i; |
} |
} |
|
|
int _isonesf(a) |
int _isonesf(int a) |
int a; |
|
{ |
{ |
return a == FTOIF(0); |
return a == _onesf(); |
} |
} |
|
|
int _randomsf() |
int _randomsf() |
{ |
{ |
int t; |
int t; |
|
|
t = (int) (mt_genrand() % current_gfs_q1); |
t = (int) (mt_genrand() % current_gfs_q); |
if ( !t ) |
if ( !current_gfs_ntoi ) |
return 0; |
return t ? FTOIF(t) : 0; |
else |
else |
return FTOIF(t); |
return t!=current_gfs_q1 ? FTOIF(t) : 0; |
} |
} |
|
|
int field_order_sf() |
int field_order_sf() |
{ |
{ |
return current_gfs_q; |
return current_gfs_q; |
} |
} |
|
|
int characteristic_sf() |
int characteristic_sf() |
{ |
{ |
return current_gfs_p; |
return current_gfs_p; |
} |
} |
|
|
int extdeg_sf() |
int extdeg_sf() |
{ |
{ |
return UDEG(current_gfs_ext); |
if ( !current_gfs_ext ) |
|
return 1; |
|
else |
|
return UDEG(current_gfs_ext); |
} |
} |