From 4de89e2f422660e33008809ae9c5043b5ac18384 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Oct 2020 12:52:24 -0700 Subject: [PATCH 01/20] Add tests for default values --- .../Simulators.Tests/Circuits/Default.qs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/Simulation/Simulators.Tests/Circuits/Default.qs diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs new file mode 100644 index 00000000000..57dce24444c --- /dev/null +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -0,0 +1,59 @@ +namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits.Default { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Simulation.Simulators.Tests.Circuits; + + @Test("QuantumSimulator") + function DefaultInt() : Unit { + AssertEqual(0, Default()); + } + + @Test("QuantumSimulator") + function DefaultBigInt() : Unit { + AssertEqual(0L, Default()); + } + + @Test("QuantumSimulator") + function DefaultDouble() : Unit { + AssertEqual(0.0, Default()); + } + + @Test("QuantumSimulator") + function DefaultBool() : Unit { + AssertEqual(false, Default()); + } + + @Test("QuantumSimulator") + function DefaultString() : Unit { + AssertEqual("", Default()); + } + + // @Test("QuantumSimulator") + // function DefaultQubit() : Unit { + // AssertEqual(???, Default()); + // } + + @Test("QuantumSimulator") + function DefaultPauli() : Unit { + AssertEqual(PauliI, Default()); + } + + @Test("QuantumSimulator") + function DefaultResult() : Unit { + AssertEqual(Zero, Default()); + } + + @Test("QuantumSimulator") + function DefaultRange() : Unit { + AssertEqual(1..1..0, Default()); + } + + // @Test("QuantumSimulator") + // function DefaultCallable() : Unit { + // AssertEqual(???, Default<(Unit -> Unit)>()); + // } + + @Test("QuantumSimulator") + function DefaultArray() : Unit { + AssertEqual(new Unit[0], Default()); + } +} From e11cd52145e694a1d91eac9ff6df90e0ac72c687 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Oct 2020 13:11:41 -0700 Subject: [PATCH 02/20] Add tests for default tuples and UDTs --- .../Simulators.Tests/Circuits/Default.qs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index 57dce24444c..3498346d8e6 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -56,4 +56,19 @@ function DefaultArray() : Unit { AssertEqual(new Unit[0], Default()); } + + @Test("QuantumSimulator") + function DefaultTuple() : Unit { + AssertEqual((false, 0), Default<(Bool, Int)>()); + AssertEqual((0, Zero, ""), Default<(Int, Result, String)>()); + } + + newtype BoolInt = (Bool, Int); + newtype IntResultString = (Int, Result, String); + + @Test("QuantumSimulator") + function DefaultUserDefinedType() : Unit { + AssertEqual(BoolInt(false, 0), Default()); + AssertEqual(IntResultString(0, Zero, ""), Default()); + } } From 5cc10cf7cf757b8ffd4e451b1bf319c0f278363b Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Oct 2020 13:19:35 -0700 Subject: [PATCH 03/20] Add test for default Unit --- src/Simulation/Simulators.Tests/Circuits/Default.qs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index 3498346d8e6..727f535239b 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -2,6 +2,11 @@ open Microsoft.Quantum.Diagnostics; open Microsoft.Quantum.Simulation.Simulators.Tests.Circuits; + @Test("QuantumSimulator") + function DefaultUnit() : Unit { + AssertEqual((), Default()); + } + @Test("QuantumSimulator") function DefaultInt() : Unit { AssertEqual(0, Default()); From 44a8794a976f49dbd59fd582ff676fabf844209c Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Thu, 15 Oct 2020 17:25:05 -0700 Subject: [PATCH 04/20] Add special-case defaults for a few types --- src/Simulation/Core/QArray.cs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index de9db576c88..c61f34a749b 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -178,21 +178,17 @@ private void CopyAndCompress() // ValueTuples, it returns an empty instance of that value tuple. private static T CreateDefault() { - if (typeof(T).IsValueType || typeof(T).IsAbstract || typeof(T) == typeof(String) || typeof(T) == typeof(QVoid)) - { - return default(T); - } - else - { - // First look for an empty constructor - ConstructorInfo defaultConstructor = typeof(T).GetConstructor(Type.EmptyTypes); - return defaultConstructor != null - ? (T)(defaultConstructor.Invoke(new object[] { })) - : Activator.CreateInstance(); - } + var type = typeof(T); + var isArray = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>); + return isArray ? (T)Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)) + : type == typeof(QRange) ? (T)(object)QRange.Empty + : type == typeof(QVoid) ? (T)(object)QVoid.Instance + : type == typeof(Result) ? (T)(object)Result.Zero + : type == typeof(string) ? (T)(object)"" + : type.GetConstructor(Type.EmptyTypes) is null ? default + : Activator.CreateInstance(); } - /// /// Create an array of length 0. /// From 1bd7b2c9fca3015de806e23831b35d9a58705713 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 12:34:00 -0700 Subject: [PATCH 05/20] Basic handling for defaults of tuples and UDTs --- src/Simulation/Core/QArray.cs | 24 +++---------- src/Simulation/Core/QDefault.cs | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 src/Simulation/Core/QDefault.cs diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index c61f34a749b..87faa56b462 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Reflection; +using Microsoft.Quantum.Runtime.Core; using Newtonsoft.Json; namespace Microsoft.Quantum.Simulation.Core @@ -106,7 +106,7 @@ public QArrayInner(long capacity) storage = new List((int)capacity); for (var i = 0L; i < capacity; ++i) { - storage.Add(CreateDefault()); + storage.Add(QDefault.OfType()); } } @@ -150,8 +150,7 @@ public void Extend(long newLength) long oldLength = storage.Count; for (int i = 0; i < (newLength - oldLength); i++) { - T obj = CreateDefault(); - storage.Add(obj); + storage.Add(QDefault.OfType()); } } } @@ -174,21 +173,6 @@ private void CopyAndCompress() step = 1; } - // Returns the default value of an object of this type of array. Normally null or 0, but for things like - // ValueTuples, it returns an empty instance of that value tuple. - private static T CreateDefault() - { - var type = typeof(T); - var isArray = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>); - return isArray ? (T)Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)) - : type == typeof(QRange) ? (T)(object)QRange.Empty - : type == typeof(QVoid) ? (T)(object)QVoid.Instance - : type == typeof(Result) ? (T)(object)Result.Zero - : type == typeof(string) ? (T)(object)"" - : type.GetConstructor(Type.EmptyTypes) is null ? default - : Activator.CreateInstance(); - } - /// /// Create an array of length 0. /// @@ -504,7 +488,7 @@ public QArrayEnumerator(QArray qArray) currentIndex = -1; } - public T Current => currentIndex >= 0 ? array[currentIndex] : CreateDefault(); + public T Current => currentIndex >= 0 ? array[currentIndex] : QDefault.OfType(); object IEnumerator.Current => this.Current; diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs new file mode 100644 index 00000000000..9b411bdcf4a --- /dev/null +++ b/src/Simulation/Core/QDefault.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.Runtime.Core +{ + internal static class QDefault + { + private static readonly IReadOnlyDictionary Values = new Dictionary + { + [typeof(QRange)] = QRange.Empty, + [typeof(QVoid)] = QVoid.Instance, + [typeof(Result)] = Result.Zero, + [typeof(string)] = "" + }; + + private static object OfType(Type type) + { + if (Values.TryGetValue(type, out var value)) + { + return value; + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>)) + { + return Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<>)) + { + return Activator.CreateInstance( + typeof(ValueTuple<>).MakeGenericType(type.GenericTypeArguments), + type.GenericTypeArguments.Select(OfType).ToArray()); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,>)) + { + return Activator.CreateInstance( + typeof(ValueTuple<,>).MakeGenericType(type.GenericTypeArguments), + type.GenericTypeArguments.Select(OfType).ToArray()); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,>)) + { + return Activator.CreateInstance( + typeof(ValueTuple<,,>).MakeGenericType(type.GenericTypeArguments), + type.GenericTypeArguments.Select(OfType).ToArray()); + } + // TODO: ValueTuple... + if (!(type.BaseType is null) && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>)) + { + return Activator.CreateInstance(type, type.BaseType.GenericTypeArguments.Select(OfType).ToArray()); + } + if (type.IsValueType) + { + return Activator.CreateInstance(type); + } + throw new NotSupportedException("There is no default value for the type."); + } + + internal static T OfType() => (T)OfType(typeof(T)); + } +} From bfc3c148e55f05a32fbbe2c63be8ccbea4b3aada Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 13:05:48 -0700 Subject: [PATCH 06/20] Add defaults for all value tuples --- src/Simulation/Core/QDefault.cs | 40 ++++++++++++++----- .../Simulators.Tests/Circuits/Default.qs | 6 +++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs index 9b411bdcf4a..ab544a2225d 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/QDefault.cs @@ -15,6 +15,9 @@ internal static class QDefault [typeof(string)] = "" }; + private static object OfGenericType(Type type, Type[] args) => + Activator.CreateInstance(type.MakeGenericType(args), args.Select(OfType).ToArray()); + private static object OfType(Type type) { if (Values.TryGetValue(type, out var value)) @@ -27,24 +30,39 @@ private static object OfType(Type type) } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<>)) { - return Activator.CreateInstance( - typeof(ValueTuple<>).MakeGenericType(type.GenericTypeArguments), - type.GenericTypeArguments.Select(OfType).ToArray()); + return OfGenericType(typeof(ValueTuple<>), type.GenericTypeArguments); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,>)) { - return Activator.CreateInstance( - typeof(ValueTuple<,>).MakeGenericType(type.GenericTypeArguments), - type.GenericTypeArguments.Select(OfType).ToArray()); + return OfGenericType(typeof(ValueTuple<,>), type.GenericTypeArguments); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,>)) { - return Activator.CreateInstance( - typeof(ValueTuple<,,>).MakeGenericType(type.GenericTypeArguments), - type.GenericTypeArguments.Select(OfType).ToArray()); + return OfGenericType(typeof(ValueTuple<,,>), type.GenericTypeArguments); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,>)) + { + return OfGenericType(typeof(ValueTuple<,,,>), type.GenericTypeArguments); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,>)) + { + return OfGenericType(typeof(ValueTuple<,,,,>), type.GenericTypeArguments); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,>)) + { + return OfGenericType(typeof(ValueTuple<,,,,,>), type.GenericTypeArguments); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,,>)) + { + return OfGenericType(typeof(ValueTuple<,,,,,,>), type.GenericTypeArguments); + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,,,>)) + { + return OfGenericType(typeof(ValueTuple<,,,,,,,>), type.GenericTypeArguments); } - // TODO: ValueTuple... - if (!(type.BaseType is null) && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>)) + if (!(type.BaseType is null) + && type.BaseType.IsGenericType + && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>)) { return Activator.CreateInstance(type, type.BaseType.GenericTypeArguments.Select(OfType).ToArray()); } diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index 727f535239b..1c286e10724 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -66,6 +66,12 @@ function DefaultTuple() : Unit { AssertEqual((false, 0), Default<(Bool, Int)>()); AssertEqual((0, Zero, ""), Default<(Int, Result, String)>()); + AssertEqual(("", "", "", ""), Default<(String, String, String, String)>()); + AssertEqual(("", "", "", "", ""), Default<(String, String, String, String, String)>()); + AssertEqual(("", "", "", "", "", ""), Default<(String, String, String, String, String, String)>()); + AssertEqual(("", "", "", "", "", "", ""), Default<(String, String, String, String, String, String, String)>()); + AssertEqual(("", "", "", "", "", "", "", ""), Default<(String, String, String, String, String, String, String, String)>()); + AssertEqual(("", "", "", "", "", "", "", "", ""), Default<(String, String, String, String, String, String, String, String, String)>()); } newtype BoolInt = (Bool, Int); From 10565e310b9dc6819a45d29e8b432b4336ba8749 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 13:32:07 -0700 Subject: [PATCH 07/20] Refactor tuple defaults --- src/Simulation/Core/QDefault.cs | 51 +++++++++++---------------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs index ab544a2225d..91ee63845c4 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/QDefault.cs @@ -15,8 +15,19 @@ internal static class QDefault [typeof(string)] = "" }; - private static object OfGenericType(Type type, Type[] args) => - Activator.CreateInstance(type.MakeGenericType(args), args.Select(OfType).ToArray()); + private static readonly IReadOnlyList Tuples = new List + { + typeof(ValueTuple<>), + typeof(ValueTuple<,>), + typeof(ValueTuple<,,>), + typeof(ValueTuple<,,,>), + typeof(ValueTuple<,,,,>), + typeof(ValueTuple<,,,,,>), + typeof(ValueTuple<,,,,,,>), + typeof(ValueTuple<,,,,,,,>) + }; + + internal static T OfType() => (T)OfType(typeof(T)); private static object OfType(Type type) { @@ -28,37 +39,9 @@ private static object OfType(Type type) { return Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)); } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<>)) - { - return OfGenericType(typeof(ValueTuple<>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,>)) - { - return OfGenericType(typeof(ValueTuple<,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,>)) - { - return OfGenericType(typeof(ValueTuple<,,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,>)) + if (type.IsGenericType && Tuples.Contains(type.GetGenericTypeDefinition())) { - return OfGenericType(typeof(ValueTuple<,,,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,>)) - { - return OfGenericType(typeof(ValueTuple<,,,,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,>)) - { - return OfGenericType(typeof(ValueTuple<,,,,,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,,>)) - { - return OfGenericType(typeof(ValueTuple<,,,,,,>), type.GenericTypeArguments); - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,,,,,,,>)) - { - return OfGenericType(typeof(ValueTuple<,,,,,,,>), type.GenericTypeArguments); + return Activator.CreateInstance(type, type.GenericTypeArguments.Select(OfType).ToArray()); } if (!(type.BaseType is null) && type.BaseType.IsGenericType @@ -70,9 +53,7 @@ private static object OfType(Type type) { return Activator.CreateInstance(type); } - throw new NotSupportedException("There is no default value for the type."); + throw new NotSupportedException("There is no default value for this type."); } - - internal static T OfType() => (T)OfType(typeof(T)); } } From 392b081bebf164f1f54b19bfb500d4b293b9232f Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 13:48:38 -0700 Subject: [PATCH 08/20] Factor out different default types --- src/Simulation/Core/QDefault.cs | 57 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs index 91ee63845c4..cb9597997e2 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/QDefault.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Quantum.Simulation.Core; @@ -29,31 +31,36 @@ internal static class QDefault internal static T OfType() => (T)OfType(typeof(T)); - private static object OfType(Type type) + private static object OfType(Type type) => + OfAnyType(type).FirstOrDefault(value => !(value is null)) + ?? throw new NotSupportedException("There is no default value for this type."); + + private static IEnumerable OfAnyType(Type type) { - if (Values.TryGetValue(type, out var value)) - { - return value; - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>)) - { - return Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)); - } - if (type.IsGenericType && Tuples.Contains(type.GetGenericTypeDefinition())) - { - return Activator.CreateInstance(type, type.GenericTypeArguments.Select(OfType).ToArray()); - } - if (!(type.BaseType is null) - && type.BaseType.IsGenericType - && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>)) - { - return Activator.CreateInstance(type, type.BaseType.GenericTypeArguments.Select(OfType).ToArray()); - } - if (type.IsValueType) - { - return Activator.CreateInstance(type); - } - throw new NotSupportedException("There is no default value for this type."); + yield return Values.GetValueOrDefault(type); + yield return OfArrayType(type); + yield return OfTupleType(type); + yield return OfUserDefinedType(type); + yield return OfValueType(type); } + + private static object? OfArrayType(Type type) => + type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>) + ? Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)) + : null; + + private static object? OfTupleType(Type type) => + type.IsGenericType && Tuples.Contains(type.GetGenericTypeDefinition()) + ? Activator.CreateInstance(type, type.GenericTypeArguments.Select(OfType).ToArray()) + : null; + + private static object? OfUserDefinedType(Type type) => + !(type.BaseType is null) + && type.BaseType.IsGenericType + && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>) + ? Activator.CreateInstance(type, type.BaseType.GenericTypeArguments.Select(OfType).ToArray()) + : null; + + private static object? OfValueType(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null; } } From ebc036e80830c86432832dc45ed86c14fedde9ce Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 13:52:42 -0700 Subject: [PATCH 09/20] Update namespace --- src/Simulation/Core/QArray.cs | 1 - src/Simulation/Core/QDefault.cs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index 87faa56b462..3da7a002dc1 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Microsoft.Quantum.Runtime.Core; using Newtonsoft.Json; namespace Microsoft.Quantum.Simulation.Core diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs index cb9597997e2..2f9de7dab68 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/QDefault.cs @@ -3,9 +3,8 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Quantum.Simulation.Core; -namespace Microsoft.Quantum.Runtime.Core +namespace Microsoft.Quantum.Simulation.Core { internal static class QDefault { From 4e99d93429d951076e40104ccccf390b091b45da Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 14:11:45 -0700 Subject: [PATCH 10/20] Update default value in UDT constructor --- src/Simulation/Core/QDefault.cs | 4 ++-- .../CsharpGeneration/SimulationCode.fs | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/QDefault.cs index 2f9de7dab68..d109434af8e 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/QDefault.cs @@ -6,7 +6,7 @@ namespace Microsoft.Quantum.Simulation.Core { - internal static class QDefault + public static class QDefault { private static readonly IReadOnlyDictionary Values = new Dictionary { @@ -28,7 +28,7 @@ internal static class QDefault typeof(ValueTuple<,,,,,,,>) }; - internal static T OfType() => (T)OfType(typeof(T)); + public static T OfType() => (T)OfType(typeof(T)); private static object OfType(Type type) => OfAnyType(type).FirstOrDefault(value => !(value is null)) diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index d1dafb7b4bf..96a8ecbc296 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -1443,15 +1443,16 @@ module SimulationCode = let context = globalContext.setUdt udt let name = userDefinedName None udt.FullName.Name.Value let qsharpType = udt.Type - let buildEmtpyConstructor = + let buildEmptyConstructor = let baseTupleType = match qsharpType.Resolution with - | ArrayType b -> roslynTypeName context b |> sprintf "QArray<%s>" - | _ -> (roslynTypeName context qsharpType) - let defaultValue = match qsharpType.Resolution with | ArrayType _ -> [ sprintf "new %s()" baseTupleType] | _ -> [ sprintf "default(%s)" baseTupleType ] - let args = [] - ``constructor`` name ``(`` args ``)`` - ``:`` defaultValue + | ArrayType item -> + roslynTypeName context item + |> sprintf "global::Microsoft.Quantum.Simulation.Core.QArray<%s>" + | _ -> roslynTypeName context qsharpType + let defaultValue = sprintf "global::Microsoft.Quantum.Simulation.Core.QDefault.OfType<%s>()" baseTupleType + ``constructor`` name ``(`` [] ``)`` + ``:`` [ defaultValue ] [ ``public`` ] ``{`` [] @@ -1522,7 +1523,7 @@ module SimulationCode = let baseClass = ``simpleBase`` baseClassName let modifiers = [ classAccessModifier udt.Modifiers.Access ] let interfaces = [ ``simpleBase`` "IApplyData" ] - let constructors = [ buildEmtpyConstructor; buildBaseTupleConstructor ] + let constructors = [ buildEmptyConstructor; buildBaseTupleConstructor ] let qubitsField = buildQubitsField context qsharpType let itemFields = buildNamedItemFields @ buildItemFields let allFields = itemFields @ qubitsField From 3153fdaf3f59ba8998f2222cd920065a6ad47244 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 14:16:00 -0700 Subject: [PATCH 11/20] Add test for UDT inside tuple --- src/Simulation/Simulators.Tests/Circuits/Default.qs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index 1c286e10724..1b51407a823 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -81,5 +81,6 @@ function DefaultUserDefinedType() : Unit { AssertEqual(BoolInt(false, 0), Default()); AssertEqual(IntResultString(0, Zero, ""), Default()); + AssertEqual((BoolInt(false, 0), IntResultString(0, Zero, "")), Default<(BoolInt, IntResultString)>()); } } From 5eefcb0c086ff2ed3657a788fd7a0a9dd7c927ba Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 14:31:02 -0700 Subject: [PATCH 12/20] Fix range default --- src/Simulation/Core/QRange.cs | 5 ++--- src/Simulation/Simulators.Tests/Circuits/Default.qs | 5 ++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Simulation/Core/QRange.cs b/src/Simulation/Core/QRange.cs index ff8133ccfac..14f10f86607 100644 --- a/src/Simulation/Core/QRange.cs +++ b/src/Simulation/Core/QRange.cs @@ -14,7 +14,7 @@ namespace Microsoft.Quantum.Simulation.Core /// public class QRange : IEnumerable { - public QRange() : this(0, 1, 0) + public QRange() : this(1, 1, 0) { } @@ -61,8 +61,7 @@ public QRange(long start, long end) : this(start, 1, end) /// /// Returns an empty range. /// - public static QRange Empty => - new QRange(0L, -1L); + public static QRange Empty => new QRange(); /// /// Returns true if the range is empty. diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index 1b51407a823..ad18198ba11 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -49,7 +49,10 @@ @Test("QuantumSimulator") function DefaultRange() : Unit { - AssertEqual(1..1..0, Default()); + let range = Default(); + AssertEqual(1, RangeStart(range)); + AssertEqual(1, RangeStep(range)); + AssertEqual(0, RangeEnd(range)); } // @Test("QuantumSimulator") From 9e60afb75a8544bb2eebb46036635dbbd5e1fabb Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 14:45:58 -0700 Subject: [PATCH 13/20] Rename QDefault to Default --- src/Simulation/Core/{QDefault.cs => Default.cs} | 2 +- src/Simulation/Core/QArray.cs | 6 +++--- src/Simulation/CsharpGeneration/SimulationCode.fs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Simulation/Core/{QDefault.cs => Default.cs} (98%) diff --git a/src/Simulation/Core/QDefault.cs b/src/Simulation/Core/Default.cs similarity index 98% rename from src/Simulation/Core/QDefault.cs rename to src/Simulation/Core/Default.cs index d109434af8e..a6363e0d0ae 100644 --- a/src/Simulation/Core/QDefault.cs +++ b/src/Simulation/Core/Default.cs @@ -6,7 +6,7 @@ namespace Microsoft.Quantum.Simulation.Core { - public static class QDefault + public static class Default { private static readonly IReadOnlyDictionary Values = new Dictionary { diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index 3da7a002dc1..6cffa495d5a 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -105,7 +105,7 @@ public QArrayInner(long capacity) storage = new List((int)capacity); for (var i = 0L; i < capacity; ++i) { - storage.Add(QDefault.OfType()); + storage.Add(Default.OfType()); } } @@ -149,7 +149,7 @@ public void Extend(long newLength) long oldLength = storage.Count; for (int i = 0; i < (newLength - oldLength); i++) { - storage.Add(QDefault.OfType()); + storage.Add(Default.OfType()); } } } @@ -487,7 +487,7 @@ public QArrayEnumerator(QArray qArray) currentIndex = -1; } - public T Current => currentIndex >= 0 ? array[currentIndex] : QDefault.OfType(); + public T Current => currentIndex >= 0 ? array[currentIndex] : Default.OfType(); object IEnumerator.Current => this.Current; diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index 96a8ecbc296..6799c749fbf 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -1450,7 +1450,7 @@ module SimulationCode = roslynTypeName context item |> sprintf "global::Microsoft.Quantum.Simulation.Core.QArray<%s>" | _ -> roslynTypeName context qsharpType - let defaultValue = sprintf "global::Microsoft.Quantum.Simulation.Core.QDefault.OfType<%s>()" baseTupleType + let defaultValue = sprintf "global::Microsoft.Quantum.Simulation.Core.Default.OfType<%s>()" baseTupleType ``constructor`` name ``(`` [] ``)`` ``:`` [ defaultValue ] [ ``public`` ] From 0d3b8b9aa1741339df5eb36f2c88a932b49c51f7 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 15:16:58 -0700 Subject: [PATCH 14/20] Default to null instead of throwing --- src/Simulation/Core/Default.cs | 4 +--- .../Simulators.Tests/Circuits/Default.qs | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Simulation/Core/Default.cs b/src/Simulation/Core/Default.cs index a6363e0d0ae..648129059a4 100644 --- a/src/Simulation/Core/Default.cs +++ b/src/Simulation/Core/Default.cs @@ -30,9 +30,7 @@ public static class Default public static T OfType() => (T)OfType(typeof(T)); - private static object OfType(Type type) => - OfAnyType(type).FirstOrDefault(value => !(value is null)) - ?? throw new NotSupportedException("There is no default value for this type."); + private static object? OfType(Type type) => OfAnyType(type).FirstOrDefault(value => !(value is null)); private static IEnumerable OfAnyType(Type type) { diff --git a/src/Simulation/Simulators.Tests/Circuits/Default.qs b/src/Simulation/Simulators.Tests/Circuits/Default.qs index ad18198ba11..55e1853dfc7 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Default.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Default.qs @@ -32,10 +32,11 @@ AssertEqual("", Default()); } - // @Test("QuantumSimulator") - // function DefaultQubit() : Unit { - // AssertEqual(???, Default()); - // } + @Test("QuantumSimulator") + function DefaultQubit() : Unit { + // Creating a default qubit (without using it) should succeed. + let _ = Default(); + } @Test("QuantumSimulator") function DefaultPauli() : Unit { @@ -55,10 +56,11 @@ AssertEqual(0, RangeEnd(range)); } - // @Test("QuantumSimulator") - // function DefaultCallable() : Unit { - // AssertEqual(???, Default<(Unit -> Unit)>()); - // } + @Test("QuantumSimulator") + function DefaultCallable() : Unit { + // Creating a default callable (without calling it) should succeed. + let _ = Default<(Unit -> Unit)>(); + } @Test("QuantumSimulator") function DefaultArray() : Unit { From 6463656b390f08e34d01866a8a76b40bec1abe0d Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 15:29:55 -0700 Subject: [PATCH 15/20] Fix nullable warning --- src/Simulation/Core/Default.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Simulation/Core/Default.cs b/src/Simulation/Core/Default.cs index 648129059a4..d6b6e4746c2 100644 --- a/src/Simulation/Core/Default.cs +++ b/src/Simulation/Core/Default.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Microsoft.Quantum.Simulation.Core @@ -28,7 +29,8 @@ public static class Default typeof(ValueTuple<,,,,,,,>) }; - public static T OfType() => (T)OfType(typeof(T)); + [return: MaybeNull] + public static T OfType() => OfType(typeof(T)) is T value ? value : default; private static object? OfType(Type type) => OfAnyType(type).FirstOrDefault(value => !(value is null)); @@ -38,7 +40,6 @@ public static class Default yield return OfArrayType(type); yield return OfTupleType(type); yield return OfUserDefinedType(type); - yield return OfValueType(type); } private static object? OfArrayType(Type type) => @@ -57,7 +58,5 @@ public static class Default && type.BaseType.GetGenericTypeDefinition() == typeof(UDTBase<>) ? Activator.CreateInstance(type, type.BaseType.GenericTypeArguments.Select(OfType).ToArray()) : null; - - private static object? OfValueType(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null; } } From b01922b0ce9aabaf7f3f204b61fce93607a05e61 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 15:42:31 -0700 Subject: [PATCH 16/20] Assert default qubit and callable are null --- src/Simulation/Simulators.Tests/CoreTests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 88917ff4c24..b087a623f40 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Reflection; using System.Text; +using Microsoft.Quantum.Core; using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; @@ -292,6 +293,14 @@ public void BigInts() }); } + [Fact] + public void DefaultQubitIsNull() => OperationsTestHelper.RunWithMultipleSimulators(async simulator => + Assert.Null(await Default.Run(simulator))); + + [Fact] + public void DefaultCallableIsNull() => OperationsTestHelper.RunWithMultipleSimulators(async simulator => + Assert.Null(await Default.Run(simulator))); + [Fact] public void CatchFail() { From d4d22ab06ba9db198e0ab79a4bca78caca4b63f9 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 15:54:17 -0700 Subject: [PATCH 17/20] Add doc comments --- src/Simulation/Core/Default.cs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Simulation/Core/Default.cs b/src/Simulation/Core/Default.cs index d6b6e4746c2..315c6c0587d 100644 --- a/src/Simulation/Core/Default.cs +++ b/src/Simulation/Core/Default.cs @@ -7,9 +7,15 @@ namespace Microsoft.Quantum.Simulation.Core { + /// + /// Creates default values of Q# types. + /// public static class Default { - private static readonly IReadOnlyDictionary Values = new Dictionary + /// + /// A dictionary from basic types to their default values. + /// + private static readonly IReadOnlyDictionary BasicValues = new Dictionary { [typeof(QRange)] = QRange.Empty, [typeof(QVoid)] = QVoid.Instance, @@ -17,6 +23,9 @@ public static class Default [typeof(string)] = "" }; + /// + /// A list of all generic tuple types. + /// private static readonly IReadOnlyList Tuples = new List { typeof(ValueTuple<>), @@ -29,29 +38,50 @@ public static class Default typeof(ValueTuple<,,,,,,,>) }; + /// + /// Returns the default value of the Q# type. May return null when null is the default value of the type, or if + /// the type is not a valid Q# type. + /// [return: MaybeNull] public static T OfType() => OfType(typeof(T)) is T value ? value : default; + /// + /// Returns the default value of the Q# type. May return null when null is the default value of the type, or if + /// the type is not a valid Q# type. + /// private static object? OfType(Type type) => OfAnyType(type).FirstOrDefault(value => !(value is null)); + /// + /// Enumerates the default values of different kinds of types. Yields null if the given type is not the right + /// kind, and yields a non-null value if a default value is found. + /// private static IEnumerable OfAnyType(Type type) { - yield return Values.GetValueOrDefault(type); + yield return BasicValues.GetValueOrDefault(type); yield return OfArrayType(type); yield return OfTupleType(type); yield return OfUserDefinedType(type); } + /// + /// If the given type is a Q# array type, returns the default array of that type, or null otherwise. + /// private static object? OfArrayType(Type type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IQArray<>) ? Activator.CreateInstance(typeof(QArray<>).MakeGenericType(type.GenericTypeArguments)) : null; + /// + /// If the given type is a Q# tuple type, returns the default tuple of that type, or null otherwise. + /// private static object? OfTupleType(Type type) => type.IsGenericType && Tuples.Contains(type.GetGenericTypeDefinition()) ? Activator.CreateInstance(type, type.GenericTypeArguments.Select(OfType).ToArray()) : null; + /// + /// If the given type is a Q# user-defined type, returns the default value of that type, or null otherwise. + /// private static object? OfUserDefinedType(Type type) => !(type.BaseType is null) && type.BaseType.IsGenericType From afb47a1d18cbe272969bdef936d7c36ed50a3d57 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 17:09:46 -0700 Subject: [PATCH 18/20] Fix C# generation tests --- .../SimulationCodeTests.fs | 34 +++++++++---------- .../CsharpGeneration/SimulationCode.fs | 10 ++---- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index b20864f09ee..ea796481265 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -2924,7 +2924,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class U : UDTBase, IApplyData { - public U() : base(default(IUnitary)) + public U() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -2950,7 +2950,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class AA : UDTBase, IApplyData { - public AA() : base(default(A)) + public AA() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -2976,7 +2976,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class Q : UDTBase, IApplyData { - public Q() : base(default(Qubit)) + public Q() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -3002,7 +3002,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class QQ : UDTBase, IApplyData { - public QQ() : base(default(Q)) + public QQ() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -3028,7 +3028,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class Qubits : UDTBase>, IApplyData { - public Qubits() : base(new QArray()) + public Qubits() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType>()) { } @@ -3054,7 +3054,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class udt_args1 : UDTBase<(Int64,IQArray)>, IApplyData { - public udt_args1() : base(default((Int64,IQArray))) + public udt_args1() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(Int64,IQArray)>()) { } @@ -3084,7 +3084,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class udt_Real : UDTBase, IApplyData { - public udt_Real() : base(default(Double)) + public udt_Real() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -3104,7 +3104,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class udt_Complex : UDTBase<(udt_Real,udt_Real)>, IApplyData { - public udt_Complex() : base(default((udt_Real,udt_Real))) + public udt_Complex() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(udt_Real,udt_Real)>()) { } @@ -3127,7 +3127,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ public class udt_TwoDimArray : UDTBase>>, IApplyData { - public udt_TwoDimArray() : base(new QArray>()) + public udt_TwoDimArray() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType>>()) { } @@ -3149,7 +3149,7 @@ internal partial class EmptyInternalOperation : Operation, ICallab """ internal class InternalType : UDTBase, IApplyData { - public InternalType() : base(default(QVoid)) + public InternalType() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -3171,7 +3171,7 @@ internal class InternalType : UDTBase, IApplyData """ public class NamedTuple : UDTBase<((Int64,Double),Int64)>, IApplyData { - public NamedTuple() : base(default(((Int64,Double),Int64))) + public NamedTuple() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<((Int64,Double),Int64)>()) { } @@ -3231,7 +3231,7 @@ namespace Microsoft.Quantum { public class Pair : UDTBase<(Int64,Int64)>, IApplyData { - public Pair() : base(default((Int64,Int64))) + public Pair() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(Int64,Int64)>()) { } @@ -3251,7 +3251,7 @@ namespace Microsoft.Quantum public class Unused : UDTBase<(Int64,Int64)>, IApplyData { - public Unused() : base(default((Int64,Int64))) + public Unused() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(Int64,Int64)>()) { } @@ -3337,7 +3337,7 @@ namespace Microsoft.Quantum { public class Pair : UDTBase<(Int64,Int64)>, IApplyData { - public Pair() : base(default((Int64,Int64))) + public Pair() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(Int64,Int64)>()) { } @@ -3361,7 +3361,7 @@ namespace Microsoft.Quantum public class NestedPair : UDTBase<(Double,((Boolean,String),Int64))>, IApplyData { - public NestedPair() : base(default((Double,((Boolean,String),Int64)))) + public NestedPair() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType<(Double,((Boolean,String),Int64))>()) { } @@ -3616,7 +3616,7 @@ namespace Microsoft.Quantum.Core { public class Attribute : UDTBase, IApplyData { - public Attribute() : base(default(QVoid)) + public Attribute() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } @@ -3636,7 +3636,7 @@ namespace Microsoft.Quantum.Diagnostics { public class Test : UDTBase, IApplyData { - public Test() : base(default(String)) + public Test() : base(global::Microsoft.Quantum.Simulation.Core.Default.OfType()) { } diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index 6799c749fbf..1475aa34235 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -1444,13 +1444,9 @@ module SimulationCode = let name = userDefinedName None udt.FullName.Name.Value let qsharpType = udt.Type let buildEmptyConstructor = - let baseTupleType = - match qsharpType.Resolution with - | ArrayType item -> - roslynTypeName context item - |> sprintf "global::Microsoft.Quantum.Simulation.Core.QArray<%s>" - | _ -> roslynTypeName context qsharpType - let defaultValue = sprintf "global::Microsoft.Quantum.Simulation.Core.Default.OfType<%s>()" baseTupleType + let defaultValue = + roslynTypeName context qsharpType + |> sprintf "global::Microsoft.Quantum.Simulation.Core.Default.OfType<%s>()" ``constructor`` name ``(`` [] ``)`` ``:`` [ defaultValue ] [ ``public`` ] From 9e835c8f3f3d9d9324af11837a17801e7ae55311 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Fri, 16 Oct 2020 17:48:50 -0700 Subject: [PATCH 19/20] Fix tuple tests --- src/Simulation/Simulators.Tests/QTupleTests.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Simulation/Simulators.Tests/QTupleTests.cs b/src/Simulation/Simulators.Tests/QTupleTests.cs index 0f5501b8a3b..ba8c49c1400 100644 --- a/src/Simulation/Simulators.Tests/QTupleTests.cs +++ b/src/Simulation/Simulators.Tests/QTupleTests.cs @@ -37,7 +37,7 @@ public void TupleEmptyConstructor() } { var actual = new TupleC(); - Assert.Equal(default((Qubit, TupleB)), ((IApplyData)actual).Value); + Assert.Equal((null as Qubit, new TupleB()), ((IApplyData)actual).Value); NullOrEmptyQubits(actual); } { @@ -47,7 +47,10 @@ public void TupleEmptyConstructor() } { var actual = new TupleE(); - Assert.Equal(default((Int64, IQArray)), ((IApplyData)actual).Value); + var value = ((IApplyData)actual).Value as (long, IQArray)?; + Assert.True(value.HasValue); + Assert.Equal(0, value.Value.Item1); + Assert.Equal(0, value.Value.Item2?.Length); NullOrEmptyQubits(actual); } { @@ -57,7 +60,15 @@ public void TupleEmptyConstructor() } { var actual = new TupleH(); - Assert.Equal(default((TupleD, TupleG)), ((IApplyData)actual).Value); + var value = ((IApplyData)actual).Value as (TupleD, TupleG)?; + Assert.True(value.HasValue); + Assert.NotNull(value.Value.Item1); + Assert.NotNull(value.Value.Item2); + Assert.Equal(0, value.Value.Item1.Data?.Length); + Assert.Null(value.Value.Item2.Item1); + Assert.Equal(new TupleF(), value.Value.Item2.Item2); + Assert.Equal(new TupleC(), value.Value.Item2.Item3); + Assert.Equal(0, value.Value.Item2.Item4?.Data?.Length); NullOrEmptyQubits(actual); } { From 4458809dd3b1c78b1ff9e96d96e43bf260da9f31 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 20 Oct 2020 15:24:21 -0700 Subject: [PATCH 20/20] More efficient array initialization --- src/Simulation/Core/QArray.cs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index 6cffa495d5a..a6e7ac4aac3 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -97,17 +97,10 @@ public QArrayInner(params T[] collection) } /// - /// Creates an array of size given by capacity and default-initializes - /// array elements. Uses C# keyword default to initialize array elements. + /// Creates an array of size given by capacity and default-initializes array elements. Uses the default Q# + /// value to initialize array elements. /// - public QArrayInner(long capacity) - { - storage = new List((int)capacity); - for (var i = 0L; i < capacity; ++i) - { - storage.Add(Default.OfType()); - } - } + public QArrayInner(long capacity) => Extend(capacity); public T GetElement(long index) => storage == null @@ -142,19 +135,19 @@ public void UnsafeSetElement(long index, T value) public void Extend(long newLength) { - if (storage == null) + var newLengthInt = Convert.ToInt32(newLength); + if (storage is null) { - storage = new List(); + storage = new List(newLengthInt); } - long oldLength = storage.Count; - for (int i = 0; i < (newLength - oldLength); i++) + else if (storage.Capacity < newLengthInt) { - storage.Add(Default.OfType()); + storage.Capacity = newLengthInt; } + storage.AddRange(Enumerable.Repeat(Default.OfType(), newLengthInt - storage.Count)); } } - private QArrayInner storage; private long start = 0; private long step = 1;