digitalmars.D - avoiding loops, allocation using arrays and ranges
- Danni Coy via Digitalmars-d (30/30) Mar 28 2016 Something just clicked in my head in the last week in terms of
- Basile B. (47/82) Mar 28 2016 I would see a complete lazy processing a bit like that:
- Danni Coy via Digitalmars-d (6/10) Mar 28 2016 .array allocates a new array. I want to store the result of v in a
- Basile B. (8/16) Mar 28 2016 .array is just used to render the result in this demo. It doesn't
- Mithun Hunsur (4/22) Mar 28 2016 I believe you're able to use
- Danni Coy via Digitalmars-d (4/6) Mar 28 2016 yes that did the trick
Something just clicked in my head in the last week in terms of component based programming. I am currently porting a C++ realtime audio app to D. The app uses jackd. I have a series of float[] buffers I read and write audio data from. lets say I want to crossfade to audio buffers I would do the following float[1024] a; //actually these allocated by jackd in C but for purposes of illustration float[1024] b; length = min(length,a.length,b.length); foreach(i; 0..nframes) { /* calculations */ a[i] = a[i]*ratio + b[i] * (1-ratio); } I can do : auto crossfade = sequence(/*calculations*/)(a[],b[],length); foreach(i; 0..length) a[i] = crossfade[i]; but it would be nice if I could do : auto crossfade = sequence(/*calculations*/)(a[],b[],length); a[0..length] = crossfade[0..length]; or even better auto ramp = sequence(/*calculations*/)(length); // create once and store for later a[] = a[]*ramp[] + b[]*(1.0-ramp[]); I know I can use array but that allocates memory and I don't want to do that in my realtime thread. I could store the ramp as a static array but I want to option to do this lazily, particularly if I end up with a lot of different permutations.
Mar 28 2016
On Monday, 28 March 2016 at 07:07:47 UTC, Danni Coy wrote:Something just clicked in my head in the last week in terms of component based programming. I am currently porting a C++ realtime audio app to D. The app uses jackd. I have a series of float[] buffers I read and write audio data from. lets say I want to crossfade to audio buffers I would do the following float[1024] a; //actually these allocated by jackd in C but for purposes of illustration float[1024] b; length = min(length,a.length,b.length); foreach(i; 0..nframes) { /* calculations */ a[i] = a[i]*ratio + b[i] * (1-ratio); } I can do : auto crossfade = sequence(/*calculations*/)(a[],b[],length); foreach(i; 0..length) a[i] = crossfade[i]; but it would be nice if I could do : auto crossfade = sequence(/*calculations*/)(a[],b[],length); a[0..length] = crossfade[0..length]; or even better auto ramp = sequence(/*calculations*/)(length); // create once and store for later a[] = a[]*ramp[] + b[]*(1.0-ramp[]); I know I can use array but that allocates memory and I don't want to do that in my realtime thread. I could store the ramp as a static array but I want to option to do this lazily, particularly if I end up with a lot of different permutations.I would see a complete lazy processing a bit like that: auto process(alias fun, R0, R1)(R0 r0, R1 r1, size_t len) if (isInputRange!R0 && isInputRange!R1 && is(ElementType!R0 == ElementType!R1)) { struct Processor { size_t i; bool empty() { return r0.empty || r1.empty; } void popFront() { ++i; r0.popFront; r1.popFront; } auto front() { return fun(i, len, r0.front, r1.front); } } Processor proc; return proc; } void main(string[] args) { float[] a = [0.0,0.0,0.0,0.0]; float[] b = [1.0,1.0,1.0,1.0]; float xfade(size_t i, size_t len, float sa, float sb) { auto ramp = (1.0 / --len) * i; return sa * ramp + (1.0 - ramp) * sb; } auto r = process!(xfade)(a, b, 4); // not evaluated auto v = process!(xfade)(r, b, 4); // still not... writeln(v.array); // everything gets eval by .array } So that you can get rid of all operators in the processing loop. This is only a demo, I think this could be more elegant and verstatile (for example the fact that the ramp could itself be a lazy range). There's probably some interesting stuff that covers this in std.range. Look at the functions that take some "Range Of Ranges" (RoR) as parameter. like transpose, transversal, etc.
Mar 28 2016
writeln(v.array); // everything gets eval by .array.array allocates a new array. I want to store the result of v in a buffer that I have preallocated in my case this just happens to be a[]; This is quite important. This is also the step I would like a more elegant way to deal with.There's probably some interesting stuff that covers this in std.range. Look at the functions that take some "Range Of Ranges" (RoR) as parameter. like transpose, transversal, etc.Thank you I will certainly take a look at these.
Mar 28 2016
On Monday, 28 March 2016 at 08:13:08 UTC, Danni Coy wrote:.array is just used to render the result in this demo. It doesn't need to be used at all. Anyway the result can be yielded in a pre-allocated array without problem, at the end of the functional stuff just loop on the resulting range and copy. With UFCS this can do something like: foreach(s; a.process!(xfade)(b, 4).process!(xfade)(b, 4)) {/*copy each sample to pre alloc array*/}writeln(v.array); // everything gets eval by .array.array allocates a new array. I want to store the result of v in a buffer that I have preallocated in my case this just happens to be a[]; This is quite important. This is also the step I would like a more elegant way to deal with.
Mar 28 2016
On Monday, 28 March 2016 at 08:21:33 UTC, Basile B. wrote:On Monday, 28 March 2016 at 08:13:08 UTC, Danni Coy wrote:I believe you're able to use https://dlang.org/phobos/std_algorithm_mutation.html#.copy to achieve this..array is just used to render the result in this demo. It doesn't need to be used at all. Anyway the result can be yielded in a pre-allocated array without problem, at the end of the functional stuff just loop on the resulting range and copy. With UFCS this can do something like: foreach(s; a.process!(xfade)(b, 4).process!(xfade)(b, 4)) {/*copy each sample to pre alloc array*/}writeln(v.array); // everything gets eval by .array.array allocates a new array. I want to store the result of v in a buffer that I have preallocated in my case this just happens to be a[]; This is quite important. This is also the step I would like a more elegant way to deal with.
Mar 28 2016
I believe you're able to use https://dlang.org/phobos/std_algorithm_mutation.html#.copy to achieve this.yes that did the trick and alias copyTo = copy; event makes it unambiguous which direction the copy is going in :)
Mar 28 2016