From 475e45af3263b99671e653221f379c48bbc92a16 Mon Sep 17 00:00:00 2001 From: cbleser Date: Sat, 2 Mar 2013 16:48:18 +0100 Subject: [PATCH 01/18] ConstOf HolderOf MutableOf added to Traits.d --- tango/core/Traits.d | 296 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 295 insertions(+), 1 deletion(-) diff --git a/tango/core/Traits.d b/tango/core/Traits.d index 11d9edb61..c7c5711e4 100644 --- a/tango/core/Traits.d +++ b/tango/core/Traits.d @@ -288,7 +288,7 @@ template isReferenceType( T ) /** - * Evaulates to true if T is a dynamic array type. + * Evaluates to true if T is a dynamic array type. */ template isDynamicArrayType( T ) { @@ -517,6 +517,299 @@ debug( UnitTest ) static assert( staticArraySize!(char[2])==2); } +/** This template finds the const type of T if T implicitly can be converted into a const type and can be hold in variable HolderOf without making a explicit copy or dup. + This template can be used on an argument of template functions if the argument is kept constant. + The called argument can be const,immutable or variable. + Ex. + class TClass(T) { + HolderOf! T value; + void func(ConstOf!T x) { + value=x; + } + } + ... + The function "func" can be called with. + auto C=new Tclass!(char[]); + char[] str; + const(char[]) const_str="Const"; + immutable(char[]) immutable_str="Immutable"; + C.func(str); + C.func(const_str); + C.func(immutable_str); +*/ + +template ConstOf(T) { + static if (is(T U:const(U)[])) { + alias const(U)[] ConstOf; + } else static if (is(T U:const(U))) { + alias const(U) ConstOf; + } else { + alias T ConstOf; + } +} + +// template ConstOf(T) { +// static if (is(T : Object)) +// alias T ConstOf; +// else static if (is(T U==immutable(U)[] )) +// alias const(U)[] ConstOf; +// else static if (is(T U:U[])) +// alias ConstOf!(U)[] ConstOf; +// else static if (is(T U:const(U))) +// alias const(U) ConstOf; +// else static assert(0, "No constant type of "~T.stringof); +// } + +/** This template is used in conjunction with the ConstOf template. + HolderOf can hold the value of the ConstOf type with out making a explicit copy. + Ex. + ConstOf!T conts_var; + HolderOf!T holder_var=const_var; +*/ + +template HolderOf(T) { + pragma(msg, "------- "~T.stringof~" -------"); + static if (is(T U==immutable(U[]))) { + // pragma(msg, "inside is(T U==immutable(U)[]) U="~U.stringof~" MutableOf!U="~MutableOf!(U).stringof); + alias const(MutableOf!U)[] HolderOf; + } else static if(is(T U:U[])) { + // pragma(msg, "inside T="~T.stringof~" is(T U:U[])"~U.stringof); + static if (is(U S==const(S))) { + // pragma(msg, "inside is(U S==const(S)) U="~U.stringof~" S="~S.stringof); + alias U[] HolderOf; + } else static if (is(U S==immutable(S))) { + // pragma(msg, "inside is(U S==immutable(S)) U="~U.stringof~" S="~S.stringof) + ; + alias const(S)[] HolderOf; + } else + alias HolderOf!(U)[] HolderOf; + } else static if (is(T U==const(U))) { + // pragma(msg, "inside is(T U==const(U)) U="~U.stringof); + static if (isAtomicType!(MutableOf!T)) { + alias U HolderOf; + } else { + alias T HolderOf; + } + } else static if (is(T U==immutable(U))) { + static if (isAtomicType!(MutableOf!T)) { + alias U HolderOf; + } else { + alias const(U) HolderOf; + } + } else { + alias T HolderOf; + } +} + +/** Converts a type to a mutable type + */ +template MutableOf(T) { + static if(is(T U:const(U)[])) + alias MutableOf!(U)[] MutableOf; + else static if(is(T U:const(U))) + alias U MutableOf; + else + alias T MutableOf; +} + + +unittest { + import tango.io.Stdout; + class TemplateClass(T) { + HolderOf!T value; + + bool equal(ConstOf!T val) const { + return val==value; + } + + T set(T val) { + return (value=val); + } + + } + + struct TestStruct { + int x,y; + real z; + this(const int x, const int y, const real z) { + this.x=x;this.y=y;this.z=z; + } + } + + class TestClass { + int x,y; + real z; + this() { + z=1.0; + } + this(const int x, const int y, const real z) { + this.x=x;this.y=y;this.z=z; + } + } + + // Implicitly conversion + static assert(is(const(int) : int)); + static assert(is(immutable(int) : int)); + static assert(is(const(Object)==const Object)); + static assert(is(int[] :const(int)[])); + static assert(is(immutable(int)[] :const(int)[])); + static assert(is(const(int)[] :const(int)[])); + static assert(is(const(int[]) :const(int)[])); + static assert(is(immutable(int[]) :const(int)[])); + static assert(is(immutable(int[]) :immutable(int)[])); + static assert(is(immutable(int[]) : const(int)[])); + static assert(is(immutable(int[][]) : const(int[])[])); + static assert(is(immutable(int[][][]) : const(int[][])[])); + + // Atomics common + static assert(is(ConstOf!(int)==const(int))); + static assert(is(ConstOf!(immutable int)==const(int))); + static assert(is(ConstOf!(const(int))==const(int))); + // Object common + static assert(is(ConstOf!(Object)==const(Object))); + static assert(is(ConstOf!(immutable(Object))==const(Object))); + static assert(is(ConstOf!(const(Object))==const Object )); + // Atomics Array common + static assert(is(ConstOf!(int[]) == const(int)[]) ); + static assert(is(ConstOf!(const(int)[]) == const(int)[]) ); + static assert(is(ConstOf!(immutable(int)[]) == const(int)[]) ); + // Fixed Atomics Array common + static assert(is(ConstOf!(const(int[])) == const(int)[]) ); + static assert(is(ConstOf!(immutable(int[])) == const(int)[]) ); + // Object Array common + static assert(is(ConstOf!(Object[]) == const(Object)[]) ); + static assert(is(ConstOf!(const(Object)[]) == const(Object)[]) ); + static assert(is(ConstOf!(immutable(Object)[]) == const(Object)[]) ); + // Fixed Object Array common + static assert(is(ConstOf!(const(int[])) == const(int)[]) ); + static assert(is(ConstOf!(immutable(int[])) == const(int)[]) ); + // Jaggles common + static assert(is(ConstOf!(int[][]) == const(int[])[])); + static assert(is(ConstOf!(const(int[])[]) == const(int[])[])); + static assert(is(ConstOf!(const(int[][])) == const(int[])[])); + static assert(is(ConstOf!(immutable(int[])[]) == const(immutable(int)[])[])); + static assert(is(ConstOf!(immutable(int[][])) == const(immutable(int)[])[])); + + // Atomics Mutable + static assert(is(MutableOf!(int)==int)); + static assert(is(MutableOf!(const(int))==int)); + static assert(is(MutableOf!(immutable(int))==int)); + // Object Mutable + static assert(is(MutableOf!(Object)==Object)); + static assert(is(MutableOf!(const(Object))==Object)); + static assert(is(MutableOf!(immutable(Object))==Object)); + // Array Mutable + static assert(is(MutableOf!(int[])==int[])); + static assert(is(MutableOf!(const(int[]))==int[])); + static assert(is(MutableOf!(immutable(int[]))==int[])); + static assert(is(MutableOf!(const(int)[])==int[])); + static assert(is(MutableOf!(immutable(int)[])==int[])); + // Jaggle Mutable + static assert(is(MutableOf!(int[][])==int[][])); + static assert(is(MutableOf!(const(int[][]))==int[][])); + static assert(is(MutableOf!(immutable(int[][]))==int[][])); + static assert(is(MutableOf!(const(int[])[])==int[][])); + static assert(is(MutableOf!(immutable(int[])[])==int[][])); + static assert(is(MutableOf!(const(int[][][]))==int[][][])); + static assert(is(MutableOf!(immutable(int[][][]))==int[][][])); + + // Atomic Holder + static assert(is(HolderOf!(int)==int)); + static assert(is(HolderOf!(const(int))==int)); + static assert(is(HolderOf!(immutable(int))==int)); + static assert(is(int : HolderOf!(int))); + static assert(is(const(int) : HolderOf!(const(int)))); + static assert(is(immutable(int) : HolderOf!(immutable(int)))); + // Object Holder + static assert(is(HolderOf!(Object)==Object)); + static assert(is(HolderOf!(const(Object))==const(Object))); + static assert(is(HolderOf!(immutable(Object))==const(Object))); + static assert(is(Object : HolderOf!(Object))); + static assert(is(const(Object) : HolderOf!(const(Object)))); + static assert(is(immutable(Object) : HolderOf!(immutable(Object)))); + // Atomic Array Holder + static assert(is(HolderOf!(int[])==int[])); + static assert(is(HolderOf!(const(int)[])== const(int)[])); + static assert(is(HolderOf!(immutable(int)[])==const(int)[])); + static assert(is(int[] : HolderOf!(int[]))); + static assert(is(const(int)[] : HolderOf!(const(int)[]))); + static assert(is(immutable(int)[] : HolderOf!(immutable(int)[]))); + // Atomic Fixed Array holder + static assert(is(HolderOf!(const(int[]))== const(int)[])); + static assert(is(HolderOf!(immutable(int[]))==const(int)[])); + static assert(is(const(int[]) : HolderOf!(const(int[])))); + static assert(is(immutable(int[]) : HolderOf!(immutable(int[])))); + // Object Array holder + static assert(is(HolderOf!(Object[])==Object[])); + static assert(is(HolderOf!(const(Object)[])==const(Object)[])); + static assert(is(HolderOf!(immutable(Object)[])==const(Object)[])); + static assert(is(Object[] : HolderOf!(Object[]))); + static assert(is(const(Object)[] : HolderOf!(const(Object)[]))); + static assert(is(immutable(Object)[] : HolderOf!(immutable(Object)[]))); + // Object Fixed Array holder + static assert(is(HolderOf!(const(Object[]))== const(Object)[])); + static assert(is(HolderOf!(immutable(Object[]))==const(Object)[])); + static assert(is(const(Object[]) : HolderOf!(const(Object[])))); + static assert(is(immutable(Object[]) : HolderOf!(immutable(Object[])))); + // Jaggle Holder + static assert(is(HolderOf!(int[][]) == int[][])); + static assert(is(HolderOf!(const(int[])[]) == const(int[])[])); + static assert(is(HolderOf!(immutable(int[])[]) == const(int[])[])); + static assert(is(immutable(int[])[] : HolderOf!(immutable(int[])[]))); + static assert(is(HolderOf!(immutable(int[][])[]) == const(int[][])[])); + static assert(is(immutable(int[][])[] : HolderOf!(immutable(int[][])[]))); + static assert(is(HolderOf!(immutable(int[][][])) == const(int[][])[])); + static assert(is(immutable(int[][][]) : HolderOf!(immutable(int[][])[]))); + + + Stdout("Runtime test").nl; + // Runtime test + auto temp_int=new TemplateClass!(int); + auto temp_struct=new TemplateClass!(TestStruct); + auto temp_class=new TemplateClass!(TestClass); + auto temp_string=new TemplateClass!(char[]); + auto temp_class_array=new TemplateClass!(TestClass[]); + Stdout("After test").nl; + // Atomics + auto y1=temp_int.set(10); + assert(temp_int.equal(10)); + assert(temp_int.equal(y1)); + int x2=30; + auto y2=temp_int.set(x2); + assert(temp_int.equal(20)); + assert(temp_int.equal(x2)); + // Struct + auto x3=TestStruct(20,40,1.0); + auto y3=temp_struct.set(x3); + assert(temp_struct.equal(y3)); + assert(temp_struct.equal(const(TestStruct)(20,40,1.0))); + assert(temp_struct.equal(immutable(TestStruct)(20,40,1.0))); + // const Struct + auto x4=const(TestStruct)(30,40,2.2); + auto y4=temp_struct.set(x4); + assert(temp_struct.equal(y4)); + assert(temp_struct.equal(const(TestStruct)(20,40,1.0))); + assert(temp_struct.equal(immutable(TestStruct)(20,40,1.0))); + // Array + char[] x5="Test".dup; + auto y5=temp_string.set(x5); + assert(temp_string.equal(y5)); + assert(temp_string.equal(cast(const(char)[])("Test"))); + assert(temp_string.equal("Test")); + + auto x6=new TestClass(20,40,1.0); + auto y6=temp_class.equal(x6); + auto x7=new TestClass[10]; + auto y7=temp_class_array.equal(x7); + static assert(is(ConstOf!(char[])==const(char)[])); + static assert(is(ConstOf!(immutable(char)[])==const(char)[])); + static assert(is(ConstOf!(immutable(char)[])==const(char)[])); + static assert(is(MutableOf!(char[])==char[])); + static assert(is(MutableOf!(immutable(char)[])==char[])); + static assert(is(MutableOf!(immutable(char)[])==char[])); + Stdout("Eof Traits").nl; +} + // ------- CTFE ------- /// compile time integer to string @@ -600,3 +893,4 @@ debug( UnitTest ) static assert( ctfe_i2a(14UL)=="14" ); } } + From 5a654b2686d5969471b6e46a6efd267ebb3fa1c2 Mon Sep 17 00:00:00 2001 From: cbleser Date: Sat, 2 Mar 2013 19:12:23 +0100 Subject: [PATCH 02/18] real is 0 bug !\?fixed --- tango/text/convert/Float.d | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/tango/text/convert/Float.d b/tango/text/convert/Float.d index 001206b10..3dfc7e71f 100644 --- a/tango/text/convert/Float.d +++ b/tango/text/convert/Float.d @@ -355,8 +355,41 @@ private char *convertl (char* buf, real value, int ndigit, int *decpt, int *sign while (value < 0.1) { value *= 10; --exp10; } while (value >= 1.0) { value /= 10; ++exp10; } } - assert(value is 0 || (0.1 <= value && value < 1.0)); - //auto zero = pad ? int.max : 1; + // + // Bug note Sat Mar 2 18:41:11 CET 2013/cbleser + // For some reason this sometimes assert an error + // because (value is 0) is always true when (value == 0.0) + // + // I have observed that this is caused when the byte outside value is not zero + // Test. + /+ + ubyte* bptr=cast(ubyte*)&value; + assert( (bptr[value.sizeof] !=0) && (value is 0)); + +/ + // I have tried to reproduce this bug in tast code + // but with out success. + // + // Bug reproduce code + // + /+ + ubyte[real.sizeof*2] bytes; + ubyte[] slide; + real* valptr; + foreach(i;0..real.sizeof-1) { + foreach(ref b;bytes) b=42; // Fill with dirt + slide=bytes[i..i+real.sizeof]; + valptr=cast(real*)slide.ptr; + *valptr=0.0; + assert(*valptr==0.0); + assert(*valptr is 0); + } + +/ + // So this code is replaced + //assert(value is 0 || (0.1 <= value && value < 1.0)); + // by (It works the same) + assert(value == 0.0 || (0.1 <= value && value < 1.0)); + + //auto zero = pad ? int.max : 1; auto zero = 1; if (fflag) { From f9addbbb127cfdeee8237e05a1314b09172041b8 Mon Sep 17 00:00:00 2001 From: ude franettet Date: Tue, 13 Aug 2013 16:41:56 +0200 Subject: [PATCH 03/18] In tango.util.container Slink nth(int n) change to nth(size_t n) to support 64bit --- tango/util/container/Slink.d | 46 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/tango/util/container/Slink.d b/tango/util/container/Slink.d index 68a01aac6..68a187e6b 100644 --- a/tango/util/container/Slink.d +++ b/tango/util/container/Slink.d @@ -28,7 +28,7 @@ import tango.util.container.model.IContainer; Still, Slink is made `public' so that you can use it to build other kinds of containers - + Note that when K is specified, support for keys are enabled. When Identity is stipulated as 'true', those keys are compared using an identity-comparison instead of equality (using 'is'). Similarly, if @@ -52,11 +52,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) { hash_t cache; // retain hash value? } - + /*********************************************************************** add support for keys also? - + ***********************************************************************/ static if (!is(typeof(K) == KeyDummy)) @@ -180,13 +180,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) return c; } } - + /*********************************************************************** Set to point to n as next cell param: n, the new next cell - + ***********************************************************************/ final Ref set (V v, Ref n) @@ -202,7 +202,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) previously pointing to param: p, the cell to splice - + ***********************************************************************/ final void attach (Ref p) @@ -214,9 +214,9 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** - Cause current cell to skip over the current next() one, + Cause current cell to skip over the current next() one, effectively removing the next element from the list - + ***********************************************************************/ final void detachNext() @@ -228,10 +228,10 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Linear search down the list looking for element - + param: element to look for Returns: the cell containing element, or null if no such - + ***********************************************************************/ final Ref find (V element) @@ -246,7 +246,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the number of cells traversed to find first occurrence of a cell with element() element, or -1 if not present - + ***********************************************************************/ final const int index (V element) @@ -262,7 +262,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Count the number of occurrences of element in list - + ***********************************************************************/ final const int count (V element) @@ -277,7 +277,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the number of cells in the list - + ***********************************************************************/ final const int count () @@ -292,7 +292,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the cell representing the last element of the list (i.e., the one whose next() is null - + ***********************************************************************/ final Ref tail () @@ -306,13 +306,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the nth cell of the list, or null if no such - + ***********************************************************************/ - final Ref nth (int n) + final Ref nth (size_t n) { auto p = &this; - for (int i; i < n; ++i) + for (size_t i; i < n; ++i) p = p.next; return p; } @@ -321,7 +321,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Make a copy of the list; i.e., a new list containing new cells but including the same elements in the same order - + ***********************************************************************/ final Ref copy (scope Ref delegate() alloc) @@ -341,7 +341,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** dup is shallow; i.e., just makes a copy of the current cell - + ***********************************************************************/ Ref dup (scope Ref delegate() alloc) @@ -358,12 +358,12 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Basic linkedlist merge algorithm. Merges the lists head by fst and snd with respect to cmp - + param: fst head of the first list param: snd head of the second list param: cmp a Comparator used to compare elements Returns: the merged ordered list - + ***********************************************************************/ static Ref merge (Ref fst, Ref snd, Comparator cmp) @@ -452,11 +452,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Standard merge sort algorithm - + param: s the list to sort param: cmp, the comparator to use for ordering Returns: the head of the sorted list - + ***********************************************************************/ static Ref sort (Ref s, Comparator cmp) From bb62619c5837aba8eff3f525e780e47f15f8067a Mon Sep 17 00:00:00 2001 From: ude franettet Date: Tue, 13 Aug 2013 16:55:45 +0200 Subject: [PATCH 04/18] False commit reverted --- tango/core/Traits.d | 298 +------------------------------------------- 1 file changed, 2 insertions(+), 296 deletions(-) diff --git a/tango/core/Traits.d b/tango/core/Traits.d index 26f3adbc5..11d9edb61 100644 --- a/tango/core/Traits.d +++ b/tango/core/Traits.d @@ -288,7 +288,7 @@ template isReferenceType( T ) /** - * Evaluates to true if T is a dynamic array type. + * Evaulates to true if T is a dynamic array type. */ template isDynamicArrayType( T ) { @@ -484,7 +484,7 @@ template staticArraySize(T) { static assert(isStaticArrayType!(T),"staticArraySize needs a static array as type"); static assert(rankOfArray!(T)==1,"implemented only for 1d arrays..."); - const size_t staticArraySize=(T).sizeof / ElementTypeOfArray!(T).sizeof; + const size_t staticArraySize=(T).sizeof / typeof(*T.ptr).sizeof; } /// is T is static array returns a dynamic array, otherwise returns T @@ -517,299 +517,6 @@ debug( UnitTest ) static assert( staticArraySize!(char[2])==2); } -/** This template finds the const type of T if T implicitly can be converted into a const type and can be hold in variable HolderOf without making a explicit copy or dup. - This template can be used on an argument of template functions if the argument is kept constant. - The called argument can be const,immutable or variable. - Ex. - class TClass(T) { - HolderOf! T value; - void func(ConstOf!T x) { - value=x; - } - } - ... - The function "func" can be called with. - auto C=new Tclass!(char[]); - char[] str; - const(char[]) const_str="Const"; - immutable(char[]) immutable_str="Immutable"; - C.func(str); - C.func(const_str); - C.func(immutable_str); -*/ - -template ConstOf(T) { - static if (is(T U:const(U)[])) { - alias const(U)[] ConstOf; - } else static if (is(T U:const(U))) { - alias const(U) ConstOf; - } else { - alias T ConstOf; - } -} - -// template ConstOf(T) { -// static if (is(T : Object)) -// alias T ConstOf; -// else static if (is(T U==immutable(U)[] )) -// alias const(U)[] ConstOf; -// else static if (is(T U:U[])) -// alias ConstOf!(U)[] ConstOf; -// else static if (is(T U:const(U))) -// alias const(U) ConstOf; -// else static assert(0, "No constant type of "~T.stringof); -// } - -/** This template is used in conjunction with the ConstOf template. - HolderOf can hold the value of the ConstOf type with out making a explicit copy. - Ex. - ConstOf!T conts_var; - HolderOf!T holder_var=const_var; -*/ - -template HolderOf(T) { - pragma(msg, "------- "~T.stringof~" -------"); - static if (is(T U==immutable(U[]))) { - // pragma(msg, "inside is(T U==immutable(U)[]) U="~U.stringof~" MutableOf!U="~MutableOf!(U).stringof); - alias const(MutableOf!U)[] HolderOf; - } else static if(is(T U:U[])) { - // pragma(msg, "inside T="~T.stringof~" is(T U:U[])"~U.stringof); - static if (is(U S==const(S))) { - // pragma(msg, "inside is(U S==const(S)) U="~U.stringof~" S="~S.stringof); - alias U[] HolderOf; - } else static if (is(U S==immutable(S))) { - // pragma(msg, "inside is(U S==immutable(S)) U="~U.stringof~" S="~S.stringof) - ; - alias const(S)[] HolderOf; - } else - alias HolderOf!(U)[] HolderOf; - } else static if (is(T U==const(U))) { - // pragma(msg, "inside is(T U==const(U)) U="~U.stringof); - static if (isAtomicType!(MutableOf!T)) { - alias U HolderOf; - } else { - alias T HolderOf; - } - } else static if (is(T U==immutable(U))) { - static if (isAtomicType!(MutableOf!T)) { - alias U HolderOf; - } else { - alias const(U) HolderOf; - } - } else { - alias T HolderOf; - } -} - -/** Converts a type to a mutable type - */ -template MutableOf(T) { - static if(is(T U:const(U)[])) - alias MutableOf!(U)[] MutableOf; - else static if(is(T U:const(U))) - alias U MutableOf; - else - alias T MutableOf; -} - - -unittest { - import tango.io.Stdout; - class TemplateClass(T) { - HolderOf!T value; - - bool equal(ConstOf!T val) const { - return val==value; - } - - T set(T val) { - return (value=val); - } - - } - - struct TestStruct { - int x,y; - real z; - this(const int x, const int y, const real z) { - this.x=x;this.y=y;this.z=z; - } - } - - class TestClass { - int x,y; - real z; - this() { - z=1.0; - } - this(const int x, const int y, const real z) { - this.x=x;this.y=y;this.z=z; - } - } - - // Implicitly conversion - static assert(is(const(int) : int)); - static assert(is(immutable(int) : int)); - static assert(is(const(Object)==const Object)); - static assert(is(int[] :const(int)[])); - static assert(is(immutable(int)[] :const(int)[])); - static assert(is(const(int)[] :const(int)[])); - static assert(is(const(int[]) :const(int)[])); - static assert(is(immutable(int[]) :const(int)[])); - static assert(is(immutable(int[]) :immutable(int)[])); - static assert(is(immutable(int[]) : const(int)[])); - static assert(is(immutable(int[][]) : const(int[])[])); - static assert(is(immutable(int[][][]) : const(int[][])[])); - - // Atomics common - static assert(is(ConstOf!(int)==const(int))); - static assert(is(ConstOf!(immutable int)==const(int))); - static assert(is(ConstOf!(const(int))==const(int))); - // Object common - static assert(is(ConstOf!(Object)==const(Object))); - static assert(is(ConstOf!(immutable(Object))==const(Object))); - static assert(is(ConstOf!(const(Object))==const Object )); - // Atomics Array common - static assert(is(ConstOf!(int[]) == const(int)[]) ); - static assert(is(ConstOf!(const(int)[]) == const(int)[]) ); - static assert(is(ConstOf!(immutable(int)[]) == const(int)[]) ); - // Fixed Atomics Array common - static assert(is(ConstOf!(const(int[])) == const(int)[]) ); - static assert(is(ConstOf!(immutable(int[])) == const(int)[]) ); - // Object Array common - static assert(is(ConstOf!(Object[]) == const(Object)[]) ); - static assert(is(ConstOf!(const(Object)[]) == const(Object)[]) ); - static assert(is(ConstOf!(immutable(Object)[]) == const(Object)[]) ); - // Fixed Object Array common - static assert(is(ConstOf!(const(int[])) == const(int)[]) ); - static assert(is(ConstOf!(immutable(int[])) == const(int)[]) ); - // Jaggles common - static assert(is(ConstOf!(int[][]) == const(int[])[])); - static assert(is(ConstOf!(const(int[])[]) == const(int[])[])); - static assert(is(ConstOf!(const(int[][])) == const(int[])[])); - static assert(is(ConstOf!(immutable(int[])[]) == const(immutable(int)[])[])); - static assert(is(ConstOf!(immutable(int[][])) == const(immutable(int)[])[])); - - // Atomics Mutable - static assert(is(MutableOf!(int)==int)); - static assert(is(MutableOf!(const(int))==int)); - static assert(is(MutableOf!(immutable(int))==int)); - // Object Mutable - static assert(is(MutableOf!(Object)==Object)); - static assert(is(MutableOf!(const(Object))==Object)); - static assert(is(MutableOf!(immutable(Object))==Object)); - // Array Mutable - static assert(is(MutableOf!(int[])==int[])); - static assert(is(MutableOf!(const(int[]))==int[])); - static assert(is(MutableOf!(immutable(int[]))==int[])); - static assert(is(MutableOf!(const(int)[])==int[])); - static assert(is(MutableOf!(immutable(int)[])==int[])); - // Jaggle Mutable - static assert(is(MutableOf!(int[][])==int[][])); - static assert(is(MutableOf!(const(int[][]))==int[][])); - static assert(is(MutableOf!(immutable(int[][]))==int[][])); - static assert(is(MutableOf!(const(int[])[])==int[][])); - static assert(is(MutableOf!(immutable(int[])[])==int[][])); - static assert(is(MutableOf!(const(int[][][]))==int[][][])); - static assert(is(MutableOf!(immutable(int[][][]))==int[][][])); - - // Atomic Holder - static assert(is(HolderOf!(int)==int)); - static assert(is(HolderOf!(const(int))==int)); - static assert(is(HolderOf!(immutable(int))==int)); - static assert(is(int : HolderOf!(int))); - static assert(is(const(int) : HolderOf!(const(int)))); - static assert(is(immutable(int) : HolderOf!(immutable(int)))); - // Object Holder - static assert(is(HolderOf!(Object)==Object)); - static assert(is(HolderOf!(const(Object))==const(Object))); - static assert(is(HolderOf!(immutable(Object))==const(Object))); - static assert(is(Object : HolderOf!(Object))); - static assert(is(const(Object) : HolderOf!(const(Object)))); - static assert(is(immutable(Object) : HolderOf!(immutable(Object)))); - // Atomic Array Holder - static assert(is(HolderOf!(int[])==int[])); - static assert(is(HolderOf!(const(int)[])== const(int)[])); - static assert(is(HolderOf!(immutable(int)[])==const(int)[])); - static assert(is(int[] : HolderOf!(int[]))); - static assert(is(const(int)[] : HolderOf!(const(int)[]))); - static assert(is(immutable(int)[] : HolderOf!(immutable(int)[]))); - // Atomic Fixed Array holder - static assert(is(HolderOf!(const(int[]))== const(int)[])); - static assert(is(HolderOf!(immutable(int[]))==const(int)[])); - static assert(is(const(int[]) : HolderOf!(const(int[])))); - static assert(is(immutable(int[]) : HolderOf!(immutable(int[])))); - // Object Array holder - static assert(is(HolderOf!(Object[])==Object[])); - static assert(is(HolderOf!(const(Object)[])==const(Object)[])); - static assert(is(HolderOf!(immutable(Object)[])==const(Object)[])); - static assert(is(Object[] : HolderOf!(Object[]))); - static assert(is(const(Object)[] : HolderOf!(const(Object)[]))); - static assert(is(immutable(Object)[] : HolderOf!(immutable(Object)[]))); - // Object Fixed Array holder - static assert(is(HolderOf!(const(Object[]))== const(Object)[])); - static assert(is(HolderOf!(immutable(Object[]))==const(Object)[])); - static assert(is(const(Object[]) : HolderOf!(const(Object[])))); - static assert(is(immutable(Object[]) : HolderOf!(immutable(Object[])))); - // Jaggle Holder - static assert(is(HolderOf!(int[][]) == int[][])); - static assert(is(HolderOf!(const(int[])[]) == const(int[])[])); - static assert(is(HolderOf!(immutable(int[])[]) == const(int[])[])); - static assert(is(immutable(int[])[] : HolderOf!(immutable(int[])[]))); - static assert(is(HolderOf!(immutable(int[][])[]) == const(int[][])[])); - static assert(is(immutable(int[][])[] : HolderOf!(immutable(int[][])[]))); - static assert(is(HolderOf!(immutable(int[][][])) == const(int[][])[])); - static assert(is(immutable(int[][][]) : HolderOf!(immutable(int[][])[]))); - - - Stdout("Runtime test").nl; - // Runtime test - auto temp_int=new TemplateClass!(int); - auto temp_struct=new TemplateClass!(TestStruct); - auto temp_class=new TemplateClass!(TestClass); - auto temp_string=new TemplateClass!(char[]); - auto temp_class_array=new TemplateClass!(TestClass[]); - Stdout("After test").nl; - // Atomics - auto y1=temp_int.set(10); - assert(temp_int.equal(10)); - assert(temp_int.equal(y1)); - int x2=30; - auto y2=temp_int.set(x2); - assert(temp_int.equal(20)); - assert(temp_int.equal(x2)); - // Struct - auto x3=TestStruct(20,40,1.0); - auto y3=temp_struct.set(x3); - assert(temp_struct.equal(y3)); - assert(temp_struct.equal(const(TestStruct)(20,40,1.0))); - assert(temp_struct.equal(immutable(TestStruct)(20,40,1.0))); - // const Struct - auto x4=const(TestStruct)(30,40,2.2); - auto y4=temp_struct.set(x4); - assert(temp_struct.equal(y4)); - assert(temp_struct.equal(const(TestStruct)(20,40,1.0))); - assert(temp_struct.equal(immutable(TestStruct)(20,40,1.0))); - // Array - char[] x5="Test".dup; - auto y5=temp_string.set(x5); - assert(temp_string.equal(y5)); - assert(temp_string.equal(cast(const(char)[])("Test"))); - assert(temp_string.equal("Test")); - - auto x6=new TestClass(20,40,1.0); - auto y6=temp_class.equal(x6); - auto x7=new TestClass[10]; - auto y7=temp_class_array.equal(x7); - static assert(is(ConstOf!(char[])==const(char)[])); - static assert(is(ConstOf!(immutable(char)[])==const(char)[])); - static assert(is(ConstOf!(immutable(char)[])==const(char)[])); - static assert(is(MutableOf!(char[])==char[])); - static assert(is(MutableOf!(immutable(char)[])==char[])); - static assert(is(MutableOf!(immutable(char)[])==char[])); - Stdout("Eof Traits").nl; -} - // ------- CTFE ------- /// compile time integer to string @@ -893,4 +600,3 @@ debug( UnitTest ) static assert( ctfe_i2a(14UL)=="14" ); } } - From 9c60ec018e32e60c3a7ebf9f5b198480f0f2a097 Mon Sep 17 00:00:00 2001 From: ude franettet Date: Tue, 13 Aug 2013 17:02:41 +0200 Subject: [PATCH 05/18] False commit reverted --- tango/text/convert/Float.d | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/tango/text/convert/Float.d b/tango/text/convert/Float.d index 3dfc7e71f..001206b10 100644 --- a/tango/text/convert/Float.d +++ b/tango/text/convert/Float.d @@ -355,41 +355,8 @@ private char *convertl (char* buf, real value, int ndigit, int *decpt, int *sign while (value < 0.1) { value *= 10; --exp10; } while (value >= 1.0) { value /= 10; ++exp10; } } - // - // Bug note Sat Mar 2 18:41:11 CET 2013/cbleser - // For some reason this sometimes assert an error - // because (value is 0) is always true when (value == 0.0) - // - // I have observed that this is caused when the byte outside value is not zero - // Test. - /+ - ubyte* bptr=cast(ubyte*)&value; - assert( (bptr[value.sizeof] !=0) && (value is 0)); - +/ - // I have tried to reproduce this bug in tast code - // but with out success. - // - // Bug reproduce code - // - /+ - ubyte[real.sizeof*2] bytes; - ubyte[] slide; - real* valptr; - foreach(i;0..real.sizeof-1) { - foreach(ref b;bytes) b=42; // Fill with dirt - slide=bytes[i..i+real.sizeof]; - valptr=cast(real*)slide.ptr; - *valptr=0.0; - assert(*valptr==0.0); - assert(*valptr is 0); - } - +/ - // So this code is replaced - //assert(value is 0 || (0.1 <= value && value < 1.0)); - // by (It works the same) - assert(value == 0.0 || (0.1 <= value && value < 1.0)); - - //auto zero = pad ? int.max : 1; + assert(value is 0 || (0.1 <= value && value < 1.0)); + //auto zero = pad ? int.max : 1; auto zero = 1; if (fflag) { From 9b98da1e7ee17f46c65ce905a2f602088bc2b163 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 11:56:19 +0200 Subject: [PATCH 06/18] cbleser/d2port is now the same as siegelord/d2port --- tango/core/Traits.d | 2 +- tango/util/container/Slink.d | 46 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tango/core/Traits.d b/tango/core/Traits.d index 40672f822..905e6fee4 100644 --- a/tango/core/Traits.d +++ b/tango/core/Traits.d @@ -484,7 +484,7 @@ template staticArraySize(T) { static assert(isStaticArrayType!(T),"staticArraySize needs a static array as type"); static assert(rankOfArray!(T)==1,"implemented only for 1d arrays..."); - const size_t staticArraySize=(T).sizeof / typeof(*T.ptr).sizeof; + const size_t staticArraySize=(T).sizeof / ElementTypeOfArray!(T).sizeof; } /// is T is static array returns a dynamic array, otherwise returns T diff --git a/tango/util/container/Slink.d b/tango/util/container/Slink.d index 68a187e6b..68a01aac6 100644 --- a/tango/util/container/Slink.d +++ b/tango/util/container/Slink.d @@ -28,7 +28,7 @@ import tango.util.container.model.IContainer; Still, Slink is made `public' so that you can use it to build other kinds of containers - + Note that when K is specified, support for keys are enabled. When Identity is stipulated as 'true', those keys are compared using an identity-comparison instead of equality (using 'is'). Similarly, if @@ -52,11 +52,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) { hash_t cache; // retain hash value? } - + /*********************************************************************** add support for keys also? - + ***********************************************************************/ static if (!is(typeof(K) == KeyDummy)) @@ -180,13 +180,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) return c; } } - + /*********************************************************************** Set to point to n as next cell param: n, the new next cell - + ***********************************************************************/ final Ref set (V v, Ref n) @@ -202,7 +202,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) previously pointing to param: p, the cell to splice - + ***********************************************************************/ final void attach (Ref p) @@ -214,9 +214,9 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** - Cause current cell to skip over the current next() one, + Cause current cell to skip over the current next() one, effectively removing the next element from the list - + ***********************************************************************/ final void detachNext() @@ -228,10 +228,10 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Linear search down the list looking for element - + param: element to look for Returns: the cell containing element, or null if no such - + ***********************************************************************/ final Ref find (V element) @@ -246,7 +246,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the number of cells traversed to find first occurrence of a cell with element() element, or -1 if not present - + ***********************************************************************/ final const int index (V element) @@ -262,7 +262,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Count the number of occurrences of element in list - + ***********************************************************************/ final const int count (V element) @@ -277,7 +277,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the number of cells in the list - + ***********************************************************************/ final const int count () @@ -292,7 +292,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the cell representing the last element of the list (i.e., the one whose next() is null - + ***********************************************************************/ final Ref tail () @@ -306,13 +306,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the nth cell of the list, or null if no such - + ***********************************************************************/ - final Ref nth (size_t n) + final Ref nth (int n) { auto p = &this; - for (size_t i; i < n; ++i) + for (int i; i < n; ++i) p = p.next; return p; } @@ -321,7 +321,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Make a copy of the list; i.e., a new list containing new cells but including the same elements in the same order - + ***********************************************************************/ final Ref copy (scope Ref delegate() alloc) @@ -341,7 +341,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** dup is shallow; i.e., just makes a copy of the current cell - + ***********************************************************************/ Ref dup (scope Ref delegate() alloc) @@ -358,12 +358,12 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Basic linkedlist merge algorithm. Merges the lists head by fst and snd with respect to cmp - + param: fst head of the first list param: snd head of the second list param: cmp a Comparator used to compare elements Returns: the merged ordered list - + ***********************************************************************/ static Ref merge (Ref fst, Ref snd, Comparator cmp) @@ -452,11 +452,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Standard merge sort algorithm - + param: s the list to sort param: cmp, the comparator to use for ordering Returns: the head of the sorted list - + ***********************************************************************/ static Ref sort (Ref s, Comparator cmp) From d59d5eeed8bd6ffe371c2b97b772c6c5510656b3 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:23:29 +0200 Subject: [PATCH 07/18] tango/util/container/Slink.d findKey and nth function change to support all mutual types --- tango/util/container/Slink.d | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tango/util/container/Slink.d b/tango/util/container/Slink.d index 68a01aac6..866a799d0 100644 --- a/tango/util/container/Slink.d +++ b/tango/util/container/Slink.d @@ -16,7 +16,7 @@ module tango.util.container.Slink; -import tango.util.container.model.IContainer; +private import tango.util.container.model.IContainer; /******************************************************************************* @@ -28,7 +28,7 @@ import tango.util.container.model.IContainer; Still, Slink is made `public' so that you can use it to build other kinds of containers - + Note that when K is specified, support for keys are enabled. When Identity is stipulated as 'true', those keys are compared using an identity-comparison instead of equality (using 'is'). Similarly, if @@ -37,7 +37,7 @@ import tango.util.container.model.IContainer; *******************************************************************************/ -alias int KeyDummy; +private alias int KeyDummy; struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) { @@ -52,11 +52,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) { hash_t cache; // retain hash value? } - + /*********************************************************************** add support for keys also? - + ***********************************************************************/ static if (!is(typeof(K) == KeyDummy)) @@ -74,7 +74,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) return typeid(K).getHash(&key); } - final Ref findKey (K key) + final Ref findKey (inout(K) key) { static if (Identity == true) { @@ -180,13 +180,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) return c; } } - + /*********************************************************************** Set to point to n as next cell param: n, the new next cell - + ***********************************************************************/ final Ref set (V v, Ref n) @@ -202,7 +202,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) previously pointing to param: p, the cell to splice - + ***********************************************************************/ final void attach (Ref p) @@ -214,9 +214,9 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** - Cause current cell to skip over the current next() one, + Cause current cell to skip over the current next() one, effectively removing the next element from the list - + ***********************************************************************/ final void detachNext() @@ -228,10 +228,10 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Linear search down the list looking for element - + param: element to look for Returns: the cell containing element, or null if no such - + ***********************************************************************/ final Ref find (V element) @@ -246,7 +246,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the number of cells traversed to find first occurrence of a cell with element() element, or -1 if not present - + ***********************************************************************/ final const int index (V element) @@ -262,7 +262,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Count the number of occurrences of element in list - + ***********************************************************************/ final const int count (V element) @@ -277,7 +277,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the number of cells in the list - + ***********************************************************************/ final const int count () @@ -292,7 +292,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Return the cell representing the last element of the list (i.e., the one whose next() is null - + ***********************************************************************/ final Ref tail () @@ -306,13 +306,13 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Return the nth cell of the list, or null if no such - + ***********************************************************************/ - final Ref nth (int n) + final inout(Ref) nth (size_t n) inout { auto p = &this; - for (int i; i < n; ++i) + for (size_t i; i < n; ++i) p = p.next; return p; } @@ -321,7 +321,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Make a copy of the list; i.e., a new list containing new cells but including the same elements in the same order - + ***********************************************************************/ final Ref copy (scope Ref delegate() alloc) @@ -341,7 +341,7 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** dup is shallow; i.e., just makes a copy of the current cell - + ***********************************************************************/ Ref dup (scope Ref delegate() alloc) @@ -358,12 +358,12 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) Basic linkedlist merge algorithm. Merges the lists head by fst and snd with respect to cmp - + param: fst head of the first list param: snd head of the second list param: cmp a Comparator used to compare elements Returns: the merged ordered list - + ***********************************************************************/ static Ref merge (Ref fst, Ref snd, Comparator cmp) @@ -452,11 +452,11 @@ struct Slink (V, K=KeyDummy, bool Identity = false, bool HashCache = false) /*********************************************************************** Standard merge sort algorithm - + param: s the list to sort param: cmp, the comparator to use for ordering Returns: the head of the sorted list - + ***********************************************************************/ static Ref sort (Ref s, Comparator cmp) From e891c8569a9f4a9f36acf3f5694a9fba84c9ded0 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:30:34 +0200 Subject: [PATCH 08/18] tango/util/container/Container.d int size parameter change to size_t to support 64bit coding better --- tango/util/container/Container.d | 338 ++++++++++++++++--------------- 1 file changed, 175 insertions(+), 163 deletions(-) diff --git a/tango/util/container/Container.d b/tango/util/container/Container.d index f54c2ba0a..277ce21ac 100644 --- a/tango/util/container/Container.d +++ b/tango/util/container/Container.d @@ -29,37 +29,37 @@ private import tango.stdc.string; struct Container { /*********************************************************************** - + default initial number of buckets of a non-empty hashmap ***********************************************************************/ - + enum size_t defaultInitialBuckets = 31; /*********************************************************************** - default load factor for a non-empty hashmap. The hash - table is resized when the proportion of elements per + default load factor for a non-empty hashmap. The hash + table is resized when the proportion of elements per buckets exceeds this limit - + ***********************************************************************/ - + enum float defaultLoadFactor = 0.75f; /*********************************************************************** - + generic value reaper, which does nothing ***********************************************************************/ - + static void reap(V) (V v) {} /*********************************************************************** - + generic key/value reaper, which does nothing ***********************************************************************/ - + static void reap(K, V) (K k, V v) {} /*********************************************************************** @@ -71,8 +71,8 @@ struct Container static size_t hash(K) (K k, size_t length) { - static if (is(K : int) || is(K : uint) || - is(K : long) || is(K : ulong) || + static if (is(K : int) || is(K : uint) || + is(K : long) || is(K : ulong) || is(K : short) || is(K : ushort) || is(K : byte) || is(K : ubyte) || is(K : char) || is(K : wchar) || is (K : dchar)) @@ -83,18 +83,18 @@ struct Container /*********************************************************************** - + GC Chunk allocator - Can save approximately 30% memory for small elements (tested - with integer elements and a chunk size of 1000), and is at - least twice as fast at adding elements when compared to the + Can save approximately 30% memory for small elements (tested + with integer elements and a chunk size of 1000), and is at + least twice as fast at adding elements when compared to the generic allocator (approximately 50x faster with LinkedList) - + Operates safely with GC managed entities ***********************************************************************/ - + struct ChunkGC(T) { static assert (T.sizeof >= (T*).sizeof, "The ChunkGC allocator can only be used for data sizes of at least " ~ ((T*).sizeof).stringof[0..$-1] ~ " bytes!"); @@ -106,9 +106,9 @@ struct Container private size_t chunks = 256; /*************************************************************** - + allocate a T-sized memory chunk - + ***************************************************************/ T* allocate () @@ -119,28 +119,28 @@ struct Container cache = p.next; return cast(T*) p; } - + /*************************************************************** - + allocate an array of T* sized memory chunks - + ***************************************************************/ - + T*[] allocate (size_t count) { auto p = (cast(T**) calloc(count, (T*).sizeof)) [0 .. count]; GC.addRange (cast(void*) p, count * (T*).sizeof); return p; } - + /*************************************************************** - + Invoked when a specific T*[] is discarded - + ***************************************************************/ - + void collect (T*[] t) - { + { if (t.ptr) { GC.removeRange (t.ptr); @@ -149,31 +149,31 @@ struct Container } /*************************************************************** - + Invoked when a specific T is discarded - + ***************************************************************/ - + void collect (T* p) - { + { assert (p); auto d = cast(Cache*) p; //*p = T.init; d.next = cache; cache = d; } - + /*************************************************************** - - Invoked when clear/reset is called on the host. + + Invoked when clear/reset is called on the host. This is a shortcut to clear everything allocated. - - Should return true if supported, or false otherwise. + + Should return true if supported, or false otherwise. False return will cause a series of discrete collect calls - + ***************************************************************/ - + bool collect (bool all = true) { if (all) @@ -190,13 +190,13 @@ struct Container } return false; } - + /*************************************************************** - + set the chunk size and prepopulate with nodes - + ***************************************************************/ - + void config (size_t chunks, size_t allocate=0) { this.chunks = chunks; @@ -204,13 +204,13 @@ struct Container for (size_t i=allocate/chunks+1; i--;) newlist(); } - + /*************************************************************** - + list manager - + ***************************************************************/ - + private void newlist () { lists.length = lists.length + 1; @@ -226,29 +226,29 @@ struct Container } cache = head; } - } + } /*********************************************************************** - + Chunk allocator (non GC) - Can save approximately 30% memory for small elements (tested - with integer elements and a chunk size of 1000), and is at - least twice as fast at adding elements when compared to the + Can save approximately 30% memory for small elements (tested + with integer elements and a chunk size of 1000), and is at + least twice as fast at adding elements when compared to the default allocator (approximately 50x faster with LinkedList) - + Note that, due to GC behaviour, you should not configure a custom allocator for containers holding anything managed by the GC. For example, you cannot use a MallocAllocator - to manage a container of classes or strings where those + to manage a container of classes or strings where those were allocated by the GC. Once something is owned by a GC then it's lifetime must be managed by GC-managed entities (otherwise the GC may think there are no live references and prematurely collect container contents). - + You can explicity manage the collection of keys and values - yourself by providing a reaper delegate. For example, if + yourself by providing a reaper delegate. For example, if you use a MallocAllocator to manage key/value pairs which are themselves allocated via malloc, then you should also provide a reaper delegate to collect those as required. @@ -257,9 +257,9 @@ struct Container scanning the date-structures involved. Use ChunkGC where that option is unwarranted, or if you have GC-managed data instead - + ***********************************************************************/ - + struct Chunk(T) { static assert (T.sizeof >= (T*).sizeof, "The Chunk allocator can only be used for data sizes of at least " ~ ((T*).sizeof).stringof[0..$-1] ~ " bytes!"); @@ -271,9 +271,9 @@ struct Container private size_t chunks = 256; /*************************************************************** - + allocate a T-sized memory chunk - + ***************************************************************/ T* allocate () @@ -284,55 +284,55 @@ struct Container cache = p.next; return cast(T*) p; } - + /*************************************************************** - + allocate an array of T* sized memory chunks - + ***************************************************************/ - + T*[] allocate (size_t count) { return (cast(T**) calloc(count, (T*).sizeof)) [0 .. count]; } - + /*************************************************************** - + Invoked when a specific T*[] is discarded - + ***************************************************************/ - + void collect (T*[] t) - { + { if (t.ptr) free (t.ptr); } /*************************************************************** - + Invoked when a specific T is discarded - + ***************************************************************/ - + void collect (T* p) - { + { assert (p); auto d = cast(Cache*) p; d.next = cache; cache = d; } - + /*************************************************************** - - Invoked when clear/reset is called on the host. + + Invoked when clear/reset is called on the host. This is a shortcut to clear everything allocated. - - Should return true if supported, or false otherwise. + + Should return true if supported, or false otherwise. False return will cause a series of discrete collect calls - + ***************************************************************/ - + bool collect (bool all = true) { if (all) @@ -348,27 +348,27 @@ struct Container } return false; } - + /*************************************************************** - + set the chunk size and prepopulate with nodes - + ***************************************************************/ - - void config (size_t chunks, int allocate=0) + + void config (size_t chunks, size_t allocate=0) { this.chunks = chunks; if (allocate) for (int i=allocate/chunks+1; i--;) newlist(); } - + /*************************************************************** - + list manager - + ***************************************************************/ - + private void newlist () { lists.length = lists.length + 1; @@ -383,194 +383,206 @@ struct Container } cache = head; } - } + } /*********************************************************************** - + generic GC allocation manager Slow and expensive in memory costs - + ***********************************************************************/ - + struct Collect(T) { /*************************************************************** - + allocate a T sized memory chunk - + ***************************************************************/ - + T* allocate () - { + { return cast(T*) GC.calloc (T.sizeof); } - + /*************************************************************** - + allocate an array of T sized memory chunks - + ***************************************************************/ - + T*[] allocate (size_t count) { return new T*[count]; } - + /*************************************************************** - + Invoked when a specific T[] is discarded - + ***************************************************************/ - + void collect (T* p) { if (p) delete p; } - + /*************************************************************** - + Invoked when a specific T[] is discarded - + ***************************************************************/ - + void collect (T*[] t) - { + { if (t) delete t; } /*************************************************************** - - Invoked when clear/reset is called on the host. + + Invoked when clear/reset is called on the host. This is a shortcut to clear everything allocated. - - Should return true if supported, or false otherwise. + + Should return true if supported, or false otherwise. False return will cause a series of discrete collect calls ***************************************************************/ - + bool collect (bool all = true) { return false; } /*************************************************************** - + set the chunk size and prepopulate with nodes - + ***************************************************************/ - - void config (size_t chunks, int allocate=0) + + void config (size_t chunks, size_t allocate=0) { } - } - - + } + + /*********************************************************************** - + Malloc allocation manager. Note that, due to GC behaviour, you should not configure a custom allocator for containers holding anything managed by the GC. For example, you cannot use a MallocAllocator - to manage a container of classes or strings where those + to manage a container of classes or strings where those were allocated by the GC. Once something is owned by a GC then it's lifetime must be managed by GC-managed entities (otherwise the GC may think there are no live references and prematurely collect container contents). - + You can explicity manage the collection of keys and values - yourself by providing a reaper delegate. For example, if + yourself by providing a reaper delegate. For example, if you use a MallocAllocator to manage key/value pairs which are themselves allocated via malloc, then you should also - provide a reaper delegate to collect those as required. - + provide a reaper delegate to collect those as required. + ***********************************************************************/ - + struct Malloc(T) { /*************************************************************** - + allocate an array of T sized memory chunks - + ***************************************************************/ - + T* allocate () { return cast(T*) calloc (1, T.sizeof); } - + /*************************************************************** - + allocate an array of T sized memory chunks - + ***************************************************************/ - + T*[] allocate (size_t count) { return (cast(T**) calloc(count, (T*).sizeof)) [0 .. count]; } - + /*************************************************************** - + Invoked when a specific T[] is discarded - + ***************************************************************/ - + + void collect (T*[] t) + { + if (t.length) + free (t.ptr); + } + + /*************************************************************** + + Invoked when a specific T[] is discarded + + ***************************************************************/ + void collect (T*[] t) - { + { if (t.length) free (t.ptr); } /*************************************************************** - + Invoked when a specific T[] is discarded - + ***************************************************************/ - + void collect (T* p) - { + { if (p) free (p); } - + /*************************************************************** - - Invoked when clear/reset is called on the host. + + Invoked when clear/reset is called on the host. This is a shortcut to clear everything allocated. - - Should return true if supported, or false otherwise. + + Should return true if supported, or false otherwise. False return will cause a series of discrete collect calls - + ***************************************************************/ - + bool collect (bool all = true) { return false; } /*************************************************************** - + set the chunk size and prepopulate with nodes - + ***************************************************************/ - - void config (size_t chunks, int allocate=0) + + void config (size_t chunks, size_t allocate=0) { } - } - - + } + + version (prior_allocator) { /*********************************************************************** - + GCChunk allocator Like the Chunk allocator, this allocates elements in chunks, @@ -578,7 +590,7 @@ version (prior_allocator) Tests have shown about a 60% speedup when using the GC chunk allocator for a Hashmap!(int, int). - + ***********************************************************************/ struct GCChunk(T, uint chunkSize) @@ -843,7 +855,7 @@ version (prior_allocator) return true; } - void config (size_t chunks, int allocate=0) + void config (size_t chunks, size_t allocate=0) { } } From f84d7b069ff2370a5888b9f879d7702706c4f8ce Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:33:09 +0200 Subject: [PATCH 09/18] size function in tango/util/container/RedBlack.d is now const again --- tango/util/container/RedBlack.d | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/tango/util/container/RedBlack.d b/tango/util/container/RedBlack.d index ecb8d75bb..97cde8fd5 100644 --- a/tango/util/container/RedBlack.d +++ b/tango/util/container/RedBlack.d @@ -227,9 +227,9 @@ struct RedBlack (V, A = AttributeDummy) /** * Return the number of nodes in the subtree **/ - @property size_t size () + @property size_t size () const { - auto c = 1; + size_t c = 1; if (left) c += left.size; if (right) @@ -584,12 +584,11 @@ struct RedBlack (V, A = AttributeDummy) { y.parent = px; if (px !is null) - { if (xpl) px.left = y; else px.right = y; - } + x.parent = y; if (ypl) { @@ -615,17 +614,15 @@ struct RedBlack (V, A = AttributeDummy) ry.parent = x; } else - { if (y is px) { x.parent = py; if (py !is null) - { if (ypl) py.left = x; else py.right = x; - } + y.parent = x; if (xpl) { @@ -654,12 +651,11 @@ struct RedBlack (V, A = AttributeDummy) { x.parent = py; if (py !is null) - { if (ypl) py.left = x; else py.right = x; - } + x.left = ly; if (ly !is null) ly.parent = x; @@ -670,12 +666,11 @@ struct RedBlack (V, A = AttributeDummy) y.parent = px; if (px !is null) - { if (xpl) px.left = y; else px.right = y; - } + y.left = lx; if (lx !is null) lx.parent = y; @@ -684,7 +679,7 @@ struct RedBlack (V, A = AttributeDummy) if (rx !is null) rx.parent = y; } - } + bool c = x.color; x.color = y.color; y.color = c; From 73822e2e1ef887ef9234603f1103175e2be96b88 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:34:20 +0200 Subject: [PATCH 10/18] size function in tango/util/container/HashSet.d is now const --- tango/util/container/HashSet.d | 122 ++++++++++++++++----------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/tango/util/container/HashSet.d b/tango/util/container/HashSet.d index 4174781c2..73bab902a 100644 --- a/tango/util/container/HashSet.d +++ b/tango/util/container/HashSet.d @@ -52,21 +52,21 @@ private import tango.util.container.model.IContainer; *******************************************************************************/ -class HashSet (V, alias Hash = Container.hash, - alias Reap = Container.reap, - alias Heap = Container.DefaultCollect) +class HashSet (V, alias Hash = Container.hash, + alias Reap = Container.reap, + alias Heap = Container.DefaultCollect) : IContainer!(V) { // use this type for Allocator configuration public alias Slink!(V) Type; - + private alias Type *Ref; private alias Heap!(Type) Alloc; // Each table entry is a list - null if no table allocated private Ref table[]; - + // number of elements contained private size_t count; @@ -75,7 +75,7 @@ class HashSet (V, alias Hash = Container.hash, // configured heap manager private Alloc heap; - + // mutation tag updates on each change private size_t mutation; @@ -104,7 +104,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Return a generic iterator for contained elements - + ***********************************************************************/ final Iterator iterator () @@ -131,22 +131,22 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Return the number of elements contained - + ***********************************************************************/ - @property final const size_t size () + @property final size_t size () const { return count; } - + /*********************************************************************** Add a new element to the set. Does not add if there is an equivalent already present. Returns true where an element is added, false where it already exists - + Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ final bool add (V element) @@ -163,18 +163,18 @@ class HashSet (V, alias Hash = Container.hash, table[h] = allocate.set (element, hd); increment; - // only check if bin was nonempty + // only check if bin was nonempty if (hd) - checkLoad; + checkLoad; return true; } /*********************************************************************** Does this set contain the given element? - + Time complexity: O(1) average; O(n) worst - + ***********************************************************************/ final bool contains (V element) @@ -192,15 +192,15 @@ class HashSet (V, alias Hash = Container.hash, Make an independent copy of the container. Does not clone elements - + Time complexity: O(n) - + ***********************************************************************/ @property final HashSet dup () { auto clone = new HashSet!(V, Hash, Reap, Heap) (loadFactor); - + if (count) { clone.buckets (buckets); @@ -215,7 +215,7 @@ class HashSet (V, alias Hash = Container.hash, Remove the provided element. Returns true if found, false otherwise - + Time complexity: O(1) average; O(n) worst ***********************************************************************/ @@ -229,7 +229,7 @@ class HashSet (V, alias Hash = Container.hash, Remove the provided element. Returns true if found, false otherwise - + Time complexity: O(1) average; O(n) worst ***********************************************************************/ @@ -257,7 +257,7 @@ class HashSet (V, alias Hash = Container.hash, else trail.next = n; return true; - } + } else { trail = p; @@ -273,7 +273,7 @@ class HashSet (V, alias Hash = Container.hash, Replace the first instance of oldElement with newElement. Returns true if oldElement was found and replaced, false otherwise. - + ***********************************************************************/ final size_t replace (V oldElement, V newElement, bool all) @@ -286,7 +286,7 @@ class HashSet (V, alias Hash = Container.hash, Replace the first instance of oldElement with newElement. Returns true if oldElement was found and replaced, false otherwise. - + ***********************************************************************/ final bool replace (V oldElement, V newElement) @@ -306,7 +306,7 @@ class HashSet (V, alias Hash = Container.hash, Remove and expose the first element. Returns false when no more elements are contained - + Time complexity: O(n) ***********************************************************************/ @@ -356,7 +356,7 @@ class HashSet (V, alias Hash = Container.hash, reset() to drop everything. Time complexity: O(n) - + ***********************************************************************/ final HashSet clear () @@ -370,7 +370,7 @@ class HashSet (V, alias Hash = Container.hash, heap manager. This releases more memory than clear() does Time complexity: O(1) - + ***********************************************************************/ final HashSet reset () @@ -397,7 +397,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Set the number of buckets and resize as required - + Time complexity: O(n) ***********************************************************************/ @@ -415,7 +415,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Return the resize threshold - + Time complexity: O(1) ***********************************************************************/ @@ -428,9 +428,9 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Set the resize threshold, and resize as required - + Time complexity: O(n) - + ***********************************************************************/ final void threshold (float desired) @@ -446,7 +446,7 @@ class HashSet (V, alias Hash = Container.hash, Configure the assigned allocator with the size of each allocation block (number of nodes allocated at one time) and the number of nodes to pre-populate the cache with. - + Time complexity: O(n) ***********************************************************************/ @@ -459,14 +459,14 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** - Copy and return the contained set of values in an array, - using the optional dst as a recipient (which is resized + Copy and return the contained set of values in an array, + using the optional dst as a recipient (which is resized as necessary). Returns a slice of dst representing the container values. - + Time complexity: O(n) - + ***********************************************************************/ final V[] toArray (V[] dst = null) @@ -477,15 +477,15 @@ class HashSet (V, alias Hash = Container.hash, size_t i = 0; foreach (v; this) dst[i++] = v; - return dst [0 .. count]; + return dst [0 .. count]; } /*********************************************************************** Is this container empty? - + Time complexity: O(1) - + ***********************************************************************/ final const bool isEmpty () @@ -496,7 +496,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Sanity check - + ***********************************************************************/ final HashSet check() @@ -525,19 +525,19 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** Allocate a node instance. This is used as the default allocator - + ***********************************************************************/ private Ref allocate () { return heap.allocate; } - + /*********************************************************************** Check to see if we are past load factor threshold. If so, resize so that we are at half of the desired threshold. - + ***********************************************************************/ private void checkLoad () @@ -551,7 +551,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** resize table to new capacity, rehashing all elements - + ***********************************************************************/ private void resize (size_t newCap) @@ -582,7 +582,7 @@ class HashSet (V, alias Hash = Container.hash, the per-node memory than to gain a little on each remove Used by iterators only - + ***********************************************************************/ private bool remove (Ref node, size_t row) @@ -602,7 +602,7 @@ class HashSet (V, alias Hash = Container.hash, else trail.next = n; return true; - } + } else { trail = p; @@ -619,7 +619,7 @@ class HashSet (V, alias Hash = Container.hash, reset() to drop everything. Time complexity: O(n) - + ***********************************************************************/ private HashSet clear (bool all) @@ -647,7 +647,7 @@ class HashSet (V, alias Hash = Container.hash, /*********************************************************************** new element was added - + ***********************************************************************/ private void increment() @@ -655,11 +655,11 @@ class HashSet (V, alias Hash = Container.hash, ++mutation; ++count; } - + /*********************************************************************** element was removed - + ***********************************************************************/ private void decrement (Ref p) @@ -669,11 +669,11 @@ class HashSet (V, alias Hash = Container.hash, ++mutation; --count; } - + /*********************************************************************** set was changed - + ***********************************************************************/ private void mutate() @@ -705,7 +705,7 @@ class HashSet (V, alias Hash = Container.hash, bool valid () { return owner.mutation is mutation; - } + } /*************************************************************** @@ -719,7 +719,7 @@ class HashSet (V, alias Hash = Container.hash, auto n = next; return (n) ? v = *n, true : false; } - + /*************************************************************** Return a pointer to the next value, or null when @@ -734,7 +734,7 @@ class HashSet (V, alias Hash = Container.hash, cell = table [row++]; else return null; - + prior = cell; cell = cell.next; return &prior.value; @@ -758,7 +758,7 @@ class HashSet (V, alias Hash = Container.hash, c = table [row++]; else break loop; - + prior = c; c = c.next; if ((result = dg(prior.value)) != 0) @@ -767,7 +767,7 @@ class HashSet (V, alias Hash = Container.hash, cell = c; return result; - } + } /*************************************************************** @@ -802,7 +802,7 @@ debug (HashSet) import tango.io.Stdout; import tango.core.Thread; import tango.time.StopWatch; - + void main() { // usage examples ... @@ -829,7 +829,7 @@ debug (HashSet) auto iterator = set.iterator; while (iterator.next(v)) {} //iterator.remove; - + // incremental iteration, with optional failfast auto it = set.iterator; while (it.valid && it.next(v)) @@ -841,8 +841,8 @@ debug (HashSet) // remove first element ... while (set.take(v)) Stdout.formatln ("taking {}, {} left", v, set.size); - - + + // setup for benchmark, with a set of integers. We // use a chunk allocator, and presize the bucket[] auto test = new HashSet!(int, Container.hash, Container.reap, Container.Chunk); From 1c1bd590b0779c762ff64c886e0b425d3cb20490 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:35:43 +0200 Subject: [PATCH 11/18] size function in tango/util/container/SortedMap.d is now const --- tango/util/container/SortedMap.d | 160 +++++++++++++++---------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/tango/util/container/SortedMap.d b/tango/util/container/SortedMap.d index 68f4a7f7c..bb28b8f8d 100644 --- a/tango/util/container/SortedMap.d +++ b/tango/util/container/SortedMap.d @@ -65,8 +65,8 @@ private import tango.core.Exception : NoSuchElementException; *******************************************************************************/ -class SortedMap (K, V, alias Reap = Container.reap, - alias Heap = Container.DefaultCollect) +class SortedMap (K, V, alias Reap = Container.reap, + alias Heap = Container.DefaultCollect) : IContainer!(V) { // use this type for Allocator configuration @@ -93,7 +93,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Make an empty tree, using given Comparator for ordering - + ***********************************************************************/ public this (Comparator c = null) @@ -104,11 +104,11 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Special version of constructor needed by dup() - + ***********************************************************************/ private this (Comparator c, size_t n) - { + { count = n; cmpElem = &compareElem; cmp = (c is null) ? &compareKey : c; @@ -128,7 +128,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Return a generic iterator for contained elements - + ***********************************************************************/ final Iterator iterator (bool forward = true) @@ -141,15 +141,15 @@ class SortedMap (K, V, alias Reap = Container.reap, i.prior = null; return i; } - + /*********************************************************************** - Return an iterator which return all elements matching + Return an iterator which return all elements matching or greater/lesser than the key in argument. The second argument dictates traversal direction. Return a generic iterator for contained elements - + ***********************************************************************/ final Iterator iterator (K key, bool forward) @@ -164,7 +164,7 @@ class SortedMap (K, V, alias Reap = Container.reap, Configure the assigned allocator with the size of each allocation block (number of nodes allocated at one time) and the number of nodes to pre-populate the cache with. - + Time complexity: O(n) ***********************************************************************/ @@ -178,18 +178,18 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Return the number of elements contained - + ***********************************************************************/ - @property final const size_t size () + @property final size_t size () const { return count; } - + /*********************************************************************** Create an independent copy. Does not clone elements - + ***********************************************************************/ @property final SortedMap dup () @@ -204,7 +204,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ final bool contains (V value) @@ -215,9 +215,9 @@ class SortedMap (K, V, alias Reap = Container.reap, } /*********************************************************************** - + ***********************************************************************/ - + final int opApply (scope int delegate (ref V value) dg) { return iterator.opApply ((ref K k, ref V v) {return dg(v);}); @@ -225,9 +225,9 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - + ***********************************************************************/ - + final int opApply (scope int delegate (ref K key, ref V value) dg) { return iterator.opApply (dg); @@ -236,7 +236,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Use a new Comparator. Causes a reorganization - + ***********************************************************************/ final SortedMap comparator (Comparator c) @@ -246,13 +246,13 @@ class SortedMap (K, V, alias Reap = Container.reap, cmp = (c is null) ? &compareKey : c; if (count !is 0) - { + { // must rebuild tree! mutate; auto t = tree.leftmost; tree = null; count = 0; - + while (t) { add_ (t.value, t.attribute, false); @@ -266,7 +266,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ final bool containsKey (K key) @@ -280,7 +280,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n) - + ***********************************************************************/ final bool containsPair (K key, V value) @@ -293,11 +293,11 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - Return the value associated with Key key. + Return the value associated with Key key. param: key a key Returns: whether the key is contained or not - + ***********************************************************************/ final bool get (K key, ref V value) @@ -319,13 +319,13 @@ class SortedMap (K, V, alias Reap = Container.reap, Return the value of the key exactly matching the provided key or, if none, the key just after/before it based on the setting of the second argument - + param: key a key param: after indicates whether to look beyond or before the given key, where there is no exact match throws: NoSuchElementException if none found returns: a pointer to the value, or null if not present - + ***********************************************************************/ K nearbyKey (K key, bool after) @@ -342,11 +342,11 @@ class SortedMap (K, V, alias Reap = Container.reap, } /*********************************************************************** - + Return the first key of the map throws: NoSuchElementException where the map is empty - + ***********************************************************************/ K firstKey () @@ -359,11 +359,11 @@ class SortedMap (K, V, alias Reap = Container.reap, } /*********************************************************************** - + Return the last key of the map throws: NoSuchElementException where the map is empty - + ***********************************************************************/ K lastKey () @@ -377,11 +377,11 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - Return the value associated with Key key. + Return the value associated with Key key. param: key a key Returns: a pointer to the value, or null if not present - + ***********************************************************************/ final V* opIn_r (K key) @@ -398,7 +398,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n) - + ***********************************************************************/ final bool keyOf (V value, ref K key) @@ -417,7 +417,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n) - + ***********************************************************************/ final SortedMap clear () @@ -427,11 +427,11 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - Reset the SortedMap contents. This releases more memory + Reset the SortedMap contents. This releases more memory than clear() does Time complexity: O(n) - + ***********************************************************************/ final SortedMap reset () @@ -454,11 +454,11 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n - + ***********************************************************************/ final size_t remove (V value, bool all = false) - { + { size_t i = count; if (count) { @@ -478,7 +478,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n) - + ***********************************************************************/ final size_t replace (V oldElement, V newElement, bool all = false) @@ -506,7 +506,7 @@ class SortedMap (K, V, alias Reap = Container.reap, Time complexity: O(log n) Takes the value associated with the least key. - + ***********************************************************************/ final bool take (ref V v) @@ -525,7 +525,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ final bool take (K key, ref V value) @@ -548,9 +548,9 @@ class SortedMap (K, V, alias Reap = Container.reap, Time complexity: O(log n) - Returns true if inserted, false where an existing key + Returns true if inserted, false where an existing key exists and was updated instead - + ***********************************************************************/ final bool add (K key, V value) @@ -562,9 +562,9 @@ class SortedMap (K, V, alias Reap = Container.reap, Time complexity: O(log n) - Returns true if inserted, false where an existing key + Returns true if inserted, false where an existing key exists and was updated instead - + ***********************************************************************/ final bool opIndexAssign (V element, K key) @@ -593,20 +593,20 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ final bool removeKey (K key) { V value; - + return take (key, value); } /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ final bool replacePair (K key, V oldElement, V newElement) @@ -626,14 +626,14 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - Copy and return the contained set of values in an array, - using the optional dst as a recipient (which is resized + Copy and return the contained set of values in an array, + using the optional dst as a recipient (which is resized as necessary). Returns a slice of dst representing the container values. - + Time complexity: O(n) - + ***********************************************************************/ final V[] toArray (V[] dst = null) @@ -644,15 +644,15 @@ class SortedMap (K, V, alias Reap = Container.reap, size_t i = 0; foreach (k, v; this) dst[i++] = v; - return dst [0 .. count]; + return dst [0 .. count]; } /*********************************************************************** Is this container empty? - + Time complexity: O(1) - + ***********************************************************************/ final const bool isEmpty () @@ -662,7 +662,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - + ***********************************************************************/ final SortedMap check () @@ -688,10 +688,10 @@ class SortedMap (K, V, alias Reap = Container.reap, return this; } - + /*********************************************************************** - + ***********************************************************************/ private void noSuchElement (immutable(char)[] msg) @@ -702,7 +702,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ private size_t instances (V value) @@ -714,9 +714,9 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** - Returns true where an element is added, false where an + Returns true where an element is added, false where an existing key is found - + ***********************************************************************/ private final bool add_ (K key, V value, bool checkOccurrence) @@ -773,7 +773,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(n) - + ***********************************************************************/ private SortedMap clear (bool all) @@ -781,7 +781,7 @@ class SortedMap (K, V, alias Reap = Container.reap, mutate; // collect each node if we can't collect all at once - if ((heap.collect(all) is false) & count) + if ((heap.collect(all) is false) & count) { auto node = tree.leftmost; while (node) @@ -800,7 +800,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** Time complexity: O(log n) - + ***********************************************************************/ private void remove (Ref node) @@ -812,7 +812,7 @@ class SortedMap (K, V, alias Reap = Container.reap, /*********************************************************************** new element was added - + ***********************************************************************/ private void increment () @@ -820,11 +820,11 @@ class SortedMap (K, V, alias Reap = Container.reap, ++mutation; ++count; } - + /*********************************************************************** element was removed - + ***********************************************************************/ private void decrement (Ref p) @@ -834,11 +834,11 @@ class SortedMap (K, V, alias Reap = Container.reap, ++mutation; --count; } - + /*********************************************************************** set was changed - + ***********************************************************************/ private void mutate () @@ -855,7 +855,7 @@ class SortedMap (K, V, alias Reap = Container.reap, Returns: a negative number if fst is less than snd; a positive number if fst is greater than snd; else 0 - + ***********************************************************************/ private static int compareKey (ref K fst, ref K snd) @@ -876,7 +876,7 @@ class SortedMap (K, V, alias Reap = Container.reap, Returns: a negative number if fst is less than snd; a positive number if fst is greater than snd; else 0 - + ***********************************************************************/ private static int compareElem(ref V fst, ref V snd) @@ -910,7 +910,7 @@ class SortedMap (K, V, alias Reap = Container.reap, bool valid () { return owner.mutation is mutation; - } + } /*************************************************************** @@ -924,7 +924,7 @@ class SortedMap (K, V, alias Reap = Container.reap, auto n = next (k); return (n) ? v = *n, true : false; } - + /*************************************************************** Return a pointer to the next value, or null when @@ -967,7 +967,7 @@ class SortedMap (K, V, alias Reap = Container.reap, } node = n; return result; - } + } /*************************************************************** @@ -1063,7 +1063,7 @@ debug (SortedMap) auto iterator = map.iterator; while (iterator.next(k, v)) {} //iterator.remove; - + // incremental iteration, with optional failfast auto it = map.iterator; while (it.valid && it.next(k, v)) @@ -1075,15 +1075,15 @@ debug (SortedMap) // remove first element ... while (map.take(v)) Stdout.formatln ("taking {}, {} left", v, map.size); - - + + // setup for benchmark, with a set of integers. We // use a chunk allocator, and presize the bucket[] auto test = new SortedMap!(int, int, Container.reap, Container.Chunk); test.cache (1000, 500_000); const count = 500_000; StopWatch w; - + auto keys = new int[count]; foreach (ref vv; keys) vv = Kiss.instance.toInt(int.max); From 05d91ccf7ac382602d9dcfd26a1aaaf626c89ce2 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 12:36:46 +0200 Subject: [PATCH 12/18] tango/util/container/more/BitSet.d dup function changed to inout type and size function changed to const --- tango/util/container/more/BitSet.d | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tango/util/container/more/BitSet.d b/tango/util/container/more/BitSet.d index 0f70777fa..6ce9c4e68 100644 --- a/tango/util/container/more/BitSet.d +++ b/tango/util/container/more/BitSet.d @@ -18,9 +18,9 @@ private import core.bitop; /****************************************************************************** - A fixed or dynamic set of bits. Note that this does no memory - allocation of its own when Size != 0, and does heap allocation - when Size is zero. Thus you can have a fixed-size low-overhead + A fixed or dynamic set of bits. Note that this does no memory + allocation of its own when Size != 0, and does heap allocation + when Size is zero. Thus you can have a fixed-size low-overhead 'instance, or a heap oriented instance. The latter has support for resizing, whereas the former does not. @@ -28,20 +28,20 @@ private import core.bitop; ******************************************************************************/ -struct BitSet (int Count=0) -{ +struct BitSet (int Count=0) +{ private enum width = size_t.sizeof * 8; - + const bool opBinary(immutable(char)[] s : "&")(size_t i) { return and(i); } - + void opOpAssign(immutable(char)[] s : "|")(size_t i) { or(i); } - + void opOpAssign(immutable(char)[] s : "^")(size_t i) { xor(i); @@ -68,7 +68,7 @@ struct BitSet (int Count=0) /********************************************************************** - Test whether the indexed bit is enabled + Test whether the indexed bit is enabled **********************************************************************/ @@ -103,7 +103,7 @@ struct BitSet (int Count=0) bits[i / width] |= (1 << (i % width)); //bts (&bits[i / width], i % width); } - + /********************************************************************** Invert an indexed bit @@ -115,7 +115,7 @@ struct BitSet (int Count=0) bits[i / width] ^= (1 << (i % width)); //btc (&bits[i / width], i % width); } - + /********************************************************************** Clear an indexed bit @@ -139,14 +139,14 @@ struct BitSet (int Count=0) bits[] = 0; return &this; } - + /********************************************************************** Clone this BitSet and return it **********************************************************************/ - @property const BitSet dup () + @property BitSet dup () inout { BitSet x; static if (Count == 0) @@ -161,7 +161,7 @@ struct BitSet (int Count=0) **********************************************************************/ - @property const size_t size () + @property size_t size () const { return width * bits.length; } From b29c5e3b7aa1b28b38298f04f52faa3d6aace034 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:23:57 +0200 Subject: [PATCH 13/18] size function in tango/util/container/more/Vector.d is now const --- tango/util/container/more/Vector.d | 33 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tango/util/container/more/Vector.d b/tango/util/container/more/Vector.d index 6348a44b1..5f1572221 100644 --- a/tango/util/container/more/Vector.d +++ b/tango/util/container/more/Vector.d @@ -3,9 +3,9 @@ copyright: Copyright (c) 2008 Kris Bell. All rights reserved license: BSD style: $(LICENSE) - - version: Initial release: April 2008 - + + version: Initial release: April 2008 + author: Kris Since: 0.99.7 @@ -26,7 +26,7 @@ private import tango.stdc.string : memmove; ******************************************************************************/ -struct Vector (V, int Size = 0) +struct Vector (V, int Size = 0) { alias add push; alias slice opSlice; @@ -60,39 +60,39 @@ struct Vector (V, int Size = 0) } /*********************************************************************** - + Return depth of the vector ***********************************************************************/ - @property const size_t size () + @property size_t size () const { return depth; } /*********************************************************************** - + Return remaining unused slots ***********************************************************************/ - const size_t unused () + size_t unused () const { return vector.length - depth; } /*********************************************************************** - + Returns a (shallow) clone of this vector ***********************************************************************/ Vector clone () - { + { Vector v; static if (Size == 0) v.vector.length = vector.length; - + v.vector[0..depth] = vector[0..depth]; v.depth = depth; return v; @@ -115,7 +115,7 @@ struct Vector (V, int Size = 0) vector[depth++] = value; } else - { + { if (depth < vector.length) vector[depth++] = value; else @@ -241,11 +241,11 @@ struct Vector (V, int Size = 0) /********************************************************************** Return the vector as an array of values, where the first - array entry represents the oldest value. - + array entry represents the oldest value. + Doing a foreach() on the returned array will traverse in the opposite direction of foreach() upon a vector - + **********************************************************************/ V[] slice () @@ -313,7 +313,7 @@ debug (Vector) { Vector!(int, 0) v; v.add (1); - + Vector!(int, 10) s; Stdout.formatln ("add four"); @@ -348,4 +348,3 @@ debug (Vector) Stdout.formatln ("size {}", s.size); } } - From 1d1e4ba75ed0e4d1b4367f99a711321c042ffe46 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:24:58 +0200 Subject: [PATCH 14/18] size function in tango/util/container/more/Stack.d is now const --- tango/util/container/more/Stack.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tango/util/container/more/Stack.d b/tango/util/container/more/Stack.d index 4628e326b..45d31f982 100644 --- a/tango/util/container/more/Stack.d +++ b/tango/util/container/more/Stack.d @@ -74,7 +74,7 @@ struct Stack (V, int Size = 0) ***********************************************************************/ - @property size_t size () + @property size_t size () const { return depth; } From cd5bb691311ff79c496f61268506e06a0ac73749 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:26:17 +0200 Subject: [PATCH 15/18] size function in tango/util/container/more/CacheMap.d is now const --- tango/util/container/more/CacheMap.d | 107 +++++++++++++-------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/tango/util/container/more/CacheMap.d b/tango/util/container/more/CacheMap.d index d143b3b6f..c14716a51 100644 --- a/tango/util/container/more/CacheMap.d +++ b/tango/util/container/more/CacheMap.d @@ -3,9 +3,9 @@ copyright: Copyright (c) 2008 Kris Bell. All rights reserved license: BSD style: $(LICENSE) - - version: Initial release: April 2008 - + + version: Initial release: April 2008 + author: Kris Since: 0.99.7 @@ -22,26 +22,26 @@ public import tango.util.container.Container; /****************************************************************************** - CacheMap extends the basic hashmap type by adding a limit to - the number of items contained at any given time. In addition, - CacheMap sorts the cache entries such that those entries + CacheMap extends the basic hashmap type by adding a limit to + the number of items contained at any given time. In addition, + CacheMap sorts the cache entries such that those entries frequently accessed are at the head of the queue, and those - least frequently accessed are at the tail. When the queue - becomes full, old entries are dropped from the tail and are - reused to house new cache entries. + least frequently accessed are at the tail. When the queue + becomes full, old entries are dropped from the tail and are + reused to house new cache entries. In other words, it retains MRU items while dropping LRU when capacity is reached. This is great for keeping commonly accessed items around, while - limiting the amount of memory used. Typically, the queue size + limiting the amount of memory used. Typically, the queue size would be set in the thousands (via the ctor) ******************************************************************************/ -class CacheMap (K, V, alias Hash = Container.hash, - alias Reap = Container.reap, - alias Heap = Container.Collect) +class CacheMap (K, V, alias Hash = Container.hash, + alias Reap = Container.reap, + alias Heap = Container.Collect) { private alias QueuedEntry Type; private alias Type *Ref; @@ -57,10 +57,10 @@ class CacheMap (K, V, alias Hash = Container.hash, /********************************************************************** - Construct a cache with the specified maximum number of + Construct a cache with the specified maximum number of entries. Additions to the cache beyond this number will reuse the slot of the least-recently-referenced cache - entry. + entry. **********************************************************************/ @@ -87,7 +87,7 @@ class CacheMap (K, V, alias Hash = Container.hash, ***********************************************************************/ - static void reaper(K, R) (K k, R r) + static void reaper(K, R) (K k, R r) { Reap (k, r.value); } @@ -97,7 +97,7 @@ class CacheMap (K, V, alias Hash = Container.hash, ***********************************************************************/ - @property final const uint size () + @property final size_t size () const { return hash.size; } @@ -151,7 +151,7 @@ class CacheMap (K, V, alias Hash = Container.hash, Place an entry into the cache and associate it with the provided key. Note that there can be only one entry for - any particular key. If two entries are added with the + any particular key. If two entries are added with the same key, the second effectively overwrites the first. Returns true if we added a new entry; false if we just @@ -171,14 +171,14 @@ class CacheMap (K, V, alias Hash = Container.hash, return false; } - // create a new entry at the list head + // create a new entry at the list head addEntry (key, value); return true; } /********************************************************************** - Remove the cache entry associated with the provided key. + Remove the cache entry associated with the provided key. Returns false if there is no such entry. **********************************************************************/ @@ -192,7 +192,7 @@ class CacheMap (K, V, alias Hash = Container.hash, /********************************************************************** - Remove (and return) the cache entry associated with the + Remove (and return) the cache entry associated with the provided key. Returns false if there is no such entry. **********************************************************************/ @@ -263,7 +263,7 @@ class CacheMap (K, V, alias Hash = Container.hash, Add an entry into the queue. If the queue is full, the least-recently-referenced entry is reused for the new - addition. + addition. **********************************************************************/ @@ -287,98 +287,98 @@ class CacheMap (K, V, alias Hash = Container.hash, } /********************************************************************** - - A doubly-linked list entry, used as a wrapper for queued + + A doubly-linked list entry, used as a wrapper for queued cache entries - + **********************************************************************/ - + private struct QueuedEntry { private K key; private Ref prev, next; private V value; - + /************************************************************** - - Set this linked-list entry with the given arguments. + + Set this linked-list entry with the given arguments. **************************************************************/ - + Ref set (K key, V value) { this.value = value; this.key = key; return &this; } - + /************************************************************** - - Insert this entry into the linked-list just in + + Insert this entry into the linked-list just in front of the given entry. - + **************************************************************/ - + Ref prepend (Ref before) { if (before) { prev = before.prev; - + // patch 'prev' to point at me if (prev) prev.next = &this; - + //patch 'before' to point at me next = before; before.prev = &this; } return &this; } - + /************************************************************** - - Add this entry into the linked-list just after + + Add this entry into the linked-list just after the given entry. - + **************************************************************/ - + Ref append (Ref after) { if (after) { next = after.next; - + // patch 'next' to point at me if (next) next.prev = &this; - + //patch 'after' to point at me prev = after; after.next = &this; } return &this; } - + /************************************************************** - - Remove this entry from the linked-list. The - previous and next entries are patched together + + Remove this entry from the linked-list. The + previous and next entries are patched together appropriately. - + **************************************************************/ - + Ref extract () { // make 'prev' and 'next' entries see each other if (prev) prev.next = next; - + if (next) next.prev = prev; - - // Murphy's law + + // Murphy's law next = prev = null; return &this; } @@ -452,4 +452,3 @@ debug (CacheMap) test.hash.check; } } - From 56916a5d7f44ec82322152b59e14b7ebbe91d5cc Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:28:27 +0200 Subject: [PATCH 16/18] tango/util/container/more/StackMap.d StackMap is dynamically resizable instead of fixed size --- tango/util/container/more/StackMap.d | 369 ++++++++++++++++++++++----- 1 file changed, 306 insertions(+), 63 deletions(-) diff --git a/tango/util/container/more/StackMap.d b/tango/util/container/more/StackMap.d index 54c1cc2cd..9618c1b72 100644 --- a/tango/util/container/more/StackMap.d +++ b/tango/util/container/more/StackMap.d @@ -3,13 +3,17 @@ copyright: Copyright (c) 2008 Kris Bell. All rights reserved license: BSD style: $(LICENSE) - - version: Initial release: April 2008 - + + version: Initial release: April 2008 + author: Kris Since: 0.99.7 + Modified version: Carsten Bleser Rasmussen + Stack map is now able to grow in size. + + *******************************************************************************/ module tango.util.container.more.StackMap; @@ -18,28 +22,32 @@ private import tango.stdc.stdlib; private import tango.util.container.HashMap; +private import tango.util.MinMax; + +private import tango.core.Exception; + public import tango.util.container.Container; /****************************************************************************** - StackMap extends the basic hashmap type by adding a limit to - the number of items contained at any given time. In addition, + StackMap extends the basic hashmap type by adding a limit to + the number of items contained at any given time. In addition, StackMap retains the order in which elements were added, and employs that during foreach() traversal. Additions to the map beyond the capacity will result in an exception being thrown. You can push and pop things just like an typical stack, and/or - traverse the entries in the order they were added, though with + traverse the entries in the order they were added, though with the additional capability of retrieving and/or removing by key. - Note also that a push/add operation will replace an existing + Note also that a push/add operation will replace an existing entry with the same key, exposing a twist on the stack notion. ******************************************************************************/ -class StackMap (K, V, alias Hash = Container.hash, - alias Reap = Container.reap, - alias Heap = Container.Collect) +class StackMap (K, V, alias Hash = Container.hash, + alias Reap = Container.reap, + alias Heap = Container.Collect) { private alias QueuedEntry Type; private alias Type *Ref; @@ -52,23 +60,44 @@ class StackMap (K, V, alias Hash = Container.hash, tail, start; // dimension of queue - private size_t capacity; + private size_t capacity; + + // Table of links + private alias Type[]* RefTypes; + private RefTypes[] tables; + size_t delegate(size_t oldsize) grow_to; + + size_t fixed(size_t size) { + return size; + } + + size_t dynamic(size_t size) { + if (size < 0x400) { + return size<<1; + } else { + return size+0x400; + } + } + /********************************************************************** - Construct a cache with the specified maximum number of + Construct a cache with the specified maximum number of entries. Additions to the cache beyond this number will throw an exception **********************************************************************/ - this (size_t capacity) + this (size_t capacity, size_t delegate(size_t oldsize) grow) { + grow_to=grow; hash = new Map; this.capacity = capacity; hash.buckets (capacity, 0.75); //links = (cast(Ref) calloc(capacity, Type.sizeof))[0..capacity]; links.length = capacity; + tables.length=1; + tables[0]=&links; // create empty list head = tail = &links[0]; @@ -80,10 +109,18 @@ class StackMap (K, V, alias Hash = Container.hash, } } + this ( size_t capacity=128, bool growable=true) { + if (growable) { + this(capacity, &dynamic); + } else { + this(capacity, &fixed); + } + } + /*********************************************************************** clean up when done - + ***********************************************************************/ ~this () @@ -97,7 +134,7 @@ class StackMap (K, V, alias Hash = Container.hash, ***********************************************************************/ - static void reaper(K, R) (K k, R r) + static void reaper(K, R) (K k, R r) { Reap (k, r.value); } @@ -107,11 +144,13 @@ class StackMap (K, V, alias Hash = Container.hash, ***********************************************************************/ - @property final const size_t size () + @property final size_t size () const { return hash.size; } + alias size length; + /*********************************************************************** @@ -127,7 +166,7 @@ class StackMap (K, V, alias Hash = Container.hash, Place an entry into the cache and associate it with the provided key. Note that there can be only one entry for - any particular key. If two entries are added with the + any particular key. If two entries are added with the same key, the second effectively overwrites the first. Returns true if we added a new entry; false if we just @@ -180,7 +219,7 @@ class StackMap (K, V, alias Hash = Container.hash, ***********************************************************************/ - final int opApply (scope int delegate(ref K key, ref V value) dg) + final int opApply (int delegate(ref K key, ref V value) dg) { K key; V value; @@ -202,7 +241,7 @@ class StackMap (K, V, alias Hash = Container.hash, Place an entry into the cache and associate it with the provided key. Note that there can be only one entry for - any particular key. If two entries are added with the + any particular key. If two entries are added with the same key, the second effectively overwrites the first. Returns true if we added a new entry; false if we just @@ -223,7 +262,7 @@ class StackMap (K, V, alias Hash = Container.hash, return false; } - // create a new entry at the list head + // create a new entry at the list head entry = addEntry (key, value); if (start is null) start = entry; @@ -248,9 +287,49 @@ class StackMap (K, V, alias Hash = Container.hash, return false; } + V[] toArray() { + auto result=new V[hash.size]; + size_t i=hash.size; + foreach(r;hash.toArray) { + result[--i]=r.value; + } + return result; + } + + V opIndex(K key) { + Ref entry=null; + V result; + if (hash.get(key, entry) ) { + result=entry.value; + } + return result; + } + + V opAssignIndex(K key, V value) { + add(key, value); + return value; + } + + + V* opIn_r(K key) { + V* result; + if (auto getv=(key in hash) ) { + result=&((*getv).value); + } + return result; + } + + StackMap dup() { + auto result=new StackMap!(K,V)(size); + foreach(k,v;this) { + result.add(k,v); + } + return result; + } + /********************************************************************** - Remove (and return) the cache entry associated with the + Remove (and return) the cache entry associated with the provided key. Returns false if there is no such entry. **********************************************************************/ @@ -264,7 +343,7 @@ class StackMap (K, V, alias Hash = Container.hash, if (entry is start) start = entry.prev; - + // don't actually kill the list entry -- just place // it at the list 'tail' ready for subsequent reuse deReference (entry); @@ -276,6 +355,63 @@ class StackMap (K, V, alias Hash = Container.hash, return false; } + /********************************************************************** + + Same as size() but more D like name of array length. + + **********************************************************************/ + + public size_t length() { + return hash.size; + } + + /********************************************************************** + + This function set the length of the StackMap. + If the size is less than the length the Stack is truncated + and hash element is the index higher than length-1 is removed + + **********************************************************************/ + + + /********************************************************************** + + This function is the same as length(size_t) except that the + StackMap is only truncated if truncate is true. + + **********************************************************************/ + + public size_t grow( size_t newsize ) + { + if ( newsize<=capacity ) { + return capacity; + } + size_t growby=newsize-capacity; + tables.length=tables.length+1; + Type[] growlinks=new Type[growby]; + tables[$-1]=&growlinks; + + // create new addtional empty list + foreach (ref link; growlinks) + { + link.prev = tail; + tail.next = &link; + tail = &link; + } + capacity=newsize; + return capacity; + } + + public bool peek( size_t index, ref K key, ref V value) { + if (indexcapacity) { + capacity=grow(newcapacity); + return addEntry(key, value); + } else { + throw new Exception ("Full"); + } } /********************************************************************** - - A doubly-linked list entry, used as a wrapper for queued - cache entries. - + + A doubly-linked list entry, used as a wrapper for queued + cache entries. + **********************************************************************/ - + private struct QueuedEntry { private K key; private Ref prev, next; private V value; - + /************************************************************** - - Set this linked-list entry with the given arguments. + + Set this linked-list entry with the given arguments. **************************************************************/ - + Ref set (K key, V value) { this.value = value; this.key = key; return &this; } - + /************************************************************** - - Insert this entry into the linked-list just in + + Insert this entry into the linked-list just in front of the given entry. - + **************************************************************/ - + Ref prepend (Ref before) { if (before) { prev = before.prev; - + // patch 'prev' to point at me if (prev) prev.next = &this; - + //patch 'before' to point at me next = before; before.prev = &this; } return &this; } - + /************************************************************** - - Add this entry into the linked-list just after + + Add this entry into the linked-list just after the given entry. - + **************************************************************/ - + Ref append (Ref after) { if (after) { next = after.next; - + // patch 'next' to point at me if (next) next.prev = &this; - + //patch 'after' to point at me prev = after; after.next = &this; } return &this; } - + /************************************************************** - - Remove this entry from the linked-list. The - previous and next entries are patched together + + Remove this entry from the linked-list. The + previous and next entries are patched together appropriately. - + **************************************************************/ - + Ref extract () { // make 'prev' and 'next' entries see each other if (prev) prev.next = next; - + if (next) next.prev = prev; - - // Murphy's law + + // Murphy's law next = prev = null; return &this; } } + +debug (UnitTest) + { + import tango.io.Stdout; + import tango.text.convert.Format; + + private struct Element(K, V) { + K k; + V v; + static Element opCall(K key, V value) { + Element result; + result.k=key; result.v=value; + return result; + } + } + + unittest { + { + alias Element!(char[], int) E_t; + auto map = new StackMap!(char[], int)(3); + E_t[7] table; + assert(map.capacity==3); + map.add ("foo", 1); table[0]=E_t("foo", 1); + map.add ("bar", 2); table[1]=E_t("bar", 2); + map.add ("wumpus", 3); table[2]=E_t("wumpus", 3); + /* grow test */ + map.add("puswum", 4); table[3]=E_t("puswum", 4); + assert(map.capacity==6); + map.add("foobar", 5); table[4]=E_t("foobar", 5); + map.add("barfoo", 6); table[5]=E_t("barfoo", 6); + /* grow again */ + map.add("again", 7); table[6]=E_t("again", 7); + assert(map.capacity==12); + + size_t i=0; + int v; + char[] key; int value; + foreach (k, v; map) { + i=v-1; + assert(k==table[i].k, Format("Key mismatch map.key={} table.key={}, index={}", k, table[i].k,i)); + assert(v==table[i].v, Format("Value mismatch map.value={} table.value={}, index={}", v, table[i].v,i)); + // i++; + } + + i=0; + map.popTail(key, value); + foreach (k, v; map) { + i=v-1; + assert(k==table[i].k, Format("Key mismatch map.key={} table.key={}, index={}", k, table[i].k,i)); + assert(v==table[i].v, Format("Value mismatch map.value={} table.value={}, index={}", v, table[i].v,i)); + } + + + map.popHead(key, value); + // Stdout.format("key={} value={}",key,value).nl; + foreach (k, v; map) { + i=v-1; + assert(k==table[i].k, Format("Key mismatch map.key={} table.key={}, index={}", k, table[i].k,i)); + assert(v==table[i].v, Format("Value mismatch map.value={} table.value={}, index={}", v, table[i].v,i)); + } + + i=0; + map.popTail(key, value); + map.popHead(key, value); + + foreach (k, v; map) { + i=v-1; + assert(k==table[i].k, Format("Key mismatch map.key={} table.key={}, index={}", k, table[i].k,i)); + assert(v==table[i].v, Format("Value mismatch map.value={} table.value={}, index={}", v, table[i].v,i)); + i++; + } + + assert("puswum" in map); + + foreach (k, v; map) { + i=v-1; + assert(k==table[i].k, Format("Key mismatch map.key={} table.key={}, index={}", k, table[i].k,i)); + assert(v==table[i].v, Format("Value mismatch map.value={} table.value={}, index={}", v, table[i].v,i)); + } + } + + } + } + + } @@ -442,8 +668,7 @@ class StackMap (K, V, alias Hash = Container.hash, *******************************************************************************/ -debug (StackMap) -{ +version (StackMapMain) { import tango.io.Stdout; import tango.core.Memory; import tango.time.StopWatch; @@ -500,6 +725,24 @@ debug (StackMap) w.start; foreach (key, value; test) {} Stdout.formatln ("{} element iteration: {}/s", test.size, test.size/w.stop); + // setup for benchmark, with a cache of integers + auto test2 = new StackMap!(int, int, Container.hash, Container.reap, Container.Chunk) (100,true); + + // benchmark adding + w.start; + for (int i=count; i--;) + test2.add (i, i); + Stdout.formatln ("{} adds: {}/s", count, count/w.stop); + + // benchmark reading + w.start; + for (int i=count; i--;) + test2.get (i, v); + Stdout.formatln ("{} lookups: {}/s", count, count/w.stop); + + // benchmark iteration + w.start; + foreach (key, value; test2) {} + Stdout.formatln ("{} element iteration: {}/s", test.size, test.size/w.stop); } } - From 05878d50d64ca677eda213d36b64764a3ec69a6a Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:51:47 +0200 Subject: [PATCH 17/18] size function in tango/util/container/HashMap.d is now const --- tango/util/container/HashMap.d | 178 ++++++++++++++++----------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/tango/util/container/HashMap.d b/tango/util/container/HashMap.d index 5bbdfe095..7a0fedfa3 100644 --- a/tango/util/container/HashMap.d +++ b/tango/util/container/HashMap.d @@ -65,9 +65,9 @@ private import tango.core.Exception : NoSuchElementException; *******************************************************************************/ -class HashMap (K, V, alias Hash = Container.hash, - alias Reap = Container.reap, - alias Heap = Container.DefaultCollect) +class HashMap (K, V, alias Hash = Container.hash, + alias Reap = Container.reap, + alias Heap = Container.DefaultCollect) : IContainer!(V) { // bucket types @@ -83,7 +83,7 @@ class HashMap (K, V, alias Hash = Container.hash, // each table entry is a linked list, or null private Ref table[]; - + // number of elements contained private size_t count; @@ -92,7 +92,7 @@ class HashMap (K, V, alias Hash = Container.hash, // configured heap manager private Alloc heap; - + // mutation tag updates on each change private size_t mutation; @@ -121,7 +121,7 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Return a generic iterator for contained elements - + ***********************************************************************/ final Iterator iterator () @@ -158,23 +158,23 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Return the number of elements contained - + ***********************************************************************/ - @property final const size_t size () + @property final size_t size () const { return count; } - + /*********************************************************************** Add a new element to the set. Does not add if there is an equivalent already present. Returns true where an element is added, false where it already exists (and was possibly updated). - + Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ final bool add (K key, V element) @@ -184,7 +184,7 @@ class HashMap (K, V, alias Hash = Container.hash, auto hd = &table [Hash (key, table.length)]; auto node = *hd; - + if (node is null) { *hd = heap.allocate.set (key, element, null); @@ -208,7 +208,7 @@ class HashMap (K, V, alias Hash = Container.hash, increment; // we only check load factor on add to nonempty bin - checkLoad; + checkLoad; } } return true; @@ -222,9 +222,9 @@ class HashMap (K, V, alias Hash = Container.hash, updated). This variation invokes the given retain function when the key does not already exist. You would typically use that to duplicate a char[], or whatever is required. - + Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ final bool add (K key, V element, K function(K) retain) @@ -234,7 +234,7 @@ class HashMap (K, V, alias Hash = Container.hash, auto hd = &table [Hash (key, table.length)]; auto node = *hd; - + if (node is null) { *hd = heap.allocate.set (retain(key), element, null); @@ -258,7 +258,7 @@ class HashMap (K, V, alias Hash = Container.hash, increment; // we only check load factor on add to nonempty bin - checkLoad; + checkLoad; } } return true; @@ -271,7 +271,7 @@ class HashMap (K, V, alias Hash = Container.hash, param: a key param: a value reference (where returned value will reside) Returns: whether the key is contained or not - + ************************************************************************/ final bool get (K key, ref V element) @@ -294,10 +294,10 @@ class HashMap (K, V, alias Hash = Container.hash, param: a key Returns: a pointer to the located value, or null if not found - + ************************************************************************/ - final V* opIn_r (K key) + final V* opIn_r (inout(K) key) { if (count) { @@ -311,9 +311,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Does this set contain the given element? - + Time complexity: O(1) average; O(n) worst - + ***********************************************************************/ final bool contains (V element) @@ -324,9 +324,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(n). - + ************************************************************************/ - + final bool keyOf (V value, ref K key) { if (count) @@ -346,9 +346,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ - + final bool containsKey (K key) { if (count) @@ -363,13 +363,13 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ - + final bool containsPair (K key, V element) { if (count) - { + { auto p = table[Hash (key, table.length)]; if (p && p.findPair (key, element)) return true; @@ -381,9 +381,9 @@ class HashMap (K, V, alias Hash = Container.hash, Make an independent copy of the container. Does not clone elements - + Time complexity: O(n) - + ***********************************************************************/ @property final HashMap dup () @@ -403,9 +403,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ - + final bool removeKey (K key) { V value; @@ -416,9 +416,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ - + final bool replaceKey (K key, K replace) { if (count) @@ -437,7 +437,7 @@ class HashMap (K, V, alias Hash = Container.hash, table[h] = n; else trail.detachNext; - + // inject into new location h = Hash (replace, table.length); table[h] = p.set (replace, p.value, table[h]); @@ -456,9 +456,9 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Time complexity: O(1) average; O(n) worst. - + ***********************************************************************/ - + final bool replacePair (K key, V oldElement, V newElement) { if (count) @@ -482,7 +482,7 @@ class HashMap (K, V, alias Hash = Container.hash, Remove and expose the first element. Returns false when no more elements are contained - + Time complexity: O(n) ***********************************************************************/ @@ -509,11 +509,11 @@ class HashMap (K, V, alias Hash = Container.hash, param: a key param: a value reference (where returned value will reside) Returns: whether the key is contained or not - + Time complexity: O(1) average, O(n) worst ***********************************************************************/ - + final bool take (K key, ref V value) { if (count) @@ -528,7 +528,7 @@ class HashMap (K, V, alias Hash = Container.hash, value = n.value; decrement (n); return true; - } + } else p = &n.next; } @@ -564,7 +564,7 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** - Remove a set of values + Remove a set of values ************************************************************************/ @@ -580,23 +580,23 @@ class HashMap (K, V, alias Hash = Container.hash, Removes element instances, and returns the number of elements removed - + Time complexity: O(1) average; O(n) worst - + ************************************************************************/ final size_t remove (V element, bool all = false) { auto i = count; - + if (i) foreach (ref node; table) - { + { auto p = node; auto trail = node; while (p) - { + { auto n = p.next; if (element == p.value) { @@ -631,13 +631,13 @@ class HashMap (K, V, alias Hash = Container.hash, the number of replacements Time complexity: O(n). - + ************************************************************************/ final size_t replace (V oldElement, V newElement, bool all = false) { size_t i; - + if (count && oldElement != newElement) foreach (node; table) while (node && (node = node.find(oldElement)) !is null) @@ -650,7 +650,7 @@ class HashMap (K, V, alias Hash = Container.hash, } return i; } - + /*********************************************************************** Clears the HashMap contents. Various attributes are @@ -658,7 +658,7 @@ class HashMap (K, V, alias Hash = Container.hash, reset() to drop everything. Time complexity: O(n) - + ***********************************************************************/ final HashMap clear () @@ -668,11 +668,11 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** - Reset the HashMap contents. This releases more memory + Reset the HashMap contents. This releases more memory than clear() does Time complexity: O(n) - + ***********************************************************************/ final HashMap reset () @@ -698,11 +698,11 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** - Set the desired number of buckets in the hash table. Any + Set the desired number of buckets in the hash table. Any value greater than or equal to one is OK. If different than current buckets, causes a version change - + Time complexity: O(n) ***********************************************************************/ @@ -721,7 +721,7 @@ class HashMap (K, V, alias Hash = Container.hash, Set the number of buckets for the given threshold and resize as required - + Time complexity: O(n) ***********************************************************************/ @@ -737,7 +737,7 @@ class HashMap (K, V, alias Hash = Container.hash, Configure the assigned allocator with the size of each allocation block (number of nodes allocated at one time) and the number of nodes to pre-populate the cache with. - + Time complexity: O(n) ***********************************************************************/ @@ -767,12 +767,12 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** Set the resize threshold, and resize as required - Set the current desired load factor. Any value greater - than 0 is OK. The current load is checked against it, + Set the current desired load factor. Any value greater + than 0 is OK. The current load is checked against it, possibly causing a resize. - + Time complexity: O(n) - + ***********************************************************************/ final void threshold (float desired) @@ -785,14 +785,14 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** - Copy and return the contained set of values in an array, - using the optional dst as a recipient (which is resized + Copy and return the contained set of values in an array, + using the optional dst as a recipient (which is resized as necessary). Returns a slice of dst representing the container values. - + Time complexity: O(n) - + ***********************************************************************/ final V[] toArray (V[] dst = null) @@ -803,15 +803,15 @@ class HashMap (K, V, alias Hash = Container.hash, size_t i = 0; foreach (k, v; this) dst[i++] = v; - return dst [0 .. count]; + return dst [0 .. count]; } /*********************************************************************** Is this container empty? - + Time complexity: O(1) - + ***********************************************************************/ final const bool isEmpty () @@ -824,7 +824,7 @@ class HashMap (K, V, alias Hash = Container.hash, Sanity check ***********************************************************************/ - + final HashMap check () { assert(!(table is null && count !is 0)); @@ -853,9 +853,9 @@ class HashMap (K, V, alias Hash = Container.hash, Count the element instances in the set (there can only be 0 or 1 instances in a Set). - + Time complexity: O(n) - + ***********************************************************************/ private size_t instances (V element) @@ -871,7 +871,7 @@ class HashMap (K, V, alias Hash = Container.hash, Check to see if we are past load factor threshold. If so, resize so that we are at half of the desired threshold. - + ***********************************************************************/ private HashMap checkLoad () @@ -886,7 +886,7 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** resize table to new capacity, rehashing all elements - + ***********************************************************************/ private void resize (size_t newCap) @@ -920,7 +920,7 @@ class HashMap (K, V, alias Hash = Container.hash, the per-node memory than to gain a little on each remove Used by iterators only - + ***********************************************************************/ private bool removeNode (Ref node, Ref* list) @@ -934,7 +934,7 @@ class HashMap (K, V, alias Hash = Container.hash, *p = n.next; decrement (n); return true; - } + } else p = &n.next; return false; @@ -947,7 +947,7 @@ class HashMap (K, V, alias Hash = Container.hash, reset() to drop everything. Time complexity: O(n) - + ***********************************************************************/ private final HashMap clear (bool all) @@ -975,7 +975,7 @@ class HashMap (K, V, alias Hash = Container.hash, /*********************************************************************** new element was added - + ***********************************************************************/ private void increment () @@ -983,11 +983,11 @@ class HashMap (K, V, alias Hash = Container.hash, ++mutation; ++count; } - + /*********************************************************************** element was removed - + ***********************************************************************/ private void decrement (Ref p) @@ -997,11 +997,11 @@ class HashMap (K, V, alias Hash = Container.hash, ++mutation; --count; } - + /*********************************************************************** set was changed - + ***********************************************************************/ private void mutate () @@ -1033,7 +1033,7 @@ class HashMap (K, V, alias Hash = Container.hash, bool valid () { return owner.mutation is mutation; - } + } /*************************************************************** @@ -1047,7 +1047,7 @@ class HashMap (K, V, alias Hash = Container.hash, auto n = next (k); return (n) ? v = *n, true : false; } - + /*************************************************************** Return a pointer to the next value, or null when @@ -1062,7 +1062,7 @@ class HashMap (K, V, alias Hash = Container.hash, cell = table [row++]; else return null; - + prior = cell; k = cell.key; cell = cell.next; @@ -1088,7 +1088,7 @@ class HashMap (K, V, alias Hash = Container.hash, c = table [row++]; else break loop; - + prior = c; c = c.next; if ((result = dg(prior.key, prior.value)) != 0) @@ -1097,7 +1097,7 @@ class HashMap (K, V, alias Hash = Container.hash, cell = c; return result; - } + } /*************************************************************** @@ -1159,7 +1159,7 @@ debug (HashMap) auto iterator = map.iterator; while (iterator.next(k, v)) {} //iterator.remove; - + // incremental iteration, with optional failfast auto it = map.iterator; while (it.valid && it.next(k, v)) @@ -1171,7 +1171,7 @@ debug (HashMap) // remove first element ... while (map.take(v)) Stdout.formatln ("taking {}, {} left", v, map.size); - + // setup for benchmark, with a set of integers. We // use a chunk allocator, and presize the bucket[] auto test = new HashMap!(int, int);//, Container.hash, Container.reap, Container.ChunkGC); From fb98d45565726ea45b42b8a25bb06a61b67ede87 Mon Sep 17 00:00:00 2001 From: udefranettet Date: Tue, 28 Apr 2015 13:53:37 +0200 Subject: [PATCH 18/18] tango/util/container/LinkedList.d Some member function has change to const and LinkedList now support. opAssignIndex and opIndex --- tango/util/container/LinkedList.d | 84 +++++++++++++++++-------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/tango/util/container/LinkedList.d b/tango/util/container/LinkedList.d index e13c2fdf1..76e44feb6 100644 --- a/tango/util/container/LinkedList.d +++ b/tango/util/container/LinkedList.d @@ -72,13 +72,13 @@ private import tango.util.container.model.IContainer; *******************************************************************************/ -class LinkedList (V, alias Reap = Container.reap, - alias Heap = Container.DefaultCollect) +class LinkedList (V, alias Reap = Container.reap, + alias Heap = Container.DefaultCollect) : IContainer!(V) { // use this type for Allocator configuration private alias Slink!(V) Type; - + private alias Type* Ref; private alias V* VRef; @@ -89,7 +89,7 @@ class LinkedList (V, alias Reap = Container.reap, // configured heap manager private Alloc heap; - + // mutation tag updates on each change private size_t mutation; @@ -133,7 +133,7 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** Return a generic iterator for contained elements - + ***********************************************************************/ final Iterator iterator () @@ -151,7 +151,7 @@ class LinkedList (V, alias Reap = Container.reap, Configure the assigned allocator with the size of each allocation block (number of nodes allocated at one time) and the number of nodes to pre-populate the cache with. - + Time complexity: O(n) ***********************************************************************/ @@ -175,10 +175,10 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** Return the number of elements contained - + ***********************************************************************/ - @property final const size_t size () + @property final size_t size () const { return count; } @@ -237,11 +237,18 @@ class LinkedList (V, alias Reap = Container.reap, ***********************************************************************/ - final V get (size_t index) + final inout(V) get (size_t index) inout { return cellAt(index).value; } + alias get opIndex; + void opIndexAssign(V val, size_t index) { + addAt(index, val); + } + + alias size length; + /*********************************************************************** Time complexity: O(n) @@ -309,7 +316,7 @@ class LinkedList (V, alias Reap = Container.reap, { auto p = cellAt (from); auto current = newlist = heap.allocate.set (p.value, null); - + for (auto i = 1; i < length; ++i) if ((p = p.next) is null) length = i; @@ -337,12 +344,12 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** Reset the HashMap contents and optionally configure a new - heap manager. We cannot guarantee to clean up reconfigured + heap manager. We cannot guarantee to clean up reconfigured allocators, so be sure to invoke reset() before discarding this class Time complexity: O(n) - + ***********************************************************************/ final LinkedList reset () @@ -351,7 +358,7 @@ class LinkedList (V, alias Reap = Container.reap, } /*********************************************************************** - + Takes the first value on the list Time complexity: O(1) @@ -701,14 +708,14 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** - Copy and return the contained set of values in an array, - using the optional dst as a recipient (which is resized + Copy and return the contained set of values in an array, + using the optional dst as a recipient (which is resized as necessary). Returns a slice of dst representing the container values. - + Time complexity: O(n) - + ***********************************************************************/ final V[] toArray (V[] dst = null) @@ -719,15 +726,15 @@ class LinkedList (V, alias Reap = Container.reap, size_t i = 0; foreach (v; this) dst[i++] = v; - return dst [0 .. count]; + return dst [0 .. count]; } /*********************************************************************** Is this container empty? - + Time complexity: O(1) - + ***********************************************************************/ final const bool isEmpty () @@ -793,7 +800,7 @@ class LinkedList (V, alias Reap = Container.reap, ***********************************************************************/ - private Ref cellAt (size_t index) + private inout(Ref) cellAt (size_t index) inout { checkIndex (index); return list.nth (index); @@ -803,7 +810,7 @@ class LinkedList (V, alias Reap = Container.reap, ***********************************************************************/ - private void checkIndex (size_t index) + private void checkIndex (size_t index) const { if (index >= count) throw new Exception ("out of range"); @@ -811,7 +818,7 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** - Splice elements of e between hd and tl. If hd + Splice elements of e between hd and tl. If hd is null return new hd Returns the count of new elements added @@ -867,7 +874,7 @@ class LinkedList (V, alias Reap = Container.reap, p = n; } } - + list = null; count = 0; return this; @@ -876,7 +883,7 @@ class LinkedList (V, alias Reap = Container.reap, /*********************************************************************** new element was added - + ***********************************************************************/ private void increment () @@ -884,11 +891,11 @@ class LinkedList (V, alias Reap = Container.reap, ++mutation; ++count; } - + /*********************************************************************** element was removed - + ***********************************************************************/ private void decrement (Ref p) @@ -898,11 +905,11 @@ class LinkedList (V, alias Reap = Container.reap, ++mutation; --count; } - + /*********************************************************************** set was changed - + ***********************************************************************/ private void mutate () @@ -933,7 +940,7 @@ class LinkedList (V, alias Reap = Container.reap, bool valid () { return owner.mutation is mutation; - } + } /*************************************************************** @@ -947,7 +954,7 @@ class LinkedList (V, alias Reap = Container.reap, auto n = next; return (n) ? v = *n, true : false; } - + /*************************************************************** Return a pointer to the next value, or null when @@ -1037,7 +1044,7 @@ class LinkedList (V, alias Reap = Container.reap, } node = n; return result; - } + } /*************************************************************** @@ -1087,7 +1094,7 @@ debug (LinkedList) foreach (value; set) Stdout (value).newline; - // explicit generic iteration + // explicit generic iteration foreach (value; set.iterator) Stdout.formatln ("{}", value); @@ -1110,7 +1117,7 @@ debug (LinkedList) auto iterator = set.iterator; while (iterator.next(v)) {} //iterator.remove; - + // incremental iteration, with optional failfast auto it = set.iterator; while (it.valid && it.next(v)) @@ -1122,8 +1129,8 @@ debug (LinkedList) // remove first element ... while (set.take(v)) Stdout.formatln ("taking {}, {} left", v, set.size); - - + + // setup for benchmark, with a set of integers. We // use a chunk allocator, and presize the bucket[] auto test = new LinkedList!(int, Container.reap, Container.Chunk); @@ -1163,11 +1170,10 @@ debug (LinkedList) // benchmark iteration - w.start; - foreach (ref iii; test) {} + w.start; + foreach (ref iii; test) {} Stdout.formatln ("{} pointer iteration: {}/s", test.size, test.size/w.stop); test.check; } } -