PageRenderTime 70ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/webmatrix/src/webmatrix/util/IntArrays.java

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