Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of https://github.com/D-Programming-Language/ph…

  • Loading branch information...
commit c9be051fcfdb3e02145c5db8d04dfedf2c6150c2 2 parents b75a7c9 + 7182ed4
Matthias Walter authored
Showing with 4,703 additions and 917 deletions.
  1. +18 −5 changelog.dd
  2. +0 −2  crc32.d
  3. +5 −7 posix.mak
  4. +147 −102 std/algorithm.d
  5. +3 −3 std/array.d
  6. +35 −7 std/bigint.d
  7. +119 −135 std/complex.d
  8. +635 −12 std/container.d
  9. +25 −32 std/conv.d
  10. +6 −1 std/cpuid.d
  11. +4 −4 std/datetime.d
  12. +0 −11 std/encoding.d
  13. +1 −1  std/exception.d
  14. +3 −3 std/file.d
  15. +39 −23 std/format.d
  16. +0 −128 std/hash/crc32.d
  17. +6 −4 std/internal/math/biguintcore.d
  18. +54 −17 std/internal/uni.d
  19. +31 −4 std/json.d
  20. +7 −1 std/math.d
  21. +0 −9 std/metastrings.d
  22. +2 −2 std/mmfile.d
  23. +2 −2 std/parallelism.d
  24. +1 −1  std/path.d
  25. +2 −1  std/perf.d
  26. +208 −27 std/random.d
  27. +813 −15 std/range.d
  28. +203 −18 std/signals.d
  29. +13 −21 std/socket.d
  30. +6 −6 std/stdio.d
  31. +9 −9 std/stream.d
  32. +361 −92 std/string.d
  33. +220 −9 std/traits.d
  34. +3 −150 std/typecons.d
  35. +88 −3 std/utf.d
  36. +1,581 −0 std/uuid.d
  37. +1 −1  std/variant.d
  38. +26 −26 std/xml.d
  39. +2 −1  unittest.d
  40. +24 −22 win32.mak
View
23 changelog.dd
@@ -1,20 +1,28 @@
$(VERSION 060, ddd mm, 2012, =================================================,
$(WHATSNEW
+ $(LI std.string: $(RED The current implementations of std.string.format and string.sformat are
+ scheduled to be replaced in November 2012 with improved implementations
+ which conform to writef. In some, rare cases, this will break code.
+ Please see the documentation for std.string.format and std.string.sformat for details.))
+ $(LI std.bitmanip: Added peek, read, write, and append for converting
+ ranges of bytes to and from integral types.)
$(LI Added std.file.tempDir which returns the path to a directory
where a program can put temporary files.)
$(LI std.process: Added escapeShellCommand, escapeShellFileName, and
escapeWindowsArgument. Documented browse function.)
- $(LI std.string: Added xformat and xsformat, they are compatible with writef.)
- $(LI Capitalized std.traits.pointerTarget to PointerTarget. Old one is
- scheduled for deprecation.)
+ $(LI std.range: Added RefRange, which effectively makes it possible to
+ pass a range by reference.)
$(LI std.traits: Added KeyType, ValueType, isScalarType, isBasicType, and
SetFunctionAttributes templates.)
- $(LI std.bitmanip: Added peek, read, write, and append for converting
- ranges of bytes to and from integral types.)
+ $(LI std.utf: Added overload of codeLength which operates on a string.)
+ $(LI Capitalized std.traits.pointerTarget to PointerTarget. Old one is
+ scheduled for deprecation.)
$(LI The overloads of std.conv.to which were scheduled for deprecation
because formattedWrite replaced them have now been deprecated.
Please use std.format.formattedWrite instead.)
+ $(LI UtfException - which was scheduled for deprecation - has been deprecated.
+ Please use UTFException instead.)
$(LI The deprecated overloads of std.array.insert and std.array.replace
have been removed. Please use insertInPlace and replaceInPlace instead.)
$(LI The deprecated toISOExtendedString and fromISOExtendedString
@@ -54,6 +62,7 @@ $(VERSION 060, ddd mm, 2012, =================================================,
$(LI $(BUGZILLA 7919): Sample code works on GDC but fails with DMD)
$(LI $(BUGZILLA 7937): Range iota.Result should be const where possible)
$(LI $(BUGZILLA 7944): std.range.iota.popFront() cycles when the range is empty)
+ $(LI $(BUGZILLA 7948): std.range.zip broken with requireSameLength)
$(LI $(BUGZILLA 7962): std.regex: Captures.length() returns incorrect value)
$(LI $(BUGZILLA 7975): Incorrect quotes escaping in std.format)
$(LI $(BUGZILLA 7982): unsigned reverse iota broken)
@@ -66,6 +75,7 @@ $(VERSION 060, ddd mm, 2012, =================================================,
$(LI $(BUGZILLA 8055): [Regression 2.059] std.algorithm.move corrupts moved object field)
$(LI $(BUGZILLA 8057): std.algorithm.move cannot use for nested struct)
$(LI $(BUGZILLA 8080): 'alias this' causes toString to be shadowed by aliased object)
+ $(LI $(BUGZILLA 8158): std.algorithm.min fails to compile with user-defined types)
$(LI $(BUGZILLA 8187): replaceFirst doesn't work for string[] haystack)
$(LI $(BUGZILLA 8112): std.algorithm.fill must accept InputRange)
$(LI $(BUGZILLA 8171): Broken std.algorithm.move for nested struct has no member)
@@ -73,6 +83,9 @@ $(VERSION 060, ddd mm, 2012, =================================================,
$(LI $(BUGZILLA 8203): Use of std.regex.match() generates "not enough preallocated memory" error)
$(LI $(BUGZILLA 8233): std.array.array fails to compile with ranges of immutable elements which have a length property)
$(LI $(BUGZILLA 8240): std.algorithm.joiner and empty inputRangeObject)
+ $(LI $(BUGZILLA 8264): [std.conv.to] constructing conversion doesn't work with alias this)
+ $(LI $(BUGZILLA 8310): writeln of Range of fixed size array)
+ $(LI $(BUGZILLA 8323): std.string.chompPrefix does not handle differing string types properly)
)
)
View
2  crc32.d
@@ -14,8 +14,6 @@
// CRC-32 calculation
module crc32;
-pragma(msg, "The 'crc32' module has been scheduled for deprecation. Please use 'std.hash.crc32' instead.");
-
private immutable uint[256] crc32_table =
[
0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535,
View
12 posix.mak
@@ -54,7 +54,7 @@ DOCSRC = ../d-programming-language.org
WEBSITE_DIR = ../web
DOC_OUTPUT_DIR = $(WEBSITE_DIR)/phobos-prerelease
BIGDOC_OUTPUT_DIR = /tmp
-SRC_DOCUMENTABLES = index.d $(addsuffix .d,$(STD_MODULES) $(STD_NET_MODULES) $(STD_HASH_MODULES) $(EXTRA_DOCUMENTABLES))
+SRC_DOCUMENTABLES = index.d $(addsuffix .d,$(STD_MODULES) $(STD_NET_MODULES) $(EXTRA_DOCUMENTABLES))
STDDOC = $(DOCSRC)/std.ddoc
BIGSTDDOC = $(DOCSRC)/std_consolidated.ddoc
DDOCFLAGS=-m$(MODEL) -d -c -o- -version=StdDdoc -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS)
@@ -112,7 +112,7 @@ DFLAGS := -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) -w -d -property -m$(MODEL)
ifeq ($(BUILD),debug)
DFLAGS += -g -debug
else
- DFLAGS += -O -release -nofloat
+ DFLAGS += -O -release
endif
# Set DOTOBJ and DOTEXE
@@ -158,12 +158,10 @@ STD_MODULES = $(addprefix std/, algorithm array ascii base64 bigint \
metastrings mmfile numeric outbuffer parallelism path perf \
process random range regex regexp signals socket socketstream \
stdint stdio stdiobase stream string syserror system traits \
- typecons typetuple uni uri utf variant xml zip zlib)
+ typecons typetuple uni uri utf uuid variant xml zip zlib)
STD_NET_MODULES = $(addprefix std/net/, isemail curl)
-STD_HASH_MODULES = $(addprefix std/hash/, crc32)
-
# OS-specific D modules
EXTRA_MODULES_LINUX := $(addprefix std/c/linux/, linux socket)
EXTRA_MODULES_OSX := $(addprefix std/c/osx/, socket)
@@ -186,7 +184,7 @@ EXTRA_MODULES += $(EXTRA_DOCUMENTABLES) $(addprefix \
processinit uni uni_tab)
# Aggregate all D modules relevant to this build
-D_MODULES = $(STD_MODULES) $(EXTRA_MODULES) $(STD_NET_MODULES) $(STD_HASH_MODULES)
+D_MODULES = crc32 $(STD_MODULES) $(EXTRA_MODULES) $(STD_NET_MODULES)
# Add the .d suffix to the module names
D_FILES = $(addsuffix .d,$(D_MODULES))
# Aggregate all D modules over all OSs (this is for the zip file)
@@ -277,7 +275,7 @@ clean :
rm -rf $(ROOT_OF_THEM_ALL) $(ZIPFILE) $(DOC_OUTPUT_DIR)
zip :
- zip $(ZIPFILE) $(MAKEFILE) $(ALL_D_FILES) $(ALL_C_FILES)
+ zip $(ZIPFILE) $(MAKEFILE) $(ALL_D_FILES) $(ALL_C_FILES) win32.mak
install : release
sudo cp $(LIB) /usr/lib/
View
249 std/algorithm.d
@@ -3881,14 +3881,14 @@ unittest
}
/**
- * $(RED Scheduled for deprecation. Please use $(XREF algorithm, countUntil)
- * instead.)
+ * $(RED Deprecated. It will be removed in January 2013.
+ * Please use $(LREF countUntil) instead.)
*
- * Same as $(D countUntil). This symbol has been scheduled for
- * deprecation because it is easily confused with the homonym function
+ * Same as $(D countUntil). This symbol has been deprecated
+ * because it is easily confused with the homonym function
* in $(D std.string).
*/
-sizediff_t indexOf(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
+deprecated sizediff_t indexOf(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (is(typeof(startsWith!pred(haystack, needle))))
{
return countUntil!pred(haystack, needle);
@@ -4152,12 +4152,15 @@ if (isInputRange!R1 &&
else
enum isDefaultPred = false;
- // Special case for two arrays
- static if (isArray!R1 && isArray!R2 &&
- ((!isSomeString!R1 && !isSomeString!R2) ||
- (isSomeString!R1 && isSomeString!R2 &&
- is(Unqual!(typeof(haystack[0])) == Unqual!(typeof(needle[0]))) &&
- isDefaultPred)))
+ static if (isDefaultPred && isArray!R1 && isArray!R2 &&
+ is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
+ {
+ if (haystack.length < needle.length) return false;
+
+ return haystack[0 .. needle.length] == needle;
+ }
+ else static if (isArray!R1 && isArray!R2 &&
+ !isNarrowString!R1 && !isNarrowString!R2)
{
if (haystack.length < needle.length) return false;
@@ -4205,8 +4208,7 @@ unittest
debug(std_algorithm) scope(success)
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
- //foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
- foreach (S; TypeTuple!(char[], wstring))
+ foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
{
assert(!startsWith(to!S("abc"), 'c'));
assert(startsWith(to!S("abc"), 'a', 'c') == 1);
@@ -4214,8 +4216,7 @@ unittest
assert(startsWith(to!S("abc"), 'x', 'n', 'a') == 3);
assert(startsWith(to!S("\uFF28abc"), 'a', '\uFF28', 'c') == 2);
- //foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
- foreach (T; TypeTuple!(dchar[], string))
+ foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
{
assert(startsWith(to!S("abc"), to!T("")));
assert(startsWith(to!S("ab"), to!T("a")));
@@ -4238,28 +4239,33 @@ unittest
}
}
- assert(startsWith([0, 1, 2, 3, 4, 5], cast(int[])null));
- assert(!startsWith([0, 1, 2, 3, 4, 5], 5));
- assert(!startsWith([0, 1, 2, 3, 4, 5], 1));
- assert(startsWith([0, 1, 2, 3, 4, 5], 0));
- assert(startsWith([0, 1, 2, 3, 4, 5], 5, 0, 1) == 2);
- assert(startsWith([0, 1, 2, 3, 4, 5], [0]));
- assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1]));
- assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1], 7) == 1);
- assert(!startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7]));
- assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7], [0, 1, 2]) == 2);
+ foreach(T; TypeTuple!(int, short))
+ {
+ immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
+
+ assert(startsWith(arr, cast(int[])null));
+ assert(!startsWith(arr, 5));
+ assert(!startsWith(arr, 1));
+ assert(startsWith(arr, 0));
+ assert(startsWith(arr, 5, 0, 1) == 2);
+ assert(startsWith(arr, [0]));
+ assert(startsWith(arr, [0, 1]));
+ assert(startsWith(arr, [0, 1], 7) == 1);
+ assert(!startsWith(arr, [0, 1, 7]));
+ assert(startsWith(arr, [0, 1, 7], [0, 1, 2]) == 2);
- assert(!startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), 1));
- assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), 0));
- assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0]));
- assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1]));
- assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1], 7) == 1);
- assert(!startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1, 7]));
- assert(startsWith(filter!"true"([0, 1, 2, 3, 4, 5]), [0, 1, 7], [0, 1, 2]) == 2);
- assert(startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1])));
- assert(startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1]), 7) == 1);
- assert(!startsWith([0, 1, 2, 3, 4, 5], filter!"true"([0, 1, 7])));
- assert(startsWith([0, 1, 2, 3, 4, 5], [0, 1, 7], filter!"true"([0, 1, 2])) == 2);
+ assert(!startsWith(filter!"true"(arr), 1));
+ assert(startsWith(filter!"true"(arr), 0));
+ assert(startsWith(filter!"true"(arr), [0]));
+ assert(startsWith(filter!"true"(arr), [0, 1]));
+ assert(startsWith(filter!"true"(arr), [0, 1], 7) == 1);
+ assert(!startsWith(filter!"true"(arr), [0, 1, 7]));
+ assert(startsWith(filter!"true"(arr), [0, 1, 7], [0, 1, 2]) == 2);
+ assert(startsWith(arr, filter!"true"([0, 1])));
+ assert(startsWith(arr, filter!"true"([0, 1]), 7) == 1);
+ assert(!startsWith(arr, filter!"true"([0, 1, 7])));
+ assert(startsWith(arr, [0, 1, 7], filter!"true"([0, 1, 2])) == 2);
+ }
}
/**
@@ -4451,18 +4457,21 @@ if (isInputRange!R1 &&
else
enum isDefaultPred = false;
- // Special case for two arrays
- static if (isArray!R1 && isArray!R2 &&
- ((!isSomeString!R1 && !isSomeString!R2) ||
- (isSomeString!R1 && isSomeString!R2 &&
- is(Unqual!(typeof(haystack[0])) == Unqual!(typeof(needle[0]))) &&
- isDefaultPred)))
+ static if (isDefaultPred && isArray!R1 && isArray!R2 &&
+ is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
+ {
+ if (haystack.length < needle.length) return false;
+
+ return haystack[$ - needle.length .. $] == needle;
+ }
+ else static if (isArray!R1 && isArray!R2 &&
+ !isNarrowString!R1 && !isNarrowString!R2)
{
if (haystack.length < needle.length) return false;
immutable diff = haystack.length - needle.length;
foreach (j; 0 .. needle.length)
{
- if (!binaryFun!(pred)(needle[j], haystack[j + diff]))
+ if (!binaryFun!pred(needle[j], haystack[j + diff]))
// not found
return false;
}
@@ -4523,8 +4532,7 @@ unittest
return Result(r);
}
- //foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
- foreach (S; TypeTuple!(char[], wstring))
+ foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
{
assert(!endsWith(to!S("abc"), 'a'));
assert(endsWith(to!S("abc"), 'a', 'c') == 2);
@@ -4532,8 +4540,7 @@ unittest
assert(endsWith(to!S("abc"), 'x', 'n', 'c') == 3);
assert(endsWith(to!S("abc\uFF28"), 'a', '\uFF28', 'c') == 2);
- //foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
- foreach (T; TypeTuple!(dchar[], string))
+ foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring))
{
assert(endsWith(to!S("abc"), to!T("")));
assert(!endsWith(to!S("abc"), to!T("a")));
@@ -4551,28 +4558,33 @@ unittest
}
}
- assert(endsWith([0, 1, 2, 3, 4, 5], cast(int[])null));
- assert(!endsWith([0, 1, 2, 3, 4, 5], 0));
- assert(!endsWith([0, 1, 2, 3, 4, 5], 4));
- assert(endsWith([0, 1, 2, 3, 4, 5], 5));
- assert(endsWith([0, 1, 2, 3, 4, 5], 0, 4, 5) == 3);
- assert(endsWith([0, 1, 2, 3, 4, 5], [5]));
- assert(endsWith([0, 1, 2, 3, 4, 5], [4, 5]));
- assert(endsWith([0, 1, 2, 3, 4, 5], [4, 5], 7) == 1);
- assert(!endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5]));
- assert(endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5], [3, 4, 5]) == 2);
+ foreach(T; TypeTuple!(int, short))
+ {
+ immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
- assert(!endsWith(wrap([0, 1, 2, 3, 4, 5]), 4));
- assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), 5));
- assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [5]));
- assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [4, 5]));
- assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [4, 5], 7) == 1);
- assert(!endsWith(wrap([0, 1, 2, 3, 4, 5]), [2, 4, 5]));
- assert(endsWith(wrap([0, 1, 2, 3, 4, 5]), [2, 4, 5], [3, 4, 5]) == 2);
- assert(endsWith([0, 1, 2, 3, 4, 5], wrap([4, 5])));
- assert(endsWith([0, 1, 2, 3, 4, 5], wrap([4, 5]), 7) == 1);
- assert(!endsWith([0, 1, 2, 3, 4, 5], wrap([2, 4, 5])));
- assert(endsWith([0, 1, 2, 3, 4, 5], [2, 4, 5], wrap([3, 4, 5])) == 2);
+ assert(endsWith(arr, cast(int[])null));
+ assert(!endsWith(arr, 0));
+ assert(!endsWith(arr, 4));
+ assert(endsWith(arr, 5));
+ assert(endsWith(arr, 0, 4, 5) == 3);
+ assert(endsWith(arr, [5]));
+ assert(endsWith(arr, [4, 5]));
+ assert(endsWith(arr, [4, 5], 7) == 1);
+ assert(!endsWith(arr, [2, 4, 5]));
+ assert(endsWith(arr, [2, 4, 5], [3, 4, 5]) == 2);
+
+ assert(!endsWith(wrap(arr), 4));
+ assert(endsWith(wrap(arr), 5));
+ assert(endsWith(wrap(arr), [5]));
+ assert(endsWith(wrap(arr), [4, 5]));
+ assert(endsWith(wrap(arr), [4, 5], 7) == 1);
+ assert(!endsWith(wrap(arr), [2, 4, 5]));
+ assert(endsWith(wrap(arr), [2, 4, 5], [3, 4, 5]) == 2);
+ assert(endsWith(arr, wrap([4, 5])));
+ assert(endsWith(arr, wrap([4, 5]), 7) == 1);
+ assert(!endsWith(arr, wrap([2, 4, 5])));
+ assert(endsWith(arr, [2, 4, 5], wrap([3, 4, 5])) == 2);
+ }
}
/**
@@ -5053,14 +5065,19 @@ template MinType(T...)
{
static if (!is(typeof(T[0].min)))
alias CommonType!(T[0 .. 2]) MinType;
- else static if (mostNegative!(T[1]) < mostNegative!(T[0]))
- alias T[1] MinType;
- else static if (mostNegative!(T[1]) > mostNegative!(T[0]))
- alias T[0] MinType;
- else static if (T[1].max < T[0].max)
- alias T[1] MinType;
else
- alias T[0] MinType;
+ {
+ enum hasMostNegative = is(typeof(mostNegative!(T[0]))) &&
+ is(typeof(mostNegative!(T[1])));
+ static if (hasMostNegative && mostNegative!(T[1]) < mostNegative!(T[0]))
+ alias T[1] MinType;
+ else static if (hasMostNegative && mostNegative!(T[1]) > mostNegative!(T[0]))
+ alias T[0] MinType;
+ else static if (T[1].max < T[0].max)
+ alias T[1] MinType;
+ else
+ alias T[0] MinType;
+ }
}
else
{
@@ -5074,17 +5091,20 @@ Returns the minimum of the passed-in values. The type of the result is
computed by using $(XREF traits, CommonType).
*/
MinType!(T1, T2, T) min(T1, T2, T...)(T1 a, T2 b, T xs)
+ if(is(typeof(a < b)))
{
static if (T.length == 0)
{
- static if (isIntegral!(T1) && isIntegral!(T2)
- && (mostNegative!(T1) < 0) != (mostNegative!(T2) < 0))
- static if (mostNegative!(T1) < 0)
+ static if (isIntegral!T1 && isIntegral!T2 &&
+ (mostNegative!T1 < 0) != (mostNegative!T2 < 0))
+ {
+ static if (mostNegative!T1 < 0)
immutable chooseB = b < a && a > 0;
else
immutable chooseB = b < a || b < 0;
+ }
else
- immutable chooseB = b < a;
+ immutable chooseB = b < a;
return cast(typeof(return)) (chooseB ? b : a);
}
else
@@ -5101,16 +5121,27 @@ unittest
short b = 6;
double c = 2;
auto d = min(a, b);
- assert(is(typeof(d) == int));
+ static assert(is(typeof(d) == int));
assert(d == 5);
auto e = min(a, b, c);
- assert(is(typeof(e) == double));
+ static assert(is(typeof(e) == double));
assert(e == 2);
// mixed signedness test
a = -10;
uint f = 10;
static assert(is(typeof(min(a, f)) == int));
assert(min(a, f) == -10);
+
+ //Test user-defined types
+ import std.datetime;
+ assert(min(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(1982, 1, 4));
+ assert(min(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(1982, 1, 4));
+ assert(min(Date(1982, 1, 4), Date.min) == Date.min);
+ assert(min(Date.min, Date(1982, 1, 4)) == Date.min);
+ assert(min(Date(1982, 1, 4), Date.max) == Date(1982, 1, 4));
+ assert(min(Date.max, Date(1982, 1, 4)) == Date(1982, 1, 4));
+ assert(min(Date.min, Date.max) == Date.min);
+ assert(min(Date.max, Date.min) == Date.min);
}
// MaxType
@@ -5151,15 +5182,18 @@ assert(e == 2);
----
*/
MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs)
+ if(is(typeof(a < b)))
{
static if (T.length == 0)
{
- static if (isIntegral!(T1) && isIntegral!(T2)
- && (mostNegative!(T1) < 0) != (mostNegative!(T2) < 0))
- static if (mostNegative!(T1) < 0)
+ static if (isIntegral!T1 && isIntegral!T2 &&
+ (mostNegative!T1 < 0) != (mostNegative!T2 < 0))
+ {
+ static if (mostNegative!T1 < 0)
immutable chooseB = b > a || a < 0;
else
immutable chooseB = b > a && b > 0;
+ }
else
immutable chooseB = b > a;
return cast(typeof(return)) (chooseB ? b : a);
@@ -5178,16 +5212,27 @@ unittest
short b = 6;
double c = 2;
auto d = max(a, b);
- assert(is(typeof(d) == int));
+ static assert(is(typeof(d) == int));
assert(d == 6);
auto e = max(a, b, c);
- assert(is(typeof(e) == double));
+ static assert(is(typeof(e) == double));
assert(e == 6);
// mixed sign
a = -5;
uint f = 5;
static assert(is(typeof(max(a, f)) == uint));
assert(max(a, f) == 5);
+
+ //Test user-defined types
+ import std.datetime;
+ assert(max(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(2012, 12, 21));
+ assert(max(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(2012, 12, 21));
+ assert(max(Date(1982, 1, 4), Date.min) == Date(1982, 1, 4));
+ assert(max(Date.min, Date(1982, 1, 4)) == Date(1982, 1, 4));
+ assert(max(Date(1982, 1, 4), Date.max) == Date.max);
+ assert(max(Date.max, Date(1982, 1, 4)) == Date.max);
+ assert(max(Date.min, Date.max) == Date.max);
+ assert(max(Date.max, Date.min) == Date.max);
}
/**
@@ -8084,31 +8129,31 @@ unittest
assert(!all!"a & 1"([1, 2, 3, 5, 7, 9]));
}
-// Scheduled for deprecation. Use std.range.SortedRange.canFind.
-bool canFindSorted(alias pred = "a < b", Range, V)(Range range, V value) {
- pragma(msg, "std.algorithm.canFindSorted is scheduled for " ~
- "deprecation. Use std.range.SortedRange.canFind instead.");
+// Deprecated. It will be removed in January 2013. Use std.range.SortedRange.canFind.
+deprecated bool canFindSorted(alias pred = "a < b", Range, V)(Range range, V value) {
+ pragma(msg, "std.algorithm.canFindSorted has been deprecated. " ~
+ "Please use std.range.SortedRange.canFind instead.");
return assumeSorted!pred(range).canFind!V(value);
}
-// Scheduled for deprecation. Use std.range.SortedRange.lowerBound.
-Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
- pragma(msg, "std.algorithm.lowerBound is scheduled for " ~
- "deprecation. Use std.range.SortedRange.lowerBound instead.");
+// Deprecated. It will be removed in January 2013. Use std.range.SortedRange.lowerBound.
+deprecated Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
+ pragma(msg, "std.algorithm.lowerBound has been deprecated. " ~
+ "Please use std.range.SortedRange.lowerBound instead.");
return assumeSorted!pred(range).lowerBound!V(value).release;
}
-// Scheduled for deprecation. Use std.range.SortedRange.upperBound.
-Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
- pragma(msg, "std.algorithm.upperBound is scheduled for " ~
- "deprecation. Use std.range.SortedRange.upperBound instead.");
+// Deprecated. It will be removed in January 2013. Use std.range.SortedRange.upperBound.
+deprecated Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
+ pragma(msg, "std.algorithm.upperBound has been deprecated. " ~
+ "Please use std.range.SortedRange.upperBound instead.");
return assumeSorted!pred(range).upperBound!V(value).release;
}
-// Scheduled for deprecation. Use std.range.SortedRange.equalRange.
-Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
- pragma(msg, "std.algorithm.equalRange is scheduled for " ~
- "deprecation. Use std.range.SortedRange.equalRange instead.");
+// Deprecated. It will be removed in January 2013. Use std.range.SortedRange.equalRange.
+deprecated Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
+ pragma(msg, "std.algorithm.equalRange has been deprecated. " ~
+ "Please use std.range.SortedRange.equalRange instead.");
return assumeSorted!pred(range).equalRange!V(value).release;
}
View
6 std/array.d
@@ -186,7 +186,7 @@ private template nDimensions(T)
{
static if(isArray!T)
{
- enum nDimensions = 1 + nDimensions!(typeof(T.init[0]));
+ enum nDimensions = 1 + nDimensions!(ArrayTarget!T);
}
else
{
@@ -266,7 +266,7 @@ if(allSatisfy!(isIntegral, I))
to!string(sizes.length) ~ " dimensions specified for a " ~
to!string(nDimensions!T) ~ " dimensional array.");
- alias typeof(T.init[0]) E;
+ alias ArrayTarget!T E;
auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!(E));
auto ret = ptr[0..sizes[0]];
@@ -1533,7 +1533,7 @@ unittest
}
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
{
- alias typeof(S.init[0]) Char;
+ alias ElementEncodingType!S Char;
S s = to!S("yet another dummy text, yet another ...");
S from = to!S("yet another");
S into = to!S("some");
View
42 std/bigint.d
@@ -79,7 +79,7 @@ public:
/// It may have a leading + or - sign; followed by "0x" if hexadecimal.
/// Underscores are permitted.
/// BUG: Should throw a IllegalArgumentException/ConvError if invalid character found
- this(T:string)(T s)
+ this(T : const(char)[] )(T s)
{
bool neg = false;
if (s[0] == '-') {
@@ -112,17 +112,19 @@ public:
}
///
- void opAssign(T: long)(T x)
+ BigInt opAssign(T: long)(T x)
{
data = cast(ulong)((x < 0) ? -x : x);
sign = (x < 0);
+ return this;
}
///
- void opAssign(T:BigInt)(T x)
+ BigInt opAssign(T:BigInt)(T x)
{
data = x.data;
sign = x.sign;
+ return this;
}
// BigInt op= integer
@@ -160,8 +162,14 @@ public:
else static if (op=="%")
{
assert(y!=0, "Division by zero");
- static assert(!is(T==long) && !is(T==ulong));
- data = cast(ulong)BigUint.modInt(data, cast(uint)u);
+ static if (is(const(T) == const(long)) || is( const(T) == const(ulong) ))
+ {
+ this %= BigInt(y);
+ }
+ else
+ {
+ data = cast(ulong)BigUint.modInt(data, cast(uint)u);
+ }
// x%y always has the same sign as x.
// This is not the same as mathematical mod.
}
@@ -214,8 +222,8 @@ public:
y.checkDivByZero();
if (!isZero())
{
- sign ^= y.sign;
data = BigUint.div(data, y.data);
+ sign = isZero() ? false : sign ^ y.sign;
}
}
else static if (op == "%")
@@ -342,7 +350,7 @@ public:
}
///
- bool opEquals(T: int)(T y) const
+ bool opEquals(T: long)(T y) const
{
if (sign != (y<0))
return 0;
@@ -523,6 +531,11 @@ unittest {
assert(BigInt(-0x1234_5678_9ABC_5A5AL).toLong() == -0x1234_5678_9ABC_5A5AL);
assert(BigInt(0xF234_5678_9ABC_5A5AL).toLong() == long.max);
assert(BigInt(-0x123456789ABCL).toInt() == -int.max);
+ char[] s1 = "123".dup; // bug 8164
+ assert(BigInt(s1) == 123);
+ char[] s2 = "0xABC".dup;
+ assert(BigInt(s2) == 2748);
+
assert((BigInt(-2) + BigInt(1)) == BigInt(-1));
BigInt a = ulong.max - 5;
auto b = -long.max % a;
@@ -532,6 +545,7 @@ unittest {
assert(BigInt(1) - 1 == 0);
assert((-4) % BigInt(5) == -4); // bug 5928
assert(BigInt(-4) % BigInt(5) == -4);
+ assert(BigInt(2)/BigInt(-3) == BigInt(0)); // bug 8022
}
unittest // Recursive division, bug 5568
@@ -561,6 +575,20 @@ unittest // Recursive division, bug 5568
BigInt z2 = BigInt(1)<<64;
BigInt w2 = BigInt(1)<<128;
assert(z2^^2 == w2);
+ // Bug 7993
+ BigInt n7793 = 10;
+ assert( n7793 / 1 == 10);
+ // Bug 7973
+ auto a7973 = 10_000_000_000_000_000;
+ const c7973 = 10_000_000_000_000_000;
+ BigInt v7973 = 2551700137;
+ v7973 %= a7973;
+ assert(v7973 == 2551700137);
+ v7973 %= c7973;
+ assert(v7973 == 2551700137);
+ // 8165
+ BigInt[2] a8165;
+ a8165[0] = a8165[1] = 1;
}
unittest
View
254 std/complex.d
@@ -1,9 +1,13 @@
// Written in the D programming language.
-/** Module that will replace the built-in types $(D cfloat), $(D cdouble),
- $(D creal), $(D ifloat), $(D idouble), and $(D ireal).
+/** This module contains the $(LREF Complex) type, which is used to represent
+ _complex numbers, along with related mathematical operations and functions.
- Authors: Lars Tandle Kyllingstad
+ $(LREF Complex) will eventually $(LINK2 ../deprecate.html, replace)
+ the built-in types $(D cfloat), $(D cdouble), $(D creal), $(D ifloat),
+ $(D idouble), and $(D ireal).
+
+ Authors: Lars Tandle Kyllingstad, Don Clugston
Copyright: Copyright (c) 2010, Lars T. Kyllingstad.
License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0)
Source: $(PHOBOSSRC std/_complex.d)
@@ -17,8 +21,6 @@ import std.numeric;
import std.traits;
-
-
/** Helper function that returns a _complex number with the specified
real and imaginary parts.
@@ -61,7 +63,6 @@ auto complex(R, I)(R re, I im) @safe pure nothrow
return Complex!double(re, im);
}
-
unittest
{
auto a = complex(1.0);
@@ -101,8 +102,6 @@ unittest
}
-
-
/** A complex number parametrised by a type $(D T), which must be either
$(D float), $(D double) or $(D real).
*/
@@ -114,38 +113,45 @@ struct Complex(T) if (isFloatingPoint!T)
/** The imaginary part of the number. */
T im;
+ /** Converts the complex number to a string representation.
-@safe pure nothrow // The following functions depend only on std.math.
-{
-
- /** Calculate the absolute value (or modulus) of the number. */
- @property T abs() const
- {
- return hypot(re, im);
- }
+ If a $(D sink) delegate is specified, the string is passed to it
+ and this function returns $(D null). Otherwise, this function
+ returns the string representation directly.
+ The output format is controlled via $(D formatSpec), which should consist
+ of a single POSIX format specifier, including the percent (%) character.
+ Note that complex numbers are floating point numbers, so the only
+ valid format characters are 'e', 'f', 'g', 'a', and 's', where 's'
+ gives the default behaviour. Positional parameters are not valid
+ in this context.
- /** Calculate the argument (or phase) of the number. */
- @property T arg() const
+ See the $(LINK2 std_format.html, std.format documentation) for
+ more information.
+ */
+ string toString(scope void delegate(const(char)[]) sink = null,
+ string formatSpec = "%s")
+ const
{
- return atan2(im, re);
- }
-
+ if (sink == null)
+ {
+ char[] buf;
+ buf.reserve(100);
+ toString((const(char)[] s) { buf ~= s; }, formatSpec);
+ return cast(string) buf;
+ }
- /** Return the complex conjugate of the number. */
- @property Complex conj() const
- {
- return Complex(re, -im);
+ formattedWrite(sink, formatSpec, re);
+ if (signbit(im) == 0) sink("+");
+ formattedWrite(sink, formatSpec, im);
+ sink("i");
+ return null;
}
-
-
+@safe pure nothrow:
// ASSIGNMENT OPERATORS
- // TODO: Make operators return by ref when DMD bug 2460 is fixed.
-
-
// this = complex
ref Complex opAssign(R : T)(Complex!R z)
{
@@ -154,7 +160,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// this = numeric
ref Complex opAssign(R : T)(R r)
{
@@ -163,30 +168,22 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
-
-
// COMPARISON OPERATORS
-
// this == complex
bool opEquals(R : T)(Complex!R z) const
{
return re == z.re && im == z.im;
}
-
// this == numeric
bool opEquals(R : T)(R r) const
{
return re == r && im == 0;
}
-
-
// UNARY OPERATORS
-
// +complex
Complex opUnary(string op)() const
if (op == "+")
@@ -194,7 +191,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// -complex
Complex opUnary(string op)() const
if (op == "-")
@@ -202,11 +198,8 @@ struct Complex(T) if (isFloatingPoint!T)
return Complex(-re, -im);
}
-
-
// BINARY OPERATORS
-
// complex op complex
Complex!(CommonType!(T,R)) opBinary(string op, R)(Complex!R z) const
{
@@ -215,7 +208,6 @@ struct Complex(T) if (isFloatingPoint!T)
return w.opOpAssign!(op)(z);
}
-
// complex op numeric
Complex!(CommonType!(T,R)) opBinary(string op, R)(R r) const
if (isNumeric!R)
@@ -225,7 +217,6 @@ struct Complex(T) if (isFloatingPoint!T)
return w.opOpAssign!(op)(r);
}
-
// numeric + complex, numeric * complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
if ((op == "+" || op == "*") && (isNumeric!R))
@@ -233,7 +224,6 @@ struct Complex(T) if (isFloatingPoint!T)
return opBinary!(op)(r);
}
-
// numeric - complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
if (op == "-" && isNumeric!R)
@@ -241,7 +231,6 @@ struct Complex(T) if (isFloatingPoint!T)
return Complex(r - re, -im);
}
-
// numeric / complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r) const
if (op == "/" && isNumeric!R)
@@ -269,10 +258,7 @@ struct Complex(T) if (isFloatingPoint!T)
return w;
}
-
-
- // OPASSIGN OPERATORS
-
+ // OP-ASSIGN OPERATORS
// complex += complex, complex -= complex
ref Complex opOpAssign(string op, C)(C z)
@@ -283,7 +269,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex *= complex
ref Complex opOpAssign(string op, C)(C z)
if (op == "*" && is(C R == Complex!R))
@@ -294,7 +279,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex /= complex
ref Complex opOpAssign(string op, C)(C z)
if (op == "/" && is(C R == Complex!R))
@@ -320,13 +304,12 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex ^^= complex
ref Complex opOpAssign(string op, C)(C z)
if (op == "^^" && is(C R == Complex!R))
{
- FPTemporary!T r = abs;
- FPTemporary!T t = arg;
+ FPTemporary!T r = abs(this);
+ FPTemporary!T t = arg(this);
FPTemporary!T ab = r^^z.re * exp(-t*z.im);
FPTemporary!T ar = t*z.re + log(r)*z.im;
@@ -335,7 +318,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex += numeric, complex -= numeric
ref Complex opOpAssign(string op, U : T)(U a)
if (op == "+" || op == "-")
@@ -344,7 +326,6 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex *= numeric, complex /= numeric
ref Complex opOpAssign(string op, U : T)(U a)
if (op == "*" || op == "/")
@@ -354,19 +335,17 @@ struct Complex(T) if (isFloatingPoint!T)
return this;
}
-
// complex ^^= real
ref Complex opOpAssign(string op, R)(R r)
if (op == "^^" && isFloatingPoint!R)
{
- FPTemporary!T ab = abs^^r;
- FPTemporary!T ar = arg*r;
+ FPTemporary!T ab = abs(this)^^r;
+ FPTemporary!T ar = arg(this)*r;
re = ab*std.math.cos(ar);
im = ab*std.math.sin(ar);
return this;
}
-
// complex ^^= int
ref Complex opOpAssign(string op, U)(U i)
if (op == "^^" && isIntegral!U)
@@ -393,60 +372,12 @@ struct Complex(T) if (isFloatingPoint!T)
}
return this;
}
-
-} // @safe pure nothrow
-
-
-
- /** Convert the complex number to a string representation.
-
- If a $(D sink) delegate is specified, the string is passed to it
- and this function returns $(D null). Otherwise, this function
- returns the string representation directly.
-
- The output format is controlled via $(D formatSpec), which should consist
- of a single POSIX format specifier, including the percent (%) character.
- Note that complex numbers are floating point numbers, so the only
- valid format characters are 'e', 'f', 'g', 'a', and 's', where 's'
- gives the default behaviour. Positional parameters are not valid
- in this context.
-
- See the $(LINK2 std_format.html, std.format documentation) for
- more information.
- */
- string toString
- (scope void delegate(const(char)[]) sink = null, string formatSpec = "%s")
- const
- {
- if (sink == null)
- {
- char[] buf;
- buf.reserve(100);
- toString((const(char)[] s) { buf ~= s; }, formatSpec);
- return cast(string) buf;
- }
-
- formattedWrite(sink, formatSpec, re);
- if (signbit(im) == 0) sink("+");
- formattedWrite(sink, formatSpec, im);
- sink("i");
- return null;
- }
}
-
unittest
{
enum EPS = double.epsilon;
-
- // Check abs() and arg()
- auto c1 = Complex!double(1.0, 1.0);
- assert (approxEqual(c1.abs, std.math.sqrt(2.0), EPS));
- assert (approxEqual(c1.arg, PI_4, EPS));
-
- auto c1c = c1.conj;
- assert (c1c.re == 1.0 && c1c.im == -1.0);
-
+ auto c1 = complex(1.0, 1.0);
// Check unary operations.
auto c2 = Complex!double(0.5, 2.0);
@@ -457,7 +388,6 @@ unittest
assert ((-c2).im == -(c2.im));
assert (c2 == -(-c2));
-
// Check complex-complex operations.
auto cpc = c1 + c2;
assert (cpc.re == c1.re + c2.re);
@@ -468,18 +398,17 @@ unittest
assert (cmc.im == c1.im - c2.im);
auto ctc = c1 * c2;
- assert (approxEqual(ctc.abs, c1.abs*c2.abs, EPS));
- assert (approxEqual(ctc.arg, c1.arg+c2.arg, EPS));
+ assert (approxEqual(abs(ctc), abs(c1)*abs(c2), EPS));
+ assert (approxEqual(arg(ctc), arg(c1)+arg(c2), EPS));
auto cdc = c1 / c2;
- assert (approxEqual(cdc.abs, c1.abs/c2.abs, EPS));
- assert (approxEqual(cdc.arg, c1.arg-c2.arg, EPS));
+ assert (approxEqual(abs(cdc), abs(c1)/abs(c2), EPS));
+ assert (approxEqual(arg(cdc), arg(c1)-arg(c2), EPS));
auto cec = c1^^c2;
assert (approxEqual(cec.re, 0.11524131979943839881, EPS));
assert (approxEqual(cec.im, 0.21870790452746026696, EPS));
-
// Check complex-real operations.
double a = 123.456;
@@ -496,8 +425,8 @@ unittest
assert (ctr.im == c1.im*a);
auto cdr = c1 / a;
- assert (approxEqual(cdr.abs, c1.abs/a, EPS));
- assert (approxEqual(cdr.arg, c1.arg, EPS));
+ assert (approxEqual(abs(cdr), abs(c1)/a, EPS));
+ assert (approxEqual(arg(cdr), arg(c1), EPS));
auto rpc = a + c1;
assert (rpc == cpr);
@@ -510,25 +439,23 @@ unittest
assert (rtc == ctr);
auto rdc = a / c1;
- assert (approxEqual(rdc.abs, a/c1.abs, EPS));
- assert (approxEqual(rdc.arg, -c1.arg, EPS));
+ assert (approxEqual(abs(rdc), a/abs(c1), EPS));
+ assert (approxEqual(arg(rdc), -arg(c1), EPS));
auto cer = c1^^3.0;
- assert (approxEqual(cer.abs, c1.abs^^3, EPS));
- assert (approxEqual(cer.arg, c1.arg*3, EPS));
-
+ assert (approxEqual(abs(cer), abs(c1)^^3, EPS));
+ assert (approxEqual(arg(cer), arg(c1)*3, EPS));
// Check Complex-int operations.
foreach (i; 0..6)
{
auto cei = c1^^i;
- assert (approxEqual(cei.abs, c1.abs^^i, EPS));
+ assert (approxEqual(abs(cei), abs(c1)^^i, EPS));
// Use cos() here to deal with arguments that go outside
// the (-pi,pi] interval (only an issue for i>3).
- assert (approxEqual(std.math.cos(cei.arg), std.math.cos(c1.arg*i), EPS));
+ assert (approxEqual(std.math.cos(arg(cei)), std.math.cos(arg(c1)*i), EPS));
}
-
// Check operations between different complex types.
auto cf = Complex!float(1.0, 1.0);
auto cr = Complex!real(1.0, 1.0);
@@ -557,7 +484,6 @@ unittest
assert (z == 1.0L);
assert (z.re == 1.0 && z.im == 0.0);
-
auto w = Complex!real(1.0, 1.0);
z = w;
assert (z == w);
@@ -581,7 +507,7 @@ unittest
assert (s1 == z1.toString());
// Using custom format specifier
- auto z2 = z1.conj;
+ auto z2 = conj(z1);
char[] s2;
z2.toString((const(char)[] c) { s2 ~= c; }, "%.8e");
assert (s2 == "1.23456789e-01-1.23456789e-01i");
@@ -589,9 +515,7 @@ unittest
}
-
-
-/* Fold Complex!(Complex!T) to Complex!T.
+/* Makes Complex!(Complex!T) fold to Complex!T.
The rationale for this is that just like the real line is a
subspace of the complex plane, the complex plane is a subspace
@@ -627,9 +551,48 @@ unittest
}
+/** Calculates the absolute value (or modulus) of a complex number. */
+T abs(T)(Complex!T z) @safe pure nothrow
+{
+ return hypot(z.re, z.im);
+}
+
+unittest
+{
+ assert (abs(complex(1.0)) == 1.0);
+ assert (abs(complex(0.0, 1.0)) == 1.0);
+ assert (abs(complex(1.0L, -2.0L)) == std.math.sqrt(5.0L));
+}
-/** Construct a complex number given its absolute value and argument. */
+/** Calculates the argument (or phase) of a complex number. */
+T arg(T)(Complex!T z) @safe pure nothrow
+{
+ return atan2(z.im, z.re);
+}
+
+unittest
+{
+ assert (arg(complex(1.0)) == 0.0);
+ assert (arg(complex(0.0L, 1.0L)) == PI_2);
+ assert (arg(complex(1.0L, 1.0L)) == PI_4);
+}
+
+
+/** Returns the complex conjugate of a complex number. */
+Complex!T conj(T)(Complex!T z) @safe pure nothrow
+{
+ return Complex!T(z.re, -z.im);
+}
+
+unittest
+{
+ assert (conj(complex(1.0)) == complex(1.0));
+ assert (conj(complex(1.0, 2.0)) == complex(1.0, -2.0));
+}
+
+
+/** Constructs a complex number given its absolute value and argument. */
Complex!(CommonType!(T, U)) fromPolar(T, U)(T modulus, U argument)
@safe pure nothrow
{
@@ -645,8 +608,6 @@ unittest
}
-
-
/** Trigonometric functions. */
Complex!T sin(T)(Complex!T z) @safe pure nothrow
{
@@ -677,6 +638,29 @@ unittest{
}
+/** Calculates cos(y) + i sin(y).
+
+ Note:
+ $(D expi) is included here for convenience and for easy migration of code
+ that uses $(XREF math,_expi). Unlike $(XREF math,_expi), which uses the
+ x87 $(I fsincos) instruction when possible, this function is no faster
+ than calculating cos(y) and sin(y) separately.
+*/
+Complex!real expi(real y) @trusted pure nothrow
+{
+ return Complex!real(std.math.cos(y), std.math.sin(y));
+}
+
+unittest
+{
+ assert(expi(1.3e5L) == complex(std.math.cos(1.3e5L), std.math.sin(1.3e5L)));
+ assert(expi(0.0L) == 1.0L);
+ auto z1 = expi(1.234);
+ auto z2 = std.math.expi(1.234);
+ assert(z1.re == z2.re && z1.im == z2.im);
+}
+
+
/** Square root. */
Complex!T sqrt(T)(Complex!T z) @safe pure nothrow
{
View
647 std/container.d
@@ -1312,7 +1312,7 @@ Complexity: $(BIGOH n)
if (orig._head == _root)
{
// remove straight from the head of the list
- for (; !orig.empty; orig.popFront())
+ for (; !r.empty; r.popFront())
{
removeFront();
}
@@ -1483,6 +1483,582 @@ unittest
}
/**
+ Implements a doubly-linked list.
+ */
+struct DList(T)
+{
+ private struct Node
+ {
+ T _payload;
+ Node * _prev;
+ Node * _next;
+ this(T a, Node* p, Node* n)
+ {
+ _payload = a;
+ _prev = p; _next = n;
+ if (p) p._next = &this;
+ if (n) n._prev = &this;
+ }
+ }
+ private Node * _first;
+ private Node * _last;
+
+/**
+Constructor taking a number of nodes
+ */
+ this(U)(U[] values...) if (isImplicitlyConvertible!(U, T))
+ {
+ insertBack(values);
+ }
+
+/**
+Constructor taking an input range
+ */
+ this(Stuff)(Stuff stuff)
+ if (isInputRange!Stuff
+ && isImplicitlyConvertible!(ElementType!Stuff, T)
+ && !is(Stuff == T[]))
+ {
+ insertBack(stuff);
+ }
+
+/**
+Comparison for equality.
+
+Complexity: $(BIGOH min(n, n1)) where $(D n1) is the number of
+elements in $(D rhs).
+ */
+ bool opEquals(ref const DList rhs) const
+ {
+ auto nthis = _first, nrhs = rhs._first;
+
+ while(true)
+ {
+ if (!nthis) return !nrhs;
+ if (!nrhs || nthis._payload != nrhs._payload) return false;
+ }
+ }
+
+ /**
+ Defines the container's primary range, which embodies a bidirectional range.
+ */
+ struct Range
+ {
+ private Node * _first;
+ private Node * _last;
+ private this(Node* first, Node* last) { _first = first; _last = last; }
+ private this(Node* n) { _first = _last = n; }
+ /// Forward range primitives.
+ @property bool empty() const { return !_first; }
+ @property T front() { return _first._payload; }
+ void popFront()
+ {
+ enforce(_first);
+ assert(_last);
+ if (_first is _last)
+ {
+ _first = _last = null;
+ }
+ else
+ {
+ _first = _first._next;
+ }
+ }
+ @property Range save() { return this; }
+ /// Bidirectional range primitives.
+ @property T back() { return _last._payload; }
+ void popBack()
+ {
+ enforce(_first);
+ assert(_last);
+ if (_first is _last)
+ {
+ _first = _last = null;
+ }
+ else
+ {
+ _last = _last._prev;
+ }
+ }
+ }
+
+ unittest
+ {
+ static assert(isBidirectionalRange!Range);
+ }
+
+/**
+Property returning $(D true) if and only if the container has no
+elements.
+
+Complexity: $(BIGOH 1)
+ */
+ @property bool empty() const
+ {
+ return _first is null;
+ }
+
+/**
+Duplicates the container. The elements themselves are not transitively
+duplicated.
+
+Complexity: $(BIGOH n).
+ */
+ @property DList dup()
+ {
+ return DList(this[]);
+ }
+
+/**
+Returns a range that iterates over all elements of the container, in
+forward order.
+
+Complexity: $(BIGOH 1)
+ */
+ Range opSlice()
+ {
+ return Range(_first, _last);
+ }
+
+/**
+Forward to $(D opSlice().front).
+
+Complexity: $(BIGOH 1)
+ */
+ @property T front()
+ {
+ enforce(_first);
+ return _first._payload;
+ }
+
+ @property T back()
+ {
+ enforce(_last);
+ return _last._payload;
+ }
+
+/**
+Returns a new $(D DList) that's the concatenation of $(D this) and its
+argument. $(D opBinaryRight) is only defined if $(D Stuff) does not
+define $(D opBinary).
+ */
+ DList opBinary(string op, Stuff)(Stuff rhs)
+ if (op == "~" && (is(Stuff == DList) || is(typeof(DList(rhs)))))
+ {
+ auto ret = this.dup;
+ ret ~= rhs;
+ return ret;
+ }
+
+ DList opOpassign(string op, Stuff)(Stuff rhs)
+ if (op == "~" && is(Stuff == DList))
+ {
+ if (_last) _last._next = rhs._first;
+ if (rhs._first) rhs_.first._prev = _last;
+ }
+
+ DList opOpassign(string op, Stuff)(Stuff rhs)
+ if (op == "~" && is(typeof(DList(rhs))))
+ {
+ opOpassign!(op)(DList(rhs));
+ }
+
+/**
+Removes all contents from the $(D DList).
+
+Postcondition: $(D empty)
+
+Complexity: $(BIGOH 1)
+ */
+ void clear()
+ {
+ _first = _last = null;
+ }
+
+/**
+Inserts $(D stuff) to the front/back of the container. $(D stuff) can be a
+value convertible to $(D T) or a range of objects convertible to $(D
+T). The stable version behaves the same, but guarantees that ranges
+iterating over the container are never invalidated.
+
+Returns: The number of elements inserted
+
+Complexity: $(BIGOH log(n))
+ */
+ size_t insertFront(Stuff)(Stuff stuff)
+ {
+ return insertBeforeNode(_first, stuff);
+ }
+
+ // ditto
+ size_t insertBack(Stuff)(Stuff stuff)
+ {
+ return insertBeforeNode(null, stuff);
+ }
+
+ /// ditto
+ alias insertBack insert;
+
+ /// ditto
+ alias insert stableInsert;
+
+ /// ditto
+ alias insertFront stableInsertFront;
+
+ /// ditto
+ alias insertBack stableInsertBack;
+
+/**
+Picks one value from the front of the container, removes it from the
+container, and returns it.
+
+Precondition: $(D !empty)
+
+Returns: The element removed.
+
+Complexity: $(BIGOH 1).
+ */
+ T removeAny()
+ {
+ enforce(!empty);
+ auto result = move(_last._payload);
+ _last = _last._prev;
+ return result;
+ }
+ /// ditto
+ alias removeAny stableRemoveAny;
+
+/**
+Removes the value at the front/back of the container. The stable version
+behaves the same, but guarantees that ranges iterating over the
+container are never invalidated.
+
+Precondition: $(D !empty)
+
+Complexity: $(BIGOH 1).
+ */
+ void removeFront()
+ {
+ enforce(_first);
+ _first = _first._next;
+ if (_first is null)
+ {
+ _last = null;
+ }
+ }
+
+ /// ditto
+ alias removeFront stableRemoveFront;
+
+ /// ditto
+ void removeBack()
+ {
+ enforce(_last);
+ _last = _last._prev;
+ if (_last is null)
+ {
+ _first = null;
+ }
+ }
+
+ /// ditto
+ alias removeBack stableRemoveBack;
+
+/**
+Removes $(D howMany) values at the front or back of the
+container. Unlike the unparameterized versions above, these functions
+do not throw if they could not remove $(D howMany) elements. Instead,
+if $(D howMany > n), all elements are removed. The returned value is
+the effective number of elements removed. The stable version behaves
+the same, but guarantees that ranges iterating over the container are
+never invalidated.
+
+Returns: The number of elements removed
+
+Complexity: $(BIGOH howMany * log(n)).
+ */
+ size_t removeFront(size_t howMany)
+ {
+ size_t result;
+ while (_first && result < howMany)
+ {
+ _first = _first._next;
+ ++result;
+ }
+ if (_first is null)
+ {
+ _last = null;
+ }
+ return result;
+ }
+
+ /// ditto
+ alias removeFront stableRemoveFront;
+
+ /// ditto
+ size_t removeBack(size_t howMany)
+ {
+ size_t result;
+ while (_last && result < howMany)
+ {
+ _last = _last._prev;
+ ++result;
+ }
+ if (_last is null)
+ {
+ _first = null;
+ }
+ return result;
+ }
+
+ /// ditto
+ alias removeBack stableRemoveBack;
+
+/**
+Inserts $(D stuff) after range $(D r), which must be a non-empty range
+previously extracted from this container.
+
+$(D stuff) can be a value convertible to $(D T) or a range of objects
+convertible to $(D T). The stable version behaves the same, but
+guarantees that ranges iterating over the container are never
+invalidated.
+
+Returns: The number of values inserted.
+
+Complexity: $(BIGOH k + m), where $(D k) is the number of elements in
+$(D r) and $(D m) is the length of $(D stuff).
+ */
+
+ size_t insertBefore(Stuff)(Range r, Stuff stuff)
+ {
+ Node* n = (r._first) ? r._first : _first;
+ return insertBeforeNode(n, stuff);
+ }
+ /// ditto
+ alias insertBefore stableInsertBefore;
+
+
+ size_t insertAfter(Stuff)(Range r, Stuff stuff)
+ {
+ Node* n = (r._last) ? r._last._next : null;
+ return insertBeforeNode(n, stuff);
+ }
+
+ /// ditto
+ alias insertAfter stableInsertAfter;
+
+ /// Helper: insert $(D stuff) before Node $(D n). If $(D n) is $(D null) then insert at end.
+ private size_t insertBeforeNode(Stuff)(Node* n, Stuff stuff)
+ if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T))
+ {
+ size_t result;
+ Node* prev = (n) ? n._prev : _last;
+ foreach (item; stuff)
+ {
+ if (_first is null)
+ {
+ prev = _first = new Node(item, null, null);
+ }
+ else if (n is _first)
+ {
+ prev = _first = new Node(item, prev, _first);
+ }
+ else
+ {
+ prev = new Node(item, prev, n);
+ }
+ ++result;
+ }
+ if (!_last || !n)
+ {
+ _last = prev;
+ }
+ return result;
+ }
+
+ /// Helper: insert $(D stuff) before Node $(D n). If $(D n) is $(D null) then insert at end.
+ private size_t insertBeforeNode(Stuff)(Node* n, Stuff stuff)
+ if (isImplicitlyConvertible!(Stuff, T))
+ {
+ Node* prev = (n !is null) ? n._prev : _last;
+ if (_first is null)
+ {
+ prev = _first = new Node(stuff, null, null);
+ }
+ else if (n is _first)
+ {
+ prev = _first = new Node(stuff, prev, _first);
+ }
+ else
+ {
+ prev = new Node(stuff, prev, n);
+ }
+ if (!_last || !n)
+ {
+ _last = prev;
+ }
+ return 1;
+ }
+
+/**
+Removes all elements belonging to $(D r), which must be a range
+obtained originally from this container. The stable version behaves the
+same, but guarantees that ranges iterating over the container are
+never invalidated.
+
+Returns: A range spanning the remaining elements in the container that
+initially were right after $(D r).
+
+Complexity: $(BIGOH 1)
+ */
+ Range remove(Range r)
+ {
+ if (r.empty)
+ {
+ return r;
+ }
+ enforce(_first);
+ Node* before = r._first._prev;
+ Node* after = r._last._next;
+ if (before)
+ {
+ before._next = after;
+ }
+ else
+ {
+ _first = after;
+ }
+ if (after)
+ {
+ after._prev = before;
+ }
+ else
+ {
+ _last = before;
+ }
+ return Range(after, _last);
+ }
+
+ /// ditto
+ alias remove stableRemove;
+ template linearRemove(R) if (is(R == Range))
+ {
+ Range linearRemove(R r) { return remove(r); };
+ }
+
+ /// ditto
+ Range linearRemove(R)(R r)
+ if (isInputRange!R && is(typeof(r.source)))
+ {
+ if (r.empty)
+ {
+ return Range(null,null);
+ }
+ enforce(r.source._first);
+ Node* first = r.source._first;
+ Node* last;
+ while(!r.empty)
+ {
+ last = r.source._first;
+ r.popFront();
+ }
+ return remove(Range(first, last));
+ }
+
+ /// ditto
+ alias linearRemove stableLinearRemove;
+}
+
+unittest
+{
+ alias DList!int IntList;
+ IntList list = IntList([0,1,2,3]);
+ assert(equal(list[],[0,1,2,3]));
+ list.insertBack([4,5,6,7]);
+ assert(equal(list[],[0,1,2,3,4,5,6,7]));
+
+ list = IntList();
+ list.insertFront([0,1,2,3]);
+ assert(equal(list[],[0,1,2,3]));
+ list.insertFront([4,5,6,7]);
+ assert(equal(list[],[4,5,6,7,0,1,2,3]));
+}
+
+unittest
+{
+ alias DList!int IntList;
+ IntList list = IntList([0,1,2,3]);
+ auto range = list[];
+ for( ; !range.empty; range.popFront())
+ {
+ int item = range.front;
+ if (item == 2)
+ {
+ list.stableLinearRemove(take(range,1));
+ }
+ }
+ assert(equal(list[],[0,1,3]));
+
+ list = IntList([0,1,2,3]);
+ range = list[];
+ for( ; !range.empty; range.popFront())
+ {
+ int item = range.front;
+ if (item == 2)
+ {
+ list.stableLinearRemove(take(range,2));
+ }
+ }
+ assert(equal(list[],[0,1]));
+
+ list = IntList([0,1,2,3]);
+ range = list[];
+ for( ; !range.empty; range.popFront())
+ {
+ int item = range.front;
+ if (item == 0)
+ {
+ list.stableLinearRemove(take(range,2));
+ }
+ }
+ assert(equal(list[],[2,3]));
+
+ list = IntList([0,1,2,3]);
+ range = list[];
+ for( ; !range.empty; range.popFront())
+ {
+ int item = range.front;
+ if (item == 1)
+ {
+ list.stableLinearRemove(take(range,2));
+ }
+ }
+ assert(equal(list[],[0,3]));
+}
+
+unittest
+{
+ auto dl = DList!string(["a", "b", "d"]);
+ dl.insertAfter(dl[], "e"); // insert at the end
+ assert(equal(dl[], ["a", "b", "d", "e"]));
+ auto dlr = dl[];
+ dlr.popBack(); dlr.popBack();
+ dl.insertAfter(dlr, "c"); // insert after "b"
+ assert(equal(dl[], ["a", "b", "c", "d", "e"]));
+}
+
+unittest
+{
+ auto dl = DList!string(["a", "b", "d"]);
+ dl.insertBefore(dl[], "e"); // insert at the front
+ assert(equal(dl[], ["e", "a", "b", "d"]));
+ auto dlr = dl[];
+ dlr.popFront(); dlr.popFront();
+ dl.insertBefore(dlr, "c"); // insert before "b"
+ assert(equal(dl[], ["e", "a", "c", "b", "d"]));
+}
+
+/**
Array type with deterministic control of memory. The memory allocated
for the array is reclaimed as soon as possible; there is no reliance
on the garbage collector. $(D Array) uses $(D malloc) and $(D free)
@@ -2126,7 +2702,7 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
size_t insertBefore(Stuff)(Range r, Stuff stuff)
if (isImplicitlyConvertible!(Stuff, T))
{
- enforce(r._outer._data == _data && r._a < length);
+ enforce(r._outer._data is _data && r._a <= length);
reserve(length + 1);
assert(_data.RefCounted.isInitialized);
// Move elements over by one slot
@@ -2142,7 +2718,7 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
size_t insertBefore(Stuff)(Range r, Stuff stuff)
if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T))
{
- enforce(r._outer._data == _data && r._a <= length);
+ enforce(r._outer._data is _data && r._a <= length);
static if (isForwardRange!Stuff)
{
// Can find the length in advance
@@ -2179,9 +2755,9 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
/// ditto
size_t insertAfter(Stuff)(Range r, Stuff stuff)
{
+ enforce(r._outer._data is _data);
// TODO: optimize
- enforce(_data);
- immutable offset = r.ptr + r.length - _data._payload.ptr;
+ immutable offset = r._b;
enforce(offset <= length);
auto result = insertBack(stuff);
bringToFront(this[offset .. length - result],
@@ -2193,23 +2769,21 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
size_t replace(Stuff)(Range r, Stuff stuff)
if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T))
{
- enforce(_data);
- immutable offset = r.ptr - _data._payload.ptr;
- enforce(offset <= length);
+ enforce(r._outer._data is _data);
size_t result;
for (; !stuff.empty; stuff.popFront())
{
if (r.empty)
{
- // append the rest
- return result + insertBack(stuff);
+ // insert the rest
+ return result + insertBefore(r, stuff);
}
r.front = stuff.front;
r.popFront();
++result;
}
// Remove remaining stuff in r
- remove(r);
+ linearRemove(r);
return result;
}
@@ -2217,6 +2791,7 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
size_t replace(Stuff)(Range r, Stuff stuff)
if (isImplicitlyConvertible!(Stuff, T))
{
+ enforce(r._outer._data is _data);
if (r.empty)
{
insertBefore(r, stuff);
@@ -2225,7 +2800,7 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff)
{
r.front = stuff;
r.popFront();
- remove(r);
+ linearRemove(r);
}
return 1;
}
@@ -2244,6 +2819,7 @@ $(D r)
*/
Range linearRemove(Range r)
{
+ enforce(r._outer._data is _data);
enforce(_data.RefCounted.isInitialized);
enforce(r._a <= r._b && r._b <= length);
immutable offset1 = r._a;
@@ -2425,6 +3001,53 @@ unittest
assert(a[1] == [3,4]);
}
+// test replace!Stuff with range Stuff
+unittest
+{
+ auto a = Array!int([1, 42, 5]);
+ a.replace(a[1 .. 2], [2, 3, 4]);
+ assert(equal(a[], [1, 2, 3, 4, 5]));
+}
+
+// test insertBefore and replace with empty Arrays
+unittest
+{
+ auto a = Array!int();
+ a.insertBefore(a[], 1);
+ assert(equal(a[], [1]));
+}
+unittest
+{
+ auto a = Array!int();
+ a.insertBefore(a[], [1, 2]);
+ assert(equal(a[], [1, 2]));
+}
+unittest
+{
+ auto a = Array!int();
+ a.replace(a[], [1, 2]);
+ assert(equal(a[], [1, 2]));
+}
+unittest
+{
+ auto a = Array!int();
+ a.replace(a[], 1);
+ assert(equal(a[], [1]));
+}
+
+// make sure that Array instances refuse ranges that don't belong to them
+unittest
+{
+ Array!int a = [1, 2, 3];
+ auto r = a.dup[];
+ assertThrown(a.insertBefore(r, 42));
+ assertThrown(a.insertBefore(r, [42]));
+ assertThrown(a.insertAfter(r, 42));
+ assertThrown(a.replace(r, 42));
+ assertThrown(a.replace(r, [42]));
+ assertThrown(a.linearRemove(r));
+}
+
// BinaryHeap
/**
Implements a $(WEB en.wikipedia.org/wiki/Binary_heap, binary heap)
View
57 std/conv.d
@@ -40,8 +40,6 @@ class ConvException : Exception
}
}
-deprecated alias ConvException ConvError; /// ditto
-
private string convError_unexpected(S)(S source) {
return source.empty ? "end of input" : text("'", source.front, "'");
}
@@ -97,7 +95,7 @@ private
if (isSomeString!T)
{
auto w = appender!T();
- FormatSpec!(typeof(T.init[0])) f;
+ FormatSpec!(ElementEncodingType!T) f;
formatValue(w, src, f);
return w.data;
}
@@ -136,8 +134,6 @@ class ConvOverflowException : ConvException
}
}
-deprecated alias ConvOverflowException ConvOverflowError; /// ditto
-
/* **************************************************************
The $(D_PARAM to) family of functions converts a value from type
@@ -784,12 +780,12 @@ $(UL
T toImpl(T, S)(S value)
if (!(isImplicitlyConvertible!(S, T) &&
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
- isSomeString!T)
+ isSomeString!T && !isAggregateType!T)
{
- static if (isSomeString!S && value[0].sizeof == T.init[0].sizeof)
+ static if (isSomeString!S && value[0].sizeof == ElementEncodingType!T.sizeof)
{
// string-to-string with incompatible qualifier conversion
- static if (is(typeof(T.init[0]) == immutable))
+ static if (is(ElementEncodingType!T == immutable))
{
// conversion (mutable|const) -> immutable
return value.idup;
@@ -808,7 +804,7 @@ T toImpl(T, S)(S value)
else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
{
// Converting void array to string
- alias Unqual!(typeof(T.init[0])) Char;
+ alias Unqual!(ElementEncodingType!T) Char;
auto raw = cast(const(ubyte)[]) value;
enforce(raw.length % Char.sizeof == 0,
new ConvException("Alignment mismatch in converting a "
@@ -1125,7 +1121,7 @@ unittest
}
/**
- $(RED Deprecated. It will be removed in December 2012.
+ $(RED Deprecated. It will be removed in January 2013.
Please use $(XREF format, formattedWrite) instead.)
Conversions to string with optional configures.
@@ -1134,7 +1130,7 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T separator = ", ", in T rig
if (!isSomeChar!(ElementType!S) && (isInputRange!S || isInputRange!(Unqual!S)) &&
isSomeString!T)
{
- pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
+ pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));
static if (!isInputRange!S)
@@ -1144,7 +1140,7 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T separator = ", ", in T rig
}
else
{
- alias Unqual!(typeof(T.init[0])) Char;
+ alias Unqual!(ElementEncodingType!T) Char;
// array-to-string conversion
auto result = appender!(Char[])();
result.put(leftBracket);
@@ -1171,7 +1167,7 @@ deprecated T toImpl(T, S)(ref S s, in T leftBracket, in T separator = " ", in T
if ((is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[])) &&
isSomeString!T)
{
- pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
+ pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));
return toImpl(s);
@@ -1182,10 +1178,10 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T keyval = ":", in T separat
if (isAssociativeArray!S &&
isSomeString!T)
{
- pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
+ pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));
- alias Unqual!(typeof(T.init[0])) Char;
+ alias Unqual!(ElementEncodingType!T) Char;
auto result = appender!(Char[])();
// hash-to-string conversion
result.put(leftBracket);
@@ -1208,7 +1204,7 @@ deprecated T toImpl(T, S)(S s, in T nullstr)
if (is(S : Object) &&
isSomeString!T)
{
- pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
+ pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));
if (!s)
@@ -1221,7 +1217,7 @@ deprecated T toImpl(T, S)(S s, in T left, in T separator = ", ", in T right = ")
if (is(S == struct) && !is(typeof(&S.init.toString)) && !isInputRange!S &&
isSomeString!T)
{
- pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
+ pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));
Tuple!(FieldTypeTuple!S) * t = void;
@@ -1229,7 +1225,7 @@ deprecated T toImpl(T, S)(S s, in T left, in T separator = ", ", in T right = ")
{
// ok, attempt to forge the tuple
t = cast(typeof(t)) &s;
- alias Unqual!(typeof(T.init[0])) Char;
+ alias Unqual!(ElementEncodingType!T) Char;
auto app = appender!(Char[])();
app.put(left);
foreach (i, e; t.field)
@@ -1330,7 +1326,7 @@ T toImpl(T, S)(S value)
!isSomeString!S && isDynamicArray!S &&
!isSomeString!T && isArray!T)
{
- alias typeof(T.init[0]) E;
+ alias ArrayTarget!T E;
auto result = new E[value.length];
foreach (i, e; value)
{
@@ -1361,6 +1357,14 @@ unittest
uint[][] e = [ a, a ];
auto f = to!(float[][])(e);
assert(f[0] == b && f[1] == b);
+
+ // Test for bug 8264
+ struct Wrap
+ {
+ string wrap;
+ alias wrap this;
+ }
+ Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work
}
/**
@@ -2589,7 +2593,7 @@ string up one position.
*/
Target parse(Target, Source)(ref Source s)
if (isSomeString!Source &&
- staticIndexOf!(Unqual!Target, dchar, Unqual!(typeof(Source.init[0]))) >= 0)
+ staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
<