Re: How use ldc pragmas?

2021-10-02 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 1 October 2021 at 19:23:06 UTC, james.p.leblanc wrote:

D-ers,


Update from myself to myself (and any others who might use the 
bash

command from my origin posting),


I try to compile the above using:


```bash
ldc2 -mattr=+avx2 myexample.d -H  
~/ldc2/import/ldc/gccbuiltins_x86.di

```

Remove the "-H ..." this should not be used (based on an earlier 
misunderstanding

of mine).  Instead, simply use:

```bash
ldc2 -mattr=+avx2 myexample.d
```

Cheers,
jpl




Re: How use ldc pragmas?

2021-10-01 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 1 October 2021 at 20:19:39 UTC, Imperatorn wrote:




Take a look at my post ;)


YES!
===


Thanks to both Imperatorn, and Max for their helpful and quick 
responses.

The problem is SOLVED!

I didn't realize that the pragma had to be placed outside of the 
main() ...
but it seems that I should have known this!  (Tomorrow, I shall 
dive into

the deeper waters with avx2.)

Sometimes, getting a simple example to build from can be the 
hardest part, eh?


Thanks Again,
James





Re: How use ldc pragmas?

2021-10-01 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 1 October 2021 at 19:58:30 UTC, max haughton wrote:

On Friday, 1 October 2021 at 19:23:06 UTC, james.p.leblanc


Is it sqrt.32 or sqrt.f32? Try the latter, LLVM docs seem to 
agree.


Hello Max,

Thanks for the correction... unfortunately, even after changing 
the "32",
to "f32", **I receive the same error**.  So there is something of 
a bigger

nature that **I am still doing wrong.**

I should have noted earlier that I am just trying to mirror the 
docs found at:


https://wiki.dlang.org/LDC-specific_language_changes

```d
// provide square root intrinsics
pragma(LDC_intrinsic, "llvm.sqrt.f32")
  float sqrt(float);
pragma(LDC_intrinsic, "llvm.sqrt.f64")
  double sqrt(double);
pragma(LDC_intrinsic, "llvm.sqrt.f80")
  real sqrt(real); // x86 only
```

Any additional hints for ldc instrinsics are greatly appreciated.
James





How use ldc pragmas?

2021-10-01 Thread james.p.leblanc via Digitalmars-d-learn

D-ers,

After experimenting with ldc's autovectorization of avx code, it 
appears there may
be counter-intuitiveness to the autovectorization (especially for 
complex numbers).

(My comment may be wrong, so any corrections are quite welcome).

Based on this, I wanted to investigate the use of ldc's pragma 
capabilities

(as found in ldc2/import/gccbuiltins_x86.di).

However, getting the ball rolling is a bit difficult, as I have 
not found a
simple example showing the whole process.  What I have just now 
is:


```d
// my example.d
import std.stdio;
import ldc.intrinsics;

void main()
{
   writeln("hello");

   float x;

   pragma(LDC_intrinsic, "llvm.sqrt.32")
   float sqrt(float);
}
```
I try to compile the above using:

```bash
ldc2 -mattr=+avx2 myexample.d -H 
~/ldc2/import/ldc/gccbuiltins_x86.di

```

But receive the following:
```console
ldcint.d(11): Error: unrecognized `pragma(LDC_intrinsic)`
```

I get the feeling that I am really "lost in the woods" here, 
probably

missing important aspects.

Are there any pointers this forum might have to help here?
(A very simple and complete example would be greatly appreciated!)

Thanks!
James



Re: Rather Bizarre slow downs using Complex!float with avx (ldc).

2021-10-01 Thread james.p.leblanc via Digitalmars-d-learn

On Thursday, 30 September 2021 at 16:52:57 UTC, Johan wrote:

On Thursday, 30 September 2021 at 16:40:03 UTC, james.p.leblanc


Generally, for performance issues like this you need to study 
assembly output (`--output-s`) or LLVM IR (`--output-ll`).

First thing I would look out for is function inlining yes/no.

cheers,
  Johan


Johan,

Thanks kindly for your reply.  As suggested, I have looked at the 
assembly output.


Strangely the fused multiplay add are indeed there in the avx 
version, but example

still runs slower for **Complex!float** data type.

I have stripped the code down to a minimum, which demonstrates 
the weird result:




```d

import ldc.attributes;  // with or without this line makes no 
difference

import std.stdio;
import std.datetime.stopwatch;
import std.complex;

alias T = Complex!float;
auto typestr = "COMPLEX FLOAT";
/* alias T = Complex!double; */
/* auto typestr = "COMPLEX DOUBLE"; */

auto alpha = cast(T) complex(0.1, -0.2);  // dummy values to fill 
arrays

auto beta = cast(T) complex(-0.7, 0.6);

auto dotprod( T[] x, T[] y)
{
   auto sum = cast(T) 0;
  foreach( size_t i ; 0 .. x.length)
 sum += x[i] * conj(y[i]);
   return sum;
}

void main()
{
   int nEle = 1000;
   int nIter = 2000;

   auto startTime = MonoTime.currTime;
   auto dur = cast(double) 
(MonoTime.currTime-startTime).total!"usecs";


   T[] x, y;
   x.length = nEle;
   y.length = nEle;
   T z;
   x[] = alpha;
   y[] = beta;

   startTime = MonoTime.currTime;
   foreach( i ; 0 .. nIter){
  foreach( j ; 0 .. nIter){
z = dotprod(x,y);
  }
   }
   auto etime = cast(double) 
(MonoTime.currTime-startTime).total!"msecs" / 1.0e3;
   writef(" result:  % 5.2f%+5.2fi  comp time:  %5.2f \n", z.re, 
z.im, etime);

}
```

For convenience I include bash script used compile/run/generate 
assembly code / and grep:


```bash
echo
echo "With AVX:"
ldc2 -O3 -release question.d --ffast-math -mcpu=haswell
question
ldc2 -output-s -O3 -release question.d --ffast-math -mcpu=haswell
mv question.s question_with_avx.s

echo
echo "Without AVX"
ldc2 -O3 -release question.d
question
ldc2 -output-s -O3 -release question.d
mv question.s question_without_avx.s

echo
echo "fused multiply adds are found in avx code (as desired)"
grep vfmadd *.s /dev/null
```

Here is output when run on my machine:

```console
With AVX:
 result:  -190.00+80.00i  comp time:   6.45

Without AVX
 result:  -190.00+80.00i  comp time:   5.74

fused multiply adds are found in avx code (as desired)
question_with_avx.s:vfmadd231ss %xmm2, %xmm5, %xmm3
question_with_avx.s:vfmadd231ss %xmm0, %xmm2, %xmm3
question_with_avx.s:vfmadd231ss %xmm2, %xmm4, %xmm1
question_with_avx.s:vfmadd231ss %xmm3, %xmm5, %xmm1
question_with_avx.s:vfmadd231ss %xmm3, %xmm1, %xmm0

```

Repeating the experiment after changing to datatype of 
Complex!double
shows AVX code to be twice as fast (perhaps more aligned with 
expectations).


**I admit my confusion as to why the Complex!float is 
misbehaving.**


Does anyone have insight to what is happening?

Thanks,
James




Rather Bizarre slow downs using Complex!float with avx (ldc).

2021-09-30 Thread james.p.leblanc via Digitalmars-d-learn

D-Ers,

I have been getting counterintuitive results on avx/no-avx timing
experiments.  Storyline to date (notes at end):

**Experiment #1)** Real float data type (i.e. non-complex 
numbers),

speed comparison.
  a)  moving from non-avx --> avx shows non-realistic speed up of 
15-25 X.

  b)  this is weird, but story continues ...

**Experiment #2)** Real double data type (non-complex numbers),
  a)  moving from non-avx --> avx again shows amazing gains, but 
the
  gains are about half of those seen in Experiment #1, so 
maybe

  this looks plausible?

**Experiment #3)**  Complex!float datatypes:
  a)  now **going from non-avx to avx shows a serious performance 
LOSS**

  of 40% to breaking even at best.  What is happening here?

**Experiment #4)**  Complex!double:
  a)  non-avx --> avx shows performancegains again about 2X (so 
the

  gains appear to be reasonable).


The main question I have is:

**"What is going on with the Complex!float performance?"**  One 
might expect

floats to have a better perfomance than doubles as we saw with the
real-value data (becuase of vector packaging, memory bandwidth, 
etc).


But, **Complex!float shows MUCH WORSE avx performance than 
Complex!Double

(by a factor of almost 4).**

```d
//Table of Computation Times
//
//   self math  std math
// explicit  no-explicit   explicit  no-explicit
//   align  alignalign  align
//   0.12   0.21  0.15  0.21 ;  # Float with AVX
//   3.23   3.24  3.30  3.22 ;  # Float without 
AVX

//   0.31   0.42  0.31  0.42 ;  # Double with AVX
//   3.25   3.24  3.24  3.27 ;  # Double without 
AVX
//   6.42   6.62  6.61  6.59 ;  # Complex!float 
with AVX
//   4.04   4.17  6.68  5.82 ;  # Complex!float 
without AVX
//   1.67   1.69  1.73  1.71 ;  # Complex!double 
with AVX
//   3.34   3.42  3.28  3.31# Complex!double 
without AVX

```

Notes:

1) Based on forum hints from ldc experts, I got good guidance
   on enabling avx ( i.e. compiling modules on command line, using
   --fast-math and -mcpu=haswell on command line).

2) From Mir-glas experts I received hints to try to implement own 
version
   of the complex math.  (this is what the "self-math" column 
refers to).


I understand that detail of the computations are not included 
here, (I
can do that if there is interest, and if I figure out an 
effective way to present

it in a forum.)

But, I thought I might begin with a simple question, **"Is there 
some well-known
issue that I am missing here".  Have others been done this road 
as well?**


Thanks for any and all input.
Best Regards,
James

PS  Sorry for the inelegant table ... I do not believe there is a 
way
to include the beautiful bars charts on this forum.  Please 
correct me

if there is a way...)



Re: Modules ... "import" vs. "compilation" ... what is the real process here?

2021-09-27 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 28 September 2021 at 05:26:29 UTC, Ali Çehreli wrote:

On 9/27/21 10:38 AM, james.p.leblanc wrote:




In addition to what Mike Parker said, templates do complicate 
matters here: Templates are instantiated (i.e. compiled for a 
specific set of template arguments) by modules that actually 
use those templates.



Ali


Ali, this is great! ...I had been tempted to also ask about how 
templates
figure into this, but realized that including this in my question 
would be

over complicating the question, so it remained unasked.

But, now I have this part answered as well.  I very much 
appreciate the

mind-reading tricks going on here on the forum!

Thank You, and Best Regards,
James




Re: Modules ... "import" vs. "compilation" ... what is the real process here?

2021-09-27 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 28 September 2021 at 02:05:43 UTC, Mike Parker wrote:

On Monday, 27 September 2021 at 17:38:29 UTC, james.p.leblanc
mpilations".



Does that help?


**Yes!...**
===
 ... this helped immensely!


This explanation gave me a much better understanding of how the
whole process works.

Mike, thanks very much for the time and thought you put into this.

Best Regards,
James







Modules ... "import" vs. "compilation" ... what is the real process here?

2021-09-27 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

I have trouble understanding "module imports" vs. "module 
compilations".


For example, in the dlang.org/tour, we have:

**"The import statement makes all public functions and types from 
the given module available."**


And from the dlang.org/spec we have:

**"Modules are always compiled at global scope and are unaffected 
by surrounding attributes or other modifiers."**


Finally, there have been discussions about allowing new ways of 
"compiling a module" by including its name on the command line.  
For example this from 2017:


https://forum.dlang.org/post/tcrdpvqvwxffnewzo...@forum.dlang.org

The more I look into this, the more that I realize that I do not 
understand this as well as I had hoped.


So, when we specify the module name on the command line, then it 
gets compiled along with the other files on the command line 
(seems reasonable).


But, if it is NOT a command line argument, then when does it get 
compiled??
(I believe that at first cut, only the public functions and types 
are "grabbed").


But, when and how are the subsequent and necessary module 
compilation (and linking) steps performed?


Finally, we use a "-I" for telling dmd to look for imports in a 
directory, but why only
"look for imports", and not "grab anything from there that is 
used, AND compile them"?


(This question is prompted by some recent desires to use ldc and 
"fastmath"... which, if I
understand correctly, will require me to include all of the 
related modules on the command
line for immediate compilation).  But, in a broader sense, I need 
to understand the related issues better.


Thank for all responses, as well as continued patience with my 
questions.


Best Regards,
James




Re: AVX for math code ... avx instructions later disappearing ?

2021-09-26 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 26 September 2021 at 19:00:54 UTC, kinke wrote:
On Sunday, 26 September 2021 at 18:08:46 UTC, james.p.leblanc 
wrote:

or even moving the array declarations to before
the dot product function, and the avx instructions will 
disappear!


That's because the `@fastmath` UDA applies to the next 
declaration only, which is the `x` array in your 2nd example 
(where it obviously has no effect). Either use `@fastmath:` 
with the colon to apply it to the entire scope, or use 
`-ffast-math` in the LDC cmdline.


Similarly, when moving the function to another module and you 
don't include that module in the cmdline, it's only imported 
and not compiled and won't show up in the resulting assembly.


Wrt. stack alignment, there aren't any issues with LDC AFAIK 
(not limited to 16 or whatever like DMD).


Kinke,

Thanks very much for your response.  There were many issues that I
had been misunderstanding in my attempts.  The provided 
explanation

helped me understand the broader scope of what is happening.

(I never even thought about the @fastmath UDA aspect! ... a bit
embarrassing for me!)  Using the -ffast-math in the LDC
cmdline seems to be a most elegant solution.

Much appreciated!
Regards,
James





AVX for math code ... avx instructions later disappearing ?

2021-09-26 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

I enjoyed reading some details of incorporating AVX into math code
from Johan Engelen's programming blog post:

http://johanengelen.github.io/ldc/2016/10/11/Math-performance-LDC.html

Basically, one can use the ldc compiler to insert avx code, nice!

In playing with some variants of his example code, I realize
that there are issues I do not understand.  For example, the 
following

code successfully incorporates the avx instructions:

```d
// File here is called dotFirst.d
import ldc.attributes : fastmath;
@fastmath

double dot( double[] a, double[] b)
{
double s = 0.0;
foreach (size_t i; 0 .. a.length) {
s += a[i] * b[i];
}
return s;
}

double[8] x =[0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, ];
double[8] y =[0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, ];

void main()
{
double z = 0.0;
z = dot(x, y);
}
```
If we run:

ldc2 -c -output-s -O3 -release dotFirst.d -mcpu=haswell
echo "Results of grep ymm dotFirst.s:"
grep ymm dotFirst.s

The "grep" shows a number of vector instructions, such as:

**vfmadd132pd 160(%rcx,%rdi,8), %ymm5, %ymm1**

However, subtle changes in the code (such as moving the dot 
product
function to a module, or even moving the array declarations to 
before

the dot product function, and the avx instructions will disappear!

```d
import ldc.attributes : fastmath;
@fastmath

double[8] x =[0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, ];
double[8] y =[0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, ];

double dot( double[] a, double[] b)
{
double s = 0.0;
foreach (size_t i; 0 .. a.length) {
...

```
Now a grep will not find a single **ymm**.

It is understood that ldc needs proper alignment to be able to do 
the vector

instructions...

**But my question is:**   how is proper alignment guaranteed? 
(Most importantly
how guaranteed among code using modules)??  (There are related 
stack alignment

issues -- 16?)

Best Regards,
James


PS I have come across scattered bits of (sometimes contradictory) 
information on

avx/simd for dlang.  Is there a canonical source for vector info?







Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 20:32:36 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:


```
Produces:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z5): question.main.MapResult!(__lambda2, 
JSONValue[]).MapResult, z5: [true, false, true]

z5: [true, false, true]



Sigh ... my suggested "minor edit" above produces a "map result" 
instead of
the desired native array ... here is the **fix** by appending 
".array" at the
end (which is the suffix Steve originally offered).  The 
following gives

the desired **bool[]** result.

```d
import std.array;

   auto z5 = jj["ba"].array.map!(v => v.get!bool).array;
   writeln("typeid(z5): ", typeid(z5), ", z5: ", z5);
   writeln("z5: ", z5);
```

Regards,
James





Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,



Here comes a minor update (small rearrangement in mapping/array 
ordering)
for anyone who may be interested.  With this small edit to the 
suggested code,

it works just fine!  Here:


 ```d

   auto z5 = jj["ba"].array.map!(v => v.get!bool);

   writeln("typeid(z5): ", typeid(z5), ", z5: ", z5);
   writeln("z5: ", z5);

```
Produces:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z5): question.main.MapResult!(__lambda2, 
JSONValue[]).MapResult, z5: [true, false, true]

z5: [true, false, true]


Cheers,
James




Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native"



How you really do this:

```d
import std.algorithm : map;
auto z5 = jj["ba"] // get the JSONValue that is at the key "ba"
  .map!(v => v.get!bool) // map each value into a boolean
  .array // create an array out of the results;
assert z5 == [true, false, true];
```

(warning, untested)

-Steve


Steve,

Your thorough explanations have helped me understand quite much.
Thank you for your energy and patience in these forum 
contributions.


In fact, I had begun to think that "map", may be what was needed 
here
and I had made a few naive attempts ... but this did not go so 
well.
With your suggested solution, I believe I can make headway on 
this.


Thanks Again,
James




Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native" 
array types,

I have hit some issues.  Example code:

```d
import std.stdio;
import std.json;

void main(){

   JSONValue jj;
   jj["d"] = [ 1.234 ];  // a "dummy" double value
   jj["ba"] = [ true, false, true];  // "ba" boolean array

   writeln("typeid(jj): ", typeid(jj), ", jj: ", jj );

   // various things that I thought might work, but do NOT

   auto z1 = cast(bool)   jj["ba"];   // attempt #1
   auto z2 = cast(bool[]) jj["ba"];   // attempt #2
   auto z3 = cast(bool)   jj["ba"].array; // attempt #3
   auto z4 = cast(bool[]) jj["ba"].array; // attempt #4
   writeln("typeid(z4): ", typeid(z4), ", z4: ", z4 );

}
```
Attempts 1,2, and 3 yield compilation errors (which I somewhat 
understand):


question.d(12): Error: cannot cast expression `jj.opIndex("ba")` 
of type `JSONValue` to `bool`
question.d(13): Error: cannot cast expression `jj.opIndex("ba")` 
of type `JSONValue` to `bool[]`
question.d(14): Error: cannot cast expression 
`jj.opIndex("ba").array()` of type `JSONValue[]` to `bool`


However, if I comment out the offending attempts (1, 2, and 3), 
then it
compiles, and can run ... but produces a result which I very much 
do NOT

understand:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z4): bool[], z4: [false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, true, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, true, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, true, false, false, false, 
false, false, false, false]


H... is there a standard way to push these JSONValues into 
nice native
array types? (The real code is eventually going to be using 
traits and mixins

... but I do not think this should pose additional problems).

All help and illumination thankfully received.
Best Regards,
James







Re: Merge 2 structs together (into a single struct)?

2021-09-16 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 17 September 2021 at 00:36:42 UTC, ag0aep6g wrote:

On 16.09.21 22:53, jfondren wrote:

string joinstruct(A, B)(string name) {


struct JoinStruct(Structs ...)
{
static foreach (S; Structs)
{
static foreach (i, alias f; S.tupleof)
{
mixin("typeof(f) ", __traits(identifier, f),
" = S.init.tupleof[i];");




Ali, jfondren, ag0aep6g,

All of your responses are greatly appreciated.  I have done test 
implementations
of them all, and they work well with my intended application. 
(Also, I learned

something new from all of them).

The struct mixin template appears to be quite robust and elegant. 
 So, I include a
simple implementation for any future readers to take it for a 
"test drive".


```d

import std.stdio;
import std.traits;

template JoinStruct(Structs ...)
{
   static foreach (S; Structs)
   {
  static foreach(i, alias f; S.tupleof)
  {
 mixin("typeof(f) ", __traits(identifier, f), " = 
S.init.tupleof[i];");

  }
   }
}

void main(){

   struct A {
  int alpha;
  float x = 1.23;
   }

   struct B {
  int beta;
  float y = 4.4;
  string s = "this is fine.";
   }

   struct C {
  int gamma = 42;
  double z = 1.2e8;
  string t = "if this was named 's', duplicate would be 
detected at compile time";

   }

   struct D {
  mixin JoinStruct!(A,B,C);
   }

   A a;
   B b;
   C c;

   writeln("\na:", a);
   writeln("\nb:", b);
   writeln("\nc:", c)
   auto d = D();
   writeln("\nd:", d);
}

```

My next steps would be to include some UDA's to ease the getopt 
building
for command line arguments.  There is a sketch from Jesse 
Phillips at


https://dev.to/jessekphillips/argument-parsing-into-structure-4p4n

For example:

```d
// Specify The Parameter Structure
struct Options
{
   @Option("threads", "t")
   @Help("Number of threads to use.")
   size_t threads;

   @Option("file")
   @Help("Input files")
   string[] files;
}
```

Again, thanks to you and many of the D community with helping to 
learn and

appreciate the capabilities of D.  It is nice to be here.

Best Regards,
James





Merge 2 structs together (into a single struct)?

2021-09-16 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

I really thought that this would be a simple enough
small project in meta programming/reflection.  Consisely,
merge two structures, which are coming from two different
elements of the code base.  (One contains standard input
options for getopt, and the other is for user customization
for getopt.)

And while there are many hints, and partial solutions among
forum posts, and books, my many attempts have not been
successful.

Is there some obvious, and simple solution to this
conundrum of mine?

```d
struct A
{
   int alpha;
   float x = 1.23;
}

struct B
{
   int beta;
   float y = 4.4;
   string s = "this is fine.";
}

```
  some static foreach magic, and mixins later ... we have the 
merger


```d
 struct AB
{
   int alpha;
   float x = 1.23;
   int beta;
   float y = 4.4;
   string s = "this is fine.";
}
```
... the point of this is really to use the struct AB
for getopt reading of command line options.

All pointers, tips and info are greatly appreciated.
Best Regards,
James




Re: How can we view source code that has been generated (say via "static foreach") ?

2021-09-15 Thread james.p.leblanc via Digitalmars-d-learn

On Thursday, 16 September 2021 at 03:26:46 UTC, Tejas wrote:
On Wednesday, 15 September 2021 at 19:59:43 UTC, 
james.p.leblanc wrote:

s


Use the `mixin` compiler flag

`dmd -mixin= file.d`

Beware, this will also include **all** the mixin code from 
standard library and runtime.


But it's manageable, reflecting on my experience.


Tejas,

Thank you for your kind response.  Wow, at first the large output 
file
from a small test program was a bit surprising .., but actually 
it is

manageable to dig through to find the interesting bits.

So, this is quite useful!  Thanks again, now I am off to do some 
digging...


Best Regards,
James




How can we view source code that has been generated (say via "static foreach") ?

2021-09-15 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

In attempting to learn and use code generation, it
would be useful to be able to view the source code
that gets generated.

However, with various combinations of templates, UDAs, and
mixins it has not been easy.

Is there some standard way this is done?

Optimal would be to print out the entire generated source
code to allow inspection.

Best Regards,
James







Re: Curious effect with traits, meta, and a foreach loop ... mystifies me.

2021-09-09 Thread james.p.leblanc via Digitalmars-d-learn

On Thursday, 9 September 2021 at 05:37:35 UTC, Tejas wrote:

On Thursday, 9 September 2021 at 05:32:29 UTC, Tejas wrote:
On Tuesday, 7 September 2021 at 17:47:15 UTC, james.p.leblanc 
wrote:

[...]

 writeln(&buffer[0]);

scope(exit) AlignedMallocator.instance.deallocate(buffer);
//...


}
```

Is this it?


Also, link :
https://dlang.org/phobos/std_experimental_allocator_mallocator.html#.Mallocator.reallocate


Adam, Tejas,

Thanks for all of your kind suggestions (the struct wrapper 
-as_array, runtime switch), and (AlignedMallocator).


All of these move me closer to a solution.  Moreover, the 
suggestions give me
a broader perspective.  So I very much appreciate the time and 
effort volunteered

by the dlang community to help newcomers such as myself.

Best Regards,
James





Can we rely on LDC respecting "align" (for avx) ??

2021-09-07 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

In searching through the forum archives (going back to 2013, 2016
etc), and experiments, it **appears to me** that LDC does indeed
respect the standard "align" properties.  (Meaning: proper 
alignment

for using AVX with static arrays can be guaranteed).

Experiments (and forum discussions) also lead me to believe that
DMD does NOT respect this alignment.

So, what is the "official status" of AVX alignment possibilities?

Succinctly:

1) Can we truly rely on LDC's alignment for AVX ?

2) Is DMD presently **not** respecting alignment? (Or have I
   misunderstood?)

This has important impact on performance of numerical 
computations.


Thanks for all illumination!

James



Re: Curious effect with traits, meta, and a foreach loop ... mystifies me.

2021-09-07 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 7 September 2021 at 17:33:31 UTC, Adam D Ruppe wrote:
On Tuesday, 7 September 2021 at 17:24:34 UTC, james.p.leblanc 
wrote:


If you want to do a runtime lookup, you need to separate the 
two pieces. This pattern works:



switch(runtime_index) {
   foreach(i, val; item.tupleof)
 case i:
   // use val
}

So the switch is at runtime but the loop and cases are all 
known at compile time.


Adam,

Thanks for the very fast, and very thorough explanation.  I 
especially
appreciate the fact that you seem to have predicted where my 
thoughts

were heading with my experiments ...

The "switch(runtime_index)" snippet will come in handy ...

What I would **REALLY** like is to be able to do (but I think 
this is
impossible) would be to "dig out" the needed "x" array depending 
on
which one of them suits my alignment needs.  (Yes, I am still 
playing

with avx2 ideas ...).

What I mean by "dig out" the needed "x" is:  if I could 
alias/enum/
or someother  trick be then able just to use that "x" as a simple 
static array.


(I doubt this is possible ... but  ?).

Thanks again, Keep Warm in Upstate!
James







Curious effect with traits, meta, and a foreach loop ... mystifies me.

2021-09-07 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

In playing with some reflection and meta programming, this 
curiosity

appeared.

Does someone understand what is happening?  I would appreciate 
learning

about it if possible.  Enclosed code snippet tells the story:

```d
import std.stdio;
import std.traits;
import std.meta;

struct  S0{ double[3] x; };
struct  S1{ double junk0 ; double[3] x; };

union U { S0 s0;  S1 s1; }

void main(){

   U u;

   double* ptr;

   u.s0.x = [ 0.0, 0.1, 0.3 ];
   u.s1.x = [ 1.0, 1.1, 1.3 ];

   writeln("typeid( u.tupleof): ",typeid( u.tupleof ) );
   writeln("typeid( u.tupleof[0]): ", typeid( u.tupleof[0] ) );
   writeln("typeid( u.tupleof[0].x): ", typeid( u.tupleof[0].x ) 
);


   writeln();

   // indeed both tuples exist
   writeln("u.tupleof[0].x.ptr: ", u.tupleof[0].x.ptr  );
   writeln("u.tupleof[1].x.ptr: ", u.tupleof[1].x.ptr  );

   // this is fine (notice that 'val' is never used
   foreach( i, val ; u.tupleof ){
  ptr = u.tupleof[i].x.ptr;
  writeln("ptr: ", ptr);
   }

   // this fails with: "Error: variable 'i' cannot be read at 
compile time

   //
   // foreach( i ; 0 .. 3 ){
   //ptr = u.tupleof[i].x.ptr;
   //writeln("ptr: ", ptr);
   // }
}

```

Best Regards,
James



Re: "+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 5 September 2021 at 21:25:06 UTC, jfondren wrote:
On Sunday, 5 September 2021 at 20:49:08 UTC, james.p.leblanc 
wrote:


Here's a reduction of your myArray.d that works with your 
unchanged usage code:


```d
module myArray;
import std.stdio;

void opOpAssign(string op)(myArray rhs) if (op == "+") {
foreach (i; 0 .. length) {
mixin("ptr[i] " ~ op ~ "= rhs.ptr[i];");
}
}

```


Wow, these quick and helpful replies are gratefully received!

They have helped me learn many new aspects of D (especially the 
overloading!)


Serious thanks to **all**.

Best Regards,
James



Re: "+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 5 September 2021 at 21:06:49 UTC, Ali Çehreli wrote:

On 9/5/21 12:43 PM, james.p.leblanc wrote:





  m[4 .. $] -= 100;
  writeln(m);

  m[] *= 2;
  writeln(m);
}

Ali


Ali,

Thanks for your example code ... I have much to learn from this
and will need to study it tomorrow when I am fresh.

I hope that I will see how to extend this so that it can do
slices on both the left side and right side ... for example:

```d

m[ 4 .. 8 ] += q[ 7 .. 11 ];

```

Best Regards,
James



Re: "+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 5 September 2021 at 20:38:29 UTC, Paul Backus wrote:
On Sunday, 5 September 2021 at 19:43:20 UTC, james.p.leblanc 
wrote:

Dear D-ers,

I have constructed a custom array type that works, but is 
missing

correct functioning on some operator overloads.


[...]


```d
import std.stdio;
import myarray_mod;
```


Please post the source code for `myarray_mod` so that we can 
reproduce the errors you're seeing.


Hello Paul,

Thanks for having a look ...

James

```d

module myArray_mod;
import std.stdio;

struct myArray{
   int* ptr;
   size_t length;

   this( int* ptr, size_t length){
  this.ptr = ptr;
  this.length = length;
   }

   myArray opIndex(){
  return this;
   }

   int opIndex(size_t i){
  return ptr[i];
   }

   int[] opIndex( SliceInfo info ){
  return ptr[ info.start .. info.end ];
   }

   void opIndexAssign(int val, size_t i){
  ptr[i] = val;
  return;
   }

   void opIndexAssign(int val, SliceInfo info){
  auto ctr=0;
  foreach( i ; info.start .. info.end ){
 ptr[i] = val;
  }
  return;
   }


   void opIndexAssign(int[] val, SliceInfo info){
  auto ctr=0;
  foreach( i ; info.start .. info.end ){
 ptr[i] = val[ctr++];
  }
  return;
   }

   // 
===


   void opIndexOpAssign(string op)(int val, int ind){
  writeln("opIndexOpAssign with INTEGER");
  if( (op == "+") || (op == "-") || (op == "*") || (op == 
"/") ){

 mixin(" ptr[ind] " ~ op ~ "= val;");
  }
  return;
   }

   void opIndexOpAssign(string op)(int val, SliceInfo info){
  writeln("opIndexOpAssign with SLICE");
  if( (op == "+") || (op == "-") || (op == "*") || (op == 
"/") ){

 foreach( i ; 0 .. length ){
mixin(" ptr[i] " ~ op ~ "= val;");
 }
  }
  return;
   }

   void opIndexOpAssign(string op)(SliceInfo rhs, SliceInfo 
lhs){
  writeln("opIndexOpAssign with LHS SLICE and RHS SLICE 
");
  if( (op == "+") || (op == "-") || (op == "*") || (op == 
"/") ){

 foreach( i ; 0 .. length ){
mixin(" ptr[i] " ~ op ~ "= 1;");
 }
  }
  return;
   }

   myArray opBinary(string op)(myArray rhs){
  writeln("opBinary");
 if( (op == "+=") || (op == "-=") || (op == "*=") || 
(op == "/=") ){

foreach( i ; 0 .. length ){
   mixin(" ptr[i] " ~ op ~ " rhs.ptr[i];");
}
 }
  return;
   }

   struct SliceInfo{ size_t start, end; }
   SliceInfo opSlice(size_t dim)(size_t start, size_t end){
  return SliceInfo(start, end);
   }

   void toString(scope void delegate(const(char)[]) sink) 
const {

  import std.format;
  sink("[");
  foreach( i ; 0 .. length ){
 formattedWrite( sink, "%s", ptr[i] );
 if( i< length-1 ) sink(", ");
  }
  sink("]");
   }
}

```




"+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

I have constructed a custom array type that works, but is missing
correct functioning on some operator overloads.

The stripped down minimum example (module) was over 100 lines (due
overloading opAssign, etc.) Probably too long to be a good forum 
post.


However, a short main may explain the issue succinctly (at end).

In words: the standard D static arrays, and dynamic array can do a
"vector accumulation" using:

```d
f += g;
```

We can even have slices on both lhs and rhs:

```d
f[ 2 .. 5 ] += g[ 4 .. 7 ];
```

So, this **should** be possibly for custom array types.  I have
looked at opIndexOpAssign, and learned a great deal from Michael
Parkers book on the use of opSlice, etc. with overloads.  Also, I 
have

searched for clues in the dmd source code ... but it was not
easy to perceive how this is done.

Here is an ugly code example (without module code -- so maybe 
useless).


How does one overload custom types with "+=" and slices on both 
left and right?


Thanks in advance,
James

**compilation error message appear as comments to right of 
offending lines**


==
```d
import std.stdio;
import myarray_mod;

void main(){

   // static arrays
   int[7] x = [ 10, 11, 12, 13, 14, 15, 16 ];
   int[7] y = [ 100, 101, 102, 103, 104, 105, 106 ];

   // custom "arrays"
   auto f = myArray( x.ptr, 7 );
   auto g = myArray( y.ptr, 6 );

   f[ 1 ] += 909;   // accumulating a scalar works fine


   f[] += 909;  // "f.opIndex() is not an lvalue and 
cannot be modified

   f += g;  // f is not a scale is is a myArray
   f[ 2 .. 5 ]+=g[ 2 .. 5]; //f.opIndex(f.opSlice(2LU, 5LU ... 
(possible missing[])


   // for standard dynamic arrays, this works fine
   int[] a = [ 1, 2, 3, 4, 5, 6 ];
   int[] b = [ 4, 5, 6, 7, 8, 9 ];
   writeln("a: ", a);
   writeln("b: ", b);
   a[ 1 .. 4 ] += b[ 2 .. 5 ];  // even with slices on both lhs & 
rhs!!

   writeln("a: ", a);

   return;
}

```



Re: Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn
On Sunday, 5 September 2021 at 17:55:09 UTC, Steven Schveighoffer 
wrote:

On 9/5/21 1:48 PM, james.p.leblanc wrote:

Dear All,



In case you can't find it, the info is 
[here](https://forum.dlang.org/help#markdown)


-Steve


THANKS!  (Also ... sigh ... I swear I have looked at the
markdon page that Steve linked to several times!

But, my eyes had been looking for the beautiful green and blue
text as an example ...  So, I completely missed the fact
that the "highlight syntax" in the box was exactly what
I was looking for.

My fault completely ... sorry for injecting noise!

James
(**Sheepishly** backing away from my keyboard now).



Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-05 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

I have noticed that quite a few posts and responses on this
forum include d snippets made with **nicely colored syntax 
highlighting.**

(I do not mean just the bold markdown text.)

This increases post clarity significantly.

How is this being done?  (I hope that this is not considered off
topic.  My goal would be able to make such posts myself.  But 
also,

if more post in this manner, it may help many.)

Best Regards,
James




Re: Singleton Object, calling member functions using UFCS (an "ugly?" example) ... better way?

2021-09-01 Thread james.p.leblanc via Digitalmars-d-learn

On Wednesday, 1 September 2021 at 22:11:29 UTC, user1234 wrote:

On Wednesday, 1 September 2021 at 22:01:12 UTC, user1234 wrote:


```

ProcessPipes gnuplot () {
__gshared ProcessPipes pipe;
return pipe.pid ? pipe : (pipe = 
pipeProcess("/usr/local/bin/gnuplot"));

}

```

user1234,

Thanks!  This is perfect, getting rid of the class altogether.

Yes, as pointed out in your response, that class was rather 
useless.
(For some unknown reason, I had been stuck on creating a 
singleton to
avoid multiple gnuplot processes -- very unnecessary as I now 
see.).


The ternary operator with the pipe id is much cleaner and leaner.

Thanks again, for your time, energy and insight.

Best Regards,
James



Re: Singleton Object, calling member functions using UFCS (an "ugly?" example) ... better way?

2021-09-01 Thread james.p.leblanc via Digitalmars-d-learn

On Wednesday, 1 September 2021 at 19:54:14 UTC, user1234 wrote:
On Wednesday, 1 September 2021 at 16:02:47 UTC, james.p.leblanc 
wrote:

Dear D-ers,

For simple plotting using a gnuplot process, I have created a 
singleton object (a stripped

down minimal working example is below.)

[...]

**However, those wrapper functions in the gnuplot_mod module 
looks a bit silly.**


[...]

Any suggestions on a better way are greatly appreciated.

Best Regards,
James


hello, I'd suggest this:

```d
shared static this() {
get(); // cache instance before main(){}
   // to get rid of the synchronized() stmt
}

static Gnuplot get() {
__gshared Gnuplot instance;
return instance ? instance : (instance = new Gnuplot());
}
```


user1234,

Thanks for your reply, I will need to look at it deeper.

I also realize that my post was not so clear, to clarify:

I needed to implement two wrapper functions ... that  are **in** 
the

module, but **outside** of the object, copied below:

**void cmd(string txt){**
**Gnuplot gp;**
**gp = gp.get();**
**gp.cmd(txt);**
**}**

**void plot(double[] x, string txt){**
**Gnuplot gp;**
**gp = gp.get();**
**gp.plot(x, txt);**
**}**

These enable use of the UFCS in main() (without prefixing with 
instantiated object's name
**gp** ).  The gp prefix only needs to be in these wrappers that 
exist in the module, not in the main().


The question is if there is a way to enable UFCS without such 
wrapper

(see example in main() in original posting).

Thanks again, and now I need to play a bit with your suggestion 
to learn

from it.

Best Regards,
James



Singleton Object, calling member functions using UFCS (an "ugly?" example) ... better way?

2021-09-01 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

For simple plotting using a gnuplot process, I have created a 
singleton object (a stripped

down minimal working example is below.)

In the example, there are two plots calls:

   1) First, call is made using the object member function 
"gp.plot(x, etc.)"
   2) The second uses a wrapper to allow use of the UFCS (uniform 
function call syntax)


The ability to use the UFCS has the usual UFCS advantages, 
additionally the coder
doesn't need to care about the actual name of the object's 
instantiation.


**However, those wrapper functions in the gnuplot_mod module 
looks a bit silly.**


**Is there a more elegant way to do this?**

First, the module:

--

   module gnuplot_mod;

   import std.stdio;
   import std.process;
   import std.conv : to;

   class Gnuplot {

  // modification of wiki.dlang.org/Low-Lock_Singleton_Pattern
  ProcessPipes pipe;
  private this() {
 this.pipe = pipeProcess("/usr/local/bin/gnuplot") ;
  }

  private static bool instantiated_;
  private __gshared Gnuplot instance_;

  static Gnuplot get() {
 if (!instantiated_) {
synchronized(Gnuplot.classinfo) {
   if (!instance_) {
  instance_ = new Gnuplot();
   }
   instantiated_ = true;
}
 }
 return instance_;
  }

  void cmd(string txt) {
 this.pipe.stdin.writeln(txt);
 this.pipe.stdin.flush();
 return;
  }

  void plot(double[] x, string txt = "ls 21 lw 2"){
 this.pipe.stdin.writeln("plot '-' u 1:2 with lines " ~ 
txt);
 foreach( ind, val ; x) this.pipe.stdin.writeln( 
to!string(ind) ~ " " ~ to!string(val) );

 this.pipe.stdin.writeln("e");
 this.pipe.stdin.flush();
  }
   }

   void cmd(string txt){
  Gnuplot gp;
  gp = gp.get();
  gp.cmd(txt);
   }

   void plot(double[] x, string txt){
  Gnuplot gp;
  gp = gp.get();
  gp.plot(x, txt);
   }

---
Now, the main ...

---

   import gnuplot_mod;
   import std.stdio;

   void main(){

  Gnuplot gp;
  gp = gp.get();

  double[] x = [1.1, 0.2, 3.1, 2.2, 3.1, 0.6];
  double[] y = [-1.1, 0.2, -3.1, 2.2, 3.1, -0.6];

  writeln("\nusing singleton's member functions: plot and 
cmd");


  gp.plot(x, "ls 31 lw 3");
  gp.cmd("pause 2");

  writeln("\nusing uniform function call syntax (UFCS): plot 
and cmd");


  y.plot("ls 41 lw 8");
  cmd("pause 2");
   }


Any suggestions on a better way are greatly appreciated.

Best Regards,
James



Re: pipeProcess, interactions with stderr ... I am missing something here

2021-08-30 Thread james.p.leblanc via Digitalmars-d-learn

On Monday, 30 August 2021 at 16:51:12 UTC, Ali Çehreli wrote:

In this case, converting your ~this to a named function solves 
the issue:


  // Was: ~this()
  void close() {
// ...
  }

// ...

  auto gp = new Gnuplot();
  scope (exit) {
gp.close();
  }

Ali



Ali


Ali,

Yet again, you have helped me.  Thanks for the keen eye and clear
description of what was happening.

I am enjoying this language **very** much, and the community has 
been incredibly

helpful to my progress.

Best Regards,
James



pipeProcess, interactions with stderr ... I am missing something here

2021-08-30 Thread james.p.leblanc via Digitalmars-d-learn

D-ers,

I am attempting to use pipeProcess for interacting with an 
external process.
My simplified routine can work somewhat.  But, trying to print 
any messages

that process writes to stderr yields the message:

(master) gnuplot > gnuplot_example
**core.exception.InvalidMemoryOperationError@src/core/exception.d(647): Invalid 
memory operation**



Simplified code:


import std.stdio;
import std.process;

class Gnuplot {
   ProcessPipes pipe;

   void cmd(string txt){
  pipe.stdin.writeln(txt);
  pipe.stdin.flush();
   }

   this(){
  this.pipe = pipeProcess("/usr/local/bin/gnuplot", 
Redirect.stdin |

  Redirect.stdout | Redirect.stderr);
   }

   ~this(){
  pipe.stdin.close();
  pipe.stdout.flush();
  pipe.stderr.flush();

  foreach( line ; pipe.stdout.byLine ) 
writeln("stdout: ", line);
  foreach( line ; pipe.stderr.byLine ) 
writeln("stderr: ", line);

   }
}

void main(){

   auto gp = new Gnuplot();
   gp.cmd("plot sin(x)");
   gp.cmd("pause 2");
   gp.cmd("plot line contains error ... should create 
output to stderr");

   gp.cmd("quit");
}


Also, I have found a few examples on similar programs (for 
example in Adam Ruppe's
D-Cookbook - page 107), which provide some very good information 
and examples.

But, I do not understand what I am seeing in my program example.

**Any pointers are gratefully received. ... especially tutorials 
or example code**


Best Regards,
James

PS  You may note that I do not have the line "scope (exit) wait 
pipe.pid".
Two reasons for this are:  I do not understand what this is 
supposed to do,

and attempts to add this froze my program.

PPS I have seen some of Steven Schveighoffers helpful 
descriptions about
piped processes and child process hanging with excessive outputs 
... this
should not be the case here ... only a handful of bytes might 
possibly be written.





Re: Possible to overload assignment of struct field ??

2021-08-23 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 24 August 2021 at 05:34:08 UTC, Ali Çehreli wrote:

On 8/23/21 10:25 PM, james.p.leblanc wrote:

So, you need a "property". Easy... :)

1) Rename the member e.g. as a_.

2) Write setter and getter functions named 'a'.

struct Foo{
  int a_;

  int a() const {
return a_;
  }

  void a(int value) {
a_ = value;
  }
}

void main(){
  auto x = Foo(1);
  x.a = 100;
  assert(x.a == 100);
}

Ali


Ali,

Thank you ... yes!  This is exactly what I needed, I have done 
something
similar as you have shown for the "getter", but had a 
"brain-lock-up"

when thinking about the setter.

A bit embarassing for my, I admit.  But, on the positive side ... 
the

solution is now burned into my brain.

Thanks again and Kind Regards,
James



Possible to overload assignment of struct field ??

2021-08-23 Thread james.p.leblanc via Digitalmars-d-learn

Greetings,

With a struct, there are many overload possibilities available.

However, I haven't been able to find how to overload assignment
of **selected fields** of a struct.

For example, suppose:

struct Foo{
  int a;
  int b;
  ...
}

void main(){
auto x = Foo( 1, 2);  // so x now instantiates

x.a = 100; // suppose I wish to enforce that 
a<5??

...
}


(I understand this is basically a field "setter" idea that is most
often associated with classes.  So, another way to state the 
quesion
might be:  "How can a field setter be done on a **already 
instantiated**

struct?)

Best Regards,
James




Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 22 August 2021 at 14:35:48 UTC, Ali Çehreli wrote:

On 8/22/21 6:03 AM, james.p.leblanc wrote:

>  struct Foo {
>  int a, b, c;
>  Foo* myadd;
>
>  this(int a, int b, int c) {
>  this.a = a;
>  this.b = b;
>  this.c = c;
>  this.myadd = &this;

As Matthias Lang mentioned, keeping a reference to itself makes 
a struct object illegal in D. D sees structs as value types: It 
is supposed that any copy can be used in place of another copy.


Ali


Ali,

You highlight am important point that I have not been completely 
aware of.


Indeed, I did have a few "warning bells" going off in my brain 
when I began
typing "this.myadd = &this;" into my program ... but, it 
compiled, so I

continued (into the potential quicksand, admittedly!)

So, thanks for illuminating this issue for me.

Also, the "postblit" hint recently posted in this thread, may 
allow me

to procede along a safer path.

Kind Regards,
James



Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 22 August 2021 at 13:37:50 UTC, jfondren wrote:


this(this) {
unique = null;
}

~this() {
pureFree(unique);
}
}


Dear jfondren,

I truly appreciate you taking the time to help me with my 
question!


**This bit of magic with the postblit may hold the key to my 
issue.**


(I have done some experiments based on your example code, am 
learning much,

and it looks VERY encouraging!

It is a bit scary how you guessed very closely what I am trying to
do.  I have a AVX aligned pointers (obtained from fftw_malloc), 
that I

want to protect.

To be a bit more specific.  The code that reads/writes from 
to/from fftw
routines is all pointer based.  But, to allow use of standard 
dlang things
such as "foreach" and friends, I've been cobbling together a 
(naive) wrapper.


This allows me to use standard dlang syntax and operator 
overloads.  I call my
struct "fakeArray" ... since it is meant to behave either as a 
static array,

or a dynamic array as needed.

It **seems** to work pretty well ... but protecting the arrays 
from accidental

programming mistakes (such as the "auto y=x") has been eluding me.

In fact, I **can** do a legitimate data copy via "y = x", as long 
as

y is already instantiated as a "fakeArray".

I must steady more the example you kindly provided (learn more 
about the

postblit, and pureFree, the const report function,  etc...)

Best Regards,
James








Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 22 August 2021 at 11:10:33 UTC, jfondren wrote:
On Sunday, 22 August 2021 at 07:58:12 UTC, james.p.leblanc 
wrote:

Hello,

If you don't get an answer that you like, I suggesting posting 
functional code and then stating your dissastisfactions with it.


Mattias, jfondren,

Thanks both for your replies, I always learn something from them.

I've trimmed my code to a minimal example to give a better idea
of my thinking on this.  You will notice that  to ensure that I
"seed" x with its real address at initialization, I must add 
@disable

this() to my struct.

import std.stdio;

struct Foo {
int a, b, c;
Foo* myadd;

this(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
this.myadd = &this;
}

@ disable this();
}

void main() {

// x is original, we wish to protect
auto x = Foo(1, 2, 3);

// y is the "bad copy", do not want operation on y to 
pollute original x

auto y=x;

writeln("&x: ",&x,", x.myadd: ",x.myadd,", the 2 agree, 
we have original!");
writeln("&y: ",&y,", y.myadd: ",y.myadd,", these 2 
disagree (must be a bad copy!");


}

Produces output:

&x: **7FFC65C02CC8**, x.myadd: **7FFC65C02CC8**, the 2 agree, we 
have original!
&y: 7FFC65C02CE8, y.myadd: **7FFC65C02CC8**, these 2 disagree 
(must be a bad copy!


So, as stated, in my struct overloading I can check if my two 
values agree
or not (exposing whether or not I have the original, or a copy), 
and react

appropriately.

I understand that the language allows circumvention of this 
method... but

I just want to catch minor mistakes in programming.

Again, all comments and thoughts are welcome.

Best Regards,
James




Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread james.p.leblanc via Digitalmars-d-learn

Hello,

Question about a possible strategy to avoid problems with
undesired/unintended copying of a structure:

1) We have a struct, call this **Foo**.

2) We instantiate it with,   **x = Foo(a,b,c);**
   a.  our constructor will initialize a field:  **this.myadd 
= &this**
   b.  this capture the address of our original "x" in 
x.myadd.


3) We wish to allow, any function calls using x, so we cannot
   disable Foo's this(this).

4) Our goal is to avoid problems with any accidental copying
   of x ... say by doing:  **auto y=x;**

5) the copy of step 4 **does not use the constructor**, thus 
y.myadd

   would contain the address of x (and not y)

6) We can exploit that y.myadd does NOT contain its own
   address (but instead contains the address of x).

   This requires adding logic checks in any Foo opAssign,
   and other overloads.  For example, we can disallow any
   such overloads by checking:

  if( &this != this.myadd ){ ... }

7) Needing to operate on x with other functions implies that
   private or const is not a solution. (I believe.)

Some initial experiments lead me to believe this may acheive
part of what I would like.  But, it feels very "hackish" and
ugly.

Is there a better way?

Best Regards,
James




Re: classify a user struct as an "array" or "slice"

2021-08-20 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 20 August 2021 at 15:38:04 UTC, Paul Backus wrote:



The most straightforward way would be to change your functions 
from accepting only `T[]` to accepting either `T[]` or 
`fakeArray`. For example:


```d
import std.traits: isDynamicArray;

// assuming `fakeArray` is a template struct/class
enum isFakeArray(T) = is(T == fakeArray!U, U);

auto foo(Array)(Array x)
if (isDynamicArray!Array || isFakeArray!Array)
{
// ...
}
```

The `if (...)` part there is a [template constraint][1]. It 
means that the template can only be instantiated when the 
condition evaluates to `true`.


[1]: https://dlang.org/spec/template.html#template_constraints


Paul,

This works like a charm!  I just implemented it ... I am most
thankful for your help again.

Next, I imagine that need to add a few "static ifs" later in the 
function

body of foo, wherein I can dig out what the element types of my
arrays are ... (I need this to initialize some summers to the 
correct

type, etc.)

These past weeks are my first attempts at using templates.  It is
impressive how powerful they are.

I have learned quite much from this forum.  But, I obviously have
quite a lot to learn.

Best Regards,
James





classify a user struct as an "array" or "slice"

2021-08-20 Thread james.p.leblanc via Digitalmars-d-learn

Greetings,

I have a user created struct, let's call this "**fakeArray**":

For all intents and purposes fakeArray behaves like an array (or 
slice, I guess).
(i.e. It has a number of operator overloadings, and *foreach* 
extensions implemented.)


I have a fairly large number of function in a module that accept 
arrays (or slices).


These are implemented as:

**auto foo(T)(T[] x) { ... }**

So, foo will accept "official" arrays and slices.

What is the easiest way to coerce all my functions to also
accept my fakeArray?

Regards,
James



Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-18 Thread james.p.leblanc via Digitalmars-d-learn

On Wednesday, 18 August 2021 at 06:53:51 UTC, Tejas wrote:


void funcTemplate(T:int)(T a){
 writeln("argument is int");
}

void funcTemplate(T : long)(T a){
 writeln("argument is long integer");
}

void main(){
 int a;
 long b;
 func(a);
 func(b);

 funcTemplate(a);
 funcTemplate(b);

}

```



Domninikus, Tejas, and All,

I see that I had been (stupidly) omitting the exclamation point
after **"isIntegral"** in my clumsy attempts to use the traits ...
thanks for your clear example helping me identify my error.

Also, thanks for mentioning the words **"template 
specialization"** , I did

not know what to call the use of **":"** in templates.

Now, I have a search term I can use to learn more ...and find it 
is in Phillippe

Signaud's informative "D-templates-tutorial".

Thanks again,
James

PS Also, I am enjoying, a entertaining and educational tutorial 
that Phillippe

has linked in his tutorial.  Other may learn from this as well:

http://www.semitwist.com/articles/EfficientAndFlexible/SinglePage/




Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn
On Tuesday, 17 August 2021 at 20:28:20 UTC, Alexandru Ermicioi 
wrote:
On Tuesday, 17 August 2021 at 19:53:52 UTC, james.p.leblanc 
wrote:


Wow!  That is absolutely beautiful ... I had never seen (or 
even

imagined) a recursive template!  This expands my mind in a good
way ... and is going into my toolbox immediately.

Best Regards,
James


Just don't over rely on it. It can cause compilation slowdowns, 
so avoid it if you can.


I've been happily trying to absorb all the helpful concepts 
posted.


A final related question in the quest for simplicity and 
robustness.


If I wanted to ensure that a function accepts only arguments of
byte, int, uint, long, etc.  (i.e. integer-like types).  Is the 
accepted

way to do this like so?:

**auto foo( T : long )(T a, T b){ ... }**

I really wish I could find a good explanation of the ":" (colon)
used in templates.  I am sure one exists ...but haven't come upon
it just yet.

(I thought "isIntegral" in traits module would be helpful...but
I failed in my experiments.)

Thanks for patience with this question!

Best Regards,
James



Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 17 August 2021 at 20:13:59 UTC, Paul Backus wrote:

FYI: in this particular case, you can use 
std.meta.staticIndexOf instead of writing the recursion out 
yourself:


import std.meta: staticIndexOf;
enum isAmong(T, S...) = staticIndexOf!(T, S) >= 0;

Docs: https://phobos.dpldocs.info/std.meta.staticIndexOf.html


All,  Thanks again ... Paul, I will try this staticIndexOf as you 
mention.


I had been receiving "circular reference to variable" error 
messages from the
"isAmong" suggestion.  (But, I very likely had  misunderstood how 
to use this.)


I would still be interested to learn what I have done wrong.  So, 
below

is my code:

import std.stdio;
import std.meta : AliasSeq;

template isAmong(T, S...) {
   static if (S.length == 0)
  enum isAmong = false;
   else
  enum isAmong = is(T == S) || isAmong(T, S[1..$]);
}

alias MyTypes = AliasSeq!(int, float);

auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) {
  writeln(" in myFunc ");
  return;
}

void main(){
  writeln("started ...");
   auto a = 1;
   auto b = 2;
   myFunc!(int)(a, b);
   return;
}


And, here are the error message:

(master) Notes > dmd recursive_template.d
recursive_template.d(9): Error: circular reference to variable 
`recursive_template.isAmong!(int, int, float).isAmong`
recursive_template.d(17): Error: template instance 
`recursive_template.isAmong!(int, int, float)` error instantiating
recursive_template.d(29):while looking for match for 
`myFunc!int`


Can anyone see what is going on?

Best Regards,
James





Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 17 August 2021 at 19:44:29 UTC, H. S. Teoh wrote:



You could use a helper template and an AliasSeq for this:

template isAmong(T, S...) {
static if (S.length == 0)
enum isAmong = false;
else
enum isAmong = is(T == S) ||
isAmong(T, S[1..$]);
}

import std.meta : AliasSeq;
alias MyTypes = AliasSeq!(int, float, MySpecialStruct);

auto myFunc(T)(T a, T b) if (isAmong!(T, MyTypes)) { ... }


T


Dear H.S. Teoh,

Wow!  That is absolutely beautiful ... I had never seen (or even
imagined) a recursive template!  This expands my mind in a good
way ... and is going into my toolbox immediately.

Best Regards,
James





Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn
On Tuesday, 17 August 2021 at 18:28:53 UTC, Steven Schveighoffer 
wrote:

On 8/17/21 2:11 PM, james.p.leblanc wrote:

Evening All,



[Template 
constraints](https://dlang.org/spec/template.html#template_constraints).


-Steve


Dear All,

Thanks! I was aware of, and have used template constraints in 
simple ways.


But, I should express my question a bit better:
"... is there a more elegant way to expression these constraints?"

Perhaps by extending Alexandru's "moo" concepts, with a list of 
allowed types:


auto moo(T : (int || float || mySpecialStruct )(T myMoo) {•••}

When re-using any such sets, it would be nice to define the set 
as follows:


S = (int || float || mySpecialStruct)

and then define "moo" more concisely as:

auto moo(T < S)(T myMoo) {•••}

( where I have used "<" to mean "T is a member of S").

Possible?

Best Regards,
James






simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread james.p.leblanc via Digitalmars-d-learn

Evening All,

Eponymous templates allow a nice calling syntax.  For example, 
"foo" here can
be called without needing the exclamation mark (!) at calling 
sites.  We see that
foo is restricting a, and b to be of the same type ... so far, so 
good.


auto foo(T)(T a, T b) { ... }

Now, suppose I need to restrict "T" only certain subsets of 
variable types.


I can imagine putting in some "static if" statements in my 
function body,
is one solution.  (Also a bit ugly as the allowed types might 
grow).


Is there a more elegant way, to do this?

Regards,
James

PS Any violations should be caught at compile time.






Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-16 Thread james.p.leblanc via Digitalmars-d-learn
On Monday, 16 August 2021 at 10:48:19 UTC, Alexandru Ermicioi 
wrote:
On Monday, 16 August 2021 at 06:36:02 UTC, james.p.leblanc 
wrote:

To be honest, I am not exactly sure what is happening here. I
am unfamiliar with the "(T : T[])" syntax ... need to read


That is template argument secialization. You're saying that T 
can be accept only types that are arrays of T, where : reads as 
'extends'.


Now T : T[] might introduce cyclic reference, so more correct 
would be: foo(T : Z[], Z)(...)


Here you say that T might accept only types that are arrays of 
Z elements.


Regards,
Alexandru.


Alexandru,

That is very helpful information.  It also answers a nagging
question I have been worried about.  Specifically, that "T : T[]"
bothered me even though I was unfamiliar with the syntax ... now
I understand the situation better.

Best Regards,
James



Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Monday, 16 August 2021 at 06:42:48 UTC, Tejas wrote:


If the code works, what's the problem?


Hej Again,

I was able to construct the working code shown above from help I
obtained here in the forum and other resources.

My original code was not working ... but updated code is working
fine ... so there are no further problems.  (Actually, I learned
a fair amount in this endeavor!)

Cheers!
jpl



Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Monday, 16 August 2021 at 06:20:11 UTC, Tejas wrote:

Maybe just write `T[]` in code rather than making it happen via 
the colon?


I also have similar troubles, removing the default value always 
helped me.


Can you show the code where you're trying to apply this?


Hej Tejas,

Sure, here is the code snippet, it resides within a struct
along with various operator overloads.

To be honest, I am not exactly sure what is happening here. I
am unfamiliar with the "(T : T[])" syntax ... need to read
up a bit on that. (However, not so eary searching for a ":")

BR,
jpl


// --- cast overloading 
---

// T[] opCast(T : T[])(){ // this works
   T[] opCast(T[])(){ // yields: "Error: identifier expected for 
template value param"

  T[] x;
  x.length = this.length;
  for( int i = 0 ; i< this.length ; i++){
 x[i] = this.ptr[i];
  }
  return x;
   }





Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Monday, 16 August 2021 at 05:26:00 UTC, Tejas wrote:

If you're finding the spec too hard, please try Ali's book. I'm 
sharing the part on operator overloading below:


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

Please ping if you still have problems; I'll then write a full 
program.


Hej Tejas!

Thanks for your message.  I have it working now.  Yes, Ali's book 
is

a tremendously good reference.  But, I had trouble digging out
the "magic sauce" from the pages to get this working.

I was able to find the sauce in a forum post by Adam Ruppe (his 
book is also

an excellent place for ideas and code).

With "opCast", my difficulty was the description of the type I 
wish to cast

to uses a colon ":".

Here is the line that allows it to function as desired:

**>>   T[] opCast(T : T[])(){... }**


Best Regards,
jpl




Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote:

On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc



— Bastiaan.


Bastiaan,


Thanks once again,
James


On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote:


Okay!  Great!  Thanks everyone Bastiaan, ag0aep6g, and russhy  ...
I see more replies come in while I was typing.

There is some excellent information here that I
need to digest.  I believe that I have what I need.

This group has been great!

BR,
James


Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc



— Bastiaan.


Bastiaan,

Thanks kindly for your response!

Unfortunately, I do not see what the program does.  I mean A is a 
structure
that has only functions.  So, how are any elements of this being 
set to

the value of v?

I tried extending the code mentioned by adding a member array, 
but no

luck.

I often have difficulties to understand the notations used in the 
spec,

and only sometimes can I extend them to working examples.

Would it be possible to add the last couple of details regarding
an array member?  I attempted but the values always remain zero
even when I set v=4.


import std;

struct A
{
   int[5] a;
   int opIndexAssign(int v) // overloads a[] = v
   {
  writeln(__FUNCTION__);
  return 42;
   }
   int opIndexAssign(int vh, size_t[2] x)  // overloads a[i 
.. j] = v

   {
  writeln(__FUNCTION__);
  return 43;
   }
   int[2] opSlice(size_t x, size_t y) // overloads i .. j
   {
  writeln(__FUNCTION__);
  return [44, 45];
   }
}

void main()
{
   A a;
   int v=4;
   writeln(a);

   a[] = v;  // same as a.opIndexAssign(v);
   writeln(a);
   a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

   writeln(a);
}


Thanks once again,
James














Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

Greetings,

I have been trying to get a working example of slice assignment 
operator
overloading ... and am befuddled.  From the spec (section 
20.6.2), the

code below appears:

struct A
{
int opIndexAssign(int v);  // overloads a[] = v
int opIndexAssign(int v, size_t[2] x);  // overloads a[i 
.. j] = v
int[2] opSlice(size_t x, size_t y); // overloads i .. 
j

}

void test()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

}

I have hacked at this trying to get a simple working example.  
Could

anyone guide me here please?

Best Regards,
James



Re: Looping over Template Types ... possible?

2021-08-14 Thread james.p.leblanc via Digitalmars-d-learn

On Saturday, 14 August 2021 at 20:20:01 UTC, Stefan Koch wrote:

On Saturday, 14 August 2021 at 20:07:21 UTC, james.p.leblanc 
wrote:

mes


it is possible

look for `AliasSeq`
in `std.meta`

foreach(T; AliasSeq!(float, double))
{
  ...
}


Stefan,

Thanks very much for your help here ... I had not
understood that AliasSeq worked in this manner.

I definitely need read the AliasSeq and try to understand
how to use this.

Best Regards,
James



Looping over Template Types ... possible?

2021-08-14 Thread james.p.leblanc via Digitalmars-d-learn

Good Evening/Day,

Suppose I have a number of function templates that each take
two types, say S and T.

I would like to exercise my routines over the combinations
of types:

set of all S:  ( double[], float[], Complex!double[], 
Complex!float[])

set of all T:  ( double, float)

Is something along the line of the following sketch possible?

foreach( s in S){
   foreach( t in T){

  foo!(S,T)( T x, S y);
  biz!(S,T)( T x, S y);

   }
}

I have done some searching for hints about this, but I perhaps
my search terms are not very good.

All hint and pointers thankfully received.

Best Regards,
James





Re: aliasing functions with function arguments as well ??

2021-08-13 Thread james.p.leblanc via Digitalmars-d-learn
On Friday, 13 August 2021 at 15:14:00 UTC, Steven Schveighoffer 
wrote:


There isn't a way to alias it. You can wrap it though, and hope 
the inliner takes care of the difference:


```d
auto foo(T)(T arg)
{
   static if(is(T == int)) return bar(arg, 42.33);
   else return bar(7, arg);
}
```

-Steve


Steve,

Thanks!  Yes ... this templated wrapper should be perfect for me!

Your help on my present question, as well as your continual
contributions to the forum are greatly appreciated!

Best Regards,
James




aliasing functions with function arguments as well ??

2021-08-13 Thread james.p.leblanc via Digitalmars-d-learn

Dear All,

How does one use 'alias' to incorporate function arguments as 
well?


(I believe this is possible, from some of the examples of 
aliasSeq, and
the traits.Parameters documentation.  However, I was unable to 
come up

with anything that works.)

What should replace the question marks (???) below?


double bar( int a, double x){
  return a*x:
}



template foo(T){
  static if ( is(T==int) ){
 alias ??? = ???
  }
  else{
 alias ??? = ???
  }
}

// when T == int, I desire the aliasing to produce resulting 
code:

foo( int a) = bar( int a, 42.33);

// when T == double, I desire:
foo( double x) = bar( 7, x);



Thanks kindly for any information!
James

PS I am aware of the "struct holding a function allowing multiple 
dispatch concept"
... while that would fit quite okay here in my simple example, it 
isn't appropriate

for my real use.



Re: nested templates using Complex! with slices, ... confused, I am!

2021-08-09 Thread james.p.leblanc via Digitalmars-d-learn

On Monday, 9 August 2021 at 18:44:34 UTC, Paul Backus wrote:

On Monday, 9 August 2021 at 18:35:56 UTC, james.p.leblanc wrote:

```d
T[] foo_temp(Complex!T[])(T x, T y){
  auto r = [x, x];
  auto i = [y, y];
  auto z = [ Complex!T(x, y), Complex!T(x,y) ];
  return z;
}
```

void main(){
  auto yd = foo_double(1.1, 2.2);
  writeln(yd); ...
}


But, no ... I am WRONG!  I get the message:

qqq.d(18): Error: identifier expected for template value 
parameter


I think what you want is:

```d
Complex!T[] foo_temp(T)(T x, T y) {
  auto r = [x, x];
  auto i = [y, y];
  auto z = [ Complex!T(x, y), Complex!T(x,y) ];
  return z;
}
```

This is what I get when I take one of the non-template versions 
and replace `float` or `double` with `T`.


H.S & Paul,

Wow, thanks for the quick replies!

It all seems so simple now ... but I just could not see it!

I had been completely (and confidently, unfortunately) 
misunderstanding

the syntax of that left most column.

Thanks again,
James




nested templates using Complex! with slices, ... confused, I am!

2021-08-09 Thread james.p.leblanc via Digitalmars-d-learn
Suppose "foo_double" should return a complex double slice, with 
double input args.
Similarly "foo_float" should return a float slice, with float 
input args.


I thought it should be easy to parameterize with a template 
taking a SINGLE

argument, either a"double" or "float" as follows:


import std.stdio;
import std.complex;

Complex!double[] foo_double(double x, double y){
  auto r = [x, x];
  auto i = [y, y];
  auto z = [ Complex!double(x, y), Complex!double(x,y) ];
  return z;
}

Complex!float[] foo_float(float x, float y){
  auto r = [x, x];
  auto i = [y, y];
  auto z = [ Complex!float(x, y), Complex!float(x,y) ];
  return z;
}

**T[] foo_temp(Complex!T[])(T x, T y){
  auto r = [x, x];
  auto i = [y, y];
  auto z = [ Complex!T(x, y), Complex!T(x,y) ];
  return z;
}**

void main(){
  auto yd = foo_double(1.1, 2.2);
  writeln(yd); ...
}


But, no ... I am WRONG!  I get the message:

qqq.d(18): Error: identifier expected for template value parameter

Nested templates using Complex! really have me confused.  How 
should I

be thinking about such things in order to understand better?

Best Regards,
James


How elegantly "funnel" all operator overloads or interest through a struct?

2021-08-09 Thread james.p.leblanc via Digitalmars-d-learn

I have a struct where I use a number of

"invariant(){enforce(  blah, blah ...);}"

statements in the struct body to enforce certain
conditions on a struct member.

Since these "invariants" are only called when struct member
functions are exercised, must I overload each
individual operation that may lead to a violation?

Or, is there any way to funnel all such operations, so my
invariants are exercised?

---

For example, struct member "x" is an integer slice,
I can account for *some of* the operations that affect the
slice slice via (such as the append operator):


// overloaded to activate enforcements
void opOpAssign(string op)(int a){mixin("this.x"~op~"= a;");}
void opOpAssign(string op)(int[] a){mixin("this.x"~op~"= a;");}


(since these are picked up as member function, they can
exercise my "invariant").



But there are a number of slicing operation that I also
need to be careful of.

I must disallow any operation that changes the
length of my slice, or the pointer associated with my
slice.

How should I account for all combinations of operations
that might change size of slice member?

Any elegant solutions here?

Best Regards,
James




Re: using "invariant" with structs ... possible to call when a field value is set??

2021-08-08 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 8 August 2021 at 11:36:51 UTC, FeepingCreature wrote:



You can make a field set function like so:

```
struct S
{
  private int x_;
  int x(int value) { return this.x_ = value; }
  int x() { return this.x_; }
}
```

This will then run invariants.

(boilerplate can automate that for you. 
https://code.dlang.org/packages/boilerplate cough 
self-advertisement cough)


FC,

Thanks! This is exactly what I had hoped might be possible!

I had made some naive "newbie-D" attempts at something like this
be couldn't get anything to work.  Thanks for providing an exable
of the exact code that would work.  Much obliged!

Best Regards,
James

PS Even more important than solving my immediate problem, I have
gained a better understanding of the struct and its member 
functions.






using "invariant" with structs ... possible to call when a field value is set??

2021-08-08 Thread james.p.leblanc via Digitalmars-d-learn

Hello,

With structs, I understand that "invariant checking" is called 
(from dlang tour):


It's called after the constructor has run and before the 
destructor is called.

It's called before entering a member function
invariant() is called after exiting a member function.

But, is is possible to have the invariant checking be performed
whenever a field is directly set?

For example, suppose a struct "S", has a field "x".  I would like 
to

have invariance check in cases such as:

S.x = 4;

Maybe there is a hidden set field function that gets called that
might be exploitable??

Thoughts on this?  Possible?  Better paths that I should consider?

Best Regards,
James




Re: Proper way to protect (lock) a struct field after initialization ??

2021-08-08 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 8 August 2021 at 10:40:51 UTC, Ali Çehreli wrote:



I understand your question differently from jfondren. You may 
be looking for a 'const' (or 'immutable') member:


struct S {
  const int i;

  this(int i) {
// This will work because "first assignment is 
initialization"

this.i = i;
  }
}

void main() {
  auto s = S(42);

  // This won't work
  s.i = 43;

  // This won't work either
  s = S(44);
}

Ali


Hello Again Ali,

Excellent!  I had tried (an erroneous) variant of this idea 
earlier ... but

also failed with my attempt.

I am appreciating very much the example you have provided.  I 
will try
this approach as well for the problem I am working on.  (Some 
details on

my path forward remain unclear ...)

Best Regards,
James



Re: Proper way to protect (lock) a struct field after initialization ??

2021-08-08 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 8 August 2021 at 10:19:46 UTC, jfondren wrote:

On Sunday, 8 August 2021 at 10:11:37 UTC, james.p.leblanc wrote:

Hello All.

Is there a standard way to protect a field of a struct after
the struct has been initialized?

Is this possible with a struct?

If not, I suppose a class (object) would be needed?  If so,
are there any simple pointers to an example of this?

Thanks in advance,

James


`private` works for structs the same as it does for classes.
https://dlang.org/spec/attribute.html#visibility_attributes

Perhaps you tried it, realized you could still access it within 
the same module, and concluded that it didn't work? Consider 
note #2 at that link: "Symbols with private visibility can only 
be accessed from within the same module." Import the struct 
into another module and test the visibility there and you'll 
get the behavior you're looking for.


Hej JFondren,

Wow, thanks for the quick response.  I had read that about the 
modules ...
but as my test example had failed, I thought that I had 
misunderstood

the larger picture.

Based on you kind reply, I went back over my example and found 
that I

had been deceiving myself.

With a quick fix-up edit, it indeed is working as your 
explanation.


Now, I proceed onto the trickier part of my endeavor ...

Thanks again, and Best Regards,
James

(Sorry for the noise...)



Proper way to protect (lock) a struct field after initialization ??

2021-08-08 Thread james.p.leblanc via Digitalmars-d-learn

Hello All.

Is there a standard way to protect a field of a struct after
the struct has been initialized?

Is this possible with a struct?

If not, I suppose a class (object) would be needed?  If so,
are there any simple pointers to an example of this?

Thanks in advance,

James



Re: Setting a hard limit on slice size, is this possible?

2021-08-07 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 8 August 2021 at 02:00:26 UTC, Tejas wrote:

On Saturday, 7 August 2021 at 19:07:04 UTC, Paul Backus wrote:

On Saturday, 7 August 2021 at 15:41:24 UTC, Tejas wrote:

On Saturday, 7 August 2021 at 15:21:01 UTC, Paul Backus wrote:

[...]


Oh wow, and here I thought I was being smart :(

So, how can we work around this without assembly language 
magic? I'm illiterate at assembly.


For stack allocations, you can use the workaround in [Vladimir 
Panteleev's comment][1]  (ignoring the ASM part, which is 
unrelated to alignment).


For heap allocations, I guess the easiest way would be to use 
[`AlignedMallocator`][2] from `std.experimental.allocator`.


[1]: https://issues.dlang.org/show_bug.cgi?id=16098#c3
[2]: 
https://phobos.dpldocs.info/std.experimental.allocator.mallocator.AlignedMallocator.html


Cool... thanks


Thanks to everyone for all of the great discussion and hints on 
this topic!


I have learned quite much, and have a gained an understanding on
how to use D effectively.

Fantastic forum here on a great language.

Best Regards,
James







Re: Setting a hard limit on slice size, is this possible?

2021-08-07 Thread james.p.leblanc via Digitalmars-d-learn

On Saturday, 7 August 2021 at 12:08:00 UTC, Paul Backus wrote:

On Saturday, 7 August 2021 at 07:32:04 UTC, Tejas wrote:
And if it really is correct, then it seems once again that 
static arrays are the answer after all:


```d
align(your_alignment) int[your_length] array;
```
No need for structs \\('_')/


The main advantage of the struct is that you can heap-allocate 
it:


```d
auto array = new Aligned!(int[4], 16);
```


**First, thanks all for helping with this question!**

The simple desire to arbitrarily align an array is certainly 
looking non-trivial.
Below is a simple program of both the suggested "struct" and 
"align array" solutions.
Unfortunately, neither is guaranteed to place the array with the 
desired alignnment.


import std.stdio;
enum ALIGNMENT=64;
enum LENGTH=10;

struct Aligned(T, size_t alignment) if (alignment >= 
T.alignof)

{
   align(alignment) T payload;
   alias payload this;
}

void main()
{
   writeln("ALIGNMENT:  ", ALIGNMENT, ",\t\tLENGTH:  ", 
LENGTH);


   int[23] junk;
   align(ALIGNMENT) int[LENGTH] z;

   writeln("\nusing 'align(ALIGNMENT) int[LENGTH] z;'");
   writeln("\ncast(ulong) z.ptr%ALIGNMENT:  ", cast(ulong) 
z.ptr%ALIGNMENT);
   writeln("int.alignof:  ", int.alignof, ",\tint.sizeof:  ", 
int.sizeof);


   writeln("&z[0]", &z[0]);
   writeln("&z[1]", &z[1]);
   writeln("&z[2]", &z[2]);

   writeln("\nusing:  'Aligned!(int, ALIGNMENT)[LENGTH] x;'");
   Aligned!(int, ALIGNMENT)[LENGTH] x;

   writeln("x.sizeof:  ", x.sizeof, "\t\tx.alignof:  ", 
x.alignof);

   writeln("x:  ", x);

   writeln("\nx.ptr:  ", x.ptr);
   writeln("&x[0]", &x[0]);
   writeln("&x[1]", &x[1]);
   writeln("&x[2]", &x[2]);
   writeln("\ncast(ulong) x.ptr%ALIGNMENT:  ", cast(ulong) 
x.ptr%ALIGNMENT);

}

---

and here is a sample output of a run:

ALIGNMENT:  64, LENGTH:  10


using 'align(ALIGNMENT) int[LENGTH] z;'

cast(ulong) z.ptr%ALIGNMENT:  ***32***
int.alignof:  4,int.sizeof:  4
&z[0]78D05B60
&z[1]78D05B64
&z[2]78D05B68


using:  'Aligned!(int, ALIGNMENT)[LENGTH] x;'
x.sizeof:  640  x.alignof:  64
x:  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

x.ptr:  78D05B90
&x[0]78D05B90
&x[1]78D05BD0
&x[2]78D05C10

cast(ulong) x.ptr%ALIGNMENT:  ***16***

---

Notice, that neither attempt yields an array starting address as
zero modulo the alignment value ...

Also, a bit weird is that the "align array" solution yields 
expected
spacing between array elements, but the "struct" solution has 
wider

separations ...

--

**Again, I am very appreciative of your replies and help with 
this.**
I have learned quite a bit from this discussion.  However, I 
remain

a bit stumped by all of this

Any ideas out there?

Best Regards,
James





Re: Setting a hard limit on slice size, is this possible?

2021-08-06 Thread james.p.leblanc via Digitalmars-d-learn

mes
On Friday, 6 August 2021 at 17:25:24 UTC, Tejas wrote:


Okay we were overthinking the solution.

Just use a static array

```d
int[your_max_length]/*or whatever type*/ var;
```

You're good to go!

I almost feel stupid now lol


Hello Tejas,

Kind thanks for your replies ... all are appreciated.

However, do NOT feel stupid ... the motivation behind why
I cannot use a standard int[your_max_length] (in other words,
use a static array), is because I need to do a specified
memory alignment (known at compile time) on my slice, or array.

I understand that neither a slice or an array is capable to doing
an arbitrary memory alignment.  (But, perhaps I am wrong about 
this ...)


I believe structs can be aligned, but need to learn more about
the speicific of that.

In the meantime, I  have written a way to get an aligned slice 
from a
static array.  Ugly beginner code is below.  While I believe this 
basic
idea should work, I would like to guarantee that my slice does 
not get

moved in memory (destroying the alignment).

Ugly code here:

--

import std.stdio;

enum MAXLENGTH = 1024;
enum ALIGN = 128;

void main(){

   // static array to allow creation of aligned slice
   ubyte[MAXLENGTH+ALIGN] u;

   writeln("u.ptr:  ", u.ptr);
   auto u_i = cast(ulong) u.ptr;

   auto u_excess = u_i%ALIGN;
   writeln("u_excess: ", u_excess);

   ulong mustadd;
   if(u_excess !=0){
   mustadd = ALIGN-u_excess;
   }
   writeln("mustadd:  ", mustadd);

   // create aligned pointer for our needed slice
   auto zp = cast(double*) (u.ptr + mustadd);

   // create slice
   double[] z = zp[0 .. MAXLENGTH];
   writeln("z.ptr:  ", z.ptr);
   writeln("z.length:  ", z.length);
   auto z_i = cast(ulong) z.ptr;
   auto z_excess = z_i%ALIGN;
   writeln("z_excess:  ", z_excess);
}


Re: Setting a hard limit on slice size, is this possible?

2021-08-06 Thread james.p.leblanc via Digitalmars-d-learn

On Friday, 6 August 2021 at 11:58:59 UTC, Paul Backus wrote:

struct MySlice(T, size_t maxLength)
{
private T[] payload;
invariant(payload.length <= maxLength);
this(T[] slice) { payload = slice; }
T opIndex(size_t i) { return payload[i]; }
// etc.
}

```

Paul,

Thanks very much for your reply.  I understand only
a fraction of the suggested solution.  I will need to
digest this a bit, and do some more background reading
on templates.

My initial, naive attempts to use this in a simple main()
were unsuccessful.  I'll keep plugging at it ...

Best Regards,
James


Setting a hard limit on slice size, is this possible?

2021-08-06 Thread james.p.leblanc via Digitalmars-d-learn

I am aware of the "capacity" concept with slices.

But, I would like to know if it is possible to set a
hard limit on a slice size.

I prefer it to error and crash instead of a doing an
extension or reallocation.

I understand my question screams of "convoluted
thinking".  But, I need to align my slice according to
certain criteria.

(Alternatively, I could use an array ... if I could
align that according to criteria known at compile
time.  Is this possible?).

I have a working solution (ugly trick, maybe is a
better description) to align my slice as desired.

But, the solution would be more robust if I could
guarantee that the slice is never moved in memory.

Any thoughts, hints, etc are welcome!

James





Re: alias using Complex!Double in module ... linker error??

2021-08-03 Thread james.p.leblanc via Digitalmars-d-learn

On Wednesday, 4 August 2021 at 01:10:15 UTC, Mike Parker wrote:
On Tuesday, 3 August 2021 at 21:40:09 UTC, james.p.leblanc 
wrote:

[...]


The alias to Complex!double is a template instantiation. A 
template instantiation creates a symbol that needs to be 
linked. So you need to compile my_module.d along with my_main.d.


```
dmd my_main.d my_module.d
```

Or alternatively:

```
dmd -i my_main.d
```

double is a built-in type, so that alias doesn't create any 
symbols that need linking.


An alias in and of itself is a compile-time-only construct, but 
the symbols you assign it might require linking something.


Mike,

Aha... that makes sense now!

Thanks kindly for helping me understand what was happening with 
your
informative reply.  The fact of template instantiations and 
symbols

had escaped me completely.

I appreciate it.

Best Regards,
James


alias using Complex!Double in module ... linker error??

2021-08-03 Thread james.p.leblanc via Digitalmars-d-learn

I am getting linker errors with this stripped-down example:

---
**my_main.d:**

import std.stdio;
import std.complex;
import my_module;


void main(){
  my_TYPE xxx;
  writeln(xxx);
}

---
**my_module.d:**

module my_module;

import std.complex;

alias my_TYPE = Complex!double;*// this causes link error: 
"undefined reference"*


/* alias my_TYPE = double; */  *// this works fine*

--

Why does the linker fail when I alias to the Complex!double ...
but would work fine when alias to the double ??

Any help to understand what is greatly appreciated.
James




Re: align dynamic array (for avx friendliness) hints? / possible??

2021-08-03 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 3 August 2021 at 17:57:47 UTC, Ali Çehreli wrote:

On 8/3/21 10:50 AM, james.p.leblanc wrote:

> **Is there some highly visible place this is already
documented?

For what it's worth, it appears as "slice from pointer" in my 
index:



http://ddili.org/ders/d.en/pointers.html#ix_pointers.slice%20from%20pointer

Admittedly, one needs to know the concept first to think about 
that entry. :/


Ali


Ali,

Thanks for your message!  (And even a bigger thanks for writing 
your book!)
Your book was one of the first D programming books I read, and 
learned much from

it.

At the time of my reading, I was too much of a new-comer to the 
D-language to see
the importance of the "slice from pointer".  This concept is a 
hidden gem of the

language IMHO!

But, with my recent needs to mix and match native D with the FFTW 
C-functions
in an avx friendly alignment, I was really searching for a way to 
keep the "best
of both worlds".  The "slice from pointer" concepts is a valuable 
one.


I need to go back and read that section of book now!

Best Regards,
James



Re: align dynamic array (for avx friendliness) hints? / possible??

2021-08-03 Thread james.p.leblanc via Digitalmars-d-learn

On Tuesday, 3 August 2021 at 16:32:34 UTC, kinke wrote:
On Tuesday, 3 August 2021 at 12:33:56 UTC, james.p.leblanc 
wrote:

Concise question:
=

I would like to use dynamic arrays, not for their
dynamic sizing properties per se' (slicing, appending, etc).
But, more for their memory protection and efficiencies (for
example,using foreach).

However, I must have the start of my array at an avx
friendly 32 byte alignment.

Is this easily acheivable?

Background:
===

I am interfacing with fftw.  If I use the fftw_malloc, then
I am forced to either:

  1)  copy to/from the allocated arrays to/from my "standard"
  dlang dynamic arrays (loss of efficiency). or ...

  2)  use standard array/pointer mechanisms everywhere(loss
  of memory safely).

My thinking is that I could forego the use of the fftw_malloc,
and simply hand fftw functions my (properly aligned) pointer
of my dlang dynamic array.

All thoughts, comments, hints, greatly appreciated!

James


AFAIK, the GC only guarantees an alignment of 16. But you can 
turn any memory allocation into a slice, simply via


```
size_t length = ...;
T* myPtr = cast(T*) fftw_malloc(length * T.sizeof); // or 
aligned_alloc, posix_memalign etc.

T[] mySlice = myPtr[0 .. length];
foreach (ref e; mySlice) ...
// free!
```


Dear Kinke,

THANKS IMMENSELY!
-

This is exactly the kind of solution that I was hoping would
be possible (elegant, simply, and clear).

This really is the perfect solution, and opens up many 
possibilities for me.


(Perhaps I had been using the wrong search terms, or perhaps 
everyone already
knows how to use this "conversion of C arrays/pointers to D 
slices" solution...

but I was stumped!)

Again, thanks kindly

**Is there some highly visible place this is already documented?
If not, it would make a great blog post as it would be beneficial
to any D newcomers bridging C/D and needing AVX alignments, etc.**


Best Regards,
James



align dynamic array (for avx friendliness) hints? / possible??

2021-08-03 Thread james.p.leblanc via Digitalmars-d-learn

Concise question:
=

I would like to use dynamic arrays, not for their
dynamic sizing properties per se' (slicing, appending, etc).
But, more for their memory protection and efficiencies (for
example,using foreach).

However, I must have the start of my array at an avx
friendly 32 byte alignment.

Is this easily acheivable?

Background:
===

I am interfacing with fftw.  If I use the fftw_malloc, then
I am forced to either:

  1)  copy to/from the allocated arrays to/from my "standard"
  dlang dynamic arrays (loss of efficiency). or ...

  2)  use standard array/pointer mechanisms everywhere(loss
  of memory safely).

My thinking is that I could forego the use of the fftw_malloc,
and simply hand fftw functions my (properly aligned) pointer
of my dlang dynamic array.

All thoughts, comments, hints, greatly appreciated!

James




Initializing a complex dynamic array (with real part from one array, and imaginary from other array)?

2021-07-21 Thread james.p.leblanc via Digitalmars-d-learn
I am trying to initialize a complex dynamic array, from two 
strictly real dynamic arrays (one to be the real part, the other 
to be the imaginary part.


Here is simple sample of what I have tried:

-

import std.stdio;
import std.math;
import std.complex;

void main(){
   auto N=2;

   double[] x,y;
   x.length = N;
   y.length = N;

   x[0] = 1.1;
   x[1] = 2.2;
   y[0] = 3.3;
   y[1] = 4.4;

   Complex!double[] z;
   z.length=N;

   z[] = complex(x[],y[]);
   // z = complex(x,y);  // also tried this, did not work
}


-


The compile error message is:

rdmd post.d
post.d(22): Error: template `std.complex.complex` cannot 
deduce function from argument types `!()(double[], double[])`, 
candidates are:

/home/leblanc/dmd2/linux/bin64/../../src/phobos/std/complex.d(46):`complex(R)(const R re)`

/home/leblanc/dmd2/linux/bin64/../../src/phobos/std/complex.d(56):`complex(R, I)(const R re, const I im)`

  with `R = double[],
   I = double[]`
  whose parameters have the following constraints:
  ``
`  > is(R : double)
  - is(I : double)
`  ``
post.d(22):All possible candidates are marked as 
`deprecated` or `@disable`

  Tip: not satisfied constraints are marked with `>`
Failed: ["/home/leblanc/dmd2/linux/bin64/dmd", "-v", "-o-", 
"post.d", "-I."]


---

I understand, I could write a simple function to do this...but 
was wondering if there is some "standard" way of doing this 
already?


Thanks,
James

PS Is cdouble (and friends) really going to be deprecated??  I 
worry that the loss of the built-in complex types eventually 
might have a downside for syntax and writing.  (But, I might very 
well be wrong about this!!).