summaryrefslogtreecommitdiff
path: root/graphics/asymptote/tests
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/tests')
-rw-r--r--graphics/asymptote/tests/Makefile24
-rw-r--r--graphics/asymptote/tests/TestLib.asy15
-rw-r--r--graphics/asymptote/tests/arith/integer.asy23
-rw-r--r--graphics/asymptote/tests/arith/pair.asy20
-rw-r--r--graphics/asymptote/tests/arith/random.asy11
-rw-r--r--graphics/asymptote/tests/arith/real.asy18
-rw-r--r--graphics/asymptote/tests/arith/roots.asy96
-rw-r--r--graphics/asymptote/tests/arith/transform.asy25
-rw-r--r--graphics/asymptote/tests/arith/triple.asy11
-rw-r--r--graphics/asymptote/tests/array/array.asy49
-rw-r--r--graphics/asymptote/tests/array/delete.asy41
-rw-r--r--graphics/asymptote/tests/array/determinant.asy18
-rw-r--r--graphics/asymptote/tests/array/fields.asy103
-rw-r--r--graphics/asymptote/tests/array/slice.asy232
-rw-r--r--graphics/asymptote/tests/array/solve.asy35
-rw-r--r--graphics/asymptote/tests/array/sort.asy39
-rw-r--r--graphics/asymptote/tests/array/transpose.asy55
-rw-r--r--graphics/asymptote/tests/bench/6000circles.asy17
-rw-r--r--graphics/asymptote/tests/frames/loop.asy196
-rw-r--r--graphics/asymptote/tests/frames/stat.asy14
-rw-r--r--graphics/asymptote/tests/frames/stat2.asy17
-rw-r--r--graphics/asymptote/tests/gc/array.asy5
-rw-r--r--graphics/asymptote/tests/gc/file.asy7
-rw-r--r--graphics/asymptote/tests/gc/funcall.asy6
-rw-r--r--graphics/asymptote/tests/gc/guide.asy5
-rw-r--r--graphics/asymptote/tests/gc/label.asy8
-rw-r--r--graphics/asymptote/tests/gc/path.asy8
-rw-r--r--graphics/asymptote/tests/gc/pen.asy4
-rw-r--r--graphics/asymptote/tests/gc/shipout.asy11
-rw-r--r--graphics/asymptote/tests/gc/string.asy6
-rw-r--r--graphics/asymptote/tests/gc/struct.asy7
-rw-r--r--graphics/asymptote/tests/gc/transform.asy6
-rw-r--r--graphics/asymptote/tests/gs/ghostscript.asy14
-rw-r--r--graphics/asymptote/tests/gsl/random.asy338
-rw-r--r--graphics/asymptote/tests/imp/unravel.asy95
-rw-r--r--graphics/asymptote/tests/output/Makefile41
-rw-r--r--graphics/asymptote/tests/output/circle.asy1
-rw-r--r--graphics/asymptote/tests/output/line.asy1
-rw-r--r--graphics/asymptote/tests/pic/trans.asy75
-rw-r--r--graphics/asymptote/tests/string/erase.asy9
-rw-r--r--graphics/asymptote/tests/string/find.asy8
-rw-r--r--graphics/asymptote/tests/string/insert.asy5
-rw-r--r--graphics/asymptote/tests/string/length.asy6
-rw-r--r--graphics/asymptote/tests/string/rfind.asy8
-rw-r--r--graphics/asymptote/tests/string/substr.asy6
-rw-r--r--graphics/asymptote/tests/types/cast.asy13
-rw-r--r--graphics/asymptote/tests/types/constructor.asy380
-rw-r--r--graphics/asymptote/tests/types/ecast.asy11
-rw-r--r--graphics/asymptote/tests/types/guide.asy160
-rw-r--r--graphics/asymptote/tests/types/init.asy17
-rw-r--r--graphics/asymptote/tests/types/keyword.asy190
-rw-r--r--graphics/asymptote/tests/types/order.asy165
-rw-r--r--graphics/asymptote/tests/types/resolve.asy157
-rw-r--r--graphics/asymptote/tests/types/shadow.asy17
-rw-r--r--graphics/asymptote/tests/types/spec.asy61
-rw-r--r--graphics/asymptote/tests/types/var.asy86
56 files changed, 2996 insertions, 0 deletions
diff --git a/graphics/asymptote/tests/Makefile b/graphics/asymptote/tests/Makefile
new file mode 100644
index 0000000000..659737bfd4
--- /dev/null
+++ b/graphics/asymptote/tests/Makefile
@@ -0,0 +1,24 @@
+.NOTPARALLEL:
+
+TESTDIRS = string arith frames types imp array pic gs
+
+EXTRADIRS = gsl output
+
+test: $(TESTDIRS)
+
+all: $(TESTDIRS) $(EXTRADIRS)
+
+$(TESTDIRS)::
+ @echo
+ ../asy -dir ../base $@/*.asy
+
+$(EXTRADIRS)::
+ @echo
+ ../asy -dir ../base $@/*.asy
+
+clean: FORCE
+ rm -f *.eps
+
+distclean: FORCE clean
+
+FORCE:
diff --git a/graphics/asymptote/tests/TestLib.asy b/graphics/asymptote/tests/TestLib.asy
new file mode 100644
index 0000000000..a4a4b23992
--- /dev/null
+++ b/graphics/asymptote/tests/TestLib.asy
@@ -0,0 +1,15 @@
+bool close(pair a, pair b)
+{
+ real norm=(b == 0) ? 1 : max(abs(a),abs(b));
+ return abs(a-b) <= 100*realEpsilon*norm;
+}
+
+void StartTest(string desc)
+{
+ write("Testing " + desc + "...",flush);
+}
+
+void EndTest()
+{
+ write("PASSED.");
+}
diff --git a/graphics/asymptote/tests/arith/integer.asy b/graphics/asymptote/tests/arith/integer.asy
new file mode 100644
index 0000000000..b5c337d273
--- /dev/null
+++ b/graphics/asymptote/tests/arith/integer.asy
@@ -0,0 +1,23 @@
+// Integer arithmetic.
+import TestLib;
+StartTest("integer addition");
+assert(1+1==2);
+EndTest();
+StartTest("integer subtraction");
+assert(2-1==1);
+EndTest();
+StartTest("integer multiplication");
+assert(2*2==4);
+EndTest();
+StartTest("integer division");
+assert(4/2==2);
+EndTest();
+StartTest("integer self ops");
+{ int x = 3; assert(++x==4); assert(x==4); }
+{ int x = 3; assert(--x==2); assert(x==2); }
+{ int x = 3; assert((x+=7) == 10); assert(x==10); }
+{ int x = 3; assert((x-=7) == -4); assert(x==-4); }
+{ int x = 3; assert((x*=7) == 21); assert(x==21); }
+{ int x = 10; assert((x%=4) == 2); assert(x==2); }
+EndTest();
+
diff --git a/graphics/asymptote/tests/arith/pair.asy b/graphics/asymptote/tests/arith/pair.asy
new file mode 100644
index 0000000000..c815f28b2f
--- /dev/null
+++ b/graphics/asymptote/tests/arith/pair.asy
@@ -0,0 +1,20 @@
+import TestLib;
+
+StartTest("complex addition");
+assert((1,0)+(0,1)==(1,1));
+EndTest();
+StartTest("complex subtraction");
+assert((1,0)-(0,1)==(1,-1));
+EndTest();
+StartTest("complex multiplication");
+assert((1,2)*(2,1)==(0,5));
+EndTest();
+StartTest("complex division");
+assert((0,5)/(2,1)==(1,2));
+EndTest();
+StartTest("length(pair)");
+assert(length((0.0,1.0)) == 1.0);
+EndTest();
+StartTest("conj()");
+assert(conj((0.0,1.0))==(0.0, -1.0));
+EndTest();
diff --git a/graphics/asymptote/tests/arith/random.asy b/graphics/asymptote/tests/arith/random.asy
new file mode 100644
index 0000000000..c972744da4
--- /dev/null
+++ b/graphics/asymptote/tests/arith/random.asy
@@ -0,0 +1,11 @@
+import TestLib;
+StartTest("random");
+bool bit32=false;
+for(int i=0; i < 1000; ++i) {
+ real x=unitrand();
+ if(x > 0.5) bit32=true;
+ assert(x >= 0.0 && x <= 1.0);
+}
+assert(bit32);
+
+EndTest();
diff --git a/graphics/asymptote/tests/arith/real.asy b/graphics/asymptote/tests/arith/real.asy
new file mode 100644
index 0000000000..1628258cf8
--- /dev/null
+++ b/graphics/asymptote/tests/arith/real.asy
@@ -0,0 +1,18 @@
+// Real arithmetic.
+
+import TestLib;
+StartTest("real error");
+assert((1.0-1.0) < realEpsilon);
+EndTest();
+StartTest("real addition");
+assert((1.0+1.0) == (2.0));
+EndTest();
+StartTest("real subtraction");
+assert((2.0-1.0) == (1.0));
+EndTest();
+StartTest("real multiplication");
+assert((2.0*2.0) == (4.0));
+EndTest();
+StartTest("real division");
+assert((4.0/2.0) == (2.0));
+EndTest();
diff --git a/graphics/asymptote/tests/arith/roots.asy b/graphics/asymptote/tests/arith/roots.asy
new file mode 100644
index 0000000000..d3e5d55f36
--- /dev/null
+++ b/graphics/asymptote/tests/arith/roots.asy
@@ -0,0 +1,96 @@
+// Roots.
+
+import TestLib;
+real x;
+real[] r;
+
+StartTest("quadratic roots");
+
+r=quadraticroots(1,0,-8);
+assert(r.length == 2);
+r=sort(r);
+x=2sqrt(2);
+assert(close(r[0],-x));
+assert(close(r[1],x));
+
+r=quadraticroots(1,2,1);
+assert(r.length == 2);
+assert(close(r[0],-1));
+assert(close(r[1],-1));
+
+r=quadraticroots(1,0,8);
+assert(r.length == 0);
+
+r=quadraticroots(0,2,3);
+assert(r.length == 1);
+assert(close(r[0],-3/2));
+
+EndTest();
+
+StartTest("cubic roots");
+
+r=cubicroots(1,0,0,-8);
+assert(r.length == 1);
+assert(close(r[0],2));
+
+real[] r=cubicroots(1,3,3,1);
+assert(r.length == 3);
+assert(close(r[0],-1));
+assert(close(r[1],-1));
+assert(close(r[2],-1));
+
+real[] r=cubicroots(1,-3,3,-1);
+assert(r.length == 3);
+assert(close(r[0],1));
+assert(close(r[1],1));
+assert(close(r[2],1));
+
+r=cubicroots(1,0,0,0);
+assert(r.length == 3);
+assert(r[0] == 0);
+assert(r[1] == 0);
+assert(r[2] == 0);
+
+r=cubicroots(1,0,-15,-4);
+assert(r.length == 3);
+r=sort(r);
+assert(close(r[0],-2-sqrt(3)));
+assert(close(r[1],-2+sqrt(3)));
+assert(close(r[2],4));
+
+r=cubicroots(1,0,-15,4);
+assert(r.length == 3);
+r=sort(r);
+assert(close(r[0],-4));
+assert(close(r[1],2-sqrt(3)));
+assert(close(r[2],2+sqrt(3)));
+
+r=cubicroots(1,0,-15,0);
+assert(r.length == 3);
+r=sort(r);
+x=sqrt(15);
+assert(close(r[0],-x));
+assert(r[1] == 0);
+assert(close(r[2],x));
+
+r=cubicroots(1,1,1,0);
+assert(r.length == 1);
+assert(r[0] == 0);
+
+r=cubicroots(1,0,20,-4);
+assert(r.length == 1);
+x=cbrt(54+6sqrt(6081));
+assert(close(r[0],x/3-20/x));
+
+EndTest();
+
+StartTest("newton");
+
+real f(real x) {return cos(x);}
+real dfdx(real x) {return -sin(x);}
+
+assert(close(newton(f,dfdx,1),pi/2));
+assert(newton(f,dfdx,0) == realMax);
+assert(newton(f,dfdx,0,2) == pi/2);
+
+EndTest();
diff --git a/graphics/asymptote/tests/arith/transform.asy b/graphics/asymptote/tests/arith/transform.asy
new file mode 100644
index 0000000000..e4e44e387b
--- /dev/null
+++ b/graphics/asymptote/tests/arith/transform.asy
@@ -0,0 +1,25 @@
+import TestLib;
+pair x = (1, 2);
+StartTest("identity transform");
+assert(identity()*x == x);
+EndTest();
+StartTest("shift transform");
+assert(shift((1,1))*x == (2, 3));
+assert(shift(1,1)*x == (2, 3));
+EndTest();
+StartTest("scaling transforms");
+assert(xscale(2)*x == (2, 2));
+assert(yscale(2)*x == (1, 4));
+assert(scale(2)*x == (2, 4));
+EndTest();
+StartTest("slant transform");
+assert(slant(1)*x == (3, 2));
+EndTest();
+StartTest("rotation transform");
+assert(length((rotate(90)*x) - (-2,1)) <= realEpsilon);
+assert(rotate(90, x)*x == x);
+EndTest();
+StartTest("reflect transform");
+assert(reflect((-1, -1), (1, 1))*x == (2, 1));
+EndTest();
+
diff --git a/graphics/asymptote/tests/arith/triple.asy b/graphics/asymptote/tests/arith/triple.asy
new file mode 100644
index 0000000000..135801b633
--- /dev/null
+++ b/graphics/asymptote/tests/arith/triple.asy
@@ -0,0 +1,11 @@
+import TestLib;
+triple t = (1,0,0);
+StartTest("polar()");
+assert(polar(t) == (pi / 2.0) );
+EndTest();
+StartTest("azimuth()");
+assert(azimuth(t) < realEpsilon);
+EndTest();
+StartTest("unit()");
+assert(length(t-unit(t)) < realEpsilon);
+EndTest();
diff --git a/graphics/asymptote/tests/array/array.asy b/graphics/asymptote/tests/array/array.asy
new file mode 100644
index 0000000000..106856fd80
--- /dev/null
+++ b/graphics/asymptote/tests/array/array.asy
@@ -0,0 +1,49 @@
+import TestLib;
+
+StartTest("array");
+
+{
+ int[] x=array(10, 7);
+ assert(x.length == 10);
+ for (int i=0; i<x.length; ++i)
+ assert(x[i] == 7);
+}
+{
+ int[][] y=array(10, array(10, 7));
+ assert(y.length == 10);
+ for (int i=0; i<y.length; ++i) {
+ assert(y[i].length == 10);
+ for (int j=0; j<y[i].length; ++j)
+ assert(y[i][j] == 7);
+ }
+}
+{
+ int[][] y=array(10, array(10, 7));
+ y[4][5] = 9;
+ assert(y.length == 10);
+ for (int i=0; i<y.length; ++i) {
+ assert(y[i].length == 10);
+ for (int j=0; j<y[i].length; ++j)
+ if (i==4 && j==5)
+ assert(y[i][j] == 9);
+ else
+ assert(y[i][j] == 7);
+ }
+}
+{
+ int[][] y=array(10, array(10, 7), depth=0);
+ y[4][5] = 9;
+ assert(y.length == 10);
+ for (int i=0; i<y.length; ++i) {
+ assert(y[i].length == 10);
+ for (int j=0; j<y[i].length; ++j)
+ if (j==5)
+ assert(y[i][j] == 9);
+ else
+ assert(y[i][j] == 7);
+ }
+}
+
+
+
+EndTest();
diff --git a/graphics/asymptote/tests/array/delete.asy b/graphics/asymptote/tests/array/delete.asy
new file mode 100644
index 0000000000..d92a3c082c
--- /dev/null
+++ b/graphics/asymptote/tests/array/delete.asy
@@ -0,0 +1,41 @@
+import TestLib;
+import math;
+
+StartTest("delete");
+
+int[] a=sequence(4);
+a.delete(2);
+assert(all(a == new int[] {0,1,3}));
+
+int[] a=sequence(4);
+a.delete(0,2);
+assert(all(a == new int[] {3}));
+
+int[] a=sequence(4);
+a.delete(1,2);
+assert(all(a == new int[] {0,3}));
+
+int[] a=sequence(4);
+a.delete(2,2);
+assert(all(a == new int[] {0,1,3}));
+
+int[] a=sequence(4);
+a.delete(2,3);
+assert(all(a == new int[] {0,1}));
+
+int[] a=sequence(4);
+a.cyclic=true;
+a.delete(2,3);
+assert(all(a == new int[] {0,1}));
+
+int[] a=sequence(4);
+a.cyclic=true;
+a.delete(2,4);
+assert(all(a == new int[] {1}));
+
+int[] a=sequence(4);
+a.cyclic=true;
+a.delete(3,1);
+assert(all(a == new int[] {2}));
+
+EndTest();
diff --git a/graphics/asymptote/tests/array/determinant.asy b/graphics/asymptote/tests/array/determinant.asy
new file mode 100644
index 0000000000..e6086d0b04
--- /dev/null
+++ b/graphics/asymptote/tests/array/determinant.asy
@@ -0,0 +1,18 @@
+import TestLib;
+import math;
+
+StartTest("determinant");
+assert(determinant(new real[][] {{0}}) == 0);
+assert(determinant(new real[][] {{1}}) == 1);
+assert(determinant(new real[][] {{1,2},{3,4}}) == -2);
+real e=1e-20;
+assert(close(determinant(new real[][] {{1e,2e},{3e,4e}}),-2e-40));
+assert(close(determinant(new real[][] {{1,2,3},{4,5,6},{7,8,9}}),0));
+assert(close(determinant(new real[][] {{1,2},{1,2}}),0));
+assert(close(determinant(new real[][] {{1,2,3,4},
+ {5,6,7,8},{9,10,11,12},{13,14,15,16}}),0));
+assert(close(determinant(new real[][] {{1,2,3,4},
+ {5,0,7,8},{9,10,0,12},{13,14,15,16}}),-2376));
+assert(close(determinant(new real[][]{{1,-2,3,0},{4,-5,6,2},{-7,-8,10,5},
+ {1,50,1,-2}}),-4588));
+EndTest();
diff --git a/graphics/asymptote/tests/array/fields.asy b/graphics/asymptote/tests/array/fields.asy
new file mode 100644
index 0000000000..9b5926d374
--- /dev/null
+++ b/graphics/asymptote/tests/array/fields.asy
@@ -0,0 +1,103 @@
+import TestLib;
+
+StartTest("fields");
+
+{
+ int[] z = {1, 2, 3};
+ assert(z.length == 3);
+ int[] keys = z.keys;
+ assert(keys.length == 3);
+ for (int i; i<3; ++i)
+ assert(keys[i] == i);
+ for (int j = 0; j < 10; ++j) {
+ assert(z.cyclic == false);
+ z.cyclic=true;
+ assert(z.cyclic == true);
+ z.cyclic=false;
+ }
+}
+
+{
+ int[] z = {2, 3, 5};
+ for (int k = -100; k <= 100; ++k)
+ assert(z.initialized(k) == (k >= 0 && k < 3));
+}
+
+{
+ int[] z;
+ for (int i=0; i<10; ++i) {
+ for (int k = 0; k <= 100; ++k) {
+ assert(z.length == k);
+ z.push(k*k+3k+1);
+ assert(z.length == k+1);
+ }
+ for (int k = 100; k >= 0; --k) {
+ assert(z.length == k+1);
+ assert(z.pop() == k*k+3k+1);
+ assert(z.length == k);
+ }
+ }
+ z.cyclic=true;
+ for (int i=0; i<10; ++i) {
+ for (int k = 0; k <= 100; ++k) {
+ assert(z.length == k);
+ z.push(k*k+3k+1);
+ assert(z.length == k+1);
+ }
+ for (int k = 100; k >= 0; --k) {
+ assert(z.length == k+1);
+ z.delete(quotient(k,2));
+ assert(z.length == k);
+ }
+ }
+}
+
+{
+ int[] base={4,5,9,5,0,2,3};
+ int[] z;
+ for (int i=0; i<9; ++i) {
+ assert(z.length == i*base.length);
+ for (int j : z.keys)
+ assert(z[j] == base[j%base.length]);
+ z.append(base);
+ }
+}
+
+{
+ int[] z = {1,2,3,4,6,7,8,9};
+ assert(z.length == 8);
+ z.insert(4, 5);
+ assert(z.length == 9);
+ z.insert(0, 0);
+ assert(z.length == 10);
+ for (int i=0; i<10; ++i)
+ assert(z[i] == i);
+ z.insert(7, 100, 101, 102, 103);
+ assert(z.length == 14);
+
+ // TODO: Test inserting/deleting lengths more seriously.
+}
+
+{
+ // Test extended for.
+ int[] a = {1,4,6,2,7,4,8,9,1,3,-1};
+ int i = 0;
+ for (int x : a) {
+ assert(x == a[i]);
+ ++i;
+ }
+ assert(i == a.length);
+}
+
+{
+ // Test extended for.
+ int[] a = {1,4,6,2,7,4,8,9,1,3,-1};
+ int i = 0;
+ for (var x : a) {
+ assert(x == a[i]);
+ ++i;
+ }
+ assert(i == a.length);
+}
+
+EndTest();
diff --git a/graphics/asymptote/tests/array/slice.asy b/graphics/asymptote/tests/array/slice.asy
new file mode 100644
index 0000000000..9010f0b5d8
--- /dev/null
+++ b/graphics/asymptote/tests/array/slice.asy
@@ -0,0 +1,232 @@
+import TestLib;
+
+StartTest("slice");
+
+int[] x={0,1,2,3,4,5,6,7,8,9};
+
+// Non-cyclic cases.
+assert(all(x[:] == x));
+assert(!alias(x[:],x));
+
+assert(all(x[0:4] == new int[] {0,1,2,3} ));
+assert(all(x[2:4] == new int[] {2,3} ));
+
+assert(all(x[5:] == new int[] {5,6,7,8,9} ));
+assert(all(x[:5] == new int[] {0,1,2,3,4} ));
+
+assert(all(x[3:3] == new int[] {} ));
+assert(all(x[3:4] == new int[] {3} ));
+assert(all(x[98:99] == new int[] {} ));
+
+assert(x[:].cyclic == false);
+assert(x[2:].cyclic == false);
+assert(x[:7].cyclic == false);
+assert(x[3:3].cyclic == false);
+assert(x[2:9].cyclic == false);
+
+// Cyclic cases
+x.cyclic=true;
+
+assert(all(x[:] == new int[] {0,1,2,3,4,5,6,7,8,9} ));
+assert(all(x[0:4] == new int[] {0,1,2,3} ));
+assert(all(x[2:4] == new int[] {2,3} ));
+
+assert(all(x[5:] == new int[] {5,6,7,8,9} ));
+assert(all(x[-5:] == new int[] {5,6,7,8,9,0,1,2,3,4,5,6,7,8,9} ));
+assert(all(x[:5] == new int[] {0,1,2,3,4} ));
+
+assert(all(x[3:3] == new int[] {} ));
+assert(all(x[3:4] == new int[] {3} ));
+
+assert(all(x[-1:1] == new int[] {9,0} ));
+assert(all(x[9:11] == new int[] {9,0} ));
+assert(all(x[9:21] == new int[] {9,0,1,2,3,4,5,6,7,8,9,0} ));
+assert(all(x[-15:15] == new int[] {5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
+ 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4}));
+assert(all(x[6728:6729] == new int[] {8} ));
+assert(all(x[-6729:-6728] == new int[] {1} ));
+
+assert(x[:].cyclic == false);
+assert(x[2:].cyclic == false);
+assert(x[:7].cyclic == false);
+assert(x[3:3].cyclic == false);
+assert(x[2:9].cyclic == false);
+assert(x[5:100].cyclic == false);
+
+pair[] z={(1,2), (3,4), (5,6)};
+assert(all(z[1:1] == new pair[] {}));
+assert(all(z[:1] == new pair[] {(1,2)}));
+assert(all(z[1:] == new pair[] {(3,4), (5,6)}));
+assert(all(z[:] == z));
+assert(all(z[1:2] == new pair[] {(3,4)}));
+
+// Writing tests.
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ int[] z={56,67,78};
+
+ y[:] = z;
+ assert(all(y == z));
+ assert(!alias(y,z));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ int[] z={56,67,78};
+ z.cyclic=true;
+
+ y[:] = z;
+ assert(all(y == z));
+ assert(!alias(y,z));
+ assert(y.cyclic == false);
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+
+ y[2:3] = y[5:6] = new int[] {77};
+ assert(all(y == new int[] {0,1,77,3,4,77,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+
+ y[:3] = y[7:] = new int[] {};
+ assert(all(y == new int[] {3,4,5,6}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+
+ y[3:5] = new int[] {13,14,15,16,17};
+ assert(all(y == new int[] {0,1,2,13,14,15,16,17,5,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+ int[] z={56,67,78};
+
+ y[:] = z;
+ assert(all(y == z));
+ assert(!alias(y,z));
+ assert(y.cyclic == true);
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+ int[] z={56,67,78};
+ z.cyclic=true;
+
+ y[:] = z;
+ assert(all(y == z));
+ assert(!alias(y,z));
+ assert(y.cyclic == true);
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[2:3] = y[5:6] = new int[] {77};
+ assert(all(y == new int[] {0,1,77,3,4,77,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[:3] = y[7:] = new int[] {};
+ assert(all(y == new int[] {3,4,5,6}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[8:] = new int[] {18,19,20,21,22};
+ assert(all(y == new int[] {0,1,2,3,4,5,6,7,18,19,20,21,22}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[-2:0] = new int[] {18,19,20,21,22};
+ assert(all(y == new int[] {0,1,2,3,4,5,6,7,18,19,20,21,22}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[18:20] = new int[] {18,19,20,21,22};
+ assert(all(y == new int[] {0,1,2,3,4,5,6,7,18,19,20,21,22}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[3:5] = new int[] {13,14,15,16,17};
+ assert(all(y == new int[] {0,1,2,13,14,15,16,17,5,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[13:15] = new int[] {13,14,15,16,17};
+ assert(all(y == new int[] {0,1,2,13,14,15,16,17,5,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[3-10:5-10] = new int[] {13,14,15,16,17};
+ assert(all(y == new int[] {0,1,2,13,14,15,16,17,5,6,7,8,9}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[8:12] = new int[] {18,19,20,21};
+ assert(all(y == new int[] {20,21,2,3,4,5,6,7,18,19}));
+}
+{
+ int[] y={0,1,2,3,4,5,6,7,8,9};
+ y.cyclic=true;
+
+ y[-2:2] = new int[] {18,19,20,21};
+ assert(all(y == new int[] {20,21,2,3,4,5,6,7,18,19}));
+}
+
+// Side Effect Test
+{
+ int state=0;
+ int[] x={0,1,2,3,4,5,6,7,8,9};
+
+ int[] a() {
+ assert(state==0);
+ ++state;
+
+ return x;
+ }
+
+ int l() {
+ assert(state==1);
+ ++state;
+
+ return 2;
+ }
+
+ int r() {
+ assert(state==2);
+ ++state;
+
+ return 6;
+ }
+
+ int[] b() {
+ assert(state==3);
+ ++state;
+
+ return new int[] {77,77};
+ }
+
+ assert(state==0);
+ a()[l():r()]=b();
+ assert(state==4);
+ assert(all(x == new int[] {0,1,77,77,6,7,8,9}));
+}
+
+
+EndTest();
diff --git a/graphics/asymptote/tests/array/solve.asy b/graphics/asymptote/tests/array/solve.asy
new file mode 100644
index 0000000000..ec1c4416ba
--- /dev/null
+++ b/graphics/asymptote/tests/array/solve.asy
@@ -0,0 +1,35 @@
+import TestLib;
+
+StartTest("solve");
+real[][] a=new real[][] {{1,1,1},{1,2,2},{0,0,1}};
+real[][] b=new real[][] {{3,9},{5,11},{1,3}};
+real[][] x=new real[][] {{1,7},{1,-1,},{1,3}};
+real[][] c=solve(a,b);
+for(int i=0; i < c.length; ++i)
+ for(int j=0; j < c[i].length; ++j)
+ assert(close(c[i][j],x[i][j]));
+
+real[][] a={{1,-2,3,0},{4,-5,6,2},{-7,-8,10,5},{1,50,1,-2}};
+real[] b={7,19,33,3};
+real[] x=solve(a,b);
+real[] c=a*x;
+for(int i=0; i < c.length; ++i)
+ assert(close(c[i],b[i]));
+EndTest();
+
+StartTest("inverse");
+real[][] a=new real[][] {{1,1,1},{1,2,2},{0,0,1}};
+real[][] ainverse=new real[][] {{2,-1,0},{-1,1,-1},{0,0,1}};
+real[][] d=inverse(a);
+real[][] l=d*a;
+real[][] r=a*d;
+real[][] I=identity(a.length);
+for(int i=0; i < d.length; ++i) {
+ for(int j=0; j < d[i].length; ++j) {
+ assert(close(d[i][j],ainverse[i][j]));
+ assert(I[i][j] == (i == j ? 1 : 0));
+ assert(close(l[i][j],I[i][j]));
+ assert(close(r[i][j],I[i][j]));
+ }
+}
+EndTest();
diff --git a/graphics/asymptote/tests/array/sort.asy b/graphics/asymptote/tests/array/sort.asy
new file mode 100644
index 0000000000..03c585b717
--- /dev/null
+++ b/graphics/asymptote/tests/array/sort.asy
@@ -0,0 +1,39 @@
+import TestLib;
+import math;
+
+string[] a={"bob","alice","pete","alice"};
+string[] b={"alice","alice","bob","pete"};
+
+StartTest("sort");
+
+assert(all(sort(a) == b));
+
+EndTest();
+
+StartTest("search");
+
+assert(search(b,"a") == -1);
+assert(search(b,"bob") == 2);
+assert(search(b,"z") == b.length-1);
+
+EndTest();
+
+StartTest("sort2");
+
+string[][] a={{"bob","9"},{"alice","5"},{"pete","7"},{"alice","4"}};
+string[][] b={{"alice","4"},{"alice","5"},{"bob","9"},{"pete","7"}};
+
+assert(sort(a) == b);
+
+EndTest();
+
+pair[] a={(2,1),(0,0),(1,1),(1,0)};
+pair[] b={(0,0),(1,0),(1,1),(2,1)};
+
+StartTest("lexicographical sort");
+assert(all(sort(a,lexorder) == b));
+EndTest();
+
+StartTest("lexicographical search");
+assert(search(b,(1,0),lexorder) == 1);
+EndTest();
diff --git a/graphics/asymptote/tests/array/transpose.asy b/graphics/asymptote/tests/array/transpose.asy
new file mode 100644
index 0000000000..f0366ba8fd
--- /dev/null
+++ b/graphics/asymptote/tests/array/transpose.asy
@@ -0,0 +1,55 @@
+import TestLib;
+import math;
+
+StartTest("transpose");
+int n=3;
+real[][] a=new real[n][n];
+real[][] b=new real[n][n];
+for(int i=0; i < n; ++i) {
+ for(int j=0; j < n; ++j) {
+ a[i][j]=b[j][i]=rand();
+ }
+}
+
+bool operator == (real[][] a, real[][] b)
+{
+ int n=a.length;
+ for(int i=0; i < n; ++i)
+ if(!all(a[i] == b[i])) return false;
+ return true;
+}
+
+bool operator == (real[][][] a, real[][][] b)
+{
+ int n=a.length;
+ for(int i=0; i < n; ++i) {
+ real[][] ai=a[i];
+ real[][] bi=b[i];
+ int m=ai.length;
+ for(int j=0; j < m; ++j) {
+ if(!all(ai[j] == bi[j])) return false;
+ }
+ }
+ return true;
+}
+
+assert(a == transpose(b));
+
+int n=3;
+real[][][] a=new real[n][n][n];
+real[][][] b=new real[n][n][n];
+real[][][] c=new real[n][n][n];
+real[][][] d=new real[n][n][n];
+for(int i=0; i < n; ++i) {
+ for(int j=0; j < n; ++j) {
+ for(int k=0; k < n; ++k) {
+ a[i][j][k]=b[j][i][k]=c[i][k][j]=d[k][j][i]=rand();
+ }
+ }
+}
+
+assert(a == transpose(b,new int[] {1,0,2}));
+assert(a == transpose(c,new int[] {0,2,1}));
+assert(a == transpose(d,new int[] {2,1,0}));
+
+EndTest();
diff --git a/graphics/asymptote/tests/bench/6000circles.asy b/graphics/asymptote/tests/bench/6000circles.asy
new file mode 100644
index 0000000000..53ebecce27
--- /dev/null
+++ b/graphics/asymptote/tests/bench/6000circles.asy
@@ -0,0 +1,17 @@
+size(0,100);
+import math;
+import stats;
+
+currentpen=magenta;
+// A centered random number
+real crand() {return unitrand()*5;}
+
+real r1;
+pair pcenter;
+
+for(int i=0; i < 6000; ++i) {
+
+r1 = unitrand()/10;
+pcenter = ( crand(), crand());
+Draw(circle(pcenter,r1));
+}
diff --git a/graphics/asymptote/tests/frames/loop.asy b/graphics/asymptote/tests/frames/loop.asy
new file mode 100644
index 0000000000..a4714d1f8d
--- /dev/null
+++ b/graphics/asymptote/tests/frames/loop.asy
@@ -0,0 +1,196 @@
+import TestLib;
+StartTest("loop");
+
+int f();
+for (int i=0; i<10; ++i) {
+ int x=i;
+ for (int j=0; j<10; ++j) {
+ int y=j;
+ if (i==5 && j==7) {
+ f = new int () { return x*y; };
+ }
+ }
+}
+assert(f()==35);
+
+int f();
+
+for (int i=0; i<10; ++i) {
+ int x=i;
+ for (int j=0; j<10; ++j) {
+ int y=j;
+ if (i==5 && j==7) {
+ f = new int () { return i*y; };
+ }
+ }
+}
+assert(f()==70);
+
+{
+ int y = 3;
+ int z = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ ++z;
+ continue;
+ y = 4;
+ }
+ assert(y == 3);
+ assert(z == 7);
+}
+{
+ int y = 3;
+ int z = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ ++z;
+ break;
+ y = 4;
+ }
+ assert(y == 3);
+ assert(z == 1);
+}
+{
+ int y = 3;
+ int z = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ void g() {}
+ ++z;
+ continue;
+ y = 4;
+ }
+ assert(y == 3);
+ assert(z == 7);
+}
+{
+ int y = 3;
+ int z = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ void g() {}
+ ++z;
+ break;
+ y = 4;
+ }
+ assert(y == 3);
+ assert(z == 1);
+}
+
+// While loops
+{
+ int y = 7;
+ int z = 0;
+ while (z < 10) {
+ ++z;
+ continue;
+ ++y;
+ }
+ assert(z == 10);
+ assert(y == 7);
+}
+
+{
+ int y = 7;
+ int z = 0;
+ while (z < 10) {
+ void g() {}
+ ++z;
+ continue;
+ ++y;
+ }
+ assert(z == 10);
+ assert(y == 7);
+}
+
+{
+ int y = 7;
+ int z = 0;
+ while (z < 10) {
+ ++z;
+ break;
+ ++y;
+ }
+ assert(z == 1);
+ assert(y == 7);
+}
+
+{
+ int y = 7;
+ int z = 0;
+ while (z < 10) {
+ void g() {}
+ ++z;
+ break;
+ ++y;
+ }
+ assert(z == 1);
+ assert(y == 7);
+}
+
+
+{
+ int y = 7;
+ int z = 0;
+ while (z < 10) {
+ ++z;
+ continue;
+ ++y;
+ }
+ assert(z == 10);
+ assert(y == 7);
+}
+
+// Do loops
+{
+ int y = 7;
+ int z = 0;
+ do {
+ void g() {}
+ ++z;
+ continue;
+ ++y;
+ } while (z < 10);
+ assert(z == 10);
+ assert(y == 7);
+}
+
+{
+ int y = 7;
+ int z = 0;
+ do {
+ ++z;
+ break;
+ ++y;
+ } while (z < 10);
+ assert(z == 1);
+ assert(y == 7);
+}
+
+{
+ int y = 7;
+ int z = 0;
+ do {
+ void g() {}
+ ++z;
+ break;
+ ++y;
+ } while (z < 10);
+ assert(z == 1);
+ assert(y == 7);
+}
+
+{
+ int x = 456;
+ do { x = 123; } while (false);
+ assert(x == 123);
+}
+
+{
+ int x = 456;
+ do { void g() {} x = 123; } while (false);
+ assert(x == 123);
+}
+
+
+EndTest();
diff --git a/graphics/asymptote/tests/frames/stat.asy b/graphics/asymptote/tests/frames/stat.asy
new file mode 100644
index 0000000000..d366b193e0
--- /dev/null
+++ b/graphics/asymptote/tests/frames/stat.asy
@@ -0,0 +1,14 @@
+import TestLib;
+StartTest("stat");
+struct T {
+ int x;
+ static void f(T t) {
+ t.x=2;
+ }
+}
+
+T t=new T;
+assert(t.x==0);
+T.f(t);
+assert(t.x==2);
+EndTest();
diff --git a/graphics/asymptote/tests/frames/stat2.asy b/graphics/asymptote/tests/frames/stat2.asy
new file mode 100644
index 0000000000..ea5863b081
--- /dev/null
+++ b/graphics/asymptote/tests/frames/stat2.asy
@@ -0,0 +1,17 @@
+import TestLib;
+StartTest("stat2");
+struct T {
+ int x;
+ static void f(T t) {
+ static void g(T t) {
+ t.x=2;
+ }
+ g(t);
+ }
+}
+
+T t=new T;
+assert(t.x==0);
+T.f(t);
+assert(t.x==2);
+EndTest();
diff --git a/graphics/asymptote/tests/gc/array.asy b/graphics/asymptote/tests/gc/array.asy
new file mode 100644
index 0000000000..43e3f9224c
--- /dev/null
+++ b/graphics/asymptote/tests/gc/array.asy
@@ -0,0 +1,5 @@
+real[] a;
+for (int i = 0; i < 1e9; ++i)
+{
+ a=new real[10];
+}
diff --git a/graphics/asymptote/tests/gc/file.asy b/graphics/asymptote/tests/gc/file.asy
new file mode 100644
index 0000000000..14dacd02b8
--- /dev/null
+++ b/graphics/asymptote/tests/gc/file.asy
@@ -0,0 +1,7 @@
+for (int i = 0; i < 1e7; ++i)
+{
+ file a=output("out/"+(string) i);
+ write(a,i,endl);
+ close(a);
+}
+
diff --git a/graphics/asymptote/tests/gc/funcall.asy b/graphics/asymptote/tests/gc/funcall.asy
new file mode 100644
index 0000000000..42661c79e3
--- /dev/null
+++ b/graphics/asymptote/tests/gc/funcall.asy
@@ -0,0 +1,6 @@
+void g()
+{}
+for (int i = 0; i < 1e9; ++i)
+{
+ g();
+}
diff --git a/graphics/asymptote/tests/gc/guide.asy b/graphics/asymptote/tests/gc/guide.asy
new file mode 100644
index 0000000000..bf00543106
--- /dev/null
+++ b/graphics/asymptote/tests/gc/guide.asy
@@ -0,0 +1,5 @@
+guide a=(0,0);
+for (int i = 0; i < 1e9; ++i)
+{
+ guide b=a--a;
+}
diff --git a/graphics/asymptote/tests/gc/label.asy b/graphics/asymptote/tests/gc/label.asy
new file mode 100644
index 0000000000..d378a3efa6
--- /dev/null
+++ b/graphics/asymptote/tests/gc/label.asy
@@ -0,0 +1,8 @@
+guide a;
+for (int i = 0; i < 1e7; ++i)
+{
+ picture pic;
+ size(pic,10cm,20cm);
+ draw(pic,"a",scale(2)*(0,0)--(1,1));
+ shipout("out/",pic);
+}
diff --git a/graphics/asymptote/tests/gc/path.asy b/graphics/asymptote/tests/gc/path.asy
new file mode 100644
index 0000000000..118826eba1
--- /dev/null
+++ b/graphics/asymptote/tests/gc/path.asy
@@ -0,0 +1,8 @@
+guide a;
+for (int i = 0; i < 1e7; ++i)
+{
+// guide a=a--(1.0,2.0);
+ path p=(1.0,2.0);
+ path q=(3.0,4.0);
+ path a=p--q;
+}
diff --git a/graphics/asymptote/tests/gc/pen.asy b/graphics/asymptote/tests/gc/pen.asy
new file mode 100644
index 0000000000..691cf6dea8
--- /dev/null
+++ b/graphics/asymptote/tests/gc/pen.asy
@@ -0,0 +1,4 @@
+for (int i = 0; i < 1e7; ++i)
+{
+ pen p = linetype(new real[] {1,2});
+}
diff --git a/graphics/asymptote/tests/gc/shipout.asy b/graphics/asymptote/tests/gc/shipout.asy
new file mode 100644
index 0000000000..e2e9c8c7da
--- /dev/null
+++ b/graphics/asymptote/tests/gc/shipout.asy
@@ -0,0 +1,11 @@
+guide a;
+for (int i = 0; i < 1e7; ++i)
+{
+ picture pic;
+ size(pic,10cm,20cm);
+ path p=(1.0,2.0);
+ path q=(3.0,4.0);
+ path a=p..q..(3,5);
+ draw(pic,a,blue+dashed);
+ shipout("out/",pic);
+}
diff --git a/graphics/asymptote/tests/gc/string.asy b/graphics/asymptote/tests/gc/string.asy
new file mode 100644
index 0000000000..f379b86224
--- /dev/null
+++ b/graphics/asymptote/tests/gc/string.asy
@@ -0,0 +1,6 @@
+string a="abc";
+for (int i = 0; i < 1e7; ++i)
+{
+ "a"+"b";
+ a=reverse(a);
+}
diff --git a/graphics/asymptote/tests/gc/struct.asy b/graphics/asymptote/tests/gc/struct.asy
new file mode 100644
index 0000000000..11a007140d
--- /dev/null
+++ b/graphics/asymptote/tests/gc/struct.asy
@@ -0,0 +1,7 @@
+for (int i = 0; i < 1e7; ++i)
+{
+ picture pic;
+ unitsize(pic, 0.02mm, 0.04mm);
+ draw(pic,unitcircle);
+ shipout("out/",pic);
+}
diff --git a/graphics/asymptote/tests/gc/transform.asy b/graphics/asymptote/tests/gc/transform.asy
new file mode 100644
index 0000000000..abeef05656
--- /dev/null
+++ b/graphics/asymptote/tests/gc/transform.asy
@@ -0,0 +1,6 @@
+path p=unitsquare;
+
+for (int i = 0; i < 1e7; ++i)
+{
+ scale(2.0)*p;
+}
diff --git a/graphics/asymptote/tests/gs/ghostscript.asy b/graphics/asymptote/tests/gs/ghostscript.asy
new file mode 100644
index 0000000000..0a76eb9a3c
--- /dev/null
+++ b/graphics/asymptote/tests/gs/ghostscript.asy
@@ -0,0 +1,14 @@
+import TestLib;
+
+StartTest("Ghostscript");
+bool uptodate=texpath("A").length != 0;
+if(!uptodate) {
+ write();
+ write();
+ write("Incompatible Ghostscript version!");
+ write("Please set environment variable ASYMPTOTE_EPSDRIVER to");
+ write("\"epswrite\" for Ghostscript < 9.14 and to \"eps2write\" for Ghostscript >= 9.14");
+ write();
+}
+assert(uptodate);
+EndTest();
diff --git a/graphics/asymptote/tests/gsl/random.asy b/graphics/asymptote/tests/gsl/random.asy
new file mode 100644
index 0000000000..2418ad93e7
--- /dev/null
+++ b/graphics/asymptote/tests/gsl/random.asy
@@ -0,0 +1,338 @@
+import TestLib;
+import gsl;
+
+StartTest("random number generators");
+rng_init();
+assert(rng_min() == 0);
+assert(rng_max() == 4294967295);
+assert(rng_get() == 4293858116);
+rng_init("taus2");
+assert(rng_min() == 0);
+assert(rng_max() == 4294967295);
+assert(rng_get() == 802792108);
+rng_init("gfsr4");
+assert(rng_min() == 0);
+assert(rng_max() == 4294967295);
+assert(rng_get() == 2901276280);
+string[] list = rng_list();
+for(string name: list)
+{
+ rng_init(name);
+ rng_min();
+ rng_max();
+ rng_get();
+}
+assert(list.length >= 62);
+rng_init();
+rng_set(1);
+assert(rng_get() == 1791095845);
+rng_set(1);
+assert(rng_get() == 1791095845);
+EndTest();
+
+StartTest("Bernoulli distribution");
+assert(close(pdf_bernoulli(0,0.3), 0.7));
+assert(close(pdf_bernoulli(1,0.3), 0.3));
+//rng_init();
+//assert(rng_bernoulli(0.3) == 0);
+EndTest();
+
+StartTest("beta distribution");
+assert(close(cdf_beta_P(0.3,5,5), 0.09880866));
+assert(close(cdf_beta_Q(0.3,5,5) + cdf_beta_P(0.3,5,5), 1));
+assert(close(cdf_beta_Pinv(cdf_beta_P(0.3,5,5),5,5), 0.3));
+assert(close(cdf_beta_Qinv(cdf_beta_Q(0.3,5,5),5,5), 0.3));
+assert(close(pdf_beta(0.3,5,5), 1.2252303));
+//rng_init();
+//assert(close(rng_beta(5,5), 0.533021338130471));
+EndTest();
+
+StartTest("binomial distribution");
+assert(close(cdf_binomial_P(5,0.3,10), 0.9526510126));
+assert(close(cdf_binomial_P(5,0.3,10) + cdf_binomial_Q(5,0.3,10), 1));
+assert(close(pdf_binomial(5,0.3,10), 0.1029193452));
+//rng_init();
+//assert(rng_binomial(0.3,10) == 8);
+EndTest();
+
+StartTest("bivariate Gaussian distribution");
+assert(close(pdf_bivariate_gaussian((1,1),(0,2),(4,6),0.5),
+ 0.00675758392382108));
+//rng_init();
+//pair z = (-0.260388644979556,2.50057001628669);
+//pair r = rng_bivariate_gaussian((0,2),(4,6),0.5);
+//assert(close(length(r - z), 0));
+EndTest();
+
+StartTest("cauchy distribution");
+assert(close(cdf_cauchy_P(1,3), 0.602416382349567));
+assert(close(cdf_cauchy_P(1,3) + cdf_cauchy_Q(1,3), 1));
+assert(close(cdf_cauchy_Pinv(cdf_cauchy_P(1,3),3), 1));
+assert(close(cdf_cauchy_Qinv(cdf_cauchy_Q(1,3),3), 1));
+assert(close(pdf_cauchy(1,3), 0.0954929658551372));
+//rng_init();
+//assert(close(rng_cauchy(3), -0.0024339597467863));
+EndTest();
+
+StartTest("chi-squared distribution");
+assert(close(cdf_chisq_P(4,6), 0.323323583816936));
+assert(close(cdf_chisq_P(4,6) + cdf_chisq_Q(4, 6), 1));
+assert(close(cdf_chisq_Pinv(cdf_chisq_P(4,6),6), 4));
+assert(close(cdf_chisq_Qinv(cdf_chisq_Q(4,6),6), 4));
+assert(close(pdf_chisq(4,6), 0.135335283236613));
+//rng_init();
+//assert(close(rng_chisq(6), 8.24171826270279));
+EndTest();
+
+StartTest("Dirichlet distribution");
+real[] alpha = {1,2,3,4};
+real[] theta = {0.1,0.2,0.3,0.4};
+assert(close(pdf_dirichlet(alpha,theta), 34.83648));
+//rng_init();
+//real[] z = {0.124480735441317,
+// 0.191823537067349,
+// 0.460543885448264,
+// 0.22315184204307};
+//real[] r = rng_dirichlet(alpha);
+//assert(close(norm(r - z), 0));
+EndTest();
+
+StartTest("exponential distribution");
+assert(close(cdf_exponential_P(2,3), 0.486582880967408));
+assert(close(cdf_exponential_P(2,3) + cdf_exponential_Q(2,3), 1));
+assert(close(cdf_exponential_Pinv(cdf_exponential_P(2,3),3), 2));
+assert(close(cdf_exponential_Qinv(cdf_exponential_Q(2,3),3), 2));
+assert(close(pdf_exponential(2,3), 0.171139039677531));
+//rng_init();
+//assert(close(rng_exponential(3), 24.7847346491112));
+EndTest();
+
+StartTest("exponential power distribution");
+assert(close(cdf_exppow_P(2,3,2), 0.82711070692442));
+assert(close(cdf_exppow_P(2,3,2) + cdf_exppow_Q(2,3,2), 1));
+assert(close(pdf_exppow(2,3,2), 0.120582432109095));
+//rng_init();
+//assert(close(rng_exppow(3,2), 0.284084267783339));
+EndTest();
+
+StartTest("F-distribution");
+assert(close(cdf_fdist_P(1,5,4), 0.485657196759213));
+assert(close(cdf_fdist_P(1,5,4) + cdf_fdist_Q(1,5,4), 1));
+//rng_init();
+//assert(close(rng_fdist(5,4), 1.20570928490019));
+EndTest();
+
+StartTest("flat (uniform) distribution");
+assert(close(cdf_flat_P(2,0,5), 0.4));
+assert(close(cdf_flat_P(2,0,5) + cdf_flat_Q(2,0,5), 1));
+assert(close(cdf_flat_Pinv(cdf_flat_P(2,0,5),0,5), 2));
+assert(close(cdf_flat_Qinv(cdf_flat_Q(2,0,5),0,5), 2));
+assert(close(pdf_flat(2,0,5), 0.2));
+//rng_init();
+//assert(close(rng_flat(0,5), 4.99870874453336));
+EndTest();
+
+StartTest("Gamma-distribution");
+assert(close(cdf_gamma_P(6,5,1), 0.71494349968337));
+assert(close(cdf_gamma_P(6,5,1) + cdf_gamma_Q(6,5,1), 1));
+assert(close(cdf_gamma_Pinv(cdf_gamma_P(6,5,1),5,1), 6));
+assert(close(cdf_gamma_Qinv(cdf_gamma_Q(6,5,1),5,1), 6));
+assert(close(pdf_gamma(6,5,1), 0.133852617539983));
+//rng_init();
+//assert(close(rng_gamma(5,1), 6.52166444209317));
+//assert(close(rng_gamma(5,1,"mt"), 5.71361391461836));
+//assert(close(rng_gamma(5,1,"knuth"), 1.53054227085541));
+EndTest();
+
+StartTest("Gaussian distribution");
+assert(close(cdf_gaussian_P(1,0,1), 0.841344746068543));
+assert(close(cdf_gaussian_P(1,0,1) + cdf_gaussian_Q(1,0,1), 1));
+assert(close(cdf_gaussian_Pinv(cdf_gaussian_P(1,0,1),0,1), 1));
+assert(close(cdf_gaussian_Qinv(cdf_gaussian_Q(1,0,1),0,1), 1));
+assert(close(pdf_gaussian(1,0,1), 0.241970724519143));
+//rng_init();
+//assert(close(rng_gaussian(0,1), 0.133918608118676));
+//assert(close(rng_gaussian(1,2,"ziggurat"), 1.90467233084303));
+//assert(close(rng_gaussian(1,2,"ratio"), 4.04779517509342));
+//assert(close(rng_gaussian(1,2,"polar"), 1.54245166575101));
+EndTest();
+
+StartTest("Gaussian tail distribution");
+assert(close(pdf_gaussian_tail(2,1,1), 0.34030367841782));
+//rng_init();
+//assert(close(rng_gaussian_tail(1,1), 1.0528474462339));
+EndTest();
+
+StartTest("geometric distribution");
+assert(close(cdf_geometric_P(6,0.1), 0.468559));
+assert(close(cdf_geometric_P(6,0.1) + cdf_geometric_Q(6,0.1), 1));
+assert(close(pdf_geometric(6,0.1), 0.059049));
+//rng_init();
+//assert(rng_geometric(0.1) == 1);
+EndTest();
+
+StartTest("Gumbel1 distribution");
+assert(close(cdf_gumbel1_P(1,3,8), 0.671462877871127));
+assert(close(cdf_gumbel1_P(1,3,8) + cdf_gumbel1_Q(1,3,8), 1));
+assert(close(cdf_gumbel1_Pinv(cdf_gumbel1_P(1,3,8),3,8), 1));
+assert(close(cdf_gumbel1_Qinv(cdf_gumbel1_Q(1,3,8),3,8), 1));
+assert(close(pdf_gumbel1(1,3,8), 0.80232403696926));
+//rng_init();
+//assert(close(rng_gumbel1(3,8), 3.44696353953564));
+EndTest();
+
+StartTest("Gumbel2 distribution");
+assert(close(cdf_gumbel2_P(2,2,3), 0.472366552741015));
+assert(close(cdf_gumbel2_P(2,2,3) + cdf_gumbel2_Q(2,2,3), 1));
+assert(close(cdf_gumbel2_Pinv(cdf_gumbel2_P(2,2,3),2,3), 2));
+assert(close(cdf_gumbel2_Qinv(cdf_gumbel2_Q(2,2,3),2,3), 2));
+assert(close(pdf_gumbel2(2,2,3), 0.354274914555761));
+//rng_init();
+//assert(close(rng_gumbel2(2,3), 107.773379309453));
+EndTest();
+
+StartTest("hypergeometric distribution");
+assert(close(cdf_hypergeometric_P(4,10,10,8), 0.675041676589664));
+assert(close(cdf_hypergeometric_P(4,10,10,8) +
+ cdf_hypergeometric_Q(4,10,10,8), 1));
+assert(close(pdf_hypergeometric(4,10,10,8), 0.350083353179329));
+//rng_init();
+//assert(rng_hypergeometric(10,10,8) == 3);
+EndTest();
+
+StartTest("Laplace distribution");
+assert(close(cdf_laplace_P(1,2), 0.696734670143683));
+assert(close(cdf_laplace_P(1,2) + cdf_laplace_Q(1,2), 1));
+assert(close(cdf_laplace_Pinv(cdf_laplace_P(1,2),2), 1));
+assert(close(cdf_laplace_Qinv(cdf_laplace_Q(1,2),2), 1));
+assert(close(pdf_laplace(1,2), 0.151632664928158));
+//rng_init();
+//assert(close(rng_laplace(2), 0.00103327123971616));
+EndTest();
+
+StartTest("Landau distribution");
+assert(close(pdf_landau(1), 0.145206637130862));
+//rng_init();
+//assert(close(rng_landau(), 3880.0374262546));
+EndTest();
+
+//StartTest("Levy stable distribution");
+//rng_init();
+//assert(close(rng_levy(1,1,0), 1232.55941432972));
+//assert(close(rng_levy(1,1,1), -0.13781830409645));
+//EndTest();
+
+StartTest("logistic distribution");
+assert(close(cdf_logistic_P(1,2), 0.622459331201855));
+assert(close(cdf_logistic_P(1,2) + cdf_logistic_Q(1,2), 1));
+assert(close(cdf_logistic_Pinv(cdf_logistic_P(1,2),2), 1));
+assert(close(cdf_logistic_Qinv(cdf_logistic_Q(1,2),2), 1));
+assert(close(pdf_logistic(1,2), 0.117501856100797));
+//rng_init();
+//assert(close(rng_logistic(2), 16.522639863849));
+EndTest();
+
+StartTest("lognormal distribution");
+assert(close(cdf_lognormal_P(6,2,1), 0.417520581602749));
+assert(close(cdf_lognormal_P(6,2,1) + cdf_lognormal_Q(6,2,1), 1));
+assert(close(cdf_lognormal_Pinv(cdf_lognormal_P(6,2,1),2,1), 6));
+assert(close(cdf_lognormal_Qinv(cdf_lognormal_Q(6,2,1),2,1), 6));
+assert(close(pdf_lognormal(6,2,1), 0.0650642483079156));
+//rng_init();
+//assert(close(rng_lognormal(2,1), 6.92337133931968));
+EndTest();
+
+StartTest("multinomial distribution");
+real[] p = {0.1,0.2,0.3,0.4};
+int[] n = {1,2,3,4};
+assert(close(pdf_multinomial(p,n), 0.03483648));
+//rng_init();
+//int[] r = {5, 0, 1, 4};
+//assert(all(rng_multinomial(10,p) == r));
+EndTest();
+
+StartTest("negative binomial distribution");
+assert(close(cdf_negative_binomial_P(6,0.5,10), 0.227249145507813));
+assert(close(cdf_negative_binomial_P(6,0.5,10) +
+ cdf_negative_binomial_Q(6,0.5,10), 1));
+assert(close(pdf_negative_binomial(6,0.5,10), 0.076370239257812));
+//rng_init();
+//assert(rng_negative_binomial(0.5,10) == 15);
+EndTest();
+
+StartTest("Pareto distribution");
+assert(close(cdf_pareto_P(4,2,2), 0.75));
+assert(close(cdf_pareto_P(4,2,2) + cdf_pareto_Q(4,2,2), 1));
+assert(close(cdf_pareto_Pinv(cdf_pareto_P(4,2,2),2,2), 4));
+assert(close(cdf_pareto_Qinv(cdf_pareto_Q(4,2,2),2,2), 4));
+assert(close(pdf_pareto(4,2,2), 0.125));
+//rng_init();
+//assert(close(rng_pareto(2,2), 2.00025830112432));
+EndTest();
+
+StartTest("Poisson distribution");
+assert(close(cdf_poisson_P(5,6), 0.445679641364611));
+assert(close(cdf_poisson_P(5,6) + cdf_poisson_Q(5,6), 1));
+assert(close(pdf_poisson(5,6), 0.16062314104798));
+//rng_init();
+//assert(rng_poisson(6) == 8);
+EndTest();
+
+StartTest("Rayleigh distribution");
+assert(close(cdf_rayleigh_P(3,2), 0.67534753264165));
+assert(close(cdf_rayleigh_P(3,2) + cdf_rayleigh_Q(3,2), 1));
+assert(close(cdf_rayleigh_Pinv(cdf_rayleigh_P(3,2),2), 3));
+assert(close(cdf_rayleigh_Qinv(cdf_rayleigh_Q(3,2),2), 3));
+assert(close(pdf_rayleigh(3,2), 0.243489350518762));
+//rng_init();
+//assert(close(rng_rayleigh(2), 0.0454563039310455));
+EndTest();
+
+StartTest("Rayleigh tail distribution");
+assert(close(pdf_rayleigh_tail(5,4,1), 0.0555449826912115));
+//rng_init();
+//assert(close(rng_rayleigh_tail(4,1), 4.0000645705903));
+EndTest();
+
+//StartTest("spherical distributions");
+//rng_init();
+//pair z = (-0.617745613497854,-0.786377998804748);
+//pair r = rng_dir2d();
+//assert(close(length(r - z), 0));
+//pair z = (0.993748310886084,0.111643605329884);
+//pair r = rng_dir2d("neumann");
+//assert(close(length(r - z), 0));
+//pair z = (0.964519203132591,-0.264012701945327);
+//pair r = rng_dir2d("trig");
+//assert(close(length(r - z), 0));
+//triple z = (0.849028025629996,0.139162687752509,-0.509691237939527);
+//triple r = rng_dir3d();
+//assert(close(length(r - z), 0));
+//real[] z = {0.420990368676528,
+// -0.626782975357296,
+// 0.0441585572224004,
+// -0.0458388920727644,
+// -0.652578753164271};
+//real[] r = rng_dir(5);
+//assert(close(norm(r - z), 0));
+//EndTest();
+
+StartTest("t-distribution");
+assert(close(cdf_tdist_P(0.6,2), 0.695283366471236));
+assert(close(cdf_tdist_P(0.6,2) + cdf_tdist_Q(0.6,2), 1));
+assert(close(cdf_tdist_Pinv(cdf_tdist_P(0.6,2),2), 0.6));
+assert(close(cdf_tdist_Qinv(cdf_tdist_Q(0.6,2),2), 0.6));
+assert(close(pdf_tdist(0.6,2), 0.275823963942424));
+//rng_init();
+//assert(close(rng_tdist(2), 0.127201714006725));
+EndTest();
+
+StartTest("Weibull distribution");
+assert(close(cdf_weibull_P(1,2,2), 0.221199216928595));
+assert(close(cdf_weibull_P(1,2,2) + cdf_weibull_Q(1,2,2), 1));
+assert(close(cdf_weibull_Pinv(cdf_weibull_P(1,2,2),2,2), 1));
+assert(close(cdf_weibull_Qinv(cdf_weibull_Q(1,2,2),2,2), 1));
+assert(close(pdf_weibull(1,2,2), 0.389400391535702));
+//rng_init();
+//assert(close(rng_weibull(2,2), 0.032142460757319));
+EndTest();
diff --git a/graphics/asymptote/tests/imp/unravel.asy b/graphics/asymptote/tests/imp/unravel.asy
new file mode 100644
index 0000000000..0f61326fd6
--- /dev/null
+++ b/graphics/asymptote/tests/imp/unravel.asy
@@ -0,0 +1,95 @@
+import TestLib;
+StartTest("unravel");
+{
+ struct A {
+ int x=1, y=2, z=3;
+ int y() { return 7; }
+ }
+
+ A a=new A;
+ unravel a;
+ assert(x==1);
+ assert(y==2);
+ assert(z==3);
+ assert(y()==7);
+}
+{
+ struct A {
+ private int x=1;
+ int y=2, z=3;
+ int y() { return 7; }
+ }
+
+ int x=5;
+ A a=new A;
+ unravel a;
+ assert(x==5);
+ assert(y==2);
+ assert(z==3);
+}
+{
+ struct A {
+ public int x=1;
+ int y=2, z=3;
+ int y() { return 7; }
+ }
+
+ int z=5;
+ A a=new A;
+ from a unravel x,y;
+ assert(x==1);
+ assert(y==2);
+ assert(z==5);
+ assert(y()==7);
+}
+{
+ struct A {
+ public int x=1;
+ int y=2, z=3;
+ int y() { return 7; }
+ }
+
+ int y=4;
+ int z=5;
+ A a=new A;
+ from a unravel x,y as blah;
+ assert(x==1);
+ assert(y==4);
+ assert(blah==2);
+ assert(z==5);
+ assert(blah()==7);
+}
+{
+ struct A {
+ struct B {
+ static int x=4;
+ }
+ }
+ A a=new A;
+ int x=3;
+ from a.B unravel x;
+ assert(x==4);
+}
+{
+ struct A {
+ struct B {
+ static int x=4;
+ }
+ }
+ A a=new A;
+ A.B b=new a.B;
+ int x=3;
+ from b unravel x;
+ assert(x==4);
+}
+{
+ struct A {
+ static struct B {
+ static int x=4;
+ }
+ }
+ int x=3;
+ from A.B unravel x;
+ assert(x==4);
+}
+EndTest();
diff --git a/graphics/asymptote/tests/output/Makefile b/graphics/asymptote/tests/output/Makefile
new file mode 100644
index 0000000000..938625ab03
--- /dev/null
+++ b/graphics/asymptote/tests/output/Makefile
@@ -0,0 +1,41 @@
+# Automated testing to see if the output of Asymptote scripts changes when the
+# program is modified.
+
+# How to call asy from the tests/output/name.out directory
+ASY=../../../asy
+
+TESTS=$(basename $(wildcard *.asy))
+
+# This command performs the testing on all scripts.
+diff: $(TESTS:=.diff)
+
+# This builds the reference copies of the output using a trusted version of asy
+ref: $(TESTS:=.ref)
+
+$(TESTS:=.ref) $(TESTS:=.out): %:
+ @echo Generating $@
+ @rm -rf $@
+ @mkdir $@
+ @cd $@; \
+ $(ASY) -keep ../$(basename $@) \
+ >$(basename $@).stdout 2>$(basename $@).stderr; \
+ ls >$(basename $@).ls; \
+ rm -f *.dvi *.pdf *.gif *.jpg *.jpeg *.png
+
+# Ignore lines with timestamps of the form hh:mm, since the time changes between
+# runs. This regex is fairly broad and it may need to be narrowed.
+$(TESTS:=.diff): %.diff: %.out
+ diff -I "[0-9][0-9]:[0-9][0-9]" -u $(@:.diff=.ref) $(@:.diff=.out)
+
+clean:
+ rm -rf *.out
+
+# The reference copies should only be built at the start, or when the behaviour
+# of Asymptote is intentionally changed, so they are not usually removed by make
+# clean.
+veryclean: clean
+ rm -rf *.ref
+
+# This tells make to build every dependency from scratch, ignoring the dates on
+# files.
+.PHONY: $(TESTS:=.ref) $(TESTS:=.out) $(TESTS:=.diff) diff ref clean veryclean
diff --git a/graphics/asymptote/tests/output/circle.asy b/graphics/asymptote/tests/output/circle.asy
new file mode 100644
index 0000000000..e0300acdb8
--- /dev/null
+++ b/graphics/asymptote/tests/output/circle.asy
@@ -0,0 +1 @@
+draw(unitcircle);
diff --git a/graphics/asymptote/tests/output/line.asy b/graphics/asymptote/tests/output/line.asy
new file mode 100644
index 0000000000..21acd4fc4e
--- /dev/null
+++ b/graphics/asymptote/tests/output/line.asy
@@ -0,0 +1 @@
+draw((0,0)--(100,0));
diff --git a/graphics/asymptote/tests/pic/trans.asy b/graphics/asymptote/tests/pic/trans.asy
new file mode 100644
index 0000000000..9a2e02decf
--- /dev/null
+++ b/graphics/asymptote/tests/pic/trans.asy
@@ -0,0 +1,75 @@
+import TestLib;
+
+StartTest("trans");
+
+// Ensure the same test each time.
+srand(3456);
+
+pair randompair()
+{
+ return (unitrand(),unitrand());
+}
+
+path randombox()
+{
+ return box(randompair(), randompair());
+}
+
+// For now, only tests transforms which take axes to axes.
+transform randomtrans()
+{
+ return rotate(90 * (rand() % 4)) * shift(unitrand(), unitrand());
+}
+
+real tolerance = 1e-4;
+
+void testpic(int objs, int trans)
+{
+ path[] pp;
+ picture orig;
+ for (int i = 0; i < objs; ++i) {
+ pp.push(randombox());
+ fill(orig, pp[i]);
+ }
+
+ picture pic = orig;
+ transform t = identity();
+ for (int i = 0; i < trans; ++i)
+ {
+ transform tt = randomtrans();
+ pic = tt * pic;
+ t = tt * t;
+ }
+
+ pair m = pic.userMin2(), M = pic.userMax2();
+ pair pm = min(t * pp), pM = max(t * pp);
+
+ assert(abs(m-pm) < tolerance);
+ assert(abs(M-pM) < tolerance);
+}
+
+for (int i = 0; i < 100; ++i)
+ testpic(1,1);
+for (int i = 0; i < 100; ++i)
+ testpic(1,1);
+for (int i = 0; i < 100; ++i)
+ testpic(3,1);
+for (int i = 0; i < 100; ++i)
+ testpic(1,2);
+for (int i = 0; i < 100; ++i)
+ testpic(2,2);
+for (int i = 0; i < 100; ++i)
+ testpic(3,2);
+for (int i = 0; i < 100; ++i)
+ testpic(3,4);
+for (int i = 0; i < 100; ++i)
+ testpic(1,4);
+for (int i = 0; i < 100; ++i)
+ testpic(2,4);
+for (int i = 0; i < 100; ++i)
+ testpic(3,4);
+for (int i = 0; i < 100; ++i)
+ testpic(3,4);
+
+
+EndTest();
diff --git a/graphics/asymptote/tests/string/erase.asy b/graphics/asymptote/tests/string/erase.asy
new file mode 100644
index 0000000000..2b38b61f35
--- /dev/null
+++ b/graphics/asymptote/tests/string/erase.asy
@@ -0,0 +1,9 @@
+import TestLib;
+StartTest("erase");
+string s = "abcdef";
+assert(erase(s,2,2) == "abef");
+assert(erase(s,-1,2) == "abcdef");
+assert(erase(s,7,1) == "abcdef");
+assert(erase(s,3,0) == "abcdef");
+assert(erase(s,5,2) == "abcde");
+EndTest();
diff --git a/graphics/asymptote/tests/string/find.asy b/graphics/asymptote/tests/string/find.asy
new file mode 100644
index 0000000000..cdf6dc6740
--- /dev/null
+++ b/graphics/asymptote/tests/string/find.asy
@@ -0,0 +1,8 @@
+import TestLib;
+StartTest("find");
+string s = "abcdefab";
+assert(find(s,"cd") == 2);
+assert(find(s,"cd",3) == -1);
+assert(find(s,"ab") == 0);
+assert(find(s,"ab",1) == 6);
+EndTest();
diff --git a/graphics/asymptote/tests/string/insert.asy b/graphics/asymptote/tests/string/insert.asy
new file mode 100644
index 0000000000..2c11a2ef00
--- /dev/null
+++ b/graphics/asymptote/tests/string/insert.asy
@@ -0,0 +1,5 @@
+import TestLib;
+StartTest("insert");
+string sub = insert("abef",2,"cd");
+assert(sub == "abcdef");
+EndTest();
diff --git a/graphics/asymptote/tests/string/length.asy b/graphics/asymptote/tests/string/length.asy
new file mode 100644
index 0000000000..dafb5d56b9
--- /dev/null
+++ b/graphics/asymptote/tests/string/length.asy
@@ -0,0 +1,6 @@
+import TestLib;
+StartTest("length");
+assert(length("") == 0);
+assert(length("abc") == 3);
+assert(length("abcdef") == 6);
+EndTest();
diff --git a/graphics/asymptote/tests/string/rfind.asy b/graphics/asymptote/tests/string/rfind.asy
new file mode 100644
index 0000000000..2291097a7e
--- /dev/null
+++ b/graphics/asymptote/tests/string/rfind.asy
@@ -0,0 +1,8 @@
+import TestLib;
+StartTest("rfind");
+string s = "abcdefab";
+assert(rfind(s,"cd") == 2);
+assert(rfind(s,"cd",1) == -1);
+assert(rfind(s,"ab") == 6);
+assert(rfind(s,"ab",5) == 0);
+EndTest();
diff --git a/graphics/asymptote/tests/string/substr.asy b/graphics/asymptote/tests/string/substr.asy
new file mode 100644
index 0000000000..6426895aa3
--- /dev/null
+++ b/graphics/asymptote/tests/string/substr.asy
@@ -0,0 +1,6 @@
+import TestLib;
+StartTest("substr");
+string s = "abcdef";
+string sub = substr(s,2,2);
+assert(sub == "cd");
+EndTest();
diff --git a/graphics/asymptote/tests/types/cast.asy b/graphics/asymptote/tests/types/cast.asy
new file mode 100644
index 0000000000..b119163755
--- /dev/null
+++ b/graphics/asymptote/tests/types/cast.asy
@@ -0,0 +1,13 @@
+import TestLib;
+StartTest("cast");
+struct A {
+ public int x;
+}
+A operator cast(int x) {
+ A a=new A;
+ a.x=x;
+ return a;
+}
+A a=7;
+assert(a.x==7);
+EndTest();
diff --git a/graphics/asymptote/tests/types/constructor.asy b/graphics/asymptote/tests/types/constructor.asy
new file mode 100644
index 0000000000..78a0684fa9
--- /dev/null
+++ b/graphics/asymptote/tests/types/constructor.asy
@@ -0,0 +1,380 @@
+import TestLib;
+StartTest("constructor");
+
+{ // Basic usage. {{{1
+ struct Foo {
+ int x;
+ int y;
+
+ void operator init() {
+ x=2; y=3;
+ }
+
+ void operator init(int x, int y=2x) {
+ this.x=x; this.y=y;
+ }
+
+ void operator init(string s ... int[] vals) {
+ for (int i=0; i<vals.length; ++i)
+ x+=vals[i];
+ y=vals.length;
+ }
+
+ static {
+ {
+ Foo f=new Foo;
+ assert(f.x==0);
+ assert(f.y==0);
+ }
+ {
+ Foo f=Foo();
+ assert(f.x==2);
+ assert(f.y==3);
+ }
+ {
+ Foo f=Foo(7);
+ assert(f.x==7);
+ assert(f.y==14);
+ }
+ {
+ Foo f=Foo(5,40);
+ assert(f.x==5);
+ assert(f.y==40);
+ }
+ {
+ Foo f=Foo(y=5,x=40);
+ assert(f.x==40);
+ assert(f.y==5);
+ }
+ {
+ Foo f=Foo("hello", 1,2,3,4);
+ assert(f.x==10);
+ assert(f.y==4);
+ }
+ }
+ }
+
+ {
+ Foo f=new Foo;
+ assert(f.x==0);
+ assert(f.y==0);
+ }
+ {
+ Foo f=Foo();
+ assert(f.x==2);
+ assert(f.y==3);
+ }
+ {
+ Foo f=Foo(7);
+ assert(f.x==7);
+ assert(f.y==14);
+ }
+ {
+ Foo f=Foo(5,40);
+ assert(f.x==5);
+ assert(f.y==40);
+ }
+ {
+ Foo f=Foo(y=5,x=40);
+ assert(f.x==40);
+ assert(f.y==5);
+ }
+ {
+ Foo f=Foo("hello", 1,2,3,4);
+ assert(f.x==10);
+ assert(f.y==4);
+ }
+}
+
+{ // Assignment {{{1
+ struct Foo {
+ int x;
+
+ static int Foo() {
+ return 7;
+ }
+
+ static assert(Foo()==7);
+
+ void five() {
+ x=5;
+ }
+
+ void six(string s) {
+ x=6;
+ }
+
+ void operator init()=five;
+
+ void operator init(string s) {
+ assert(false);
+ }
+ operator init=six;
+
+ static {
+ assert(Foo().x==5);
+ assert(Foo("milk").x==6);
+ }
+
+ void operator init(int x) {
+ this.x=2x;
+ }
+
+ static Foo constructor(int)=Foo;
+
+ static {
+ assert(constructor(5).x==10);
+ }
+ }
+
+ assert(Foo().x==5);
+ assert(Foo("milk").x==6);
+ assert(Foo.constructor(5).x==10);
+}
+
+{ // Permission {{{1
+ int Foo() {
+ return 3;
+ }
+
+ struct Foo {
+ int x;
+
+ private void operator init() {
+ x=2;
+ }
+ }
+ // The implicit constructor should not be unravelled, as it is private.
+ assert(Foo()==3);
+}
+{ // Shadowing {{{1
+ struct Foo {
+ static Foo Foo() {
+ return null;
+ }
+
+ static assert(Foo()==null);
+
+ void operator init() {
+ }
+
+ static assert(Foo()!=null);
+ }
+
+ assert(Foo()!=null);
+
+ // Can't use Bar because of conflicts with the drawing command.
+ struct Barr {
+ void operator init() {
+ }
+
+ static assert(Barr()!=null);
+
+ static Barr Barr() {
+ return null;
+ }
+
+ static assert(Barr()==null);
+ }
+
+ assert(Barr()!=null);
+
+ struct Blah {
+ void operator init() {
+ }
+
+ static assert(Blah()!=null);
+
+ static Blah Blah() {
+ return null;
+ }
+
+ static assert(Blah()==null);
+ }
+ from Blah unravel Blah;
+
+ assert(Blah()==null);
+}
+
+{ // Static {{{1
+ struct Foo {
+ static int Foo() {
+ return 7;
+ }
+
+ static void operator init() {
+ }
+
+ static assert(Foo()==7);
+ }
+
+ struct Barr {
+ int x;
+
+ void operator init() {
+ x=77;
+ }
+
+ static assert(Barr().x==77);
+
+ static void operator init() {
+ assert(false);
+ }
+
+ static assert(Barr().x==77);
+ }
+
+ assert(Barr().x==77);
+}
+
+{ // Struct name shadowing. {{{1
+ struct Foo {
+ int x;
+ typedef int Foo;
+
+ void operator init() {
+ x=89;
+ }
+
+ static assert(Foo().x==89);
+ }
+
+ assert(Foo().x==89);
+
+ struct Barr {
+ int x;
+ struct Barr {
+ }
+
+ void operator init() {
+ x=89;
+ }
+
+ static assert(Barr().x==89);
+ }
+
+ assert(Barr().x==89);
+}
+{ // Function Comparison
+ struct A {
+ // Defines a function A A(int).
+ void operator init(int x) {}
+ }
+ assert(!(A == null));
+ assert(A != null);
+}
+
+// File-level {{{1
+// This assumes the file is named constructor.asy
+
+int constructor() {
+ return 44;
+}
+void operator init() {
+ assert(false);
+}
+assert(constructor()==44);
+
+EndTest(); // {{{1
+
+StartTest("tuple"); // {{{1
+{
+ pair z = (1,2);
+ assert(z.x==1);
+ assert(z.y==2);
+ pair w = z;
+ w = (2,3);
+ assert(z.x==1);
+ assert(z.y==2);
+}
+{
+ triple z = (1,2,6);
+ assert(z.x==1);
+ assert(z.y==2);
+ assert(z.z==6);
+ triple w = z;
+ w = (2,3,9);
+ assert(z.x==1);
+ assert(z.y==2);
+ assert(z.z==6);
+}
+{
+ transform z = (1,2,3,4,5,6);
+ assert(z.x==1);
+ assert(z.y==2);
+ assert(z.xx==3);
+ assert(z.xy==4);
+ assert(z.yx==5);
+ assert(z.yy==6);
+}
+{
+ pair z = (34.0, 35.0);
+ triple t = (34.0, 35.0, 36.0);
+
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == z);
+ assert((34,35.0) == z);
+ assert((34.0,35.0) == z);
+ }
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ int operator tuple(int x, real y) { return 123; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == z);
+ assert((34,35.0) == 123);
+ assert((34.0,35.0) == z);
+ }
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ int operator tuple(int x, real y) { return 123; }
+ int operator tuple(real x, int y) { return 456; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == 456);
+ assert((34,35.0) == 123);
+ assert((34.0,35.0) == z);
+ }
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ int operator tuple(real x, int y) { return 456; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == 456);
+ assert((34,35.0) == z);
+ assert((34.0,35.0) == z);
+ }
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ int operator tuple(int x, real y) { return 123; }
+ int operator tuple(real x, int y) { return 456; }
+ int operator tuple(real x, real y) { return 789; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == 456);
+ assert((34,35.0) == 123);
+ assert((34.0,35.0) == 789);
+ }
+ {
+ int operator tuple(int x, int y) { return x+y; }
+ int operator tuple(real x, real y) { return 789; }
+ assert((1,2) == 3);
+ assert((34,35) == 34+35);
+ assert((34.0,35) == 789);
+ assert((34,35.0) == 789);
+ assert((34.0,35.0) == 789);
+ }
+ {
+ int operator tuple(...int[] x) { return x.length; }
+ assert((34,35) == z);
+ assert((34,35,36) == t);
+ assert((34,35,36,37) == 4);
+ assert((34,35,36,37,38) == 5);
+ assert((34,35,36,37,1,2,3,4) == 8);
+ assert((34,35,36,37,1,2,3,4,5,6,7,8,9) == 13);
+ }
+}
+EndTest();
diff --git a/graphics/asymptote/tests/types/ecast.asy b/graphics/asymptote/tests/types/ecast.asy
new file mode 100644
index 0000000000..d16d7bc449
--- /dev/null
+++ b/graphics/asymptote/tests/types/ecast.asy
@@ -0,0 +1,11 @@
+import TestLib;
+StartTest("ecast");
+struct A {
+ public int x;
+}
+int operator ecast(A a) {
+ return a.x;
+}
+A a=new A; a.x=5;
+assert((int)a==5);
+EndTest();
diff --git a/graphics/asymptote/tests/types/guide.asy b/graphics/asymptote/tests/types/guide.asy
new file mode 100644
index 0000000000..ec16e0ed7c
--- /dev/null
+++ b/graphics/asymptote/tests/types/guide.asy
@@ -0,0 +1,160 @@
+import TestLib;
+StartTest("guide");
+
+guide g;
+assert(size(g) == 0);
+assert(length(g) == -1);
+
+guide g=(0,0){curl 2}..(1,1){W}..tension 5 and 6 ..{N}(4,2)..{curl 3}(0,1);
+
+g=reverse(reverse(g));
+
+assert(size(g) == 4);
+assert(length(g) == 3);
+
+assert(size((path) g) == 4);
+assert(length((path) g) == 3);
+
+assert(size((guide) (path) g) == 4);
+assert(length((guide) (path) g) == 3);
+
+assert(close(point(g,-1),(0,0)));
+assert(close(point(g,0),(0,0)));
+assert(close(point(g,1),(1,1)));
+assert(close(point(g,3),(0,1)));
+assert(close(point(g,4),(0,1)));
+
+tensionSpecifier t=tensionSpecifier(g,1);
+assert(close(t.out,5));
+assert(close(t.in,6));
+assert(t.atLeast == false);
+
+pair[] z=dirSpecifier(g,0);
+assert(close(z[0],0));
+assert(close(z[1],0));
+
+pair[] z=dirSpecifier(g,1);
+assert(close(z[0],W));
+assert(close(z[1],N));
+
+real[] x=curlSpecifier(g,0);
+assert(close(x[0],2));
+assert(close(x[1],1));
+
+real[] x=curlSpecifier(g,length(g)-1);
+assert(close(x[0],1));
+assert(close(x[1],3));
+
+assert(!cyclic(g));
+assert(!cyclic((path) g));
+assert(!cyclic((guide) (path) g));
+
+guide g=(0,0)..controls (3,5)..(1,1){W}..tension atleast 5 and 6 ..{N}(4,2)..
+controls(1,2) and (2,4).. (0,1)..cycle;
+
+g=reverse(reverse(g));
+
+assert(size(g) == 4);
+assert(length(g) == 4);
+
+assert(size((path) g) == 4);
+assert(length((path) g) == 4);
+
+assert(size((guide) (path) g) == 4);
+assert(length((guide) (path) g) == 4);
+
+tensionSpecifier t=tensionSpecifier(g,1);
+assert(close(t.out,5));
+assert(close(t.in,6));
+assert(t.atLeast == true);
+
+pair[] z=controlSpecifier(g,0);
+assert(close(z[0],(3,5)));
+assert(close(z[1],(3,5)));
+
+pair[] z=controlSpecifier(g,2);
+assert(close(z[0],(1,2)));
+assert(close(z[1],(2,4)));
+
+real[] x=curlSpecifier(g,0);
+assert(close(x[0],1));
+assert(close(x[1],1));
+
+real[] x=curlSpecifier(g,length(g)-1);
+assert(close(x[0],1));
+assert(close(x[1],1));
+
+assert(cyclic(g));
+assert(cyclic((path) g));
+assert(cyclic((guide) (path) g));
+
+guide g=(0,0)..controls (3,5)..(1,1){W}..tension atleast 5 and 6 ..{N}(4,2)..
+cycle..controls(1,2) and (2,4)..(0,1)..cycle;
+
+assert(size(g) == 5);
+assert(length(g) == 5);
+
+assert(size((path) g) == 5);
+assert(length((path) g) == 5);
+
+assert(size((guide) (path) g) == 5);
+assert(length((guide) (path) g) == 5);
+
+pair[] z=dirSpecifier(g,0);
+assert(close(z[0],0));
+assert(close(z[1],0));
+
+pair[] z=dirSpecifier(g,1);
+assert(close(z[0],W));
+assert(close(z[1],N));
+
+tensionSpecifier t=tensionSpecifier(g,1);
+assert(close(t.out,5));
+assert(close(t.in,6));
+assert(t.atLeast == true);
+
+pair[] z=controlSpecifier(g,0);
+assert(close(z[0],(3,5)));
+assert(close(z[1],(3,5)));
+
+real[] x=curlSpecifier(g,0);
+assert(close(x[0],1));
+assert(close(x[1],1));
+
+real[] x=curlSpecifier(g,length(g)-1);
+assert(close(x[0],1));
+assert(close(x[1],1));
+
+assert(cyclic(g));
+assert(cyclic((path) g));
+assert(cyclic((guide) (path) g));
+
+guide g=(0,0)..controls (3,5) and (4,6)..cycle;
+
+g=reverse(g);
+
+assert(size(g) == 1);
+assert(length(g) == 1);
+
+pair[] z=controlSpecifier(g,0);
+assert(close(z[0],(4,6)));
+assert(close(z[1],(3,5)));
+
+// Test building guides in loops.
+int N = 100;
+guide g;
+for (int i = 0; i < N; ++i)
+ g = g--(i,i^2);
+path p=g;
+for (int i = 0; i < N; ++i)
+ assert(point(p, i) == (i,i^2));
+
+int N = 100;
+guide g;
+for (int i = 0; i < N; ++i)
+ g = (i,i^2)--g;
+path p=g;
+for (int i = N-1, j = 0; i >= 0; --i, ++j)
+ assert(point(p, j) == (i,i^2));
+EndTest();
+
diff --git a/graphics/asymptote/tests/types/init.asy b/graphics/asymptote/tests/types/init.asy
new file mode 100644
index 0000000000..5557bd0676
--- /dev/null
+++ b/graphics/asymptote/tests/types/init.asy
@@ -0,0 +1,17 @@
+import TestLib;
+StartTest("init");
+int operator init() { return 7; }
+int x;
+assert(x==7);
+
+struct A {
+ int x=3;
+}
+A a;
+assert(a!=null);
+assert(a.x==3);
+
+A operator init() { return null; }
+A aa;
+assert(aa==null);
+EndTest();
diff --git a/graphics/asymptote/tests/types/keyword.asy b/graphics/asymptote/tests/types/keyword.asy
new file mode 100644
index 0000000000..73e407b6f8
--- /dev/null
+++ b/graphics/asymptote/tests/types/keyword.asy
@@ -0,0 +1,190 @@
+import TestLib;
+StartTest("keyword");
+{
+ int f(int keyword x) {
+ return 2*x;
+ }
+
+ assert(f(x=17) == 34);
+}
+
+{
+ int f(int keyword x = 10) {
+ return 2*x;
+ }
+
+ assert(f() == 20);
+}
+
+{
+ int f(int keyword x = 10, int keyword y = 20)
+ {
+ return 2x+y;
+ }
+
+ assert(f(x=1,y=2) == 4);
+ assert(f(y=1,x=2) == 5);
+ assert(f(x=1) == 22);
+ assert(f(y=7) == 27);
+ assert(f() == 40);
+}
+
+{
+ int f(int keyword x, int keyword y = 20)
+ {
+ return x+y;
+ }
+
+ assert(f(x=1,y=2) == 3);
+ assert(f(x=1) == 21);
+}
+
+{
+ int f(int keyword x = 10, int keyword y)
+ {
+ return x+y;
+ }
+
+ assert(f(x=1,y=2) == 3);
+ assert(f(y=2) == 12);
+}
+
+{
+ int f(int keyword x, int keyword y)
+ {
+ return x+y;
+ }
+
+ assert(f(x=1,y=2) == 3);
+}
+
+{
+ int f(int x, int keyword y)
+ {
+ return 2x+y;
+ }
+
+ assert(f(x=1,y=2) == 4);
+ assert(f(1,y=2) == 4);
+ assert(f(y=2,1) == 4);
+ assert(f(y=2,x=1) == 4);
+}
+
+{
+ int f(... int[] nums, int keyword r)
+ {
+ return r;
+ }
+
+ assert(f(r=3) == 3);
+ assert(f(1,r=3) == 3);
+ assert(f(1,2, r=3) == 3);
+ assert(f(1,2,4,5,6, r=3) == 3);
+ assert(f(r=3, 10, 20, 30) == 3);
+ assert(f(4, 5, r=3, 10, 20, 30) == 3);
+ assert(f(4, 5, r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(... new int[] {40,50,60}, r=3) == 3);
+ assert(f(... new int[] {40,50,60}, r=3) == 3);
+}
+
+{
+ int f(... int[] nums, int keyword r=77)
+ {
+ return r;
+ }
+
+ assert(f(r=3) == 3);
+ assert(f(1,r=3) == 3);
+ assert(f(1,2, r=3) == 3);
+ assert(f(1,2,4,5,6, r=3) == 3);
+ assert(f(r=3, 10, 20, 30) == 3);
+ assert(f(4, 5, r=3, 10, 20, 30) == 3);
+ assert(f(4, 5, r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(... new int[] {40,50,60}, r=3) == 3);
+ assert(f(... new int[] {40,50,60}, r=3) == 3);
+
+ assert(f() == 77);
+ assert(f(1) == 77);
+ assert(f(1,2) == 77);
+ assert(f(1,2,4,5,6) == 77);
+ assert(f(10, 20, 30) == 77);
+ assert(f(4, 5, 10, 20, 30) == 77);
+ assert(f(4, 5, 10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(... new int[] {40,50,60}) == 77);
+ assert(f(... new int[] {40,50,60}) == 77);
+}
+
+{
+ int f(int x ... int[] nums, int keyword r=77)
+ {
+ return r;
+ }
+
+ assert(f(345,r=3) == 3);
+ assert(f(345,1,r=3) == 3);
+ assert(f(345,1,2, r=3) == 3);
+ assert(f(345,1,2,4,5,6, r=3) == 3);
+ assert(f(345,r=3, 10, 20, 30) == 3);
+ assert(f(345,4, 5, r=3, 10, 20, 30) == 3);
+ assert(f(345,4, 5, r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(345,r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(345,r=3, 10, 20, 30 ... new int[] {40,50,60}) == 3);
+ assert(f(345 ... new int[] {40,50,60}, r=3) == 3);
+ assert(f(345 ... new int[] {40,50,60}, r=3) == 3);
+
+ assert(f(345) == 77);
+ assert(f(345,1) == 77);
+ assert(f(345,1,2) == 77);
+ assert(f(345,1,2,4,5,6) == 77);
+ assert(f(345,10, 20, 30) == 77);
+ assert(f(345,4, 5, 10, 20, 30) == 77);
+ assert(f(345,4, 5, 10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(345,10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(345,10, 20, 30 ... new int[] {40,50,60}) == 77);
+ assert(f(345 ... new int[] {40,50,60}) == 77);
+ assert(f(345 ... new int[] {40,50,60}) == 77);
+}
+
+{
+ int sqr(int x=7) { return x*x; }
+ int f(int keyword x) = sqr;
+ int g(int keyword x=666) = sqr;
+ assert(f(x=5) == 25);
+ assert(g(x=5) == 25);
+ assert(g() == 49);
+}
+{
+ int sqr(int n=7) { return n*n; }
+ int f(int keyword x) = sqr;
+ int g(int keyword x=666) = sqr;
+ assert(f(x=5) == 25);
+ assert(g(x=5) == 25);
+ assert(g() == 49);
+}
+{
+ int sqr(int keyword x=7) { return x*x; }
+ int f(int x) = sqr;
+ int g(int x=666) = sqr;
+ assert(f(x=5) == 25);
+ assert(g(x=5) == 25);
+ assert(f(5) == 25);
+ assert(g(5) == 25);
+ assert(g() == 49);
+}
+{
+ int sqr(int keyword n=7) { return n*n; }
+ int f(int x) = sqr;
+ int g(int x=666) = sqr;
+ assert(f(x=5) == 25);
+ assert(g(x=5) == 25);
+ assert(f(5) == 25);
+ assert(g(5) == 25);
+ assert(g() == 49);
+}
+EndTest();
diff --git a/graphics/asymptote/tests/types/order.asy b/graphics/asymptote/tests/types/order.asy
new file mode 100644
index 0000000000..b2530b17ab
--- /dev/null
+++ b/graphics/asymptote/tests/types/order.asy
@@ -0,0 +1,165 @@
+import TestLib;
+StartTest("order");
+
+// Ordering tests.
+int counter = 0;
+int step(int n) { ++counter; assert(counter == n); return n; }
+int[] stepArray(int n) { return new int[] {step(n)}; }
+void reset() { counter = 0; }
+
+{
+ reset();
+ assert(step(1) + step(2) == step(3)); step(4);
+}
+
+{
+ reset();
+ assert(step(1) == 0 || step(2) == 2); step(3);
+}
+
+{
+ reset();
+ step(1) == 0 && step(999) == step(456); step(2);
+}
+
+{
+ reset();
+ int x = step(1), y = step(2); step(3);
+ int x = step(4), y = step(5); step(6);
+}
+
+{
+ void f(int x, int y) {}
+
+ reset();
+ f(step(1), step(2)); step(3);
+ reset();
+ f(x=step(1), y=step(2)); step(3);
+ reset();
+ f(y=step(1), x=step(2)); step(3);
+ reset();
+ f(x=step(1), step(2)); step(3);
+ reset();
+ f(y=step(1), step(2)); step(3);
+ reset();
+ f(step(1), x=step(2)); step(3);
+ reset();
+ f(step(1), y=step(2)); step(3);
+}
+
+{
+ void f(int x, int y ... int[] z) {}
+
+ reset();
+ f(step(1), step(2)); step(3);
+ reset();
+ f(x=step(1), y=step(2)); step(3);
+ reset();
+ f(y=step(1), x=step(2)); step(3);
+ reset();
+ f(x=step(1), step(2)); step(3);
+ reset();
+ f(y=step(1), step(2)); step(3);
+ reset();
+ f(step(1), x=step(2)); step(3);
+ reset();
+ f(step(1), y=step(2)); step(3);
+
+ reset();
+ f(step(1), step(2), step(3)); step(4);
+ reset();
+ f(x=step(1), y=step(2), step(3)); step(4);
+ reset();
+ f(y=step(1), x=step(2), step(3)); step(4);
+ reset();
+ f(x=step(1), step(2), step(3)); step(4);
+ reset();
+ f(y=step(1), step(2), step(3)); step(4);
+ reset();
+ f(step(1), x=step(2), step(3)); step(4);
+ reset();
+ f(step(1), y=step(2), step(3)); step(4);
+
+ reset();
+ f(step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(x=step(1), y=step(2), step(3), step(4)); step(5);
+ reset();
+ f(y=step(1), x=step(2), step(3), step(4)); step(5);
+ reset();
+ f(x=step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(y=step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(step(1), x=step(2), step(3), step(4)); step(5);
+ reset();
+ f(step(1), y=step(2), step(3), step(4)); step(5);
+
+ reset();
+ f(step(1), step(2), step(3)); step(4);
+ reset();
+ f(x=step(1), step(2), y=step(3)); step(4);
+ reset();
+ f(y=step(1), step(2), x=step(3)); step(4);
+ reset();
+ f(x=step(1), step(2), step(3)); step(4);
+ reset();
+ f(y=step(1), step(2), step(3)); step(4);
+ reset();
+ f(step(1), step(2), x=step(3)); step(4);
+ reset();
+ f(step(1), step(2), y=step(3)); step(4);
+
+ reset();
+ f(step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(x=step(1), step(2), y=step(3), step(4)); step(5);
+ reset();
+ f(y=step(1), step(2), x=step(3), step(4)); step(5);
+ reset();
+ f(x=step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(y=step(1), step(2), step(3), step(4)); step(5);
+ reset();
+ f(step(1), step(2), x=step(3), step(4)); step(5);
+ reset();
+ f(step(1), step(2), y=step(3), step(4)); step(5);
+
+ reset();
+ f(step(1), step(2), step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(x=step(1), step(2), y=step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(y=step(1), step(2), x=step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(x=step(1), step(2), step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(y=step(1), step(2), step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(step(1), step(2), x=step(3), step(4)... stepArray(5)); step(6);
+ reset();
+ f(step(1), step(2), y=step(3), step(4)... stepArray(5)); step(6);
+
+ reset();
+ f(...stepArray(1), x=step(2), y=step(3)); step(4);
+ reset();
+ f(...stepArray(1), y=step(2), x=step(3)); step(4);
+ reset();
+ f(step(1)...stepArray(2), x=step(3), y=step(4)); step(5);
+ reset();
+ f(step(1)...stepArray(2), y=step(3), x=step(4)); step(5);
+ reset();
+ f(step(1),step(2)...stepArray(3), y=step(4), x=step(5)); step(6);
+ reset();
+ f(step(1),step(2)...stepArray(3), y=step(4), x=step(5)); step(6);
+ reset();
+ f(step(1),step(2),x=step(3)...stepArray(4), y=step(5)); step(6);
+ reset();
+ f(step(1),step(2),x=step(3)...stepArray(4), y=step(5)); step(6);
+}
+
+
+
+// TODO: Add packing vs. casting tests.
+
+EndTest();
diff --git a/graphics/asymptote/tests/types/resolve.asy b/graphics/asymptote/tests/types/resolve.asy
new file mode 100644
index 0000000000..b668b15490
--- /dev/null
+++ b/graphics/asymptote/tests/types/resolve.asy
@@ -0,0 +1,157 @@
+import TestLib;
+StartTest("resolve");
+struct A {} struct B {} struct C {}
+
+int f(B, real) { return 1; }
+int f(C, int) { return 2; }
+B operator cast(A) { return new B; }
+
+assert(f(new A, 3) == 1);
+C operator cast(A) { return new C; }
+assert(f(new A, 3) == 2);
+
+int givex(int x, int y) { return x; }
+assert(givex(2002,3) == 2002);
+assert(givex(2002,2002) == 2002);
+assert(givex(-2005,2005) == -2005);
+assert(givex(x=-77,205) == -77);
+assert(givex(-77,y=205) == -77);
+assert(givex(-77,x=205) == 205);
+assert(givex(x=-77,y=205) == -77);
+assert(givex(y=-77,x=205) == 205);
+
+int g(real x, real y) { return 7; }
+int g(int x, real y) { return 8; }
+
+assert(g(4, 4) == 8);
+assert(g(4, 4.4) == 8);
+assert(g(4.4, 4) == 7);
+assert(g(4.4, 4.4) == 7);
+
+assert(g(x=4, y=4) == 8);
+assert(g(x=4, y=4.4) == 8);
+assert(g(x=4.4, y=4) == 7);
+assert(g(x=4.4, y=4.4) == 7);
+
+assert(g(x=4, 4) == 8);
+assert(g(x=4, 4.4) == 8);
+assert(g(x=4.4, 4) == 7);
+assert(g(x=4.4, 4.4) == 7);
+
+assert(g(4, y=4) == 8);
+assert(g(4, y=4.4) == 8);
+assert(g(4.4, y=4) == 7);
+assert(g(4.4, y=4.4) == 7);
+
+assert(g(y=4, x=4) == 8);
+assert(g(y=4, x=4.4) == 7);
+assert(g(y=4.4, x=4) == 8);
+assert(g(y=4.4, x=4.4) == 7);
+
+assert(g(4, x=4) == 8);
+assert(g(4, x=4.4) == 7);
+assert(g(4.4, x=4) == 8);
+assert(g(4.4, x=4.4) == 7);
+
+assert(g(y=4, 4) == 8);
+assert(g(y=4, 4.4) == 7);
+assert(g(y=4.4, 4) == 8);
+assert(g(y=4.4, 4.4) == 7);
+
+// Test exact matching over casting.
+{
+ void f(int x, real y=0.0, int z=0) {
+ assert(x==1);
+ assert(y==2.0);
+ assert(z==0);
+ }
+ f(1,2);
+}
+{
+ void f() {
+ assert(false);
+ }
+ void f(int x, real y=0.0, int z=0) {
+ assert(x==1);
+ assert(y==2.0);
+ assert(z==0);
+ }
+ f(1,2);
+}
+{
+ void f() {
+ assert(false);
+ }
+ void f(int x, int y) {
+ assert(x==1);
+ assert(y==2);
+ }
+ void f(int x, real y=0.0, int z=0) {
+ assert(false);
+ }
+ f(1,2);
+}
+{
+ struct A {}
+ struct B {}
+ struct C {}
+
+ void f(B);
+ void g(B);
+
+ // Should resolve to void (B).
+ assert(f == g);
+ assert(g == f);
+ assert(!(f != g));
+ assert(!(g != f));
+}
+{
+ struct A {}
+ struct B {}
+ struct C {}
+
+ void f(A), f(B);
+ void g(B), g(C);
+
+ // Should resolve to void (B).
+ assert(f == g);
+ assert(g == f);
+ assert(!(f != g));
+ assert(!(g != f));
+}
+{
+ struct A {}
+ struct B {}
+ struct C {}
+
+ void f(B);
+ void g(B), g(C);
+
+ // Should resolve to void (B).
+ assert(f == g);
+ assert(g == f);
+ assert(!(f != g));
+ assert(!(g != f));
+}
+{
+ struct A {}
+ struct B {}
+ struct C {}
+
+ void f(B);
+ void g(B), g(C);
+
+ // Should resolve to void (B).
+ assert(f == g);
+ assert(g == f);
+ assert(!(f != g));
+ assert(!(g != f));
+}
+{
+void foo() {}
+assert((foo == null ? 5 : 8) == 8);
+}
+
+// TODO: Add packing vs. casting tests.
+
+EndTest();
diff --git a/graphics/asymptote/tests/types/shadow.asy b/graphics/asymptote/tests/types/shadow.asy
new file mode 100644
index 0000000000..09d73abc02
--- /dev/null
+++ b/graphics/asymptote/tests/types/shadow.asy
@@ -0,0 +1,17 @@
+import TestLib;
+StartTest("shadow");
+int x = 1;
+int getX() { return x; }
+void setX(int value) { x=value; }
+
+// Shadow x with another int, but x should still be in memory.
+int x = 2;
+assert(x==2);
+assert(getX()==1);
+x = 4;
+assert(x==4);
+assert(getX()==1);
+setX(7);
+assert(x==4);
+assert(getX()==7);
+EndTest();
diff --git a/graphics/asymptote/tests/types/spec.asy b/graphics/asymptote/tests/types/spec.asy
new file mode 100644
index 0000000000..9093644640
--- /dev/null
+++ b/graphics/asymptote/tests/types/spec.asy
@@ -0,0 +1,61 @@
+import TestLib;
+StartTest("spec");
+
+// Test if the cycle keyword can be used in different contexts.
+{
+ int operator cast(cycleToken) {
+ return 55;
+ }
+ int x=cycle;
+ assert(x==55);
+}
+
+// Test the tensionSpecifier type.
+{
+ tensionSpecifier operator ..(string a, tensionSpecifier t, string b) {
+ return t;
+ }
+ tensionSpecifier t="hello" .. tension 2 .. "joe";
+ assert(t.out==2);
+ assert(t.in==2);
+ assert(t.atLeast==false);
+
+ tensionSpecifier t="hello" .. tension 3 and 2 .. "joe";
+ assert(t.out==3);
+ assert(t.in==2);
+ assert(t.atLeast==false);
+
+ tensionSpecifier t="hello" .. tension atleast 7 .. "joe";
+ assert(t.out==7);
+ assert(t.in==7);
+ assert(t.atLeast==true);
+
+ tensionSpecifier t="hello" .. tension atleast 3 and 2 .. "joe";
+ assert(t.out==3);
+ assert(t.in==2);
+ assert(t.atLeast==true);
+}
+
+// Test the curlSpecifier type.
+{
+ curlSpecifier operator ..(curlSpecifier spec, string b) {
+ return spec;
+ }
+ curlSpecifier operator ..(string a, curlSpecifier spec) {
+ return spec;
+ }
+ curlSpecifier operator ..(string a, curlSpecifier spec, string b) {
+ return spec;
+ }
+
+ curlSpecifier spec="hello"{curl 3}.."joe";
+ assert(spec.value==3);
+ assert(spec.side==JOIN_OUT);
+
+ curlSpecifier spec="hello"..{curl 7}"joe";
+ assert(spec.value==7);
+ assert(spec.side==JOIN_IN);
+}
+
+EndTest();
+
diff --git a/graphics/asymptote/tests/types/var.asy b/graphics/asymptote/tests/types/var.asy
new file mode 100644
index 0000000000..a54500b7d0
--- /dev/null
+++ b/graphics/asymptote/tests/types/var.asy
@@ -0,0 +1,86 @@
+import TestLib;
+StartTest("var");
+var x = 4;
+assert(x + x == 8);
+assert(x^2 == 16);
+assert((real)x == 4.0);
+
+var y = x;
+assert(y + y == 8);
+assert(x + y == 8);
+assert(y^2 == 16);
+assert((real)y == 4.0);
+
+var z = 2 * x;
+assert(z + z == 16);
+assert(x + z == 12);
+assert(z^2 == 64);
+assert((real)z == 8.0);
+
+var t = sin(0);
+assert(t == 0.0);
+assert(2t == 0.0);
+
+struct A {
+ int x;
+};
+
+A a;
+a.x = 3;
+
+var b = a;
+assert(a == b);
+assert(a.x == 3);
+
+A func(int x, int y) { return a; }
+
+var c = func(2,3);
+assert(a == b);
+assert(a.x == 3);
+
+int f(int x) { return x*x; }
+var g = f;
+assert(g == f);
+for (int i = 0; i < 100; ++i)
+ assert(g(i) == i*i);
+
+/* var can be replaced with a normal type. */
+{
+ typedef int var;
+ var x;
+ assert(x == 0);
+
+ var v = 14;
+ assert(v == 14);
+}
+
+{
+ struct var {
+ int x;
+ }
+
+ var n = null;
+ assert(n == null);
+
+ var a;
+ assert(a != null);
+ assert(a.x == 0);
+ a.x = 11;
+ assert(a.x == 11);
+}
+
+// Test for single evaluation of the initializer.
+{
+ int x = 3;
+ assert(x == 3);
+ var y = ++x;
+ assert(x == 4);
+ assert(y == 4);
+}
+
+{
+ int f = 4, f() = null;
+ var x = (int)f;
+ assert(x == 4);
+}
+EndTest();