bug, or is this also intended?

2016-10-03 Thread deed via Digitalmars-d-learn

Unexpected auto-concatenation of string elements:

string[] arr = ["a", "b" "c"];// ["a", "bc"], length==2
int[] arr2   = [[1], [2] [3]];// Error: array index 3 is out 
of bounds [2][0 .. 1]
  // Error: array index 3 is out 
of bounds [0..1]


dmd 2.071.2-b2



Re: Meta-programming: iterating over a container with different types

2016-09-23 Thread deed via Digitalmars-d-learn

On Friday, 23 September 2016 at 09:21:56 UTC, Claude wrote:

...


// Maybe you can try using std.variant?

import std.variant;
alias Component = Variant;

class Entity
{
void register (Component v) { components ~= v; }
void unregister (T) () {
foreach (i, c; components) if (c.type == typeid(T))
components = components[0..i] ~ components[i+1 .. $];
}
Component getComponent (T) () {
foreach (i, c; components) if (c.type == typeid(T))
return components[i];
}
Component[] components;
// iterating over the components
alias components this;

// or you can provide an inputRange interface by implementing
//
// bool empty () {}
// Component front () {}
// void popFront () {}
//
// to support whatever type of backing data structure you 
have.

// (see http://ddili.org/ders/d.en/ranges.html)
}

unittest
{
import std.stdio;
Entity e = new Entity();
e.register(Component(42));
e.register(Component("loire"));
e.register(Component(3.14));
foreach (c; e) write(c, " "); writeln;  // Prints 42 "loire" 
3.14

e.unregister!string;
foreach (c; e) write(c, " "); writeln;  // Prints 42 3.14
e.unregister!double;
foreach (c; e) write(c, " "); writeln;  // Prints 42
e.unregister!int;
assert(e.components.length == 0);
}


Re: bug?

2016-09-15 Thread deed via Digitalmars-d-learn
On Thursday, 15 September 2016 at 14:42:13 UTC, Jonathan M Davis 
wrote:
On Thursday, September 15, 2016 14:07:18 deed via 
Digitalmars-d-learn wrote:
On Thursday, 15 September 2016 at 13:57:13 UTC, rikki 
cattermole


wrote:
> Not a bug, it is never used.

I'd expect an "Error: ... no effect ..." from the compiler.


That would only work in fairly simplistic cases. For instance, 
if you were allocating an array of structs instead of an array 
of ints, then it _could_ have an effect. So, it's not an error 
that would catch much. And it's not like the code is doing 
anything illegal - just useless, which is why it gets optimized 
out.


- Jonathan M Davis


I dont't feel strongly about this at all, it was just my first 
reaction that it was a meaningless statement that the compiler 
should warn about or give an error on.


I'm curious when you would need to do only `new Struct[](1000);` 
instead of

`auto structs = new Struct[](1000);`?

In case it was not clear, the code was:
char[] str;
// ...
str.length = ...
str[i] = ...

and was intended to be updated to:
char[] str = new char[](len);
// ...
str[i] = ...

but somehow the line ended up as
char[] str; new char[](len);
// ..
str[i] = ... // oops.


Re: bug?

2016-09-15 Thread deed via Digitalmars-d-learn
On Thursday, 15 September 2016 at 13:57:13 UTC, rikki cattermole 
wrote:

Not a bug, it is never used.


I'd expect an "Error: ... no effect ..." from the compiler.


bug?

2016-09-15 Thread deed via Digitalmars-d-learn

void main ()
{
new int[](1);
}

Compiles with dmd 2.071.2-b2, but no code is generated for `new 
int[](1);`.

Caused a bug due to:

char[] arr;
got updated to
char[] arr; new char[](SIZE);

If it's considered a bug and someone would file it, I'd be 
thankful.


Re: Chaining opIndex

2016-05-10 Thread deed via Digitalmars-d-learn

On Monday, 9 May 2016 at 22:33:37 UTC, John Colvin wrote:

There are lots of ways to approach this. Here's one possibility:

auto cars(Bar bar)
{
static struct Res
{
Bar bar;
Car opIndex(size_t i)
{
return /* e.g. getCar(bar, i); */
}
}
return Res(bar);
}


Thanks. Didn't think of function returning struct with opIndex. 
Having this as opCall in a struct Cars might be a solution.


What other approaches did you have in mind?


Chaining opIndex

2016-05-09 Thread deed via Digitalmars-d-learn

struct Foo {
Bars bars;
...
}

struct Foos {
Foo[] arr;
Foo opIndex (size_t idx) { return arr[idx]; }
...
}

struct Bar {
// No Car[] cars;
...
}

struct Bars {
Bar[] arr;
Bar opIndex (size_t idx) { return arr[idx]; }
...
}

struct Car {
...
}

Foos foos;
Foo foo = foos[1];  // Works
Bar bar = foos[1].bars[2];  // Works
Car car = foos[1].bars[2].cars[3];  // Desired abstraction.

For any Bar there are some Cars, but Bar doesn't hold any Cars. 
In other words, there could be a function Car cars (Bar bar, 
size_t idx) { ... }, but that would be called with parens;


Car car = foos[i].bars[j].cars(k);

which would be inconsistent and confusing. Defining

struct Cars {
Car opIndex (Bar bar, size_t idx) {}
}

and

struct Bar {
Cars cars;
...
}

doesn't enable chaining and then would have to be used like this, 
AFAIK:


Car car = cars[foos[i].bars[j], k];

Which is out of the question. Any suggestions to achieve the 
desired abstraction in a clean manner?




Re: aliasing/referencing expressions in with statements

2016-04-22 Thread deed via Digitalmars-d-learn

On Friday, 22 April 2016 at 01:42:11 UTC, Yuxuan Shui wrote:

Maybe use something like:

auto a = () => instanceA.verboseFieldA.verboseFieldB;


You can certainly declare temporaries and rely on the compiler 
optimizing those away:


auto a = instanceA.verboseFieldA.verboseFieldB;
auto b = instanceA.aDescriptiveName;
auto value = intanceC.value;

// use a, b and value

If that were considered a sound solution, it would partly 
undermine the purpose of with statements, except for referring to 
multiple fields within the same instance, which I guess is common 
enough and makes it more convenient to express member functions 
as free functions. However, it seems simple for the compiler to 
lower such a with statement, so I wonder whether there are any 
technical reasons not to? I.e:


with (a = expressionA, b = expressionB, instanceC) {
  // access to instanceC's fields and replace a and b
  // with expressionA and expressionB, respectively.
}

That would make for very clear expressions while still allowing 
descriptive field names. Other solutions, as templates or mixins, 
seem a little too clumsy.


aliasing/referencing expressions in with statements

2016-04-21 Thread deed via Digitalmars-d-learn
Often I find myself wanting to alias an expression, such as 
verbose fields, possibly nested. AFAIK, the with statement makes 
it easier, but not as good as it could have been. What I'd like 
to express is for example something like this:



with( a = instanceA.verboseFieldA.verboseFieldB,
  b = instanceA.aDescriptiveName,
  instanceC)
{
  // use a, b and value:
  b[value] = b[a + value] * (a*value)^^a;
}

// given:

struct A {
  B verboseFieldA;
  int[] aDescriptiveName;
  ...
}
struct B {
  int verboseFieldB;
  ...
}
struct C {
  int value;
  ...
}

A instanceA;
B instanceB;
C instanceC;


1) Is it possible to achieve something similar in D now? And if 
not:
2) Are there any implementation considerations in this direction, 
extending the with statement?


Re: Set cursor position in a file

2016-04-10 Thread deed via Digitalmars-d-learn

On Sunday, 10 April 2016 at 16:19:51 UTC, Lucien wrote:

Hello,

Is there the possibility to set the cursor position in a file ?

Example:

void main()
{
  File myFile = File("myFile.txt");

  showFile(myFile);

  // set cursor pos to 0

  showFile(myFile);
}

void showFile(File f)
{
  while (!f.eof())
  {
write(f.readln());
  }
}


Thanks in advance.


See std.stdio.File.seek.

For your example, if all you want to do is to write a file to 
std.out:

---
import std.file : read;
import std.stdio : write;

string file = cast(string) read("filename.txt");
write(file);
---



Re: Ternary if and ~ does not work quite well

2015-10-12 Thread deed via Digitalmars-d-learn

On Monday, 12 October 2015 at 15:39:15 UTC, TheFlyingFiddle wrote:

How does this compile?


{
string str = "hello";
foreach (n; [32, 119, 111, 114, 108, 100, 33]) str ~= n;

import std.stdio : writeln;
str.writeln;// prints "hello world!"

writeln(true == 1); // true
writeln(false == 0);// true

string str2 = str.dup;

str ~= 0;
str2 ~= false;
writeln(str == str2);   // true

str ~= 1;
str2 ~= true;
writeln(str == str2);   // true
}



Re: reading file byLine

2015-09-14 Thread deed via Digitalmars-d-learn

On Monday, 14 September 2015 at 18:36:54 UTC, Meta wrote:
As an aside, you should use `sort()` instead of the 
parentheses-less `sort`. The reason for this is that doing 
`arr.sort` invokes the old builtin array sorting which is 
terribly slow, whereas `import std.algorithm; arr.sort()` uses 
the much better sorting algorithm defined in Phobos.


Thanks for pointing out.


Re: reading file byLine

2015-09-13 Thread deed via Digitalmars-d-learn

On Sunday, 13 September 2015 at 03:20:31 UTC, deed wrote:

string s = "Some text";
s.retro.find("e"); // `Some te` (Surprising to me. 
Error? 2.067.1)


Sorry, the above is wrong, .retro.find does indeed return what's 
expected.


string s = "Some text";
s.retro.find("e").writeln;   // Prints `et emoS`, as expected.


Re: reading file byLine

2015-09-13 Thread deed via Digitalmars-d-learn

On Sunday, 13 September 2015 at 03:20:31 UTC, deed wrote:

...
and since `string` is an alias for `const(char)[]`, it's not ...


string is an alias for immutable(char)[], not const(char)[].
http://dlang.org/arrays.html#strings

Sorry about the noise.




Re: reading file byLine

2015-09-12 Thread deed via Digitalmars-d-learn

On Saturday, 12 September 2015 at 12:51:04 UTC, Namal wrote:
Anyway, there is no .reverse for strings I guess, what is the 
way to completely reverse a string in D?


What do you want to do? Do you want to keep your data in original 
order, but get a reversed view of it for something, or do you 
actually want to reverse your original array?


You can use `retro` to simply read your array backwards, i.e.:
string s = "Some text";
s.retro.writeln;   // `txet emoS`
s.writeln; // `Some text`
s.retro.find("e"); // `Some te` (Surprising to me. Error? 
2.067.1)

s.retro.until("e").writeln;// `tx`
s.find("e");   // `Some`

The string is still kept in original order, but `retro` returns a 
range reading the array backwards. If you want to store a 
reversed string in memory, that's possible too, of course. One 
way of doing it, is to convert your retro range to a string:


s = s.retro.to!string;
s.writeln; // `txet emoS`

This will allocate new memory for the reversed copy and assign it 
to `s`.
Reverse is an algorithm that swaps values at different indices 
and since `string` is an alias for `const(char)[]`, it's not 
allowed. It means that each element of the array is const, so you 
cannot mutate any elements, but you can append or remove elements 
or assign the slice to view another part of the string or some 
other string. Hence, a `s.reverse` will give you an error. If you 
use `char[]` instead of `const(char)[]` you can use reverse and 
reuse the same memory for the reversed `char[]`. To illustrate:


char[] t = ['a', 'b', 'c'];
std.algorithm.reverse(t);
t.writeln; // `cba`

// s[0] = s[$-1];  // Error, cannot mutate const elements
auto r = s.retro;
s.length = 0;
r.each!(e => s ~= e);
s.writeln; // s has the reversed string, obtained 
through
   // a temporary range object, setting 
length to
   // zero and appending the elements 
from the
   // range, which is allowed for 
const(char)[]


Re: Adjacent Pairs Range

2015-09-12 Thread deed via Digitalmars-d-learn

On Saturday, 12 September 2015 at 10:17:19 UTC, Nordlöw wrote:
How do I most elegantly iterate all the adjacent pairs in an 
`InputRange` using Phobos?


Something like

[1,2,3,4] => [(1,2), (2,3), (3,4)]


Why not just:

zip(arr[0 .. $-1], arr[1 .. $])

?


Re: Lazy sort

2015-09-11 Thread deed via Digitalmars-d-learn

On Friday, 11 September 2015 at 10:41:16 UTC, ixid wrote:
Does sort have to be eager or would it be possible to have a 
lazy version? It's messy to always have to use array and leap 
in and out of lazy operations within a UFCS chain. Surely as 
many functions as possible should be optionally lazy.


Wouldn't that mean removing min or max lazily?


Re: using std.algorithm to find intersection of DateTime[][] arg

2015-09-10 Thread deed via Digitalmars-d-learn
On Wednesday, 9 September 2015 at 20:28:35 UTC, Laeeth Isharc 
wrote:

I have a DateTime[][] arg ...
I would like to find the intersection of the dates.


A suggestion:

auto minLength  = arg.map!(a => a.length).reduce!min;
auto minIdx = arg.map!(a => 
a.length).countUntil(minLength);
auto intersection   = arg[minIdx].filter!(e => 
chain(arg[0..minIdx], arg[minIdx..$]).all!(a => 
a.assumeSorted.contains(e)));


reduce with setIntersection seems the most straightforward, but 
needs array AFAIK, i.e.:


auto intersection =
//reduce!((r, x) => setIntersection(r, x))(arg);  // doesn't 
work
  reduce!((r, x) => setIntersection(r, x).array)(arg);// does, 
but with array




Re: What is "FilterResult" type?

2015-09-09 Thread deed via Digitalmars-d-learn
On Wednesday, 9 September 2015 at 11:30:26 UTC, Bahman Movaqar 
wrote:

On Wednesday, 9 September 2015 at 08:29:20 UTC, cym13 wrote:

The way I would have written it is:

auto result = foobars.filter!(fb => nums.all!(n => (fb.x * 
fb.y) > n))
 .filter!(fb => nums.all!(n => fb.x < n && 
fb.y < n));


For the lame example I gave, something similar occurred to me 
at first; but then I thought 4 `filter`s (assuming `all` is 
simply a `filter`) might be non-idiomatic as it might incur 
some performance penalty.


Note that this can easily be rewritten with only one `filter` and 
one `all`:


auto result = foobars.filter!(
fb => nums.all!(
n => fb.x * fb.y > n
  && fb.x < n
  && fb.y < n));


Re: reading file byLine

2015-09-07 Thread deed via Digitalmars-d-learn

On Sunday, 6 September 2015 at 22:04:55 UTC, Namal wrote:
oh, sorry. But I found out what I have been doing wrong besides 
that.


arr.sort.uniq;

uniq(arr) or arr.sort.uniq; compiles but doesn't store it in 
the arr array, I need to store it in a new one.


Right, it's like

int x = 3;
// x + 5;  // Just an expression evaluated to 8,
   // but what do you want to do with it?
   // It won't affect your program and the
   // compiler will give you an error.

int y = x + 5; // But you can assign the expression to
   // a new variable
x = x + 5; // or you can assign it back
writeln(x);// or you can pass it to a function.


// For your case:

int[] arr = [1, 2, 3, 2, 1, 4];
arr.sort;  // Operating on arr in place -> arr itself is 
mutated

arr.writeln;   // [1, 1, 2, 2, 3, 4]
arr.uniq;  // Not operating on arr, it's like the 
expression

   // x + 5 (but no compiler error is given).
arr.uniq.writeln;  // [1, 2, 3, 4] (Expression passed to writeln)
arr.writeln;   // [1, 1, 2, 2, 3, 4] (Not affected)

int[] newArr = arr.uniq.array;
   // Expression put into a new array assigned to 
newArr

newArr.writeln;// [1, 2, 3, 4]
arr.writeln;   // Still the sorted array. [1, 1, 2, 2, 3, 4]
arr = arr.uniq.array; // Now arr is assigned the uniq array
arr.writeln;   // [1, 2, 3, 4]


You need to know whether the function will mutate your array; 
sort does, while uniq doesn't. If you want to do things requiring 
mutation, but still want your original data unchanged, you can 
duplicate the data with .dup before the mutating operations, like 
this:


int[] data = [1, 2, 2, 1];
int[] uniqData = data.dup.sort.uniq.array;
data.writeln;  // [1, 2, 2, 1] Unchanged, a duplicate was 
sorted.

uniqData.writeln;  // [1, 2]



Re: reading file byLine

2015-09-07 Thread deed via Digitalmars-d-learn

On Monday, 7 September 2015 at 10:25:09 UTC, deed wrote:

writeln(x);// or you can pass it to a function.


I meant `writeln(x + 5)`


Re: reading file byLine

2015-09-06 Thread deed via Digitalmars-d-learn

On Sunday, 6 September 2015 at 17:57:49 UTC, Namal wrote:

Yeah, I just checked, it is 2.066,  how can I install the new 
version on ubuntu with sudo apt-get?


sudo apt-get install dmd
will give you dmd v2.067.1. Don't know when it will be upgraded 
to 2.068 though.


Re: reading file byLine

2015-09-05 Thread deed via Digitalmars-d-learn

On Saturday, 5 September 2015 at 17:31:39 UTC, Namal wrote:

Yeah, I have have been trying this example from wiki books

https://en.wikibooks.org/wiki/Learning_D_With_Project_Euler

It is not even compiling.


What exactly is not compiling?


Re: reading file byLine

2015-09-05 Thread deed via Digitalmars-d-learn

On Saturday, 5 September 2015 at 12:41:37 UTC, Namal wrote:
Thx guys. Now I try out the split function. I read the file as 
a single string?


auto arr = split(cast(string)read(filename),",");

where the file has "A", "B", "C"

and I get the output ["\"A\"", " \"B\"", " \"C\"\n"]

I can understand that read functions reads the endl but what 
does it with the quotation marks? how can I modify read so I 
get just ["A", "B", "C"]


'\' is the escape character and is used to disambiguate start or 
end of string (") and a quotation mark within the string (\"), 
the same way as "\n" means newline and not '\' 'n', which would 
have been "\\n".


So what you have is [`"A"`, ` "B"`, ` "C"\n`], if you use ` for 
start\stop of string. You say you want ["A", "B", "C"], so you 
need to remove whitespace. You can do that with std.string.strip. 
Assuming you also want to remove the quotation marks present in 
the file, one solution is to use std.string.chomp and 
std.string.chompPrefix, for example:


string s = cast(string) read(filename);
s.split(",")
 .map!strip
 .map!(s => chomp(s, "\"")
 .map!(s => chompPrefix(s, "\"")
 .writeln
 ;


Re: reading file byLine

2015-09-05 Thread deed via Digitalmars-d-learn

On Saturday, 5 September 2015 at 14:44:19 UTC, deed wrote:

 .map!(s => chomp(s, "\"")
 .map!(s => chompPrefix(s, "\"")


should be

 .map!(s => chomp(s, "\""))
 .map!(s => chompPrefix(s, "\""))


Re: reading file byLine

2015-09-04 Thread deed via Digitalmars-d-learn

On Friday, 4 September 2015 at 07:27:54 UTC, Namal wrote:

On Friday, 4 September 2015 at 01:55:13 UTC, deed wrote:

On Friday, 4 September 2015 at 01:31:28 UTC, Namal wrote:
How can I get just the maximum element? Do I need to give a 
range for it?


Use max? 
http://dlang.org/phobos/std_algorithm_comparison.html#max


Sorry, I don't understand the syntax yet. How do I tell max to 
search all elements?

You can search all elements by using reduce
http://dlang.org/phobos/std_algorithm_iteration.html#reduce


I mean, why does sort(myarray) is legit and max(myarray) isn't.

I don't know why, other than that is the current design in Phobos.


import std.algorithm, std.range, std.array, std.string, std.stdio,
std.conv;

int[] arr1 = [1, 2, 30];
//arr1.max.writeln; // Doesn't work, as you say
arr1.reduce!max.writeln;// This does. Prints 30.

int[] arr2 = [4, 5, 6];
int[][] arr = [arr1, arr2];
arr.reduce!max.writeln; // Returns either arr1 or arr2. 
Element by
// element comparison until one is 
greatest.

// Prints arr2, since 1 < 4.
arr.joiner.reduce!max.writeln; // Flattens arr1 and arr2 to one 
arr and

// finds max. Prints 30.

//For your example:
auto f = File("filename", "r");
auto numbers = f// 1 2 3\n4 5 6
.byLine // ["1 2 3", "4 5 6"]
.map!(a => a.split) // [["1", "2", "3"], ["4", "5", "6"]]
.map!(a => a.to!(int[]))// [[1, 2, 3], [4, 5, 6]]
.array; // Allocates and puts the elements 
into an

// int[][] for reuse of state.

numbers // [[1, 2, 3], [4, 5, 6]]
.map!(reduce!max)   // [3, 6]
.writeln;   // prints [3, 6]

numbers // [[1, 2, 3], [4, 5, 6]]
.joiner // [1, 2, 3, 4, 5, 6]
.reduce!max // 6
.writeln;   // prints 6


Re: reading file byLine

2015-09-03 Thread deed via Digitalmars-d-learn

On Friday, 4 September 2015 at 01:31:28 UTC, Namal wrote:
How can I get just the maximum element? Do I need to give a 
range for it?


Use max? http://dlang.org/phobos/std_algorithm_comparison.html#max


Struct template

2014-11-03 Thread deed via Digitalmars-d-learn

struct Internal { int i; double d; string s; }

struct External_int {
  Internal internal;
  @property Internal* ptr () { return internal; }

  this (int a)
  {
internal.s = int;
internal.i = a;
  }
}

struct External (T) {
  Internal internal;
  @property Internal* ptr () { return internal; }

  static if (is(typeof(T) == int))
  {
this (T a)
{
  internal.s = int;
  internal.i = a;
}
  }
}

void main ()
{
  auto e1 = External_int(1); // Ok
  auto e2 = External!int(1); // Nope, cannot implicitly
 // convert expression (1)
 // of type int to Internal
}


Why? And how is this fixed? Thanks.


Re: Struct template

2014-11-03 Thread deed via Digitalmars-d-learn

static if (is(typeof(T) == int))

should be

static if (is(T == int))


T is already a type.


Ahh. Thanks!


win64 - win32.oaidl.VARIANT - error LNK2019

2014-10-31 Thread deed via Digitalmars-d-learn
// bindings from 
https://github.com/CS-svnmirror/dsource-bindings-win32/blob/308739a417eaaba85a5d3ce7741fd43d3042efe0/oaidl.d


---
import win32.oaidl;

// The following gives linker error: error LNK2019: unresolved 
external

// symbol _D5win325oaidl7VARIANT6__initZ referenced
// in function ...
VARIANT v;
v.vt = VARENUM.VT_I4;
v.lVal = 1;

// while this works - no linker error
VARIANT v = { vt: VARENUM.VT_I4, lVal: 1 };


Defining a similar structure as VARIANT with anonymous structs 
and unions targeting linux seemed to work fine without linker 
problems. What is the idiomatic way of handling this on win64?


Re: win64 - win32.oaidl.VARIANT - error LNK2019

2014-10-31 Thread deed via Digitalmars-d-learn
Your link is failing because the .init value of the struct is 
not found. The .init will be in the object file corresponding 
to the module where the struct is defined, so to fix the linker 
error, add the win32.oaidl module to the list of modules you're 
compiling and linking. An easy way to do that is to use rdmd 
instead of dmd to build your program.


Thank you for your prompt reply and maintaining the bindings on 
GitHub!


I used dub (with dmd). The win32 files reside in another 
directory and the path is specified in importPaths. If I 
understand you correctly, the oaidl.d file should also be 
specified in sourceFiles in the .json file?


Re: Bug?

2014-10-24 Thread deed via Digitalmars-d-learn

On Thursday, 23 October 2014 at 21:42:46 UTC, anonymous wrote:

On Thursday, 23 October 2014 at 21:17:25 UTC, deed wrote:

Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
for both Windows and Linux. This just illustrates the sin 
function.


I think the tests marked [1] are expected to fail. They 
involve

converting one operand of the comparison to double, but not the
other. The comparison is done using real precision. So, one
operand goes through a real-double-real conversion, which
changes the value.


You're right about those marked [1]; sin returns real and 
shouldn't be expected to equal the same value truncated to double 
or float and then extended back to real.


Converting the sin to double and compare is expected to work for 
those, and it does when compiled with -m64, but not with -m32, on 
Linux:


--
import std.math : sin;
import std.conv : to;
double fun (double a) { return sin(a); }

immutable double a = 3.
assert (fun(a) == sin(a).to!double);  // Works when compiled with 
-m64

--

The behaviour of those only marked [2] and [4] (the 32-bit 
versions) seems to be a bug.


Re: Bug?

2014-10-24 Thread deed via Digitalmars-d-learn
OK, I tried with OSX 64-bit compiler. Perhaps 32 bit would not 
fare as well. What platform are you testing on?


Have tried Linux and Windows 64-bit and it seems to be an issue 
when compiled with -m32. Tests are provided here 
http://dpaste.dzfl.pl/5f55f4152aa8.


I agree that one cannot compare double and real and expect 
equality, so the ones marked with [1] are not incorrect 
behaviour, while [2] and [4] seem to be bugs.




Bug?

2014-10-23 Thread deed via Digitalmars-d-learn

// DMD v2.066.0
// All asserts pass (!)

import std.math : sin, cos, tan, asin, acos, atan,
  sinh, cosh, tanh, asinh, acosh, atanh;

alias F = double;

immutable F a = 3, b = 5;

F fmul (F a) pure { return a * b;  }
F fsin (F a) pure { return sin(a); }

struct Smul { F value; this (F a) { value = a * b;  } alias value 
this; }
struct Ssin { F value; this (F a) { value = sin(a); } alias value 
this; }


F ans_mul = fmul(a);
F ans_sin = fsin(a);

Smul smul = Smul(a);
Ssin ssin = Ssin(a);


// All combinations of a*b, fmul(a), Smul(a), ans_mul and smul 
pass

// the equality test. E.g.:
assert (a*b == a*b);
assert (a*b == fmul(a));
assert (a*b == Smul(a));
assert (a*b == ans_mul);
assert (a*b == smul);

assert (fmul(a) == fmul(a));
assert (fmul(a) == Smul(a));
assert (fmul(a) == ans_mul);
assert (fmul(a) == smul);


// However, for std.math.sin it's different:
assert (sin(a) == fsin(a));// But not in 2.065
assert (sin(a) != Ssin(a));// ?
assert (sin(a) != ans_sin);// ?
assert (sin(a) != ssin);   // ?

assert (fsin(a) != fsin(a));   // ?
assert (fsin(a) != Ssin(a));   // ?
assert (fsin(a) != ans_sin);   // ?
assert (fsin(a) != ssin);  // ?

// Same goes for cos, tan, asin, acos, atan:
F fcos  (F a) { return cos(a);  }
F ftan  (F a) { return tan(a);  }
F fasin (F a) { return asin(a); }
F facos (F a) { return acos(a); }
F fatan (F a) { return atan(a); }

assert (fcos(a)  != fcos(a));  // ?
assert (ftan(a)  != ftan(a));  // ?
assert (fasin(a) != fasin(a)); // ?
assert (facos(a) != facos(a)); // ?
assert (fatan(a) != fatan(a)); // ?


// And then it goes only downhill for
// sinh, cosh, tanh, asinh, acosh and atanh:
assert (sinh(a)!= sinh(a));// ?
assert (cosh(a)!= cosh(a));// ?
assert (tanh(a)!= tanh(a));// ?
assert (asinh(a)   != asinh(a));   // ?
assert (acosh(a)   != acosh(a));   // ?
assert (atanh(0.5) != atanh(0.5)); // ?

--

Why bother?

import std.algorithm : max;

F fun (F a, F b) { return max(a,b) + 1.; }
unittest { assert (gun(1, 2) == gun(2, 1)); } // Passes

F pun (F a, F b) { return sin(max(a,b)); }
unittest { assert (fun(1, 2) == fun(2, 1)); } // Fails


Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn



--

Why bother?

import std.algorithm : max;

F fun (F a, F b) { return max(a,b) + 1.; }
unittest { assert (gun(1, 2) == gun(2, 1)); } // Passes

F pun (F a, F b) { return sin(max(a,b)); }
unittest { assert (fun(1, 2) == fun(2, 1)); } // Fails


// Fun, gun, pun...
unittest { assert (fun(1, 2) == fun(2, 1)); } // Passes
unittest { assert (pun(1, 2) == pun(2, 1)); } // Fails


Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn

assert (fasin(a) != fasin(a)); // ?
assert (facos(a) != facos(a)); // ?


Too quick there.. But:

assert (fasin(0.5) != fasin(0.5));   // ?
assert (facos(0.5) != facos(0.5));   // ?


Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn

Using equality is not a good idea with floating point.

The compiler will on a whim, or depending on whether it can 
inline or not, use higher precision floats, changing the 
outcome slightly.


I cannot say for certain whether this explains all the issues 
you have, the very last one seems troubling to me at least.


-Steve


Sure, in many cases it's a bad idea. While I understand that 
sin(PI) != 0.0, but approxEqual(sin(PI), 0.0) == true, I would 
expect the following to pass:


assert (0.0 == 0.0);
assert (1.2345 == 1.2345);

F a = 1.2345, b = 9.8765;

assert (a+b == b+a);
assert (a*b == b*a);

F fun (F a) pure;

assert (fun(a) + fun(b) == fun(b) + fun(a));
assert (fun(a) * fun(b) == fun(b) * fun(a));

auto a = fun(100);
auto b = fun(100);

assert (a == b);
assert (fun(100) == fun(100));


Now, if fun's body is { return sin(a); }, the behaviour changes 
to:


auto c = fun(100);
auto d = fun(100);

assert (c == d);  // Ok
assert (fun(100) != fun(100)) // I have a hard time understanding
  // this is correct behaviour


Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn
On Thursday, 23 October 2014 at 18:26:53 UTC, Steven 
Schveighoffer wrote:

On 10/23/14 2:18 PM, deed wrote:

Using equality is not a good idea with floating point.

The compiler will on a whim, or depending on whether it can 
inline or
not, use higher precision floats, changing the outcome 
slightly.


I cannot say for certain whether this explains all the issues 
you

have, the very last one seems troubling to me at least.



Sure, in many cases it's a bad idea. While I understand that 
sin(PI) !=
0.0, but approxEqual(sin(PI), 0.0) == true, I would expect the 
following

to pass:

assert (0.0 == 0.0);
assert (1.2345 == 1.2345);
F a = 1.2345, b = 9.8765;

assert (a+b == b+a);
assert (a*b == b*a);


None of these fail on my system


Same for me, that's the point; it's perfectly valid to compare 
floating points.





F fun (F a) pure;

assert (fun(a) + fun(b) == fun(b) + fun(a));
assert (fun(a) * fun(b) == fun(b) * fun(a));

auto a = fun(100);
auto b = fun(100);

assert (a == b);
assert (fun(100) == fun(100));



Not sure what body of fun is, so I cannot test this.


Could be anything taking a floating point and returning a 
floating point.
You would expect to get the same back for the same input, 
especially when

it's pure. If so, the asserts above are expected to hold.


Now, if fun's body is { return sin(a); }, the behaviour 
changes to:


auto c = fun(100);
auto d = fun(100);

assert (c == d);  // Ok
assert (fun(100) != fun(100)) // I have a hard time 
understanding

  // this is correct behaviour


Tried that out, it does not fail on my machine. Can you be more 
specific on your testing? What compiler/platform? Stock 
compiler, or did you build it yourself?


Right. It doesn't fail, and that's the problem.

assert (fun(100) == fun(100));  // Should pass, and does with
// body { return a + 1; }
// but not with
// body { return sin(a); }
assert (fun(100) != fun(100));  // Shouldn't pass, but passes with
// body { return sin(a);}

Compiler: DMD32 D Compiler v2.066.0

Also tried dpaste.dzfl.pl with 2.065.0 and DMD 2.x Git 
(cfb5842b49),
which had slightly different behaviour; more of the sin tests 
which should
pass in my opinion did with those two. Hence, it appears to be 
regressions.




-Steve




Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn
A similar problem was recently (about 2-3 weeks ago IIRC) seen 
in one of
the Phobos PR's. It appears to be related to the autoextension 
of float
to double (or double to real, I forget which) in certain 
contexts on
Windows.  @deed Could you please try to reduce the failing test 
to a

minimal code example, and post a disassembly of the concerned
function(s)? This could either be a subtle codegen bug, or 
something

more fundamentally broken with 80-bit real support.


T


Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
for both Windows and Linux. This just illustrates the sin 
function.


Re: Bug?

2014-10-23 Thread deed via Digitalmars-d-learn

Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
for both Windows and Linux. This just illustrates the sin 
function.


Replacing double with real makes everything pass on Linux Mint 16 
with -m32 and -m64. Replacing double with float seems to give the 
same problems as before, but hasn't been extensively tested. It 
seems very likely to be a conversion issue, as H. S. Teoh 
mentioned.


Error: array operation d1[] + d2[] without assignment not implemented

2014-09-13 Thread deed via Digitalmars-d-learn

struct Vector (T)
{
  T[]arr;
  void opSliceAssign (T[] a) { arr[] = a[]; }
}
unittest
{
  auto v = Vector!double([1, 2]);
  double[] d1 = [11, 12];
  double[] d2 = [21, 22];
  double[] d3 = new double[](2);
  d3[] = d1[] + d2[];
  assert (d3 == [11.+21., 12.+22.]);
  assert (is(typeof(d1[] + d2[]) == double[]));
  v[] = d1[]  // Fine
  v[] = d1[] + d2[];  // Error: array operation d1[] + d2[] 
without assignment not implemented

}

How can opSliceAssign be defined to make this work?


Re: Error: array operation d1[] + d2[] without assignment not implemented

2014-09-13 Thread deed via Digitalmars-d-learn

Hi!

struct Vector (T)
{
T[]arr;
T[] opSlice() { return arr; }
}
Vector!double v;
double[] d;
v[][] = d[] + d[];

//first [] call opSlise, second [] for array syntax

Best Regards,
Ilya


Thanks for your suggestion. It's not as attractive though, it 
would be the same as v.arr[] = ..., exposing the naked array. The 
syntax also becomes a bit confusing.


With alias this it works, but functionality is lost. See
http://dpaste.dzfl.pl/35081c1f1745

It feels not consistent, so I guess that's the reason for the 
not implemented message.