@@ -443,6 +443,82 @@ def evalAscFactorial : PositivityExt where eval {u α} _ _ e := do
443443 pure (.positive q(Nat.ascFactorial_pos $n $k))
444444 | _, _, _ => throwError "failed to match Nat.ascFactorial"
445445
446+ /-- Extension for `Nat.gcd`.
447+ Uses positivity of the left term, if available, then tries the right term.
448+
449+ The implementation relies on the fact that `Positivity.core` on `ℕ` never returns `nonzero`. -/
450+ @[positivity Nat.gcd _ _]
451+ def evalNatGCD : PositivityExt where eval {u α} z p e := do
452+ match u, α, e with
453+ | 0 , ~q(ℕ), ~q(Nat.gcd $a $b) =>
454+ assertInstancesCommute
455+ match ← core z p a with
456+ | .positive pa => return .positive q(Nat.gcd_pos_of_pos_left $b $pa)
457+ | _ =>
458+ match ← core z p b with
459+ | .positive pb => return .positive q(Nat.gcd_pos_of_pos_right $a $pb)
460+ | _ => failure
461+ | _, _, _ => throwError "not Nat.gcd"
462+
463+ /-- Extension for `Nat.lcm`. -/
464+ @[positivity Nat.lcm _ _]
465+ def evalNatLCM : PositivityExt where eval {u α} z p e := do
466+ match u, α, e with
467+ | 0 , ~q(ℕ), ~q(Nat.lcm $a $b) =>
468+ assertInstancesCommute
469+ match ← core z p a with
470+ | .positive pa =>
471+ match ← core z p b with
472+ | .positive pb =>
473+ return .positive q(Nat.lcm_pos $pa $pb)
474+ | _ => failure
475+ | _ => failure
476+ | _, _, _ => throwError "not Nat.lcm"
477+
478+ /-- Extension for `Nat.sqrt`. -/
479+ @[positivity Nat.sqrt _]
480+ def evalNatSqrt : PositivityExt where eval {u α} z p e := do
481+ match u, α, e with
482+ | 0 , ~q(ℕ), ~q(Nat.sqrt $n) =>
483+ assumeInstancesCommute
484+ match ← core z p n with
485+ | .positive pa => return .positive q(Nat.sqrt_pos.mpr $pa)
486+ | _ => failure
487+ | _, _, _ => throwError "not Nat.sqrt"
488+
489+ /-- Extension for `Int.gcd`.
490+ Uses positivity of the left term, if available, then tries the right term. -/
491+ @[positivity Int.gcd _ _]
492+ def evalIntGCD : PositivityExt where eval {u α} _ _ e := do
493+ match u, α, e with
494+ | 0 , ~q(ℕ), ~q(Int.gcd $a $b) =>
495+ let z ← synthInstanceQ (q(Zero ℤ) : Q(Type ))
496+ let p ← synthInstanceQ (q(PartialOrder ℤ) : Q(Type ))
497+ assertInstancesCommute
498+ match (← catchNone (core z p a)).toNonzero with
499+ | some na => return .positive q(Int.gcd_pos_of_ne_zero_left $b $na)
500+ | none =>
501+ match (← core z p b).toNonzero with
502+ | some nb => return .positive q(Int.gcd_pos_of_ne_zero_right $a $nb)
503+ | none => failure
504+ | _, _, _ => throwError "not Int.gcd"
505+
506+ /-- Extension for `Int.lcm`. -/
507+ @[positivity Int.lcm _ _]
508+ def evalIntLCM : PositivityExt where eval {u α} _ _ e := do
509+ match u, α, e with
510+ | 0 , ~q(ℕ), ~q(Int.lcm $a $b) =>
511+ let z ← synthInstanceQ (q(Zero ℤ) : Q(Type ))
512+ let p ← synthInstanceQ (q(PartialOrder ℤ) : Q(Type ))
513+ assertInstancesCommute
514+ match (← core z p a).toNonzero with
515+ | some na =>
516+ match (← core z p b).toNonzero with
517+ | some nb => return .positive q(Int.lcm_pos $na $nb)
518+ | _ => failure
519+ | _ => failure
520+ | _, _, _ => throwError "not Int.lcm"
521+
446522section NNRat
447523open NNRat
448524
0 commit comments