// This code is part of Cqlib.
//
// (C) Copyright China Telecom Quantum Group 2026
//
// This code is licensed under the Apache License, Version 2.0. You may
// obtain a copy of this license in the LICENSE.txt file in the root directory
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
//
// Any modifications or derivative works of this code must retain this
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.
// Always-safe normalization rules expressible in the rule DSL.
//
// Numeric angle canonicalization and special-angle folding belong to the
// canonicalizer's standard-gate normalization policy because they require
// tolerance-aware arithmetic and, for 2π rotations, explicit global-phase
// preservation.
rule normalize_i {
match { I 0 }
rewrite {}
}
rule normalize_gphase_zero {
match { GPhase(a) }
require { a == 0 mod 2*π }
rewrite {}
}
rule normalize_phase_zero {
match { Phase(a) 0 }
require { a == 0 mod 2*π }
rewrite {}
}
rule normalize_rx_zero {
match { RX(a) 0 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_ry_zero {
match { RY(a) 0 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_rz_zero {
match { RZ(a) 0 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_rxx_zero {
match { RXX(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_ryy_zero {
match { RYY(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_rzz_zero {
match { RZZ(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_rzx_zero {
match { RZX(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_rxy_zero {
match { RXY(a, phi) 0 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_u_zero {
match { U(a, b, c) 0 }
require { a == 0 mod 4*π, b == 0 mod 2*π, c == 0 mod 2*π }
rewrite {}
}
rule normalize_fsim_zero {
match { FSIM(a, b) 0 1 }
require { a == 0 mod 2*π, b == 0 mod 2*π }
rewrite {}
}
rule normalize_crx_zero {
match { CRX(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_cry_zero {
match { CRY(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_crz_zero {
match { CRZ(a) 0 1 }
require { a == 0 mod 4*π }
rewrite {}
}
rule normalize_mcphase1_zero {
match { MCPhase[1](a) 0 1 }
require { a == 0 mod 2*π }
rewrite {}
}
rule normalize_mcphase2_zero {
match { MCPhase[2](a) 0 1 2 }
require { a == 0 mod 2*π }
rewrite {}
}
rule normalize_rx_2pi {
match { RX(a) 0 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_ry_2pi {
match { RY(a) 0 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_rz_2pi {
match { RZ(a) 0 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_rxx_2pi {
match { RXX(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_ryy_2pi {
match { RYY(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_rzz_2pi {
match { RZZ(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_rzx_2pi {
match { RZX(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}
rule normalize_crx_2pi {
match { CRX(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { Phase(π) 0 }
}
rule normalize_cry_2pi {
match { CRY(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { Phase(π) 0 }
}
rule normalize_crz_2pi {
match { CRZ(a) 0 1 }
require { a == 2*π mod 4*π }
rewrite { Phase(π) 0 }
}
// A full RXY turn is minus identity, independently of its axis.
rule normalize_rxy_2pi {
match { RXY(a, phi) 0 }
require { a == 2*π mod 4*π }
rewrite { GPhase(π) }
}