Suppose I implement a double ended queue using two pointers:
struct Queue {int *memory, *start, *end; }
void queue_init(int size) {
memory = malloc(sizeof(int) * size);
start = end = memory + (size - 1) / 2;
}
void queue_push_start(int x) { *start = x; start--; }
void queue_push_end(int x) { end++; *end = x; }
int queue_head() { return *start; }
int queue_tail() { return *end; }
void queue_deque_head() { start++; }
void queue_deque_tail() { tail--; }
See that the state of the queue is technically three numbers, { memory, start, end }
(Pointers are just numbers after all). But this is coordinate dependent , as start
and end
are relative to the location of memory
. Now suppose I have a procedure to reallocate the queue size:
void queue_realloc(Queue *q, int new_size) {
int start_offset = q->memory - q->start;
int end_offset = q->memory - q->end;
int *oldmem = q->memory;
q->memory = realloc(q->memory, new_size);
memcpy(q->memory, oldmem + q->start, sizeof(int) * (end_offset - start_offset);
q->start = q->memory + start_offset;
q->end = q->memory - end_offset;
}
Notice that when I do this, the values of start
and end
can be completely different!
However, see that the length of the queue, given by (end - start)
is invariant : It hasn't changed!
In the exact same way, a "tensor" is a collection of numbers that describes something physical with respect to a particular coordinate system (the pointers start
and end
with respect to the memory
coordinate system). "tensor calculus" is a bunch of rules that tell you how the numbers change when one changes coordinate systems (ie, how the pointers start
and end
change when the pointer memory
changes). Some quantities that are computed from tensors are "physical", like the length of the queue, as they are invariant under transformations.
Tensor calculus gives a principled way to make sure that the final answers we calculate are "invariant" / "physical" / "real". The actual locations of start
and end
don't matter, as (end - start)
will always be the length of the list!
Physicists (and people who write memory allocators) need such elaborate tracking, to keep track of what is "real" and what is "coordinate dependent", since a lot of physics involves crazy coordinate systems , and having ways to know what things are real and what are artefacts of one's coordinate system is invaluable. For a real example, consider the case of singularities of the Schwarzschild solution to GR, where we initially thought there were two singularities, but it later turned out there was only one "real" singularity, and the other singularity was due to a poor choice of coordinate system:
Although there was general consensus that the singularity at r = 0 was a 'genuine' physical singularity, the nature of the singularity at r = rs remained unclear. In 1921 Paul Painlevé and in 1922 Allvar Gullstrand independently produced a metric, a spherically symmetric solution of Einstein's equations, which we now know is coordinate transformation of the Schwarzschild metric, Gullstrand–Painlevé coordinates, in which there was no singularity at r = rs. They, however, did not recognize that their solutions were just coordinate transform