microsoft / QuantumLibraries

Q# libraries for the Quantum Development Kit
https://docs.microsoft.com/quantum
MIT License
543 stars 179 forks source link

A Wrong Check for the argument in `IdenticalPointPosFactFxP` #645

Closed weucode closed 1 year ago

weucode commented 2 years ago

Describe the bug Function IdenticalPointPosFactFxP tries to ensure the items in FixedPoint[] have the same decimal places. The corresponding lines start at https://github.com/microsoft/QuantumLibraries/blob/025a8126023602cd3c57c2d0e07d1c682954c557/Numerics/src/FixedPoint/Facts.qs#L59

However, the Most will get the array except the last item; it will go wrong when the length of FixedPoint[] is 2, that is, only check the first element to the first element. eg. AddFxP called IdenticalPointPosFactFxP with such a value, the source code is in https://github.com/microsoft/QuantumLibraries/blob/025a8126023602cd3c57c2d0e07d1c682954c557/Numerics/src/FixedPoint/Addition.qs#L41

Rest is proper to replace Most, and it is suggested to check another function IdenticalFormatFactFxP in the same source file. Hoping my found are helpful to you guys.

To Reproduce The following program will not get an unhandled exception.

namespace NameSpace {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Arithmetic;

    @EntryPoint()
    operation main() : Unit {
        use q1 = Qubit[3];
        mutable a = FixedPoint(2, q1);
        use q2 = Qubit[3];
        mutable b = FixedPoint(4, q2);
                let fixedPoints = [a, b];
        IdenticalPointPosFactFxP(fixedPoints);
    }
}

But if replace Most to Rest, it will detect and interrupt.

namespace NameSpace {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Arithmetic;
    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Diagnostics;

    function IdenticalPointPosFactFxP1(fixedPoints : FixedPoint[]) : Unit {
        if IsEmpty(fixedPoints) {
            return ();
        }
        let (position, register) = fixedPoints[0]!;
        Fact(position > 0, "Point position must be greater than zero.");
        let n = Length(register);
        for fp in Rest(fixedPoints) {
            EqualityFactI(Length(fp::Register) - fp::IntegerBits, n - position,
                "FixedPoint numbers must have identical point alignment.");
        }
    }

    @EntryPoint()
    operation main() : Unit {
        use q1 = Qubit[3];
        mutable a = FixedPoint(2, q1);
        use q2 = Qubit[3];
        mutable b = FixedPoint(4, q2);
                let fixedPoints = [a, b];
        IdenticalPointPosFactFxP1(fixedPoints);
    }
}

System information

operating system : Ubuntu 22.04 LTS dotnet version : 6.0.301 QDK : 0.27.238334

weucode commented 1 year ago

Fixed in #654.