Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

First cut at NDK optimizations - 25% faster

  • Loading branch information...
commit 6b83a7a67aa257bfce452394c6aa930bdab641a2 1 parent ccac77b
@dbyrne authored
View
137 native-src/FractalMath/FractalMath.c
@@ -1,6 +1,137 @@
#include "byrne_fractal_NativeLib.h"
+#include <math.h>
-JNIEXPORT jstring JNICALL Java_byrne_fractal_NativeLib_getHelloWorld
-(JNIEnv * env, jobject obj) {
- return (*env)->NewStringUTF(env, "Hello NDK 2!");
+#ifndef maxVal
+ #define maxVal( a, b ) ( ((a) > (b)) ? (a) : (b) )
+#endif
+
+#ifndef abs
+ #define abs( a ) ( ((a) < (0)) ? (a*-1) : (a) )
+#endif
+
+
+
+JNIEXPORT jintArray JNICALL Java_byrne_fractal_NativeLib_getFractalRow
+(JNIEnv * env, jobject obj,
+ jint row, jint xres, jint yres,
+ jint power, jint max, jint equation, jint fractalType, jdouble P, jdouble Q,
+ jdouble realmin, jdouble realmax,
+ jdouble imagmin, jdouble imagmax) {
+
+ jintArray result;
+ jdouble xtmp=0,x=-1,y=-1,prev_x=-1,prev_y=-1,tmp_prev_x,tmp_prev_y,mu=1,xsq,ysq;
+ jint index;
+ jint lessThanMax;
+
+ result = (*env)->NewIntArray(env, xres);
+ if (result == NULL) {
+ return NULL; /* out of memory error thrown */
+ }
+
+ jint fractalRow[xres];
+
+ jdouble deltaP = (realmax - realmin)/xres;
+ jdouble deltaQ = (imagmax - imagmin)/yres;
+
+ if (fractalType == 1)
+ Q = imagmax - row*deltaQ;
+
+ jint col;
+ for(col=0; col < xres; col++) {
+
+ if (fractalType == 1) {
+
+ P = realmin + col*deltaP;
+ x = y = 0.0;
+ prev_x = prev_y = 0.0;
+ } else {
+ x = realmin + (double)col * deltaP;
+ y = imagmax - (double)row *deltaQ;
+ prev_x = x;
+ prev_y = y;
+ }
+
+ lessThanMax = 0;
+
+ jint extraIterations = 0;
+ for (index = 0; index < max; index++) {
+ xsq = x*x;
+ ysq = y*y;
+
+ if (xsq + ysq > 4) {
+ //a few extra iterations improves color smoothing - why don't some equations work when a higher number is used?
+ if (extraIterations == 2) {
+ lessThanMax = 1;
+ mu = index + 2 - (log(log(sqrt(xsq + ysq))/ log(2.0))/log(power));
+ break;
+ } else {
+ extraIterations++;
+ index--;
+ }
+ }
+
+ //TODO Refactoring needed.
+ switch (equation) {
+ case 1:
+ xtmp = xsq - ysq + P;
+ y = (2*x*y) + Q;
+ break;
+ case 2:
+ xtmp = xsq*x - 3*x*ysq + P;
+ y = -ysq*y + 3*xsq*y + Q;
+ break;
+ case 3:
+ xtmp = xsq*xsq - 6*xsq*ysq + ysq*ysq + P;
+ y = 4*xsq*x*y - 4*x*ysq*y + Q;
+ break;
+ case 4:
+ xtmp = xsq*xsq*x-10*xsq*x*ysq+5*x*ysq*ysq + P;
+ y=(5*xsq*xsq*y-10*xsq*ysq*y+ysq*ysq*y) + Q;
+ break;
+ case 5:
+ xtmp = xsq*xsq*xsq-15*xsq*xsq*ysq+15*xsq*ysq*ysq-ysq*ysq*ysq + P;
+ y=(6*xsq*xsq*x*y-20*xsq*x*ysq*y+6*x*ysq*ysq*y) + Q;
+ break;
+ case 6:
+ xtmp = xsq*xsq - 6*xsq*ysq + ysq*ysq - (xsq*x - 3*x*ysq) - (xsq - ysq) + P;
+ y = 4*xsq*x*y - 4*x*ysq*y - (-ysq*y + 3*xsq*y) - (2*x*y) + Q;
+ break;
+ case 7:
+ xtmp = xsq*xsq*xsq-15*xsq*xsq*ysq+15*xsq*ysq*ysq-ysq*ysq*ysq - (xsq - ysq) + P;
+ y = (6*xsq*xsq*x*y-20*xsq*x*ysq*y+6*x*ysq*ysq*y) - (2*x*y) + Q;
+ break;
+ case 8:
+ xtmp = xsq - ysq + P;
+ y = (2*abs(x)*abs(y)) - Q;
+ break;
+ case 9:
+ tmp_prev_x = x;
+ tmp_prev_y = y;
+ xtmp = (xsq - ysq) + prev_x + P;
+ y = (2*x*y) + prev_y + Q;
+ prev_x = tmp_prev_x;
+ prev_y = tmp_prev_y;
+ break;
+ case 10:
+ tmp_prev_x = x;
+ tmp_prev_y = y;
+ xtmp = (xsq - ysq) + P + Q*prev_x;
+ y = (2*x*y) + Q*prev_y;
+ prev_x = tmp_prev_x;
+ prev_y = tmp_prev_y;
+ break;
+ }
+ x = xtmp;
+ }
+
+ if (lessThanMax == 1) {
+ fractalRow[col] = maxVal(0,((int)round(mu*10)-1))%(max*10);
+ } else {
+ fractalRow[col] = -1;
+ }
+ //TODO Store results so color changes don't require recalculation
+
+ }
+ (*env)->SetIntArrayRegion(env, result, 0, xres, fractalRow);
+ return result;
}
View
8 native-src/FractalMath/byrne_fractal_NativeLib.h
@@ -9,11 +9,11 @@ extern "C" {
#endif
/*
* Class: byrne_fractal_NativeLib
- * Method: getHelloWorld
- * Signature: ()Ljava/lang/String;
+ * Method: getFractalRow
+ * Signature: (IIIIIIIDDDDDD)[I
*/
-JNIEXPORT jstring JNICALL Java_byrne_fractal_NativeLib_getHelloWorld
- (JNIEnv *, jobject);
+JNIEXPORT jintArray JNICALL Java_byrne_fractal_NativeLib_getFractalRow
+ (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble);
#ifdef __cplusplus
}
View
29 src/byrne/fractal/ComplexEquation.java
@@ -20,23 +20,28 @@
package byrne.fractal;
public enum ComplexEquation {
- SECOND_ORDER(2),
- THIRD_ORDER(3),
- FOURTH_ORDER(4),
- FIFTH_ORDER(5),
- SIXTH_ORDER(6),
- Z4Z3Z2(4),
- Z6Z2(6),
- BURNING_SHIP(2),
- MANOWAR(2),
- PHOENIX(2);
+ SECOND_ORDER(1,2),
+ THIRD_ORDER(2,3),
+ FOURTH_ORDER(3,4),
+ FIFTH_ORDER(4,5),
+ SIXTH_ORDER(5,6),
+ Z4Z3Z2(6,4),
+ Z6Z2(7,6),
+ BURNING_SHIP(8,2),
+ MANOWAR(9,2),
+ PHOENIX(10,2);
- private int power;
+ private int power, native_integer;
- ComplexEquation(int p) {
+ ComplexEquation(int i, int p) {
+ native_integer = i;
power = p;
}
+ int getInt() {
+ return native_integer;
+ }
+
int getPower() {
return power;
}
View
10 src/byrne/fractal/FractalType.java
@@ -20,5 +20,13 @@
package byrne.fractal;
public enum FractalType {
- MANDELBROT, JULIA
+ MANDELBROT(1), JULIA(2);
+
+ private int native_integer;
+ FractalType(int i) {
+ native_integer = i;
+ }
+ public int getInt() {
+ return native_integer;
+ }
}
View
118 src/byrne/fractal/GenerateFractalTask.java
@@ -146,7 +146,7 @@ public GenerateFractalTask(FractalParameters p, FractalView fv) {
private Bitmap createBitmap() {
- System.out.println(mNativeLib.getHelloWorld());
+
ComplexEquation equation = params.getEquation();
int power = equation.getPower();
@@ -173,6 +173,7 @@ private Bitmap createBitmap() {
paint.setStrokeWidth(1);
int[] colorIntegers = calculateColors();
+ int[] rowColors;
double x=-1, y=-1, prev_x = -1, prev_y =-1,tmp_prev_x,tmp_prev_y, mu = 1;
int index;
@@ -187,106 +188,20 @@ private Bitmap createBitmap() {
for (int rpass = 0; rpass < PASSES; rpass++) {
for (int row=rpass; row < yres; row += PASSES) {
+
updateCount++;
if (updateCount % 8 == 0) {
if (isCancelled())
return b;
this.publishProgress(b);
- }
-
- if (type == FractalType.MANDELBROT) {
- Q = imagmax - row*deltaQ;
- }
-
+ }
+ rowColors = mNativeLib.getFractalRow(row,xres,yres,
+ power,max,equation.getInt(),type.getInt(),P,Q,
+ realmin,realmax,imagmin,imagmax);
for (int col=0; col < xres; col++) {
- if (type == FractalType.MANDELBROT) {
- P = realmin + col*deltaP;
- x = y = 0.0;
- prev_x = prev_y = 0.0;
- } else if (type == FractalType.JULIA) {
-
- x = realmin + (double)col * deltaP;
- y = imagmax - (double)row * deltaQ;
- prev_x = x;
- prev_y = y;
- }
- lessThanMax = false;
- double xsq, ysq;
- int extraIterations = 0;
- for (index = 0; index < max; index++) {
- xsq = x*x;
- ysq = y*y;
-
- if (xsq + ysq > 4) {
- //a few extra iterations improves color smoothing - why don't some equations work when a higher number is used?
- if (extraIterations == 2) {
- lessThanMax = true;
- mu = index + 2 - (Math.log(Math.log(Math.sqrt(xsq + ysq))/ Math.log(2.0))/Math.log(power));
- break;
- } else {
- extraIterations++;
- index--;
- }
- }
-
- //TODO Refactoring needed. Maybe change ComplexEquation to an abstract class?
- switch (equation) {
- case SECOND_ORDER:
- xtmp = xsq - ysq + P;
- y = (2*x*y) + Q;
- break;
- case THIRD_ORDER:
- xtmp = xsq*x - 3*x*ysq + P;
- y = -ysq*y + 3*xsq*y + Q;
- break;
- case FOURTH_ORDER:
- xtmp = xsq*xsq - 6*xsq*ysq + ysq*ysq + P;
- y = 4*xsq*x*y - 4*x*ysq*y + Q;
- break;
- case FIFTH_ORDER:
- xtmp = xsq*xsq*x-10*xsq*x*ysq+5*x*ysq*ysq + P;
- y=(5*xsq*xsq*y-10*xsq*ysq*y+ysq*ysq*y) + Q;
- break;
- case SIXTH_ORDER:
- xtmp = xsq*xsq*xsq-15*xsq*xsq*ysq+15*xsq*ysq*ysq-ysq*ysq*ysq + P;
- y=(6*xsq*xsq*x*y-20*xsq*x*ysq*y+6*x*ysq*ysq*y) + Q;
- break;
- case Z4Z3Z2:
- xtmp = xsq*xsq - 6*xsq*ysq + ysq*ysq - (xsq*x - 3*x*ysq) - (xsq - ysq) + P;
- y = 4*xsq*x*y - 4*x*ysq*y - (-ysq*y + 3*xsq*y) - (2*x*y) + Q;
- break;
- case Z6Z2:
- xtmp = xsq*xsq*xsq-15*xsq*xsq*ysq+15*xsq*ysq*ysq-ysq*ysq*ysq - (xsq - ysq) + P;
- y = (6*xsq*xsq*x*y-20*xsq*x*ysq*y+6*x*ysq*ysq*y) - (2*x*y) + Q;
- break;
- case BURNING_SHIP:
- xtmp = xsq - ysq + P;
- y = (2*Math.abs(x)*Math.abs(y)) - Q;
- break;
- case MANOWAR:
- tmp_prev_x = x;
- tmp_prev_y = y;
- xtmp = (xsq - ysq) + prev_x + P;
- y = (2*x*y) + prev_y + Q;
- prev_x = tmp_prev_x;
- prev_y = tmp_prev_y;
- break;
- case PHOENIX:
- tmp_prev_x = x;
- tmp_prev_y = y;
- xtmp = (xsq - ysq) + P + Q*prev_x;
- y = (2*x*y) + Q*prev_y;
- prev_x = tmp_prev_x;
- prev_y = tmp_prev_y;
- break;
- }
- x = xtmp;
- }
-
- if (lessThanMax) {
- int colorIndex = Math.max(0,((int)Math.round(mu*10)-1))%(max*10);
- paint.setColor(colorIntegers[colorIndex]);
+ if (rowColors[col] >= 0) {
+ paint.setColor(colorIntegers[rowColors[col]]);
} else {
paint.setColor(Color.BLACK);
}
@@ -315,8 +230,19 @@ private Bitmap createBitmap() {
}
}
class NativeLib {
- public native String getHelloWorld();
-
+ public native int[] getFractalRow(int row,
+ int xres,
+ int yres,
+ int power,
+ int max,
+ int equation,
+ int type,
+ double P,
+ double Q,
+ double realmin,
+ double realmax,
+ double imagmin,
+ double imagmax);
static {
System.loadLibrary("FractalMath");
}
Please sign in to comment.
Something went wrong with that request. Please try again.