www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Big integrals, opApply autoindex, safer integrals

reply bearophile <bearophileHUGS lycos.com> writes:
Recently we have discussed a lot about the balance of putting things inside the
language or outside of it. It's a subtle balance and it's dynamic too, with
time it can change (for example the removal of complex numbers from D2?).
Surely it will need more discussions in the future too.

In the past I have discussed about the uses of multi-precision integral
numbers. They can be put inside the std lib (std.bigint) or inside the compiler
(many other languages, etc).

But there's another intermediate solution regarding those multi-precision
numbers: keep them outside the language but allow the language to manage them
with a transparent syntax. So even if the compiler doesn't know how to add two
of such numbers (and you have to load such operations from a module), the
syntax of the language allows you to write:

import bigints: Bigint;
...
Bigint x = 71_459_266_416_693_160_362_545_788_781_600;

Instead of:
BigInt x = "71459266416693160362545788781600";

This keeps the implementation of the operations outside the compiler, keeping
it simpler and allowing different implementations, for example using bindings
to the GNU multiprecision, and allows the user to manage such numbers in a
transparent way, as (or almost as) they were built-in in the language.

(Such strategy of putting just "transparent" syntax support into the language,
and keeping the implementation outside it, can be used in other situations too,
for example for a possible set data structure, etc).

-----------------------

In my structs/classes that support iteration I may have a method like:
int opApply(int delegate(ref string) dg) {...}

But I may also often want to iterate on such objects with a progressive index
too, so I have to duplicate all the code like this:

int opApply(int delegate(ref int, ref string) dg) {...}

I think it can be useful to invent some way for the compiler to create such
second method by itself, (only when the programmer asks so).

(There are alternative ways to solve this problem, for example creating an
iterable struct like xenumerate() similar to the Python enumerate(), or
iterating the single-argument opApply() inside the two argument opApply(), but
such solutions slow down the code).

-----------------------

The recent discussions about numbers with double meaning have to address
bugs-waiting-to-happen like this too:

long n = 1_000_000 * 1_000_000;
Now n == -727379968

And several other silly things like the following ones:

uint n2 = -100;
now n2 == 4294967196

writefln(050); // ==> 40

Bye,
bearophile
Dec 26 2008
parent reply Weed <resume755 mail.ru> writes:
bearophile пишет:
 Recently we have discussed a lot about the balance of putting things
 inside the language or outside of it. It's a subtle balance and it's
 dynamic too, with time it can change (for example the removal of
 complex numbers from D2?). Surely it will need more discussions in
 the future too.
 
 In the past I have discussed about the uses of multi-precision
 integral numbers. They can be put inside the std lib (std.bigint) or
 inside the compiler (many other languages, etc).
 
 But there's another intermediate solution regarding those
 multi-precision numbers: keep them outside the language but allow the
 language to manage them with a transparent syntax. So even if the
 compiler doesn't know how to add two of such numbers (and you have to
 load such operations from a module), the syntax of the language
 allows you to write:
 
 import bigints: Bigint; ... Bigint x =
 71_459_266_416_693_160_362_545_788_781_600;
 
 Instead of: BigInt x = "71459266416693160362545788781600";
 
 This keeps the implementation of the operations outside the compiler,
 keeping it simpler and allowing different implementations, for
 example using bindings to the GNU multiprecision, and allows the user
 to manage such numbers in a transparent way, as (or almost as) they
 were built-in in the language.
 
It is not enough to make Bigint the object?
Dec 26 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Weed:
 It is not enough to make Bigint the object?
I think I have already answered your question (and at the moment BigInt is a struct, I think). Bye, bearophile
Dec 26 2008
parent reply Weed <resume755 mail.ru> writes:
bearophile пишет:
 Weed:
 It is not enough to make Bigint the object?
I think I have already answered your question (and at the moment BigInt is a struct, I think).
I did not understand the problem. You can make an object Bigint. You can add, deduct the value BigInt. You can declare them as follows: Bigint x = "71_459_266_416_693_160_362_545_788_781_600"; or even so (to avoid confusion with strings): Bigint x = Bigint("71_459_266_416_693_160_362_545_788_781_600"); Only that it will be impossible to do so to declare x static :) And another: where else can I apply it?
Dec 26 2008
next sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
Weed schrieb:
 bearophile пишет:
 Weed:
 It is not enough to make Bigint the object?
I think I have already answered your question (and at the moment BigInt is a struct, I think).
I did not understand the problem. You can make an object Bigint. You can add, deduct the value BigInt. You can declare them as follows: Bigint x = "71_459_266_416_693_160_362_545_788_781_600"; or even so (to avoid confusion with strings): Bigint x = Bigint("71_459_266_416_693_160_362_545_788_781_600"); Only that it will be impossible to do so to declare x static :) And another: where else can I apply it?
he just want to avoid the "..." around the number
Dec 26 2008
parent bearophile <bearophileHUGS lycos.com> writes:
dennis luehring:
 he just want to avoid the "..." around the number
I know it may seem a small thing, but it allows you to write generic code that works both with int numbers and Bigint ones, just changing one type, for example of an alias or a template :-) Bye, bearophile
Dec 26 2008
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Weed:
 And another: where else can I apply it?
Apply what to where? (English isn't my first either). Bye, bearophile
Dec 26 2008
parent reply Weed <resume755 mail.ru> writes:
bearophile пишет:
 Weed:
 And another: where else can I apply it?
where else can I use that thing?
 
 Apply what to where?
 (English isn't my first either).
and my too :)
Dec 26 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too? Bye, bearophile
Dec 26 2008
parent reply Weed <resume755 mail.ru> writes:
bearophile пишет:
 Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too?
I thought proposes a more advanced method for operators overloading :) It seems to me, all operators working with values should correspond to processor instructions. Instruction like "Sum int [80] with int [30]" does not exist and it is not necessary to do for it the built-in-like syntax.
Dec 26 2008
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Weed wrote:
 bearophile пишет:
 Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too?
I thought proposes a more advanced method for operators overloading :) It seems to me, all operators working with values should correspond to processor instructions. Instruction like "Sum int [80] with int [30]" does not exist and it is not necessary to do for it the built-in-like syntax.
I disagree. Programing languages are for programmers, i.e Humans, not CPUs. if you want to work with a programming language that corressponds to a CPU, go learn Assemby language. It makes perferct sense to use operators that do not corespond to cpu instructions, for example: auto m1 = new Matrix(10, 30); auto m2 = new Matrix(30, 20); ... fill m1, m2 with data... auto res = m1 * m2; The point of programming languages is to provide abstarctions to the underlying machine, so that we humans can express complex problems to the CPU more easily. also, another reason for allowing: "Sum int [80] with int [30]" is due to vectorization. modern CPUs can perform operations on vectors so instead of doing: for (int i = 0; i < 80; ++i) { sum[i] = a[i] + b[i] } the CPU can process those in chunks of 4 ints at a time or something like that. This is already implemented in DMD.
Dec 26 2008
parent reply Weed <resume755 mail.ru> writes:
Yigal Chripun пишет:
 Weed wrote:
 bearophile пишет:
 Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too?
I thought proposes a more advanced method for operators overloading :) It seems to me, all operators working with values should correspond to processor instructions. Instruction like "Sum int [80] with int [30]" does not exist and it is not necessary to do for it the built-in-like syntax.
I disagree. Programing languages are for programmers, i.e Humans, not CPUs. if you want to work with a programming language that corressponds to a CPU, go learn Assemby language. It makes perferct sense to use operators that do not corespond to cpu instructions, for example: auto m1 = new Matrix(10, 30); auto m2 = new Matrix(30, 20); ... fill m1, m2 with data... auto res = m1 * m2;
Ohhh! Matrices! Mmmm... :)
 The point of programming languages is to provide abstarctions to the
 underlying machine,
without the overhead!
 so that we humans can express complex problems to
 the CPU more easily.
Yes. But language without the overhead costs almost get what I said.
 
 also, another reason for allowing: "Sum int [80] with int [30]" is due
 to vectorization. modern CPUs can perform operations on vectors so
 instead of doing:
 for (int i = 0; i < 80; ++i) { sum[i] = a[i] + b[i] }
 the CPU can process those in chunks of 4 ints at a time or something
 like that. This is already implemented in DMD.
int[80] there is not an array of type int, it very big 80 bit int value So initialization of mathematical types at compile time would be more interesting:)
Dec 26 2008
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Weed wrote:
 Yigal Chripun пишет:
 Weed wrote:
 bearophile пишет:
 Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too?
I thought proposes a more advanced method for operators overloading :) It seems to me, all operators working with values should correspond to processor instructions. Instruction like "Sum int [80] with int [30]" does not exist and it is not necessary to do for it the built-in-like syntax.
I disagree. Programing languages are for programmers, i.e Humans, not CPUs. if you want to work with a programming language that corressponds to a CPU, go learn Assemby language. It makes perferct sense to use operators that do not corespond to cpu instructions, for example: auto m1 = new Matrix(10, 30); auto m2 = new Matrix(30, 20); ... fill m1, m2 with data... auto res = m1 * m2;
Ohhh! Matrices! Mmmm... :)
 The point of programming languages is to provide abstarctions to the
 underlying machine,
without the overhead!
 so that we humans can express complex problems to
 the CPU more easily.
Yes. But language without the overhead costs almost get what I said.
 also, another reason for allowing: "Sum int [80] with int [30]" is due
 to vectorization. modern CPUs can perform operations on vectors so
 instead of doing:
 for (int i = 0; i<  80; ++i) { sum[i] = a[i] + b[i] }
 the CPU can process those in chunks of 4 ints at a time or something
 like that. This is already implemented in DMD.
int[80] there is not an array of type int, it very big 80 bit int value So initialization of mathematical types at compile time would be more interesting:)
sorry, I don't understand your english. int[80] is an array. see: auto a = int[80]; personally I'm against your idea of using static data as this is thread unsafe. D2 will have shared to deal with multi-threading issues like that. still, I'd say that static should be limited to invariant data. it makes sense to do: static invariant m = IdentityMatrix(3,5); for instance, but what's the benefits of doing the same for mutable data? I don't see it..
Dec 26 2008
parent Weed <resume755 mail.ru> writes:
Yigal Chripun пишет:
 Weed wrote:
 Yigal Chripun пишет:
 Weed wrote:
 bearophile пишет:
 Weed:
 where else can I use that thing?
I was talking about a built-in syntax for multi-precision integral numbers. I presume you can use it only when you want to use multi-precision integral number :-) Do you feel the need to use it in other situations too?
I thought proposes a more advanced method for operators overloading :) It seems to me, all operators working with values should correspond to processor instructions. Instruction like "Sum int [80] with int [30]" does not exist and it is not necessary to do for it the built-in-like syntax.
I disagree. Programing languages are for programmers, i.e Humans, not CPUs. if you want to work with a programming language that corressponds to a CPU, go learn Assemby language. It makes perferct sense to use operators that do not corespond to cpu instructions, for example: auto m1 = new Matrix(10, 30); auto m2 = new Matrix(30, 20); ... fill m1, m2 with data... auto res = m1 * m2;
Ohhh! Matrices! Mmmm... :)
 The point of programming languages is to provide abstarctions to the
 underlying machine,
without the overhead!
 so that we humans can express complex problems to
 the CPU more easily.
Yes. But language without the overhead costs almost get what I said.
 also, another reason for allowing: "Sum int [80] with int [30]" is due
 to vectorization. modern CPUs can perform operations on vectors so
 instead of doing:
 for (int i = 0; i<  80; ++i) { sum[i] = a[i] + b[i] }
 the CPU can process those in chunks of 4 ints at a time or something
 like that. This is already implemented in DMD.
int[80] there is not an array of type int, it very big 80 bit int value So initialization of mathematical types at compile time would be more interesting:)
sorry, I don't understand your english.
You are in the majority:)
 int[80] is an array. see:
No! int [80] is not an array here! It 80bit int value: 01010010010101001001010100100101010010010101001001010100100101010010010101001001 I just accidentally used the D syntax to describe it. Sorry.
 auto a = int[80];
 personally I'm against your idea of using static data as this is thread
 unsafe.
What is my idea?
 D2 will have shared to deal with multi-threading issues like that.
 still, I'd say that static should be limited to invariant data.
 it makes sense to do:
 static invariant m = IdentityMatrix(3,5);
 for instance, but what's the benefits of doing the same for mutable
 data? I don't see it..
 
 
Dec 26 2008