kpmartin@watmath.UUCP (Kevin Martin) (08/26/84)
With non-zero lower bounds, but no bounds checking, there is no need for subtracting each lower subscript bound from the corresponding subscript. Since the lower bounds and multipliers are constants, all the constant terms can be pulled out, to form one constant, e.g. for a zero-origin 10 by 20 by 30 array, z_offset(i, j, k) = 20 * (30 * i + j) + k For one-origin, general_offset(i, j, k) = 20 * (30 * (i-1) + (j-1)) + (k-1) = 20 * (30 * i - 30 + j - 1) + (k-1) = 20 * (30 * i + j - 31) + (k-1) = 20 * (30 * i + j) - 620 + k - 1 = 20 * (30 * i + j) + k - 621 = z_offset(i, j, k) - z_offset(1, 1, 1) Note that the second term is a compile-time constant. Kevin Martin, UofW Software Development Group
rbt@sftig.UUCP (08/28/84)
>>With non-zero lower bounds, but no bounds checking, there is no need for >>subtracting each lower subscript bound from the corresponding subscript. >>Since the lower bounds and multipliers are constants, all the constant >>terms can be pulled out, to form one constant, e.g. for a zero-origin >>10 by 20 by 30 array, >> z_offset(i, j, k) = 20 * (30 * i + j) + k >>For one-origin, >> general_offset(i, j, k) = 20 * (30 * (i-1) + (j-1)) + (k-1) >> = 20 * (30 * i - 30 + j - 1) + (k-1) >> = 20 * (30 * i + j - 31) + (k-1) >> = 20 * (30 * i + j) - 620 + k - 1 >> = 20 * (30 * i + j) + k - 621 >> = z_offset(i, j, k) - z_offset(1, 1, 1) >> >>Note that the second term is a compile-time constant. >> Kevin Martin, UofW Software Development Group >> The Fortran compiler for the UNIVAC 1108 used to do exactly this sort of thing all the time. They went one step further and added the constant offset into the starting address of the array at compile time and placed that address into the address part of the memory reference instruction and the z_offset value into an index register. This resulted in very fast subscript calculation and a very subtle bug. Sometimes the starting address of the array was a small number, and the constant offset was a large number, so the number that the compiler wanted to put into the address field of the instruction turned out to be negative. This would not have been a problem, except that the hardware insisted on treating its address fields as unsigned numbers. When this happened, it usually resulted in a storage limits violation, which was easy to debug, but sometimes it did not (especially for very large programs, which occupied most of the address space -- a random storage reference had a high probability of succeeding) and then the program ran but produced wrong answers. The poor user had the devil's own time finding that sort of bug! Worse yet, there was not very much the user could do to work around it once they *had* found the problem. Rick Thomas ihnp4!btlunix!rbt