[BACK]Return to subcyclo.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

Annotation of OpenXM_contrib/pari-2.2/src/basemath/subcyclo.c, Revision 1.1

1.1     ! noro        1: /* $Id: subcyclo.c,v 1.21 2002/07/04 12:25:04 bill Exp $
        !             2:
        !             3: Copyright (C) 2000  The PARI group.
        !             4:
        !             5: This file is part of the PARI/GP package.
        !             6:
        !             7: PARI/GP is free software; you can redistribute it and/or modify it under the
        !             8: terms of the GNU General Public License as published by the Free Software
        !             9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
        !            10: ANY WARRANTY WHATSOEVER.
        !            11:
        !            12: Check the License for details. You should have received a copy of it, along
        !            13: with the package; see the file 'COPYING'. If not, write to the Free Software
        !            14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
        !            15:
        !            16: #include "pari.h"
        !            17:
        !            18: extern GEN vandermondeinversemod(GEN L, GEN T, GEN den, GEN mod);
        !            19: extern GEN supnorm(GEN L, long prec);
        !            20:
        !            21: /*************************************************************************/
        !            22: /**                                                                     **/
        !            23: /**              Routines for handling subgroups of (Z/nZ)^*            **/
        !            24: /**              without requiring discrete logarithms.                 **/
        !            25: /**                                                                     **/
        !            26: /*************************************************************************/
        !            27:
        !            28: /* Subgroups are [gen,ord,bits] where
        !            29:  * gen is a vecsmall of generators
        !            30:  * ord is theirs relative orders
        !            31:  * bits is a bit vector of the elements, of length(n).
        !            32:  */
        !            33:
        !            34:  /*The algorithm is similar to testpermutation*/
        !            35: void
        !            36: znstar_partial_coset_func(long n, GEN H, void (*func)(void *data,long c)
        !            37:     , void *data, long d, long c)
        !            38: {
        !            39:   GEN gen = (GEN) H[1];
        !            40:   GEN ord = (GEN) H[2];
        !            41:   GEN cache = vecsmall_const(d,c);
        !            42:   long i, j, card = 1;
        !            43:
        !            44:   (*func)(data,c);
        !            45:   for (i = 1; i <= d; i++) card *= ord[i];
        !            46:   for(i=1; i<card; i++)
        !            47:   {
        !            48:     long k, m = i;
        !            49:     for(j=1; j<d && m%ord[j]==0 ;j++) m /= ord[j];
        !            50:     cache[j] = mulssmod(cache[j],gen[j],n);
        !            51:     for (k=1; k<j; k++) cache[k] = cache[j];
        !            52:     (*func)(data, cache[j]);
        !            53:   }
        !            54: }
        !            55:
        !            56: void
        !            57: znstar_coset_func(long n, GEN H, void (*func)(void *data,long c)
        !            58:     , void *data, long c)
        !            59: {
        !            60:   znstar_partial_coset_func(n, H, func,data, lg(H[1])-1, c);
        !            61: }
        !            62:
        !            63: /*Add the element of the bitvec of the coset c modulo the subgroup of H
        !            64:  * generated by the first d generators to the bitvec bits.*/
        !            65:
        !            66: void
        !            67: znstar_partial_coset_bits_inplace(long n, GEN H, GEN bits, long d, long c)
        !            68: {
        !            69:   gpmem_t ltop=avma;
        !            70:   znstar_partial_coset_func(n,H, (void (*)(void *,long)) &bitvec_set,
        !            71:       (void *) bits, d, c);
        !            72:   avma=ltop;
        !            73: }
        !            74:
        !            75: void
        !            76: znstar_coset_bits_inplace(long n, GEN H, GEN bits, long c)
        !            77: {
        !            78:   znstar_partial_coset_bits_inplace(n, H, bits, lg(H[1])-1, c);
        !            79: }
        !            80:
        !            81: GEN
        !            82: znstar_partial_coset_bits(long n, GEN H, long d, long c)
        !            83: {
        !            84:   GEN bits=bitvec_alloc(n);
        !            85:   znstar_partial_coset_bits_inplace(n,H,bits,d,c);
        !            86:   return bits;
        !            87: }
        !            88:
        !            89: /*Compute the bitvec of the elements of the  subgroup of H generated by the
        !            90:  * first d generators.
        !            91:  */
        !            92:
        !            93: GEN
        !            94: znstar_coset_bits(long n, GEN H, long c)
        !            95: {
        !            96:   return znstar_partial_coset_bits(n, H, lg(H[1])-1, c);
        !            97: }
        !            98:
        !            99: /*Compute the bitvec of the elements of the  subgroup of H generated by the
        !           100:  * first d generators.*/
        !           101:
        !           102: GEN
        !           103: znstar_partial_bits(long n, GEN H, long d)
        !           104: {
        !           105:   return znstar_partial_coset_bits(n, H, d, 1);
        !           106: }
        !           107: /*Compute the bitvec of the elements of H.*/
        !           108:
        !           109: GEN
        !           110: znstar_bits(long n, GEN H)
        !           111: {
        !           112:   return znstar_partial_bits(n,H,lg(H[1])-1);
        !           113: }
        !           114:
        !           115: /*Compute the subgroup of (Z/nZ)^* generated by the elements of
        !           116:  * the vecsmall V.
        !           117:  */
        !           118:
        !           119: GEN
        !           120: znstar_generate(long n, GEN V)
        !           121: {
        !           122:   gpmem_t ltop=avma;
        !           123:   GEN res=cgetg(4,t_VEC);
        !           124:   GEN gen=cgetg(lg(V),t_VECSMALL);
        !           125:   GEN ord=cgetg(lg(V),t_VECSMALL);
        !           126:   GEN bits;
        !           127:   long i,r=0;
        !           128:   res[1]=(long)gen;
        !           129:   res[2]=(long)ord;
        !           130:   bits=znstar_partial_bits(n,res,r);
        !           131:   for(i=1;i<lg(V);i++)
        !           132:   {
        !           133:     long v=V[i];
        !           134:     long g=v;
        !           135:     long o=0;
        !           136:     while(!bitvec_test(bits,g))
        !           137:     {
        !           138:       g=mulssmod(g,v,n);
        !           139:       o++;
        !           140:     }
        !           141:     if (o)
        !           142:     {
        !           143:       r++;
        !           144:       gen[r]=v;
        !           145:       ord[r]=o+1;
        !           146:       cgiv(bits);
        !           147:       bits=znstar_partial_bits(n,res,r);
        !           148:     }
        !           149:   }
        !           150:   setlg(gen,r+1);
        !           151:   setlg(ord,r+1);
        !           152:   res[3]=(long)bits;
        !           153:   return gerepilecopy(ltop,res);
        !           154: }
        !           155:
        !           156: /* Return the lists of element of H.
        !           157:  * This can be implemented with znstar_coset_func instead.
        !           158:  */
        !           159:
        !           160: GEN
        !           161: znstar_elts(long n, GEN H)
        !           162: {
        !           163:   long card=group_order(H);
        !           164:   GEN gen=(GEN)H[1], ord=(GEN)H[2];
        !           165:   GEN sg = cgetg(1 + card, t_VECSMALL);
        !           166:   long k, j, l;
        !           167:   sg[1] = 1;
        !           168:   for (j = 1, l = 1; j < lg(gen); j++)
        !           169:   {
        !           170:     int     c = l * (ord[j] - 1);
        !           171:     for (k = 1; k <= c; k++)   /* I like it */
        !           172:       sg[++l] = mulssmod(sg[k], gen[j], n);
        !           173:   }
        !           174:   vecsmall_sort(sg);
        !           175:   return sg;
        !           176: }
        !           177:
        !           178: /* Take a znstar H and n dividing the modulus of H.
        !           179:  * Output H reduced to modulus n */
        !           180:
        !           181: GEN
        !           182: znstar_reduce_modulus(GEN H, long n)
        !           183: {
        !           184:   gpmem_t ltop=avma;
        !           185:   GEN gen=cgetg(lg(H[1]),t_VECSMALL);
        !           186:   long i;
        !           187:   for(i=1; i < lg(gen); i++)
        !           188:     gen[i] = mael(H,1,i)%n;
        !           189:   return gerepileupto(ltop, znstar_generate(n,gen));
        !           190: }
        !           191: /*Compute conductor of H*/
        !           192:
        !           193: long znstar_conductor(long n, GEN H)
        !           194: {
        !           195:   gpmem_t ltop=avma;
        !           196:   int i,j;
        !           197:   GEN F;
        !           198:   long cnd=n;
        !           199:   F = decomp_small(n);
        !           200:   for(i=lg((GEN)F[1])-1;i>0;i--)
        !           201:   {
        !           202:     long p=coeff(F,i,1);
        !           203:     long e=coeff(F,i,2);
        !           204:     long q=n;
        !           205:     if (DEBUGLEVEL>=4)
        !           206:       fprintferr("SubCyclo: testing %ld^%ld\n",p,e);
        !           207:     for (  ; e>=1; e--)
        !           208:     {
        !           209:       long z = 1;
        !           210:       q /= p;
        !           211:       for (j = 1; j < p; j++)
        !           212:       {
        !           213:        z += q;
        !           214:        if (!bitvec_test((GEN) H[3],z) && cgcd(z,n)==1)
        !           215:           break;
        !           216:       }
        !           217:       if ( j < p )
        !           218:       {
        !           219:        if (DEBUGLEVEL>=4)
        !           220:          fprintferr("SubCyclo: %ld not found\n",z);
        !           221:        break;
        !           222:       }
        !           223:       cnd /= p;
        !           224:       if (DEBUGLEVEL>=4)
        !           225:        fprintferr("SubCyclo: new conductor:%ld\n",cnd);
        !           226:     }
        !           227:   }
        !           228:   if (DEBUGLEVEL>=6)
        !           229:     fprintferr("SubCyclo: conductor:%ld\n",cnd);
        !           230:   avma=ltop;
        !           231:   return cnd;
        !           232: }
        !           233:
        !           234: /* Calcule les orbites d'un sous-groupe de Z/nZ donne par un
        !           235:  * generateur ou d'un ensemble de generateur donne par un vecteur.
        !           236:  */
        !           237: GEN
        !           238: znstar_cosets(long n, long phi_n, GEN H)
        !           239: {
        !           240:   long    k;
        !           241:   long    c = 0;
        !           242:   long    card   = group_order(H);
        !           243:   long    index  = phi_n/card;
        !           244:   GEN     cosets = cgetg(index+1,t_VECSMALL);
        !           245:   gpmem_t ltop = avma;
        !           246:   GEN     bits   = bitvec_alloc(n);
        !           247:   for (k = 1; k <= index; k++)
        !           248:   {
        !           249:     for (c++ ; bitvec_test(bits,c) || cgcd(c,n)!=1; c++);
        !           250:     cosets[k]=c;
        !           251:     znstar_coset_bits_inplace(n, H, bits, c);
        !           252:   }
        !           253:   avma=ltop;
        !           254:   return cosets;
        !           255: }
        !           256:
        !           257:
        !           258: /*************************************************************************/
        !           259: /**                                                                     **/
        !           260: /**                     znstar/HNF interface                            **/
        !           261: /**                                                                     **/
        !           262: /*************************************************************************/
        !           263:
        !           264: /* Convert a true znstar output by znstar to a `small znstar'
        !           265:  */
        !           266:
        !           267: GEN
        !           268: znstar_small(GEN zn)
        !           269: {
        !           270:   GEN Z=cgetg(4,t_VEC);
        !           271:   Z[1]=licopy(gmael3(zn,3,1,1));
        !           272:   Z[2]=(long) gtovecsmall((GEN)zn[2]);
        !           273:   Z[3]=(long) lift((GEN)zn[3]);
        !           274:   return Z;
        !           275: }
        !           276:
        !           277:
        !           278: /* Compute generators for the subgroup of (Z/nZ)* given in HNF.
        !           279:  */
        !           280: GEN
        !           281: znstar_hnf_generators(GEN Z, GEN M)
        !           282: {
        !           283:   long l = lg(M);
        !           284:   GEN gen=cgetg(l, t_VECSMALL);
        !           285:   gpmem_t ltop=avma;
        !           286:   GEN zgen= (GEN) Z[3];
        !           287:   long n = itos((GEN) Z[1]);
        !           288:   GEN m = stoi(n);
        !           289:   long j,h;
        !           290:   for (j = 1; j < l; j++)
        !           291:   {
        !           292:     gen[j] = 1;
        !           293:     for (h = 1; h < l; h++)
        !           294:       gen[j] = mulssmod(gen[j],
        !           295:           itos(powmodulo((GEN) zgen[h], gmael(M,j,h),m)),n);
        !           296:   }
        !           297:   avma=ltop;
        !           298:   return gen;
        !           299: }
        !           300:
        !           301: GEN
        !           302: znstar_hnf(GEN Z, GEN M)
        !           303: {
        !           304:   return znstar_generate(itos((GEN)Z[1]),znstar_hnf_generators(Z,M));
        !           305: }
        !           306:
        !           307: GEN
        !           308: znstar_hnf_elts(GEN Z, GEN H)
        !           309: {
        !           310:   gpmem_t ltop=avma;
        !           311:   GEN G=znstar_hnf(Z,H);
        !           312:   long n=itos((GEN)Z[1]);
        !           313:   GEN list=znstar_elts(n,G);
        !           314:   return gerepileupto(ltop,list);
        !           315: }
        !           316:
        !           317: /*************************************************************************/
        !           318: /**                                                                     **/
        !           319: /**                     subcyclo                                        **/
        !           320: /**                                                                     **/
        !           321: /*************************************************************************/
        !           322:
        !           323: static GEN gscycloconductor(GEN g, long n, long flag)
        !           324: {
        !           325:   if (flag==2)
        !           326:   {
        !           327:     GEN V=cgetg(3,t_VEC);
        !           328:     V[1]=lcopy(g);
        !           329:     V[2]=lstoi(n);
        !           330:     return V;
        !           331:   }
        !           332:   return g;
        !           333: }
        !           334:
        !           335: static long
        !           336: lift_check_modulus(GEN H, long n)
        !           337: {
        !           338:   long t=typ(H);
        !           339:   long h;
        !           340:   switch(t)
        !           341:   {
        !           342:     case t_INTMOD:
        !           343:       if (cmpsi(n,(GEN)H[1]))
        !           344:        err(talker,"wrong modulus in galoissubcyclo");
        !           345:       H = (GEN)H[2];
        !           346:     case t_INT:
        !           347:       h=smodis(H,n);
        !           348:       if (cgcd(h,n)!=1)
        !           349:        err(talker,"generators must be prime to conductor in galoissubcyclo");
        !           350:       return h;
        !           351:   }
        !           352:   err(talker,"wrong type in galoissubcyclo");
        !           353:   return 0;/*not reached*/
        !           354: }
        !           355:
        !           356: GEN subcyclo_complex_bound(gpmem_t ltop, GEN V, long prec)
        !           357: {
        !           358:   GEN pol = roots_to_pol(V,0);
        !           359:   GEN vec = gtovec(greal(pol));
        !           360:   GEN borne = ceil_safe(supnorm(vec,prec));
        !           361:   return gerepileupto(ltop,borne);
        !           362: }
        !           363:
        !           364: GEN subcyclo_complex_cyclic(long n, long d, long m ,long z, long g, GEN powz, long prec)
        !           365: {
        !           366:   GEN V=cgetg(d+1,t_VEC);
        !           367:   long base=1;
        !           368:   long i,k;
        !           369:   for (i=1;i<=d;i++,base=mulssmod(base,z,n))
        !           370:   {
        !           371:     gpmem_t ltop=avma;
        !           372:     long ex=base;
        !           373:     GEN s=gzero;
        !           374:     (void)new_chunk(2*prec + 3);
        !           375:     for (k=0; k<m; k++, ex = mulssmod(ex,g,n))
        !           376:       s=gadd(s,(GEN)powz[ex]);
        !           377:     avma=ltop;
        !           378:     V[i]=lcopy(s);
        !           379:   }
        !           380:   return V;
        !           381: }
        !           382:
        !           383: /* Newton sums mod le. if le==NULL, works with complex instead */
        !           384: GEN
        !           385: subcyclo_cyclic(long n, long d, long m ,long z, long g, GEN powz, GEN le)
        !           386: {
        !           387:   GEN V=cgetg(d+1,t_VEC);
        !           388:   long base=1;
        !           389:   long i,k;
        !           390:   long lle=le?lg(le)*2+1:2*lg(powz[1])+3;/*Assume dvmdii use lx+ly space*/
        !           391:   for (i=1;i<=d;i++,base=mulssmod(base,z,n))
        !           392:   {
        !           393:     gpmem_t ltop=avma;
        !           394:     long ex=base;
        !           395:     GEN s=gzero;
        !           396:     (void)new_chunk(lle); /* HACK */
        !           397:     for (k=0; k<m; k++, ex = mulssmod(ex,g,n))
        !           398:       s=gadd(s,(GEN)powz[ex]);
        !           399:     avma=ltop;
        !           400:     V[i]=le?lmodii(s,le):lcopy(s);
        !           401:   }
        !           402:   return V;
        !           403: }
        !           404:
        !           405: struct _subcyclo_orbits_s
        !           406: {
        !           407:   GEN powz;
        !           408:   GEN *s;
        !           409:   ulong count;
        !           410:   gpmem_t ltop;
        !           411: };
        !           412:
        !           413: void
        !           414: _subcyclo_orbits(struct _subcyclo_orbits_s *data, long k)
        !           415: {
        !           416:   GEN powz = data->powz;
        !           417:   GEN *s = data->s;
        !           418:
        !           419:   if (!data->count) data->ltop= avma;
        !           420:   *s = gadd(*s,(GEN)powz[k]);
        !           421:   data->count++;
        !           422:   if ((data->count & 0xffUL) == 0)
        !           423:     *s = gerepileupto(data->ltop, *s);
        !           424: }
        !           425:
        !           426: /* Newton sums mod le. if le==NULL, works with complex instead */
        !           427: GEN
        !           428: subcyclo_orbits(long n, GEN H, GEN O, GEN powz, GEN le)
        !           429: {
        !           430:   long i, d=lg(O);
        !           431:   GEN V=cgetg(d,t_VEC);
        !           432:   struct _subcyclo_orbits_s data;
        !           433:   long lle=le?lg(le)*2+1:2*lg(powz[1])+3;/*Assume dvmdii use lx+ly space*/
        !           434:   data.powz = powz;
        !           435:   for(i=1; i<d; i++)
        !           436:   {
        !           437:     GEN s = gzero;
        !           438:     gpmem_t av = avma;
        !           439:     (void)new_chunk(lle);
        !           440:     data.count = 0;
        !           441:     data.s     = &s;
        !           442:     znstar_coset_func(n, H, (void (*)(void *,long)) _subcyclo_orbits,
        !           443:       (void *) &data, O[i]);
        !           444:     avma = av; /* HACK */
        !           445:     V[i] = le?lmodii(s,le):lcopy(s);
        !           446:   }
        !           447:   return V;
        !           448: }
        !           449:
        !           450: GEN
        !           451: subcyclo_start(long n, long d, long o, GEN borne, long *ptr_val,long *ptr_l)
        !           452: {
        !           453:   gpmem_t av;
        !           454:   GEN l,le,z;
        !           455:   long i;
        !           456:   long e,val;
        !           457:   if (DEBUGLEVEL >= 1) (void)timer2();
        !           458:   l=stoi(n+1);e=1;
        !           459:   while(!isprime(l))
        !           460:   {
        !           461:     l=addis(l,n);
        !           462:     e++;
        !           463:   }
        !           464:   if (DEBUGLEVEL >= 4)
        !           465:     fprintferr("Subcyclo: prime l=%Z\n",l);
        !           466:   av=avma;
        !           467:   if (!borne)
        !           468:   {
        !           469:     /*Borne utilise':
        !           470:       Vecmax(Vec((x+o)^d)=max{binome(d,i)*o^i ;1<=i<=d}
        !           471:      */
        !           472:     i=d-(1+d)/(1+o);
        !           473:     borne=mulii(binome(stoi(d),i),gpowgs(stoi(o),i));
        !           474:   }
        !           475:   if (DEBUGLEVEL >= 4)
        !           476:     fprintferr("Subcyclo: borne=%Z\n",borne);
        !           477:   val=logint(shifti(borne,2),l,NULL);
        !           478:   avma=av;
        !           479:   if (DEBUGLEVEL >= 4)
        !           480:     fprintferr("Subcyclo: val=%ld\n",val);
        !           481:   le=gpowgs(l,val);
        !           482:   z=lift(gpowgs(gener(l),e));
        !           483:   z=padicsqrtnlift(gun,stoi(n),z,l,val);
        !           484:   if (DEBUGLEVEL >= 1)
        !           485:     msgtimer("padicsqrtnlift.");
        !           486:   *ptr_val=val;
        !           487:   *ptr_l=itos(l);
        !           488:   return gmodulcp(z,le);
        !           489: }
        !           490:
        !           491: GEN
        !           492: subcyclo_complex_roots(long n, long real, long prec)
        !           493: {
        !           494:   GEN powz, z = exp_Ir(divrs(Pi2n(1, prec), n)); /* = e_n(1) */
        !           495:   long i, k = (n+3)>>1;
        !           496:
        !           497:   powz = cgetg(n,t_VEC);
        !           498:   powz[1] = (long)z;
        !           499:   for (i=2; i<k; i++) powz[i] = lmul(z,(GEN)powz[i-1]);
        !           500:   if (real) /* totally real field, take real part */
        !           501:   {
        !           502:     for (i=1; i<k; i++) powz[i] = mael(powz,i,1);
        !           503:     for (   ; i<n; i++) powz[i] = powz[n-i];
        !           504:   }
        !           505:   else
        !           506:     for (   ; i<n; i++) powz[i] = lconj((GEN)powz[n-i]);
        !           507:   return powz;
        !           508: }
        !           509:
        !           510: GEN
        !           511: subcyclo_roots(long n, GEN zl)
        !           512: {
        !           513:   GEN le=(GEN) zl[1];
        !           514:   GEN z=(GEN) zl[2];
        !           515:   long lle=lg(le)*3; /*Assume dvmdii use lx+ly space*/
        !           516:   long i;
        !           517:   GEN powz = cgetg(n,t_VEC);
        !           518:   powz[1] = (long) z;
        !           519:   for (i=2; i<n; i++)
        !           520:   {
        !           521:     gpmem_t av=avma;
        !           522:     GEN p1;
        !           523:     (void)new_chunk(lle); /* HACK */
        !           524:     p1 = mulii(z,(GEN)powz[i-1]);
        !           525:     avma=av;
        !           526:     powz[i] = lmodii(p1,le);
        !           527:   }
        !           528:   return powz;
        !           529: }
        !           530:
        !           531: GEN
        !           532: galoiscyclo(long n, long v)
        !           533: {
        !           534:   ulong ltop=avma;
        !           535:   GEN grp,G;
        !           536:   GEN z, le;
        !           537:   long val,l;
        !           538:   GEN L;
        !           539:   long i,j,k;
        !           540:   GEN zn=znstar(stoi(n));
        !           541:   long card=itos((GEN) zn[1]);
        !           542:   GEN gen=lift((GEN)zn[3]);
        !           543:   GEN ord=gtovecsmall((GEN)zn[2]);
        !           544:   GEN elts;
        !           545:   z=subcyclo_start(n,card/2,2,NULL,&val,&l);
        !           546:   le=(GEN) z[1];
        !           547:   z=(GEN) z[2];
        !           548:   L = cgetg(1+card,t_VEC);
        !           549:   L[1] = (long) z;
        !           550:   for (j = 1, i = 1; j < lg(gen); j++)
        !           551:   {
        !           552:     int     c = i * (ord[j] - 1);
        !           553:     for (k = 1; k <= c; k++)   /* I like it */
        !           554:       L[++i] = (long) powmodulo((GEN)L[k],(GEN)gen[j],le);
        !           555:   }
        !           556:   G=abelian_group(ord);
        !           557:   elts = group_elts(G, card); /*not stack clean*/
        !           558:   grp = cgetg(9, t_VEC);
        !           559:   grp[1] = (long) cyclo(n,v);
        !           560:   grp[2] = lgetg(4,t_VEC);
        !           561:   mael(grp,2,1) = lstoi(l);
        !           562:   mael(grp,2,2) = lstoi(val);
        !           563:   mael(grp,2,3) = licopy(le);
        !           564:   grp[3] = lcopy(L);
        !           565:   grp[4] = (long) vandermondeinversemod(L, (GEN) grp[1], gun, le);
        !           566:   grp[5] = un;
        !           567:   grp[6] = lcopy(elts);
        !           568:   grp[7] = lcopy((GEN)G[1]);
        !           569:   grp[8] = lcopy((GEN)G[2]);
        !           570:   return gerepileupto(ltop,grp);
        !           571: }
        !           572:
        !           573: /* Convert a bnrinit(Q,n) to a znstar(n)
        !           574:  * complex is set to 0 if the bnr is real and to 1 if it is complex.
        !           575:  * Not stack clean
        !           576:  */
        !           577: GEN bnrtozn(GEN bnr, long *complex)
        !           578: {
        !           579:   GEN zk;
        !           580:   GEN gen;
        !           581:   GEN cond;
        !           582:   long l2;
        !           583:   long i;
        !           584:   GEN p3;         /* vec */
        !           585:   GEN res;
        !           586:   checkbnrgen(bnr);
        !           587:   zk = (GEN) bnr[5];
        !           588:   gen = (GEN) zk[3];
        !           589:   /*cond is the finite part of the conductor
        !           590:    * complex is the infinite part*/
        !           591:   cond = gcoeff(gmael3(bnr,2,1,1), 1, 1);
        !           592:   *complex = signe(gmael4(bnr,2,1,2,1));
        !           593:   l2 = lg(gen);
        !           594:   res= cgetg(4,t_VEC);
        !           595:   res[1]=zk[1];
        !           596:   res[2]=zk[2];
        !           597:   p3 = cgetg(l2, t_VEC);
        !           598:   for (i = 1; i < l2; ++i)
        !           599:   {
        !           600:     GEN x=(GEN) gen[i];
        !           601:     if (typ(x) == t_MAT)
        !           602:       x = gcoeff(x, 1, 1);
        !           603:     else if (typ(x) == t_COL)
        !           604:       x = (GEN) x[1];
        !           605:     p3[i] = (long) gmodulcp(mpabs(x), cond);
        !           606:   }
        !           607:   res[3] = (long) p3;
        !           608:   return res;
        !           609: }
        !           610:
        !           611: GEN
        !           612: galoissubcyclo(GEN N, GEN sg, long flag, long v)
        !           613: {
        !           614:   gpmem_t ltop=avma,av;
        !           615:   GEN H, V;
        !           616:   long i;
        !           617:   GEN O;
        !           618:   GEN Z=NULL;
        !           619:   GEN B,zl,L,T,le,powz;
        !           620:   long val,l;
        !           621:   long n, cnd, complex=1;
        !           622:   long card, phi_n;
        !           623:   if (flag<0 || flag>2) err(flagerr,"galoissubcyclo");
        !           624:   if ( v==-1 ) v=0;
        !           625:   if (!sg) sg=gun;
        !           626:   switch(typ(N))
        !           627:   {
        !           628:     case t_INT:
        !           629:       n=itos(N);
        !           630:       if ( n<1 ) err(arither2);
        !           631:       break;
        !           632:     case t_VEC:
        !           633:       if (lg(N)==7)
        !           634:         N=bnrtozn(N,&complex);
        !           635:       if (lg(N)==4)
        !           636:       {
        !           637:         Z=N;
        !           638:         if (typ(Z[3])!=t_VEC)
        !           639:           err(typeer,"galoissubcyclo");
        !           640:         if (lg(Z[3])==1)
        !           641:           n=1;
        !           642:         else
        !           643:         {
        !           644:           if (typ(gmael(Z,3,1))!= t_INTMOD)
        !           645: #ifdef NETHACK_MESSAGES
        !           646:             err(talker,"You have transgressed!");
        !           647: #else
        !           648:             err(talker,"Please do not try to break PARI with ridiculously counterfeit data. Thanks!");
        !           649: #endif
        !           650:           n=itos(gmael3(Z,3,1,1));
        !           651:         }
        !           652:         break;
        !           653:       }
        !           654:     default: /*fall through*/
        !           655:       err(typeer,"galoissubcyclo");
        !           656:       return NULL;/*Not reached*/
        !           657:   }
        !           658:   if (n==1) {avma=ltop; return polx[v];}
        !           659:   switch(typ(sg))
        !           660:   {
        !           661:      case t_INTMOD: case t_INT:
        !           662:       V=cgetg(2,t_VECSMALL);
        !           663:       V[1]=lift_check_modulus(sg,n);
        !           664:       break;
        !           665:     case t_VECSMALL:
        !           666:       V=gcopy(sg);
        !           667:       for (i=1;i<lg(V);i++)
        !           668:         if (V[i]<0)
        !           669:           V[i]=mulssmod(-V[i],n-1,n);
        !           670:       break;
        !           671:     case t_VEC:
        !           672:     case t_COL:
        !           673:       V=cgetg(lg(sg),t_VECSMALL);
        !           674:       for(i=1;i<lg(sg);i++)
        !           675:         V[i] = (long)lift_check_modulus((GEN)sg[i],n);
        !           676:       break;
        !           677:     case t_MAT:/*Fall through*/
        !           678:       {
        !           679:         if (lg(sg) == 1 || lg(sg) != lg(sg[1]))
        !           680:           err(talker,"not a HNF matrix in galoissubcyclo");
        !           681:         if (!Z)
        !           682:           err(talker,"N must be a bnrinit or a znstar if H is a matrix in galoissubcyclo");
        !           683:         if ( lg(Z[2]) != lg(sg) || lg(Z[3]) != lg(sg))
        !           684:           err(talker,"Matrix of wrong dimensions in galoissubcyclo");
        !           685:         V = znstar_hnf_generators(znstar_small(Z),sg);
        !           686:       }
        !           687:       break;
        !           688:     default:
        !           689:       err(typeer,"galoissubcyclo");
        !           690:       return NULL;/*Not reached*/
        !           691:   }
        !           692:   if (!complex) /*Add complex conjugation*/
        !           693:     V=vecsmall_append(V,n-1);
        !           694:   H = znstar_generate(n,V);
        !           695:   /* compute the complex/real status
        !           696:    * it is real iff z -> conj(z)=z^-1=z^(n-1) is in H
        !           697:    */
        !           698:   if (DEBUGLEVEL >= 6)
        !           699:   {
        !           700:     fprintferr("Subcyclo: elements:");
        !           701:     for (i=1;i<n;i++)
        !           702:       if (bitvec_test((GEN)H[3],i))
        !           703:         fprintferr(" %ld",i);
        !           704:     fprintferr("\n");
        !           705:   }
        !           706:   complex = !bitvec_test((GEN) H[3],n-1);
        !           707:   if (DEBUGLEVEL >= 6)
        !           708:     fprintferr("Subcyclo: complex=%ld\n",complex);
        !           709:   if (DEBUGLEVEL >= 1) (void)timer2();
        !           710:   cnd = znstar_conductor(n,H);
        !           711:   if (DEBUGLEVEL >= 1)
        !           712:     msgtimer("znstar_conductor");
        !           713:   if ( flag == 1 )  { avma=ltop; return stoi(cnd); }
        !           714:   if (n != cnd)
        !           715:   {
        !           716:     H = znstar_reduce_modulus(H, cnd);
        !           717:     n = cnd;
        !           718:   }
        !           719:   card = group_order(H);
        !           720:   phi_n= itos(phi(stoi(n)));
        !           721:   if ( card==phi_n )
        !           722:   {
        !           723:     avma=ltop;
        !           724:     if (flag==3) return galoiscyclo(n,v);
        !           725:     return gscycloconductor(cyclo(n,v),n,flag);
        !           726:   }
        !           727:   O = znstar_cosets(n, phi_n, H);
        !           728:   if (DEBUGLEVEL >= 1)
        !           729:     msgtimer("znstar_cosets");
        !           730:   if (DEBUGLEVEL >= 6)
        !           731:     fprintferr("Subcyclo: orbits=%Z\n",O);
        !           732:   if (DEBUGLEVEL >= 4)
        !           733:     fprintferr("Subcyclo: %ld orbits with %ld elements each\n",phi_n/card,card);
        !           734:   av=avma;
        !           735:   powz=subcyclo_complex_roots(n,!complex,3);
        !           736:   L=subcyclo_orbits(n,H,O,powz,NULL);
        !           737:   B=subcyclo_complex_bound(av,L,3);
        !           738:   zl=subcyclo_start(n,phi_n/card,card,B,&val,&l);
        !           739:   powz=subcyclo_roots(n,zl);
        !           740:   le=(GEN) zl[1];
        !           741:   L=subcyclo_orbits(n,H,O,powz,le);
        !           742:   T=FpV_roots_to_pol(L,le,v);
        !           743:   T=FpX_center(T,le);
        !           744:   return gerepileupto(ltop,gscycloconductor(T,n,flag));
        !           745: }
        !           746:
        !           747: GEN
        !           748: subcyclo(long n, long d, long v)
        !           749: {
        !           750:   gpmem_t ltop=avma;
        !           751:   long o,p,al,r,g,gd;
        !           752:   GEN fa,G;
        !           753:   GEN zl,L,T,le;
        !           754:   long l,val;
        !           755:   GEN B,powz;
        !           756:   if (v<0) v = 0;
        !           757:   if (d==1) return polx[v];
        !           758:   if (d<=0 || n<=0) err(typeer,"subcyclo");
        !           759:   if ((n & 3) == 2) n >>= 1;
        !           760:   if (n == 1 || d >= n) err(talker,"degree does not divide phi(n) in subcyclo");
        !           761:   fa = decomp(stoi(n));
        !           762:   p = itos(gmael(fa,1,1));
        !           763:   al= itos(gmael(fa,2,1));
        !           764:   if (lg((GEN)fa[1]) > 2 || (p==2 && al>2))
        !           765:     err(talker,"non-cyclic case in polsubcyclo: use galoissubcyclo instead");
        !           766:   avma=ltop;
        !           767:   r = cgcd(d,n); /* = p^(v_p(d))*/
        !           768:   n = r*p;
        !           769:   o = n-r; /* = phi(n) */
        !           770:   if (o == d) return cyclo(n,v);
        !           771:   if (o % d) err(talker,"degree does not divide phi(n) in subcyclo");
        !           772:   o /= d;
        !           773:   if (p==2)
        !           774:   {
        !           775:     GEN pol = powgi(polx[v],gdeux); pol[2]=un; /* replace gzero */
        !           776:     return pol; /* = x^2 + 1 */
        !           777:   }
        !           778:   G=gener(stoi(n));
        !           779:   g=itos((GEN)G[2]);
        !           780:   gd=itos((GEN)gpowgs(G,d)[2]);
        !           781:   avma=ltop;
        !           782:   powz=subcyclo_complex_roots(n,(o&1)==0,3);
        !           783:   L=subcyclo_cyclic(n,d,o,g,gd,powz,NULL);
        !           784:   B=subcyclo_complex_bound(ltop,L,3);
        !           785:   zl=subcyclo_start(n,d,o,B,&val,&l);
        !           786:   le=(GEN)zl[1];
        !           787:   powz=subcyclo_roots(n,zl);
        !           788:   if (DEBUGLEVEL >= 6)
        !           789:     msgtimer("subcyclo_roots");
        !           790:   L=subcyclo_cyclic(n,d,o,g,gd,powz,le);
        !           791:   if (DEBUGLEVEL >= 6)
        !           792:     msgtimer("subcyclo_cyclic");
        !           793:   T=FpV_roots_to_pol(L,le,v);
        !           794:   if (DEBUGLEVEL >= 6)
        !           795:     msgtimer("roots_to_pol");
        !           796:   T=FpX_center(T,le);
        !           797:   return gerepileupto(ltop,T);
        !           798: }
        !           799:
        !           800: GEN polsubcyclo(long n, long d, long v)
        !           801: {
        !           802:   gpmem_t ltop=avma;
        !           803:   GEN L, Z=znstar(stoi(n));
        !           804:   /*subcyclo is twice faster but Z must be cyclic*/
        !           805:   if (lg(Z[2]) == 2 && divise((GEN)Z[1],stoi(d)))
        !           806:   {
        !           807:     avma=ltop;
        !           808:     return subcyclo(n, d, v);
        !           809:   }
        !           810:   L=subgrouplist((GEN) Z[2], _vec(stoi(d)));
        !           811:   if (lg(L) == 2)
        !           812:     return gerepileupto(ltop, galoissubcyclo(Z, (GEN) L[1], 0, v));
        !           813:   else
        !           814:   {
        !           815:     GEN V=cgetg(lg(L),t_VEC);
        !           816:     long i;
        !           817:     for (i=1; i< lg(V); i++)
        !           818:       V[i] = (long) galoissubcyclo(Z, (GEN) L[i], 0, v);
        !           819:     return gerepileupto(ltop,V);
        !           820:   }
        !           821: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>