Exemple #1
0
double gintegrand(double b,int x,int y,double *p2,double *nodes,
		   double *phi_nodes,int nb_nodes,double scale)

{
  double xpos,ypos,tmp,tmp2, phi_b,phip_b, u;
  double g_x,g_y,gprime_x,gprime_y;
  double integ=0;


  /* Spline interpolation of the ridge; computation of its derivative
     ---------------------------------------------------------------*/
  splint2(nodes,phi_nodes,p2,nb_nodes,b,&phi_b,&phip_b);


  /* Evaluation of the integrand
     --------------------------*/
  xpos = (x-b);
  g_x = gfunc(xpos,scale);
  gprime_x = gprime(xpos,scale);
  ypos = (y-b);
  g_y = gfunc(ypos,scale);
  gprime_y = gprime(ypos,scale);

  u = phi_b*(x-y);

  /* First part */

  tmp= (phip_b*phip_b*xpos*ypos - phi_b*phip_b*(xpos+ypos));
  tmp *= g_x*g_y;
  integ = tmp;

  tmp=gprime_x*gprime_y;
  integ += tmp;

  integ *= cos(u);

  /* Second part */

  tmp2 = phip_b*xpos -phi_b;
  tmp2 *= (gprime_y*g_x);

  tmp = phip_b*ypos -phi_b;
  tmp *= (gprime_x*g_y);
  tmp2 -= tmp;

  tmp2 *= sin(u);

  integ += tmp2;

  return integ;
}
JVector
TanhLinNetwork::gprime
	(
	const JIndex	layerIndex,
	const JVector&	g
	)
	const
{
	const JSize dimCount = g.GetDimensionCount();

	JVector result(dimCount);

	for (JIndex i=1;i<=dimCount;i++)
		{
		const JFloat value = g.GetElement(i);
		result.SetElement(i, gprime(layerIndex, value));
		}

	return result;
}
Exemple #3
0
/*############################################################################*/
static AED_REAL calc_xmoment(int NLayers, AED_REAL *iheight, AED_REAL *density)
{
#ifndef _VISUAL_C_
    AED_REAL BFSQ[Nmorph], mid_depth[Nmorph];
#else
    AED_REAL *BFSQ, *mid_depth;
#endif
    AED_REAL XMom, XMomO;
    int i;

/*-----------------------------------------------------------------------------*/
#ifdef _VISUAL_C_
    BFSQ = malloc(sizeof(AED_REAL) * Nmorph);
    mid_depth = malloc(sizeof(AED_REAL) * Nmorph);
#endif

    XMom = 0.0;
    XMomO = 0.0;

    mid_depth[0] = iheight[0] / 2.0;

    for (i = 1; i < NLayers; i++) {
        mid_depth[i]=(iheight[i]+iheight[i-1])/2.0;

        BFSQ[i] = gprime(density[i], density[i-1]) / (mid_depth[i] - mid_depth[i-1]);

        XMom  = XMom + iheight[i-1] * BFSQ[i] * (dMphLevelVol[i+1]+dMphLevelVol[i]) / 2.0;
        XMomO = XMomO +               BFSQ[i] * (dMphLevelVol[i+1]+dMphLevelVol[i]) / 2.0;
    }

    if (XMomO <= 0.0)
        XMom = -1.0;
    else
        XMom = XMom / XMomO;

#ifdef _VISUAL_C_
    free(BFSQ); free(mid_depth);
#endif

    return XMom;
}
Exemple #4
0
/******************************************************************************
 #CAB#  These comments are clearly WRONG!                                     *
 * This subroutine finds the level of Neutral Bouyancy for a given inflow     *
 * and returns the layer number (i), the half-thickness (B0), basin length    *
 * at the intrusion midpoint (AL), basin width at the intrusion               *
 * midpoint, and the mean intrusion velocity (UINF) in m/s.                   *
 ******************************************************************************/
void insert(AED_REAL q, AED_REAL di, AED_REAL bsl, AED_REAL temp, AED_REAL salt,
                             AED_REAL *wqx, int ntims, AED_REAL *width, int *ll)
{
    AED_REAL AHLE;
    AED_REAL AL;
    AED_REAL ALSQ;
    AED_REAL BL;
    AED_REAL B0;
    AED_REAL DBB,DELT,DELB;
    AED_REAL DHLE;
    AED_REAL DT;
#ifndef _VISUAL_C_
    // The visual c compiler doesn't like this so must malloc manually
    AED_REAL DVR[MaxLayers];
#else
    AED_REAL *DVR;
#endif
    AED_REAL DZ;
    AED_REAL F;
    AED_REAL GD;
    AED_REAL GR;
    AED_REAL R;
    AED_REAL TDASH;
    AED_REAL UINF;
    AED_REAL VISCOS;
    AED_REAL XN;
    AED_REAL XNSQ;
    AED_REAL ZP,ZT,ZB;

    int wqidx;
    int i,j,k;
    int iz;
    int JB,JT;
    int KX,KY;
    int NB1;
    int NT1;

/*----------------------------------------------------------------------------*/

#ifdef _VISUAL_C_
    DVR = malloc(sizeof(AED_REAL) * MaxLayers);
#endif

    DELT=0.;
    DELB=0.;

    for (iz = botmLayer; iz <= surfLayer; iz++)
       if (Lake[iz].Height > 0.) break;
    if (iz > surfLayer) iz = surfLayer;

    DHLE = Lake[iz].Height;
    AHLE = Lake[iz].LayerArea;

    if (di <= Lake[surfLayer].Density) {
        // Here for surface overflow
        i = surfLayer;
        *ll = i;
        B0 = (Lake[surfLayer].Height-Lake[surfLayer-1].Height)/ 2.0;
        AL = LenAtCrest;
        if (*width <= 1E-7) *width = Lake[surfLayer].LayerArea / AL;
        UINF = q / ( 2.0 * B0 * (*width));
    } else {
        // Find level of neutral buoyancy
        for (i = surfLayer; i > botmLayer; i--)
            if (di <= Lake[i-1].Density) break;

        if (i <= botmLayer) {
            //  Here for underflow
            i = botmLayer;
            *ll = i;
            AL = DHLE/sin(bsl);
            if ((*width) <= 1E-7) (*width) = AHLE / AL;
            B0 = (DHLE/ 2.0)/ 2.0;
            UINF = q / ( 2.0 * B0 * (*width));
        } else {
            //  Here for intrusion
            JT = i;
            *ll = i;
            JB = i-1;
            AL = Lake[i].Height/sin(bsl);
            ALSQ = sqr(AL);
            if ((*width) <= 1E-7) (*width) = Lake[i].LayerArea/AL;

            while(1) {
                DT = Lake[JT].MeanHeight;
                DBB = Lake[JB].MeanHeight;
                DZ = DT - DBB;
                XNSQ = g*(Lake[JB].Density-Lake[JT].Density)/(di*DZ);
                if (XNSQ  <=  zero)
                    //  Here for unstable stratification
                    BL=AL;
                else {
                    //  here for stable stratification
                    XN = sqrt(XNSQ);
                    F = q/((*width)*ntims*XN*ALSQ);
                    VISCOS = Lake[i].Epsilon * 20.0;
                    if (VISCOS <= 0.) VISCOS=Visc;
                    GR = XNSQ*sqr(ALSQ)/sqr(VISCOS);

                    R = F*pow(GR,(1.0/3.0));
                    TDASH=ntims*XN/(pow(GR,(1.0/6.0)));
                    R /= TDASH;
                    if (R > 1.)
                        BL = 0.44*TDASH*AL*sqrt(R);
                    else
                        BL = 0.57*AL*pow(R, (3.0/ 2.0))*pow((TDASH/R), (5.0/6.0));

                    BL = MIN(BL,AL);
                    if (BL < 1.0) BL = 1.0;
                }

                // B0 is 1/2 the intrusion thickness
                B0 = q/((*width)*BL);
                if (B0 > DZ) {
                    if ( !((JT == surfLayer) && (JB == botmLayer)) ) {
                        if (JT != surfLayer) JT++;
                        if (JB != botmLayer) JB--;
                        continue;
                    }
                }
                break;
            }

            if (Lake[i].Height < (DHLE + 1.0)) {
                AL = DHLE/sin(bsl);
                if ((*width) <= 1E-7) (*width) = AHLE / AL;
                B0 = (DHLE+ 2.0)/ 2.0;
            }
            UINF = q/( 2.0*B0*(*width));
        }
    }

    //  Mix the inflow with the appropriate layers.
    NT1=i;
    ZP=Lake[i].MeanHeight;
    if ( ! (i > botmLayer && i < surfLayer) ) {
        //  Here for underflow, overflow, or fully mixed
        NB1=i;
        DVR[i]=q;
    } else {
        // Here for intrusion
        while(1) {
            NT1++;
            DELT = 0.0;
            if (NT1  !=  surfLayer) {
                GD=gprime(Lake[NT1].Density,Lake[i].Density);
                if (GD > zero) DELT = 0.15 * pow((UINF/(ntims)),2) / GD;
                if (DELT > (Lake[NT1].MeanHeight-ZP) || GD <= zero) continue;
                if (Lake[NT1-1].Height > (ZP+DELT)) NT1--;
            }
            break;
        }

        ZT=Lake[NT1].Height;
        NB1=i;
        while(1) {
            NB1--;
            if (NB1 != botmLayer) {
                GD = gprime(Lake[i].Density,Lake[NB1].Density);
                if (GD > zero) DELB = 0.15 * sqr((UINF/(ntims))) / GD;
                if (DELB > (ZP-Lake[NB1].MeanHeight) || GD <= zero) continue;
                if (Lake[NB1].Height < (ZP-DELB)) NB1++;
            }
            break;
        }

        ZB = zero;
        if (NB1 > botmLayer) ZB = Lake[NB1-1].Height;
        if (NB1 == NT1) {
            // Here if intrusion is entirely within layer i
            DVR[NB1]=q;
        } else {
            // Aportion inflow amongst layers NB1,NB1+1,---,NT1
            DELT = ZT - ZP;
            DELB = ZP - ZB;
            if (NB1 != i) {
                DVR[NB1]=q*(Lake[NB1].Height-ZB+DELB*sin(Pi*(Lake[NB1].Height-ZP)/DELB)/Pi)/(ZT-ZB);
                if (NB1 != (i-1)) {
                    KX = NB1+1;
                    KY = i-1;
                    for (k = KX; k <= KY; k++)
                        DVR[k]=q*(Lake[k].Height-Lake[k-1].Height+DELB *
                            (sin(Pi*(ZP-Lake[k-1].Height)/DELB)-sin(Pi*(ZP-Lake[k].Height)/DELB))/Pi)/(ZT-ZB);
                }
            }
            DVR[i]=q*(ZP-Lake[i-1].Height+DELB*sin(Pi*(ZP-Lake[i-1].Height)/DELB)/Pi)/(ZT-ZB);
            DVR[i]=DVR[i]+q*(Lake[i].Height-ZP+DELT*sin(Pi*(Lake[i].Height-ZP)/DELT)/Pi)/(ZT-ZB);
            if (NT1 != i) {
                if (NT1 != (i+1)) {
                    KX=i+1;
                    KY=NT1-1;
                    for (k = KX; k<=KY; k++)
                        DVR[k]=q*(Lake[k].Height-Lake[k-1].Height+DELT*(sin(Pi*(Lake[k].Height-ZP)/
                                  DELT)-sin(Pi*(Lake[k-1].Height-ZP)/DELT))/Pi)/(ZT-ZB);
                }
                DVR[NT1]=q*(ZT-Lake[NT1-1].Height+DELT*sin(Pi*(ZP-Lake[NT1-1].Height)/DELT)/Pi)/(ZT-ZB);
            }
        }
    }

    // Insert inflow into reservoir and adjust layer properties
    // Include water quality and particles
    for (k = NB1; k <= NT1; k++) {
        Lake[k].Temp = combine(Lake[k].Temp,Lake[k].LayerVol,Lake[k].Density, temp,DVR[k],di);
        Lake[k].Salinity = combine(Lake[k].Salinity,Lake[k].LayerVol,Lake[k].Density,salt,DVR[k],di);

        for (wqidx = 0; wqidx < Num_WQ_Vars; wqidx++)
            _WQ_Vars(wqidx,k) = combine_vol(_WQ_Vars(wqidx,k),Lake[k].LayerVol,wqx[wqidx],DVR[k]);

        Lake[k].Density=calculate_density(Lake[k].Temp,Lake[k].Salinity);
        Lake[k].LayerVol=Lake[k].LayerVol+DVR[k];
    }

    Lake[botmLayer].Vol1 = Lake[botmLayer].LayerVol;
    if (surfLayer != botmLayer) {
        for (j = (botmLayer+1); j <= surfLayer; j++)
            Lake[j].Vol1 = Lake[j-1].Vol1 + Lake[j].LayerVol;
    }

#ifdef _VISUAL_C_
    free(DVR);
#endif
}
Exemple #5
0
int main()
{  /*  factoring program using Lenstras Elliptic Curve method */
    int phase,m,k,nc,iv,pos,btch,u,v;
    long i,p,pa,interval;
    big q,x,z,a,x1,z1,x2,z2,xt,zt,n,fvw;
    static big fu[1+MULT/2];
    static BOOL cp[1+MULT/2];
    mip=mirsys(30,0);
    q=mirvar(0);
    x=mirvar(0);
    z=mirvar(0);
    a=mirvar(0);
    x1=mirvar(0);
    z1=mirvar(0);
    x2=mirvar(0);
    z2=mirvar(0);
    n=mirvar(0);
    t=mirvar(0);
    s1=mirvar(0);
    d1=mirvar(0);
    s2=mirvar(0);
    d2=mirvar(0);
    ak=mirvar(0);
    xt=mirvar(0);
    zt=mirvar(0);
    fvw=mirvar(0);
    w=mirvar(0);
    gprime(LIMIT1);
    for (m=1;m<=MULT/2;m+=2)
        if (igcd(MULT,m)==1)
        {
            fu[m]=mirvar(0);
            cp[m]=TRUE;
        }
        else cp[m]=FALSE;
    printf("input number to be factored\n");
    cinnum(n,stdin);

    if (isprime(n))
    {
        printf("this number is prime!\n");
        return 0;
    }
    prepare_monty(n);
    for (nc=1,k=6;k<100;k++)
    { /* try a new curve */
                             /* generating an elliptic curve */
        u=k*k-5;
        v=4*k;
        convert(u,x);  nres(x,x);
        convert(v,z);  nres(z,z);
        nres_modsub(z,x,a);   /* a=v-u */

        copy(x,t);
        nres_modmult(x,x,x);
        nres_modmult(x,t,x);  /* x=u^3 */

        copy(z,t);
        nres_modmult(z,z,z);
        nres_modmult(z,t,z);  /* z=v^3 */

        copy(a,t);
        nres_modmult(t,t,t);
        nres_modmult(t,a,t);  /* t=(v-u)^3 */

        convert(3*u,a); nres(a,a);
        convert(v,ak);  nres(ak,ak);
        nres_modadd(a,ak,a);
        nres_modmult(t,a,t);  /* t=(v-u)^3.(3u+v) */

        convert(u,a);  nres(a,a);
        copy(a,ak);
        nres_modmult(a,a,a);
        nres_modmult(a,ak,a);   /* a=u^3 */
        convert(v,ak); nres(ak,ak);
        nres_modmult(a,ak,a);   /* a=u^3.v */
        nres_premult(a,16,a);
        nres_moddiv(t,a,ak);     /* ak=(v-u)^3.(3u+v)/16u^3v */

        nc++;

        phase=1;
        p=0;
        i=0;
        btch=50;
        printf("phase 1 - trying all primes less than %d\n",LIMIT1);
        printf("prime= %8ld",p);
        forever
        { /* main loop */
            if (phase==1)
            {
                p=mip->PRIMES[i];
                if (mip->PRIMES[i+1]==0)
                { /* now change gear */
                    phase=2;
                    printf("\nphase 2 - trying last prime less than %ld\n",
                            LIMIT2);
                    printf("prime= %8ld",p);
                    copy(x,xt);
                    copy(z,zt);
                    nres_modadd(x,z,s2);
                    nres_modsub(x,z,d2);                    /*   P = (s2,d2) */
                    duplication(s2,d2,x,z);
                    nres_modadd(x,z,s1);
                    nres_modsub(x,z,d1);                    /* 2.P = (s1,d1) */

                    nres_moddiv(x1,z1,fu[1]);               /* fu[1] = x1/z1 */
                    
                    addition(x1,z1,s1,d1,s2,d2,x2,z2); /* 3.P = (x2,z2) */
                    for (m=5;m<=MULT/2;m+=2)
                    { /* calculate m.P = (x,z) and store fu[m] = x/z */
                        nres_modadd(x2,z2,s2);
                        nres_modsub(x2,z2,d2);
                        addition(x1,z1,s2,d2,s1,d1,x,z);
                        copy(x2,x1);
                        copy(z2,z1);
                        copy(x,x2);
                        copy(z,z2);
                        if (!cp[m]) continue;
                        copy(z2,fu[m]);
                        nres_moddiv(x2,fu[m],fu[m]);
                    }
                    ellipse(xt,zt,MULT,x,z,x2,z2);
                    nres_modadd(x,z,xt);
                    nres_modsub(x,z,zt);              /* MULT.P = (xt,zt) */
                    iv=(int)(p/MULT);
                    if (p%MULT>MULT/2) iv++;
                    interval=(long)iv*MULT; 
                    p=interval+1;
                    ellipse(x,z,iv,x1,z1,x2,z2); /* (x1,z1) = iv.MULT.P */
                    nres_moddiv(x1,z1,fvw);                /* fvw = x1/z1 */
                    nres_modsub(fvw,fu[p%MULT],q);
                    marks(interval);
                    btch*=100;
                    i++;
                    continue;
                }
                pa=p;
                while ((LIMIT1/p) > pa) pa*=p;
                ellipse(x,z,(int)pa,x1,z1,x2,z2);
                copy(x1,x);
                copy(z1,z);
                copy(z,q);
            }
            else
            { /* phase 2 - looking for last large prime factor of (p+1+d) */
                p+=2;
                pos=(int)(p%MULT);
                if (pos>MULT/2)
                { /* increment giant step */
                    iv++;
                    interval=(long)iv*MULT;
                    p=interval+1;
                    marks(interval);
                    pos=1;
                    nres_moddiv(x2,z2,fvw);
                    nres_modadd(x2,z2,s2);
                    nres_modsub(x2,z2,d2);
                    addition(x1,z1,s2,d2,xt,zt,x,z);
                    copy(x2,x1);
                    copy(z2,z1);
                    copy(x,x2);
                    copy(z,z2);
                }
                if (!cp[pos]) continue;

        /* if neither interval +/- pos is prime, don't bother */
                if (!plus[pos] && !minus[pos]) continue;
                nres_modsub(fvw,fu[pos],t);
                nres_modmult(q,t,q);
            }
            if (i++%btch==0)
            { /* try for a solution */
                printf("\b\b\b\b\b\b\b\b%8ld",p);
                fflush(stdout);
                egcd(q,n,t);
                if (size(t)==1)
                {
                    if (p>LIMIT2) break;
                    else continue;
                }
                if (compare(t,n)==0)
                {
                    printf("\ndegenerate case");
                    break;
                }
                printf("\nfactors are\n");
                if (isprime(t)) printf("prime factor     ");
                else            printf("composite factor ");
                cotnum(t,stdout);
                divide(n,t,n);
                if (isprime(n)) printf("prime factor     ");
                else            printf("composite factor ");
                cotnum(n,stdout);
                return 0;
            }
        }
        if (nc>NCURVES) break;
        printf("\ntrying a different curve %d\n",nc);
    } 
    printf("\nfailed to factor\n");
    return 0;
}
Exemple #6
0
int main()
{  /*  factoring program using Williams (p+1) method */
    int k,phase,m,nt,iv,pos,btch;
    long i,p,pa,interval;
    big b,q,n,fp,fvw,fd,fn,t;
    static big fu[1+MULT/2];
    static BOOL cp[1+MULT/2];
    mip=mirsys(30,0);
    b=mirvar(0);
    q=mirvar(0);
    n=mirvar(0);
    t=mirvar(0);
    fp=mirvar(0);
    fvw=mirvar(0);
    fd=mirvar(0);
    fn=mirvar(0);
    gprime(LIMIT1);
    for (m=1;m<=MULT/2;m+=2)
        if (igcd(MULT,m)==1)
        {
            fu[m]=mirvar(0);
            cp[m]=TRUE;
        }
        else cp[m]=FALSE;
    printf("input number to be factored\n");
    cinnum(n,stdin);
    if (isprime(n))
    {
        printf("this number is prime!\n");
        return 0;
    }
    for (nt=0,k=3;k<10;k++)
    { /* try more than once for p+1 condition (may be p-1) */
        convert(k,b);              /* try b=3,4,5..        */
        convert((k*k-4),t);
        if (egcd(t,n,t)!=1) continue; /* check (b*b-4,n)!=0 */
        nt++;
        phase=1;
        p=0;
        btch=50;
        i=0;
        printf("phase 1 - trying all primes less than %d\n",LIMIT1);
        printf("prime= %8ld",p);
        forever
        { /* main loop */
            if (phase==1)
            { /* looking for all factors of p+1 < LIMIT1 */
                p=mip->PRIMES[i];
                if (mip->PRIMES[i+1]==0)
                { /* now change gear */
                    phase=2;
                    printf("\nphase 2 - trying last prime less than %ld\n"
                           ,LIMIT2);
                    printf("prime= %8ld",p);
                    copy(b,fu[1]);
                    copy(b,fp);
                    mad(b,b,b,n,n,fd);
                    decr(fd,2,fd);     
                    negify(b,t);
                    mad(fd,b,t,n,n,fn);
                    for (m=5;m<=MULT/2;m+=2)
                    { /* store fu[m] = Vm(b) */
                        negify(fp,t);
                        mad(fn,fd,t,n,n,t);
                        copy(fn,fp);
                        copy(t,fn);
                        if (!cp[m]) continue;
                        copy(t,fu[m]);
                    }
                    convert(MULT,t);    
                    lucas(b,t,n,fp,fd);
                    iv=(int)(p/MULT);
                    if (p%MULT>MULT/2) iv++;
                    interval=(long)iv*MULT;
                    p=interval+1;
                    convert(iv,t);
                    lucas(fd,t,n,fp,fvw);
                    negify(fp,fp);
                    subtract(fvw,fu[p%MULT],q);
                    marks(interval);
                    btch*=100;
                    i++;
                    continue;
                }
                pa=p;
                while ((LIMIT1/p) > pa) pa*=p;
                convert((int)pa,t);   
                lucas(b,t,n,fp,q);
                copy(q,b);
                decr(q,2,q);
            }
            else
            { /* phase 2 - looking for last large prime factor of (p+1) */
                p+=2;
                pos=(int)(p%MULT);
                if (pos>MULT/2)
                { /* increment giant step */
                    iv++;
                    interval=(long)iv*MULT;
                    p=interval+1;
                    marks(interval);
                    pos=1;
                    copy(fvw,t);
                    mad(fvw,fd,fp,n,n,fvw);
                    negify(t,fp);
                }
                if (!cp[pos]) continue;

        /* if neither interval+/-pos is prime, don't bother */
                if (!plus[pos] && !minus[pos]) continue;
                subtract(fvw,fu[pos],t);
                mad(q,t,t,n,n,q);  /* batching gcds */
            }
            if (i++%btch==0)
            { /* try for a solution */
                printf("\b\b\b\b\b\b\b\b%8ld",p);
                fflush(stdout);
                egcd(q,n,t);
                if (size(t)==1)
                {
                    if (p>LIMIT2) break;
                    else continue;
                }
                if (compare(t,n)==0)
                {
                    printf("\ndegenerate case");
                    break;
                }
                printf("\nfactors are\n");
                if (isprime(t)) printf("prime factor     ");
                else          printf("composite factor ");
                cotnum(t,stdout);
                divide(n,t,n);
                if (isprime(n)) printf("prime factor     ");
                else          printf("composite factor ");
                cotnum(n,stdout);
                return 0;
            }
        } 
        if (nt>=NTRYS) break;
        printf("\ntrying again\n");
    }
    printf("\nfailed to factor\n");
    return 0;
}
Exemple #7
0
int main()
{
    FILE *fp;
    big q,p,p1,h,t,g,low,high;
    big pool[POOL_SIZE];
    BOOL fail;
    int i,j,p1bits,np;
    long seed,m,permutation;
    miracl *mip=mirsys(100,0);
    q=mirvar(0);
    p=mirvar(0);
    h=mirvar(0);
    t=mirvar(0);
    g=mirvar(0);
    p1=mirvar(0);
    low=mirvar(0);
    high=mirvar(0);
    gprime(10000);

/* randomise */
    printf("Enter 9 digit random number seed  = ");
    scanf("%ld",&seed);
    getchar();
    irand(seed);
    
    p1bits=PBITS-QBITS-1;

/* find number of primes pa, pb, pc etc., that will be needed */

    np=1;
    while (p1bits/np >= OBITS) np++;
    np--;

/* find the high/low limits for these primes, so that 
   the generated prime p will be exactly PBITS in length */

    expb2(p1bits-1,t);
    nroot(t,np,low);      /* np-th integer root */
    incr(low,1,low);

    premult(t,2,t);
    decr(t,1,t);
    nroot(t,np,high);

    subtract(high,low,t);   /* raise low limit up to half-way...  */
    subdiv(t,2,t);
    subtract(high,t,low);

/* generate q  */
    forever
    { /* make sure leading two bits of q 11... */
        expb2(QBITS,q);
        bigbits(QBITS-2,t);
        subtract(q,t,q);
        nxprime(q,q);
        if (logb2(q)>QBITS) continue;
        break;
    }
    printf("q= (%d bits)\n",logb2(q));
    cotnum(q,stdout);

/* generate prime pool from which permutations of np 
   primes will be picked until a Lim-Lee prime is found */

    for (i=0;i<POOL_SIZE;i++)
    { /* generate the primes pa, pb, pc etc.. */
        pool[i]=mirvar(0);
        forever
        { 
            bigrand(high,p1);
            if (mr_compare(p1,low)<0) continue;
            nxprime(p1,p1);
            if (mr_compare(p1,high)>0) continue;
            copy(p1,pool[i]);  
            break;
        }
    }

/* The '1' bits in the permutation indicate which primes are 
   picked from the pool. If np=5, start at 11111, then 101111 etc */

    permutation=1L;
    for (i=0;i<np;i++) permutation<<=1;
    permutation-=1;     /* permuation = 2^np-1 */

/* generate p   */
    fail=FALSE;
    forever 
    {
        convert(1,p1);
        for (i=j=0,m=1L;j<np;i++,m<<=1)
        {
            if (i>=POOL_SIZE) 
            { /* ran out of primes... */
                fail=TRUE;
                break;
            }
            if (m&permutation) 
            {
                multiply(p1,pool[i],p1); 
                j++;
            }
        } 
        if (fail) break;
        printf(".");   
        premult(q,2,p);
        multiply(p,p1,p);
        incr(p,1,p);
        permutation=increment(permutation);
        if (logb2(p)!=PBITS) continue;
        if (isprime(p)) break; 
    } 

    if (fail)
    {
        printf("\nFailed - very unlikely! - try increasing POOL_SIZE\n");
        return 0;
    }

    printf("\np= (%d bits)\n",logb2(p));
    cotnum(p,stdout);

/* finally find g */
    do {
        decr(p,1,t);
        bigrand(t,h);
        divide(t,q,t);
        powmod(h,t,p,g);
    } while(size(g)==1);    
   
    printf("g= (%d bits)\n",logb2(g));
    cotnum(g,stdout);

    fp=fopen("common.dss","wt");
    fprintf(fp,"%d\n",PBITS);
    mip->IOBASE=16;
    cotnum(p,fp);
    cotnum(q,fp);
    cotnum(g,fp);
    fclose(fp);
    return 0;
}