Comment #0 by andrej.mitrovich — 2011-06-03T06:15:46Z
import std.math;
import std.stdio;
import std.range;
auto makeSine(int TableSize)()
{
double[TableSize] result;
// double[] result = new double[](TableSize); // this fixes the issue
foreach (index, ref sample; result)
{
sample = cast(double)sin((cast(double)index / cast(double)TableSize) * PI * 2.);
}
writeln(result);
return cycle(result);
}
void main()
{
auto sineTable = makeSine!(10);
writeln(take(sineTable, 10));
writeln(take(sineTable, 10));
double[] arr;
foreach (sample; take(sineTable, 10))
{
arr ~= sample;
}
writeln(arr);
}
Results:
[0, 0.587785, 0.951057, 0.951057, 0.587785, -5.42101e-20, -0.587785, -0.951057, -0.951057, -0.587785]
[6.14906e-318, 2.59842e-307, 2.31044e-317, 0.951057, 0.587785, -5.42101e-20, 2.64149e-308, 2.08636e-317, 1.82805e-307, 2.641e-308]
[6.14906e-318, 2.59842e-307, 2.31044e-317, 2.59842e-307, 2.31044e-317, -5.42101e-20, 2.64149e-308, 2.08636e-317, 1.82805e-307, 2.641e-308]
[6.14906e-318, 2.64128e-308, 2.49803e-307, 2.2817e-314, 6.3666e-314, -5.42101e-20, 2.64149e-308, -nan, 1.82805e-307, 2.64126e-308]
If bugzilla makes it hard to read I've pasted the results here: http://paste.pocoo.org/show/400027/
Comment #1 by andrej.mitrovich — 2011-06-03T06:25:49Z
Actually this has nothing to do with CTFE:
import std.math;
import std.stdio;
import std.range;
auto makeSine()
{
double[10] result;
//~ double[] result = new double[](TableSize); // this fixes the issue
foreach (index, ref sample; result)
{
sample = cast(double)sin((cast(double)index / cast(double)10) * PI * 2.);
}
writeln(result);
return cycle(result);
}
void main()
{
auto sineTable = makeSine();
writeln(take(sineTable, 10));
}
Comment #2 by schveiguy — 2011-06-03T06:34:16Z
Actually, it's expected :) result is on the stack, which goes away when you return from the function (this is why the heap-allocating version has no issues).
I'm assuming the whole shenanigans with cycle and take are so the compiler doesn't complain? That should probably be a hint...
Comment #3 by andrej.mitrovich — 2011-06-03T06:42:45Z
Smiley face, but this is a subtle thing without any warnings from the compiler.
I'm using cycle here for good purpose and not to drown the compiler, take would be used to fill a buffer of some certain length.
I'll just use the heap, it's not a problem. I just assumed using a range on stack-allocated data would copy the data when returning the range from the function.
Comment #4 by andrej.mitrovich — 2011-06-03T06:45:00Z
Actually I can just dup manually instead of using the heap:
return cycle(result.dup);
Comment #5 by schveiguy — 2011-06-03T06:58:42Z
(In reply to comment #3)
> I'm using cycle here for good purpose and not to drown the compiler, take would
> be used to fill a buffer of some certain length.
OK, it just seemed strange that you were cycling something of length 10, and then only taking 10 elements from it. I wondered what the purpose of this was.
Sorry for the assumption.
Comment #6 by andrej.mitrovich — 2011-06-03T07:16:40Z
Here's a more complete example:
http://paste.pocoo.org/show/400066/
Basically it's a sinewave that repeats forever. Changing the stepping will increase the pitch, the buffer length depends on the soundcard (for example the soundcard might require a couple of buffers of a certain length to be filled each second), table size basically increases the resolution or smoothness of the curve.
I think that's it, anyway. I'm still new to the whole concept of audio programming. :)
Comment #7 by bearophile_hugs — 2011-06-03T10:21:52Z
(In reply to comment #4)
> Actually I can just dup manually instead of using the heap:
>
> return cycle(result.dup);
.dup creates a copy on the heap.
This is a safer implementation:
import std.stdio, std.math, std.algorithm, std.range;
auto makeSine() {
return cycle(map!q{ sin(a * PI) }(iota(0, 2, 0.2)));
}
void main() {
auto sineTable = makeSine();
writeln(take(sineTable, 10));
}
Regarding the unsafety of the version that uses a fixed sized array, I'd like the compiler to warn better against such bugs.
Comment #8 by kennytm — 2011-06-03T12:55:56Z
(In reply to comment #7)
> (In reply to comment #4)
> > Actually I can just dup manually instead of using the heap:
> >
> > return cycle(result.dup);
>
> .dup creates a copy on the heap.
>
>
> This is a safer implementation:
>
> import std.stdio, std.math, std.algorithm, std.range;
>
> auto makeSine() {
> return cycle(map!q{ sin(a * PI) }(iota(0, 2, 0.2)));
> }
>
> void main() {
> auto sineTable = makeSine();
> writeln(take(sineTable, 10));
> }
>
>
> Regarding the unsafety of the version that uses a fixed sized array, I'd like
> the compiler to warn better against such bugs.
This will evaluate 'sin(a * PI)' N times, which totally goes against the reason of making a sine table. You should 'array' the 'map' before 'cycle'-ing.