qsharp-lang 1.13.1-dev → 1.13.3-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +1 -0
- package/dist/compiler/compiler.d.ts +3 -3
- package/dist/compiler/compiler.js +2 -2
- package/dist/debug-service/debug-service.d.ts +1 -1
- package/dist/katas-content.generated.js +1 -1
- package/dist/katas-content.generated.md.js +1 -1
- package/dist/shared/circuit.d.ts +64 -0
- package/dist/shared/circuit.js +16 -0
- package/dist/shared/register.d.ts +35 -0
- package/dist/shared/register.js +10 -0
- package/docs/Microsoft.Quantum.Core/Length.md +1 -1
- package/docs/Microsoft.Quantum.Core/Repeated.md +1 -1
- package/docs/Microsoft.Quantum.Core/index.md +1 -1
- package/docs/Std.Arithmetic/AddLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfEqualLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessOrEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessOrEqualLE.md +1 -1
- package/docs/Std.Arithmetic/FourierTDIncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByI.md +1 -1
- package/docs/Std.Arithmetic/IncByIUsingIncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByL.md +1 -1
- package/docs/Std.Arithmetic/IncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByLEUsingAddLE.md +1 -1
- package/docs/Std.Arithmetic/IncByLUsingIncByLE.md +1 -1
- package/docs/Std.Arithmetic/LookAheadDKRSAddLE.md +1 -1
- package/docs/Std.Arithmetic/MAJ.md +1 -1
- package/docs/Std.Arithmetic/ReflectAboutInteger.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryCGAddLE.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryCGIncByLE.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryTTKIncByLE.md +1 -1
- package/docs/Std.Arithmetic/index.md +1 -1
- package/docs/Std.Arrays/All.md +1 -1
- package/docs/Std.Arrays/Any.md +1 -1
- package/docs/Std.Arrays/Chunks.md +1 -1
- package/docs/Std.Arrays/CircularlyShifted.md +1 -1
- package/docs/Std.Arrays/ColumnAt.md +1 -1
- package/docs/Std.Arrays/Count.md +1 -1
- package/docs/Std.Arrays/Diagonal.md +1 -1
- package/docs/Std.Arrays/DrawMany.md +1 -1
- package/docs/Std.Arrays/Enumerated.md +1 -1
- package/docs/Std.Arrays/Excluding.md +1 -1
- package/docs/Std.Arrays/Filtered.md +1 -1
- package/docs/Std.Arrays/FlatMapped.md +1 -1
- package/docs/Std.Arrays/Flattened.md +1 -1
- package/docs/Std.Arrays/Fold.md +1 -1
- package/docs/Std.Arrays/ForEach.md +1 -1
- package/docs/Std.Arrays/Head.md +1 -1
- package/docs/Std.Arrays/HeadAndRest.md +1 -1
- package/docs/Std.Arrays/IndexOf.md +1 -1
- package/docs/Std.Arrays/IndexRange.md +1 -1
- package/docs/Std.Arrays/Interleaved.md +1 -1
- package/docs/Std.Arrays/IsEmpty.md +1 -1
- package/docs/Std.Arrays/IsRectangularArray.md +1 -1
- package/docs/Std.Arrays/IsSorted.md +1 -1
- package/docs/Std.Arrays/IsSquareArray.md +1 -1
- package/docs/Std.Arrays/Mapped.md +1 -1
- package/docs/Std.Arrays/MappedByIndex.md +1 -1
- package/docs/Std.Arrays/MappedOverRange.md +1 -1
- package/docs/Std.Arrays/Most.md +1 -1
- package/docs/Std.Arrays/MostAndTail.md +1 -1
- package/docs/Std.Arrays/Padded.md +1 -1
- package/docs/Std.Arrays/Partitioned.md +1 -1
- package/docs/Std.Arrays/Rest.md +1 -1
- package/docs/Std.Arrays/Reversed.md +1 -1
- package/docs/Std.Arrays/SequenceI.md +1 -1
- package/docs/Std.Arrays/SequenceL.md +1 -1
- package/docs/Std.Arrays/Sorted.md +1 -1
- package/docs/Std.Arrays/Subarray.md +1 -1
- package/docs/Std.Arrays/Swapped.md +1 -1
- package/docs/Std.Arrays/Tail.md +1 -1
- package/docs/Std.Arrays/Transposed.md +1 -1
- package/docs/Std.Arrays/Unzipped.md +1 -1
- package/docs/Std.Arrays/Where.md +1 -1
- package/docs/Std.Arrays/Windows.md +1 -1
- package/docs/Std.Arrays/Zipped.md +1 -1
- package/docs/Std.Arrays/index.md +1 -1
- package/docs/Std.Canon/ApplyCNOTChain.md +1 -1
- package/docs/Std.Canon/ApplyControlledOnBitString.md +1 -1
- package/docs/Std.Canon/ApplyControlledOnInt.md +1 -1
- package/docs/Std.Canon/ApplyP.md +1 -1
- package/docs/Std.Canon/ApplyPauli.md +1 -1
- package/docs/Std.Canon/ApplyPauliFromBitString.md +1 -1
- package/docs/Std.Canon/ApplyPauliFromInt.md +1 -1
- package/docs/Std.Canon/ApplyQFT.md +1 -1
- package/docs/Std.Canon/ApplyToEach.md +1 -1
- package/docs/Std.Canon/ApplyToEachA.md +1 -1
- package/docs/Std.Canon/ApplyToEachC.md +1 -1
- package/docs/Std.Canon/ApplyToEachCA.md +1 -1
- package/docs/Std.Canon/ApplyXorInPlace.md +1 -1
- package/docs/Std.Canon/ApplyXorInPlaceL.md +1 -1
- package/docs/Std.Canon/CX.md +1 -1
- package/docs/Std.Canon/CY.md +1 -1
- package/docs/Std.Canon/CZ.md +1 -1
- package/docs/Std.Canon/Fst.md +1 -1
- package/docs/Std.Canon/Relabel.md +1 -1
- package/docs/Std.Canon/Snd.md +1 -1
- package/docs/Std.Canon/SwapReverseRegister.md +1 -1
- package/docs/Std.Canon/index.md +1 -1
- package/docs/Std.Convert/BigIntAsBoolArray.md +1 -1
- package/docs/Std.Convert/BoolArrayAsBigInt.md +1 -1
- package/docs/Std.Convert/BoolArrayAsInt.md +1 -1
- package/docs/Std.Convert/BoolArrayAsResultArray.md +1 -1
- package/docs/Std.Convert/BoolAsResult.md +1 -1
- package/docs/Std.Convert/ComplexAsComplexPolar.md +1 -1
- package/docs/Std.Convert/ComplexPolarAsComplex.md +1 -1
- package/docs/Std.Convert/DoubleAsStringWithPrecision.md +1 -1
- package/docs/Std.Convert/IntAsBigInt.md +1 -1
- package/docs/Std.Convert/IntAsBoolArray.md +1 -1
- package/docs/Std.Convert/IntAsDouble.md +1 -1
- package/docs/Std.Convert/ResultArrayAsBoolArray.md +1 -1
- package/docs/Std.Convert/ResultArrayAsInt.md +1 -1
- package/docs/Std.Convert/ResultAsBool.md +1 -1
- package/docs/Std.Convert/index.md +1 -1
- package/docs/Std.Core/Length.md +1 -1
- package/docs/Std.Core/Repeated.md +1 -1
- package/docs/Std.Core/index.md +1 -1
- package/docs/Std.Diagnostics/ApplyIdleNoise.md +1 -1
- package/docs/Std.Diagnostics/BitFlipNoise.md +1 -1
- package/docs/Std.Diagnostics/CheckAllZero.md +1 -1
- package/docs/Std.Diagnostics/CheckOperationsAreEqual.md +1 -1
- package/docs/Std.Diagnostics/CheckZero.md +1 -1
- package/docs/Std.Diagnostics/ConfigurePauliNoise.md +1 -1
- package/docs/Std.Diagnostics/DepolarizingNoise.md +1 -1
- package/docs/Std.Diagnostics/DumpMachine.md +1 -1
- package/docs/Std.Diagnostics/DumpOperation.md +1 -1
- package/docs/Std.Diagnostics/DumpRegister.md +1 -1
- package/docs/Std.Diagnostics/Fact.md +1 -1
- package/docs/Std.Diagnostics/NoNoise.md +1 -1
- package/docs/Std.Diagnostics/PhaseFlipNoise.md +1 -1
- package/docs/Std.Diagnostics/StartCountingFunction.md +1 -1
- package/docs/Std.Diagnostics/StartCountingOperation.md +1 -1
- package/docs/Std.Diagnostics/StartCountingQubits.md +1 -1
- package/docs/Std.Diagnostics/StopCountingFunction.md +1 -1
- package/docs/Std.Diagnostics/StopCountingOperation.md +1 -1
- package/docs/Std.Diagnostics/StopCountingQubits.md +1 -1
- package/docs/Std.Diagnostics/index.md +1 -1
- package/docs/Std.Intrinsic/AND.md +1 -1
- package/docs/Std.Intrinsic/ApplyUnitary.md +1 -1
- package/docs/Std.Intrinsic/CCNOT.md +1 -1
- package/docs/Std.Intrinsic/CNOT.md +1 -1
- package/docs/Std.Intrinsic/Exp.md +1 -1
- package/docs/Std.Intrinsic/H.md +1 -1
- package/docs/Std.Intrinsic/I.md +1 -1
- package/docs/Std.Intrinsic/M.md +1 -1
- package/docs/Std.Intrinsic/Measure.md +1 -1
- package/docs/Std.Intrinsic/Message.md +1 -1
- package/docs/Std.Intrinsic/R.md +1 -1
- package/docs/Std.Intrinsic/R1.md +1 -1
- package/docs/Std.Intrinsic/R1Frac.md +1 -1
- package/docs/Std.Intrinsic/RFrac.md +1 -1
- package/docs/Std.Intrinsic/Reset.md +1 -1
- package/docs/Std.Intrinsic/ResetAll.md +1 -1
- package/docs/Std.Intrinsic/Rx.md +1 -1
- package/docs/Std.Intrinsic/Rxx.md +1 -1
- package/docs/Std.Intrinsic/Ry.md +1 -1
- package/docs/Std.Intrinsic/Ryy.md +1 -1
- package/docs/Std.Intrinsic/Rz.md +1 -1
- package/docs/Std.Intrinsic/Rzz.md +1 -1
- package/docs/Std.Intrinsic/S.md +1 -1
- package/docs/Std.Intrinsic/SWAP.md +1 -1
- package/docs/Std.Intrinsic/T.md +1 -1
- package/docs/Std.Intrinsic/X.md +1 -1
- package/docs/Std.Intrinsic/Y.md +1 -1
- package/docs/Std.Intrinsic/Z.md +1 -1
- package/docs/Std.Intrinsic/index.md +1 -1
- package/docs/Std.Logical/Xor.md +1 -1
- package/docs/Std.Logical/index.md +1 -1
- package/docs/Std.Math/AbsComplex.md +1 -1
- package/docs/Std.Math/AbsComplexPolar.md +1 -1
- package/docs/Std.Math/AbsD.md +1 -1
- package/docs/Std.Math/AbsI.md +1 -1
- package/docs/Std.Math/AbsL.md +1 -1
- package/docs/Std.Math/AbsSquaredComplex.md +1 -1
- package/docs/Std.Math/AbsSquaredComplexPolar.md +1 -1
- package/docs/Std.Math/ApproximateFactorial.md +1 -1
- package/docs/Std.Math/ArcCos.md +1 -1
- package/docs/Std.Math/ArcCosh.md +1 -1
- package/docs/Std.Math/ArcSin.md +1 -1
- package/docs/Std.Math/ArcSinh.md +1 -1
- package/docs/Std.Math/ArcTan.md +1 -1
- package/docs/Std.Math/ArcTan2.md +1 -1
- package/docs/Std.Math/ArcTanh.md +1 -1
- package/docs/Std.Math/ArgComplex.md +1 -1
- package/docs/Std.Math/ArgComplexPolar.md +1 -1
- package/docs/Std.Math/Binom.md +1 -1
- package/docs/Std.Math/BitSizeI.md +1 -1
- package/docs/Std.Math/BitSizeL.md +1 -1
- package/docs/Std.Math/Ceiling.md +1 -1
- package/docs/Std.Math/Complex.md +1 -1
- package/docs/Std.Math/ComplexPolar.md +1 -1
- package/docs/Std.Math/ContinuedFractionConvergentI.md +1 -1
- package/docs/Std.Math/ContinuedFractionConvergentL.md +1 -1
- package/docs/Std.Math/Cos.md +1 -1
- package/docs/Std.Math/Cosh.md +1 -1
- package/docs/Std.Math/DivRemI.md +1 -1
- package/docs/Std.Math/DivRemL.md +1 -1
- package/docs/Std.Math/DividedByC.md +1 -1
- package/docs/Std.Math/DividedByCP.md +1 -1
- package/docs/Std.Math/E.md +1 -1
- package/docs/Std.Math/ExpModI.md +1 -1
- package/docs/Std.Math/ExpModL.md +1 -1
- package/docs/Std.Math/ExtendedGreatestCommonDivisorI.md +1 -1
- package/docs/Std.Math/ExtendedGreatestCommonDivisorL.md +1 -1
- package/docs/Std.Math/FactorialI.md +1 -1
- package/docs/Std.Math/FactorialL.md +1 -1
- package/docs/Std.Math/Floor.md +1 -1
- package/docs/Std.Math/GreatestCommonDivisorI.md +1 -1
- package/docs/Std.Math/GreatestCommonDivisorL.md +1 -1
- package/docs/Std.Math/HammingWeightI.md +1 -1
- package/docs/Std.Math/InverseModI.md +1 -1
- package/docs/Std.Math/InverseModL.md +1 -1
- package/docs/Std.Math/IsCoprimeI.md +1 -1
- package/docs/Std.Math/IsCoprimeL.md +1 -1
- package/docs/Std.Math/IsInfinite.md +1 -1
- package/docs/Std.Math/IsNaN.md +1 -1
- package/docs/Std.Math/LargestFixedPoint.md +1 -1
- package/docs/Std.Math/Lg.md +1 -1
- package/docs/Std.Math/Log.md +1 -1
- package/docs/Std.Math/Log10.md +1 -1
- package/docs/Std.Math/LogFactorialD.md +1 -1
- package/docs/Std.Math/LogGammaD.md +1 -1
- package/docs/Std.Math/LogOf2.md +1 -1
- package/docs/Std.Math/Max.md +1 -1
- package/docs/Std.Math/MaxD.md +1 -1
- package/docs/Std.Math/MaxI.md +1 -1
- package/docs/Std.Math/MaxL.md +1 -1
- package/docs/Std.Math/Min.md +1 -1
- package/docs/Std.Math/MinD.md +1 -1
- package/docs/Std.Math/MinI.md +1 -1
- package/docs/Std.Math/MinL.md +1 -1
- package/docs/Std.Math/MinusC.md +1 -1
- package/docs/Std.Math/MinusCP.md +1 -1
- package/docs/Std.Math/ModulusI.md +1 -1
- package/docs/Std.Math/ModulusL.md +1 -1
- package/docs/Std.Math/NegationC.md +1 -1
- package/docs/Std.Math/NegationCP.md +1 -1
- package/docs/Std.Math/PI.md +1 -1
- package/docs/Std.Math/PNorm.md +1 -1
- package/docs/Std.Math/PNormalized.md +1 -1
- package/docs/Std.Math/PlusC.md +1 -1
- package/docs/Std.Math/PlusCP.md +1 -1
- package/docs/Std.Math/PowC.md +1 -1
- package/docs/Std.Math/PowCP.md +1 -1
- package/docs/Std.Math/RealMod.md +1 -1
- package/docs/Std.Math/Round.md +1 -1
- package/docs/Std.Math/SignD.md +1 -1
- package/docs/Std.Math/SignI.md +1 -1
- package/docs/Std.Math/SignL.md +1 -1
- package/docs/Std.Math/Sin.md +1 -1
- package/docs/Std.Math/Sinh.md +1 -1
- package/docs/Std.Math/SmallestFixedPoint.md +1 -1
- package/docs/Std.Math/Sqrt.md +1 -1
- package/docs/Std.Math/SquaredNorm.md +1 -1
- package/docs/Std.Math/Tan.md +1 -1
- package/docs/Std.Math/Tanh.md +1 -1
- package/docs/Std.Math/TimesC.md +1 -1
- package/docs/Std.Math/TimesCP.md +1 -1
- package/docs/Std.Math/TrailingZeroCountI.md +1 -1
- package/docs/Std.Math/TrailingZeroCountL.md +1 -1
- package/docs/Std.Math/Truncate.md +1 -1
- package/docs/Std.Math/index.md +1 -1
- package/docs/Std.Measurement/MResetEachZ.md +1 -1
- package/docs/Std.Measurement/MResetX.md +1 -1
- package/docs/Std.Measurement/MResetY.md +1 -1
- package/docs/Std.Measurement/MResetZ.md +1 -1
- package/docs/Std.Measurement/MeasureAllZ.md +1 -1
- package/docs/Std.Measurement/MeasureEachZ.md +1 -1
- package/docs/Std.Measurement/MeasureInteger.md +1 -1
- package/docs/Std.Measurement/index.md +1 -1
- package/docs/Std.Random/DrawRandomBool.md +1 -1
- package/docs/Std.Random/DrawRandomDouble.md +1 -1
- package/docs/Std.Random/DrawRandomInt.md +1 -1
- package/docs/Std.Random/index.md +1 -1
- package/docs/Std.Range/IsRangeEmpty.md +1 -1
- package/docs/Std.Range/RangeEnd.md +1 -1
- package/docs/Std.Range/RangeReverse.md +1 -1
- package/docs/Std.Range/RangeStart.md +1 -1
- package/docs/Std.Range/RangeStep.md +1 -1
- package/docs/Std.Range/index.md +1 -1
- package/docs/Std.ResourceEstimation/AccountForEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/AuxQubitCount.md +1 -1
- package/docs/Std.ResourceEstimation/BeginEstimateCaching.md +1 -1
- package/docs/Std.ResourceEstimation/BeginRepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/CczCount.md +1 -1
- package/docs/Std.ResourceEstimation/EndEstimateCaching.md +1 -1
- package/docs/Std.ResourceEstimation/EndRepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/MeasurementCount.md +1 -1
- package/docs/Std.ResourceEstimation/PSSPCLayout.md +1 -1
- package/docs/Std.ResourceEstimation/RepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/RotationCount.md +1 -1
- package/docs/Std.ResourceEstimation/RotationDepth.md +1 -1
- package/docs/Std.ResourceEstimation/SingleVariant.md +1 -1
- package/docs/Std.ResourceEstimation/TCount.md +1 -1
- package/docs/Std.ResourceEstimation/index.md +1 -1
- package/docs/Std.StatePreparation/ApproximatelyPreparePureStateCP.md +1 -1
- package/docs/Std.StatePreparation/PreparePureStateD.md +1 -1
- package/docs/Std.StatePreparation/index.md +1 -1
- package/docs/Std.TableLookup/Select.md +1 -1
- package/docs/Std.TableLookup/index.md +1 -1
- package/docs/index.md +1 -1
- package/lib/node/qsc_wasm.cjs +17 -14
- package/lib/node/qsc_wasm.d.cts +3 -6
- package/lib/node/qsc_wasm_bg.wasm +0 -0
- package/lib/web/qsc_wasm.d.ts +4 -7
- package/lib/web/qsc_wasm.js +17 -14
- package/lib/web/qsc_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/ux/circuit-vis/README.md +1 -0
- package/ux/circuit-vis/circuit.ts +10 -0
- package/ux/circuit-vis/constants.ts +39 -0
- package/ux/circuit-vis/formatters/formatUtils.ts +220 -0
- package/ux/circuit-vis/formatters/gateFormatter.ts +557 -0
- package/ux/circuit-vis/formatters/inputFormatter.ts +78 -0
- package/ux/circuit-vis/formatters/registerFormatter.ts +118 -0
- package/ux/circuit-vis/index.ts +30 -0
- package/ux/circuit-vis/metadata.ts +56 -0
- package/ux/circuit-vis/process.ts +536 -0
- package/ux/circuit-vis/register.ts +9 -0
- package/ux/circuit-vis/sqore.ts +376 -0
- package/ux/circuit-vis/styles.ts +236 -0
- package/ux/circuit-vis/utils.ts +77 -0
- package/ux/circuit.tsx +2 -2
- package/ux/data.ts +1 -1
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
minGateWidth,
|
|
6
|
+
startX,
|
|
7
|
+
gatePadding,
|
|
8
|
+
controlBtnOffset,
|
|
9
|
+
groupBoxPadding,
|
|
10
|
+
} from "./constants";
|
|
11
|
+
import { Operation, ConditionalRender } from "./circuit";
|
|
12
|
+
import { Metadata, GateType } from "./metadata";
|
|
13
|
+
import { Register, RegisterMap, RegisterType } from "./register";
|
|
14
|
+
import { getGateWidth } from "./utils";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Takes in a list of operations and maps them to `metadata` objects which
|
|
18
|
+
* contains information for formatting the corresponding SVG.
|
|
19
|
+
*
|
|
20
|
+
* @param operations Array of operations.
|
|
21
|
+
* @param registers Mapping from qubit IDs to register metadata.
|
|
22
|
+
*
|
|
23
|
+
* @returns An object containing `metadataList` (Array of Metadata objects) and
|
|
24
|
+
* `svgWidth` which is the width of the entire SVG.
|
|
25
|
+
*/
|
|
26
|
+
const processOperations = (
|
|
27
|
+
operations: Operation[],
|
|
28
|
+
registers: RegisterMap,
|
|
29
|
+
): { metadataList: Metadata[]; svgWidth: number } => {
|
|
30
|
+
if (operations.length === 0) return { metadataList: [], svgWidth: startX };
|
|
31
|
+
|
|
32
|
+
// Group operations based on registers
|
|
33
|
+
const groupedOps: number[][] = _groupOperations(operations, registers);
|
|
34
|
+
|
|
35
|
+
// Align operations on multiple registers
|
|
36
|
+
const alignedOps: (number | null)[][] = _alignOps(groupedOps);
|
|
37
|
+
|
|
38
|
+
// Maintain widths of each column to account for variable-sized gates
|
|
39
|
+
const numColumns: number = Math.max(
|
|
40
|
+
0,
|
|
41
|
+
...alignedOps.map((ops) => ops.length),
|
|
42
|
+
);
|
|
43
|
+
const columnsWidths: number[] = new Array(numColumns).fill(minGateWidth);
|
|
44
|
+
|
|
45
|
+
// Get classical registers and their starting column index
|
|
46
|
+
const classicalRegs: [number, Register][] = _getClassicalRegStart(
|
|
47
|
+
operations,
|
|
48
|
+
alignedOps,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// Keep track of which ops are already seen to avoid duplicate rendering
|
|
52
|
+
const visited: { [opIdx: number]: boolean } = {};
|
|
53
|
+
|
|
54
|
+
// Map operation index to gate metadata for formatting later
|
|
55
|
+
const opsMetadata: Metadata[][] = alignedOps.map((regOps) =>
|
|
56
|
+
regOps.map((opIdx, col) => {
|
|
57
|
+
let op: Operation | null = null;
|
|
58
|
+
|
|
59
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
60
|
+
if (opIdx != null && !visited.hasOwnProperty(opIdx)) {
|
|
61
|
+
op = operations[opIdx];
|
|
62
|
+
visited[opIdx] = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const metadata: Metadata = _opToMetadata(op, registers);
|
|
66
|
+
|
|
67
|
+
if (
|
|
68
|
+
op != null &&
|
|
69
|
+
[GateType.Unitary, GateType.ControlledUnitary].includes(metadata.type)
|
|
70
|
+
) {
|
|
71
|
+
// If gate is a unitary type, split targetsY into groups if there
|
|
72
|
+
// is a classical register between them for rendering
|
|
73
|
+
|
|
74
|
+
// Get y coordinates of classical registers in the same column as this operation
|
|
75
|
+
const classicalRegY: number[] = classicalRegs
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
.filter(([regCol, _]) => regCol <= col)
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
79
|
+
.map(([_, reg]) => {
|
|
80
|
+
if (reg.cId == null)
|
|
81
|
+
throw new Error("Could not find cId for classical register.");
|
|
82
|
+
const { children } = registers[reg.qId];
|
|
83
|
+
if (children == null)
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Failed to find classical registers for qubit ID ${reg.qId}.`,
|
|
86
|
+
);
|
|
87
|
+
return children[reg.cId].y;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
metadata.targetsY = _splitTargetsY(
|
|
91
|
+
op.targets,
|
|
92
|
+
classicalRegY,
|
|
93
|
+
registers,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Expand column size, if needed
|
|
98
|
+
if (metadata.width > columnsWidths[col]) {
|
|
99
|
+
columnsWidths[col] = metadata.width;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return metadata;
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Fill in x coord of each gate
|
|
107
|
+
const endX: number = _fillMetadataX(opsMetadata, columnsWidths);
|
|
108
|
+
|
|
109
|
+
// Flatten operations and filter out invalid gates
|
|
110
|
+
const metadataList: Metadata[] = opsMetadata
|
|
111
|
+
.flat()
|
|
112
|
+
.filter(({ type }) => type != GateType.Invalid);
|
|
113
|
+
|
|
114
|
+
return { metadataList, svgWidth: endX };
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Group gates provided by operations into their respective registers.
|
|
119
|
+
*
|
|
120
|
+
* @param operations Array of operations.
|
|
121
|
+
* @param numRegs Total number of registers.
|
|
122
|
+
*
|
|
123
|
+
* @returns 2D array of indices where `groupedOps[i][j]` is the index of the operations
|
|
124
|
+
* at register `i` and column `j` (not yet aligned/padded).
|
|
125
|
+
*/
|
|
126
|
+
const _groupOperations = (
|
|
127
|
+
operations: Operation[],
|
|
128
|
+
registers: RegisterMap,
|
|
129
|
+
): number[][] => {
|
|
130
|
+
// NOTE: We get the max ID instead of just number of keys because there can be a qubit ID that
|
|
131
|
+
// isn't acted upon and thus does not show up as a key in registers.
|
|
132
|
+
const numRegs: number =
|
|
133
|
+
Math.max(-1, ...Object.keys(registers).map(Number)) + 1;
|
|
134
|
+
const groupedOps: number[][] = Array.from(Array(numRegs), () => new Array(0));
|
|
135
|
+
operations.forEach(({ targets, controls }, instrIdx) => {
|
|
136
|
+
const ctrls: Register[] = controls || [];
|
|
137
|
+
const qRegs: Register[] = [...ctrls, ...targets].filter(
|
|
138
|
+
({ type }) => (type || RegisterType.Qubit) === RegisterType.Qubit,
|
|
139
|
+
);
|
|
140
|
+
const qRegIdxList: number[] = qRegs.map(({ qId }) => qId);
|
|
141
|
+
const clsControls: Register[] = ctrls.filter(
|
|
142
|
+
({ type }) => (type || RegisterType.Qubit) === RegisterType.Classical,
|
|
143
|
+
);
|
|
144
|
+
const isClassicallyControlled: boolean = clsControls.length > 0;
|
|
145
|
+
if (!isClassicallyControlled && qRegs.length === 0) return;
|
|
146
|
+
// If operation is classically-controlled, pad all qubit registers. Otherwise, only pad
|
|
147
|
+
// the contiguous range of registers that it covers.
|
|
148
|
+
const minRegIdx: number = isClassicallyControlled
|
|
149
|
+
? 0
|
|
150
|
+
: Math.min(...qRegIdxList);
|
|
151
|
+
const maxRegIdx: number = isClassicallyControlled
|
|
152
|
+
? numRegs - 1
|
|
153
|
+
: Math.max(...qRegIdxList);
|
|
154
|
+
// Add operation also to registers that are in-between target registers
|
|
155
|
+
// so that other gates won't render in the middle.
|
|
156
|
+
for (let i = minRegIdx; i <= maxRegIdx; i++) {
|
|
157
|
+
groupedOps[i].push(instrIdx);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return groupedOps;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Aligns operations by padding registers with `null`s to make sure that multiqubit
|
|
165
|
+
* gates are in the same column.
|
|
166
|
+
* e.g. ---[x]---[x]--
|
|
167
|
+
* ----------|---
|
|
168
|
+
*
|
|
169
|
+
* @param ops 2D array of operations. Each row represents a register
|
|
170
|
+
* and the operations acting on it (in-order).
|
|
171
|
+
*
|
|
172
|
+
* @returns 2D array of aligned operations padded with `null`s.
|
|
173
|
+
*/
|
|
174
|
+
const _alignOps = (ops: number[][]): (number | null)[][] => {
|
|
175
|
+
let maxNumOps: number = Math.max(0, ...ops.map((regOps) => regOps.length));
|
|
176
|
+
let col = 0;
|
|
177
|
+
// Deep copy ops to be returned as paddedOps
|
|
178
|
+
const paddedOps: (number | null)[][] = JSON.parse(JSON.stringify(ops));
|
|
179
|
+
while (col < maxNumOps) {
|
|
180
|
+
for (let regIdx = 0; regIdx < paddedOps.length; regIdx++) {
|
|
181
|
+
const reg: (number | null)[] = paddedOps[regIdx];
|
|
182
|
+
if (reg.length <= col) continue;
|
|
183
|
+
|
|
184
|
+
// Should never be null (nulls are only padded to previous columns)
|
|
185
|
+
const opIdx: number | null = reg[col];
|
|
186
|
+
|
|
187
|
+
// Get position of gate
|
|
188
|
+
const targetsPos: number[] = paddedOps.map((regOps) =>
|
|
189
|
+
regOps.indexOf(opIdx),
|
|
190
|
+
);
|
|
191
|
+
const gatePos: number = Math.max(-1, ...targetsPos);
|
|
192
|
+
|
|
193
|
+
// If current column is not desired gate position, pad with null
|
|
194
|
+
if (col < gatePos) {
|
|
195
|
+
paddedOps[regIdx].splice(col, 0, null);
|
|
196
|
+
maxNumOps = Math.max(maxNumOps, paddedOps[regIdx].length);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
col++;
|
|
200
|
+
}
|
|
201
|
+
return paddedOps;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Retrieves the starting index of each classical register.
|
|
206
|
+
*
|
|
207
|
+
* @param ops Array of operations.
|
|
208
|
+
* @param idxList 2D array of aligned operation indices.
|
|
209
|
+
*
|
|
210
|
+
* @returns Array of classical register and their starting column indices in the form [[column, register]].
|
|
211
|
+
*/
|
|
212
|
+
const _getClassicalRegStart = (
|
|
213
|
+
ops: Operation[],
|
|
214
|
+
idxList: (number | null)[][],
|
|
215
|
+
): [number, Register][] => {
|
|
216
|
+
const clsRegs: [number, Register][] = [];
|
|
217
|
+
idxList.forEach((reg) => {
|
|
218
|
+
for (let col = 0; col < reg.length; col++) {
|
|
219
|
+
const opIdx: number | null = reg[col];
|
|
220
|
+
if (opIdx != null && ops[opIdx].isMeasurement) {
|
|
221
|
+
const targetClsRegs: Register[] = ops[opIdx].targets.filter(
|
|
222
|
+
(reg) => reg.type === RegisterType.Classical,
|
|
223
|
+
);
|
|
224
|
+
targetClsRegs.forEach((reg) => clsRegs.push([col, reg]));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
return clsRegs;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Maps operation to metadata (e.g. gate type, position, dimensions, text)
|
|
233
|
+
* required to render the image.
|
|
234
|
+
*
|
|
235
|
+
* @param op Operation to be mapped into metadata format.
|
|
236
|
+
* @param registers Array of registers.
|
|
237
|
+
*
|
|
238
|
+
* @returns Metadata representation of given operation.
|
|
239
|
+
*/
|
|
240
|
+
const _opToMetadata = (
|
|
241
|
+
op: Operation | null,
|
|
242
|
+
registers: RegisterMap,
|
|
243
|
+
): Metadata => {
|
|
244
|
+
const metadata: Metadata = {
|
|
245
|
+
type: GateType.Invalid,
|
|
246
|
+
x: 0,
|
|
247
|
+
controlsY: [],
|
|
248
|
+
targetsY: [],
|
|
249
|
+
label: "",
|
|
250
|
+
width: -1,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
if (op == null) return metadata;
|
|
254
|
+
|
|
255
|
+
const {
|
|
256
|
+
gate,
|
|
257
|
+
dataAttributes,
|
|
258
|
+
displayArgs,
|
|
259
|
+
isMeasurement,
|
|
260
|
+
isConditional,
|
|
261
|
+
isControlled,
|
|
262
|
+
isAdjoint,
|
|
263
|
+
controls,
|
|
264
|
+
targets,
|
|
265
|
+
children,
|
|
266
|
+
conditionalRender,
|
|
267
|
+
} = op;
|
|
268
|
+
|
|
269
|
+
// Set y coords
|
|
270
|
+
metadata.controlsY = controls?.map((reg) => _getRegY(reg, registers)) || [];
|
|
271
|
+
metadata.targetsY = targets.map((reg) => _getRegY(reg, registers));
|
|
272
|
+
|
|
273
|
+
if (isConditional) {
|
|
274
|
+
// Classically-controlled operations
|
|
275
|
+
if (children == null || children.length == 0)
|
|
276
|
+
throw new Error(
|
|
277
|
+
"No children operations found for classically-controlled operation.",
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
// Gates to display when classical bit is 0.
|
|
281
|
+
const onZeroOps: Operation[] = children.filter(
|
|
282
|
+
(op) => op.conditionalRender !== ConditionalRender.OnOne,
|
|
283
|
+
);
|
|
284
|
+
let childrenInstrs = processOperations(onZeroOps, registers);
|
|
285
|
+
const zeroGates: Metadata[] = childrenInstrs.metadataList;
|
|
286
|
+
const zeroChildWidth: number = childrenInstrs.svgWidth;
|
|
287
|
+
|
|
288
|
+
// Gates to display when classical bit is 1.
|
|
289
|
+
const onOneOps: Operation[] = children.filter(
|
|
290
|
+
(op) => op.conditionalRender !== ConditionalRender.OnZero,
|
|
291
|
+
);
|
|
292
|
+
childrenInstrs = processOperations(onOneOps, registers);
|
|
293
|
+
const oneGates: Metadata[] = childrenInstrs.metadataList;
|
|
294
|
+
const oneChildWidth: number = childrenInstrs.svgWidth;
|
|
295
|
+
|
|
296
|
+
// Subtract startX (left-side) and 2*gatePadding (right-side) from nested child gates width
|
|
297
|
+
const width: number =
|
|
298
|
+
Math.max(zeroChildWidth, oneChildWidth) - startX - gatePadding * 2;
|
|
299
|
+
|
|
300
|
+
metadata.type = GateType.ClassicalControlled;
|
|
301
|
+
metadata.children = [zeroGates, oneGates];
|
|
302
|
+
// Add additional width from control button and inner box padding for dashed box
|
|
303
|
+
metadata.width = width + controlBtnOffset + groupBoxPadding * 2;
|
|
304
|
+
|
|
305
|
+
// Set targets to first and last quantum registers so we can render the surrounding box
|
|
306
|
+
// around all quantum registers.
|
|
307
|
+
const qubitsY: number[] = Object.values(registers).map(({ y }) => y);
|
|
308
|
+
if (qubitsY.length > 0)
|
|
309
|
+
metadata.targetsY = [Math.min(...qubitsY), Math.max(...qubitsY)];
|
|
310
|
+
} else if (
|
|
311
|
+
conditionalRender == ConditionalRender.AsGroup &&
|
|
312
|
+
(children?.length || 0) > 0
|
|
313
|
+
) {
|
|
314
|
+
const childrenInstrs = processOperations(
|
|
315
|
+
children as Operation[],
|
|
316
|
+
registers,
|
|
317
|
+
);
|
|
318
|
+
metadata.type = GateType.Group;
|
|
319
|
+
metadata.children = childrenInstrs.metadataList;
|
|
320
|
+
// _zoomButton function in gateFormatter.ts relies on
|
|
321
|
+
// 'expanded' attribute to render zoom button
|
|
322
|
+
metadata.dataAttributes = { expanded: "true" };
|
|
323
|
+
// Subtract startX (left-side) and add inner box padding (minus nested gate padding) for dashed box
|
|
324
|
+
metadata.width =
|
|
325
|
+
childrenInstrs.svgWidth - startX + (groupBoxPadding - gatePadding) * 2;
|
|
326
|
+
} else if (isMeasurement) {
|
|
327
|
+
metadata.type = GateType.Measure;
|
|
328
|
+
} else if (gate === "SWAP") {
|
|
329
|
+
metadata.type = GateType.Swap;
|
|
330
|
+
} else if (isControlled) {
|
|
331
|
+
metadata.type = gate === "X" ? GateType.Cnot : GateType.ControlledUnitary;
|
|
332
|
+
metadata.label = gate;
|
|
333
|
+
} else if (gate === "X") {
|
|
334
|
+
metadata.type = GateType.X;
|
|
335
|
+
metadata.label = gate;
|
|
336
|
+
} else {
|
|
337
|
+
// Any other gate treated as a simple unitary gate
|
|
338
|
+
metadata.type = GateType.Unitary;
|
|
339
|
+
metadata.label = gate;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// If adjoint, add ' to the end of gate label
|
|
343
|
+
if (isAdjoint && metadata.label.length > 0) metadata.label += "'";
|
|
344
|
+
|
|
345
|
+
// If gate has extra arguments, display them
|
|
346
|
+
if (displayArgs != null) metadata.displayArgs = displayArgs;
|
|
347
|
+
|
|
348
|
+
// Set gate width
|
|
349
|
+
metadata.width = getGateWidth(metadata);
|
|
350
|
+
|
|
351
|
+
// Extend existing data attributes with user-provided data attributes
|
|
352
|
+
if (dataAttributes != null)
|
|
353
|
+
metadata.dataAttributes = { ...metadata.dataAttributes, ...dataAttributes };
|
|
354
|
+
|
|
355
|
+
return metadata;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Compute the y coord of a given register.
|
|
360
|
+
*
|
|
361
|
+
* @param reg Register to compute y coord of.
|
|
362
|
+
* @param registers Map of qubit IDs to RegisterMetadata.
|
|
363
|
+
*
|
|
364
|
+
* @returns The y coord of give register.
|
|
365
|
+
*/
|
|
366
|
+
const _getRegY = (reg: Register, registers: RegisterMap): number => {
|
|
367
|
+
const { type, qId, cId } = reg;
|
|
368
|
+
if (!Object.prototype.hasOwnProperty.call(registers, qId))
|
|
369
|
+
throw new Error(`ERROR: Qubit register with ID ${qId} not found.`);
|
|
370
|
+
const { y, children } = registers[qId];
|
|
371
|
+
switch (type) {
|
|
372
|
+
case undefined:
|
|
373
|
+
case RegisterType.Qubit:
|
|
374
|
+
return y;
|
|
375
|
+
case RegisterType.Classical:
|
|
376
|
+
if (children == null)
|
|
377
|
+
throw new Error(
|
|
378
|
+
`ERROR: No classical registers found for qubit ID ${qId}.`,
|
|
379
|
+
);
|
|
380
|
+
if (cId == null)
|
|
381
|
+
throw new Error(
|
|
382
|
+
`ERROR: No ID defined for classical register associated with qubit ID ${qId}.`,
|
|
383
|
+
);
|
|
384
|
+
if (children.length <= cId)
|
|
385
|
+
throw new Error(
|
|
386
|
+
`ERROR: Classical register ID ${cId} invalid for qubit ID ${qId} with ${children.length} classical register(s).`,
|
|
387
|
+
);
|
|
388
|
+
return children[cId].y;
|
|
389
|
+
default:
|
|
390
|
+
throw new Error(`ERROR: Unknown register type ${type}.`);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Splits `targets` if non-adjacent or intersected by classical registers.
|
|
396
|
+
*
|
|
397
|
+
* @param targets Target qubit registers.
|
|
398
|
+
* @param classicalRegY y coords of classical registers overlapping current column.
|
|
399
|
+
* @param registers Mapping from register qubit IDs to register metadata.
|
|
400
|
+
*
|
|
401
|
+
* @returns Groups of target qubit y coords.
|
|
402
|
+
*/
|
|
403
|
+
const _splitTargetsY = (
|
|
404
|
+
targets: Register[],
|
|
405
|
+
classicalRegY: number[],
|
|
406
|
+
registers: RegisterMap,
|
|
407
|
+
): number[][] => {
|
|
408
|
+
if (targets.length === 0) return [];
|
|
409
|
+
|
|
410
|
+
// Get qIds sorted by ascending y value
|
|
411
|
+
const orderedQIds: number[] = Object.keys(registers).map(Number);
|
|
412
|
+
orderedQIds.sort((a, b) => registers[a].y - registers[b].y);
|
|
413
|
+
const qIdPosition: { [qId: number]: number } = {};
|
|
414
|
+
orderedQIds.forEach((qId, i) => (qIdPosition[qId] = i));
|
|
415
|
+
|
|
416
|
+
// Sort targets and classicalRegY by ascending y value
|
|
417
|
+
targets = targets.slice();
|
|
418
|
+
targets.sort((a, b) => {
|
|
419
|
+
const posDiff: number = qIdPosition[a.qId] - qIdPosition[b.qId];
|
|
420
|
+
if (posDiff === 0 && a.cId != null && b.cId != null) return a.cId - b.cId;
|
|
421
|
+
else return posDiff;
|
|
422
|
+
});
|
|
423
|
+
classicalRegY = classicalRegY.slice();
|
|
424
|
+
classicalRegY.sort((a, b) => a - b);
|
|
425
|
+
|
|
426
|
+
let prevPos = 0;
|
|
427
|
+
let prevY = 0;
|
|
428
|
+
|
|
429
|
+
return targets.reduce((groups: number[][], target: Register) => {
|
|
430
|
+
const y = _getRegY(target, registers);
|
|
431
|
+
const pos = qIdPosition[target.qId];
|
|
432
|
+
|
|
433
|
+
// Split into new group if one of the following holds:
|
|
434
|
+
// 1. First target register
|
|
435
|
+
// 2. Non-adjacent qubit registers
|
|
436
|
+
// 3. There is a classical register between current and previous register
|
|
437
|
+
if (
|
|
438
|
+
groups.length === 0 ||
|
|
439
|
+
pos > prevPos + 1 ||
|
|
440
|
+
(classicalRegY[0] > prevY && classicalRegY[0] < y)
|
|
441
|
+
)
|
|
442
|
+
groups.push([y]);
|
|
443
|
+
else groups[groups.length - 1].push(y);
|
|
444
|
+
|
|
445
|
+
prevPos = pos;
|
|
446
|
+
prevY = y;
|
|
447
|
+
|
|
448
|
+
// Remove classical registers that are higher than current y
|
|
449
|
+
while (classicalRegY.length > 0 && classicalRegY[0] <= y)
|
|
450
|
+
classicalRegY.shift();
|
|
451
|
+
|
|
452
|
+
return groups;
|
|
453
|
+
}, []);
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Updates the x coord of each metadata in the given 2D array of metadata and returns rightmost x coord.
|
|
458
|
+
*
|
|
459
|
+
* @param opsMetadata 2D array of metadata.
|
|
460
|
+
* @param columnWidths Array of column widths.
|
|
461
|
+
*
|
|
462
|
+
* @returns Rightmost x coord.
|
|
463
|
+
*/
|
|
464
|
+
const _fillMetadataX = (
|
|
465
|
+
opsMetadata: Metadata[][],
|
|
466
|
+
columnWidths: number[],
|
|
467
|
+
): number => {
|
|
468
|
+
let currX: number = startX;
|
|
469
|
+
|
|
470
|
+
const colStartX: number[] = columnWidths.map((width) => {
|
|
471
|
+
const x: number = currX;
|
|
472
|
+
currX += width + gatePadding * 2;
|
|
473
|
+
return x;
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
const endX: number = currX;
|
|
477
|
+
|
|
478
|
+
opsMetadata.forEach((regOps) =>
|
|
479
|
+
regOps.forEach((metadata, col) => {
|
|
480
|
+
const x = colStartX[col];
|
|
481
|
+
switch (metadata.type) {
|
|
482
|
+
case GateType.ClassicalControlled:
|
|
483
|
+
case GateType.Group:
|
|
484
|
+
{
|
|
485
|
+
// Subtract startX offset from nested gates and add offset and padding
|
|
486
|
+
let offset: number = x - startX + groupBoxPadding;
|
|
487
|
+
if (metadata.type === GateType.ClassicalControlled)
|
|
488
|
+
offset += controlBtnOffset;
|
|
489
|
+
|
|
490
|
+
// Offset each x coord in children gates
|
|
491
|
+
_offsetChildrenX(metadata.children, offset);
|
|
492
|
+
|
|
493
|
+
// We don't use the centre x coord because we only care about the rightmost x for
|
|
494
|
+
// rendering the box around the group of nested gates
|
|
495
|
+
metadata.x = x;
|
|
496
|
+
}
|
|
497
|
+
break;
|
|
498
|
+
|
|
499
|
+
default:
|
|
500
|
+
metadata.x = x + columnWidths[col] / 2;
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
}),
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
return endX;
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Offset x coords of nested children operations.
|
|
511
|
+
*
|
|
512
|
+
* @param children 2D array of children metadata.
|
|
513
|
+
* @param offset x coord offset.
|
|
514
|
+
*/
|
|
515
|
+
const _offsetChildrenX = (
|
|
516
|
+
children: (Metadata | Metadata[])[] | undefined,
|
|
517
|
+
offset: number,
|
|
518
|
+
): void => {
|
|
519
|
+
if (children == null) return;
|
|
520
|
+
children.flat().forEach((child) => {
|
|
521
|
+
child.x += offset;
|
|
522
|
+
_offsetChildrenX(child.children, offset);
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
export {
|
|
527
|
+
processOperations,
|
|
528
|
+
_groupOperations,
|
|
529
|
+
_alignOps,
|
|
530
|
+
_getClassicalRegStart,
|
|
531
|
+
_opToMetadata,
|
|
532
|
+
_getRegY,
|
|
533
|
+
_splitTargetsY,
|
|
534
|
+
_fillMetadataX,
|
|
535
|
+
_offsetChildrenX,
|
|
536
|
+
};
|