/* For Copyright and License see LICENSE.txt and COPYING.txt in the root directory */ package com.nerdscentral.audio.pitch.algorithm; import static java.lang.Math.cos; import static java.lang.Math.exp; import static java.lang.Math.hypot; import static java.lang.Math.sin; import static java.lang.Math.sqrt; import com.nerdscentral.sython.SFMaths; /** A straight port from C - so very, very static! */ public class SFComplex { public double re; public double im; public SFComplex(double r, double i) { this.re = r; this.im = i; } public SFComplex() { } static SFComplex czero = new SFComplex(0.0, 0.0); static SFComplex evaluate(SFComplex[] topco, int nz, SFComplex[] botco, int np, double z) { /* evaluate response, substituting for z */ SFComplex z2 = new SFComplex(z, 0); return cdiv(eval(topco, nz, z2), eval(botco, np, z2)); } static SFComplex evaluate(SFComplex[] topco, SFComplex[] botco, int np, SFComplex z) { /* evaluate response, substituting for z */ return cdiv(eval(topco, np, z), eval(botco, np, z)); } static SFComplex eval(SFComplex[] coeffs, int np, SFComplex z) { /* evaluate polynomial in z, substituting for z */ SFComplex sum; int i; sum = czero; for (i = np; i >= 0; i--) sum = cadd(cmul(sum, z), coeffs[i]); return sum; } static SFComplex csqrt(SFComplex x) { SFComplex z = new SFComplex(); double r = hypot(x.im, x.re); z.re = Xsqrt(0.5 * (r + x.re)); z.im = Xsqrt(0.5 * (r - x.re)); if (x.im < 0.0) z.im = -z.im; return z; } static double Xsqrt(double x) { /* * because of deficiencies in hypot on Sparc, it's possible for arg of Xsqrt to be small and -ve, which logically it can't * be (since r >= |x.re|). Take it as 0. Probably non relevant In Java! */ return (x >= 0.0) ? sqrt(x) : 0.0; } static SFComplex cexp(SFComplex x) { SFComplex z = new SFComplex(); double r; r = exp(x.re); z.re = r * cos(x.im); z.im = r * sin(x.im); return z; } static SFComplex cconj(SFComplex x) { SFComplex z = new SFComplex(); z.re = x.re; z.im = -x.im; return z; } static SFComplex cadd(SFComplex x, SFComplex y) { SFComplex z = new SFComplex(); z.re = x.re + y.re; z.im = x.im + y.im; return z; } static SFComplex csub(SFComplex x, SFComplex y) { SFComplex z = new SFComplex(); z.re = x.re - y.re; z.im = x.im - y.im; return z; } static SFComplex cmul(SFComplex x, SFComplex y) { SFComplex z = new SFComplex(); z.re = (x.re * y.re - x.im * y.im); z.im = (x.im * y.re + x.re * y.im); return z; } static SFComplex cdiv(SFComplex x, SFComplex y) { SFComplex z = new SFComplex(); double mag = y.re * y.re + y.im * y.im; z.re = (x.re * y.re + x.im * y.im) / mag; z.im = (x.im * y.re - x.re * y.im) / mag; return z; } static void multin(SFComplex w, int npz, SFComplex coeffs[]) { /* multiply factor (z-w) into coeffs */ SFComplex nw = SFComplex.cmul(w, new SFComplex(-1, 0)); for (int i = npz; i >= 1; i--) { coeffs[i] = SFComplex.cadd((SFComplex.cmul(nw, coeffs[i])), coeffs[i - 1]); } coeffs[0] = SFComplex.cmul(nw, coeffs[0]); } static SFComplex expj(double theta) { return new SFComplex(SFMaths.cos(theta), SFMaths.sin(theta)); } static SFComplex evaluate(SFComplex topco[], int nz, SFComplex botco[], int np, SFComplex z) { return SFComplex.cdiv(eval(topco, nz, z), eval(botco, np, z)); } }