ShapeHistogram.java

00001 package edu.stanford.hci.r3.pen.gesture;
00002 
00003 import java.util.ArrayList;
00004 
00005 import cern.colt.matrix.DoubleMatrix2D;
00006 import cern.colt.matrix.impl.DenseDoubleMatrix2D;
00007 import cern.colt.matrix.linalg.Algebra;
00008 import cern.colt.matrix.linalg.SingularValueDecomposition;
00009 
00020 public class ShapeHistogram {
00021         static public class Pair {
00022                 public int column;
00023 
00024                 public int row;
00025 
00026                 public Pair(int row, int column) {
00027                         this.row = row;
00028                         this.column = column;
00029                 }
00030         }
00031 
00032         public static double costWeighting = .3;
00033 
00034         static Pair Z0;
00035 
00036         // ah, point arrays
00037         static public DoubleMatrix2D bookstein(int N, double[][] X, double[][] X2, double beta_k,
00038                         double[] E) {
00039                 // int N = X.length;
00040                 // int Nb = X2.length;
00041                 // assert(N == Nb);
00042                 double[][] r2 = new double[N + 3][N + 3];
00043                 for (int i = 0; i < N; i++)
00044                         for (int j = i; j < N; j++)
00045                                 r2[i][j] = r2[j][i] = Math.pow(X[i][0] - X[j][0], 2)
00046                                                 + Math.pow(X[i][1] - X[j][1], 2);
00047                 for (int i = 0; i < N; i++)
00048                         r2[i][i] *= Math.log(r2[i][i] + 1);
00049                 for (int i = 0; i < N; i++)
00050                         for (int j = i + 1; j < N; j++)
00051                                 r2[i][j] = r2[j][i] = r2[j][i] * Math.log(r2[j][i]);
00052                 DoubleMatrix2D K = new DenseDoubleMatrix2D(r2); // too large, but I'm lazy
00053                 for (int i = 0; i < N; i++) {
00054                         r2[i][i] += beta_k;
00055                         r2[i][N] = r2[N][i] = 1;
00056                         r2[i][N + 1] = r2[N + 1][i] = X[i][0];
00057                         r2[i][N + 2] = r2[N + 2][i] = X[i][1];
00058                 }
00059                 // for(int i=0;i<N;i++) for(int j=0;j<N;j++)
00060                 // r2[i][j]+=beta_k;
00061                 Algebra algebra = new Algebra();
00062                 DoubleMatrix2D L = new DenseDoubleMatrix2D(r2);
00063                 DoubleMatrix2D invL = algebra.inverse(L);
00064                 double[][] v = new double[N + 3][2];
00065                 for (int i = 0; i < N; i++) {
00066                         v[i][0] = X2[i][0];
00067                         v[i][1] = X2[i][1];
00068                 }
00069                 DoubleMatrix2D V = new DenseDoubleMatrix2D(v);
00070                 DoubleMatrix2D c = algebra.mult(invL, V);
00071                 DoubleMatrix2D Qpart = algebra.mult(K, c);
00072                 DoubleMatrix2D Q = algebra.mult(algebra.transpose(c), Qpart);
00073                 // extra bits are all zero, so it's cool
00074                 E[0] = algebra.trace(Q) / N; // bending energy
00075                 // affine cost
00076                 double[][] a = new double[2][2];
00077                 a[0][0] = c.getQuick(N + 1, 0);
00078                 a[0][1] = c.getQuick(N + 1, 1);
00079                 a[1][0] = c.getQuick(N + 2, 0);
00080                 a[1][1] = c.getQuick(N + 2, 1);
00081                 if (a[0][0] == Double.NaN)
00082                         System.exit(-1);
00083                 SingularValueDecomposition s = new SingularValueDecomposition(new DenseDoubleMatrix2D(a));
00084                 E[1] = Math.log(s.cond());
00085                 return c;
00086         }
00087 
00088         static public void clear_covers(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00089                 for (int i = 0; i < n; i++) {
00090                         R_cov[i] = 0;
00091                         C_cov[i] = 0;
00092                 }
00093         }
00094 
00095         static public double[][] computeCostMatrix(ArrayList<ShapeHistogram> first,
00096                         ArrayList<ShapeHistogram> second, int size1, int size2, double dummy_epsilon) {
00097                 assert (first.size() == second.size()); // perhaps I should do those dummy points
00098                 int points = first.size();
00099                 double[][] cost = new double[points][points];
00100                 for (int i = 0; i < points; i++) {
00101                         ShapeHistogram s1 = first.get(i);
00102                         for (int j = 0; j < points; j++) {
00103                                 if (i >= size1 || j >= size2) {
00104                                         cost[i][j] = dummy_epsilon;
00105                                         continue;
00106                                 }
00107                                 ShapeHistogram s2 = second.get(j);
00108                                 double sum = 0;
00109                                 for (int k = 0; k < s1.data.length; k++) {
00110                                         int s1k = s1.data[k];
00111                                         int s2k = s2.data[k];
00112                                         if (s1k == s2k)
00113                                                 continue;
00114                                         sum += Math.pow(s1k - s2k, 2) / (double) (s1k + s2k);
00115                                 }
00116                                 cost[i][j] = .5 * sum;// + Math.random() * .1;
00117                         }
00118                 }
00119                 return cost;
00120         }
00121 
00122         static public void convert_path(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov,
00123                         ArrayList<Pair> path) {
00124                 for (int i = 0; i < path.size(); i++) {
00125                         Pair point = path.get(i);
00126                         if (M[point.row][point.column] == 1)
00127                                 M[point.row][point.column] = 0;
00128                         else
00129                                 M[point.row][point.column] = 1;
00130                 }
00131         }
00132 
00133         static public double distance(double[][] costMatrix, int[] mapping, int firstSize,
00134                         int secondSize) {
00135                 // leave out dummy points, scale
00136                 int points = mapping.length;
00137                 double cost = 0;
00138                 int count = Math.min(firstSize, secondSize);
00139                 for (int i = 0; i < points; i++) {
00140                         int first = i;
00141                         int second = mapping[i];
00142                         if (first >= firstSize || second >= secondSize)
00143                                 continue;
00144                         cost += costMatrix[i][mapping[i]];
00145                 }
00146                 return cost / count;
00147         }
00148 
00149         static public void erase_primes(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00150                 for (int i = 0; i < n; i++) {
00151                         for (int j = 0; j < n; j++) {
00152                                 if (M[i][j] == 2)
00153                                         M[i][j] = 0;
00154                         }
00155                 }
00156         }
00157 
00158         static public Pair find_a_zero(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00159                 int row = -1;
00160                 int col = -1;
00161                 boolean done = false;
00162                 for (int i = 0; i < n && !done; i++)
00163                         for (int j = 0; j < n; j++) {
00164                                 if (C[i][j] == 0 && R_cov[i] == 0 && C_cov[j] == 0) {
00165                                         row = i;
00166                                         col = j;
00167                                         done = true;
00168                                 }
00169                         }
00170                 return new Pair(row, col);
00171         }
00172 
00173         static public Pair find_prime_in_row(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov,
00174                         int row) {
00175                 int column = -1;
00176                 for (int j = 0; j < n; j++)
00177                         if (M[row][j] == 2)
00178                                 column = j;
00179                 return new Pair(row, column);
00180         }
00181 
00182         static public double find_smallest(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00183                 double minval = Double.MAX_VALUE;
00184                 for (int i = 0; i < n; i++)
00185                         for (int j = 0; j < n; j++)
00186                                 if (R_cov[i] == 0 && C_cov[j] == 0 && minval > C[i][j])
00187                                         minval = C[i][j];
00188                 return minval;
00189         }
00190 
00191         static public Pair find_star_in_col(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov,
00192                         int column) {
00193                 int row = -1;
00194                 for (int i = 0; i < n; i++)
00195                         if (M[i][column] == 1)
00196                                 row = i;
00197                 return new Pair(row, column);
00198         }
00199 
00200         static public int find_star_in_row(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov,
00201                         int row) {
00202                 int col = -1;
00203                 for (int j = 0; j < n; j++)
00204                         if (M[row][j] == 1)
00205                                 col = j;
00206                 return col;
00207         }
00208 
00209         // http://www.public.iastate.edu/~ddoty/HungarianAlgorithm.html
00210         static public int[] munkres(int n, double[][] costs) {
00211                 // n : constant integer := 20;
00212                 // C : is array(1..n,1..n) of float;
00213                 // M : is array(1..n,1..n) of integer;
00214                 // Row,Col : is array(1..n) of integer;
00215                 int stepnum;
00216                 boolean done;
00217                 double[][] C = new double[n][n];
00218                 int[][] M = new int[n][n];
00219                 int[] Row = new int[n];
00220                 int[] Col = new int[n];
00221 
00222                 for (int j = 0; j < n; j++)
00223                         for (int i = 0; i < n; i++)
00224                                 C[j][i] = costs[j][i];
00225 
00226                 done = false;
00227                 stepnum = 1;
00228                 while (!done) {
00229                         switch (stepnum) {
00230                         case 1:
00231                                 stepnum = step1(n, C, M, Row, Col);
00232                                 break;
00233                         case 2:
00234                                 stepnum = step2(n, C, M, Row, Col);
00235                                 break;
00236                         case 3:
00237                                 stepnum = step3(n, C, M, Row, Col);
00238                                 break;
00239                         case 4:
00240                                 stepnum = step4(n, C, M, Row, Col);
00241                                 break;
00242                         case 5:
00243                                 stepnum = step5(n, C, M, Row, Col);
00244                                 break;
00245                         case 6:
00246                                 stepnum = step6(n, C, M, Row, Col);
00247                                 break;
00248                         default:
00249                                 done = true;
00250                         }
00251                 }
00252                 int[] matching = new int[n];
00253                 for (int i = 0; i < n; i++)
00254                         for (int j = 0; j < n; j++)
00255                                 if (M[i][j] == 1) {
00256                                         matching[i] = j;
00257                                         continue;
00258                                 }
00259                 return matching;
00260         }
00261 
00262         static public double shapeContextCost(int N, double[][] costs, boolean[] good_rows,
00263                         boolean[] good_columns, int good_count) {
00264                 double rowMin = 0, colMin = 0;
00265                 for (int i = 0; i < N; i++) {
00266                         if (!good_rows[i])
00267                                 continue;
00268                         double m = Double.MAX_VALUE;
00269                         for (int j = 0; j < N; j++)
00270                                 if (good_columns[j] && costs[i][j] < m)
00271                                         m = costs[i][j];
00272                         colMin += m;
00273                 }
00274                 colMin /= good_count;
00275                 for (int j = 0; j < N; j++) {
00276                         if (!good_columns[j])
00277                                 continue;
00278                         double m = Double.MAX_VALUE;
00279                         for (int i = 0; i < N; i++)
00280                                 if (good_rows[i] && costs[i][j] < m)
00281                                         m = costs[i][j];
00282                         rowMin += m;
00283                 }
00284                 rowMin /= good_count;
00285                 return Math.max(rowMin, colMin);
00286         }
00287 
00288         public static double shapeContextMetric(ShapeContext shape1, ShapeContext shape2,
00289                         boolean rotationInvariant, boolean timeSensitive, boolean verbose) {
00290                 int dummy_padding = 6;
00291                 int N = Math.max(shape1.size(), shape2.size()) + dummy_padding;
00292                 int n = N;// Math.min(shape1.size(), shape2.size()) + dummy_padding;
00293                 ArrayList<ShapeHistogram> histogram1 = shape1.generateShapeHistogram(N, dummy_padding,
00294                                 rotationInvariant, timeSensitive);
00295                 ArrayList<ShapeHistogram> histogram2 = shape2.generateShapeHistogram(N, dummy_padding,
00296                                 rotationInvariant, timeSensitive);
00297                 // dummy value must vary as function of number of points used
00298                 double[][] costs = computeCostMatrix(histogram1, histogram2, shape1.size(), shape2.size(),
00299                                 10);
00300                 int[] matching = munkres(N, costs);
00301                 double[][] X1_new = shape1.points(N - dummy_padding);
00302                 double[][] X2_new = shape2.points(N - dummy_padding);
00303                 // take the NON-dummy points from both
00304                 // a point in X1 should not be matched to a dummy point; a point in X2 should not be matched
00305                 // from a dummy
00306                 int count = 0;
00307                 double[][] X1 = new double[n - dummy_padding][2];
00308                 double[][] X2 = new double[n - dummy_padding][2];
00309                 boolean[] good_rows = new boolean[N];
00310                 boolean[] good_columns = new boolean[N];
00311                 double mean_x1 = 0, mean_x2 = 0, mean_y1 = 0, mean_y2 = 0;
00312                 for (int i = 0; i < X1_new.length; i++)
00313                         if (matching[i] < X2_new.length) { // if this one is matched to a non-dummy
00314                                 X1[count][0] = X1_new[i][0];
00315                                 X1[count][1] = X1_new[i][1];
00316                                 X2[count][0] = X2_new[matching[i]][0];
00317                                 X2[count][1] = X2_new[matching[i]][1];
00318                                 mean_x1 += X1[count][0];
00319                                 mean_y1 += X1[count][1];
00320                                 mean_x2 += X2[count][0];
00321                                 mean_y2 += X2[count][1];
00322                                 good_rows[i] = true;
00323                                 good_columns[matching[i]] = true;
00324                                 count++;
00325                         }
00326                 mean_x1 /= count;
00327                 mean_y1 /= count;
00328                 mean_x2 /= count;
00329                 mean_y2 /= count;
00330                 // X1 = X1_new;
00331                 // X2 = X2_new;
00332                 for (int i = 0; i < count; i++) {
00333                         X1[i][0] -= mean_x1;
00334                         X1[i][1] -= mean_y1;
00335                         X2[i][0] -= mean_x2;
00336                         X2[i][1] -= mean_y2;
00337 
00338                 }
00339 
00340                 double[] eArray = new double[2];
00341                 double dist = 0;
00342                 for (int i = 0; i < count; i++)
00343                         for (int j = i + 1; j < count; j++)
00344                                 dist += Math.sqrt(Math.pow(X1[i][0] - X1[j][0], 2)
00345                                                 + Math.pow(X1[i][1] - X1[j][1], 2));
00346                 dist /= (n * (n - 1)) / 2;
00347                 double beta_k = Math.pow(dist, 2) * 1;
00348                 DoubleMatrix2D c = bookstein(count, X1, X2, beta_k, eArray);
00349                 double sc_cost = shapeContextCost(N, costs, good_rows, good_columns, count);
00350                 double[][] Xwarped = warp(X1, X2, c, count);
00351                 double mean_squared_error = 0;
00352                 for (int i = 0; i < count; i++) {
00353                         mean_squared_error += Math.sqrt(Math.pow(Xwarped[i][0] - X2[i][0], 2)
00354                                         + Math.pow(Xwarped[i][1] - X2[i][1], 2));
00355                 }
00356                 mean_squared_error /= count;
00357                 // System.out.println("mse: " + mean_squared_error);
00358                 // using digit distance function from paper
00359                 double total_cost = sc_cost + costWeighting * eArray[0];
00360                 if (verbose) {
00361                         // System.out.println("Total cost: " + total_cost + " bending cost: " + E[0] + " sc
00362                         // cost: " + sc_cost + " affine cost: " + E[1]);
00363                         // System.out.println(eArray[1]);
00364                         // System.out.println("Discarded " + (N - count - dummy_padding) + " points.");
00365                 }
00366 
00367                 /*
00368                  * if (false) { ArrayList<InkSample> old = new ArrayList<InkSample>(); ArrayList<InkSample>
00369                  * neW = new ArrayList<InkSample>(); for(int i = 0; i < count; i++) { old.add(new
00370                  * InkSample(X2[i][0]+20, X2[i][1]+20, 0, 0)); neW.add(new InkSample(Xwarped[i][0]+60,
00371                  * Xwarped[i][1]+60, 0, 0)); } Random random = new Random(); Ink ink = new Ink();
00372                  * ink.addStroke(new InkStroke(old, new Points())); ink.addStroke(new InkStroke(neW, new
00373                  * Points())); InkRenderer renderer = new InkRenderer(ink); renderer.renderToJPEG(new
00374                  * File("warped_context_"+random.nextInt()+".jpg"), new Pixels(300), new Points(100), new
00375                  * Points(100)); }
00376                  */
00377                 return total_cost; // just bending energy
00378                 // return 1.6 * E[0] + sc_cost + .3 * E[1];
00379         }
00380         /*
00381          * 
00382          * Pseudocode
00383          * 
00384          * constructor(bins[],mins[],maxes[],bands(=length bins))
00385          * 
00386          * add(double values[]) {increment all relevant bins}
00387          * 
00388          */
00389 
00390         static public boolean star_in_row(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov,
00391                         int row) {
00392                 for (int j = 0; j < n; j++)
00393                         if (M[row][j] == 1)
00394                                 return true;
00395                 return false;
00396         }
00397 
00398         static public int step1(int n, double[][] C, int[][] M, int[] Row, int[] Col) {
00399                 double minval = 0;
00400                 for (int i = 0; i < n; i++) {
00401                         minval = C[i][0];
00402                         for (int j = 1; j < n; j++) {
00403                                 if (minval > C[i][j])
00404                                         minval = C[i][j];
00405                         }
00406                         for (int j = 0; j < n; j++) {
00407                                 C[i][j] -= minval;
00408                         }
00409                 }
00410                 return 2;
00411         }
00412 
00413         static public int step2(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00414                 for (int i = 0; i < n; i++) {
00415                         for (int j = 0; j < n; j++) {
00416                                 if (C[i][j] == 0 && C_cov[j] == 0 && R_cov[i] == 0) {
00417                                         M[i][j] = 1;
00418                                         C_cov[j] = 1;
00419                                         R_cov[i] = 1;
00420                                 }
00421                         }
00422                 }
00423                 for (int i = 0; i < n; i++) {
00424                         C_cov[i] = 0;
00425                         R_cov[i] = 0;
00426                 }
00427                 return 3;
00428         }
00429 
00430         static public int step3(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00431                 int count;
00432                 for (int i = 0; i < n; i++) {
00433                         for (int j = 0; j < n; j++) {
00434                                 if (M[i][j] == 1) {
00435                                         C_cov[j] = 1;
00436                                 }
00437                         }
00438                 }
00439                 count = 0;
00440                 for (int j = 0; j < n; j++)
00441                         count = count + C_cov[j];
00442                 int step;
00443                 if (count >= n)
00444                         step = 7;
00445                 else
00446                         step = 4;
00447                 return step;
00448         }
00449 
00450         static public int step4(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00451                 while (true) {
00452                         Pair pair = find_a_zero(n, C, M, R_cov, C_cov);
00453                         if (pair.row == -1)
00454                                 return 6;
00455                         M[pair.row][pair.column] = 2;
00456                         if (star_in_row(n, C, M, R_cov, C_cov, pair.row)) {
00457                                 int col = find_star_in_row(n, C, M, R_cov, C_cov, pair.row);
00458                                 R_cov[pair.row] = 1;
00459                                 C_cov[col] = 0;
00460                         } else {
00461                                 Z0 = pair;
00462                                 return 5;
00463                         }
00464                 }
00465         }
00466 
00467         static public int step5(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00468                 int count = 1;
00469                 ArrayList<Pair> path = new ArrayList<Pair>();
00470                 path.add(Z0);
00471                 boolean done = false;
00472                 while (!done) {
00473                         Pair last = path.get(path.size() - 1);
00474                         Pair star = find_star_in_col(n, C, M, R_cov, C_cov, last.column);
00475                         if (star.row > -1) {
00476                                 path.add(new Pair(star.row, last.column));
00477                         } else
00478                                 done = true;
00479                         if (!done) {
00480                                 Pair prime = find_prime_in_row(n, C, M, R_cov, C_cov, star.row);
00481                                 path.add(new Pair(star.row, prime.column));
00482                         }
00483                 }
00484                 convert_path(n, C, M, R_cov, C_cov, path);
00485                 clear_covers(n, C, M, R_cov, C_cov);
00486                 erase_primes(n, C, M, R_cov, C_cov);
00487                 return 3;
00488         }
00489 
00490         static public int step6(int n, double[][] C, int[][] M, int[] R_cov, int[] C_cov) {
00491                 double minval = find_smallest(n, C, M, R_cov, C_cov);
00492                 for (int i = 0; i < n; i++)
00493                         for (int j = 0; j < n; j++) {
00494                                 if (R_cov[i] == 1)
00495                                         C[i][j] += minval;
00496                                 if (C_cov[j] == 0)
00497                                         C[i][j] -= minval;
00498                         }
00499                 return 4;
00500         }
00501 
00502         static public double[][] warp(double[][] X, double[][] X2, DoubleMatrix2D c, int N) {
00503                 Algebra algebra = new Algebra();
00504                 double[][] d2 = new double[N][N];
00505                 final double eps = 1e-10;
00506                 for (int i = 0; i < N; i++)
00507                         for (int j = i; j < N; j++) {
00508                                 double tmp = Math.pow(X[i][0] - X[j][0], 2) + Math.pow(X[i][1] - X[j][1], 2);
00509                                 d2[i][j] = d2[j][i] = tmp * Math.log(tmp + eps);
00510                         }
00511                 DoubleMatrix2D cCoord = new DenseDoubleMatrix2D(N, 2);
00512                 for (int i = 0; i < N; i++) {
00513                         cCoord.setQuick(i, 0, c.getQuick(i, 0));
00514                         cCoord.setQuick(i, 1, c.getQuick(i, 1));
00515                 }
00516 
00517                 DoubleMatrix2D warped = algebra
00518                                 .mult(algebra.transpose(cCoord), new DenseDoubleMatrix2D(d2));
00519 
00520                 DoubleMatrix2D partial = new DenseDoubleMatrix2D(2, 3);
00521                 for (int i = 0; i < 3; i++) {
00522                         partial.setQuick(0, i, c.getQuick(N + i, 0));
00523                         partial.setQuick(1, i, c.getQuick(N + i, 1));
00524                 }
00525                 double[][] paddedX = new double[3][N];
00526                 for (int i = 0; i < N; i++) {
00527                         paddedX[0][i] = 1;
00528                         paddedX[1][i] = X[i][0];
00529                         paddedX[2][i] = X[i][1];
00530                 }
00531                 DoubleMatrix2D affine = algebra.mult(partial, new DenseDoubleMatrix2D(paddedX));
00532                 double[][] result = new double[N][2];
00533                 for (int i = 0; i < N; i++) {
00534                         result[i][0] = affine.getQuick(0, i) + warped.getQuick(0, i);
00535                         result[i][1] = affine.getQuick(1, i) + warped.getQuick(1, i);
00536                 }
00537                 return result;
00538         }
00539 
00540         int bands;
00541 
00542         int[] bin_counts = null;
00543 
00544         double[][] bins = null;
00545 
00546         int[] data = null;
00547 
00548         boolean[] explicit_binning = null;
00549 
00550         double[] maxes = null;
00551 
00552         double[] mins = null;
00553 
00554         public ShapeHistogram() { // default constructor
00555         }
00556 
00557         // n+1 values for each dimension with explicit binning
00558         public ShapeHistogram(int[] bin_counts, double[] mins, double[] maxes,
00559                         boolean[] explicit_binning, double[][] bins, int bands) {
00560                 // old-fashioned it. More convenient for ANN anyway
00561                 int size = 1;
00562                 for (int i = 0; i < bands; i++)
00563                         size *= bin_counts[i];
00564                 data = new int[size];
00565                 this.bands = bands;
00566                 this.bins = bins;
00567                 this.bin_counts = bin_counts;
00568                 this.mins = mins;
00569                 this.maxes = maxes;
00570                 this.explicit_binning = explicit_binning;
00571         }
00572 
00573         public boolean addPoint(double[] input) {
00574                 assert (input.length == bands);
00575                 int multiplier = 1;
00576                 int index = 0;
00577                 for (int i = 0; i < bands; i++) {
00578                         int subindex;
00579                         int bin_count = bin_counts[i];
00580                         if (explicit_binning[i]) {
00581                                 for (subindex = 0; subindex < bin_counts[i]; subindex++)
00582                                         if (input[i] <= bins[i][subindex])
00583                                                 break;
00584                                 if (subindex == bin_counts[i])
00585                                         return false;
00586                         } else
00587                                 subindex = Math.min(
00588                                                 (int) (((input[i] - mins[i]) / (maxes[i] - mins[i])) * bin_count),
00589                                                 bin_count - 1);
00590                         index += multiplier * subindex;
00591                         multiplier *= bin_count;
00592                 }
00593                 data[index]++;
00594                 return true;
00595         }
00596 }

Generated on Sat Apr 14 18:21:38 2007 for R3 Paper Toolkit by  doxygen 1.4.7