diff -r d7c525fd68b2 -r 1cf4f1e930af src/HOL/Library/Discrete_Functions.thy --- a/src/HOL/Library/Discrete_Functions.thy Sun Nov 02 19:47:30 2025 +0100 +++ b/src/HOL/Library/Discrete_Functions.thy Sun Nov 02 19:47:30 2025 +0100 @@ -197,15 +197,6 @@ by (intro antisym Max.boundedI Max.coboundedI) simp_all qed - -lemma floor_sqrt_code[code]: "floor_sqrt n = Max (Set.filter (\m. m\<^sup>2 \ n) {0..n})" -proof - - from power2_nat_le_imp_le [of _ n] - have "{m. m \ n \ m\<^sup>2 \ n} = {m. m\<^sup>2 \ n}" by auto - then show ?thesis - by (simp add: floor_sqrt_def) -qed - lemma floor_sqrt_inverse_power2 [simp]: "floor_sqrt (n\<^sup>2) = n" proof - have "{m. m \ n} \ {}" by auto @@ -220,6 +211,10 @@ lemma floor_sqrt_one [simp]: "floor_sqrt 1 = 1" using floor_sqrt_inverse_power2 [of 1] by simp +lemma floor_sqrt_Suc_0 [simp]: + \floor_sqrt (Suc 0) = 1\ + using floor_sqrt_inverse_power2 [of 1] by simp + lemma mono_floor_sqrt: "mono floor_sqrt" proof fix m n :: nat @@ -311,13 +306,34 @@ lemma le_floor_sqrtI: "x^2 \ y \ x \ floor_sqrt y" by (simp add: le_floor_sqrt_iff) -lemma floor_sqrt_le_iff: "floor_sqrt y \ x \ (\z. z^2 \ y \ z \ x)" - using Max.bounded_iff[OF floor_sqrt_aux] by (simp add: floor_sqrt_def) +lemma floor_sqrt_le_iff: + \floor_sqrt y \ x \ (\z. z\<^sup>2 \ y \ z \ x)\ + using Max.bounded_iff [OF floor_sqrt_aux] + by (simp add: floor_sqrt_def) lemma floor_sqrt_leI: "(\z. z^2 \ y \ z \ x) \ floor_sqrt y \ x" by (simp add: floor_sqrt_le_iff) +lemma floor_sqrt_less_eq_half: + \floor_sqrt n \ Suc n div 2\ +proof (rule floor_sqrt_leI) + fix m + assume \m\<^sup>2 \ n\ + have \m < Suc (Suc n div 2)\ + proof (rule ccontr, unfold not_less) + assume \Suc (Suc n div 2) \ m\ + then have \(Suc (Suc n div 2))\<^sup>2 \ m\<^sup>2\ + by simp + then have \(Suc (Suc n div 2))\<^sup>2 \ n\ + using \m\<^sup>2 \ n\ by (rule order_trans) + then show False + by (simp only: Suc_eq_plus1 power2_sum algebra_simps) auto + qed + then show \m \ Suc n div 2\ + by simp +qed + lemma floor_sqrt_Suc: "floor_sqrt (Suc n) = (if \m. Suc n = m^2 then Suc (floor_sqrt n) else floor_sqrt n)" proof cases @@ -343,4 +359,71 @@ ultimately show ?thesis using asm by simp qed +text \Computation by divide and conquer\ + +definition floor_sqrt_between :: \nat \ nat \ nat \ nat\ + where floor_sqrt_between_eq: + \floor_sqrt_between m q n = + (if floor_sqrt n \ {m.. + \\ + The \<^term>\0::nat\ is not for relevant regular computation + and can be chosen arbitrarily. + \ + +lemma floor_sqrt_between_out_of_bounds: + \floor_sqrt_between m 0 n = 0\ + by (simp add: floor_sqrt_between_eq) + +lemma floor_sqrt_between_singleton: + \floor_sqrt_between m (Suc 0) n = + (if m\<^sup>2 \ n \ n < (Suc m)\<^sup>2 then m else 0)\ + by (auto simp add: floor_sqrt_between_eq Suc_floor_sqrt_power2_gt floor_sqrt_unique) + +lemma floor_sqrt_between_rec: + \floor_sqrt_between m q n = ( + let + r = q div 2; + p = m + r; + s = p\<^sup>2 + in + if s = n + then p + else if s < n + then floor_sqrt_between (m + r) (q - r) n + else floor_sqrt_between m r n + )\ if \q > 0\ + using that le_floor_sqrt_iff [of \m + q div 2\ n] + by (auto simp add: floor_sqrt_between_eq Let_def not_less) + +lemma floor_sqrt_between_code [code]: + \floor_sqrt_between m q n = ( + if q = 0 then 0 + else if q = 1 + then if m\<^sup>2 \ n \ n < (Suc m)\<^sup>2 + then m + else 0 + else + let + r = q div 2; + p = m + r; + s = p\<^sup>2 + in + if s = n + then p + else if s < n + then floor_sqrt_between (m + r) (q - r) n + else floor_sqrt_between m r n + )\ +proof - + consider \q = 0\ | \q = 1\ | \q \ 2\ + by (cases \q \ 2\; cases q) simp_all + then show ?thesis + by cases + (simp_all add: floor_sqrt_between_out_of_bounds floor_sqrt_between_singleton floor_sqrt_between_rec) +qed + +lemma [code]: + \floor_sqrt n = floor_sqrt_between 0 (Suc (Suc n div 2)) n\ + using floor_sqrt_less_eq_half [of n] by (simp add: floor_sqrt_between_eq) + end