[Contents]

operators::overloaded -- conversions and overloaded functions

Introduction

The library operators::overloaded provides a framework for conversions between domains. It also allows for defining multiparameter overloaded functions.

Details

Creating Elements


operators::overloaded(default, <signatures> )

Parameters

default- A function.
signatures- A table associating implementations to signatures.

Details

Method declareDomain: declaration of a domain

Method declareConversion: declaration of a new conversion

Method convert: conversion of an object

Method convertExplicit: explicit conversion of an object

Method conversion: conversion between domains

Method printConversions: summary of existing conversions

Method declareSignature: declaration of a new signature

Example 1

We start by using some predefined conversions. Here is how to convert an integer into an element of Z/3Z using the canonical projection:

.
>> Z3 := Dom::IntegerMod(3):
   a := operators::overloaded::convert(7, Z3)
     
                                  1 mod 3
        

Then, we can embed Z/3Z into an algebraic extension, and do the conversion:

>> K := Dom::AlgebraicExtension(Z3, X^2=1):
   b := operators::overloaded::convert(a, K);
   domtype(b)
     
                                     1
      
                                                     2
        Dom::AlgebraicExtension(Dom::IntegerMod(3), X  - 1 = 0, X)
        

Being aware of the two basic conversions above, the system can apply them transitively:

>> operators::overloaded::convert(7, K)
     
                                     1
        

Currently only the natural conversions between the basic MuPAD domains are predefined in the system:

>> operators::overloaded::printConversions()
     
      Dom::IntegerMod(3)      -> Dom::AlgebraicExtension(Dom::IntegerMod(3), X^2 - 1 = 0, X)
      DOM_COMPLEX     -> Dom::Complex
      Dom::Float      -> Dom::Complex
      Dom::Rational   -> Dom::Complex
      DOM_EXPR        -> Dom::ExpressionField()
      DOM_IDENT       -> Dom::ExpressionField()
      Dom::Complex    -> Dom::ExpressionField()
      Dom::Real       -> Dom::ExpressionField()
      DOM_FLOAT       -> Dom::Float
      Dom::Rational   -> Dom::Float
      DOM_INT         -> Dom::Integer
      Dom::Integer    -> Dom::IntegerMod(3)
      DOM_RAT         -> Dom::Rational
      Dom::Integer    -> Dom::Rational
      Dom::Float      -> Dom::Real
      Dom::Rational   -> Dom::Real
        

Most of those conversions are actually trivial, since the target domains are facade domains like Dom::Integer. Furthermore, for parametrized domains like Dom::IntegerMod(3), the conversions are declared on the fly when the domains are created.

It is easy to extend the system to deal with new domains and conversions. We define the ring P of univariate polynomials over K, declare it to the conversion system, and declare the canonical embedding from the field K::

>> P := Dom::UnivariatePolynomial(x, K):
   operators::overloaded::declareDomain(P):
   operators::overloaded::declareConversion(K, P, 
                     c -> multcoeffs(P::one, c)):
     
        

Now, we indifferently can do conversions from the integers, from Z3, or from K into P:

>> c := operators::overloaded::convert(7, P);
   domtype(c)
     
                                     1
      
      Dom::UnivariatePolynomial(x, Dom::AlgebraicExtension(
      
                              2
         Dom::IntegerMod(3), X  - 1 = 0, X), LexOrder)
        

Example 2

We define a new overloaded function myconcat which, by default, returns an unevaluated call:

>> myconcat := operators::overloaded
   (() -> (userinfo(0, "default implementation"); hold(myconcat)(args())),
    table([DOM_STRING, DOM_STRING] =
            ((s1,s2) -> (userinfo(0, "concatenating strings"); s1.s2)),
          [DOM_LIST,   DOM_LIST]   =
            ((s1,s2) -> (userinfo(0, "concatenating lists"); s1.s2)))):
     

myconcat can be used indifferently to concatenate two strings or two lists:

>> setuserinfo(Any, 1):
   setuserinfo(Graph, 0):
   myconcat("bla", "ble");
   myconcat([1, 2, 3], [4, 5, 6])
     
      Info: concatenating strings
      
                                 "blable"
      Info: concatenating lists
      
                            [1, 2, 3, 4, 5, 6]
        

By default, an unevaluated call is returned:

>> myconcat(35, 73)
     
      Info: default implementation
      
                             myconcat(35, 73)
        

Let us extend the concatenation to integers, in a non standard way:

>> operators::overloaded::declareSignature
     (myconcat,
      [Dom::Integer, Dom::Integer],
      (x, y) -> (userinfo(0, "concatenating integers");
                 text2expr(expr2text(x).expr2text(y)))):
   myconcat(35, 73)
     
      Info: concatenating integers
      
                                   3573
        

Of course, this is not very well defined, in particular if the second argument is negative!

>> myconcat(35, -73)
     
      Info: concatenating integers
      
                                  35 - 73
        
>> setuserinfo(Any, 0):
     
        

The point of all this is just to highlight the fact that the programmer should be very careful with the semantic of the conversions and overloaded operators he or she defines. The system does not check that they are consistent in any way; in most cases that would be impossible.

To conclude here are some examples of not-so-well defined conversions that are likely to produce problems in a larger scale environment:

>> operators::overloaded::declareDomain(DOM_IDENT):
   operators::overloaded::declareDomain(DOM_STRING):
   operators::overloaded::declareConversion(DOM_IDENT, DOM_STRING, expr2text):
   myconcat(bla,   "ble");
   myconcat("bla", ble);
   myconcat(bla,   ble)
     
                                 "blable"
      
                                 "blable"
      
                                 "blable"
        

Note in particular what happens in the last computation: the system did not know how to concatenate two identifiers; so it decided to lift both identifiers into strings, and concatenate them as strings. In some cases, this behavior is perfectly acceptable (the result may, for example, live in a domain that is isomorphic to the domain of at least one of the operands), but in most cases it is not. In a future version of this library, we plan to provide means to forbid such conversions.

Background

[Contents]


MuPAD Combinat, an open source algebraic combinatorics package