diff --git a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj index a78b19dd7c0..0a8cfcfa1c3 100644 --- a/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj +++ b/src/Simulation/CSharpGeneration/Microsoft.Quantum.CSharpGeneration.fsproj @@ -22,7 +22,7 @@ - + diff --git a/src/Simulation/CSharpGeneration/SimulationCode.fs b/src/Simulation/CSharpGeneration/SimulationCode.fs index 6b4029c0030..c80ae30877e 100644 --- a/src/Simulation/CSharpGeneration/SimulationCode.fs +++ b/src/Simulation/CSharpGeneration/SimulationCode.fs @@ -409,6 +409,7 @@ module SimulationCode = | NamedItem (ex, acc) -> buildNamedItem ex acc | ArrayItem (a, i) -> buildArrayItem a i | ValueArray elems -> buildValueArray ex.ResolvedType elems + | SizedArray (value, size) -> buildSizedArray value size | NewArray (t, expr) -> buildNewArray t expr | AdjointApplication op -> (buildExpression op) <|.|> (``ident`` "Adjoint") | ControlledApplication op -> (buildExpression op) <|.|> (``ident`` "Controlled") @@ -591,6 +592,10 @@ module SimulationCode = // TODO: diagnostics. | _ -> failwith "" + and buildSizedArray value size = + let supplier = ``() =>`` [] (captureExpression value) :> ExpressionSyntax + ident "QArray" <.> (ident "Filled", [ supplier; buildExpression size ]) + and buildNewArray b count = let arrayType = (ArrayType b |> QArrayType).Value arrayType <.> (``ident`` "Create", [count |> buildExpression]) diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs index a6e7ac4aac3..7f4eee399cc 100644 --- a/src/Simulation/Core/QArray.cs +++ b/src/Simulation/Core/QArray.cs @@ -135,16 +135,22 @@ public void UnsafeSetElement(long index, T value) public void Extend(long newLength) { - var newLengthInt = Convert.ToInt32(newLength); - if (storage is null) - { - storage = new List(newLengthInt); - } - else if (storage.Capacity < newLengthInt) - { - storage.Capacity = newLengthInt; - } - storage.AddRange(Enumerable.Repeat(Default.OfType(), newLengthInt - storage.Count)); + var value = Default.OfType(); + Extend(() => value, Convert.ToInt32(newLength - Length)); + } + + /// + /// Extends the length of the array by calling times to + /// supply a value for each new index. + /// + internal void Extend(Func supplier, long count) + { + var total = Convert.ToInt32(Length + count); + storage ??= new List(total); + storage.Capacity = Math.Max(storage.Capacity, total); + storage.AddRange(Enumerable + .Repeat(null, Convert.ToInt32(count)) + .Select(_ => supplier())); } } @@ -232,8 +238,8 @@ public QArray(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 initializes each array element to the default value it has in + /// Q#. /// public static QArray Create(long capacity) => new QArray { @@ -241,6 +247,17 @@ public QArray(params T[] collection) Length = capacity }; + /// + /// Creates an array filled by calling times to supply a + /// value for each index. + /// + internal static QArray Filled(Func supplier, long count) + { + var array = new QArray { Length = count }; + array.storage.Extend(supplier, count); + return array; + } + /// /// Creates a copy of this array. /// @@ -517,6 +534,17 @@ public static implicit operator QArray(QArray arg) => arg; } + /// + /// Contains static methods for creating s. + /// + public static class QArray + { + /// + /// Creates an array filled by calling times to supply a + /// value for each index. + /// + public static QArray Filled(Func supplier, long count) => QArray.Filled(supplier, count); + } /// /// This JsonConverter converts instances of IQArray['T] as QArray['T] @@ -557,4 +585,3 @@ public override bool CanConvert(Type objectType) => objectType.GetGenericTypeDefinition() == typeof(QArray<>); } } - diff --git a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj index 7e8e61d22f6..ebe74577f64 100644 --- a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj +++ b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj b/src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj index a80ac901a6b..ac98ed0cbba 100644 --- a/src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj +++ b/src/Simulation/QSharpCore/Microsoft.Quantum.QSharp.Core.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/QSharpFoundation/Microsoft.Quantum.QSharp.Foundation.csproj b/src/Simulation/QSharpFoundation/Microsoft.Quantum.QSharp.Foundation.csproj index 69118c12e1e..0c593afc8a5 100644 --- a/src/Simulation/QSharpFoundation/Microsoft.Quantum.QSharp.Foundation.csproj +++ b/src/Simulation/QSharpFoundation/Microsoft.Quantum.QSharp.Foundation.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators.Tests/Circuits/Arrays.qs b/src/Simulation/Simulators.Tests/Circuits/Arrays.qs new file mode 100644 index 00000000000..6af632a5451 --- /dev/null +++ b/src/Simulation/Simulators.Tests/Circuits/Arrays.qs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Intrinsic; + + operation MapF<'T, 'U>(mapper : ('T -> 'U), source : 'T[]) : 'U[] { + mutable result = new 'U[Length(source)]; + for (i in 0 .. Length(source) - 1) { + let m = mapper(source[i]); + set result = result w/ i <- m; + } + + return result; + } + + operation LengthTest() : Unit { + let a1 = [One, Zero]; + let a2 = [Zero, Zero, Zero]; + + AssertEqual(2, Length(a1)); + AssertEqual(3, Length(a2)); + + let values = MapF(Length, [a1, a2]); + AssertEqual(2, values[0]); + AssertEqual(3, values[1]); + } + + @Test("QuantumSimulator") + function CreateArrayWithPositiveSize() : Unit { + let xs = [true, size = 3]; + AssertEqual([true, true, true], xs); + } + + @Test("QuantumSimulator") + function CreateArrayWithZeroSize() : Unit { + let xs = [true, size = 0]; + AssertEqual(0, Length(xs)); + } + + function CreateArrayWithNegativeSize() : Bool[] { + return [true, size = -1]; + } + + @Test("QuantumSimulator") + function CreateArrayWithSizeExpression() : Unit { + let n = 2; + let xs = [7, size = n + 1]; + AssertEqual([7, 7, 7], xs); + } + + @Test("QuantumSimulator") + function CreateArrayWithValueExpression() : Unit { + let x = "foo"; + let xs = [x + "bar", size = 3]; + AssertEqual(["foobar", "foobar", "foobar"], xs); + } + + @Test("QuantumSimulator") + function SizedArrayShouldIncrementArrayItemRefCount() : Unit { + mutable item = [1]; + let items = [item, size = 2]; + set item w/= 0 <- 2; + + AssertEqual([2], item); + AssertEqual([[1], [1]], items); + } + + @Test("QuantumSimulator") + function ArrayOfArraysShouldCopyOnUpdate() : Unit { + mutable items = [[1], size = 2]; + set items w/= 0 <- items[0] w/ 0 <- 2; + + AssertEqual([[2], [1]], items); + } +} diff --git a/src/Simulation/Simulators.Tests/Circuits/Length.qs b/src/Simulation/Simulators.Tests/Circuits/Length.qs deleted file mode 100644 index 1cdadf8552b..00000000000 --- a/src/Simulation/Simulators.Tests/Circuits/Length.qs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits -{ - open Microsoft.Quantum.Intrinsic; - - operation MapF<'T, 'U> (mapper : ('T -> 'U), source : 'T[]) : 'U[] { - - mutable result = new 'U[Length(source)]; - - for (i in 0 .. Length(source) - 1) { - let m = mapper(source[i]); - set result = result w/ i <- m; - } - - return result; - } - - - operation LengthTest () : Unit - { - let a1 = [One, Zero]; - let a2 = [Zero, Zero, Zero]; - - AssertEqual(2, Length(a1)); - AssertEqual(3, Length(a2)); - - let values = MapF(Length, [a1, a2]); - AssertEqual(2, values[0]); - AssertEqual(3, values[1]); - } -} diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 8432e3c4494..2a337c041f7 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -324,5 +324,13 @@ public void CatchFail() [Fact] public void InternalCallables() => OperationsTestHelper.RunWithMultipleSimulators(s => Circuits.InternalCallablesTest.Run(s).Wait()); + + [Fact] + public void CreateArrayWithNegativeSize() => + // TODO: This should throw ArgumentOutOfRangeException, but issue #536 causes the wrong exception type to be + // thrown: https://github.com/microsoft/qsharp-runtime/issues/536 + Assert.ThrowsAny(() => + OperationsTestHelper.RunWithMultipleSimulators(simulator => + Circuits.CreateArrayWithNegativeSize.Run(simulator).Wait())); } } diff --git a/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj index 5384a2f6901..305c9c85ef3 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/IntrinsicTests/IntrinsicTests.csproj b/src/Simulation/Simulators.Tests/TestProjects/IntrinsicTests/IntrinsicTests.csproj index 9075b363ba0..32acf2561d3 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/IntrinsicTests/IntrinsicTests.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/IntrinsicTests/IntrinsicTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj index e0b14d1bfa7..d60fa52b246 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj index 556eda7eaad..06b9464ee83 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 false diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj index 2479cfcbd73..4ce1b17ce64 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj index 2479cfcbd73..4ce1b17ce64 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj index 6badef1cce5..847c0c804de 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj index b6ff9d91069..500cc3a4b76 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QSharpExe/QSharpExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj index 91bf1cd73be..f14e6cef64b 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj index bd33c8fe071..f16fd41c26c 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index 497ff79d40a..27f152a4366 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj b/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj index 9e9d51b6c22..80077b83787 100644 --- a/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj +++ b/src/Simulation/Simulators.Type1.Tests/Tests.Microsoft.Quantum.Simulators.Type1.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj b/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj index 094f95bf64b..698f53400f5 100644 --- a/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj +++ b/src/Simulation/Simulators.Type2.Tests/Tests.Microsoft.Quantum.Simulators.Type2.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj b/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj index 8bd1d9a7828..d66eb0ee909 100644 --- a/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj +++ b/src/Simulation/Simulators.Type3.Tests/Tests.Microsoft.Quantum.Simulators.Type3.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj index df891ab5eb0..2b2cf28cb92 100644 --- a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj b/src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj index f21cd835b30..0519a40b106 100644 --- a/src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj +++ b/src/Simulation/Type1Core/Microsoft.Quantum.Type1.Core.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj b/src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj index 9bec9e8d8f2..5a3f78e20a5 100644 --- a/src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj +++ b/src/Simulation/Type2Core/Microsoft.Quantum.Type2.Core.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj b/src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj index fb0d25c2e8e..7d9715f3020 100644 --- a/src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj +++ b/src/Simulation/Type3Core/Microsoft.Quantum.Type3.Core.csproj @@ -1,4 +1,4 @@ - +