From 85eef3f110bcb440632093642052512def4e7644 Mon Sep 17 00:00:00 2001 From: Scott Carda <55811729+ScottCarda-MS@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:59:07 -0800 Subject: [PATCH] Remove Refs to Microsoft.Quantum in Libraries (#2041) This removes the references to `Microsoft.Quantum` namespaces in the Q# libraries and replaces them with references to `Std` namespaces. This also changes many "See Also" references to links and adds logic to the VS Code extension that supports those links. --- compiler/qsc_doc_gen/src/generate_docs.rs | 3 +-- .../qsc_doc_gen/src/generate_docs/tests.rs | 6 ++--- compiler/qsc_partial_eval/src/tests/misc.rs | 2 +- library/std/README.md | 4 +-- library/std/src/Std/Arrays.qs | 24 ++++++++--------- library/std/src/Std/Canon.qs | 6 ++--- library/std/src/Std/Intrinsic.qs | 4 +-- library/std/src/Std/Math.qs | 26 +++++++++---------- library/std/src/Std/Measurement.qs | 8 +++--- vscode/src/webview/docview.tsx | 18 ++++++++++++- 10 files changed, 57 insertions(+), 44 deletions(-) diff --git a/compiler/qsc_doc_gen/src/generate_docs.rs b/compiler/qsc_doc_gen/src/generate_docs.rs index ccd9f14c20..f3d7ce450f 100644 --- a/compiler/qsc_doc_gen/src/generate_docs.rs +++ b/compiler/qsc_doc_gen/src/generate_docs.rs @@ -463,10 +463,9 @@ fn generate_exported_file_content( // Note: we are assuming the package kind does not change let true_metadata = get_metadata(package_kind, true_ns.clone(), true_item, display)?; let true_fqn = true_metadata.fully_qualified_name(); - let name = true_metadata.name; let summary = format!( - "This is an exported item. The actual definition is found here: [{name}](xref:Qdk.{true_fqn})" + "This is an exported item. The actual definition is found here: [{true_fqn}](xref:Qdk.{true_fqn})" ); metadata.summary = summary.clone(); diff --git a/compiler/qsc_doc_gen/src/generate_docs/tests.rs b/compiler/qsc_doc_gen/src/generate_docs/tests.rs index 94fa1daa14..e471b3ce12 100644 --- a/compiler/qsc_doc_gen/src/generate_docs/tests.rs +++ b/compiler/qsc_doc_gen/src/generate_docs/tests.rs @@ -118,21 +118,21 @@ fn redirect_generation() { --- uid: Qdk.Microsoft.Quantum.Core.Length title: Length exported item - description: "Q# Length exported item: This is an exported item. The actual definition is found here: [Length](xref:Qdk.Std.Core.Length)" + description: "Q# Length exported item: This is an exported item. The actual definition is found here: [Std.Core.Length](xref:Qdk.Std.Core.Length)" ms.date: {TIMESTAMP} ms.topic: managed-reference qsharp.kind: export qsharp.package: __Std__ qsharp.namespace: Microsoft.Quantum.Core qsharp.name: Length - qsharp.summary: "This is an exported item. The actual definition is found here: [Length](xref:Qdk.Std.Core.Length)" + qsharp.summary: "This is an exported item. The actual definition is found here: [Std.Core.Length](xref:Qdk.Std.Core.Length)" --- # Length exported item Fully qualified name: Microsoft.Quantum.Core.Length - This is an exported item. The actual definition is found here: [Length](xref:Qdk.Std.Core.Length) + This is an exported item. The actual definition is found here: [Std.Core.Length](xref:Qdk.Std.Core.Length) "#]] .assert_eq(full_contents.as_str()); } diff --git a/compiler/qsc_partial_eval/src/tests/misc.rs b/compiler/qsc_partial_eval/src/tests/misc.rs index 49dd390953..30f9094766 100644 --- a/compiler/qsc_partial_eval/src/tests/misc.rs +++ b/compiler/qsc_partial_eval/src/tests/misc.rs @@ -602,5 +602,5 @@ fn evaluation_error_within_stdlib_yield_correct_package_span() { } "#, }); - assert_error(&error, &expect!["UnexpectedDynamicValue(PackageSpan { package: PackageId(1), span: Span { lo: 13850, hi: 13865 } })"]); + assert_error(&error, &expect!["UnexpectedDynamicValue(PackageSpan { package: PackageId(1), span: Span { lo: 13910, hi: 13925 } })"]); } diff --git a/library/std/README.md b/library/std/README.md index 23dce7d6ed..d693899a47 100644 --- a/library/std/README.md +++ b/library/std/README.md @@ -12,11 +12,9 @@ Files in the library match the contained namespace. This makes it easier to find Unless otherwise noted, callables that are defined as `body intrinsic` are generated into external declarations in QIR with exact callable name and signature matches. The containing namespace is not included in the generated name. This simplifies QIR code generation and makes correlating Q# declaration to the resulting QIR program easier. Body intrinsic callables should avoid using generics and aggregate types if possible to keep the corresponding LLVM signatures simple and increase the likelihood of hardware compatibility. -One notable exception to this is the `Microsoft.Quantum.Core.Length` function, which is both `body intrinsic` and generic across the array type. As a result, it needs special handling during monomorphization and code generation to correlate it to the right pattern for extracting length from the array structure. Open question: should this be transitioned to an operator or some other form that avoid such a prominent counterexample? - ### QIR Quantum Gate Instructions -The library includes a set of one- and two-qubit gates represented as `__quantum__qis__*__body` or `__quantum__qis__*__adj` QIR declarations. The expectation is that these gates form a common QIR API surface that Q# is compiled into. Any target would either need to support these quantum gate instructions natively or provide a QIR definition of that gate instruction in terms of supported native gates. These definitions can then be linked with the QIR program via LLVM tools and resolve to the target specific gate set. This approach provides broader compatibility at the QIR level and avoids the need for front end language targetting; as a result, this Q# library design is not expected to require any target packages or operation substitution. +The library includes a set of one- and two-qubit gates represented as `__quantum__qis__*__body` or `__quantum__qis__*__adj` QIR declarations. The expectation is that these gates form a common QIR API surface that Q# is compiled into. Any target would either need to support these quantum gate instructions natively or provide a QIR definition of that gate instruction in terms of supported native gates. These definitions can then be linked with the QIR program via LLVM tools and resolve to the target specific gate set. This approach provides broader compatibility at the QIR level and avoids the need for front end language targeting; as a result, this Q# library design is not expected to require any target packages or operation substitution. To avoid using any opaque array types in the quantum gate instruction set, the library utilizes decomposition strategies to express the Q# controlled specialization (which allows an arbitrary number of controls) in terms of singly- and doubly-controlled gates. While this makes simulation somewhat more expensive in terms of allocating extra controls and performing more operations, it more closely matches the patterns used by hardware and provides better API surface for QIR programs to have hardware compatibility. diff --git a/library/std/src/Std/Arrays.qs b/library/std/src/Std/Arrays.qs index ff577e0ff3..b335926d36 100644 --- a/library/std/src/Std/Arrays.qs +++ b/library/std/src/Std/Arrays.qs @@ -171,8 +171,8 @@ function CircularlyShifted<'T>(stepCount : Int, array : 'T[]) : 'T[] { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Transposed -/// - Microsoft.Quantum.Arrays.Diagonal +/// - [Std.Arrays.Transposed](xref:Qdk.Std.Arrays.Transposed) +/// - [Std.Arrays.Diagonal](xref:Qdk.Std.Arrays.Diagonal) function ColumnAt<'T>(column : Int, matrix : 'T[][]) : 'T[] { Fact(IsRectangularArray(matrix), "`matrix` is not a rectangular array"); mutable columnValues = []; @@ -238,7 +238,7 @@ function Count<'T>(predicate : ('T -> Bool), array : 'T[]) : Int { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Transposed +/// - [Std.Arrays.Transposed](xref:Qdk.Std.Arrays.Transposed) function Diagonal<'T>(matrix : 'T[][]) : 'T[] { Fact(IsRectangularArray(matrix), "`matrix` is not a rectangular array"); let rows = Length(matrix); @@ -274,7 +274,7 @@ function Diagonal<'T>(matrix : 'T[][]) : 'T[] { /// The following samples an alternating array of results. /// ```qsharp /// use qubit = Qubit(); -/// let results = Microsoft.Quantum.Arrays.DrawMany(q => {X(q); M(q)}, 3, qubit); +/// let results = Std.Arrays.DrawMany(q => {X(q); M(q)}, 3, qubit); /// ``` operation DrawMany<'TInput, 'TOutput>(op : ('TInput => 'TOutput), nSamples : Int, input : 'TInput) : 'TOutput[] { mutable outputs = []; @@ -505,7 +505,7 @@ function Fold<'State, 'T>(folder : (('State, 'T) -> 'State), state : 'State, arr /// An array `'U[]` of elements that are mapped by the `action` operation. /// /// # See Also -/// - Microsoft.Quantum.Arrays.Mapped +/// - [Std.Arrays.Mapped](xref:Qdk.Std.Arrays.Mapped) operation ForEach<'T, 'U>(action : ('T => 'U), array : 'T[]) : 'U[] { mutable output = []; for element in array { @@ -686,7 +686,7 @@ function IsEmpty<'T>(array : 'T[]) : Bool { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.IsSquareArray +/// - [Std.Arrays.IsSquareArray](xref:Qdk.Std.Arrays.IsSquareArray) function IsRectangularArray<'T>(array : 'T[][]) : Bool { if (Length(array) > 0) { let columnCount = Length(Head(array)); @@ -754,7 +754,7 @@ function IsSorted<'T>(comparison : (('T, 'T) -> Bool), array : 'T[]) : Bool { /// `true` if the array is square, `false` otherwise. /// /// # See Also -/// - Microsoft.Quantum.Arrays.IsRectangularArray +/// - [Std.Arrays.IsRectangularArray](xref:Qdk.Std.Arrays.IsRectangularArray) function IsSquareArray<'T>(array : 'T[][]) : Bool { if (Length(array) > 0) { let columnCount = Length(array); @@ -789,7 +789,7 @@ function IsSquareArray<'T>(array : 'T[][]) : Bool { /// An array `'U[]` of elements that are mapped by the `mapper` function. /// /// # See Also -/// - Microsoft.Quantum.Arrays.ForEach +/// - [Std.Arrays.ForEach](xref:Qdk.Std.Arrays.ForEach) function Mapped<'T, 'U>(mapper : ('T -> 'U), array : 'T[]) : 'U[] { mutable mapped = []; for element in array { @@ -830,7 +830,7 @@ function Mapped<'T, 'U>(mapper : ('T -> 'U), array : 'T[]) : 'U[] { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Mapped +/// - [Std.Arrays.Mapped](xref:Qdk.Std.Arrays.Mapped) function MappedByIndex<'T, 'U>(mapper : ((Int, 'T) -> 'U), array : 'T[]) : 'U[] { mutable mapped = []; for index in 0..Length(array) - 1 { @@ -865,7 +865,7 @@ function MappedByIndex<'T, 'U>(mapper : ((Int, 'T) -> 'U), array : 'T[]) : 'U[] /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Mapped +/// - [Std.Arrays.Mapped](xref:Qdk.Std.Arrays.Mapped) function MappedOverRange<'T>(mapper : (Int -> 'T), range : Range) : 'T[] { mutable output = []; for element in range { @@ -1320,7 +1320,7 @@ function Tail<'A>(array : 'A[]) : 'A { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Zipped +/// - [Std.Arrays.Zipped](xref:Qdk.Std.Arrays.Zipped) function Unzipped<'T, 'U>(array : ('T, 'U)[]) : ('T[], 'U[]) { mutable first = []; mutable second = []; @@ -1429,7 +1429,7 @@ function Windows<'T>(size : Int, array : 'T[]) : 'T[][] { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Arrays.Unzipped +/// - [Std.Arrays.Unzipped](xref:Qdk.Std.Arrays.Unzipped) function Zipped<'T, 'U>(left : 'T[], right : 'U[]) : ('T, 'U)[] { let arrayLength = MinI(Length(left), Length(right)); mutable zipped = []; diff --git a/library/std/src/Std/Canon.qs b/library/std/src/Std/Canon.qs index 94ae4e4e72..98751cc66a 100644 --- a/library/std/src/Std/Canon.qs +++ b/library/std/src/Std/Canon.qs @@ -54,7 +54,7 @@ operation ApplyToEach<'T>(singleElementOperation : ('T => Unit), register : 'T[] /// ``` /// /// # See Also -/// - Microsoft.Quantum.Canon.ApplyToEach +/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach) operation ApplyToEachA<'T>(singleElementOperation : ('T => Unit is Adj), register : 'T[]) : Unit is Adj { for item in register { singleElementOperation(item); @@ -83,7 +83,7 @@ operation ApplyToEachA<'T>(singleElementOperation : ('T => Unit is Adj), registe /// ``` /// /// # See Also -/// - Microsoft.Quantum.Canon.ApplyToEach +/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach) operation ApplyToEachC<'T>(singleElementOperation : ('T => Unit is Ctl), register : 'T[]) : Unit is Ctl { for item in register { singleElementOperation(item); @@ -112,7 +112,7 @@ operation ApplyToEachC<'T>(singleElementOperation : ('T => Unit is Ctl), registe /// ``` /// /// # See Also -/// - Microsoft.Quantum.Canon.ApplyToEach +/// - [Std.Canon.ApplyToEach](xref:Qdk.Std.Canon.ApplyToEach) operation ApplyToEachCA<'T>(singleElementOperation : ('T => Unit is Adj + Ctl), register : 'T[]) : Unit is Adj + Ctl { for item in register { singleElementOperation(item); diff --git a/library/std/src/Std/Intrinsic.qs b/library/std/src/Std/Intrinsic.qs index 1cc3e1f1d6..f6d6fa332d 100644 --- a/library/std/src/Std/Intrinsic.qs +++ b/library/std/src/Std/Intrinsic.qs @@ -463,7 +463,7 @@ operation R1(theta : Double, qubit : Qubit) : Unit is Adj + Ctl { /// /// WARNING: /// This operation uses the **opposite** sign convention from -/// Microsoft.Quantum.Intrinsic.R. +/// Std.Intrinsic.R. /// /// # Input /// ## numerator @@ -523,7 +523,7 @@ operation ResetAll(qubits : Qubit[]) : Unit { /// /// WARNING: /// This operation uses the **opposite** sign convention from -/// Microsoft.Quantum.Intrinsic.R. +/// Std.Intrinsic.R. /// /// # Input /// ## pauli diff --git a/library/std/src/Std/Math.qs b/library/std/src/Std/Math.qs index 281fcfef4a..e3dc39138f 100644 --- a/library/std/src/Std/Math.qs +++ b/library/std/src/Std/Math.qs @@ -22,7 +22,7 @@ import Std.Diagnostics.*; /// [Wikipedia article - Pi](https://en.wikipedia.org/wiki/Pi) /// /// # See Also -/// - Microsoft.Quantum.Math.E +/// - [Std.Math.E](xref:Qdk.Std.Math.E) function PI() : Double { 3.14159265358979323846 } @@ -39,7 +39,7 @@ function PI() : Double { /// [Wikipedia article - e](https://en.wikipedia.org/wiki/E_(mathematical_constant)) /// /// # See Also -/// - Microsoft.Quantum.Math.PI +/// - [Std.Math.PI](xref:Qdk.Std.Math.PI) function E() : Double { 2.7182818284590452354 } @@ -103,7 +103,7 @@ function IsNaN(d : Double) : Bool { /// ``` /// /// # See Also -/// - Microsoft.Quantum.Math.IsNaN +/// - [Std.Math.IsNaN](xref:Qdk.Std.Math.IsNaN) function IsInfinite(d : Double) : Bool { return d == 1.0 / 0.0 or d == -1.0 / 0.0; } @@ -820,11 +820,11 @@ function HammingWeightI(n : Int) : Int { /// The factorial of `n`. /// /// # Remarks -/// For inputs greater than 20, please use `Microsoft.Quantum.Math.FactorialL`. +/// For inputs greater than 20, please use `Std.Math.FactorialL`. /// /// # See Also -/// - Microsoft.Quantum.Math.FactorialL -/// - Microsoft.Quantum.Math.ApproximateFactorial +/// - [Std.Math.FactorialL](xref:Qdk.Std.Math.FactorialL) +/// - [Std.Math.ApproximateFactorial](xref:Qdk.Std.Math.ApproximateFactorial) function FactorialI(n : Int) : Int { Fact(n >= 0, "The factorial is not defined for negative inputs."); Fact(n <= 20, "The largest factorial that can be stored as an Int is 20!. Use FactorialL or ApproximateFactorial."); @@ -865,8 +865,8 @@ function FactorialI(n : Int) : Int { /// The factorial of `n`. /// /// # See Also -/// - Microsoft.Quantum.Math.FactorialI -/// - Microsoft.Quantum.Math.ApproximateFactorial +/// - [Std.Math.FactorialI](xref:Qdk.Std.Math.FactorialI) +/// - [Std.Math.ApproximateFactorial](xref:Qdk.Std.Math.ApproximateFactorial) function FactorialL(n : Int) : BigInt { Fact(n >= 0, "The factorial is not defined for negative inputs."); @@ -896,8 +896,8 @@ function FactorialL(n : Int) : BigInt { /// The approximate factorial of `n`. /// /// # See Also -/// - Microsoft.Quantum.Math.FactorialI -/// - Microsoft.Quantum.Math.FactorialL +/// - [Std.Math.FactorialI](xref:Qdk.Std.Math.FactorialI) +/// - [Std.Math.FactorialL](xref:Qdk.Std.Math.FactorialL) function ApproximateFactorial(n : Int) : Double { Fact(n >= 0, "The factorial is not defined for negative inputs."); Fact(n <= 169, "The largest approximate factorial that can be stored as a Double is 169!. Use FactorialL."); @@ -979,9 +979,9 @@ function LogGammaD(x : Double) : Double { /// The natural logarithm of the factorial of the provided input. /// /// # See Also -/// - Microsoft.Quantum.Math.ApproximateFactorial -/// - Microsoft.Quantum.Math.FactorialI -/// - Microsoft.Quantum.Math.FactorialL +/// - [Std.Math.ApproximateFactorial](xref:Qdk.Std.Math.ApproximateFactorial) +/// - [Std.Math.FactorialI](xref:Qdk.Std.Math.FactorialI) +/// - [Std.Math.FactorialL](xref:Qdk.Std.Math.FactorialL) function LogFactorialD(n : Int) : Double { LogGammaD(IntAsDouble(n) + 1.0) } diff --git a/library/std/src/Std/Measurement.qs b/library/std/src/Std/Measurement.qs index 8639b947c4..81bc287eaa 100644 --- a/library/std/src/Std/Measurement.qs +++ b/library/std/src/Std/Measurement.qs @@ -24,7 +24,7 @@ open QIR.Intrinsic; /// The result of measuring in the `Z ⊗ Z ⊗ ••• ⊗ Z` basis. /// /// # See also -/// - Microsoft.Quantum.Measurement.MeasureEachZ +/// - [Std.Measurement.MeasureEachZ](xref:Qdk.Std.Measurement.MeasureEachZ) operation MeasureAllZ(register : Qubit[]) : Result { Measure(Repeated(PauliZ, Length(register)), register) } @@ -54,8 +54,8 @@ operation MeasureAllZ(register : Qubit[]) : Result { /// and returns one result. The operation does not reset the qubits. /// /// # See also -/// - Microsoft.Quantum.Measurement.MeasureAllZ -/// - Microsoft.Quantum.Measurement.MResetEachZ +/// - [Std.Measurement.MeasureAllZ](xref:Qdk.Std.Measurement.MeasureAllZ) +/// - [Std.Measurement.MResetEachZ](xref:Qdk.Std.Measurement.MResetEachZ) operation MeasureEachZ(register : Qubit[]) : Result[] { mutable results = []; for qubit in register { @@ -76,7 +76,7 @@ operation MeasureEachZ(register : Qubit[]) : Result[] { /// An array of measurement results. /// /// # See also -/// - Microsoft.Quantum.Measurement.MeasureEachZ +/// - [Std.Measurement.MeasureEachZ](xref:Qdk.Std.Measurement.MeasureEachZ) operation MResetEachZ(register : Qubit[]) : Result[] { mutable results = []; for qubit in register { diff --git a/vscode/src/webview/docview.tsx b/vscode/src/webview/docview.tsx index 1d6b8ec8c5..efe758a700 100644 --- a/vscode/src/webview/docview.tsx +++ b/vscode/src/webview/docview.tsx @@ -168,6 +168,22 @@ function DocsPage(props: { fragmentsToRender: ItemDocs[] }) { const [searchText, setSearchText] = useState(""); useEffect(() => { + // Update the xref links to navigate to the correct member + document.querySelectorAll('a[href^="xref:"]').forEach((a) => { + const anchor = a as HTMLAnchorElement; + const xref = "xref:"; + let link = anchor.href.slice(xref.length); + link = link.replaceAll(".", "/"); + // Just for Qdk links, we want to strip out the leading "Qdk." + if (link.startsWith("Qdk/")) { + link = link.slice(4); + } + a.addEventListener("click", (e) => { + e.preventDefault(); + setPath(link); + }); + }); + // If the member is navigated to, scroll to it after rendering const member = currPath.split("/")[2]; scrollToElement(member); @@ -184,7 +200,7 @@ function DocsPage(props: { fragmentsToRender: ItemDocs[] }) { ? [] : getSearchResults(searchText, props.fragmentsToRender); - // Used to bold the text links when overing + // Used to bold the text links when hovering function overLi(e: MouseEvent) { (e.target as HTMLElement).style.fontWeight = "600"; (e.target as HTMLElement).style.textDecoration = "underline";