For your information: that already exists in FPC. It's called operator
overloading:
http://www.freepascal.org/docs-html/ref/refch12.html#x161-16800012
-- Felipe Monteiro de Carvalho
Except that you have to code every single case separately, 2x6, 3x10, 4x4x4, etc. You need to write a separate routine for every shape of array you want to use.
Frank Rubin
On Fri, Aug 6, 2010 at 8:35 AM, Contestcen@aol.com wrote:
Except that you have to code every single case separately, 2x6, 3x10, 4x4x4, etc. You need to write a separate routine for every shape of array you want to use.
Or you could use dynamic arrays instead of static ones. Then you can write only one case.
Dear Frank Rubin,
"Except that you have to code every single case separately, 2x6, 3x10, 4x4x4, etc. You need to write a separate routine for every shape of array you want to use."
Not so:
Use open arrays (always 0-based):
type Matrix = array of array of TRing;
Youu can write code, roughly:
operator * (const A, B: Matrix): Matrix;
var RowA, ColA, RowB, ColB, I, J, K: Integer; T: TRing;
begin RowA := Length(A); ... ColB := Length(B[0]); if ColA <> RowB then ... SetLength(Result, RowA); for J := 0 to RowA - 1 do SetLength(Result[J], ColB); for I := 0 to RowA - 1 do for K := 0 to ColB - 1 do begin T := Zero; // prefer just 0 for J := 0 to ColA - 1 do T := T + A[I, J]*B[J, K]; Result[I, K] := T; end; end;
once and for all, covering all sizes of matrices.
The problem I do not yet know how to solve: to do it for all TRing.
So I need a type TRing that can include any structure that has + and * operators, and a 0 element:
Integers, Floats, Rationals, Gaussian Integers, Polynomials with xxx coefficients,... any possible data type I can define with overloaded +, *, etc.
Note that 0 is a problem in itself -- one really needs to overload it too!
Frank Heckenbach's first reply to me may contain the answer. I haven't completely digested it yet.
Cheers,
Harley
----------------------------------------------------
Contestcen@aol.com wrote:
For your information: that already exists in FPC. It's called operator
overloading:
http://www.freepascal.org/docs-html/ref/refch12.html#x161-16800012
-- Felipe Monteiro de Carvalho
Except that you have to code every single case separately, 2x6, 3x10, 4x4x4, etc. You need to write a separate routine for every shape of array you want to use.
Frank Rubin
Prof. Harley Flanders wrote:
"Except that you have to code every single case separately, 2x6, 3x10, 4x4x4, etc. You need to write a separate routine for every shape of array you want to use."
Not so:
Use open arrays (always 0-based):
type Matrix = array of array of TRing;
[...]
Just as a reminder, this is the GPC list. Discussion of compiler features for comparison is welcome, but posting of (I suppose) FPC specific code would fit better on the FPC list, I think.
The problem I do not yet know how to solve: to do it for all TRing.
So I need a type TRing that can include any structure that has + and * operators, and a 0 element:
Integers, Floats, Rationals, Gaussian Integers, Polynomials with xxx coefficients,... any possible data type I can define with overloaded +, *, etc.
That's more or less exactly the description of (one of) the problems that templates are there to solve.
Note that 0 is a problem in itself -- one really needs to overload it too!
Indeed, I intentionally omitted this discussion in my previous mail to avoid distraction.
Some ideas:
- Define a constructor for each relevant type that initializes to the zero element. Problem: It would fail for simple types (integer, real) which are not initialized by default and cannot have user-defined constructors.
- Define an (overloaded) procedure "Zero" (or so). A function would seem more natural, but since it would take no parameters, it couldn't be overloaded. (C++ would allow it as a template function, but to disambiguate, each call would need to specify the type, as in "Zero <MyRing> ()".)
- Since for each ring multiplication with an integer is well-defined, you could require an operator * (n: Integer; x: MyRing): MyRing; and to get Zero, you can do "0 * x" with any ring element x (such as the first element of one of the operand matrices). Though this might produce slightly non-optimal code, but it's a more general solution.
- Of course, you can write "x - x" (using an arbitrary element) whenever you need a 0, but that's also likely to produce non-topimal code in many cases.
- If you want to assume a ring with 1, you can even define conversion from integer to the ring (as n -> n * One). In C++, you can do this by implementing additional constructors (i.e., the take an integer parameter n, and construct n * One). Though you can't define constructors for built-in types, this doesn't hurt in this case, since they already support this conversion (trivial for integer types, automatic integer -> real conversion).
- If you don't like the last one, you could define a singleton "Zero" element (i.e., an element of a new type ("TZero") that isn't used anywhere else and doesn't carry meaningful data), and define a constructor that takes a "TZero" parameter and constructs the zero element. (It wouldn't actually use the value of the "TZero" element, just its static (compile-time) type information, so it could be optimally efficient when inlined.) Again, built-in types can have no user-defined constructors, but at least in C++, this could be solved by defining "type-cast operators" of the "TZero" type to integer, real, etc.
Frank