View mode: basic / threaded / horizontal-split · Log in · Help
November 27, 2007
Initialising a class with a native datatype necessary for GMP
In this post I will try to explain a problem, which I encountered in my GMP implementation. There are different approaches, how one may implement GMP, but the main goal here is that GMP numbers (mpz, mpq, mpf for integer, rational, floating point) can be used like normal ints and floats!

Especially, the following things should work (with T any of those types):

| T func (T a, T b = 0)
| {
|   T result = 10;
|   return result * a + b;
| }
|
| ...
|
| int main (char[][] args)
| {
|   T value = 2;
|   value = func (value, 1);
|   value = func (value);
|   Stdout.format ("value = {0}", value).newline;
| }

There are two things, which are AFAIK impossible to do with current D:
(1) T can be a default parameter like in line 1.
(2) T can be initialized with a type that is not T (e.g. mpz with an int)

Although, there are at least two different ways to implement GMP: either classes (which is very elegant in D) or templated structs (like in C++), but both cannot solve issues (1) or (2)!

With current D, the only solution, I found, was the following helper function:

| T num (T) (int n)
| {
|   static if (is (typeof(T) == mpz))
|   {
|     return new mpz (n);
|   }
|   else
|   {
|     return n;
|   }
|}

With this template, one can write

| T func (T a, T b = num !(T) (0))
| {
|   T result = num !(T) (10);
|   ...
| }

But this is ugly code and I'm lazy to add all those calls when refactoring an int-based program to a template/GMP-based one!

I have the following ideas, how one could make this more pretty:

1. Make an implicit cast from a type to a class equivalent to a constructor, taking the type as the only parameter.

2. Let the expression "new int (10)" be semantically the same as "10" (Although I think this would be very inconsistent behavior)

Any other ideas?

I believe that there is the necessarity for something to happen, because GMP is a very important choice for computing in science and the current status seems to dissatisfactory to me!

best regards
Matthias Walter
November 27, 2007
Re: Initialising a class with a native datatype necessary for GMP
Matthias Walter wrote:
> In this post I will try to explain a problem, which I encountered in my
> GMP implementation. There are different approaches, how one may
> implement GMP, but the main goal here is that GMP numbers (mpz, mpq, mpf
> for integer, rational, floating point) can be used like normal ints and
> floats!
> 
> Especially, the following things should work (with T any of those
> types):
> 
> | T func (T a, T b = 0)

In case if T is a class, I'd suggest

  T func (T a, T b = null)
  {
    if (b is null)
      b=new b(defaultvalue);
    ...
  }

In case if T is a struct, I'd suggest

  const T uninit={foo:0 ... };

  T func (T a, T b = uninit)
  {
    if (b==uninit)
      b={ ... };
    ...
  }

I know they're not perfect, but I wanted to suggest 'em anyway. =)

regards, frank
November 27, 2007
Re: Initialising a class with a native datatype necessary for GMP
Matthias Walter wrote:
> In this post I will try to explain a problem, which I encountered in my GMP implementation. There are different approaches, how one may implement GMP, but the main goal here is that GMP numbers (mpz, mpq, mpf for integer, rational, floating point) can be used like normal ints and floats!
> 
> Especially, the following things should work (with T any of those types):
> 
> | T func (T a, T b = 0)
> | {
> |   T result = 10;
> |   return result * a + b;
> | }
> |
> | ...
> |
> | int main (char[][] args)
> | {
> |   T value = 2;
> |   value = func (value, 1);
> |   value = func (value);
> |   Stdout.format ("value = {0}", value).newline;
> | }
> 
> There are two things, which are AFAIK impossible to do with current D:
>  (1) T can be a default parameter like in line 1.
>  (2) T can be initialized with a type that is not T (e.g. mpz with an int)
> 
> Although, there are at least two different ways to implement GMP: either classes (which is very elegant in D) or templated structs (like in C++), 


Classes cannot give you something that can be used "just like ints and 
floats".  They can't have a default value because the "default" value is 
always a null pointer.  You have to 'new' them somewhere.  Also a=b 
always copies the reference not the data.  So structs are really your 
only choice if you want behavior similar to a built-in type.

>but both cannot solve issues (1) or (2)!
> 
> With current D, the only solution, I found, was the following helper function:
> 
> | T num (T) (int n)
> | {
> |   static if (is (typeof(T) == mpz))
> |   {
> |     return new mpz (n);
> |   }
> |   else
> |   {
> |     return n;
> |   }
> |}
> 
> With this template, one can write
> 
> | T func (T a, T b = num !(T) (0))
> | {
> |   T result = num !(T) (10);
> |   ...
> | }
> 
> But this is ugly code and I'm lazy to add all those calls when refactoring an int-based program to a template/GMP-based one!
> 
> I have the following ideas, how one could make this more pretty:
> 
> 1. Make an implicit cast from a type to a class equivalent to a constructor, taking the type as the only parameter.
> 
> 2. Let the expression "new int (10)" be semantically the same as "10" (Although I think this would be very inconsistent behavior)
> 
> Any other ideas?
> 
> I believe that there is the necessarity for something to happen, because GMP is a very important choice for computing in science and the current status seems to dissatisfactory to me!
> 
> best regards
> Matthias Walter

I think what you describe is the same issue as this one:
http://d.puremagic.com/issues/show_bug.cgi?id=1547

If you agree then maybe you can attach your summary of the problem to 
that report.

--bb
November 28, 2007
Re: Initialising a class with a native datatype necessary for GMP
Bill Baxter Wrote:

> Matthias Walter wrote:
> > In this post I will try to explain a problem, which I encountered in my GMP implementation. There are different approaches, how one may implement GMP, but the main goal here is that GMP numbers (mpz, mpq, mpf for integer, rational, floating point) can be used like normal ints and floats!
> > 
> > Especially, the following things should work (with T any of those types):
> > 
> > | T func (T a, T b = 0)
> > | {
> > |   T result = 10;
> > |   return result * a + b;
> > | }
> > |
> > | ...
> > |
> > | int main (char[][] args)
> > | {
> > |   T value = 2;
> > |   value = func (value, 1);
> > |   value = func (value);
> > |   Stdout.format ("value = {0}", value).newline;
> > | }
> > 
> > There are two things, which are AFAIK impossible to do with current D:
> >  (1) T can be a default parameter like in line 1.
> >  (2) T can be initialized with a type that is not T (e.g. mpz with an int)
> > 
> > Although, there are at least two different ways to implement GMP: either classes (which is very elegant in D) or templated structs (like in C++), 
> 
> 
> Classes cannot give you something that can be used "just like ints and 
> floats".  They can't have a default value because the "default" value is 
> always a null pointer.  You have to 'new' them somewhere.  Also a=b 
> always copies the reference not the data.  So structs are really your 
> only choice if you want behavior similar to a built-in type.
> 
> >but both cannot solve issues (1) or (2)!
> > 
> > With current D, the only solution, I found, was the following helper function:
> > 
> > | T num (T) (int n)
> > | {
> > |   static if (is (typeof(T) == mpz))
> > |   {
> > |     return new mpz (n);
> > |   }
> > |   else
> > |   {
> > |     return n;
> > |   }
> > |}
> > 
> > With this template, one can write
> > 
> > | T func (T a, T b = num !(T) (0))
> > | {
> > |   T result = num !(T) (10);
> > |   ...
> > | }
> > 
> > But this is ugly code and I'm lazy to add all those calls when refactoring an int-based program to a template/GMP-based one!
> > 
> > I have the following ideas, how one could make this more pretty:
> > 
> > 1. Make an implicit cast from a type to a class equivalent to a constructor, taking the type as the only parameter.
> > 
> > 2. Let the expression "new int (10)" be semantically the same as "10" (Although I think this would be very inconsistent behavior)
> > 
> > Any other ideas?
> > 
> > I believe that there is the necessarity for something to happen, because GMP is a very important choice for computing in science and the current status seems to dissatisfactory to me!
> > 
> > best regards
> > Matthias Walter
> 
> I think what you describe is the same issue as this one:
> http://d.puremagic.com/issues/show_bug.cgi?id=1547
> 
> If you agree then maybe you can attach your summary of the problem to 
> that report.
> 
> --bb

Okay, commented your bug-report, pointing out my example and the area, where the bug applies here.

best regards
Matthias Walter
Top | Discussion index | About this forum | D home