Re: A Friendly Challenge for D

2018-10-16 Thread Jabari Zakiya via Digitalmars-d

On Tuesday, 16 October 2018 at 21:12:39 UTC, welkam wrote:
On Tuesday, 16 October 2018 at 20:58:54 UTC, Jabari Zakiya 
wrote:
And they could be modded to catch semantics like this and 
produce faster code.


Its hard to prove that you will only write 1 or 0 in the array 
and even if you write such pass it wont fire very often. So 
slower compile times for no gain in common case.



My guess is the difference in code execution times based on 
the ALU operation pipeline.



and my guess is that CPU knows that its going to write the same 
value to memory so it ignores that write.


Exactly. It does the same instruction twice, and once it's set 
the first time it can ignore setting it the second time.


However with seg[k] = 1 , the mov instruction always moves, 
because it doesn't know|care what the previous value was. That's 
my guess.


Life is too short for such things. Today compilers are good at 
optimizing low level stuff. Those decades of improvements add 
up.


Amen! :-)



Re: A Friendly Challenge for D

2018-10-16 Thread welkam via Digitalmars-d

On Tuesday, 16 October 2018 at 20:58:54 UTC, Jabari Zakiya wrote:
And they could be modded to catch semantics like this and 
produce faster code.


Its hard to prove that you will only write 1 or 0 in the array 
and even if you write such pass it wont fire very often. So 
slower compile times for no gain in common case.



My guess is the difference in code execution times based on the 
ALU operation pipeline.



and my guess is that CPU knows that its going to write the same 
value to memory so it ignores that write.


I used to know most of these tricks back in the Pentium days, 
but I haven't had a need to keep up with Intel Ixx core chips 
machine|compiler > level instruction optimizations.


Life is too short for such things. Today compilers are good at 
optimizing low level stuff. Those decades of improvements add up.


Re: A Friendly Challenge for D

2018-10-16 Thread Jabari Zakiya via Digitalmars-d

On Tuesday, 16 October 2018 at 20:38:24 UTC, welkam wrote:
On Tuesday, 16 October 2018 at 17:57:23 UTC, Jabari Zakiya 
wrote:
This is the exact same behavior I found with the Nim compiler 
too.


Well Nim compiler is more like translator. It translates Nim 
code to c or c++. Since gcc was responsible for optimizations 
and instruction selection it would be more correct to say that 
gcc behavior was same as llvm.




How many other unknown gotchas are in the compilers? :-(


the number of inlining shall be 3
https://www.youtube.com/watch?v=s4wnuiCwTGU


Yes, it finally is the compiler doing it, and Clang does the same 
thing.
And they could be modded to catch semantics like this and produce 
faster code.


My guess is the difference in code execution times based on the 
ALU operation pipeline.


seg[k] = seg[k] | 1

can be done "inplace" in the pipeline, where the lsb can to be 
changed in mem, whereas


seg[k] = 1

may require a separate constant|value creation and memory write, 
and bypass the ALU.


I used to know most of these tricks back in the Pentium days, but 
I haven't had a need to keep up with Intel Ixx core chips 
machine|compiler level instruction optimizations.




Re: A Friendly Challenge for D

2018-10-16 Thread welkam via Digitalmars-d

On Tuesday, 16 October 2018 at 17:57:23 UTC, Jabari Zakiya wrote:
This is the exact same behavior I found with the Nim compiler 
too.


Well Nim compiler is more like translator. It translates Nim code 
to c or c++. Since gcc was responsible for optimizations and 
instruction selection it would be more correct to say that gcc 
behavior was same as llvm.




How many other unknown gotchas are in the compilers? :-(


the number of inlining shall be 3
https://www.youtube.com/watch?v=s4wnuiCwTGU




Re: A Friendly Challenge for D

2018-10-16 Thread Jabari Zakiya via Digitalmars-d

On Tuesday, 16 October 2018 at 07:09:05 UTC, Vijay Nayar wrote:

On Monday, 15 October 2018 at 22:17:57 UTC, Jabari Zakiya wrote:
$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is 
largely due to slightly better optimization from the LLVM 
based ldc2 compiler, where I believe Nim is using gcc.


Here's what I get on my system.

$ echo 3_000_000_000 | ./twinprimes_test7yc.0180.gcc821
Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.144 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.144 secs


Hey Vijay I found subtle static typing errors.

When N < 2^32 - 1 (4,294,967,295) the twimprime count and 
lastprime values are correct.

When N > 2^32 - 1 both values start to be incorrect.

Examples: For N = 4,000,000,000 you get correct answers

$ echo 40 | ./twinprimes_ssoz
Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 233766231; resgroups = 1731602
each 135 threads has nextp[2 x 6332] array
setup time = 667 μs and 5 hnsecs
perform twinprimes ssoz sieve
sieve time = 181 ms, 277 μs, and 6 hnsecs
last segment = 27666 resgroups; segment slices = 27
total twins = 11944438; last twin = 399798+/- 1
total time = 181 ms, 945 μs, and 1 hnsec

Examples: For N = 5,000,000,000 you get wrong answers

$ echo 50 | ./twinprimes_ssoz
Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 292207792; resgroups = 2164503
each 135 threads has nextp[2 x 6999] array
setup time = 744 μs and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 225 ms, 323 μs, and 4 hnsecs
last segment = 1815 resgroups; segment slices = 34
total twins = 14618173; last twin = 705034592+/- 1
total time = 226 ms, 68 μs, and 1 hnse

These are correct answers for N = 5,000,000,000

$ echo 50 | ./twinprimes_test7yc.0180.gcc821
Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 292207792; resgroups = 2164503
each 135 threads has nextp[2 x 6999] array
setup time = 0.001 secs
perform twinprimes ssoz sieve
sieve time = 0.237 secs
last segment = 1815 resgroups; segment slices = 34
total twins = 14618166; last twin = 499860+/-1
total time = 0.237 secs

The first easy check should show the lastprime value just a 
little smaller than N.
See the timing|results table I posted earlier to see correct 
outputs as N gets bigger.


It took me a looong time, and was a big PITA, to get the correct 
static typing too in Nim, especially coming from a dynamic 
language like Ruby.




Re: A Friendly Challenge for D

2018-10-16 Thread Jabari Zakiya via Digitalmars-d

On Tuesday, 16 October 2018 at 16:57:12 UTC, welkam wrote:
So I run profiler and 97% of time is spent in void twinsSieve 
function and hotspots are seg[k] = seg[k] |  1; lines. Since 
seg[k] can only be 1 or 0 I removed that or operation. And the 
results are. Queue the drum-roll... 5% slower.


I thought that all of my studying was getting somewhere. That I 
beginning to understand things but no. Performing OR operation 
and then storing data is faster than just storing data. 
[sarcasm] Of course it makes sense [/sarcasm]


I looked at assembler and nothing changed except

orb$0x1,(%rbx,%rdi,1)

is changed to

movb   $0x1,(%rbx,%rdi,1)

I`m completely lost.


This is the exact same behavior I found with the Nim compiler too.

seg[k] = 1  is slower than seg[k] = seg[k] or 1, which is why 
it's coded like that.


Thanks for finding the exact instruction difference.

How many other unknown gotchas are in the compilers? :-(



Re: A Friendly Challenge for D

2018-10-16 Thread Jon Degenhardt via Digitalmars-d

On Tuesday, 16 October 2018 at 07:09:05 UTC, Vijay Nayar wrote:
D has multiple compilers, but for the speed of the finished 
binary, LDC2 is generally recommended.  I used version 1.11.0.  
https://github.com/ldc-developers/ldc/releases/tag/v1.11.0


I was using DUB to manage the project, but to build the 
stand-alone file from the gist link, use this command:  $ ldc2 
-release -O3 twinprimes_ssoz.d

And to run it:  $ echo "30" | ./twinprimes_ssoz


It'd be interesting to see if LTO or PGO generated an 
improvement. It looks like it could in this case, as it might 
optimize some of the inner loops. LTO is easy, enable it with:


-flto= -defaultlib=phobos2-ldc-lto,druntime-ldc-lto

(see: https://github.com/ldc-developers/ldc/releases/tag/v1.9.0). 
I've been using 'thin' on OSX, 'full' on Linux.


PGO is a bit more work, but not too bad. A good primer is here: 
https://johanengelen.github.io/ldc/2016/07/15/Profile-Guided-Optimization-with-LDC.html


--Jon




Re: A Friendly Challenge for D

2018-10-16 Thread welkam via Digitalmars-d
So I run profiler and 97% of time is spent in void twinsSieve 
function and hotspots are seg[k] = seg[k] |  1; lines. Since 
seg[k] can only be 1 or 0 I removed that or operation. And the 
results are. Queue the drum-roll... 5% slower.


I thought that all of my studying was getting somewhere. That I 
beginning to understand things but no. Performing OR operation 
and then storing data is faster than just storing data. [sarcasm] 
Of course it makes sense [/sarcasm]


I looked at assembler and nothing changed except

orb$0x1,(%rbx,%rdi,1)

is changed to

movb   $0x1,(%rbx,%rdi,1)

I`m completely lost.


Re: A Friendly Challenge for D

2018-10-16 Thread Vijay Nayar via Digitalmars-d

On Monday, 15 October 2018 at 22:17:57 UTC, Jabari Zakiya wrote:
$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is 
largely due to slightly better optimization from the LLVM 
based ldc2 compiler, where I believe Nim is using gcc.


Here's what I get on my system.

$ echo 3_000_000_000 | ./twinprimes_test7yc.0180.gcc821
Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.144 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.144 secs

Could you list your hardware, D ver, compiler specs.

I will run your code on my system with your D version and 
compiler, if I can.


Excellent work!


D has multiple compilers, but for the speed of the finished 
binary, LDC2 is generally recommended.  I used version 1.11.0.  
https://github.com/ldc-developers/ldc/releases/tag/v1.11.0


I was using DUB to manage the project, but to build the 
stand-alone file from the gist link, use this command:  $ ldc2 
-release -O3 twinprimes_ssoz.d

And to run it:  $ echo "30" | ./twinprimes_ssoz

Running the program a bunch of times, I get variable results, 
mostly between 195ms and 250ms.  Running the Nim version, I also 
get variable results, mostly between 230ms and 280ms.


My system is an Alienware 14x R2 from 2012.  Specs can be found 
here: 
https://www.cnet.com/products/alienware-m14xr2-14-core-i7-3630qm-8-gb-ram-750-gb-hdd/specs/


Re: A Friendly Challenge for D

2018-10-15 Thread Jabari Zakiya via Digitalmars-d
$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is 
largely due to slightly better optimization from the LLVM based 
ldc2 compiler, where I believe Nim is using gcc.


Here's what I get on my system.

$ echo 3_000_000_000 | ./twinprimes_test7yc.0180.gcc821
Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.144 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.144 secs

Could you list your hardware, D ver, compiler specs.

I will run your code on my system with your D version and 
compiler, if I can.


Excellent work!



Re: A Friendly Challenge for D

2018-10-15 Thread Jabari Zakiya via Digitalmars-d
I don't actually understand the underlying algorithm, but I at 
least understand the flow of the program and the structure.  
The algorithm utilized depends heavily on using shared memory 
access, which can be done in D, but I definitely wouldn't call 
it idiomatic.  In D, message passing is preferred, but it 
really can't be well demonstrated on your algorithm without a 
deeper understanding of the algorithm itself.


A complete working version can be found at: 
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


I modified both versions of the program to utilize the 
pgParameters13 for more of an apples-to-apples comparison.


The final results are as follows:
$ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim 
&& echo "30" | ./twinprimes_ssoz

Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.222 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.223 secs

$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is 
largely due to slightly better optimization from the LLVM based 
ldc2 compiler, where I believe Nim is using gcc.


Hey Great!  I'll take some time and study your code.

Nim currently allows using gcc or clang: --cc:gcc or --cc:clang, 
and

compiles to C: nim c --cc:gcc... or C++: nim c++ --cc:gcc...

You can compile in Nim with/out using garbage collection (GC) and 
choose GC.
This version needs GC to recover mem created in each thread, or 
it will eat
it up. See operation of program using htop/top to see threads|mem 
at work.


If D has a fast bitarray structure, try it to create the data 
arrays
"prms" in proc "sozpg" and "seg" arrays is "twin_sieves". This 
could allow
for larger segment sizes|arrays that fit into cpu cache, reducing 
the number
of segment slices to process. This would all have to be profiled 
and
encapsulated in "selectPG", which adaptively selects to best PG 
to use.


Here is a table of output data and performance times (in seconds).

The results were produced on a System76 laptop with an Intel I7 
6700HQ cpu,
2.6-3.5 GHz clock, with 8 threads, and 16GB of memory. I compiled 
the file
"twinprimes_ssoz.nim" with Nim versions 0.18.0, and the just 
released 0.19.0,
using gcc 8.2.1 with Manjaro (Linux) in Virtual Box. I then ran 
the executables
on my host Linux system (which only has gcc-4.9.8) to use all 8 
threads.


The output was produced on a "quiet" system, where I turned off 
the laptop and
rebooted, and ran tests with only a terminal and spreedsheet open 
(to record

results). The times are the "best" times from multiple runs.

I also compare times from the program "primesieve" - 
https://primesieve.org/

which states on its site:


primesieve is a free software program and C/C++ library that 
generates primes using a highly optimized sieve of Eratosthenes 
implementation. It counts the primes below 10^10 in just 0.45 
seconds on an Intel Core i7-6700 CPU (4 x 3.4 GHz). primesieve 
can generate primes and prime k‑tuplets up to 2^64.



(An optimized C/C++ versions of twinprimes_ssoz would be nice to 
compare against too.)



  Number  | Twimprimes | Last Twinprime |twinprime_ssoz.nim, 
gcc-8.2.1| primesieve |
  ||| 0.18.0   |
0.19.0|   9.7.1|

--|||--|--||
1 x 10^09 |3424506 | 199872 |  0.043   |  
0.041   | 0.049  |

--|||--|--||
5 x 10^09 |   14618166 | 499860 |  0.219   |  
0.226   | 0.248  |

--|||--|--||
1 x 10^10 |   27412679 | 999702 |  0.398   |  
0.401   | 0.533  |

--|||--|--||
5 x 10^10 |  118903682 |4999590 |  2.364   |  
2.331   | 2.978  |

--|||--|--||
1 x 10^11 |  224376048 |762 |  4.5

Re: A Friendly Challenge for D

2018-10-15 Thread Vijay Nayar via Digitalmars-d

On Sunday, 14 October 2018 at 10:51:11 UTC, Vijay Nayar wrote:
Once I get the bugs out, I'm curious to see if any performance 
differences crop up.  There's the theory that says they should 
be the same, and then there's the practice.


I don't actually understand the underlying algorithm, but I at 
least understand the flow of the program and the structure.  The 
algorithm utilized depends heavily on using shared memory access, 
which can be done in D, but I definitely wouldn't call it 
idiomatic.  In D, message passing is preferred, but it really 
can't be well demonstrated on your algorithm without a deeper 
understanding of the algorithm itself.


A complete working version can be found at: 
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


I modified both versions of the program to utilize the 
pgParameters13 for more of an apples-to-apples comparison.


The final results are as follows:
$ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim && 
echo "30" | ./twinprimes_ssoz

Enter integer number: threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 0.000 secs
perform twinprimes ssoz sieve
sieve time = 0.222 secs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/-1
total time = 0.223 secs

$ dub build --compiler=ldc2 -b=release && echo "30" | 
./twinprimes

Enter integer number:
threads = 8
each thread segment is [1 x 65536] bytes array
twinprime candidates = 175324676; resgroups = 1298702
each 135 threads has nextp[2 x 5566] array
setup time = 1 ms, 864 μs, and 7 hnsecs
perform twinprimes ssoz sieve
sieve time = 196 ms, 566 μs, and 5 hnsecs
last segment = 53518 resgroups; segment slices = 20
total twins = 9210144; last twin = 299712+/- 1
total time = 198 ms, 431 μs, and 2 hnsecs

My understanding is that the difference in performance is largely 
due to slightly better optimization from the LLVM based ldc2 
compiler, where I believe Nim is using gcc.




Re: A Friendly Challenge for D

2018-10-14 Thread Bastiaan Veelo via Digitalmars-d

On Sunday, 14 October 2018 at 10:51:11 UTC, Vijay Nayar wrote:
But as previous posters have said, the code is not really very 
different between Nim and D.  Most of it is array manipulation 
and arithmetic operations, and not many of the features of 
either D or Nim are very different.  Both turn into fast code, 
both have garbage collection, and both have generally similar 
operators and libraries for this kind of problem.


The biggest differences I observed revolved not around the 
languages themselves, but around code style.


Are you aware of DCompute? [1] I haven’t used it myself but since 
Jabari explicitly mentioned taking advantage of the GPU, it may 
be worth giving it a try. It should have an impact on performance 
and possibly on style as well, even though it will still be D. It 
would be nice if Nicholas could chime in on this thread.


Bastiaan.

[1] 
https://dlang.org/blog/2017/10/30/d-compute-running-d-on-the-gpu/


Re: A Friendly Challenge for D

2018-10-14 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 19:04:48 UTC, Jabari Zakiya wrote:

On Saturday, 13 October 2018 at 18:31:57 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar 
wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code 
is working correctly, and that the compiler is choking 
either/and because of a hard time limit and/or memory limit. 
That's why I put in a compiler output statement in 
'genPGparameters' to see the progression of the PG 
parameters being built by the compiler to initially find 
when the compiler started choking. You may also need to 
patch whatever facility in the D compiler chain that 
controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits 
exist for the D compiler at compile-time, so I may need to do 
some homework.


It's not just DMD either.

$ ldc2 twinprimes_ssoz.d
...
generating parameters for P17
Killed

$ gdc twinprimes_ssoz.d
...
generating parameters for P17
gdc: internal compiler error: Killed (program cc1d)
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.

$ dmd twinprimes_ssoz.d
...
generating parameters for P17
Killed


In the Nim code, starting line 91 is when the PG constants are 
being generate at compile time.


-
# Generate at compile time the parameters for PGs P5-P17.
const parametersp5  = genPGparameters(5)
const parametersp7  = genPGparameters(7)
const parametersp11 = genPGparameters(11)
const parametersp13 = genPGparameters(13)
const parametersp17 = genPGparameters(17)
-

Can it compile just using P5 (the first line, others commented 
out), and then P7, etc?


I'm not understanding your comments now.

If you can get a working version up and running (with correct 
output) we can solve the P17 compiler issues later (or in a 
parallel forum thread), especially if you have to delve into 
the weeds of the compiler chain.


In my mind (same with Nim process) getting working code using 
any PG is first order priority (because you'll need getting 
multi-threading working too). Once you can do that, by default, 
you can then use any generator you want if you create the 
correct parameters for it. That's one of the advantages of the 
algorithm, it's PG agnostic (as long as your hardware will 
accommodate it).


So don't prioritize getting P17 to compile right now (in this 
thread). Create the working generic structure that can work 
with any PG first.


Updated:  
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


I still get a few runtime errors likely from mistakes in my 
conversion for certain primes.  I'll resolve those after I get 
back from the gym.


But as previous posters have said, the code is not really very 
different between Nim and D.  Most of it is array manipulation 
and arithmetic operations, and not many of the features of either 
D or Nim are very different.  Both turn into fast code, both have 
garbage collection, and both have generally similar operators and 
libraries for this kind of problem.


The biggest differences I observed revolved not around the 
languages themselves, but around code style.  For example, can 
you put a loop and 3 additional statements on a single line in D? 
 Yes.  But it is considered to be not very readable code from a 
style perspective.


Once I get the bugs out, I'm curious to see if any performance 
differences crop up.  There's the theory that says they should be 
the same, and then there's the practice.


Re: A Friendly Challenge for D

2018-10-13 Thread Jabari Zakiya via Digitalmars-d

On Saturday, 13 October 2018 at 18:31:57 UTC, Vijay Nayar wrote:

On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code 
is working correctly, and that the compiler is choking 
either/and because of a hard time limit and/or memory limit. 
That's why I put in a compiler output statement in 
'genPGparameters' to see the progression of the PG parameters 
being built by the compiler to initially find when the 
compiler started choking. You may also need to patch whatever 
facility in the D compiler chain that controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits 
exist for the D compiler at compile-time, so I may need to do 
some homework.


It's not just DMD either.

$ ldc2 twinprimes_ssoz.d
...
generating parameters for P17
Killed

$ gdc twinprimes_ssoz.d
...
generating parameters for P17
gdc: internal compiler error: Killed (program cc1d)
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.

$ dmd twinprimes_ssoz.d
...
generating parameters for P17
Killed


In the Nim code, starting line 91 is when the PG constants are 
being generate at compile time.


-
# Generate at compile time the parameters for PGs P5-P17.
const parametersp5  = genPGparameters(5)
const parametersp7  = genPGparameters(7)
const parametersp11 = genPGparameters(11)
const parametersp13 = genPGparameters(13)
const parametersp17 = genPGparameters(17)
-

Can it compile just using P5 (the first line, others commented 
out), and then P7, etc?


I'm not understanding your comments now.

If you can get a working version up and running (with correct 
output) we can solve the P17 compiler issues later (or in a 
parallel forum thread), especially if you have to delve into the 
weeds of the compiler chain.


In my mind (same with Nim process) getting working code using any 
PG is first order priority (because you'll need getting 
multi-threading working too). Once you can do that, by default, 
you can then use any generator you want if you create the correct 
parameters for it. That's one of the advantages of the algorithm, 
it's PG agnostic (as long as your hardware will accommodate it).


So don't prioritize getting P17 to compile right now (in this 
thread). Create the working generic structure that can work with 
any PG first.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code is 
working correctly, and that the compiler is choking either/and 
because of a hard time limit and/or memory limit. That's why I 
put in a compiler output statement in 'genPGparameters' to see 
the progression of the PG parameters being built by the 
compiler to initially find when the compiler started choking. 
You may also need to patch whatever facility in the D compiler 
chain that controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits exist 
for the D compiler at compile-time, so I may need to do some 
homework.


It's not just DMD either.

$ ldc2 twinprimes_ssoz.d
...
generating parameters for P17
Killed

$ gdc twinprimes_ssoz.d
...
generating parameters for P17
gdc: internal compiler error: Killed (program cc1d)
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.

$ dmd twinprimes_ssoz.d
...
generating parameters for P17
Killed



Re: A Friendly Challenge for D

2018-10-13 Thread Jabari Zakiya via Digitalmars-d

On Saturday, 13 October 2018 at 18:14:20 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya 
wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants 
as the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code is 
working correctly, and that the compiler is choking either/and 
because of a hard time limit and/or memory limit. That's why I 
put in a compiler output statement in 'genPGparameters' to see 
the progression of the PG parameters being built by the 
compiler to initially find when the compiler started choking. 
You may also need to patch whatever facility in the D compiler 
chain that controls this too.


It's P17, the biggest one that takes the longest to build in 
the Nim version. I actually don't know what memory limits exist 
for the D compiler at compile-time, so I may need to do some

homework.


Yes, that's what I figured, because that's when the Nim compiler 
initially balked. The variable that was patched in the Nim 
configg file set a hard limit on number of operations the 
compiler could do. It's used as a break switch on a runaway 
process (infinite loop, etc). It's probably something like that 
in the D compiler too, just guessing offhand. I hope it isn't a 
memory limit. However, the program will run fine without using 
P17. It's currently selected as the optimum PG for inputs greater 
than 15 trillion (15,000,000,000,000), so the program will run 
fine and produce correct output using P13 instead, but just not 
as fast.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 18:05:45 UTC, Jabari Zakiya wrote:


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants as 
the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, 
etc) to see where it fails. That will let you know the code is 
working correctly, and that the compiler is choking either/and 
because of a hard time limit and/or memory limit. That's why I 
put in a compiler output statement in 'genPGparameters' to see 
the progression of the PG parameters being built by the 
compiler to initially find when the compiler started choking. 
You may also need to patch whatever facility in the D compiler 
chain that controls this too.


It's P17, the biggest one that takes the longest to build in the 
Nim version. I actually don't know what memory limits exist for 
the D compiler at compile-time, so I may need to do some homework.


Re: A Friendly Challenge for D

2018-10-13 Thread Jabari Zakiya via Digitalmars-d

On Saturday, 13 October 2018 at 17:36:33 UTC, Vijay Nayar wrote:

On Saturday, 13 October 2018 at 15:50:06 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 15:19:07 UTC, Jabari Zakiya 
wrote:

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:
On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar 
wrote:

[...]


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 
'import algorithm' directive. The file is now fixed to 
include it. Download the corrected version or patch your file 
accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in 
this version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 
Billion or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly 
advisable) the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give 
reference times to compare against.


Ok, now it builds.  I was previously following the build 
instructions from the Nim website and am not super clear what 
the "koch" tool does, but following your instructions, the 
program does build and run.  I'll take a stab at making a D 
version.


Interesting results so far.  I have a partially converted 
program here:  
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


The interesting part is that during compilation (with the 
command "dmd twinprimes_ssoz.d"), the compilation will abort 
with the message "Killed" and no further information. That's a 
new one for me, so I'm looking into the cause.


It may be also running into a hard time limit imposed on 
compilation that Nim had/has that prevented my code from 
initially compiling. I'm generating a lot of PG parameter 
constants at compile time, and it's doing a lot of number 
crunching and building larger and larger arrays of constants as 
the PG's get larger.


Try compiling with successive PG's (just P5, then P5 and P7, etc) 
to see where it fails. That will let you know the code is working 
correctly, and that the compiler is choking either/and because of 
a hard time limit and/or memory limit. That's why I put in a 
compiler output statement in 'genPGparameters' to see the 
progression of the PG parameters being built by the compiler to 
initially find when the compiler started choking. You may also 
need to patch whatever facility in the D compiler chain that 
controls this too.




Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 15:50:06 UTC, Vijay Nayar wrote:
On Saturday, 13 October 2018 at 15:19:07 UTC, Jabari Zakiya 
wrote:

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:
On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar 
wrote:

[...]


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 
'import algorithm' directive. The file is now fixed to include 
it. Download the corrected version or patch your file 
accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in 
this version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 
Billion or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly advisable) 
the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give reference 
times to compare against.


Ok, now it builds.  I was previously following the build 
instructions from the Nim website and am not super clear what 
the "koch" tool does, but following your instructions, the 
program does build and run.  I'll take a stab at making a D 
version.


Interesting results so far.  I have a partially converted program 
here:  
https://gist.github.com/vnayar/79e2d0a9850833b8859dd9f08997b4d7


The interesting part is that during compilation (with the command 
"dmd twinprimes_ssoz.d"), the compilation will abort with the 
message "Killed" and no further information. That's a new one for 
me, so I'm looking into the cause.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 15:19:07 UTC, Jabari Zakiya wrote:

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:
On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar 
wrote:

[...]


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 
'import algorithm' directive. The file is now fixed to include 
it. Download the corrected version or patch your file 
accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in 
this version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 Billion 
or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly advisable) 
the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give reference 
times to compare against.


Ok, now it builds.  I was previously following the build 
instructions from the Nim website and am not super clear what the 
"koch" tool does, but following your instructions, the program 
does build and run.  I'll take a stab at making a D version.


Re: A Friendly Challenge for D

2018-10-13 Thread Jabari Zakiya via Digitalmars-d

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:

On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar wrote:


I downloaded the reference NIM implementation and got the 
latest nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to 
fix that?


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


My mistake. I updated the file and forgot to include the 'import 
algorithm' directive. The file is now fixed to include it. 
Download the corrected version or patch your file accordingly.


As stated in the file intro **YOU MUST DO THIS** to get it to 
compile with current Nim (they were supposed to fix this in this 
version 0.19.0 but didn't).


 To compile for nim versions <= 0.19.0 do following:
 1) in file: ~/nim-0.19.0/compiler/vmdef.nim
 2) set variable: MaxLoopIterations* = 1_000_000_000 (1 Billion 
or >)

 3) then rebuild sysem: ./koch boot -d:release

If you are using 'choosenim' to install Nim (highly advisable) 
the full path is:


 ~/.choosenim/toolchains/nim-0.19.0/compiler/vmdef.nim

I'll post performance results from my laptop to give reference 
times to compare against.


Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Saturday, 13 October 2018 at 14:32:33 UTC, welkam wrote:

On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar wrote:


I downloaded the reference NIM implementation and got the 
latest nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to 
fix that?


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations


I ran into the same problem as you did, and then followed the 
instructions from the error.  I modified the compiler source and 
increased the number of maximum iterations from 3_000_000 to 
1_000_000_000, rebuilt and installed it, but still ran into the 
exact same problem.  There may be something up with the algorithm 
itself.


Re: A Friendly Challenge for D

2018-10-13 Thread welkam via Digitalmars-d

On Saturday, 13 October 2018 at 09:22:16 UTC, Vijay Nayar wrote:


I downloaded the reference NIM implementation and got the 
latest nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to 
fix that?


import algorithm

thats all but then it spits out

lib/nim/pure/algorithm.nim(144, 11) Error: interpretation 
requires too many iterations




Re: A Friendly Challenge for D

2018-10-13 Thread Vijay Nayar via Digitalmars-d

On Friday, 12 October 2018 at 21:08:03 UTC, Jabari Zakiya wrote:

On Friday, 12 October 2018 at 20:05:29 UTC, welkam wrote:
On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya 
wrote:
The real point of the challenge is too see what idiomatic 
code...


There is no idiomatic D code. There is only better 
implementations.


D doesnt tell you how to write your code. It gives you many 
tools and you choose which tools to use. That`s what people 
like about D.


I await your implementation(s)! :-)


I downloaded the reference NIM implementation and got the latest 
nim compiler, but I received the following error:

  $ nim c --cc:gcc --d:release --threads:on twinprimes_ssoz.nim
  twinprimes_ssoz.nim(74, 11) Error: attempting to call 
undeclared routine: 'sort'


For a person not familiar with nim, what's the fastest way to fix 
that?


Re: A Friendly Challenge for D

2018-10-12 Thread Jabari Zakiya via Digitalmars-d

On Friday, 12 October 2018 at 20:05:29 UTC, welkam wrote:

On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya wrote:
The real point of the challenge is too see what idiomatic 
code...


There is no idiomatic D code. There is only better 
implementations.


D doesnt tell you how to write your code. It gives you many 
tools and you choose which tools to use. That`s what people 
like about D.


I await your implementation(s)! :-)


Re: A Friendly Challenge for D

2018-10-12 Thread welkam via Digitalmars-d

On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya wrote:
The real point of the challenge is too see what idiomatic 
code...


There is no idiomatic D code. There is only better 
implementations.


D doesnt tell you how to write your code. It gives you many tools 
and you choose which tools to use. That`s what people like about 
D.


Re: A Friendly Challenge for D

2018-10-12 Thread welkam via Digitalmars-d

On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya wrote:
Hmm,I don't think what you're saying about similar 
output|performance with other languages is empirically correct, 
but it's really not the point of the challenge.



Thats why godbolt exists.

c++ and Rust
https://godbolt.org/z/FffXY2
C and D
https://godbolt.org/z/YQvkXU

Look at assembly output. Its all the same. Compilers are very 
good at recognizing simple arithmetic computations and can reason 
about it. What they struggle with is memory access.


On Friday, 12 October 2018 at 16:19:59 UTC, Jabari Zakiya wrote:
Finally, a really fast D implementation can be a marketing 
bananza to show people > in the numerical analysis, data|signal 
processing fields, et al, that D can be used by them to solve 
their problems and be more performant than C++, etc


eBay`s tsv-utils is fastest in the world
https://github.com/eBay/tsv-utils/blob/master/docs/comparative-benchmarks-2018.md#top-four-in-each-benchmark

D`s JSON parsing is fastest in the world
https://github.com/kostya/benchmarks#json

Sambamba is BAM data processor and is fastest in the world
https://www.basepairtech.com/blog/sorting-bam-files-samtools-vs-sambamba/

Mir GLAS is faster than OpenBLAS and Eigen
http://blog.mir.dlang.io/glas/benchmark/openblas/2016/09/23/glas-gemm-benchmark.html

There are enough examples but they are not enough to change minds


Re: A Friendly Challenge for D

2018-10-12 Thread Jabari Zakiya via Digitalmars-d

On Friday, 12 October 2018 at 15:11:17 UTC, welkam wrote:
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:
What I am requesting here is for a person(s) who is an 
"expert" (very good) to create a very fast D version, using 
whatever tricks it has to maximize performance.


I would like to include in my paper a good comparison of 
various implementations in different compiled languages 
(C/C++, D, Nim, etc) to show how it performs with each.


I looked into your NIM code and from programmers point of view 
there is nothing interesting going on. Simple data structures 
and simple operations. If you wrote equivalent code in C, C++, 
D, NIM, Rust, Zig and compiled with same optimizing compiler 
(llvm or gcc) you should get the same machine code and almost 
the same performance (less than 1% difference due to runtime). 
If you got different machine code for equivalent implementation 
then you should file a bug report.


The only way you will get different performance is by changing 
implementation details but then you would compare apples to 
oranges.


Hmm,I don't think what you're saying about similar 
output|performance with other languages is empirically correct, 
but it's really not the point of the challenge.


The real point of the challenge is too see what idiomatic code, 
written for performance, using the best resources that the 
language provides, will produce compared, to the Nim version. 
It's not to see what a line-by-line translation from Nim to D 
would look like. That may be a start to get something working, 
but shouldn't be the end goal.


I'm using the Nim version here as the "reference implementation" 
so it can be used as the standard for comparison (accuracy of 
results and performance). The goal for D (et al) users is to use 
whatever resources it provides to maybe do better.


Example. Nim currently doesn't provide standard bitarrays. Using 
bitarrays in place of byte arrays should perform faster because 
more data can fit in cache and operate faster.


Also, to parallelize the algorithm maybe using OpenMP, CUDA, etc 
is the way to do it for D. I don't know what constructs D uses 
for parallel multiprocessing. And as noted before, this 
algorithms screams out to be done with GPUs.


But you are correct that the Nim code uses very simple coding 
operations. That is one of its beauties! :) It is simple to 
understand and implement mathematically, short and simple to 
code, and architecturally adaptable to hardware.


So to really do the challenge, the Nim code needs to be compiled 
and run (per instructions in code) to use as the "reference 
implementation", to see what correct outputs look like, and their 
times, and then other implementations can be compared to it.


I would hope, after getting an output correct implementation done 
(to show you really know what you're doing) then alternative 
implementations can be done to wring out better performance.


I think this is a good challenge for anyone wanting to learn D 
too, because it involves something substantially more than a 
"toy" algorithm, but short enough to do with minimal time and 
effort, that involves the need to know (learn about) D in enough 
detail to determine the "best" (alternative) way to do it.


Finally, a really fast D implementation can be a marketing 
bananza to show people in the numerical analysis, data|signal 
processing fields, et al, that D can be used by them to solve 
their problems and be more performant than C++, etc.


Again, people should feel free to email me if the want more 
direct answers to questions, or help.




Re: A Friendly Challenge for D

2018-10-12 Thread welkam via Digitalmars-d
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:
What I am requesting here is for a person(s) who is an "expert" 
(very good) to create a very fast D version, using whatever 
tricks it has to maximize performance.


I would like to include in my paper a good comparison of 
various implementations in different compiled languages (C/C++, 
D, Nim, etc) to show how it performs with each.


I looked into your NIM code and from programmers point of view 
there is nothing interesting going on. Simple data structures and 
simple operations. If you wrote equivalent code in C, C++, D, 
NIM, Rust, Zig and compiled with same optimizing compiler (llvm 
or gcc) you should get the same machine code and almost the same 
performance (less than 1% difference due to runtime). If you got 
different machine code for equivalent implementation then you 
should file a bug report.


The only way you will get different performance is by changing 
implementation details but then you would compare apples to 
oranges.





Re: A Friendly Challenge for D

2018-10-11 Thread Ali Çehreli via Digitalmars-d

On 10/11/2018 10:14 AM, Jabari Zakiya wrote:

> Ok, hopefully this will work for everyone. Try this link:
>
> https://mega.nz/#!yJxUEQgK!MY9dwjiWheE8tACtEeS0szduIvdBjiyTn4O6mMD_aZw

Thank you. That worked just fine. I clicked the Download link and the 
pdf was saved on my end. :)


Ali



Re: A Friendly Challenge for D

2018-10-11 Thread Jabari Zakiya via Digitalmars-d

On Thursday, 11 October 2018 at 16:13:17 UTC, Jabari Zakiya wrote:
On Thursday, 11 October 2018 at 14:49:54 UTC, Carl Sturtivant 
wrote:
On Thursday, 11 October 2018 at 13:26:19 UTC, Jabari Zakiyth 
wrote:
On Thursday, 11 October 2018 at 05:11:20 UTC, Ali Çehreli 
wrote:

[...]


What country are you trying to get access from, because I 
know people in the US have gotten the papers from those link, 
for free and without an account. It may also have something 
to do with your browser. They work for me in various modern 
browsers, including the Tor Browser.


Not credible --- I cannot get either without an account 
browsing from the US using Firefox with no unusual 
arrangements.


Wow. Those links used to work with no problem, so I don't know 
what is it (vpn use, etc,?).


OK, this will definitely work. Send me an email and I will 
email you the paper (and figure out a sure fire way to make it 
available).


Construct this full email (for humans).

(my first initial)(lastname) at gmail


Ok, hopefully this will work for everyone. Try this link:

https://mega.nz/#!yJxUEQgK!MY9dwjiWheE8tACtEeS0szduIvdBjiyTn4O6mMD_aZw

However, I'm still interested to find out what is|are the 
specific issues with the other links so I can make a possible bug 
report to those services.


1) Can you actually get to the site?

2) Can you see the document (a reference to it)?

3) Can you read the document online (did you try)?

4) What happened when you tried to download it (popup requiring 
account, etc)?


The paper is from 2014, Scribd has changed a lot since then. The 
more information people can provide will help me determine how to 
provide better access to them.


But you can always email me to get them as a last resort, or just 
to ask questions.




Re: A Friendly Challenge for D

2018-10-11 Thread Jabari Zakiya via Digitalmars-d
On Thursday, 11 October 2018 at 14:49:54 UTC, Carl Sturtivant 
wrote:
On Thursday, 11 October 2018 at 13:26:19 UTC, Jabari Zakiyth 
wrote:
On Thursday, 11 October 2018 at 05:11:20 UTC, Ali Çehreli 
wrote:

[...]


What country are you trying to get access from, because I know 
people in the US have gotten the papers from those link, for 
free and without an account. It may also have something to do 
with your browser. They work for me in various modern 
browsers, including the Tor Browser.


Not credible --- I cannot get either without an account 
browsing from the US using Firefox with no unusual arrangements.


Wow. Those links used to work with no problem, so I don't know 
what is it (vpn use, etc,?).


OK, this will definitely work. Send me an email and I will email 
you the paper (and figure out a sure fire way to make it 
available).


Construct this full email (for humans).

(my first initial)(lastname) at gmail


Re: A Friendly Challenge for D

2018-10-11 Thread Carl Sturtivant via Digitalmars-d
On Thursday, 11 October 2018 at 13:26:19 UTC, Jabari Zakiyth 
wrote:

On Thursday, 11 October 2018 at 05:11:20 UTC, Ali Çehreli wrote:

[...]


What country are you trying to get access from, because I know 
people in the US have gotten the papers from those link, for 
free and without an account. It may also have something to do 
with your browser. They work for me in various modern browsers, 
including the Tor Browser.


Not credible --- I cannot get either without an account browsing 
from the US using Firefox with no unusual arrangements.


Re: A Friendly Challenge for D

2018-10-11 Thread Jabari Zakiyth via Digitalmars-d

On Thursday, 11 October 2018 at 05:11:20 UTC, Ali Çehreli wrote:

On 10/10/2018 07:52 PM, Jabari Zakiyth wrote:
> On Wednesday, 10 October 2018 at 22:25:17 UTC, Neia Neutuladh
wrote:
>> On 10/10/2018 03:05 PM, Jabari Zakiya wrote:
>>> 
https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ

>>
>> It would be great if you could provide a link to a freely
downloadable
>> version of this.
>
> You can download the paper for free from that link. Did you
have trouble
> doing it?

I think the problem is, scribd requires an account, which they 
apparently happy to link to an existing Google or Facebook 
account.


> Here's another link to paper.
>
> 
https://www.academia.edu/7583194/The_Segmented_Sieve_of_Zakiya_SSoZ_


Similarly, that one requires a Google account.

> Here, again, is the link to the Nim code. Just install Nim
(current
> 0.19.0) and compile and run it per instructions in code. I
recommend
> people do that to see its outputs and verify its results.
>
> 
https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e


That works! :)

Ali


What country are you trying to get access from, because I know 
people in the US have gotten the papers from those link, for free 
and without an account. It may also have something to do with 
your browser. They work for me in various modern browsers, 
including the Tor Browser.





Re: A Friendly Challenge for D

2018-10-10 Thread Ali Çehreli via Digitalmars-d

On 10/10/2018 07:52 PM, Jabari Zakiyth wrote:
> On Wednesday, 10 October 2018 at 22:25:17 UTC, Neia Neutuladh wrote:
>> On 10/10/2018 03:05 PM, Jabari Zakiya wrote:
>>> https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ
>>
>> It would be great if you could provide a link to a freely downloadable
>> version of this.
>
> You can download the paper for free from that link. Did you have trouble
> doing it?

I think the problem is, scribd requires an account, which they 
apparently happy to link to an existing Google or Facebook account.


> Here's another link to paper.
>
> https://www.academia.edu/7583194/The_Segmented_Sieve_of_Zakiya_SSoZ_

Similarly, that one requires a Google account.

> Here, again, is the link to the Nim code. Just install Nim (current
> 0.19.0) and compile and run it per instructions in code. I recommend
> people do that to see its outputs and verify its results.
>
> https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e

That works! :)

Ali



Re: A Friendly Challenge for D

2018-10-10 Thread Jabari Zakiyth via Digitalmars-d

On Thursday, 11 October 2018 at 00:22:10 UTC, tide wrote:
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:
I would like to include in my paper a good comparison of 
various implementations in different compiled languages 
(C/C++, D, Nim, etc) to show how it performs with each.


If you want help with your paper, possibly some kind of decent 
financial incentive would be appropriate. If the algorithm 
benefits from more threads than finding or creating an 
implementation that runs on a GPU would probably be the true 
performance test. CPUs have like 4-8 cores in the mainstream? A 
GPU has hundreds, though with some limitations.


I'm writing the paper anyway (just like the others), so other 
implementations are icing on the cake to show implementation 
variations, as a benefit to readers. Maybe if I set up a website 
and created a Rosetta Code repo for people to post their 
different language implementations, and offer a T-shirt for 
fastest implementation. :-)


Yes, a GPU based implementation would be the epitome for this 
algorithm, by far. This is actually why I have gotten the 
algorithm to this implementation so that the number crunching can 
all be done in parallel threads. (It would also be screamingly 
fast done in hardware in a FPGA too.) However, I only have 
standard consumer grade laptops. Hopefully someone(s) with 
sufficient hardware, interest, and time, will take this upon 
themselves to do this and publicize their results.


Re: A Friendly Challenge for D

2018-10-10 Thread Jabari Zakiyth via Digitalmars-d
On Wednesday, 10 October 2018 at 22:25:17 UTC, Neia Neutuladh 
wrote:

On 10/10/2018 03:05 PM, Jabari Zakiya wrote:

https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ


It would be great if you could provide a link to a freely 
downloadable version of this.


You can download the paper for free from that link. Did you have 
trouble doing it?


Here's another link to paper.

https://www.academia.edu/7583194/The_Segmented_Sieve_of_Zakiya_SSoZ_


Here, again, is the link to the Nim code. Just install Nim 
(current 0.19.0) and compile and run it per instructions in code. 
I recommend people do that to see its outputs and verify its 
results.


https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e


Re: A Friendly Challenge for D

2018-10-10 Thread tide via Digitalmars-d
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:
I would like to include in my paper a good comparison of 
various implementations in different compiled languages (C/C++, 
D, Nim, etc) to show how it performs with each.


If you want help with your paper, possibly some kind of decent 
financial incentive would be appropriate. If the algorithm 
benefits from more threads than finding or creating an 
implementation that runs on a GPU would probably be the true 
performance test. CPUs have like 4-8 cores in the mainstream? A 
GPU has hundreds, though with some limitations.


Re: A Friendly Challenge for D

2018-10-10 Thread Neia Neutuladh via Digitalmars-d

On 10/10/2018 03:05 PM, Jabari Zakiya wrote:

https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ


It would be great if you could provide a link to a freely downloadable 
version of this.


Re: A Friendly Challenge for D

2018-10-10 Thread Jabari Zakiya via Digitalmars-d

On Wednesday, 10 October 2018 at 20:43:01 UTC, Kagamin wrote:
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:

https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e


As i understand, main thread preallocates global memory and 
tracks it, and other threads don't track it?


Here's an abreviated elementary explanation of the algorithm and 
implementation.
You will need to read (download) my paper "The Segmented Sieve of 
Zakiya (SSoZ)"
because I will make reference to things in it, to keep this as 
short as possible.


https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ

To really understand the math and theory of the algorithm 
requires primarily
just understanding Table 3 on page 3 of the paper, as it 
encapsulates everything.
You can read the paper to understand the language of the 
algorithm used in the code.


Twinprimes are 2 (odd) primes that differ by only 2 eg. 3-5, 5-7, 
11-13, 29-31.


Table 3 shows all the residues values (prime candidates|pcs) and 
residues groups
(resgroups|columns) to find all the primes upto 541 using P5 
(modpg = 30, rescnt = 8).


For a given value N, it will be represented with a PG table of 
some number of
resgroups, with max size I call Kmax (the regroups value N 
residues in).


Using P5, I only need to sieve primes along the residue tracks 
(restracks) that can
produce twinprimes, here 11-13, 17-19, 29-31. Thus I create 3 
byte arrays, one for each twinpair, and use the lower 2 bits to 
represent the upper and lower twinprime restracks.


Then for each twinpair (here 3) I run 3 thread which perform the 
SSoZ on the entire Kmax length of resgroups in parallel. At the 
end I accumulate the results and print them out. This, in a 
nutshell, is what the algorithm does. The paper gives you enough 
to understand the fundamental nature of the algorithm, though 
I've learned so much more than in 2014. :)


The larger the PG the more twinpair restracks (see page 14) there 
are to use. For larger numbers you want to use the largest PG 
possible that 'fits' into the hardware cpu. All my 
development|testing was done on laptops using Intel I5|I7 cpus 
with 4 or 8 threads. I'm really interested how it performs on 
other platforms (ARM, AMD, PowerPC, etc).



The main proc "twinprimes_ssoz" manages program flow and set as 
follows:


1) accepts the input number (an integer) in "val" from the cli

2) sets "num" to be first odd number < "val" if "val" even

3) calls "selectPG" with "num" to select optimum Prime Generator 
(PG) parameters


4) compute various working parameters per selected PG and number 
value (see refs)


5) compute global values for number of primes, and their values, 
<= sqrt(num) for

selected PG with proc "sozpg"

6) Set initial twinprime count for selected PG

7) Then with proc "segsieve" allocate one thread to perform SSoZ 
(segmented sieve of zakiya)
on each twinprime pair residues (determined by selected PG), and 
count number of twinprmes

computed in each thread.

8) Then determine true total twinprime count and last twinprime 
<= "num"


It also is timing different intervals and prints out diagnostics 
and final output.



The proc "twins_sieve" is the primary function that manages and 
performs the SSoZ for
a given twinprim pair parameters in each thread. The more threads 
the faster the process goes.


I'll provide more info later. I have to run now. I wanted to get 
this out now while I

was at my laptop, and online.


Re: A Friendly Challenge for D

2018-10-10 Thread Kagamin via Digitalmars-d
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:

https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e


As i understand, main thread preallocates global memory and 
tracks it, and other threads don't track it?


Re: A Friendly Challenge for D

2018-10-10 Thread SrMordred via Digitalmars-d
On Wednesday, 10 October 2018 at 16:15:56 UTC, Jabari Zakiya 
wrote:

[...]


Looking forward to this :)


A Friendly Challenge for D

2018-10-10 Thread Jabari Zakiya via Digitalmars-d

Hi.

I hope this is the right place to request this, if not please 
tell me a better one.


I had looked at D, and played with it some circa 2010~2012, but 
time and life took my priorities away. But I'm still interested 
in learning different languages, but there are so many more now 
it's hard to devote the time to learn them to some high level of 
proficiency.


Subsequently, I started learning Nim, because I find the syntax 
and constructs simpler and more familiar than most (I'm coming 
mostly from a Ruby background).


I have developed in Nim a program to find twinprimes that seems 
to be the fastest of its type, compared to primesieve 
(https://primesieve.org/) which claims to be the fastest, written 
in C++.


Here is the code to my Nim implementation of twinprimes_ssoz.

https://gist.github.com/jzakiya/6c7e1868bd749a6b1add62e3e3b2341e

The total file is just 318 lines of code, with about 60 separate 
lines of comments.
The code is extensively commented per line to explain what's 
happening.
Reading the references given in the code introduction will 
explain the general process.

See  "The Segmented Sieve of Zakiya (SSoZ)"
https://www.scribd.com/doc/228155369/The-Segmented-Sieve-of-Zakiya-SSoZ

I am in the process of writing up a paper to explain this 
application, and implementation. What I am requesting here is for 
a person(s) who is an "expert" (very good) to create a very fast 
D version, using whatever tricks it has to maximize performance.


I would like to include in my paper a good comparison of various 
implementations in different compiled languages (C/C++, D, Nim, 
etc) to show how it performs with each.


This algorithm is designed to be run in multiprocessing 
environments (more core/threads, better performance). The Nim 
version (0.18.0, 0.19.0 recently released) uses its native 
parallel processing structure. In C++, et al, it may be best 
implemented using OPenMP, or CUDA, etc. These are implementation 
details one versed in a language could determine.


Well that's it. I am willing to share performance data, compared 
to primesive, if you like. The beauty of this 
algorithm|implementation is its simplicity in design, and minimal 
code. It shouldn't be that hard to understand to determine how to 
translate into D. Of course, I'm am fully available to answer 
questions and provide help.


Thanks

Jabari




Re: Knowing the approach to solve a D challenge

2018-02-16 Thread Jesse Phillips via Digitalmars-d

On Friday, 16 February 2018 at 09:44:27 UTC, aberba wrote:
D has tone of features and library solutions. When you 
encounter a problem, how do you approach solving it in code?


1. Do you first write it in idiomatic D style or a more general 
approach before porting to idiomatic D?


Like always, it depends. Do I attribute up all my functions with 
const/@safe/nothrow... (is that even idiomatic) no. Do I build a 
range to process some data... sometimes. Do I utilize 
std.algorithm/std.range functions to process my data... when 
available.


Even my C# code tends to be more idiomatic D than others.

2. Do you find yourself mostly rolling out your own 
implementation first before using a library function?


I don't know. If a rolled my own I probably don't know of the 
library function/function combination that does the same thing.



3. Do the use of generics come out of first try or a rewrite?


Usually not. If I don't have another use-case I probably don't 
know what needs

to be generic.

4. What rough percentage of phobos knowledge is required for 
reasonable good problem solving efficiency?


I would guess average. The reason I say this because unlike 
popular languages search doesn't always provide a good example 
for every question so you kind of need to already know what 
you're looking for. It doesn't help that sometimes the answer is 
a combination of this (.reduce!max that isn't found in std.math)


Re: Knowing the approach to solve a D challenge

2018-02-16 Thread Dukc via Digitalmars-d

On Friday, 16 February 2018 at 09:44:27 UTC, aberba wrote:
1. Do you first write it in idiomatic D style or a more general 
approach before porting to idiomatic D?


In micro-level, it's usually fairly idiomatic from get-go. 
Usually no heap allocations at inner loops, for-looping, static 
variables etc. Sometimes if I get a bit desperate of frustated I 
might do this a bit.


But at larger level, I often find myself shifting work between 
functions, structs, modules and so. In other words, redesigning.


2. Do you find yourself mostly rolling out your own 
implementation first before using a library function?


No, the vast majority of my calls are from Phobos or other 
libraries I use. And in case of Phobos at least, it's stuff is so 
general that I don't need to design my own function often. An 
exception is std.algorithm.each, but just to get better error 
messages (template constraints don't tell why the call did not 
work).



3. Do the use of generics come out of first try or a rewrite?


Rewriting a lot, but that's the case with all coding. With 
generics, i often tend to forget ! before an alias parameter.


4. What rough percentage of phobos knowledge is required for 
reasonable good problem solving efficiency?


If we talk about experience of the language in general, it's more 
than with C-style programming, Java or C# but less than with C++ 
generics. I don't think you have to know Phobos throughout, but 
you have to know the language and understand the philosophy of 
ranges quite deeply.


Percentages aren't important, I think that as long as you know 
the general purpose of std.algorithm, std.range, std.stdio, 
std.conv and std.array that gets you started. Again, if you know 
the language and understand the range concept.




Re: Knowing the approach to solve a D challenge

2018-02-16 Thread Chris via Digitalmars-d

On Friday, 16 February 2018 at 09:44:27 UTC, aberba wrote:
D has tone of features and library solutions. When you 
encounter a problem, how do you approach solving it in code?


1. Do you first write it in idiomatic D style or a more general 
approach before porting to idiomatic D?


As idiomatic as possible. But it depends on how big and/or 
important the method/function is. The more important and/or 
bigger, the more idiomatic. Sometimes a `foreach` will do in a 
small function.


But D makes it easy to write idiomatic code straight away, 
although sometimes it can be a bit annoying when you get messages 
like "cannot implicitly convert x of type y to z". So you have to 
keep track of what you are chaining.


2. Do you find yourself mostly rolling out your own 
implementation first before using a library function?


I usually start to roll out my own for a few minutes until I say 
"Hold on, maybe the library already has a function that does 
exactly that!" And it often does. That's because I get a better 
understanding of what I need, when I roll my own for a while. 
Using the library straight away can sometimes result in shooting 
yourself in the foot. So it's a mix of both.



3. Do the use of generics come out of first try or a rewrite?


Depends on the problem at hand. I you know you will have to 
handle several types down the road, it's a minimal generic that 
accepts only one type to begin with but that can be extended to 
others. It's a bit "play by ear". If I'm dealing with HTML and I 
know that JSON or CSV will be needed later, I write the function 
in a way that it can easily be extended. If a function returns 
the user name as a `string`, I won't bother with generics. That's 
just normal, I think.


4. What rough percentage of phobos knowledge is required for 
reasonable good problem solving efficiency?


You cannot know every function, of course, and new functions are 
being added all the time. What you need to know is what Phobos 
can do in general and where to look for it. The cheat sheet 
should be the first port of call. You can save a lot of time by 
skimming through the library regularly. Also, it's worth looking 
at other people's code in the "learn" section. What often happens 
to me, when I see a solution, I go "Jesus, that's clever, I'll 
keep that in mind!" The learn section is good because it focuses 
on one (small) problem at a time.




Re: Knowing the approach to solve a D challenge

2018-02-16 Thread Joakim via Digitalmars-d
I don't write much D code, but here are my answers for _any_ 
language.


On Friday, 16 February 2018 at 09:44:27 UTC, aberba wrote:
D has tone of features and library solutions. When you 
encounter a problem, how do you approach solving it in code?


1. Do you first write it in idiomatic D style or a more general 
approach before porting to idiomatic D?


The style in my head, which sometimes is D function chains, for 
example, this chain I put in Phobos:


https://github.com/dlang/phobos/blob/master/std/datetime/timezone.d#L2501

Compare it to the previously-written non-Android version just 
below, which could probably be written as such a chain but might 
be too unwieldy if done that way.


2. Do you find yourself mostly rolling out your own 
implementation first before using a library function?


Look for a library function, and if nothing works, write your own.


3. Do the use of generics come out of first try or a rewrite?


I don't really need them for my own functions, so can't say.

4. What rough percentage of phobos knowledge is required for 
reasonable good problem solving efficiency?


Just hunt for something when you need it.  Knowing Phobos well is 
like indexing your data beforehand, you'll find something much 
quicker.


The reason D supports so many styles is so you don't have to 
force yourself to use only one style.  The D idioms are there if 
you need them though, and you may find using them gives you 
better code.


Re: Knowing the approach to solve a D challenge

2018-02-16 Thread rikki cattermole via Digitalmars-d

On 16/02/2018 9:44 AM, aberba wrote:
D has tone of features and library solutions. When you encounter a 
problem, how do you approach solving it in code?


1. Do you first write it in idiomatic D style or a more general approach 
before porting to idiomatic D?


2. Do you find yourself mostly rolling out your own implementation first 
before using a library function?


3. Do the use of generics come out of first try or a rewrite?

4. What rough percentage of phobos knowledge is required for reasonable 
good problem solving efficiency?


A: Do it any way possible

If it needs a rewrite then yes more idiomatic and better designed :)


Knowing the approach to solve a D challenge

2018-02-16 Thread aberba via Digitalmars-d
D has tone of features and library solutions. When you encounter 
a problem, how do you approach solving it in code?


1. Do you first write it in idiomatic D style or a more general 
approach before porting to idiomatic D?


2. Do you find yourself mostly rolling out your own 
implementation first before using a library function?


3. Do the use of generics come out of first try or a rewrite?

4. What rough percentage of phobos knowledge is required for 
reasonable good problem solving efficiency?





Challenge on Russian Stack Overflow

2016-11-11 Thread Jack Applegame via Digitalmars-d
I found funny (from my point of view) challenge in Russian Stack 
Overflow.

Any language accepted.

You need to make the loop

for (int x=0; x<3; ++x) {}

endless.

Rules:
- you can't modify the loop's code itself;
- you can't modify the loop's variable inside the body of loop;
- you can't wrap the loop in an outer infinite loop or insert an 
infinite loop inside the body;


For example,  C++ solution:


int main() {
#define int bool
for (int x=0; x<3; ++x);
return 0;
}


This is my D solution - 
http://ru.stackoverflow.com/a/589748/218208


Solution with the highest rating wins.


Re: Challenge

2016-10-05 Thread Manu via Digitalmars-d
On 6 October 2016 at 01:07, Jonathan M Davis via Digitalmars-d
 wrote:
> On Thursday, October 06, 2016 00:38:54 Manu via Digitalmars-d wrote:
>> I thought there was a distinction between typetuple and alias? Some
>> expression can be captured by a typetuple, but not by alias?
>> There must be a reason for that horrible and prolific pattern "(T...)
>> if(T.length == 1) { ... T[0] ... }" instead of "(alias T) { ... T ...
>> }"?
>
> That has to do with the fact alias template parameters don't take keywords,
> even if they're types. alias declarations don't have that problem. If they
> did, we couldn't have stuff like size_t or c_long. In theory, Walter has
> agreed that we'll fix it so that template alias parameters are consistent
> with alias declarations, but that hasn't happened yet. And until it does,
> we're stuck with the weird variadic templates of length 1.

I see. It sounds like one of these things that needs a serious priority boost.
There are a lot of weirdness-es in template code that make is SO HARD
for non-absolute-experts to understand. It's practically impossible to
author correct code unless you are a serious forum regular of a phobos
contributor.
These weird patterns that are effectively workarounds need to be
ejected into space as soon as possible. I get seriously embarrassed
every time I have to explain these sorts of things to one my
colleagues!


Re: Challenge

2016-10-05 Thread Jonathan M Davis via Digitalmars-d
On Thursday, October 06, 2016 00:38:54 Manu via Digitalmars-d wrote:
> I thought there was a distinction between typetuple and alias? Some
> expression can be captured by a typetuple, but not by alias?
> There must be a reason for that horrible and prolific pattern "(T...)
> if(T.length == 1) { ... T[0] ... }" instead of "(alias T) { ... T ...
> }"?

That has to do with the fact alias template parameters don't take keywords,
even if they're types. alias declarations don't have that problem. If they
did, we couldn't have stuff like size_t or c_long. In theory, Walter has
agreed that we'll fix it so that template alias parameters are consistent
with alias declarations, but that hasn't happened yet. And until it does,
we're stuck with the weird variadic templates of length 1.

- Jonathan M Davis



Re: Challenge

2016-10-05 Thread Manu via Digitalmars-d
On 5 October 2016 at 19:45, Jonathan M Davis via Digitalmars-d
 wrote:
> On Wednesday, October 05, 2016 09:24:56 John Colvin via Digitalmars-d wrote:
>> > It _is_ however recommended to use __traits(getMember, T,
>> > member) over manually building it with strings with something
>> > like T.stringof ~ "." ~ member, because the string manipulation
>> > falls about in corner cases (e.g. it could result in a symbol
>> > conflict). It's just that then has the unfortunate side effect
>> > of requiring AliasSeq because of the bug.
>> >
>> > - Jonathan M Davis
>>
>> https://dlang.org/phobos/std_meta.html#.Alias   :)
>
> IMHO, that doesn't improve things much, but it is slightly shorter. Thanks
> for pointing it out.

I thought there was a distinction between typetuple and alias? Some
expression can be captured by a typetuple, but not by alias?
There must be a reason for that horrible and prolific pattern "(T...)
if(T.length == 1) { ... T[0] ... }" instead of "(alias T) { ... T ...
}"?


Re: Challenge

2016-10-05 Thread Jonathan M Davis via Digitalmars-d
On Wednesday, October 05, 2016 09:24:56 John Colvin via Digitalmars-d wrote:
> > It _is_ however recommended to use __traits(getMember, T,
> > member) over manually building it with strings with something
> > like T.stringof ~ "." ~ member, because the string manipulation
> > falls about in corner cases (e.g. it could result in a symbol
> > conflict). It's just that then has the unfortunate side effect
> > of requiring AliasSeq because of the bug.
> >
> > - Jonathan M Davis
>
> https://dlang.org/phobos/std_meta.html#.Alias   :)

IMHO, that doesn't improve things much, but it is slightly shorter. Thanks
for pointing it out.

- Jonathan M Davis



Re: Challenge

2016-10-05 Thread John Colvin via Digitalmars-d
On Wednesday, 5 October 2016 at 02:15:13 UTC, Jonathan M Davis 
wrote:
On Wednesday, October 05, 2016 11:20:44 Manu via Digitalmars-d 
wrote:
> While you're at it, might I suggest also adding 
> std.traits.isProperty?

>
>  Something like:
> template isProperty(T, string member)
> {
>
>   import std.meta : AliasSeq;
>   import std.traits : FunctionTypeOf;
>   alias sym = AliasSeq!(__traits(getMember, T, member))[0];
>   enum isProperty = !is(typeof(sym) == function) &&
>
> is(FunctionTypeOf!(typeof(&sym)) == function);
> }

Why this AliasSeq business? That line is rather an 
abomination... why are all these horrible expressions popping 
up as recommendations nowadays?


The AliasSeq muck is there because for some reason you can't 
alias the result of __traits, so doing something like


alias sym = __traits(getMember, T, member);

isn't legal. So, this has nothing to do with a recommendation 
of best practice and everything to do with an annoying bug.


https://issues.dlang.org/show_bug.cgi?id=7804

It _is_ however recommended to use __traits(getMember, T, 
member) over manually building it with strings with something 
like T.stringof ~ "." ~ member, because the string manipulation 
falls about in corner cases (e.g. it could result in a symbol 
conflict). It's just that then has the unfortunate side effect 
of requiring AliasSeq because of the bug.


- Jonathan M Davis


https://dlang.org/phobos/std_meta.html#.Alias   :)


Re: Challenge

2016-10-05 Thread Daniel N via Digitalmars-d
On Wednesday, 5 October 2016 at 02:15:13 UTC, Jonathan M Davis 
wrote:
The AliasSeq muck is there because for some reason you can't 
alias the result of __traits, so doing something like


alias sym = __traits(getMember, T, member);

isn't legal. So, this has nothing to do with a recommendation 
of best practice and everything to do with an annoying bug.




When aliasing a single symbol, I find it much cleaner to use...
Identity!(...) or I!(...)
... instead of
AliasSeq!(...)[0]



Re: Challenge

2016-10-04 Thread Jonathan M Davis via Digitalmars-d
On Wednesday, October 05, 2016 11:20:44 Manu via Digitalmars-d wrote:
> > While you're at it, might I suggest also adding std.traits.isProperty?
> >
> >  Something like:
> > template isProperty(T, string member)
> > {
> >
> >   import std.meta : AliasSeq;
> >   import std.traits : FunctionTypeOf;
> >   alias sym = AliasSeq!(__traits(getMember, T, member))[0];
> >   enum isProperty = !is(typeof(sym) == function) &&
> >
> > is(FunctionTypeOf!(typeof(&sym)) == function);
> > }
>
> Why this AliasSeq business? That line is rather an abomination... why
> are all these horrible expressions popping up as recommendations
> nowadays?

The AliasSeq muck is there because for some reason you can't alias the
result of __traits, so doing something like

alias sym = __traits(getMember, T, member);

isn't legal. So, this has nothing to do with a recommendation of best
practice and everything to do with an annoying bug.

https://issues.dlang.org/show_bug.cgi?id=7804

It _is_ however recommended to use __traits(getMember, T, member) over
manually building it with strings with something like T.stringof ~ "." ~
member, because the string manipulation falls about in corner cases (e.g. it
could result in a symbol conflict). It's just that then has the unfortunate
side effect of requiring AliasSeq because of the bug.

- Jonathan M Davis



Re: Challenge

2016-10-04 Thread Manu via Digitalmars-d
On 4 October 2016 at 22:48, Manu  wrote:
> On 4 October 2016 at 14:40, Jonathan M Davis via Digitalmars-d
>  wrote:
>> On Tuesday, October 04, 2016 14:24:59 Manu via Digitalmars-d wrote:
>>> On 4 October 2016 at 12:30, Jonathan M Davis via Digitalmars-d
>>>
>>>  wrote:
>>> > On Tuesday, October 04, 2016 11:13:36 Manu via Digitalmars-d wrote:
>>> >> I'm feeling John's solution is a little bit simpler. But nice work,
>>> >> thanks!
>>> >
>>> > So, it is. LOL. I'd actually glanced over that post while I was in the
>>> > middle of getting my version to work, and I read it too quickly, because I
>>> > understood that it had just solved the property problem and that it didn't
>>> > work for all cases. I'll have to update my PR. Though his code does make
>>> > the mistake of doing
>>> >
>>> > mixin(`alias mem = T.` ~ member ~ `;`);
>>> >
>>> > rather than doing something like
>>> >
>>> > alias mem = AliasSeq!(__traits(getMember, T, member))[0];
>>> >
>>> > which means that there are some cases where it won't work properly. The
>>> > core logic is simpler though, which is definitely a plus.
>>>
>>> Make that change in your PR :)
>>
>> I already updated it and was actually able to make it slightly simpler than
>> John's example (as far as I can tell, FunctionTypeOf is only needed in the
>> case where the address is taken).
>>
>>> I think the PR is important. It's not obvious how to do this, and it's
>>> very useful. I was astonished it's not already there.
>>
>> Yeah. I ran into a need for something similar recently, but my
>> implementation at the time wasn't as thorough, since it just used offsetof
>> to do the check (though in my case, I think that was enough). Getting it
>> completely right is surprisingly difficult.
>>
>> I was also surprised that while we have quite a few __traits for functions,
>> they're severely lacking for variables (e.g. I was looking for the variable
>> equivalent of __traits(isStaticFunction, ...), and there is no such beast).
>> For that matter, even testing whether something is a variable is
>> surprisingly difficult.
>>
>> - Jonathan M Davis
>
> While you're at it, might I suggest also adding std.traits.isProperty?
>  Something like:
>
> template isProperty(T, string member)
> {
>   import std.meta : AliasSeq;
>   import std.traits : FunctionTypeOf;
>   alias sym = AliasSeq!(__traits(getMember, T, member))[0];
>   enum isProperty = !is(typeof(sym) == function) &&
> is(FunctionTypeOf!(typeof(&sym)) == function);
> }

Why this AliasSeq business? That line is rather an abomination... why
are all these horrible expressions popping up as recommendations
nowadays?


Re: Challenge

2016-10-04 Thread Manu via Digitalmars-d
On 4 October 2016 at 14:40, Jonathan M Davis via Digitalmars-d
 wrote:
> On Tuesday, October 04, 2016 14:24:59 Manu via Digitalmars-d wrote:
>> On 4 October 2016 at 12:30, Jonathan M Davis via Digitalmars-d
>>
>>  wrote:
>> > On Tuesday, October 04, 2016 11:13:36 Manu via Digitalmars-d wrote:
>> >> I'm feeling John's solution is a little bit simpler. But nice work,
>> >> thanks!
>> >
>> > So, it is. LOL. I'd actually glanced over that post while I was in the
>> > middle of getting my version to work, and I read it too quickly, because I
>> > understood that it had just solved the property problem and that it didn't
>> > work for all cases. I'll have to update my PR. Though his code does make
>> > the mistake of doing
>> >
>> > mixin(`alias mem = T.` ~ member ~ `;`);
>> >
>> > rather than doing something like
>> >
>> > alias mem = AliasSeq!(__traits(getMember, T, member))[0];
>> >
>> > which means that there are some cases where it won't work properly. The
>> > core logic is simpler though, which is definitely a plus.
>>
>> Make that change in your PR :)
>
> I already updated it and was actually able to make it slightly simpler than
> John's example (as far as I can tell, FunctionTypeOf is only needed in the
> case where the address is taken).
>
>> I think the PR is important. It's not obvious how to do this, and it's
>> very useful. I was astonished it's not already there.
>
> Yeah. I ran into a need for something similar recently, but my
> implementation at the time wasn't as thorough, since it just used offsetof
> to do the check (though in my case, I think that was enough). Getting it
> completely right is surprisingly difficult.
>
> I was also surprised that while we have quite a few __traits for functions,
> they're severely lacking for variables (e.g. I was looking for the variable
> equivalent of __traits(isStaticFunction, ...), and there is no such beast).
> For that matter, even testing whether something is a variable is
> surprisingly difficult.
>
> - Jonathan M Davis

While you're at it, might I suggest also adding std.traits.isProperty?
 Something like:

template isProperty(T, string member)
{
  import std.meta : AliasSeq;
  import std.traits : FunctionTypeOf;
  alias sym = AliasSeq!(__traits(getMember, T, member))[0];
  enum isProperty = !is(typeof(sym) == function) &&
is(FunctionTypeOf!(typeof(&sym)) == function);
}


Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 4 October 2016 at 14:40, Jonathan M Davis via Digitalmars-d
 wrote:
> [...]
> For that matter, even testing whether something is a variable is
> surprisingly difficult.

True story! I've written that one before... I spent ages trying to get it right!
When people say D is highly complex, these are the reasons. There are
a lot of edges, and some arbitrary corners where things just don't
work.
*mutter mutter* storage class *mutter mutter*


Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, October 04, 2016 14:24:59 Manu via Digitalmars-d wrote:
> On 4 October 2016 at 12:30, Jonathan M Davis via Digitalmars-d
>
>  wrote:
> > On Tuesday, October 04, 2016 11:13:36 Manu via Digitalmars-d wrote:
> >> I'm feeling John's solution is a little bit simpler. But nice work,
> >> thanks!
> >
> > So, it is. LOL. I'd actually glanced over that post while I was in the
> > middle of getting my version to work, and I read it too quickly, because I
> > understood that it had just solved the property problem and that it didn't
> > work for all cases. I'll have to update my PR. Though his code does make
> > the mistake of doing
> >
> > mixin(`alias mem = T.` ~ member ~ `;`);
> >
> > rather than doing something like
> >
> > alias mem = AliasSeq!(__traits(getMember, T, member))[0];
> >
> > which means that there are some cases where it won't work properly. The
> > core logic is simpler though, which is definitely a plus.
>
> Make that change in your PR :)

I already updated it and was actually able to make it slightly simpler than
John's example (as far as I can tell, FunctionTypeOf is only needed in the
case where the address is taken).

> I think the PR is important. It's not obvious how to do this, and it's
> very useful. I was astonished it's not already there.

Yeah. I ran into a need for something similar recently, but my
implementation at the time wasn't as thorough, since it just used offsetof
to do the check (though in my case, I think that was enough). Getting it
completely right is surprisingly difficult.

I was also surprised that while we have quite a few __traits for functions,
they're severely lacking for variables (e.g. I was looking for the variable
equivalent of __traits(isStaticFunction, ...), and there is no such beast).
For that matter, even testing whether something is a variable is
surprisingly difficult.

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 4 October 2016 at 12:30, Jonathan M Davis via Digitalmars-d
 wrote:
> On Tuesday, October 04, 2016 11:13:36 Manu via Digitalmars-d wrote:
>> I'm feeling John's solution is a little bit simpler. But nice work, thanks!
>
> So, it is. LOL. I'd actually glanced over that post while I was in the
> middle of getting my version to work, and I read it too quickly, because I
> understood that it had just solved the property problem and that it didn't
> work for all cases. I'll have to update my PR. Though his code does make the
> mistake of doing
>
> mixin(`alias mem = T.` ~ member ~ `;`);
>
> rather than doing something like
>
> alias mem = AliasSeq!(__traits(getMember, T, member))[0];
>
> which means that there are some cases where it won't work properly. The core
> logic is simpler though, which is definitely a plus.

Make that change in your PR :)
I think the PR is important. It's not obvious how to do this, and it's
very useful. I was astonished it's not already there.


Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, October 04, 2016 11:13:36 Manu via Digitalmars-d wrote:
> I'm feeling John's solution is a little bit simpler. But nice work, thanks!

So, it is. LOL. I'd actually glanced over that post while I was in the
middle of getting my version to work, and I read it too quickly, because I
understood that it had just solved the property problem and that it didn't
work for all cases. I'll have to update my PR. Though his code does make the
mistake of doing

mixin(`alias mem = T.` ~ member ~ `;`);

rather than doing something like

alias mem = AliasSeq!(__traits(getMember, T, member))[0];

which means that there are some cases where it won't work properly. The core
logic is simpler though, which is definitely a plus.

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 4 October 2016 at 05:01, Jonathan M Davis via Digitalmars-d
 wrote:
> On Monday, October 03, 2016 11:13:52 Jonathan M Davis via Digitalmars-d wrote:
>> template isStaticMember(T, string member)
>> {
>> static if (!__traits(hasMember, T, member))
>> enum bool isStaticMember = false;
>> else
>> {
>> import std.meta : AliasSeq;
>> import std.traits : FunctionTypeOf;
>> alias sym = AliasSeq!(__traits(getMember, T, member))[0];
>>
>> static if (__traits(isStaticFunction, sym))
>> enum bool isStaticMember = true;
>> else static if (is(FunctionTypeOf!sym == function) &&
>> is(FunctionTypeOf!(typeof(&sym)) == function))
>> {
>> enum bool isStaticMember = false;
>> }
>> else
>> {
>> enum bool isStaticMember = !__traits(compiles, sym.offsetof) &&
>>__traits(compiles, &sym);
>> }
>> }
>> }
>
> Well, since I took the time to write it, I created a PR for it:
>
> https://github.com/dlang/phobos/pull/4834
>
> So, if anyone sees problems with my implementation, go poke holes in it.
>
> - Jonathan M Davis
>

I'm feeling John's solution is a little bit simpler. But nice work, thanks!


Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 4 October 2016 at 00:25, John Colvin via Digitalmars-d
 wrote:
> On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:
>>
>> Fill in the blank...
>> I'm having a really hard time with this. I've made it work with a
>> mountain of code, and I want to see what others come up with...
>
>
> template isStaticMember(T, string member)
> {
> mixin(`alias mem = T.` ~ member ~ `;`);
> import std.traits : FunctionTypeOf;
> static if (is(FunctionTypeOf!mem == function) &&
> is(FunctionTypeOf!(typeof(&mem)) == function))
> enum bool isStaticMember = __traits(isStaticFunction, mem);
> else
> enum bool isStaticMember = is(typeof(&mem));
> }
>
> Basically, using FunctionTypeOf catches @property functions (which just
> typeof wouldn't), but it also catches member variables with function types,
> so we need the second FunctionTypeOf to see if it's still a function when
> you take its address (true for member functions, including @property
> functions, not true for member variables with function types).
>
> Everything else is just "can you take the address of this".

Very nice. This is the quality of solution I was looking for! 3 Significant LOC.
I knew a simple solution must exist. I didn't think of FunctionTypeOf.


Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Monday, October 03, 2016 11:13:52 Jonathan M Davis via Digitalmars-d wrote:
> template isStaticMember(T, string member)
> {
> static if (!__traits(hasMember, T, member))
> enum bool isStaticMember = false;
> else
> {
> import std.meta : AliasSeq;
> import std.traits : FunctionTypeOf;
> alias sym = AliasSeq!(__traits(getMember, T, member))[0];
>
> static if (__traits(isStaticFunction, sym))
> enum bool isStaticMember = true;
> else static if (is(FunctionTypeOf!sym == function) &&
> is(FunctionTypeOf!(typeof(&sym)) == function))
> {
> enum bool isStaticMember = false;
> }
> else
> {
> enum bool isStaticMember = !__traits(compiles, sym.offsetof) &&
>__traits(compiles, &sym);
> }
> }
> }

Well, since I took the time to write it, I created a PR for it:

https://github.com/dlang/phobos/pull/4834

So, if anyone sees problems with my implementation, go poke holes in it.

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Ali Çehreli via Digitalmars-d

On 10/03/2016 07:41 AM, Seb wrote:

On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:

Fill in the blank...
I'm having a really hard time with this. I've made it work with a
mountain of code, and I want to see what others come up with...

If you succeed, put it in std.traits!

Recommend, use latest DMD nightly. I find differences with latest
nightly vs release.


See also:

http://stackoverflow.com/questions/39430684/check-if-class-member-is-static


Appeared on dlang forum as well: :)

  http://forum.dlang.org/post/nni8lp$1ihk$1...@digitalmars.com

Ali



Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Monday, October 03, 2016 08:38:22 Jonathan M Davis via Digitalmars-d wrote:
> On Monday, October 03, 2016 23:19:19 Manu via Digitalmars-d wrote:
> > Fill in the blank...
> > I'm having a really hard time with this. I've made it work with a
> > mountain of code, and I want to see what others come up with...
>
> It's certainly possible that this misses something, but it passes all of
> your test cases:
>
> template isStaticMember(T, string member)
> {
> static if(!__traits(hasMember, T, member))
> enum bool isStaticMember = false;
> else
> {
> import std.meta : AliasSeq;
> import std.traits : FunctionTypeOf;
> alias sym = AliasSeq!(__traits(getMember, T, member))[0];
> static if(__traits(isStaticFunction, sym))
> enum bool isStaticMember = true;
> else static if(is(FunctionTypeOf!sym == function) &&
>is(FunctionTypeOf!(typeof(&sym)) == function))
> {
> enum bool isStaticMember = false;
> }
> else
> {
> enum bool isStaticMember = !__traits(compiles, sym.offsetof) &&
>!is(sym == enum) &&
>!is(sym == class) &&
>!is(sym == struct) &&
>__traits(compiles, &sym);
> }
> }
> }

Actually, it can be reduced even further:

template isStaticMember(T, string member)
{
static if (!__traits(hasMember, T, member))
enum bool isStaticMember = false;
else
{
import std.meta : AliasSeq;
import std.traits : FunctionTypeOf;
alias sym = AliasSeq!(__traits(getMember, T, member))[0];

static if (__traits(isStaticFunction, sym))
enum bool isStaticMember = true;
else static if (is(FunctionTypeOf!sym == function) &&
is(FunctionTypeOf!(typeof(&sym)) == function))
{
enum bool isStaticMember = false;
}
else
{
enum bool isStaticMember = !__traits(compiles, sym.offsetof) &&
   __traits(compiles, &sym);
}
}
}

Checking for the address makes it unnecessary to check for enums, classes,
or structs.

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Monday, October 03, 2016 23:19:19 Manu via Digitalmars-d wrote:
> Fill in the blank...
> I'm having a really hard time with this. I've made it work with a
> mountain of code, and I want to see what others come up with...

It's certainly possible that this misses something, but it passes all of
your test cases:

template isStaticMember(T, string member)
{
static if(!__traits(hasMember, T, member))
enum bool isStaticMember = false;
else
{
import std.meta : AliasSeq;
import std.traits : FunctionTypeOf;
alias sym = AliasSeq!(__traits(getMember, T, member))[0];
static if(__traits(isStaticFunction, sym))
enum bool isStaticMember = true;
else static if(is(FunctionTypeOf!sym == function) &&
   is(FunctionTypeOf!(typeof(&sym)) == function))
{
enum bool isStaticMember = false;
}
else
{
enum bool isStaticMember = !__traits(compiles, sym.offsetof) &&
   !is(sym == enum) &&
   !is(sym == class) &&
   !is(sym == struct) &&
   __traits(compiles, &sym);
}
}
}

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Jonathan M Davis via Digitalmars-d
On Monday, October 03, 2016 23:19:19 Manu via Digitalmars-d wrote:
> Fill in the blank...
> I'm having a really hard time with this. I've made it work with a
> mountain of code, and I want to see what others come up with...
>
> If you succeed, put it in std.traits!
>
> Recommend, use latest DMD nightly. I find differences with latest
> nightly vs release.
>
> 
> --- template isStaticMember(T, string member)
> {
>   enum bool isStaticMember = [code goes here];
> }
>
>
> struct S
> {
>   enum X = 10;
>   enum Y
>   {
> i = 10
>   }
>   struct S {}
>   class C {}
>
>   static int x = 0;
>   __gshared int y = 0;
>   static void f() {}
>   static void f2() pure nothrow @nogc @safe {}
>
>   shared void g() {}
>
>   static void function() fp;
>   __gshared void function() gfp;
>   void function() fpm;
>
>   void m() {}
>   final void m2() const pure nothrow @nogc @safe {}
>
>   inout(int) iom() inout { return 10; }
>   static inout(int) iosf(inout int x) { return x; }
>
>   @property int p() { return 10; }
>   static @property int sp() { return 10; }
> }
>
> class C
> {
>   enum X = 10;
>   enum Y
>   {
> i = 10
>   }
>   struct S {}
>   class C {}
>
>   static int x = 0;
>   __gshared int y = 0;
>   static void f() {}
>   static void f2() pure nothrow @nogc @safe {}
>
>   shared void g() {}
>
>   static void function() fp;
>   __gshared void function() gfp;
>   void function() fpm;
>
>   void m() {}
>   final void m2() const pure nothrow @nogc @safe {}
>
>   inout(int) iom() inout { return 10; }
>   static inout(int) iosf(inout int x) { return x; }
>
>   @property int p() { return 10; }
>   static @property int sp() { return 10; }
> }
>
> static assert(!isStaticMember!(S, "X"), "!");
> static assert(!isStaticMember!(S, "Y"), "!");
> static assert(!isStaticMember!(S, "Y.i"), "!");
> static assert(!isStaticMember!(S, "S"), "!");
> static assert(!isStaticMember!(S, "C"), "!");
> static assert( isStaticMember!(S, "x"), "!");
> static assert( isStaticMember!(S, "y"), "!");
> static assert( isStaticMember!(S, "f"), "!");
> static assert( isStaticMember!(S, "f2"), "!");
> static assert(!isStaticMember!(S, "g"), "!");
> static assert( isStaticMember!(S, "fp"), "!");
> static assert( isStaticMember!(S, "gfp"), "!");
> static assert(!isStaticMember!(S, "fpm"), "!");
> static assert(!isStaticMember!(S, "m"), "!");
> static assert(!isStaticMember!(S, "m2"), "!");
> static assert(!isStaticMember!(S, "iom"), "!");
> static assert( isStaticMember!(S, "iosm"), "!");
> static assert(!isStaticMember!(S, "p"), "!");
> static assert( isStaticMember!(S, "sp"), "!");
>
> static assert(!isStaticMember!(C, "X"), "!");
> static assert(!isStaticMember!(C, "Y"), "!");
> static assert(!isStaticMember!(C, "Y.i"), "!");
> static assert(!isStaticMember!(C, "S"), "!");
> static assert(!isStaticMember!(C, "C"), "!");
> static assert( isStaticMember!(C, "x"), "!");
> static assert( isStaticMember!(C, "y"), "!");
> static assert( isStaticMember!(C, "f"), "!");
> static assert( isStaticMember!(C, "f2"), "!");
> static assert(!isStaticMember!(C, "g"), "!");
> static assert( isStaticMember!(C, "fp"), "!");
> static assert( isStaticMember!(C, "gfp"), "!");
> static assert(!isStaticMember!(C, "fpm"), "!");
> static assert(!isStaticMember!(C, "m"), "!");
> static assert(!isStaticMember!(C, "m2"), "!");
> static assert(!isStaticMember!(C, "iom"), "!");
> static assert( isStaticMember!(C, "iosm"), "!");
> static assert(!isStaticMember!(C, "p"), "!");
> static assert( isStaticMember!(C, "sp"), "!");

I would point out that iosm is missing from both the struct and the class,
so it can't be true for isStaticMember. I assume that you meant for it to be
iosf, which _is_ declared?

- Jonathan M Davis



Re: Challenge

2016-10-03 Thread Seb via Digitalmars-d

On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:

Fill in the blank...
I'm having a really hard time with this. I've made it work with 
a

mountain of code, and I want to see what others come up with...

If you succeed, put it in std.traits!

Recommend, use latest DMD nightly. I find differences with 
latest nightly vs release.


See also:

http://stackoverflow.com/questions/39430684/check-if-class-member-is-static


Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 3 October 2016 at 23:48, Manu  wrote:
> On 3 October 2016 at 23:41, Manu  wrote:
>> I'm finding this rather annoying:
>>
>> struct S
>> {
>>   static @property int p() { return 10; }
>> }
>>
>> pragma(msg, typeof(&S.p)); // prints: int function() @property
>> pragma(msg, is(typeof(&S.p) == function)); // prints: false
>>
>> It looks like a function... but I can't identify it as a function!
>
> I guess that should read: is(typeof(&S.p) == R function(A), R, A...)) ??


Here's a leg-up:

template isStaticMember(T, string member)
{
  mixin("alias M = T." ~ member ~ ";");
  static if(__traits(compiles, &M))
  {
static if(!is(typeof(M) == function))
{
  static if(is(typeof(&M) == R function(A), R, A...))
  {
import std.traits : functionAttributes, FunctionAttribute;
enum isStaticMember = (functionAttributes!M &
FunctionAttribute.property) && /* distinguish static/non-static
@property somehow */ */;
  }
  else
enum isStaticMember = true;
}
else
{
  enum isStaticMember = __traits(isStaticFunction, M);
}
  }
  else
enum isStaticMember = false;
}


Re: Challenge

2016-10-03 Thread John Colvin via Digitalmars-d

On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:

Fill in the blank...
I'm having a really hard time with this. I've made it work with 
a

mountain of code, and I want to see what others come up with...


template isStaticMember(T, string member)
{
mixin(`alias mem = T.` ~ member ~ `;`);
import std.traits : FunctionTypeOf;
static if (is(FunctionTypeOf!mem == function) && 
is(FunctionTypeOf!(typeof(&mem)) == function))
enum bool isStaticMember = __traits(isStaticFunction, 
mem);

else
enum bool isStaticMember = is(typeof(&mem));
}

Basically, using FunctionTypeOf catches @property functions 
(which just typeof wouldn't), but it also catches member 
variables with function types, so we need the second 
FunctionTypeOf to see if it's still a function when you take its 
address (true for member functions, including @property 
functions, not true for member variables with function types).


Everything else is just "can you take the address of this".


Re: Challenge

2016-10-03 Thread Temtaime via Digitalmars-d

On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:

Fill in the blank...
I'm having a really hard time with this. I've made it work with 
a

mountain of code, and I want to see what others come up with...

[...]


Dere's a typo

static assert( isStaticMember!(S, "iosm"), "!");

Should be iosf

Easy:

template isStaticMember(T, string member)
{
static if(__traits(compiles, &__traits(getMember, T, member)))
{
		static if(is(FunctionTypeOf!(__traits(getMember, T, member)) == 
function))

{
			enum isStaticMember = isFunctionPointer!(__traits(getMember, 
T, member)) || isDelegate!(__traits(getMember, T, member)) || 
__traits(isStaticFunction, __traits(getMember, T, member));

}
else
{
			enum isStaticMember = true;//!is(typeof(__traits(getMember, T, 
member).offsetof));

}
}
else
{
enum isStaticMember = false;
}
}


Re: Challenge

2016-10-03 Thread Kagamin via Digitalmars-d

On Monday, 3 October 2016 at 13:41:13 UTC, Manu wrote:

I'm finding this rather annoying:

struct S
{
  static @property int p() { return 10; }
}

pragma(msg, typeof(&S.p)); // prints: int function() @property
pragma(msg, is(typeof(&S.p) == function)); // prints: false

It looks like a function... but I can't identify it as a 
function!


https://dlang.org/phobos/std_traits.html#isSomeFunction ?


Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 3 October 2016 at 23:50, John Colvin via Digitalmars-d
 wrote:
> On Monday, 3 October 2016 at 13:41:13 UTC, Manu wrote:
>>
>> I'm finding this rather annoying:
>>
>> struct S
>> {
>>   static @property int p() { return 10; }
>> }
>>
>> pragma(msg, typeof(&S.p)); // prints: int function() @property
>> pragma(msg, is(typeof(&S.p) == function)); // prints: false
>>
>> It looks like a function... but I can't identify it as a function!
>
>
> The problem is that function pointers in "is" expressions don't match
> "function" or "delegate".
>
> static assert (is(void delegate() == delegate)); //passes
> static assert (is(void function() == function)); //fails
> static assert (is(void function() == delegate)); //fails
>
> Bug report?

Nar, I just forgot about this well-known edge. 'function' means
something different in is(); it means a proper-function, *not* a
function pointer. if(X == R function(A), R, A...) will test for
function pointers.
It's still hard though, @property's are hard to detect, and I am
really struggling to distinguish between static and non-static
properties without testing for assignments, which is terrible.


Re: Challenge

2016-10-03 Thread Dicebot via Digitalmars-d

On Monday, 3 October 2016 at 13:50:26 UTC, John Colvin wrote:
The problem is that function pointers in "is" expressions don't 
match "function" or "delegate".


static assert (is(void delegate() == delegate)); //passes
static assert (is(void function() == function)); //fails
static assert (is(void function() == delegate)); //fails

Bug report?


Note that there is at least some code that relies on current 
behavior to distinguish delegate/function fields from method 
declarations in aggregates.


Re: Challenge

2016-10-03 Thread Dicebot via Digitalmars-d

On Monday, 3 October 2016 at 13:41:13 UTC, Manu wrote:

I'm finding this rather annoying:

struct S
{
  static @property int p() { return 10; }
}

pragma(msg, typeof(&S.p)); // prints: int function() @property
pragma(msg, is(typeof(&S.p) == function)); // prints: false

It looks like a function... but I can't identify it as a 
function!



It works if both:

a) you remove @property
b) you don't convert it to function pointer

struct S
{
   static int p() { return 10; }
}

pragma(msg, is(typeof(S.p) == function); // true

Sadly `is(X == function)` is very obscure and confusing because 
it doesn't do what one may expect it to do. In current form it 
can only be used if something is a function declaration, 
everything else is `false`. It is not even possible to manually 
express a type which will pass `is(T == function)`, you can only 
get `true` by applying `typeof` to existing function declaration.


And @property screws it because the only current effect of 
property is exactly changing result of `typeof(propertyFoo)` from 
function type to result type.


Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
On 3 October 2016 at 23:41, Manu  wrote:
> I'm finding this rather annoying:
>
> struct S
> {
>   static @property int p() { return 10; }
> }
>
> pragma(msg, typeof(&S.p)); // prints: int function() @property
> pragma(msg, is(typeof(&S.p) == function)); // prints: false
>
> It looks like a function... but I can't identify it as a function!

I guess that should read: is(typeof(&S.p) == R function(A), R, A...)) ??


Re: Challenge

2016-10-03 Thread John Colvin via Digitalmars-d

On Monday, 3 October 2016 at 13:41:13 UTC, Manu wrote:

I'm finding this rather annoying:

struct S
{
  static @property int p() { return 10; }
}

pragma(msg, typeof(&S.p)); // prints: int function() @property
pragma(msg, is(typeof(&S.p) == function)); // prints: false

It looks like a function... but I can't identify it as a 
function!


The problem is that function pointers in "is" expressions don't 
match "function" or "delegate".


static assert (is(void delegate() == delegate)); //passes
static assert (is(void function() == function)); //fails
static assert (is(void function() == delegate)); //fails

Bug report?


Re: Challenge

2016-10-03 Thread Andrea Fontana via Digitalmars-d

On Monday, 3 October 2016 at 13:19:19 UTC, Manu wrote:

Fill in the blank...
I'm having a really hard time with this. I've made it work with 
a

mountain of code, and I want to see what others come up with...

If you succeed, put it in std.traits!


Pretty easy:
template isStaticMember(T, string member)
{
  enum bool isStaticMember =
	!(member=="X" || member=="Y" || member=="Y.i"  || member=="S"  
|| member=="C" ||
	member=="g"  || member=="fpm" || member=="m" || member=="m2" || 
member=="iom"  || member=="p");

}

Ok, I'm joking.




Re: Challenge

2016-10-03 Thread Manu via Digitalmars-d
I'm finding this rather annoying:

struct S
{
  static @property int p() { return 10; }
}

pragma(msg, typeof(&S.p)); // prints: int function() @property
pragma(msg, is(typeof(&S.p) == function)); // prints: false

It looks like a function... but I can't identify it as a function!


Challenge

2016-10-03 Thread Manu via Digitalmars-d
Fill in the blank...
I'm having a really hard time with this. I've made it work with a
mountain of code, and I want to see what others come up with...

If you succeed, put it in std.traits!

Recommend, use latest DMD nightly. I find differences with latest
nightly vs release.

---
template isStaticMember(T, string member)
{
  enum bool isStaticMember = [code goes here];
}


struct S
{
  enum X = 10;
  enum Y
  {
i = 10
  }
  struct S {}
  class C {}

  static int x = 0;
  __gshared int y = 0;
  static void f() {}
  static void f2() pure nothrow @nogc @safe {}

  shared void g() {}

  static void function() fp;
  __gshared void function() gfp;
  void function() fpm;

  void m() {}
  final void m2() const pure nothrow @nogc @safe {}

  inout(int) iom() inout { return 10; }
  static inout(int) iosf(inout int x) { return x; }

  @property int p() { return 10; }
  static @property int sp() { return 10; }
}

class C
{
  enum X = 10;
  enum Y
  {
i = 10
  }
  struct S {}
  class C {}

  static int x = 0;
  __gshared int y = 0;
  static void f() {}
  static void f2() pure nothrow @nogc @safe {}

  shared void g() {}

  static void function() fp;
  __gshared void function() gfp;
  void function() fpm;

  void m() {}
  final void m2() const pure nothrow @nogc @safe {}

  inout(int) iom() inout { return 10; }
  static inout(int) iosf(inout int x) { return x; }

  @property int p() { return 10; }
  static @property int sp() { return 10; }
}

static assert(!isStaticMember!(S, "X"), "!");
static assert(!isStaticMember!(S, "Y"), "!");
static assert(!isStaticMember!(S, "Y.i"), "!");
static assert(!isStaticMember!(S, "S"), "!");
static assert(!isStaticMember!(S, "C"), "!");
static assert( isStaticMember!(S, "x"), "!");
static assert( isStaticMember!(S, "y"), "!");
static assert( isStaticMember!(S, "f"), "!");
static assert( isStaticMember!(S, "f2"), "!");
static assert(!isStaticMember!(S, "g"), "!");
static assert( isStaticMember!(S, "fp"), "!");
static assert( isStaticMember!(S, "gfp"), "!");
static assert(!isStaticMember!(S, "fpm"), "!");
static assert(!isStaticMember!(S, "m"), "!");
static assert(!isStaticMember!(S, "m2"), "!");
static assert(!isStaticMember!(S, "iom"), "!");
static assert( isStaticMember!(S, "iosm"), "!");
static assert(!isStaticMember!(S, "p"), "!");
static assert( isStaticMember!(S, "sp"), "!");

static assert(!isStaticMember!(C, "X"), "!");
static assert(!isStaticMember!(C, "Y"), "!");
static assert(!isStaticMember!(C, "Y.i"), "!");
static assert(!isStaticMember!(C, "S"), "!");
static assert(!isStaticMember!(C, "C"), "!");
static assert( isStaticMember!(C, "x"), "!");
static assert( isStaticMember!(C, "y"), "!");
static assert( isStaticMember!(C, "f"), "!");
static assert( isStaticMember!(C, "f2"), "!");
static assert(!isStaticMember!(C, "g"), "!");
static assert( isStaticMember!(C, "fp"), "!");
static assert( isStaticMember!(C, "gfp"), "!");
static assert(!isStaticMember!(C, "fpm"), "!");
static assert(!isStaticMember!(C, "m"), "!");
static assert(!isStaticMember!(C, "m2"), "!");
static assert(!isStaticMember!(C, "iom"), "!");
static assert( isStaticMember!(C, "iosm"), "!");
static assert(!isStaticMember!(C, "p"), "!");
static assert( isStaticMember!(C, "sp"), "!");


Re: Challenge: fair partition function

2016-02-08 Thread Xinok via Digitalmars-d
On Monday, 8 February 2016 at 23:25:00 UTC, Andrei Alexandrescu 
wrote:
Consider defining a function that partitions a range around a 
given index like this:


size_t pivotPartition(alias less = (a, b) => a < b, Range)
(Range r, size_t pivot);

Returns x, one of the the indexes that r[pivot] would have if r 
were sorted. Also, r[0 .. x] contains stuff no greater than 
r[x] and r[x + 1 .. $] contains stuff no less than r[x].


The challenge is to implement such a function with fairness: if 
several elements are equal to r[pivot], return the index 
closest to r.length / 2.


The function should be efficient, minimize calls to less and 
swap, etc. A variant that is efficient but does not implement 
fairness is below.


...


Ultimately, I think you're going to have to perform two 
comparisons on *some* elements to check for equality. I thought 
of a few tricks which may or may not help.




(1) Keep your code as is and add a final pass to count the number 
of elements. However, you only need to scan the larger partition 
since it contains the index (r.length / 2) and you're trying to 
move closer to that point. The elements in the smaller partition 
can simply be ignored.




(2) You may have code which looks something like this:

if(less(e, pivot)){ /+ less than +/ }
else if(less(pivot, e)){ /+ greater than +/ }
else{ /+ equal to +/ }}

This is a big win if most of the elements are less than the 
pivot, but also a big loss if most of the elements are greater 
than the pivot. A simple trick is to repeat the code twice but 
swap the order of comparisons so you get:


if(less(pivot, e)){ /+ greater than +/ }
else if(less(e, pivot)){ /+ less than +/ }
else{ /+ equal to +/ }}

This will place us closer to an average 1.5 comparisons per 
element which is better than (1).




(3) Similar to (2) except you only compare each element once so 
you're not checking for equality. You're simply alternating 
between checking if (e < pivot) or if (pivot < e). So the code 
may look something like this:


if(less(pivot, e)){ less }
else{ greater or equal }

if(less(e, pivot)){ greater }
else{ less or equal }

From this, you can group the elements into four partitions:

[LE L G GE]

So you have elements which are definitely less than or greater 
than the pivot but also some elements which *may* be equal to the 
pivot. Combine this with the first trick (1) and you only have to 
scan LE or GE for equality but not both. This is putting us 
closer to an average 1.25 comparisons per element but a 4-way 
partition would also require much more work.


Challenge: fair partition function

2016-02-08 Thread Andrei Alexandrescu via Digitalmars-d
Consider defining a function that partitions a range around a given 
index like this:


size_t pivotPartition(alias less = (a, b) => a < b, Range)
(Range r, size_t pivot);

Returns x, one of the the indexes that r[pivot] would have if r were 
sorted. Also, r[0 .. x] contains stuff no greater than r[x] and r[x + 1 
.. $] contains stuff no less than r[x].


The challenge is to implement such a function with fairness: if several 
elements are equal to r[pivot], return the index closest to r.length / 2.


The function should be efficient, minimize calls to less and swap, etc. 
A variant that is efficient but does not implement fairness is below.



Andrei


size_t pivotPartition(alias less = (a, b) => a < b, Range)
(Range r, size_t pivot)
{
assert(pivot < r.length || r.length == 0 && pivot == 0);
if (r.length <= 1) return 0;
import std.algorithm : swapAt;
r.swapAt(pivot, 0);
size_t lo = 1, hi = r.length - 1;
loop: for (;;)
{
for (;; ++lo)
{
if (lo > hi) break loop;
if (less(r[0], r[lo])) break;
}
// found the left bound
assert(lo <= hi);
for (;; --hi)
{
if (lo == hi) break loop;
if (less(r[hi], r[0])) break;
}
// found the right bound, swap & make progress
r.swapAt(lo++, hi--);
}
--lo;
r.swapAt(lo, 0);
return lo;
}


Re: Challenge

2015-08-30 Thread anonymous via Digitalmars-d
On Sunday 30 August 2015 16:43, rsw0x wrote:

> Is there any reason that closure in this particular example can't
> be created on the stack? Seems a bit weird.

It may be possible to store it on the stack somehow, or as part of the map 
struct. I don't know.

The point is, that's not what happens. It goes on the GC heap, breaking 
@nogc.



Re: Challenge

2015-08-30 Thread rsw0x via Digitalmars-d

On Sunday, 30 August 2015 at 13:36:45 UTC, anonymous wrote:

On Sunday 30 August 2015 12:21, rsw0x wrote:


[...]


I think this shouldn't compile and it only does so because of 
issue 14771.


https://issues.dlang.org/show_bug.cgi?id=14771

The delegate in foo uses a local variable and it's returned 
from the function, so it needs a closure. Where does the 
closure go if not on the GC heap?


See also this Learn thread about how to call map with a 
delegate in a @nogc function:


http://forum.dlang.org/post/kpwbtskhnkkiwkdsf...@forum.dlang.org

Ali Çehreli's solution there may or may not actually be @nogc, 
but I'm afraid it relies on issue 14771 any way:


http://forum.dlang.org/post/mqr506$10kf$1...@digitalmars.com


Is there any reason that closure in this particular example can't 
be created on the stack? Seems a bit weird.


Re: Challenge

2015-08-30 Thread anonymous via Digitalmars-d
On Sunday 30 August 2015 12:21, rsw0x wrote:

> import std.algorithm, std.range;
> 
> auto foo(R)(R a, immutable int b)
> {
>  return a.map!(x => x + b);
> }
> 
> @nogc @safe unittest
> {
>  int[3] test = [1,2,3];
> 
>  assert(test[].foo(3).equal(only(4,5,6)));
> }
> 
> does this count?

I think this shouldn't compile and it only does so because of issue 14771.

https://issues.dlang.org/show_bug.cgi?id=14771

The delegate in foo uses a local variable and it's returned from the 
function, so it needs a closure. Where does the closure go if not on the GC 
heap?

See also this Learn thread about how to call map with a delegate in a @nogc 
function:

http://forum.dlang.org/post/kpwbtskhnkkiwkdsf...@forum.dlang.org

Ali Çehreli's solution there may or may not actually be @nogc, but I'm 
afraid it relies on issue 14771 any way:

http://forum.dlang.org/post/mqr506$10kf$1...@digitalmars.com


Re: Challenge

2015-08-30 Thread John Colvin via Digitalmars-d

On Sunday, 30 August 2015 at 11:21:34 UTC, Russel Winder wrote:
On Sun, 2015-08-30 at 10:38 +, John Colvin via 
Digitalmars-d wrote:

On Sunday, 30 August 2015 at 10:15:14 UTC, John Colvin wrote:
> [...]

Ok, so now I feel stupid. Not only was the unittest I gave 
above broken anyway, I realised what my underlying problem was 
within minutes of posting...


So what was the problem?


Carry on, nothing to see here...


See above…


https://issues.dlang.org/show_bug.cgi?id=14982 was confusing me.


Re: Challenge

2015-08-30 Thread Russel Winder via Digitalmars-d
On Sun, 2015-08-30 at 10:38 +, John Colvin via Digitalmars-d wrote:
> On Sunday, 30 August 2015 at 10:15:14 UTC, John Colvin wrote:
> > import std.algorithm, std.range;
> > 
> > auto foo(R)(R a, immutable int b)
> > {
> > return a.map!(x => x + b);
> > }
> > 
> > unittest @nogc @safe
> > {
> > int[] test = [1,2,3];
> > 
> > assert(test.foo(3).equal(only(4,5,6)));
> > }
> > 
> > Challenge: reimplement `foo` such that above unittest will 
> > compile. No cheating with malloc etc. Bonus points if you don't 
> > have to implement a modified version of std.algorithm.map
> 
> Ok, so now I feel stupid. Not only was the unittest I gave above 
> broken anyway, I realised what my underlying problem was within 
> minutes of posting...

So what was the problem?

> Carry on, nothing to see here...

See above…

-- 
Russel.
=
Dr Russel Winder  t: +44 20 7585 2200   voip: sip:russel.win...@ekiga.net
41 Buckmaster Roadm: +44 7770 465 077   xmpp: rus...@winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder




Re: Challenge

2015-08-30 Thread John Colvin via Digitalmars-d

On Sunday, 30 August 2015 at 10:15:14 UTC, John Colvin wrote:

import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

unittest @nogc @safe
{
int[] test = [1,2,3];

assert(test.foo(3).equal(only(4,5,6)));
}

Challenge: reimplement `foo` such that above unittest will 
compile. No cheating with malloc etc. Bonus points if you don't 
have to implement a modified version of std.algorithm.map


Ok, so now I feel stupid. Not only was the unittest I gave above 
broken anyway, I realised what my underlying problem was within 
minutes of posting...


Carry on, nothing to see here...


Re: Challenge

2015-08-30 Thread rsw0x via Digitalmars-d

On Sunday, 30 August 2015 at 10:21:20 UTC, rsw0x wrote:

On Sunday, 30 August 2015 at 10:15:14 UTC, John Colvin wrote:

import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

unittest @nogc @safe
{
int[] test = [1,2,3];

assert(test.foo(3).equal(only(4,5,6)));
}

Challenge: reimplement `foo` such that above unittest will 
compile. No cheating with malloc etc. Bonus points if you 
don't have to implement a modified version of std.algorithm.map


import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

@nogc @safe unittest
{
int[3] test = [1,2,3];

assert(test[].foo(3).equal(only(4,5,6)));
}

does this count?


Oh, I think I see what you were asking. It doesn't compile with 
LDC, but it compiles just fine with latest DMD.

hmm


Re: Challenge

2015-08-30 Thread rsw0x via Digitalmars-d

On Sunday, 30 August 2015 at 10:15:14 UTC, John Colvin wrote:

import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

unittest @nogc @safe
{
int[] test = [1,2,3];

assert(test.foo(3).equal(only(4,5,6)));
}

Challenge: reimplement `foo` such that above unittest will 
compile. No cheating with malloc etc. Bonus points if you don't 
have to implement a modified version of std.algorithm.map


import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

@nogc @safe unittest
{
int[3] test = [1,2,3];

assert(test[].foo(3).equal(only(4,5,6)));
}

does this count?


Challenge

2015-08-30 Thread John Colvin via Digitalmars-d

import std.algorithm, std.range;

auto foo(R)(R a, immutable int b)
{
return a.map!(x => x + b);
}

unittest @nogc @safe
{
int[] test = [1,2,3];

assert(test.foo(3).equal(only(4,5,6)));
}

Challenge: reimplement `foo` such that above unittest will 
compile. No cheating with malloc etc. Bonus points if you don't 
have to implement a modified version of std.algorithm.map


Re: Today's programming challenge - How's your Range-Fu ?

2015-04-21 Thread John Colvin via Digitalmars-d

On Tuesday, 21 April 2015 at 13:06:22 UTC, JohnnyK wrote:

On Monday, 20 April 2015 at 19:24:01 UTC, Panke wrote:

On Monday, 20 April 2015 at 18:03:50 UTC, John Colvin wrote:

On Monday, 20 April 2015 at 17:48:17 UTC, Panke wrote:
To measure the columns needed to print a string, you'll need 
the number of graphemes. (d|)?string.length gives you the 
number of code units.


Even that's not really true.


Why? Doesn't string.length give you the byte count?


I was talking about the "you'll need the number of graphemes". 
s.length returns the number of elements in the slice, which in 
the case of D's string types gives is the same as the number of 
code units.



I think what you are looking for is string.sizeof?

From the D reference

.sizeof	Returns the array length multiplied by the number of 
bytes per array element.
.length	Returns the number of elements in the array. This is a 
fixed quantity for static arrays. It is of type size_t.


That is for static arrays only. .sizeof for slices is just 
size_t.sizeof + T*.sizeof i.e. 8 on 32 bit, 16 on 64 bit.


Re: Today's programming challenge - How's your Range-Fu ?

2015-04-21 Thread JohnnyK via Digitalmars-d

On Monday, 20 April 2015 at 19:24:01 UTC, Panke wrote:

On Monday, 20 April 2015 at 18:03:50 UTC, John Colvin wrote:

On Monday, 20 April 2015 at 17:48:17 UTC, Panke wrote:
To measure the columns needed to print a string, you'll need 
the number of graphemes. (d|)?string.length gives you the 
number of code units.


Even that's not really true.


Why? Doesn't string.length give you the byte count?


I think what you are looking for is string.sizeof?

From the D reference

.sizeof	Returns the array length multiplied by the number of 
bytes per array element.
.length	Returns the number of elements in the array. This is a 
fixed quantity for static arrays. It is of type size_t.



Isn't a string type an array of characters (char[] string UTF-8, 
wchar[] string UTF-16, and dchar[] string UTF-32) and not 
arbitrary bytes?


Re: Today's programming challenge - How's your Range-Fu ?

2015-04-20 Thread rumbu via Digitalmars-d

On Monday, 20 April 2015 at 19:24:01 UTC, Panke wrote:

On Monday, 20 April 2015 at 18:03:50 UTC, John Colvin wrote:

On Monday, 20 April 2015 at 17:48:17 UTC, Panke wrote:
To measure the columns needed to print a string, you'll need 
the number of graphemes. (d|)?string.length gives you the 
number of code units.


Even that's not really true.


Why? Doesn't string.length give you the byte count?


You'll also need the unicode character display width:
Even if the font is monospaced, there are characters (Katakana, 
Hangul and even in Latin script) with variable width.



ABCDEFGH
ABCDEFGH (unicode 0xff21 through 0xff27).

If the text above is not correctly displayed on your computer, a 
Korean console can be viewed here:


http://upload.wikimedia.org/wikipedia/commons/1/14/KoreanDOSPrompt.png





Re: Today's programming challenge - How's your Range-Fu ?

2015-04-20 Thread Panke via Digitalmars-d

On Monday, 20 April 2015 at 18:03:50 UTC, John Colvin wrote:

On Monday, 20 April 2015 at 17:48:17 UTC, Panke wrote:
To measure the columns needed to print a string, you'll need 
the number of graphemes. (d|)?string.length gives you the 
number of code units.


Even that's not really true.


Why? Doesn't string.length give you the byte count?


Re: Today's programming challenge - How's your Range-Fu ?

2015-04-20 Thread Chris via Digitalmars-d

On Monday, 20 April 2015 at 17:48:17 UTC, Panke wrote:
This can lead to subtle bugs, cf. length of random and e_one. 
You have to convert everything to dstring to get the 
"expected" result. However, this is not always desirable.


There are three things that you need to be aware of when 
handling unicode: code units, code points and graphems.


This is why I use a helper function that uses byCodePoint and 
byGrapheme. At least for my use cases it returns the correct 
length. However, I might think about an alternative version based 
on the discussion here.


In general the length of one guarantees anything about the 
length of the other, except for utf32, which is a 1:1 mapping 
between code units and code points.


In this thread, we were discussing the relationship between 
code points and graphemes. You're examples however apply to the 
relationship between code units and code points.


To measure the columns needed to print a string, you'll need 
the number of graphemes. (d|)?string.length gives you the 
number of code units.


If you normalize a string (in the sequence of 
characters/codepoints sense, not object.string) to NFC, it will 
decompose every precomposed character in the string (like é, 
single codeunit), establish a defined order between the 
composite characters and then recompose a selected few 
graphemes (like é). This way é always ends up as a single code 
unit in NFC. There are dozens of other combinations where 
you'll still have n:1 mapping between code points and graphemes 
left after normalization.


Example given already in this thread: putting an arrow over an 
latin letter is typical in math and always more than one 
codepoint.




  1   2   3   4   5   6   >