Converting fast MCLT algorithm in Matlab to java - java

I have java code which gives me FFT output from real inputs. I need to perform MCLT. Currently I have the FFT output with me in the following format. I have seen some fast MCLT alogrithm (https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-2005-02.pdf), coded in Matlab, but can not understand it perfectly. Can someone help me in writing corresponding java code.
Java Code Starting point:
int dtLength = data.length/2;
double[] realPart = new double[dtLength];
double[] imagPart = new double[dtLength];
Matlab Code:
function X = fmclt(x)
% FMCLT - Compute MCLT of a vector via double-length FFT
%
% H. Malvar, September 2001 -- (c) 1998-2001 Microsoft Corp.
%
% Syntax: X = fmclt(x)
%
% Input: x : real-valued input vector of length 2*M
%
% Output: X : complex-valued MCLT coefficients, M subbands
% in Matlab, by default j = sqrt(-1)
% determine # of subbands, M
L = length(x);
M = L/2;
% normalized FFT of input
U = sqrt(1/(2*M)) * fft(x);
% compute modulation function
k = [0:M]';
c = W(8,2*k+1) .* W(4*M,k);
% modulate U into V
V = c .* U(1:M+1);
% compute MCLT coefficients
X = j * V(1:M) + V(2:M+1);
return;
% Local function: complex exponential
function w = W(M,r)
w = exp(-j*2*pi*r/M);
return;

Even though this question is kinda borderline for SO, the paper was quite interesting so I decided to invest some time reading it and trying to convert the Matlab code into Java. Here is the result:
import org.apache.commons.math3.complex.Complex;
public class MCLT
{
public static void main(String args[])
{
Complex[] x = new Complex[16];
for (int i = 1; i <= 16; ++i)
x[(i - 1)] = new Complex((double)i, 0.0d);
Complex[] result = fmclt(x);
for (int i = 0; i < result.length; ++i)
System.out.println(result[i]);
}
public static Complex[] fmclt(Complex[] x)
{
int L = x.length;
int M = L / 2;
double z = Math.sqrt(1.0d / (2.0d * M));
Complex[] F = fft(x);
Complex[] U = new Complex[F.length];
for (int i = 0; i < F.length; ++i)
U[i] = F[i].multiply(z);
double[] k = new double[(M + 1)];
for (int i = 0; i <= M; ++i)
k[i] = (double)i;
Complex[] c = new Complex[(M + 1)];
for (int i = 0; i <= M; ++i)
c[i] = W(8.0d, ((2.0d * k[i]) + 1.0d)).multiply(W((4.0d * M), k[i]));
Complex[][] V = new Complex[(M + 1)][];
for (int i = 0; i <= M; ++i)
{
V[i] = new Complex[(M + 1)];
for (int j = 0; j <= M; ++j)
V[i][j] = c[i].multiply(U[j]);
}
Complex[] V1 = new Complex[M];
for (int i = 0; i < M; ++i)
V1[i] = V[i][0];
Complex[] V2 = new Complex[M];
for (int i = 1; i <= M; ++i)
V2[(i - 1)] = V[i][0];
Complex b = new Complex(0.0d, 1.0d);
Complex[] result = new Complex[M];
for (int i = 0; i < M; ++i)
result[i] = b.multiply(V1[i]).add(V2[i]);
return result;
}
public static Complex[] fft(Complex[] x)
{
int n = x.length;
if (n == 1)
return new Complex[] { x[0] };
if ((n % 2) != 0)
throw new IllegalArgumentException("Invalid length.");
int nh = n / 2;
Complex[] even = new Complex[nh];
for (int i = 0; i < nh; ++i)
even[i] = x[(2 * i)];
Complex[] q = fft(even);
Complex[] odd = even;
for (int i = 0; i < nh; ++i)
odd[i] = x[((2 * i) + 1)];
Complex[] r = fft(odd);
Complex[] y = new Complex[n];
for (int i = 0; i < nh; ++i)
{
double kth = -2.0d * i * (Math.PI / n);
Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
y[i] = q[i].add(wk.multiply(r[i]));
y[(i + nh)] = q[i].subtract(wk.multiply(r[i]));
}
return y;
}
public static Complex W(double M, double r)
{
Complex j = (new Complex(0.0d, 1.0d)).multiply(-1.0d);
double z = 2.0d * Math.PI * (r / M);
return j.multiply(z).exp();
}
}
Using separate double arrays for real and imaginary parts wasn't a good design choice in my opinion, so I decided to base my code on the Complex class of Apache Commons library instead.
In order to calculate the Fast Fourier Transform, I decided to use some ready-made code. My fft function is based on this implementation, which seems to be very reliable and makes use of the aforementioned Complex class.
Using the same vector of values, both Matlab and Java codes return the same output. You can test the code online by copy-pasting it on this website, but you also need to install the Apache Commons library before being able to successfully run it. Click on the Add External Library (from Maven Repo) button located at the bottom, and then insert the following parameters in the input form:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>

Related

How to use NNLS for non-negative multiple linear regression?

I am trying to solve Non-negative multiple linear regression problem in Java.
And I found a solver class org.apache.spark.mllib.optimization.NNLS written in Scala.
However, I don't know how to use this.
What makes me confused is that the interface of the following method seems strange.
I thought that A is a MxN matrix and b is a M-vector, and the arguments ata and atb should be a NxN matrix and N-vector, respectively.
However, the actual type of ata is double[].
public static double[] solve(double[] ata, double[] atb, NNLS.Workspace ws)
I searched for an example code but I couldn't find.
Can anyone give me a sample code?
The library is written in Scala, but I want Java code if possible.
DISCLAIMER I've never used NNLS and got no idea about non-negative multiple linear regression.
You look at Spark 2.1.1's NNLS that does what you want, but is not the way to go since the latest Spark 2.2.1 marked as private[spark].
private[spark] object NNLS {
More importantly, as of Spark 2.0, org.apache.spark.mllib package (incl. org.apache.spark.mllib.optimization that NNLS belongs to) is in maintenance mode:
The MLlib RDD-based API is now in maintenance mode.
As of Spark 2.0, the RDD-based APIs in the spark.mllib package have entered maintenance mode. The primary Machine Learning API for Spark is now the DataFrame-based API in the spark.ml package.
In other words, you should stay away from the package and NNLS in particular.
What are the alternatives then?
You could look at the tests of NNLS, i.e. NNLSSuite where you could find some answers.
However, the actual type of ata is double[].
That's a matrix so elements are doubles again. As a matter of fact, ata is passed directly to BLAS's dgemv (here and here) that is described in the LAPACK docs:
DGEMV performs one of the matrix-vector operations
y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y,
where alpha and beta are scalars, x and y are vectors and A is an
m by n matrix.
That should give you enough answers.
Another question would be what the recommended way in Spark MLlib for NNLS-like computations is?
It looks like Spark MLLib's ALS algorithm uses NNLS under the covers (which may not be that surprising for machine learning practitioners).
That part of the code is used when ALS is configured to train a model with nonnegative parameter turned on, i.e. true (which is disabled by default).
nonnegative Param for whether to apply nonnegativity constraints.
Default: false
whether to use nonnegative constraint for least squares
I would recommend reviewing that part of Spark MLlib to get deeper into the uses of NNLS for solving non-negative linear regression problem.
I wrote a test code.
Though I got some warnings like Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS, it works well for simple cases, but beta often becomes 0 when m is very large (about 3000).
package test;
import org.apache.spark.mllib.optimization.NNLS;
public class NNLSTest {
public static void main(String[] args) {
int n = 6, m = 300;
ExampleInMatLabDoc();
AllPositiveBetaNoiseInY(n, m);
SomeNegativesInBeta(n, m);
NoCorrelation(n, m);
}
private static void test(double[][] X, double[] y, double[] b) {
int m = X.length; int n = X[0].length;
double[] Xty = new double[n];
for (int i = 0; i < n; i++) {
Xty[i] = 0.0;
for (int j = 0; j < m; j++) Xty[i] += X[j][i] * y[j];
}
double[] XtX = new double[n * n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
XtX[n * i + j] = 0.0;
for (int k = 0; k < m; k++) XtX[n * i + j] += X[k][i] * X[k][j];
}
}
double[] beta = NNLS.solve(XtX, Xty, NNLS.createWorkspace(n));
System.out.println("\ntrue beta\tbeta");
for (int i = 0; i < beta.length; i++) System.out.println(b[i] + "\t" + beta[i]);
}
private static void ExampleInMatLabDoc() {
// https://jp.mathworks.com/help/matlab/ref/lsqnonneg.html
double[] y = new double[] { 0.8587, 0.1781, 0.0747, 0.8405 };
double[][] x = new double[4][];
x[0] = new double[] { 0.0372, 0.2869 };
x[1] = new double[] { 0.6861, 0.7071 };
x[2] = new double[] { 0.6233, 0.6245 };
x[3] = new double[] { 0.6344, 0.6170 };
double[] b = new double[] { 0.0, 0.6929 };
test(x, y, b);
}
private static void AllPositiveBetaNoiseInY(int n, int m) {
double[] b = new double[n];
for (int i = 0; i < n; i++) b[i] = Math.random() * 100.0; // random value in [0:100]
double[] y = new double[m];
double[][] x = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
x[i][0] = 1.0;
y[i] = b[0];
for (int j = 1; j < n; j++) {
x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
y[i] += x[i][j] * b[j];
}
y[i] *= 1.0 + (2.0 * Math.random() - 1.0) * 0.1; // add noise
}
test(x, y, b);
}
private static void SomeNegativesInBeta(int n, int m) {
double[] b = new double[n];
for (int i = 0; i < n; i++) b[i] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
double[] y = new double[m];
double[][] x = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
x[i][0] = 1.0;
y[i] = b[0];
for (int j = 1; j < n; j++) {
x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
y[i] += x[i][j] * b[j];
}
}
test(x, y, b);
}
private static void NoCorrelation(int n, int m) {
double[] y = new double[m];
double[][] x = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
x[i][0] = 1.0;
for (int j = 1; j < n; j++)
x[i][j] = (2.0 * Math.random() - 1.0) * 100.0; // random value in [-100:100]
y[i] = (2.0 * Math.random() - 1.0) * 100.0;
}
double[] b = new double[n];
for (int i = 0; i < n; i++) b[i] = 0;
test(x, y, b);
}
}

Numbers too big for variables

I am to find the last ten digits of 1^1 + 2^2 + 3^3.. + 1000^1000.
Is there any way to find this out with pure logic? I think you can't store a number that big.
This question is from a math competition, but I thought of trying to do this in Java.
You don't need to store number that big, you just need the last ten digits. You can store this in a long.
An efficient way to calculate large powers is to multiply and the squares e.g. 19^19 = 19 * 19^2 * 19 ^ 16 = 19 * 19 ^ 2 * 19^2^2^2^2. When you have value which is greater than 10^10 you can truncate the last 10 digits.
BTW the last ten digits of 1000^1000 is 0000000000 and when your add this to your sum, it's the same as adding zero ;)
Edit: While you don't have to use BigInteger, it is simpler to write.
BigInteger tenDigits = BigInteger.valueOf(10).pow(10);
BigInteger sum = BigInteger.ZERO;
for (int i= 1; i <= 1000; i++) {
BigInteger bi = BigInteger.valueOf(i);
sum = sum.add(bi.modPow(bi, tenDigits));
}
sum = sum.mod(tenDigits);
modPow is more efficient than pow with mod seperately as it doesn't have to calculate very large numbers, only the result of the mod.
You could use BigIntegers...
public static void main(String[] args) {
BigInteger acc = BigInteger.ZERO;
for (int k = 1; k <= 1000; k++) {
BigInteger pow = BigInteger.valueOf(k).pow(k);
acc = acc.add(pow);
}
System.out.println(acc);
}
I believe the problem comes from Project Euler, so it's not just a math problem; it should require some computation as well. I don't know how it could be solved with pencil and paper other than by duplicating the calculations a computer might make. I can't see much in the way of a purely mathematical solution. Mathematics can help us optimize the code, however.
To raise a^n, find the binary expansion of n:
n = n_k x 2^k + n_(k-1) x 2^(k-1) + ... + n_0 x 2^0
where n_i = 0 or 1 are the binary digits of n with the zeroth digit on the right. Then
a^n = a^(n_k x 2^k) x a^(n_(k-1) x 2^(k-1)) x ... x a^(n_0 x 2^0).
We can ignore any factors where n_i = 0, since the factor is then a^0 = 1. The process can be written as an algorithm which is O(log n) time and O(1) space (see below).
Next, as a challenge, in order to avoid the use of BigInteger, we can break the calculation into two parts: finding the answer mod 2^10 and finding the answer mod 5^10. In both cases the numbers in the relevant ranges and products of numbers in the relevant ranges fit into longs. The downside is that we have to use the Chinese Remainder Theorem to recombine the results, but it's not that hard, and it's instructive. The hardest part of using the Chinese Remainder Theorem is finding inverses mod m, but that can be accomplished in a straightforward manner using a modification of the Euclidean algorithm.
Asymptotic running time is O(n log n), space is O(1), and everything fits into a few long variables, no BigInteger or other sophisticated library required.
public class SeriesMod1010 {
public static long pow(long a,long n,long m) { // a^n mod m
long result = 1;
long a2i = a%m; // a^2^i for i = 0, ...
while (n>0) {
if (n%2 == 1) {
result *= a2i;
result %= m;
}
a2i *= a2i;
a2i %= m;
n /= 2;
}
return result;
}
public static long inverse(long a, long m) { // mult. inverse of a mod m
long r = m;
long nr = a;
long t = 0;
long nt = 1;
long tmp;
while (nr != 0) {
long q = r/nr;
tmp = nt; nt = t - q*nt; t = tmp;
tmp = nr; nr = r - q*nr; r = tmp;
}
if (r > 1) return -1; // no inverse
if (t < 0) t += m;
return t;
}
public static void main(String[] args) {
long twoTo10 = 1024;
long sum210 = 0;
for (long i=1; i<=1000; i++) {
sum210 += pow(i,i,twoTo10);
sum210 %= twoTo10;
}
long fiveTo10 = 9_765_625;
long sum510 = 0;
for (long i=1; i<=1000; i++) {
sum510 += pow(i,i,fiveTo10);
sum510 %= fiveTo10;
}
// recombine the numbers with the Chinese remainder theorem
long tenTo10 = 10_000_000_000L;
long answer = sum210 * inverse(fiveTo10,twoTo10) * fiveTo10
+ sum510 * inverse(twoTo10,fiveTo10) * twoTo10;
answer %= tenTo10;
System.out.println(answer);
}
}
use BigIntegers :
import java.math.BigInteger;
public class Program {
public static void main(String[] args) {
BigInteger result = new BigInteger("1");
BigInteger temp = new BigInteger("1");
BigInteger I;
for(int i = 1 ; i < 1001 ; i++){
I = new BigInteger(""+i);
for(int j = 1 ; j < i ; j++){
temp = temp.multiply(I);
}
result = result.multiply(temp);
temp = new BigInteger("1");
}
System.out.println(result);
}
}
It can be solved without BigInteger, because you need to store only 10 last digits on every addition or multiplication operation, using % to avoid overflow:
int n = 1000;
long result = 0;
long tenDigits = 10_000_000_000L;
for (int i = 1; i <= n; i++) {
long r = i;
for (int j = 2; j <= i; j++) {
r = (r * i) % tenDigits;
}
result += r;
}
return result % tenDigits;
Complexity is O(N^2), supposed that multiplication runs in constant time.
Answer: 9110846700.
The decimal base uses 0...9 (10 digits) to represent digits, a number that is in the second position right to left represents Digits * base.length^l2rPosition. Using this logics you can create a class that "pretty much does what your primary school teacher told you to, back when we used paper to calculate stuff, but with a baseN number and base-to-base conversions" I have done this class fully functional in C#, but I don't have time to translate it completely to java, this is about the same logics behind java.math.BigInteger. (with less performance I bet for I used a lot of lists >_>" No time to optimize it now
class IntEx {
ArrayList<Integer> digits = new ArrayList<>();
long baseSize = Integer.MAX_VALUE+1;
boolean negative = false;
public IntEx(int init)
{
set(init);
}
public void set(int number)
{
digits = new ArrayList<>();
int backup = number;
do
{
int index = (int)(backup % baseSize);
digits.add(index);
backup = (int) (backup / baseSize);
} while ((backup) > 0);
}
// ... other operations
private void add(IntEx number)
{
IntEx greater = number.digits.size() > digits.size() ? number : this;
IntEx lesser = number.digits.size() < digits.size() ? number : this;
int leftOvers = 0;
ArrayList<Integer> result = new ArrayList<>();
for (int i = 0; i < greater.digits.size() || leftOvers > 0; i++)
{
int sum;
if (i >= greater.digits.size())
sum = leftOvers;
else if(i >= lesser.digits.size())
sum = leftOvers + greater.digits.get(i);
else
sum = digits.get(i) + number.digits.get(i) + leftOvers;
leftOvers = 0;
if (sum > baseSize-1)
{
while (sum > baseSize-1)
{
sum -= baseSize;
leftOvers += 1;
}
result.add(sum);
}
else
{
result.add(sum);
leftOvers = 0;
}
}
digits = result;
}
private void multiply(IntEx target)
{
ArrayList<IntEx> MultiParts = new ArrayList<>();
for (int i = 0; i < digits.size(); i++)
{
IntEx thisPart = new IntEx(0);
thisPart.digits = new ArrayList<>();
for (int k = 0; k < i; k++)
thisPart.digits.add(0);
int Leftovers = 0;
for (int j = 0; j < target.digits.size(); j++)
{
int multiFragment = digits.get(i) * (int) target.digits.get(j) + Leftovers;
Leftovers = (int) (multiFragment / baseSize);
thisPart.digits.add((int)(multiFragment % baseSize));
}
while (Leftovers > 0)
{
thisPart.digits.add((int)(Leftovers % baseSize));
Leftovers = (int) (Leftovers / baseSize);
}
MultiParts.add(thisPart);
}
IntEx newNumber = new IntEx(0);
for (int i = 0; i < MultiParts.size(); i++)
{
newNumber.add(MultiParts.get(i));
}
digits = newNumber.digits;
}
public long longValue() throws Exception
{
int position = 0;
long multi = 1;
long retValue = 0;
if (digits.isEmpty()) return 0;
if (digits.size() > 16) throw new Exception("The number within IntEx class is too big to fit into a long");
do
{
retValue += digits.get(position) * multi;
multi *= baseSize;
position++;
} while (position < digits.size());
return retValue;
}
public static long BaseConvert(String number, String base)
{
boolean negative = number.startsWith("-");
number = number.replace("-", "");
ArrayList<Character> localDigits = new ArrayList<>();
for(int i = number.toCharArray().length - 1; i >=0; i--) {
localDigits.add(number.charAt(i));
}
// List<>().reverse is missing in this damn java. -_-
long retValue = 0;
long Multi = 1;
char[] CharsBase = base.toCharArray();
for (int i = 0; i < number.length(); i++)
{
int t = base.indexOf(localDigits.get(i));
retValue += base.indexOf(localDigits.get(i)) * Multi;
Multi *= base.length();
}
if (negative)
retValue = -retValue;
return retValue;
}
public static String BaseMult(String a, String b, String Base)
{
ArrayList<String> MultiParts = new ArrayList<>();
// this huge block is a tribute to java not having "Reverse()" method.
char[] x = new char[a.length()];
char[] y = new char[b.length()];
for(int i = 0; i < a.length(); i++) {
x[i] = a.charAt(a.length()-i);
}
for(int i = 0; i < b.length(); i++) {
y[i] = a.charAt(a.length()-i);
}
a = new String(x);
b = new String(y);
// ---------------------------------------------------------------------
for (int i = 0; i < a.length(); i++)
{
ArrayList<Character> thisPart = new ArrayList<>();
for (int k = 0; k < i; k++)
thisPart.add(Base.charAt(0));
int leftOvers = 0;
for (int j = 0; j < b.length(); j++)
{
// Need I say repeated characters in base may cause mayhem?
int MultiFragment = Base.indexOf(a.charAt(i)) * Base.indexOf(b.charAt(j)) + leftOvers;
leftOvers = MultiFragment / Base.length();
thisPart.add(Base.charAt(MultiFragment % Base.length()));
}
while (leftOvers > 0)
{
thisPart.add(Base.charAt(leftOvers % Base.length()));
leftOvers = leftOvers / Base.length();
}
char[] thisPartReverse = new char[thisPart.size()];
for(int z = 0; z < thisPart.size();z++)
thisPartReverse[z] = thisPart.get(thisPart.size()-z);
MultiParts.add(new String(thisPartReverse));
}
String retValue = ""+Base.charAt(0);
for (int i = 0; i < MultiParts.size(); i++)
{
retValue = BaseSum(retValue, MultiParts.get(i), Base);
}
return retValue;
}
public static String BaseSum(String a, String b, String Base)
{
// this huge block is a tribute to java not having "Reverse()" method.
char[] x = new char[a.length()];
char[] y = new char[b.length()];
for(int i = 0; i < a.length(); i++) {
x[i] = a.charAt(a.length()-i);
}
for(int i = 0; i < b.length(); i++) {
y[i] = a.charAt(a.length()-i);
}
a = new String(x);
b = new String(y);
// ---------------------------------------------------------------------
String greater = a.length() > b.length() ? a : b;
String lesser = a.length() < b.length() ? a : b;
int leftOvers = 0;
ArrayList<Character> result = new ArrayList();
for (int i = 0; i < greater.length() || leftOvers > 0; i++)
{
int sum;
if (i >= greater.length())
sum = leftOvers;
else if (i >= lesser.length())
sum = leftOvers + Base.indexOf(greater.charAt(i));
else
sum = Base.indexOf(a.charAt(i)) + Base.indexOf(b.charAt(i)) + leftOvers;
leftOvers = 0;
if (sum > Base.length()-1)
{
while (sum > Base.length()-1)
{
sum -= Base.length();
leftOvers += 1;
}
result.add(Base.charAt(sum));
}
else
{
result.add(Base.charAt(sum));
leftOvers = 0;
}
}
char[] reverseResult = new char[result.size()];
for(int i = 0; i < result.size(); i++)
reverseResult[i] = result.get(result.size() -i);
return new String(reverseResult);
}
public static String BaseConvertItoA(long number, String base)
{
ArrayList<Character> retValue = new ArrayList<>();
boolean negative = false;
long backup = number;
if (negative = (backup < 0))
backup = -backup;
do
{
int index = (int)(backup % base.length());
retValue.add(base.charAt(index));
backup = backup / base.length();
} while ((backup) > 0);
if (negative)
retValue.add('-');
char[] reverseRetVal = new char[retValue.size()];
for(int i = 0; i < retValue.size(); i++)
reverseRetVal[i] = retValue.get(retValue.size()-i);
return new String(reverseRetVal);
}
public String ToString(String base)
{
if(base == null || base.length() < 2)
base = "0123456789";
ArrayList<Character> retVal = new ArrayList<>();
char[] CharsBase = base.toCharArray();
int TamanhoBase = base.length();
String result = ""+base.charAt(0);
String multi = ""+base.charAt(1);
String lbase = IntEx.BaseConvertItoA(baseSize, base);
for (int i = 0; i < digits.size(); i++)
{
String ThisByte = IntEx.BaseConvertItoA(digits.get(i), base);
String Next = IntEx.BaseMult(ThisByte, multi, base);
result = IntEx.BaseSum(result, Next, base);
multi = IntEx.BaseMult(multi, lbase, base);
}
return result;
}
public static void main(String... args) {
int ref = 0;
IntEx result = new IntEx(0);
while(++ref <= 1000)
{
IntEx mul = new IntEx(1000);
for (int i = 0; i < 1000; ++i) {
mul.multiply(new IntEx(i));
}
result.add(mul);
}
System.out.println(result.toString());
}
}
Disclaimer: This is a rough translation/localization from a C# study, there are lots of code omitted. This is "almost" the same logics behind java.math.BigInteger (you can open BigInteger code on your favorite designer and check for yourself. If may I be forgetting a overloaded operator behind not translated to java, have a bit of patience and forgiveness, this example is just for a "maybe" clarification of the theory.
Also, just a sidenote, I know it is "Trying to reinvent the wheel", but considering this question has academic purpose I think its fairly rasonable to share.
One can see the result of this study on gitHub (not localized though), I'm not expanding that C# code here for its very extensive and not the language of this question.
This gives the correct answer without excess calculations. A Long is sufficient.
public String lastTen() {
long answer = 0;
String txtAnswer = "";
int length = 0;
int i = 1;
for(i = 1; i <= 1000; i++) {
answer += Math.pow(i, i);
txtAnswer = Long.toString(answer);
length = txtAnswer.length();
if(length > 9) break;
}
return txtAnswer.substring(length-10);
}

code does not work with arrays (multiple arrays in arraylist)

hi I'm having a little problem with arrays.
here's the code:
int frame_size = 410;
int frame_shift = 320;
ArrayList<double[]> frames = new ArrayList<double[]>();
for (int i = 0; i + frame_size < inbuf.length; i = i + frame_shift) {
double[] frame = new double[frame_size];
System.arraycopy(inbuf, i, frame, 0, frame_size);
frames.add(frame);
}
here I share a large array into several small, and add them to arraylist
I need to get more of ArrayList arrays and pass them to the function, and then accept the answer and assemble arrays processed one:
int[] Cover = new int[frames.size() * nParam];
for (int i = 0; i < frames.size(); i++) {
double[] finMc = Gos.getVek(frames.get(i));
for (int c = 0; c < finMc.length; c++) {
int mc = (int) finMc[c];
for (int m = 0; m < Cover.length; m++) {
Cover[m] = mc;
}
}
}
all this code does not work (
all elements of the array are zero Cover.
Сover[0] = 0
Cover[1] = 0
Cover[2] = 0
...
help solve the problem, please!)
thank you in advance)
Update
int frame_size = 410;
int frame_shift = 320;
ArrayList<double[]> frames = new ArrayList<double[]>();
for (int i = 0; i + frame_size < inbuf.length; i = i + frame_shift) {
double[] frame = new double[frame_size];
System.arraycopy(inbuf, i, frame, 0, frame_size);
frames.add(frame);
}
int[] Cover = new int[frames.size() * nParam];
for (int i = 0; i < frames.size(); i++) {
double[] finMc = Gos.getVek(frames.get(i));
for (int c = 0; c < finMc.length; c++) {
int mc = (int) finMc[c];
Cover[i * frames.size() + c] = (int) finMc[c];
}
}
Code^ not work(
UPDATE 2
double[] inbuf = new double[Size];
inbuf = toDoubleArray(Gos.data);
inbuf[2] = 10;
inbuf[4] = 14;
toDoubleArray
public static double[] toDoubleArray(byte[] byteArray) {
int times = Double.SIZE / Byte.SIZE;
double[] doubles = new double[byteArray.length / times];
for (int i = 0; i < doubles.length; i++) {
doubles[i] = ByteBuffer.wrap(byteArray, i * times, times)
.getDouble();
}
return doubles;
}
Code not work:
int frame_size = 410;
int frame_shift = 320;
ArrayList<double[]> frames = new ArrayList<double[]>();
for (int i = 0; i + frame_size < inbuf.length; i = i + frame_shift) {
double[] frame = new double[frame_size];
System.arraycopy(inbuf, i, frame, 0, frame_size);
frames.add(frame);
}
double[] Cover = new double[frames.size() * nParam];
for (int i = 0; i < frames.size(); i++) {
double[] finMc = Gos.getVek(frames.get(i));
for (int c = 0; c < finMc.length; c++) {
Cover[i * frames.size() + c] = finMc[c];
}
}
A couple of thoughts spring to mind immediately:
1)
for (int m = 0; m < Cover.length; m++) {
Cover[m] = mc;
}
This block starts m over at 0 every time through the loop. This means you're always writing over the same portion of the Cover array. So effectively, it's only the last frame's data that's stored. You probably meant
for(int m = i * frames.size(); m < (i+1)*frames.size(); i++) {
Cover[m] = mc;
}
But this raises a further issue -- you're writing the same value (mc) into the entire area allocated for a whole frame of data. You probably want to merge this loop with the previous loop so that this doesn't happen.
for (int c = 0; c < finMc.length; c++) {
Cover[i * frames.size() + c] = (int)finMc[c];
}
2) int mc = (int) finMc[c];
That line casts the value to an int which truncates the value stored at finMc[c]. If finMc[c] is between 0 and 1 this will yield 0 when the data is copied and casted. This is compounded by the previous issue which ensures that only the last frame's data ever gets copied. This is simply solved by removing the cast and declaring Cover as an array of doubles instead of ints.
So in sum, the code might work a bit better if it's written this way:
double[] Cover = new double[frames.size() * nParam];
for (int i = 0; i < frames.size(); i++) {
double[] finMc = Gos.getVek(frames.get(i));
for (int c = 0; c < finMc.length; c++) {
Cover[i * frames.size() + c] = finMc[c];
}
}

Image Enhancement using FFT in java

I am working on fingerprint image enhancement with Fast Fourier Transformation. I got the idea from this site.
I have implemented the FFT function using 32*32 window, and after that as the referral site suggested, I want to multiply power spectrum with the FFT. But I do not get,
How do I calculate Power Spectrum for an image? Or is there any ideal value for Power Spectrum ?
Code for FFT:
public FFT(int[] pixels, int w, int h) {
// progress = 0;
input = new TwoDArray(pixels, w, h);
intermediate = new TwoDArray(pixels, w, h);
output = new TwoDArray(pixels, w, h);
transform();
}
void transform() {
for (int i = 0; i < input.size; i+=32) {
for(int j = 0; j < input.size; j+=32){
ComplexNumber[] cn = recursiveFFT(input.getWindow(i,j));
output.putWindow(i,j, cn);
}
}
for (int j = 0; j < output.values.length; ++j) {
for (int i = 0; i < output.values[0].length; ++i) {
intermediate.values[i][j] = output.values[i][j];
input.values[i][j] = output.values[i][j];
}
}
}
static ComplexNumber[] recursiveFFT(ComplexNumber[] x) {
int N = x.length;
// base case
if (N == 1) return new ComplexNumber[] { x[0] };
// radix 2 Cooley-Tukey FFT
if (N % 2 != 0) { throw new RuntimeException("N is not a power of 2"); }
// fft of even terms
ComplexNumber[] even = new ComplexNumber[N/2];
for (int k = 0; k < N/2; k++) {
even[k] = x[2*k];
}
ComplexNumber[] q = recursiveFFT(even);
// fft of odd terms
ComplexNumber[] odd = even; // reuse the array
for (int k = 0; k < N/2; k++) {
odd[k] = x[2*k + 1];
}
ComplexNumber[] r = recursiveFFT(odd);
// combine
ComplexNumber[] y = new ComplexNumber[N];
for (int k = 0; k < N/2; k++) {
double kth = -2 * k * Math.PI / N;
ComplexNumber wk = new ComplexNumber(Math.cos(kth), Math.sin(kth));
ComplexNumber tmp = ComplexNumber.cMult(wk, r[k]);
y[k] = ComplexNumber.cSum(q[k], tmp);
ComplexNumber temp = ComplexNumber.cMult(wk, r[k]);
y[k + N/2] = ComplexNumber.cDif(q[k], temp);
}
return y;
}
I'm thinking that the power spectrum is the square of the output of the Fourier transform.
power#givenFrequency = x(x*) where x* is the complex conjugate
The total power in the image block would then be the sum over all frequency and space.
I have no idea if this helps.

Port Matlab's FFT to native Java

I want to port Matlab's Fast Fourier transform function fft() to native Java code.
As a starting point I am using the code of JMathLib where the FFT is implemented as follows:
// given double[] x as the input signal
n = x.length; // assume n is a power of 2
nu = (int)(Math.log(n)/Math.log(2));
int n2 = n/2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] mag = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++) {
xre[i] = x[i];
xim[i] = 0.0;
}
int k = 0;
for (int l = 1; l <= nu; l++) {
while (k < n) {
for (int i = 1; i <= n2; i++) {
p = bitrev (k >> nu1);
arg = 2 * (double) Math.PI * p / n;
c = (double) Math.cos (arg);
s = (double) Math.sin (arg);
tr = xre[k+n2]*c + xim[k+n2]*s;
ti = xim[k+n2]*c - xre[k+n2]*s;
xre[k+n2] = xre[k] - tr;
xim[k+n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 = n2/2;
}
k = 0;
int r;
while (k < n) {
r = bitrev (k);
if (r > k) {
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
// The result
// -> real part stored in xre
// -> imaginary part stored in xim
Unfortunately it doesn't give me the right results when I unit test it, for example with the array
double[] x = { 1.0d, 5.0d, 9.0d, 13.0d };
the result in Matlab:
28.0
-8.0 - 8.0i
-8.0
-8.0 + 8.0i
the result in my implementation:
28.0
-8.0 + 8.0i
-8.0
-8.0 - 8.0i
Note how the signs are wrong in the complex part.
When I use longer, more complex signals the differences between the implementations affects also the numbers. So the implementation differences does not only relate to some sign-"error".
My question: how can I adapt my implemenation to make it "equal" to the Matlab one?
Or: is there already a library that does exactly this?
in order to use Jtransforms for FFT on matrix you need to do fft col by col and then join them into a matrix. here is my code which i compared with Matlab fft
double [][] newRes = new double[samplesPerWindow*2][Matrixres.numberOfSegments];
double [] colForFFT = new double [samplesPerWindow*2];
DoubleFFT_1D fft = new DoubleFFT_1D(samplesPerWindow);
for(int y = 0; y < Matrixres.numberOfSegments; y++)
{
//copy the original col into a col and and a col of zeros before FFT
for(int x = 0; x < samplesPerWindow; x++)
{
colForFFT[x] = Matrixres.res[x][y];
}
//fft on each col of the matrix
fft.realForwardFull(colForFFT); //Y=fft(y,nfft);
//copy the output of col*2 size into a new matrix
for(int x = 0; x < samplesPerWindow*2; x++)
{
newRes[x][y] = colForFFT[x];
}
}
hope this what you are looking for. note that Jtransforms represent Complex numbers as
array[2*k] = Re[k], array[2*k+1] = Im[k]

Categories