[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Complex numbers in the library
Hi all!
I have a couple questions that relate to the efficiency of the
implementation of complex numbers in the library. Perhaps this should be
addressed to Griebling, but I thought that the rest of us would have some
input. These questions assume the declaration:
TYPE
COMPLEX = POINTER TO COMPLEXDesc;
COMPLEXDesc = RECORD r, i: (*LONG*)REAL END;
As I see it, there are three notations to choose from for the implementation
of complex math:
- Functional, i.e. PROCEDURE sin(x: COMPLEX): COMPLEX;
- Advantages: Mathematical notation should be much easier to use.
- Disadvantages: Allocates a number on the heap with every invocation,
which is essentially a side effect and which would be extremely
inefficient, both
in time and in heap fragmentation; also has space overhead for both the
record header and the pointer. Overcoming these would require some rather
difficult heap object lifetime analysis and a more advanced collector.
- Procedural, i.e. PROCEDURE sin(x: COMPLEXDesc; VAR ret: COMPLEXDesc);
- Advantages: Greater space efficiency, allows the programmer to choose
whether or not to heap-allocate the numbers. This style allows you to use
arrays of COMPLEXDesc records when doing matrix/vector work. Such arrays
have been typically implemented with one type header for the array and one
for _all_ of the elements. If the elements had to be allocated individually,
there would be a space overhead of the pointer and a type header for _each_
element. This would get very big, very quick, and become very fragmented.
- Disadvantages: Using this notation would not be as easy for the programmer.
The users of this library would have to allocate the space for the numbers
themselves, and manage all of the temporaries. Many mathematicians would
like to avoid having to do this because it confuses the algorithms with
implementation details.
- Recycling Functional, i.e. PROCEDURE sin(x, ret: COMPLEX): COMPLEX;
The second parameter is either given a pointer to a preallocated COMPLEXDesc
that can be reused, or NIL. The result is returned from the function, either
the recycled record or a newly allocated one with new values filling it.
- Advantages: Can be used in a functional style with only minor wierdness
(none in a language with optional parameters, but that's another matter :).
If we are careful to minimize aliasing effects in the implementation, this
notation can be used to speed calculation dramatically and cut down on heap
fragmentation. The programmer that uses these functions can allocate one or
two temporaries early on, and these temporaries can be reused over and over
again. The compiler and collector would have fewer objects to do lifetime
analysis with. If the programmer doesn't want to go through the trouble of
allocating temporaries, this notation has the same characteristics of the
first notation (you always have had to choose to recycle :).
- Disadvantages: This still has that space and time overhead of heap objects,
and doesn't strictly follow the math notation. The programmer has to do a
little work to speed things up that would be done by the compiler with the
procedural notation.
Complex math is currently implemented with the functional notation in the
library. Here's my proposal for how the library could be implemented:
- Modules LowComplexMath and LowLongComplexMath, done in the Procedural style,
and exporting the COMPLEX and COMPLEXDesc types.
- Modules ComplexMath and LongComplexMath, done in the Recycling Functional
style, implemented using the Low* modules, and exporting aliases to the Low*
types as their own.
- Other modules yet to be determined that do math on arrays of COMPLEXDesc,
using the Low* modules to do their dirty work.
This arrangement would allow you to do math in the functional style where it
matters, i.e. with individual complex numbers, but would still allow you to
use the procedural style where you really need to minimize overhead, i.e.
when you are working with arrays or other large quantities of numbers.
So what do you think?
Brian Hawley
bhawley@luc.edu