cumsum method

dynamic cumsum({
  1. bool continuous = false,
  2. int? axis,
})

Performs cumulative sum operations similar to numpy's cumsum but with more flexibility.

Parameters:

  • continuous: When true, continues accumulation across axis boundaries (default: false)
  • axis: The summation axis (null returns flattened list, 0-4 for matrix operations):
    • null: Flattened list
    • 0: Column-wise accumulation
    • 1: Row-wise accumulation
    • 2: Diagonal (top-left to bottom-right)
    • 3: Diagonal (bottom-left to top-right)
    • 4: Diagonal (top-right to bottom-left)

Returns:

Examples:

var arr = Matrix([
  [1, 5, 6],
  [4, 7, 2],
  [3, 1, 9]
]);

print(arr.cumsum());
// [1, 6, 12, 4, 11, 13, 3, 4, 13]

print(arr.cumsum(continuous: true));
// [1, 6, 12, 16, 23, 25, 28, 29, 38]

print(arr.cumsum(axis: 0));
// ┌ 1  5  6 ┐
// │ 5 12  8 │
// └ 8 13 17 ┘

print(arr.cumsum(continuous: true, axis: 0));
// ┌ 1 13 27 ┐
// │ 5 20 29 │
// └ 8 21 38 ┘

print(arr.cumsum(axis: 1));
// ┌ 1  6 12 ┐
// │ 4 11 13 │
// └ 3  4 13 ┘

print(arr.cumsum(continuous: true, axis: 1));
// ┌  1  6 12 ┐
// │ 16 23 25 │
// └ 28 29 38 ┘

print(arr.cumsum(axis: 2));
// ┌ 1 5  6 ┐
// │ 4 8  7 │
// └ 3 5 17 ┘

print(arr.cumsum(continuous: true, axis: 2));
// ┌ 9 30 38 ┐
// │ 7 16 32 │
// └ 3 8 25 ┘

print(arr.cumsum(axis: 3));
// ┌ 1 9  16 ┐
// │ 4 10 3  │
// └ 3 1  9  ┘

print(arr.cumsum(continuous: true, axis: 3));
// ┌ 38 37 28 ┐
// │ 32 22 12 │
// └ 15 10 9 ┘

print(arr.cumsum(axis: 4));
// ┌ 1  5  6 ┐
// │ 9  13 2 │
// └ 16 3  9 ┘

print(arr.cumsum(continuous: true, axis: 4));
// ┌ 38 33 18 ┐
// │ 37 25 11 │
// └ 28 12 9 ┘

Implementation

dynamic cumsum({bool continuous = false, int? axis}) {
  int rows = _data.length;
  int cols = _data[0].length;

  List<List<dynamic>> result =
      List.generate(rows, (i) => List.filled(cols, 0));

  switch (axis) {
    case null:
      if (continuous) {
        // Continuous accumulation across entire matrix
        List flat = [];
        dynamic cumulative = 0;
        for (var row in _data) {
          for (var val in row) {
            cumulative += val;
            flat.add(cumulative);
          }
        }
        return flat;
      } else {
        // Row-wise accumulation without continuity
        List flat = [];
        for (var row in _data) {
          dynamic rowSum = 0;
          for (var val in row) {
            rowSum += val;
            flat.add(rowSum);
          }
        }
        return flat;
      }
    case 0: // Column-wise
      for (int j = 0; j < cols; j++) {
        for (int i = 0; i < rows; i++) {
          result[i][j] = _data[i][j];
          if (continuous) {
            if (j > 0 && i == 0) {
              result[i][j] += result[rows - 1][j - 1];
            }
            if (i > 0) {
              result[i][j] += result[i - 1][j];
            }
          } else {
            if (i > 0) {
              result[i][j] += result[i - 1][j];
            }
          }
        }
      }
      break;

    case 1: // Row-wise
      for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
          result[i][j] = _data[i][j];
          if (continuous) {
            if (i > 0 && j == 0) {
              result[i][j] += result[i - 1][cols - 1];
            }
            if (j > 0) {
              result[i][j] += result[i][j - 1];
            }
          } else {
            if (j > 0) {
              result[i][j] += result[i][j - 1];
            }
          }
        }
      }
      break;

    case 2: // Diagonal top-left to bottom-right
      if (continuous) {
        List<List<int>> coords = [];
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            coords.add([i, j]);
          }
        }
        coords.sort((a, b) {
          int diffA = a[0] - a[1];
          int diffB = b[0] - b[1];
          if (diffA != diffB) {
            return diffB.compareTo(diffA);
          } else {
            return a[0].compareTo(b[0]);
          }
        });
        dynamic cumulative = 0;
        for (var coord in coords) {
          int i = coord[0];
          int j = coord[1];
          cumulative += _data[i][j];
          result[i][j] = cumulative;
        }
      } else {
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            result[i][j] = _data[i][j];
            if (i > 0 && j > 0) {
              result[i][j] += result[i - 1][j - 1];
            }
          }
        }
      }

    case 3: // Diagonal bottom-left to top-right
      if (continuous) {
        List<List<int>> coords = [];
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            coords.add([i, j]);
          }
        }
        coords.sort((a, b) {
          int sumA = a[0] + a[1];
          int sumB = b[0] + b[1];
          if (sumA != sumB) {
            return sumB.compareTo(sumA);
          } else {
            return b[0].compareTo(a[0]);
          }
        });
        dynamic cumulative = 0;
        for (var coord in coords) {
          int i = coord[0];
          int j = coord[1];
          cumulative += _data[i][j];
          result[i][j] = cumulative;
        }
      } else {
        for (int j = 0; j < cols; j++) {
          for (int i = rows - 1; i >= 0; i--) {
            result[i][j] = _data[i][j];
            if (i < rows - 1 && j > 0) {
              result[i][j] += result[i + 1][j - 1];
            }
          }
        }
      }
      break;

    case 4: // Diagonal top-right to bottom-left
      if (continuous) {
        List<List<int>> coords = [];
        for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
            coords.add([i, j]);
          }
        }
        coords.sort((a, b) {
          int sumA = a[0] + a[1];
          int sumB = b[0] + b[1];
          if (sumA != sumB) {
            return sumB.compareTo(sumA);
          } else {
            return b[1].compareTo(a[1]);
          }
        });
        dynamic cumulative = 0;
        for (var coord in coords) {
          int i = coord[0];
          int j = coord[1];
          cumulative += _data[i][j];
          result[i][j] = cumulative;
        }
      } else {
        for (int j = cols - 1; j >= 0; j--) {
          for (int i = 0; i < rows; i++) {
            result[i][j] = _data[i][j];
            if (i > 0 && j < cols - 1) {
              result[i][j] += result[i - 1][j + 1];
            }
          }
        }
      }
      break;

    default:
      throw ArgumentError('Invalid axis value');
  }

  return Matrix(result);
}