1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
|
(**
The dyadic rationals are numbers of the shape [m * 2 ^ e] with [m : Z] and [e : Z]
for some [Integers] implementation [Z]. These numbers form a ring and can be
embedded into any [Rationals] implementation [Q].
*)
From Coq Require Import Ring.
Require Import
MathClasses.interfaces.abstract_algebra
MathClasses.interfaces.integers MathClasses.interfaces.naturals MathClasses.interfaces.rationals
MathClasses.interfaces.additional_operations MathClasses.interfaces.orders
MathClasses.orders.minmax MathClasses.orders.integers MathClasses.orders.rationals
MathClasses.implementations.nonneg_integers_naturals MathClasses.implementations.stdlib_rationals
MathClasses.theory.rationals MathClasses.theory.shiftl MathClasses.theory.int_pow MathClasses.theory.nat_pow MathClasses.theory.abs.
Record Dyadic Z := dyadic { mant: Z; expo: Z }.
Arguments dyadic {Z} _ _.
Arguments mant {Z} _.
Arguments expo {Z} _.
Infix "▼" := dyadic (at level 80) : mc_scope.
Section dyadics.
Context `{Integers Z} `{Apart Z} `{!TrivialApart Z} `{!FullPseudoSemiRingOrder Zle Zlt}
`{equiv_dec : ∀ (x y : Z), Decision (x = y)}
`{le_dec : ∀ (x y : Z), Decision (x ≤ y)}
`{!ShiftLSpec Z (Z⁺) sl}.
Notation Dyadic := (Dyadic Z).
Add Ring Z: (rings.stdlib_ring_theory Z).
Global Program Instance dy_plus: Plus Dyadic := λ x y,
if decide_rel (≤) (expo x) (expo y)
then mant x + mant y ≪ (expo y - expo x)↾_ ▼ expo x ⊓ expo y
else mant x ≪ (expo x - expo y)↾_ + mant y ▼ expo x ⊓ expo y.
Next Obligation. now apply rings.flip_nonneg_minus. Qed.
Next Obligation. apply rings.flip_nonneg_minus. now apply orders.le_flip. Qed.
Global Instance dy_inject: Cast Z Dyadic := λ x, x ▼ 0.
Global Instance dy_negate: Negate Dyadic := λ x, -mant x ▼ expo x.
Global Instance dy_mult: Mult Dyadic := λ x y, mant x * mant y ▼ expo x + expo y.
Global Instance dy_0: Zero Dyadic := ('0 : Dyadic).
Global Instance dy_1: One Dyadic := ('1 : Dyadic).
(*
We define equality on the dyadics by injecting them into the rationals.
Since we do not want to parametrize the equality relation and all properties
on the dyadics by an arbitrary rationals implementations we have to pick some
specific rationals implementations. Although [Frac Z] seems like a nice choice,
it actually becomes quite slow, hence we stick with plain old [Qarith.Q].
Although we will make a specific choice for a rationals implementation to define
the equality relation, we will define the embedding for arbitrary rationals
implementations first.
*)
Section DtoQ_slow.
Context `{Rationals Q} `{Pow Q Z} (ZtoQ: Z → Q).
Definition DtoQ_slow (x : Dyadic) := ZtoQ (mant x) * 2 ^ (expo x).
End DtoQ_slow.
Section with_rationals.
Context `{Rationals Q} `{!IntPowSpec Q Z ipw} `{!SemiRing_Morphism (ZtoQ: Z → Q)}.
Add Ring Q: (rings.stdlib_ring_theory Q).
Notation DtoQ_slow' := (DtoQ_slow ZtoQ).
Lemma ZtoQ_shift (x n : Z) Pn : ZtoQ (x ≪ n↾Pn) = ZtoQ x * 2 ^ n.
Proof.
rewrite shiftl_nat_pow.
rewrite rings.preserves_mult, nat_pow.preserves_nat_pow, rings.preserves_2.
now rewrite <-(int_pow_nat_pow 2).
Qed.
Lemma DtoQ_slow_preserves_plus x y : DtoQ_slow' (x + y) = DtoQ_slow' x + DtoQ_slow' y.
Proof.
destruct x as [xn xe], y as [yn ye].
unfold plus at 1. unfold DtoQ_slow, dy_plus. simpl.
case (decide_rel (≤) xe ye); intros E; simpl.
rewrite rings.preserves_plus, ZtoQ_shift.
rewrite (lattices.meet_l xe ye) by assumption.
ring_simplify.
rewrite <-associativity, <-int_pow_exp_plus.
now setoid_replace (ye - xe + xe) with ye by ring.
now apply (rings.is_ne_0 (2:Q)).
rewrite rings.preserves_plus, ZtoQ_shift.
rewrite lattices.meet_r.
ring_simplify.
rewrite <-associativity, <-int_pow_exp_plus.
now setoid_replace (xe - ye + ye) with xe by ring.
now apply (rings.is_ne_0 (2:Q)).
now apply orders.le_flip.
Qed.
Lemma DtoQ_slow_preserves_negate x : DtoQ_slow' (-x) = -DtoQ_slow' x.
Proof.
unfold DtoQ_slow. simpl.
rewrite rings.preserves_negate. ring.
Qed.
Lemma DtoQ_slow_preserves_mult x y : DtoQ_slow' (x * y) = DtoQ_slow' x * DtoQ_slow' y.
Proof.
destruct x as [xn xe], y as [yn ye].
unfold DtoQ_slow. simpl.
rewrite rings.preserves_mult.
rewrite int_pow_exp_plus.
ring.
apply (rings.is_ne_0 (2:Q)).
Qed.
Lemma DtoQ_slow_preserves_0 : DtoQ_slow' 0 = 0.
Proof.
unfold DtoQ_slow. simpl.
rewrite rings.preserves_0. ring.
Qed.
Lemma DtoQ_slow_preserves_1 : DtoQ_slow' 1 = 1.
Proof.
unfold DtoQ_slow. simpl.
rewrite int_pow_0, rings.preserves_1. ring.
Qed.
End with_rationals.
Notation StdQ := QArith_base.Q.
Notation ZtoStdQ := (integers.integers_to_ring Z StdQ).
Notation DtoStdQ := (DtoQ_slow ZtoStdQ).
Add Ring StdQ : (rings.stdlib_ring_theory StdQ).
Global Instance dy_equiv: Equiv Dyadic := λ x y, DtoStdQ x = DtoStdQ y.
Instance: Setoid Dyadic.
Proof. now apply (setoids.projected_setoid DtoStdQ). Qed.
Instance: Proper ((=) ==> (=)) DtoStdQ.
Proof. now repeat red. Qed.
Instance: Injective DtoStdQ.
Proof. now repeat (split; try apply _). Qed.
Global Instance: Ring Dyadic.
Proof.
apply (rings.projected_ring DtoStdQ).
exact DtoQ_slow_preserves_plus.
exact DtoQ_slow_preserves_0.
exact DtoQ_slow_preserves_mult.
exact DtoQ_slow_preserves_1.
exact DtoQ_slow_preserves_negate.
Qed.
Global Instance dyadic_proper: Proper ((=) ==> (=) ==> (=)) dyadic.
Proof.
intros ? ? E1 ? ? E2.
unfold equiv, dy_equiv, DtoQ_slow. simpl.
now rewrite E1, E2.
Qed.
Instance: SemiRing_Morphism DtoStdQ.
Proof.
repeat (split; try apply _).
exact DtoQ_slow_preserves_plus.
exact DtoQ_slow_preserves_0.
exact DtoQ_slow_preserves_mult.
exact DtoQ_slow_preserves_1.
Qed.
Instance: Setoid_Morphism dy_inject.
Proof.
split; try apply _.
intros x y E.
unfold equiv, dy_equiv, dy_inject, DtoQ_slow. simpl in *.
rewrite int_pow_0. now rewrite E.
Qed.
Global Instance: Injective dy_inject.
Proof.
repeat (split; try apply _).
intros x y E. unfold equiv, dy_equiv, dy_inject, DtoQ_slow in E. simpl in *.
rewrite int_pow_0 in E. ring_simplify in E.
now apply (injective ZtoStdQ).
Qed.
Global Instance: SemiRing_Morphism dy_inject.
Proof.
repeat (split; try apply _).
intros x y. unfold sg_op at 2, plus_is_sg_op, dy_plus.
unfold equiv, dy_equiv, dy_inject, DtoQ_slow; simpl.
case (decide_rel); intros E; simpl.
rewrite 2!rings.preserves_plus, ZtoQ_shift.
rewrite rings.plus_negate_r.
rewrite lattices.meet_l, int_pow_0. ring.
reflexivity.
now destruct E.
intros x y. unfold sg_op at 2, mult_is_sg_op, dy_mult. simpl.
now setoid_replace (0 + 0:Z) with (0:Z) by ring.
Qed.
Lemma dy_eq_dec_aux (x y : Dyadic) p :
mant x = mant y ≪ (expo y - expo x)↾p ↔ x = y.
Proof.
destruct x as [xm xe], y as [ym ye].
assert (xe ≤ ye).
now apply rings.flip_nonneg_minus.
split; intros E.
unfold equiv, dy_equiv, DtoQ_slow. simpl in *.
rewrite E, ZtoQ_shift.
rewrite <-associativity, <-int_pow_exp_plus.
now setoid_replace (ye - xe + xe) with ye by ring.
easy.
unfold equiv, dy_equiv, DtoQ_slow in E. simpl in *.
apply (injective ZtoStdQ).
apply (right_cancellation (.*.) (2 ^ xe)).
rewrite E, ZtoQ_shift.
rewrite <-associativity, <-int_pow_exp_plus.
now setoid_replace (ye - xe + xe) with ye by ring.
easy.
Qed.
Lemma dy_eq_dec_aux_neg (x y : Dyadic) p :
mant x ≠ mant y ≪ (expo y - expo x)↾p ↔ x ≠ y.
Proof. split; intros E; intro; apply E; eapply dy_eq_dec_aux; eassumption. Qed.
Global Program Instance dy_eq_dec : ∀ (x y: Dyadic), Decision (x = y) := λ x y,
if decide_rel (≤) (expo x) (expo y)
then if decide_rel (=) (mant x) (mant y ≪ (expo y - expo x)↾_) then left _ else right _
else if decide_rel (=) (mant x ≪ (expo x - expo y)↾_) (mant y) then left _ else right _.
Next Obligation. now apply rings.flip_nonneg_minus. Qed.
Next Obligation. eapply dy_eq_dec_aux; eauto. Qed.
Next Obligation. eapply dy_eq_dec_aux_neg; eauto. Qed.
Next Obligation. apply rings.flip_nonneg_minus. now apply orders.le_flip. Qed.
Next Obligation. symmetry. eapply dy_eq_dec_aux. symmetry. eassumption. Qed.
Next Obligation. apply not_symmetry. eapply dy_eq_dec_aux_neg. apply not_symmetry. eassumption. Qed.
Global Instance dy_pow `{!Pow Z (Z⁺)} : Pow Dyadic (Z⁺) := λ x n, (mant x) ^ n ▼ 'n * expo x.
Global Instance dy_pow_spec `{!NatPowSpec Z (Z⁺) pw} : NatPowSpec Dyadic (Z⁺) dy_pow.
Proof.
split; unfold pow, dy_pow.
intros [xm xe] [ym ye] E1 e1 e2 E2.
unfold equiv, dy_equiv, DtoQ_slow in E1 |- *. simpl in *.
setoid_replace (xm ^ e1) with (xm ^ e2) by now apply (_ : Proper ((=) ==> (=) ==> (=)) pw). (* fixme *)
rewrite E2. clear e1 E2.
rewrite 2!(preserves_nat_pow (f:=ZtoStdQ)).
rewrite 2!(commutativity ('e2 : Z)).
rewrite 2!int_pow_exp_mult.
rewrite 2!int_pow_nat_pow.
rewrite <-2!nat_pow_base_mult.
now rewrite E1.
intros [xm xe]. simpl.
rewrite rings.preserves_0, left_absorb.
now rewrite nat_pow_0.
intros [xm xe] n. simpl.
rewrite nat_pow_S.
rewrite rings.preserves_plus, rings.preserves_1.
now rewrite distribute_r, left_identity.
Qed.
Global Instance dy_shiftl: ShiftL Dyadic Z := λ x n, mant x ▼ n + expo x.
Global Instance: ShiftLSpec Dyadic Z dy_shiftl.
Proof.
split.
intros [xm xe] [ym ye] E1 n1 n2 E2.
unfold shiftl, dy_shiftl, equiv, dy_equiv, DtoQ_slow in *. simpl in *.
rewrite 2!int_pow_exp_plus; try apply (rings.is_ne_0 (2:StdQ)).
transitivity (ZtoStdQ xm * 2 ^ xe * 2 ^ n1).
ring.
rewrite E1, E2. ring.
intros [xm xe].
unfold shiftl, dy_shiftl, equiv, dy_equiv, DtoQ_slow. simpl.
now rewrite left_identity.
intros [xm xe] n. simpl.
rewrite <-(rings.preserves_2 (f:=dy_inject)).
unfold shiftl, dy_shiftl, equiv, dy_equiv, DtoQ_slow. simpl.
rewrite <-associativity, int_pow_S.
rewrite rings.preserves_mult, rings.preserves_2.
rewrite rings.plus_0_l. ring.
apply (rings.is_ne_0 (2:StdQ)).
Qed.
Global Instance dy_le: Le Dyadic := λ x y, DtoStdQ x ≤ DtoStdQ y.
Global Instance dy_lt: Lt Dyadic := orders.dec_lt.
Instance: Proper ((=) ==> (=) ==> iff) dy_le.
Proof.
intros [x1m x1e] [y1m y1e] E1 [x2m x2e] [y2m y2e] E2.
unfold dy_le, equiv, dy_equiv, DtoQ_slow in *. simpl in *.
now rewrite E1, E2.
Qed.
Instance: SemiRingOrder dy_le.
Proof. now apply (rings.projected_ring_order DtoStdQ). Qed.
Instance: TotalRelation dy_le.
Proof. now apply (maps.projected_total_order DtoStdQ). Qed.
Instance: OrderEmbedding DtoStdQ.
Proof. now repeat (split; try apply _). Qed.
Global Instance: ZeroProduct Dyadic.
Proof.
intros x y E.
destruct (zero_product (DtoStdQ x) (DtoStdQ y)) as [Ex|Ey].
now rewrite <-rings.preserves_mult, E, rings.preserves_0.
left. apply (injective DtoStdQ). now rewrite Ex, rings.preserves_0.
right. apply (injective DtoStdQ). now rewrite Ey, rings.preserves_0.
Qed.
Global Instance: FullPseudoSemiRingOrder dy_le dy_lt.
Proof. now rapply (semirings.dec_full_pseudo_srorder (R:=Dyadic)). Qed.
Lemma nonneg_mant (x : Dyadic) : 0 ≤ x ↔ 0 ≤ mant x.
Proof.
split; intros E.
unfold le, dy_le, DtoQ_slow in E. simpl in *.
apply (order_reflecting ZtoStdQ).
apply (order_reflecting (.* 2 ^ expo x)).
now rewrite rings.preserves_0, left_absorb in E |- *.
unfold le, dy_le, DtoQ_slow. simpl.
apply (order_preserving ZtoStdQ) in E.
apply (order_preserving (.* 2 ^ expo x)) in E.
now rewrite rings.preserves_0, left_absorb in E |- *.
Qed.
Lemma nonpos_mant (x : Dyadic) : x ≤ 0 ↔ mant x ≤ 0.
Proof.
rewrite 2!rings.flip_nonpos_negate.
apply nonneg_mant.
Qed.
Global Program Instance dy_abs `{!Abs Z} : Abs Dyadic := λ x, abs (mant x) ▼ expo x.
Next Obligation.
split; intros E.
rewrite abs_nonneg.
now destruct x.
now apply nonneg_mant.
rewrite abs_nonpos.
now destruct x.
now apply nonpos_mant.
Qed.
Lemma dy_le_dec_aux (x y : Dyadic) p :
mant x ≤ mant y ≪ (expo y - expo x)↾p → x ≤ y.
Proof.
destruct x as [xm xe], y as [ym ye].
intros E. unfold le, dy_le, DtoQ_slow. simpl in *.
apply (order_preserving ZtoStdQ) in E.
rewrite ZtoQ_shift in E.
apply (order_preserving (.* 2 ^ xe)) in E.
rewrite <-associativity, <-int_pow_exp_plus in E.
now setoid_replace ((ye - xe) + xe) with ye in E by ring.
now apply (rings.is_ne_0 (2:StdQ)).
Qed.
Local Obligation Tactic := idtac.
Global Program Instance dy_le_dec : ∀ (x y: Dyadic), Decision (x ≤ y) := λ x y,
if decide_rel (≤) (expo x) (expo y)
then if decide_rel (≤) (mant x) (mant y ≪ (expo y - expo x)↾_) then left _ else right _
else if decide_rel (≤) (mant x ≪ (expo x - expo y)↾_) (mant y) then left _ else right _.
Next Obligation.
intros. now apply rings.flip_nonneg_minus.
Qed.
Next Obligation.
intros x y E1 E2. eapply dy_le_dec_aux. eassumption.
Qed.
Next Obligation.
intros x y E1 E2.
apply orders.lt_not_le_flip.
apply orders.not_le_lt_flip in E2. apply rings.flip_lt_negate in E2.
rewrite orders.lt_iff_le_ne in E2. destruct E2 as [E2a E2b]. split.
apply rings.flip_le_negate.
eapply dy_le_dec_aux.
simpl. rewrite shiftl_negate. eassumption.
intros E3. apply E2b. apply sm_proper.
apply dy_eq_dec_aux. now symmetry.
Qed.
Next Obligation.
intros. apply rings.flip_nonneg_minus. now apply orders.le_flip.
Qed.
Next Obligation.
intros x y E1 E2.
apply orders.le_equiv_lt in E2. destruct E2 as [E2 | E2].
apply orders.eq_le. symmetry in E2 |- *.
eapply dy_eq_dec_aux. eassumption.
apply rings.flip_le_negate.
eapply dy_le_dec_aux.
simpl. rewrite shiftl_negate. apply rings.flip_le_negate. apply orders.lt_le, E2.
Qed.
Next Obligation.
intros x y E1 E2.
apply orders.not_le_lt_flip in E2.
rewrite orders.lt_iff_le_ne in E2. destruct E2 as [E2a E2b].
apply orders.lt_not_le_flip. apply orders.lt_iff_le_ne. split.
eapply dy_le_dec_aux. eassumption.
eapply dy_eq_dec_aux_neg. eassumption.
Qed.
(*
The embedding into the rationals as presented above, is quite slow because it
involves performing exponentiation on the rationals while we have a (presumably)
much faster shift operation on the integers. We therefore define a faster
embedding, prove that it is equivalent to the one above, and derive some basic
properties.
*)
Section DtoQ.
Context `{Rationals Q} (ZtoQ: Z → Q) `{!SemiRing_Morphism (ZtoQ: Z → Q)}.
Local Obligation Tactic := program_simpl.
Program Definition DtoQ (x : Dyadic) : Q :=
if decide_rel (≤) 0 (expo x)
then ZtoQ (mant x ≪ (expo x)↾_)
else ZtoQ (mant x) / ZtoQ (1 ≪ (-expo x)↾_).
Next Obligation.
apply rings.flip_nonpos_negate.
now apply orders.le_flip.
Qed.
End DtoQ.
Section embed_rationals.
Context `{Rationals Q} `{!IntPowSpec Q Z ipw} `{!SemiRing_Morphism (ZtoQ: Z → Q)}.
Context `{Apart Q} `{!TrivialApart Q} `{!FullPseudoSemiRingOrder Qlt Qle}.
Add Ring Q2 : (rings.stdlib_ring_theory Q).
Notation DtoQ' := (DtoQ ZtoQ).
Notation DtoQ_slow' := (DtoQ_slow ZtoQ).
Notation StdQtoQ := (rationals_to_rationals StdQ Q).
Instance: Params (@DtoQ_slow) 6 := {}.
Lemma DtoQ_slow_correct : DtoQ_slow' = StdQtoQ ∘ DtoStdQ.
Proof.
intros x y E. unfold compose. rewrite <- E. clear y E.
unfold DtoQ_slow.
rewrite rings.preserves_mult, (preserves_int_pow 2), rings.preserves_2.
now rewrite (integers.to_ring_unique_alt ZtoQ (StdQtoQ ∘ ZtoStdQ)).
Qed.
Global Instance: SemiRing_Morphism DtoQ_slow'.
Proof. apply (rings.semiring_morphism_proper _ _ DtoQ_slow_correct), _. Qed.
Global Instance: Injective DtoQ_slow'.
Proof. rewrite DtoQ_slow_correct. apply _. Qed.
Global Instance: OrderEmbedding DtoQ_slow'.
Proof. apply (maps.order_embedding_proper _ _ DtoQ_slow_correct). apply _. Qed.
Lemma DtoQ_correct : DtoQ' = DtoQ_slow'.
Proof.
intros x y E. rewrite <-E. clear y E.
unfold DtoQ, DtoQ_slow.
destruct x as [xm xe]. simpl.
case (decide_rel); intros E.
now rewrite ZtoQ_shift.
rewrite int_pow_negate_alt, ZtoQ_shift.
now rewrite rings.preserves_1, left_identity.
Qed.
Global Instance: SemiRing_Morphism DtoQ'.
Proof. apply (rings.semiring_morphism_proper _ _ DtoQ_correct), _. Qed.
Global Instance: Injective DtoQ'.
Proof. rewrite DtoQ_correct. apply _. Qed.
Global Instance: OrderEmbedding DtoQ'.
Proof. apply (maps.order_embedding_proper _ _ DtoQ_correct). apply _. Qed.
End embed_rationals.
End dyadics.
|