author | wenzelm |
Mon, 11 Apr 2016 15:26:58 +0200 | |
changeset 62954 | c5d0fdc260fa |
parent 62352 | 35a9e1cbb5b3 |
permissions | -rw-r--r-- |
62352
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
1 |
(* Title: HOL/Library/Polynomial_GCD_euclidean.thy |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
2 |
Author: Brian Huffman |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
3 |
Author: Clemens Ballarin |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
4 |
Author: Amine Chaieb |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
5 |
Author: Florian Haftmann |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
6 |
*) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
7 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
8 |
section \<open>GCD and LCM on polynomials over a field\<close> |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
9 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
10 |
theory Polynomial_GCD_euclidean |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
11 |
imports Main "~~/src/HOL/GCD" "~~/src/HOL/Library/Polynomial" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
12 |
begin |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
13 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
14 |
subsection \<open>GCD of polynomials\<close> |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
15 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
16 |
instantiation poly :: (field) gcd |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
17 |
begin |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
18 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
19 |
function gcd_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
20 |
where |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
21 |
"gcd (x::'a poly) 0 = smult (inverse (coeff x (degree x))) x" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
22 |
| "y \<noteq> 0 \<Longrightarrow> gcd (x::'a poly) y = gcd y (x mod y)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
23 |
by auto |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
24 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
25 |
termination "gcd :: _ poly \<Rightarrow> _" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
26 |
by (relation "measure (\<lambda>(x, y). if y = 0 then 0 else Suc (degree y))") |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
27 |
(auto dest: degree_mod_less) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
28 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
29 |
declare gcd_poly.simps [simp del] |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
30 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
31 |
definition lcm_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
32 |
where |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
33 |
"lcm_poly a b = a * b div smult (coeff a (degree a) * coeff b (degree b)) (gcd a b)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
34 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
35 |
instance .. |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
36 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
37 |
end |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
38 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
39 |
lemma |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
40 |
fixes x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
41 |
shows poly_gcd_dvd1 [iff]: "gcd x y dvd x" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
42 |
and poly_gcd_dvd2 [iff]: "gcd x y dvd y" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
43 |
apply (induct x y rule: gcd_poly.induct) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
44 |
apply (simp_all add: gcd_poly.simps) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
45 |
apply (fastforce simp add: smult_dvd_iff dest: inverse_zero_imp_zero) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
46 |
apply (blast dest: dvd_mod_imp_dvd) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
47 |
done |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
48 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
49 |
lemma poly_gcd_greatest: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
50 |
fixes k x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
51 |
shows "k dvd x \<Longrightarrow> k dvd y \<Longrightarrow> k dvd gcd x y" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
52 |
by (induct x y rule: gcd_poly.induct) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
53 |
(simp_all add: gcd_poly.simps dvd_mod dvd_smult) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
54 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
55 |
lemma dvd_poly_gcd_iff [iff]: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
56 |
fixes k x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
57 |
shows "k dvd gcd x y \<longleftrightarrow> k dvd x \<and> k dvd y" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
58 |
by (auto intro!: poly_gcd_greatest intro: dvd_trans [of _ "gcd x y"]) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
59 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
60 |
lemma poly_gcd_monic: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
61 |
fixes x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
62 |
shows "coeff (gcd x y) (degree (gcd x y)) = |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
63 |
(if x = 0 \<and> y = 0 then 0 else 1)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
64 |
by (induct x y rule: gcd_poly.induct) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
65 |
(simp_all add: gcd_poly.simps nonzero_imp_inverse_nonzero) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
66 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
67 |
lemma poly_gcd_zero_iff [simp]: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
68 |
fixes x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
69 |
shows "gcd x y = 0 \<longleftrightarrow> x = 0 \<and> y = 0" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
70 |
by (simp only: dvd_0_left_iff [symmetric] dvd_poly_gcd_iff) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
71 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
72 |
lemma poly_gcd_0_0 [simp]: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
73 |
"gcd (0::_ poly) 0 = 0" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
74 |
by simp |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
75 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
76 |
lemma poly_dvd_antisym: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
77 |
fixes p q :: "'a::idom poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
78 |
assumes coeff: "coeff p (degree p) = coeff q (degree q)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
79 |
assumes dvd1: "p dvd q" and dvd2: "q dvd p" shows "p = q" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
80 |
proof (cases "p = 0") |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
81 |
case True with coeff show "p = q" by simp |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
82 |
next |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
83 |
case False with coeff have "q \<noteq> 0" by auto |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
84 |
have degree: "degree p = degree q" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
85 |
using \<open>p dvd q\<close> \<open>q dvd p\<close> \<open>p \<noteq> 0\<close> \<open>q \<noteq> 0\<close> |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
86 |
by (intro order_antisym dvd_imp_degree_le) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
87 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
88 |
from \<open>p dvd q\<close> obtain a where a: "q = p * a" .. |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
89 |
with \<open>q \<noteq> 0\<close> have "a \<noteq> 0" by auto |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
90 |
with degree a \<open>p \<noteq> 0\<close> have "degree a = 0" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
91 |
by (simp add: degree_mult_eq) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
92 |
with coeff a show "p = q" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
93 |
by (cases a, auto split: if_splits) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
94 |
qed |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
95 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
96 |
lemma poly_gcd_unique: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
97 |
fixes d x y :: "_ poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
98 |
assumes dvd1: "d dvd x" and dvd2: "d dvd y" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
99 |
and greatest: "\<And>k. k dvd x \<Longrightarrow> k dvd y \<Longrightarrow> k dvd d" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
100 |
and monic: "coeff d (degree d) = (if x = 0 \<and> y = 0 then 0 else 1)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
101 |
shows "gcd x y = d" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
102 |
proof - |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
103 |
have "coeff (gcd x y) (degree (gcd x y)) = coeff d (degree d)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
104 |
by (simp_all add: poly_gcd_monic monic) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
105 |
moreover have "gcd x y dvd d" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
106 |
using poly_gcd_dvd1 poly_gcd_dvd2 by (rule greatest) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
107 |
moreover have "d dvd gcd x y" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
108 |
using dvd1 dvd2 by (rule poly_gcd_greatest) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
109 |
ultimately show ?thesis |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
110 |
by (rule poly_dvd_antisym) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
111 |
qed |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
112 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
113 |
instance poly :: (field) semiring_gcd |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
114 |
proof |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
115 |
fix p q :: "'a::field poly" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
116 |
show "normalize (gcd p q) = gcd p q" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
117 |
by (induct p q rule: gcd_poly.induct) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
118 |
(simp_all add: gcd_poly.simps normalize_poly_def) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
119 |
show "lcm p q = normalize (p * q) div gcd p q" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
120 |
by (simp add: coeff_degree_mult div_smult_left div_smult_right lcm_poly_def normalize_poly_def) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
121 |
(metis (no_types, lifting) div_smult_right inverse_mult_distrib inverse_zero mult.commute pdivmod_rel pdivmod_rel_def smult_eq_0_iff) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
122 |
qed simp_all |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
123 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
124 |
lemma poly_gcd_1_left [simp]: "gcd 1 y = (1 :: _ poly)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
125 |
by (rule poly_gcd_unique) simp_all |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
126 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
127 |
lemma poly_gcd_1_right [simp]: "gcd x 1 = (1 :: _ poly)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
128 |
by (rule poly_gcd_unique) simp_all |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
129 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
130 |
lemma poly_gcd_minus_left [simp]: "gcd (- x) y = gcd x (y :: _ poly)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
131 |
by (rule poly_gcd_unique) (simp_all add: poly_gcd_monic) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
132 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
133 |
lemma poly_gcd_minus_right [simp]: "gcd x (- y) = gcd x (y :: _ poly)" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
134 |
by (rule poly_gcd_unique) (simp_all add: poly_gcd_monic) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
135 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
136 |
lemma poly_gcd_code [code]: |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
137 |
"gcd x y = (if y = 0 then normalize x else gcd y (x mod (y :: _ poly)))" |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
138 |
by (simp add: gcd_poly.simps) |
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
139 |
|
35a9e1cbb5b3
separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff
changeset
|
140 |
end |