matlab ellipord函数 C实现

ellipord

void ellipord(double *w, int nw, double rp, double rs, int *order, double *wn)
{
    int type=0;
	double* wp=(double*)malloc(sizeof(double)*nw/2);
	double* ws=(double*)malloc(sizeof(double)*nw/2);
	double* temp=(double*)malloc(sizeof(double)*nw/2);
	double* WA=(double*)malloc(sizeof(double)*nw/2);
	double* WN=(double*)malloc(sizeof(double)*nw/2);

	for(int i=0;i<nw/2;i++)
	{
		wp[i]=w[i];
        temp[i]=wp[i];
		ws[i]=w[nw/2+i];
	}

	if(nw==2)
	{
		type=0;
	}
	else if(nw==4)
	{
		type=2;
	}
	if(wp[0]<ws[0])
	{
		type+=1;
	}
	else
	{
		type+=2;
	}


	for(int i=0;i<nw/2;i++)
	{
		wp[i]=tan(PI*wp[i]/2.0);
		ws[i]=tan(PI*ws[i]/2.0);
	}

    if (type == 1)
    {
        // low
        for (int i = 0; i < nw / 2; i++)
        {
            WA[i] = ws[i] / wp[i];
        }
        *order = findelliporder(WA, nw / 2, rp, rs);
    }
    else if (type == 2)
    {
        // high
        for (int i = 0; i < nw / 2; i++)
        {
            WA[i] = wp[i] / ws[i];
        }
        *order = findelliporder(WA, nw / 2, rp, rs);
    }
    else if (type == 3)
    {
        double Fpass1 = wp[0];
        double Fpass2 = wp[1];
        double Fstop1 = ws[0];
        double Fstop2 = ws[1];
        double c = sin(PI * (Fpass1 + Fpass2)) / (sin(PI * Fpass1) + sin(PI * Fpass2));
        double wpa = fabs(sin(PI * Fpass2) / (cos(PI * Fpass2) - c));
        double ws1 = sin(PI * Fstop1) / (cos(PI * Fstop1) - c);
        double ws2 = sin(PI * Fstop2) / (cos(PI * Fstop2) - c);
        double wsa = fmin(fabs(ws1), fabs(ws2));
        double* w=(double*)malloc(sizeof(double)*2);
        w[0]=wpa;
        w[1]=wsa;
        *order=ellipords(w,2,rp,rs);
        free(w);
    }
    else if(type ==4)
    {
         for (int i = 0; i < nw / 2; i++)
         {
            WA[i]=(ws[i]*ws[i] - wp[0]*wp[1])/(ws[i]*(wp[0]-wp[1]));
         }
         *order = findelliporder(WA, nw / 2, rp, rs);
    }

    for (int i = 0; i < nw / 2; i++)
    {
        wn[i]=temp[i];
    }

    free(temp);
    free(wp);
    free(ws);
    free(WN);
    free(WA);
}

其中ellipords代码如下:

int ellipords(double *w, int nw, double rp, double rs)
{
    int order=0;
    int type=0;
	double* wp=(double*)malloc(sizeof(double)*nw/2);
	double* ws=(double*)malloc(sizeof(double)*nw/2);
	double* WA=(double*)malloc(sizeof(double)*nw/2);
	double* WN=(double*)malloc(sizeof(double)*nw/2);
	double W0;

	for(int i=0;i<nw/2;i++)
	{
		wp[i]=w[i];
		ws[i]=w[nw/2+i];
	}

	if(nw==2)
	{
		type=0;
	}
	else if(nw==4)
	{
		type=2;
	}
	if(wp[0]<ws[0])
	{
		type+=1;
	}
	else
	{
		type+=2;
	}

    if (type == 1)
    {
        // low
        for (int i = 0; i < nw / 2; i++)
        {
            WA[i] = ws[i] / wp[i];
        }
        order = findelliporder(WA, nw / 2, rp, rs);
    }
    else if (type == 2)
    {
        // high
        for (int i = 0; i < nw / 2; i++)
        {
            WA[i] = wp[i] / ws[i];
        }
        order = findelliporder(WA, nw / 2, rp, rs);
    }
    else if (type == 3)
    {
        for (int i = 0; i < nw / 2; i++)
        {
            wp[i] = tan(PI * wp[i] / 2.0);
            ws[i] = tan(PI * ws[i] / 2.0);
        }

        double Fpass1 = wp[0];
        double Fpass2 = wp[1];
        double Fstop1 = ws[0];
        double Fstop2 = ws[1];
        double c = sin(PI * (Fpass1 + Fpass2)) / (sin(PI * Fpass1) + sin(PI * Fpass2));
        double wpa = fabs(sin(PI * Fpass2) / (cos(PI * Fpass2) - c));
        double ws1 = sin(PI * Fstop1) / (cos(PI * Fstop1) - c);
        double ws2 = sin(PI * Fstop2) / (cos(PI * Fstop2) - c);
        double wsa = fmin(fabs(ws1), fabs(ws2));
        double* w=(double*)malloc(sizeof(double)*2);
        w[0]=wpa;
        w[1]=wsa;
        order=ellipords(w,2,rp,rs);
        free(w);
    }
    else if(type ==4)
    {
         for (int i = 0; i < nw / 2; i++)
         {
            WA[i]=(ws[i]*ws[i] - wp[0]*wp[1])/(ws[0]*(wp[0]-wp[1]));
         }
         order = findelliporder(WA, nw / 2, rp, rs);
    }

    free(wp);
    free(ws);
    free(WN);
    free(WA);

    return order;
}

其中findelliporder代码如下:

int findelliporder(double* wa,int size,double rp,double rs)
{
    int order;
    double minWA = INFINITY;
    double epsilon;
    double k1;
    double k;
    // Assuming ellipke function is already defined
    double *ks = (double *)malloc(sizeof(double) * 2);
    double *ks1 = (double *)malloc(sizeof(double) * 2);

    for (int i = 0; i < size; i++)
    {
        double absValue = fabs(wa[i]);
        minWA = fmin(minWA, absValue);
    }

    epsilon = sqrt(pow(10, 0.1 * rp) - 1.0);
    k1 = epsilon / sqrt(pow(10, 0.1 * rs) - 1.0);
    k = 1.0 / minWA;
    ks[0] = k * k;
    ks[1] = 1 - k * k;
    ks1[0] = k1 * k1;
    ks1[1] = 1 - k1 * k1;
    double *capk = ellipke(ks, 2);
    double *capk1 = ellipke(ks1, 2);
    order = ceil((capk[0] * capk1[1]) / (capk[1] * capk1[0]));

    free(ks);
    free(ks1);
    free(capk);
    free(capk1);
    return order;
}

又出现函数ellipke实现如下:

double* ellipke(double* m, int size) 
{
     double tol=EPS;
     double* e=(double*)malloc(sizeof(double)*size);
     double* k=(double*)malloc(sizeof(double)*size);
    for (int i = 0; i < size; i++) {
        double mi = m[i];

        double classin = (mi == 0.0) ? 0.0 : (mi == 1.0) ? 1.0 : 2.0 * mi;
       
        if (mi == 0) {
            k[i] = 0;
            e[i] = 0;
            continue;
        }

        if (mi == 1) {
            k[i] = INFINITY;
            e[i] = INFINITY;
            continue;
        }
        double a0 = 1;
        double b0 = sqrt(1 - mi);
        double c0 = NAN;
        double s0 = mi;
        int i1 = 0;
        double mm = INFINITY;

        while (mm > tol) {
            double a1 = (a0 + b0) / 2;
            double b1 = sqrt(a0 * b0);
            double c1 = (a0 - b0) / 2;
            i1++;

            double w1 = pow(2, i1) * pow(c1, 2);
            mm = fmax(w1, 0);

            s0 += w1;
            a0 = a1;
            b0 = b1;
            c0 = c1;
        }

        k[i] = PI / (2 * a0);
        e[i] = k[i] * (1 - s0 / 2);

        if (mi == 1) {
            k[i] = INFINITY;
            e[i] = 1;  // or some other value based on your specific case
        }
    }

    return k;
}

经过和matlab函数对比,验证无误。