June 03, 2004
>I'm also a bit slow ;-) Can you give me the "for Dummies" explanation of why a+=b is not allowed? In my humble brain
>
>   a += b;
>
>is syntax sugar for
>
>   a = a + b;
>
>so what am I missing here?

*) a += b modifes the object referenced by a.
*) a = a + b modifies the reference a, but not the object (formerly) referenced
by a.

Example: Suppose you have a third Int, named c. And suppose that at some previous point in the code you had said:

>       c = a;

Now the difference between + and += becomes:

>       a += b;    // will modify both a and c
>       a = a + b; // will modify a, but not c

For this reason, I outlawed += and friends for my class. (+= is fine with structs, but not with classes. For reasons I won't go into here, Int is a class).

Arcane Jill


June 03, 2004
On Thu, 3 Jun 2004 06:51:09 +0000 (UTC), Arcane Jill wrote:

>>I'm also a bit slow ;-) Can you give me the "for Dummies" explanation of why a+=b is not allowed? In my humble brain
>>
>>   a += b;
>>
>>is syntax sugar for
>>
>>   a = a + b;
>>
>>so what am I missing here?
> 
> *) a += b modifes the object referenced by a.
> *) a = a + b modifies the reference a, but not the object (formerly) referenced
> by a.
> 
> Example: Suppose you have a third Int, named c. And suppose that at some previous point in the code you had said:
> 
>>       c = a;
> 
> Now the difference between + and += becomes:
> 
>>       a += b;    // will modify both a and c
>>       a = a + b; // will modify a, but not c

Thanks. I understand what is happening here.

> For this reason, I outlawed += and friends for my class. (+= is fine with structs, but not with classes. For reasons I won't go into here, Int is a class).

Could one have designed the class such that 'a += b' behaved the same as 'a = a + b'?

As I see it now, you have decided to disturb the normal D behaviour with respect to Int objects. It seems that the normal behaviour of D for += is to update the object referred to by 'a' (as you state). Thus any other variables that refer to the same instance are also 'automagically' udpated too. This is what D does, right? Now you have disallowed this normal behaviour. So what if I wanted to use this normal D behaviour, just as I would for other classes?

This is all hypothetical, devil's advocate stuff, so please don't take offense.


BTW, I presume that what one is supposed to do when taking a copy of a class object's value is to do ...

   c = new Int(a);

rather than

   c = a;


I really must start doing more than playing with D...now where *did* I put that spare time of mine?

-- 
Derek
Melbourne, Australia
3/Jun/04 5:30:22 PM
June 03, 2004
In article <c9mkj4$1pdj$1@digitaldaemon.com>, Derek Parnell says...
>
>Thanks. I understand what is happening here.
> 
>As I see it now, you have decided to disturb the normal D behaviour with respect to Int objects. It seems that the normal behaviour of D for += is to update the object referred to by 'a' (as you state). Thus any other variables that refer to the same instance are also 'automagically' udpated too. This is what D does, right? Now you have disallowed this normal behaviour. So what if I wanted to use this normal D behaviour, just as I would for other classes?

Take a pointer. Given knowledge of the internals of Int it would then be possible to modify the object directly, which would then modify the object for all references to it. Of course, I did not provide *any* functions to allow you to do this, but given knowledge of the internals of Int (which you could glean from the source code) you could write functions which did. Not sure why you'd want to though.

Having said that, not providing certain operator overloads is not "disallowing normal behavior". There is no rule that says every class must overload all operators. Not overloading operators is still "normal behavior".


>BTW, I presume that what one is supposed to do when taking a copy of a class object's value is to do ...
>
>   c = new Int(a);
>
>rather than
>
>   c = a;

Not any more. I've ditched the copy constructor. Now you *can't* take a copy, leaving you with no choice but c = a;. There really is no need to deep copy an immutable object.

Arcane Jill


June 03, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9ml84$1q9a$1@digitaldaemon.com...
> In article <c9mkj4$1pdj$1@digitaldaemon.com>, Derek Parnell says...
> >
> >Thanks. I understand what is happening here.
> >
> >As I see it now, you have decided to disturb the normal D behaviour with respect to Int objects. It seems that the normal behaviour of D for += is to update the object referred to by 'a' (as you state). Thus any other variables that refer to the same instance are also 'automagically'
udpated
> >too. This is what D does, right? Now you have disallowed this normal behaviour. So what if I wanted to use this normal D behaviour, just as I would for other classes?
>
> Take a pointer. Given knowledge of the internals of Int it would then be possible to modify the object directly, which would then modify the object
for
> all references to it. Of course, I did not provide *any* functions to
allow you
> to do this, but given knowledge of the internals of Int (which you could
glean
> from the source code) you could write functions which did. Not sure why
you'd
> want to though.
>
> Having said that, not providing certain operator overloads is not
"disallowing
> normal behavior". There is no rule that says every class must overload all operators. Not overloading operators is still "normal behavior".
>
>
> >BTW, I presume that what one is supposed to do when taking a copy of a class object's value is to do ...
> >
> >   c = new Int(a);
> >
> >rather than
> >
> >   c = a;
>
> Not any more. I've ditched the copy constructor. Now you *can't* take a
copy,
> leaving you with no choice but c = a;. There really is no need to deep
copy an
> immutable object.

I neaded to have a copy of Int (or maybe i didn't?) and
i did it like this:
c = 0 + a;

This does make a copy, doesn't it?

> Arcane Jill
>
>


June 03, 2004
In article <c9l5vg$2ljv$1@digitaldaemon.com>, Walter says...

>Since the GC is allowed to move memory around (even though the current implementation does not) in order to do compaction, wiping memory on a delete is not reliable. I suggest it would be better to allocate the secure array using std.c.stdlib.malloc, and then when explicitly free'ing it with std.c.stdlib.free, do the wipe. That way you'll be in complete control of any copies.

Thanks. In the long term I will think seriously about this. For now, it doesn't matter, as (a) the crypto lib doesn't exist yet, and (b) the current implementation of the gc doesn't move memory around. But thank you for pointing this out. I will take your advice seriously, and my class will do the right thing, in time.



>There's still another problem, though. D's GC does not *guarantee* that destructors will get run for non-auto objects.

What!!??? Sorry - I don't get that.

Then what's the point of a destructor? You might as well prohibit destructors on non-auto objects if that's true.

Please could you explain this behavior? Just assume I'm really stupid and know nothing about how garbage collectors work.



>Therefore, you might want to
>keep a list of all the secure arrays created that haven't been wiped yet,
>then on program close with a module destructor, go through the list and wipe
>any remaining ones.

It's a thought. Ta.

Arcane Jill


June 03, 2004
In article <c9mmoj$1sbb$1@digitaldaemon.com>, Ivan Senji says...

>I neaded to have a copy of Int

Why?


>i did it like this:
>c = 0 + a;
>
>This does make a copy, doesn't it?

Nope. You'll find that c === a after that. And multiplying by 1 won't help either. Nor will shifting right or left by zero. The lib is well optimized. But what I don't get is ... WHY do you need a deep copy?

Jill

PS. If you give me a really good reason why a copy-by-reference is not sufficient, given that Int is immutable, then I will put dup() back in. I'm trying to be helpful, not mean.


June 03, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9n1aq$2as8$1@digitaldaemon.com...
> In article <c9mmoj$1sbb$1@digitaldaemon.com>, Ivan Senji says...
>
> >I neaded to have a copy of Int
>
> Why?

You didn't notice that i also said "or maybe i didn't?"
Now i'm pretty sure i didn't need a deep copy, but
i only thought i nead it :)

> >i did it like this:
> >c = 0 + a;
> >
> >This does make a copy, doesn't it?
>
> Nope. You'll find that c === a after that. And multiplying by 1 won't help either. Nor will shifting right or left by zero. The lib is well
optimized. But
> what I don't get is ... WHY do you need a deep copy?

Wow! It really is optimized.

PS. I have a problem with Stack Overflow error with this code: It doesn't happen when seed is smaller!

<CODE>
import std.c.stdio;

import etc.bigint;
import etc.prime;

int main ( char [] [] args )
{
 Int seed = new Int("12345678901234567890123456789");
 printf("seed = %.*s\n",seed.toString);

 Int p = getProbablePrimeLess(seed);
 Int q = getProbablePrimeGreater(seed);

 printf("seed = %.*s\np    = %.*s\nq    =
%.*s\n",seed.toString,p.toString,q.toString);

 printf("prime(p) == %d, prime(q) ==
%d\n",isProbablyPrime(p),isProbablyPrime(q));

 Int n = p*q;

 printf("n = %.*s\n",n.toString);

 Int fi = (p-1)*(q-1);

 printf("fi = %.*s\n",fi.toString);

 printf("n    = %.*s\n",n.toString);
 printf("prime == %d\n",isProbablyPrime(n));
 printf("fi   = %.*s\n",fi.toString);
 printf("prime == %d\n",isProbablyPrime(fi));

 getch();
 return 1;
}
</CODE>

> Jill
>
> PS. If you give me a really good reason why a copy-by-reference is not sufficient, given that Int is immutable, then I will put dup() back in.
I'm
> trying to be helpful, not mean.
>
>


June 03, 2004
Arcane Jill wrote:

> In article <c99nfj$1nrf$1@digitaldaemon.com>, J Anderson says...
> 
>>Why was big int made a class? Why not a struct?
> 
> 1. Ease of initialization. a = new Int(5); is better than Int a;
> a.init(5);

As it has been said elsewhere, opCall would help you there.

> 2. Most importantly (to me). Only classes can have a destructor. In a
> version(Secure) build, the destructor wipes the memory which held the
> Int's value. This is important in cryptography, since big integers may
> hold cryptographic keys, etc., and you don't want those values lying
> around in memory indefinitely. (In a non version(Secure), there is no
> destructor, of course).
> 
> Believe me, I thought long an hard about this, but it does make sense. Regardless of whether I had used a struct or a class, there's a dynamic array inside there, and that would always have been passed by reference, even in a struct, so there really wouldn't have been much gain. Constructors and destructors were the deciding factors for me.

For that purpose, I would think it would make sense to split the problem: put the BigInt functionality into a struct for general purpose, and if you need detailed control over the storage for security, box it up into a class.

You are right, that the implementation has to be based on a dynamic array, so you will get reference semantics in any case, but if you implement it as a class, you will get reference-to-reference behavior, which will certainly me even more confusing. Having a struct that contains an array reference will give behavior similar to strings. Any D programmer should be used to that. Reference-to-reference on the other hand will give some really strange effects.
June 04, 2004
On Thu, 3 Jun 2004 07:50:28 +0000 (UTC), Arcane Jill wrote:

> In article <c9mkj4$1pdj$1@digitaldaemon.com>, Derek Parnell says...
>>
>>Thanks. I understand what is happening here.
>> 
>>As I see it now, you have decided to disturb the normal D behaviour with respect to Int objects. It seems that the normal behaviour of D for += is to update the object referred to by 'a' (as you state). Thus any other variables that refer to the same instance are also 'automagically' udpated too. This is what D does, right? Now you have disallowed this normal behaviour. So what if I wanted to use this normal D behaviour, just as I would for other classes?
> 
> Take a pointer. Given knowledge of the internals of Int it would then be possible to modify the object directly, which would then modify the object for all references to it. Of course, I did not provide *any* functions to allow you to do this, but given knowledge of the internals of Int (which you could glean from the source code) you could write functions which did. Not sure why you'd want to though.
> 
> Having said that, not providing certain operator overloads is not "disallowing normal behavior". There is no rule that says every class must overload all operators. Not overloading operators is still "normal behavior".

True.

>>BTW, I presume that what one is supposed to do when taking a copy of a class object's value is to do ...
>>
>>   c = new Int(a);
>>
>>rather than
>>
>>   c = a;
> 
> Not any more. I've ditched the copy constructor. Now you *can't* take a copy, leaving you with no choice but c = a;. There really is no need to deep copy an immutable object.

I might need one to restore a value on transaction backout.

   Int oldVal;

   oldVal = a;

   a = a + b;
   if (DoSomething(a) == 0)
      // Restore previous value.
      a = oldVal;


-- 
Derek
Melbourne, Australia
4/Jun/04 1:39:10 PM
June 04, 2004
In article <c9or5a$1u4v$1@digitaldaemon.com>, Derek Parnell says... ..
>I might need one to restore a value on transaction backout.
>
>   Int oldVal;
>
>   oldVal = a;
>
>   a = a + b;
>   if (DoSomething(a) == 0)
>      // Restore previous value.
>      a = oldVal;

Assuming no bugs, this example will work without deep copy.  The "+" creates a new object; the oldVal still points to the old version.  Immutable means that objects never change.  "a=a+b" points the reference a at a new object which is the sum of a and b.

This is a powerful technique.  In garbage collected languages it is common to implement binary trees and other structures so that you can add new elements to the tree, and keep the old reference.  You end up with two complete trees that share all the pieces they have in common.  If you add another element you have a third tree, again sharing most of the nodes between all the trees.  You can keep all three and iterate over them; you don't need to know they are shared.

If file systems were done this way, you could keep a "root pointer" to a filesystem somewhere and later on swap it back in as the top element, restoring the FS to the previous state instantly.  You could capture a new "whole filesystem view" as often as every minute with little impact on performance (unless you are doing a lot of writing), and later on, go back to any period in the lifetime of the system.

(But most FS's don't do this, so never mind.)

Kevin Bealer