digitalmars.D.announce - Another take on decimal data types
- rumbu (44/44) Jan 08 2018 This is my first D finalized project (+16k loc).
- rikki cattermole (3/3) Jan 08 2018 Great job.
- rumbu (8/16) Jan 09 2018 1) I don't understand :)
- Dennis Cote (6/7) Jan 09 2018 I noticed a minor typo in the documentation:
- Daniel Kozak (4/44) Jan 08 2018 Wow awesome, it would be nice if you could add it as a dub package (
- Bastiaan Veelo (2/3) Jan 09 2018 Wow, slick documentation!
- Mike Franklin (4/8) Jan 09 2018 Wow!. So thorough. Documentation is fantastic. Very nice work,
- aberba (2/11) Jan 09 2018 I couldn't say it better. Its really well done...
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (8/9) Jan 11 2018 Great stuff! Will this work in betterC mode?
- Seb (8/13) Jan 11 2018 We have now this page:
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (9/18) Jan 11 2018 Hi, thanks. Should have been more precise: An informaiton for every lib
- rumbu (38/41) Jan 11 2018 It will not work without some refactory. Most of phobos/druntime
- jmh530 (3/21) Jan 11 2018 Ilya has expressed interest in a betterC formatting library for
- Steven Schveighoffer (4/16) Jan 11 2018 Some of those are intrinsics, and don't actually link to any druntime
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (12/32) Jan 11 2018 Yes, makes sense.
- kdevel (32/35) Jan 11 2018 Really?
- Dmitry Olshansky (2/37) Jan 11 2018
- kdevel (21/24) Jan 11 2018 Sure.
- Steven Schveighoffer (5/10) Jan 11 2018 But dmd isn't a C compiler, nor does it have to worry about the problems...
- H. S. Teoh (16/26) Jan 11 2018 [...]
- Joakim (6/34) Jan 12 2018 Interesting, guess this was added last April with dmd 2.074?
- Dmitry Olshansky (10/35) Jan 11 2018 “”” GNU C Library lets you define “””
- kdevel (7/14) Jan 11 2018 This must read
- kdevel (37/39) Jan 12 2018 nosine.d
- rumbu (2/5) Jan 12 2018 Sorry, broke some code when I made the split. Now it's working.
- kdevel (7/13) Jan 13 2018 $ dub
- kdevel (29/35) Jan 13 2018 diff --git a/dub.json b/dub.json
- kdevel (14/27) Jan 13 2018 Now my code does no longer compiles against the decimal package.
- rumbu (11/13) Jan 13 2018 I received a suggestion to reorganize the file structure because
- mark_mcs (9/12) Jan 13 2018 Dub uses the roaming profile directory for its cache storage.
- kdevel (34/48) Jan 13 2018 I have now the following directory structure:
- kdevel (66/73) Jan 13 2018 I can compile/run the nosine.d now. But implicit conversion
- rumbu (19/20) Jan 13 2018 Implicit conversion is not available at library level, D does not
- kdevel (174/189) Jan 13 2018 rsinus.d
- rumbu (24/25) Jan 13 2018 That's because you are mixing floating point and decimal.
- Jack Stouffer (4/7) Jan 12 2018 This looks really good. I think with a little work it would be
This is my first D finalized project (+16k loc). I know that there are other two projects intended to provide a decimal data type for D, but I consider mine the most complete and most compliant to the standards (at least until now). There are two years of since I'm working on it (and learning D in the same time), but I concentrated most of the efforts in the last two months. It was a nice exercise because I was happy to remember the math I learn through my college years (trigonometry, logarithms, Taylor series, derivatives, etc). Unfortunately I'm not using the same math during my day-to day job. Maybe in another post I will share my struggles I encountered during the development (plenty of). But a big thank you goes to Rainer Schuetze: without Visual Studio and without the integrated debugger this project was impossible to maintain. Now on topic: - fully IEEE-754-2008 compliant; - one flat file; - using Intel's binary decimal enconding; - three decimal data types: decimal32, decimal64 and decimal128 - all D operators supported for all numeric types (left and right side integrals, floats, chars); - conversion supported from/to integrals, floats, bools, chars - conversion to/from other decimal formats (Microsoft Currency, Microsoft Decimal, IBM Densely Packed Decimal) - all std.math functions implemented (even logarithms and trigonometry); - all format specifiers implemented (%f, %e, %g, %a); - integrated with phobos format and conversion functions (to, format, writef); - thread local precision (from 1 to 34 decimal digits); - new rounding mode - Europe's most used - tiesToAway; - alternate exception handling (through flags); - minimal dependencies (some traits and some floating point functions); - comprehensive documentation; Source code: https://github.com/rumbu13/decimal/blob/master/src/decimal.d Documentation: http://rumbu13.github.io/decimal/doc/decimal.html The project is more than in an alpha state, all operations were tested but not exhaustively. What's next: - more tests; - benchmarks;
Jan 08 2018
Great job. 1) Assembly 2) That file needs to be split up. I can feel the lag as I scroll it.
Jan 08 2018
On Monday, 8 January 2018 at 22:54:06 UTC, rikki cattermole wrote:Great job. 1) Assembly 2) That file needs to be split up. I can feel the lag as I scroll it.1) I don't understand :) 2) Done. On Monday, 8 January 2018 at 22:46:27 UTC, Daniel Kozak wrote:Wow awesome, it would be nice if you could add it as a dub package ( http://code.dlang.org/publish) to dub repository (http://code.dlang.org)Done. Github project: https://github.com/rumbu13/decimal Documentation: http://rumbu13.github.io/decimal/doc/package.html Dub package: https://code.dlang.org/packages/decimal
Jan 09 2018
On Tuesday, 9 January 2018 at 22:00:13 UTC, rumbu wrote:Documentation: http://rumbu13.github.io/decimal/doc/package.htmlI noticed a minor typo in the documentation: auto b = decimal32(123456789); //inexact, represented as 1234568 * x 10^^2 I believe the "*" should be deleted. This is great documentation!
Jan 09 2018
Wow awesome, it would be nice if you could add it as a dub package ( http://code.dlang.org/publish) to dub repository (http://code.dlang.org) On Mon, Jan 8, 2018 at 11:16 PM, rumbu via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:This is my first D finalized project (+16k loc). I know that there are other two projects intended to provide a decimal data type for D, but I consider mine the most complete and most compliant to the standards (at least until now). There are two years of since I'm working on it (and learning D in the same time), but I concentrated most of the efforts in the last two months. It was a nice exercise because I was happy to remember the math I learn through my college years (trigonometry, logarithms, Taylor series, derivatives, etc). Unfortunately I'm not using the same math during my day-to day job. Maybe in another post I will share my struggles I encountered during the development (plenty of). But a big thank you goes to Rainer Schuetze: without Visual Studio and without the integrated debugger this project was impossible to maintain. Now on topic: - fully IEEE-754-2008 compliant; - one flat file; - using Intel's binary decimal enconding; - three decimal data types: decimal32, decimal64 and decimal128 - all D operators supported for all numeric types (left and right side integrals, floats, chars); - conversion supported from/to integrals, floats, bools, chars - conversion to/from other decimal formats (Microsoft Currency, Microsoft Decimal, IBM Densely Packed Decimal) - all std.math functions implemented (even logarithms and trigonometry); - all format specifiers implemented (%f, %e, %g, %a); - integrated with phobos format and conversion functions (to, format, writef); - thread local precision (from 1 to 34 decimal digits); - new rounding mode - Europe's most used - tiesToAway; - alternate exception handling (through flags); - minimal dependencies (some traits and some floating point functions); - comprehensive documentation; Source code: https://github.com/rumbu13/decimal/blob/master/src/decimal.d Documentation: http://rumbu13.github.io/decimal/doc/decimal.html The project is more than in an alpha state, all operations were tested but not exhaustively. What's next: - more tests; - benchmarks;
Jan 08 2018
On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:Documentation: http://rumbu13.github.io/decimal/doc/decimal.htmlWow, slick documentation!
Jan 09 2018
On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:This is my first D finalized project (+16k loc). I know that there are other two projects intended to provide a decimal data type for D, but I consider mine the most complete and most compliant to the standards (at least until now).Wow!. So thorough. Documentation is fantastic. Very nice work, indeed! Mike
Jan 09 2018
On Tuesday, 9 January 2018 at 10:41:42 UTC, Mike Franklin wrote:On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:I couldn't say it better. Its really well done...This is my first D finalized project (+16k loc). I know that there are other two projects intended to provide a decimal data type for D, but I consider mine the most complete and most compliant to the standards (at least until now).Wow!. So thorough. Documentation is fantastic. Very nice work, indeed! Mike
Jan 09 2018
On 2018-01-08 22:16:25 +0000, rumbu said:This is my first D finalized project (+16k loc).Great stuff! Will this work in betterC mode? Side-Note: I'm always missing the betterC information or is the philosophy to just try it out? -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
Jan 11 2018
On Thursday, 11 January 2018 at 11:19:41 UTC, Robert M. Münch wrote:On 2018-01-08 22:16:25 +0000, rumbu said:We have now this page: https://dlang.org/spec/betterc.html Well, betterC it's still a WIP feature and its feature subset is improved from release to release. In doubt you can always use run.dlang.io to quickly try out things.This is my first D finalized project (+16k loc).Great stuff! Will this work in betterC mode? Side-Note: I'm always missing the betterC information or is the philosophy to just try it out?
Jan 11 2018
On 2018-01-11 15:34:04 +0000, Seb said:Hi, thanks. Should have been more precise: An informaiton for every lib if it is compatible with betterC. IMO betterC is the strategic trojan horse to get D into the broader masses.Side-Note: I'm always missing the betterC information or is the philosophy to just try it out?We have now this page: https://dlang.org/spec/betterc.htmlWell, betterC it's still a WIP feature and its feature subset is improved from release to release. In doubt you can always use run.dlang.io to quickly try out things.That's great, thanks for the hint. -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
Jan 11 2018
On Thursday, 11 January 2018 at 11:19:41 UTC, Robert M. Münch wrote:On 2018-01-08 22:16:25 +0000, rumbu said:It will not work without some refactory. Most of phobos/druntime dependencies are minimal an can be rewritten - in fact there are only 9 dependencies: bsr, bsf, addu, subu, adds, subs from druntime and isNaN, isinfinity, signbit from std.math. The rest of the dependencies are simply traits that must work by default under betterC. Once dependencies are solved, another problem will be the exception mechanism. 90% of arithmetic operations are meant to throw exceptions, but this can be overridden by the alternate exception handling - raising and setting flags. BUT - a very big but - the most important issue is the formatting thing. Even there is no direct dependency on std.format or std.stdio, the formatting mechanism is designed to fit nicely into phobos formatting paradigm. That means that there is no way to output decimal values on the console without phobos. I confess that 30% of my development time was the formatting feature: displaying correctly any possible combination of width, padding, alignment in 4 different formats (%f, %g, %e, %a) was really a challenge and despite of hundreds of unit tests, I'm not convinced today that I covered all the corner cases. The f*cking %g took me 3 days to find out exactly what is meant to do. More than that, each compiler producer have a different idea about format specifiers. Linking your application against snn, msvcrt or glibc will render completely different results for printf("%g", ...). On top of that, neither the FormatSpec documentation from phobos is something complete and clear... AFAIK, there is no way to plug a custom formatting mechanism into printf, not even in plain C (ok, I'm aware that gcc has something in this respect). To sum things up, it is possible to use it in betterC mode if: - all dependencies are rewritten; - the exception handling is dropped out completely; - a printf equivalent for decimal types is rewritten from scratch or - decimal values must be converted to binary float before printing them - but this will negate the main purpose of the decimal type - precision.This is my first D finalized project (+16k loc).Great stuff! Will this work in betterC mode?
Jan 11 2018
On Thursday, 11 January 2018 at 18:15:23 UTC, rumbu wrote:[snip] BUT - a very big but - the most important issue is the formatting thing. Even there is no direct dependency on std.format or std.stdio, the formatting mechanism is designed to fit nicely into phobos formatting paradigm. That means that there is no way to output decimal values on the console without phobos. I confess that 30% of my development time was the formatting feature: displaying correctly any possible combination of width, padding, alignment in 4 different formats (%f, %g, %e, %a) was really a challenge and despite of hundreds of unit tests, I'm not convinced today that I covered all the corner cases. The f*cking %g took me 3 days to find out exactly what is meant to do. More than that, each compiler producer have a different idea about format specifiers. Linking your application against snn, msvcrt or glibc will render completely different results for printf("%g", ...). On top of that, neither the FormatSpec documentation from phobos is something complete and clear...Ilya has expressed interest in a betterC formatting library for libmir.
Jan 11 2018
On 1/11/18 1:15 PM, rumbu wrote:On Thursday, 11 January 2018 at 11:19:41 UTC, Robert M. Münch wrote:Some of those are intrinsics, and don't actually link to any druntime functions. -SteveOn 2018-01-08 22:16:25 +0000, rumbu said:It will not work without some refactory. Most of phobos/druntime dependencies are minimal an can be rewritten - in fact there are only 9 dependencies: bsr, bsf, addu, subu, adds, subs from druntime and isNaN, isinfinity, signbit from std.math.This is my first D finalized project (+16k loc).Great stuff! Will this work in betterC mode?
Jan 11 2018
On 2018-01-11 18:15:23 +0000, rumbu said:On Thursday, 11 January 2018 at 11:19:41 UTC, Robert M. Mnch wrote:Ok, that doesn't sound impossible.Great stuff! Will this work in betterC mode?It will not work without some refactory. Most of phobos/druntime dependencies are minimal an can be rewritten - in fact there are only 9 dependencies: bsr, bsf, addu, subu, adds, subs from druntime and isNaN, isinfinity, signbit from std.math. The rest of the dependencies are simply traits that must work by default under betterC.Once dependencies are solved, another problem will be the exception mechanism. 90% of arithmetic operations are meant to throw exceptions, but this can be overridden by the alternate exception handling - raising and setting flags.Yes, makes sense.BUT - a very big but - the most important issue is the formatting thing. ... a printf equivalent for decimal types is rewritten from scratch or - decimal values must be converted to binary float before printing them - but this will negate the main purpose of the decimal type - precision.Well, I think even using a decimal128 for some calculations to have higher precision intermediate results and only converting them to float for UI interaction would make a lot of sense. At least in our use-case, that would be quite interesting. Looking forward to see some benchmarks. -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
Jan 11 2018
Great project! On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:- all format specifiers implemented (%f, %e, %g, %a);Really? [...]What's next: - more tests;Here you are: ``` import std.stdio; import decimal; void main () { decimal32 d = "0.7"; d *= decimal32("1.05"); d.writeln; printf ("%.2f\n", d); float f = 0.7f; f *= 1.05f; f.writeln; printf ("%.2f\n", f); decimal32 e = 1_000_000_000; while (e > 1e-7) { e.writeln; e /= 10; } } ``` This prints: 0.735 0.00 <--- expected: 0.74 0.735 0.73 <--- loop output missing (DMD64 D Compiler v2.077.1)
Jan 11 2018
On Thursday, 11 January 2018 at 20:35:03 UTC, kdevel wrote:Great project! On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:C’s printf by definition can’t be customized. What did you expect?- all format specifiers implemented (%f, %e, %g, %a);Really? [...]What's next: - more tests;Here you are: ``` import std.stdio; import decimal; void main () { decimal32 d = "0.7"; d *= decimal32("1.05"); d.writeln; printf ("%.2f\n", d);float f = 0.7f; f *= 1.05f; f.writeln; printf ("%.2f\n", f); decimal32 e = 1_000_000_000; while (e > 1e-7) { e.writeln; e /= 10; } } ``` This prints: 0.735 0.00 <--- expected: 0.74 0.735 0.73 <--- loop output missing (DMD64 D Compiler v2.077.1)
Jan 11 2018
On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:Sure. http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.htmlprintf ("%.2f\n", d);C’s printf by definition can’t be customized.What did you expect?To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6: mis.c ``` #include <stdio.h> int main () { double d = 0; printf ("%p\n", d); return 0; } ``` $ gcc -Wall mis.c mis.c: In function 'main': mis.c:6:14: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'double' [-Wformat=] printf ("%p\n", d);
Jan 11 2018
On 1/11/18 4:12 PM, kdevel wrote:On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:But dmd isn't a C compiler, nor does it have to worry about the problems C has (namely, untyped varargs). To dmd, printf is just another function, there's nothing special about it. -SteveWhat did you expect?To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:
Jan 11 2018
On Thu, Jan 11, 2018 at 04:38:57PM -0500, Steven Schveighoffer via Digitalmars-d-announce wrote:On 1/11/18 4:12 PM, kdevel wrote:[...] Yeah, checking C-style printf formats isn't dmd's problem. The Phobos equivalent of printf, however, *does* support compile-time format checking in the latest version: writefln!"%s %d %d"("abc", 1); // "Orphan format specifier: %d" writefln!"%s %d"("abc", 1, 2); // "Orphan format arguments: args[2..3]" writefln!"%s %d"(1, "abc"); // "Incorrect format specifier for range: %d" writefln!"%f"(1); // "incompatible format character for integral argument: %f" Best of all, this is all done via CTFE in the library code, no hard-coding in the compiler necessary. You can implement your own compile-time checker for your own DSLs in the same way, without needing to hack the compiler. T -- MSDOS = MicroSoft's Denial Of ServiceOn Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:But dmd isn't a C compiler, nor does it have to worry about the problems C has (namely, untyped varargs). To dmd, printf is just another function, there's nothing special about it.What did you expect?To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:
Jan 11 2018
On Thursday, 11 January 2018 at 22:07:42 UTC, H. S. Teoh wrote:On Thu, Jan 11, 2018 at 04:38:57PM -0500, Steven Schveighoffer via Digitalmars-d-announce wrote:Interesting, guess this was added last April with dmd 2.074? https://dlang.org/changelog/2.074.0.html#std-format-formattedWrite You or someone should write up a blog post about this, with both this example and expanding on how D enables this kind of functionality in general.On 1/11/18 4:12 PM, kdevel wrote:[...] Yeah, checking C-style printf formats isn't dmd's problem. The Phobos equivalent of printf, however, *does* support compile-time format checking in the latest version: writefln!"%s %d %d"("abc", 1); // "Orphan format specifier: %d" writefln!"%s %d"("abc", 1, 2); // "Orphan format arguments: args[2..3]" writefln!"%s %d"(1, "abc"); // "Incorrect format specifier for range: %d" writefln!"%f"(1); // "incompatible format character for integral argument: %f" Best of all, this is all done via CTFE in the library code, no hard-coding in the compiler necessary. You can implement your own compile-time checker for your own DSLs in the same way, without needing to hack the compiler.On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:But dmd isn't a C compiler, nor does it have to worry about the problems C has (namely, untyped varargs). To dmd, printf is just another function, there's nothing special about it.What did you expect?To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:
Jan 12 2018
On Thursday, 11 January 2018 at 21:12:59 UTC, kdevel wrote:On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:“”” GNU C Library lets you define “”” Here is your compatibility story.Sure.printf ("%.2f\n", d);C’s printf by definition can’t be customized.1. It’s a warning. 2. There is no typechecking it’s just a hardcoded linting in the compiler. 3. It’s D use writefln or if going for C primitives know their quirks. 4. Passing anything but basic types to C vararg is undefined in C++ IIRC, dunno what D should do about it.What did you expect?To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:mis.c ``` #include <stdio.h> int main () { double d = 0; printf ("%p\n", d); return 0; } ``` $ gcc -Wall mis.c mis.c: In function 'main': mis.c:6:14: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'double' [-Wformat=] printf ("%p\n", d);
Jan 11 2018
On Thursday, 11 January 2018 at 20:35:03 UTC, kdevel wrote:printf ("%.2f\n", d);This must read writefln ("%.2f", d); Would have expected a compile time/run time error.This prints: 0.735 0.00 <--- expected: 0.74Good. writefln prints the expected value.0.735 0.73 <--- loop output missingThis is still missing. If I change the while-loop threshold to 1e-9 the values are printed.
Jan 11 2018
On Thursday, 11 January 2018 at 20:44:13 UTC, kdevel wrote:On Thursday, 11 January 2018 at 20:35:03 UTC, kdevel wrote:loop.d ``` import std.stdio; import decimal; void loopme(T) () { "---".writeln; T e = T(1000); while (e > T(1e-6)) { e.writeln; e /= 10; } } void main () { loopme!float; loopme!decimal32; } ``` This prints --- 1000 100 10 1 0.1 0.01 0.001 0.0001 1e-05 --- 1000 100 10 1 0.1 0.0100000 <-- 0.00100000 <-- 0.000100000 <-- 1.00000e-05 <-- Why are there trailing zeroes?<--- loop output missing
Jan 11 2018
On Thursday, 11 January 2018 at 21:24:30 UTC, kdevel wrote:On Thursday, 11 January 2018 at 20:44:13 UTC, kdevel wrote:As I said, the %g specifier (used by default in writeln) makes me cry. Anyway, I made some modifications, now it prints correctly (in fact using floats just proves the need of decimals on my system): -- 1000 100 10 1 0.1 0.01 0.00099999 0.000099999 1e-05 --- 1000 100 10 1 0.1 0.01 0.001 0.0001 1e-05 Regarding printf, I cannot help, this is a C function, has nothing to do with D formatting.On Thursday, 11 January 2018 at 20:35:03 UTC, kdevel wrote:loop.d ``` import std.stdio; import decimal; void loopme(T) () { "---".writeln; T e = T(1000); while (e > T(1e-6)) { e.writeln; e /= 10; } } void main () { loopme!float; loopme!decimal32; } ``` This prints --- 1000 100 10 1 0.1 0.01 0.001 0.0001 1e-05 --- 1000 100 10 1 0.1 0.0100000 <-- 0.00100000 <-- 0.000100000 <-- 1.00000e-05 <-- Why are there trailing zeroes?<--- loop output missing
Jan 11 2018
On Thursday, 11 January 2018 at 22:36:40 UTC, rumbu wrote:1000 100 10 1 0.1 0.01 0.001 0.0001 1e-05 Regarding printf, I cannot help, this is a C function, has nothing to do with D formatting.Sure. What about the failed comparison: gt.d ``` import std.stdio; import decimal; void loopme(T) () { "---".writeln; T e = 10; while (e > 1e-6) { e /= 10; writeln (e, ' ', e > 1e-6); } } void main () { loopme!decimal32; loopme!decimal64; loopme!decimal128; } ``` This gives here: --- 1 true 0.1 false --- 1 true 0.1 false --- 1 true 0.1 true 0.0100000 true 0.00100000 true 0.000100000 true 1.00000e-05 true 1.00000e-06 true 1.00000e-07 false
Jan 11 2018
On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote: What about the failed comparison:gt.d ``` import std.stdio; import decimal; void loopme(T) () { "---".writeln; T e = 10; while (e > 1e-6) { e /= 10; writeln (e, ' ', e > 1e-6); } } void main () { loopme!decimal32; loopme!decimal64; loopme!decimal128; } ``` This gives here: --- 1 true 0.1 false --- 1 true 0.1 false --- 1 true 0.1 true 0.0100000 true 0.00100000 true 0.000100000 true 1.00000e-05 true 1.00000e-06 true 1.00000e-07 falseThis is not failed comparison. 1e-6 cannnot be represented exactly as binary floating point, it is in fact 0.00000099999999999999995481 as double which happens to be less than 1e-6. decimal32 and decimal64 are rounding up the value, decimal128 has enough precision (34 digits) to render exactly the value above. ----- 7 digits: 0.0000010 15 digits: 0.000001000000000 34 digits: 0.0000009999999999999999548100000000
Jan 11 2018
On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote: What about the failed comparison:.... You are right in fact, there is also a failed comparison. Now corrected.
Jan 11 2018
On Friday, 12 January 2018 at 05:18:15 UTC, rumbu wrote:Works. Thanks for the changes!On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote: What about the failed comparison:.... You are right in fact, there is also a failed comparison. Now corrected.
Jan 12 2018
On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:- all std.math functions implemented (even logarithms and trigonometry);nosine.d ``` import std.stdio; // import std.math; import decimal; void nosine (T) () { T d = T(1.1); writeln (sin(d)); } void main () { nosine!decimal32; nosine!decimal64; nosine!decimal128; } ``` $ dmd nosine.d decimal.git/libdecimal.a decimal/package.d(10505): Error: undefined identifier decimalCapAngle decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!32) error instantiating nosine.d(8): instantiated from here: sin!(Decimal!32) nosine.d(13): instantiated from here: nosine!(Decimal!32) decimal/package.d(10505): Error: undefined identifier decimalCapAngle decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!64) error instantiating nosine.d(8): instantiated from here: sin!(Decimal!64) nosine.d(14): instantiated from here: nosine!(Decimal!64) decimal/package.d(10505): Error: undefined identifier decimalCapAngle decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!128) error instantiating nosine.d(8): instantiated from here: sin!(Decimal!128) nosine.d(15): instantiated from here: nosine!(Decimal!128)
Jan 12 2018
On Friday, 12 January 2018 at 13:09:42 UTC, kdevel wrote:$ dmd nosine.d decimal.git/libdecimal.a decimal/package.d(10505): Error: undefined identifier decimalCapAngleSorry, broke some code when I made the split. Now it's working.
Jan 12 2018
On Saturday, 13 January 2018 at 01:30:12 UTC, rumbu wrote:On Friday, 12 January 2018 at 13:09:42 UTC, kdevel wrote:$ dub Performing "debug" build using dmd for x86_64. decimal ~master: building configuration "library"... src/test/test.d(4,5): Error: only one main allowed. Previously found main at src/benchmark/benchmark.d(143,5) dmd failed with exit code 1.$ dmd nosine.d decimal.git/libdecimal.a decimal/package.d(10505): Error: undefined identifier decimalCapAngleSorry, broke some code when I made the split. Now it's working.
Jan 13 2018
On Saturday, 13 January 2018 at 13:44:20 UTC, kdevel wrote:$ dub Performing "debug" build using dmd for x86_64. decimal ~master: building configuration "library"... src/test/test.d(4,5): Error: only one main allowed. Previously found main at src/benchmark/benchmark.d(143,5) dmd failed with exit code 1.diff --git a/dub.json b/dub.json index c48899f..d8882c1 100644 --- a/dub.json +++ b/dub.json -10,16 +10,16 "configurations": [ { "name": "library", - "excludedSourceFiles": [ "src/benchmark.d", "src/test.d" ] + "excludedSourceFiles": [ "src/benchmark/benchmark.d", "src/test/test.d" ] }, { "name": "unittest", - "excludedSourceFiles": [ "src/benchmark.d", "src/test.d" ] + "excludedSourceFiles": [ "src/benchmark/benchmark.d", "src/test/test.d" ] }, { "name": "benchmark", "targetType": "executable", - "excludedSourceFiles": [ "src/test.d" ] + "excludedSourceFiles": [ "src/test/test.d" ] } ] }
Jan 13 2018
On Saturday, 13 January 2018 at 13:49:59 UTC, kdevel wrote:diff --git a/dub.json b/dub.json index c48899f..d8882c1 100644 --- a/dub.json +++ b/dub.json -10,16 +10,16 "configurations": [ { "name": "library", - "excludedSourceFiles": [ "src/benchmark.d", "src/test.d" ] + "excludedSourceFiles": [ "src/benchmark/benchmark.d", "src/test/test.d" ] },Now my code does no longer compiles against the decimal package. This is my directory structure: dlang-decimal/ decimal -> decimal.git/src decimal.git [created by git clone <url> decimal.git] nosine.d $ dmd nosine decimal.git/libdecimal.a nosine.d(3): Error: module decimal is in file 'decimal.d' which cannot be read import path[0] = /.../dmd2/linux/bin64/../../src/phobos import path[1] = /.../dmd2/linux/bin64/../../src/druntime/import make: *** [nosine] Fehler 1
Jan 13 2018
On Saturday, 13 January 2018 at 13:56:20 UTC, kdevel wrote:Now my code does no longer compiles against the decimal package. This is my directory structure:I received a suggestion to reorganize the file structure because of some bug in dub (https://issues.dlang.org/show_bug.cgi?id=11847). The dub.json remained out of sync. I changed it, but I am not 100% sure that it's working. I am not experienced with dub, If someone wants to maintain dub.json, I will be more than happy to accept any pull request. Personally I hate dub because it's polluting my %APPDATA% folder and each time I connect my laptop to the company domain network, I must wait to sync zillions of files.
Jan 13 2018
On Saturday, 13 January 2018 at 14:43:53 UTC, rumbu wrote:Personally I hate dub because it's polluting my %APPDATA% folder and each time I connect my laptop to the company domain network, I must wait to sync zillions of files.Dub uses the roaming profile directory for its cache storage. This needs to be changed to the local profile directory. I'll submit a PR for this at some point in the near future. I have the dub build working locally and will be submitting another PR for that shortly. Unless anyone has any valid complaints, I'd like to convert dub.json to SDL format so that I can add comments without trying to work around the JSON syntax limitations.
Jan 13 2018
On Saturday, 13 January 2018 at 14:43:53 UTC, rumbu wrote:On Saturday, 13 January 2018 at 13:56:20 UTC, kdevel wrote:I only invoked dub in order to generate libdecimal.aNow my code does no longer compiles against the decimal package. This is my directory structure:I received a suggestion to reorganize the file structure because of some bug in dub (https://issues.dlang.org/show_bug.cgi?id=11847). The dub.json remained out of sync. I changed it, but I am not 100% sure that it's working. I am not experienced with dub, If someone wants to maintain dub.json, I will be more than happy to accept any pull request.Personally I hate dub because it's polluting my %APPDATA% folder and each time I connect my laptop to the company domain network, I must wait to sync zillions of files.I have now the following directory structure: dlang-decimal/ decimal -> decimal.git/src/decimal/ decimal.git/ [git cloned <url> decimal.git] libdecimal.a src/ decimal/ floats.d floats.di integrals.d integrals.di package.d package.di ranges.d ranges.di sinks.d sinks.di nosine.d I have generated the .di files with dmd -H *.d within the src/decimal directory. Now dmd in unwilling to compile: $ dmd nosine.d decimal.git/libdecimal.a decimal/integrals.di(537): Error: xadd cannot be interpreted at compile time, because it has no available source code decimal/integrals.di(567): called from here: xadd(result, z) decimal/integrals.di(121): called from here: fma(this, 10u, cast(uint)(cast(int)c - 48), ovf) decimal/integrals.di(978): called from here: unsigned(0LU, 0LU).this("100000000000000000000") [the four lines repeat untill 77 lines are printed] How come?
Jan 13 2018
On Saturday, 13 January 2018 at 14:43:53 UTC, rumbu wrote:I received a suggestion to reorganize the file structure because of some bug in dub (https://issues.dlang.org/show_bug.cgi?id=11847). The dub.json remained out of sync. I changed it, but I am not 100% sure that it's working. I am not experienced with dub, If someone wants to maintain dub.json, I will be more than happy to accept any pull request.I can compile/run the nosine.d now. But implicit conversion between decimalX and float/double/real does not seem to work. I came across this in sinus.d ``` import std.stdio; import std.math; import decimal; void main () { real r; for (r = 1; r < 6; r += .1L) { decimal128 d = r; auto dsin = sin (d); auto rsin = sin (r); real delta = dsin - rsin; writefln ("%9.2f %30.24f %12.4g", r, rsin, dsin, delta); } } ``` $ dmd sinus.d decimal.git/libdecimal.a sinus.d(12): Error: cannot implicitly convert expression dsin.opBinary(rsin) of type Decimal!128 to real I tried to change the subtraction to ``` real delta = dsin; delta -= rsin; ``` getting sinus_e1.d(12): Error: cannot implicitly convert expression dsin of type Decimal!128 to real Changes this into ``` real delta = dsin.to!real; delta -= rsin; ``` sinus_e2.d(12): Error: template decimal.to cannot deduce function from argument types !(real)(Decimal!128), candidates are: decimal/package.d(5814): decimal.to(T, D)(auto ref const D x, const RoundingMode mode) if (isIntegral!T && isDecimal!D) decimal/package.d(5832): decimal.to(F, D)(auto ref const D x, const RoundingMode mode) if (isFloatingPoint!F && isDecimal!D) to no avail. Also ``` real delta = cast(real) dsin; ``` did not succeed: decimal/package.d(933): Error: undefined identifier mode, did you mean template modf(D)(auto ref const D x, ref D y) if (isDecimal!D)? sinus_e3.d(12): Error: template instance decimal.Decimal!128.Decimal.opCast!real error instantiating Also ``` real delta = dsin.to!(real, RoundingMode.tiesToEven); ``` ain't work: sinus_e4.d(12): Error: template decimal.to cannot deduce function from argument types !(real, cast(RoundingMode)0)(Decimal!128), candidates are: decimal/package.d(5814): decimal.to(T, D)(auto ref const D x, const RoundingMode mode) if (isIntegral!T && isDecimal!D) decimal/package.d(5832): decimal.to(F, D)(auto ref const D x, const RoundingMode mode) if (isFloatingPoint!F && isDecimal!D) How can I convert a decimalX to float/double/real?
Jan 13 2018
On Saturday, 13 January 2018 at 17:19:31 UTC, kdevel wrote:How can I convert a decimalX to float/double/real?Implicit conversion is not available at library level, D does not have an implicit conversion operator; Subtracting decimalX - real will result in a decimalX. This was a design decision, but I'm open to suggestions. The following code works: real r; for (r = 1; r < 6; r += .1L) { decimal128 d = r; auto dsin = sin (d); auto rsin = sin (r); auto delta = dsin - rsin; //delta is decimal128 writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, dsin, delta); } if you really need to convert decimalX values to floating point counterparts, you'll need to cast them: x = cast(real)somedecimalvalue; (but update your files before this, I discovered a bug in opCast)
Jan 13 2018
On Saturday, 13 January 2018 at 17:46:15 UTC, rumbu wrote:The following code works: real r; for (r = 1; r < 6; r += .1L) { decimal128 d = r; auto dsin = sin (d); auto rsin = sin (r); auto delta = dsin - rsin; //delta is decimal128 writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, dsin, delta); }rsinus.d ``` import std.stdio; import std.math; import decimal; void main () { real r; for (r = 1; r < 6; r += .1L) { decimal128 d = r; auto dsin = sin (d); auto rsin = sin (r); auto delta = dsin - rsin; writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, dsin, delta); } } ``` I get large numerical dicrepancies and an exception: 1.00 0.841470984807896506664591 0.841470984807896506632968 3.633e-18 1.10 0.891207360061435339970703 0.878166666666666700439167 -1e-02 1.20 0.932039085967226349689098 0.932735999999999982229600 1e-04 1.30 0.963558185417192964729825 0.964774416666666678037840 1e-03 1.40 0.985449729988460180693261 0.985449729988460165022208 2.352e-17 1.50 0.997494986604054430972058 0.997494986604054430940101 -1.206e-17 1.60 0.999573603041505164359688 0.917333333333333309393333 -1e-02 1.70 0.991664810452468615338453 0.991664810452468621659666 5.316e-17 1.80 0.973847630878195186514452 0.973847630878195177217801 3.222e-17 1.90 0.946300087687414488452770 0.946300087687414518558711 5.006e-17 2.00 0.909297426825681695322298 0.909297426825681695408286 -1.229e-17 2.10 0.863209366648873770600393 0.863209366648873727768592 -9.243e-17 2.20 0.808496403819590184279108 0.808496403819590083669388 -1.180e-16 2.30 0.745705212176720177432929 0.745705212176720299976718 1.573e-16 2.40 0.675463180551150926659871 0.675463180551150998081025 4.488e-17 2.50 0.598472144103956494242628 0.598472144103956494052117 -5.365e-17 2.60 0.515501371821464235509908 0.515501371821464164136844 -1.059e-16 2.70 0.427379880233829934906920 0.427379880233829779962563 -1.640e-16 2.80 0.334988150155904919986691 0.334988150155905092912699 1.534e-16 2.90 0.239249329213982328722001 0.239249329213982423337949 8.154e-17 3.00 0.141120008059867222739193 0.141120008059867222100109 9.000e-18 3.10 0.041580662433290579926783 0.041580662433290496264607 -8.502e-17 3.20 -0.058374143427579908318645 -0.058374143427580079845578 -1.746e-16 3.30 -0.157745694143248381115198 -0.157745694143248199327762 1.774e-16 3.40 -0.255541102026831318288136 -0.255541102026831224503296 1.098e-16 3.50 -0.350783227689619847116916 -0.350783227689619848119312 -1.252e-17 3.60 -0.442520443294852383234834 -0.442520443294852457798085 -5.310e-17 3.70 -0.529836140908493212172466 -0.529836140908493358228498 -1.787e-16 3.80 -0.611857890942719074699619 -0.611857890942718929385788 9.811e-17 3.90 -0.687766159183973817053612 -0.687766159183973746224122 2.078e-17 4.00 -0.756802495307928250372134 -0.756802495307928251373997 -5.067e-17 4.10 -0.818277111064410503490831 -0.818277111064410297331800 1.797e-16 4.20 -0.871575772413588059281658 -0.871575772413588143861425 -6.686e-17 4.30 -0.916165936749454983402223 -0.916165936749454908701153 1.013e-16 4.40 -0.951602073889515953533484 -0.951602073889516059449964 -1.634e-16 4.50 -0.977530117665097055001684 -0.977530117665097055387688 -4.889e-17 4.60 -0.993691003633464455912887 -0.993691003633464414974720 -8.475e-18 4.70 -0.999923257564100884174467 -0.999923257564100886240565 -5.624e-17 4.80 -0.996164608835840671935500 -0.996164608835840688651004 -8.651e-18 4.90 -0.982452612624332512691275 -0.982452612624332448489733 2.651e-17 5.00 -0.958924274663138469525139 -0.958924274663138468894495 -1.739e-17 5.10 -0.925814682327732297803524 -0.925814682327732436044974 -9.704e-17 5.20 -0.883454655720153265790421 -0.883454655720153186437488 5.926e-17 5.30 -0.832267442223901164892897 -0.832267442223901270573400 -1.281e-16 5.40 -0.772764487555987363974919 -0.772764487555987145324893 2.202e-16 5.50 -0.705540325570391908089566 -0.705540325570391906230803 1.647e-17 5.60 -0.631266637872321313522395 -0.631266637872321596869491 -3.079e-16 5.70 -0.550685542597637763537807 -25.165500000000002545915000 - core.exception.RangeError decimal/package.d(6652): Range violation ---------------- ??:? _d_arrayboundsp [0x46ccea] decimal/package.d:6652 void decimal.sinkFloat!(char, decimal.integrals.unsigned!(128).unsigned).sinkFloat(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), const(decimal.integrals.unsigned!(128).unsigned), const(int), const(bool), const(decimal.RoundingMode), const(bool)) [0x460a41] decimal/package.d:6851 void decimal.sinkGeneral!(char, decimal.integrals.unsigned!(128).unsigned).sinkGeneral(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), const(decimal.integrals.unsigned!(128).unsigned), const(int), const(bool), const(decimal.RoundingMode)) [0x461ae9] decimal/package.d:6890 void decimal.sinkDecimal!(char, decimal.Decimal!(128).Decimal).sinkDecimal(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), ref const(decimal.Decimal!(128).Decimal), const(decimal.RoundingMode)) [0x460208] decimal/package.d:1316 const void decimal.Decimal!(128).Decimal.toString!(char).toString(scope void delegate(const(char)[]), std.format.FormatSpec!(char).FormatSpec) [0x45fff1] /.../dmd2/linux/bin64/../../src/phobos/std/format.d:3341 void std.format.formatObject!(std.stdio.File.LockingTextWriter, decimal.Decimal!(128).Decimal, char).formatObject(ref std.stdio.File.LockingTextWriter, ref decimal.Decimal!(128).Decimal, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x4620c2] /.../dmd2/linux/bin64/../../src/phobos/std/format.d:3669 void std.format.formatValue!(std.stdio.File.LockingTextWriter, decimal.Decimal!(128).Decimal, char).formatValue(ref std.stdio.File.LockingTextWriter, ref decimal.Decimal!(128).Decimal, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x462069] /.../dmd2/linux/bin64/../../src/phobos/std/format.d:568 uint std.format.formattedWrite!(std.stdio.File.LockingTextWriter, char, real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal).formattedWrite(ref std.stdio.File.LockingTextWriter, const(char[]), real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal) [0x45711b] /.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:1496 void std.stdio.File.writefln!(char, real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal).writefln(const(char[]), real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal) [0x456be6] /.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:3797 void std.stdio.writefln!(char, real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal).writefln(const(char[]), real, real, decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal) [0x456b37] rsinus.d:12 _Dmain [0x44c27d]if you really need to convert decimalX values to floating point counterparts, you'll need to cast them: x = cast(real)somedecimalvalue; (but update your files before this, I discovered a bug in opCast)Yea, this seems to work now.
Jan 13 2018
On Saturday, 13 January 2018 at 18:37:10 UTC, kdevel wrote:I get large numerical dicrepancies and an exception:That's because you are mixing floating point and decimal. Just to take one example: double 1.1 cannot be represented exactly as floating point and it's in fact 1.10000002384185791015625. sin is calculated using a Taylor series: sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... and so on. Raising to power all that junk after 1.1 will lead finally to error. If you really want to find out sin(1.1) using decimal, try sin(decimal128("1.1")) or sin(decimal128(1)/10); For exact values like sin(1.0), I let you decide which one is more exact: Wolfram Alpha: 0.8414709848078965066525023216302989 real: 0.8414709848078965066645910000000000 double: 0.8414709848078965048700000000000000 float: 0.8414709568023681640600000000000000 decimal128: 0.8414709848078965066329679978908351 decimal64: 0.8414709848078965000000000000000000 decimal32: 0.8414710000000000000000000000000000 Anyway, I wouldn't call a difference at the 18th digit a "large discrepancy" when we are talking about irrational numbers. Regarding the exception, I cannot reproduce it, but I'll look into it. Thank you for your exhaustive testing :)
Jan 13 2018
On Saturday, 13 January 2018 at 19:28:40 UTC, rumbu wrote:On Saturday, 13 January 2018 at 18:37:10 UTC, kdevel wrote:Sure. double has 53 mantissa bits but float only 24. But that is not my point. I am *not* talking about the 1e-18 but about these lines: 1.10 0.891207360061435339970703 0.878166666666666700439167 -1e-02 1.20 0.932039085967226349689098 0.932735999999999982229600 1e-04 1.30 0.963558185417192964729825 0.964774416666666678037840 1e-03 and 5.70 -0.550685542597637763537807 -25.165500000000002545915000 - At 5.7 the value is obviously out of range.I get large numerical dicrepancies and an exception:That's because you are mixing floating point and decimal. Just to take one example: double 1.1 cannot be represented exactly as floating point and it's in fact 1.10000002384185791015625.sin is calculated using a Taylor series: sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... and so on. Raising to power all that junk after 1.1 will lead finally to error. If you really want to find out sin(1.1) using decimal, try sin(decimal128("1.1")) or sin(decimal128(1)/10);Chapter 9.2 of IEEE-754-2008 says the domain of sin(x) is (-inf, inf). So if the argument x is outside the radius of convergence of the Taylor series x must be reduced modulo 2pi such that it fits.For exact values like sin(1.0), I let you decide which one is more exact: Wolfram Alpha: 0.8414709848078965066525023216302989 real: 0.8414709848078965066645910000000000 double: 0.8414709848078965048700000000000000 float: 0.8414709568023681640600000000000000 decimal128: 0.8414709848078965066329679978908351 decimal64: 0.8414709848078965000000000000000000 decimal32: 0.8414710000000000000000000000000000 Anyway, I wouldn't call a difference at the 18th digit a "large discrepancy" when we are talking about irrational numbers.See above.Regarding the exception, I cannot reproduce it, but I'll look into it.Nice.Thank you for your exhaustive testing :)There's more to come (sorry for the greek symbols, could not resist to check this utf-8 feature): unity.d ``` import std.stdio; import std.typecons; import std.range; import std.math; import decimal; immutable size_t N = 100; void unity (T) () { writeln ("\n=== ", T.stringof, " ===\n"); immutable one = T (1); immutable two = T (2); immutable π = atan (one) * 4; writefln!"π = <%30.24f>" (π); foreach (i; iota(N + 1)) { auto φ = two * π * i / N; auto sinφ = sin (φ); auto cosφ = cos (φ); auto unity = sinφ * sinφ + cosφ * cosφ; auto δ = one - unity; writeln ("φ = <", φ, ">, δ = <", δ, ">"); } } void main () { // unity!float; // unity!double; // unity!real; // unity!decimal32; unity!decimal64; unity!decimal128; } ``` Selected lines from the output produced here (Linux, DMD64 D Compiler v2.077.1): === Decimal!64 === π = < 3.141592653589793000000000> φ = <0>, δ = <0> φ = <0.0628319>, δ = <0> φ = <0.125664>, δ = <1e-16> possibly okay : φ = <0.942478>, δ = <2.41721e-06> too large : φ = <2.45044>, δ = <-6.57811e-07> ditto φ = <2.51327>, δ = <-3.83012e-10> ditto φ = <2.57611>, δ = <0.479476> ditto : : : === Decimal!128 === π = < 3.141592653589793238612055> φ = <0>, δ = <0> φ = <1e-02>, δ = <-1.73780e-22> : Something went wrong with printing φ. And also this program crashes: core.exception.RangeError decimal/package.d(6652): Range violation ---------------- ??:? _d_arrayboundsp [0x80bc65f] ??:? void decimal.sinkFloat!(char, decimal.integrals.unsigned!(128).unsigned).sinkFloat(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), const(decimal.integrals.unsigned!(128).unsigned), const(int), const(bool), const(decimal.RoundingMode), const(bool)) [0x80b2976] ??:? void decimal.sinkGeneral!(char, decimal.integrals.unsigned!(128).unsigned).sinkGeneral(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), const(decimal.integrals.unsigned!(128).unsigned), const(int), const(bool), const(decimal.RoundingMode)) [0x80b33a4] ??:? void decimal.sinkDecimal!(char, decimal.Decimal!(128).Decimal).sinkDecimal(ref const(std.format.FormatSpec!(char).FormatSpec), void delegate(const(char)[]), ref const(decimal.Decimal!(128).Decimal), const(decimal.RoundingMode)) [0x80b241a] ??:? const void decimal.Decimal!(128).Decimal.toString!(char).toString(scope void delegate(const(char)[]), std.format.FormatSpec!(char).FormatSpec) [0x80b22bb] ??:? void std.format.formatObject!(std.stdio.File.LockingTextWriter, decimal.Decimal!(128).Decimal, char).formatObject(ref std.stdio.File.LockingTextWriter, ref decimal.Decimal!(128).Decimal, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x80b73cf] ??:? void std.format.formatValue!(std.stdio.File.LockingTextWriter, decimal.Decimal!(128).Decimal, char).formatValue(ref std.stdio.File.LockingTextWriter, ref decimal.Decimal!(128).Decimal, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x80b7393] ??:? uint std.format.formattedWrite!(std.stdio.File.LockingTextWriter, char, decimal.Decimal!(128).Decimal).formattedWrite(ref std.stdio.File.LockingTextWriter, const(char[]), decimal.Decimal!(128).Decimal) [0x80b6efd] ??:? void std.stdio.File.write!(immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], char).write(immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], char) [0x8093176] ??:? void std.stdio.writeln!(immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[]).writeln(immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[], decimal.Decimal!(128).Decimal, immutable(char)[]) [0x80930c8] ??:? void unity.unity!(decimal.Decimal!(128).Decimal).unity() [0x8092f62] ??:? _Dmain [0x80905ec]
Jan 13 2018
On Saturday, 13 January 2018 at 20:40:20 UTC, kdevel wrote:On Saturday, 13 January 2018 at 19:28:40 UTC, rumbu wrote:There was an error in 128/256 bit division. The exception might be caused also by the same division since in the output values are rounded also by division. I think now it's solved. Now it prints: 1.00 +0.841470984807896506690000 +0.8414709848078965066525023216302990 +2.653e-18 1.10 +0.891207360061435339970000 +0.8912073600614353383642161528821827 +6.642e-19 1.20 +0.932039085967226349660000 +0.9320390859672263482207034175881317 +7.207e-19 1.30 +0.963558185417192964750000 +0.9635581854171929634976039012289115 +1.998e-18 1.40 +0.985449729988460180680000 +0.9854497299884601806594745788060975 +2.659e-18 1.50 +0.997494986604054430920000 +0.9974949866040544309417233711414873 +2.942e-18 1.60 +0.999573603041505164340000 +0.9995736030415051644881114370526778 +2.988e-18 1.70 +0.991664810452468615300000 +0.9916648104524686161192003644210237 +3.119e-18 1.80 +0.973847630878195186490000 +0.9738476308781951865323731788433576 +2.532e-18 1.90 +0.946300087687414488450000 +0.9463000876874144907527365796794817 +4.753e-18 2.00 +0.909297426825681695360000 +0.9092974268256816953960198659117448 +2.896e-18 2.10 +0.863209366648873770580000 +0.8632093666488737742146820454680267 +5.515e-18 2.20 +0.808496403819590184280000 +0.8084964038195901884235447312035390 +6.724e-18 2.30 +0.745705212176720177430000 +0.7457052121767201827156143818820931 +7.216e-18 2.40 +0.675463180551150926640000 +0.6754631805511509324649212496712473 +7.965e-18 2.50 +0.598472144103956494230000 +0.5984721441039565012621472421085657 +8.762e-18 2.60 +0.515501371821464235500000 +0.5155013718214642429697257155298933 +8.470e-18 2.70 +0.427379880233829934900000 +0.4273798802338299426927023640114310 +8.893e-18 2.80 +0.334988150155904919980000 +0.3349881501559049280238548187303455 +9.224e-18 2.90 +0.239249329213982328710000 +0.2392493292139823378938385702354806 +1.009e-17 3.00 +0.141120008059867222730000 +0.1411200080598672320006697688125648 +9.751e-18 3.10 +0.041580662433290579925000 +0.0415806624332905891860497743294677 +9.416e-18 3.20 -0.058374143427579908319000 -0.0583741434275798991542696566715643 +8.966e-18 3.30 -0.157745694143248381120000 -0.1577456941432483701618970386961038 +1.049e-17 3.40 -0.255541102026831318290000 -0.2555411020268313076483241184102069 +9.852e-18 3.50 -0.350783227689619847110000 -0.3507832276896198368828885525540795 +8.817e-18 3.60 -0.442520443294852383210000 -0.4425204432948523726088679351487828 +8.991e-18 3.70 -0.529836140908493212180000 -0.5298361409084932021854772134659022 +8.015e-18 3.80 -0.611857890942719074680000 -0.6118578909427190654510058312314653 +7.749e-18 3.90 -0.687766159183973817050000 -0.6877661591839738086537681707768678 +6.346e-18 4.00 -0.756802495307928250370000 -0.7568024953079282428752720232848741 +5.825e-18 4.10 -0.818277111064410503450000 -0.8182771110644104967923257194259585 +4.708e-18 4.20 -0.871575772413588059290000 -0.8715757724135880526646647777983275 +4.035e-18 4.30 -0.916165936749454983420000 -0.9161659367494549780197217790850059 +2.480e-18 4.40 -0.951602073889515953550000 -0.9516020738895159488107335437472529 +1.689e-18 4.50 -0.977530117665097054990000 -0.9775301176650970518056064241753746 -3.056e-19 4.60 -0.993691003633464455930000 -0.9936910036334644542315117020129026 -1.232e-18 4.70 -0.999923257564100884190000 -0.9999232575641008839565405992429380 -2.457e-18 4.80 -0.996164608835840671960000 -0.9961646088358406733565781684136726 -3.857e-18 4.90 -0.982452612624332512720000 -0.9824526126243325156335998995246860 -5.634e-18 5.00 -0.958924274663138469490000 -0.9589242746631384739990737444940666 -8.499e-18 5.10 -0.925814682327732297800000 -0.9258146823277323037497456163785133 -9.250e-18 5.20 -0.883454655720153265820000 -0.8834546557201532731063845238285883 -1.041e-17 5.30 -0.832267442223901164880000 -0.8322674422239011735432977190794839 -1.104e-17 5.40 -0.772764487555987363960000 -0.7727644875559873750523273015869194 -1.385e-17 5.50 -0.705540325570391908070000 -0.7055403255703919225313239842210499 -1.603e-17 5.60 -0.631266637872321313520000 -0.6312666378723213293016843594524164 -1.760e-17 5.70 -0.550685542597637763540000 -0.5506855425976377779216063046556619 -1.622e-17 5.80 -0.464602179413757213930000 -0.4646021794137572317851754163529263 -1.909e-17 5.90 -0.373876664830236362540000 -0.3738766648302363811468503760962045 -1.985e-17 6.00 -0.279415498198925875720000 -0.2794154981989258948954720395703132 -2.020e-17On Saturday, 13 January 2018 at 18:37:10 UTC, kdevel wrote:Sure. double has 53 mantissa bits but float only 24. But that is not my point. I am *not* talking about the 1e-18 but about these lines: 1.10 0.891207360061435339970703 0.878166666666666700439167 -1e-02 1.20 0.932039085967226349689098 0.932735999999999982229600 1e-04 1.30 0.963558185417192964729825 0.964774416666666678037840 1e-03 and 5.70 -0.550685542597637763537807 -25.165500000000002545915000 - At 5.7 the value is obviously out of range.I get large numerical dicrepancies and an exception:That's because you are mixing floating point and decimal. Just to take one example: double 1.1 cannot be represented exactly as floating point and it's in fact 1.10000002384185791015625.Chapter 9.2 of IEEE-754-2008 says the domain of sin(x) is (-inf, inf). So if the argument >x is outside the radius of convergence of the Taylor series x must be reduced modulo 2pi >such that it fits.That's exactly how it's done internally: https://github.com/rumbu13/decimal/blob/master/src/decimal/package.d#L13380 Your unity test also seems now to compute correctly. My maximum |δ| for decimal128 is now 1e-34There's more to come (sorry for the greek symbols, could not resist to check this utf-8 feature)I like them too: https://github.com/rumbu13/decimal/blob/master/src/decimal/package.d#L13558 Do you have something against including parts of your test published here as unittests? Thanks.
Jan 13 2018
On Saturday, 13 January 2018 at 22:05:02 UTC, rumbu wrote:Now it prints: 1.00 +0.841470984807896506690000 +0.8414709848078965066525023216302990 +2.653e-18My values differ slightly 1.00 0.841470984807896506664591 0.841470984807896506652502 3.653e-18 But I would check this later.Your unity test also seems now to compute correctly. My maximum |δ| for decimal128 is now 1e-34Same here.Do you have something against including parts of your test published here as unittests? Thanks.No, of course not, please take whatever you need! I have another testcase which prints awkward results: sinus_31.d ``` import std.stdio; import std.math; import decimal; void main () { real r; for (r = 1; r < 6; r += .1L) { decimal128 d = r; auto dsin = sin (d); auto rsin = sin (r); real delta = cast(real) dsin; delta -= rsin; writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, dsin, delta); } } ``` Please note the large deltas in case of negative operands. I suspect the conversion to real is wrong for these numbers: 1.00 0.841470984807896506664591 0.841470984807896506652502 -5.421e-20 1.10 0.891207360061435339970703 0.891207360061435378734271 3.871e-17 1.20 0.932039085967226349689098 0.932039085967226332095783 -1.756e-17 1.30 0.963558185417192964729825 0.963558185417192975802550 1.106e-17 1.40 0.985449729988460180693261 0.985449729988460165022497 -1.567e-17 1.50 0.997494986604054430972058 0.997494986604054430941723 -5.421e-20 1.60 0.999573603041505164359688 0.999573603041505161845555 -2.548e-18 1.70 0.991664810452468615338453 0.991664810452468621659514 6.343e-18 1.80 0.973847630878195186514452 0.973847630878195177217087 -9.324e-18 1.90 0.946300087687414488452770 0.946300087687414518555639 3.014e-17 2.00 0.909297426825681695322298 0.909297426825681695396020 5.421e-20 2.10 0.863209366648873770600393 0.863209366648873727768840 -4.283e-17 2.20 0.808496403819590184279108 0.808496403819590083670346 -1.006e-16 2.30 0.745705212176720177432929 0.745705212176720299980194 1.226e-16 2.40 0.675463180551150926659871 0.675463180551150998092962 7.145e-17 2.50 0.598472144103956494242628 0.598472144103956494051855 -2.168e-19 2.60 0.515501371821464235509908 0.515501371821464164135960 -7.139e-17 2.70 0.427379880233829934906920 0.427379880233829779959717 -1.549e-16 2.80 0.334988150155904919986691 0.334988150155905092912764 1.729e-16 2.90 0.239249329213982328722001 0.239249329213982423338157 9.458e-17 3.00 0.141120008059867222739193 0.141120008059867222100745 -6.37e-19 3.10 0.041580662433290579926783 0.041580662433290496266481 -8.366e-17 3.20 -0.058374143427579908318645 -0.058374143427580079845624 0.1167 3.30 -0.157745694143248381115198 -0.157745694143248199327897 0.3155 3.40 -0.255541102026831318288136 -0.255541102026831224503680 0.5111 3.50 -0.350783227689619847116916 -0.350783227689619848120369 0.7016 3.60 -0.442520443294852383234834 -0.442520443294852457800917 0.885 3.70 -0.529836140908493212172466 -0.529836140908493358235883 1.06 3.80 -0.611857890942719074699619 -0.611857890942718929404559 1.224 3.90 -0.687766159183973817053612 -0.687766159183973746223590 1.376 4.00 -0.756802495307928250372134 -0.756802495307928251372639 1.514 4.10 -0.818277111064410503490831 -0.818277111064410297328416 1.637 4.20 -0.871575772413588059281658 -0.871575772413588143853178 1.743 4.30 -0.916165936749454983402223 -0.916165936749454908681465 1.832 4.40 -0.951602073889515953533484 -0.951602073889516059450567 1.903 4.50 -0.977530117665097055001684 -0.977530117665097055389135 1.955 4.60 -0.993691003633464455912887 -0.993691003633464414978127 1.987 4.70 -0.999923257564100884174467 -0.999923257564100886248443 2 4.80 -0.996164608835840671935500 -0.996164608835840688668900 1.992 4.90 -0.982452612624332512691275 -0.982452612624332448489147 1.965 5.00 -0.958924274663138469525139 -0.958924274663138468893154 1.918 5.10 -0.925814682327732297803524 -0.925814682327732436041956 1.852 5.20 -0.883454655720153265790421 -0.883454655720153186430800 1.767 5.30 -0.832267442223901164892897 -0.832267442223901270558807 1.665 5.40 -0.772764487555987363974919 -0.772764487555987145293506 1.546 5.50 -0.705540325570391908089566 -0.705540325570391906231919 1.411 5.60 -0.631266637872321313522395 -0.631266637872321596871912 1.263 5.70 -0.550685542597637763537807 -0.550685542597637621830316 1.101 5.80 -0.464602179413757213934100 -0.464602179413757384094532 0.9292 5.90 -0.373876664830236362535186 -0.373876664830236042617223 0.7478 6.00 -0.279415498198925875709877 -0.279415498198925872811555 0.5588 There's also code which one would expect to compile: lt.d ``` import std.stdio; import decimal; void main () { decimal32 d; if (d < 0) writeln ("< 0"); else writeln ("not < 0"); } ``` $ dmd -g lt.d decimal.git/libdecimal.a decimal/package.d(9404): Error: template decimal.cmp cannot deduce function from argument types !()(uint, int, bool, uint, int, bool), candidates are: decimal/package.d(2574): decimal.cmp(D1, D2)(auto ref const D1 x, auto ref const D2 y) if (isDecimal!(D1, D2)) decimal/package.d(1073): Error: template instance decimal.decimalCmp!(Decimal!32, int) error instantiating lt.d(7): instantiated from here: opCmp!int and also this one: coerce.d ``` import std.stdio; import std.typecons; import decimal; void main () { decimal32 d = "1"; auto p = 4 * d; auto q = d * 4; writeln (typeof(p).stringof); writeln (typeof(q).stringof); } ``` $ dmd -g coerce.d decimal.git/libdecimal.a decimal/package.d(8339): Error: template instance isFloatingpoint!F template 'isFloatingpoint' is not defined, did you mean isFloatingPoint? coerce.d(8): Error: template instance decimal.Decimal!32.Decimal.opBinaryRight!("*", int) error instantiating
Jan 13 2018
On Saturday, 13 January 2018 at 22:51:18 UTC, kdevel wrote:On Saturday, 13 January 2018 at 22:05:02 UTC, rumbu wrote:Can you please tell me on your system what are the values for real.sizeof and real.mant_dig?Now it prints: 1.00 +0.841470984807896506690000 +0.8414709848078965066525023216302990 +2.653e-18My values differ slightly 1.00 0.841470984807896506664591 0.841470984807896506652502 3.653e-18 But I would check this later.Please note the large deltas in case of negative operands. I suspect the conversion to real is wrong for these numbers:-0.996164608835840688668900 1.992 4.90 -0.982452612624332512691275 -0.982452612624332448489147 1.965 5.00 -0.958924274663138469525139 -0.958924274663138468893154 1.918 5.10 -0.925814682327732297803524Forgot to propagate the sign in case of decimal to binary conversion. Corrected.There's also code which one would expect to compile:It compiles now.
Jan 13 2018
On Sunday, 14 January 2018 at 07:20:26 UTC, rumbu wrote:On Saturday, 13 January 2018 at 22:51:18 UTC, kdevel wrote:They are 12 and 64 (-m32) and 16 and 64 (-m64).[...]Can you please tell me on your system what are the values for real.sizeof and real.mant_dig?ACK.[...][...]Forgot to propagate the sign in case of decimal to binary conversion. Corrected.ACK.[...]It compiles now.
Jan 14 2018
On Sunday, 14 January 2018 at 11:44:39 UTC, kdevel wrote:On Sunday, 14 January 2018 at 07:20:26 UTC, rumbu wrote:This is curious. Because the only documented real type with a 64-bit mantissa is the 80-bit Intel Extended Precision format with a unique sizeof of 10 (and not 12 or 16). Actually, real80 is the only type I'm supporting in the library, any other real type is converted to double. This will explain some loss of precision. Do you have more information about the real type on you system, because on mine (Windows), real.sizeof is always 10, irrespective of -m32 or -m64. Mantissa will be easy to extract being 64-bit, but I don't know the exact layout of your real type to extract the exponent.On Saturday, 13 January 2018 at 22:51:18 UTC, kdevel wrote:They are 12 and 64 (-m32) and 16 and 64 (-m64).[...]Can you please tell me on your system what are the values for real.sizeof and real.mant_dig?
Jan 14 2018
On Sunday, 14 January 2018 at 12:35:43 UTC, rumbu wrote:On Sunday, 14 January 2018 at 11:44:39 UTC, kdevel wrote:sizeof returns the in-memory size (at least in C and C++) which is subject to alignment constraints. 32-bit mode typically requires 4-byte aligned access (96 bit = 12 byte) while 64-bit requires 8-byte alignment (128 bit = 16 bytes) for optimal performance. Cf. e.g. p. 28 of "SYSTEM V APPLICATION BINARY INTERFACE Intel386" (long double) http://www.sco.com/developers/devspecs/abi386-4.pdf and p. 12 of "System V Application Binary Interface AMD64 Architecture Processor Supplement" https://www.uclibc.org/docs/psABI-x86_64.pdfOn Sunday, 14 January 2018 at 07:20:26 UTC, rumbu wrote:This is curious. Because the only documented real type with a 64-bit mantissa is the 80-bit Intel Extended Precision format with a unique sizeof of 10 (and not 12 or 16).On Saturday, 13 January 2018 at 22:51:18 UTC, kdevel wrote:They are 12 and 64 (-m32) and 16 and 64 (-m64).[...]Can you please tell me on your system what are the values for real.sizeof and real.mant_dig?Actually, real80 is the only type I'm supporting in the library, any other real type is converted to double. This will explain some loss of precision.Agreed.Do you have more information about the real type on you system, because on mine (Windows), real.sizeof is always 10, irrespective of -m32 or -m64. Mantissa will be easy to extract being 64-bit, but I don't know the exact layout of your real type to extract the exponent.Assumed that your machine has a X86_64 cpu real = long double is the 80-bit extended precision format. I suppose you are running windows and it may be that the Window ABI stores these reals 16-bit (2-byte) aligned. In this case there will be no padding. But I have not found info on this topic.
Jan 14 2018
On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:Source code: https://github.com/rumbu13/decimal/blob/master/src/decimal.d Documentation: http://rumbu13.github.io/decimal/doc/decimal.htmlThis looks really good. I think with a little work it would be ready for proposal into Phobos. I only wish I knew about it two months ago :/
Jan 12 2018