PageRenderTime 28ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/webmatrix/src/webmatrix/util/DoubleArrays.java

https://bitbucket.org/gidiko/gridapp
Java | 1432 lines | 754 code | 153 blank | 525 comment | 119 complexity | d46c021e1cf170eedd3859cf2b8eda5b MD5 | raw file
  1. package webmatrix.util;
  2. import java.util.*;
  3. import java.io.*;
  4. /**
  5. * Utility methods for arrays of doubles.
  6. */
  7. public class DoubleArrays {
  8. //////////////////////////////////////////////////////////////////////
  9. // Methods with broad applicability
  10. //////////////////////////////////////////////////////////////////////
  11. /**
  12. * Returns an array of data contained in given <code>vector</code>
  13. *
  14. * @param vector vector containing data.
  15. * @return array of data.
  16. */
  17. public static double[] toArray(Vector<Double> vector) {
  18. int size = vector.size();
  19. double[] result = new double[size];
  20. Enumeration<Double> elements = vector.elements();
  21. int index = 0;
  22. while (elements.hasMoreElements()) {
  23. result[index] = elements.nextElement().doubleValue();
  24. index++;
  25. }
  26. return result;
  27. }
  28. /**
  29. * Returns a shuffling of <code>data</code>.
  30. *
  31. * @param data data to shuffle.
  32. * @return shuffled data.
  33. */
  34. public static double[] shuffle(double[] data) {
  35. int size = data.length;
  36. double[] dataShuffled = new double[size];
  37. System.arraycopy(data, 0, dataShuffled, 0, size);
  38. for (int i = 0; i < size; i++) {
  39. int target = i + (int)(Math.random() * (size - i));
  40. double temp = dataShuffled[i];
  41. dataShuffled[i] = dataShuffled[target];
  42. dataShuffled[target] = temp;
  43. }
  44. return dataShuffled;
  45. }
  46. /**
  47. * Permutes entries in <code>data</code> according to given permutation
  48. * vector <code>map</code>.
  49. * data[i] <- data[map[i]].
  50. *
  51. * @param data data to permute.
  52. * @param map permutation vector.
  53. * @return data with permutation applied.
  54. */
  55. public static double[] permute(double[] data, int[] map) {
  56. int n = map.length;
  57. double[] dataPermuted = new double[n];
  58. for (int i = 0; i < n; i++) {
  59. dataPermuted[i] = data[map[i]];
  60. }
  61. return dataPermuted;
  62. }
  63. /**
  64. * Normalizes data to unity (sum of its elements set to one)
  65. * Divides each entry by data sum
  66. *
  67. * @param data data to normalize.
  68. * @return normalized data.
  69. */
  70. public static double[] normalize(double[] data) {
  71. double sum = sum(data);
  72. return scale(data, 1.0 / sum);
  73. }
  74. /**
  75. * Returns an array of <code>n</code> random numbers.
  76. *
  77. * @param n length of the array.
  78. * @return array of random numbers.
  79. */
  80. public static double[] random(int n) {
  81. double[] data = new double[n];
  82. for(int i = 0; i < n; i++) {
  83. data[i] = Math.random();
  84. }
  85. return data;
  86. }
  87. /**
  88. * Returns a 2D array of <code>m x n</code> random numbers.
  89. *
  90. * @param m number of rows.
  91. * @param n number of columns.
  92. * @return 2D array of random numbers.
  93. */
  94. public static double[][] random(int m, int n) {
  95. double[][] data = new double[m][n];
  96. for(int i = 0; i < m; i++) {
  97. data[i] = random(n);
  98. }
  99. return data;
  100. }
  101. /**
  102. * Removes duplicates.
  103. *
  104. * @param data data with possible duplicate entries.
  105. * @return data with duplicates removed.
  106. */
  107. public static double[] removeDuplicates(double[] data) {
  108. int n = data.length;
  109. Set set = new HashSet<Double>();
  110. for (int i = 0; i < n; i++) {
  111. set.add(data[i]);
  112. }
  113. Vector<Double> uniquesVector = new Vector<Double>();
  114. uniquesVector.addAll(set);
  115. double[] uniques = toArray(uniquesVector);
  116. return uniques;
  117. }
  118. /**
  119. * Removes duplicates from leaf arrays in data.
  120. *
  121. * @param data data with possible duplicate entries in leaf arrays.
  122. * @return data with duplicate entries in leaf arrays removed.
  123. */
  124. public static double[][] removeDuplicates(double[][] data) {
  125. int size = data.length;
  126. double[][] condensed = new double[size][];
  127. for (int i = 0; i < size; i++) {
  128. double[] leaf = removeDuplicates(data[i]);
  129. condensed[i] = leaf;
  130. }
  131. return condensed;
  132. }
  133. /**
  134. * Returns a count of the appearances of an element within some data.
  135. *
  136. * @param data data searched in.
  137. * @param element element searched for.
  138. * @return number of counts.
  139. */
  140. public static int count(double data[], double element) {
  141. int counter = 0;
  142. int size = data.length;
  143. for(int i = 0; i < size; i++) {
  144. if(data[i] == element) {
  145. counter++;
  146. }
  147. }
  148. return counter;
  149. }
  150. /**
  151. * Returns an array of positions of element within some data.
  152. *
  153. * @param data data searched in.
  154. * @param element element searched for.
  155. * @return array of positions.
  156. */
  157. public static int[] position(double data[], double element) {
  158. int size = data.length;
  159. int counts = count(data, element);
  160. int[] index = new int[counts];
  161. int counter = 0;
  162. for (int i = 0; i < size; i++) {
  163. if(data[i] == element) {
  164. index[counter] = i;
  165. counter++;
  166. }
  167. }
  168. return index;
  169. }
  170. /**
  171. * Returns a range of elements within <code>[0.0, end)</code> with <code>step =
  172. * 1.0</code> (starting from <code>0.0</code>).
  173. *
  174. * @param end upper bound for range.
  175. * @return range of elements
  176. */
  177. public static double[] range(double end) {
  178. return range(0.0, end);
  179. }
  180. /**
  181. * Returns a range of elements within <code>[start, end)</code> with <code>step =
  182. * 1.0</code> (starting from <code>start</code>).
  183. *
  184. * @param start lower bound for range.
  185. * @param end upper bound for range.
  186. * @return range of elements
  187. */
  188. public static double[] range(double start, double end) {
  189. return range(start, end, 1.0);
  190. }
  191. /**
  192. * Returns a range of elements within <code>[start, end)</code> with given
  193. * <code>step</code> (starting from <code>start</code>).
  194. *
  195. * @param start lower bound for range.
  196. * @param end upper bound for range.
  197. * @param step distance of consecutive elements
  198. * @return range of elements
  199. */
  200. public static double[] range(double start, double end, double step) {
  201. double num = end - start;
  202. int steps = (int)Math.ceil(num / step);
  203. double[] result = new double[steps];
  204. for (int i = 0; i < steps; i++) {
  205. result[i] = start + i * step;
  206. }
  207. return result;
  208. }
  209. /**
  210. * Returns a 2D array by splitting <code>data</code> into given number of
  211. * <code>rows</code>
  212. *
  213. * @param data data to split.
  214. * @param rows number of rows.
  215. * @return 2D array.
  216. */
  217. public static double[][] splitByRows(double[] data, int rows) {
  218. int size = data.length;
  219. int columns = size / rows;
  220. double[][] result = new double[rows][columns];
  221. int i, j;
  222. for (int k = 0; k < size ; k++) {
  223. i = k / columns;
  224. j = k % columns;
  225. result[i][j] = data[k];
  226. }
  227. return result;
  228. }
  229. /**
  230. * Returns a 2D array by splitting <code>data</code> into given number of
  231. * <code>columns</code>
  232. *
  233. * @param data data to split.
  234. * @param columns number of columns.
  235. * @return 2D array.
  236. */
  237. public static double[][] splitByColumns(double[] data, int columns) {
  238. int size = data.length;
  239. int rows = size / columns;
  240. double[][] result = new double[rows][columns];
  241. int i, j;
  242. for (int k = 0; k < size ; k++) {
  243. i = k % rows;
  244. j = k / rows;
  245. result[i][j] = data[k];
  246. }
  247. return result;
  248. }
  249. /**
  250. * Returns a 1D array of data by traversing rectangular array <code>a</code>
  251. * in row-major order (C-like).
  252. *
  253. * @param a rectangular array traversed.
  254. * @return 1D array.
  255. */
  256. public static double[] packByRows(double[][] a) {
  257. int rows = a.length;
  258. int columns = a[0].length;
  259. int size = rows * columns;
  260. double[] result = new double[size];
  261. int counter = 0;
  262. for (int i = 0; i < rows; i++) {
  263. for (int j = 0 ; j < columns; j++) {
  264. result[counter] = a[i][j];
  265. counter++;
  266. }
  267. }
  268. return result;
  269. }
  270. /**
  271. * Returns a 1D array of data by traversing rectangular array <code>a</code>
  272. * in column-major order (Fortran-like).
  273. *
  274. * @param a rectangular array traversed.
  275. * @return 1D array.
  276. */
  277. public static double[] packByColumns(double[][] a) {
  278. int rows = a.length;
  279. int columns = a[0].length;
  280. int size = rows * columns;
  281. double[] result = new double[size];
  282. int counter = 0;
  283. for (int j = 0; j < columns; j++) {
  284. for (int i = 0 ; i < rows; i++) {
  285. result[counter] = a[i][j];
  286. counter++;
  287. }
  288. }
  289. return result;
  290. }
  291. /**
  292. * Returns a 1D array of data by traversing array <code>a</code>
  293. * in row-major order (C-like). Note that the array does not have to be rectangular.
  294. *
  295. * @param a rectangular array traversed.
  296. * @return 1D array.
  297. */
  298. public static double[] flatten(double[][] a) {
  299. int rows = a.length;
  300. int size = 0;
  301. for (int i = 0; i < rows; i++) {
  302. size = size + a[i].length;
  303. }
  304. double[] result = new double[size];
  305. int counter = 0;
  306. for (int i = 0; i < rows; i++) {
  307. int cols = a[i].length;
  308. for (int j = 0 ; j < cols; j++) {
  309. result[counter] = a[i][j];
  310. counter++;
  311. }
  312. }
  313. return result;
  314. }
  315. /**
  316. * Returns norm1 of the difference of two 1D data arrays.
  317. * Norm1 is the sum of absolute values.
  318. *
  319. * @param x a data array.
  320. * @param y the other data array.
  321. * @return norm1.
  322. */
  323. public static double diffNorm1(double[] x, double[] y) {
  324. int size = x.length;
  325. double diff = 0.0;
  326. for(int i = 0; i < size; i++) {
  327. diff = diff + Math.abs(x[i] - y[i]);
  328. }
  329. return diff;
  330. }
  331. /**
  332. * Returns norm of the difference of two 1D data arrays.
  333. * Norm2 is also known as the Euclidean distance: the square root of the sum
  334. * of squares.
  335. *
  336. * @param x a data array.
  337. * @param y the other data array.
  338. * @return norm2.
  339. */
  340. public static double diffNorm2(double[] x, double[] y) {
  341. int size = x.length;
  342. double diff = 0.0;
  343. for(int i = 0; i < size; i++) {
  344. double temp = x[i] - y[i];
  345. diff = diff + temp * temp;
  346. }
  347. return Math.sqrt(diff);
  348. }
  349. /**
  350. * Returns normInf of the difference of two 1D data arrays.
  351. * NormInf is the maximum of the absolute values.
  352. *
  353. * @param x a data array.
  354. * @param y the other data array.
  355. * @return normInf.
  356. */
  357. public static double diffNormInf(double[] x, double[] y) {
  358. int size = x.length;
  359. double max = Math.abs(x[0] - y[0]);
  360. for (int i = 1; i < size; i++) {
  361. double abs = Math.abs(x[i] - y[i]);
  362. if (abs > max) {
  363. max = abs;
  364. }
  365. }
  366. return max;
  367. }
  368. /**
  369. * Returns absolute values of given data array elements.
  370. *
  371. * @param data data array.
  372. * @return absolute values.
  373. */
  374. public static double[] abs(double[] data) {
  375. int size = data.length;
  376. double[] result = new double[size];
  377. for (int i = 0; i < size; i++) {
  378. result[i] = Math.abs(data[i]);
  379. }
  380. return result;
  381. }
  382. /**
  383. * Returns maximum element in <code>data</code>.
  384. *
  385. * @param data data.
  386. * @return maximum.
  387. */
  388. public static double max(double[] data) {
  389. int size = data.length;
  390. double max = data[0];
  391. for (int i = 1; i < size; i++) {
  392. if (data[i] > max) {
  393. max = data[i];
  394. }
  395. }
  396. return max;
  397. }
  398. /**
  399. * Returns minimum element in <code>data</code>.
  400. *
  401. * @param data data.
  402. * @return minimum.
  403. */
  404. public static double min(double[] data) {
  405. int size = data.length;
  406. double min = data[0];
  407. for (int i = 1; i < size; i++) {
  408. if (data[i] < min) {
  409. min = data[i];
  410. }
  411. }
  412. return min;
  413. }
  414. /**
  415. * Returns the sum of two 1D data arrays.
  416. *
  417. * @param x a data array.
  418. * @param y the other data array.
  419. * @return sum.
  420. */
  421. public static double[] plus(double[] x, double[] y) {
  422. int size = x.length;
  423. double[] result = new double[size];
  424. for(int i = 0; i < size; i++) {
  425. result[i] = x[i] + y[i];
  426. }
  427. return result;
  428. }
  429. /**
  430. * Returns the difference of two 1D data arrays.
  431. *
  432. * @param x a data array.
  433. * @param y the data array subtracted.
  434. * @return difference.
  435. */
  436. public static double[] minus(double[] x, double[] y) {
  437. int size = x.length;
  438. double[] result = new double[size];
  439. for(int i = 0; i < size; i++) {
  440. result[i] = x[i] - y[i];
  441. }
  442. return result;
  443. }
  444. /**
  445. * Returns the element-by-element products of two 1D data arrays.
  446. *
  447. * @param x a data array.
  448. * @param y the other data array.
  449. * @return element-by-element products.
  450. */
  451. public static double[] mult(double[] x, double[] y) {
  452. int size = x.length;
  453. double[] result = new double[size];
  454. for(int i = 0; i < size; i++) {
  455. result[i] = x[i] * y[i];
  456. }
  457. return result;
  458. }
  459. /**
  460. * Returns the element-by-element quotients of two 1D data arrays.
  461. *
  462. * @param x a data array.
  463. * @param y data array of divisors.
  464. * @return element-by-element quotients.
  465. */
  466. public static double[] div(double[] x, double[] y) {
  467. int size = x.length;
  468. double[] result = new double[size];
  469. for(int i = 0; i < size; i++) {
  470. result[i] = x[i] / y[i];
  471. }
  472. return result;
  473. }
  474. /**
  475. * Returns <code>data</code> scaled by (each element multiplied by)
  476. * <code>alpha</code>.
  477. *
  478. * @param data data array to scale
  479. * @param alpha scaling factor.
  480. * @return scaled data.
  481. */
  482. public static double[] scale(double[] data, double alpha) {
  483. int size = data.length;
  484. double[] result = new double[size];
  485. for(int i = 0; i < size; i++) {
  486. result[i] = data[i] * alpha;
  487. }
  488. return result;
  489. }
  490. public static double[] mult(double[] data, double alpha) {
  491. return scale(data, alpha);
  492. }
  493. public static double[] plus(double[] data, double elem) {
  494. int size = data.length;
  495. double[] result = new double[size];
  496. for(int i = 0; i < size; i++) {
  497. result[i] = data[i] + elem;
  498. }
  499. return result;
  500. }
  501. /**
  502. * Returns only those data contained within closed interval <code>[lower,
  503. * upper]</code>
  504. *
  505. * @param data array to search.
  506. * @param lower lower bound.
  507. * @param upper upper bound.
  508. * @return data contained in closed interval.
  509. */
  510. public static double[] filterByBounds(double[] data, double lower, double upper) {
  511. int size = data.length;
  512. int counter = 0;
  513. // how many
  514. for (int i = 0; i < size; i++) {
  515. double product = (data[i] - lower) * (data[i] - upper);
  516. if (product <= 0) {
  517. counter++;
  518. }
  519. }
  520. // store them
  521. double[] result = new double[counter];
  522. counter = 0;
  523. for (int i = 0; i < size; i++) {
  524. double product = (data[i] - lower) * (data[i] - upper);
  525. if (product <= 0) {
  526. result[counter] = data[i];
  527. counter++;
  528. }
  529. }
  530. return result;
  531. }
  532. /**
  533. * Returns only those data NOT contained within closed interval <code>[lower,
  534. * upper]</code>
  535. *
  536. * @param data array to search.
  537. * @param lower lower bound.
  538. * @param upper upper bound.
  539. * @return data NOT contained in closed interval.
  540. */
  541. public static double[] filterByOffBounds(double[] data, double lower, double upper) {
  542. int size = data.length;
  543. int counter = 0;
  544. // how many
  545. for (int i = 0; i < size; i++) {
  546. double product = (data[i] - lower) * (data[i] - upper);
  547. if (product > 0) {
  548. counter++;
  549. }
  550. }
  551. // store them
  552. double[] result = new double[counter];
  553. counter = 0;
  554. for (int i = 0; i < size; i++) {
  555. double product = (data[i] - lower) * (data[i] - upper);
  556. if (product > 0) {
  557. result[counter] = data[i];
  558. counter++;
  559. }
  560. }
  561. return result;
  562. }
  563. /**
  564. * Returns the inner product of two 1D data arrays.
  565. * This is just the sum of its element-by-element products.
  566. *
  567. * @param x a data array.
  568. * @param y the other data array.
  569. * @return inner product.
  570. */
  571. public static double innerMult(double[] x, double[] y) {
  572. int size = x.length;
  573. double result = 0.0;
  574. for(int i = 0; i < size; i++) {
  575. result = result + x[i] * y[i];
  576. }
  577. return result;
  578. }
  579. /**
  580. * Returns the outer product of two 1D data arrays.
  581. * This is a 2D array containing elements of the form <code>a[i,j] = x[i] *
  582. * y[j]</code>.
  583. *
  584. * @param x a data array.
  585. * @param y the other data array.
  586. * @return outer product.
  587. */
  588. public static double[][] outerMult(double[] x, double[] y) {
  589. int sizex = x.length;
  590. int sizey = y.length;
  591. double[][] result = new double[sizex][sizey];
  592. for (int i = 0; i < sizex; i++) {
  593. for (int j = 0; j < sizey; j++) {
  594. result[i][j] = x[i] * y[j];
  595. }
  596. }
  597. return result;
  598. }
  599. /**
  600. * Returns the sum of elements in given 1D data array.
  601. *
  602. * @param data data array.
  603. * @return sum of elements.
  604. */
  605. public static double sum(double[] data) {
  606. int size = data.length;
  607. double sum = 0.0;
  608. for (int i = 0; i < size; i++) {
  609. sum = sum + data[i];
  610. }
  611. return sum;
  612. }
  613. /**
  614. * Returns a copy of given 1D data array.
  615. *
  616. * @param data data array.
  617. * @return copy.
  618. */
  619. public static double[] copy(double[] data) {
  620. int size = data.length;
  621. double[] result = new double[size];
  622. System.arraycopy(data, 0, result, 0, size);
  623. return result;
  624. }
  625. /**
  626. * Returns a copy of given 2D data array.
  627. *
  628. * @param data data array.
  629. * @return copy.
  630. */
  631. public static double[][] copy(double[][] data) {
  632. int sizex = data.length;
  633. double[][] result = new double[sizex][];
  634. for (int i = 0; i < sizex; i++) {
  635. int sizey = data[i].length;
  636. result[i] = new double[sizey];
  637. System.arraycopy(data[i], 0, result[i], 0, sizey);
  638. }
  639. return result;
  640. }
  641. /**
  642. * Returns true if given data arrays are exactly the same.
  643. *
  644. * @param x a data array.
  645. * @param y the other data array.
  646. * @return true if given data arrays are exactly the same.
  647. */
  648. public static boolean same(double[] x, double[] y) {
  649. int sizex = x.length;
  650. int sizey = y.length;
  651. if (sizex != sizey){
  652. return false;
  653. }
  654. for (int i = 0; i < sizex; i++){
  655. if(x[i] != y[i]) {
  656. return false;
  657. }
  658. }
  659. return true;
  660. }
  661. /**
  662. * Returns true if given data arrays are exactly the same.
  663. *
  664. * @param x a data array.
  665. * @param y the other data array.
  666. * @return true if given data arrays are exactly the same.
  667. */
  668. public static boolean same(double[][] x, double[][] y) {
  669. int sizex = x.length;
  670. int sizey = y.length;
  671. if (sizex != sizey){
  672. return false;
  673. }
  674. for (int i = 0; i < sizex; i++) {
  675. if (!same(x[i], y[i])){
  676. return false;
  677. }
  678. }
  679. return true;
  680. }
  681. /**
  682. * Returns an array of row sizes in given data matrix.
  683. *
  684. * @param data data matrix
  685. * @return array of row sizes
  686. */
  687. public static int[] sizes(double[][] data) {
  688. int size = data.length;
  689. int[] howlong = new int[size];
  690. for (int i = 0; i < size; i++) {
  691. howlong[i] = data[i].length;
  692. }
  693. return howlong;
  694. }
  695. /**
  696. * Returns 1D skeleton array with space allocated for <code>m</code>
  697. * elements.
  698. *
  699. * @return 1D skeleton array.
  700. */
  701. public static double[] make(int m) {
  702. double[] result = new double[m];
  703. return result;
  704. }
  705. /**
  706. * Returns 2D skeleton array with space allocated for <code>m x n</code>
  707. * elements.
  708. *
  709. * @return 2D skeleton array.
  710. */
  711. public static double[][] make(int m, int n) {
  712. double[][] result = new double[m][n];
  713. return result;
  714. }
  715. /**
  716. * Assigns <code>value</code> to all data array elements.
  717. *
  718. * @param data 1D data array to change.
  719. * @param value value to assign.
  720. */
  721. public static void assign(double[] data, double value) {
  722. Arrays.fill(data, value);
  723. }
  724. /**
  725. * Assigns <code>value</code> to all data array elements.
  726. *
  727. * @param data 2D data array to change.
  728. * @param value value to assign.
  729. */
  730. public static void assign(double[][] data, double value) {
  731. int size = data.length;
  732. for (int i = 0; i < size; i++) {
  733. Arrays.fill(data[i], value);
  734. }
  735. }
  736. /**
  737. * Return 1D array with all its <code>n</code> elements set to
  738. * <code>value</code>.
  739. *
  740. * @param n number of elements.
  741. * @param value value to assign.
  742. * @return 1D array.
  743. */
  744. public static double[] repeat(double value, int n) {
  745. double[] result = new double[n];
  746. Arrays.fill(result, value);
  747. return result;
  748. }
  749. /**
  750. * Appends array <code>x</code> to <code>data</code> array and returns the
  751. * increased-size array.
  752. *
  753. * @param data the original array.
  754. * @param x array to append to the original.
  755. * @return increased-size array.
  756. */
  757. public static double[] append(double[] data, double[] x) {
  758. int size = data.length + x.length;
  759. double[] result = new double[size];
  760. System.arraycopy(data, 0, result, 0, data.length);
  761. System.arraycopy(x, 0, result, data.length, x.length);
  762. return result;
  763. }
  764. /**
  765. * Returns ranking order of data vector, meaning the order imposed by
  766. * the values of its elements.
  767. * ranks[i] contains the integer rank of data[i]. It
  768. * follows that maximum value in data is found for i with ranks[i] = 0
  769. *
  770. * @param data containing ranking values.
  771. * @return integer ranks of data.
  772. */
  773. public static int[] ranking(double[] data) {
  774. int size = data.length;
  775. double[] datasorted = new double[size];
  776. int[] ranks = new int[size];
  777. System.arraycopy(data, 0, datasorted, 0, size);
  778. Arrays.sort(datasorted);
  779. int[] starts = new int[size];
  780. int[] ends = new int[size];
  781. int[] filled = IntArrays.repeat(0, size);
  782. int[] changes = flips(datasorted);
  783. System.arraycopy(changes, 0, starts, 1, size - 1);
  784. starts[0] = 0;
  785. System.arraycopy(changes, 0, ends, 0, size - 1);
  786. ends[size - 1] = size;
  787. for(int i = 0; i < size; i++) {
  788. // XXX the ambiguity here is problem source for rankingPermutation()
  789. int spos = Arrays.binarySearch(datasorted, data[i]);
  790. int pos = 0;
  791. if (filled[spos] == 1) {
  792. int start = starts[spos];
  793. int end = ends[spos];
  794. for (int j = start; j < end; j++) {
  795. if (filled[j] == 0) {
  796. filled[j] = 1;
  797. pos = j;
  798. break;
  799. }
  800. }
  801. } else {
  802. filled[spos] = 1;
  803. pos = spos;
  804. }
  805. ranks[i] = pos;
  806. }
  807. return IntArrays.reverse(ranks);
  808. }
  809. public static int[][] repeatLimits(double[] data) {
  810. int[] bounds = flips(data);
  811. int bsize = bounds.length;
  812. int size = bsize + 1;
  813. int[][] limits = new int[size][2];
  814. for (int i = 0; i < bsize; i++) {
  815. limits[i][1] = bounds[i];
  816. }
  817. for (int i = 1; i < size; i++) {
  818. limits[i][0] = bounds[i - 1];
  819. }
  820. limits[0][0] = 0;
  821. limits[size - 1][1] = data.length;
  822. return limits;
  823. }
  824. public static int[] flips(double[] data) {
  825. int size = data.length;
  826. double[] diffs = gaps(data, 1);
  827. int dsize = diffs.length;
  828. int changes = 0;
  829. for (int i = 0; i < dsize; i++) {
  830. if (diffs[i] != 0.0) {
  831. changes++;
  832. }
  833. }
  834. int[] index = new int[changes];
  835. changes = 0;
  836. for (int i = 0; i < dsize; i++) {
  837. if (diffs[i] != 0.0) {
  838. index[changes] = i + 1;
  839. changes++;
  840. }
  841. }
  842. return index;
  843. }
  844. // data[i + gap] - data[i]
  845. public static double[] gaps(double[] data, int gap) {
  846. int size = data.length;
  847. int dsize = size - gap;
  848. double[] diffs = new double[dsize];
  849. for (int i = 0; i < dsize; i++) {
  850. diffs[i] = data[i + gap] - data[i];
  851. }
  852. return diffs;
  853. }
  854. ///
  855. public static int[] rankingOld(double[] data) {
  856. int size = data.length;
  857. double[] datasorted = new double[size];
  858. int[] ranks = new int[size];
  859. System.arraycopy(data, 0, datasorted, 0, size);
  860. Arrays.sort(datasorted);
  861. double[] uniques = removeDuplicates(data);
  862. Arrays.sort(uniques);
  863. int usize = uniques.length;
  864. int counter = 0;
  865. int[] starts = new int[size];
  866. int[] ends = new int[size];
  867. for (int i = 0; i < usize; i++) {
  868. double value = uniques[i];
  869. int start = counter;
  870. int localcounter = 0;
  871. while((counter < size) && (datasorted[counter] == value)) {
  872. starts[counter] = start;
  873. counter++;
  874. }
  875. for (int j = start; j < counter; j++) {
  876. ends[j] = counter;
  877. }
  878. }
  879. int[] filled = new int[size];
  880. for(int i = 0; i < size; i++) {
  881. // XXX the ambiguity here is problem source for rankingPermutation()
  882. int pos = Arrays.binarySearch(datasorted, data[i]);
  883. // but sorting was in ascending order, so...
  884. if (filled[pos] == 0) {
  885. ranks[i] = pos;
  886. filled[pos] = 1;
  887. } else {
  888. int start = starts[i];
  889. int end = ends[i];
  890. for (int j = start; j < end; j++) {
  891. if (filled[j] == 0){
  892. ranks[i] = j;
  893. filled[j] = 1;
  894. break;
  895. }
  896. }
  897. }
  898. }
  899. return IntArrays.reverse(ranks);
  900. }
  901. /**
  902. * Returns a permutation which when applied to x vector will give y vector.
  903. *
  904. * @param x vector to be permuted.
  905. * @param y vector to which we want to permute to.
  906. * @return permutation.
  907. */
  908. public static int[] permutation(double[] x, double[] y) {
  909. int size = x.length;
  910. int[] xranks = new int[size];
  911. int[] iyranks = new int[size];
  912. int[] map = new int[size];
  913. double[] xsorted = new double[size];
  914. System.arraycopy(x, 0, xsorted, 0, size);
  915. Arrays.sort(xsorted);
  916. for (int i = 0; i < size; i++) {
  917. int pos = Arrays.binarySearch(xsorted, x[i]);
  918. xranks[i] = pos;
  919. }
  920. double[] ysorted = new double[size];
  921. System.arraycopy(y, 0, ysorted, 0, size);
  922. Arrays.sort(ysorted);
  923. for (int i = 0; i < size; i++) {
  924. int pos = Arrays.binarySearch(ysorted, y[i]);
  925. iyranks[pos] = i;
  926. }
  927. for (int i = 0; i < size; i++) {
  928. map[i] = xranks[iyranks[i]];
  929. }
  930. return map;
  931. }
  932. /**
  933. * Returns a permutation which when applied to data vector will sort it in
  934. * descending order. permutation[i] contains the position of the i-th
  935. * largest entry in data. It follows that permutation[0] is the index to
  936. * largest value in data vector.
  937. *
  938. * @param data containing ranking values.
  939. * @return descending order data permutation.
  940. */
  941. public static int[] rankingPermutation(double[] data) {
  942. int size = data.length;
  943. int[] map = new int[size];
  944. int[] ranks = ranking(data);
  945. for (int i = 0; i < size; i++) {
  946. map[ranks[i]] = i;
  947. }
  948. return map;
  949. }
  950. /**
  951. * Returns perturbation index between two vectors.
  952. * This is calculated by accumulating terms of the form <code> gap * weight
  953. * / size </code> where gap is the difference between ranking positions of a
  954. * node in rankings contained in a and b, weighted by actual rank
  955. * (i.e. changes in ranking for high rank nodes contribute more than changes
  956. * in the tail of rankings.
  957. *
  958. * @param a vector against which we compare.
  959. * @param b vector compared to <code>a>/code>.
  960. * @return perturbation index.
  961. */
  962. public static double rankingPerturbation(double[] a, double[] b) {
  963. int size = a.length;
  964. int[] map = new int[size];
  965. int[] aranks = rankingPermutation(a);
  966. int[] branks = rankingPermutation(b);
  967. // map[k]: what is the ranking of node k?
  968. for (int i = 0; i < size; i++) {
  969. map[branks[i]] = i;
  970. }
  971. // perturbation index
  972. double pindex = 0.0;
  973. for (int i = 0; i < size; i++) {
  974. int gap;
  975. int weight = size - i;
  976. int apos = aranks[i];
  977. // bpos: the ranking of node apos after.
  978. int bpos = map[apos];
  979. // i: this is the ranking of node apos before.
  980. gap = Math.abs(bpos - i);
  981. pindex = pindex + gap * (double)weight / (double)size;
  982. }
  983. return pindex;
  984. }
  985. //////////////////////////////////////////////////////////////////////
  986. // Methods with more or less project applicability
  987. //////////////////////////////////////////////////////////////////////
  988. /**
  989. * Returns a number which is similar in spirit to greatest common divisor
  990. * for a set of floating point numbers.
  991. *
  992. * @param data floating point numbers.
  993. * @return gcd of these floating point numbers.
  994. */
  995. public static double gcd(double[] data) {
  996. double THRESHOLD = 1.0e-6;
  997. int size = data.length;
  998. double unit = 0.0;
  999. if (size == 0) {
  1000. unit = data[0];
  1001. return unit;
  1002. } else {
  1003. double min = data[0];
  1004. for (int i = 1; i < size; i++) {
  1005. min = Math.min(min, data[i]);
  1006. }
  1007. int k = 0;
  1008. int i = 0;
  1009. double links;
  1010. double absRemainder;
  1011. while (k != size) {
  1012. i++;
  1013. unit = min / i;
  1014. k = 0;
  1015. while (k < size) {
  1016. absRemainder = Math.abs(Math.IEEEremainder(data[k], unit));
  1017. if (absRemainder < THRESHOLD) {
  1018. k++;
  1019. } else {
  1020. break;
  1021. }
  1022. }
  1023. }
  1024. }
  1025. return unit;
  1026. }
  1027. /**
  1028. * Returns an array of minimum integers with ratios equal to the respective ratios of
  1029. * numbers in given data.
  1030. *
  1031. * @param data floating point numbers.
  1032. * @return array of minimum integers.
  1033. */
  1034. public static int[] gcdMultipliers(double[] data) {
  1035. int size = data.length;
  1036. int[] multipliers = new int[size];
  1037. double unit = gcd(data);
  1038. for (int i = 0; i < size; i++) {
  1039. multipliers[i] = (int)Math.round(data[i] / unit);
  1040. }
  1041. return multipliers;
  1042. }
  1043. /**
  1044. * Loads data array from binary file.
  1045. * The binary file is supposed to successively contain:
  1046. * <p>
  1047. * <table border="1">
  1048. * <tr>
  1049. * <td><b>datatype</b></td>
  1050. * <td><b>name</b></td>
  1051. * <td><b>description</b></td>
  1052. * </tr>
  1053. * <tr>
  1054. * <td><code>int</code></td>
  1055. * <td><code>m</code></td>
  1056. * <td>number of rows</td>
  1057. * </tr>
  1058. * <tr>
  1059. * <td><code>int</code></td>
  1060. * <td><code>n</code></td>
  1061. * <td>number of columns</td>
  1062. * </tr>
  1063. * <tr>
  1064. * <td><code>double[m * n]</code></td>
  1065. * <td><code>data</code></td>
  1066. * <td>vector of values</td>
  1067. * </tr>
  1068. * </table>
  1069. * </p>
  1070. * <p>
  1071. * Total number of bytes: <code> 8 + 8 * m * n </code>
  1072. * </p>
  1073. *
  1074. * @param filename name of file.
  1075. * @return 2D data array.
  1076. * @throws IOException if file cannot be read.
  1077. */
  1078. public static double[][] load(String filename) throws IOException {
  1079. DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
  1080. int m = dis.readInt();
  1081. int n = dis.readInt();
  1082. int num = m * n;
  1083. double[] data = new double[num];
  1084. for (int i = 0; i < num; i++) {
  1085. data[i] = dis.readDouble();
  1086. }
  1087. dis.close();
  1088. double[][] result = splitByRows(data, m);
  1089. return result;
  1090. }
  1091. /**
  1092. * Stores 2D data array to binary file.
  1093. * The binary file successively contains:
  1094. * <p>
  1095. * <table border="1">
  1096. * <tr>
  1097. * <td><b>datatype</b></td>
  1098. * <td><b>name</b></td>
  1099. * <td><b>description</b></td>
  1100. * </tr>
  1101. * <tr>
  1102. * <td><code>int</code></td>
  1103. * <td><code>m</code></td>
  1104. * <td>number of rows</td>
  1105. * </tr>
  1106. * <tr>
  1107. * <td><code>int</code></td>
  1108. * <td><code>n</code></td>
  1109. * <td>number of columns</td>
  1110. * </tr>
  1111. * <tr>
  1112. * <td><code>double[m * n]</code></td>
  1113. * <td><code>data</code></td>
  1114. * <td>array of values</td>
  1115. * </tr>
  1116. * </table>
  1117. * </p>
  1118. * <p>
  1119. * Total number of bytes: <code> 8 + 8 * m * n </code>
  1120. * </p>
  1121. * @param data 2D data array to be written.
  1122. * @param filename name of file.
  1123. * @param rowmajor if true, writes 2D data array in row-major order.
  1124. * @throws IOException if file cannot be written.
  1125. */
  1126. public static void dump(double[][] data, String filename, boolean rowmajor) throws IOException {
  1127. DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
  1128. int m = data.length;
  1129. int n = data[0].length;
  1130. int num = m * n;
  1131. dos.writeInt(m);
  1132. dos.writeInt(n);
  1133. double[] dataToWrite = null;
  1134. if (rowmajor) {
  1135. dataToWrite = packByRows(data);
  1136. } else {
  1137. dataToWrite = packByColumns(data);
  1138. }
  1139. for (int i = 0; i < num; i++) {
  1140. dos.writeDouble(dataToWrite[i]);
  1141. }
  1142. dos.close();
  1143. }
  1144. public static void dump(double[][] data, String filename) throws IOException {
  1145. dump(data, filename, true);
  1146. }
  1147. /**
  1148. * Stores 1D data array to binary file.
  1149. * The binary file successively contains:
  1150. * <p>
  1151. * <table border="1">
  1152. * <tr>
  1153. * <td><b>datatype</b></td>
  1154. * <td><b>name</b></td>
  1155. * <td><b>description</b></td>
  1156. * </tr>
  1157. * <tr>
  1158. * <td><code>int</code></td>
  1159. * <td><code>m</code></td>
  1160. * <td>number of rows</td>
  1161. * </tr>
  1162. * <tr>
  1163. * <td><code>int</code></td>
  1164. * <td><code>n</code></td>
  1165. * <td>number of columns</td>
  1166. * </tr>
  1167. * <tr>
  1168. * <td><code>double[m * n]</code></td>
  1169. * <td><code>data</code></td>
  1170. * <td>vector of values</td>
  1171. * </tr>
  1172. * </table>
  1173. * </p>
  1174. * <p>
  1175. * Total number of bytes: <code> 8 + 8 * m * n </code>
  1176. * </p>
  1177. * One of m, n is 1.
  1178. * @param data 1D data array.
  1179. * @param filename name of file.
  1180. * @param row if true, writes data array as a row vector (m=1).
  1181. * @throws IOException if file cannot be written.
  1182. */
  1183. public static void dump(double[] data, String filename, boolean row) throws IOException {
  1184. DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
  1185. int num = data.length;
  1186. int m;
  1187. int n;
  1188. if (row) {
  1189. m = 1;
  1190. n = num;
  1191. } else {
  1192. m = num;
  1193. n = 1;
  1194. }
  1195. dos.writeInt(m);
  1196. dos.writeInt(n);
  1197. for (int i = 0; i < num; i++) {
  1198. dos.writeDouble(data[i]);
  1199. }
  1200. dos.close();
  1201. }
  1202. public static void dump(double[] data, String filename) throws IOException {
  1203. dump(data, filename, true);
  1204. }
  1205. /**
  1206. * Returns 1D data array with elements in reverse order
  1207. *
  1208. * @param data data array to reverse.
  1209. * @return reversed data array.
  1210. */
  1211. public static double[] reverse(double[] data) {
  1212. int size = data.length;
  1213. double[] reversed = new double[size];
  1214. for (int i = 0; i < size; i++) {
  1215. reversed[i] = data[size - i - 1];
  1216. }
  1217. return reversed;
  1218. }
  1219. /**
  1220. * Returns number of smallest elements in data with some not over the value
  1221. * of nth data element (put in descending order).
  1222. *
  1223. * @param data data array to inspect.
  1224. * @param n nth largest element.
  1225. * @return number of tail elements.
  1226. */
  1227. public static int nthWeakerTail(double[] data, int n) {
  1228. int size = data.length;
  1229. // sort first in any case
  1230. double[] dataSorted = new double[size];
  1231. System.arraycopy(data, 0, dataSorted, 0, size);
  1232. Arrays.sort(dataSorted);
  1233. // larger values first
  1234. dataSorted = reverse(dataSorted);
  1235. double limit = data[n];
  1236. double sum = 0.0;
  1237. int num = 0;
  1238. while (sum < limit) {
  1239. sum = sum + dataSorted[size - num - 1];
  1240. num++;
  1241. }
  1242. return num;
  1243. }
  1244. /**
  1245. * Zeros data elements indexed by <code>index</code> and distributes their
  1246. * values uniformly to rest data. Sum is preserved.
  1247. *
  1248. * @param data data array.
  1249. * @param index index array of elements to zero.
  1250. * @return data with zerod positions.
  1251. */
  1252. public static double[] neutral(double[] data, int[] index) {
  1253. int size = data.length;
  1254. int isize = index.length;
  1255. double[] neutrals = new double[size];
  1256. double sum = 0.0;
  1257. for (int i = 0; i < isize; i++) {
  1258. sum = sum + data[index[i]];
  1259. }
  1260. // actives
  1261. int asize = size - isize;
  1262. double share = sum / asize;
  1263. // sentinel -> +1
  1264. int[] indexSorted = new int[isize + 1];
  1265. System.arraycopy(index, 0, indexSorted, 0, isize);
  1266. indexSorted[isize] = size;
  1267. Arrays.sort(indexSorted);
  1268. int counter = 0;
  1269. for (int i = 0; i < size; i++) {
  1270. if (i == indexSorted[counter]) {
  1271. neutrals[i] = 0.0;
  1272. counter++;
  1273. } else {
  1274. neutrals[i] = data[i] + share;
  1275. }
  1276. }
  1277. return neutrals;
  1278. }
  1279. }