// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. // fn is_sorted>(items: Items) -> bool { // let vec_items: Vec = items.collect(); // equal(sorted(vec_items.iter()), vec_items.iter()) // } // MulAssign for PauliUnitary and PauliUnitaryAbs with rhs that implements Pauli or PauliAbs use std::ops::{Mul, MulAssign, Neg}; use crate::NeutralElement; use super::{ generic::{PhaseExponent, PhaseExponentMutable}, Pauli, PauliBinaryOps, PauliBits, PauliMutable, PauliNeutralElement, PauliUnitary, PauliUnitaryProjective, }; impl> MulAssign<&PauliRight> for PauliUnitary where PauliUnitary: PauliBinaryOps, BitsLeft: PauliBits, PhaseLeft: PhaseExponent, { fn mul_assign(&mut self, other: &PauliRight) { self.mul_assign_right(other); } } impl> MulAssign<&PauliRight> for PauliUnitaryProjective where PauliUnitaryProjective: PauliBinaryOps, BitsLeft: PauliBits, { fn mul_assign(&mut self, other: &PauliRight) { self.mul_assign_right(other); } } pub struct Phase(Exponent); impl Phase { pub fn from_exponent(exponent: Exponent) -> Self { Self(exponent) } } // Multiply an object by a reference on the right, consume the object return multiplication result impl> Mul<&PauliRight> for PauliUnitary where PauliUnitary: for<'a> MulAssign<&'a PauliRight>, BitsLeft: PauliBits, PhaseLeft: PhaseExponent, { type Output = PauliUnitary; fn mul(mut self, other: &PauliRight) -> Self::Output { self *= other; self } } impl> Mul<&PauliRight> for PauliUnitaryProjective where PauliUnitaryProjective: for<'a> MulAssign<&'a PauliRight>, BitsLeft: PauliBits, { type Output = PauliUnitaryProjective; fn mul(mut self, other: &PauliRight) -> Self::Output { self *= other; self } } // Multiply an object by a reference on the left, consume the object return multiplication result impl> Mul for &PauliUnitary where PauliRight: PauliBinaryOps>, BitsLeft: PauliBits, PhaseLeft: PhaseExponent, { type Output = PauliRight; fn mul(self, mut other: PauliRight) -> Self::Output { other.mul_assign_left(self); other } } impl> Mul for &PauliUnitaryProjective where PauliRight: PauliBinaryOps>, BitsLeft: PauliBits, { type Output = PauliRight; fn mul(self, mut other: PauliRight) -> Self::Output { other.mul_assign_left(self); other } } // Multiplying by a phase impl MulAssign> for PauliUnitary where PauliUnitary: PauliMutable + Pauli, { fn mul_assign(&mut self, phase: Phase) { self.add_assign_phase_exp(phase.0.raw_value()); } } impl Mul> for PauliUnitary where PauliUnitary: PauliMutable + Pauli, { type Output = PauliUnitary; fn mul(mut self, phase: Phase) -> Self::Output { self.add_assign_phase_exp(phase.0.raw_value()); self } } impl Mul<&PauliUnitary> for &PauliUnitary where PauliUnitary: PauliNeutralElement, as NeutralElement>::NeutralElementType: PauliBinaryOps>, BitsRight: PauliBits, PhaseRight: PhaseExponent, BitsLeft: PauliBits, PhaseLeft: PhaseExponent, { type Output = as NeutralElement>::NeutralElementType; fn mul(self, other: &PauliUnitary) -> Self::Output { let mut res = as NeutralElement>::neutral_element(self); res.assign(self); res.mul_assign_right(other); res } } impl Mul<&PauliUnitaryProjective> for &PauliUnitaryProjective where PauliUnitaryProjective: PauliNeutralElement, as NeutralElement>::NeutralElementType: PauliBinaryOps>, BitsRight: PauliBits, BitsLeft: PauliBits, { type Output = as NeutralElement>::NeutralElementType; fn mul(self, other: &PauliUnitaryProjective) -> Self::Output { let mut res = as NeutralElement>::neutral_element(self); res.assign(self); res.mul_assign_right(other); res } } // negating object consumes it and returns the negation impl Neg for PauliUnitary where PauliUnitary: PauliMutable + Pauli, { type Output = Self; fn neg(mut self) -> Self::Output { self.add_assign_phase_exp(2u8); self } } impl Neg for PauliUnitaryProjective where PauliUnitaryProjective: PauliMutable, { type Output = Self; fn neg(self) -> Self::Output { self } } // negating object consumes it and returns the negation impl Neg for &PauliUnitary where PauliUnitary: PauliMutable + Pauli, { type Output = PauliUnitary; fn neg(self) -> Self::Output { let mut res = self.clone(); res.add_assign_phase_exp(2u8); res } } impl Neg for &PauliUnitaryProjective where PauliUnitaryProjective: PauliMutable, { type Output = PauliUnitaryProjective; fn neg(self) -> Self::Output { self.clone() } }