Skip to content

Commit 7468d44

Browse files
feat: norm_num support for Int.fract (#26428)
1 parent 5b59b3a commit 7468d44

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

Mathlib/Data/Rat/Floor.lean

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ open Int
2828
namespace Rat
2929

3030
variable {α : Type*} [Field α] [LinearOrder α] [IsStrictOrderedRing α] [FloorRing α]
31+
variable {R : Type*} [Ring R] [LinearOrder R] [IsStrictOrderedRing R] [FloorRing R]
3132

3233
@[deprecated Rat.le_floor_iff (since := "2025-09-02")]
3334
protected theorem le_floor {z : ℤ} : ∀ {r : ℚ}, z ≤ Rat.floor r ↔ (z : ℚ) ≤ r
@@ -228,6 +229,60 @@ def evalIntCeil : NormNumExt where eval {u αZ} e := do
228229
return .isNegNat q(inferInstance) z q(isInt_intCeil_ofIsRat_neg $x $n $d $h)
229230
| _, _, _ => failure
230231

232+
theorem isNat_intFract_of_isNat (r : R) (m : ℕ) : IsNat r m → IsNat (Int.fract r) 0 := by
233+
rintro ⟨⟨⟩⟩; exact ⟨by simp⟩
234+
235+
theorem isNat_intFract_of_isInt (r : R) (m : ℤ) : IsInt r m → IsNat (Int.fract r) 0 := by
236+
rintro ⟨⟨⟩⟩; exact ⟨by simp⟩
237+
238+
theorem isNNRat_intFract_of_isNNRat (r : α) (n d : ℕ) :
239+
IsNNRat r n d → IsNNRat (Int.fract r) (n % d) d := by
240+
rintro ⟨inv, rfl⟩
241+
refine ⟨inv, ?_⟩
242+
simp only [invOf_eq_inv, ← div_eq_mul_inv, fract_div_natCast_eq_div_natCast_mod]
243+
244+
theorem isRat_intFract_of_isRat_negOfNat (r : α) (n d : ℕ) :
245+
IsRat r (negOfNat n) d → IsRat (Int.fract r) (-n % d) d := by
246+
rintro ⟨inv, rfl⟩
247+
refine ⟨inv, ?_⟩
248+
simp only [invOf_eq_inv, ← div_eq_mul_inv, fract_div_intCast_eq_div_intCast_mod,
249+
negOfNat_eq, ofNat_eq_coe]
250+
251+
/-- `norm_num` extension for `Int.fract` -/
252+
@[norm_num (Int.fract _)]
253+
def evalIntFract : NormNumExt where eval {u α} e := do
254+
match e with
255+
| ~q(@Int.fract _ $instR $instO $instF $x) =>
256+
match ← derive x with
257+
| .isBool .. => failure
258+
| .isNat _ _ pb => do
259+
let _i ← synthInstanceQ q(IsStrictOrderedRing $α)
260+
assertInstancesCommute
261+
have z : Q(ℕ) := Lean.mkRawNatLit 0
262+
letI : $z =Q 0 := ⟨⟩
263+
return .isNat _ z q(isNat_intFract_of_isNat $x _ $pb)
264+
| .isNegNat _ _ pb => do
265+
let _i ← synthInstanceQ q(IsStrictOrderedRing $α)
266+
assertInstancesCommute
267+
have z : Q(ℕ) := Lean.mkRawNatLit 0
268+
letI : $z =Q 0 := ⟨⟩
269+
return .isNat _ z q(isNat_intFract_of_isInt _ _ $pb)
270+
| .isNNRat _ q n d h => do
271+
let _i ← synthInstanceQ q(Field $α)
272+
let _i ← synthInstanceQ q(IsStrictOrderedRing $α)
273+
assertInstancesCommute
274+
have n' : Q(ℕ) := Lean.mkRawNatLit (q.num.natAbs % q.den)
275+
letI : $n' =Q $n % $d := ⟨⟩
276+
return .isNNRat _ (Int.fract q) n' d q(isNNRat_intFract_of_isNNRat _ $n $d $h)
277+
| .isNegNNRat _ q n d h => do
278+
let _i ← synthInstanceQ q(Field $α)
279+
let _i ← synthInstanceQ q(IsStrictOrderedRing $α)
280+
assertInstancesCommute
281+
have n' : Q(ℤ) := mkRawIntLit (q.num % q.den)
282+
letI : $n' =Q -$n % $d := ⟨⟩
283+
return .isRat _ (Int.fract q) n' d q(isRat_intFract_of_isRat_negOfNat _ $n $d $h)
284+
| _, _, _ => failure
285+
231286
end NormNum
232287

233288
end Rat

MathlibTest/norm_num_ext.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,11 @@ example : ⌈(2 : R)⌉ = 2 := by norm_num
435435
example : ⌈(15 / 16 : K)⌉ + 1 = 2 := by norm_num
436436
example : ⌈(-15 / 16 : K)⌉ + 1 = 1 := by norm_num
437437

438+
example : Int.fract (2 : R) = 0 := by norm_num
439+
example : Int.fract (16 / 15 : K) = 1 / 15 := by norm_num
440+
example : Int.fract (3.7 : ℚ) = 0.7 := by norm_num
441+
example : Int.fract (-3.7 : ℚ) = 0.3 := by norm_num
442+
438443
end floor
439444

440445
section jacobi

0 commit comments

Comments
 (0)