www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Alternate signs in a range

reply "matovitch" <camille.brugel laposte.net> writes:
Hello !

I got a problem which I'm sure can be solved by a smart one 
liner. I would like to obtain the term by term product of a given 
range by the infinite cyclic range cycle([1,-1]). How can I do 
that ?
Jan 26 2014
next sibling parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 12:50:05 UTC, matovitch wrote:
 Hello !

 I got a problem which I'm sure can be solved by a smart one 
 liner. I would like to obtain the term by term product of a 
 given range by the infinite cyclic range cycle([1,-1]). How can 
 I do that ?
dpaste seems to be somewhat slow. import std.range; import std.algorithm; import std.stdio; void main() { auto myRange = iota(0,10); foreach(e; myRange.zip(cycle([1,-1])).map!(a => a[0]*a[1])) writeln(e); } Like this?
Jan 26 2014
parent "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 13:05:55 UTC, Stanislav Blinov 
wrote:
 On Sunday, 26 January 2014 at 12:50:05 UTC, matovitch wrote:
 Hello !

 I got a problem which I'm sure can be solved by a smart one 
 liner. I would like to obtain the term by term product of a 
 given range by the infinite cyclic range cycle([1,-1]). How 
 can I do that ?
dpaste seems to be somewhat slow. import std.range; import std.algorithm; import std.stdio; void main() { auto myRange = iota(0,10); foreach(e; myRange.zip(cycle([1,-1])).map!(a => a[0]*a[1])) writeln(e); } Like this?
Exactly ! I just found this solution too. Thanks.
Jan 26 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
matovitch:

 I got a problem which I'm sure can be solved by a smart one 
 liner. I would like to obtain the term by term product of a 
 given range by the infinite cyclic range cycle([1,-1]). How can 
 I do that ?
void main() { import std.stdio, std.range, std.algorithm; auto r = [10, 20, 30, 40, 50]; auto p = cycle([1, -1]); auto result = r.zip(p).map!(rp => rp[0] * rp[1]); result.writeln; } But it's easy to avoid the multiplication and replace it with a conditional neg. Bye, bearophile
Jan 26 2014
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 13:06:38 UTC, bearophile wrote:
 matovitch:

 I got a problem which I'm sure can be solved by a smart one 
 liner. I would like to obtain the term by term product of a 
 given range by the infinite cyclic range cycle([1,-1]). How 
 can I do that ?
void main() { import std.stdio, std.range, std.algorithm; auto r = [10, 20, 30, 40, 50]; auto p = cycle([1, -1]); auto result = r.zip(p).map!(rp => rp[0] * rp[1]); result.writeln; } But it's easy to avoid the multiplication and replace it with a conditional neg. Bye, bearophile
How would you do this ? map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
Jan 26 2014
parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
 But it's easy to avoid the multiplication and replace it with 
 a conditional neg.

 Bye,
 bearophile
How would you do this ? map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
import std.range; import std.algorithm; import std.stdio; void main() { auto myRange = iota(0,10); auto index = sequence!((a,n) => a[0]+n)(1); auto result = myRange.zip(index).map!(a => a[1] & 1 ? a[0] : -a[0]); result.writeln; }
Jan 26 2014
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 13:21:24 UTC, Stanislav Blinov 
wrote:
 But it's easy to avoid the multiplication and replace it with 
 a conditional neg.

 Bye,
 bearophile
How would you do this ? map!(a => (a.index & 1) ? a : -a)([1, 2]) ? (index field isn't available of course)
import std.range; import std.algorithm; import std.stdio; void main() { auto myRange = iota(0,10); auto index = sequence!((a,n) => a[0]+n)(1); auto result = myRange.zip(index).map!(a => a[1] & 1 ? a[0] : -a[0]); result.writeln; }
Zipping an index array is uglier in my opinion... ;-)
Jan 26 2014
next sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
Now DMD compiler segfaulted. Here is my code if you are 
interested...

The berstein.d file :

import std.array;
import std.range;
import std.traits;
import std.algorithm;

bool isBernstein(alias K)() {

     static if (isArray!(typeof(K)) &&
                 (K.empty || isNumeric!(typeof(K[0]))))
         return true;

     return false;
}

struct Bernstein(alias K, int S)
     if (isBernstein!(K))
{
     immutable typeof(K) kernel = K;
     immutable int shift = S;
}

template reverse(alias B)
{
     alias reverse = Bernstein!(array(retro(B.kernel)),
                                - (B.shift + 
cast(int)B.kernel.length - 1));
}

template alternate(alias B)
{
     alias alternate = Bernstein!(
         array(map!(a => a[0] * a[1])(zip(B.kernel, cycle([-1, 
1])))),
         B.shift);
}

and the berstein_test.d file :

import berstein;
import std.stdio;
import std.range;
import std.algorithm;

void main() {
     alternate!(Bernstein!([1.,1.], 0)) haar_scale;

     writeln(haar_scale.kernel);
     writeln(haar_scale.shift);

}

I get the following error message :

/usr/include/dmd/phobos/std/range.d(4220): Error: Internal 
Compiler Error: CTFE literal Tuple(void, void)._expand_field_0
dmd: ctfeexpr.c:359: Expression* copyLiteral(Expression*): 
Assertion `0' failed.
Aborted (core dumped)
Jan 26 2014
next sibling parent "matovitch" <camille.brugel laposte.net> writes:
 I get the following error message :

 /usr/include/dmd/phobos/std/range.d(4220): Error: Internal 
 Compiler Error: CTFE literal Tuple(void, void)._expand_field_0
 dmd: ctfeexpr.c:359: Expression* copyLiteral(Expression*): 
 Assertion `0' failed.
 Aborted (core dumped)
Someone already encounter this error here http://is.gd/2rsFQJ ...
Jan 26 2014
prev sibling parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 13:33:58 UTC, matovitch wrote:
 Now DMD compiler segfaulted. Here is my code if you are 
 interested...

 struct Bernstein(alias K, int S)
     if (isBernstein!(K))
 {
     immutable typeof(K) kernel = K;
     immutable int shift = S;
 }
s/immutable/enum/ ?
Jan 26 2014
next sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 14:22:16 UTC, Stanislav Blinov 
wrote:
 On Sunday, 26 January 2014 at 13:33:58 UTC, matovitch wrote:
 Now DMD compiler segfaulted. Here is my code if you are 
 interested...

 struct Bernstein(alias K, int S)
    if (isBernstein!(K))
 {
    immutable typeof(K) kernel = K;
    immutable int shift = S;
 }
s/immutable/enum/ ?
I am a *total* beginner so I am sure my code should look at least strange to experts. How should I write this ? Why ? ps : It seems the compiler lost the type information when unpacking the tuple ? This code doesn't compile : template alternate(alias B) { alias alternate = Bernstein!( array(map!(a => a[0])(zip(B.kernel, cycle([-1, 1])))), B.shift); }
Jan 26 2014
parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 14:29:54 UTC, matovitch wrote:

 s/immutable/enum/

 ?
I am a *total* beginner so I am sure my code should look at least strange to experts. How should I write this ? Why ?
I am not sure exactly what are you trying to achieve. My comment meant "ditch immutable, replace with enum" :) Also ditch array() calls. This compiles: import std.array; import std.range; import std.traits; import std.algorithm; template isBernstein(alias K) { enum bool isBernstein = (K.empty || isNumeric!(typeof(K.front))); } struct Bernstein(alias K, int S) if (isBernstein!K) { enum kernel = K; enum shift = S; } template reverse(alias B) { alias reverse = Bernstein!(retro(B.kernel), -(B.shift + cast(int)B.kernel.length - 1)); } template alternate(alias B) { alias alternate = Bernstein!(map!(a => a[0] * a[1])(zip(B.kernel, cycle([-1, 1]))), B.shift); } void main() { alias haar_scale = alternate!(Bernstein!([1.,1.], 0)); writeln(haar_scale.kernel); writeln(haar_scale.shift); } I don't know if it works as intended though.
 ps : It seems the compiler lost the type information when 
 unpacking the tuple ?
Which tuple?
 This code doesn't compile :

 template alternate(alias B)
 {
     alias alternate = Bernstein!(
         array(map!(a => a[0])(zip(B.kernel, cycle([-1, 1])))),
         B.shift);
 }
It does for me.
Jan 26 2014
parent "matovitch" <camille.brugel laposte.net> writes:
It works exactly as expected. Thank you very much for your help !
Jan 26 2014
prev sibling parent "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 14:22:16 UTC, Stanislav Blinov 
wrote:
 On Sunday, 26 January 2014 at 13:33:58 UTC, matovitch wrote:
 s/immutable/enum/

 ?
I just get the vi style ! :D
Jan 26 2014
prev sibling parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 13:24:06 UTC, matovitch wrote:

 Zipping an index array is uglier in my opinion... ;-)
Extract it into a function and stick it into your library, it's extremely useful :) import std.range; import std.algorithm; import std.stdio; auto enumerate(R)(R r) { return zip(sequence!((a,n) => a[0]+n)(0), r); } void main() { auto myRange = iota(0,10); auto result = myRange.enumerate.map!(a => a[0] & 1 ? -a[1] : a[1]); result.writeln; } We need generic enumerate() in Phobos :(
Jan 26 2014
next sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
 Extract it into a function and stick it into your library, it's 
 extremely useful :)
Anyway, the proposed solutions use twice much memory than a simple for loop...is the compiler smart enougth to optimize this kind of code ?
Jan 26 2014
parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 13:45:32 UTC, matovitch wrote:

 Anyway, the proposed solutions use twice much memory than a 
 simple for loop...
???
 is the compiler smart enougth to optimize this kind of code ?
There are ongoing discussions on what and how current D compilers optimize nowadays. I don't have a link though.
Jan 26 2014
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 14:13:28 UTC, Stanislav Blinov 
wrote:
 On Sunday, 26 January 2014 at 13:45:32 UTC, matovitch wrote:

 Anyway, the proposed solutions use twice much memory than a 
 simple for loop...
???
Well in a for loop, you only need one more index variable whereas here we store the whole index range.
Jan 26 2014
parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 14:24:35 UTC, matovitch wrote:

 Well in a for loop, you only need one more index variable 
 whereas here we store the whole index range.
Not the *whole* range, that would be impossible since it's infinite :) In this particular instance, index range is a struct consisting of three variables: initial state (0), current sequencer (n), and current element as cache. D ranges are lazy. Well, most of them.
Jan 26 2014
parent "matovitch" <camille.brugel laposte.net> writes:
On Sunday, 26 January 2014 at 14:32:48 UTC, Stanislav Blinov 
wrote:
 On Sunday, 26 January 2014 at 14:24:35 UTC, matovitch wrote:

 Well in a for loop, you only need one more index variable 
 whereas here we store the whole index range.
Not the *whole* range, that would be impossible since it's infinite :) In this particular instance, index range is a struct consisting of three variables: initial state (0), current sequencer (n), and current element as cache. D ranges are lazy. Well, most of them.
This is great ! Let's trust phobos then.
Jan 26 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Stanislav Blinov:

 We need generic enumerate() in Phobos :(
It will come soon :-) https://github.com/D-Programming-Language/phobos/pull/1866 (Take a look at my comment about foreach there) This also shows we need a good syntax to unpack tuples:
 void main() {
 	auto myRange = iota(0,10);
 	auto result = myRange.enumerate.map!(a => a[0] & 1 ? -a[1] : 
 a[1]);
 	result.writeln;
 }
It could be written like: myRange.enumerate.map!(t{i, x} => i % 2 ? -x : x); Bye, bearophile
Jan 26 2014
parent "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Sunday, 26 January 2014 at 13:49:34 UTC, bearophile wrote:
 Stanislav Blinov:
 We need generic enumerate() in Phobos :(
It will come soon :-) https://github.com/D-Programming-Language/phobos/pull/1866
Cool!
 This also shows we need a good syntax to unpack tuples:
100% agree.
 myRange.enumerate.map!(t{i, x} => i % 2 ? -x : x);
Why not just like ((i, x) => i % 2 ? -x : x)? Isn't (a,b,...) how an unpacked tuple should look like?
Jan 26 2014