Skip to content

Instantly share code, notes, and snippets.

@mnemocron
Last active April 27, 2018 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnemocron/41957a35eda9dc3aead6cc5f313c7036 to your computer and use it in GitHub Desktop.
Save mnemocron/41957a35eda9dc3aead6cc5f313c7036 to your computer and use it in GitHub Desktop.
Fensterfunktionen für Signalverarbeitung
package pro2e.matlabfunctions;
import java.math.BigDecimal;
public class Fensterfunktionen {
/**
* @brief enumerations for the different window functions
*/
public static final int RECTANGULAR = 0;
public static final int CHEBYSHEV = 1;
public static final int BINOMIAL = 2;
public static final int COSINE = 3;
public static final int COSINESQUARE = 4;
public static final int VONHANN = 5;
public static final int HANNING = 6;
public static final int BLACKMAN = 7;
public static final int WELCH = 8;
public static final int BARTLETT = 9;
public static final int BARTLETTHANN = 10;
public static final int TRIANGULAR = 11;
public static final int EXPONENTIAL = 12;
public static enum Window {
RECTANGULAR, CHEBYSHEV, BINOMIAL, COSINE, COSINESQUARE, VONHANN, HANNING, BLACKMAN, WELCH, BARTLETT, BARTLETTHANN, TRIANGULAR, EXPONENTIAL
};
/**
* @brief Quantisierungsfunktion nach Binärwerten - Methode: Floor
* @param val
* array of normalized values (range: 0-1)
* @param bits
* the number of bits
* @return
*/
public static double[] Quantize(double[] val, int bits) {
double[] out = new double[val.length];
for (int i = 0; i < val.length; i++) {
// out[i]=quantize(val[i], bits);
out[i] = RoundToBinary(val[i], bits, ROUND_FLOOR);
}
return out;
}
/**
* @TODO TESTING
* @brief Quantisierungsfunktion nach Binärwerten - Methode: Round-Up
* @param val
* @param bits
* @return
*/
public static double Quantize(double val, int bits) {
int resolution = (int) Math.pow(2, bits);
double step = 1.0 / resolution;
double ret = 0;
while (ret < val) {
ret += step;
}
return ret;
}
public static final int ROUND_FLOOR = 0;
public static final int ROUND_CEIL = 1;
public static final int ROUND_NEAREST = 2;
/**
*
* @param val
* @param bits
* @param method
* @return
*/
public static double RoundToBinary(double val, int bits, int method) {
int resolution = (int) Math.pow(2, bits);
double step = 1.0 / resolution;
double ret = 0;
if (method == ROUND_CEIL) {
ret = 0;
while (ret < val) {
ret += step;
}
}
if (method == ROUND_FLOOR) {
ret = Math.pow(2, bits);
while (ret > val) {
ret -= step;
}
}
if (method == ROUND_NEAREST) {
/** @TODO */
}
return ret;
}
/**
* @brief Rechteckfenster / entspricht dem Matlab-Befehl ones(1, N)
* @param N
* @return
*/
public static double[] Rectangular(int N) {
double[] out = new double[N];
for (int i = 0; i < out.length; i++) {
out[i] = 1;
}
return out;
}
/**
* @brief Dreiecksfenster (ohne Anheben)
* @param N
* @return
*/
public static double[] Triangular(int N) {
int gerade;
double[] FensterfunktionDreieck = new double[N];
for (int i = 0; i < ((N / 2) + 1); i++) {
FensterfunktionDreieck[i] = 1.0 - Math.abs(((i) - (N) / 2.0) / ((N) / 2.0));
}
if ((N) % 2 == 0) {
gerade = 1;
} else {
gerade = 0;
}
for (int i = 0; i < ((N) / 2) + gerade; i++) {
FensterfunktionDreieck[N - 1 - i] = FensterfunktionDreieck[i];
}
return FensterfunktionDreieck;
}
/**
* @brief Exponentialfunktion mit anpassbarer Steigung
* @param N
* @param steigung
* @return
*/
public static double[] Exponential(int N, double steigung) {
double[] FensterExponential = new double[N];
for (int i = 0; i < N; i++) {
FensterExponential[i] = Math
.exp(-Math.abs((i) - ((N - 1.0) / 2.0)) * (1 / ((N * 8.69) / (2.0 * steigung))));
}
return FensterExponential;
}
/**
* @brief Binominal-Fenster
* @details Das Binomial-Fenster unterdr�ckt s�mtliche Nebenkeulen in einer
* Arrayantennen-Anwendung
* @note Dependency: MiniMatlab Funktion
*
* <pre>
* BigDecimal factorial(int num)
* </pre>
*
* @param N
* @return
*/
public static double[] Binominal(int N) {
double[] d = new double[N];
/**
* @NOTE Calculating using double numbers only works up to N~20 --> using
* BigDecimal for greater values
*/
if (N > 18) { // Slower Algorithm but works with greater numbers
BigDecimal[] out = new BigDecimal[N];
for (int k = 0; k < out.length; k++) {
BigDecimal big = MiniMatlab.factorialBig(N - 1)
.divide((MiniMatlab.factorialBig(k)).multiply(MiniMatlab.factorialBig((N - 1) - k)));
out[k] = big;
}
d = MiniMatlab.normalize(out);
} else { // Quicker Algorithm with double numbers
double[] out = new double[N];
for (int k = 0; k < out.length; k++) {
double big = MiniMatlab.factorial(N - 1)
/ ((MiniMatlab.factorial(k)) * (MiniMatlab.factorial((N - 1) - k)));
out[k] = big;
}
d = MiniMatlab.normalize(out);
}
return d;
}
/**
* This function computes the chebyshev polyomial T_n(x)
*
* @param n
* @param x
* @return
* @see http://practicalcryptography.com/miscellaneous/machine-learning/implementing-dolph-chebyshev-window/
*/
private static double Cheby_poly(int n, double x) {
double res;
if (Math.abs(x) <= 1)
res = Math.cos(n * Math.acos(x));
else
res = Math.cosh(n * MiniMatlab.acosh(x));
return res;
}
/**
* @brief Dolph Chebyshev Fenster - entspricht dem Matlab commad chebwin()
* chebwin(N,R) returns the N-point Chebyshev window with R decibels of
* relative sidelobe attenuation.
* @param N
* size of output array
* @param atten
* attenuation
* @return
* @see http://practicalcryptography.com/miscellaneous/machine-learning/implementing-dolph-chebyshev-window/
*/
public static double[] Chebwin(int N, double atten) {
double[] out = new double[N];
int nn, i;
double M, n, sum = 0, max = 0;
double tg = Math.pow(10, atten / 20); /* 1/r term [2], 10^gamma [2] */
double x0 = Math.cosh((1.0 / (N - 1)) * MiniMatlab.acosh(tg));
M = (N - 1) / 2;
if (N % 2 == 0)
M = M + 0.5; /* handle even length windows */
for (nn = 0; nn < (N / 2 + 1); nn++) {
n = nn - M;
sum = 0;
for (i = 1; i <= M; i++) {
sum += Cheby_poly(N - 1, x0 * Math.cos(Math.PI * i / N)) * Math.cos(2.0 * n * Math.PI * i / N);
}
out[nn] = tg + 2 * sum;
out[N - nn - 1] = out[nn];
if (out[nn] > max)
max = out[nn];
}
for (nn = 0; nn < N; nn++)
out[nn] /= max; /* normalise everything */
return out;
}
/**
* @brief Cosinusfenster (anhebbar)
* @param N
* @param x
* @return
*/
public static double[] Cosin(int N, double x) {
double[] out = new double[N];
for (int i = 0; i < N; i++) {
out[i] = x * Math.cos(((Math.PI * i) / (N - 1)) - (Math.PI / 2)) + (1.0 - x);
}
return out;
}
public static double[] CosinSquare(int N, double x) {
double[] out = new double[N];
for (int i = 0; i < N; i++) {
out[i] = Math.pow(x * Math.cos(((Math.PI * i) / (N - 1)) - (Math.PI / 2)) + (1.0 - x), 2);
}
return out;
}
/**
* @brief von Hann Fenster
* @note Tested: working
* @param size
* @return
*/
public static double[] VonHann(int size) {
double[] samples = new double[size];
for (int i = 0; i < size; i++) {
samples[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / (double) (size - 1)));
}
return samples;
}
/**
* @brief Hanning Fenster
* @note Tested: working
* @param size
* @return
*/
public static double[] Hanning(int size) {
double[] samples = new double[size];
for (int i = 0; i < size; ++i) {
samples[i] = (1 * 0.5 * (1.0 - Math.cos(2 * Math.PI * i / (size - 1))));
}
return samples;
}
/**
* @brief Blackman Fenster
* @note Tested: working
* @param size
* @return
*/
public static double[] Blackman(int size) {
double[] samples = new double[size];
double alpha = 0.16, a0 = (1.0 - alpha) / 2.0, a1 = 0.5, a2 = alpha / 2.0;
for (int i = 0; i < size; ++i) {
samples[i] = a0 - a1 * Math.cos((2 * Math.PI * i) / (double) (size - 1))
+ a2 * Math.cos((4 * Math.PI * i) / (double) (size - 1));
}
return samples;
}
/**
* @brief Welch Fenster
* @note Tested: working
* @param size
* @return
*/
public static double[] Welch(int size) {
double[] samples = new double[size];
for (int i = 0; i < size; ++i) {
samples[i] = (1 * (1 - Math.pow((double) (i - ((size - 1) / 2)) / (double) ((size - 1) / 2), 2)));
}
return samples;
}
/**
* @brief Bartlett Hann Fenster
* @note Tested: working
* @param size
* @return
*/
public static double[] BartlettHann(int size) {
double[] samples = new double[size];
double a0 = 0.62, a1 = 0.48, a2 = 0.38;
for (int i = 0; i < size; ++i) {
samples[i] = a0 - a1 * Math.abs((((double) i) / (double) (size - 1)) - 0.5)
- a2 * Math.cos((2 * Math.PI * i) / (double) (size - 1));
}
return samples;
}
}
package pro2e.matlabfunctions;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator;
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
import org.apache.commons.math3.analysis.solvers.LaguerreSolver;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.transform.DftNormalization;
import org.apache.commons.math3.transform.FastFourierTransformer;
import org.apache.commons.math3.transform.TransformType;
public class MiniMatlab {
static final FastFourierTransformer transformer = new FastFourierTransformer(DftNormalization.STANDARD);
static final SplineInterpolator interpolator = new SplineInterpolator();
/**
* @brief berechnet die Summe aller Werte im Array a
* @param a
* @return
*/
public static double sum(double[] a) {
double sum = 0.0;
for(int ii=0; ii<a.length; ii++) {
sum += a[ii];
}
return sum;
}
/**
* @brief gibt Absolutwerte eines Complex Arrays zurück
* @param z
* @return
*/
public static double[] abs(Complex[] z) {
double[] ret = new double[z.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = z[i].abs();
}
return ret;
}
/**
* @brief gibt den Absolutwert der Zahl a zurück
* @param z
* @return
*/
public static double abs(double a) {
if(a >= 0) return a;
else return -a;
}
/**
* @brief gibt Absolutwerte eines double Arrays zurück
* @param z
* @return
*/
public static double[] abs(double[] a) {
double[] ret = new double[a.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = abs(a[i]);
}
return ret;
}
/**
* @brief gibt die kleinere Zahl von a und b zurück
* @param a
* @param b
* @return
*/
public static int min(int a, int b) {
if(a < b)
return a;
else
return b;
}
/**
* @brief gibt die kleinste Zahl aus dem Array a zurück
* @param a
* @return
*/
public static int min(int[] a) {
int min = 0;
for(int i=0; i<a.length; i++) {
if(a[i]<min) min = a[i];
}
return min;
}
/**
* @brief gibt die grössere Zahl von a und b zurück
* @param a
* @param b
* @return
*/
public static int max(int a, int b) {
if(a > b)
return a;
else
return b;
}
/**
* @brief gibt die grösste Zahl aus dem Array a zurück
* @param a
* @return
*/
public static int max(int[] a) {
int max = 0;
for(int i=0; i<a.length; i++) {
if(a[i]>max) max = a[i];
}
return max;
}
/**
* @brief gibt die grösste Zahl aus dem Array a zurück
* @param a
* @return
*/
public static double max(double[] a) {
double max = 0;
for(int i=0; i<a.length; i++) {
if(a[i]>max) max = a[i];
}
return max;
}
/**
* @brief gibt die grösste Zahl aus dem Array a zurück
* @param a
* @return
*/
public static BigDecimal max(BigDecimal[] a) {
BigDecimal max = BigDecimal.ZERO;
for(int i=0; i<a.length; i++) {
if(a[i].compareTo(max) == 1)
max = a[i];
}
return max;
}
/**
* @brief normalisiert die das Array a auf eine Skala von -1 bis +1
* @param a
* @return
*/
public static double[] normalize(double[] a) {
double max = max(abs(a));
for (int i = 0; i < a.length; i++) {
a[i] /= max;
}
return a;
}
/**
* @brief Berechnet die Absolutwerte eines BigDecimal Arrays
* @param a
* @return
*/
public static BigDecimal[] abs(BigDecimal[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = a[i].abs();
}
return a;
}
public static double[] normalize(BigDecimal[] a) {
BigDecimal max = max(abs(a));
for (int i = 0; i < a.length; i++) {
a[i] = a[i].divide(max, 10, RoundingMode.HALF_UP); // Rundungspräzision einstellen (10 Nachkommastellen)
}
double[] d = new double[a.length];
for (int i = 0; i < d.length; i++) {
d[i] = a[i].doubleValue();
}
return d;
}
/**
* @brief berechnet den Arcuscosinushyperbolicus
* @param x
* @return
*/
public static double acosh(double x) {
return Math.log(x + Math.sqrt(x * x - 1.0));
}
public static String add(String s1, String s2) {
String[] a = s1.split("[, ]+");
String[] b = s2.split("[, ]+");
String res = "";
if (a.length < b.length) {
String[] tmp = a;
a = b;
b = tmp;
}
String[] bb = new String[a.length];
for (int i = 0; i < bb.length; i++) {
bb[i] = "";
}
for (int i = 0; i < b.length; i++) {
bb[i + (a.length - b.length)] = b[i];
}
for (int n = 0; n < a.length; n++) {
if (bb[n].length() == 0)
res += "(" + a[n] + ") ";
else
res += "(" + a[n] + ")+" + "(" + bb[n] + ") ";
}
return res;
}
/**
* @brief Berechnet den Arcussinushyperbolicus
* @param x
* @return
*/
public static double asinh(double x) {
return Math.log(x + Math.sqrt(x * x + 1.0));
}
/**
* <pre>
* Prüft ob exp und act, auf n signifikante Stellen, übereinstimmen.
* </pre>
*
* @param exp
* @param act
* @param n
* @return
*/
public static boolean assertEq(double exp, double act, int n) {
String fmt = "0.";
for (int j = 0; j < n - 1; j++) {
fmt += "0";
}
fmt += "E000";
DecimalFormat decimalFormat = new DecimalFormat(fmt);
String stExp = decimalFormat.format(exp);
String stAct = decimalFormat.format(act);
return stExp.equals(stAct);
}
public static double atanh(double x) {
return 0.5 * Math.log((x + 1.0) / (x - 1.0));
}
public static final double[] c2d(Complex[] c) {
double[] d = new double[c.length];
for (int i = 0; i < d.length; i++) {
d[i] = c[i].getReal();
}
return d;
}
public static final Complex[] colon(Complex[] a, int begin, int end) {
Complex[] res = new Complex[end - begin + 1];
for (int i = 0; i <= end - begin; i++) {
res[i] = new Complex(a[begin + i].getReal(), a[begin + i].getImaginary());
}
return res;
}
public static final double[] colon(double[] a, int begin, int end) {
double[] res = new double[end - begin + 1];
for (int i = 0; i <= end - begin; i++) {
res[i] = a[begin + i];
}
return res;
}
public static final Complex[] colonColon(Complex[] a, int begin, int step, int end) {
Complex[] res = new Complex[Math.abs((end - begin) / step) + 1];
for (int i = 0; i <= Math.abs((end - begin) / step); i++) {
res[i] = new Complex(a[begin + i * step].getReal(), a[begin + i * step].getImaginary());
}
return res;
}
public static final double[] colonColon(double[] a, int begin, int step, int end) {
double[] res = new double[Math.abs((end - begin) / step) + 1];
for (int i = 0; i <= Math.abs((end - begin) / step); i++) {
res[i] = a[begin + i * step];
}
return res;
}
public static final Complex[] concat(Complex[] a, Complex b) {
Complex[] res = new Complex[a.length + 1];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = new Complex(a[i].getReal(), a[i].getImaginary());
}
res[k++] = new Complex(b.getReal(), b.getImaginary());
return res;
}
public static final Complex[] concat(Complex[] a, Complex b, Complex[] c) {
Complex[] res = new Complex[a.length + 1 + c.length];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = new Complex(a[i].getReal(), a[i].getImaginary());
}
res[k++] = new Complex(b.getReal(), b.getImaginary());
for (int i = 0; i < c.length; i++) {
res[k++] = new Complex(c[i].getReal(), c[i].getImaginary());
}
return res;
}
public static final Complex[] concat(Complex[] a, Complex[] b) {
Complex[] res = new Complex[a.length + b.length];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = new Complex(a[i].getReal(), a[i].getImaginary());
}
for (int i = 0; i < b.length; i++) {
res[k++] = new Complex(b[i].getReal(), b[i].getImaginary());
}
return res;
}
public static final double[] concat(double[] a, double b) {
double[] res = new double[a.length + 1];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = a[i];
}
res[k++] = b;
return res;
}
public static final double[] concat(double[] a, double b, double[] c) {
double[] res = new double[a.length + 1 + c.length];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = a[i];
}
res[k++] = b;
for (int i = 0; i < c.length; i++) {
res[k++] = c[i];
}
return res;
}
public static final double[] concat(double[] a, double[] b) {
double[] res = new double[a.length + b.length];
int k = 0;
for (int i = 0; i < a.length; i++) {
res[k++] = a[i];
}
for (int i = 0; i < b.length; i++) {
res[k++] = b[i];
}
return res;
}
public static final Complex[] conj(Complex[] a) {
Complex[] res = new Complex[a.length];
for (int i = 0; i < res.length; i++) {
res[i] = new Complex(a[i].getReal(), -a[i].getImaginary());
}
return res;
}
public static final Complex[] conv(Complex[] a, Complex[] b) {
Complex[] res = new Complex[a.length + b.length - 1];
for (int n = 0; n < res.length; n++) {
res[n] = new Complex(0, 0);
for (int i = Math.max(0, n - a.length + 1); i <= Math.min(b.length - 1, n); i++) {
res[n] = res[n].add(b[i].multiply(a[n - i]));
}
}
return res;
}
public static final double[] conv(double[] a, double[] b) {
double[] res = new double[a.length + b.length - 1];
for (int n = 0; n < res.length; n++) {
for (int i = Math.max(0, n - a.length + 1); i <= Math.min(b.length - 1, n); i++) {
res[n] += b[i] * a[n - i];
}
}
return res;
}
public static final String conv(String s1, String s2) {
String[] a = s1.split("[, ]+");
String[] b = s2.split("[, ]+");
String[] res = new String[a.length + b.length - 1];
String s = "";
for (int n = 0; n < a.length + b.length - 1; n++) {
res[n] = "";
for (int i = Math.max(0, n - a.length + 1); i <= Math.min(b.length - 1, n); i++) {
if (!a[n - i].equals("0") && !b[i].equals("0")) {
if (res[n].length() == 0) {
res[n] += b[i] + "*" + "(" + a[n - i] + ")";
} else {
res[n] += "+" + b[i] + "*" + "(" + a[n - i] + ")";
}
}
}
if (res[n].length() == 0)
res[n] = " 0 ";
else
res[n] += " ";
s += res[n];
}
return s;
}
public static double[][] csvread(String dateiName) {
double[][] data = null;
int nLines = 0;
int nColumns = 0;
try {
// Anzahl Zeilen und Anzahl Kolonnen festlegen:
BufferedReader eingabeDatei = new BufferedReader(new FileReader(dateiName));
String[] s = eingabeDatei.readLine().split("[, ]+");
nColumns = s.length;
while (eingabeDatei.readLine() != null) {
nLines++;
}
eingabeDatei.close();
// Gezählte Anzahl Zeilen und Kolonnen lesen:
eingabeDatei = new BufferedReader(new FileReader(dateiName));
data = new double[nLines][nColumns];
for (int i = 0; i < data.length; i++) {
s = eingabeDatei.readLine().split("[, ]+");
for (int k = 0; k < s.length; k++) {
data[i][k] = Double.parseDouble(s[k]);
}
}
eingabeDatei.close();
} catch (IOException exc) {
System.err.println("Dateifehler: " + exc.toString());
}
return data;
}
public static final Complex[] fft(Complex[] x) {
Complex[] X = transformer.transform(x, TransformType.FORWARD);
return X;
}
public static final Complex[] fft(double[] x) {
Complex[] X = transformer.transform(x, TransformType.FORWARD);
return X;
}
/**
* Berechnet den Frequenzgang aufgrund von Zähler- und Nennerpolynom b resp. a
* sowie der Frequenzachse f.
*
* @param b
* Zählerpolynom
* @param a
* Nennerpolynom
* @param f
* Frequenzachse
* @return Komplexwertiger Frequenzgang.
*/
public static final Complex[] freqs(double[] b, double[] a, double[] f) {
Complex[] res = new Complex[f.length];
for (int k = 0; k < res.length; k++) {
Complex jw = new Complex(0, 2.0 * Math.PI * f[k]);
Complex zaehler = MiniMatlab.polyval(b, jw);
Complex nenner = MiniMatlab.polyval(a, jw);
res[k] = zaehler.divide(nenner);
}
return res;
}
public static final Complex[] ifft(Complex[] X) {
Complex[] x = transformer.transform(X, TransformType.INVERSE);
return x;
}
public static final double[] linspace(double begin, double end, int cnt) {
double[] res = new double[cnt];
double delta = (end - begin) / (cnt - 1);
res[0] = begin;
for (int i = 1; i < res.length - 1; i++) {
res[i] = begin + i * delta;
}
res[res.length - 1] = end;
return res;
}
public static final double[] multiply(double[] a, double b) {
for (int i = 0; i < a.length; i++) {
a[i] *= b;
}
return a;
}
public static final double[] ones(int i) {
double[] p = new double[i];
for (int j = 0; j < p.length; j++) {
p[j] = 1.0;
}
return p;
}
public static final Complex[] poly(Complex[] v) {
Complex[] c = { new Complex(1.0, 0.0), v[0].negate() };
for (int i = 1; i < v.length; i++) {
c = conv(c, new Complex[] { new Complex(1.0, 0.0), v[i].negate() });
}
return c;
}
public static final double[] poly(double[] v) {
double[] res = { 1.0, -v[0] };
for (int i = 1; i < v.length; i++) {
res = conv(res, new double[] { 1.0, -v[i] });
}
return res;
}
public static final double[] polyReal(Complex[] v) {
Complex[] c = { new Complex(1.0, 0.0), v[0].negate() };
for (int i = 1; i < v.length; i++) {
c = MiniMatlab.conv(c, new Complex[] { new Complex(1.0, 0.0), v[i].negate() });
}
double[] res = new double[c.length];
for (int i = 0; i < c.length; i++) {
res[i] = c[i].getReal();
}
return res;
}
public static final Complex polyval(Complex[] p, Complex x) {
// if (Complex.equals(x, Complex.ZERO)) {
// x = new Complex(1e-12, 0.0);
// }
Complex res = new Complex(0, 0);
for (int i = 0; i < p.length; i++) {
res = res.add(x.pow(p.length - i - 1).multiply(p[i]));
}
return res;
}
public static final Complex polyval(double[] p, Complex x) {
Complex res = new Complex(0, 0);
for (int i = 0; i < p.length; i++) {
res = res.add(x.pow(p.length - i - 1).multiply(p[i]));
}
return res;
}
public static void print(String s, Complex[] x) {
System.out.println(s + " = [\t" + x[0].getReal() + " + " + x[0].getImaginary() + "i,");
for (int i = 1; i < x.length - 1; i++) {
System.out.println("\t" + x[i].getReal() + " + " + x[i].getImaginary() + "i,");
}
System.out.println("\t" + x[x.length - 1].getReal() + " + " + x[x.length - 1].getImaginary() + "i];");
}
public static void print(String s, double[] x) {
if (x.length == 1) {
System.out.println(s + " = \t" + x[0] + ";");
} else {
System.out.println(s + " = [\t" + x[0] + ",");
for (int i = 1; i < x.length - 1; i++) {
System.out.println("\t" + x[i] + ",");
}
System.out.println("\t" + x[x.length - 1] + "]';");
}
}
public static double[] real(Complex[] c) {
double[] res = new double[c.length];
for (int i = 0; i < res.length; i++) {
res[i] = c[i].getReal();
}
return res;
}
public static final Object[] residue(double[] b, double[] a) {
double K = 0;
Polynom B = new Polynom(b);
B.trim();
Polynom A = new Polynom(a);
A.trim();
int N = B.length() - 1;
int M = A.length() - 1;
if (N == M) {
K = B.p[0] / A.p[0];
B = B.subtract(A.multiply(K));
}
Complex[] P = A.roots();
Complex[] R = new Complex[P.length];
for (int m = 0; m < R.length; m++) {
int k = 0;
Complex[] p = new Complex[R.length - 1];
for (int j = 0; j < R.length; j++) {
if (m != j) {
p[k++] = P[j];
}
}
Complex[] pa = poly(p);
Complex pvB = B.polyval(P[m]);
Complex pvA = polyval(pa, P[m]);
Complex pvD = pvB.divide(pvA);
R[m] = pvD.divide(A.p[0]);
}
return new Object[] { R, P, K };
}
public static final Object[] residue(double b, Complex[] poles) {
double K = 0;
Polynom B = new Polynom(new double[] { b });
B.trim();
Polynom A = new Polynom(poly(poles));
A.trim();
int N = B.length() - 1;
int M = A.length() - 1;
if (N == M) {
K = B.p[0] / A.p[0];
B = B.subtract(A.multiply(K));
}
Complex[] P = poles;
Complex[] R = new Complex[P.length];
for (int m = 0; m < R.length; m++) {
int k = 0;
Complex[] p = new Complex[R.length - 1];
for (int j = 0; j < R.length; j++) {
if (m != j) {
p[k++] = P[j];
}
}
Complex[] pa = poly(p);
Complex pvB = B.polyval(P[m]);
Complex pvA = polyval(pa, P[m]);
Complex pvD = pvB.divide(pvA);
R[m] = pvD.divide(A.p[0]);
}
return new Object[] { R, P, K };
}
public static final Complex[] roots(double[] poly) {
final LaguerreSolver solver = new LaguerreSolver(1e-6, 1e-8);
double[] p = new double[poly.length];
// Koeffizient der höchsten Potenz durch Multiplikation mit einer
// Konstanten auf 1 normieren:
double s = 1.0 / poly[0];
for (int i = 0; i < poly.length; i++) {
p[i] = poly[i] * s;
}
// Nullstellen bei Null zählen und entfernen
int n = 0;
while (p[p.length - 1 - n] <= 1e-16) {
n++;
}
double[] pnz = new double[p.length - n];
for (int k = 0; k < pnz.length; k++) {
pnz[k] = p[k];
}
// Normierungskonstante berechnen:
s = Math.pow(p[pnz.length - 1], 1.0 / (p.length - 1));
// Durch [s^0 s^1 s^2 s^3 ... s^N] dividieren:
for (int i = 0; i < pnz.length; i++)
pnz[i] /= Math.pow(s, i);
// Um mit Matlab konform zu sein flippen:
double[] flip = new double[pnz.length];
for (int i = 0; i < flip.length; i++)
flip[pnz.length - i - 1] = pnz[i];
// Wurzeln berechnen:
Complex[] r = solver.solveAllComplex(flip, 0.0);
// Sortieren: Grösster Imag.-Teil kommt im RESULTAT zuerst.
r = sort(r);
// Imaginärteil von NS, die nich konjugiert komplex vorkommen, auf Null
// setzen.
// boolean[] cc = new boolean[r.length];
// for (int j = 0; j < r.length - 1; j++) {
// for (int k = 0; k < r.length; k++) {
// if (k != j) {
// if (assertEq(r[j].getReal(), r[k].getReal(), 6)
// && assertEq(r[j].getImaginary(), -r[k].getImaginary(), 6)) {
// r[j] = new Complex((r[j].getReal() + r[k].getReal()) / 2.0,
// ( (r[j].getImaginary() - r[k].getImaginary()) ) / 2.0);
// r[k] = new Complex(r[j].getReal(), -r[j].getImaginary());
// cc[j] = cc[k] = true;
// }
// }
// }
// }
//
// for (int j = 0; j < cc.length; j++) {
// if (!cc[j]) r[j] = new Complex(r[j].getReal(), 0.0);
// }
// Wurzeln durch Multiplikation mit s wieder entnormieren:
for (int i = 0; i < r.length; i++) {
r[i] = r[i].multiply(s);
}
Complex[] res = new Complex[r.length + n];
// Nullstellen einfügen und um mit Matlab konform zu sein flippen:
int i = 0;
for (; i < n; i++) {
res[i] = new Complex(0.0, 0.0);
}
for (; i < r.length + n; i++)
res[i] = r[r.length - i - 1 + n];
return res;
}
public static final Object[] schrittRESI(double[] B, double[] A, double fs, int N) {
double T = 1 / fs;
double[] t = MiniMatlab.linspace(0.0, (N - 1) * T, N);
// Koeff. der höchste Potenz des Nenners auf 1.0 normieren:
B = MiniMatlab.multiply(B, 1.0 / A[0]);
A = MiniMatlab.multiply(A, 1.0 / A[0]);
// 1e-12 an A anhängen und Residuen rechnen
Object[] obj = MiniMatlab.residue(B, MiniMatlab.concat(A, 1e-12));
Complex[] R = (Complex[]) obj[0];
Complex[] P = (Complex[]) obj[1];
double K = ((Double) obj[2]).doubleValue();
double[] h = MiniMatlab.zeros(t.length);
if (K != 0.0) {
h[0] = K;
}
// Schrittantwort rechnen
for (int i = 0; i < t.length; i++) {
for (int k = 0; k < R.length; k++) {
h[i] = h[i] + P[k].multiply(t[i]).exp().multiply(R[k]).getReal(); // .devide(fs);
}
}
return new Object[] { h, t };
}
private static Complex[] sort(Complex[] a) {
boolean flag = true;
while (flag) {
flag = false;
for (int i = 0; i < a.length - 1; i++) {
if (Math.abs(a[i].getImaginary()) > Math.abs(a[i + 1].getImaginary())) {
Complex temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
flag = true;
}
}
}
return a;
}
public static double spline(double[] x, double[] y, double v) {
PolynomialSplineFunction f = interpolator.interpolate(x, y);
return f.value(v);
}
public static final double[] zeros(int i) {
double[] p = new double[i];
return p;
}
public static final Complex[] zerosC(int i) {
Complex[] p = new Complex[i];
for (int j = 0; j < p.length; j++) {
p[j] = new Complex(0.0, 0.0);
}
return p;
}
/**
* @brief Berechnet facrotial für grosse Zahlen (num > 19)
* @param num
* @return
*/
public static BigDecimal factorialBig(int num) {
BigDecimal fact = BigDecimal.valueOf(1);
for (int i = 1; i <= num; i++)
fact = fact.multiply(BigDecimal.valueOf(i));
return fact;
}
/**
* @brief Berechnet factorial für kleine Zahlen (num < 19)
* @param num
* @return
*/
public static int factorial(int num) {
int fact = 1;
for (int i = 1; i <= num; i++)
fact = fact * ((i));
return fact;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment