What's opIndexAssign supposed to return ?

2020-02-25 Thread wjoe via Digitalmars-d-learn

Lets say I've got 3 overloads of opIndexAssign:

auto opIndexAssign(T t);
auto opIndexAssign(T t, size_t i); and
auto opIndexAssign(T t, size_t[2] i);

I would assume to return what I would return with opIndex but I'd 
rather not act upon assumptions.
But if yes is it supposed to be the newly assigned values or the 
pre-assignment ones ? By value or by reference ? And if it's the 
new stuff can I just return t ?


The language manual on operator overloading didn't answer that 
question and neither did an internet search which didn't find any 
useful information. Something unrelated and a heads up about 
introducing opIndexAssign from 2004.





Re: What's opIndexAssign supposed to return ?

2020-02-25 Thread Petar via Digitalmars-d-learn

On Tuesday, 25 February 2020 at 11:02:40 UTC, wjoe wrote:

Lets say I've got 3 overloads of opIndexAssign:

auto opIndexAssign(T t);
auto opIndexAssign(T t, size_t i); and
auto opIndexAssign(T t, size_t[2] i);

I would assume to return what I would return with opIndex but 
I'd rather not act upon assumptions.
But if yes is it supposed to be the newly assigned values or 
the pre-assignment ones ? By value or by reference ? And if 
it's the new stuff can I just return t ?


The language manual on operator overloading didn't answer that 
question and neither did an internet search which didn't find 
any useful information. Something unrelated and a heads up 
about introducing opIndexAssign from 2004.


opIndexAssign is the operator used in the following code:

arr[1] = 8;

It returns the element at index 1 (so 8 in this case) by 
reference.

This allows you to do:

(arr[1] = 8)++;
assert(arr[1] == 9);

Whether or not you want to support this behavior in your custom 
data structure is up to you. It's perfectly valid to return the 
element by value or even return void.


Returning void from any custom assignment operator is always a 
safe choice. It's possible that some algorithms (e.g. in Phobos 
or third-party libraries) may need op*Assign to return something, 
but in that unlikely case you'll get a compile-time error, so it 
will be an easy fix.




Re: What's opIndexAssign supposed to return ?

2020-02-25 Thread wjoe via Digitalmars-d-learn
On Tuesday, 25 February 2020 at 11:49:50 UTC, Petar Kirov 
[ZombineDev] wrote:

On Tuesday, 25 February 2020 at 11:02:40 UTC, wjoe wrote:

[...]


opIndexAssign is the operator used in the following code:

arr[1] = 8;

It returns the element at index 1 (so 8 in this case) by 
reference.

This allows you to do:

(arr[1] = 8)++;
assert(arr[1] == 9);

Whether or not you want to support this behavior in your custom 
data structure is up to you. It's perfectly valid to return the 
element by value or even return void.


Returning void from any custom assignment operator is always a 
safe choice. It's possible that some algorithms (e.g. in Phobos 
or third-party libraries) may need op*Assign to return 
something, but in that unlikely case you'll get a compile-time 
error, so it will be an easy fix.


Excellent answer ! Thanks for your fast reply :)


Re: What's opIndexAssign supposed to return ?

2020-02-25 Thread Ali Çehreli via Digitalmars-d-learn
On 2/25/20 3:02 AM, wjoe wrote:> Lets say I've got 3 overloads of 
opIndexAssign:

>
> auto opIndexAssign(T t);

> an internet search which didn't find any useful
> information.

I have examples for non-templatized and templatized versions of 
opIndexAssign here:



http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.opIndexAssign


http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.opIndexAssign%20template

I used this index to find those:

  http://ddili.org/ders/d.en/ix.html

Ali



Re: 2D matrix operation (subtraction)

2020-02-25 Thread jmh530 via Digitalmars-d-learn

On Saturday, 22 February 2020 at 08:29:32 UTC, 9il wrote:

[snip]

Maybe mir.series [1] can work for you.


I had a few other thoughts after looking at septc's solution of 
using

y[0..$, 0] *= 100;
to do the calculation.

1) There is probably scope for an additional select function to 
handle the use case of choosing a specific row/column. For 
instance, what if instead of

y[0..$, 0]
you want
y[0..$, b, 0..$]
for some arbitrary b. I think you would need to do something like
y.select!1(b, b + 1);
which doesn't have the best API, IMO, because you have to repeat 
b. Maybe just an overload for select that only takes one input 
instead of two?


2) The select series of functions does not seem to work as easily 
as array indexing does. When I tried to use the 
select/selectFront functions to do what he is doing, I had to 
something like

auto z = y.selectFront!1(1);
z[] *= 100;
This would adjust y as expected (not z). However, I couldn't 
figure out how to combine these together to one line. For 
instance, I couldn't do

y.selectFront!1(1) *= 100;
or
auto y = x.selectFront!1(1).each!(a => a * 100);
though something like
y[0..$, 0].each!"a *= 100";
works without issue.

It got a little frustrating to combine those with any kind of 
iteration. TBH, I think more than the select functions, the 
functionality I would probably be looking for is more what I was 
doing with byDim!1[0] in the prior post.


I could imagine some very simple version looking like below
auto selectDim(size_t dim, T)(T x, size_t a, size_t b) {
return byDim!dim[a .. b];
}
with a corresponding version
auto selectDim(size_t dim, T)(T x, size_t a) {
return byDim!dim[a .. (a + 1)];
}
This simple version would only work with one dimension, even 
though byDim can handle multiple.


Re: What's opIndexAssign supposed to return ?

2020-02-25 Thread wjoe via Digitalmars-d-learn

On Tuesday, 25 February 2020 at 15:30:19 UTC, Ali Çehreli wrote:
On 2/25/20 3:02 AM, wjoe wrote:> Lets say I've got 3 overloads 
of opIndexAssign:

>
> auto opIndexAssign(T t);

> an internet search which didn't find any useful
> information.

I have examples for non-templatized and templatized versions of 
opIndexAssign here:



http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.opIndexAssign


http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.opIndexAssign%20template

I used this index to find those:

  http://ddili.org/ders/d.en/ix.html

Ali


This is great! Thank you. Curious why this wasn't found by my 
internet search.


library dependencies nightmare, D edition

2020-02-25 Thread Marcel via Digitalmars-d-learn

Hello!
I have two libraries, where library B depends on library A, where 
both libraries consist of multiple packages. Say my project (I'm 
using VisualD) folder layout is the following:


C/:
   libA
  A_Package1
  A_Package2
  A_Package3
   libB
  B_Package1 - Imports from libA.Package2
  B_Package2
  B_Package3
  Executable Module - Imports from libB.Package1

Why am I getting "Error: module "Package1" is in file 
libA\Package2 which cannot be read" messages? I tried changing 
the folder layout so that LibA is inside a dependencies folder 
inside LibB, but nothing changed. What am I missing?




Re: library dependencies nightmare, D edition

2020-02-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/25/20 4:31 PM, Marcel wrote:

Hello!
I have two libraries, where library B depends on library A, where both 
libraries consist of multiple packages. Say my project (I'm using 
VisualD) folder layout is the following:


C/:
    libA
   A_Package1
   A_Package2
   A_Package3
    libB
   B_Package1 - Imports from libA.Package2
   B_Package2
   B_Package3
   Executable Module - Imports from libB.Package1

Why am I getting "Error: module "Package1" is in file libA\Package2 
which cannot be read" messages? I tried changing the folder layout so 
that LibA is inside a dependencies folder inside LibB, but nothing 
changed. What am I missing?




It would be most helpful to have actual messages, because you might be 
missing something.


Several causes for such errors:

1. You are trying to read a file that it cannot find given the command 
line parameters
2. The file has a module that is different from the actual package/file 
it is in.


Could be something else too. Maybe you have the same package name from 
both libraries? That should work, as long as you don't define the same 
module in both packages.


-Steve


Re: library dependencies nightmare, D edition

2020-02-25 Thread Marcel via Digitalmars-d-learn
On Tuesday, 25 February 2020 at 21:48:00 UTC, Steven 
Schveighoffer wrote:

On 2/25/20 4:31 PM, Marcel wrote:

Hello!
I have two libraries, where library B depends on library A, 
where both libraries consist of multiple packages. Say my 
project (I'm using VisualD) folder layout is the following:


C/:
    libA
   A_Package1
   A_Package2
   A_Package3
    libB
   B_Package1 - Imports from libA.Package2
   B_Package2
   B_Package3
   Executable Module - Imports from libB.Package1

Why am I getting "Error: module "Package1" is in file 
libA\Package2 which cannot be read" messages? I tried changing 
the folder layout so that LibA is inside a dependencies folder 
inside LibB, but nothing changed. What am I missing?




It would be most helpful to have actual messages, because you 
might be missing something.


Several causes for such errors:

1. You are trying to read a file that it cannot find given the 
command line parameters
2. The file has a module that is different from the actual 
package/file it is in.


Could be something else too. Maybe you have the same package 
name from both libraries? That should work, as long as you 
don't define the same module in both packages.


-Steve


I can't give you the actual error messages right now, but both 
libraries have packages that define modules with the same name. 
For example, both libraries have packages with a module called 
"utility.d". Unfortunately, this isn't the only thing that causes 
compilation to fail though.


Re: library dependencies nightmare, D edition

2020-02-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/25/20 5:26 PM, Marcel wrote:


I can't give you the actual error messages right now, but both libraries 
have packages that define modules with the same name. For example, both 
libraries have packages with a module called "utility.d". Unfortunately, 
this isn't the only thing that causes compilation to fail though.


is this imported via:

import utility;

? or is it

import packagea.utility;

?

If the former, then that is definitely a problem I think. Two libraries 
can have the same package name, but cannot have the same top-level 
module name (you can't split modules).


But I think you might have a different error for that condition.

Make sure that whatever module it is complaining about has a correct 
module declaration in both libraries.


i.e. even if you have:

packagea/utility.d
packageb/utility.d

and you import via:

import packagea.utility;

make sure packagea/utility.d has the module declaration:

module packagea.utility;

-Steve


Re: library dependencies nightmare, D edition

2020-02-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Feb 25, 2020 at 10:26:48PM +, Marcel via Digitalmars-d-learn wrote:
[...]
> I can't give you the actual error messages right now, but both
> libraries have packages that define modules with the same name. For
> example, both libraries have packages with a module called
> "utility.d". Unfortunately, this isn't the only thing that causes
> compilation to fail though.

Are these top-level modules?  If they are contained under packages,
e.g., package1.utility vs. package2.utility, it shouldn't be a problem.

>From what you described, though, it looks like your compile command is
missing some -I flags.  I don't use VisualD so I can't help you in the
details, but if there's some settings somewhere for include paths, that
might be what you need to fix this problem.


T

-- 
People who are more than casually interested in computers should have at least 
some idea of what the underlying hardware is like. Otherwise the programs they 
write will be pretty weird. -- D. Knuth


Re: library dependencies nightmare, D edition

2020-02-25 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 25 February 2020 at 22:26:48 UTC, Marcel wrote:
For example, both libraries have packages with a module called 
"utility.d".


This is why I now have a strict policy that ALL modules must have 
at least a two part name; company.utility or whatever.


alas not everyone follows that :(


Re: library dependencies nightmare, D edition

2020-02-25 Thread Marcel via Digitalmars-d-learn
On Tuesday, 25 February 2020 at 22:35:07 UTC, Steven 
Schveighoffer wrote:

On 2/25/20 5:26 PM, Marcel wrote:


I can't give you the actual error messages right now, but both 
libraries have packages that define modules with the same 
name. For example, both libraries have packages with a module 
called "utility.d". Unfortunately, this isn't the only thing 
that causes compilation to fail though.


is this imported via:

import utility;

? or is it

import packagea.utility;

?

If the former, then that is definitely a problem I think. Two 
libraries can have the same package name, but cannot have the 
same top-level module name (you can't split modules).


But I think you might have a different error for that condition.

Make sure that whatever module it is complaining about has a 
correct module declaration in both libraries.


i.e. even if you have:

packagea/utility.d
packageb/utility.d

and you import via:

import packagea.utility;

make sure packagea/utility.d has the module declaration:

module packagea.utility;

-Steve


The issue isn't with the module declaration, it is declared and 
imported as package1.utility. I think its an issue with VisualD's 
feature of adding import paths of project dependencies...




Strange counter-performance in an alternative `decimalLength9` function

2020-02-25 Thread Basile B. via Digitalmars-d-learn
So after reading the translation of RYU I was interested too see 
if the decimalLength() function can be written to be faster, as 
it cascades up to 8 CMP.


After struggling with bad ideas I finally find something that 
looks nice:


- count the leading zero of the input
- switch() this count to have in the worst of the cases only 1 
CMP (when the bit number possibly changes the digit count, e.g 9 
-> 10 (when bsr(input) == 4)


after writing all the values allowing to know the cases where a 
comparison is necessary...


  min2 = 0b10
  max2 = 0b11
  min3 = 0b100
  max3 = 0b111
  ...
  ...
  min32 = 0b100...0
  max32 = 0b111...1

...I finally write the "nice" thing.

---
#!dmd -boundscheck=off -O -release -inline
import std.stdio;

ubyte decimalLength9(const uint v)
{
if (v >= 1) { return 9; }
if (v >= 1000) { return 8; }
if (v >= 100) { return 7; }
if (v >= 10) { return 6; }
if (v >= 1) { return 5; }
if (v >= 1000) { return 4; }
if (v >= 100) { return 3; }
if (v >= 10) { return 2; }
return 1;
}

ubyte fdecimalLength9(const uint v) pure nothrow
{
import core.bitop;
const ubyte lzc = cast(ubyte) (bsr(v) + 1);
ubyte result;
switch (lzc)
{
case 0 :
case 1 :
case 2 :
case 3 : result =  1; break;
case 4 : result =  v >= 10  ? 2 : 1; break;
case 5 :
case 6 : result =  2; break;
case 7 : result =  v >= 100  ? 3 : 2; break;
case 8 :
case 9 : result =  3; break;
case 10: result =  v >= 1000  ? 4 : 3; break;
case 11:
case 12:
case 13: result =  4; break;
case 14: result =  v >= 1  ? 5 : 4; break;
case 15:
case 16: result =  5; break;
case 17: result =  v >= 10  ? 6 : 5; break;
case 18:
case 19: result =  6; break;
case 20: result =  v >= 100  ? 7 : 6; break;
case 21:
case 22:
case 23: result =  7; break;
case 24: result =  v >= 1000  ? 8 : 7; break;
case 25:
case 26: result =  8; break;
case 27: result =  v >= 1  ? 9 : 8; break;
case 28:
case 29:
case 30:
case 31:
case 32: result =  9; break;
default: assert(false);
}
return result;
}

private ubyte ffdecimalLength9(const uint v) pure nothrow
{
import core.bitop;
const ubyte lzc = cast(ubyte) (bsr(v) + 1);
static immutable pure nothrow ubyte function(uint)[33] tbl =
[
0 : (uint a) => ubyte(1),
1 : (uint a) => ubyte(1),
2 : (uint a) => ubyte(1),
3 : (uint a) => ubyte(1),
4 : (uint a) => a >= 10  ? ubyte(2) : ubyte(1),
5 : (uint a) => ubyte(2),
6 : (uint a) => ubyte(2),
7 : (uint a) => a >= 100  ? ubyte(3) : ubyte(2),
8 : (uint a) => ubyte(3),
9 : (uint a) => ubyte(3),
10: (uint a) => a >= 1000  ? ubyte(4) : ubyte(3),
11: (uint a) => ubyte(4),
12: (uint a) => ubyte(4),
13: (uint a) => ubyte(4),
14: (uint a) => a >= 1  ? ubyte(5) : ubyte(4),
15: (uint a) => ubyte(5),
16: (uint a) => ubyte(5),
17: (uint a) => a >= 10  ? ubyte(6) : ubyte(5),
18: (uint a) => ubyte(6),
19: (uint a) => ubyte(6),
20: (uint a) => a >= 100  ? ubyte(7) : ubyte(6),
21: (uint a) => ubyte(7),
22: (uint a) => ubyte(7),
23: (uint a) => ubyte(7),
24: (uint a) => a >= 1000  ? ubyte(8) : ubyte(7),
25: (uint a) => ubyte(8),
26: (uint a) => ubyte(8),
27: (uint a) => a >= 1  ? ubyte(9) : ubyte(8),
28: (uint a) => ubyte(9),
29: (uint a) => ubyte(9),
30: (uint a) => ubyte(9),
31: (uint a) => ubyte(9),
32: (uint a) => ubyte(9),
];
return tbl[lzc](v);
}

void main()
{
import std.datetime.stopwatch, std.range, std.algorithm;

int s1, s2, s3;
benchmark!({ iota(1u).each!(a => s1 += 
decimalLength9(a+1)); })(10).writeln;
benchmark!({ iota(1u).each!(a => s2 += 
fdecimalLength9(a+1));})(10).writeln;
benchmark!({ iota(1u).each!(a => s3 += 
ffdecimalLength9(a+1));})(10).writeln;

assert(s1 == s2);
assert(s1 == s3);
}
---

Then bad surprise. Even with ldmd (so ldc2 basically) feeded with 
the args from the script line. Maybe the fdecimalLength9 version 
is slightly faster. Only *slightly*. Good news, I've lost my 
time. So I try an alternative version that uses a table of 
delegates instead of a switch (ffdecimalLength9) and surprise, 
"tada", it is like **100x** slower then the two others.


How is that possible ?


Re: Strange counter-performance in an alternative `decimalLength9` function

2020-02-25 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Feb 26, 2020 at 12:50:35AM +, Basile B. via Digitalmars-d-learn 
wrote:
[...]
> #!dmd -boundscheck=off -O -release -inline
[...]

TBH, I'm skeptical of any performance results using dmd.  I wouldn't pay
attention to performance numbers obtained this way, and rather look at
the ldmd/ldc2 numbers.


[...]
> Then bad surprise. Even with ldmd (so ldc2 basically) feeded with the
> args from the script line. Maybe the fdecimalLength9 version is
> slightly faster.  Only *slightly*. Good news, I've lost my time. So I
> try an alternative version that uses a table of delegates instead of a
> switch (ffdecimalLength9) and surprise, "tada", it is like **100x**
> slower then the two others.
> 
> How is that possible ?

Did you check the assembly output to see what the difference is?

Delegates involve a function call, which involves function call
overhead, which includes a CPU pipeline hazard.  Worse yet it's an
indirect call, meaning you're defeating the CPU branch predictor and
invalidating the instruction cache. And on top of that, delegates
involve allocating a context, and you *really* do not want allocations
inside an inner loop.

And of course, normal function calls are easier for compilers to inline,
because the destination is fixed. Indirect calls involving delegates are
hard to predict, and the optimizer is more liable to just give up.

These are just my educated guesses, of course.  For the real answer,
look at the assembly output. :-D


T

-- 
What are you when you run out of Monet? Baroque.


Re: Strange counter-performance in an alternative `decimalLength9` function

2020-02-25 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 26 February 2020 at 01:10:07 UTC, H. S. Teoh wrote:
On Wed, Feb 26, 2020 at 12:50:35AM +, Basile B. via 
Digitalmars-d-learn wrote: [...]

#!dmd -boundscheck=off -O -release -inline

[...]

TBH, I'm skeptical of any performance results using dmd.  I 
wouldn't pay attention to performance numbers obtained this 
way, and rather look at the ldmd/ldc2 numbers.


I didn't use DMD. The script line is actually interpreted by the 
IDE. It drops the compiler name and just parse the arg and pass 
them to a compiler that's defined by non overridable options. In 
my case I used LDMD (this is LDC you see, but with a DMD like 
options syntax)