Initializing help system before first use

Definition of operators

In this section we show several examples of the implementation of operators. A comprehensive list of all operators that may be defined in Mosel is given in the appendix.

Constructors

In the chapter about the task module we have already seen examples of functions for cloning a new type and constructing it in different ways. Here the cloning operation is implemented as follows:

static int cx_new0(XPRMcontext ctx, void *libctx)
{
 s_complex *complex,*new_complex;

 complex=XPRM_POP_REF(ctx);
 if(complex!=NULL)
 {
  new_complex=cx_create(ctx, libctx, NULL, 0);
  *new_complex=*complex;
  XPRM_PUSH_REF(ctx, new_complex);
 }
 else
  XPRM_PUSH_REF(ctx, NULL);
 return XPRM_RT_OK;
}

A new complex number is constructed from two given real numbers thus:

static int cx_new2(XPRMcontext ctx, void *libctx)
{
 s_complex *complex;

 complex=cx_create(ctx, libctx, NULL, 0);
 complex->re=XPRM_POP_REAL(ctx);
 complex->im=XPRM_POP_REAL(ctx);
 XPRM_PUSH_REF(ctx, complex);
 return XPRM_RT_OK;
}

Comparison operators

Another operation that we have already seen in the task module is the comparison between new types. This can be done in a very similar way for module complex and is not repeated here. In addition, it makes sense to define a comparison between a complex and a real number:

static int cx_eql_r(XPRMcontext ctx,void *libctx)
{
 s_complex *c1;
 double r;
 int b;

 c1=XPRM_POP_REF(ctx);
 r=XPRM_POP_REAL(ctx);
 if(c1!=NULL)
  b=(c1->im==0)&&(c1->re==r);
 else
  b=(r==0);
 XPRM_PUSH_INT(ctx,b);
 return XPRM_RT_OK;
}

Arithmetic operators

The arithmetic operations must implement the rules to perform these operations on complex numbers.

Multiplication

Taking the example of the multiplication, we have to define the multiplication of two complex numbers: (a+bi) · (c+di) = ac - bd + (ad+bc)i

static int cx_mul(XPRMcontext ctx, void *libctx)
{
 s_complex *c1,*c2;
 double re,im;

 c1=XPRM_POP_REF(ctx);
 c2=XPRM_POP_REF(ctx);
 if(c1!=NULL)
 {
  if(c2!=NULL)
  {
   re=c1->re*c2->re-c1->im*c2->im;
   im=c1->re*c2->im+c1->im*c2->re;
   c1->re=re;
   c1->im=im;
  }
  else
   c1->re=c2->im=0;
 }
 cx_delete(ctx, libctx, c2, 0);
 XPRM_PUSH_REF(ctx, c1);
 return XPRM_RT_OK;
}

and also the multiplication of a complex with a real: (a+bi) · r = ar + bri

static int cx_mul_r(XPRMcontext ctx, void *libctx)
{
 s_complex *c1;
 double r;

 c1=XPRM_POP_REF(ctx);
 r=XPRM_POP_REAL(ctx);
 if(c1!=NULL)
 {
  c1->re*=r;
  c1->im*=r;
 }
 XPRM_PUSH_REF(ctx, c1);
 return XPRM_RT_OK;
}

It is not necessary to define the multiplication of a real with a complex since this operation is commutative and Mosel therefore deduces this case.

Addition, subtraction, division

The addition of two complex numbers and of a complex and a real number is implemented in a very similar way to multiplication. Once we have got the two types of addition, we simply need to implement the negation (–complex) in order for Mosel to be able to deduce subtraction (real – complex and complex – complex):

static int cx_neg(XPRMcontext ctx, void *libctx)
{
 s_complex *c1;

 c1=XPRM_POP_REF(ctx);
 if(c1!=NULL)
 {
  c1->re=-c1->re;
  c1->im=-c1->im;
 }
 XPRM_PUSH_REF(ctx,c1);
 return XPRM_RT_OK;
}

For division, we need to implement all three cases since this operation is not commutative: complex/complex, complex/real and real/complex. Since these functions again are similar to the implementations of the other arithmetic operations that have been shown, they are not printed here.

Identity elements for addition and multiplication

In the list of operators printed in the previous section, there appear two more operators: @0 and @1. These two generate the identity elements for addition and multiplication respectively:

static int cx_zero(XPRMcontext ctx, void *libctx)
{
 XPRM_PUSH_REF(ctx,cx_create(ctx, libctx, NULL, 0));
 return XPRM_RT_OK;
}

static int cx_one(XPRMcontext ctx, void *libctx)
{
 s_complex *complex;

 complex=cx_create(ctx, libctx, NULL, 0);
 complex->re=1;
 XPRM_PUSH_REF(ctx, complex);
 return XPRM_RT_OK;
}

Once addition and the 0-element have been defined, Mosel deduces the aggregate operator SUM. With multiplication and the 1-element, we obtain the aggregate operator PROD for our new type.