triangular matrix
index numbers
algorithm design
matrix coefficients
mathematical computation

algorithm for index numbers of triangular matrix coefficients

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When a matrix is triangular, half of its entries are known to be zero, so storing the full square matrix wastes space. A common optimization is packed storage, where only the meaningful coefficients are placed in a one-dimensional array. The core problem then becomes index mapping: given matrix coordinates, what is the position in that packed array?

Choose a Storage Order First

There is no single universal formula until you fix the storage convention. Two decisions matter:

  • upper or lower triangular matrix
  • row-major or column-major packed order

Without that, two correct implementations can produce different linear indices for the same matrix coordinate.

This article uses zero-based indexing and row-major packed storage.

Lower Triangular Matrix Formula

For a lower triangular matrix, valid positions satisfy i >= j. In row-major packed storage, row 0 contributes one stored element, row 1 contributes two, and so on.

The number of stored elements before row i is:

  • 'i * (i + 1) / 2'

So the packed index is:

  • 'k = i * (i + 1) / 2 + j'

A Python implementation:

python
1def lower_triangular_index(i, j):
2    if j > i:
3        raise ValueError("Position is outside the stored lower triangle")
4    return i * (i + 1) // 2 + j
5
6
7for i in range(4):
8    for j in range(i + 1):
9        print((i, j), lower_triangular_index(i, j))

For a 4 x 4 lower triangular matrix, this maps the stored coefficients to indices 0 through 9.

Upper Triangular Matrix Formula

For an upper triangular matrix, valid positions satisfy j >= i. In row-major packed storage, row 0 contributes n stored elements, row 1 contributes n - 1, and so on.

The number of elements before row i is:

  • 'i * n - i * (i - 1) / 2'

So the packed index becomes:

  • 'k = i * n - i * (i - 1) / 2 + (j - i)'

Here is a runnable version:

python
1def upper_triangular_index(n, i, j):
2    if j < i:
3        raise ValueError("Position is outside the stored upper triangle")
4    return i * n - i * (i - 1) // 2 + (j - i)
5
6
7n = 4
8for i in range(n):
9    for j in range(i, n):
10        print((i, j), upper_triangular_index(n, i, j))

This formula depends on the full matrix size n, which is why it takes one extra parameter.

Why Triangular Numbers Appear

The formulas use triangular-number counts because the number of stored elements grows or shrinks by one per row.

For the lower triangle, the prefix lengths are:

  • '1'
  • '1 + 2'
  • '1 + 2 + 3'

That cumulative pattern is exactly why the i * (i + 1) / 2 term appears.

Verify the Mapping with Packed Storage

Once you have the formula, storing and reading values becomes straightforward.

python
1def build_lower_storage(matrix):
2    packed = []
3    for i, row in enumerate(matrix):
4        for j in range(i + 1):
5            packed.append(row[j])
6    return packed
7
8
9matrix = [
10    [1, 0, 0],
11    [2, 3, 0],
12    [4, 5, 6],
13]
14
15packed = build_lower_storage(matrix)
16print(packed)
17print(packed[lower_triangular_index(2, 1)])

The index formula lets you access packed coefficients without rebuilding the square matrix.

Common Pitfalls

  • Forgetting to define the storage order before deriving the formula.
  • Mixing zero-based and one-based indexing.
  • Applying a lower-triangle formula to upper-triangle storage, or the reverse.
  • Ignoring invalid coordinates outside the stored triangle.
  • Recomputing the full matrix when packed access would be enough.

Summary

  • Triangular matrices are often stored in packed one-dimensional form to save space.
  • The index formula depends on upper versus lower storage and on row-major versus column-major order.
  • For zero-based lower-triangular row-major storage, use i * (i + 1) / 2 + j.
  • For zero-based upper-triangular row-major storage, use i * n - i * (i - 1) / 2 + (j - i).
  • Define the layout first, then derive or implement the matching formula.

Course illustration
Course illustration

All Rights Reserved.