www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Big Integers Online

reply Arcane Jill <Arcane_member pathlink.com> writes:
I have placed source code for "etc.bigint", a module and package for manipulated
unlimited precision integers, online at:

http://www.fast-forward.info/ramonsky/stuff/d/bigint.html

(PS. I found it mildly inconvenient that I had to put supporting files in
directory "etc/bigint_files/" instead of "etc/bigint/", because D wouldn't let
me have a module and a directory with the same path).

There is no binary - it's "build-it-yourself". But there /is/ documentation.

Over the next few days I'll try to get this also copied onto dsource (maybe even
with a binary this time, who knows?)

By the way - how does one persuade the dmd linker to produce a library? Probably
a dumb question I know, but I always just linked everything against main to get
an executable.

Arcane Jill
May 29 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Arcane Jill wrote:

I have placed source code for "etc.bigint", a module and package for manipulated
unlimited precision integers, online at:

http://www.fast-forward.info/ramonsky/stuff/d/bigint.html

(PS. I found it mildly inconvenient that I had to put supporting files in
directory "etc/bigint_files/" instead of "etc/bigint/", because D wouldn't let
me have a module and a directory with the same path).

There is no binary - it's "build-it-yourself". But there /is/ documentation.

Over the next few days I'll try to get this also copied onto dsource (maybe even
with a binary this time, who knows?)

By the way - how does one persuade the dmd linker to produce a library? Probably
a dumb question I know, but I always just linked everything against main to get
an executable.

Arcane Jill
  
Why was big int made a class? Why not a struct? Do you intend to extend it? -- -Anderson: http://badmama.com.au/~anderson/
May 29 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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); 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. Jill
May 29 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
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); 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. Jill
That's fine I was just asking. -- -Anderson: http://badmama.com.au/~anderson/
May 29 2004
prev sibling next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
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);
You do know you can go: Int a = a(); with opCall. -- -Anderson: http://badmama.com.au/~anderson/
May 29 2004
parent reply Antti =?iso-8859-1?Q?Syk=E4ri?= <jsykari gamma.hut.fi> writes:
In article <c99pq0$1r32$2 digitaldaemon.com>, J Anderson wrote:
 You do know you can go:
 
 Int a = a();
You probably meant: Int a = Int(); -A -- I will not be using Plan 9 in the creation of weapons of mass destruction to be used by nations other than the US.
May 30 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Antti Sykäri wrote:

In article <c99pq0$1r32$2 digitaldaemon.com>, J Anderson wrote:
  

You do know you can go:

Int a = a();
    
You probably meant: Int a = Int(); -A
Or that as well ;) -- -Anderson: http://badmama.com.au/~anderson/
May 30 2004
parent reply hellcatv hotmail.com writes:
private import etc.bigint;

int main (char args[][]) {
Int i = new Int("730750818665451459101842416358141509827966271488");
char [] v = i.toString();
printf ("%.*s %.*s = ",v,v);
v = (i*i).toString();
printf ("%.*s\n",v);
return 0;
}

730750818665451459101842416358141509827966271488
730750818665451459101842416358141509827966271488 = Error: AssertError Failure
etc/bigint_files/lowlevel.d(50)

looks problematic...
hope ye' can figure it out...
May 30 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9dtp8$1bf3$1 digitaldaemon.com>, hellcatv hotmail.com says...
private import etc.bigint;

int main (char args[][]) {
Int i = new Int("730750818665451459101842416358141509827966271488");
char [] v = i.toString();
printf ("%.*s %.*s = ",v,v);
v = (i*i).toString();
printf ("%.*s\n",v);
return 0;
Wow. Well, I guess that's what asserts are FOR. In C++ the code would have carried on and got the wrong answer. (Nice one, Walter!) Anyway, I have reproduced it. I will let you know when I've fixed it. Hopefully sometime today. Jill PS. I can make libraries now, so hopefully the next release will be easier to get going.
May 31 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9eosp$2k30$1 digitaldaemon.com>, Arcane Jill says...

Anyway, I have reproduced it. I will let you know when I've fixed it. Hopefully
sometime today.
Fixed. New version online, same place. (Looking forward to moving to dsource though.) Jill
May 31 2004
parent reply hellcatv hotmail.com writes:
In article <c9et6g$2pt4$1 digitaldaemon.com>, Arcane Jill says...
In article <c9eosp$2k30$1 digitaldaemon.com>, Arcane Jill says...

Anyway, I have reproduced it. I will let you know when I've fixed it. Hopefully
sometime today.
Fixed. New version online, same place. (Looking forward to moving to dsource though.) Jill
I'd like to mention that you have a compiler error on non x86 machines: etc/bigint_files/multiply.d(299): declaration bigintSquareClassic.xi is already defined basically you need to move uint xi into the version() { tag. Also: you fixed the test case I posted, but this one isn't fixed (same failure): import etc.bigint; int main (char args[][]) { Int i = new Int("1557113549234358496979015513794451750344390547442359561355264"); Int j = new Int ("18446744073709551616"); char [] v = i.toString(); char [] u = j.toString(); printf ("%.*s %.*s = ",v,u); v = (i*j).toString(); printf ("%.*s\n",v); return 0; }
May 31 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9g1a3$1ab1$1 digitaldaemon.com>, hellcatv hotmail.com says...
Also: you fixed the test case I posted, but this one isn't fixed (same failure):
Will fix tonight. I should be able to move everything to dsource soon too, but I'll keep a most-fixed version on my website anyway, at least for a time. I'll also add in those big rationals one we're on dsource. Arcane Jill PS. TEMPORARY WORKAROUND - I suspect that if you build with version(DisableKaratsuba) the problem may go away. Disallowing the more complex (but possibly faster) Karatsuba multiplication algorithm forces the lib to use classical long-multiplication, which is much simpler, and unlikely to be buggy. (But obviously I will fix the bug anyway).
Jun 01 2004
next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
Will fix tonight.
Fixed and uploaded. Jill
Jun 01 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c9hatr$3pd$1 digitaldaemon.com...
 PS. TEMPORARY WORKAROUND - I suspect that if you build with
 version(DisableKaratsuba) the problem may go away. Disallowing the more
complex
 (but possibly faster) Karatsuba multiplication algorithm forces the lib to
use
 classical long-multiplication, which is much simpler, and unlikely to be
buggy. This sounds like a job for DbC! I suggest adding an 'out' postcondition for the Karatsuba algorithm. In that postcondition, do the classical multiplication, then assert that the results match. For debug builds, this will be a great confidence builder in making sure the more complex code is right.
Jun 02 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9l5vg$2ljv$2 digitaldaemon.com>, Walter says...
This sounds like a job for DbC! I suggest adding an 'out' postcondition for
the Karatsuba algorithm. In that postcondition, do the classical
multiplication, then assert that the results match. For debug builds, this
will be a great confidence builder in making sure the more complex code is
right.
I'm ahead of you there. My class has made that test all along. The reported bug (which I've actually fixed now) was detected by a DbC assert - though not that one, as one of the lower-level functions asserted in the middle of executing the Karatsuba algorithm. Thanks to you, my friend, it was possible to isolate this error and fix it very fast. This class is well and truly DbC'ed. The out conditions really do test whether the answer is right wherever it can, for as many functions as possible. For this reason, of course, the (theoreticaly faster) Karatsuba algorithm is actually much /slower/ in a debug build, because it calls the classical algorithm to check whether it got the answer right! Only in a release build could it actually be faster. Jill
Jun 02 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c99o8r$1p31$1 digitaldaemon.com...
 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);
 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). 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. There's still another problem, though. D's GC does not *guarantee* that destructors will get run for non-auto objects. 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.
Jun 02 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
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
Jun 03 2004
prev sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
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.
Jun 03 2004
prev sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <c99nfj$1nrf$1 digitaldaemon.com>, J Anderson says...

  Do you intend to extend it?
I don't think so. I hadn't planned to. Maybe we could add "final" to make that clear. But you never know - someone might want to. Jill
May 29 2004
prev sibling next sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
Now for some stupid questions:
How do i use it?
I got it working by including al of the files in bigint_files
in my project (i am using DIDE), is it the right way?

I also got an error message about exceptions being
in two packages or something like that, and there were two
deprecated C-style casts.

When i finally got it to work i tried:

import std.c.stdio;
import etc.bigint;

int main(char[][] args)
{
    Int n= new Int("123456");

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

and it prints:
n = 23456

i tried it with acouple of numbers and i never get the first digit.

"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c99mrv$1mv6$1 digitaldaemon.com...
 I have placed source code for "etc.bigint", a module and package for
manipulated
 unlimited precision integers, online at:

 http://www.fast-forward.info/ramonsky/stuff/d/bigint.html

 (PS. I found it mildly inconvenient that I had to put supporting files in
 directory "etc/bigint_files/" instead of "etc/bigint/", because D wouldn't
let
 me have a module and a directory with the same path).

 There is no binary - it's "build-it-yourself". But there /is/
documentation.
 Over the next few days I'll try to get this also copied onto dsource
(maybe even
 with a binary this time, who knows?)

 By the way - how does one persuade the dmd linker to produce a library?
Probably
 a dumb question I know, but I always just linked everything against main
to get
 an executable.

 Arcane Jill
May 29 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9a37n$282p$1 digitaldaemon.com>, Ivan Senji says...
Now for some stupid questions:
How do i use it?
Well, I only included source files. Guess I should have included a lib you can link against, but it's early days.
I got it working by including al of the files in bigint_files
in my project (i am using DIDE), is it the right way?
No. It *should* be as simple as "import etc.bigint;". That works for me. The supporting modules are supposed to be "behind the scenes" (though actually still individually importable if you really want to). The way I build it is as follows: (1) Separately compile each source file, using the -I compiler switch so that the compiler knows where to start looking for the etc tree. (2) Compile your own source file(s), again with -I to tell it where to find the bigint files. (3) Link all of those files together. I agree that this is messy. I think I should probably get some pre-built libs together after the project is moved to dsource.
I also got an error message about exceptions being
in two packages or something like that.
I think it's possible that without the -I switch, the compiler may not be able to find some things. I can only guess that that's the problem. If you want, I could always post the complete set of command lines emitted by my build process. You might not necessarily want to copy that (as I keep debug objs separately from release objs) but it might help us figure out what the problem is.
and there were two
deprecated C-style casts.
Feel free to ditch them. After dsource, you'll be able to fix that for everyone, but for now, if you give the file and line numbers, I can fix it in my mastercopy.
When i finally got it to work i tried:

import std.c.stdio;
import etc.bigint;

int main(char[][] args)
{
    Int n= new Int("123456");

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

and it prints:
n = 23456
You are correct. It's a bug. I just reproduced it. I will fix it and add that one to the unit tests. Will let you know when it's done.
i tried it with acouple of numbers and i never get the first digit.
My apologies. It worked once upon a time. I must assume I subsequently broke it. Most things are unit tested to prevent that from happening. I can't imagine how I was so stupid as to let that one slip by. Will get back to you when it's fixed. Arcane Jill.
May 29 2004
next sibling parent reply DemmeGod <me demmegod.com> writes:
Why not write a makefile, or better yet a Scons SConstruct file?

John

 The way I build it is as follows:
 
 (1) Separately compile each source file, using the -I compiler switch so
 that the compiler knows where to start looking for the etc tree.
 
 (2) Compile your own source file(s), again with -I to tell it where to
 find the bigint files.
 
 (3) Link all of those files together.
 
 I agree that this is messy. I think I should probably get some pre-built
 libs together after the project is moved to dsource.
 
May 30 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <pan.2004.05.30.07.23.32.756180 demmegod.com>, DemmeGod says...
Why not write a makefile, or better yet a Scons SConstruct file?

John
Ahem. Embarrassing confession time... Because I can't write makefiles. And I don't know what a Scons SConstruct file is. See - although I can /use/ makefiles, I always seem to get them wrong when I try to hand craft them, no matter how many times I read through the man page. I'm spoilt on Windows GUIs now. I made myself a custom build utility. You see, in D, EVERYTHING we need to know about what files to compile and link is contained within the ".d" files themselves. My tool starts at the file containing main(), recurses through all imports, discovers all dependencies, figures out what to build and what not to build, and then executes the commands to achieve that. Then it links them all together. The advantage of this system is that to add a module to the build process, or to remove a module from the build process, all I have to do is ... well ... nothing. If there's an import statement referring to it in a file reachable from main, then it's in, otherwise it's not. No makefile. All I need is a configuration file telling it what version symbols to define (and even that's optional if I want the default of none at all). Advantages for me are ease of use, plus not having to write a makefile. (And not having to tweak it every time I add or remove a file). Disadvantages are that it's not-standard. Although I could let other people have a bash at using my home made DMake thingy, most people don't like non-standard builders. Not only that, but my cunning scheme will only work for D. As soon as any C files try to get in on the act, it will all fall over. But... If any makefile experts out there would like to help me out by building a makefile for me, I certainly wouldn't say no for the assistance. The commands emitted by my builder (when everything is out of date) are listed below. These are for a debug build. For a release build, change "Debug" to "Release" and "-debug -g -inline -unittest" to "-release -O" throughout. I should add that the below trace uses *my* directory structure and so won't work for anyone else. Also, this just links all the files together, including "main.d" (the first one compiled) which is *NOT* part of the lib, it's just there so that there's a main() and I can make an executable. I actually don't know how to make a D library. The manual is very clear about about how to make executables, and lists command line switches for the D compiler, but there's a lot less information about the D linker. As you can see from the below trace, I've been using dmd itself to invoke the linker indirectly. So, er, help anyone? Objectives: (1) make a makefile that will work for everyone, and (2) tell me how to make a D library instead of an executable. ===================================================== THE OUTPUT OF JILL'S BUILD PROCESS (building "main.d" linked to all of the bigint files) (These lines will wrap. Hope you can untangle them) ===================================================== cd X:\D\Modules\etc\bigint_test C:\dmd\bin\dmd -c .\main.d -debug -g -inline -unittest -IX:\D\Modules -od.\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\bigint.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\prime.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\factorial.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\exception.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\multiply.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\radix.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\modexp.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\prime.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\lowlevel.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\modinv.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -c X:\D\Modules\etc\bigint_files\gcd.d -debug -g -inline -unittest -IX:\D\Modules -odX:\D\Modules\etc\bigint_files\Debug C:\dmd\bin\dmd -g X:\D\Modules\etc\bigint_files\Debug\exception.obj X:\D\Modules\etc\bigint_files\Debug\lowlevel.obj X:\D\Modules\etc\bigint_files\Debug\multiply.obj X:\D\Modules\etc\bigint_files\Debug\radix.obj X:\D\Modules\etc\bigint_files\Debug\bigint.obj X:\D\Modules\etc\bigint_files\Debug\gcd.obj X:\D\Modules\etc\bigint_files\Debug\modinv.obj X:\D\Modules\etc\bigint_files\Debug\modexp.obj X:\D\Modules\etc\Debug\prime.obj X:\D\Modules\etc\bigint_files\Debug\prime.obj X:\D\Modules\etc\bigint_files\Debug\factorial.obj X:\D\Modules\etc\Debug\bigint.obj .\Debug\main.obj -ofbigint_test.exe | tail -n+4 move bigint_test.exe Debug\bigint_test.exe move bigint_test.map Debug\bigint_test.map
May 30 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Arcane Jill wrote:
 In article <pan.2004.05.30.07.23.32.756180 demmegod.com>, DemmeGod says...
 
Why not write a makefile, or better yet a Scons SConstruct file?

John
Ahem. Embarrassing confession time... Because I can't write makefiles. And I don't know what a Scons SConstruct file is.
Here's a SConstruct. (SCons is hosted at <http://www.scons.org>) This is ever so slightly different in that all the .obj files get dumped in with the source, but that's because I'm a gimp and need to update the SCons tool to be better. import os from glob import glob env = Environment(ENV=os.environ) env.Append(DFLAGS=Split(''' -debug -g -inline -unittest ''') ) to the path SRC = ( glob('etc/*.d') + glob('etc/bigint_files/*.d') ) bigint = env.Program('bigint', SRC) -- andy
May 30 2004
parent DemmeGod <me demmegod.com> writes:
Would you be referring to the bug I posted on SF:
http://sourceforge.net/tracker/index.php?func=detail&aid=952905&group_id=30337&atid=398971

that I don't think _anybody_ has even read?

On Sun, 30 May 2004 08:43:49 -0700, Andy Friesen wrote:

 This is ever so slightly different in that all the .obj files get dumped
 in with the source, but that's because I'm a gimp and need to update the
 SCons tool to be better.
May 30 2004
prev sibling next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c9cu9v$1pu$1 digitaldaemon.com...
 In article <pan.2004.05.30.07.23.32.756180 demmegod.com>, DemmeGod says...
 ...
 I actually don't know how to make a D library. The manual is very clear
about
 ...
I didn't know also but i looked at what DIDE does and a minute later i have a library: So here it is: C:\dmd\bin\dmd.exe -O -inline -release -c -I. -I.. -odE:\DLANGU~1\BIGINT~1 "E:\D language\bigintlib\bigint.d" "E:\D language\bigintlib\exception.d" "E:\D language\bigintlib\factorial.d" "E:\D language\bigintlib\gcd.d" "E:\D language\bigintlib\lowlevel.d" "E:\D language\bigintlib\modexp.d" "E:\D language\bigintlib\modinv.d" "E:\D language\bigintlib\multiply.d" "E:\D language\bigintlib\prime.d" "E:\D language\bigintlib\radix.d" "E:\D language\bigintlib\squareroot.d" C:\dmd\bin\..\..\dm\bin\lib.exe -c bigintlib "E:\DLANGU~1\BIGINT~1\bigint.obj" "E:\DLANGU~1\BIGINT~1\exception.obj" "E:\DLANGU~1\BIGINT~1\factorial.obj" "E:\DLANGU~1\BIGINT~1\gcd.obj" "E:\DLANGU~1\BIGINT~1\lowlevel.obj" "E:\DLANGU~1\BIGINT~1\modexp.obj" "E:\DLANGU~1\BIGINT~1\modinv.obj" "E:\DLANGU~1\BIGINT~1\multiply.obj" "E:\DLANGU~1\BIGINT~1\prime.obj" "E:\DLANGU~1\BIGINT~1\radix.obj" "E:\DLANGU~1\BIGINT~1\squareroot.obj" All i have to do is import etc.bigint; and link with bigintlib.lib and it works. The paths is something you will have to change!
May 30 2004
prev sibling next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Arcane Jill wrote:

 In article <pan.2004.05.30.07.23.32.756180 demmegod.com>, DemmeGod says...
 
Why not write a makefile, or better yet a Scons SConstruct file?

John
Ahem. Embarrassing confession time... Because I can't write makefiles. And I don't know what a Scons SConstruct file is.
Below follows a main.aap that can build and install bigint. A-A-P can be found at www.a-a-p.org and do the same things as SCons in a less cryptic syntax (IMHO). And to everyone; just because I wonder: I see that a lot of people use SCons; apart from the fact that you heard about it first (most likely), what makes SCons a better choice than A-A-P? To just build:
 aap
To install:
 aap install
BTW, had to add the -d switch as there were C-style casts in the version main.aap ---------------------- :import d DEBUG = yes DDEBUG = -debug DFLAGS += -inline -unittest -d Source = etc/*.d etc/bigint_files/*.d :lib bigint : $Source ----------------------- Lars Ivar Igesund
May 30 2004
parent reply Andy Friesen <andy ikagames.com> writes:
Lars Ivar Igesund wrote:
 And to everyone; just because I wonder: I see that a lot of people use 
 SCons; apart from the fact that you heard about it first (most likely), 
 what makes SCons a better choice than A-A-P?
I like that SCons is an API as opposed to a language. This has the effect of obliviating the distinction between using and extending SCons. The fact that SCons is Python, a language I am very much a fan of, doesn't hurt things either. ;) -- andy
May 30 2004
parent reply Stephan Wienczny <wienczny web.de> writes:
IMHO such tools have to be easy to use. I don't want to have to write 
too complicated code I'd have to debug later. If I wanted that I could 
use a bash scipt.
AFAIK I don't want to extend the abilities of my building tool I want to 
use it ;-)

Andy Friesen wrote:
 Lars Ivar Igesund wrote:
 
 And to everyone; just because I wonder: I see that a lot of people use 
 SCons; apart from the fact that you heard about it first (most 
 likely), what makes SCons a better choice than A-A-P?
I like that SCons is an API as opposed to a language. This has the effect of obliviating the distinction between using and extending SCons. The fact that SCons is Python, a language I am very much a fan of, doesn't hurt things either. ;) -- andy
May 30 2004
parent reply Andy Friesen <andy ikagames.com> writes:
Stephan Wienczny wrote:
 IMHO such tools have to be easy to use. I don't want to have to write 
 too complicated code I'd have to debug later. If I wanted that I could 
 use a bash scipt.
 AFAIK I don't want to extend the abilities of my building tool I want to 
 use it ;-)
I agree on all points except the last. Guess who added D support to SCons. ;) Python is easily my favourite language for getting stuff done fast; SCons lets me leverage that while still describing what to do, as opposed to how it ought to be done. (automatic dependancy checking etc) -- andy
May 30 2004
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Andy Friesen wrote:

 Stephan Wienczny wrote:
 
 IMHO such tools have to be easy to use. I don't want to have to write 
 too complicated code I'd have to debug later. If I wanted that I could 
 use a bash scipt.
 AFAIK I don't want to extend the abilities of my building tool I want 
 to use it ;-)
I agree on all points except the last. Guess who added D support to SCons. ;)
Yeah :) I wasn't really asking you :)
 Python is easily my favourite language for getting stuff done fast; 
 SCons lets me leverage that while still describing what to do, as 
 opposed to how it ought to be done. (automatic dependancy checking etc)
 
  -- andy
IMO, Python is not a good argument here. A-A-P is implemented in Python, and is fairly easy extendable through modules. Also, Python code can be used directly in the recipes, either on a statement-per-statement basis, or in larger blocks. Lars Ivar Igesund
May 31 2004
prev sibling parent reply Paolo Invernizzi <arathorn inwind.it> writes:
Andy Friesen wrote:

 Guess who added D support to SCons. ;)
BTW, Andy, can you add this little patch on dmd.py? In the win32 case, modify the: env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS $_DLINKLIBFLAGS' to env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS $_DLINKLIBFLAGS' In this way Scons can build DLL on windows using the env.Program builder ( I know, a little crap... but it works ;-) --- Paolo Invernizzi
May 31 2004
parent Paolo Invernizzi <arathorn inwind.it> writes:
Paolo Invernizzi wrote:

Ooopss!

to

-of${TARGET.base}


 to
 
 env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS 
 $_DLINKLIBFLAGS'
May 31 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c9cu9v$1pu$1 digitaldaemon.com...
 See - although I can /use/ makefiles, I always seem to get them wrong when
I try
 to hand craft them, no matter how many times I read through the man page.
Don't feel bad, NOBODY learns how to write makefiles by reading the man page. The usual way is to take an existing makefile and hack away at it to make it work for a new project. Incidentally, this is why makefiles tend to be unreadable horrors. I suspect that make was never designed, it was hacked together in a weekend by some programmer who never thought much about it <g>.
Jun 02 2004
prev sibling next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c9bu8h$1oi8$1 digitaldaemon.com...
 In article <c9a37n$282p$1 digitaldaemon.com>, Ivan Senji says...
Now for some stupid questions:
How do i use it?
Well, I only included source files. Guess I should have included a lib you
can
 link against, but it's early days.


I got it working by including al of the files in bigint_files
in my project (i am using DIDE), is it the right way?
No. It *should* be as simple as "import etc.bigint;". That works for me.
The
 supporting modules are supposed to be "behind the scenes" (though actually
still
 individually importable if you really want to).

 The way I build it is as follows:

 (1) Separately compile each source file, using the -I compiler switch so
that
 the compiler knows where to start looking for the etc tree.

 (2) Compile your own source file(s), again with -I to tell it where to
find the
 bigint files.

 (3) Link all of those files together.

 I agree that this is messy. I think I should probably get some pre-built
libs
 together after the project is moved to dsource.
I'll try this! By the way i have to say i like your big integers a lot, they work GREAT :)
I also got an error message about exceptions being
in two packages or something like that.
I think it's possible that without the -I switch, the compiler may not be
able
 to find some things. I can only guess that that's the problem.

 If you want, I could always post the complete set of command lines emitted
by my
 build process. You might not necessarily want to copy that (as I keep
debug objs
 separately from release objs) but it might help us figure out what the
problem
 is.

and there were two
deprecated C-style casts.
Feel free to ditch them. After dsource, you'll be able to fix that for
everyone,
 but for now, if you give the file and line numbers, I can fix it in my
 mastercopy.



When i finally got it to work i tried:

import std.c.stdio;
import etc.bigint;

int main(char[][] args)
{
    Int n= new Int("123456");

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

and it prints:
n = 23456
You are correct. It's a bug. I just reproduced it. I will fix it and add
that
 one to the unit tests. Will let you know when it's done.



i tried it with acouple of numbers and i never get the first digit.
My apologies. It worked once upon a time. I must assume I subsequently
broke it.
 Most things are unit tested to prevent that from happening. I can't
imagine how
 I was so stupid as to let that one slip by.

 Will get back to you when it's fixed.

 Arcane Jill.
May 30 2004
prev sibling next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
import std.c.stdio;
import etc.bigint;

int main(char[][] args)
{
    Int n= new Int("123456");

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

and it prints:
n = 23456
I have now fixed this embarrassing bug and uploaded the new version to the same place. I have also added that particular example to the unit tests, so it should never happen again. My apologies Arcane Jill
May 30 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:c9bu8h$1oi8$1 digitaldaemon.com...
 In article <c9a37n$282p$1 digitaldaemon.com>, Ivan Senji says...
int main(char[][] args)
{
    Int n= new Int("123456");
    printf("n = %.*s",n.toString);
}
and it prints:
n = 23456
You are correct. It's a bug. I just reproduced it. I will fix it and add
that
 one to the unit tests. Will let you know when it's done.
Can I suggest another use for DbC? In the toString() function, add an 'out' postcondition which converts back to an int. Assert that it matches the original int.
Jun 02 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9l6gn$2mcm$1 digitaldaemon.com>, Walter says...


Can I suggest another use for DbC? In the toString() function, add an 'out'
postcondition which converts back to an int. Assert that it matches the
original int.
Now that's one I missed! Well spotted. Ok - will add that one sometime soon. Jill
Jun 02 2004
prev sibling next sibling parent hellcatv hotmail.com writes:
You rock, Arcane Jill

In article <c99mrv$1mv6$1 digitaldaemon.com>, Arcane Jill says...
I have placed source code for "etc.bigint", a module and package for manipulated
unlimited precision integers, online at:

http://www.fast-forward.info/ramonsky/stuff/d/bigint.html

(PS. I found it mildly inconvenient that I had to put supporting files in
directory "etc/bigint_files/" instead of "etc/bigint/", because D wouldn't let
me have a module and a directory with the same path).

There is no binary - it's "build-it-yourself". But there /is/ documentation.

Over the next few days I'll try to get this also copied onto dsource (maybe even
with a binary this time, who knows?)

By the way - how does one persuade the dmd linker to produce a library? Probably
a dumb question I know, but I always just linked everything against main to get
an executable.

Arcane Jill
May 29 2004
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Arcane Jill wrote:

 I have placed source code for "etc.bigint", a module and package for
manipulated
 unlimited precision integers, online at:
 
 http://www.fast-forward.info/ramonsky/stuff/d/bigint.html
<snip> 1. "Construct an Int having the value value. This is a copy constructor. It copies by value, not by reference." You seem to indicate that Int objects are immutable. In that case, why bother with the copy constructor and dup method? 2. You have overloaded operators for combining with int and uint. Why not long and ulong? Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 01 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <c9i0d5$12or$1 digitaldaemon.com>, Stewart Gordon says...

1. "Construct an Int having the value value. This is a copy constructor. 
It copies by value, not by reference."

You seem to indicate that Int objects are immutable.  In that case, why 
bother with the copy constructor and dup method?
Err... you've got me there. Historical reasons, I guess. I think some of the lib code may need to use that constructor internally, and there seemed little point in making it private. Maybe it would be ok to remove that at this stage, but I'd have to think hard before taking that step in case it broke anything. But you're right. Public calls will almost certainly never need it.
2. You have overloaded operators for combining with int and uint.  Why 
not long and ulong?
No reason. I just forgot. But it's never too late to add them. Also missing are constructors from float, double and real, for much the same reason. They, too, can be added in the future. (Also, it will be dsourced in a couple of days, so it will be easier for other people to add anything I've missed out.) Jill
Jun 01 2004
prev sibling next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
Following Stewart Gordon's suggestions, the copy constructor and the dup()
function have been removed from the Int class (Ints are immutable, so
copy-by-value is never needed), and constructors have been added for conversion
from long, ulong, float, double and real.

Following my own suggestions, this lib now defines a new type, Bool, which
stores a true boolean value and which will not auto-cast to or from int. All Int
functions which return or accept boolean values now utilise Bool (except
opEquals(), obviously).

Thanks to Brad, I seem now to have access to a dsource project for Deimos, which
now includes the classes Int and Bool. But it seems I have a lot to learn.
Though I've used CVS before (dsource uses Subversion) I've not got to learn all
about trunks, branches, tags and so forth. I'm going to take my time over this,
because I don't want to get it wrong, so - I shall probably not be ready for a
few more days. But come next weekend, hey, who knows?

Jill
Jun 02 2004
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sat, 29 May 2004 09:58:23 +0000 (UTC), Arcane Jill wrote:

 I have placed source code for "etc.bigint", a module and package for
manipulated
 unlimited precision integers, online at:
 
 http://www.fast-forward.info/ramonsky/stuff/d/bigint.html
 
 (PS. I found it mildly inconvenient that I had to put supporting files in
 directory "etc/bigint_files/" instead of "etc/bigint/", because D wouldn't let
 me have a module and a directory with the same path).
 
 There is no binary - it's "build-it-yourself". But there /is/ documentation.
 
 Over the next few days I'll try to get this also copied onto dsource (maybe
even
 with a binary this time, who knows?)
 
 By the way - how does one persuade the dmd linker to produce a library?
Probably
 a dumb question I know, but I always just linked everything against main to get
 an executable.
 
 Arcane Jill
I am *so* impressed! This is an excellent piece of work. Well done indeed. I can't wait for the crypto stuff as this is also an area that I work in. 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? -- Derek 3/Jun/04 11:22:48 AM
Jun 02 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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
Jun 02 2004
parent reply Derek Parnell <derek psych.ward> writes:
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
Jun 03 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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
Jun 03 2004
next sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"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
Jun 03 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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.
Jun 03 2004
parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"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.
Jun 03 2004
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
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
Jun 03 2004
parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
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
Jun 03 2004
parent Derek Parnell <derek psych.ward> writes:
On Fri, 4 Jun 2004 05:27:37 +0000 (UTC), Kevin Bealer wrote:

 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.
Thanks. This all makes good sense. I didn't realize, but should have, that the '+' forced a new instance to be created. -- Derek Melbourne, Australia 4/Jun/04 5:05:21 PM
Jun 04 2004