Re: in / out for C++ programmers

2012-03-23 Thread Jonathan M Davis
On Friday, March 23, 2012 23:37:27 Ali Çehreli wrote:
> 'in' is the same as 'const scope'. const part is easy to understand but
> I don't know what 'scope' does. I could not understand what the spec
> means with "references in the parameter cannot be escaped (e.g. assigned
> to a global variable)" for scope:
> 
>http://dlang.org/function.html

You mean that you don't understand what it means for a reference to escape a 
function? One example of this with pointers would be

int* func()
{
int a;
return &a;
}

A pointer to a local variable has escaped the function. That pointer is 
invalid. A case this simple gets caught by the compiler, but it's very easy 
to get around that (e.g. passing &a to a function which returns it and then 
return the result of that function rather than &a directly).

In the case of scope, it means that what you pass in cannot be assigned to a 
global or static variable, and it cannot be returned from that function. So, 
for instance.

int[] foo(const int[] a)
{
...
}

could not assign a to a global or static variable and cannot return it. This 
can allow some additional optimizations as well as improve safety in some 
cases. For instance, if you pass

int[5] b;

to foo, then you know that no slice of that static array will escape, since 
something like

int[] bar()
{
int[5] c;
return c;
}

is just as bad as the case with &a. I believe that scope is used primarily 
with delegates however (particularly, since you often _want_ to be able to 
return a slice of an array passed to a function). It guarantees that the the 
delegate's context won't escape the function and can make it so that the 
delegate's context doesn't have to be allocated on the heap, which improves 
efficiency.

scope is pointless with types which aren't pointers or references though.

- Jonathan M Davis


Re: in / out for C++ programmers

2012-03-23 Thread Ali Çehreli

On 03/23/2012 11:28 PM, Dan wrote:
> When would you use in / out parameters instead of ref & const keywords?

I am just about finished translating a chapter exactly on that topic. 
I've just realized that I have some questions myself. :)


'out' is the equivalent of a reference in C++, with additionally 
initializing the out parameter upon entry to the function.


void foo(out int i)
{
assert(i == 0);  // regardless of what it was before the call
}

'in' is the same as 'const scope'. const part is easy to understand but 
I don't know what 'scope' does. I could not understand what the spec 
means with "references in the parameter cannot be escaped (e.g. assigned 
to a global variable)" for scope:


  http://dlang.org/function.html

'ref' is the same as a C++ reference.

Ali



Re: in / out for C++ programmers

2012-03-23 Thread Jonathan M Davis
On Saturday, March 24, 2012 07:28:08 Dan wrote:
> When would you use in / out parameters instead of ref & const
> keywords?

out sets the variable to its init value, so you don't run into issues with 
the behavior of the function changing based on the value of the variable 
that you passed in. out is intended for variables that are for returning an 
extra value from the function, not passing one in. You use ref if you want 
to actually use the value that you pass in.

in is the same as const scope and has nothing to do with ref at all.

- Jonathan M Davis


in / out for C++ programmers

2012-03-23 Thread Dan
When would you use in / out parameters instead of ref & const 
keywords?


Thanks.


Re: Map with maintained insertion order

2012-03-23 Thread Brad Anderson
On Saturday, 24 March 2012 at 01:07:56 UTC, Jonathan M Davis 
wrote:

On Friday, March 23, 2012 23:48:51 Andrej Mitrovic wrote:
Does someone have a map implementation that maintains the 
insertion

order of the keys?

E.g.:

string[string] map;
map["foo"] = "x";
map["bar"] = "y";

When iterating over map keys I want to visit "foo" first, then 
"bar", and

so on.


I can't think of any data structure that does that off the top 
of my head,
though there may very well be one. If you don't mind the extra 
memory
overhead, it wouldn't be all that hard to do it with multiple 
maps wrapped

in a single type. You could do something like

class InsertedOrderMap
{
string[string] _map;
RedBlackTree!(Tuple!(int, string), "a[0] < b[0]") 
_insertionOrder;


...
}

_map holds the normal map and _insertionOrder holds pairs of 
the insertion

ordered and the key to _map.

You can then have your range iterate over _insertionOrder and 
use the keys
to return either the keys, values, or pairs of keys and values 
from _map,

depending on what you want to iterate over.

That _does_ require having two data structures in one, and 
there may a be a
better way to do it, but just off the top of my head, that's 
the best that I
can come up with. I don't know how you could have a data 
structure where
it's efficient to index by both insertion order and key without 
effectively
having two data structures. But I really should go reread my 
data structures

books. It's been too long since I studied that stuff.

- Jonathan M Davis


Ruby's Hash in 1.9 maintains insertion order.  It does it using a 
linked list between the nodes as they are created (so yes, 
essentially two data structures).


Regards,
Brad Anderson


Re: Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
On 3/24/12, Andrej Mitrovic  wrote:
> Correction, it's:
> template isValue(T)
> {
> enum bool isValue = is(typeof( { Value v; T t; v = t; } ))
> || is(typeof( { BaseElement!Value v; T t; v = t; } ))
> || is(BaseElement!Value == T);
> }

Last check not needed, so:
> template isValue(T)
> {
> enum bool isValue = is(typeof( { Value v; T t; v = t; } ))
> || is(typeof( { BaseElement!Value v; T t; v = t; } ));
> }

Anyway I'll stop spamming.


Re: Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
On 3/24/12, Andrej Mitrovic  wrote:
> static if (isArray!Value)
> {
> template isValue(T)
> {
>enum bool isValue = is(typeof( { Value v; T t; v = t; } )) ||
> is(BaseElement!Value == T);
> }
> }

Correction, it's:
template isValue(T)
{
enum bool isValue = is(typeof( { Value v; T t; v = t; } ))
|| is(typeof( { BaseElement!Value v; T t; v = t; } ))
|| is(BaseElement!Value == T);
}

Complicated beast, but I have to take into acount both 'alias this'
tricks and the fact that ~= works when RHS is either an element type
or an array.


Re: Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
On 3/24/12, Andrej Mitrovic  wrote:
> On 3/23/12, Andrej Mitrovic  wrote:
>> Does someone have a map implementation that maintains the insertion
>> order of the keys?
>
> Here's a sloppy implementation:

I forgot to make opIndex ref, but also the isValue check fails on
structs with alias this, it's better to use is(typeof()) instead of
directly checking the type. The fix would be:

static if (isArray!Value)
{
template isValue(T)
{
   enum bool isValue = is(typeof( { Value v; T t; v = t; } )) ||
is(BaseElement!Value == T);
}
}
else
{
template isValue(T) { enum bool isValue = is(typeof( { Value v; T
t; v = t; } )); }
}


Re: Map with maintained insertion order

2012-03-23 Thread H. S. Teoh
On Fri, Mar 23, 2012 at 06:33:54PM -0700, H. S. Teoh wrote:
> On Fri, Mar 23, 2012 at 06:07:42PM -0700, Jonathan M Davis wrote:
> > On Friday, March 23, 2012 23:48:51 Andrej Mitrovic wrote:
> > > Does someone have a map implementation that maintains the insertion
> > > order of the keys?
> > > 
> > > E.g.:
> > > 
> > > string[string] map;
> > > map["foo"] = "x";
> > > map["bar"] = "y";
> > > 
> > > When iterating over map keys I want to visit "foo" first, then
> > > "bar", and so on.
> > 
> > I can't think of any data structure that does that off the top of my
> > head, though there may very well be one.
> [...]
> 
> Yes there is one. It's called a B-tree. And it's probably total overkill
> for what you need. :-) But also, B-trees have O(log n) access time, not
> O(1). :-(
[...]

Actually, nevermind that. B-trees are probably not what you're looking
for at all, and they aren't really suited to the task anyway (you want
to sort by insertion order, not key order).

What you *could* do is implement a hash augmented with next/prev
pointers in each slot, IOW, a linked list. The hash itself stores a
pointer to the head and tail of the list. When a new slot is created,
the tail of the list is updated to link to it. When a slot is deleted,
its neighbours are updated. This will maintain O(1) performance of the
hash.

In fact, you could use the current AA implementation if you wrap your
data in a struct that contains the extra pointers, and wrap around the
AA operations to update these pointers as needed.


T

-- 
Valentine's Day: an occasion for florists to reach into the wallets of nominal 
lovers in dire need of being reminded to profess their hypothetical love for 
their long-forgotten.


Re: Map with maintained insertion order

2012-03-23 Thread H. S. Teoh
On Fri, Mar 23, 2012 at 06:07:42PM -0700, Jonathan M Davis wrote:
> On Friday, March 23, 2012 23:48:51 Andrej Mitrovic wrote:
> > Does someone have a map implementation that maintains the insertion
> > order of the keys?
> > 
> > E.g.:
> > 
> > string[string] map;
> > map["foo"] = "x";
> > map["bar"] = "y";
> > 
> > When iterating over map keys I want to visit "foo" first, then
> > "bar", and so on.
> 
> I can't think of any data structure that does that off the top of my
> head, though there may very well be one.
[...]

Yes there is one. It's called a B-tree. And it's probably total overkill
for what you need. :-) But also, B-trees have O(log n) access time, not
O(1). :-(


T

-- 
Right now I'm having amnesia and deja vu at the same time. I think I've 
forgotten this before.


Re: Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
On 3/24/12, Jonathan M Davis  wrote:
> I can't think of any data structure that does that off the top of my head

Java has it and they call it a LinkedHashMap:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedHashMap.html

> That _does_ require having two data structures in one, and there may a be a
> better way to do it, but just off the top of my head, that's the best that I
> can come up with. I don't know how you could have a data structure where
> it's efficient to index by both insertion order and key without effectively
> having two data structures.

Yeah it's not efficient, but in my use-case I'm not looking so much
for efficiency but convenience. Sometimes I have to look up a key
based on a name to modify some values, and I have to keep the order of
the keys.


Re: Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
On 3/23/12, Andrej Mitrovic  wrote:
> Does someone have a map implementation that maintains the insertion
> order of the keys?

Here's a sloppy implementation:

module test;

import std.stdio;
import std.traits;

template KeyType(V : V[K], K)
if (isAssociativeArray!(V[K]))
{
alias K KeyType;
}

template ValueType(V : V[K], K)
if (isAssociativeArray!(V[K]))
{
alias V ValueType;
}

template BaseElement(T : U[], U)
{
alias U BaseElement;
}

struct LinkedHash(T)
if (isAssociativeArray!T)
{
alias KeyType!T Key;
alias ValueType!T Value;

static if (isArray!Value)
template isValue(T) { enum bool isValue = (is(T == Value) ||
is(BaseElement!Value == T)); }
else
template isValue(T) { enum bool isValue = is(T == Value); }

Value[] payload;
size_t[Key] keyToIndex;
Key[size_t] indexToKey;
size_t lastIndex;

size_t getNewIndex()
{
payload.length = payload.length + 1;
return lastIndex++;
}

size_t* getKeyIndex(string key)
{
if (auto index = key in keyToIndex)
return index;
else
return null;
}

Value opIndex(in Key key)
{
if (auto index = getKeyIndex(key))
return payload[*index];
else
assert(0, "Key '" ~ key ~ "' not found.");
}

void opIndexAssign(V)(V value, Key key)
if (isValue!V)
{
if (auto index = getKeyIndex(key))
payload[*index] = value;
else
{
auto index = getNewIndex();
payload[index] = value;
keyToIndex[key] = index;
indexToKey[index] = key;
}
}

void opIndexOpAssign(string op, V)(V value, Key key)
if (isValue!V)
{
if (auto index = getKeyIndex(key))
mixin("payload[*index] " ~ op ~ "= value;");
else
{
auto index = getNewIndex();
mixin("payload[index] " ~ op ~ "= value;");
keyToIndex[key] = index;
indexToKey[index] = key;
}
}

int opApply(scope int delegate(ref Key, ref Value) dg)
{
foreach (index; 0 .. lastIndex)
{
auto result = dg(indexToKey[index], payload[index]);
if (result)
return result;
}

return 0;
}
}

void main()
{
auto names = ["1", "2", "3", "4", "5", "6", "7", "8"];

LinkedHash!(string[string]) stringMap;
foreach (name; names)
stringMap[name] ~= "test";

foreach (key, val; stringMap)
writefln("%s: %s", key, val);

LinkedHash!(string[][string]) stringArrMap;
stringArrMap["100"] = ["foo"];
stringArrMap["101"] ~= "bar";

foreach (name; names)
stringArrMap[name] ~= "test";

foreach (key, val; stringArrMap)
writefln("%s: %s", key, val);
}


Re: Map with maintained insertion order

2012-03-23 Thread Jonathan M Davis
On Friday, March 23, 2012 23:48:51 Andrej Mitrovic wrote:
> Does someone have a map implementation that maintains the insertion
> order of the keys?
> 
> E.g.:
> 
> string[string] map;
> map["foo"] = "x";
> map["bar"] = "y";
> 
> When iterating over map keys I want to visit "foo" first, then "bar", and
> so on.

I can't think of any data structure that does that off the top of my head, 
though there may very well be one. If you don't mind the extra memory 
overhead, it wouldn't be all that hard to do it with multiple maps wrapped 
in a single type. You could do something like

class InsertedOrderMap
{
string[string] _map;
RedBlackTree!(Tuple!(int, string), "a[0] < b[0]") _insertionOrder;

...
}

_map holds the normal map and _insertionOrder holds pairs of the insertion 
ordered and the key to _map.

You can then have your range iterate over _insertionOrder and use the keys 
to return either the keys, values, or pairs of keys and values from _map, 
depending on what you want to iterate over.

That _does_ require having two data structures in one, and there may a be a 
better way to do it, but just off the top of my head, that's the best that I 
can come up with. I don't know how you could have a data structure where 
it's efficient to index by both insertion order and key without effectively 
having two data structures. But I really should go reread my data structures 
books. It's been too long since I studied that stuff.

- Jonathan M Davis


Re: Freeing memory allocated at C function

2012-03-23 Thread Pedro Lacerda
On Fri, Mar 23, 2012 at 3:43 AM, Ali Çehreli  wrote:

> You can register on GC if you wrap the resources in a class. Then the
> class object's destructor would call the clean up code. The problem is, it
> is undeterministic when the destructor will be called, or will it be called
> at all!
>
> Or you can wrap in a struct which has deterministic destruction like in
> C++, when leaving scopes.
>


The object is long lived, so the class wrapper is the way to go.
Thanks


Re: Confused by refusal to expand template

2012-03-23 Thread Timon Gehr

On 03/23/2012 11:58 PM, David wrote:

Am 23.03.2012 23:52, schrieb H. S. Teoh:

Code:
struct S {
int f(K)(K x) {
return 1;
}
void func(K)(inout(K) x) {
auto h = f(x);
}
}
void main() {
S s;
s.func("abc"); // This is line 44
}

This refuses to compile:

test2.d(44): Error: template test2.S.func(K) does not match any
function template declaration
test2.d(44): Error: template test2.S.func(K) cannot deduce template
function from argument types !()(string)

Removing 'inout' fixes the problem. But I don't understand why.


T


I've never really used inout, but don't you need it also for the
return-type?


Not any more (DMD 2.059). See 
http://d.puremagic.com/issues/show_bug.cgi?id=7105



Furthermore you don't the the inout here, since this
template does match const/immutable/nothing anyways.


His intention probably is to prevent multiple instantiation of a 
template based on different constness.


Re: Confused by refusal to expand template

2012-03-23 Thread David

Am 23.03.2012 23:52, schrieb H. S. Teoh:

Code:
struct S {
int f(K)(K x) {
return 1;
}
void func(K)(inout(K) x) {
auto h = f(x);
}
}
void main() {
S s;
s.func("abc");// This is line 44
}

This refuses to compile:

test2.d(44): Error: template test2.S.func(K) does not match any function 
template declaration
test2.d(44): Error: template test2.S.func(K) cannot deduce template function 
from argument types !()(string)

Removing 'inout' fixes the problem. But I don't understand why.


T

I've never really used inout, but don't you need it also for the 
return-type? Furthermore you don't the the inout here, since this 
template does match const/immutable/nothing anyways.


Re: Confused by refusal to expand template

2012-03-23 Thread Timon Gehr

On 03/23/2012 11:52 PM, H. S. Teoh wrote:

Code:
struct S {
int f(K)(K x) {
return 1;
}
void func(K)(inout(K) x) {
auto h = f(x);
}
}
void main() {
S s;
s.func("abc");// This is line 44
}

This refuses to compile:

test2.d(44): Error: template test2.S.func(K) does not match any function 
template declaration
test2.d(44): Error: template test2.S.func(K) cannot deduce template function 
from argument types !()(string)

Removing 'inout' fixes the problem. But I don't understand why.


T



You already brought this up IIRC. The IFTI matching algorithm is too 
weak. I think it should work.


Confused by refusal to expand template

2012-03-23 Thread H. S. Teoh
Code:
struct S {
int f(K)(K x) {
return 1;
}
void func(K)(inout(K) x) {
auto h = f(x);
}
}
void main() {
S s;
s.func("abc");  // This is line 44
}

This refuses to compile:

test2.d(44): Error: template test2.S.func(K) does not match any function 
template declaration
test2.d(44): Error: template test2.S.func(K) cannot deduce template function 
from argument types !()(string)

Removing 'inout' fixes the problem. But I don't understand why.


T

-- 
Perhaps the most widespread illusion is that if we were in power we would 
behave very differently from those who now hold it---when, in truth, in order 
to get power we would have to become very much like them. -- Unknown


Map with maintained insertion order

2012-03-23 Thread Andrej Mitrovic
Does someone have a map implementation that maintains the insertion
order of the keys?

E.g.:

string[string] map;
map["foo"] = "x";
map["bar"] = "y";

When iterating over map keys I want to visit "foo" first, then "bar", and so on.


Re: Template constraint and specializations

2012-03-23 Thread Andrej Mitrovic
On 3/23/12, Philippe Sigaud  wrote:
> It works for me

Yes but check the isA template. It seems there's something causing a
nested variadic template to fail. This won't work in a template
constraint (it returns false):

template isA(alias Foo)
{
   template isA(T)
   {
   enum bool isA = __traits(compiles,
   {
   void tester(Args...)(Foo!(Args) args);
   tester(T.init);
   });
   }
}
alias isA!Foo isFoo;

But if you change "Args..." to "Args" then it works, although only for
single-type templates.. I'm not sure what's going on..


Re: Template constraint and specializations

2012-03-23 Thread Philippe Sigaud
On Fri, Mar 23, 2012 at 21:27, Andrej Mitrovic
 wrote:

> That can't work. For a Foo!int your code will expand like so:

> See for yourself:

? It works for me:


template isBar(T)
{
enum isBar = __traits(compiles,
{
void tester(Args...)(Bar!Args arg) {}
tester(T.init);
});
}


template isFoo(T)
{
enum isFoo = __traits(compiles,
{
void tester(Arg)(Foo!Arg arg) {}
tester(T.init);
});
}


struct Foo(T)
{
}

struct Bar(T...)
{}

void useFoo(T)(T t) if (isFoo!T)
{
}

void useBar(T)(T t) if (isBar!T)
{
}

void main()
{
Foo!int foo;
useFoo(foo);
Bar!(int, string, double) bar;
useBar(bar);
}


Re: string[] to char**

2012-03-23 Thread Andrej Mitrovic
On 3/23/12, bearophile  wrote:
> This is one way to do it:
>  immutable(char)** p = array(map!toStringz(data)).ptr;

This is asked so frequently that I think we could consider adding it to Phobos.


Re: Template constraint and specializations

2012-03-23 Thread Andrej Mitrovic
On 3/23/12, Philippe Sigaud  wrote:
> testFoo is a function that accepts any Foo!( ... ) for any ... The
> second line tests it on a value of type T (T.init).

That can't work. For a Foo!int your code will expand like so:

// original code
void tester(Args...)(Foo!Args args);
tester(T.init);

void tester(Args...)(Foo!Args args);
tester((Foo!int).init);  // T is a template instance

void tester(Foo!int)(Foo!(Foo!int) args);  // Args.. becomes the
template instance type
tester((Foo!int).init);

See for yourself:

template isA(alias Foo)
{
template isA(T)
{
//~ pragma(msg, T.init);
enum bool isA = __traits(compiles,
{
void tester(Args...)(Foo!Args args);
tester(T.init);
});
}
}

struct Foo(T)
{
}

alias isA!Foo isFoo;

void useFoo(T)(T t)
if (isFoo!T)  // no-go
{
}

void main()
{
Foo!int foo;
useFoo(foo);
}


Re: string[] to char**

2012-03-23 Thread Ali Çehreli

On 03/23/2012 11:23 AM, Ali Çehreli wrote:

On 03/23/2012 08:48 AM, simendsjo wrote:
 > What's the best way to convert char** from string[]?

In C, char** communicates transfer of ownership.


Ok, I once again misunderstood the question. :( My question in the 
comment remains.


Thank you,
Ali



Re: string[] to char**

2012-03-23 Thread Ali Çehreli

On 03/23/2012 08:48 AM, simendsjo wrote:
> What's the best way to convert char** from string[]?

In C, char** communicates transfer of ownership. Is that what you are 
trying to do? Are you going to pass a slice to a C function to be filled 
in by that C function?


Such functions usually assign to *str. In that case you can use the 
"make slice from raw pointer" method below. I hope others will answer my 
concern in the comment below:


import std.stdio;
import std.c.stdlib;
import std.c.string;

void C_func_with_an_out_parameter(char ** str)
{
*str = cast(char*)calloc(1, 10);
(*str)[0] = 'A';
(*str)[1] = '\0';
}

void main()
{
char * p;
C_func_with_an_out_parameter(&p);

char[] slice = p[0..strlen(p)]; // <-- make a D slice

/*
 * Note: I don't think that the memory that
 * std.stdlib.calloc() returns is managed by the GC. For
 * that reason, I don't think it will be safe to share the
 * element with another slice and expect normal behavior
 * of element-sharing between slices.
 *
 * In other words, this would be risky:
 *
 * char[] anotherSlice = slice;
 */
writeln(slice);

free(p);
}

Ali


Re: Template constraint and specializations

2012-03-23 Thread Philippe Sigaud
On Fri, Mar 23, 2012 at 10:17, Ed McCardell  wrote:

>>> Is there a way to write a template constraint that matches any
>>>
>>> specialization of a given type?
>>
>>
>> Nope. But there are simple workarounds:
>>
>> class Foo(bool feature1, bool feature2) { enum _isFoo = true; }
>>
>> template isFoo(T) {
>>     enum bool isFoo = __traits(hasMember, T, "_isFoo");
>> }

Another solution that does not require you to add an _isFoo member:
use template function instantiation:

template isFoo(T)
{
enum bool isFoo = __traits(compiles, {

void testFoo(Args...)(Foo!Args arg);

testFoo(T.init);
});
}

testFoo is a function that accepts any Foo!( ... ) for any ... The
second line tests it on a value of type T (T.init).

This can be generalized even further, to create any template-testing function:

template isA(alias Foo)
{
template isA(T)
{
enum bool isA = __traits(compiles, { void
tester(Args...)(Foo!Args args); tester(T.init);});
}
}


usage:

alias isA!Foo isFoo;

template useFoo(T) if (isFoo!T)
{

}


Re: string[] to char**

2012-03-23 Thread bearophile

On Friday, 23 March 2012 at 15:48:12 UTC, simendsjo wrote:

What's the best way to convert char** from string[]?


This is one way to do it:


import std.algorithm, std.array, std.string, core.stdc.stdio;
void main() {
auto data = ["red", "yellow", "green"];
immutable(char)** p = array(map!toStringz(data)).ptr;
printf("%s %s %s\n", p[0], p[1], p[2]);
}


Note: the pointer array is managed by the D GC.

With DMD 2.059:

immutable(char)** p = data.map!toStringz().array().ptr;

Bye,
bearophile


string[] to char**

2012-03-23 Thread simendsjo

What's the best way to convert char** from string[]?


Re: Calling c shared library

2012-03-23 Thread simendsjo

On Fri, 23 Mar 2012 15:04:48 +0100, simendsjo  wrote:


Forgive my programming 101 question :)

I want to call a method from a precompiled shared library:
// c header
void f(void);

// my d file
extern(C) void f();
void main() {}

$ dmd mydfile.d
libphobos2.a(deh2_33a_525.o): In function  
`_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):  
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):  
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):  
undefined reference to `_deh_end'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):  
undefined reference to `_deh_end'

collect2: ld returned 1 exit status
--- errorlevel 1

Is there a way to do the above, or do I have to manually load the shared  
library and use alias'es for the functions?


Stupidity has a new name, and it's simendsjo!

I actually had extern(C): at the top of my file, but extern(C) void main()  
was nowhere to be found :)


Re: Vector operations optimization.

2012-03-23 Thread Comrad

On Friday, 23 March 2012 at 11:20:59 UTC, Trass3r wrote:

The flags you want are -O, -inline -release.

If you don't have those, then that might explain some of the 
slow down

on slicing, since -release drops a ton of runtime checks.


-noboundscheck option can also speed up things.


dmd is anyway very slow, ldc2 was better, but still not fast 
enough.


Re: Vector operations optimization.

2012-03-23 Thread Comrad

On Friday, 23 March 2012 at 10:48:55 UTC, Dmitry Olshansky wrote:

On 23.03.2012 9:57, Comrad wrote:

On Thursday, 22 March 2012 at 10:43:35 UTC, Trass3r wrote:
What is the status at the moment? What compiler and with 
which

compiler flags I should use to achieve maximum performance?


In general gdc or ldc. Not sure how good vectorization is 
though, esp.

auto-vectorization.
On the other hand the so called vector operations like a[] = 
b[] +

c[]; are lowered to hand-written SSE assembly even in dmd.


I had such a snippet to test:

1 import std.stdio;
2 void main()
3 {
4 double[2] a=[1.,0.];
5 double[2] a1=[1.,0.];
6 double[2] a2=[1.,0.];
7 double[2] a3=[0.,0.];


Here is a culprit, the array ops [] are tuned for arbitrary 
long(!) arrays, they are not plain 1 simd SEE op. They are 
handcrafted loops(!) on SSE ops, cool and fast for arrays in 
general, not fixed pairs/trios/etc. I believe it might change 
in future, if compiler is able to deduce that size is fixed, 
and use more optimal code for small sizes.




So currently there is no such an optimization exists for any d
compiler?



Calling c shared library

2012-03-23 Thread simendsjo

Forgive my programming 101 question :)

I want to call a method from a precompiled shared library:
// c header
void f(void);

// my d file
extern(C) void f();
void main() {}

$ dmd mydfile.d
libphobos2.a(deh2_33a_525.o): In function  
`_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x4):  
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xc):  
undefined reference to `_deh_beg'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x13):  
undefined reference to `_deh_end'
src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x37):  
undefined reference to `_deh_end'

collect2: ld returned 1 exit status
--- errorlevel 1

Is there a way to do the above, or do I have to manually load the shared  
library and use alias'es for the functions?


Re: Template constraint and specializations

2012-03-23 Thread bearophile

Andrej Mitrovic:


Nope. But there are simple workarounds:


Why isn't something similar to this working?

import std.traits: Unqual;

class Foo(bool feature1, bool feature2) {}

template isFoo(T) {
static if (is(Unqual!T Unused : Foo!Features, Features...)) {
enum isFoo = true;
} else {
enum isFoo = false;
}
}

void main() {
auto f1 = new Foo!(true, false)();
static assert(isFoo!(typeof(f1)));
}


Bye,
bearophile


Re: Vector operations optimization.

2012-03-23 Thread Trass3r

The flags you want are -O, -inline -release.

If you don't have those, then that might explain some of the slow down
on slicing, since -release drops a ton of runtime checks.


-noboundscheck option can also speed up things.


Re: Vector operations optimization.

2012-03-23 Thread Dmitry Olshansky

On 23.03.2012 9:57, Comrad wrote:

On Thursday, 22 March 2012 at 10:43:35 UTC, Trass3r wrote:

What is the status at the moment? What compiler and with which
compiler flags I should use to achieve maximum performance?


In general gdc or ldc. Not sure how good vectorization is though, esp.
auto-vectorization.
On the other hand the so called vector operations like a[] = b[] +
c[]; are lowered to hand-written SSE assembly even in dmd.


I had such a snippet to test:

1 import std.stdio;
2 void main()
3 {
4 double[2] a=[1.,0.];
5 double[2] a1=[1.,0.];
6 double[2] a2=[1.,0.];
7 double[2] a3=[0.,0.];


Here is a culprit, the array ops [] are tuned for arbitrary long(!) 
arrays, they are not plain 1 simd SEE op. They are handcrafted loops(!) 
on SSE ops, cool and fast for arrays in general, not fixed 
pairs/trios/etc. I believe it might change in future, if compiler is 
able to deduce that size is fixed, and use more optimal code for small 
sizes.



8 foreach(i;0..10)
9 a3[]+=a[]+a1[]*a2[];
10 writeln(a3);
11 }

And I compared with the following d code:

1 import std.stdio;
2 void main()
3 {
4 double[2] a=[1.,0.];
5 double[2] a1=[1.,0.];
6 double[2] a2=[1.,0.];
7 double[2] a3=[0.,0.];
8 foreach(i;0..10)
9 {
10 a3[0]+=a[0]+a1[0]*a2[0];
11 a3[1]+=a[1]+a1[1]*a2[1];
12 }
13 writeln(a3);
14 }

And with the following c code:

1 #include 
2 int main()
3 {
4 double a[2]={1.,0.};
5 double a1[2]={1.,0.};
6 double a2[2]={1.,0.};
7 double a3[2];
8 unsigned i;
9 for(i=0;i<10;++i)
10 {
11 a3[0]+=a[0]+a1[0]*a2[0];
12 a3[1]+=a[1]+a1[1]*a2[1];
13 }
14 printf("%f %f\n",a3[0],a3[1]);
15 return 0;
16 }

The last one I compiled with gcc two previous with dmd and ldc. C code
with -O2
was the fastest and as fast as d without slicing compiled with ldc. d
code with slicing was 3 times slower (ldc compiler). I tried to compile
with different optimization flags, that didn't help. Maybe I used the
wrong ones. Can someone comment on this?



--
Dmitry Olshansky


Re: Template constraint and specializations

2012-03-23 Thread Ed McCardell

On 03/23/2012 04:14 AM, Andrej Mitrovic wrote:

On 3/23/12, Ed McCardell  wrote:

Is there a way to write a template constraint that matches any
specialization of a given type?


Nope. But there are simple workarounds:

class Foo(bool feature1, bool feature2) { enum _isFoo = true; }

template isFoo(T) {
 enum bool isFoo = __traits(hasMember, T, "_isFoo");
}


Thanks! I was tempted to try something hacky for the constraint, like

  if (T.stringof == "Foo")

but tagging the type with an enum works better all around.

--Ed


Re: Template constraint and specializations

2012-03-23 Thread Andrej Mitrovic
On 3/23/12, Ed McCardell  wrote:
> Is there a way to write a template constraint that matches any
> specialization of a given type?

Nope. But there are simple workarounds:

class Foo(bool feature1, bool feature2) { enum _isFoo = true; }

template isFoo(T) {
enum bool isFoo = __traits(hasMember, T, "_isFoo");
}

void useFoo(T)(T foo)
   if (isFoo!T)
{
   // call methods of foo that don't change based on feature1/feature2
}

void main()
{
Foo!(true, false) foo;
useFoo(foo);
}


Template constraint and specializations

2012-03-23 Thread Ed McCardell
Is there a way to write a template constraint that matches any 
specialization of a given type?


For example can the following be done without having to write out every 
combination of feature1 and feature2:


  class Foo(bool feature1, bool feature2) { ... }

  void useFoo(T)(T foo)
  if (is(T == Foo!(false, false)) || is(T == Foo!(false, true)) ||
  is(T == Foo!(true, false)) || is(T == Foo!(true, true)))
  {
 // call methods of foo that don't change based on feature1/feature2
  }

Thanks,

--Ed