-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtruncpowerseries.v
1639 lines (1327 loc) · 56.3 KB
/
truncpowerseries.v
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
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *)
(*****************************************************************************)
(* some doc here *)
(*****************************************************************************)
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.
From mathcomp Require Import fintype div tuple finfun bigop finset fingroup.
From mathcomp Require Import perm ssralg poly polydiv mxpoly binomial bigop.
From mathcomp Require Import finalg zmodp matrix mxalgebra polyXY ring_quotient.
From Newtonsums Require Import auxresults fraction polyorder polydec revpoly.
Import FracField.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Import GRing.Theory.
Local Open Scope ring_scope.
Local Open Scope quotient_scope.
Delimit Scope tfps_scope with tfps.
Reserved Notation "{ 'tfps' K n }"
(at level 0, K at next level, format "{ 'tfps' K n }").
Reserved Notation "[ 'tfps' s <= n => F ]"
(at level 0, n at next level, s ident, format "[ 'tfps' s <= n => F ]").
Reserved Notation "[ 'tfps' s => F ]"
(at level 0, s ident, format "[ 'tfps' s => F ]").
Reserved Notation "c %:S" (at level 2).
Reserved Notation "f *h g" (at level 2).
Reserved Notation "f ^` ()" (at level 8).
Local Notation "p ^ f" := (map_poly f p).
Section MorePolyTheory.
Variable (R : ringType).
Lemma leq_size_deriv (p : {poly R}) : size p^`() <= (size p).-1.
Proof.
have [->|pN0] := eqVneq p 0; first by rewrite deriv0 size_poly0.
by rewrite -ltnS prednK // ?lt_size_deriv // size_poly_gt0.
Qed.
Lemma p_neq0 (p : {poly R}): (exists (x : R), p.[x] != 0) -> p != 0.
Proof.
by move => [x px_neq0]; move: px_neq0; apply: contra => /eqP ->; rewrite horner0.
Qed.
Variable (K : fieldType).
Fact polyXP (p : {poly K}) : reflect (p`_0 = 0) ('X %| p).
Proof. by rewrite -['X]subr0 -polyC0 -horner_coef0; apply: polyXsubCP. Qed.
Fact nth0_eq_nth0 (p q : {poly K}) :
p %= q -> (p`_0 == 0) = (q`_0 == 0).
Proof.
move => p_eqp_q; rewrite -!horner_coef0.
apply/(sameP eqP).
apply/(equivP eqP).
apply: (rwP2 (polyXsubCP _ _)).
apply: (aux_equivb (polyXsubCP _ _)).
by apply: eqp_dvdr.
Qed.
Hypothesis char_K_is_zero : [char K] =i pred0.
Fact size_deriv (p : {poly K}) : size (p ^`()%R) = (size p).-1.
Proof.
have [lt_sp_1 | le_sp_1] := ltnP (size p) 2.
move: (size1_polyC lt_sp_1) => ->.
by rewrite derivC size_poly0 size_polyC ; case: (_ != _).
rewrite size_poly_eq // !prednK ; last first.
move: (ltn_predK le_sp_1) => H.
by move: le_sp_1 ; rewrite -{1}H -[X in _ < X]add1n -add1n leq_add2l.
rewrite -mulr_natr mulf_eq0 ; apply/norP ; split.
by rewrite -lead_coefE lead_coef_eq0 -size_poly_gt0 (ltn_trans _ le_sp_1).
move: (charf0P K) => char_K_property.
move/char_K_property : char_K_is_zero => char_K.
rewrite char_K -lt0n.
move: (ltn_predK le_sp_1) => H.
by move: le_sp_1 ; rewrite -{1}H -[X in _ < X]add1n -add1n leq_add2l.
Qed.
Lemma p_cst (p : {poly K}) : p ^`() = 0 -> {c : K | p = c %:P}.
Proof.
move/eqP ; rewrite -size_poly_eq0 size_deriv.
move/eqP => H_size_p.
exists p`_0 ; apply: size1_polyC.
by rewrite (leq_trans (leqSpred _)) // H_size_p.
Qed.
(* this kind of injectivity + deriv result could be useful ? *)
(* Lemma deriv_poly_eq (K : fieldType) (p q : {poly K}) :
p`_0 == q`_0 -> p^`() == q^`() -> p = q.
Proof.
rewrite -subr_eq0 -coefB -[p^`() == q^`()]subr_eq0 -derivB.
move => coef0_eq0 deriv_eq0 ; apply/eqP.
rewrite -subr_eq0 ; apply/eqP ; move: coef0_eq0 deriv_eq0.
exact: deriv_poly_eq0.
Qed. *)
End MorePolyTheory.
Section ModPolyTheory.
Variable (K : fieldType).
Fact leq_modpXn m (p : {poly K}) : size (p %% 'X^m) <= m.
Proof.
by rewrite -ltnS (leq_trans (ltn_modpN0 _ _)) // -?size_poly_eq0 size_polyXn.
Qed.
Lemma coef_modXn m (p : {poly K}) i : (p %% 'X^m)`_i =
if i < m then p`_i else 0.
Proof.
have [lt_i_m|le_m_i] := ltnP; last first.
by rewrite nth_default // (leq_trans (leq_modpXn _ _)).
have /polyP /(_ i) := divp_eq p 'X^m.
by rewrite coefD coefMXn lt_i_m add0r.
Qed.
(* should not be visible outside this file *)
Fact modCXn a n : 0 < n -> a%:P %% 'X^n = a%:P :> {poly K}.
Proof.
move=> lt_0n.
by rewrite modp_small // size_polyC size_polyXn (leq_ltn_trans (leq_b1 _)).
Qed.
Fact modp_modp (p u v : {poly K}) : u %| v -> (p %% v) %% u = p %% u.
Proof.
move => dvdp_u_v.
have [->|v_neq0] := eqVneq v 0; first by rewrite modp0.
rewrite (divp_eq p v) modp_addl_mul_small ?ltn_modp //.
by rewrite modp_add [X in X + _]modp_eq0 ?dvdp_mull // add0r.
Qed.
Fact coef0M (p q : {poly K}) : (p * q)`_0 = p`_0 * q`_0.
(* Proof. by rewrite coefM big_ord_recl big_ord0 addr0. Qed. *)
Proof. by rewrite -!horner_coef0 hornerM. Qed.
(* should not be visible outside this file *)
Fact modX_eq0 (p : {poly K}) (n m : nat) : p`_0 = 0 -> n < m ->
(p ^+ m) %% 'X^n.+1 = 0.
Proof.
rewrite -horner_coef0 => /polyXsubCP p0_eq0 n_lt_m.
rewrite polyC0 subr0 in p0_eq0.
apply/modp_eq0P.
by rewrite (dvdp_trans (dvdp_exp2l ('X : {poly K}) n_lt_m)) // dvdp_exp2r.
Qed.
End ModPolyTheory.
Section MoreBigop.
Definition swap (R : Type) (x : R * R) := (x.2, x.1).
Lemma swap_inj (R : Type) : involutive (@swap R).
Proof. by move => [x1 x2]. Qed.
Lemma triangular_swap (R : Type) (idx : R) (op : Monoid.com_law idx)
(m : nat) (P : 'I_m -> 'I_m -> bool) (F : nat -> nat -> R) :
\big[op/idx]_(i < m) \big[op/idx]_(j < m | P i j) F i j =
\big[op/idx]_(j < m) \big[op/idx]_(i < m | P i j) F i j.
Proof. by rewrite !pair_big_dep (reindex_inj (inv_inj (@swap_inj _))). Qed.
Lemma index_translation (R : Type) (idx : R) (op : Monoid.law idx)
(m j : nat) (F : nat -> R) :
\big[op/idx]_(i < m - j) F i =
\big[op/idx]_(k < m | j <= k) F (k - j)%N.
Proof.
rewrite -(big_mkord predT F) /= (big_mknat _ j m (fun k => F (k - j)%N)).
rewrite -{2}[j]add0n (big_addn 0 m j _ _).
by apply: eq_bigr => i _ ; rewrite addnK.
Qed.
Lemma aux_triangular_index_bigop (R : Type) (idx : R) (op : Monoid.com_law idx)
(m : nat) (F : nat -> nat -> R) :
\big[op/idx]_(i < m) \big[op/idx]_(j < m | i + j < m) F i j =
\big[op/idx]_(k < m) \big[op/idx]_(l < k.+1) F l (k - l)%N.
Proof.
evar (G : 'I_m -> R) ; rewrite [LHS](eq_bigr G) => [|i _] ; last first.
+ rewrite (eq_bigl (fun j => nat_of_ord j < (m - (nat_of_ord i))%N))=> [|j /=].
- rewrite big_ord_narrow => [ | _ /= ] ; first exact: leq_subr.
by rewrite index_translation; symmetry; rewrite /G; reflexivity.
- by rewrite ltn_subRL.
+ rewrite /G (triangular_swap _ (fun i k => (nat_of_ord i) <= (nat_of_ord k))
(fun i k => F i (k - i)%N)).
apply: eq_big => [ // | i _].
rewrite (eq_bigl (fun i0 => (nat_of_ord i0) < i.+1)) => [ | j ] ; last first.
- by rewrite -ltnS.
- by rewrite big_ord_narrow.
Qed.
Lemma triangular_index_bigop (R : Type) (idx : R) (op : Monoid.com_law idx)
(m n: nat) (F : nat -> nat -> R) :
n <= m ->
\big[op/idx]_(i < m) \big[op/idx]_(j < m | i + j < n) F i j =
\big[op/idx]_(k < n) \big[op/idx]_(l < k.+1) F l (k - l)%N.
Proof.
move => leq_nm.
rewrite -(subnKC leq_nm) big_split_ord /=.
rewrite [X in op _ X]big1_seq => [|i _]; last first.
rewrite big_hasC // ; apply/hasPn => x _.
by rewrite -[X in _ < X]addn0 -addnA ltn_add2l ltn0.
rewrite Monoid.Theory.simpm /= -aux_triangular_index_bigop.
apply: eq_bigr => i _ ; rewrite subnKC //.
rewrite (eq_bigl (fun j => (i + (nat_of_ord j) < n) && ((nat_of_ord j) < n)))
; last first.
move => j; symmetry.
rewrite andb_idr //; apply: contraLR; rewrite -!leqNgt => leq_nj.
by rewrite (leq_trans leq_nj) // leq_addl.
by rewrite big_ord_narrow_cond.
Qed.
End MoreBigop.
Section TruncatedPowerSeries.
Variables (K : fieldType) (n : nat).
Record tfps := MkTfps
{
truncated_tfps :> {poly K};
_ : size truncated_tfps <= n.+1
}.
Definition tfps_of of phant K := tfps.
Local Notation "'{tfps}'" := (tfps_of (Phant K)).
Canonical tfps_subType := [subType for truncated_tfps].
Definition tfps_eqMixin := [eqMixin of tfps by <:].
Canonical tfps_eqType := EqType {tfps} tfps_eqMixin.
Definition tfps_choiceMixin := [choiceMixin of tfps by <:].
Canonical tfps_choiceType := ChoiceType {tfps} tfps_choiceMixin.
Definition Tfps_of (p : {poly K}) (p_small : size p <= n.+1) :
{tfps} := MkTfps p_small.
Definition Tfpsp (p : {poly K}) := Tfps_of (leq_modpXn _ p).
Definition tfps_of_fun (f : nat -> K) := Tfps_of (size_poly _ f).
End TruncatedPowerSeries.
Section TruncatedPowerSeriesTheory.
Variables (K : fieldType) (n : nat).
Local Notation "{ 'tfps' K n }" := (tfps_of n (Phant K)).
Local Notation tfps := {tfps K n}.
Local Notation "[ 'tfps' s <= n => F ]" := (tfps_of_fun n (fun s => F)).
Local Notation "[ 'tfps' s => F ]" := [tfps s <= n => F].
Implicit Types (f g : tfps).
Lemma size_tfps f : size (val f) <= n.+1.
Proof. by case: f. Qed.
Fact mod_tfps (m : nat) f : n <= m -> f %% 'X^m.+1 = (val f).
Proof.
move => leq_nm.
by rewrite modp_small // size_polyXn ltnS (leq_trans (size_tfps _)).
Qed.
Fact Tfpsp_modp (m : nat) (p : {poly K}) : n < m ->
Tfpsp n (p %% 'X^m) = Tfpsp n p.
Proof. by move=> lt_nm; apply/val_inj=> /=; rewrite modp_modp // dvdp_exp2l. Qed.
Lemma tfps_nth_default f j : j > n -> f`_j = 0.
Proof. by move=> j_big; rewrite nth_default // (leq_trans _ j_big) ?size_tfps. Qed.
Lemma tfps_coefK f : [tfps s => f`_s] = f.
Proof.
apply/val_inj/polyP=> j; rewrite coef_poly ltnS.
by have [//|j_big] := leqP; rewrite tfps_nth_default.
Qed.
Lemma coef_tfps s (f : nat -> K) :
[tfps s => f s]`_s = if s <= n then f s else 0.
Proof. by rewrite coef_poly. Qed.
Lemma eq_tfps f g : (forall i : 'I_n.+1, f`_i = g`_i) <-> (f = g).
Proof.
split=> [eq_s|-> //]; apply/val_inj/polyP => i /=.
have [i_small|i_big] := ltnP i n.+1; first by rewrite (eq_s (Ordinal i_small)).
by rewrite -[f]tfps_coefK -[g]tfps_coefK !coef_tfps leqNgt i_big.
Qed.
Lemma nth0_Tfpsp (p : {poly K}) : (Tfpsp n p)`_0 = p`_0.
Proof. by rewrite coef_modXn ltn0Sn. Qed.
(* zmodType structure *)
Fact zero_tfps_subproof : size (0 : {poly K}) <= n.+1.
Proof. by rewrite size_poly0. Qed.
Definition zero_tfps := Tfps_of zero_tfps_subproof.
Lemma add_tfps_subproof f g :
size (val f + val g) <= n.+1.
Proof. by rewrite (leq_trans (size_add _ _)) // geq_max !size_tfps. Qed.
Definition add_tfps f g := Tfps_of (add_tfps_subproof f g).
Lemma opp_tfps_proof f : size (- val f) <= n.+1.
Proof. by rewrite size_opp ?size_tfps. Qed.
Definition opp_tfps f := Tfps_of (opp_tfps_proof f).
Fact add_tfpsA : associative add_tfps.
Proof. by move => f1 f2 f3; apply/val_inj; apply: addrA. Qed.
Fact add_tfpsC : commutative add_tfps.
Proof. by move => f1 f2; apply/val_inj; apply: addrC. Qed.
Fact add_tfps0f : left_id zero_tfps add_tfps.
Proof. by move => f; apply/val_inj; apply: add0r. Qed.
Fact add_tfpsK : left_inverse zero_tfps opp_tfps add_tfps.
Proof. by move => f; apply/val_inj; apply: addNr. Qed.
Definition tfps_zmodMixin :=
ZmodMixin add_tfpsA add_tfpsC add_tfps0f add_tfpsK.
Canonical tfps_zmodType := ZmodType tfps tfps_zmodMixin.
Lemma Tfpsp0 : Tfpsp n 0 = 0.
Proof. by apply/val_inj => /=; rewrite mod0p. Qed.
(* ringType structure *)
Fact one_tfps_proof : size (1 : {poly K}) <= n.+1.
Proof. by rewrite size_polyC (leq_trans (leq_b1 _)). Qed.
Definition one_tfps : tfps := Tfps_of one_tfps_proof.
Definition mul_tfps f g := Tfpsp n (val f * val g).
Definition hmul_tfps f g := [tfps j => f`_j * g`_j].
Definition deriv_tfps f : {tfps K n.-1} := [tfps s <= n.-1 => f`_s.+1 *+ s.+1].
Local Notation "f *h g" := (hmul_tfps f g) (at level 2).
Lemma hmul_tfpsC : commutative hmul_tfps.
Proof.
by move=> f1 f2; apply/val_inj/polyP => /= i; rewrite !coef_poly mulrC.
Qed.
Lemma hmul_tfpsA : associative hmul_tfps.
Proof.
move=> f1 f2 f3; apply/val_inj/polyP => /= i.
by rewrite // !coef_poly; case: (_ < _) => //; apply: mulrA.
Qed.
Lemma hmul_tfps0r f : 0 *h f = 0.
Proof.
by apply/val_inj/polyP=> i /=; rewrite coef_poly coef0 mul0r if_same.
Qed.
Lemma hmul_tfpsr0 f : f *h 0 = 0.
Proof. by rewrite hmul_tfpsC hmul_tfps0r. Qed.
Fact left_id_one_mul_tfps : left_id one_tfps mul_tfps.
Proof.
move=> p; apply val_inj; rewrite /= mul1r.
by rewrite modp_small // size_polyXn ltnS ?size_tfps.
Qed.
Fact mul_tfpsC : commutative mul_tfps.
Proof. by move=> f1 f2; apply val_inj => /=; rewrite mulrC. Qed.
Fact left_distributive_mul_tfps : left_distributive mul_tfps add_tfps.
Proof. by move=> f1 f2 f3; apply val_inj => /=; rewrite mulrDl modp_add. Qed.
Fact mul_tfpsA : associative mul_tfps.
Proof.
move=> f1 f2 f3; apply/val_inj.
by rewrite /= [in RHS]mulrC !modp_mul mulrA mulrC.
Qed.
Fact one_tfps_not_zero : one_tfps != 0.
Proof. by rewrite -val_eqE oner_neq0. Qed.
Definition tfps_ringMixin := ComRingMixin mul_tfpsA mul_tfpsC
left_id_one_mul_tfps left_distributive_mul_tfps one_tfps_not_zero.
Canonical tfps_ringType := RingType tfps tfps_ringMixin.
Canonical tfps_comRingType := ComRingType tfps mul_tfpsC.
(* comUnitRingType structure *)
Lemma coef_Tfpsp (p : {poly K}) s : (Tfpsp n p)`_s = if s <= n then p`_s else 0.
Proof. by rewrite coef_modXn. Qed.
Fixpoint coef_inv_rec (p : {poly K}) (m i : nat) : K :=
match m with
| O => p`_(locked 0%N) ^-1
| S m => if i == 0%N then p`_(locked 0%N) ^-1
else - p`_(locked 0%N) ^-1 * \sum_(k < i) p`_(i - k)
* coef_inv_rec p m k
end.
Definition coef_inv (p : {poly K}) i : K := coef_inv_rec p i i.
Lemma coef_inv_recE (p : {poly K}) m i : i <= m ->
coef_inv_rec p m i = coef_inv p i.
Proof.
rewrite /coef_inv; elim: m {-2}m (leqnn m) i=> [k | m IHm].
by rewrite leqn0 => /eqP -> i ; rewrite leqn0 => /eqP ->.
case=> [k i |k]; first by rewrite leqn0 => /eqP ->.
rewrite ltnS => le_km [ // | i ] ; rewrite ltnS => le_ik /=.
congr (_ * _) ; apply: eq_bigr => l _.
by rewrite !IHm 1?(leq_trans (leq_ord _)) // (leq_trans le_ik).
Qed.
Lemma coef_inv0 (p: {poly K}) : coef_inv p 0 = p`_0 ^-1.
Proof. by rewrite /coef_inv /= -lock. Qed.
Lemma coef_invS (p: {poly K}) j : coef_inv p j.+1 =
-(p`_0 ^-1) * (\sum_(k < j.+1) p`_(j.+1 - k) * (coef_inv p k)).
Proof.
rewrite /coef_inv /= -lock; congr (_ * _) ; apply: eq_bigr => k _.
by rewrite coef_inv_recE // leq_ord.
Qed.
Definition unit_tfps : pred tfps := fun f => (f`_0 \in GRing.unit).
Definition inv_tfps f :=
if f \in unit_tfps then [tfps s => coef_inv f s] else f.
Fact coef_inv_tfps_subproof f i : f \in unit_tfps ->
(inv_tfps f)`_i =
if i > n then 0 else
if i == 0%N then f`_0 ^-1 else
- (f`_0 ^-1) * (\sum_(j < i) f`_(i - j) * (inv_tfps f)`_j).
Proof.
have [i_big|i_small] := ltnP; first by rewrite tfps_nth_default.
move=> f_unit; rewrite /inv_tfps f_unit !coef_tfps.
case: i => [|i] in i_small *; first by rewrite coef_inv0.
rewrite i_small coef_invS.
congr (_ * _); apply: eq_bigr => j _; rewrite coef_tfps ifT //.
by rewrite (leq_trans _ i_small) // leqW ?leq_ord.
Qed.
Fact nonunit_inv_tfps : {in [predC unit_tfps], inv_tfps =1 id}.
Proof. by move=> f; rewrite inE /inv_tfps /= => /negPf ->. Qed.
Fact unit_tfpsP f g : g * f = 1 -> unit_tfps f.
Proof.
move=> /val_eqP /eqP.
move/(congr1 (fun x => (val x)`_O)).
rewrite coef_modXn coef0M coefC eqxx /unit_tfps mulrC => h.
by apply/unitrPr; exists g`_0.
Qed.
Fact tfps_mulVr : {in unit_tfps, left_inverse 1 inv_tfps *%R}.
Proof.
move=> f f_unit; apply/val_inj; rewrite /inv_tfps f_unit /=.
apply/polyP => i; rewrite coef_modXn.
have [i_small | i_big] := ltnP; last first.
by rewrite coefC gtn_eqF // (leq_trans _ i_big).
rewrite coefC; case: i => [|i] in i_small *.
by rewrite coef0M coef_poly /= coef_inv0 mulVr.
rewrite coefM big_ord_recr coef_poly i_small subnn.
apply: canLR (addNKr _) _; rewrite addr0.
apply: canLR (mulrVK _) _; rewrite // mulrC mulrN -mulNr.
rewrite coef_invS; congr (_ * _); apply: eq_bigr => j _ /=.
by rewrite mulrC coef_poly (leq_trans _ i_small) 1?leqW.
Qed.
Definition tfps_comUnitRingMixin := ComUnitRingMixin
tfps_mulVr unit_tfpsP nonunit_inv_tfps.
Canonical unit_tfpsRingType := UnitRingType tfps tfps_comUnitRingMixin.
Lemma coef_inv_tfps f i : f \is a GRing.unit -> f^-1`_i =
if i > n then 0 else
if i == 0%N then f`_0 ^-1
else - (f`_0 ^-1) * (\sum_(j < i) f`_(i - j) * f^-1`_j).
Proof. exact: coef_inv_tfps_subproof. Qed.
Fact val_mul_tfps f g : val (f * g) = (val f) * (val g) %% 'X^n.+1.
Proof. by []. Qed.
Fact val_exp_tfps f (m : nat) :
val (f ^+ m) = (val f ^+ m) %% 'X^n.+1.
Proof.
elim: m => [|m ihm] //=; first by rewrite expr0 modCXn.
by rewrite exprS /= ihm modp_mul -exprS.
Qed.
Lemma hmul_tfpsr1 f : f *h 1 = Tfpsp n (f`_0)%:P.
Proof.
apply/val_inj/polyP => s; rewrite coef_tfps coef_Tfpsp !coefC.
by case: s => [|s]; rewrite ?mulr1 ?mulr0.
Qed.
Lemma hmul_tfps1r f : 1 *h f = Tfpsp n (f`_0)%:P.
Proof. by rewrite hmul_tfpsC hmul_tfpsr1. Qed.
Canonical tfps_comUnitRingType := [comUnitRingType of tfps].
Lemma unit_tfpsE f : (f \in GRing.unit) = (f`_0 != 0).
Proof. by rewrite qualifE /= /unit_tfps unitfE. Qed.
Fact nth0_mul_tfps f g : (f * g)`_0 = f`_0 * g`_0.
Proof. by rewrite coef_Tfpsp coef0M. Qed.
Fact nth0_inv f : (f ^-1)`_0 = (f`_0)^-1.
Proof.
have [f_unit|] := boolP (f \is a GRing.unit); first by rewrite coef_inv_tfps.
move=> fNunit; have := fNunit; rewrite -unitrV; move: fNunit.
by rewrite !unit_tfpsE !negbK => /eqP -> /eqP ->; rewrite invr0.
Qed.
Definition scale_tfps (c : K) f := Tfpsp n (c *: (val f)).
Fact scale_tfpsA a b f : scale_tfps a (scale_tfps b f) = scale_tfps (a * b) f.
Proof.
by apply/val_inj => /=; rewrite modp_scalel modp_mod -modp_scalel scalerA.
Qed.
Fact scale_1tfps : left_id (1 : K) scale_tfps.
Proof.
move=> x; apply/val_inj => /=.
by rewrite scale1r modp_small // size_polyXn ltnS ?size_tfps.
Qed.
Fact scale_tfpsDl f: {morph scale_tfps^~ f : a b / a + b}.
Proof.
move=> a b ; apply/val_inj => /=.
by rewrite scalerDl modp_add.
Qed.
Fact scale_tfpsDr (a : K) : {morph scale_tfps a : f g / f + g}.
Proof. by move=> f g; apply/val_inj => /=; rewrite scalerDr modp_add. Qed.
Fact scale_tfpsAl (a : K) f g : scale_tfps a (f * g) = scale_tfps a f * g.
Proof.
apply/val_inj => /=.
rewrite modp_scalel modp_small; last by rewrite ltn_modp expf_neq0 // polyX_eq0.
by rewrite [in RHS]mulrC modp_mul [in RHS]mulrC -modp_scalel -scalerAl.
Qed.
Definition tfps_lmodMixin := LmodMixin scale_tfpsA scale_1tfps
scale_tfpsDr scale_tfpsDl.
Canonical tfps_lmodType := Eval hnf in LmodType K tfps tfps_lmodMixin.
Canonical tfps_lalgType := Eval hnf in LalgType K tfps scale_tfpsAl.
Canonical tfps_algType := CommAlgType K tfps.
Canonical unit_tfpsAlgType := Eval hnf in [unitAlgType K of tfps].
Local Notation "c %:S" := (Tfpsp _ (c %:P)) (at level 2).
Fact onefE : 1 = 1 %:S.
Proof. by apply/val_inj => /=; rewrite modCXn. Qed.
End TruncatedPowerSeriesTheory.
Module Notations.
Local Open Scope tfps_scope.
Notation "{ 'tfps' K n }" := (tfps_of n (Phant K)) : tfps_scope.
Notation "[ 'tfps' s <= n => F ]" := (tfps_of_fun n (fun s => F)) : tfps_scope.
Notation "[ 'tfps' s => F ]" := [tfps s <= _ => F] : tfps_scope.
Notation "c %:S" := (Tfpsp _ (c %:P)) (at level 2) : tfps_scope.
Notation "f *h g" := (hmul_tfps f g) (at level 2) : tfps_scope.
Notation "f ^` () " := (deriv_tfps f) (at level 8) : tfps_scope.
End Notations.
Import Notations.
Local Open Scope tfps_scope.
Section MoreTruncatedPowerSeries.
Lemma Tfpsp_Tfpsp (K : fieldType) (m n : nat) (p : {poly K}) : m <= n ->
Tfpsp m (Tfpsp n p) = Tfpsp m p.
Proof. by move=> le_mn; apply/val_inj=> /=; rewrite modp_modp // dvdp_exp2l. Qed.
End MoreTruncatedPowerSeries.
Section Truncated_Powerseries.
Variables (K : fieldType) (n : nat).
Fact Tfpsp_is_additive : additive (@Tfpsp K n).
Proof. by move => f g; apply/val_inj => /=; rewrite modp_add modNp. Qed.
Canonical Tfpsp_additive := Additive Tfpsp_is_additive.
Lemma Tfpsp_is_multiplicative: multiplicative (@Tfpsp K n).
Proof.
split => [f g|]; last by apply/val_inj => /=; rewrite modCXn.
by apply/val_inj => /=; rewrite modp_mul [in RHS]mulrC modp_mul mulrC.
Qed.
Canonical Tfpsp_rmorphism := AddRMorphism Tfpsp_is_multiplicative.
Fact TfpspZ (c : K) (p : {poly K}): (Tfpsp n (c *: p))= c *:(Tfpsp n p).
Proof. by apply/val_inj => /=; rewrite -modp_scalel modp_mod. Qed.
Canonical Tfpsp_linear := AddLinear TfpspZ.
Canonical Tfpsp_lrmorphism := [lrmorphism of (Tfpsp n)].
(* tests *)
Fact tfps0 : Tfpsp n (0 : {poly K}) = 0.
Proof. by rewrite linear0. Qed.
Fact tfps1 : Tfpsp n (1 : {poly K}) = 1.
Proof. by rewrite rmorph1. Qed.
Lemma Tfpsp_is_unit (p : {poly K}) :
((Tfpsp n p) \is a GRing.unit) = (p`_0 != 0).
Proof. by rewrite unit_tfpsE nth0_Tfpsp. Qed.
Lemma TfpspE (p : {poly K}) : p %% 'X^ n.+1 = Tfpsp n p.
Proof. by apply/val_inj => /=. Qed.
End Truncated_Powerseries.
Section MapTfps.
Variables (K L : fieldType) (n : nat) (f : {rmorphism K -> L}).
Implicit Type g h : {tfps K n}.
Definition map_tfps g := Tfpsp n (map_poly f (val g)).
Lemma map_tfpsM g h : map_tfps (g * h) = (map_tfps g) * (map_tfps h).
Proof.
apply/val_inj => /=.
rewrite map_modp rmorphX /= map_polyX modp_mod rmorphM modp_mul.
by rewrite [in RHS]mulrC modp_mul mulrC.
Qed.
Fact map_tfps_is_additive : additive map_tfps.
Proof.
move => x y; apply/val_inj => /=.
by rewrite rmorphB /= modp_add modNp.
Qed.
Canonical map_tfps_additive := Additive map_tfps_is_additive.
Fact map_tfps_is_multiplicative : multiplicative map_tfps.
Proof.
split => [x y|]; first by rewrite map_tfpsM.
by apply/val_inj => /=; rewrite rmorph1 modCXn.
Qed.
Canonical map_tfps_rmorphism := AddRMorphism map_tfps_is_multiplicative.
Lemma map_tfpsZ (c : K) g : (map_tfps (c *: g)) = (f c) *: (map_tfps g).
Proof.
apply/val_inj => /=.
by rewrite map_modp rmorphX /= map_polyX linearZ [in LHS]modp_scalel.
Qed.
Lemma tfps_is_cst (g : tfps K 0%N) : g = (g`_0) %:S.
Proof.
by apply/val_inj=> /=; rewrite modCXn //; apply: size1_polyC; rewrite size_tfps.
Qed.
(* used once; to remove ? *)
Lemma tfpsC_mul : {morph (fun x => (x%:S : {tfps K n})) : a b / a * b >-> a * b}.
Proof.
move=> a b; apply/val_inj => /=; rewrite polyC_mul modp_mul.
by rewrite [in RHS]mulrC modp_mul mulrC.
Qed.
Canonical map_tfps_linear := let R := ({tfps K n}) in
AddLinear (map_tfpsZ : scalable_for (f \; *:%R) map_tfps).
Canonical map_tfps_lrmorphism := [lrmorphism of map_tfps].
(* tests *)
Fact test_map_tfps0 : map_tfps 0 = 0.
Proof. by rewrite linear0. Qed.
Fact test_map_tfpsD g h : map_tfps (g + h) = (map_tfps g) + (map_tfps h).
Proof. by rewrite linearD. Qed.
Lemma Tfps_map_poly (p : {poly K}) :
@Tfpsp L n (p ^ f) = map_tfps (Tfpsp n p).
Proof. by apply/val_inj => /=; rewrite map_modp map_polyXn modp_mod. Qed.
Local Notation "g ^ f" := (map_tfps g) : tfps_scope.
Lemma map_hmul g h : (g *h h) ^ f = (g ^ f) *h (h ^ f).
Proof.
apply/val_inj => /=; rewrite -polyP => i.
rewrite coef_modXn coef_map 2!coef_poly !coef_modXn.
by case: (i < n.+1) => //=; rewrite rmorphM !coef_map.
Qed.
Lemma map_tfps_injective : injective map_tfps.
Proof.
move => x y; move/val_eqP => /=.
rewrite ?(modp_small, (size_polyXn, size_map_poly, ltnS, size_tfps)) //.
by move/val_eqP => H; move: (map_poly_inj f H); apply/val_inj.
Qed.
End MapTfps.
Section IdFun.
Lemma map_poly_idfun (R : ringType) : map_poly (@idfun R) =1 @idfun {poly R}.
Proof. exact: coefK. Qed.
Lemma idfun_injective A : injective (@idfun A). Proof. done. Qed.
Canonical idfun_is_injmorphism (A : ringType) :=
InjMorphism (@idfun_injective A).
End IdFun.
Lemma map_powerseries_idfun (K : fieldType) (m : nat) :
map_tfps [rmorphism of (@idfun K)] =1 @idfun ({tfps K m}).
Proof.
move => p; apply: val_inj => /=.
by rewrite map_poly_idfun modp_small // size_polyXn ltnS size_tfps.
Qed.
Section Coefficient01.
Variables (K : fieldType) (n : nat).
Implicit Types (f g : {tfps K n}).
Definition coef0_is_0 : pred_class := fun f : {tfps K n} => f`_0 == 0.
Lemma coef0_is_0E f : (f \in coef0_is_0) = (f`_0 == 0).
Proof. by rewrite -topredE. Qed.
Definition coef0_is_1 : pred_class := fun f : {tfps K n} => f`_0 == 1.
Lemma coef0_is_1E f : (f \in coef0_is_1) = (f`_0 == 1).
Proof. by rewrite -topredE. Qed.
Definition exp f :=
if f \notin coef0_is_0 then 0 else
Tfpsp n (\sum_(i < n.+1) ((i`! %:R) ^-1) *: (val f ^+i)).
Definition log f :=
if f \notin coef0_is_1 then 0 else
Tfpsp n (- \sum_(1 <= i < n.+1) ((i %:R) ^-1) *: ((1 - val f) ^+i)).
Fact c0_is_0_idealr : idealr_closed coef0_is_0.
Proof.
split => [|| a p q ]; rewrite ?coef0_is_0E ?coefC ?eqxx ?oner_eq0 //.
move=> /eqP p0_eq0 /eqP q0_eq0.
by rewrite coefD q0_eq0 addr0 nth0_mul_tfps p0_eq0 mulr0.
Qed.
Fact c0_is_0_key : pred_key coef0_is_0. Proof. by []. Qed.
Canonical c0_is_0_keyed := KeyedPred c0_is_0_key.
Canonical c0_is_0_opprPred := OpprPred c0_is_0_idealr.
Canonical c0_is_0_addrPred := AddrPred c0_is_0_idealr.
Canonical c0_is_0_zmodPred := ZmodPred c0_is_0_idealr.
Definition c0_is_0_ntideal := idealr_closed_nontrivial c0_is_0_idealr.
Canonical c0_is_0_ideal := MkIdeal c0_is_0_zmodPred c0_is_0_ntideal.
Fact c0_is_0_prime : prime_idealr_closed coef0_is_0.
Proof.
by move => x y; rewrite -!topredE /= /coef0_is_0 nth0_mul_tfps mulf_eq0.
Qed.
Canonical coef0_is_0_pideal := MkPrimeIdeal c0_is_0_ideal c0_is_0_prime.
(* tests *)
Example zero_in_coef0_is_0 : 0 \in coef0_is_0.
Proof. by rewrite rpred0. Qed.
Example coef0_is_0D f g :
f \in coef0_is_0 -> g \in coef0_is_0 -> f + g \in coef0_is_0.
Proof. by move=> hf hg; rewrite rpredD. Qed.
Example coef0_os_0N f : f \in coef0_is_0 -> (-f) \in coef0_is_0.
Proof. by move=> hf; rewrite rpredN. Qed.
Example coef0_is_0_prime_test f g :
f * g \in coef0_is_0 -> (f \in coef0_is_0) || (g \in coef0_is_0).
Proof. by rewrite prime_idealrM. Qed.
Fact mulr_closed_c0_is_1 : mulr_closed coef0_is_1.
Proof.
split=> [|x y]; rewrite !coef0_is_1E ?coefC //.
by rewrite nth0_mul_tfps; move/eqP ->; move/eqP ->; rewrite mul1r.
Qed.
Fact invr_closed_c0_is_1 : invr_closed coef0_is_1.
Proof.
move=> f; rewrite !coef0_is_1E nth0_inv; move/eqP ->.
by rewrite invr1.
Qed.
Fact c0_is_1_key : pred_key coef0_is_1. Proof. by []. Qed.
Canonical c0_is_1_keyed := KeyedPred c0_is_1_key.
Canonical c0_is_1_MulrPred := MulrPred mulr_closed_c0_is_1.
Canonical c0_is_1_DivrPred := DivrPred invr_closed_c0_is_1.
(* tests *)
Example one_in_coef0_is_1 : 1 \in coef0_is_1.
Proof. by rewrite rpred1. Qed.
Example coef0_is_1M f g :
f \in coef0_is_1 -> g \in coef0_is_1 -> f * g \in coef0_is_1.
Proof. by move=> hf hg; rewrite rpredM. Qed.
Example coef0_is_1V f : f \in coef0_is_1 -> f^-1 \in coef0_is_1.
Proof. by move=> hf; rewrite rpredVr. Qed.
Example coef0_is_1_div f g :
f \in coef0_is_1 -> g \in coef0_is_1 -> f / g \in coef0_is_1.
Proof. by move=> hf hg; rewrite rpred_div. Qed.
End Coefficient01.
Section DivisionByX.
Variable (K : fieldType).
Definition divfX (m : nat) (f : {tfps K m}) := Tfpsp m.-1 (f %/ 'X).
Lemma divfXE (m : nat) (f : {tfps K m}) :
f \in (@coef0_is_0 K m) -> divfX f = [tfps i => f`_i.+1].
Proof.
move/eqP/polyXP; rewrite dvdp_eq /divfX; move/eqP => h.
rewrite [in RHS]h; apply/eq_tfps => i.
by rewrite coef_poly coef_modXn coefMX.
Qed.
End DivisionByX.
Lemma map_tfps_divfX (K L : fieldType) (f : {rmorphism K -> L})
(m : nat) (g : tfps K m) :
map_tfps f (divfX g) = divfX (map_tfps f g).
Proof.
apply/val_inj => /=.
rewrite map_modp rmorphX /= map_polyX modp_mod map_divp map_polyX.
by rewrite [(_ ^ _ %% _)]modp_small // size_polyXn size_map_poly ltnS size_tfps.
Qed.
Section Derivative.
Variables (K : fieldType) (n : nat).
(* can be generalized with R ? *)
Lemma deriv_modp (p : {poly K}) :
((p %% 'X ^+ n.+1)^`() = (p ^`()) %% 'X ^+ n)%R.
Proof.
rewrite {2}[p](divp_eq _ ('X^n.+1)) derivD derivM !modp_add.
rewrite -addrA [X in X + _]modp_eq0 ; last first.
rewrite dvdp_mull // dvdp_Pexp2l ?leqnSn // size_polyX //.
rewrite add0r [X in X + _]modp_eq0 ; last first.
rewrite dvdp_mull // derivXn /= -scaler_nat.
have [->|Sm_neq0] := eqVneq (n.+1)%:R (0 : K).
by rewrite scale0r dvdp0.
by rewrite dvdp_scaler.
rewrite add0r [RHS]modp_small // size_polyXn.
have [-> | p_modXSm_neq0] := eqVneq (p %% 'X^n.+1) 0.
+ by rewrite deriv0 size_poly0.
+ by rewrite (leq_trans _ (leq_modpXn n.+1 p)) // lt_size_deriv.
Qed.
Fact mod_deriv_tfps (m : nat) (f : {tfps K n}) : n <= m ->
(val f)^`() %% 'X^m = ((val f)^`())%R.
Proof.
move => leq_nm; rewrite modp_small // size_polyXn ltnS.
rewrite (leq_trans _ leq_nm) // (leq_trans (leq_size_deriv _)) //.
have [->//|sfN0] := eqVneq (size (val f)) 0%N.
by rewrite -ltnS prednK ?size_tfps // lt0n.
Qed.
Lemma deriv_tfpsE (f : {tfps K n}) : deriv_tfps f = Tfpsp n.-1 (val f)^`().
Proof.
by apply/val_inj; apply/polyP => i; rewrite coef_poly coef_modXn coef_deriv.
Qed.
(* Local Notation "f ^` () " := (deriv_tfps f) (at level 8) : tfps_scope. *)
Fact deriv_tfps0 : (0 : {tfps K n}) ^`() = 0.
Proof.
apply/val_inj => /=; rewrite polyseq0; apply/polyP => i.
by rewrite coef_poly coefC mul0rn; case: (_ < _); case: i.
Qed.
(* can I simplify this proof ? *)
Lemma deriv_tfpsC (c : K) : c %:S ^`() = 0 :> {tfps _ n.-1}.
Proof.
apply/val_inj => /=; apply/polyP => i.
rewrite modp_small; last first.
by rewrite size_polyC size_polyXn (leq_ltn_trans (leq_b1 _)).
rewrite coef_poly coefC if_same polyseqC.
by case: (_ < _) => //; case: (_ == _); rewrite /= ?nth_nil mul0rn.
Qed.
Fact deriv_tfpsD (f g : {tfps K n}) : (f + g)^`() = f^`()%tfps + g^`()%tfps.
Proof.
apply/val_inj; apply/polyP => i; rewrite coefD !coef_poly coefD.
by case: (_ < _) => //=; rewrite ?addr0 // -mulrnDl.
Qed.
Fact deriv_tfpsZ (c : K) (f : {tfps K n}) : (c *: f) ^`() = c *: f ^`()%tfps.
Proof.
apply/val_inj; apply/polyP => i.
rewrite coef_poly coef_modXn !coefZ coef_modXn !coefZ coef_poly.
congr if_expr; rewrite [in RHS]fun_if mulr0 ltnS.
rewrite [LHS](@fun_if _ _ (fun x => x *+i.+1)) mul0rn.
move: f; case: n => [p|m p]; last by congr if_expr; rewrite mulrnAr.
by rewrite [p]tfps_is_cst coef_Tfpsp mul0rn mulr0 if_same.
Qed.
Fact deriv_tfps_is_linear : linear (@deriv_tfps K n).
Proof. by move => c f g; rewrite deriv_tfpsD deriv_tfpsZ. Qed.
Canonical deriv_tfps_additive := Additive deriv_tfps_is_linear.
Canonical deriv_tfps_linear := Linear deriv_tfps_is_linear.
(* tests *)
Example test_deriv_tfps0 : 0 ^`() = 0 :> {tfps K n.-1}.
Proof. by rewrite linear0. Qed.
Example test_deriv_tfpsD (f g : {tfps K n}) :
(f + g)^`()%tfps = f^`()%tfps + g^`()%tfps.
Proof. by rewrite linearD. Qed.
End Derivative.
Section MoreDerivative.
Variable (K : fieldType) (m : nat).
Hypothesis char_K_is_zero : [char K] =i pred0.
Lemma pw_cst (f : {tfps K m}) : f ^` () = 0 -> {c : K | f = c %:S}.
Proof.
move: f; case: m => [f _| n f]; first by rewrite [f]tfps_is_cst; exists (f`_0).
rewrite deriv_tfpsE ; move/eqP ; rewrite -val_eqE /= => /eqP.
rewrite modp_small => [derivp_eq0|]; last first.
+ rewrite size_polyXn.
have [->|fN0] := eqVneq f 0; first by rewrite linear0 size_poly0.
by rewrite (leq_trans (lt_size_deriv _)) // size_tfps.
+ move: (p_cst char_K_is_zero derivp_eq0) => [c Hc].
by exists c; apply/val_inj => /=; rewrite modCXn.
Qed.
Lemma pw_eq0 (f : {tfps K m}) :
f ^` () = 0 -> {x : K | (val f).[x] = 0} -> f = 0.
Proof.
rewrite deriv_tfpsE /=; move/eqP ; rewrite -val_eqE /=.
have [-> _ _ // |fN0] := eqVneq f 0.
rewrite modp_small ?size_polyXn ?(leq_trans (lt_size_deriv _)) ?size_tfps //.
move/eqP => derivp_eq0; move: (p_cst char_K_is_zero derivp_eq0) => [c Hc].
rewrite Hc; move => [x hx]; rewrite hornerC in hx.
by apply/val_inj => /=; rewrite Hc hx.
by rewrite (leq_trans (size_tfps _)) //; clear fN0 f; case: m => [|n].
Qed.
Lemma pw_eq (f g : {tfps K m}) :
f ^` () = g ^` () -> {x : K | (val f).[x] = (val g).[x]} -> f = g.
Proof.
move => H [x Hx].
apply/eqP ; rewrite -subr_eq0 ; apply/eqP.
apply: pw_eq0; first by rewrite linearB /= H subrr.
by exists x ; rewrite -horner_evalE rmorphB /= horner_evalE Hx subrr.
Qed.
Lemma deriv_Tfps0p (f : {tfps K 0}) : f ^` () = 0.
Proof.
by rewrite [f]tfps_is_cst deriv_tfpsE deriv_modp derivC mod0p rmorph0.
Qed.
Lemma deriv_tfpsM (f g : {tfps K m}) :
(f * g) ^`() = f ^`()%tfps * (Tfpsp m.-1 g) + (Tfpsp m.-1 f) * g ^`()%tfps.
Proof.
move : f g; case: m => /= [f g | n f g].
rewrite [f]tfps_is_cst [g]tfps_is_cst -tfpsC_mul !deriv_tfpsC mul0r mulr0.
by rewrite addr0.
apply/val_inj; rewrite !deriv_tfpsE //=.
rewrite deriv_modp derivM modp_mul modp_mul2 -modp_add modp_mod !modp_add.
by rewrite !modp_mul; congr (_ + _); rewrite mulrC [in RHS]mulrC modp_mul.
Qed.
Fact TfpsVf n p (f : {tfps K p}) :
n <= p ->
Tfpsp n (f^-1) = (Tfpsp n f) ^-1.
Proof.
move=> leq_mn.
have [/eqP p0_eq0|p0_neq0] := eqVneq f`_0 0.
by rewrite ?(invr_out, unit_tfpsE, nth0_Tfpsp, negbK).
apply: (@mulrI _ (Tfpsp _ f)); rewrite ?divrr ?(unit_tfpsE, nth0_Tfpsp) //.