Re: Building (and including libraries) without dub
On Saturday, 26 August 2017 at 09:03:03 UTC, Hasen Judy wrote: What if I want to include a 3rd party library? Surely before dub existed, people were incorporating other libraries in their projects. sometimes pragma("lib", ...) very usefull (if i understand you correctly) https://dlang.org/spec/pragma.html#lib
Re: How to store data when using parallel processing
On Sunday, 27 August 2017 at 01:58:04 UTC, Jonathan M Davis wrote: [...] Thanks Jonathan, that makes sense. As it turns out, the Mutex approach actually makes things slower. In this case I believe trying to use multiple cores isn't worth it. Cheers.
Confusion over enforce and assert - both are compiled out in release mode
In the docs regarding contract programming and the use of enforce / assert: https://dlang.org/library/std/exception/enforce.html it says: "enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program. That is what assert is for. Also, do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because they will be compiled out when compiling with -release. Use assert in contracts." However, I am finding that BOTH enforce and assert are compiled out by dmd and ldc in release mode. Is there a standard way of doing what enforce does inside an "in" contract block that will work in release mode? I'm guessing I should write my own function for now.
Making a repo of downloaded dub package
More than once I have downloaded a DUB package which almost compiles but not quite. The fixes are often so trivial that even the user can do them, and the package starts working. But one may want to create a pull request to fix those issues for others too. Is there any way to make the automatically downloaded dub package into a git repository which acts as if cloned from GitHub before making the changes?
Re: Confusion over enforce and assert - both are compiled out in release mode
On 08/27/2017 12:02 PM, Andrew Chapman wrote: However, I am finding that BOTH enforce and assert are compiled out by dmd and ldc in release mode. Is there a standard way of doing what enforce does inside an "in" contract block that will work in release mode? I'm guessing I should write my own function for now. The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled.
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote: On 08/27/2017 12:02 PM, Andrew Chapman wrote: However, I am finding that BOTH enforce and assert are compiled out by dmd and ldc in release mode. Is there a standard way of doing what enforce does inside an "in" contract block that will work in release mode? I'm guessing I should write my own function for now. The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled. Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful.
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote: On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote: On 08/27/2017 12:02 PM, Andrew Chapman wrote: However, I am finding that BOTH enforce and assert are compiled out by dmd and ldc in release mode. Is there a standard way of doing what enforce does inside an "in" contract block that will work in release mode? I'm guessing I should write my own function for now. The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled. Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful. I actually think even better would be if they acted like array bounds checking -always there by default, in release mode done is @safe code but not in @system. And for none if bounds checking is disabled. That would let users implement custom bounds checking types. Asserts would still be always if in release version, bounds checking would be done by if ... throw.
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote: On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote: On 08/27/2017 12:02 PM, Andrew Chapman wrote: However, I am finding that BOTH enforce and assert are compiled out by dmd and ldc in release mode. Is there a standard way of doing what enforce does inside an "in" contract block that will work in release mode? I'm guessing I should write my own function for now. The whole `in` block is ignored in release mode. Doesn't matter what you put in there. Nothing of it will be compiled. Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful. If you need that, you could compile using ldc in release mode (which you probably want to do anyway): --- test.d --- import std.exception; import std.stdio; void foo(int x) in { enforce(x > 0); } body { } void bar(int x) in { assert(x > 0); } body { } void baz(int x) in { if (!(x > 0)) assert(0); } body { } void main() { (-1).foo.assertThrown; (-1).bar; (-1).baz; } -- $ ldc2 test.d -> failed assert in bar's in contract terminates the program $ ldc2 -release test.d -> failed assertThrown in main terminates the program $ ldc2 -release -enable-contracts test.d -> failed assert in baz's in contract terminates the program $ ldc2 -release -enable-contracts -enable-asserts test.d -> failed assert in bar's in contract terminates the program
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:37:50 UTC, Moritz Maxeiner wrote: On Sunday, 27 August 2017 at 10:17:47 UTC, Andrew Chapman wrote: On Sunday, 27 August 2017 at 10:08:15 UTC, ag0aep6g wrote: [...] Thanks, that explains it. I think it's a bit of a shame that the "in" blocks can't be used in release mode as the clarity they provide for precondition logic is wonderful. If you need that, you could compile using ldc in release mode (which you probably want to do anyway): --- test.d --- import std.exception; import std.stdio; void foo(int x) in { enforce(x > 0); } body { } void bar(int x) in { assert(x > 0); } body { } void baz(int x) in { if (!(x > 0)) assert(0); } body { } void main() { (-1).foo.assertThrown; (-1).bar; (-1).baz; } -- $ ldc2 test.d -> failed assert in bar's in contract terminates the program $ ldc2 -release test.d -> failed assertThrown in main terminates the program $ ldc2 -release -enable-contracts test.d -> failed assert in baz's in contract terminates the program $ ldc2 -release -enable-contracts -enable-asserts test.d -> failed assert in bar's in contract terminates the program Oh interesting. Does DUB support passing through the --enable-contracts flag to ldc? Also, if this is an ldc specific thing it's probably not a good idea i'd imagine, since in the future one may want to use a GDC, or DMD?
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:46:53 UTC, Andrew Chapman wrote: On Sunday, 27 August 2017 at 10:37:50 UTC, Moritz Maxeiner wrote: [...] Oh interesting. Does DUB support passing through the --enable-contracts flag to ldc? Sure, using platform specific build settings [1] such as `"dflags-ldc": ["--enable-contracts"]`. Also, if this is an ldc specific thing it's probably not a good idea i'd imagine, since in the future one may want to use a GDC, or DMD? If you want to use another compiler that supports it, add the appropriate "dflags-COMPILER" setting to your package file. With regards to dmd: Don't use it for release builds, use gdc or ldc (better optimizations). https://code.dlang.org/package-format?lang=json#build-settings
Re: 2 Dimensional Array Sorting
On Saturday, 26 August 2017 at 10:53:03 UTC, Vino.B wrote: On Saturday, 26 August 2017 at 10:45:13 UTC, Vino.B wrote: On Saturday, 26 August 2017 at 10:07:53 UTC, user1234 wrote: [...] Hi, Now there is no duplicate , but the sequence is still not correct [...] Hi, If I execute the script several time's i still get the duplicate entries. From, Vino.B Hi, After analyzing a bit further was able to find that the out data before sorting is like below(4 - 2 dimensional array) hence the sorting is not working, so may i know how do i make this as a single 2 dimensional array like below Required: [["C:\\Temp\\TEAM2\\TEAM\\DIR1", "40"], ["C:\\Temp\\TEAM2\\TEAM\\DIR2", "2228"], ["C:\\Temp\\TEAM3\\EXPORT\\dir2", "61"], ["C:\\Temp\\TEAM2\\PROD_TEAM\\dir1", "35772"], ["C:\\Temp\\TEAM2\\BACKUP\\dir1", "35732"], ["C:\\Temp\\TEAM3\\BACKUP\\dir1", "71465"], ["C:\\Temp\\TEAM2\\EXPORT\\dir2", "30"]] Output: [["C:\\Temp\\TEAM2\\TEAM\\DIR1", "40"], ["C:\\Temp\\TEAM2\\TEAM\\DIR2", "2228"], ["C:\\Temp\\TEAM3\\EXPORT\\dir2", "61"]] - 2darray 1 [["C:\\Temp\\TEAM2\\PROD_TEAM\\dir1", "35772"]] - 2darray 2 [["C:\\Temp\\TEAM2\\BACKUP\\dir1", "35732"], ["C:\\Temp\\TEAM3\\BACKUP\\dir1", "71465"]] - 2darray 3 [["C:\\Temp\\TEAM2\\EXPORT\\dir2", "30"]] - 2darray 4 From, Vino.B
Re: Confusion over enforce and assert - both are compiled out in release mode
On Sunday, 27 August 2017 at 10:46:53 UTC, Andrew Chapman wrote: [...] Oh interesting. Does DUB support passing through the --enable-contracts flag to ldc? Also, if this is an ldc specific thing it's probably not a good idea i'd imagine, since in the future one may want to use a GDC, or DMD? Also, with regards to gdc, its release mode `-frelease` option is explicitly specified in the manual as being shorthand for a specific set of options: This is equivalent to compiling with the following options: gdc -fno-assert -fbounds-check=safe -fno-invariants \ -fno-postconditions -fno-preconditions -fno-switch-errors As it doesn't seem to turn on/off any other options / optimizations, you can use `"dflags-gdc": [...]` to specify your own set of "release" options without losing anything. In particular, I would overwrite dub's default "release" build type [1] and add your own per compiler build settings, so dub won't pass `-frelease` to gdc when using `dub --build=release`. [1] https://code.dlang.org/package-format?lang=json#build-types
Re: 2 Dimensional Array Sorting
On Sunday, 27 August 2017 at 11:53:29 UTC, Vino.B wrote: On Saturday, 26 August 2017 at 10:53:03 UTC, Vino.B wrote: [...] Hi, After analyzing a bit further was able to find that the out data before sorting is like below(4 - 2 dimensional array) hence the sorting is not working, so may i know how do i make this as a single 2 dimensional array like below [...] Hi, Thank you very much, was able to resolve the issue. From, Vino.B
Re: Retrieve the data of all the threads together once all threads are completed in a task pool
On Saturday, 26 August 2017 at 18:26:30 UTC, vino wrote: On Saturday, 26 August 2017 at 17:38:37 UTC, Vino.B wrote: [...] Hi All, Was able to find a solution, but the output writes additional empty lines., request your help on how to print without the empty lines. [...] Hi All, Thank you very much issue resolved.
Re: Getting error in dmd testsuite
On Saturday, 26 August 2017 at 21:59:10 UTC, Thomas Mader wrote: Hello, I am building ldc on Nix (https://nixos.org/nix/) but keep getting an error while running the cppa.d test from the dmd testsuite (https://github.com/ldc-developers/dmd-testsuite). 1588: ... runnable/cppa.d -L-lstdc++ (-g) -O 1588: Test failed. The logged output: 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/bin/ldmd2 -conf= -m64 -Irunnable -L-lstdc++ -od/tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable -of/tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0 runnable/cppa.d /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppb.cpp.o 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0.o: In function `_Dmain': 1588: runnable/cppa.d:(.text._Dmain[_Dmain]+0x49f): undefined reference to `int foo15372(int)' 1588: runnable/cppa.d:(.text._Dmain[_Dmain]+0x4b2): undefined reference to `Foo15802::boo(int)' 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0.o:(.data.rel.ro._D4cppa6C131616__vtblZ[_D4cppa6C131616__vtblZ]+0x0): undefined reference to `C13161::dummyfunc()' 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0.o:(.data.rel.ro._D4cppa4Test6__vtblZ[_D4cppa4Test6__vtblZ]+0x0): undefined reference to `C13161::dummyfunc()' 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0.o:(.data.rel.ro._D4cppa7C13161a6__vtblZ[_D4cppa7C13161a6__vtblZ]+0x0): undefined reference to `C13161a::dummyfunc()' 1588: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa_0.o:(.data.rel.ro._D4cppa5Testa6__vtblZ[_D4cppa5Testa6__vtblZ]+0x0): undefined reference to `C13161a::dummyfunc()' 1588: collect2: error: ld returned 1 exit status 1588: Error: /nix/store/df84hkmhrhx1c2zpvrhmk6aprhlzkasx-gcc-wrapper-6.4.0/bin/gcc failed with status: 1 1588: 1588: 1588: == 1588: Test failed: expected rc == 0, exited with rc == 1 1588: 1588: make[2]: *** [Makefile:335: /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppa.d.out] Error 1 Apart from that all other tests pass. Any ideas? It's running on Linux with gcc 6.4.0. That module tests linking with C++ files, looks like you have some symbols that don't match up. That's weird, because those normally work with gcc. For each of them, use the readelf command from binutils to compare the symbols generated and see how they differ. For example, readelf -sW /tmp/nix-build-ldc-1.3.0.drv-0/build/dmd-testsuite/runnable/cppb.cpp.o |grep foo15372 Then run the same command on the D side, ie for cppa_0.o, and compare the symbols. File a bug on the ldc github if you can't figure it out: https://github.com/ldc-developers/ldc/issues
How to implement Timeout function
Hi, Can I have Timeout function like this one [1] in Ruby? I want to check if a TCP service is running, and the check would return error if timeout occurs. Thanks a lot [1] https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb
Re: How to implement Timeout function
On Sunday, 27 August 2017 at 15:56:14 UTC, Saigon wrote: Hi, Can I have Timeout function like this one [1] in Ruby? I want to check if a TCP service is running, and the check would return error if timeout occurs. Thanks a lot [1] https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb Can it be blocking?
Re: How to implement Timeout function
On Sunday, 27 August 2017 at 15:56:55 UTC, Jerry wrote: On Sunday, 27 August 2017 at 15:56:14 UTC, Saigon wrote: Hi, Can I have Timeout function like this one [1] in Ruby? I want to check if a TCP service is running, and the check would return error if timeout occurs. Thanks a lot [1] https://github.com/ruby/ruby/blob/trunk/lib/timeout.rb Can it be blocking? Yes it can in my case.
Re: No CTFE of function
On Sunday, 27 August 2017 at 00:20:47 UTC, ag0aep6g wrote: On 08/27/2017 01:53 AM, Cecil Ward wrote: On Saturday, 26 August 2017 at 23:49:30 UTC, Cecil Ward wrote: [...] I think I understand, but I'm not sure. I should have explained properly. I suspect what I should have said was that I was expecting an _optimisation_ and I didn't see it. I thought that a specific instance of a call to my pure function that has all compile-time-known arguments would just produce generated code that returned an explicit constant that is worked out by CTFE calculation, replacing the actual code for the general function entirely. So for example auto foo() { return bar( 2, 3 ); } (where bar is strongly pure and completely CTFE-able) should have been replaced by generated x64 code looking exactly literally like auto foo() { return 5; } expect that the returned result would be a fixed-length literal array of 32-but numbers in my case (no dynamic arrays anywhere, these I believe potentially involve RTL calls and the allocator internally). I was expecting this optimisation to 'return literal constant only' because I have seen it before in other cases with GDC. Obviously generating a call that involves running the algorithm at runtime is a performance disaster when it certainly could have all been thrown away in the particular case in point and been replaced by a return of a precomputed value with zero runtime cost. So this is actually an issue with specific compilers, but I was wondering if I have missed anything about any D general rules that make CTFE evaluation practically impossible? I don't know what might prevent the optimization. You can force (actual) CTFE with an enum or static variable. Then you don't have to rely on the optimizer. And the compiler will reject the code if you try something that can't be done at compile time. Example: auto foo() { enum r = bar(2, 3); return r; } Please don't use the term "CTFE" for the optimization. The two are related, of course. The optimizer may literally evaluate functions at compile time. But I think we better reserve the acronym "CTFE" for the guaranteed/forced kind of precomputation, to avoid confusion. Static had already been tried. Failed. Thanks to your tip, I tried enum next. Failed as well, wouldn't compile with GDC. I tried LDC, which did the right thing in all cases. Optimised correctly in every use case to not compute in the generated code, just return the literal compile-time calculated result array by writing a load of immediate values straight to the destination. Hurrah for LDC. Then tried DMD via web-based edit/compile feature at dlang.org website. Refused to compile in the enum case and actually told me why, in a very very cryptic way. I worked out that it has a problem internally (this is a now an assignment into an enum, so I have permission to use the term CTFE now) in that it refuses to do CTFE if any variable is declared using an =void initialiser to stop the wasteful huge pre-fill with zeros which could take half an hour on a large object with slow memory and for all I know play havoc with the cache. So simply deleting the = void fixed the problem with DMD. So that's it. There are unknown random internal factors that prevent CTFE or CTFE-type optimisation. I had wondered if pointers might present a problem. The function in question originally was specced something like pure nothrow @nogc @safe void pure_compute( result_t * p_result, in input_t x ) and just as a test, I tried changing it to result_t pure_compute( in input_t x ) instead. I don't think it makes any difference though. I discovered the DMD -void thing at that point so this was not checked out properly. Your enum tip was very helpful. Ps GDC errors: Another thing that has wasted a load of time is that GDC signals errors on lines where there is a function call that is fine, yet the only problem is in the body of the function that is _being_ called itself, and fixing the function makes the phantom error at the call-site go away. This nasty behaviour has you looking for errors at and before the call-site, or thinking you have the spec of the call args wrong or incorrect types. [Compiler-Explorer problem : I am perhaps blaming GDC unfairly, because I have only ever used it through the telescope that is d.godbolt.org and I am assuming that reports errors on the correct source lines. It doesn't show error message text tho, which is a nightmare, but nothing to do with the compiler obviously.]
Re: No CTFE of function
On Sunday, 27 August 2017 at 17:36:54 UTC, Cecil Ward wrote: On Sunday, 27 August 2017 at 00:20:47 UTC, ag0aep6g wrote: [...] Static had already been tried. Failed. Thanks to your tip, I tried enum next. Failed as well, wouldn't compile with GDC. [...] I wonder if there is anything written up anywhere about what kinds of things are blockers to either CTFE or to successful constant-folding optimisation in particular compilers or in general? Would be useful to know what to stay away from if you really need to make sure that horrendously slow code does not get run at runtime. Sometimes it is possible or even relatively easy to reorganise things and do without certain practices in order to win such a massive reward.
gcd with doubles
Hi, all. Can anybody explain to me why void main() { import std.numeric; assert(gcd(0.5,32) == 0.5); assert(gcd(0.2,32) == 0.2); } fails on the second assert? I'm aware, that calculating gcd on doubles is not so obvios, as on integers. But if the library accepts doubles, and basically the return is correct occasionally, why it is not always the case? Is there a workaround, maybe?
Re: gcd with doubles
ok... googled a little bit. Seems to be the problem of the kind floating poing <--> decimal... Will try to get by with some division and lrint logic, as there is a lack of definition, how to define a gcd in general case. For example with 30 and 0.16. Never mind...
Re: gcd with doubles
On Sunday, 27 August 2017 at 19:47:59 UTC, Alex wrote: Hi, all. Can anybody explain to me why void main() { import std.numeric; assert(gcd(0.5,32) == 0.5); assert(gcd(0.2,32) == 0.2); } fails on the second assert? I'm aware, that calculating gcd on doubles is not so obvios, as on integers. But if the library accepts doubles, and basically the return is correct occasionally, why it is not always the case? If the type isn't a builtin integral and can't be bit shifted, the gcd algorithm falls back to using the Euclidean algorithm in order to support custom number types, so the above gdc in the above reduces to: --- double gcd(double a, double b) { while (b != 0) { auto t = b; b = a % b; a = t; } return a; } --- The issue boils down to the fact that `32 % 0.2` yield `0.2` instead of `0.0`, so the best answer I can give is "because floating points calculations are approximations". I'm actually not sure if this is a bug in fmod or expected behaviour, but I'd tend to the latter. Is there a workaround, maybe? If you know how many digits of precision after the decimal dot you can multiply beforehand, gcd in integer realm, and div afterwards (be warned, the below is only an example implementation for readability, it does not do the required overflow checks for the double -> ulong conversion!): --- import std.traits : isFloatingPoint; T gcd(ubyte precision, T)(T a, T b) if (isFloatingPoint!T) { import std.numeric : _gcd = gcd; immutable T coeff = 10 * precision; return (cast(T) _gcd(cast(ulong) (a * coeff), cast(ulong) (b * coeff))) / coeff; } ---
Re: Comparison of Enumerations with base type of String?
whoa, you can use a struct as a basetype for an enum? I'm guessing it allows you to associate more information with the enum without using lookup tables and the like? And equality is probably just a memberwise comparison of the struct itself? That seems interesting like an interesting idea, although I'm not sure if I'd ever use it. I'm mostly just trying to get a feel for how things work underneath so I have a general understanding of the performance implications of things (in a very general sense). Thanks for the indepth responses, I've learned a few things from them.
Unable to set static data member of a class (results in default value 0)
I have: class DataSignal : Thread { public: static int dataReadDelay; void run() { while (true) { Thread.sleep(dur!"msecs"(dataReadDelay)); // Read in the new file data } } } in main I have: DataSignal.dataReadDelay = 8000; // initialize a bunch of signals Then when each thread is running they sleep for 0 seconds, and I can verify that dataReadDelay is staying at 0. I have initialized it no where else. This seems like a major bug.
Re: Unable to set static data member of a class (results in default value 0)
On Sunday, 27 August 2017 at 22:21:11 UTC, Enjoys Math wrote: static int dataReadDelay; That's thread-local. Use shared to make it shared across all threads, and/or initialize it in the same thread as the use. See: https://dlang.org/migrate-to-shared.html https://tour.dlang.org/tour/en/multithreading/thread-local-storage
Re: Comparison of Enumerations with base type of String?
On Sunday, August 27, 2017 22:01:52 Michael Reiland via Digitalmars-d-learn wrote: > whoa, you can use a struct as a basetype for an enum? I'm > guessing it allows you to associate more information with the > enum without using lookup tables and the like? And equality is > probably just a memberwise comparison of the struct itself? > > That seems interesting like an interesting idea, although I'm not > sure if I'd ever use it. Yeah, you can use pretty much any type as a base type for an enum - though once you're dealing with heap-allocated objects, it gets a bit entertaining, just like it does with enums that are manifest constants. e.g. enum a = [1, 2, 3]; will allocate that array every time that you use the enum. I don't think that mutable or const classes will work, but you can also use immutable classes, which should not result in an allocation every time (since they're immutable, they can be put in the read-only segment by the compiler like with string literals), but using structs almost certainly makes more sense if you really want a user-defined type. Basically, any time you have a group of constants that you want to treat as a group of constants, an enum can make sense, even if those constants are structs. Java implemented enums as classes, so this enables similar capabilities to what you could do with enums in Java. I can't remember if I've ever used a enum with a base type of struct though. Usually, I either need ints or strings. I've definitely used manifest constants that are structs, but actual enums that are structs are not something that I'v frequently found useful, much as I'm glad that it's possible. Ultimately, enums really aren't all that different from anything else with the same base type except that you can't take their address, they're basically copy-pasted wherever they're used (though it's the value that's copy-pasted, not the expression used to create the value - so you wouldn't end up with something like a struct constructor being called), some operations aren't legal on them which are legal on the base type (mostly assignment from non-enums), and anything which explicitly checks that they're an enum may treat them differently. But overall, you'll mostly get out of an enum what you'd expect from the base type. The only caveat that I can think of at the moment with regards to performance is that dynamic arrays (other than strings) result in an allocation every time they're used, which can be surprising if you're not aware of it, and that applies to manifest constants as well as proper enums. Really, manifest constants and proper enums are pretty much the same thing except that proper enums declare an actual type with a known set of values, whereas a manifest constant retains its original type. The performance implications should be the same though. And the fact that they're so similar is part of why the enum keyword was reused, even though that annoys some folks, since a manifest constant isn't really an enum. - Jonathan M Davis
Re: Unable to set static data member of a class (results in default value 0)
On Sunday, August 27, 2017 22:29:46 Adam D. Ruppe via Digitalmars-d-learn wrote: > On Sunday, 27 August 2017 at 22:21:11 UTC, Enjoys Math wrote: > >static int dataReadDelay; > > That's thread-local. Use shared to make it shared across all > threads, and/or initialize it in the same thread as the use. > > > See: > https://dlang.org/migrate-to-shared.html > https://tour.dlang.org/tour/en/multithreading/thread-local-storage Yeah, so the thread with main in it should have the value set, but for every other thread, it would be default-initialized. If you're just looking to set it that one value for all threads and not change it, I'd suggest that you just set it directly and make it immutable - or use enum, so it's a manifest constant. If you want to change it though, you will need to use shared and deal with protecting it appropriately when accessing it. - Jonathan M Davis
Re: gcd with doubles
On Sunday, 27 August 2017 at 19:47:59 UTC, Alex wrote: [..] Is there a workaround, maybe? To expand on the earlier workaround: You can also adapt a floating point to string algorithm in order to dynamically determine an upper bound on the number of after decimal point digits required. Below is an untested adaption of the reference C implementation of errol0[1] for that purpose (MIT license as that is what the original code is under): --- void main() { assert(gcd(0.5, 32) == 0.5); assert(gcd(0.2, 32) == 0.2); assert(gcd(1.3e2, 3e-5) == 1e-5); } template gcd(T) { import std.traits : isFloatingPoint; T gcd(T a, T b) { static if (isFloatingPoint!T) { return fgcd(a, b); } else { import std.numeric : igcd = gcd; return igcd(a, b); } } static if (isFloatingPoint!T) { import std.math : nextUp, nextDown, pow, abs, isFinite; import std.algorithm : max; T fgcd(T a, T b) in { assert (a.isFinite); assert (b.isFinite); assert (a < ulong.max); assert (b < ulong.max); } body { short a_exponent; int a_digitCount = errol0CountOnly(abs(a), a_exponent); short b_exponent; int b_digitCount = errol0CountOnly(abs(b), b_exponent); a_digitCount -= a_exponent; if (a_digitCount < 0) { a_digitCount = 0; } b_digitCount -= b_exponent; if (b_digitCount < 0) { b_digitCount = 0; } auto coeff = pow(10, max(a_digitCount, b_digitCount)); assert (a * coeff < ulong.max); assert (b * coeff < ulong.max); return (cast(T) euclid(cast(ulong) (a * coeff), cast(ulong) (b * coeff))) / coeff; } ulong euclid(ulong a, ulong b) { while (b != 0) { auto t = b; b = a % b; a = t; } return a; } struct HighPrecisionFloatingPoint { T base, offset; void normalize() { T base = this.base; this.base += this.offset; this.offset += base - this.base; } void mul10() { T base = this.base; this.base *= T(10); this.offset *= T(10); T offset = this.base; offset -= base * T(8); offset -= base * T(2); this.offset -= offset; normalize(); } void div10() { T base = this.base; this.base /= T(10); this.offset /= T(10); base -= this.base * T(8); base -= this.base * T(2); this.offset += base / T(10); normalize(); } } alias HP = HighPrecisionFloatingPoint; enum epsilon = T(0.001); ushort errol0CountOnly(T f, out short exponent) { ushort digitCount; T ten = T(1); exponent = 1; auto mid = HP(f, T(0)); while (((mid.base > T(10)) || ((mid.base == T(10)) && (mid.offset >= T(0 && (exponent < 308)) { exponent += 1; mid.div10(); ten /= T(10); } while (((mid.base < T(1)) || ((mid.base == T(1)) && (mid.offset < T(0 && (exponent > -307)) { exponent -= 1; mid.mul10(); ten *= T(10); } auto inhi = HP(mid.base, mid.offset + (nextUp(f) - f) * ten / (T(2) + epsilon)); auto inlo = HP(mid.base, mid.offset + (nextDown(f) - f) * ten / (T(2) + epsilon)); inhi.normalize(); inlo.normalize(); while (inhi.base > T(10) || (inhi.base == T(10) && (inhi.offset >= T(0 { exponent += 1; inhi.div10(); inlo.div10(); } while (inhi.base < T(1) || (inhi.base == T(1) && (inhi.offset < T(0 { exponent -= 1; inhi.mul10(); inlo.mul10(); } while (inhi.base != T(0) || inhi.offset != T(0)) { auto hdig = cast(ubyte) inhi.base; if ((inhi.base == hdig) && (inhi.offset < T(0))) { hdig -= 1; } auto ldig = cast(ubyte) inlo.base; if ((inlo.base == ldig) && (inlo.offset < 0)) { ldig -= 1;
C callbacks getting a value of 0! Bug in D?
Trying to set a callback for portaudio and it's seeing zero for the value passed. Pa_OpenStream(&stream, input, output, sampleRate, cast(ulong)0, cast(PaStreamFlags)(PaStreamFlags.NoFlag + 0*PaStreamFlags.PrimeOutputBuffersUsingStreamCallback), cast(PaStreamCallback)(a,b,c,d,e,f){ callbackCalled = true; return 0; }, null); I am using a debug build of portaudio that prints out all the parameters before anything else, so it's not an issue with portaudio. I've tried passing a normal function: __gshared int sawtooth(const(void)* inputBuffer, void* outputBuffer, ulong framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { return 0; } and passing it as &sawtooth. with the same issue. I've tried changing the calling convention and using __gshared but the value is always 0. It seems other values are 0 too and can't seem to get any value in to the callback(Even a random one). The output essentially always looks like this: Opening Stream! Pa_OpenStream called: PaStream** stream: 0x00823EA0 PaStreamParameters *inputParameters: NULL PaStreamParameters *outputParameters: 0x02C6C1C0 PaDeviceIndex outputParameters->device: 3 int outputParameters->channelCount: 4 PaSampleFormat outputParameters->sampleFormat: 1 PaTime outputParameters->suggestedLatency: 0.135000 void *outputParameters->hostApiSpecificStreamInfo: 0x double sampleRate: 44100 unsigned long framesPerBuffer: 256 PaStreamFlags streamFlags: 0x0 PaStreamCallback *streamCallback: 0x void *userData: 0x Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 1 Pa_GetSampleSize returned: int: 4 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_GetSampleSize called: PaSampleFormat format: 8 Pa_GetSampleSize returned: int: 2 Pa_OpenStream returned: *(PaStream** stream): 0x03BEAD50 PaError: 0 ( Success ) everything seems correct except: PaStreamCallback *streamCallback: 0x void *userData: 0x You can find the full code at https://forum.dlang.org/thread/lkbswgpsgxynhfyzw...@forum.dlang.org This is either a bug in D, an issue with calling conventions, or how one passes the data. The original portaudio open stream function, so you can see that it simply prints it's arguments: PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ) { PaError result; PaUtilHostApiRepresentation *hostApi = 0; PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice; PaStreamParameters hostApiInputParameters, hostApiOutputParameters; PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr; #ifdef PA_LOG_API_CALLS PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" ); PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream )); if( inputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters )); PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device )); PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount )); PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat )); PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency )); PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo )); } if( outputParameters == NULL ){ PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" )); }else{ PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters )); PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device )); PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount ));
Re: C callbacks getting a value of 0! Bug in D?
Looking at the assembly shows something like this: 0041ea98 push 0x0 0041ea9a push 0x0 0041ea9c push 0x0 0041ea9e push dword 0x100 0041eaa3 mov ecx, [typeid(PaStreamParameters)+0xe36fc (0x80d4cc)] 0041eaa9 mov eax, [fs:0x2c] 0041eaaf mov edx, [eax+ecx*4] 0041eab2 push dword [edx+0x1c] 0041eab8 push dword [edx+0x18] 0041eabe push dword [ebp-0x54] 0041eac1 push dword [ebp-0x5c] 0041eac4 mov ebx, PA.stream (0x823f30) 0041eac9 push ebx 0041eaca call dword near [Pa_OpenStream (0x823f18)] I noticed that those 0's were the values being fed in to the function. I remember converting c_ulong's to ulong's and that they were probably uint's in D. Converting those fixed the problem and the callback is now called! I converted all the ulongs to uint's but there were a few longs and I don't know if they are c_longs or d_longs... Anyways, At least I'm on the right track.
Re: No CTFE of function
On Sunday, 27 August 2017 at 17:47:54 UTC, Cecil Ward wrote: I wonder if there is anything written up anywhere about what kinds of things are blockers to either CTFE or to successful constant-folding optimisation in particular compilers or in general? Would be useful to know what to stay away from if you really need to make sure that horrendously slow code does not get run at runtime. Sometimes it is possible or even relatively easy to reorganise things and do without certain practices in order to win such a massive reward. The rules for CTFE are outlined in the docs [1]. What is described there is all there is to it. If those criteria are not met, the function cannot be executed at compile time. More importantly, as mentioned earlier in the thread, CTFE will only occur if a function *must* be executed at compile time, i.e. it is in a context where the result of the function is required at compile-time. An enum declaration is such a situation, a variable initialization is not. There are also a couple of posts on the D Blog. Stefan has written about the new CTFE engine [1] and I posted something showing a compile-time sort. These illustrate the points laid out in the documentation. As for compiler optimizations, there are some basic optimizations that will be common across all compilers, and you can google for compiler optimizations to find such generalities. Many of these apply across languages, and those specific to the C-family languages will likely be found in D compilers. Beyond that, I'm unaware of any documentation that outlines optimizations in D compilers. [1] https://dlang.org/spec/function.html#interpretation [2] https://dlang.org/blog/2017/04/10/the-new-ctfe-engine/ [3] https://dlang.org/blog/2017/06/05/compile-time-sort-in-d/
Re: How do I create a fileWatcher with an onFileChange event using spawn?
On 2017-08-25 23:25, Enjoys Math wrote: Something like this: module file_watcher; import std.concurrency; import std.file; import std.signals; import std.datetime; void fileWatcher(Tid tid, string filename, int loopSleep) { auto modified0 = timeLastModified(filename); while (true) { modified = timeLastModified(filename); if (modified > modified0) { modified0 = modified; //if (onFileChange !is null) // onFileChange(receiver); } sleep(dur!"msecs"(loopSleep)); } } But I'm not sure how to send the onFiledChange event. A delegate perhaps? Or you can look at any of the existing event driven libraries that do this: http://code.dlang.org/packages/vibe-core http://code.dlang.org/packages/libasync -- /Jacob Carlborg
Re: How do I create a fileWatcher with an onFileChange event using spawn?
On Monday, 28 August 2017 at 06:27:20 UTC, Jacob Carlborg wrote: On 2017-08-25 23:25, Enjoys Math wrote: Something like this: module file_watcher; import std.concurrency; import std.file; import std.signals; import std.datetime; void fileWatcher(Tid tid, string filename, int loopSleep) { auto modified0 = timeLastModified(filename); while (true) { modified = timeLastModified(filename); if (modified > modified0) { modified0 = modified; //if (onFileChange !is null) // onFileChange(receiver); } sleep(dur!"msecs"(loopSleep)); } } But I'm not sure how to send the onFiledChange event. A delegate perhaps? Or you can look at any of the existing event driven libraries that do this: http://code.dlang.org/packages/vibe-core http://code.dlang.org/packages/libasync In addition, to avoid polling, it's possible to register yourself to the operating system so it will tell you when a modification on the given file has happened: https://msdn.microsoft.com/en-us/library/aa364417%28VS.85%29.aspx?f=255&MSPPError=-2147217396 http://man7.org/linux/man-pages/man7/inotify.7.html