concat.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { isBigNumber, isMatrix, isNumber } from '../../utils/is.js';
  2. import { clone } from '../../utils/object.js';
  3. import { arraySize } from '../../utils/array.js';
  4. import { IndexError } from '../../error/IndexError.js';
  5. import { DimensionError } from '../../error/DimensionError.js';
  6. import { factory } from '../../utils/factory.js';
  7. var name = 'concat';
  8. var dependencies = ['typed', 'matrix', 'isInteger'];
  9. export var createConcat = /* #__PURE__ */factory(name, dependencies, _ref => {
  10. var {
  11. typed,
  12. matrix,
  13. isInteger
  14. } = _ref;
  15. /**
  16. * Concatenate two or more matrices.
  17. *
  18. * Syntax:
  19. *
  20. * math.concat(A, B, C, ...)
  21. * math.concat(A, B, C, ..., dim)
  22. *
  23. * Where:
  24. *
  25. * - `dim: number` is a zero-based dimension over which to concatenate the matrices.
  26. * By default the last dimension of the matrices.
  27. *
  28. * Examples:
  29. *
  30. * const A = [[1, 2], [5, 6]]
  31. * const B = [[3, 4], [7, 8]]
  32. *
  33. * math.concat(A, B) // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
  34. * math.concat(A, B, 0) // returns [[1, 2], [5, 6], [3, 4], [7, 8]]
  35. * math.concat('hello', ' ', 'world') // returns 'hello world'
  36. *
  37. * See also:
  38. *
  39. * size, squeeze, subset, transpose
  40. *
  41. * @param {... Array | Matrix} args Two or more matrices
  42. * @return {Array | Matrix} Concatenated matrix
  43. */
  44. return typed(name, {
  45. // TODO: change signature to '...Array | Matrix, dim?' when supported
  46. '...Array | Matrix | number | BigNumber': function ArrayMatrixNumberBigNumber(args) {
  47. var i;
  48. var len = args.length;
  49. var dim = -1; // zero-based dimension
  50. var prevDim;
  51. var asMatrix = false;
  52. var matrices = []; // contains multi dimensional arrays
  53. for (i = 0; i < len; i++) {
  54. var arg = args[i];
  55. // test whether we need to return a Matrix (if not we return an Array)
  56. if (isMatrix(arg)) {
  57. asMatrix = true;
  58. }
  59. if (isNumber(arg) || isBigNumber(arg)) {
  60. if (i !== len - 1) {
  61. throw new Error('Dimension must be specified as last argument');
  62. }
  63. // last argument contains the dimension on which to concatenate
  64. prevDim = dim;
  65. dim = arg.valueOf(); // change BigNumber to number
  66. if (!isInteger(dim)) {
  67. throw new TypeError('Integer number expected for dimension');
  68. }
  69. if (dim < 0 || i > 0 && dim > prevDim) {
  70. // TODO: would be more clear when throwing a DimensionError here
  71. throw new IndexError(dim, prevDim + 1);
  72. }
  73. } else {
  74. // this is a matrix or array
  75. var m = clone(arg).valueOf();
  76. var size = arraySize(m);
  77. matrices[i] = m;
  78. prevDim = dim;
  79. dim = size.length - 1;
  80. // verify whether each of the matrices has the same number of dimensions
  81. if (i > 0 && dim !== prevDim) {
  82. throw new DimensionError(prevDim + 1, dim + 1);
  83. }
  84. }
  85. }
  86. if (matrices.length === 0) {
  87. throw new SyntaxError('At least one matrix expected');
  88. }
  89. var res = matrices.shift();
  90. while (matrices.length) {
  91. res = _concat(res, matrices.shift(), dim, 0);
  92. }
  93. return asMatrix ? matrix(res) : res;
  94. },
  95. '...string': function string(args) {
  96. return args.join('');
  97. }
  98. });
  99. });
  100. /**
  101. * Recursively concatenate two matrices.
  102. * The contents of the matrices is not cloned.
  103. * @param {Array} a Multi dimensional array
  104. * @param {Array} b Multi dimensional array
  105. * @param {number} concatDim The dimension on which to concatenate (zero-based)
  106. * @param {number} dim The current dim (zero-based)
  107. * @return {Array} c The concatenated matrix
  108. * @private
  109. */
  110. function _concat(a, b, concatDim, dim) {
  111. if (dim < concatDim) {
  112. // recurse into next dimension
  113. if (a.length !== b.length) {
  114. throw new DimensionError(a.length, b.length);
  115. }
  116. var c = [];
  117. for (var i = 0; i < a.length; i++) {
  118. c[i] = _concat(a[i], b[i], concatDim, dim + 1);
  119. }
  120. return c;
  121. } else {
  122. // concatenate this dimension
  123. return a.concat(b);
  124. }
  125. }