Over on the usenet newsgroup comp.math.soft-sys.maple, someone asked about using Maple's overload facility to redefine the operators such as `*`, `+`, etc.

The difficulty for the submitter is that while overload (and option overload for procedures) can provide enhanced operators for new routines, it doesn't affect routines saved in the Maple Library which already have their bindings. Overloading does not subsequently change the bindings of the operators when used in (most all) Library routines.

One way to try and get around this is to actually redefine the global operators. And since overload is on topic, one can still use it in the replacements that one writes.

In order to redefine global operators one must first unprotect them. They are protected for a very good reason. If the replacements are not adequate then Maple can fail in a multitude of ways. It's a case of caveat emptor.

I suggest that anyone interested in this topic read Joe Riel's excellent post on the topic. I have not gone to the trouble of using below all the fine detail that Joe describes (try..catch within cases, etc).

The usenet submitter used the Quaternions example from the ?overload help-page. While it's true that that example overloads arithmetic operators like `*` and `+`, it doesn't provide fallback cases using the overload function. So I've tried to provide a version which has such.

The key difficulty in overloading is properly covering the all the relevant cases. I'm sure that I will have missed some. I'd welcome it is anyone points out some of the holes.

> Quaternion := module()
>     option package;
>     export `?[]`, `*`, `+`, `-`, mvMultiply;
>     local `?[assign]`, `?[select]`, ModuleLoad, ModuleApply:
>     ModuleApply := proc( h, i, j, k )
>        QUATERNION(h,i,j,k);
>     end proc:
>     ModuleLoad := proc()
>         global `print/QUATERNION`;
>         if not type(:-orig_mvMultiply,procedure) then
>             :-orig_mvMultiply:=copy(:-mvMultiply):
>             unprotect(:-mvMultiply):
>             :-mvMultiply:=mvMultiply:
>         end if;
>         if not type(:-orig_star,procedure) then
>             :-orig_star:=copy(:-`*`):
>             unprotect(:-`*`):
>             :-`*`:=`*`:
>         end if;
>         TypeTools[AddType]( `*`,
>                             t->type(t,'specfunc(anything,`*`)'));
>         `print/QUATERNION` := proc(h,i,j,k)
>              h + `i `*i + `j `*j + `k `*k;
>         end proc:
>         TypeTools[AddType]( tQuaternion,
>                             t->evalb(op(0,t) = 'QUATERNION'));
>     end proc:
>     ModuleLoad();
>     `+` := overload( [
>         proc(a::tQuaternion, b::tQuaternion, $)
>         option overload:
>            QUATERNION(op(1,a)+op(1,b), op(2,a)+op(2,b),
>                       op(3,a)+op(3,b), op(4,a)+op(4,b));
>         end proc,
>         proc(a::anything)
>         option overload:
>            :-`+`(args);
>         end proc
>         ]);
>     `-` := proc(a::tQuaternion)
>         option overload:
>         QUATERNION(-op(1,a), -op(2,a), -op(3,a), -op(4,a));
>     end proc;
>     `*` := overload( [
>         proc(a::tQuaternion, b::tQuaternion, $)
>         option overload:
>         local A, B;
>         A := [op(a)]:  B := [op(b)]:
>         QUATERNION(A[1]*B[1] - A[2]*B[2] - A[3]*B[3] - A[4]*B[4],
>                    A[1]*B[2] + A[2]*B[1] + A[3]*B[4] - A[4]*B[3],
>                    A[1]*B[3] - A[2]*B[4] + A[3]*B[1] + A[4]*B[2],
>                    A[1]*B[4] + A[2]*B[3] - A[3]*B[2] + A[4]*B[1]);
>         end proc,
>         proc(a::anything,b::anything)
>         option overload;
>             :-orig_star(args);
>         end proc
>      ]);
>      mvMultiply := overload( [
>         proc(r1::Matrix(tQuaternion),r2::Matrix(tQuaternion))
>            option overload;
>            local i, j, k, C;
>            if nargs=3 then C:=args[3];
>            else C:=Matrix(op([1,1],r1),op([1,2],r2));
>            end if;
>            # Will need cases for Matrix-Vector, Matrix-Matrix,
>            # Vector-Vector, Matrix-scalar, and Vector-scalar.
>            # This is just the Matrix-Matrix case.
>            for i from 1 to op([1,1],r1) do
>              for j from 1 to op([1,2],r2) do
>                 for k from 1 to op([1,2],r1) do
>                    C[i,j]:=Quaternion:-`+`(C[i,j],
>                                            Quaternion:-`*`(r1[i,k],r2[k,j]));
>                 end do;
>              end do;
>            end do;
>            result;
>         end proc,
>         proc(r1::{rtable,scalar},r2::{rtable,scalar})
>            option overload;
>            :-orig_mvMultiply(args);
>         end proc
>      ]);
>     `?[]` := proc(q::uneval, index::[{1,2,3,4}], val)
>         option overload:
>         if nargs = 2 then
>             `?[select]`(eval(q),op(index));
>         else
>             `?[assign]`(q,eval(q),op(index),op(val));
>         end if;
>     end proc:
>     `?[select]` := proc(q::tQuaternion, index::{1,2,3,4} )
>         op(index, q)
>     end proc:
>     `?[assign]` := proc(var::uneval, q::tQuaternion, index::{1,2,3,4},
>                         val::integer )
>         var := subsop(index = val, q);
>     end proc:
> end module:
>
> with(Quaternion):
>
> a := Quaternion(5,6,7,8):
> b := Quaternion(1,2,3,4):
> A,B := Matrix([[a]]),Matrix([[b]]):
>
> 3*4;
                                      12
 
> 3 . 4;
                                      12
 
> Matrix([[3]]) . Matrix([[4]]);
                                     [12]
 
> a*b;
                          -60 + 20 i  + 14 j  + 32 k
 
> a . b;
                          -60 + 20 i  + 14 j  + 32 k
 
> A . B;
                         [-60 + 20 i  + 14 j  + 32 k ]
 
> 0*A;
                                      [0]
 
> 0*a;
                                       0
 
> 0 . a;
                                       0
 
> a*a*a;
                       -2110 - 444 i  - 518 j  - 592 k
 
> `*`(a,b,c); # fix me
              (5 + 6 i  + 7 j  + 8 k ) (1 + 2 i  + 3 j  + 4 k ) c
 

I'm not sure what's going on here,

> zip(`*`,A,B);
              [(5 + 6 i  + 7 j  + 8 k ) (1 + 2 i  + 3 j  + 4 k )]
 
> zip(Quaternion:-`*`,A,B);
              [(5 + 6 i  + 7 j  + 8 k ) (1 + 2 i  + 3 j  + 4 k )]

Oh, one more thing: think extra hard before to try and redefine :-`=`. It's used in a surprising number of ways in the Maple language. It's used in `seq` calls, in if..then conditionals, in procedure options, in plot/dsolve/int range arguments, etc, etc. And it can handle NULL on either side. And so on...

acer


Please Wait...