Skip to content

← JAX Numerical Computing step 25 of 25

Hard Primitives

Cumulative Trapezoidal Integration

Jump to the task

Accumulate the area between samples

Suppose you measure velocity at evenly spaced times and want the displacement since the first sample. Between each pair of measurements, approximate velocity with a straight line. Its signed area is the average of the two velocities multiplied by the time interval.

segment_area[i] = (y[i] + y[i + 1]) / 2 * dx

A cumulative integral adds these segment areas as you move along the samples. Negative values can subtract from the total: this computes signed area, not total distance traveled or absolute area.

Worked example

import jax.numpy as jnp

y = jnp.array([0.0, 1.0, 2.0, 3.0])
dx = 1.0
segment_areas = (y[:-1] + y[1:]) / 2 * dx
# [0.5, 1.5, 2.5]
result = jnp.cumsum(segment_areas)
# [0.5, 2.0, 4.5]

The first result covers the first interval. The second covers the first two intervals: 0.5 + 1.5 = 2. The third covers all three. Each segment uses two neighboring samples, so four samples produce three results. There is no initial zero in the returned array.

The trapezoidal rule integrates the straight-line approximation exactly in real arithmetic. For an unknown curved function between samples, this is an approximation; sparse measurements can miss important changes. Floating-point arithmetic also introduces rounding.

Problem

Implement cumulative_integral(y, dx) using adjacent slices and jnp.cumsum.

  • y is a one-dimensional float32 array of N samples.
  • dx is a finite scalar giving the uniform step in the coordinate.
  • Return running sums of the trapezoid areas, without a leading zero. For N >= 1, the output shape is (N - 1,). Empty input also gives empty output; with fewer than two samples there is no interval.

Zero dx gives zero areas for finite samples. Negative dx reverses their sign, corresponding to moving in the decreasing-coordinate direction. A time interval would normally be positive.

Things to watch

y[:-1] and y[1:] contain matching left and right endpoints. Average each pair before multiplying by dx, then cumulatively sum the areas. Applying cumsum directly to y sums sample values rather than areas.

For nonuniform coordinates, each segment needs its own width x[1:] - x[:-1]. You can cumulatively sum those variable-width areas using the same pattern. jnp.trapezoid(y, x) returns only the total integral, so it is not a replacement for the running output here.