Added Real_Asymp package
authorManuel Eberl <eberlm@in.tum.de>
Sun Jul 15 14:46:57 2018 +0200 (12 months ago)
changeset 68630c55f6f0b3854
parent 68629 f36858fdf768
child 68637 ec8c7c9459e0
Added Real_Asymp package
CONTRIBUTORS
NEWS
src/Doc/ROOT
src/Doc/Real_Asymp/Real_Asymp_Doc.thy
src/Doc/Real_Asymp/document/root.tex
src/Doc/Real_Asymp/document/style.sty
src/HOL/ROOT
src/HOL/Real_Asymp/Eventuallize.thy
src/HOL/Real_Asymp/Inst_Existentials.thy
src/HOL/Real_Asymp/Lazy_Eval.thy
src/HOL/Real_Asymp/Multiseries_Expansion.thy
src/HOL/Real_Asymp/Multiseries_Expansion_Bounds.thy
src/HOL/Real_Asymp/Real_Asymp.thy
src/HOL/Real_Asymp/Real_Asymp_Approx.thy
src/HOL/Real_Asymp/Real_Asymp_Examples.thy
src/HOL/Real_Asymp/asymptotic_basis.ML
src/HOL/Real_Asymp/exp_log_expression.ML
src/HOL/Real_Asymp/expansion_interface.ML
src/HOL/Real_Asymp/inst_existentials.ML
src/HOL/Real_Asymp/lazy_eval.ML
src/HOL/Real_Asymp/multiseries_expansion.ML
src/HOL/Real_Asymp/multiseries_expansion_bounds.ML
src/HOL/Real_Asymp/real_asymp.ML
src/HOL/Real_Asymp/real_asymp_diag.ML
     1.1 --- a/CONTRIBUTORS	Sun Jul 15 01:14:04 2018 +0100
     1.2 +++ b/CONTRIBUTORS	Sun Jul 15 14:46:57 2018 +0200
     1.3 @@ -6,6 +6,10 @@
     1.4  Contributions to Isabelle2018
     1.5  -----------------------------
     1.6  
     1.7 +* July 2018: Manuel Eberl
     1.8 +  "real_asymp" proof method for automatic proofs of real limits, "Big-O"
     1.9 +  statements, etc.
    1.10 +
    1.11  * June 2018: Fabian Immler
    1.12    More tool support for HOL-Types_To_Sets.
    1.13  
     2.1 --- a/NEWS	Sun Jul 15 01:14:04 2018 +0100
     2.2 +++ b/NEWS	Sun Jul 15 14:46:57 2018 +0200
     2.3 @@ -231,6 +231,9 @@
     2.4  
     2.5  *** HOL ***
     2.6  
     2.7 +* New proof method "real_asymp" to prove asymptotics or real-valued 
     2.8 +  functions (limits, "Big-O", etc.) automatically.
     2.9 +
    2.10  * Sledgehammer: bundled version of "vampire" (for non-commercial users)
    2.11  helps to avoid fragility of "remote_vampire" service.
    2.12  
     3.1 --- a/src/Doc/ROOT	Sun Jul 15 01:14:04 2018 +0100
     3.2 +++ b/src/Doc/ROOT	Sun Jul 15 14:46:57 2018 +0200
     3.3 @@ -359,6 +359,20 @@
     3.4      "root.tex"
     3.5      "svmono.cls"
     3.6  
     3.7 +session Real_Asymp (doc) in "Real_Asymp" = "HOL-Real_Asymp" +
     3.8 +  theories
     3.9 +    Real_Asymp_Doc
    3.10 +  document_files (in "..")
    3.11 +    "prepare_document"
    3.12 +    "pdfsetup.sty"
    3.13 +    "iman.sty"
    3.14 +    "extra.sty"
    3.15 +    "isar.sty"
    3.16 +    "manual.bib"
    3.17 +  document_files
    3.18 +    "root.tex"
    3.19 +    "style.sty"
    3.20 +
    3.21  session Sledgehammer (doc) in "Sledgehammer" = Pure +
    3.22    options [document_variants = "sledgehammer"]
    3.23    document_files (in "..")
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/Doc/Real_Asymp/Real_Asymp_Doc.thy	Sun Jul 15 14:46:57 2018 +0200
     4.3 @@ -0,0 +1,286 @@
     4.4 +(*<*)
     4.5 +theory Real_Asymp_Doc
     4.6 +  imports "HOL-Real_Asymp.Real_Asymp"
     4.7 +begin
     4.8 +
     4.9 +ML_file \<open>../antiquote_setup.ML\<close>
    4.10 +(*>*)
    4.11 +
    4.12 +section \<open>Introduction\<close>
    4.13 +
    4.14 +text \<open>
    4.15 +  This document describes the \<^verbatim>\<open>real_asymp\<close> package that provides a number of tools
    4.16 +  related to the asymptotics of real-valued functions. These tools are:
    4.17 +
    4.18 +    \<^item> The @{method real_asymp} method to prove limits, statements involving Landau symbols
    4.19 +      (`Big-O' etc.), and asymptotic equivalence (\<open>\<sim>\<close>)
    4.20 +
    4.21 +    \<^item> The @{command real_limit} command to compute the limit of a real-valued function at a
    4.22 +      certain point
    4.23 +
    4.24 +    \<^item> The @{command real_expansion} command to compute the asymptotic expansion of a
    4.25 +      real-valued function at a certain point
    4.26 +
    4.27 +  These three tools will be described in the following sections.
    4.28 +\<close>
    4.29 +
    4.30 +section \<open>Supported Operations\<close>
    4.31 +
    4.32 +text \<open>
    4.33 +  The \<^verbatim>\<open>real_asymp\<close> package fully supports the following operations:
    4.34 +
    4.35 +    \<^item> Basic arithmetic (addition, subtraction, multiplication, division)
    4.36 +
    4.37 +    \<^item> Powers with constant natural exponent
    4.38 +
    4.39 +    \<^item> @{term exp}, @{term ln}, @{term log}, @{term sqrt}, @{term "root k"} (for a constant k)
    4.40 +  
    4.41 +    \<^item> @{term sin}, @{term cos}, @{term tan} at finite points
    4.42 +
    4.43 +    \<^item> @{term sinh}, @{term cosh}, @{term tanh}
    4.44 +
    4.45 +    \<^item> @{term min}, @{term max}, @{term abs}
    4.46 +
    4.47 +  Additionally, the following operations are supported in a `best effort' fashion using asymptotic
    4.48 +  upper/lower bounds:
    4.49 +
    4.50 +    \<^item> Powers with variable natural exponent
    4.51 +
    4.52 +    \<^item> @{term sin} and @{term cos} at \<open>\<plusminus>\<infinity>\<close>
    4.53 +
    4.54 +    \<^item> @{term floor}, @{term ceiling}, @{term frac}, and \<open>mod\<close>
    4.55 +
    4.56 +  Additionally, the @{term arctan} function is partially supported. The method may fail when
    4.57 +  the argument to @{term arctan} contains functions of different order of growth.
    4.58 +\<close>
    4.59 +
    4.60 +
    4.61 +section \<open>Proving Limits and Asymptotic Properties\<close>
    4.62 +
    4.63 +text \<open>
    4.64 +  \[
    4.65 +    @{method_def (HOL) real_asymp} : \<open>method\<close>
    4.66 +  \]
    4.67 +
    4.68 +  @{rail \<open>
    4.69 +    @@{method (HOL) real_asymp} opt? (@{syntax simpmod} * )
    4.70 +    ;
    4.71 +    opt: '(' ('verbose' | 'fallback' ) ')'
    4.72 +    ;
    4.73 +    @{syntax_def simpmod}: ('add' | 'del' | 'only' | 'split' (() | '!' | 'del') |
    4.74 +      'cong' (() | 'add' | 'del')) ':' @{syntax thms}
    4.75 +  \<close>}
    4.76 +\<close>
    4.77 +
    4.78 +text \<open>
    4.79 +  The @{method real_asymp} method is a semi-automatic proof method for proving certain statements
    4.80 +  related to the asymptotic behaviour of real-valued functions. In the following, let \<open>f\<close> and \<open>g\<close>
    4.81 +  be functions of type @{typ "real \<Rightarrow> real"} and \<open>F\<close> and \<open>G\<close> real filters.
    4.82 +
    4.83 +  The functions \<open>f\<close> and \<open>g\<close> can be built from the operations mentioned before and may contain free 
    4.84 +  variables. The filters \<open>F\<close> and \<open>G\<close> can be either \<open>\<plusminus>\<infinity>\<close> or a finite point in \<open>\<real>\<close>, possibly
    4.85 +  with approach from the left or from the right.
    4.86 +
    4.87 +  The class of statements that is supported by @{method real_asymp} then consists of:
    4.88 +
    4.89 +    \<^item> Limits, i.\,e.\ @{prop "filterlim f F G"}
    4.90 +
    4.91 +    \<^item> Landau symbols, i.\,e.\ @{prop "f \<in> O[F](g)"} and analogously for \<^emph>\<open>o\<close>, \<open>\<Omega>\<close>, \<open>\<omega>\<close>, \<open>\<Theta>\<close>
    4.92 +
    4.93 +    \<^item> Asymptotic equivalence, i.\,e.\ @{prop "f \<sim>[F] g"}
    4.94 +
    4.95 +    \<^item> Asymptotic inequalities, i.\,e.\ @{prop "eventually (\<lambda>x. f x \<le> g x) F"}
    4.96 +
    4.97 +  For typical problems arising in practice that do not contain free variables, @{method real_asymp}
    4.98 +  tends to succeed fully automatically within fractions of seconds, e.\,g.:
    4.99 +\<close>
   4.100 +
   4.101 +lemma \<open>filterlim (\<lambda>x::real. (1 + 1 / x) powr x) (nhds (exp 1)) at_top\<close>
   4.102 +  by real_asymp
   4.103 +
   4.104 +text \<open>
   4.105 +  What makes the method \<^emph>\<open>semi-automatic\<close> is the fact that it has to internally determine the 
   4.106 +  sign of real-valued constants and identical zeroness of real-valued functions, and while the
   4.107 +  internal heuristics for this work very well most of the time, there are situations where the 
   4.108 +  method fails to determine the sign of a constant, in which case the user needs to go back and
   4.109 +  supply more information about the sign of that constant in order to get a result.
   4.110 +
   4.111 +  A simple example is the following:
   4.112 +\<close>
   4.113 +(*<*)
   4.114 +experiment
   4.115 +  fixes a :: real
   4.116 +begin
   4.117 +(*>*)
   4.118 +lemma \<open>filterlim (\<lambda>x::real. exp (a * x)) at_top at_top\<close>
   4.119 +oops
   4.120 +
   4.121 +text \<open>
   4.122 +  Here, @{method real_asymp} outputs an error message stating that it could not determine the
   4.123 +  sign of the free variable @{term "a :: real"}. In this case, the user must add the assumption
   4.124 +  \<open>a > 0\<close> and give it to @{method real_asymp}.
   4.125 +\<close>
   4.126 +lemma
   4.127 +  assumes \<open>a > 0\<close>
   4.128 +  shows   \<open>filterlim (\<lambda>x::real. exp (a * x)) at_top at_top\<close>
   4.129 +  using assms by real_asymp
   4.130 +(*<*)
   4.131 +end
   4.132 +(*>*)
   4.133 +text \<open>
   4.134 +  Additional modifications to the simpset that is used for determining signs can also be made
   4.135 +  with \<open>simp add:\<close> modifiers etc.\ in the same way as when using the @{method simp} method directly.
   4.136 +
   4.137 +  The same situation can also occur without free variables if the constant in question is a
   4.138 +  complicated expression that the simplifier does not know enough ebout,
   4.139 +  e.\,g.\ @{term "pi - exp 1"}.
   4.140 +
   4.141 +  In order to trace problems with sign determination, the \<open>(verbose)\<close> option can be passed to
   4.142 +  @{method real_asymp}. It will then print a detailed error message whenever it encounters
   4.143 +  a sign determination problem that it cannot solve.
   4.144 +
   4.145 +  The \<open>(fallback)\<close> flag causes the method not to use asymptotic interval arithmetic, but only
   4.146 +  the much simpler core mechanism of computing a single Multiseries expansion for the input
   4.147 +  function. There should normally be no need to use this flag; however, the core part of the 
   4.148 +  code has been tested much more rigorously than the asymptotic interval part. In case there 
   4.149 +  is some implementation problem with it for a problem that can be solved without it, the 
   4.150 +  \<open>(fallback)\<close> option can be used until that problem is resolved.
   4.151 +\<close>
   4.152 +
   4.153 +
   4.154 +
   4.155 +section \<open>Diagnostic Commands\<close>
   4.156 +
   4.157 +text \<open>
   4.158 +  \[\begin{array}{rcl}
   4.159 +    @{command_def (HOL) real_limit} & : & \<open>context \<rightarrow>\<close> \\
   4.160 +    @{command_def (HOL) real_expansion} & : & \<open>context \<rightarrow>\<close>
   4.161 +  \end{array}\]
   4.162 +
   4.163 +  @{rail \<open>
   4.164 +    @@{command (HOL) real_limit} (limitopt*)
   4.165 +    ;
   4.166 +    @@{command (HOL) real_expansion} (expansionopt*)
   4.167 +    ;
   4.168 +    limitopt : ('limit' ':' @{syntax term}) | ('facts' ':' @{syntax thms})
   4.169 +    ;
   4.170 +    expansionopt : 
   4.171 +        ('limit' ':' @{syntax term}) |
   4.172 +        ('terms' ':' @{syntax nat} ('(' 'strict' ')') ?) |
   4.173 +        ('facts' ':' @{syntax thms})
   4.174 +  \<close>}
   4.175 +
   4.176 +    \<^descr>@{command real_limit} computes the limit of the given function \<open>f(x)\<close> for as \<open>x\<close> tends
   4.177 +    to the specified limit point. Additional facts can be provided with the \<open>facts\<close> option, 
   4.178 +    similarly to the @{command using} command with @{method real_asymp}. The limit point given
   4.179 +    by the \<open>limit\<close> option must be one of the filters @{term "at_top"}, @{term "at_bot"}, 
   4.180 +    @{term "at_left"}, or @{term "at_right"}. If no limit point is given, @{term "at_top"} is used
   4.181 +    by default.
   4.182 +  
   4.183 +    \<^medskip>
   4.184 +    The output of @{command real_limit} can be \<open>\<infinity>\<close>, \<open>-\<infinity>\<close>, \<open>\<plusminus>\<infinity>\<close>, \<open>c\<close> (for some real constant \<open>c\<close>),
   4.185 +    \<open>0\<^sup>+\<close>, or \<open>0\<^sup>-\<close>. The \<open>+\<close> and \<open>-\<close> in the last case indicate whether the approach is from above
   4.186 +    or from below (corresponding to @{term "at_right (0::real)"} and @{term "at_left (0::real)"}); 
   4.187 +    for technical reasons, this information is currently not displayed if the limit is not 0.
   4.188 +  
   4.189 +    \<^medskip>
   4.190 +    If the given function does not tend to a definite limit (e.\,g.\ @{term "sin x"} for \<open>x \<rightarrow> \<infinity>\<close>),
   4.191 +    the command might nevertheless succeed to compute an asymptotic upper and/or lower bound and
   4.192 +    display the limits of these bounds instead.
   4.193 +
   4.194 +    \<^descr>@{command real_expansion} works similarly to @{command real_limit}, but displays the first few
   4.195 +    terms of the asymptotic multiseries expansion of the given function at the given limit point 
   4.196 +    and the order of growth of the remainder term.
   4.197 +  
   4.198 +    In addition to the options already explained for the @{command real_limit} command, it takes
   4.199 +    an additional option \<open>terms\<close> that controls how many of the leading terms of the expansion are
   4.200 +    printed. If the \<open>(strict)\<close> modifier is passed to the \<open>terms option\<close>, terms whose coefficient is
   4.201 +    0 are dropped from the output and do not count to the number of terms to be output.
   4.202 +  
   4.203 +    \<^medskip>
   4.204 +    By default, the first three terms are output and the \<open>strict\<close> option is disabled.
   4.205 +
   4.206 +  Note that these two commands are intended for diagnostic use only. While the central part
   4.207 +  of their implementation – finding a multiseries expansion and reading off the limit – are the
   4.208 +  same as in the @{method real_asymp} method and therefore trustworthy, there is a small amount
   4.209 +  of unverified code involved in pre-processing and printing (e.\,g.\ for reducing all the
   4.210 +  different options for the \<open>limit\<close> option to the @{term at_top} case).
   4.211 +\<close>
   4.212 +
   4.213 +
   4.214 +section \<open>Extensibility\<close>
   4.215 +
   4.216 +subsection \<open>Basic fact collections\<close>
   4.217 +
   4.218 +text \<open>
   4.219 +  The easiest way to add support for additional operations is to add corresponding facts
   4.220 +  to one of the following fact collections. However, this only works for particularly simple cases.
   4.221 +
   4.222 +    \<^descr>@{thm [source] real_asymp_reify_simps} specifies a list of (unconditional) equations that are 
   4.223 +     unfolded as a first step of @{method real_asymp} and the related commands. This can be used to 
   4.224 +     add support for operations that can be represented easily by other operations that are already
   4.225 +     supported, such as @{term sinh}, which is equal to @{term "\<lambda>x. (exp x - exp (-x)) / 2"}.
   4.226 +
   4.227 +    \<^descr>@{thm [source] real_asymp_nat_reify} and @{thm [source] real_asymp_int_reify} is used to
   4.228 +     convert operations on natural numbers or integers to operations on real numbers. This enables
   4.229 +     @{method real_asymp} to also work on functions that return a natural number or an integer.
   4.230 +\<close>
   4.231 +
   4.232 +subsection \<open>Expanding Custom Operations\<close>
   4.233 +
   4.234 +text \<open>
   4.235 +  Support for some non-trivial new operation \<open>f(x\<^sub>1, \<dots>, x\<^sub>n)\<close> can be added dynamically at any
   4.236 +  time, but it involves writing ML code and involves a significant amount of effort, especially
   4.237 +  when the function has essential singularities.
   4.238 +
   4.239 +  The first step is to write an ML function that takes as arguments
   4.240 +    \<^item> the expansion context
   4.241 +    \<^item> the term \<open>t\<close> to expand (which will be of the form \<open>f(g\<^sub>1(x), \<dots>, g\<^sub>n(x))\<close>)
   4.242 +    \<^item> a list of \<open>n\<close> theorems of the form @{prop "(g\<^sub>i expands_to G\<^sub>i) bs"}
   4.243 +    \<^item> the current basis \<open>bs\<close>
   4.244 +  and returns a theorem of the form @{prop "(t expands_to F) bs'"} and a new basis \<open>bs'\<close> which 
   4.245 +  must be a superset of the original basis.
   4.246 +
   4.247 +  This function must then be registered as a handler for the operation by proving a vacuous lemma
   4.248 +  of the form @{prop "REAL_ASYMP_CUSTOM f"} (which is only used for tagging) and passing that
   4.249 +  lemma and the expansion function to @{ML [source] Exp_Log_Expression.register_custom_from_thm}
   4.250 +  in a @{command local_setup} invocation.
   4.251 +
   4.252 +  If the expansion produced by the handler function contains new definitions, corresponding 
   4.253 +  evaluation equations must be added to the fact collection @{thm [source] real_asymp_eval_eqs}.
   4.254 +  These equations must have the form \<open>h p\<^sub>1 \<dots> p\<^sub>m = rhs\<close> where \<open>h\<close> must be a constant of arity \<open>m\<close>
   4.255 +  (i.\,e.\ the function on the left-hand side must be fully applied) and the \<open>p\<^sub>i\<close> can be patterns
   4.256 +  involving \<open>constructors\<close>.
   4.257 +
   4.258 +  New constructors for this pattern matching can be registered by adding a theorem of the form
   4.259 +  @{prop "REAL_ASYMP_EVAL_CONSTRUCTOR c"} to the fact collection
   4.260 +  @{thm [source] exp_log_eval_constructor}, but this should be quite rare in practice.
   4.261 +
   4.262 +  \<^medskip>
   4.263 +  Note that there is currently no way to add support for custom operations in connection with
   4.264 +  `oscillating' terms. The above mechanism only works if all arguments of the new operation have
   4.265 +  an exact multiseries expansion.
   4.266 +\<close>
   4.267 +
   4.268 +
   4.269 +subsection \<open>Extending the Sign Oracle\<close>
   4.270 +
   4.271 +text \<open>
   4.272 +  By default, the \<^verbatim>\<open>real_asymp\<close> package uses the simplifier with the given simpset and facts
   4.273 +  in order to determine the sign of real constants. This is done by invoking the simplifier
   4.274 +  on goals like \<open>c = 0\<close>, \<open>c \<noteq> 0\<close>, \<open>c > 0\<close>, or \<open>c < 0\<close> or some subset thereof, depending on the
   4.275 +  context.
   4.276 +
   4.277 +  If the simplifier cannot prove any of them, the entire method (or command) invocation will fail.
   4.278 +  It is, however, possible to dynamically add additional sign oracles that will be tried; the 
   4.279 +  most obvious candidate for an oracle that one may want to add or remove dynamically are 
   4.280 +  approximation-based tactics.
   4.281 +
   4.282 +  Adding such a tactic can be done by calling
   4.283 +  @{ML [source] Multiseries_Expansion.register_sign_oracle}. Note that if the tactic cannot prove
   4.284 +  a goal, it should fail as fast as possible.
   4.285 +\<close>
   4.286 +
   4.287 +(*<*)
   4.288 +end
   4.289 +(*>*)
   4.290 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/Doc/Real_Asymp/document/root.tex	Sun Jul 15 14:46:57 2018 +0200
     5.3 @@ -0,0 +1,39 @@
     5.4 +\documentclass[11pt,a4paper]{article}
     5.5 +\usepackage{amsfonts, amsmath, amssymb}
     5.6 +\usepackage{railsetup}
     5.7 +\usepackage{iman}
     5.8 +\usepackage{extra}
     5.9 +\usepackage{isar}
    5.10 +\usepackage{isabelle}
    5.11 +\usepackage{isabellesym}
    5.12 +\usepackage{style}
    5.13 +
    5.14 +% this should be the last package used
    5.15 +\usepackage{pdfsetup}
    5.16 +
    5.17 +% urls in roman style, theory text in math-similar italics
    5.18 +\urlstyle{rm}
    5.19 +\isabellestyle{it}
    5.20 +
    5.21 +
    5.22 +\begin{document}
    5.23 +
    5.24 +\title{\texttt{real\_asymp}: Semi-Automatic Real Asymptotics\\ in Isabelle\slash HOL}
    5.25 +\author{Manuel Eberl}
    5.26 +\maketitle
    5.27 +
    5.28 +\tableofcontents
    5.29 +\newpage
    5.30 +\parindent 0pt\parskip 0.5ex
    5.31 +
    5.32 +\input{session}
    5.33 +
    5.34 +\bibliographystyle{abbrv}
    5.35 +\bibliography{root}
    5.36 +
    5.37 +\end{document}
    5.38 +
    5.39 +%%% Local Variables:
    5.40 +%%% mode: latex
    5.41 +%%% TeX-master: t
    5.42 +%%% End:
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/Doc/Real_Asymp/document/style.sty	Sun Jul 15 14:46:57 2018 +0200
     6.3 @@ -0,0 +1,46 @@
     6.4 +
     6.5 +%% toc
     6.6 +\newcommand{\tocentry}[1]{\cleardoublepage\phantomsection\addcontentsline{toc}{chapter}{#1}
     6.7 +\@mkboth{\MakeUppercase{#1}}{\MakeUppercase{#1}}}
     6.8 +
     6.9 +%% paragraphs
    6.10 +\setlength{\parindent}{1em}
    6.11 +
    6.12 +%% references
    6.13 +\newcommand{\secref}[1]{\S\ref{#1}}
    6.14 +\newcommand{\figref}[1]{figure~\ref{#1}}
    6.15 +
    6.16 +%% logical markup
    6.17 +\newcommand{\strong}[1]{{\bfseries {#1}}}
    6.18 +\newcommand{\qn}[1]{\emph{#1}}
    6.19 +
    6.20 +%% typographic conventions
    6.21 +\newcommand{\qt}[1]{``{#1}''}
    6.22 +\newcommand{\ditem}[1]{\item[\isastyletext #1]}
    6.23 +
    6.24 +%% quote environment
    6.25 +\isakeeptag{quote}
    6.26 +\renewenvironment{quote}
    6.27 +  {\list{}{\leftmargin2em\rightmargin0pt}\parindent0pt\parskip0pt\item\relax}
    6.28 +  {\endlist}
    6.29 +\renewcommand{\isatagquote}{\begin{quote}}
    6.30 +\renewcommand{\endisatagquote}{\end{quote}}
    6.31 +\newcommand{\quotebreak}{\\[1.2ex]}
    6.32 +
    6.33 +%% presentation
    6.34 +\setcounter{secnumdepth}{2} \setcounter{tocdepth}{2}
    6.35 +
    6.36 +%% character detail
    6.37 +\renewcommand{\isadigit}[1]{\isamath{#1}}
    6.38 +\binperiod
    6.39 +\underscoreoff
    6.40 +
    6.41 +%% format
    6.42 +\pagestyle{headings}
    6.43 +\isabellestyle{it}
    6.44 +
    6.45 +
    6.46 +%%% Local Variables: 
    6.47 +%%% mode: latex
    6.48 +%%% TeX-master: "implementation"
    6.49 +%%% End: 
     7.1 --- a/src/HOL/ROOT	Sun Jul 15 01:14:04 2018 +0100
     7.2 +++ b/src/HOL/ROOT	Sun Jul 15 14:46:57 2018 +0200
     7.3 @@ -78,6 +78,14 @@
     7.4      (*conflicting type class instantiations and dependent applications*)
     7.5      Field_as_Ring
     7.6  
     7.7 +session "HOL-Real_Asymp" in Real_Asymp = HOL +
     7.8 +  sessions
     7.9 +    "HOL-Decision_Procs"
    7.10 +  theories
    7.11 +    Real_Asymp
    7.12 +    Real_Asymp_Approx
    7.13 +    Real_Asymp_Examples    
    7.14 +
    7.15  session "HOL-Hahn_Banach" in Hahn_Banach = "HOL-Library" +
    7.16    description {*
    7.17      Author:     Gertrud Bauer, TU Munich
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/HOL/Real_Asymp/Eventuallize.thy	Sun Jul 15 14:46:57 2018 +0200
     8.3 @@ -0,0 +1,57 @@
     8.4 +section \<open>Lifting theorems onto filters\<close>
     8.5 +theory Eventuallize
     8.6 +  imports Complex_Main
     8.7 +begin
     8.8 +
     8.9 +text \<open>
    8.10 +  The following attribute and ML function lift a given theorem of the form
    8.11 +    @{prop "\<forall>x. A x \<longrightarrow> B x \<longrightarrow> C x"}
    8.12 +  to
    8.13 +    @{prop "eventually A F \<Longrightarrow> eventually B F \<Longrightarrow> eventually C F"} .
    8.14 +\<close>
    8.15 +
    8.16 +ML \<open>
    8.17 +signature EVENTUALLIZE =
    8.18 +sig
    8.19 +val eventuallize : Proof.context -> thm -> int option -> thm
    8.20 +end
    8.21 +
    8.22 +structure Eventuallize : EVENTUALLIZE =
    8.23 +struct
    8.24 +
    8.25 +fun dest_All (Const (@{const_name "HOL.All"}, _) $ Abs (x, T, t)) = (x, T, t)
    8.26 +  | dest_All (Const (@{const_name "HOL.All"}, T) $ f) =
    8.27 +      ("x", T |> dest_funT |> fst |> dest_funT |> fst, f $ Bound 0)
    8.28 +  | dest_All t = raise TERM ("dest_All", [t])
    8.29 +
    8.30 +fun strip_imp (@{term "(\<longrightarrow>)"} $ a $ b) = apfst (cons a) (strip_imp b)
    8.31 +  | strip_imp t = ([], t)
    8.32 +
    8.33 +fun eventuallize ctxt thm n =
    8.34 +  let
    8.35 +    fun err n = raise THM ("Invalid index in eventuallize: " ^ Int.toString n, 0, [thm])
    8.36 +    val n_max =
    8.37 +      thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_All |> #3 |> strip_imp |> fst |> length
    8.38 +    val _ = case n of NONE => () | SOME n =>
    8.39 +      if n >= 0 andalso n <= n_max then () else err n
    8.40 +    val n = case n of SOME n => n | NONE => n_max
    8.41 +    fun conv n =
    8.42 +      if n < 2 then Conv.all_conv else Conv.arg_conv (conv (n - 1)) then_conv
    8.43 +        Conv.rewr_conv @{thm eq_reflection[OF imp_conjL [symmetric]]}
    8.44 +    val conv = Conv.arg_conv (Conv.binder_conv (K (conv n)) ctxt)
    8.45 +    val thm' = Conv.fconv_rule conv thm
    8.46 +    fun go n = if n < 2 then @{thm _} else @{thm eventually_conj} OF [@{thm _}, go (n - 1)]
    8.47 +  in
    8.48 +    @{thm eventually_rev_mp[OF _ always_eventually]} OF [go n, thm']
    8.49 +  end
    8.50 +
    8.51 +end
    8.52 +\<close>
    8.53 +
    8.54 +attribute_setup eventuallized = \<open>
    8.55 +  Scan.lift (Scan.option Parse.nat) >>
    8.56 +    (fn n => fn (ctxt, thm) =>
    8.57 +      (NONE, SOME (Eventuallize.eventuallize (Context.proof_of ctxt) thm n)))
    8.58 +\<close>
    8.59 +
    8.60 +end
    8.61 \ No newline at end of file
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/HOL/Real_Asymp/Inst_Existentials.thy	Sun Jul 15 14:46:57 2018 +0200
     9.3 @@ -0,0 +1,21 @@
     9.4 +section \<open>Tactic for instantiating existentials\<close>
     9.5 +theory Inst_Existentials
     9.6 +  imports Main
     9.7 +begin
     9.8 +
     9.9 +text \<open>
    9.10 +  Coinduction proofs in Isabelle often lead to proof obligations with nested conjunctions and
    9.11 +  existential quantifiers, e.g. @{prop "\<exists>x y. P x y \<and> (\<exists>z. Q x y z)"} .
    9.12 +
    9.13 +  The following tactic allows instantiating these existentials with a given list of witnesses.
    9.14 +\<close>
    9.15 +
    9.16 +ML_file \<open>inst_existentials.ML\<close>
    9.17 +
    9.18 +method_setup inst_existentials = \<open>
    9.19 +  Scan.lift (Scan.repeat Parse.term) >> 
    9.20 +    (fn ts => fn ctxt => SIMPLE_METHOD' (Inst_Existentials.tac ctxt 
    9.21 +       (map (Syntax.read_term ctxt)  ts)))
    9.22 +\<close>
    9.23 +
    9.24 +end
    9.25 \ No newline at end of file
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/HOL/Real_Asymp/Lazy_Eval.thy	Sun Jul 15 14:46:57 2018 +0200
    10.3 @@ -0,0 +1,39 @@
    10.4 +section \<open>Lazy evaluation within the logic\<close>
    10.5 +theory Lazy_Eval
    10.6 +imports
    10.7 +  Complex_Main
    10.8 +begin
    10.9 +
   10.10 +text \<open>  
   10.11 +  This is infrastructure to lazily evaluate an expression (typically something corecursive)
   10.12 +  within the logic by simple rewriting. A signature of supported (co-)datatype constructures 
   10.13 +  upon which pattern matching is allowed and a list of function equations that are used in
   10.14 +  rewriting must be provided.
   10.15 +
   10.16 +  One can then e.\,g.\ determine whether a given pattern matches a given expression. To do this,
   10.17 +  the expression will be rewritten using the given function equations until enough constructors
   10.18 +  have been exposed to decide whether the pattern matches.
   10.19 +
   10.20 +  This infrastructure was developed specifically for evaluating Multiseries expressions, but
   10.21 +  can, in principle, be used for other purposes as well.
   10.22 +\<close>
   10.23 +
   10.24 +lemma meta_eq_TrueE: "PROP P \<equiv> Trueprop True \<Longrightarrow> PROP P" by simp
   10.25 +
   10.26 +datatype cmp_result = LT | EQ | GT
   10.27 +
   10.28 +definition COMPARE :: "real \<Rightarrow> real \<Rightarrow> cmp_result" where
   10.29 +  "COMPARE x y = (if x < y then LT else if x > y then GT else EQ)"
   10.30 +
   10.31 +lemma COMPARE_intros: 
   10.32 +  "x < y \<Longrightarrow> COMPARE x y \<equiv> LT" "x > y \<Longrightarrow> COMPARE x y \<equiv> GT" "x = y \<Longrightarrow> COMPARE x y \<equiv> EQ"
   10.33 +  by (simp_all add: COMPARE_def)
   10.34 +  
   10.35 +primrec CMP_BRANCH :: "cmp_result \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> 'a" where
   10.36 +  "CMP_BRANCH LT x y z = x"
   10.37 +| "CMP_BRANCH EQ x y z = y"
   10.38 +| "CMP_BRANCH GT x y z = z"  
   10.39 +
   10.40 +ML_file \<open>lazy_eval.ML\<close>
   10.41 +
   10.42 +end
   10.43 \ No newline at end of file
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/HOL/Real_Asymp/Multiseries_Expansion.thy	Sun Jul 15 14:46:57 2018 +0200
    11.3 @@ -0,0 +1,5390 @@
    11.4 +(*
    11.5 +  File:    Multiseries_Expansion.thy
    11.6 +  Author:  Manuel Eberl, TU München
    11.7 +
    11.8 +  Asymptotic bases and Multiseries expansions of real-valued functions.
    11.9 +  Contains automation to prove limits and asymptotic relationships between such functions.
   11.10 +*)
   11.11 +section \<open>Multiseries expansions\<close>
   11.12 +theory Multiseries_Expansion
   11.13 +imports
   11.14 +  "HOL-Library.BNF_Corec"
   11.15 +  "HOL-Library.Landau_Symbols"
   11.16 +  Lazy_Eval
   11.17 +  Inst_Existentials
   11.18 +  Eventuallize
   11.19 +begin
   11.20 +
   11.21 +(* TODO Move *)
   11.22 +lemma real_powr_at_top: 
   11.23 +  assumes "(p::real) > 0"
   11.24 +  shows   "filterlim (\<lambda>x. x powr p) at_top at_top"
   11.25 +proof (subst filterlim_cong[OF refl refl])
   11.26 +  show "LIM x at_top. exp (p * ln x) :> at_top"
   11.27 +    by (rule filterlim_compose[OF exp_at_top filterlim_tendsto_pos_mult_at_top[OF tendsto_const]])
   11.28 +       (simp_all add: ln_at_top assms)
   11.29 +  show "eventually (\<lambda>x. x powr p = exp (p * ln x)) at_top"
   11.30 +    using eventually_gt_at_top[of 0] by eventually_elim (simp add: powr_def)
   11.31 +qed
   11.32 +
   11.33 +
   11.34 +subsection \<open>Streams and lazy lists\<close>
   11.35 +
   11.36 +codatatype 'a msstream = MSSCons 'a "'a msstream"
   11.37 +
   11.38 +primrec mssnth :: "'a msstream \<Rightarrow> nat \<Rightarrow> 'a" where
   11.39 +  "mssnth xs 0 = (case xs of MSSCons x xs \<Rightarrow> x)"
   11.40 +| "mssnth xs (Suc n) = (case xs of MSSCons x xs \<Rightarrow> mssnth xs n)"
   11.41 +
   11.42 +codatatype 'a msllist = MSLNil | MSLCons 'a "'a msllist"
   11.43 +  for map: mslmap
   11.44 +
   11.45 +fun lcoeff where
   11.46 +  "lcoeff MSLNil n = 0"
   11.47 +| "lcoeff (MSLCons x xs) 0 = x"
   11.48 +| "lcoeff (MSLCons x xs) (Suc n) = lcoeff xs n"
   11.49 +
   11.50 +primcorec msllist_of_msstream :: "'a msstream \<Rightarrow> 'a msllist" where
   11.51 +  "msllist_of_msstream xs = (case xs of MSSCons x xs \<Rightarrow> MSLCons x (msllist_of_msstream xs))"
   11.52 +  
   11.53 +lemma msllist_of_msstream_MSSCons [simp]: 
   11.54 +  "msllist_of_msstream (MSSCons x xs) = MSLCons x (msllist_of_msstream xs)"
   11.55 +  by (subst msllist_of_msstream.code) simp
   11.56 +
   11.57 +lemma lcoeff_llist_of_stream [simp]: "lcoeff (msllist_of_msstream xs) n = mssnth xs n"
   11.58 +  by (induction "msllist_of_msstream xs" n arbitrary: xs rule: lcoeff.induct;
   11.59 +      subst msllist_of_msstream.code) (auto split: msstream.splits)
   11.60 +
   11.61 +
   11.62 +subsection \<open>Convergent power series\<close>
   11.63 +
   11.64 +subsubsection \<open>Definition\<close>
   11.65 +
   11.66 +definition convergent_powser :: "real msllist \<Rightarrow> bool" where
   11.67 +  "convergent_powser cs \<longleftrightarrow> (\<exists>R>0. \<forall>x. abs x < R \<longrightarrow> summable (\<lambda>n. lcoeff cs n * x ^ n))"
   11.68 + 
   11.69 +lemma convergent_powser_stl:
   11.70 +  assumes "convergent_powser (MSLCons c cs)"
   11.71 +  shows   "convergent_powser cs"
   11.72 +proof -
   11.73 +  from assms obtain R where "R > 0" "\<And>x. abs x < R \<Longrightarrow> summable (\<lambda>n. lcoeff (MSLCons c cs) n * x ^ n)"
   11.74 +    unfolding convergent_powser_def by blast
   11.75 +  hence "summable (\<lambda>n. lcoeff cs n * x ^ n)" if "abs x < R" for x
   11.76 +    using that by (subst (asm) summable_powser_split_head [symmetric]) simp
   11.77 +  thus ?thesis using \<open>R > 0\<close> by (auto simp: convergent_powser_def)
   11.78 +qed
   11.79 +  
   11.80 +  
   11.81 +definition powser :: "real msllist \<Rightarrow> real \<Rightarrow> real" where
   11.82 +  "powser cs x = suminf (\<lambda>n. lcoeff cs n * x ^ n)"
   11.83 +
   11.84 +lemma isCont_powser:
   11.85 +  assumes "convergent_powser cs"
   11.86 +  shows   "isCont (powser cs) 0"
   11.87 +proof -
   11.88 +  from assms obtain R where R: "R > 0" "\<And>x. abs x < R \<Longrightarrow> summable (\<lambda>n. lcoeff cs n * x ^ n)"
   11.89 +    unfolding convergent_powser_def by blast
   11.90 +  hence *: "summable (\<lambda>n. lcoeff cs n * (R/2) ^ n)" by (intro R) simp_all
   11.91 +  from \<open>R > 0\<close> show ?thesis unfolding powser_def
   11.92 +    by (intro isCont_powser[OF *]) simp_all
   11.93 +qed
   11.94 +
   11.95 +lemma powser_MSLNil [simp]: "powser MSLNil = (\<lambda>_. 0)"
   11.96 +  by (simp add: fun_eq_iff powser_def)
   11.97 +
   11.98 +lemma powser_MSLCons:
   11.99 +  assumes "convergent_powser (MSLCons c cs)"
  11.100 +  shows   "eventually (\<lambda>x. powser (MSLCons c cs) x = x * powser cs x + c) (nhds 0)"
  11.101 +proof -
  11.102 +  from assms obtain R where R: "R > 0" "\<And>x. abs x < R \<Longrightarrow> summable (\<lambda>n. lcoeff (MSLCons c cs) n * x ^ n)"
  11.103 +    unfolding convergent_powser_def by blast
  11.104 +  from R have "powser (MSLCons c cs) x = x * powser cs x + c" if "abs x < R" for x
  11.105 +    using that unfolding powser_def by (subst powser_split_head) simp_all
  11.106 +  moreover have "eventually (\<lambda>x. abs x < R) (nhds 0)"
  11.107 +    using \<open>R > 0\<close> filterlim_ident[of "nhds (0::real)"]
  11.108 +    by (subst (asm) tendsto_iff) (simp add: dist_real_def)
  11.109 +  ultimately show ?thesis by (auto elim: eventually_mono)
  11.110 +qed
  11.111 +
  11.112 +definition convergent_powser' :: "real msllist \<Rightarrow> (real \<Rightarrow> real) \<Rightarrow> bool" where
  11.113 +  "convergent_powser' cs f \<longleftrightarrow> (\<exists>R>0. \<forall>x. abs x < R \<longrightarrow> (\<lambda>n. lcoeff cs n * x ^ n) sums f x)"
  11.114 +
  11.115 +lemma convergent_powser'_imp_convergent_powser:
  11.116 +  "convergent_powser' cs f \<Longrightarrow> convergent_powser cs" 
  11.117 +  unfolding convergent_powser_def convergent_powser'_def by (auto simp: sums_iff)
  11.118 +
  11.119 +lemma convergent_powser'_eventually:
  11.120 +  assumes "convergent_powser' cs f"
  11.121 +  shows   "eventually (\<lambda>x. powser cs x = f x) (nhds 0)"
  11.122 +proof -
  11.123 +  from assms obtain R where "R > 0" "\<And>x. abs x < R \<Longrightarrow> (\<lambda>n. lcoeff cs n * x ^ n) sums f x"
  11.124 +    unfolding convergent_powser'_def by blast
  11.125 +  hence "powser cs x = f x" if "abs x < R" for x
  11.126 +    using that by (simp add: powser_def sums_iff)
  11.127 +  moreover have "eventually (\<lambda>x. abs x < R) (nhds 0)"
  11.128 +    using \<open>R > 0\<close> filterlim_ident[of "nhds (0::real)"]
  11.129 +    by (subst (asm) tendsto_iff) (simp add: dist_real_def)
  11.130 +  ultimately show ?thesis by (auto elim: eventually_mono)
  11.131 +qed  
  11.132 +
  11.133 +
  11.134 +subsubsection \<open>Geometric series\<close>
  11.135 +
  11.136 +primcorec mssalternate :: "'a \<Rightarrow> 'a \<Rightarrow> 'a msstream" where
  11.137 +  "mssalternate a b = MSSCons a (mssalternate b a)"
  11.138 +
  11.139 +lemma case_mssalternate [simp]: 
  11.140 +  "(case mssalternate a b of MSSCons c d \<Rightarrow> f c d) = f a (mssalternate b a)"
  11.141 +  by (subst mssalternate.code) simp
  11.142 +
  11.143 +lemma mssnth_mssalternate: "mssnth (mssalternate a b) n = (if even n then a else b)"
  11.144 +  by (induction n arbitrary: a b; subst mssalternate.code) simp_all
  11.145 +  
  11.146 +lemma convergent_powser'_geometric:
  11.147 +  "convergent_powser' (msllist_of_msstream (mssalternate 1 (-1))) (\<lambda>x. inverse (1 + x))"
  11.148 +proof -
  11.149 +  have "(\<lambda>n. lcoeff (msllist_of_msstream (mssalternate 1 (-1))) n * x ^ n) sums (inverse (1 + x))"
  11.150 +    if "abs x < 1" for x :: real
  11.151 +  proof -
  11.152 +    have "(\<lambda>n. (-1) ^ n * x ^ n) sums (inverse (1 + x))"
  11.153 +      using that geometric_sums[of "-x"] by (simp add: field_simps power_mult_distrib [symmetric])
  11.154 +    also have "(\<lambda>n. (-1) ^ n * x ^ n) =
  11.155 +                 (\<lambda>n. lcoeff (msllist_of_msstream (mssalternate 1 (-1))) n * x ^ n)"
  11.156 +      by (auto simp add: mssnth_mssalternate fun_eq_iff)
  11.157 +    finally show ?thesis .
  11.158 +  qed
  11.159 +  thus ?thesis unfolding convergent_powser'_def by (force intro!: exI[of _ 1])
  11.160 +qed
  11.161 +
  11.162 +
  11.163 +subsubsection \<open>Exponential series\<close>
  11.164 +
  11.165 +primcorec exp_series_stream_aux :: "real \<Rightarrow> real \<Rightarrow> real msstream" where
  11.166 +  "exp_series_stream_aux acc n = MSSCons acc (exp_series_stream_aux (acc / n) (n + 1))"
  11.167 +  
  11.168 +lemma mssnth_exp_series_stream_aux:
  11.169 +  "mssnth (exp_series_stream_aux (1 / fact n) (n + 1)) m = 1 / fact (n + m)"
  11.170 +proof (induction m arbitrary: n)
  11.171 +  case (0 n)
  11.172 +  thus ?case by (subst exp_series_stream_aux.code) simp
  11.173 +next
  11.174 +  case (Suc m n)
  11.175 +  from Suc.IH[of "n + 1"] show ?case
  11.176 +    by (subst exp_series_stream_aux.code) (simp add: algebra_simps)
  11.177 +qed
  11.178 +
  11.179 +definition exp_series_stream :: "real msstream" where
  11.180 +  "exp_series_stream = exp_series_stream_aux 1 1"
  11.181 +  
  11.182 +lemma mssnth_exp_series_stream:
  11.183 +  "mssnth exp_series_stream n = 1 / fact n"
  11.184 +  unfolding exp_series_stream_def using mssnth_exp_series_stream_aux[of 0 n] by simp
  11.185 +
  11.186 +lemma convergent_powser'_exp:
  11.187 +  "convergent_powser' (msllist_of_msstream exp_series_stream) exp"
  11.188 +proof -
  11.189 +  have "(\<lambda>n. lcoeff (msllist_of_msstream exp_series_stream) n * x ^ n) sums exp x" for x :: real
  11.190 +    using exp_converges[of x] by (simp add: mssnth_exp_series_stream divide_simps)
  11.191 +  thus ?thesis by (auto intro: exI[of _ "1::real"] simp: convergent_powser'_def)
  11.192 +qed
  11.193 +  
  11.194 +
  11.195 +subsubsection \<open>Logarithm series\<close>
  11.196 +
  11.197 +primcorec ln_series_stream_aux :: "bool \<Rightarrow> real \<Rightarrow> real msstream" where
  11.198 +  "ln_series_stream_aux b n = 
  11.199 +     MSSCons (if b then -inverse n else inverse n) (ln_series_stream_aux (\<not>b) (n+1))"
  11.200 +
  11.201 +lemma mssnth_ln_series_stream_aux:
  11.202 +  "mssnth (ln_series_stream_aux b x) n = 
  11.203 +     (if b then - ((-1)^n) * inverse (x + real n) else ((-1)^n) * inverse (x + real n))"
  11.204 +  by (induction n arbitrary: b x; subst ln_series_stream_aux.code) simp_all
  11.205 +
  11.206 +definition ln_series_stream :: "real msstream" where
  11.207 +  "ln_series_stream = MSSCons 0 (ln_series_stream_aux False 1)"
  11.208 +  
  11.209 +lemma mssnth_ln_series_stream:
  11.210 +  "mssnth ln_series_stream n = (-1) ^ Suc n / real n"
  11.211 +  unfolding ln_series_stream_def 
  11.212 +  by (cases n) (simp_all add: mssnth_ln_series_stream_aux field_simps)
  11.213 +
  11.214 +lemma ln_series': 
  11.215 +  assumes "abs (x::real) < 1"
  11.216 +  shows   "(\<lambda>n. - ((-x)^n) / of_nat n) sums ln (1 + x)"
  11.217 +proof -
  11.218 +  have "\<forall>n\<ge>1. norm (-((-x)^n)) / of_nat n \<le> norm x ^ n / 1"
  11.219 +    by (intro exI[of _ "1::nat"] allI impI frac_le) (simp_all add: power_abs)
  11.220 +  hence "\<exists>N. \<forall>n\<ge>N. norm (-((-x)^n) / of_nat n) \<le> norm x ^ n" 
  11.221 +    by (intro exI[of _ 1]) simp_all
  11.222 +  moreover from assms have "summable (\<lambda>n. norm x ^ n)" 
  11.223 +    by (intro summable_geometric) simp_all
  11.224 +  ultimately have *: "summable (\<lambda>n. - ((-x)^n) / of_nat n)"
  11.225 +    by (rule summable_comparison_test)
  11.226 +  moreover from assms have "0 < 1 + x" "1 + x < 2" by simp_all
  11.227 +  from ln_series[OF this] 
  11.228 +    have "ln (1 + x) = (\<Sum>n. - ((-x) ^ Suc n) / real (Suc n))"
  11.229 +    by (simp_all add: power_minus' mult_ac)
  11.230 +  hence "ln (1 + x) = (\<Sum>n. - ((-x) ^ n / real n))"
  11.231 +    by (subst (asm) suminf_split_head[OF *]) simp_all
  11.232 +  ultimately show ?thesis by (simp add: sums_iff)
  11.233 +qed
  11.234 +
  11.235 +lemma convergent_powser'_ln:
  11.236 +  "convergent_powser' (msllist_of_msstream ln_series_stream) (\<lambda>x. ln (1 + x))"
  11.237 +proof -
  11.238 +  have "(\<lambda>n. lcoeff (msllist_of_msstream ln_series_stream)n * x ^ n) sums ln (1 + x)"
  11.239 +    if "abs x < 1" for x
  11.240 +  proof -
  11.241 +    from that have "(\<lambda>n. - ((- x) ^ n) / real n) sums ln (1 + x)" by (rule ln_series')
  11.242 +    also have "(\<lambda>n. - ((- x) ^ n) / real n) =
  11.243 +                 (\<lambda>n. lcoeff (msllist_of_msstream ln_series_stream) n * x ^ n)"
  11.244 +      by (auto simp: fun_eq_iff mssnth_ln_series_stream power_mult_distrib [symmetric])
  11.245 +    finally show ?thesis .
  11.246 +  qed
  11.247 +  thus ?thesis unfolding convergent_powser'_def by (force intro!: exI[of _ 1])
  11.248 +qed
  11.249 +
  11.250 +
  11.251 +subsubsection \<open>Generalized binomial series\<close>
  11.252 +
  11.253 +primcorec gbinomial_series_aux :: "bool \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real msllist" where
  11.254 +  "gbinomial_series_aux abort x n acc =
  11.255 +     (if abort \<and> acc = 0 then MSLNil else 
  11.256 +        MSLCons acc (gbinomial_series_aux abort x (n + 1) ((x - n) / (n + 1) * acc)))"
  11.257 +
  11.258 +lemma gbinomial_series_abort [simp]: "gbinomial_series_aux True x n 0 = MSLNil"
  11.259 +  by (subst gbinomial_series_aux.code) simp
  11.260 +
  11.261 +definition gbinomial_series :: "bool \<Rightarrow> real \<Rightarrow> real msllist" where
  11.262 +  "gbinomial_series abort x = gbinomial_series_aux abort x 0 1"
  11.263 +
  11.264 +
  11.265 +(* TODO Move *)
  11.266 +lemma gbinomial_Suc_rec:
  11.267 +  "(x gchoose (Suc k)) = (x gchoose k) * ((x - of_nat k) / (of_nat k + 1))"
  11.268 +proof -
  11.269 +  have "((x - 1) + 1) gchoose (Suc k) = x * (x - 1 gchoose k) / (1 + of_nat k)"
  11.270 +    by (subst gbinomial_factors) simp
  11.271 +  also have "x * (x - 1 gchoose k) = (x - of_nat k) * (x gchoose k)"
  11.272 +    by (rule gbinomial_absorb_comp [symmetric])
  11.273 +  finally show ?thesis by (simp add: algebra_simps)
  11.274 +qed
  11.275 +
  11.276 +lemma lcoeff_gbinomial_series_aux:
  11.277 +  "lcoeff (gbinomial_series_aux abort x m (x gchoose m)) n = (x gchoose (n + m))"
  11.278 +proof (induction n arbitrary: m)
  11.279 +  case 0
  11.280 +  show ?case by (subst gbinomial_series_aux.code) simp
  11.281 +next
  11.282 +  case (Suc n m)
  11.283 +  show ?case
  11.284 +  proof (cases "abort \<and> (x gchoose m) = 0")
  11.285 +    case True
  11.286 +    with gbinomial_mult_fact[of m x] obtain k where "x = real k" "k < m"
  11.287 +      by auto
  11.288 +    hence "(x gchoose Suc (n + m)) = 0"
  11.289 +      using gbinomial_mult_fact[of "Suc (n + m)" x]
  11.290 +      by (simp add: gbinomial_altdef_of_nat)
  11.291 +    with True show ?thesis by (subst gbinomial_series_aux.code) simp
  11.292 +  next
  11.293 +    case False
  11.294 +    hence "lcoeff (gbinomial_series_aux abort x m (x gchoose m)) (Suc n) = 
  11.295 +             lcoeff (gbinomial_series_aux abort x (Suc m) ((x gchoose m) *
  11.296 +             ((x - real m) / (real m + 1)))) n"
  11.297 +      by (subst gbinomial_series_aux.code) (auto simp: algebra_simps)
  11.298 +    also have "((x gchoose m) * ((x - real m) / (real m + 1))) = x gchoose (Suc m)" 
  11.299 +      by (rule gbinomial_Suc_rec [symmetric])
  11.300 +    also have "lcoeff (gbinomial_series_aux abort x (Suc m) \<dots>) n = x gchoose (n + Suc m)"
  11.301 +      by (rule Suc.IH)
  11.302 +    finally show ?thesis by simp
  11.303 +  qed
  11.304 +qed
  11.305 +
  11.306 +lemma lcoeff_gbinomial_series [simp]:
  11.307 +  "lcoeff (gbinomial_series abort x) n = (x gchoose n)"
  11.308 +  using lcoeff_gbinomial_series_aux[of abort x 0 n] by (simp add: gbinomial_series_def)
  11.309 +
  11.310 +lemma gbinomial_ratio_limit:
  11.311 +  fixes a :: "'a :: real_normed_field"
  11.312 +  assumes "a \<notin> \<nat>"
  11.313 +  shows "(\<lambda>n. (a gchoose n) / (a gchoose Suc n)) \<longlonglongrightarrow> -1"
  11.314 +proof (rule Lim_transform_eventually)
  11.315 +  let ?f = "\<lambda>n. inverse (a / of_nat (Suc n) - of_nat n / of_nat (Suc n))"
  11.316 +  from eventually_gt_at_top[of "0::nat"]
  11.317 +    show "eventually (\<lambda>n. ?f n = (a gchoose n) /(a gchoose Suc n)) sequentially"
  11.318 +  proof eventually_elim
  11.319 +    fix n :: nat assume n: "n > 0"
  11.320 +    then obtain q where q: "n = Suc q" by (cases n) blast
  11.321 +    let ?P = "\<Prod>i=0..<n. a - of_nat i"
  11.322 +    from n have "(a gchoose n) / (a gchoose Suc n) = (of_nat (Suc n) :: 'a) *
  11.323 +                   (?P / (\<Prod>i=0..n. a - of_nat i))"
  11.324 +      by (simp add: gbinomial_prod_rev atLeastLessThanSuc_atLeastAtMost)
  11.325 +    also from q have "(\<Prod>i=0..n. a - of_nat i) = ?P * (a - of_nat n)"
  11.326 +      by (simp add: prod.atLeast0_atMost_Suc atLeastLessThanSuc_atLeastAtMost)
  11.327 +    also have "?P / \<dots> = (?P / ?P) / (a - of_nat n)" by (rule divide_divide_eq_left[symmetric])
  11.328 +    also from assms have "?P / ?P = 1" by auto
  11.329 +    also have "of_nat (Suc n) * (1 / (a - of_nat n)) =
  11.330 +                   inverse (inverse (of_nat (Suc n)) * (a - of_nat n))" by (simp add: field_simps)
  11.331 +    also have "inverse (of_nat (Suc n)) * (a - of_nat n) =
  11.332 +                 a / of_nat (Suc n) - of_nat n / of_nat (Suc n)"
  11.333 +      by (simp add: field_simps del: of_nat_Suc)
  11.334 +    finally show "?f n = (a gchoose n) / (a gchoose Suc n)" by simp
  11.335 +  qed
  11.336 +
  11.337 +  have "(\<lambda>n. norm a / (of_nat (Suc n))) \<longlonglongrightarrow> 0"
  11.338 +    unfolding divide_inverse
  11.339 +    by (intro tendsto_mult_right_zero LIMSEQ_inverse_real_of_nat)
  11.340 +  hence "(\<lambda>n. a / of_nat (Suc n)) \<longlonglongrightarrow> 0"
  11.341 +    by (subst tendsto_norm_zero_iff[symmetric]) (simp add: norm_divide del: of_nat_Suc)
  11.342 +  hence "?f \<longlonglongrightarrow> inverse (0 - 1)"
  11.343 +    by (intro tendsto_inverse tendsto_diff LIMSEQ_n_over_Suc_n) simp_all
  11.344 +  thus "?f \<longlonglongrightarrow> -1" by simp
  11.345 +qed
  11.346 +  
  11.347 +lemma summable_gbinomial:
  11.348 +  fixes a z :: real
  11.349 +  assumes "norm z < 1"
  11.350 +  shows   "summable (\<lambda>n. (a gchoose n) * z ^ n)"
  11.351 +proof (cases "z = 0 \<or> a \<in> \<nat>")
  11.352 +  case False
  11.353 +  define r where "r = (norm z + 1) / 2"
  11.354 +  from assms have r: "r > norm z" "r < 1" by (simp_all add: r_def field_simps)
  11.355 +  from False have "abs z > 0" by auto
  11.356 +  from False have "a \<notin> \<nat>" by (auto elim!: Nats_cases)
  11.357 +  hence *: "(\<lambda>n. norm (z / ((a gchoose n) / (a gchoose (Suc n))))) \<longlonglongrightarrow> norm (z / (-1))"
  11.358 +    by (intro tendsto_norm tendsto_divide tendsto_const gbinomial_ratio_limit) simp_all
  11.359 +  hence "\<forall>\<^sub>F x in at_top. norm (z / ((a gchoose x) / (a gchoose Suc x))) > 0"
  11.360 +    using assms False by (intro order_tendstoD) auto
  11.361 +  hence nz: "\<forall>\<^sub>F x in at_top. (a gchoose x) \<noteq> 0" by eventually_elim auto
  11.362 +      
  11.363 +  have "\<forall>\<^sub>F x in at_top. norm (z / ((a gchoose x) / (a gchoose Suc x))) < r"
  11.364 +    using assms r by (intro order_tendstoD(2)[OF *]) simp_all
  11.365 +  with nz have "\<forall>\<^sub>F n in at_top. norm ((a gchoose (Suc n)) * z) \<le> r * norm (a gchoose n)"
  11.366 +    by eventually_elim (simp add: field_simps abs_mult split: if_splits)
  11.367 +  hence "\<forall>\<^sub>F n in at_top. norm (z ^ n) * norm ((a gchoose (Suc n)) * z) \<le>
  11.368 +                           norm (z ^ n) * (r * norm (a gchoose n))"
  11.369 +    by eventually_elim (insert False, intro mult_left_mono, auto)
  11.370 +  hence "\<forall>\<^sub>F n in at_top. norm ((a gchoose (Suc n)) * z ^ (Suc n)) \<le> 
  11.371 +                           r * norm ((a gchoose n) * z ^ n)"
  11.372 +    by (simp add: abs_mult mult_ac)
  11.373 +  then obtain N where N: "\<And>n. n \<ge> N \<Longrightarrow> norm ((a gchoose (Suc n)) * z ^ (Suc n)) \<le>
  11.374 +                                          r * norm ((a gchoose n) * z ^ n)"
  11.375 +    unfolding eventually_at_top_linorder by blast
  11.376 +  show "summable (\<lambda>n. (a gchoose n) * z ^ n)"
  11.377 +    by (intro summable_ratio_test[OF r(2), of N] N)
  11.378 +next
  11.379 +  case True
  11.380 +  thus ?thesis
  11.381 +  proof
  11.382 +    assume "a \<in> \<nat>"
  11.383 +    then obtain n where [simp]: "a = of_nat n" by (auto elim: Nats_cases)
  11.384 +    from eventually_gt_at_top[of n] 
  11.385 +      have "eventually (\<lambda>n. (a gchoose n) * z ^ n = 0) at_top"
  11.386 +      by eventually_elim (simp add: binomial_gbinomial [symmetric])
  11.387 +    from summable_cong[OF this] show ?thesis by simp
  11.388 +  qed auto
  11.389 +qed
  11.390 +
  11.391 +lemma gen_binomial_real:
  11.392 +  fixes z :: real
  11.393 +  assumes "norm z < 1"
  11.394 +  shows   "(\<lambda>n. (a gchoose n) * z^n) sums (1 + z) powr a"
  11.395 +proof -
  11.396 +  define K where "K = 1 - (1 - norm z) / 2"
  11.397 +  from assms have K: "K > 0" "K < 1" "norm z < K"
  11.398 +     unfolding K_def by (auto simp: field_simps intro!: add_pos_nonneg)
  11.399 +  let ?f = "\<lambda>n. a gchoose n" and ?f' = "diffs (\<lambda>n. a gchoose n)"
  11.400 +  have summable_strong: "summable (\<lambda>n. ?f n * z ^ n)" if "norm z < 1" for z using that
  11.401 +    by (intro summable_gbinomial)
  11.402 +  with K have summable: "summable (\<lambda>n. ?f n * z ^ n)" if "norm z < K" for z using that by auto
  11.403 +  hence summable': "summable (\<lambda>n. ?f' n * z ^ n)" if "norm z < K" for z using that
  11.404 +    by (intro termdiff_converges[of _ K]) simp_all
  11.405 +
  11.406 +  define f f' where [abs_def]: "f z = (\<Sum>n. ?f n * z ^ n)" "f' z = (\<Sum>n. ?f' n * z ^ n)" for z
  11.407 +  {
  11.408 +    fix z :: real assume z: "norm z < K"
  11.409 +    from summable_mult2[OF summable'[OF z], of z]
  11.410 +      have summable1: "summable (\<lambda>n. ?f' n * z ^ Suc n)" by (simp add: mult_ac)
  11.411 +    hence summable2: "summable (\<lambda>n. of_nat n * ?f n * z^n)"
  11.412 +      unfolding diffs_def by (subst (asm) summable_Suc_iff)
  11.413 +
  11.414 +    have "(1 + z) * f' z = (\<Sum>n. ?f' n * z^n) + (\<Sum>n. ?f' n * z^Suc n)"
  11.415 +      unfolding f_f'_def using summable' z by (simp add: algebra_simps suminf_mult)
  11.416 +    also have "(\<Sum>n. ?f' n * z^n) = (\<Sum>n. of_nat (Suc n) * ?f (Suc n) * z^n)"
  11.417 +      by (intro suminf_cong) (simp add: diffs_def)
  11.418 +    also have "(\<Sum>n. ?f' n * z^Suc n) = (\<Sum>n. of_nat n * ?f n * z ^ n)"
  11.419 +      using summable1 suminf_split_initial_segment[OF summable1] unfolding diffs_def
  11.420 +      by (subst suminf_split_head, subst (asm) summable_Suc_iff) simp_all
  11.421 +    also have "(\<Sum>n. of_nat (Suc n) * ?f (Suc n) * z^n) + (\<Sum>n. of_nat n * ?f n * z^n) =
  11.422 +                 (\<Sum>n. a * ?f n * z^n)"
  11.423 +      by (subst gbinomial_mult_1, subst suminf_add)
  11.424 +         (insert summable'[OF z] summable2,
  11.425 +          simp_all add: summable_powser_split_head algebra_simps diffs_def)
  11.426 +    also have "\<dots> = a * f z" unfolding f_f'_def
  11.427 +      by (subst suminf_mult[symmetric]) (simp_all add: summable[OF z] mult_ac)
  11.428 +    finally have "a * f z = (1 + z) * f' z" by simp
  11.429 +  } note deriv = this
  11.430 +
  11.431 +  have [derivative_intros]: "(f has_field_derivative f' z) (at z)" if "norm z < of_real K" for z
  11.432 +    unfolding f_f'_def using K that
  11.433 +    by (intro termdiffs_strong[of "?f" K z] summable_strong) simp_all
  11.434 +  have "f 0 = (\<Sum>n. if n = 0 then 1 else 0)" unfolding f_f'_def by (intro suminf_cong) simp
  11.435 +  also have "\<dots> = 1" using sums_single[of 0 "\<lambda>_. 1::real"] unfolding sums_iff by simp
  11.436 +  finally have [simp]: "f 0 = 1" .
  11.437 +
  11.438 +  have "f z * (1 + z) powr (-a) = f 0 * (1 + 0) powr (-a)"
  11.439 +  proof (rule DERIV_isconst3[where ?f = "\<lambda>x. f x * (1 + x) powr (-a)"])
  11.440 +    fix z :: real assume z': "z \<in> {-K<..<K}"
  11.441 +    hence z: "norm z < K" using K by auto
  11.442 +    with K have nz: "1 + z \<noteq> 0" by (auto dest!: minus_unique)
  11.443 +    from z K have "norm z < 1" by simp
  11.444 +    hence "((\<lambda>z. f z * (1 + z) powr (-a)) has_field_derivative
  11.445 +              f' z * (1 + z) powr (-a) - a * f z * (1 + z) powr (-a-1)) (at z)" using z
  11.446 +      by (auto intro!: derivative_eq_intros)
  11.447 +    also from z have "a * f z = (1 + z) * f' z" by (rule deriv)
  11.448 +    also have "f' z * (1 + z) powr - a - (1 + z) * f' z * (1 + z) powr (- a - 1) = 0"
  11.449 +      using \<open>norm z < 1\<close> by (auto simp add: field_simps powr_diff)
  11.450 +    finally show "((\<lambda>z. f z * (1 + z) powr (-a)) has_field_derivative 0) (at z)" .
  11.451 +  qed (insert K, auto)
  11.452 +  also have "f 0 * (1 + 0) powr -a = 1" by simp
  11.453 +  finally have "f z = (1 + z) powr a" using K
  11.454 +    by (simp add: field_simps dist_real_def powr_minus)
  11.455 +  with summable K show ?thesis unfolding f_f'_def by (simp add: sums_iff)
  11.456 +qed
  11.457 +
  11.458 +lemma convergent_powser'_gbinomial:
  11.459 +  "convergent_powser' (gbinomial_series abort p) (\<lambda>x. (1 + x) powr p)"
  11.460 +proof -
  11.461 +  have "(\<lambda>n. lcoeff (gbinomial_series abort p) n * x ^ n) sums (1 + x) powr p" if "abs x < 1" for x
  11.462 +    using that gen_binomial_real[of x p] by simp
  11.463 +  thus ?thesis unfolding convergent_powser'_def by (force intro!: exI[of _ 1])
  11.464 +qed
  11.465 +
  11.466 +lemma convergent_powser'_gbinomial':
  11.467 +  "convergent_powser' (gbinomial_series abort (real n)) (\<lambda>x. (1 + x) ^ n)"
  11.468 +proof -
  11.469 +  {
  11.470 +    fix x :: real
  11.471 +    have "(\<lambda>k. if k \<in> {0..n} then real (n choose k) * x ^ k else 0) sums (x + 1) ^ n"
  11.472 +      using sums_If_finite_set[of "{..n}" "\<lambda>k. real (n choose k) * x ^ k"]
  11.473 +      by (subst binomial_ring) simp
  11.474 +    also have "(\<lambda>k. if k \<in> {0..n} then real (n choose k) * x ^ k else 0) = 
  11.475 +                 (\<lambda>k. lcoeff (gbinomial_series abort (real n)) k * x ^ k)"
  11.476 +      by (simp add: fun_eq_iff binomial_gbinomial [symmetric])
  11.477 +    finally have "\<dots> sums (1 + x) ^ n" by (simp add: add_ac)
  11.478 +  }
  11.479 +  thus ?thesis unfolding convergent_powser'_def
  11.480 +    by (auto intro!: exI[of _ 1])
  11.481 +qed
  11.482 +
  11.483 +
  11.484 +subsubsection \<open>Sine and cosine\<close>
  11.485 +
  11.486 +primcorec sin_series_stream_aux :: "bool \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real msstream" where
  11.487 +  "sin_series_stream_aux b acc m = 
  11.488 +    MSSCons (if b then -inverse acc else inverse acc)
  11.489 +          (sin_series_stream_aux (\<not>b) (acc * (m + 1) * (m + 2)) (m + 2))"
  11.490 +
  11.491 +lemma mssnth_sin_series_stream_aux:
  11.492 +  "mssnth (sin_series_stream_aux b (fact m) m) n = 
  11.493 +     (if b then -1 else 1) * (-1) ^ n / (fact (2 * n + m))"
  11.494 +proof (induction n arbitrary: b m) 
  11.495 +  case (0 b m)
  11.496 +  thus ?case by (subst sin_series_stream_aux.code) (simp add: field_simps)
  11.497 +next
  11.498 +  case (Suc n b m)
  11.499 +  show ?case using Suc.IH[of "\<not>b" "m + 2"]
  11.500 +    by (subst sin_series_stream_aux.code) (auto simp: field_simps)
  11.501 +qed
  11.502 +
  11.503 +definition sin_series_stream where
  11.504 +  "sin_series_stream = sin_series_stream_aux False 1 1"
  11.505 +
  11.506 +lemma mssnth_sin_series_stream:
  11.507 +  "mssnth sin_series_stream n = (-1) ^ n / fact (2 * n + 1)"
  11.508 +  using mssnth_sin_series_stream_aux[of False 1 n] unfolding sin_series_stream_def by simp
  11.509 +
  11.510 +definition cos_series_stream where
  11.511 +  "cos_series_stream = sin_series_stream_aux False 1 0"
  11.512 +
  11.513 +lemma mssnth_cos_series_stream:
  11.514 +  "mssnth cos_series_stream n = (-1) ^ n / fact (2 * n)"
  11.515 +  using mssnth_sin_series_stream_aux[of False 0 n] unfolding cos_series_stream_def by simp
  11.516 +
  11.517 +lemma summable_pre_sin: "summable (\<lambda>n. mssnth sin_series_stream n * (x::real) ^ n)"
  11.518 +proof -
  11.519 +  have *: "summable (\<lambda>n. 1 / fact n * abs x ^ n)"
  11.520 +    using exp_converges[of "abs x"] by (simp add: sums_iff field_simps)
  11.521 +  {
  11.522 +    fix n :: nat
  11.523 +    have "\<bar>x\<bar> ^ n / fact (2 * n + 1) \<le> \<bar>x\<bar> ^ n / fact n"
  11.524 +      by (intro divide_left_mono fact_mono) auto
  11.525 +    hence "norm (mssnth sin_series_stream n * x ^ n) \<le> 1 / fact n * abs x ^ n"
  11.526 +      by (simp add: mssnth_sin_series_stream abs_mult power_abs field_simps)
  11.527 +  }
  11.528 +  thus ?thesis
  11.529 +    by (intro summable_comparison_test[OF _ *]) (auto intro!: exI[of _ 0])
  11.530 +qed
  11.531 +
  11.532 +lemma summable_pre_cos: "summable (\<lambda>n. mssnth cos_series_stream n * (x::real) ^ n)"
  11.533 +proof -
  11.534 +  have *: "summable (\<lambda>n. 1 / fact n * abs x ^ n)"
  11.535 +    using exp_converges[of "abs x"] by (simp add: sums_iff field_simps)
  11.536 +  {
  11.537 +    fix n :: nat
  11.538 +    have "\<bar>x\<bar> ^ n / fact (2 * n) \<le> \<bar>x\<bar> ^ n / fact n"
  11.539 +      by (intro divide_left_mono fact_mono) auto
  11.540 +    hence "norm (mssnth cos_series_stream n * x ^ n) \<le> 1 / fact n * abs x ^ n"
  11.541 +      by (simp add: mssnth_cos_series_stream abs_mult power_abs field_simps)
  11.542 +  }
  11.543 +  thus ?thesis
  11.544 +    by (intro summable_comparison_test[OF _ *]) (auto intro!: exI[of _ 0])
  11.545 +qed
  11.546 +
  11.547 +lemma cos_conv_pre_cos:
  11.548 +  "cos x = powser (msllist_of_msstream cos_series_stream) (x ^ 2)"
  11.549 +proof -
  11.550 +  have "(\<lambda>n. cos_coeff (2 * n) * x ^ (2 * n)) sums cos x"
  11.551 +    using cos_converges[of x]
  11.552 +    by (subst sums_mono_reindex[of "\<lambda>n. 2 * n"])
  11.553 +       (auto simp: strict_mono_def cos_coeff_def elim!: evenE)
  11.554 +  also have "(\<lambda>n. cos_coeff (2 * n) * x ^ (2 * n)) =
  11.555 +               (\<lambda>n. mssnth cos_series_stream n * (x ^ 2) ^ n)"
  11.556 +    by (simp add: fun_eq_iff mssnth_cos_series_stream cos_coeff_def power_mult)
  11.557 +  finally have sums: "(\<lambda>n. mssnth cos_series_stream n * x\<^sup>2 ^ n) sums cos x" .
  11.558 +  thus ?thesis by (simp add: powser_def sums_iff)
  11.559 +qed
  11.560 +
  11.561 +lemma sin_conv_pre_sin:
  11.562 +  "sin x = x * powser (msllist_of_msstream sin_series_stream) (x ^ 2)"
  11.563 +proof -
  11.564 +  have "(\<lambda>n. sin_coeff (2 * n + 1) * x ^ (2 * n + 1)) sums sin x"
  11.565 +    using sin_converges[of x]
  11.566 +    by (subst sums_mono_reindex[of "\<lambda>n. 2 * n + 1"])
  11.567 +       (auto simp: strict_mono_def sin_coeff_def elim!: oddE)
  11.568 +  also have "(\<lambda>n. sin_coeff (2 * n + 1) * x ^ (2 * n + 1)) =
  11.569 +               (\<lambda>n. x * mssnth sin_series_stream n * (x ^ 2) ^ n)"
  11.570 +    by (simp add: fun_eq_iff mssnth_sin_series_stream sin_coeff_def power_mult [symmetric] algebra_simps)
  11.571 +  finally have sums: "(\<lambda>n. x * mssnth sin_series_stream n * x\<^sup>2 ^ n) sums sin x" .
  11.572 +  thus ?thesis using summable_pre_sin[of "x^2"] 
  11.573 +    by (simp add: powser_def sums_iff suminf_mult [symmetric] mult.assoc)
  11.574 +qed
  11.575 +
  11.576 +lemma convergent_powser_sin_series_stream:
  11.577 +  "convergent_powser (msllist_of_msstream sin_series_stream)"
  11.578 +  (is "convergent_powser ?cs")
  11.579 +proof -
  11.580 +  show ?thesis using summable_pre_sin unfolding convergent_powser_def
  11.581 +    by (intro exI[of _ 1]) auto
  11.582 +qed
  11.583 +
  11.584 +lemma convergent_powser_cos_series_stream:
  11.585 +  "convergent_powser (msllist_of_msstream cos_series_stream)"
  11.586 +  (is "convergent_powser ?cs")
  11.587 +proof -
  11.588 +  show ?thesis using summable_pre_cos unfolding convergent_powser_def
  11.589 +    by (intro exI[of _ 1]) auto
  11.590 +qed
  11.591 +  
  11.592 +  
  11.593 +subsubsection \<open>Arc tangent\<close>
  11.594 +
  11.595 +definition arctan_coeffs :: "nat \<Rightarrow> 'a :: {real_normed_div_algebra, banach}" where
  11.596 +  "arctan_coeffs n = (if odd n then (-1) ^ (n div 2) / of_nat n else 0)"
  11.597 +
  11.598 +lemma arctan_converges:
  11.599 +  assumes "norm x < 1"
  11.600 +  shows   "(\<lambda>n. arctan_coeffs n * x ^ n) sums arctan x"
  11.601 +proof -
  11.602 +  have A: "(\<lambda>n. diffs arctan_coeffs n * x ^ n) sums (1 / (1 + x^2))" if "norm x < 1" for x :: real
  11.603 +  proof -
  11.604 +    let ?f = "\<lambda>n. (if odd n then 0 else (-1) ^ (n div 2)) * x ^ n"
  11.605 +    from that have "norm x ^ 2 < 1 ^ 2" by (intro power_strict_mono) simp_all
  11.606 +    hence "(\<lambda>n. (-(x^2))^n) sums (1 / (1 - (-(x^2))))" by (intro geometric_sums) simp_all
  11.607 +    also have "1 - (-(x^2)) = 1 + x^2" by simp
  11.608 +    also have "(\<lambda>n. (-(x^2))^n) = (\<lambda>n. ?f (2*n))" by (auto simp: fun_eq_iff power_minus' power_mult)
  11.609 +    also have "range (( *) (2::nat)) = {n. even n}"
  11.610 +      by (auto elim!: evenE)
  11.611 +    hence "(\<lambda>n. ?f (2*n)) sums (1 / (1 + x^2)) \<longleftrightarrow> ?f sums (1 / (1 + x^2))"
  11.612 +      by (intro sums_mono_reindex) (simp_all add: strict_mono_Suc_iff)
  11.613 +    also have "?f = (\<lambda>n. diffs arctan_coeffs n * x ^ n)"
  11.614 +      by (simp add: fun_eq_iff arctan_coeffs_def diffs_def)
  11.615 +    finally show "(\<lambda>n. diffs arctan_coeffs n * x ^ n) sums (1 / (1 + x^2))" .
  11.616 +  qed
  11.617 +  
  11.618 +  have B: "summable (\<lambda>n. arctan_coeffs n * x ^ n)" if "norm x < 1" for x :: real
  11.619 +  proof (rule summable_comparison_test)
  11.620 +    show "\<exists>N. \<forall>n\<ge>N. norm (arctan_coeffs n * x ^ n) \<le> 1 * norm x ^ n"
  11.621 +      unfolding norm_mult norm_power
  11.622 +      by (intro exI[of _ "0::nat"] allI impI mult_right_mono)
  11.623 +         (simp_all add: arctan_coeffs_def divide_simps)
  11.624 +    from that show "summable (\<lambda>n. 1 * norm x ^ n)"
  11.625 +      by (intro summable_mult summable_geometric) simp_all
  11.626 +  qed
  11.627 +  
  11.628 +  define F :: "real \<Rightarrow> real" where "F = (\<lambda>x. \<Sum>n. arctan_coeffs n * x ^ n)"
  11.629 +  have [derivative_intros]:
  11.630 +    "(F has_field_derivative (1 / (1 + x^2))) (at x)" if "norm x < 1" for x :: real
  11.631 +  proof -
  11.632 +    define K :: real where "K = (1 + norm x) / 2"
  11.633 +    from that have K: "norm x < K" "K < 1" by (simp_all add: K_def field_simps)
  11.634 +    have "(F has_field_derivative (\<Sum>n. diffs arctan_coeffs n * x ^ n)) (at x)"
  11.635 +      unfolding F_def using K by (intro termdiffs_strong[where K = K] B) simp_all
  11.636 +    also from A[OF that] have "(\<Sum>n. diffs arctan_coeffs n * x ^ n) = 1 / (1 + x^2)"
  11.637 +      by (simp add: sums_iff)
  11.638 +    finally show ?thesis .
  11.639 +  qed
  11.640 +  from assms have "arctan x - F x = arctan 0 - F 0"
  11.641 +    by (intro DERIV_isconst3[of "-1" 1 _ _ "\<lambda>x. arctan x - F x"])
  11.642 +       (auto intro!: derivative_eq_intros simp: field_simps)
  11.643 +  hence "F x = arctan x" by (simp add: F_def arctan_coeffs_def)
  11.644 +  with B[OF assms] show ?thesis by (simp add: sums_iff F_def)
  11.645 +qed
  11.646 +
  11.647 +primcorec arctan_series_stream_aux :: "bool \<Rightarrow> real \<Rightarrow> real msstream" where
  11.648 +  "arctan_series_stream_aux b n = 
  11.649 +     MSSCons (if b then -inverse n else inverse n) (arctan_series_stream_aux (\<not>b) (n + 2))"
  11.650 +
  11.651 +lemma mssnth_arctan_series_stream_aux: 
  11.652 +  "mssnth (arctan_series_stream_aux b n) m = (-1) ^ (if b then Suc m else m) / (2*m + n)"
  11.653 +  by (induction m arbitrary: b n; subst arctan_series_stream_aux.code)
  11.654 +     (auto simp: field_simps split: if_splits)
  11.655 +
  11.656 +definition arctan_series_stream where
  11.657 +  "arctan_series_stream = arctan_series_stream_aux False 1"
  11.658 +
  11.659 +lemma mssnth_arctan_series_stream:
  11.660 +  "mssnth arctan_series_stream n = (-1) ^ n / (2 * n + 1)"
  11.661 +  by (simp add: arctan_series_stream_def mssnth_arctan_series_stream_aux)
  11.662 +
  11.663 +lemma summable_pre_arctan:
  11.664 +  assumes "norm x < 1"
  11.665 +  shows   "summable (\<lambda>n. mssnth arctan_series_stream n * x ^ n)" (is "summable ?f")
  11.666 +proof (rule summable_comparison_test)
  11.667 +  show "summable (\<lambda>n. abs x ^ n)" using assms by (intro summable_geometric) auto
  11.668 +  show "\<exists>N. \<forall>n\<ge>N. norm (?f n) \<le> abs x ^ n"
  11.669 +  proof (intro exI[of _ 0] allI impI)
  11.670 +    fix n :: nat
  11.671 +    have "norm (?f n) = \<bar>x\<bar> ^ n / (2 * real n + 1)"
  11.672 +      by (simp add: mssnth_arctan_series_stream abs_mult power_abs)
  11.673 +    also have "\<dots> \<le> \<bar>x\<bar> ^ n / 1" by (intro divide_left_mono) auto
  11.674 +    finally show "norm (?f n) \<le> abs x ^ n" by simp
  11.675 +  qed
  11.676 +qed
  11.677 +
  11.678 +lemma arctan_conv_pre_arctan:
  11.679 +  assumes "norm x < 1"
  11.680 +  shows   "arctan x = x * powser (msllist_of_msstream arctan_series_stream) (x ^ 2)"
  11.681 +proof -
  11.682 +  from assms have "norm x * norm x < 1 * 1" by (intro mult_strict_mono) auto
  11.683 +  hence norm_less: "norm (x ^ 2) < 1" by (simp add: power2_eq_square)
  11.684 +  have "(\<lambda>n. arctan_coeffs n * x ^ n) sums arctan x"
  11.685 +    by (intro arctan_converges assms)
  11.686 +  also have "?this \<longleftrightarrow> (\<lambda>n. arctan_coeffs (2 * n + 1) * x ^ (2 * n + 1)) sums arctan x"
  11.687 +    by (intro sums_mono_reindex [symmetric])
  11.688 +       (auto simp: arctan_coeffs_def strict_mono_def elim!: oddE)
  11.689 +  also have "(\<lambda>n. arctan_coeffs (2 * n + 1) * x ^ (2 * n + 1)) =
  11.690 +               (\<lambda>n. x * mssnth arctan_series_stream n * (x ^ 2) ^ n)"
  11.691 +    by (simp add: fun_eq_iff mssnth_arctan_series_stream 
  11.692 +                  power_mult [symmetric] arctan_coeffs_def mult_ac)
  11.693 +  finally have "(\<lambda>n. x * mssnth arctan_series_stream n * x\<^sup>2 ^ n) sums arctan x" .
  11.694 +  thus ?thesis using summable_pre_arctan[OF norm_less] assms
  11.695 +    by (simp add: powser_def sums_iff suminf_mult [symmetric] mult.assoc)
  11.696 +qed
  11.697 +
  11.698 +lemma convergent_powser_arctan: 
  11.699 +  "convergent_powser (msllist_of_msstream arctan_series_stream)"
  11.700 +  unfolding convergent_powser_def
  11.701 +  using summable_pre_arctan by (intro exI[of _ 1]) auto
  11.702 +
  11.703 +lemma arctan_inverse_pos: "x > 0 \<Longrightarrow> arctan x = pi / 2 - arctan (inverse x)"
  11.704 +  using arctan_inverse[of x] by (simp add: field_simps)
  11.705 +    
  11.706 +lemma arctan_inverse_neg: "x < 0 \<Longrightarrow> arctan x = -pi / 2 - arctan (inverse x)"
  11.707 +  using arctan_inverse[of x] by (simp add: field_simps)
  11.708 +
  11.709 +
  11.710 +
  11.711 +subsection \<open>Multiseries\<close>
  11.712 +
  11.713 +subsubsection \<open>Asymptotic bases\<close>
  11.714 +
  11.715 +type_synonym basis = "(real \<Rightarrow> real) list"
  11.716 +
  11.717 +lemma transp_ln_smallo_ln: "transp (\<lambda>f g. (\<lambda>x::real. ln (g x)) \<in> o(\<lambda>x. ln (f x)))"
  11.718 +  by (rule transpI, erule landau_o.small.trans)
  11.719 +
  11.720 +definition basis_wf :: "basis \<Rightarrow> bool" where
  11.721 +  "basis_wf basis \<longleftrightarrow> (\<forall>f\<in>set basis. filterlim f at_top at_top) \<and> 
  11.722 +                      sorted_wrt (\<lambda>f g. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (f x))) basis"
  11.723 +
  11.724 +lemma basis_wf_Nil [simp]: "basis_wf []"
  11.725 +  by (simp add: basis_wf_def)
  11.726 +
  11.727 +lemma basis_wf_Cons: 
  11.728 +  "basis_wf (f # basis) \<longleftrightarrow> 
  11.729 +     filterlim f at_top at_top \<and> (\<forall>g\<in>set basis. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (f x))) \<and> basis_wf basis"
  11.730 +  unfolding basis_wf_def by auto
  11.731 +
  11.732 +(* TODO: Move *)
  11.733 +lemma sorted_wrt_snoc:
  11.734 +  assumes trans: "transp P" and "sorted_wrt P xs" "P (last xs) y"
  11.735 +  shows   "sorted_wrt P (xs @ [y])"
  11.736 +proof (subst sorted_wrt_append, intro conjI ballI)
  11.737 +  fix x y' assume x: "x \<in> set xs" and y': "y' \<in> set [y]"
  11.738 +  from y' have [simp]: "y' = y" by simp
  11.739 +  show "P x y'"
  11.740 +  proof (cases "x = last xs")
  11.741 +    case False
  11.742 +    from x have eq: "xs = butlast xs @ [last xs]"
  11.743 +      by (subst append_butlast_last_id) auto
  11.744 +    from x and False have x': "x \<in> set (butlast xs)" by (subst (asm) eq) auto
  11.745 +    have "sorted_wrt P xs" by fact
  11.746 +    also note eq
  11.747 +    finally have "P x (last xs)" using x'
  11.748 +      by (subst (asm) sorted_wrt_append) auto
  11.749 +    with \<open>P (last xs) y\<close> have "P x y" using transpD[OF trans] by blast
  11.750 +    thus ?thesis by simp
  11.751 +  qed (insert assms, auto)
  11.752 +qed (insert assms, auto)  
  11.753 +
  11.754 +lemma basis_wf_snoc:
  11.755 +  assumes "bs \<noteq> []"
  11.756 +  assumes "basis_wf bs" "filterlim b at_top at_top"
  11.757 +  assumes "(\<lambda>x. ln (b x)) \<in> o(\<lambda>x. ln (last bs x))"
  11.758 +  shows   "basis_wf (bs @ [b])"
  11.759 +proof -
  11.760 +  have "transp (\<lambda>f g. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (f x)))"
  11.761 +    by (auto simp: transp_def intro: landau_o.small.trans)
  11.762 +  thus ?thesis using assms
  11.763 +    by (auto simp add: basis_wf_def sorted_wrt_snoc[OF transp_ln_smallo_ln])
  11.764 +qed
  11.765 +
  11.766 +lemma basis_wf_singleton: "basis_wf [b] \<longleftrightarrow> filterlim b at_top at_top"
  11.767 +  by (simp add: basis_wf_Cons)
  11.768 +
  11.769 +lemma basis_wf_many: "basis_wf (b # b' # bs) \<longleftrightarrow>
  11.770 +  filterlim b at_top at_top \<and> (\<lambda>x. ln (b' x)) \<in> o(\<lambda>x. ln (b x)) \<and> basis_wf (b' # bs)"
  11.771 +  unfolding basis_wf_def by (subst sorted_wrt2[OF transp_ln_smallo_ln]) auto
  11.772 +
  11.773 +
  11.774 +subsubsection \<open>Monomials\<close>
  11.775 +
  11.776 +type_synonym monom = "real \<times> real list"
  11.777 +
  11.778 +definition eval_monom :: "monom \<Rightarrow> basis \<Rightarrow> real \<Rightarrow> real" where
  11.779 +  "eval_monom = (\<lambda>(c,es) basis x. c * prod_list (map (\<lambda>(b,e). b x powr e) (zip basis es)))"
  11.780 +  
  11.781 +lemma eval_monom_Nil1 [simp]: "eval_monom (c, []) basis = (\<lambda>_. c)"
  11.782 +  by (simp add: eval_monom_def split: prod.split)
  11.783 +
  11.784 +lemma eval_monom_Nil2 [simp]: "eval_monom monom [] = (\<lambda>_. fst monom)"
  11.785 +  by (simp add: eval_monom_def split: prod.split)
  11.786 +
  11.787 +lemma eval_monom_Cons: 
  11.788 +  "eval_monom (c, e # es) (b # basis) = (\<lambda>x. eval_monom (c, es) basis x * b x powr e)"
  11.789 +  by (simp add: eval_monom_def fun_eq_iff split: prod.split)
  11.790 +
  11.791 +definition inverse_monom :: "monom \<Rightarrow> monom" where
  11.792 +  "inverse_monom monom = (case monom of (c, es) \<Rightarrow> (inverse c, map uminus es))"
  11.793 +
  11.794 +lemma length_snd_inverse_monom [simp]: 
  11.795 +  "length (snd (inverse_monom monom)) = length (snd monom)"
  11.796 +  by (simp add: inverse_monom_def split: prod.split)
  11.797 +
  11.798 +lemma eval_monom_pos:
  11.799 +  assumes "basis_wf basis" "fst monom > 0"
  11.800 +  shows   "eventually (\<lambda>x. eval_monom monom basis x > 0) at_top"
  11.801 +proof (cases monom)
  11.802 +  case (Pair c es)
  11.803 +  with assms have "c > 0" by simp
  11.804 +  with assms(1) show ?thesis unfolding Pair
  11.805 +  proof (induction es arbitrary: basis)
  11.806 +    case (Cons e es)
  11.807 +    note A = this
  11.808 +    thus ?case
  11.809 +    proof (cases basis)
  11.810 +      case (Cons b basis')
  11.811 +      with A(1)[of basis'] A(2,3) 
  11.812 +        have A: "\<forall>\<^sub>F x in at_top. eval_monom (c, es) basis' x > 0" 
  11.813 +         and B: "eventually (\<lambda>x. b x > 0) at_top"
  11.814 +        by (simp_all add: basis_wf_Cons filterlim_at_top_dense)
  11.815 +      thus ?thesis by eventually_elim (simp add: Cons eval_monom_Cons)
  11.816 +    qed simp
  11.817 +  qed simp
  11.818 +qed
  11.819 +
  11.820 +lemma eval_monom_uminus: "eval_monom (-c, es) basis x = -eval_monom (c, es) basis x"
  11.821 +  by (simp add: eval_monom_def)
  11.822 +
  11.823 +lemma eval_monom_neg:
  11.824 +  assumes "basis_wf basis" "fst monom < 0"
  11.825 +  shows   "eventually (\<lambda>x. eval_monom monom basis x < 0) at_top"    
  11.826 +proof -
  11.827 +  from assms have "eventually (\<lambda>x. eval_monom (-fst monom, snd monom) basis x > 0) at_top"
  11.828 +    by (intro eval_monom_pos) simp_all
  11.829 +  thus ?thesis by (simp add: eval_monom_uminus)
  11.830 +qed
  11.831 +
  11.832 +lemma eval_monom_nonzero:
  11.833 +  assumes "basis_wf basis" "fst monom \<noteq> 0"
  11.834 +  shows   "eventually (\<lambda>x. eval_monom monom basis x \<noteq> 0) at_top"
  11.835 +proof (cases "fst monom" "0 :: real" rule: linorder_cases)
  11.836 +  case greater
  11.837 +  with assms have "eventually (\<lambda>x. eval_monom monom basis x > 0) at_top"
  11.838 +    by (simp add: eval_monom_pos)
  11.839 +  thus ?thesis by eventually_elim simp
  11.840 +next
  11.841 +  case less
  11.842 +  with assms have "eventually (\<lambda>x. eval_monom (-fst monom, snd monom) basis x > 0) at_top"
  11.843 +    by (simp add: eval_monom_pos)
  11.844 +  thus ?thesis by eventually_elim (simp add: eval_monom_uminus)
  11.845 +qed (insert assms, simp_all)
  11.846 +
  11.847 +
  11.848 +subsubsection \<open>Typeclass for multiseries\<close>
  11.849 +
  11.850 +class multiseries = plus + minus + times + uminus + inverse + 
  11.851 +  fixes is_expansion :: "'a \<Rightarrow> basis \<Rightarrow> bool"
  11.852 +    and expansion_level :: "'a itself \<Rightarrow> nat"
  11.853 +    and eval :: "'a \<Rightarrow> real \<Rightarrow> real"
  11.854 +    and zero_expansion :: 'a
  11.855 +    and const_expansion :: "real \<Rightarrow> 'a"
  11.856 +    and powr_expansion :: "bool \<Rightarrow> 'a \<Rightarrow> real \<Rightarrow> 'a"
  11.857 +    and power_expansion :: "bool \<Rightarrow> 'a \<Rightarrow> nat \<Rightarrow> 'a"
  11.858 +    and trimmed :: "'a \<Rightarrow> bool"
  11.859 +    and dominant_term :: "'a \<Rightarrow> monom"
  11.860 +
  11.861 +  assumes is_expansion_length:
  11.862 +    "is_expansion F basis \<Longrightarrow> length basis = expansion_level (TYPE('a))"
  11.863 +  assumes is_expansion_zero:
  11.864 +    "basis_wf basis \<Longrightarrow> length basis = expansion_level (TYPE('a)) \<Longrightarrow> 
  11.865 +       is_expansion zero_expansion basis"
  11.866 +  assumes is_expansion_const:
  11.867 +    "basis_wf basis \<Longrightarrow> length basis = expansion_level (TYPE('a)) \<Longrightarrow> 
  11.868 +       is_expansion (const_expansion c) basis"
  11.869 +  assumes is_expansion_uminus:
  11.870 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> is_expansion (-F) basis"
  11.871 +  assumes is_expansion_add: 
  11.872 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> is_expansion G basis \<Longrightarrow> 
  11.873 +       is_expansion (F + G) basis"
  11.874 +  assumes is_expansion_minus: 
  11.875 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> is_expansion G basis \<Longrightarrow> 
  11.876 +       is_expansion (F - G) basis"
  11.877 +  assumes is_expansion_mult: 
  11.878 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> is_expansion G basis \<Longrightarrow> 
  11.879 +       is_expansion (F * G) basis"
  11.880 +  assumes is_expansion_inverse:
  11.881 +    "basis_wf basis \<Longrightarrow> trimmed F \<Longrightarrow> is_expansion F basis \<Longrightarrow> 
  11.882 +       is_expansion (inverse F) basis"
  11.883 +  assumes is_expansion_divide:
  11.884 +    "basis_wf basis \<Longrightarrow> trimmed G \<Longrightarrow> is_expansion F basis \<Longrightarrow> is_expansion G basis \<Longrightarrow> 
  11.885 +       is_expansion (F / G) basis"
  11.886 +  assumes is_expansion_powr:
  11.887 +    "basis_wf basis \<Longrightarrow> trimmed F \<Longrightarrow> fst (dominant_term F) > 0 \<Longrightarrow> is_expansion F basis \<Longrightarrow>
  11.888 +       is_expansion (powr_expansion abort F p) basis"
  11.889 +  assumes is_expansion_power:
  11.890 +    "basis_wf basis \<Longrightarrow> trimmed F \<Longrightarrow> is_expansion F basis \<Longrightarrow>
  11.891 +       is_expansion (power_expansion abort F n) basis"
  11.892 +  
  11.893 +  assumes is_expansion_imp_smallo:
  11.894 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> filterlim b at_top at_top \<Longrightarrow>
  11.895 +       (\<forall>g\<in>set basis. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (b x))) \<Longrightarrow> e > 0 \<Longrightarrow> eval F \<in> o(\<lambda>x. b x powr e)"
  11.896 +  assumes is_expansion_imp_smallomega:
  11.897 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> filterlim b at_top at_top \<Longrightarrow> trimmed F \<Longrightarrow> 
  11.898 +       (\<forall>g\<in>set basis. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (b x))) \<Longrightarrow> e < 0 \<Longrightarrow> eval F \<in> \<omega>(\<lambda>x. b x powr e)"
  11.899 +  assumes trimmed_imp_eventually_sgn:
  11.900 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> trimmed F \<Longrightarrow>
  11.901 +       eventually (\<lambda>x. sgn (eval F x) = sgn (fst (dominant_term F))) at_top"
  11.902 +  assumes trimmed_imp_eventually_nz: 
  11.903 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> trimmed F \<Longrightarrow> 
  11.904 +       eventually (\<lambda>x. eval F x \<noteq> 0) at_top"
  11.905 +  assumes trimmed_imp_dominant_term_nz: "trimmed F \<Longrightarrow> fst (dominant_term F) \<noteq> 0"
  11.906 +  
  11.907 +  assumes dominant_term: 
  11.908 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow> trimmed F \<Longrightarrow>
  11.909 +       eval F \<sim>[at_top] eval_monom (dominant_term F) basis"
  11.910 +  assumes dominant_term_bigo:
  11.911 +    "basis_wf basis \<Longrightarrow> is_expansion F basis \<Longrightarrow>
  11.912 +       eval F \<in> O(eval_monom (1, snd (dominant_term F)) basis)"
  11.913 +  assumes length_dominant_term:
  11.914 +    "length (snd (dominant_term F)) = expansion_level TYPE('a)"
  11.915 +  assumes fst_dominant_term_uminus [simp]: "fst (dominant_term (- F)) = -fst (dominant_term F)"
  11.916 +  assumes trimmed_uminus_iff [simp]: "trimmed (-F) \<longleftrightarrow> trimmed F"
  11.917 +  
  11.918 +  assumes add_zero_expansion_left [simp]: "zero_expansion + F = F"
  11.919 +  assumes add_zero_expansion_right [simp]: "F + zero_expansion = F"
  11.920 +  
  11.921 +  assumes eval_zero [simp]: "eval zero_expansion x = 0"
  11.922 +  assumes eval_const [simp]: "eval (const_expansion c) x = c"
  11.923 +  assumes eval_uminus [simp]: "eval (-F) = (\<lambda>x. -eval F x)"
  11.924 +  assumes eval_plus [simp]: "eval (F + G) = (\<lambda>x. eval F x + eval G x)"
  11.925 +  assumes eval_minus [simp]: "eval (F - G) = (\<lambda>x. eval F x - eval G x)"
  11.926 +  assumes eval_times [simp]: "eval (F * G) = (\<lambda>x. eval F x * eval G x)"
  11.927 +  assumes eval_inverse [simp]: "eval (inverse F) = (\<lambda>x. inverse (eval F x))"
  11.928 +  assumes eval_divide [simp]: "eval (F / G) = (\<lambda>x. eval F x / eval G x)"
  11.929 +  assumes eval_powr [simp]: "eval (powr_expansion abort F p) = (\<lambda>x. eval F x powr p)"
  11.930 +  assumes eval_power [simp]: "eval (power_expansion abort F n) = (\<lambda>x. eval F x ^ n)"
  11.931 +  assumes minus_eq_plus_uminus: "F - G = F + (-G)"
  11.932 +  assumes times_const_expansion_1: "const_expansion 1 * F = F"
  11.933 +  assumes trimmed_const_expansion: "trimmed (const_expansion c) \<longleftrightarrow> c \<noteq> 0"
  11.934 +begin
  11.935 +
  11.936 +definition trimmed_pos where
  11.937 +  "trimmed_pos F \<longleftrightarrow> trimmed F \<and> fst (dominant_term F) > 0"
  11.938 +
  11.939 +definition trimmed_neg where
  11.940 +  "trimmed_neg F \<longleftrightarrow> trimmed F \<and> fst (dominant_term F) < 0"
  11.941 +
  11.942 +lemma trimmed_pos_uminus: "trimmed_neg F \<Longrightarrow> trimmed_pos (-F)"
  11.943 +  by (simp add: trimmed_neg_def trimmed_pos_def)
  11.944 +
  11.945 +lemma trimmed_pos_imp_trimmed: "trimmed_pos x \<Longrightarrow> trimmed x"
  11.946 +  by (simp add: trimmed_pos_def)
  11.947 +
  11.948 +lemma trimmed_neg_imp_trimmed: "trimmed_neg x \<Longrightarrow> trimmed x"
  11.949 +  by (simp add: trimmed_neg_def)
  11.950 +
  11.951 +end
  11.952 +
  11.953 +
  11.954 +subsubsection \<open>Zero-rank expansions\<close>
  11.955 +
  11.956 +instantiation real :: multiseries
  11.957 +begin
  11.958 +
  11.959 +inductive is_expansion_real :: "real \<Rightarrow> basis \<Rightarrow> bool" where
  11.960 +  "is_expansion_real c []"
  11.961 +  
  11.962 +definition expansion_level_real :: "real itself \<Rightarrow> nat" where
  11.963 +  expansion_level_real_def [simp]: "expansion_level_real _ = 0"
  11.964 +
  11.965 +definition eval_real :: "real \<Rightarrow> real \<Rightarrow> real" where
  11.966 +  eval_real_def [simp]: "eval_real c = (\<lambda>_. c)"
  11.967 +
  11.968 +definition zero_expansion_real :: "real" where
  11.969 +  zero_expansion_real_def [simp]: "zero_expansion_real = 0"
  11.970 +  
  11.971 +definition const_expansion_real :: "real \<Rightarrow> real" where
  11.972 +  const_expansion_real_def [simp]: "const_expansion_real x = x"
  11.973 +
  11.974 +definition powr_expansion_real :: "bool \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real" where
  11.975 +  powr_expansion_real_def [simp]: "powr_expansion_real _ x p = x powr p"
  11.976 +
  11.977 +definition power_expansion_real :: "bool \<Rightarrow> real \<Rightarrow> nat \<Rightarrow> real" where
  11.978 +  power_expansion_real_def [simp]: "power_expansion_real _ x n = x ^ n"
  11.979 +
  11.980 +definition trimmed_real :: "real \<Rightarrow> bool" where
  11.981 +  trimmed_real_def [simp]: "trimmed_real x \<longleftrightarrow> x \<noteq> 0"
  11.982 +
  11.983 +definition dominant_term_real :: "real \<Rightarrow> monom" where
  11.984 +  dominant_term_real_def [simp]: "dominant_term_real c = (c, [])"
  11.985 +
  11.986 +instance proof
  11.987 +  fix basis :: basis and b :: "real \<Rightarrow> real" and e F :: real
  11.988 +  assume *: "basis_wf basis" "filterlim b at_top at_top" "is_expansion F basis" "0 < e"
  11.989 +  have "(\<lambda>x. b x powr e) \<in> \<omega>(\<lambda>_. 1)"
  11.990 +    by (intro smallomegaI_filterlim_at_infinity filterlim_at_top_imp_at_infinity) 
  11.991 +       (auto intro!: filterlim_compose[OF real_powr_at_top] * )
  11.992 +  with * show "eval F \<in> o(\<lambda>x. b x powr e)"
  11.993 +    by (cases "F = 0") (auto elim!: is_expansion_real.cases simp: smallomega_iff_smallo)
  11.994 +next
  11.995 +  fix basis :: basis and b :: "real \<Rightarrow> real" and e F :: real
  11.996 +  assume *: "basis_wf basis" "filterlim b at_top at_top" "is_expansion F basis" 
  11.997 +            "e < 0" "trimmed F"
  11.998 +  from * have pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
  11.999 +  have "(\<lambda>x. b x powr -e) \<in> \<omega>(\<lambda>_. 1)"
 11.1000 +    by (intro smallomegaI_filterlim_at_infinity filterlim_at_top_imp_at_infinity) 
 11.1001 +       (auto intro!: filterlim_compose[OF real_powr_at_top] * )
 11.1002 +  with pos have "(\<lambda>x. b x powr e) \<in> o(\<lambda>_. 1)" unfolding powr_minus
 11.1003 +    by (subst (asm) landau_omega.small.inverse_eq2)
 11.1004 +       (auto elim: eventually_mono simp: smallomega_iff_smallo)
 11.1005 +  with * show "eval F \<in> \<omega>(\<lambda>x. b x powr e)"
 11.1006 +    by (auto elim!: is_expansion_real.cases simp: smallomega_iff_smallo)
 11.1007 +qed (auto intro!: is_expansion_real.intros elim!: is_expansion_real.cases)
 11.1008 +
 11.1009 +end
 11.1010 +
 11.1011 +lemma eval_real: "eval (c :: real) x = c" by simp
 11.1012 +
 11.1013 +
 11.1014 +subsubsection \<open>Operations on multiseries\<close>
 11.1015 +
 11.1016 +lemma ms_aux_cases [case_names MSLNil MSLCons]:
 11.1017 +  fixes xs :: "('a \<times> real) msllist"
 11.1018 +  obtains "xs = MSLNil" | c e xs' where "xs = MSLCons (c, e) xs'"
 11.1019 +proof (cases xs)
 11.1020 +  case (MSLCons x xs')
 11.1021 +  with that(2)[of "fst x" "snd x" xs'] show ?thesis by auto
 11.1022 +qed auto
 11.1023 +
 11.1024 +definition ms_aux_hd_exp :: "('a \<times> real) msllist \<Rightarrow> real option" where
 11.1025 +  "ms_aux_hd_exp xs = (case xs of MSLNil \<Rightarrow> None | MSLCons (_, e) _ \<Rightarrow> Some e)"
 11.1026 +
 11.1027 +primrec ms_exp_gt :: "real \<Rightarrow> real option \<Rightarrow> bool" where
 11.1028 +  "ms_exp_gt x None = True"
 11.1029 +| "ms_exp_gt x (Some y) \<longleftrightarrow> x > y"
 11.1030 +
 11.1031 +lemma ms_aux_hd_exp_MSLNil [simp]: "ms_aux_hd_exp MSLNil = None"
 11.1032 +  by (simp add: ms_aux_hd_exp_def split: prod.split)
 11.1033 +  
 11.1034 +lemma ms_aux_hd_exp_MSLCons [simp]: "ms_aux_hd_exp (MSLCons x xs) = Some (snd x)"
 11.1035 +  by (simp add: ms_aux_hd_exp_def split: prod.split)
 11.1036 +
 11.1037 +coinductive is_expansion_aux :: 
 11.1038 +    "('a :: multiseries \<times> real) msllist \<Rightarrow> (real \<Rightarrow> real) \<Rightarrow> basis \<Rightarrow> bool" where
 11.1039 +  is_expansion_MSLNil: 
 11.1040 +    "eventually (\<lambda>x. f x = 0) at_top \<Longrightarrow> length basis = Suc (expansion_level TYPE('a)) \<Longrightarrow>
 11.1041 +       is_expansion_aux MSLNil f basis"
 11.1042 +| is_expansion_MSLCons: 
 11.1043 +    "is_expansion_aux xs (\<lambda>x. f x - eval C x * b x powr e) (b # basis) \<Longrightarrow>
 11.1044 +       is_expansion C basis \<Longrightarrow>
 11.1045 +       (\<And>e'. e' > e \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')) \<Longrightarrow> ms_exp_gt e (ms_aux_hd_exp xs) \<Longrightarrow>
 11.1046 +       is_expansion_aux (MSLCons (C, e) xs) f (b # basis)"
 11.1047 +
 11.1048 +inductive_cases is_expansion_aux_MSLCons: "is_expansion_aux (MSLCons (c, e) xs) f basis"
 11.1049 + 
 11.1050 +lemma is_expansion_aux_basis_nonempty: "is_expansion_aux F f basis \<Longrightarrow> basis \<noteq> []"
 11.1051 +  by (erule is_expansion_aux.cases) auto
 11.1052 +
 11.1053 +lemma is_expansion_aux_expansion_level:
 11.1054 +  assumes "is_expansion_aux (G :: ('a::multiseries \<times> real) msllist) g basis"
 11.1055 +  shows   "length basis = Suc (expansion_level TYPE('a))"
 11.1056 +  using assms by (cases rule: is_expansion_aux.cases) (auto dest: is_expansion_length)  
 11.1057 +
 11.1058 +lemma is_expansion_aux_imp_smallo:
 11.1059 +  assumes "is_expansion_aux xs f basis" "ms_exp_gt p (ms_aux_hd_exp xs)" 
 11.1060 +  shows   "f \<in> o(\<lambda>x. hd basis x powr p)"
 11.1061 +  using assms
 11.1062 +proof (cases rule: is_expansion_aux.cases)
 11.1063 +  case is_expansion_MSLNil
 11.1064 +  show ?thesis by (simp add: landau_o.small.in_cong[OF is_expansion_MSLNil(2)])
 11.1065 +next
 11.1066 +  case (is_expansion_MSLCons xs C b e basis)
 11.1067 +  with assms have "f \<in> o(\<lambda>x. b x powr p)"
 11.1068 +    by (intro is_expansion_MSLCons) (simp_all add: ms_aux_hd_exp_def)
 11.1069 +  thus ?thesis by (simp add: is_expansion_MSLCons)
 11.1070 +qed
 11.1071 +
 11.1072 +lemma is_expansion_aux_imp_smallo':
 11.1073 +  assumes "is_expansion_aux xs f basis"
 11.1074 +  obtains e where "f \<in> o(\<lambda>x. hd basis x powr e)"
 11.1075 +proof -
 11.1076 +  define e where "e = (case ms_aux_hd_exp xs of None \<Rightarrow> 0 | Some e \<Rightarrow> e + 1)"
 11.1077 +  have "ms_exp_gt e (ms_aux_hd_exp xs)"
 11.1078 +    by (auto simp add: e_def ms_aux_hd_exp_def split: msllist.splits)
 11.1079 +  from assms this have "f \<in> o(\<lambda>x. hd basis x powr e)" by (rule is_expansion_aux_imp_smallo)
 11.1080 +  from that[OF this] show ?thesis .
 11.1081 +qed
 11.1082 +
 11.1083 +lemma is_expansion_aux_imp_smallo'':
 11.1084 +  assumes "is_expansion_aux xs f basis" "ms_exp_gt e' (ms_aux_hd_exp xs)"
 11.1085 +  obtains e where "e < e'" "f \<in> o(\<lambda>x. hd basis x powr e)"
 11.1086 +proof -
 11.1087 +  define e where "e = (case ms_aux_hd_exp xs of None \<Rightarrow> e' - 1 | Some e \<Rightarrow> (e' + e) / 2)"
 11.1088 +  from assms have "ms_exp_gt e (ms_aux_hd_exp xs)" "e < e'"
 11.1089 +    by (cases xs; simp add: e_def field_simps)+
 11.1090 +  from assms(1) this(1) have "f \<in> o(\<lambda>x. hd basis x powr e)" by (rule is_expansion_aux_imp_smallo)
 11.1091 +  from that[OF \<open>e < e'\<close> this] show ?thesis .
 11.1092 +qed
 11.1093 +
 11.1094 +definition trimmed_ms_aux :: "('a :: multiseries \<times> real) msllist \<Rightarrow> bool" where
 11.1095 +  "trimmed_ms_aux xs = (case xs of MSLNil \<Rightarrow> False | MSLCons (C, _) _ \<Rightarrow> trimmed C)"
 11.1096 + 
 11.1097 +lemma not_trimmed_ms_aux_MSLNil [simp]: "\<not>trimmed_ms_aux MSLNil"
 11.1098 +  by (simp add: trimmed_ms_aux_def)
 11.1099 +
 11.1100 +lemma trimmed_ms_aux_MSLCons: "trimmed_ms_aux (MSLCons x xs) = trimmed (fst x)"
 11.1101 +  by (simp add: trimmed_ms_aux_def split: prod.split)
 11.1102 +
 11.1103 +lemma trimmed_ms_aux_imp_nz:
 11.1104 +  assumes "basis_wf basis" "is_expansion_aux xs f basis" "trimmed_ms_aux xs"
 11.1105 +  shows   "eventually (\<lambda>x. f x \<noteq> 0) at_top"
 11.1106 +proof (cases xs rule: ms_aux_cases)
 11.1107 +  case (MSLCons C e xs')
 11.1108 +  from assms this obtain b basis' where *: "basis = b # basis'"
 11.1109 +    "is_expansion_aux xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')" 
 11.1110 +    "ms_exp_gt e (ms_aux_hd_exp xs')" "is_expansion C basis'" "\<And>e'. e' > e \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')"
 11.1111 +    by (auto elim!: is_expansion_aux_MSLCons)
 11.1112 +  from assms(1,3) * have nz: "eventually (\<lambda>x. eval C x \<noteq> 0) at_top"
 11.1113 +    by (auto simp: trimmed_ms_aux_def MSLCons basis_wf_Cons
 11.1114 +             intro: trimmed_imp_eventually_nz[of basis'])
 11.1115 +  from assms(1) * have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1116 +  hence b_nz: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.1117 +  
 11.1118 +  from is_expansion_aux_imp_smallo''[OF *(2,3)]
 11.1119 +  obtain e' where e': "e' < e" "(\<lambda>x. f x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr e')"
 11.1120 +    unfolding list.sel by blast
 11.1121 +  note this(2)
 11.1122 +  also have "\<dots> = o(\<lambda>x. b x powr (e' - e) * b x powr e)" by (simp add: powr_add [symmetric])
 11.1123 +  also from assms * e' have "eval C \<in> \<omega>(\<lambda>x. b x powr (e' - e))"
 11.1124 +    by (intro is_expansion_imp_smallomega[OF _ *(4)])
 11.1125 +       (simp_all add: MSLCons basis_wf_Cons trimmed_ms_aux_def)
 11.1126 +  hence "(\<lambda>x. b x powr (e' - e) * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.1127 +    by (intro landau_o.small_big_mult is_expansion_imp_smallomega) 
 11.1128 +       (simp_all add: smallomega_iff_smallo)
 11.1129 +  finally have "(\<lambda>x. f x - eval C x * b x powr e + eval C x * b x powr e) \<in> 
 11.1130 +                  \<Theta>(\<lambda>x. eval C x * b x powr e)"
 11.1131 +    by (subst bigtheta_sym, subst landau_theta.plus_absorb1) simp_all
 11.1132 +  hence theta: "f \<in> \<Theta>(\<lambda>x. eval C x * b x powr e)" by simp
 11.1133 +  have "eventually (\<lambda>x. eval C x * b x powr e \<noteq> 0) at_top"
 11.1134 +    using b_nz nz by eventually_elim simp
 11.1135 +  thus ?thesis by (subst eventually_nonzero_bigtheta [OF theta])
 11.1136 +qed (insert assms, simp_all add: trimmed_ms_aux_def)
 11.1137 +
 11.1138 +lemma is_expansion_aux_imp_smallomega:
 11.1139 +  assumes "basis_wf basis" "is_expansion_aux xs f basis" "filterlim b' at_top at_top"
 11.1140 +          "trimmed_ms_aux xs" "\<forall>g\<in>set basis. (\<lambda>x. ln (g x)) \<in> o(\<lambda>x. ln (b' x))" "r < 0"
 11.1141 +  shows   "f \<in> \<omega>(\<lambda>x. b' x powr r)"
 11.1142 +proof (cases xs rule: ms_aux_cases)
 11.1143 +  case (MSLCons C e xs')
 11.1144 +  from assms this obtain b basis' where *: "basis = b # basis'" "trimmed C"
 11.1145 +    "is_expansion_aux xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.1146 +    "ms_exp_gt e (ms_aux_hd_exp xs')"
 11.1147 +    "is_expansion C basis'" "\<And>e'. e' > e \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')"
 11.1148 +    by (auto elim!: is_expansion_aux_MSLCons simp: trimmed_ms_aux_def)
 11.1149 +  from assms * have nz: "eventually (\<lambda>x. eval C x \<noteq> 0) at_top"
 11.1150 +    by (intro trimmed_imp_eventually_nz[of basis']) (simp_all add: basis_wf_Cons)
 11.1151 +  from assms(1) * have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1152 +  hence b_nz: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.1153 +  
 11.1154 +  from is_expansion_aux_imp_smallo''[OF *(3,4)]
 11.1155 +  obtain e' where e': "e' < e" "(\<lambda>x. f x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr e')"
 11.1156 +    unfolding list.sel by blast
 11.1157 +  note this(2)
 11.1158 +  also have "\<dots> = o(\<lambda>x. b x powr (e' - e) * b x powr e)" by (simp add: powr_add [symmetric])
 11.1159 +  also from assms * e' have "eval C \<in> \<omega>(\<lambda>x. b x powr (e' - e))"
 11.1160 +    by (intro is_expansion_imp_smallomega[OF _ *(5)])
 11.1161 +       (simp_all add: MSLCons basis_wf_Cons trimmed_ms_aux_def)
 11.1162 +  hence "(\<lambda>x. b x powr (e' - e) * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.1163 +    by (intro landau_o.small_big_mult is_expansion_imp_smallomega) 
 11.1164 +       (simp_all add: smallomega_iff_smallo)
 11.1165 +  finally have "(\<lambda>x. f x - eval C x * b x powr e + eval C x * b x powr e) \<in> 
 11.1166 +                  \<Theta>(\<lambda>x. eval C x * b x powr e)"
 11.1167 +    by (subst bigtheta_sym, subst landau_theta.plus_absorb1) simp_all
 11.1168 +  hence theta: "f \<in> \<Theta>(\<lambda>x. eval C x * b x powr e)" by simp
 11.1169 +  also from * assms e' have "(\<lambda>x. eval C x * b x powr e) \<in> \<omega>(\<lambda>x. b x powr (e' - e) * b x powr e)"
 11.1170 +    by (intro landau_omega.small_big_mult is_expansion_imp_smallomega[of basis'])
 11.1171 +       (simp_all add: basis_wf_Cons)
 11.1172 +  also have "\<dots> = \<omega>(\<lambda>x. b x powr e')" by (simp add: powr_add [symmetric])
 11.1173 +  also from *(1) assms have "(\<lambda>x. b x powr e') \<in> \<omega>(\<lambda>x. b' x powr r)"
 11.1174 +    unfolding smallomega_iff_smallo by (intro ln_smallo_imp_flat') (simp_all add: basis_wf_Cons)
 11.1175 +  finally show ?thesis .
 11.1176 +qed (insert assms, simp_all add: trimmed_ms_aux_def)  
 11.1177 +
 11.1178 +definition dominant_term_ms_aux :: "('a :: multiseries \<times> real) msllist \<Rightarrow> monom" where
 11.1179 +  "dominant_term_ms_aux xs =
 11.1180 +     (case xs of MSLNil \<Rightarrow> (0, replicate (Suc (expansion_level TYPE('a))) 0)
 11.1181 +               | MSLCons (C, e) _ \<Rightarrow> case dominant_term C of (c, es) \<Rightarrow> (c, e # es))"
 11.1182 +
 11.1183 +lemma dominant_term_ms_aux_MSLCons: 
 11.1184 +  "dominant_term_ms_aux (MSLCons (C, e) xs) = map_prod id (\<lambda>es. e # es) (dominant_term C)"
 11.1185 +  by (simp add: dominant_term_ms_aux_def case_prod_unfold map_prod_def)
 11.1186 +
 11.1187 +lemma length_dominant_term_ms_aux [simp]:
 11.1188 +  "length (snd (dominant_term_ms_aux (xs :: ('a :: multiseries \<times> real) msllist))) = 
 11.1189 +     Suc (expansion_level TYPE('a))"
 11.1190 +proof (cases xs rule: ms_aux_cases)
 11.1191 +  case (MSLCons C e xs')
 11.1192 +  hence "length (snd (dominant_term_ms_aux xs)) = Suc (length (snd (dominant_term C)))"
 11.1193 +    by (simp add: dominant_term_ms_aux_def split: prod.splits)
 11.1194 +  also note length_dominant_term
 11.1195 +  finally show ?thesis .
 11.1196 +qed (simp_all add: dominant_term_ms_aux_def split: msllist.splits prod.splits)
 11.1197 +
 11.1198 +definition const_ms_aux :: "real \<Rightarrow> ('a :: multiseries \<times> real) msllist" where
 11.1199 +  "const_ms_aux c = MSLCons (const_expansion c, 0) MSLNil"
 11.1200 +
 11.1201 +definition uminus_ms_aux :: "('a :: uminus \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1202 +  "uminus_ms_aux xs = mslmap (map_prod uminus id) xs"
 11.1203 +  
 11.1204 +corec (friend) plus_ms_aux :: "('a :: plus \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1205 +  "plus_ms_aux xs ys =
 11.1206 +     (case (xs, ys) of
 11.1207 +        (MSLNil, MSLNil) \<Rightarrow> MSLNil
 11.1208 +      | (MSLNil, MSLCons y ys) \<Rightarrow> MSLCons y ys
 11.1209 +      | (MSLCons x xs, MSLNil) \<Rightarrow> MSLCons x xs
 11.1210 +      | (MSLCons x xs, MSLCons y ys) \<Rightarrow>
 11.1211 +          if snd x > snd y then MSLCons x (plus_ms_aux xs (MSLCons y ys))
 11.1212 +          else if snd x < snd y then MSLCons y (plus_ms_aux (MSLCons x xs) ys)
 11.1213 +          else MSLCons (fst x + fst y, snd x) (plus_ms_aux xs ys))"
 11.1214 +
 11.1215 +context
 11.1216 +begin
 11.1217 +
 11.1218 +friend_of_corec mslmap where
 11.1219 +  "mslmap (f :: 'a \<Rightarrow> 'a) xs = 
 11.1220 +     (case xs of MSLNil \<Rightarrow> MSLNil | MSLCons x xs \<Rightarrow> MSLCons (f x) (mslmap f xs))"
 11.1221 +   by (simp split: msllist.splits, transfer_prover)
 11.1222 +
 11.1223 +corec (friend) times_ms_aux
 11.1224 +     :: "('a :: {plus,times} \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1225 +  "times_ms_aux xs ys =
 11.1226 +     (case (xs, ys) of
 11.1227 +        (MSLNil, ys) \<Rightarrow> MSLNil
 11.1228 +      | (xs, MSLNil) \<Rightarrow> MSLNil
 11.1229 +      | (MSLCons x xs, MSLCons y ys) \<Rightarrow>
 11.1230 +           MSLCons (fst x * fst y, snd x + snd y) 
 11.1231 +             (plus_ms_aux (mslmap (map_prod (( *) (fst x)) ((+) (snd x))) ys)
 11.1232 +               (times_ms_aux xs (MSLCons y ys))))"
 11.1233 +
 11.1234 +definition scale_shift_ms_aux :: "('a :: times \<times> real) \<Rightarrow> ('a \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1235 +  "scale_shift_ms_aux = (\<lambda>(a,b) xs. mslmap (map_prod (( *) a) ((+) b)) xs)"
 11.1236 +
 11.1237 +lemma times_ms_aux_altdef:
 11.1238 +  "times_ms_aux xs ys = 
 11.1239 +     (case (xs, ys) of
 11.1240 +        (MSLNil, ys) \<Rightarrow> MSLNil
 11.1241 +      | (xs, MSLNil) \<Rightarrow> MSLNil
 11.1242 +      | (MSLCons x xs, MSLCons y ys) \<Rightarrow>
 11.1243 +          MSLCons (fst x * fst y, snd x + snd y)
 11.1244 +            (plus_ms_aux (scale_shift_ms_aux x ys) (times_ms_aux xs (MSLCons y ys))))"
 11.1245 +  by (subst times_ms_aux.code) (simp_all add: scale_shift_ms_aux_def split: msllist.splits)
 11.1246 +end
 11.1247 +
 11.1248 +corec powser_ms_aux :: "real msllist \<Rightarrow> ('a :: multiseries \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1249 +  "powser_ms_aux cs xs = (case cs of MSLNil \<Rightarrow> MSLNil | MSLCons c cs \<Rightarrow>
 11.1250 +     MSLCons (const_expansion c, 0) (times_ms_aux xs (powser_ms_aux cs xs)))"
 11.1251 +  
 11.1252 +definition minus_ms_aux :: "('a :: multiseries \<times> real) msllist \<Rightarrow> _" where
 11.1253 +  "minus_ms_aux xs ys = plus_ms_aux xs (uminus_ms_aux ys)"
 11.1254 +
 11.1255 +lemma is_expansion_aux_coinduct [consumes 1, case_names is_expansion_aux]:
 11.1256 +  fixes xs :: "('a :: multiseries \<times> real) msllist"
 11.1257 +  assumes "X xs f basis" "(\<And>xs f basis. X xs f basis \<Longrightarrow> 
 11.1258 +     (xs = MSLNil \<and> (\<forall>\<^sub>F x in at_top. f x = 0) \<and> length basis = Suc (expansion_level TYPE('a))) \<or>
 11.1259 +     (\<exists>xs' b e basis' C. xs = MSLCons (C, e) xs' \<and> basis = b # basis' \<and>
 11.1260 +        (X xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')) \<and> is_expansion C basis' \<and>
 11.1261 +        (\<forall>x>e. f \<in> o(\<lambda>xa. b xa powr x)) \<and> ms_exp_gt e (ms_aux_hd_exp xs')))"
 11.1262 +  shows "is_expansion_aux xs f basis"
 11.1263 +using assms(1)
 11.1264 +proof (coinduction arbitrary: xs f)
 11.1265 +  case (is_expansion_aux xs f)
 11.1266 +  from assms(2)[OF is_expansion_aux] show ?case by blast
 11.1267 +qed 
 11.1268 +
 11.1269 +lemma is_expansion_aux_cong:
 11.1270 +  assumes "is_expansion_aux F f basis"
 11.1271 +  assumes "eventually (\<lambda>x. f x = g x) at_top"
 11.1272 +  shows   "is_expansion_aux F g basis"
 11.1273 +  using assms
 11.1274 +proof (coinduction arbitrary: F f g rule: is_expansion_aux_coinduct)
 11.1275 +  case (is_expansion_aux F f g)
 11.1276 +  from this have ev: "eventually (\<lambda>x. g x = f x) at_top" by (simp add: eq_commute)
 11.1277 +  from ev have [simp]: "eventually (\<lambda>x. g x = 0) at_top \<longleftrightarrow> eventually (\<lambda>x. f x = 0) at_top"
 11.1278 +    by (rule eventually_subst')
 11.1279 +  from ev have [simp]: "(\<forall>\<^sub>F x in at_top. h x = g x - h' x) \<longleftrightarrow>
 11.1280 +                          (\<forall>\<^sub>F x in at_top. h x = f x - h' x)" for h h'
 11.1281 +      by (rule eventually_subst')
 11.1282 +  note [simp] = landau_o.small.in_cong[OF ev]
 11.1283 +  from is_expansion_aux(1) show ?case
 11.1284 +    by (cases rule: is_expansion_aux.cases) force+  
 11.1285 +qed
 11.1286 +
 11.1287 +lemma scale_shift_ms_aux_conv_mslmap: 
 11.1288 +  "scale_shift_ms_aux x = mslmap (map_prod (( *) (fst x)) ((+) (snd x)))"
 11.1289 +  by (rule ext) (simp add: scale_shift_ms_aux_def map_prod_def case_prod_unfold)
 11.1290 +
 11.1291 +fun inverse_ms_aux :: "('a :: multiseries \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1292 +  "inverse_ms_aux (MSLCons x xs) = 
 11.1293 +     (let c' = inverse (fst x)
 11.1294 +      in  scale_shift_ms_aux (c', -snd x) 
 11.1295 +            (powser_ms_aux (msllist_of_msstream (mssalternate 1 (-1)))
 11.1296 +              (scale_shift_ms_aux (c', -snd x) xs)))"
 11.1297 +
 11.1298 +(* TODO: Move? *)
 11.1299 +lemma inverse_prod_list: "inverse (prod_list xs :: 'a :: field) = prod_list (map inverse xs)"
 11.1300 +  by (induction xs) simp_all
 11.1301 +
 11.1302 +lemma eval_inverse_monom: 
 11.1303 +  "eval_monom (inverse_monom monom) basis = (\<lambda>x. inverse (eval_monom monom basis x))"
 11.1304 +  by (rule ext) (simp add: eval_monom_def inverse_monom_def zip_map2 o_def case_prod_unfold
 11.1305 +                   inverse_prod_list powr_minus)
 11.1306 +
 11.1307 +fun powr_ms_aux :: "bool \<Rightarrow> ('a :: multiseries \<times> real) msllist \<Rightarrow> real \<Rightarrow> ('a \<times> real) msllist" where
 11.1308 +  "powr_ms_aux abort (MSLCons x xs) p = 
 11.1309 +      scale_shift_ms_aux (powr_expansion abort (fst x) p, snd x * p)
 11.1310 +        (powser_ms_aux (gbinomial_series abort p)
 11.1311 +          (scale_shift_ms_aux (inverse (fst x), -snd x) xs))"
 11.1312 +
 11.1313 +fun power_ms_aux :: "bool \<Rightarrow> ('a :: multiseries \<times> real) msllist \<Rightarrow> nat \<Rightarrow> ('a \<times> real) msllist" where
 11.1314 +  "power_ms_aux abort (MSLCons x xs) n = 
 11.1315 +      scale_shift_ms_aux (power_expansion abort (fst x) n, snd x * real n)
 11.1316 +        (powser_ms_aux (gbinomial_series abort (real n))
 11.1317 +          (scale_shift_ms_aux (inverse (fst x), -snd x) xs))"
 11.1318 +
 11.1319 +definition sin_ms_aux' :: "('a :: multiseries \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1320 +  "sin_ms_aux' xs = times_ms_aux xs (powser_ms_aux (msllist_of_msstream sin_series_stream)
 11.1321 +                      (times_ms_aux xs xs))"
 11.1322 +  
 11.1323 +definition cos_ms_aux' :: "('a :: multiseries \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.1324 +  "cos_ms_aux' xs = powser_ms_aux (msllist_of_msstream cos_series_stream) (times_ms_aux xs xs)"
 11.1325 +
 11.1326 +subsubsection \<open>Basic properties of multiseries operations\<close>  
 11.1327 +
 11.1328 +lemma uminus_ms_aux_MSLNil [simp]: "uminus_ms_aux MSLNil = MSLNil"
 11.1329 +  by (simp add: uminus_ms_aux_def)
 11.1330 +  
 11.1331 +lemma uminus_ms_aux_MSLCons: "uminus_ms_aux (MSLCons x xs) = MSLCons (-fst x, snd x) (uminus_ms_aux xs)"
 11.1332 +  by (simp add: uminus_ms_aux_def map_prod_def split: prod.splits)
 11.1333 +
 11.1334 +lemma uminus_ms_aux_MSLNil_iff [simp]: "uminus_ms_aux xs = MSLNil \<longleftrightarrow> xs = MSLNil"
 11.1335 +  by (simp add: uminus_ms_aux_def)
 11.1336 +  
 11.1337 +lemma hd_exp_uminus [simp]: "ms_aux_hd_exp (uminus_ms_aux xs) = ms_aux_hd_exp xs"
 11.1338 +  by (simp add: uminus_ms_aux_def ms_aux_hd_exp_def split: msllist.splits prod.split)
 11.1339 +  
 11.1340 +lemma scale_shift_ms_aux_MSLNil_iff [simp]: "scale_shift_ms_aux x F = MSLNil \<longleftrightarrow> F = MSLNil"
 11.1341 +  by (auto simp: scale_shift_ms_aux_def split: prod.split)
 11.1342 +
 11.1343 +lemma scale_shift_ms_aux_MSLNil [simp]: "scale_shift_ms_aux x MSLNil = MSLNil"
 11.1344 +  by (simp add: scale_shift_ms_aux_def split: prod.split)
 11.1345 +
 11.1346 +lemma scale_shift_ms_aux_1 [simp]:
 11.1347 +  "scale_shift_ms_aux (1 :: real, 0) xs = xs"
 11.1348 +  by (simp add: scale_shift_ms_aux_def map_prod_def msllist.map_id)
 11.1349 +
 11.1350 +lemma scale_shift_ms_aux_MSLCons: 
 11.1351 +  "scale_shift_ms_aux x (MSLCons y F) = MSLCons (fst x * fst y, snd x + snd y) (scale_shift_ms_aux x F)"
 11.1352 +  by (auto simp: scale_shift_ms_aux_def map_prod_def split: prod.split)
 11.1353 +
 11.1354 +lemma hd_exp_basis:
 11.1355 +  "ms_aux_hd_exp (scale_shift_ms_aux x xs) = map_option ((+) (snd x)) (ms_aux_hd_exp xs)"
 11.1356 +  by (auto simp: ms_aux_hd_exp_def scale_shift_ms_aux_MSLCons split: msllist.split)
 11.1357 +
 11.1358 +lemma plus_ms_aux_MSLNil_iff: "plus_ms_aux F G = MSLNil \<longleftrightarrow> F = MSLNil \<and> G = MSLNil"
 11.1359 +  by (subst plus_ms_aux.code) (simp split: msllist.splits)
 11.1360 +
 11.1361 +lemma plus_ms_aux_MSLNil [simp]: "plus_ms_aux F MSLNil = F" "plus_ms_aux MSLNil G = G"
 11.1362 +  by (subst plus_ms_aux.code, simp split: msllist.splits)+
 11.1363 +
 11.1364 +lemma plus_ms_aux_MSLCons: 
 11.1365 +  "plus_ms_aux (MSLCons x xs) (MSLCons y ys) = 
 11.1366 +     (if snd x > snd y then MSLCons x (plus_ms_aux xs (MSLCons y ys))
 11.1367 +      else if snd x < snd y then MSLCons y (plus_ms_aux (MSLCons x xs) ys)
 11.1368 +      else MSLCons (fst x + fst y, snd x) (plus_ms_aux xs ys))"
 11.1369 +  by (subst plus_ms_aux.code) simp
 11.1370 +
 11.1371 +lemma hd_exp_plus:
 11.1372 +  "ms_aux_hd_exp (plus_ms_aux xs ys) = combine_options max (ms_aux_hd_exp xs) (ms_aux_hd_exp ys)"
 11.1373 +  by (cases xs; cases ys)
 11.1374 +     (simp_all add: plus_ms_aux_MSLCons ms_aux_hd_exp_def max_def split: prod.split)
 11.1375 +
 11.1376 +lemma minus_ms_aux_MSLNil_left [simp]: "minus_ms_aux MSLNil ys = uminus_ms_aux ys"
 11.1377 +  by (simp add: minus_ms_aux_def)
 11.1378 +
 11.1379 +lemma minus_ms_aux_MSLNil_right [simp]: "minus_ms_aux xs MSLNil = xs"
 11.1380 +  by (simp add: minus_ms_aux_def)
 11.1381 +
 11.1382 +lemma times_ms_aux_MSLNil_iff: "times_ms_aux F G = MSLNil \<longleftrightarrow> F = MSLNil \<or> G = MSLNil"
 11.1383 +  by (subst times_ms_aux.code) (simp split: msllist.splits)
 11.1384 +
 11.1385 +lemma times_ms_aux_MSLNil [simp]: "times_ms_aux MSLNil G = MSLNil" "times_ms_aux F MSLNil = MSLNil"
 11.1386 +  by (subst times_ms_aux.code, simp split: msllist.splits)+
 11.1387 +
 11.1388 +lemma times_ms_aux_MSLCons: "times_ms_aux (MSLCons x xs) (MSLCons y ys) = 
 11.1389 +  MSLCons (fst x * fst y, snd x + snd y) (plus_ms_aux (scale_shift_ms_aux x ys)
 11.1390 +       (times_ms_aux xs (MSLCons y ys)))"
 11.1391 +  by (subst times_ms_aux_altdef) simp
 11.1392 +
 11.1393 +lemma hd_exp_times:
 11.1394 +  "ms_aux_hd_exp (times_ms_aux xs ys) = 
 11.1395 +     (case (ms_aux_hd_exp xs, ms_aux_hd_exp ys) of (Some x, Some y) \<Rightarrow> Some (x + y) | _ \<Rightarrow> None)"
 11.1396 +  by (cases xs; cases ys) (simp_all add: times_ms_aux_MSLCons ms_aux_hd_exp_def split: prod.split)
 11.1397 +
 11.1398 +
 11.1399 +subsubsection \<open>Induction upto friends for multiseries\<close>
 11.1400 +
 11.1401 +inductive ms_closure :: 
 11.1402 +  "(('a :: multiseries \<times> real) msllist \<Rightarrow> (real \<Rightarrow> real) \<Rightarrow> basis \<Rightarrow> bool) \<Rightarrow>
 11.1403 +   ('a :: multiseries \<times> real) msllist \<Rightarrow> (real \<Rightarrow> real) \<Rightarrow> basis \<Rightarrow> bool" for P where
 11.1404 +  ms_closure_embed: 
 11.1405 +    "P xs f basis \<Longrightarrow> ms_closure P xs f basis"
 11.1406 +| ms_closure_cong: 
 11.1407 +    "ms_closure P xs f basis \<Longrightarrow> eventually (\<lambda>x. f x = g x) at_top \<Longrightarrow> ms_closure P xs g basis"
 11.1408 +| ms_closure_MSLCons:
 11.1409 +    "ms_closure P xs (\<lambda>x. f x - eval C x * b x powr e) (b # basis) \<Longrightarrow>
 11.1410 +       is_expansion C basis \<Longrightarrow> (\<And>e'. e' > e \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')) \<Longrightarrow>
 11.1411 +       ms_exp_gt e (ms_aux_hd_exp xs) \<Longrightarrow>
 11.1412 +       ms_closure P (MSLCons (C, e) xs) f (b # basis)"
 11.1413 +| ms_closure_add: 
 11.1414 +    "ms_closure P xs f basis \<Longrightarrow> ms_closure P ys g basis \<Longrightarrow> 
 11.1415 +       ms_closure P (plus_ms_aux xs ys) (\<lambda>x. f x + g x) basis"
 11.1416 +| ms_closure_mult: 
 11.1417 +    "ms_closure P xs f basis \<Longrightarrow> ms_closure P ys g basis \<Longrightarrow> 
 11.1418 +       ms_closure P (times_ms_aux xs ys) (\<lambda>x. f x * g x) basis"
 11.1419 +| ms_closure_basis: 
 11.1420 +    "ms_closure P xs f (b # basis) \<Longrightarrow> is_expansion C basis \<Longrightarrow>
 11.1421 +       ms_closure P (scale_shift_ms_aux (C,e) xs) (\<lambda>x. eval C x * b x powr e * f x) (b # basis)"
 11.1422 + | ms_closure_embed':
 11.1423 +    "is_expansion_aux xs f basis \<Longrightarrow> ms_closure P xs f basis"
 11.1424 +
 11.1425 +lemma is_expansion_aux_coinduct_upto [consumes 2, case_names A B]:
 11.1426 +  fixes xs :: "('a :: multiseries \<times> real) msllist"
 11.1427 +  assumes *: "X xs f basis" and basis: "basis_wf basis"
 11.1428 +  and step: "\<And>xs f basis. X xs f basis \<Longrightarrow> 
 11.1429 +    (xs = MSLNil \<and> eventually (\<lambda>x. f x = 0) at_top \<and> length basis = Suc (expansion_level TYPE('a))) \<or>
 11.1430 +    (\<exists>xs' b e basis' C. xs = MSLCons (C, e) xs' \<and> basis = b # basis' \<and>
 11.1431 +       ms_closure X xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis') \<and>
 11.1432 +       is_expansion C basis' \<and> (\<forall>e'>e. f \<in> o(\<lambda>x. b x powr e')) \<and> ms_exp_gt e (ms_aux_hd_exp xs'))"
 11.1433 +  shows "is_expansion_aux xs f basis"
 11.1434 +proof -
 11.1435 +  from * have "ms_closure X xs f basis" by (rule ms_closure_embed[of X xs f basis])
 11.1436 +  thus ?thesis
 11.1437 +  proof (coinduction arbitrary: xs f rule: is_expansion_aux_coinduct)
 11.1438 +    case (is_expansion_aux xs f)
 11.1439 +    from this and basis show ?case
 11.1440 +    proof (induction rule: ms_closure.induct)
 11.1441 +      case (ms_closure_embed xs f basis)
 11.1442 +      from step[OF ms_closure_embed(1)] show ?case by auto
 11.1443 +    next
 11.1444 +      case (ms_closure_MSLCons xs f C b e basis)
 11.1445 +      thus ?case by auto
 11.1446 +    next
 11.1447 +      case (ms_closure_cong xs f basis g)
 11.1448 +      note ev = \<open>\<forall>\<^sub>F x in at_top. f x = g x\<close>
 11.1449 +      hence ev_zero_iff: "eventually (\<lambda>x. f x = 0) at_top \<longleftrightarrow> eventually (\<lambda>x. g x = 0) at_top"
 11.1450 +        by (rule eventually_subst')
 11.1451 +      have *: "ms_closure X xs' (\<lambda>x. f x - c x * b x powr e) basis \<longleftrightarrow>
 11.1452 +                 ms_closure X xs' (\<lambda>x. g x - c x * b x powr e) basis" for xs' c b e
 11.1453 +        by (rule iffI; erule ms_closure.intros(2)) (insert ev, auto elim: eventually_mono)
 11.1454 +      from ms_closure_cong show ?case
 11.1455 +        by (simp add: ev_zero_iff * landau_o.small.in_cong[OF ev])     
 11.1456 +    next
 11.1457 +      case (ms_closure_embed' xs f basis)
 11.1458 +      from this show ?case
 11.1459 +        by (cases rule: is_expansion_aux.cases) (force intro: ms_closure.intros(7))+
 11.1460 +    next
 11.1461 +      
 11.1462 +      case (ms_closure_basis xs f b basis C e)
 11.1463 +      show ?case
 11.1464 +      proof (cases xs rule: ms_aux_cases)
 11.1465 +        case MSLNil
 11.1466 +        with ms_closure_basis show ?thesis
 11.1467 +          by (auto simp: scale_shift_ms_aux_def split: prod.split elim: eventually_mono)
 11.1468 +      next
 11.1469 +        case (MSLCons C' e' xs')
 11.1470 +        with ms_closure_basis have IH:
 11.1471 +          "ms_closure X (MSLCons (C', e') xs') f (b # basis)"
 11.1472 +          "is_expansion C basis" "xs = MSLCons (C', e') xs'"
 11.1473 +          "ms_closure X xs' (\<lambda>x. f x - eval C' x * b x powr e') (b # basis)"
 11.1474 +          "ms_exp_gt e' (ms_aux_hd_exp xs')"
 11.1475 +          "is_expansion C' basis" "\<And>x. x > e' \<Longrightarrow> f \<in> o(\<lambda>xa. b xa powr x)"
 11.1476 +          by auto
 11.1477 +        
 11.1478 +        {
 11.1479 +          fix e'' :: real assume *: "e + e' < e''"
 11.1480 +          define d where "d = (e'' - e - e') / 2"
 11.1481 +          from * have "d > 0" by (simp add: d_def)
 11.1482 +          hence "(\<lambda>x. eval C x * b x powr e * f x) \<in> o(\<lambda>x. b x powr d * b x powr e * b x powr (e'+d))"
 11.1483 +            using ms_closure_basis(4) IH
 11.1484 +            by (intro landau_o.small.mult[OF landau_o.small_big_mult] IH 
 11.1485 +              is_expansion_imp_smallo[OF _ IH(2)]) (simp_all add: basis_wf_Cons)
 11.1486 +          also have "\<dots> = o(\<lambda>x. b x powr e'')" by (simp add: d_def powr_add [symmetric])
 11.1487 +          finally have "(\<lambda>x. eval C x * b x powr e * f x) \<in> \<dots>" .
 11.1488 +        }
 11.1489 +        moreover have "ms_closure X xs' (\<lambda>x. f x - eval C' x * b x powr e') (b # basis)"
 11.1490 +          using ms_closure_basis IH by auto
 11.1491 +        note ms_closure.intros(6)[OF this IH(2), of e]
 11.1492 +        moreover have "ms_exp_gt (e + e') (ms_aux_hd_exp (scale_shift_ms_aux (C, e) xs'))"
 11.1493 +          using \<open>ms_exp_gt e' (ms_aux_hd_exp xs')\<close>
 11.1494 +          by (cases xs') (simp_all add: hd_exp_basis scale_shift_ms_aux_def )
 11.1495 +        ultimately show ?thesis using IH(2,6) MSLCons ms_closure_basis(4)
 11.1496 +          by (auto simp: scale_shift_ms_aux_MSLCons algebra_simps powr_add basis_wf_Cons
 11.1497 +                   intro: is_expansion_mult)
 11.1498 +      qed
 11.1499 +      
 11.1500 +    next
 11.1501 +      case (ms_closure_add xs f basis ys g)
 11.1502 +      show ?case
 11.1503 +      proof (cases xs ys rule: ms_aux_cases[case_product ms_aux_cases])
 11.1504 +        case MSLNil_MSLNil
 11.1505 +        with ms_closure_add 
 11.1506 +          have "eventually (\<lambda>x. f x = 0) at_top" "eventually (\<lambda>x. g x = 0) at_top"
 11.1507 +            by simp_all
 11.1508 +        hence "eventually (\<lambda>x. f x + g x = 0) at_top" by eventually_elim simp
 11.1509 +        with MSLNil_MSLNil ms_closure_add show ?thesis by simp
 11.1510 +      next
 11.1511 +        case (MSLNil_MSLCons c e xs')
 11.1512 +        with ms_closure_add have "eventually (\<lambda>x. f x = 0) at_top" by simp
 11.1513 +        hence ev: "eventually (\<lambda>x. f x + g x = g x) at_top" by eventually_elim simp
 11.1514 +        have *: "ms_closure X xs (\<lambda>x. f x + g x - y x) basis \<longleftrightarrow> 
 11.1515 +                   ms_closure X xs (\<lambda>x. g x - y x) basis" for y basis xs
 11.1516 +          by (rule iffI; erule ms_closure_cong) (insert ev, simp_all)
 11.1517 +        from MSLNil_MSLCons ms_closure_add
 11.1518 +        show ?thesis by (simp add: * landau_o.small.in_cong[OF ev])
 11.1519 +      next
 11.1520 +        case (MSLCons_MSLNil c e xs')
 11.1521 +        with ms_closure_add have "eventually (\<lambda>x. g x = 0) at_top" by simp
 11.1522 +        hence ev: "eventually (\<lambda>x. f x + g x = f x) at_top" by eventually_elim simp
 11.1523 +        have *: "ms_closure X xs (\<lambda>x. f x + g x - y x) basis \<longleftrightarrow> 
 11.1524 +                   ms_closure X xs (\<lambda>x. f x - y x) basis" for y basis xs
 11.1525 +          by (rule iffI; erule ms_closure_cong) (insert ev, simp_all)
 11.1526 +        from MSLCons_MSLNil ms_closure_add
 11.1527 +        show ?thesis by (simp add: * landau_o.small.in_cong[OF ev])          
 11.1528 +      next
 11.1529 +        case (MSLCons_MSLCons C1 e1 xs' C2 e2 ys')
 11.1530 +        with ms_closure_add obtain b basis' where IH:
 11.1531 +          "basis_wf (b # basis')" "basis = b # basis'"
 11.1532 +          "ms_closure X (MSLCons (C1, e1) xs') f (b # basis')"
 11.1533 +          "ms_closure X (MSLCons (C2, e2) ys') g (b # basis')"
 11.1534 +          "xs = MSLCons (C1, e1) xs'" "ys = MSLCons (C2, e2) ys'"
 11.1535 +          "ms_closure X xs' (\<lambda>x. f x - eval C1 x * b x powr e1) (b # basis')"
 11.1536 +          "ms_closure X ys' (\<lambda>x. g x - eval C2 x * b x powr e2) (b # basis')"
 11.1537 +          "is_expansion C1 basis'" "\<And>e. e > e1 \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e)"
 11.1538 +          "is_expansion C2 basis'" "\<And>e. e > e2 \<Longrightarrow> g \<in> o(\<lambda>x. b x powr e)"
 11.1539 +          "ms_exp_gt e1 (ms_aux_hd_exp xs')" "ms_exp_gt e2 (ms_aux_hd_exp ys')"
 11.1540 +          by blast
 11.1541 +        have o: "(\<lambda>x. f x + g x) \<in> o(\<lambda>x. b x powr e)" if "e > max e1 e2" for e
 11.1542 +          using that by (intro sum_in_smallo IH) simp_all
 11.1543 +      
 11.1544 +        show ?thesis
 11.1545 +        proof (cases e1 e2 rule: linorder_cases)
 11.1546 +          case less
 11.1547 +          have gt: "ms_exp_gt e2 (combine_options max (Some e1) (ms_aux_hd_exp ys'))"
 11.1548 +            using \<open>ms_exp_gt e2 _\<close> less by (cases "ms_aux_hd_exp ys'") auto
 11.1549 +          have "ms_closure X (plus_ms_aux xs ys')
 11.1550 +                  (\<lambda>x. f x + (g x - eval C2 x * b x powr e2)) (b # basis')"
 11.1551 +            by (rule ms_closure.intros(4)) (insert IH, simp_all)
 11.1552 +          with less IH(2,11,14) o gt show ?thesis
 11.1553 +            by (intro disjI2) (simp add: MSLCons_MSLCons plus_ms_aux_MSLCons algebra_simps hd_exp_plus)
 11.1554 +        next
 11.1555 +          case greater
 11.1556 +          have gt: "ms_exp_gt e1 (combine_options max (ms_aux_hd_exp xs') (Some e2))"
 11.1557 +            using \<open>ms_exp_gt e1 _\<close> greater by (cases "ms_aux_hd_exp xs'") auto
 11.1558 +          have "ms_closure X (plus_ms_aux xs' ys)
 11.1559 +                  (\<lambda>x. (f x - eval C1 x * b x powr e1) + g x) (b # basis')"
 11.1560 +            by (rule ms_closure.intros(4)) (insert IH, simp_all)
 11.1561 +          with greater IH(2,9,13) o gt show ?thesis
 11.1562 +            by (intro disjI2) (simp add:  MSLCons_MSLCons plus_ms_aux_MSLCons algebra_simps hd_exp_plus)
 11.1563 +        next
 11.1564 +          case equal
 11.1565 +          have gt: "ms_exp_gt e2 (combine_options max (ms_aux_hd_exp xs')
 11.1566 +                      (ms_aux_hd_exp ys'))"
 11.1567 +            using \<open>ms_exp_gt e1 _\<close> \<open>ms_exp_gt e2 _\<close> equal
 11.1568 +            by (cases "ms_aux_hd_exp xs'"; cases "ms_aux_hd_exp ys'") auto
 11.1569 +          have "ms_closure X (plus_ms_aux xs' ys')
 11.1570 +                  (\<lambda>x. (f x - eval C1 x * b x powr e1) + (g x - eval C2 x * b x powr e2)) (b # basis')"
 11.1571 +            by (rule ms_closure.intros(4)) (insert IH, simp_all)
 11.1572 +          with equal IH(1,2,9,11,13,14) o gt show ?thesis
 11.1573 +            by (intro disjI2) 
 11.1574 +               (auto intro: is_expansion_add 
 11.1575 +                     simp: plus_ms_aux_MSLCons basis_wf_Cons algebra_simps hd_exp_plus  MSLCons_MSLCons)
 11.1576 +        qed
 11.1577 +      qed
 11.1578 +      
 11.1579 +    next
 11.1580 +      
 11.1581 +      case (ms_closure_mult xs f basis ys g)
 11.1582 +      show ?case
 11.1583 +      proof (cases "xs = MSLNil \<or> ys = MSLNil")
 11.1584 +        case True
 11.1585 +        with ms_closure_mult 
 11.1586 +          have "eventually (\<lambda>x. f x = 0) at_top \<or> eventually (\<lambda>x. g x = 0) at_top" by blast
 11.1587 +        hence "eventually (\<lambda>x. f x * g x = 0) at_top" by (auto elim: eventually_mono)
 11.1588 +        with ms_closure_mult True show ?thesis by auto
 11.1589 +      next
 11.1590 +        case False
 11.1591 +        with ms_closure_mult obtain C1 e1 xs' C2 e2 ys' b basis' where IH:
 11.1592 +          "xs = MSLCons (C1, e1) xs'" "ys = MSLCons (C2, e2) ys'"
 11.1593 +          "basis_wf (b # basis')" "basis = b # basis'"
 11.1594 +          "ms_closure X (MSLCons (C1, e1) xs') f (b # basis')"
 11.1595 +          "ms_closure X (MSLCons (C2, e2) ys') g (b # basis')"
 11.1596 +          "ms_closure X xs' (\<lambda>x. f x - eval C1 x * b x powr e1) (b # basis')"
 11.1597 +          "ms_closure X ys' (\<lambda>x. g x - eval C2 x * b x powr e2) (b # basis')"
 11.1598 +          "is_expansion C1 basis'" "\<And>e. e > e1 \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e)"
 11.1599 +          "is_expansion C2 basis'" "\<And>e. e > e2 \<Longrightarrow> g \<in> o(\<lambda>x. b x powr e)"
 11.1600 +          "ms_exp_gt e1 (ms_aux_hd_exp xs')" "ms_exp_gt e2 (ms_aux_hd_exp ys')"
 11.1601 +          by blast
 11.1602 +        have o: "(\<lambda>x. f x * g x) \<in> o(\<lambda>x. b x powr e)" if "e > e1 + e2" for e
 11.1603 +        proof -
 11.1604 +          define d where "d = (e - e1 - e2) / 2"
 11.1605 +          from that have d: "d > 0" by (simp add: d_def)
 11.1606 +          hence "(\<lambda>x. f x * g x) \<in> o(\<lambda>x. b x powr (e1 + d) * b x powr (e2 + d))"
 11.1607 +            by (intro landau_o.small.mult IH) simp_all
 11.1608 +          also have "\<dots> = o(\<lambda>x. b x powr e)" by (simp add: d_def powr_add [symmetric])
 11.1609 +          finally show ?thesis .
 11.1610 +        qed
 11.1611 +
 11.1612 +        have "ms_closure X (plus_ms_aux (scale_shift_ms_aux (C1, e1) ys') (times_ms_aux xs' ys))
 11.1613 +                (\<lambda>x. eval C1 x * b x powr e1 * (g x - eval C2 x * b x powr e2) + 
 11.1614 +                     ((f x - eval C1 x * b x powr e1) * g x)) (b # basis')"
 11.1615 +          (is "ms_closure _ ?zs ?f _") using ms_closure_mult IH(4)
 11.1616 +          by (intro ms_closure.intros(4-6) IH) simp_all
 11.1617 +        also have "?f = (\<lambda>x. f x * g x - eval C1 x * eval C2 x * b x powr (e1 + e2))"
 11.1618 +          by (intro ext) (simp add: algebra_simps powr_add)
 11.1619 +        finally have "ms_closure X ?zs \<dots> (b # basis')" .
 11.1620 +        moreover from \<open>ms_exp_gt e1 _\<close> \<open>ms_exp_gt e2 _\<close>
 11.1621 +        have "ms_exp_gt (e1 + e2) (combine_options max (map_option ((+) e1) 
 11.1622 +                (ms_aux_hd_exp ys')) (case ms_aux_hd_exp xs' of None \<Rightarrow> None | Some x \<Rightarrow>
 11.1623 +                  (case Some e2 of None \<Rightarrow> None | Some y \<Rightarrow> Some (x + y))))"
 11.1624 +            by (cases "ms_aux_hd_exp xs'"; cases "ms_aux_hd_exp ys'")
 11.1625 +               (simp_all add: hd_exp_times hd_exp_plus hd_exp_basis IH)
 11.1626 +        ultimately show ?thesis using IH(1,2,3,4,9,11) o
 11.1627 +          by (auto simp: times_ms_aux_MSLCons basis_wf_Cons hd_exp_times hd_exp_plus hd_exp_basis
 11.1628 +                   intro: is_expansion_mult)
 11.1629 +      qed
 11.1630 +    qed
 11.1631 +  qed
 11.1632 +qed
 11.1633 +
 11.1634 +
 11.1635 +
 11.1636 +subsubsection \<open>Dominant terms\<close>
 11.1637 +
 11.1638 +lemma one_smallo_powr: "e > (0::real) \<Longrightarrow> (\<lambda>_. 1) \<in> o(\<lambda>x. x powr e)"
 11.1639 +  by (auto simp: smallomega_iff_smallo [symmetric] real_powr_at_top 
 11.1640 +                 smallomegaI_filterlim_at_top_norm)
 11.1641 +
 11.1642 +lemma powr_smallo_one: "e < (0::real) \<Longrightarrow> (\<lambda>x. x powr e) \<in> o(\<lambda>_. 1)"
 11.1643 +  by (intro smalloI_tendsto) (auto intro!: tendsto_neg_powr filterlim_ident)
 11.1644 +
 11.1645 +lemma eval_monom_smallo':
 11.1646 +  assumes "basis_wf (b # basis)" "e > 0"
 11.1647 +  shows   "eval_monom x basis \<in> o(\<lambda>x. b x powr e)"
 11.1648 +proof (cases x)
 11.1649 +  case (Pair c es)
 11.1650 +  from assms show ?thesis unfolding Pair
 11.1651 +  proof (induction es arbitrary: b basis e)
 11.1652 +    case (Nil b basis e)
 11.1653 +    hence b: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1654 +    have "eval_monom (c, []) basis \<in> O(\<lambda>_. 1)" by simp
 11.1655 +    also have "(\<lambda>_. 1) \<in> o(\<lambda>x. b x powr e)"
 11.1656 +      by (rule landau_o.small.compose[OF _ b]) (insert Nil, simp add: one_smallo_powr)
 11.1657 +    finally show ?case .
 11.1658 +  next
 11.1659 +    case (Cons e' es b basis e)
 11.1660 +    show ?case
 11.1661 +    proof (cases basis)
 11.1662 +      case Nil
 11.1663 +      from Cons have b: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1664 +      from Nil have "eval_monom (c, e' # es) basis \<in> O(\<lambda>_. 1)" by simp
 11.1665 +      also have "(\<lambda>_. 1) \<in> o(\<lambda>x. b x powr e)"
 11.1666 +        by (rule landau_o.small.compose[OF _ b]) (insert Cons.prems, simp add: one_smallo_powr)
 11.1667 +      finally show ?thesis .
 11.1668 +    next
 11.1669 +      case (Cons b' basis')
 11.1670 +      from Cons.prems have "eval_monom (c, es) basis' \<in> o(\<lambda>x. b' x powr 1)"
 11.1671 +        by (intro Cons.IH) (simp_all add: basis_wf_Cons Cons)
 11.1672 +      hence "(\<lambda>x. eval_monom (c, es) basis' x * b' x powr e') \<in> o(\<lambda>x. b' x powr 1 * b' x powr e')"
 11.1673 +        by (rule landau_o.small_big_mult) simp_all
 11.1674 +      also have "\<dots> = o(\<lambda>x. b' x powr (1 + e'))" by (simp add: powr_add)
 11.1675 +      also from Cons.prems have "(\<lambda>x. b' x powr (1 + e')) \<in> o(\<lambda>x. b x powr e)"
 11.1676 +        by (intro ln_smallo_imp_flat) (simp_all add: basis_wf_Cons Cons)
 11.1677 +      finally show ?thesis by (simp add: powr_add [symmetric] Cons eval_monom_Cons)
 11.1678 +    qed
 11.1679 +  qed
 11.1680 +qed
 11.1681 +
 11.1682 +lemma eval_monom_smallomega':
 11.1683 +  assumes "basis_wf (b # basis)" "e < 0"
 11.1684 +  shows   "eval_monom (1, es) basis \<in> \<omega>(\<lambda>x. b x powr e)"
 11.1685 +  using assms
 11.1686 +proof (induction es arbitrary: b basis e)
 11.1687 +  case (Nil b basis e)
 11.1688 +  hence b: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1689 +  have "eval_monom (1, []) basis \<in> \<Omega>(\<lambda>_. 1)" by simp
 11.1690 +  also have "(\<lambda>_. 1) \<in> \<omega>(\<lambda>x. b x powr e)" unfolding smallomega_iff_smallo
 11.1691 +    by (rule landau_o.small.compose[OF _ b]) (insert Nil, simp add: powr_smallo_one)
 11.1692 +  finally show ?case .
 11.1693 +next
 11.1694 +  case (Cons e' es b basis e)
 11.1695 +  show ?case
 11.1696 +  proof (cases basis)
 11.1697 +    case Nil
 11.1698 +    from Cons have b: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1699 +    from Nil have "eval_monom (1, e' # es) basis \<in> \<Omega>(\<lambda>_. 1)" by simp
 11.1700 +    also have "(\<lambda>_. 1) \<in> \<omega>(\<lambda>x. b x powr e)" unfolding smallomega_iff_smallo
 11.1701 +      by (rule landau_o.small.compose[OF _ b]) (insert Cons.prems, simp add: powr_smallo_one)
 11.1702 +    finally show ?thesis .
 11.1703 +  next
 11.1704 +    case (Cons b' basis')
 11.1705 +    from Cons.prems have "eval_monom (1, es) basis' \<in> \<omega>(\<lambda>x. b' x powr -1)"
 11.1706 +      by (intro Cons.IH) (simp_all add: basis_wf_Cons Cons)
 11.1707 +    hence "(\<lambda>x. eval_monom (1, es) basis' x * b' x powr e') \<in> \<omega>(\<lambda>x. b' x powr -1 * b' x powr e')"
 11.1708 +      by (rule landau_omega.small_big_mult) simp_all
 11.1709 +    also have "\<dots> = \<omega>(\<lambda>x. b' x powr (e' - 1))" by (simp add: powr_diff powr_minus field_simps)
 11.1710 +    also from Cons.prems have "(\<lambda>x. b' x powr (e' - 1)) \<in> \<omega>(\<lambda>x. b x powr e)"
 11.1711 +      unfolding smallomega_iff_smallo
 11.1712 +      by (intro ln_smallo_imp_flat') (simp_all add: basis_wf_Cons Cons)
 11.1713 +    finally show ?thesis by (simp add: powr_add [symmetric] Cons eval_monom_Cons)
 11.1714 +  qed
 11.1715 +qed
 11.1716 +
 11.1717 +lemma dominant_term_ms_aux:
 11.1718 +  assumes basis: "basis_wf basis" and xs: "trimmed_ms_aux xs" "is_expansion_aux xs f basis"
 11.1719 +  shows   "f \<sim>[at_top] eval_monom (dominant_term_ms_aux xs) basis" (is ?thesis1)
 11.1720 +    and   "eventually (\<lambda>x. sgn (f x) = sgn (fst (dominant_term_ms_aux xs))) at_top" (is ?thesis2)
 11.1721 +proof -
 11.1722 +  include asymp_equiv_notation
 11.1723 +  from xs(2,1) obtain xs' C b e basis' where xs':
 11.1724 +    "trimmed C" "xs = MSLCons (C, e) xs'" "basis = b # basis'"
 11.1725 +    "is_expansion_aux xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.1726 +    "is_expansion C basis'" "(\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'))"
 11.1727 +    "ms_exp_gt e (ms_aux_hd_exp xs')"
 11.1728 +    by (cases rule: is_expansion_aux.cases) (auto simp: trimmed_ms_aux_MSLCons)
 11.1729 +  from is_expansion_aux_imp_smallo''[OF xs'(4,7)]
 11.1730 +    obtain e' where e': "e' < e" "(\<lambda>x. f x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr e')"
 11.1731 +      unfolding list.sel by blast   
 11.1732 +  from basis xs' have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1733 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.1734 +    
 11.1735 +  note e'(2)
 11.1736 +  also have "o(\<lambda>x. b x powr e') = o(\<lambda>x. b x powr (e' - e) * b x powr e)" 
 11.1737 +    by (simp add: powr_add [symmetric])
 11.1738 +  also from xs' basis e'(1) have "eval C \<in> \<omega>(\<lambda>x. b x powr (e' - e))"
 11.1739 +    by (intro is_expansion_imp_smallomega[of basis']) (simp_all add: basis_wf_Cons)
 11.1740 +  hence "(\<lambda>x. b x powr (e' - e) * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.1741 +    by (intro landau_o.small_big_mult) (simp_all add: smallomega_iff_smallo)
 11.1742 +  finally have *: "(\<lambda>x. f x - eval C x * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)" .
 11.1743 +  hence "f \<sim> (\<lambda>x. eval C x * b x powr e)" by (intro smallo_imp_asymp_equiv) simp
 11.1744 +  also from basis xs' have "eval C \<sim> (\<lambda>x. eval_monom (dominant_term C) basis' x)"
 11.1745 +    by (intro dominant_term) (simp_all add: basis_wf_Cons)
 11.1746 +  also have "(\<lambda>a. eval_monom (dominant_term C) basis' a * b a powr e) = 
 11.1747 +               eval_monom (dominant_term_ms_aux xs) basis"
 11.1748 +    by (auto simp add: dominant_term_ms_aux_def xs' eval_monom_Cons fun_eq_iff split: prod.split)
 11.1749 +  finally show ?thesis1 by - (simp_all add: asymp_equiv_intros)
 11.1750 +  
 11.1751 +  have "eventually (\<lambda>x. sgn (eval C x * b x powr e + (f x - eval C x * b x powr e)) = 
 11.1752 +                          sgn (eval C x * b x powr e)) at_top"
 11.1753 +    by (intro smallo_imp_eventually_sgn *)
 11.1754 +  moreover have "eventually (\<lambda>x. sgn (eval C x) = sgn (fst (dominant_term C))) at_top"
 11.1755 +    using xs' basis by (intro trimmed_imp_eventually_sgn[of basis']) (simp_all add: basis_wf_Cons)
 11.1756 +  ultimately have "eventually (\<lambda>x. sgn (f x) = sgn (fst (dominant_term C))) at_top"
 11.1757 +    using b_pos by eventually_elim (simp_all add: sgn_mult)
 11.1758 +  thus ?thesis2 using xs'(2) by (auto simp: dominant_term_ms_aux_def split: prod.split)
 11.1759 +qed
 11.1760 +
 11.1761 +lemma eval_monom_smallo:
 11.1762 +  assumes "basis \<noteq> []" "basis_wf basis" "length es = length basis" "e > hd es"
 11.1763 +  shows   "eval_monom (c, es) basis \<in> o(\<lambda>x. hd basis x powr e)"
 11.1764 +proof (cases es; cases basis)
 11.1765 +  fix b basis' e' es' assume [simp]: "basis = b # basis'" "es = e' # es'"
 11.1766 +  from assms have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1767 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" 
 11.1768 +    using filterlim_at_top_dense by blast
 11.1769 +  have "(\<lambda>x. eval_monom (1, es') basis' x * b x powr e') \<in> o(\<lambda>x. b x powr (e - e') * b x powr e')"
 11.1770 +    using assms by (intro landau_o.small_big_mult eval_monom_smallo') auto
 11.1771 +  also have "(\<lambda>x. b x powr (e - e') * b x powr e') \<in> \<Theta>(\<lambda>x. b x powr e)"
 11.1772 +    by (intro bigthetaI_cong eventually_mono[OF b_pos]) (auto simp: powr_diff)
 11.1773 +  finally show ?thesis by (simp add: eval_monom_def algebra_simps)
 11.1774 +qed (insert assms, auto)
 11.1775 +
 11.1776 +lemma eval_monom_smallomega:
 11.1777 +  assumes "basis \<noteq> []" "basis_wf basis" "length es = length basis" "e < hd es"
 11.1778 +  shows   "eval_monom (1, es) basis \<in> \<omega>(\<lambda>x. hd basis x powr e)"
 11.1779 +proof (cases es; cases basis)
 11.1780 +  fix b basis' e' es' assume [simp]: "basis = b # basis'" "es = e' # es'"
 11.1781 +  from assms have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1782 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" 
 11.1783 +    using filterlim_at_top_dense by blast
 11.1784 +  have "(\<lambda>x. eval_monom (1, es') basis' x * b x powr e') \<in> \<omega>(\<lambda>x. b x powr (e - e') * b x powr e')"
 11.1785 +    using assms by (intro landau_omega.small_big_mult eval_monom_smallomega') auto
 11.1786 +  also have "(\<lambda>x. b x powr (e - e') * b x powr e') \<in> \<Theta>(\<lambda>x. b x powr e)"
 11.1787 +    by (intro bigthetaI_cong eventually_mono[OF b_pos]) (auto simp: powr_diff)
 11.1788 +  finally show ?thesis by (simp add: eval_monom_Cons)
 11.1789 +qed (insert assms, auto)
 11.1790 +
 11.1791 +
 11.1792 +subsubsection \<open>Correctness of multiseries operations\<close>
 11.1793 +
 11.1794 +lemma drop_zero_ms_aux:
 11.1795 +  assumes "eventually (\<lambda>x. eval C x = 0) at_top"
 11.1796 +  assumes "is_expansion_aux (MSLCons (C, e) xs) f basis"
 11.1797 +  shows   "is_expansion_aux xs f basis"
 11.1798 +proof (rule is_expansion_aux_cong)
 11.1799 +  from assms(2) show "is_expansion_aux xs (\<lambda>x. f x - eval C x * hd basis x powr e) basis"
 11.1800 +    by (auto elim: is_expansion_aux_MSLCons)
 11.1801 +  from assms(1) show "eventually (\<lambda>x. f x - eval C x * hd basis x powr e = f x) at_top"
 11.1802 +    by eventually_elim simp
 11.1803 +qed
 11.1804 +
 11.1805 +lemma dominant_term_ms_aux_bigo:
 11.1806 +  assumes basis: "basis_wf basis" and xs: "is_expansion_aux xs f basis"
 11.1807 +  shows   "f \<in> O(eval_monom (1, snd (dominant_term_ms_aux xs)) basis)" (is ?thesis1)
 11.1808 +proof (cases xs rule: ms_aux_cases)
 11.1809 +  case MSLNil
 11.1810 +  with assms have "eventually (\<lambda>x. f x = 0) at_top"
 11.1811 +    by (auto elim: is_expansion_aux.cases)
 11.1812 +  hence "f \<in> \<Theta>(\<lambda>_. 0)" by (intro bigthetaI_cong) auto
 11.1813 +  also have "(\<lambda>_. 0) \<in> O(eval_monom (1, snd (dominant_term_ms_aux xs)) basis)" by simp
 11.1814 +  finally show ?thesis .
 11.1815 +next
 11.1816 +  case [simp]: (MSLCons C e xs')
 11.1817 +  from xs obtain b basis' where xs':
 11.1818 +    "basis = b # basis'"
 11.1819 +    "is_expansion_aux xs' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.1820 +    "is_expansion C basis'" "(\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'))"
 11.1821 +    "ms_exp_gt e (ms_aux_hd_exp xs')"
 11.1822 +    by (cases rule: is_expansion_aux.cases) auto
 11.1823 +  from is_expansion_aux_imp_smallo''[OF xs'(2,5)]
 11.1824 +    obtain e' where e': "e' < e" "(\<lambda>x. f x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr e')"
 11.1825 +      unfolding list.sel by blast   
 11.1826 +  from basis xs' have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1827 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.1828 +
 11.1829 +  let ?h = "(\<lambda>x. eval_monom (1, snd (dominant_term C)) basis' x * b x powr e)"
 11.1830 +  note e'(2)
 11.1831 +  also have "(\<lambda>x. b x powr e') \<in> \<Theta>(\<lambda>x. b x powr (e' - e) * b x powr e)"
 11.1832 +    by (intro bigthetaI_cong eventually_mono[OF b_pos]) (auto simp: powr_diff)
 11.1833 +  also have "(\<lambda>x. b x powr (e' - e) * b x powr e) \<in> o(?h)"
 11.1834 +    unfolding smallomega_iff_smallo [symmetric] using e'(1) basis xs'
 11.1835 +    by (intro landau_omega.small_big_mult landau_omega.big_refl eval_monom_smallomega')
 11.1836 +       (simp_all add: basis_wf_Cons)
 11.1837 +  finally have "(\<lambda>x. f x - eval C x * b x powr e) \<in> O(?h)" by (rule landau_o.small_imp_big)
 11.1838 +  moreover have "(\<lambda>x. eval C x * b x powr e) \<in> O(?h)"
 11.1839 +    using basis xs' by (intro landau_o.big.mult dominant_term_bigo) (auto simp: basis_wf_Cons)
 11.1840 +  ultimately have "(\<lambda>x. f x - eval C x * b x powr e + eval C x * b x powr e) \<in> O(?h)"
 11.1841 +    by (rule sum_in_bigo)
 11.1842 +  hence "f \<in> O(?h)" by simp
 11.1843 +  also have "?h = eval_monom (1, snd (dominant_term_ms_aux xs)) basis"
 11.1844 +    using xs' by (auto simp: dominant_term_ms_aux_def case_prod_unfold eval_monom_Cons)
 11.1845 +  finally show ?thesis .
 11.1846 +qed
 11.1847 +
 11.1848 +lemma const_ms_aux:
 11.1849 +  assumes basis: "basis_wf basis" 
 11.1850 +      and "length basis = Suc (expansion_level TYPE('a::multiseries))"
 11.1851 +  shows   "is_expansion_aux (const_ms_aux c :: ('a \<times> real) msllist) (\<lambda>_. c) basis"
 11.1852 +proof -
 11.1853 +  from assms(2) obtain b basis' where [simp]: "basis = b # basis'" by (cases basis) simp_all
 11.1854 +  from basis have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.1855 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.1856 +
 11.1857 +  have "(\<lambda>_. c) \<in> o(\<lambda>x. b x powr e)" if "e > 0" for e
 11.1858 +  proof -
 11.1859 +    have "(\<lambda>_. c) \<in> O(\<lambda>_. 1)" by (cases "c = 0") simp_all  
 11.1860 +    also from b_pos have "(\<lambda>_. 1) \<in> \<Theta>(\<lambda>x. b x powr 0)" 
 11.1861 +      by (intro bigthetaI_cong) (auto elim: eventually_mono)
 11.1862 +    also from that b_limit have "(\<lambda>x. b x powr 0) \<in> o(\<lambda>x. b x powr e)" 
 11.1863 +      by (subst powr_smallo_iff) auto
 11.1864 +    finally show ?thesis .
 11.1865 +  qed
 11.1866 +  with b_pos assms show ?thesis
 11.1867 +    by (auto intro!: is_expansion_aux.intros simp: const_ms_aux_def is_expansion_const basis_wf_Cons 
 11.1868 +             elim: eventually_mono)
 11.1869 +qed
 11.1870 +
 11.1871 +lemma uminus_ms_aux:
 11.1872 +  assumes basis: "basis_wf basis"
 11.1873 +  assumes F: "is_expansion_aux F f basis"
 11.1874 +  shows   "is_expansion_aux (uminus_ms_aux F) (\<lambda>x. -f x) basis"
 11.1875 +  using F
 11.1876 +proof (coinduction arbitrary: F f rule: is_expansion_aux_coinduct)
 11.1877 +  case (is_expansion_aux F f)
 11.1878 +  note IH = is_expansion_aux
 11.1879 +  show ?case
 11.1880 +  proof (cases F rule: ms_aux_cases)
 11.1881 +    case MSLNil
 11.1882 +    with IH show ?thesis by (auto simp: uminus_ms_aux_def elim: is_expansion_aux.cases)
 11.1883 +  next
 11.1884 +    case (MSLCons C e xs)
 11.1885 +    with IH obtain b basis'
 11.1886 +      where IH: "basis = b # basis'" 
 11.1887 +                "is_expansion_aux xs (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.1888 +                "is_expansion C basis'"
 11.1889 +                "\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')" "ms_exp_gt e (ms_aux_hd_exp xs)"
 11.1890 +      by (auto elim: is_expansion_aux_MSLCons)
 11.1891 +    from basis IH have basis': "basis_wf basis'" by (simp add: basis_wf_Cons)
 11.1892 +    with IH basis show ?thesis
 11.1893 +      by (force simp: uminus_ms_aux_MSLCons MSLCons is_expansion_uminus)
 11.1894 +  qed
 11.1895 +qed
 11.1896 +
 11.1897 +lemma plus_ms_aux:
 11.1898 +  assumes "basis_wf basis" "is_expansion_aux F f basis" "is_expansion_aux G g basis"
 11.1899 +  shows   "is_expansion_aux (plus_ms_aux F G) (\<lambda>x. f x + g x) basis"
 11.1900 +  using assms
 11.1901 +proof (coinduction arbitrary: F f G g rule: is_expansion_aux_coinduct)
 11.1902 +  case (is_expansion_aux F f G g)
 11.1903 +  note IH = this
 11.1904 +  show ?case
 11.1905 +  proof (cases F G rule: ms_aux_cases[case_product ms_aux_cases])
 11.1906 +    assume [simp]: "F = MSLNil" "G = MSLNil"
 11.1907 +    with IH have *: "eventually (\<lambda>x. f x = 0) at_top" "eventually (\<lambda>x. g x = 0) at_top" 
 11.1908 +                 and length: "length basis = Suc (expansion_level TYPE('a))"
 11.1909 +      by (auto elim: is_expansion_aux.cases)
 11.1910 +    from * have "eventually (\<lambda>x. f x + g x = 0) at_top" by eventually_elim simp
 11.1911 +    with length show ?case by simp 
 11.1912 +  next
 11.1913 +    assume [simp]: "F = MSLNil"
 11.1914 +    fix C e G' assume G: "G = MSLCons (C, e) G'"
 11.1915 +    from IH have f: "eventually (\<lambda>x. f x = 0) at_top" by (auto elim: is_expansion_aux.cases)
 11.1916 +    from f have "eventually (\<lambda>x. f x + g x = g x) at_top" by eventually_elim simp
 11.1917 +    note eq = landau_o.small.in_cong[OF this]
 11.1918 +    from IH(3) G obtain b basis' where G':
 11.1919 +      "basis = b # basis'"
 11.1920 +      "is_expansion_aux G' (\<lambda>x. g x - eval C x * b x powr e) (b # basis')"
 11.1921 +      "is_expansion C basis'" "\<forall>e'>e. g \<in> o(\<lambda>x. b x powr e')" "ms_exp_gt e (ms_aux_hd_exp G')"
 11.1922 +      by (auto elim!: is_expansion_aux_MSLCons)
 11.1923 +    show ?thesis
 11.1924 +      by (rule disjI2, inst_existentials G' b e basis' C F f G' "\<lambda>x. g x - eval C x * b x powr e")
 11.1925 +         (insert G' IH(1,2), simp_all add: G eq algebra_simps)
 11.1926 +  next
 11.1927 +    assume [simp]: "G = MSLNil"
 11.1928 +    fix C e F' assume F: "F = MSLCons (C, e) F'"
 11.1929 +    from IH have g: "eventually (\<lambda>x. g x = 0) at_top" by (auto elim: is_expansion_aux.cases)
 11.1930 +    hence "eventually (\<lambda>x. f x + g x = f x) at_top" by eventually_elim simp
 11.1931 +    note eq = landau_o.small.in_cong[OF this]
 11.1932 +    from IH F obtain b basis' where F':
 11.1933 +      "basis = b # basis'"
 11.1934 +      "is_expansion_aux F' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.1935 +      "is_expansion C basis'" "\<forall>e'>e. f \<in> o(\<lambda>x. b x powr e')" "ms_exp_gt e (ms_aux_hd_exp F')"
 11.1936 +      by (auto elim!: is_expansion_aux_MSLCons)
 11.1937 +    show ?thesis
 11.1938 +      by (rule disjI2, inst_existentials F' b e basis' C F' "\<lambda>x. f x - eval C x * b x powr e" G g)
 11.1939 +         (insert F g F' IH, simp_all add: eq algebra_simps)
 11.1940 +  next
 11.1941 +    fix C1 e1 F' C2 e2 G'
 11.1942 +    assume F: "F = MSLCons (C1, e1) F'" and G: "G = MSLCons (C2, e2) G'"
 11.1943 +    from IH F obtain b basis' where
 11.1944 +      basis': "basis = b # basis'" and F':
 11.1945 +      "is_expansion_aux F' (\<lambda>x. f x - eval C1 x * b x powr e1) (b # basis')"
 11.1946 +      "is_expansion C1 basis'" "\<And>e'. e' > e1 \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')" 
 11.1947 +      "ms_exp_gt e1 (ms_aux_hd_exp F')"
 11.1948 +      by (auto elim!: is_expansion_aux_MSLCons)
 11.1949 +    from IH G basis' have G':
 11.1950 +      "is_expansion_aux G' (\<lambda>x. g x - eval C2 x * b x powr e2) (b # basis')"
 11.1951 +      "is_expansion C2 basis'" "\<And>e'. e' > e2 \<Longrightarrow> g \<in> o(\<lambda>x. b x powr e')"
 11.1952 +      "ms_exp_gt e2 (ms_aux_hd_exp G')"
 11.1953 +      by (auto elim!: is_expansion_aux_MSLCons)  
 11.1954 +    hence *: "\<forall>x>max e1 e2. (\<lambda>x. f x + g x) \<in> o(\<lambda>xa. b xa powr x)"
 11.1955 +      by (intro allI impI sum_in_smallo F' G') simp_all
 11.1956 +      
 11.1957 +    consider "e1 > e2" | "e1 < e2" | "e1 = e2" by force
 11.1958 +    thus ?thesis
 11.1959 +    proof cases
 11.1960 +      assume e: "e1 > e2"
 11.1961 +      have gt: "ms_exp_gt e1 (combine_options max (ms_aux_hd_exp F') (Some e2))"
 11.1962 +        using \<open>ms_exp_gt e1 _\<close> e by (cases "ms_aux_hd_exp F'") simp_all
 11.1963 +      show ?thesis
 11.1964 +        by (rule disjI2, inst_existentials "plus_ms_aux F' G" b e1 basis' C1 F' 
 11.1965 +                           "\<lambda>x. f x - eval C1 x * b x powr e1" G g)
 11.1966 +           (insert e F'(1,2,4) IH(1,3) basis'(1) * gt,
 11.1967 +            simp_all add: F G plus_ms_aux_MSLCons algebra_simps hd_exp_plus)
 11.1968 +    next
 11.1969 +      assume e: "e1 < e2"
 11.1970 +      have gt: "ms_exp_gt e2 (combine_options max (Some e1) (ms_aux_hd_exp G'))"
 11.1971 +        using \<open>ms_exp_gt e2 _\<close> e by (cases "ms_aux_hd_exp G'") simp_all
 11.1972 +      show ?thesis
 11.1973 +        by (rule disjI2, inst_existentials "plus_ms_aux F G'" b e2 basis' C2 F f G'
 11.1974 +                           "\<lambda>x. g x - eval C2 x * b x powr e2")
 11.1975 +           (insert e G'(1,2,4) IH(1,2) basis'(1) * gt, 
 11.1976 +            simp_all add: F G plus_ms_aux_MSLCons algebra_simps hd_exp_plus)
 11.1977 +    next
 11.1978 +      assume e: "e1 = e2"
 11.1979 +      have gt: "ms_exp_gt e2 (combine_options max (ms_aux_hd_exp F') (ms_aux_hd_exp G'))"
 11.1980 +        using \<open>ms_exp_gt e1 _\<close> \<open>ms_exp_gt e2 _\<close> e
 11.1981 +        by (cases "ms_aux_hd_exp F'"; cases "ms_aux_hd_exp G'") simp_all
 11.1982 +      show ?thesis
 11.1983 +        by (rule disjI2, inst_existentials "plus_ms_aux F' G'" b e1 basis' "C1 + C2" F' 
 11.1984 +                         "\<lambda>x. f x - eval C1 x * b x powr e1" G' "\<lambda>x. g x - eval C2 x * b x powr e2")
 11.1985 +           (insert e F'(1,2,4) G'(1,2,4) IH(1) basis'(1) * gt, 
 11.1986 +            simp_all add: F G plus_ms_aux_MSLCons algebra_simps hd_exp_plus is_expansion_add basis_wf_Cons)
 11.1987 +    qed
 11.1988 +  qed
 11.1989 +qed
 11.1990 +
 11.1991 +lemma minus_ms_aux:
 11.1992 +  assumes "basis_wf basis" "is_expansion_aux F f basis" "is_expansion_aux G g basis"
 11.1993 +  shows   "is_expansion_aux (minus_ms_aux F G) (\<lambda>x. f x - g x) basis"
 11.1994 +proof -
 11.1995 +  have "is_expansion_aux (minus_ms_aux F G) (\<lambda>x. f x + (- g x)) basis"
 11.1996 +    unfolding minus_ms_aux_def by (intro plus_ms_aux uminus_ms_aux assms)
 11.1997 +  thus ?thesis by simp
 11.1998 +qed
 11.1999 +
 11.2000 +lemma scale_shift_ms_aux:
 11.2001 +  assumes basis: "basis_wf (b # basis)"
 11.2002 +  assumes F: "is_expansion_aux F f (b # basis)"
 11.2003 +  assumes C: "is_expansion C basis"
 11.2004 +  shows   "is_expansion_aux (scale_shift_ms_aux (C, e) F) (\<lambda>x. eval C x * b x powr e * f x) (b # basis)"
 11.2005 +  using F
 11.2006 +proof (coinduction arbitrary: F f rule: is_expansion_aux_coinduct)
 11.2007 +  case (is_expansion_aux F f)
 11.2008 +  note IH = is_expansion_aux
 11.2009 +  show ?case
 11.2010 +  proof (cases F rule: ms_aux_cases)
 11.2011 +    case MSLNil
 11.2012 +    with IH show ?thesis 
 11.2013 +      by (auto simp: scale_shift_ms_aux_def elim!: is_expansion_aux.cases eventually_mono)
 11.2014 +  next
 11.2015 +    case (MSLCons C' e' xs)
 11.2016 +    with IH have IH: "is_expansion_aux xs (\<lambda>x. f x - eval C' x * b x powr e') (b # basis)"
 11.2017 +                     "is_expansion C' basis" "ms_exp_gt e' (ms_aux_hd_exp xs)"
 11.2018 +                     "\<And>e''. e' < e'' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'')"
 11.2019 +      by (auto elim: is_expansion_aux_MSLCons)
 11.2020 +    
 11.2021 +    have "(\<lambda>x. eval C x * b x powr e * f x) \<in> o(\<lambda>x. b x powr e'')" if "e'' > e + e'" for e''
 11.2022 +    proof -
 11.2023 +      define d where "d = (e'' - e - e') / 2"
 11.2024 +      from that have d: "d > 0" by (simp add: d_def)
 11.2025 +      have "(\<lambda>x. eval C x * b x powr e * f x) \<in> o(\<lambda>x. b x powr d * b x powr e * b x powr (e' + d))"
 11.2026 +        using d basis
 11.2027 +        by (intro landau_o.small.mult[OF landau_o.small_big_mult] 
 11.2028 +              is_expansion_imp_smallo[OF _ C] IH) (simp_all add: basis_wf_Cons)
 11.2029 +      also have "\<dots> = o(\<lambda>x. b x powr e'')" by (simp add: d_def powr_add [symmetric])
 11.2030 +      finally show ?thesis .
 11.2031 +    qed
 11.2032 +    moreover have "ms_exp_gt (e + e') (ms_aux_hd_exp (scale_shift_ms_aux (C, e) xs))"
 11.2033 +      using IH(3) by (cases "ms_aux_hd_exp xs") (simp_all add: hd_exp_basis)
 11.2034 +    ultimately show ?thesis using basis IH(1,2)
 11.2035 +      by (intro disjI2, inst_existentials "scale_shift_ms_aux (C, e) xs" b "e + e'" 
 11.2036 +                          basis "C * C'" xs "\<lambda>x. f x - eval C' x * b x powr e'")
 11.2037 +         (simp_all add: scale_shift_ms_aux_MSLCons MSLCons is_expansion_mult basis_wf_Cons
 11.2038 +                        algebra_simps powr_add C)
 11.2039 +  qed
 11.2040 +qed
 11.2041 +
 11.2042 +lemma times_ms_aux:
 11.2043 +  assumes basis: "basis_wf basis"
 11.2044 +  assumes F: "is_expansion_aux F f basis" and G: "is_expansion_aux G g basis"
 11.2045 +  shows   "is_expansion_aux (times_ms_aux F G) (\<lambda>x. f x * g x) basis"
 11.2046 +  using F G
 11.2047 +proof (coinduction arbitrary: F f G g rule: is_expansion_aux_coinduct_upto)
 11.2048 +  case (B F f G g)
 11.2049 +  note IH = this
 11.2050 +  show ?case
 11.2051 +  proof (cases "F = MSLNil \<or> G = MSLNil")
 11.2052 +    case True
 11.2053 +    with IH have "eventually (\<lambda>x. f x = 0) at_top \<or> eventually (\<lambda>x. g x = 0) at_top"
 11.2054 +      and length: "length basis = Suc (expansion_level TYPE('a))"
 11.2055 +      by (auto elim: is_expansion_aux.cases)
 11.2056 +    from this(1) have "eventually (\<lambda>x. f x * g x = 0) at_top" by (auto elim!: eventually_mono)
 11.2057 +    with length True show ?thesis by auto
 11.2058 +  next
 11.2059 +    case False
 11.2060 +    from False obtain C1 e1 F' where F: "F = MSLCons (C1, e1) F'" 
 11.2061 +      by (cases F rule: ms_aux_cases) simp_all
 11.2062 +    from False obtain C2 e2 G' where G: "G = MSLCons (C2, e2) G'" 
 11.2063 +      by (cases G rule: ms_aux_cases) simp_all
 11.2064 +    
 11.2065 +    from IH(1) F obtain b basis' where
 11.2066 +      basis': "basis = b # basis'" and F':
 11.2067 +      "is_expansion_aux F' (\<lambda>x. f x - eval C1 x * b x powr e1) (b # basis')"
 11.2068 +      "is_expansion C1 basis'" "\<And>e'. e' > e1 \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e')"
 11.2069 +      "ms_exp_gt e1 (ms_aux_hd_exp F')"
 11.2070 +      by (auto elim!: is_expansion_aux_MSLCons)
 11.2071 +    from IH(2) G basis' have G':
 11.2072 +      "is_expansion_aux G' (\<lambda>x. g x - eval C2 x * b x powr e2) (b # basis')"
 11.2073 +      "is_expansion C2 basis'" "\<And>e'. e' > e2 \<Longrightarrow> g \<in> o(\<lambda>x. b x powr e')"
 11.2074 +      "ms_exp_gt e2 (ms_aux_hd_exp G')"
 11.2075 +      by (auto elim!: is_expansion_aux_MSLCons)  
 11.2076 +    let ?P = "(\<lambda>xs'' fa'' basisa''. \<exists>F f G. xs'' = times_ms_aux F G \<and>
 11.2077 +            (\<exists>g. fa'' = (\<lambda>x. f x * g x) \<and> basisa'' = b # basis' \<and> is_expansion_aux F f
 11.2078 +                  (b # basis') \<and> is_expansion_aux G g (b # basis')))"
 11.2079 +    have "ms_closure ?P (plus_ms_aux (scale_shift_ms_aux (C1, e1) G') (times_ms_aux F' G))
 11.2080 +            (\<lambda>x. eval C1 x * b x powr e1 * (g x - eval C2 x * b x powr e2) +
 11.2081 +                 (f x - eval C1 x * b x powr e1) * g x) (b # basis')"
 11.2082 +      (is "ms_closure _ ?zs _ _") using IH(2) basis' basis
 11.2083 +      by (intro ms_closure_add ms_closure_embed'[OF scale_shift_ms_aux] 
 11.2084 +            ms_closure_mult[OF ms_closure_embed' ms_closure_embed'] F' G') simp_all
 11.2085 +    hence "ms_closure ?P (plus_ms_aux (scale_shift_ms_aux (C1, e1) G') (times_ms_aux F' G))
 11.2086 +            (\<lambda>x. f x * g x - eval C1 x * eval C2 x * b x powr (e1 + e2)) (b # basis')"
 11.2087 +      by (simp add: algebra_simps powr_add)
 11.2088 +    moreover have "(\<lambda>x. f x * g x) \<in> o(\<lambda>x. b x powr e)" if "e > e1 + e2" for e
 11.2089 +    proof -
 11.2090 +      define d where "d = (e - e1 - e2) / 2"
 11.2091 +      from that have "d > 0" by (simp add: d_def)
 11.2092 +      hence "(\<lambda>x. f x * g x) \<in> o(\<lambda>x. b x powr (e1 + d) * b x powr (e2 + d))"
 11.2093 +        by (intro landau_o.small.mult F' G') simp_all
 11.2094 +      also have "\<dots> = o(\<lambda>x. b x powr e)"
 11.2095 +        by (simp add: d_def powr_add [symmetric])
 11.2096 +      finally show ?thesis .
 11.2097 +    qed
 11.2098 +    moreover from \<open>ms_exp_gt e1 _\<close> \<open>ms_exp_gt e2 _\<close>
 11.2099 +      have "ms_exp_gt (e1 + e2) (ms_aux_hd_exp ?zs)"
 11.2100 +        by (cases "ms_aux_hd_exp F'"; cases "ms_aux_hd_exp G'") 
 11.2101 +           (simp_all add: hd_exp_times hd_exp_plus hd_exp_basis G)    
 11.2102 +    ultimately show ?thesis using F'(2) G'(2) basis' basis
 11.2103 +      by (simp add: times_ms_aux_MSLCons basis_wf_Cons is_expansion_mult F G)
 11.2104 +  qed
 11.2105 +qed (insert basis, simp_all)
 11.2106 +
 11.2107 +
 11.2108 +
 11.2109 +
 11.2110 +lemma powser_ms_aux_MSLNil_iff [simp]: "powser_ms_aux cs f = MSLNil \<longleftrightarrow> cs = MSLNil"
 11.2111 +  by (subst powser_ms_aux.code) (simp split: msllist.splits)
 11.2112 +
 11.2113 +lemma powser_ms_aux_MSLNil [simp]: "powser_ms_aux MSLNil f = MSLNil"
 11.2114 +  by (subst powser_ms_aux.code) simp
 11.2115 +
 11.2116 +lemma powser_ms_aux_MSLNil' [simp]: 
 11.2117 +  "powser_ms_aux (MSLCons c cs) MSLNil = MSLCons (const_expansion c, 0) MSLNil"
 11.2118 +  by (subst powser_ms_aux.code) simp
 11.2119 +
 11.2120 +lemma powser_ms_aux_MSLCons: 
 11.2121 +  "powser_ms_aux (MSLCons c cs) f = MSLCons (const_expansion c, 0) (times_ms_aux f (powser_ms_aux cs f))"
 11.2122 +  by (subst powser_ms_aux.code) simp
 11.2123 +
 11.2124 +lemma hd_exp_powser: "ms_aux_hd_exp (powser_ms_aux cs f) = (if cs = MSLNil then None else Some 0)"
 11.2125 +  by (subst powser_ms_aux.code) (simp split: msllist.splits)
 11.2126 +  
 11.2127 +lemma powser_ms_aux:
 11.2128 +  assumes "convergent_powser cs" and basis: "basis_wf basis"
 11.2129 +  assumes G: "is_expansion_aux G g basis" "ms_exp_gt 0 (ms_aux_hd_exp G)"
 11.2130 +  shows   "is_expansion_aux (powser_ms_aux cs G) (powser cs \<circ> g) basis"
 11.2131 +using assms(1)
 11.2132 +proof (coinduction arbitrary: cs rule: is_expansion_aux_coinduct_upto)
 11.2133 +  case (B cs)
 11.2134 +  show ?case
 11.2135 +  proof (cases cs)
 11.2136 +    case MSLNil
 11.2137 +    with G show ?thesis by (auto simp: is_expansion_aux_expansion_level)
 11.2138 +  next
 11.2139 +    case (MSLCons c cs')
 11.2140 +    from is_expansion_aux_basis_nonempty[OF G(1)]
 11.2141 +      obtain b basis' where basis': "basis = b # basis'" by (cases basis) simp_all
 11.2142 +    from B have conv: "convergent_powser cs'" by (auto simp: MSLCons dest: convergent_powser_stl)  
 11.2143 +    from basis basis' have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2144 +    hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2145 +    
 11.2146 +    from G(2) have "g \<in> o(\<lambda>x. hd basis x powr 0)"
 11.2147 +      by (intro is_expansion_aux_imp_smallo[OF G(1)]) simp
 11.2148 +    with basis' have "g \<in> o(\<lambda>x. b x powr 0)" by simp
 11.2149 +    also have "(\<lambda>x. b x powr 0) \<in> \<Theta>(\<lambda>x. 1)" 
 11.2150 +       using b_pos by (intro bigthetaI_cong) (auto elim!: eventually_mono)
 11.2151 +    finally have g_limit: "(g \<longlongrightarrow> 0) at_top" by (auto dest: smalloD_tendsto)
 11.2152 +  
 11.2153 +    let ?P = "(\<lambda>xs'' fa'' basisa''. \<exists>cs. xs'' = powser_ms_aux cs G \<and>
 11.2154 +                     fa'' = powser cs \<circ> g \<and> basisa'' = b # basis' \<and> convergent_powser cs)"
 11.2155 +    have "ms_closure ?P (times_ms_aux G (powser_ms_aux cs' G)) 
 11.2156 +            (\<lambda>x. g x * (powser cs' \<circ> g) x) basis" using conv
 11.2157 +      by (intro ms_closure_mult [OF ms_closure_embed' ms_closure_embed] G)
 11.2158 +         (auto simp add: basis' o_def)
 11.2159 +    also have "(\<lambda>x. g x * (powser cs' \<circ> g) x) = (\<lambda>x. x * powser cs' x) \<circ> g"
 11.2160 +      by (simp add: o_def)
 11.2161 +    finally have "ms_closure ?P (times_ms_aux G (powser_ms_aux cs' G)) 
 11.2162 +                    (\<lambda>x. (powser cs \<circ> g) x - c * b x powr 0) basis" unfolding o_def
 11.2163 +    proof (rule ms_closure_cong)
 11.2164 +      note b_pos
 11.2165 +      moreover have "eventually (\<lambda>x. powser cs (g x) = g x * powser cs' (g x) + c) at_top"
 11.2166 +      proof -
 11.2167 +        from B have "eventually (\<lambda>x. powser cs x = x * powser cs' x + c) (nhds 0)"
 11.2168 +          by (simp add: MSLCons powser_MSLCons)
 11.2169 +        from this and g_limit show ?thesis by (rule eventually_compose_filterlim)
 11.2170 +      qed
 11.2171 +      ultimately show "eventually (\<lambda>x. g x * powser cs' (g x) = 
 11.2172 +                         powser cs (g x) - c * b x powr 0) at_top"
 11.2173 +        by eventually_elim simp
 11.2174 +    qed 
 11.2175 +    moreover from basis G have "is_expansion (const_expansion c :: 'a) basis'"
 11.2176 +      by (intro is_expansion_const)
 11.2177 +         (auto dest: is_expansion_aux_expansion_level simp: basis' basis_wf_Cons)
 11.2178 +    moreover have "powser cs \<circ> g \<in> o(\<lambda>x. b x powr e)" if "e > 0" for e
 11.2179 +    proof -
 11.2180 +      have "((powser cs \<circ> g) \<longlongrightarrow> powser cs 0) at_top" unfolding o_def
 11.2181 +        by (intro isCont_tendsto_compose[OF _ g_limit] isCont_powser B)
 11.2182 +      hence "powser cs \<circ> g \<in> O(\<lambda>_. 1)" 
 11.2183 +        by (intro bigoI_tendsto[where c = "powser cs 0"]) (simp_all add: o_def)
 11.2184 +      also from b_pos have  "O(\<lambda>_. 1) = O(\<lambda>x. b x powr 0)" 
 11.2185 +        by (intro landau_o.big.cong) (auto elim: eventually_mono)
 11.2186 +      also from that b_limit have "(\<lambda>x. b x powr 0) \<in> o(\<lambda>x. b x powr e)"
 11.2187 +        by (subst powr_smallo_iff) simp_all
 11.2188 +      finally show ?thesis .
 11.2189 +    qed
 11.2190 +    moreover from G have "ms_exp_gt 0 (ms_aux_hd_exp (times_ms_aux G (powser_ms_aux cs' G)))"
 11.2191 +      by (cases "ms_aux_hd_exp G") (simp_all add: hd_exp_times MSLCons hd_exp_powser)
 11.2192 +    ultimately show ?thesis
 11.2193 +      by (simp add: MSLCons powser_ms_aux_MSLCons basis')
 11.2194 +  qed
 11.2195 +qed (insert assms, simp_all)
 11.2196 +  
 11.2197 +lemma powser_ms_aux':
 11.2198 +  assumes powser: "convergent_powser' cs f" and basis: "basis_wf basis"
 11.2199 +  assumes G: "is_expansion_aux G g basis" "ms_exp_gt 0 (ms_aux_hd_exp G)"
 11.2200 +  shows   "is_expansion_aux (powser_ms_aux cs G) (f \<circ> g) basis"
 11.2201 +proof (rule is_expansion_aux_cong)
 11.2202 +  from is_expansion_aux_basis_nonempty[OF G(1)] basis
 11.2203 +    have "filterlim (hd basis) at_top at_top" by (cases basis) (simp_all add: basis_wf_Cons)
 11.2204 +  hence pos: "eventually (\<lambda>x. hd basis x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2205 +  from G(2) have "g \<in> o(\<lambda>x. hd basis x powr 0)"
 11.2206 +    by (intro is_expansion_aux_imp_smallo[OF G(1)]) simp
 11.2207 +  also have "(\<lambda>x. hd basis x powr 0) \<in> \<Theta>(\<lambda>x. 1)" 
 11.2208 +     using pos by (intro bigthetaI_cong) (auto elim!: eventually_mono)
 11.2209 +  finally have g_limit: "(g \<longlongrightarrow> 0) at_top" by (auto dest: smalloD_tendsto)
 11.2210 +  
 11.2211 +  from powser have "eventually (\<lambda>x. powser cs x = f x) (nhds 0)"
 11.2212 +    by (rule convergent_powser'_eventually)
 11.2213 +  from this and g_limit show "eventually (\<lambda>x. (powser cs \<circ> g) x = (f \<circ> g) x) at_top" 
 11.2214 +    unfolding o_def by (rule eventually_compose_filterlim)
 11.2215 +qed (rule assms powser_ms_aux convergent_powser'_imp_convergent_powser)+
 11.2216 +
 11.2217 +lemma inverse_ms_aux:
 11.2218 +  assumes basis: "basis_wf basis"
 11.2219 +  assumes F: "is_expansion_aux F f basis" "trimmed_ms_aux F"
 11.2220 +  shows   "is_expansion_aux (inverse_ms_aux F) (\<lambda>x. inverse (f x)) basis"
 11.2221 +proof (cases F rule: ms_aux_cases)
 11.2222 +  case (MSLCons C e F')
 11.2223 +  from F MSLCons obtain b basis' where F': "basis = b # basis'" "trimmed C"
 11.2224 +    "is_expansion_aux F' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.2225 +    "is_expansion C basis'" "(\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'))" 
 11.2226 +    "ms_exp_gt e (ms_aux_hd_exp F')"
 11.2227 +    by (auto elim!: is_expansion_aux_MSLCons simp: trimmed_ms_aux_def)
 11.2228 +  define f' where "f' = (\<lambda>x. f x - eval C x * b x powr e)"
 11.2229 +  from basis F' have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2230 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2231 +  moreover from F'(6)
 11.2232 +    have "ms_exp_gt 0 (ms_aux_hd_exp (scale_shift_ms_aux (inverse C, - e) F'))"
 11.2233 +    by (cases "ms_aux_hd_exp F'") (simp_all add: hd_exp_basis)
 11.2234 +  ultimately have
 11.2235 +       "is_expansion_aux (inverse_ms_aux F) 
 11.2236 +          (\<lambda>x. eval (inverse C) x * b x powr (-e) * 
 11.2237 +                 ((\<lambda>x. inverse (1 + x)) \<circ> (\<lambda>x. eval (inverse C) x * b x powr (-e) * f' x)) x)
 11.2238 +          (b # basis')" (is "is_expansion_aux _ ?h _")
 11.2239 +    unfolding MSLCons inverse_ms_aux.simps Let_def fst_conv snd_conv f'_def eval_inverse [symmetric]
 11.2240 +    using basis F(2) F'(1,3,4)
 11.2241 +    by (intro scale_shift_ms_aux powser_ms_aux' is_expansion_inverse)
 11.2242 +       (simp_all add: convergent_powser'_geometric basis_wf_Cons trimmed_ms_aux_def MSLCons)
 11.2243 +  also have "b # basis' = basis" by (simp add: F')
 11.2244 +  finally show ?thesis
 11.2245 +  proof (rule is_expansion_aux_cong, goal_cases)
 11.2246 +    case 1
 11.2247 +    from basis F' have "eventually (\<lambda>x. eval C x \<noteq> 0) at_top" 
 11.2248 +      by (intro trimmed_imp_eventually_nz[of basis']) (simp_all add: basis_wf_Cons)
 11.2249 +    with b_pos show ?case by eventually_elim (simp add: o_def field_simps powr_minus f'_def)
 11.2250 +  qed
 11.2251 +qed (insert assms, auto simp: trimmed_ms_aux_def)
 11.2252 +
 11.2253 +lemma hd_exp_inverse: 
 11.2254 +  "xs \<noteq> MSLNil \<Longrightarrow> ms_aux_hd_exp (inverse_ms_aux xs) = map_option uminus (ms_aux_hd_exp xs)"
 11.2255 +  by (cases xs) (auto simp: Let_def hd_exp_basis hd_exp_powser inverse_ms_aux.simps)
 11.2256 +
 11.2257 +lemma eval_pos_if_dominant_term_pos:
 11.2258 +  assumes "basis_wf basis" "is_expansion F basis" "trimmed F"
 11.2259 +          "fst (dominant_term F) > 0"
 11.2260 +  shows   "eventually (\<lambda>x. eval F x > 0) at_top"
 11.2261 +proof -
 11.2262 +  have "eval F \<sim>[at_top] eval_monom (dominant_term F) basis"
 11.2263 +    by (intro dominant_term assms)
 11.2264 +  from trimmed_imp_eventually_sgn[OF assms(1-3)]
 11.2265 +    have "\<forall>\<^sub>F x in at_top. sgn (eval F x) = sgn (fst (dominant_term F))" .
 11.2266 +  moreover from assms
 11.2267 +    have "eventually (\<lambda>x. eval_monom (dominant_term F) basis x > 0) at_top"
 11.2268 +    by (intro eval_monom_pos)
 11.2269 +  ultimately show ?thesis by eventually_elim (insert assms, simp add: sgn_if split: if_splits)
 11.2270 +qed
 11.2271 +
 11.2272 +lemma eval_pos_if_dominant_term_pos':
 11.2273 +  assumes "basis_wf basis" "trimmed_ms_aux F" "is_expansion_aux F f basis" 
 11.2274 +          "fst (dominant_term_ms_aux F) > 0"
 11.2275 +  shows   "eventually (\<lambda>x. f x > 0) at_top"
 11.2276 +proof -
 11.2277 +  have "f \<sim>[at_top] eval_monom (dominant_term_ms_aux F) basis"
 11.2278 +    by (intro dominant_term_ms_aux assms)
 11.2279 +  from dominant_term_ms_aux(2)[OF assms(1-3)]
 11.2280 +    have "\<forall>\<^sub>F x in at_top. sgn (f x) = sgn (fst (dominant_term_ms_aux F))" .
 11.2281 +  moreover from assms
 11.2282 +    have "eventually (\<lambda>x. eval_monom (dominant_term_ms_aux F) basis x > 0) at_top"
 11.2283 +    by (intro eval_monom_pos)
 11.2284 +  ultimately show ?thesis by eventually_elim (insert assms, simp add: sgn_if split: if_splits)
 11.2285 +qed
 11.2286 +  
 11.2287 +lemma eval_neg_if_dominant_term_neg':
 11.2288 +  assumes "basis_wf basis" "trimmed_ms_aux F" "is_expansion_aux F f basis" 
 11.2289 +          "fst (dominant_term_ms_aux F) < 0"
 11.2290 +  shows   "eventually (\<lambda>x. f x < 0) at_top"
 11.2291 +proof -
 11.2292 +  have "f \<sim>[at_top] eval_monom (dominant_term_ms_aux F) basis"
 11.2293 +    by (intro dominant_term_ms_aux assms)
 11.2294 +  from dominant_term_ms_aux(2)[OF assms(1-3)]
 11.2295 +    have "\<forall>\<^sub>F x in at_top. sgn (f x) = sgn (fst (dominant_term_ms_aux F))" .
 11.2296 +  moreover from assms
 11.2297 +  have "eventually (\<lambda>x. eval_monom (dominant_term_ms_aux F) basis x < 0) at_top"
 11.2298 +    by (intro eval_monom_neg)
 11.2299 +  ultimately show ?thesis by eventually_elim (insert assms, simp add: sgn_if split: if_splits)
 11.2300 +qed
 11.2301 +
 11.2302 +lemma fst_dominant_term_ms_aux_MSLCons: 
 11.2303 +  "fst (dominant_term_ms_aux (MSLCons x xs)) = fst (dominant_term (fst x))"
 11.2304 +  by (auto simp: dominant_term_ms_aux_def split: prod.splits)
 11.2305 +
 11.2306 +lemma powr_ms_aux:
 11.2307 +  assumes basis: "basis_wf basis"
 11.2308 +  assumes F: "is_expansion_aux F f basis" "trimmed_ms_aux F" "fst (dominant_term_ms_aux F) > 0"
 11.2309 +  shows   "is_expansion_aux (powr_ms_aux abort F p) (\<lambda>x.  f x powr p) basis"
 11.2310 +proof (cases F rule: ms_aux_cases)
 11.2311 +  case (MSLCons C e F')
 11.2312 +  from F MSLCons obtain b basis' where F': "basis = b # basis'" "trimmed C" "fst (dominant_term C) > 0"
 11.2313 +    "is_expansion_aux F' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.2314 +    "is_expansion C basis'" "(\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'))"
 11.2315 +    "ms_exp_gt e (ms_aux_hd_exp F')"
 11.2316 +    by (auto elim!: is_expansion_aux_MSLCons simp: trimmed_ms_aux_def dominant_term_ms_aux_def 
 11.2317 +             split: prod.splits)
 11.2318 +  define f' where "f' = (\<lambda>x. f x - eval C x * b x powr e)"
 11.2319 +  from basis F' have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2320 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2321 +  moreover from F' have "ms_exp_gt 0 (ms_aux_hd_exp (scale_shift_ms_aux (inverse C, - e) F'))"
 11.2322 +    by (cases "ms_aux_hd_exp F'") (simp_all add: hd_exp_basis)
 11.2323 +  ultimately have
 11.2324 +       "is_expansion_aux (powr_ms_aux abort F p) 
 11.2325 +          (\<lambda>x. eval (powr_expansion abort C p) x * b x powr (e * p) * 
 11.2326 +                 ((\<lambda>x. (1 + x) powr p) \<circ> (\<lambda>x. eval (inverse C) x * b x powr (-e) * f' x)) x)
 11.2327 +          (b # basis')" (is "is_expansion_aux _ ?h _")
 11.2328 +    unfolding MSLCons powr_ms_aux.simps Let_def fst_conv snd_conv f'_def eval_inverse [symmetric]
 11.2329 +        using basis F'(1-5)
 11.2330 +    by (intro scale_shift_ms_aux powser_ms_aux' is_expansion_inverse is_expansion_powr)
 11.2331 +       (simp_all add: MSLCons basis_wf_Cons convergent_powser'_gbinomial)
 11.2332 +  also have "b # basis' = basis" by (simp add: F')
 11.2333 +  finally show ?thesis
 11.2334 +  proof (rule is_expansion_aux_cong, goal_cases)
 11.2335 +    case 1
 11.2336 +    from basis F' have "eventually (\<lambda>x. eval C x > 0) at_top" 
 11.2337 +      by (intro eval_pos_if_dominant_term_pos[of basis']) (simp_all add: basis_wf_Cons)
 11.2338 +    moreover from basis F have "eventually (\<lambda>x. f x > 0) at_top"
 11.2339 +      by (intro eval_pos_if_dominant_term_pos'[of basis F])
 11.2340 +    ultimately show ?case using b_pos
 11.2341 +      by eventually_elim 
 11.2342 +         (simp add: powr_powr [symmetric] powr_minus powr_mult powr_divide f'_def field_simps)
 11.2343 +  qed
 11.2344 +qed (insert assms, auto simp: trimmed_ms_aux_def)
 11.2345 +
 11.2346 +lemma power_ms_aux:
 11.2347 +  assumes basis: "basis_wf basis"
 11.2348 +  assumes F: "is_expansion_aux F f basis" "trimmed_ms_aux F"
 11.2349 +  shows   "is_expansion_aux (power_ms_aux abort F n) (\<lambda>x. f x ^ n) basis"
 11.2350 +proof (cases F rule: ms_aux_cases)
 11.2351 +  case (MSLCons C e F')
 11.2352 +  from F MSLCons obtain b basis' where F': "basis = b # basis'" "trimmed C"
 11.2353 +    "is_expansion_aux F' (\<lambda>x. f x - eval C x * b x powr e) (b # basis')"
 11.2354 +    "is_expansion C basis'" "(\<And>e'. e < e' \<Longrightarrow> f \<in> o(\<lambda>x. b x powr e'))" 
 11.2355 +    "ms_exp_gt e (ms_aux_hd_exp F')"
 11.2356 +    by (auto elim!: is_expansion_aux_MSLCons simp: trimmed_ms_aux_def dominant_term_ms_aux_def 
 11.2357 +             split: prod.splits)
 11.2358 +  define f' where "f' = (\<lambda>x. f x - eval C x * b x powr e)"
 11.2359 +  from basis F' have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2360 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2361 +  moreover have "ms_exp_gt 0 (ms_aux_hd_exp (scale_shift_ms_aux (inverse C, - e) F'))"
 11.2362 +    using F'(6) by (cases "ms_aux_hd_exp F'") (simp_all add: hd_exp_basis)
 11.2363 +  ultimately have
 11.2364 +       "is_expansion_aux (power_ms_aux abort F n) 
 11.2365 +          (\<lambda>x. eval (power_expansion abort C n) x * b x powr (e * real n) * 
 11.2366 +                 ((\<lambda>x. (1 + x) ^ n) \<circ> (\<lambda>x. eval (inverse C) x * b x powr (-e) * f' x)) x)
 11.2367 +          (b # basis')" (is "is_expansion_aux _ ?h _")
 11.2368 +    unfolding MSLCons power_ms_aux.simps Let_def fst_conv snd_conv f'_def eval_inverse [symmetric]
 11.2369 +        using basis F'(1-4)
 11.2370 +    by (intro scale_shift_ms_aux powser_ms_aux' is_expansion_inverse is_expansion_power)
 11.2371 +       (simp_all add: MSLCons basis_wf_Cons convergent_powser'_gbinomial')
 11.2372 +  also have "b # basis' = basis" by (simp add: F')
 11.2373 +  finally show ?thesis
 11.2374 +  proof (rule is_expansion_aux_cong, goal_cases)
 11.2375 +    case 1
 11.2376 +    from F'(1,2,4) basis have "eventually (\<lambda>x. eval C x \<noteq> 0) at_top"
 11.2377 +      using trimmed_imp_eventually_nz[of basis' C] by (simp add: basis_wf_Cons)
 11.2378 +    thus ?case using b_pos
 11.2379 +      by eventually_elim
 11.2380 +         (simp add: field_simps f'_def powr_minus powr_powr [symmetric] powr_realpow 
 11.2381 +                    power_mult_distrib [symmetric] power_divide [symmetric]
 11.2382 +               del: power_mult_distrib power_divide)
 11.2383 +  qed
 11.2384 +qed (insert assms, auto simp: trimmed_ms_aux_def)
 11.2385 +
 11.2386 +lemma snd_dominant_term_ms_aux_MSLCons:
 11.2387 +  "snd (dominant_term_ms_aux (MSLCons (C, e) xs)) = e # snd (dominant_term C)"
 11.2388 +  by (simp add: dominant_term_ms_aux_def case_prod_unfold)
 11.2389 +
 11.2390 +
 11.2391 +subsubsection \<open>Type-class instantiations\<close>
 11.2392 +
 11.2393 +datatype 'a ms = MS "('a \<times> real) msllist" "real \<Rightarrow> real"
 11.2394 +
 11.2395 +instantiation ms :: (uminus) uminus
 11.2396 +begin
 11.2397 +
 11.2398 +primrec uminus_ms where
 11.2399 +  "-(MS xs f) = MS (uminus_ms_aux xs) (\<lambda>x. -f x)"
 11.2400 +  
 11.2401 +instance ..
 11.2402 +end
 11.2403 +
 11.2404 +instantiation ms :: (plus) plus
 11.2405 +begin
 11.2406 +
 11.2407 +fun plus_ms :: "'a ms \<Rightarrow> 'a ms \<Rightarrow> 'a ms" where
 11.2408 +  "MS xs f + MS ys g = MS (plus_ms_aux xs ys) (\<lambda>x. f x + g x)"
 11.2409 +
 11.2410 +instance ..
 11.2411 +end
 11.2412 +
 11.2413 +instantiation ms :: ("{plus,uminus}") minus
 11.2414 +begin
 11.2415 +
 11.2416 +definition minus_ms :: "'a ms \<Rightarrow> 'a ms \<Rightarrow> 'a ms" where
 11.2417 +  "F - G = F + -(G :: 'a ms)"
 11.2418 +
 11.2419 +instance ..
 11.2420 +end
 11.2421 +
 11.2422 +instantiation ms :: ("{plus,times}") times
 11.2423 +begin
 11.2424 +
 11.2425 +fun times_ms :: "'a ms \<Rightarrow> 'a ms \<Rightarrow> 'a ms" where
 11.2426 +  "MS xs f * MS ys g = MS (times_ms_aux xs ys) (\<lambda>x. f x * g x)"
 11.2427 +
 11.2428 +instance ..
 11.2429 +end
 11.2430 +
 11.2431 +instantiation ms :: (multiseries) inverse
 11.2432 +begin
 11.2433 +
 11.2434 +fun inverse_ms :: "'a ms \<Rightarrow> 'a ms" where
 11.2435 +  "inverse_ms (MS xs f) = MS (inverse_ms_aux xs) (\<lambda>x. inverse (f x))"
 11.2436 +
 11.2437 +fun divide_ms :: "'a ms \<Rightarrow> 'a ms \<Rightarrow> 'a ms" where
 11.2438 +  "divide_ms (MS xs f) (MS ys g) = MS (times_ms_aux xs (inverse_ms_aux ys)) (\<lambda>x. f x / g x)"
 11.2439 +
 11.2440 +instance ..
 11.2441 +end
 11.2442 +
 11.2443 +
 11.2444 +instantiation ms :: (multiseries) multiseries
 11.2445 +begin
 11.2446 +
 11.2447 +definition expansion_level_ms :: "'a ms itself \<Rightarrow> nat" where
 11.2448 +  expansion_level_ms_def [simp]: "expansion_level_ms _ = Suc (expansion_level (TYPE('a)))"
 11.2449 +
 11.2450 +definition zero_expansion_ms :: "'a ms" where
 11.2451 +  "zero_expansion = MS MSLNil (\<lambda>_. 0)"
 11.2452 +
 11.2453 +definition const_expansion_ms :: "real \<Rightarrow> 'a ms" where
 11.2454 +  "const_expansion c = MS (const_ms_aux c) (\<lambda>_. c)"
 11.2455 +
 11.2456 +primrec is_expansion_ms :: "'a ms \<Rightarrow> basis \<Rightarrow> bool" where
 11.2457 +  "is_expansion (MS xs f) = is_expansion_aux xs f"
 11.2458 +
 11.2459 +lemma is_expansion_ms_def': "is_expansion F = (case F of MS xs f \<Rightarrow> is_expansion_aux xs f)"
 11.2460 +  by (simp add: is_expansion_ms_def split: ms.splits)
 11.2461 +
 11.2462 +primrec eval_ms :: "'a ms \<Rightarrow> real \<Rightarrow> real" where
 11.2463 +  "eval_ms (MS _ f) = f"
 11.2464 +  
 11.2465 +lemma eval_ms_def': "eval F = (case F of MS _ f \<Rightarrow> f)"
 11.2466 +  by (cases F) simp_all
 11.2467 +
 11.2468 +primrec powr_expansion_ms :: "bool \<Rightarrow> 'a ms \<Rightarrow> real \<Rightarrow> 'a ms" where
 11.2469 +  "powr_expansion_ms abort (MS xs f) p = MS (powr_ms_aux abort xs p) (\<lambda>x. f x powr p)"
 11.2470 +  
 11.2471 +primrec power_expansion_ms :: "bool \<Rightarrow> 'a ms \<Rightarrow> nat \<Rightarrow> 'a ms" where
 11.2472 +  "power_expansion_ms abort (MS xs f) n = MS (power_ms_aux abort xs n) (\<lambda>x. f x ^ n)"
 11.2473 +
 11.2474 +primrec trimmed_ms :: "'a ms \<Rightarrow> bool" where
 11.2475 +  "trimmed_ms (MS xs _) \<longleftrightarrow> trimmed_ms_aux xs"
 11.2476 +
 11.2477 +primrec dominant_term_ms :: "'a ms \<Rightarrow> monom" where
 11.2478 +  "dominant_term_ms (MS xs _) = dominant_term_ms_aux xs"
 11.2479 +
 11.2480 +lemma length_dominant_term_ms: 
 11.2481 +  "length (snd (dominant_term (F :: 'a ms))) = Suc (expansion_level TYPE('a))"
 11.2482 +  by (cases F) (simp_all add: length_dominant_term)  
 11.2483 +
 11.2484 +instance 
 11.2485 +proof (standard, goal_cases length_basis zero const uminus plus minus times 
 11.2486 +         inverse divide powr power smallo smallomega trimmed dominant dominant_bigo)
 11.2487 +  case (smallo basis F b e)
 11.2488 +  from \<open>is_expansion F basis\<close> obtain xs f where F: "F = MS xs f" "is_expansion_aux xs f basis"
 11.2489 +    by (simp add: is_expansion_ms_def' split: ms.splits)
 11.2490 +  from F(2) have nonempty: "basis \<noteq> []" by (rule is_expansion_aux_basis_nonempty)
 11.2491 +  with smallo have filterlim_hd_basis: "filterlim (hd basis) at_top at_top"
 11.2492 +    by (cases basis) (simp_all add: basis_wf_Cons)
 11.2493 +  from F(2) obtain e' where "f \<in> o(\<lambda>x. hd basis x powr e')"
 11.2494 +    by (erule is_expansion_aux_imp_smallo')
 11.2495 +  also from smallo nonempty filterlim_hd_basis have "(\<lambda>x. hd basis x powr e') \<in> o(\<lambda>x. b x powr e)"
 11.2496 +    by (intro ln_smallo_imp_flat) auto
 11.2497 +  finally show ?case by (simp add: F)
 11.2498 +next
 11.2499 +  case (smallomega basis F b e)
 11.2500 +  obtain xs f where F: "F = MS xs f" by (cases F) simp_all
 11.2501 +  from this smallomega have *: "is_expansion_aux xs f basis" by simp
 11.2502 +  with smallomega F have "f \<in> \<omega>(\<lambda>x. b x powr e)"
 11.2503 +    by (intro is_expansion_aux_imp_smallomega [OF _ *])
 11.2504 +       (simp_all add: is_expansion_ms_def' split: ms.splits)
 11.2505 +  with F show ?case by simp
 11.2506 +next
 11.2507 +  case (minus basis F G)
 11.2508 +  thus ?case
 11.2509 +    by (simp add: minus_ms_def is_expansion_ms_def' add_uminus_conv_diff [symmetric] 
 11.2510 +                  plus_ms_aux uminus_ms_aux del: add_uminus_conv_diff split: ms.splits)
 11.2511 +next
 11.2512 +  case (divide basis F G)
 11.2513 +  have "G / F = G * inverse F" by (cases F; cases G) (simp add: divide_inverse)
 11.2514 +  with divide show ?case
 11.2515 +    by (simp add: is_expansion_ms_def' divide_inverse times_ms_aux inverse_ms_aux split: ms.splits)
 11.2516 +next
 11.2517 +  fix c :: real
 11.2518 +  show "trimmed (const_expansion c :: 'a ms) \<longleftrightarrow> c \<noteq> 0"
 11.2519 +    by (simp add: const_expansion_ms_def trimmed_ms_aux_def const_ms_aux_def 
 11.2520 +                  trimmed_const_expansion split: msllist.splits)
 11.2521 +next
 11.2522 +  fix F :: "'a ms" assume "trimmed F"
 11.2523 +  thus "fst (dominant_term F) \<noteq> 0"
 11.2524 +    by (cases F) (auto simp: dominant_term_ms_aux_def trimmed_ms_aux_MSLCons case_prod_unfold 
 11.2525 +                    trimmed_imp_dominant_term_nz split: msllist.splits)
 11.2526 +next
 11.2527 +  fix F :: "'a ms"
 11.2528 +  have "times_ms_aux (MSLCons (const_expansion 1, 0) MSLNil) xs = xs" for xs :: "('a \<times> real) msllist"
 11.2529 +  proof (coinduction arbitrary: xs rule: msllist.coinduct_upto)
 11.2530 +    case Eq_real_prod_msllist
 11.2531 +    have "map_prod (( *) (const_expansion 1 :: 'a)) ((+) (0::real)) = (\<lambda>x. x)"
 11.2532 +      by (rule ext) (simp add: map_prod_def times_const_expansion_1 case_prod_unfold)
 11.2533 +    moreover have "mslmap \<dots> = (\<lambda>x. x)" by (rule ext) (simp add: msllist.map_ident)
 11.2534 +    ultimately have "scale_shift_ms_aux (const_expansion 1 :: 'a, 0) = (\<lambda>x. x)"
 11.2535 +      by (simp add: scale_shift_ms_aux_conv_mslmap)
 11.2536 +    thus ?case
 11.2537 +      by (cases xs rule: ms_aux_cases)
 11.2538 +         (auto simp: times_ms_aux_MSLCons times_const_expansion_1
 11.2539 +            times_ms_aux.corec.cong_refl)
 11.2540 +  qed
 11.2541 +  thus "const_expansion 1 * F = F"
 11.2542 +    by (cases F) (simp add: const_expansion_ms_def const_ms_aux_def)
 11.2543 +next
 11.2544 +  fix F :: "'a ms"
 11.2545 +  show "fst (dominant_term (- F)) = - fst (dominant_term F)"
 11.2546 +       "trimmed (-F) \<longleftrightarrow> trimmed F"
 11.2547 +     by (cases F; simp add: dominant_term_ms_aux_def case_prod_unfold uminus_ms_aux_MSLCons
 11.2548 +           trimmed_ms_aux_def split: msllist.splits)+
 11.2549 +next
 11.2550 +  fix F :: "'a ms"
 11.2551 +  show "zero_expansion + F = F" "F + zero_expansion = F"
 11.2552 +    by (cases F; simp add: zero_expansion_ms_def)+
 11.2553 +qed (auto simp: eval_ms_def' const_expansion_ms_def trimmed_ms_aux_imp_nz is_expansion_ms_def' 
 11.2554 +                 const_ms_aux uminus_ms_aux plus_ms_aux times_ms_aux inverse_ms_aux 
 11.2555 +                 is_expansion_aux_expansion_level dominant_term_ms_aux length_dominant_term_ms
 11.2556 +                 minus_ms_def powr_ms_aux power_ms_aux zero_expansion_ms_def 
 11.2557 +                 is_expansion_aux.intros(1) dominant_term_ms_aux_bigo
 11.2558 +          split: ms.splits)
 11.2559 +
 11.2560 +end
 11.2561 +
 11.2562 +
 11.2563 +subsubsection \<open>Changing the evaluation function of a multiseries\<close>
 11.2564 +
 11.2565 +definition modify_eval :: "(real \<Rightarrow> real) \<Rightarrow> 'a ms \<Rightarrow> 'a ms" where
 11.2566 +  "modify_eval f F = (case F of MS xs _ \<Rightarrow> MS xs f)"
 11.2567 +
 11.2568 +lemma eval_modify_eval [simp]: "eval (modify_eval f F) = f"
 11.2569 +  by (cases F) (simp add: modify_eval_def)
 11.2570 +
 11.2571 +
 11.2572 +subsubsection \<open>Scaling expansions\<close>
 11.2573 +
 11.2574 +definition scale_ms :: "real \<Rightarrow> 'a :: multiseries \<Rightarrow> 'a" where
 11.2575 +  "scale_ms c F = const_expansion c * F"
 11.2576 +
 11.2577 +lemma scale_ms_real [simp]: "scale_ms c (c' :: real) = c * c'"
 11.2578 +  by (simp add: scale_ms_def)
 11.2579 +
 11.2580 +definition scale_ms_aux :: "real \<Rightarrow> ('a :: multiseries \<times> real) msllist \<Rightarrow> ('a \<times> real) msllist" where
 11.2581 +  "scale_ms_aux c xs = scale_shift_ms_aux (const_expansion c, 0) xs"
 11.2582 +
 11.2583 +
 11.2584 +lemma scale_ms_aux_eq_MSLNil_iff [simp]: "scale_ms_aux x xs = MSLNil \<longleftrightarrow> xs = MSLNil"
 11.2585 +  unfolding scale_ms_aux_def by simp
 11.2586 +
 11.2587 +lemma times_ms_aux_singleton:
 11.2588 +  "times_ms_aux (MSLCons (c, e) MSLNil) xs = scale_shift_ms_aux (c, e) xs"
 11.2589 +proof (coinduction arbitrary: xs rule: msllist.coinduct_strong)
 11.2590 +  case (Eq_msllist xs)
 11.2591 +  thus ?case
 11.2592 +    by (cases xs rule: ms_aux_cases)
 11.2593 +       (simp_all add: scale_shift_ms_aux_def times_ms_aux_MSLCons)
 11.2594 +qed
 11.2595 +
 11.2596 +lemma scale_ms [simp]: "scale_ms c (MS xs f) = MS (scale_ms_aux c xs) (\<lambda>x. c * f x)"
 11.2597 +  by (simp add: scale_ms_def scale_ms_aux_def const_expansion_ms_def const_ms_aux_def 
 11.2598 +        times_ms_aux_singleton)
 11.2599 +
 11.2600 +lemma scale_ms_aux_MSLNil [simp]: "scale_ms_aux c MSLNil = MSLNil" 
 11.2601 +  by (simp add: scale_ms_aux_def)
 11.2602 +
 11.2603 +lemma scale_ms_aux_MSLCons: 
 11.2604 +  "scale_ms_aux c (MSLCons (c', e) xs) = MSLCons (scale_ms c c', e) (scale_ms_aux c xs)"
 11.2605 +  by (simp add: scale_ms_aux_def scale_shift_ms_aux_MSLCons scale_ms_def)
 11.2606 +
 11.2607 +
 11.2608 +subsubsection \<open>Additional convenience rules\<close>
 11.2609 +
 11.2610 +lemma trimmed_pos_real_iff [simp]: "trimmed_pos (x :: real) \<longleftrightarrow> x > 0"
 11.2611 +  by (auto simp: trimmed_pos_def)
 11.2612 +
 11.2613 +lemma trimmed_pos_ms_iff: 
 11.2614 +  "trimmed_pos (MS xs f) \<longleftrightarrow> (case xs of MSLNil \<Rightarrow> False | MSLCons x xs \<Rightarrow> trimmed_pos (fst x))"
 11.2615 +  by (auto simp add: trimmed_pos_def dominant_term_ms_aux_def trimmed_ms_aux_def
 11.2616 +           split: msllist.splits prod.splits)
 11.2617 +
 11.2618 +lemma not_trimmed_pos_MSLNil [simp]: "\<not>trimmed_pos (MS MSLNil f)"
 11.2619 +  by (simp add: trimmed_pos_ms_iff)
 11.2620 +
 11.2621 +lemma trimmed_pos_MSLCons [simp]: "trimmed_pos (MS (MSLCons x xs) f) = trimmed_pos (fst x)"
 11.2622 +  by (simp add: trimmed_pos_ms_iff)
 11.2623 +
 11.2624 +lemma drop_zero_ms:
 11.2625 +  assumes "eventually (\<lambda>x. eval C x = 0) at_top"
 11.2626 +  assumes "is_expansion (MS (MSLCons (C, e) xs) f) basis"
 11.2627 +  shows   "is_expansion (MS xs f) basis"
 11.2628 +  using assms by (auto simp: is_expansion_ms_def intro: drop_zero_ms_aux)
 11.2629 +
 11.2630 +lemma expansion_level_eq_Nil: "length [] = expansion_level TYPE(real)" by simp
 11.2631 +lemma expansion_level_eq_Cons: 
 11.2632 +  "length xs = expansion_level TYPE('a::multiseries) \<Longrightarrow>
 11.2633 +     length (x # xs) = expansion_level TYPE('a ms)" by simp
 11.2634 +
 11.2635 +lemma basis_wf_insert_ln: 
 11.2636 +  assumes "basis_wf [b]"
 11.2637 +  shows   "basis_wf [\<lambda>x. ln (b x)]" (is ?thesis1)
 11.2638 +          "basis_wf [b, \<lambda>x. ln (b x)]" (is ?thesis2)
 11.2639 +          "is_expansion (MS (MSLCons (1::real,1) MSLNil) (\<lambda>x. ln (b x))) [\<lambda>x. ln (b x)]" (is ?thesis3)
 11.2640 +proof -
 11.2641 +  have "ln \<in> o(\<lambda>x. x :: real)"
 11.2642 +    using ln_x_over_x_tendsto_0 by (intro smalloI_tendsto) auto
 11.2643 +  with assms show ?thesis1 ?thesis2
 11.2644 +    by (auto simp: basis_wf_Cons
 11.2645 +          intro!: landau_o.small.compose[of _ _ _ "\<lambda>x. ln (b x)"] filterlim_compose[OF ln_at_top])
 11.2646 +  from assms have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2647 +  hence ev: "eventually (\<lambda>x. b x > 1) at_top" by (simp add: filterlim_at_top_dense)
 11.2648 +  have "(\<lambda>x::real. x) \<in> \<Theta>(\<lambda>x. x powr 1)"
 11.2649 +    by (intro bigthetaI_cong eventually_mono[OF eventually_gt_at_top[of 0]]) auto
 11.2650 +  also have "(\<lambda>x::real. x powr 1) \<in> o(\<lambda>a. a powr e)" if "e > 1" for e
 11.2651 +    by (subst powr_smallo_iff) (auto simp: that filterlim_ident)
 11.2652 +  finally show ?thesis3 using assms ev
 11.2653 +    by (auto intro!: is_expansion_aux.intros landau_o.small.compose[of _ at_top _ "\<lambda>x. ln (b x)"]
 11.2654 +                     filterlim_compose[OF ln_at_top b_limit] is_expansion_real.intros
 11.2655 +             elim!: eventually_mono)
 11.2656 +qed
 11.2657 +
 11.2658 +lemma basis_wf_lift_modification:
 11.2659 +  assumes "basis_wf (b' # b # bs)" "basis_wf (b # bs')"
 11.2660 +  shows   "basis_wf (b' # b # bs')"
 11.2661 +  using assms by (simp add: basis_wf_many)
 11.2662 +
 11.2663 +lemma default_basis_wf: "basis_wf [\<lambda>x. x]" 
 11.2664 +  by (simp add: basis_wf_Cons filterlim_ident)
 11.2665 +
 11.2666 +  
 11.2667 +subsubsection \<open>Lifting expansions\<close>
 11.2668 +
 11.2669 +definition is_lifting where
 11.2670 +  "is_lifting f basis basis' \<longleftrightarrow> 
 11.2671 +     (\<forall>C. eval (f C) = eval C \<and> (is_expansion C basis \<longrightarrow> is_expansion (f C) basis') \<and>
 11.2672 +          trimmed (f C) = trimmed C \<and> fst (dominant_term (f C)) = fst (dominant_term C))"
 11.2673 +  
 11.2674 +lemma is_liftingD:
 11.2675 +  assumes "is_lifting f basis basis'"
 11.2676 +  shows   "eval (f C) = eval C" "is_expansion C basis \<Longrightarrow> is_expansion (f C) basis'"
 11.2677 +          "trimmed (f C) \<longleftrightarrow> trimmed C" "fst (dominant_term (f C)) = fst (dominant_term C)"
 11.2678 +  using assms [unfolded is_lifting_def] unfolding is_lifting_def by blast+
 11.2679 +  
 11.2680 +
 11.2681 +definition lift_ms :: "'a :: multiseries \<Rightarrow> 'a ms" where
 11.2682 +  "lift_ms C = MS (MSLCons (C, 0) MSLNil) (eval C)"
 11.2683 +
 11.2684 +lemma is_expansion_lift:
 11.2685 +  assumes "basis_wf (b # basis)" "is_expansion C basis"
 11.2686 +  shows   "is_expansion (lift_ms C) (b # basis)"
 11.2687 +proof -
 11.2688 +  from assms have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.2689 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.2690 +  moreover from assms have "eval C \<in> o(\<lambda>x. b x powr e)" if "e > 0" for e
 11.2691 +    using that by (intro is_expansion_imp_smallo[OF _ assms(2)]) (simp_all add: basis_wf_Cons)
 11.2692 +  ultimately show ?thesis using assms
 11.2693 +    by (auto intro!: is_expansion_aux.intros simp: lift_ms_def is_expansion_length 
 11.2694 +             elim: eventually_mono)
 11.2695 +qed
 11.2696 +
 11.2697 +lemma eval_lift_ms [simp]: "eval (lift_ms C) = eval C"
 11.2698 +  by (simp add: lift_ms_def)
 11.2699 +
 11.2700 +lemma is_lifting_lift:
 11.2701 +  assumes "basis_wf (b # basis)"
 11.2702 +  shows   "is_lifting lift_ms basis (b # basis)"
 11.2703 +  using is_expansion_lift[OF assms] unfolding is_lifting_def
 11.2704 +  by (auto simp: lift_ms_def trimmed_ms_aux_MSLCons dominant_term_ms_aux_def case_prod_unfold)
 11.2705 +
 11.2706 +
 11.2707 +definition map_ms_aux :: 
 11.2708 +    "('a :: multiseries \<Rightarrow> 'b :: multiseries) \<Rightarrow> 
 11.2709 +       ('a \<times> real) msllist \<Rightarrow> ('b \<times> real) msllist" where
 11.2710 +  "map_ms_aux f xs = mslmap (\<lambda>(c,e). (f c, e)) xs"
 11.2711 +
 11.2712 +lemma map_ms_aux_MSLNil [simp]: "map_ms_aux f MSLNil = MSLNil"
 11.2713 +  by (simp add: map_ms_aux_def)
 11.2714 +
 11.2715 +lemma map_ms_aux_MSLCons: "map_ms_aux f (MSLCons (C, e) xs) = MSLCons (f C, e) (map_ms_aux f xs)"
 11.2716 +  by (simp add: map_ms_aux_def)
 11.2717 +
 11.2718 +lemma hd_exp_map [simp]: "ms_aux_hd_exp (map_ms_aux f xs) = ms_aux_hd_exp xs"
 11.2719 +  by (simp add: ms_aux_hd_exp_def map_ms_aux_def split: msllist.splits)
 11.2720 +
 11.2721 +lemma map_ms_altdef: "map_ms f (MS xs g) = MS (map_ms_aux f xs) g"
 11.2722 +  by (simp add: map_ms_aux_def map_prod_def)
 11.2723 +
 11.2724 +lemma eval_map_ms [simp]: "eval (map_ms f F) = eval F"
 11.2725 +  by (cases F) simp_all
 11.2726 +
 11.2727 +lemma is_expansion_map_aux:
 11.2728 +  fixes f :: "'a :: multiseries \<Rightarrow> 'b :: multiseries"
 11.2729 +  assumes "is_expansion_aux xs g (b # basis)"
 11.2730 +  assumes "\<And>C. is_expansion C basis \<Longrightarrow> is_expansion (f C) basis'"
 11.2731 +  assumes "length basis' = expansion_level TYPE('b)"
 11.2732 +  assumes "\<And>C. eval (f C) = eval C"
 11.2733 +  shows   "is_expansion_aux (map_ms_aux f xs) g (b # basis')"
 11.2734 +  using assms(1)
 11.2735 +proof (coinduction arbitrary: xs g rule: is_expansion_aux_coinduct)
 11.2736 +  case (is_expansion_aux xs g)
 11.2737 +  show ?case
 11.2738 +  proof (cases xs rule: ms_aux_cases)
 11.2739 +    case MSLNil
 11.2740 +    with is_expansion_aux show ?thesis
 11.2741 +      by (auto simp: assms elim: is_expansion_aux.cases)
 11.2742 +  next
 11.2743 +    case (MSLCons c e xs')
 11.2744 +    with is_expansion_aux show ?thesis
 11.2745 +      by (auto elim!: is_expansion_aux_MSLCons simp: map_ms_aux_MSLCons assms)
 11.2746 +  qed    
 11.2747 +qed
 11.2748 +
 11.2749 +lemma is_expansion_map:
 11.2750 +  fixes f :: "'a :: multiseries \<Rightarrow> 'b :: multiseries"
 11.2751 +    and F :: "'a ms"
 11.2752 +  assumes "is_expansion G (b # basis)"
 11.2753 +  assumes "\<And>C. is_expansion C basis \<Longrightarrow> is_expansion (f C) basis'"
 11.2754 +  assumes "\<And>C. eval (f C) = eval C"
 11.2755 +  assumes "length basis' = expansion_level TYPE('b)"
 11.2756 +  shows   "is_expansion (map_ms f G) (b # basis')"
 11.2757 +  using assms by (cases G, simp only: map_ms_altdef) (auto intro!: is_expansion_map_aux)
 11.2758 +
 11.2759 +lemma is_expansion_map_final: 
 11.2760 +  fixes f :: "'a :: multiseries \<Rightarrow> 'b :: multiseries"
 11.2761 +    and F :: "'a ms"
 11.2762 +  assumes "is_lifting f basis basis'"
 11.2763 +  assumes "is_expansion G (b # basis)"
 11.2764 +  assumes "length basis' = expansion_level TYPE('b)"
 11.2765 +  shows   "is_expansion (map_ms f G) (b # basis')"
 11.2766 +  by (rule is_expansion_map[OF assms(2)]) (insert assms, simp_all add: is_lifting_def)
 11.2767 +
 11.2768 +lemma fst_dominant_term_map_ms: 
 11.2769 +  "is_lifting f basis basis' \<Longrightarrow> fst (dominant_term (map_ms f C)) = fst (dominant_term C)"
 11.2770 +  by (cases C)
 11.2771 +     (simp add: dominant_term_ms_aux_def case_prod_unfold is_lifting_def split: msllist.splits)
 11.2772 +
 11.2773 +lemma trimmed_map_ms:
 11.2774 +  "is_lifting f basis basis' \<Longrightarrow> trimmed (map_ms f C) \<longleftrightarrow> trimmed C"
 11.2775 +  by (cases C) (simp add: trimmed_ms_aux_def is_lifting_def split: msllist.splits)
 11.2776 +
 11.2777 +lemma is_lifting_map: 
 11.2778 +  fixes f :: "'a :: multiseries \<Rightarrow> 'b :: multiseries"
 11.2779 +    and F :: "'a ms"
 11.2780 +  assumes "is_lifting f basis basis'"
 11.2781 +  assumes "length basis' = expansion_level TYPE('b)"
 11.2782 +  shows   "is_lifting (map_ms f) (b # basis) (b # basis')"
 11.2783 +  unfolding is_lifting_def
 11.2784 +  by (intro allI conjI impI is_expansion_map_final[OF assms(1)]) 
 11.2785 +     (insert assms, simp_all add: is_lifting_def fst_dominant_term_map_ms[OF assms(1)] 
 11.2786 +        trimmed_map_ms[OF assms(1)])
 11.2787 +
 11.2788 +lemma is_lifting_id: "is_lifting (\<lambda>x. x) basis basis"
 11.2789 +  by (simp add: is_lifting_def)
 11.2790 +
 11.2791 +lemma is_lifting_trans: 
 11.2792 +  "is_lifting f basis basis' \<Longrightarrow> is_lifting g basis' basis'' \<Longrightarrow> is_lifting (\<lambda>x. g (f x)) basis basis''"
 11.2793 +  by (auto simp: is_lifting_def)
 11.2794 +
 11.2795 +lemma is_expansion_X: "is_expansion (MS (MSLCons (1 :: real, 1) MSLNil) (\<lambda>x. x)) [\<lambda>x. x]"
 11.2796 +proof -
 11.2797 +  have "(\<lambda>x::real. x) \<in> \<Theta>(\<lambda>x. x powr 1)"
 11.2798 +    by (intro bigthetaI_cong eventually_mono[OF eventually_gt_at_top[of 0]]) auto
 11.2799 +  also have "(\<lambda>x::real. x powr 1) \<in> o(\<lambda>a. a powr e)" if "e > 1" for e
 11.2800 +    by (subst powr_smallo_iff) (auto simp: that filterlim_ident)
 11.2801 +  finally show ?thesis  
 11.2802 +    by (auto intro!: is_expansion_aux.intros is_expansion_real.intros 
 11.2803 +                     eventually_mono[OF eventually_gt_at_top[of "0::real"]])
 11.2804 +qed
 11.2805 +
 11.2806 +
 11.2807 +inductive expands_to :: "(real \<Rightarrow> real) \<Rightarrow> 'a :: multiseries \<Rightarrow> basis \<Rightarrow> bool" 
 11.2808 +    (infix "(expands'_to)" 50) where
 11.2809 +  "is_expansion F basis \<Longrightarrow> eventually (\<lambda>x. eval F x = f x) at_top \<Longrightarrow> (f expands_to F) basis"
 11.2810 +
 11.2811 +lemma dominant_term_expands_to:
 11.2812 +  assumes "basis_wf basis" "(f expands_to F) basis" "trimmed F"
 11.2813 +  shows   "f \<sim>[at_top] eval_monom (dominant_term F) basis"
 11.2814 +proof -
 11.2815 +  from assms have "eval F \<sim>[at_top] f" by (intro asymp_equiv_refl_ev) (simp add: expands_to.simps)
 11.2816 +  also from dominant_term[OF assms(1) _ assms(3)] assms(2)
 11.2817 +    have "eval F \<sim>[at_top] eval_monom (dominant_term F) basis" by (simp add: expands_to.simps)
 11.2818 +  finally show ?thesis by (subst asymp_equiv_sym) simp_all
 11.2819 +qed
 11.2820 +
 11.2821 +lemma expands_to_cong:
 11.2822 +  "(f expands_to F) basis \<Longrightarrow> eventually (\<lambda>x. f x = g x) at_top \<Longrightarrow> (g expands_to F) basis"
 11.2823 +  by (auto simp: expands_to.simps elim: eventually_elim2)
 11.2824 +
 11.2825 +lemma expands_to_cong':
 11.2826 +  assumes "(f expands_to MS xs g) basis" "eventually (\<lambda>x. g x = g' x) at_top"
 11.2827 +  shows   "(f expands_to MS xs g') basis"
 11.2828 +proof -
 11.2829 +  have "is_expansion_aux xs g' basis"
 11.2830 +    by (rule is_expansion_aux_cong [OF _ assms(2)]) (insert assms(1), simp add: expands_to.simps)
 11.2831 +  with assms show ?thesis
 11.2832 +    by (auto simp: expands_to.simps elim: eventually_elim2)
 11.2833 +qed
 11.2834 +
 11.2835 +lemma eval_expands_to: "(f expands_to F) basis \<Longrightarrow> eventually (\<lambda>x. eval F x = f x) at_top"
 11.2836 +  by (simp add: expands_to.simps)
 11.2837 +
 11.2838 +lemma expands_to_real_compose:
 11.2839 +  assumes "(f expands_to (c::real)) bs"
 11.2840 +  shows   "((\<lambda>x. g (f x)) expands_to g c) bs"
 11.2841 +  using assms by (auto simp: expands_to.simps is_expansion_real.simps elim: eventually_mono)
 11.2842 +
 11.2843 +lemma expands_to_lift_compose:
 11.2844 +  assumes "(f expands_to MS (MSLCons (C, e) xs) f') bs'"
 11.2845 +  assumes "eventually (\<lambda>x. f' x - h x = 0) at_top" "e = 0"
 11.2846 +  assumes "((\<lambda>x. g (h x)) expands_to G) bs" "basis_wf (b # bs)"
 11.2847 +  shows   "((\<lambda>x. g (f x)) expands_to lift_ms G) (b # bs)"
 11.2848 +proof -
 11.2849 +  from assms have "\<forall>\<^sub>F x in at_top. f' x = f x" "\<forall>\<^sub>F x in at_top. eval G x = g (h x)"
 11.2850 +    by (auto simp: expands_to.simps)
 11.2851 +  with assms(2) have "\<forall>\<^sub>F x in at_top. eval G x = g (f x)"
 11.2852 +    by eventually_elim simp
 11.2853 +  with assms show ?thesis
 11.2854 +    by (intro expands_to.intros is_expansion_lift) (auto simp: expands_to.simps)
 11.2855 +qed
 11.2856 +
 11.2857 +lemma expands_to_zero: 
 11.2858 +    "basis_wf basis \<Longrightarrow> length basis = expansion_level TYPE('a) \<Longrightarrow>
 11.2859 +       ((\<lambda>_. 0) expands_to (zero_expansion :: 'a :: multiseries)) basis"
 11.2860 +  by (auto simp add: expands_to.simps is_expansion_zero)
 11.2861 +  
 11.2862 +lemma expands_to_const: 
 11.2863 +    "basis_wf basis \<Longrightarrow> length basis = expansion_level TYPE('a) \<Longrightarrow>
 11.2864 +       ((\<lambda>_. c) expands_to (const_expansion c :: 'a :: multiseries)) basis"
 11.2865 +  by (auto simp add: expands_to.simps is_expansion_const)
 11.2866 +
 11.2867 +lemma expands_to_X: "((\<lambda>x. x) expands_to MS (MSLCons (1 :: real, 1) MSLNil) (\<lambda>x. x)) [\<lambda>x. x]"
 11.2868 +  using is_expansion_X by (simp add: expands_to.simps)
 11.2869 +    
 11.2870 +lemma expands_to_uminus:
 11.2871 +  "basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> ((\<lambda>x. -f x) expands_to -F) basis"
 11.2872 +  by (auto simp: expands_to.simps is_expansion_uminus)
 11.2873 +
 11.2874 +lemma expands_to_add:
 11.2875 +  "basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> (g expands_to G) basis \<Longrightarrow>
 11.2876 +     ((\<lambda>x. f x + g x) expands_to F + G) basis"
 11.2877 +  by (auto simp: expands_to.simps is_expansion_add elim: eventually_elim2)
 11.2878 +
 11.2879 +lemma expands_to_minus:
 11.2880 +  "basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> (g expands_to G) basis \<Longrightarrow>
 11.2881 +     ((\<lambda>x. f x - g x) expands_to F - G) basis"
 11.2882 +  by (auto simp: expands_to.simps is_expansion_minus elim: eventually_elim2)
 11.2883 +
 11.2884 +lemma expands_to_mult:
 11.2885 +  "basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> (g expands_to G) basis \<Longrightarrow>
 11.2886 +     ((\<lambda>x. f x * g x) expands_to F * G) basis"
 11.2887 +  by (auto simp: expands_to.simps is_expansion_mult elim: eventually_elim2)
 11.2888 +
 11.2889 +lemma expands_to_inverse:
 11.2890 +  "trimmed F \<Longrightarrow> basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow>
 11.2891 +     ((\<lambda>x. inverse (f x)) expands_to inverse F) basis"
 11.2892 +  by (auto simp: expands_to.simps is_expansion_inverse)
 11.2893 +
 11.2894 +lemma expands_to_divide:
 11.2895 +  "trimmed G \<Longrightarrow> basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> (g expands_to G) basis \<Longrightarrow>
 11.2896 +     ((\<lambda>x. f x / g x) expands_to F / G) basis"
 11.2897 +  by (auto simp: expands_to.simps is_expansion_divide elim: eventually_elim2)
 11.2898 +
 11.2899 +lemma expands_to_powr_0:
 11.2900 +  "eventually (\<lambda>x. f x = 0) at_top \<Longrightarrow> g \<equiv> g \<Longrightarrow> basis_wf bs \<Longrightarrow>
 11.2901 +     length bs = expansion_level TYPE('a) \<Longrightarrow>
 11.2902 +     ((\<lambda>x. f x powr g x) expands_to (zero_expansion :: 'a :: multiseries)) bs"
 11.2903 +  by (erule (1) expands_to_cong[OF expands_to_zero]) simp_all
 11.2904 +
 11.2905 +lemma expands_to_powr_const:
 11.2906 +  "trimmed_pos F \<Longrightarrow> basis_wf basis \<Longrightarrow> (f expands_to F) basis \<Longrightarrow> p \<equiv> p \<Longrightarrow>
 11.2907 +     ((\<lambda>x. f x powr p) expands_to powr_expansion abort F p) basis"
 11.2908 +  by (auto simp: expands_to.simps is_expansion_powr trimmed_pos_def elim: eventually_mono)
 11.2909 +
 11.2910 +lemma expands_to_powr_const_0:
 11.2911 +  "eventually (\<lambda>x. f x = 0) at_top \<Longrightarrow> basis_wf bs \<Longrightarrow> 
 11.2912 +     length bs = expansion_level TYPE('a :: multiseries) \<Longrightarrow>
 11.2913 +     p \<equiv> p \<Longrightarrow> ((\<lambda>x. f x powr p) expands_to (zero_expansion :: 'a)) bs"
 11.2914 +  by (rule expands_to_cong[OF expands_to_zero]) auto
 11.2915 +  
 11.2916 +
 11.2917 +lemma expands_to_powr:
 11.2918 +  assumes "trimmed_pos F" "basis_wf basis'" "(f expands_to F) basis'"
 11.2919 +  assumes "((\<lambda>x. exp (ln (f x) * g x)) expands_to E) basis"
 11.2920 +  shows   "((\<lambda>x. f x powr g x) expands_to E) basis"
 11.2921 +using assms(4)
 11.2922 +proof (rule expands_to_cong)
 11.2923 +  from eval_pos_if_dominant_term_pos[of basis' F] assms(1-4)
 11.2924 +    show "eventually (\<lambda>x. exp (ln (f x) * g x) = f x powr g x) at_top"
 11.2925 +    by (auto simp: expands_to.simps trimmed_pos_def powr_def elim: eventually_elim2)
 11.2926 +qed
 11.2927 +
 11.2928 +lemma expands_to_ln_powr:
 11.2929 +  assumes "trimmed_pos F" "basis_wf basis'" "(f expands_to F) basis'"
 11.2930 +  assumes "((\<lambda>x. ln (f x) * g x) expands_to E) basis"
 11.2931 +  shows   "((\<lambda>x. ln (f x powr g x)) expands_to E) basis"
 11.2932 +using assms(4)
 11.2933 +proof (rule expands_to_cong)
 11.2934 +  from eval_pos_if_dominant_term_pos[of basis' F] assms(1-4)
 11.2935 +    show "eventually (\<lambda>x. ln (f x) * g x = ln (f x powr g x)) at_top"
 11.2936 +    by (auto simp: expands_to.simps trimmed_pos_def powr_def elim: eventually_elim2)
 11.2937 +qed
 11.2938 +  
 11.2939 +lemma expands_to_exp_ln:
 11.2940 +  assumes "trimmed_pos F" "basis_wf basis" "(f expands_to F) basis"
 11.2941 +  shows   "((\<lambda>x. exp (ln (f x))) expands_to F) basis"
 11.2942 +using assms(3)
 11.2943 +proof (rule expands_to_cong)
 11.2944 +  from eval_pos_if_dominant_term_pos[of basis F] assms
 11.2945 +    show "eventually (\<lambda>x. f x = exp (ln (f x))) at_top"
 11.2946 +    by (auto simp: expands_to.simps trimmed_pos_def powr_def elim: eventually_elim2)
 11.2947 +qed
 11.2948 +
 11.2949 +lemma expands_to_power:
 11.2950 +  assumes "trimmed F" "basis_wf basis" "(f expands_to F) basis"
 11.2951 +  shows   "((\<lambda>x. f x ^ n) expands_to power_expansion abort F n) basis"
 11.2952 +  using assms by (auto simp: expands_to.simps is_expansion_power elim: eventually_mono)
 11.2953 +
 11.2954 +lemma expands_to_power_0:
 11.2955 +  assumes "eventually (\<lambda>x. f x = 0) at_top" "basis_wf basis"
 11.2956 +          "length basis = expansion_level TYPE('a :: multiseries)" "n \<equiv> n"
 11.2957 +  shows   "((\<lambda>x. f x ^ n) expands_to (const_expansion (0 ^ n) :: 'a)) basis"
 11.2958 +  by (rule expands_to_cong[OF expands_to_const]) (insert assms, auto elim: eventually_mono)
 11.2959 +
 11.2960 +lemma expands_to_0th_root:
 11.2961 +  assumes  "n = 0" "basis_wf basis" "length basis = expansion_level TYPE('a :: multiseries)" "f \<equiv> f"
 11.2962 +  shows   "((\<lambda>x. root n (f x)) expands_to (zero_expansion :: 'a)) basis"
 11.2963 +  by (rule expands_to_cong[OF expands_to_zero]) (insert assms, auto)
 11.2964 +
 11.2965 +lemma expands_to_root_0:
 11.2966 +  assumes  "n > 0" "eventually (\<lambda>x. f x = 0) at_top"
 11.2967 +           "basis_wf basis" "length basis = expansion_level TYPE('a :: multiseries)"
 11.2968 +  shows   "((\<lambda>x. root n (f x)) expands_to (zero_expansion :: 'a)) basis"
 11.2969 +  by (rule expands_to_cong[OF expands_to_zero]) (insert assms, auto elim: eventually_mono)
 11.2970 +
 11.2971 +lemma expands_to_root:
 11.2972 +  assumes  "n > 0" "trimmed_pos F" "basis_wf basis" "(f expands_to F) basis"
 11.2973 +  shows   "((\<lambda>x. root n (f x)) expands_to powr_expansion False F (inverse (real n))) basis"
 11.2974 +proof -
 11.2975 +  have "((\<lambda>x. f x powr (inverse (real n))) expands_to 
 11.2976 +          powr_expansion False F (inverse (real n))) basis"
 11.2977 +    using assms(2-) by (rule expands_to_powr_const)
 11.2978 +  moreover have "eventually (\<lambda>x. f x powr (inverse (real n)) = root n (f x)) at_top"
 11.2979 +    using eval_pos_if_dominant_term_pos[of basis F] assms
 11.2980 +    by (auto simp: trimmed_pos_def expands_to.simps root_powr_inverse field_simps
 11.2981 +             elim: eventually_elim2)
 11.2982 +  ultimately show ?thesis by (rule expands_to_cong)
 11.2983 +qed
 11.2984 +
 11.2985 +lemma expands_to_root_neg:
 11.2986 +  assumes  "n > 0" "trimmed_neg F" "basis_wf basis" "(f expands_to F) basis"
 11.2987 +  shows   "((\<lambda>x. root n (f x)) expands_to
 11.2988 +             -powr_expansion False (-F) (inverse (real n))) basis"
 11.2989 +proof (rule expands_to_cong)
 11.2990 +  show "((\<lambda>x. -root n (-f x)) expands_to
 11.2991 +          -powr_expansion False (-F) (inverse (real n))) basis"
 11.2992 +    using assms by (intro expands_to_uminus expands_to_root trimmed_pos_uminus) auto
 11.2993 +qed (simp_all add: real_root_minus)
 11.2994 +
 11.2995 +lemma expands_to_sqrt:
 11.2996 +  assumes "trimmed_pos F" "basis_wf basis" "(f expands_to F) basis"
 11.2997 +  shows   "((\<lambda>x. sqrt (f x)) expands_to powr_expansion False F (1/2)) basis"
 11.2998 +  using expands_to_root[of 2 F basis f] assms by (simp add: sqrt_def)
 11.2999 +
 11.3000 +lemma expands_to_exp_real:
 11.3001 +  "(f expands_to (F :: real)) basis \<Longrightarrow> ((\<lambda>x. exp (f x)) expands_to exp F) basis"
 11.3002 +  by (auto simp: expands_to.simps is_expansion_real.simps elim: eventually_mono)
 11.3003 +
 11.3004 +lemma expands_to_exp_MSLNil:
 11.3005 +  assumes "(f expands_to (MS MSLNil f' :: 'a :: multiseries ms)) bs" "basis_wf bs"
 11.3006 +  shows   "((\<lambda>x. exp (f x)) expands_to (const_expansion 1 :: 'a ms)) bs"
 11.3007 +proof -
 11.3008 +  from assms have
 11.3009 +     "eventually (\<lambda>x. f' x = 0) at_top" "eventually (\<lambda>x. f' x = f x) at_top"
 11.3010 +     and [simp]: "length bs = Suc (expansion_level(TYPE('a)))"
 11.3011 +    by (auto simp: expands_to.simps elim: is_expansion_aux.cases)
 11.3012 +  from this(1,2) have "eventually (\<lambda>x. 1 = exp (f x)) at_top"
 11.3013 +    by eventually_elim simp
 11.3014 +  thus ?thesis by (auto simp: expands_to.simps intro!: is_expansion_const assms)
 11.3015 +qed
 11.3016 +
 11.3017 +lemma expands_to_exp_zero:
 11.3018 +  "(g expands_to MS xs f) basis \<Longrightarrow> eventually (\<lambda>x. f x = 0) at_top \<Longrightarrow> basis_wf basis \<Longrightarrow>
 11.3019 +     length basis = expansion_level TYPE('a :: multiseries) \<Longrightarrow>
 11.3020 +     ((\<lambda>x. exp (g x)) expands_to (const_expansion 1 :: 'a)) basis"
 11.3021 +  by (auto simp: expands_to.simps intro!: is_expansion_const elim: eventually_elim2)
 11.3022 +
 11.3023 +lemma expands_to_sin_real: 
 11.3024 +  "(f expands_to (F :: real)) basis \<Longrightarrow> ((\<lambda>x. sin (f x)) expands_to sin F) basis"
 11.3025 +  by (auto simp: expands_to.simps is_expansion_real.simps elim: eventually_mono)
 11.3026 +
 11.3027 +lemma expands_to_cos_real: 
 11.3028 +  "(f expands_to (F :: real)) basis \<Longrightarrow> ((\<lambda>x. cos (f x)) expands_to cos F) basis"
 11.3029 +  by (auto simp: expands_to.simps is_expansion_real.simps elim: eventually_mono)
 11.3030 +   
 11.3031 +lemma expands_to_sin_MSLNil:
 11.3032 +  "(f expands_to MS (MSLNil:: ('a \<times> real) msllist) g) basis \<Longrightarrow> basis_wf basis \<Longrightarrow> 
 11.3033 +     ((\<lambda>x. sin (f x)) expands_to MS (MSLNil :: ('a :: multiseries \<times> real) msllist) (\<lambda>x. 0)) basis"
 11.3034 +  by (auto simp: expands_to.simps dominant_term_ms_aux_def intro!: is_expansion_aux.intros
 11.3035 +           elim: eventually_elim2 is_expansion_aux.cases)
 11.3036 +
 11.3037 +lemma expands_to_cos_MSLNil:
 11.3038 +  "(f expands_to MS (MSLNil:: ('a :: multiseries \<times> real) msllist) g) basis \<Longrightarrow> basis_wf basis \<Longrightarrow> 
 11.3039 +     ((\<lambda>x. cos (f x)) expands_to (const_expansion 1 :: 'a ms)) basis"
 11.3040 +  by (auto simp: expands_to.simps dominant_term_ms_aux_def const_expansion_ms_def 
 11.3041 +           intro!: const_ms_aux elim: is_expansion_aux.cases eventually_elim2)
 11.3042 +
 11.3043 +lemma sin_ms_aux':
 11.3044 +  assumes "ms_exp_gt 0 (ms_aux_hd_exp xs)" "basis_wf basis" "is_expansion_aux xs f basis"
 11.3045 +  shows   "is_expansion_aux (sin_ms_aux' xs) (\<lambda>x. sin (f x)) basis"
 11.3046 +  unfolding sin_ms_aux'_def sin_conv_pre_sin power2_eq_square using assms
 11.3047 +  by (intro times_ms_aux powser_ms_aux[unfolded o_def] convergent_powser_sin_series_stream)
 11.3048 +     (auto simp: hd_exp_times add_neg_neg split: option.splits)
 11.3049 +
 11.3050 +lemma cos_ms_aux':
 11.3051 +  assumes "ms_exp_gt 0 (ms_aux_hd_exp xs)" "basis_wf basis" "is_expansion_aux xs f basis"
 11.3052 +  shows   "is_expansion_aux (cos_ms_aux' xs) (\<lambda>x. cos (f x)) basis"
 11.3053 +  unfolding cos_ms_aux'_def cos_conv_pre_cos power2_eq_square using assms
 11.3054 +  by (intro times_ms_aux powser_ms_aux[unfolded o_def] convergent_powser_cos_series_stream)
 11.3055 +     (auto simp: hd_exp_times add_neg_neg split: option.splits)
 11.3056 +
 11.3057 +lemma expands_to_sin_ms_neg_exp: 
 11.3058 +  assumes "e < 0" "basis_wf basis" "(f expands_to MS (MSLCons (C, e) xs) g) basis"
 11.3059 +  shows   "((\<lambda>x. sin (f x)) expands_to MS (sin_ms_aux' (MSLCons (C, e) xs)) (\<lambda>x. sin (g x))) basis"
 11.3060 +  using assms by (auto simp: expands_to.simps snd_dominant_term_ms_aux_MSLCons o_def
 11.3061 +                       intro!: sin_ms_aux' elim: eventually_mono)
 11.3062 +
 11.3063 +lemma expands_to_cos_ms_neg_exp: 
 11.3064 +  assumes "e < 0" "basis_wf basis" "(f expands_to MS (MSLCons (C, e) xs) g) basis"
 11.3065 +  shows   "((\<lambda>x. cos (f x)) expands_to MS (cos_ms_aux' (MSLCons (C, e) xs)) (\<lambda>x. cos (g x))) basis"
 11.3066 +  using assms by (auto simp: expands_to.simps snd_dominant_term_ms_aux_MSLCons o_def
 11.3067 +                       intro!: cos_ms_aux' elim: eventually_mono)
 11.3068 +
 11.3069 +lemma is_expansion_sin_ms_zero_exp: 
 11.3070 +  fixes F :: "('a :: multiseries \<times> real) msllist"
 11.3071 +  assumes basis: "basis_wf (b # basis)" 
 11.3072 +  assumes F: "is_expansion (MS (MSLCons (C, 0) xs) f) (b # basis)"
 11.3073 +  assumes Sin: "((\<lambda>x. sin (eval C x)) expands_to (Sin :: 'a)) basis"
 11.3074 +  assumes Cos: "((\<lambda>x. cos (eval C x)) expands_to (Cos :: 'a)) basis"
 11.3075 +  shows   "is_expansion 
 11.3076 +             (MS (plus_ms_aux (scale_shift_ms_aux (Sin, 0) (cos_ms_aux' xs))
 11.3077 +                              (scale_shift_ms_aux (Cos, 0) (sin_ms_aux' xs))) 
 11.3078 +             (\<lambda>x. sin (f x))) (b # basis)" (is "is_expansion (MS ?A _) _")
 11.3079 +proof -
 11.3080 +  let ?g = "\<lambda>x. f x - eval C x * b x powr 0"
 11.3081 +  let ?h = "\<lambda>x. eval Sin x * b x powr 0 * cos (?g x) + eval Cos x * b x powr 0 * sin (?g x)"
 11.3082 +  from basis have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.3083 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.3084 +  from F have F': "is_expansion_aux xs ?g (b # basis)" 
 11.3085 +                  "ms_exp_gt 0 (ms_aux_hd_exp xs)" "is_expansion C basis"
 11.3086 +    by (auto elim!: is_expansion_aux_MSLCons) 
 11.3087 +  have "is_expansion_aux ?A ?h (b # basis)"
 11.3088 +    using basis Sin Cos unfolding F'(1)
 11.3089 +    by (intro plus_ms_aux scale_shift_ms_aux cos_ms_aux' sin_ms_aux' F')
 11.3090 +       (simp_all add: expands_to.simps)
 11.3091 +  moreover from b_pos eval_expands_to[OF Sin] eval_expands_to[OF Cos] 
 11.3092 +    have "eventually (\<lambda>x. ?h x = sin (f x)) at_top"
 11.3093 +    by eventually_elim (simp add: sin_add [symmetric])
 11.3094 +  ultimately have "is_expansion_aux ?A (\<lambda>x. sin (f x)) (b # basis)"
 11.3095 +    by (rule is_expansion_aux_cong)
 11.3096 +  thus ?thesis by simp
 11.3097 +qed
 11.3098 +
 11.3099 +lemma is_expansion_cos_ms_zero_exp: 
 11.3100 +  fixes F :: "('a :: multiseries \<times> real) msllist"
 11.3101 +  assumes basis: "basis_wf (b # basis)" 
 11.3102 +  assumes F: "is_expansion (MS (MSLCons (C, 0) xs) f) (b # basis)"
 11.3103 +  assumes Sin: "((\<lambda>x. sin (eval C x)) expands_to (Sin :: 'a)) basis"
 11.3104 +  assumes Cos: "((\<lambda>x. cos (eval C x)) expands_to (Cos :: 'a)) basis"
 11.3105 +  shows   "is_expansion 
 11.3106 +             (MS (minus_ms_aux (scale_shift_ms_aux (Cos, 0) (cos_ms_aux' xs))
 11.3107 +                              (scale_shift_ms_aux (Sin, 0) (sin_ms_aux' xs))) 
 11.3108 +             (\<lambda>x. cos (f x))) (b # basis)" (is "is_expansion (MS ?A _) _")
 11.3109 +proof -
 11.3110 +  let ?g = "\<lambda>x. f x - eval C x * b x powr 0"
 11.3111 +  let ?h = "\<lambda>x. eval Cos x * b x powr 0 * cos (?g x) - eval Sin x * b x powr 0 * sin (?g x)"
 11.3112 +  from basis have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.3113 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.3114 +  from F have F': "is_expansion_aux xs ?g (b # basis)" 
 11.3115 +                  "ms_exp_gt 0 (ms_aux_hd_exp xs)" "is_expansion C basis"
 11.3116 +    by (auto elim!: is_expansion_aux_MSLCons) 
 11.3117 +  have "is_expansion_aux ?A ?h (b # basis)"
 11.3118 +    using basis Sin Cos unfolding F'(1)
 11.3119 +    by (intro minus_ms_aux scale_shift_ms_aux cos_ms_aux' sin_ms_aux' F')
 11.3120 +       (simp_all add: expands_to.simps)
 11.3121 +  moreover from b_pos eval_expands_to[OF Sin] eval_expands_to[OF Cos] 
 11.3122 +    have "eventually (\<lambda>x. ?h x = cos (f x)) at_top"
 11.3123 +    by eventually_elim (simp add: cos_add [symmetric])
 11.3124 +  ultimately have "is_expansion_aux ?A (\<lambda>x. cos (f x)) (b # basis)"
 11.3125 +    by (rule is_expansion_aux_cong)
 11.3126 +  thus ?thesis by simp
 11.3127 +qed
 11.3128 +
 11.3129 +lemma expands_to_sin_ms_zero_exp: 
 11.3130 +  assumes e: "e = 0" and basis: "basis_wf (b # basis)" 
 11.3131 +  assumes F: "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)"
 11.3132 +  assumes Sin: "((\<lambda>x. sin (c x)) expands_to Sin) basis"
 11.3133 +  assumes Cos: "((\<lambda>x. cos (c x)) expands_to Cos) basis"
 11.3134 +  assumes C: "eval C = c"
 11.3135 +  shows   "((\<lambda>x. sin (f x)) expands_to 
 11.3136 +             MS (plus_ms_aux (scale_shift_ms_aux (Sin, 0) (cos_ms_aux' xs))
 11.3137 +                              (scale_shift_ms_aux (Cos, 0) (sin_ms_aux' xs)))
 11.3138 +                (\<lambda>x. sin (g x))) (b # basis)"
 11.3139 +  using is_expansion_sin_ms_zero_exp[of b basis C xs g Sin Cos] assms
 11.3140 +  by (auto simp: expands_to.simps elim: eventually_mono)
 11.3141 +    
 11.3142 +lemma expands_to_cos_ms_zero_exp: 
 11.3143 +  assumes e: "e = 0" and basis: "basis_wf (b # basis)" 
 11.3144 +  assumes F: "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)"
 11.3145 +  assumes Sin: "((\<lambda>x. sin (c x)) expands_to Sin) basis"
 11.3146 +  assumes Cos: "((\<lambda>x. cos (c x)) expands_to Cos) basis"
 11.3147 +  assumes C: "eval C = c"
 11.3148 +  shows   "((\<lambda>x. cos (f x)) expands_to 
 11.3149 +             MS (minus_ms_aux (scale_shift_ms_aux (Cos, 0) (cos_ms_aux' xs))
 11.3150 +                              (scale_shift_ms_aux (Sin, 0) (sin_ms_aux' xs)))
 11.3151 +                (\<lambda>x. cos (g x))) (b # basis)"
 11.3152 +  using is_expansion_cos_ms_zero_exp[of b basis C xs g Sin Cos] assms
 11.3153 +  by (auto simp: expands_to.simps elim: eventually_mono)
 11.3154 +  
 11.3155 +
 11.3156 +
 11.3157 +lemma expands_to_sgn_zero:
 11.3158 +  assumes "eventually (\<lambda>x. f x = 0) at_top" "basis_wf basis"
 11.3159 +          "length basis = expansion_level TYPE('a :: multiseries)"
 11.3160 +  shows   "((\<lambda>x. sgn (f x)) expands_to (zero_expansion :: 'a)) basis"
 11.3161 +  by (rule expands_to_cong[OF expands_to_zero]) (insert assms, auto simp: sgn_eq_0_iff)
 11.3162 +
 11.3163 +lemma expands_to_sgn_pos:
 11.3164 +  assumes "trimmed_pos F" "(f expands_to F) basis" "basis_wf basis"
 11.3165 +          "length basis = expansion_level TYPE('a :: multiseries)"
 11.3166 +  shows   "((\<lambda>x. sgn (f x)) expands_to (const_expansion 1 :: 'a)) basis"
 11.3167 +proof (rule expands_to_cong[OF expands_to_const])
 11.3168 +  from trimmed_imp_eventually_sgn[of basis F] assms
 11.3169 +    have "eventually (\<lambda>x. sgn (eval F x) = 1) at_top" 
 11.3170 +      by (simp add: expands_to.simps trimmed_pos_def)
 11.3171 +  moreover from assms have "eventually (\<lambda>x. eval F x = f x) at_top"
 11.3172 +    by (simp add: expands_to.simps)
 11.3173 +  ultimately show "eventually (\<lambda>x. 1 = sgn (f x)) at_top" by eventually_elim simp
 11.3174 +qed (insert assms, auto)
 11.3175 +
 11.3176 +lemma expands_to_sgn_neg:
 11.3177 +  assumes "trimmed_neg F" "(f expands_to F) basis" "basis_wf basis"
 11.3178 +          "length basis = expansion_level TYPE('a :: multiseries)"
 11.3179 +  shows   "((\<lambda>x. sgn (f x)) expands_to (const_expansion (-1) :: 'a)) basis"
 11.3180 +proof (rule expands_to_cong[OF expands_to_const])
 11.3181 +  from trimmed_imp_eventually_sgn[of basis F] assms
 11.3182 +    have "eventually (\<lambda>x. sgn (eval F x) = -1) at_top" 
 11.3183 +      by (simp add: expands_to.simps trimmed_neg_def)
 11.3184 +  moreover from assms have "eventually (\<lambda>x. eval F x = f x) at_top"
 11.3185 +    by (simp add: expands_to.simps)
 11.3186 +  ultimately show "eventually (\<lambda>x. -1 = sgn (f x)) at_top" by eventually_elim simp
 11.3187 +qed (insert assms, auto)
 11.3188 +
 11.3189 +
 11.3190 +
 11.3191 +lemma expands_to_abs_pos:
 11.3192 +  assumes "trimmed_pos F" "basis_wf basis" "(f expands_to F) basis"
 11.3193 +  shows   "((\<lambda>x. abs (f x)) expands_to F) basis"
 11.3194 +using assms(3)
 11.3195 +proof (rule expands_to_cong)
 11.3196 +  from trimmed_imp_eventually_sgn[of basis F] assms
 11.3197 +    have "eventually (\<lambda>x. sgn (eval F x) = 1) at_top" 
 11.3198 +    by (simp add: expands_to.simps trimmed_pos_def)
 11.3199 +  with assms(3) show "eventually (\<lambda>x. f x = abs (f x)) at_top" 
 11.3200 +    by (auto simp: expands_to.simps sgn_if split: if_splits elim: eventually_elim2)
 11.3201 +qed
 11.3202 +
 11.3203 +lemma expands_to_abs_neg:
 11.3204 +  assumes "trimmed_neg F" "basis_wf basis" "(f expands_to F) basis"
 11.3205 +  shows   "((\<lambda>x. abs (f x)) expands_to -F) basis"
 11.3206 +using expands_to_uminus[OF assms(2,3)]
 11.3207 +proof (rule expands_to_cong)
 11.3208 +  from trimmed_imp_eventually_sgn[of basis F] assms
 11.3209 +    have "eventually (\<lambda>x. sgn (eval F x) = -1) at_top" 
 11.3210 +    by (simp add: expands_to.simps trimmed_neg_def)
 11.3211 +  with assms(3) show "eventually (\<lambda>x. -f x = abs (f x)) at_top" 
 11.3212 +    by (auto simp: expands_to.simps sgn_if split: if_splits elim: eventually_elim2)
 11.3213 +qed
 11.3214 +
 11.3215 +lemma expands_to_imp_eventually_nz:
 11.3216 +  assumes "basis_wf basis" "(f expands_to F) basis" "trimmed F"
 11.3217 +  shows   "eventually (\<lambda>x. f x \<noteq> 0) at_top"
 11.3218 +  using trimmed_imp_eventually_nz[OF assms(1), of F] assms(2,3)
 11.3219 +  by (auto simp: expands_to.simps elim: eventually_elim2)
 11.3220 +
 11.3221 +lemma expands_to_imp_eventually_pos:
 11.3222 +  assumes "basis_wf basis" "(f expands_to F) basis" "trimmed_pos F"
 11.3223 +  shows   "eventually (\<lambda>x. f x > 0) at_top"
 11.3224 +  using eval_pos_if_dominant_term_pos[of basis F] assms 
 11.3225 +  by (auto simp: expands_to.simps trimmed_pos_def elim: eventually_elim2)
 11.3226 +
 11.3227 +lemma expands_to_imp_eventually_neg:
 11.3228 +  assumes "basis_wf basis" "(f expands_to F) basis" "trimmed_neg F"
 11.3229 +  shows   "eventually (\<lambda>x. f x < 0) at_top"
 11.3230 +  using eval_pos_if_dominant_term_pos[of basis "-F"] assms
 11.3231 +  by (auto simp: expands_to.simps trimmed_neg_def is_expansion_uminus elim: eventually_elim2)
 11.3232 +
 11.3233 +lemma expands_to_imp_eventually_gt:
 11.3234 +  assumes "basis_wf basis" "((\<lambda>x. f x - g x) expands_to F) basis" "trimmed_pos F"
 11.3235 +  shows   "eventually (\<lambda>x. f x > g x) at_top"
 11.3236 +  using expands_to_imp_eventually_pos[OF assms] by simp
 11.3237 +
 11.3238 +lemma expands_to_imp_eventually_lt:
 11.3239 +  assumes "basis_wf basis" "((\<lambda>x. f x - g x) expands_to F) basis" "trimmed_neg F"
 11.3240 +  shows   "eventually (\<lambda>x. f x < g x) at_top"
 11.3241 +  using expands_to_imp_eventually_neg[OF assms] by simp
 11.3242 +
 11.3243 +lemma eventually_diff_zero_imp_eq:
 11.3244 +  fixes f g :: "real \<Rightarrow> real"
 11.3245 +  assumes "eventually (\<lambda>x. f x - g x = 0) at_top"
 11.3246 +  shows   "eventually (\<lambda>x. f x = g x) at_top"
 11.3247 +  using assms by eventually_elim simp
 11.3248 +
 11.3249 +lemma smallo_trimmed_imp_eventually_less:
 11.3250 +  fixes f g :: "real \<Rightarrow> real"
 11.3251 +  assumes "f \<in> o(g)" "(g expands_to G) bs" "basis_wf bs" "trimmed_pos G"
 11.3252 +  shows   "eventually (\<lambda>x. f x < g x) at_top"
 11.3253 +proof -
 11.3254 +  from assms(2-4) have pos: "eventually (\<lambda>x. g x > 0) at_top"
 11.3255 +    using expands_to_imp_eventually_pos by blast
 11.3256 +  have "(1 / 2 :: real) > 0" by simp
 11.3257 +  from landau_o.smallD[OF assms(1) this] and pos
 11.3258 +    show ?thesis by eventually_elim (simp add: abs_if split: if_splits)
 11.3259 +qed
 11.3260 +
 11.3261 +lemma smallo_trimmed_imp_eventually_greater:
 11.3262 +  fixes f g :: "real \<Rightarrow> real"
 11.3263 +  assumes "f \<in> o(g)" "(g expands_to G) bs" "basis_wf bs" "trimmed_neg G"
 11.3264 +  shows   "eventually (\<lambda>x. f x > g x) at_top"
 11.3265 +proof -
 11.3266 +  from assms(2-4) have pos: "eventually (\<lambda>x. g x < 0) at_top"
 11.3267 +    using expands_to_imp_eventually_neg by blast
 11.3268 +  have "(1 / 2 :: real) > 0" by simp
 11.3269 +  from landau_o.smallD[OF assms(1) this] and pos
 11.3270 +    show ?thesis by eventually_elim (simp add: abs_if split: if_splits)
 11.3271 +qed
 11.3272 +
 11.3273 +lemma expands_to_min_lt:
 11.3274 +  assumes "(f expands_to F) basis" "eventually (\<lambda>x. f x < g x) at_top"
 11.3275 +  shows   "((\<lambda>x. min (f x) (g x)) expands_to F) basis"
 11.3276 +  using assms(1)
 11.3277 +  by (rule expands_to_cong) (insert assms(2), auto simp: min_def elim: eventually_mono)
 11.3278 +
 11.3279 +lemma expands_to_min_eq:
 11.3280 +  assumes "(f expands_to F) basis" "eventually (\<lambda>x. f x = g x) at_top"
 11.3281 +  shows   "((\<lambda>x. min (f x) (g x)) expands_to F) basis"
 11.3282 +  using assms(1)
 11.3283 +  by (rule expands_to_cong) (insert assms(2), auto simp: min_def elim: eventually_mono)
 11.3284 +
 11.3285 +lemma expands_to_min_gt:
 11.3286 +  assumes "(g expands_to G) basis" "eventually (\<lambda>x. f x > g x) at_top"
 11.3287 +  shows   "((\<lambda>x. min (f x) (g x)) expands_to G) basis"
 11.3288 +  using assms(1)
 11.3289 +  by (rule expands_to_cong) (insert assms(2), auto simp: min_def elim: eventually_mono)
 11.3290 +    
 11.3291 +lemma expands_to_max_gt:
 11.3292 +  assumes "(f expands_to F) basis" "eventually (\<lambda>x. f x > g x) at_top"
 11.3293 +  shows   "((\<lambda>x. max (f x) (g x)) expands_to F) basis"
 11.3294 +  using assms(1)
 11.3295 +  by (rule expands_to_cong) (insert assms(2), auto simp: max_def elim: eventually_mono)
 11.3296 +    
 11.3297 +lemma expands_to_max_eq:
 11.3298 +  assumes "(f expands_to F) basis" "eventually (\<lambda>x. f x = g x) at_top"
 11.3299 +  shows   "((\<lambda>x. max (f x) (g x)) expands_to F) basis"
 11.3300 +  using assms(1)
 11.3301 +  by (rule expands_to_cong) (insert assms(2), auto simp: max_def elim: eventually_mono)
 11.3302 +
 11.3303 +lemma expands_to_max_lt:
 11.3304 +  assumes "(g expands_to G) basis" "eventually (\<lambda>x. f x < g x) at_top"
 11.3305 +  shows   "((\<lambda>x. max (f x) (g x)) expands_to G) basis"
 11.3306 +  using assms(1)
 11.3307 +  by (rule expands_to_cong) (insert assms(2), auto simp: max_def elim: eventually_mono)
 11.3308 +
 11.3309 +
 11.3310 +lemma expands_to_lift:
 11.3311 +  "is_lifting f basis basis' \<Longrightarrow> (c expands_to C) basis \<Longrightarrow> (c expands_to (f C)) basis'"
 11.3312 +  by (simp add: is_lifting_def expands_to.simps)
 11.3313 +    
 11.3314 +lemma expands_to_basic_powr: 
 11.3315 +  assumes "basis_wf (b # basis)" "length basis = expansion_level TYPE('a::multiseries)"
 11.3316 +  shows   "((\<lambda>x. b x powr e) expands_to 
 11.3317 +             MS (MSLCons (const_expansion 1 :: 'a, e) MSLNil) (\<lambda>x. b x powr e)) (b # basis)"
 11.3318 +  using assms by (auto simp: expands_to.simps basis_wf_Cons powr_smallo_iff
 11.3319 +                       intro!: is_expansion_aux.intros is_expansion_const powr_smallo_iff)
 11.3320 +
 11.3321 +lemma expands_to_basic_inverse: 
 11.3322 +  assumes "basis_wf (b # basis)" "length basis = expansion_level TYPE('a::multiseries)"
 11.3323 +  shows   "((\<lambda>x. inverse (b x)) expands_to 
 11.3324 +             MS (MSLCons (const_expansion 1 :: 'a, -1) MSLNil) (\<lambda>x. b x powr -1)) (b # basis)"
 11.3325 +proof -
 11.3326 +  from assms have "eventually (\<lambda>x. b x > 0) at_top" 
 11.3327 +    by (simp add: basis_wf_Cons filterlim_at_top_dense)
 11.3328 +  moreover have "(\<lambda>a. inverse (a powr 1)) \<in> o(\<lambda>a. a powr e')" if "e' > -1" for e' :: real
 11.3329 +    using that by (simp add: landau_o.small.inverse_eq2 powr_add [symmetric] one_smallo_powr)
 11.3330 +  ultimately show ?thesis using assms
 11.3331 +    by (auto simp: expands_to.simps basis_wf_Cons powr_minus
 11.3332 +             elim: eventually_mono
 11.3333 +             intro!: is_expansion_aux.intros is_expansion_const
 11.3334 +                     landau_o.small.compose[of _ at_top _ b])
 11.3335 +qed
 11.3336 +
 11.3337 +lemma expands_to_div':
 11.3338 +  assumes "basis_wf basis" "(f expands_to F) basis" "((\<lambda>x. inverse (g x)) expands_to G) basis"
 11.3339 +  shows   "((\<lambda>x. f x / g x) expands_to F * G) basis"
 11.3340 +  using expands_to_mult[OF assms] by (simp add: divide_simps)
 11.3341 +
 11.3342 +lemma expands_to_basic: 
 11.3343 +  assumes "basis_wf (b # basis)" "length basis = expansion_level TYPE('a::multiseries)"
 11.3344 +  shows   "(b expands_to MS (MSLCons (const_expansion 1 :: 'a, 1) MSLNil) b) (b # basis)"
 11.3345 +proof -
 11.3346 +  from assms have "eventually (\<lambda>x. b x > 0) at_top" 
 11.3347 +    by (simp add: basis_wf_Cons filterlim_at_top_dense)
 11.3348 +  moreover {
 11.3349 +    fix e' :: real assume e': "e' > 1"
 11.3350 +    have "(\<lambda>x::real. x) \<in> \<Theta>(\<lambda>x. x powr 1)"
 11.3351 +      by (intro bigthetaI_cong eventually_mono[OF eventually_gt_at_top[of 0]]) auto
 11.3352 +    also have "(\<lambda>x. x powr 1) \<in> o(\<lambda>x. x powr e')"
 11.3353 +      using e' by (subst powr_smallo_iff) (auto simp: filterlim_ident)
 11.3354 +    finally have "(\<lambda>x. x) \<in> o(\<lambda>x. x powr e')" .
 11.3355 +  }
 11.3356 +  ultimately show ?thesis using assms
 11.3357 +    by (auto simp: expands_to.simps basis_wf_Cons elim: eventually_mono
 11.3358 +             intro!: is_expansion_aux.intros is_expansion_const
 11.3359 +                     landau_o.small.compose[of _ at_top _ b])
 11.3360 +qed
 11.3361 +
 11.3362 +lemma expands_to_lift':
 11.3363 +  assumes "basis_wf (b # basis)" "(f expands_to MS xs g) basis"
 11.3364 +  shows   "(f expands_to (MS (MSLCons (MS xs g, 0) MSLNil) g)) (b # basis)"
 11.3365 +proof -
 11.3366 +  have "is_lifting lift_ms basis (b # basis)" by (rule is_lifting_lift) fact+
 11.3367 +  from expands_to_lift[OF this assms(2)] show ?thesis by (simp add: lift_ms_def)
 11.3368 +qed
 11.3369 +
 11.3370 +lemma expands_to_lift'':
 11.3371 +  assumes "basis_wf (b # basis)" "(f expands_to F) basis"
 11.3372 +  shows   "(f expands_to (MS (MSLCons (F, 0) MSLNil) (eval F))) (b # basis)"
 11.3373 +proof -
 11.3374 +  have "is_lifting lift_ms basis (b # basis)" by (rule is_lifting_lift) fact+
 11.3375 +  from expands_to_lift[OF this assms(2)] show ?thesis by (simp add: lift_ms_def)
 11.3376 +qed
 11.3377 +
 11.3378 +lemma expands_to_drop_zero:
 11.3379 +  assumes "eventually (\<lambda>x. eval C x = 0) at_top"
 11.3380 +  assumes "(f expands_to (MS (MSLCons (C, e) xs) g)) basis"
 11.3381 +  shows   "(f expands_to (MS xs g)) basis"
 11.3382 +  using assms drop_zero_ms[of C e xs g basis] by (simp add: expands_to.simps)
 11.3383 +
 11.3384 +lemma expands_to_hd'':
 11.3385 +  assumes "(f expands_to (MS (MSLCons (C, e) xs) g)) (b # basis)"
 11.3386 +  shows   "(eval C expands_to C) basis"
 11.3387 +  using assms by (auto simp: expands_to.simps elim: is_expansion_aux_MSLCons)
 11.3388 +
 11.3389 +lemma expands_to_hd:
 11.3390 +  assumes "(f expands_to (MS (MSLCons (MS ys h, e) xs) g)) (b # basis)"
 11.3391 +  shows   "(h expands_to MS ys h) basis"
 11.3392 +  using assms by (auto simp: expands_to.simps elim: is_expansion_aux_MSLCons)
 11.3393 +
 11.3394 +lemma expands_to_hd':
 11.3395 +  assumes "(f expands_to (MS (MSLCons (c :: real, e) xs) g)) (b # basis)"
 11.3396 +  shows   "((\<lambda>_. c) expands_to c) basis"
 11.3397 +  using assms by (auto simp: expands_to.simps elim: is_expansion_aux_MSLCons)
 11.3398 +
 11.3399 +lemma expands_to_trim_cong:
 11.3400 +  assumes "(f expands_to (MS (MSLCons (C, e) xs) g)) (b # basis)"
 11.3401 +  assumes "(eval C expands_to C') basis"
 11.3402 +  shows   "(f expands_to (MS (MSLCons (C', e) xs) g)) (b # basis)"
 11.3403 +proof -
 11.3404 +  from assms(1) have "is_expansion_aux xs (\<lambda>x. g x - eval C x * b x powr e) (b # basis)"
 11.3405 +    by (auto simp: expands_to.simps elim!: is_expansion_aux_MSLCons)
 11.3406 +  hence "is_expansion_aux xs (\<lambda>x. g x - eval C' x * b x powr e) (b # basis)"
 11.3407 +    by (rule is_expansion_aux_cong)
 11.3408 +       (insert assms(2), auto simp: expands_to.simps elim: eventually_mono)
 11.3409 +  with assms show ?thesis
 11.3410 +    by (auto simp: expands_to.simps elim!: is_expansion_aux_MSLCons intro!: is_expansion_aux.intros)
 11.3411 +qed
 11.3412 +
 11.3413 +lemma is_expansion_aux_expands_to:
 11.3414 +  assumes "(f expands_to MS xs g) basis"
 11.3415 +  shows   "is_expansion_aux xs f basis"
 11.3416 +proof -
 11.3417 +  from assms have "is_expansion_aux xs g basis" "eventually (\<lambda>x. g x = f x) at_top" 
 11.3418 +    by (simp_all add: expands_to.simps)
 11.3419 +  thus ?thesis by (rule is_expansion_aux_cong)
 11.3420 +qed
 11.3421 +
 11.3422 +lemma ln_series_stream_aux_code:
 11.3423 +  "ln_series_stream_aux True c = MSSCons (- inverse c) (ln_series_stream_aux False (c + 1))"
 11.3424 +  "ln_series_stream_aux False c = MSSCons (inverse c) (ln_series_stream_aux True (c + 1))"
 11.3425 +  by (subst ln_series_stream_aux.code, simp)+
 11.3426 +
 11.3427 +definition powser_ms_aux' where
 11.3428 +  "powser_ms_aux' cs xs = powser_ms_aux (msllist_of_msstream cs) xs"
 11.3429 +
 11.3430 +lemma ln_ms_aux:
 11.3431 +  fixes C L :: "'a :: multiseries"
 11.3432 +  assumes trimmed: "trimmed_pos C" and basis: "basis_wf (b # basis)"
 11.3433 +  assumes F: "is_expansion_aux (MSLCons (C, e) xs) f (b # basis)"
 11.3434 +  assumes L: "((\<lambda>x. ln (eval C x) + e * ln (b x)) expands_to L) basis"
 11.3435 +  shows   "is_expansion_aux 
 11.3436 +             (MSLCons (L, 0) (times_ms_aux (scale_shift_ms_aux (inverse C, - e) xs)
 11.3437 +               (powser_ms_aux' (ln_series_stream_aux False 1) 
 11.3438 +                 (scale_shift_ms_aux (inverse C, - e) xs))))
 11.3439 +             (\<lambda>x. ln (f x)) (b # basis)"
 11.3440 +    (is "is_expansion_aux ?G _ _")
 11.3441 +proof -
 11.3442 +  from F have F': 
 11.3443 +    "is_expansion_aux xs (\<lambda>x. f x - eval C x * b x powr e) (b # basis)"
 11.3444 +    "is_expansion C basis" "\<forall>e'>e. f \<in> o(\<lambda>x. b x powr e')" "ms_exp_gt e (ms_aux_hd_exp xs)"
 11.3445 +    by (auto elim!: is_expansion_aux_MSLCons)
 11.3446 +  from basis have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.3447 +  hence b_pos: "eventually (\<lambda>x. b x > 1) at_top" by (simp add: filterlim_at_top_dense)
 11.3448 +  from eval_pos_if_dominant_term_pos[of basis C] trimmed F' basis
 11.3449 +    have C_pos: "eventually (\<lambda>x. eval C x > 0) at_top"
 11.3450 +      by (auto simp: basis_wf_Cons trimmed_pos_def)
 11.3451 +  from eval_pos_if_dominant_term_pos'[OF basis _ F] trimmed
 11.3452 +  have f_pos: "eventually (\<lambda>x. f x > 0) at_top"
 11.3453 +    by (simp add: trimmed_pos_def trimmed_ms_aux_def dominant_term_ms_aux_def case_prod_unfold)
 11.3454 +  
 11.3455 +  from F' have "ms_exp_gt 0 (map_option ((+) (-e)) (ms_aux_hd_exp xs))" 
 11.3456 +    by (cases "ms_aux_hd_exp xs") simp_all
 11.3457 +  hence "is_expansion_aux (powser_ms_aux' ln_series_stream (scale_shift_ms_aux (inverse C, -e) xs))
 11.3458 +          ((\<lambda>x. ln (1 + x)) \<circ> (\<lambda>x. eval (inverse C) x * b x powr -e * 
 11.3459 +              (f x - eval C x * b x powr e))) (b # basis)" (is "is_expansion_aux _ ?g _")
 11.3460 +    unfolding powser_ms_aux'_def using powser_ms_aux' basis F' trimmed
 11.3461 +    by (intro powser_ms_aux' convergent_powser'_ln scale_shift_ms_aux is_expansion_inverse F')
 11.3462 +       (simp_all add: trimmed_pos_def hd_exp_basis basis_wf_Cons)
 11.3463 +  moreover have "eventually (\<lambda>x. ?g x = ln (f x) - eval L x * b x powr 0) at_top"
 11.3464 +    using b_pos C_pos f_pos eval_expands_to[OF L]
 11.3465 +    by eventually_elim 
 11.3466 +       (simp add: powr_minus algebra_simps ln_mult ln_inverse expands_to.simps ln_powr)
 11.3467 +  ultimately 
 11.3468 +    have "is_expansion_aux (powser_ms_aux' ln_series_stream (scale_shift_ms_aux (inverse C, -e) xs))
 11.3469 +            (\<lambda>x. ln (f x) - eval L x * b x powr 0) (b # basis)" 
 11.3470 +      by (rule is_expansion_aux_cong)
 11.3471 +  hence *: "is_expansion_aux (times_ms_aux (scale_shift_ms_aux (inverse C, - e) xs)
 11.3472 +              (powser_ms_aux' (ln_series_stream_aux False 1) (scale_shift_ms_aux (inverse C, - e) xs)))
 11.3473 +              (\<lambda>x. ln (f x) - eval L x * b x powr 0) (b # basis)"
 11.3474 +    unfolding ln_series_stream_def powser_ms_aux'_def powser_ms_aux_MSLCons msllist_of_msstream_MSSCons
 11.3475 +    by (rule drop_zero_ms_aux [rotated]) simp_all
 11.3476 +  moreover from F' have exp: "ms_exp_gt 0 (map_option ((+) (-e)) (ms_aux_hd_exp xs))"
 11.3477 +    by (cases "ms_aux_hd_exp xs") simp_all
 11.3478 +  moreover have "(\<lambda>x. ln (f x)) \<in> o(\<lambda>x. b x powr e')" if "e' > 0" for e'
 11.3479 +  proof -
 11.3480 +    from is_expansion_aux_imp_smallo[OF *, of e'] that exp
 11.3481 +    have "(\<lambda>x. ln (f x) - eval L x * b x powr 0) \<in> o(\<lambda>x. b x powr e')" 
 11.3482 +      by (cases "ms_aux_hd_exp xs") 
 11.3483 +         (simp_all add: hd_exp_times hd_exp_powser hd_exp_basis powser_ms_aux'_def)
 11.3484 +    moreover {
 11.3485 +      from L F' basis that have "eval L \<in> o(\<lambda>x. b x powr e')"
 11.3486 +        by (intro is_expansion_imp_smallo[of basis]) (simp_all add: basis_wf_Cons expands_to.simps)
 11.3487 +      also have "eval L \<in> o(\<lambda>x. b x powr e') \<longleftrightarrow> (\<lambda>x. eval L x * b x powr 0) \<in> o(\<lambda>x. b x powr e')"
 11.3488 +        using b_pos by (intro landau_o.small.in_cong) (auto elim: eventually_mono)
 11.3489 +      finally have \<dots> .
 11.3490 +    } ultimately have "(\<lambda>x. ln (f x) - eval L x * b x powr 0 + eval L x * b x powr 0) \<in> 
 11.3491 +                          o(\<lambda>x. b x powr e')" by (rule sum_in_smallo)
 11.3492 +    thus ?thesis by simp
 11.3493 +  qed
 11.3494 +  ultimately show "is_expansion_aux ?G (\<lambda>x. ln (f x)) (b # basis)" using L
 11.3495 +    by (intro is_expansion_aux.intros)
 11.3496 +       (auto simp: expands_to.simps hd_exp_times hd_exp_powser hd_exp_basis
 11.3497 +                   powser_ms_aux'_def split: option.splits)
 11.3498 +qed
 11.3499 +
 11.3500 +lemma expands_to_ln:
 11.3501 +  fixes C L :: "'a :: multiseries"
 11.3502 +  assumes trimmed: "trimmed_pos (MS (MSLCons (C, e) xs) g)" and basis: "basis_wf (b # basis)"
 11.3503 +  assumes F: "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)"
 11.3504 +  assumes L: "((\<lambda>x. ln (h x) + e * ln (b x)) expands_to L) basis"
 11.3505 +  and h: "eval C = h"
 11.3506 +  shows   "((\<lambda>x. ln (f x)) expands_to MS
 11.3507 +             (MSLCons (L, 0) (times_ms_aux (scale_shift_ms_aux (inverse C, - e) xs)
 11.3508 +               (powser_ms_aux' (ln_series_stream_aux False 1) 
 11.3509 +                 (scale_shift_ms_aux (inverse C, - e) xs)))) (\<lambda>x. ln (f x))) (b # basis)"
 11.3510 +  using is_expansion_aux_expands_to[OF F] assms by (auto simp: expands_to.simps intro!: ln_ms_aux)
 11.3511 +
 11.3512 +lemma trimmed_lifting:
 11.3513 +  assumes "is_lifting f basis basis'"
 11.3514 +  assumes "trimmed F"
 11.3515 +  shows   "trimmed (f F)"
 11.3516 +  using assms by (simp add: is_lifting_def)
 11.3517 +
 11.3518 +lemma trimmed_pos_lifting:
 11.3519 +  assumes "is_lifting f basis basis'"
 11.3520 +  assumes "trimmed_pos F"
 11.3521 +  shows   "trimmed_pos (f F)"
 11.3522 +  using assms by (simp add: is_lifting_def trimmed_pos_def)
 11.3523 +
 11.3524 +lemma expands_to_ln_aux_0:
 11.3525 +  assumes e: "e = 0"
 11.3526 +  assumes L1: "((\<lambda>x. ln (g x)) expands_to L) basis"
 11.3527 +  shows "((\<lambda>x. ln (g x) + e * ln (b x)) expands_to L) basis"
 11.3528 +  using assms by simp
 11.3529 +
 11.3530 +lemma expands_to_ln_aux_1:
 11.3531 +  assumes e: "e = 1"
 11.3532 +  assumes basis: "basis_wf (b # basis)"
 11.3533 +  assumes L1: "((\<lambda>x. ln (g x)) expands_to L1) basis"
 11.3534 +  assumes L2: "((\<lambda>x. ln (b x)) expands_to L2) basis"
 11.3535 +  shows "((\<lambda>x. ln (g x) + e * ln (b x)) expands_to L1 + L2) basis"
 11.3536 +  using assms by (intro expands_to_add) (simp_all add: basis_wf_Cons)
 11.3537 +
 11.3538 +lemma expands_to_ln_eventually_1:
 11.3539 +  assumes "basis_wf basis" "length basis = expansion_level TYPE('a)"
 11.3540 +  assumes "eventually (\<lambda>x. f x - 1 = 0) at_top"
 11.3541 +  shows   "((\<lambda>x. ln (f x)) expands_to (zero_expansion :: 'a :: multiseries)) basis"
 11.3542 +  by (rule expands_to_cong [OF expands_to_zero]) (insert assms, auto elim: eventually_mono)  
 11.3543 +
 11.3544 +lemma expands_to_ln_aux:
 11.3545 +  assumes basis: "basis_wf (b # basis)"
 11.3546 +  assumes L1: "((\<lambda>x. ln (g x)) expands_to L1) basis"
 11.3547 +  assumes L2: "((\<lambda>x. ln (b x)) expands_to L2) basis"
 11.3548 +  shows "((\<lambda>x. ln (g x) + e * ln (b x)) expands_to L1 + scale_ms e L2) basis"
 11.3549 +proof -
 11.3550 +  from L1 have "length basis = expansion_level TYPE('a)"
 11.3551 +    by (auto simp: expands_to.simps is_expansion_length)
 11.3552 +  with assms show ?thesis unfolding scale_ms_def
 11.3553 +    by (intro expands_to_add assms expands_to_mult expands_to_const) 
 11.3554 +       (simp_all add: basis_wf_Cons)
 11.3555 +qed
 11.3556 +
 11.3557 +lemma expands_to_ln_to_expands_to_ln_eval:
 11.3558 +  assumes "((\<lambda>x. ln (f x) + F x) expands_to L) basis"
 11.3559 +  shows   "((\<lambda>x. ln (eval (MS xs f) x) + F x) expands_to L) basis"
 11.3560 +  using assms by simp
 11.3561 +
 11.3562 +lemma expands_to_ln_const:
 11.3563 +  "((\<lambda>x. ln (eval (C :: real) x)) expands_to ln C) []"
 11.3564 +  by (simp add: expands_to.simps is_expansion_real.intros)
 11.3565 +
 11.3566 +lemma expands_to_meta_eq_cong:
 11.3567 +  assumes "(f expands_to F) basis" "F \<equiv> G"
 11.3568 +  shows   "(f expands_to G) basis"
 11.3569 +  using assms by simp
 11.3570 +    
 11.3571 +lemma expands_to_meta_eq_cong':
 11.3572 +  assumes "(g expands_to F) basis" "f \<equiv> g"
 11.3573 +  shows   "(f expands_to F) basis"
 11.3574 +  using assms by simp
 11.3575 +
 11.3576 +
 11.3577 +lemma uminus_ms_aux_MSLCons_eval:
 11.3578 +  "uminus_ms_aux (MSLCons (c, e) xs) = MSLCons (-c, e) (uminus_ms_aux xs)"
 11.3579 +  by (simp add: uminus_ms_aux_MSLCons)
 11.3580 +
 11.3581 +lemma scale_shift_ms_aux_MSLCons_eval:
 11.3582 +  "scale_shift_ms_aux (c, e) (MSLCons (c', e') xs) =
 11.3583 +     MSLCons (c * c', e + e') (scale_shift_ms_aux (c, e) xs)"
 11.3584 +  by (simp add: scale_shift_ms_aux_MSLCons)
 11.3585 +
 11.3586 +lemma times_ms_aux_MSLCons_eval: "times_ms_aux (MSLCons (c1, e1) xs) (MSLCons (c2, e2) ys) = 
 11.3587 +  MSLCons (c1 * c2, e1 + e2) (plus_ms_aux (scale_shift_ms_aux (c1, e1) ys) 
 11.3588 +    (times_ms_aux xs (MSLCons (c2, e2) ys)))"
 11.3589 +  by (simp add: times_ms_aux_MSLCons)
 11.3590 +
 11.3591 +lemma plus_ms_aux_MSLCons_eval:
 11.3592 +  "plus_ms_aux (MSLCons (c1, e1) xs) (MSLCons (c2, e2) ys) =
 11.3593 +     CMP_BRANCH (COMPARE e1 e2) 
 11.3594 +       (MSLCons (c2, e2) (plus_ms_aux (MSLCons (c1, e1) xs) ys))
 11.3595 +       (MSLCons (c1 + c2, e1) (plus_ms_aux xs ys))
 11.3596 +       (MSLCons (c1, e1) (plus_ms_aux xs (MSLCons (c2, e2) ys)))"
 11.3597 +  by (simp add: CMP_BRANCH_def COMPARE_def plus_ms_aux_MSLCons)
 11.3598 +
 11.3599 +lemma inverse_ms_aux_MSLCons: "inverse_ms_aux (MSLCons (C, e) xs) = 
 11.3600 +   scale_shift_ms_aux (inverse C, - e)
 11.3601 +     (powser_ms_aux' (mssalternate 1 (- 1))
 11.3602 +       (scale_shift_ms_aux (inverse C, - e)
 11.3603 +         xs))"
 11.3604 +  by (simp add: Let_def inverse_ms_aux.simps powser_ms_aux'_def)
 11.3605 +
 11.3606 +lemma powr_ms_aux_MSLCons: "powr_ms_aux abort (MSLCons (C, e) xs) p = 
 11.3607 +  scale_shift_ms_aux (powr_expansion abort C p, e * p)
 11.3608 +     (powser_ms_aux (gbinomial_series abort p)
 11.3609 +       (scale_shift_ms_aux (inverse C, - e) xs))"
 11.3610 +  by simp
 11.3611 +
 11.3612 +lemma power_ms_aux_MSLCons: "power_ms_aux abort (MSLCons (C, e) xs) n = 
 11.3613 +  scale_shift_ms_aux (power_expansion abort C n, e * real n)
 11.3614 +     (powser_ms_aux (gbinomial_series abort (real n))
 11.3615 +       (scale_shift_ms_aux (inverse C, - e) xs))"
 11.3616 +  by simp
 11.3617 +
 11.3618 +lemma minus_ms_aux_MSLCons_eval:
 11.3619 +  "minus_ms_aux (MSLCons (c1, e1) xs) (MSLCons (c2, e2) ys) = 
 11.3620 +     CMP_BRANCH (COMPARE e1 e2) 
 11.3621 +       (MSLCons (-c2, e2) (minus_ms_aux (MSLCons (c1, e1) xs) ys))
 11.3622 +       (MSLCons (c1 - c2, e1) (minus_ms_aux xs ys))
 11.3623 +       (MSLCons (c1, e1) (minus_ms_aux xs (MSLCons (c2, e2) ys)))"
 11.3624 +  by (simp add: minus_ms_aux_def plus_ms_aux_MSLCons_eval uminus_ms_aux_MSLCons minus_eq_plus_uminus)
 11.3625 +  
 11.3626 +lemma minus_ms_altdef: "MS xs f - MS ys g = MS (minus_ms_aux xs ys) (\<lambda>x. f x - g x)"
 11.3627 +  by (simp add: minus_ms_def minus_ms_aux_def)
 11.3628 +
 11.3629 +lemma const_expansion_ms_eval: "const_expansion c = MS (MSLCons (const_expansion c, 0) MSLNil) (\<lambda>_. c)"
 11.3630 +  by (simp add: const_expansion_ms_def const_ms_aux_def)
 11.3631 + 
 11.3632 +lemma powser_ms_aux'_MSSCons:
 11.3633 +  "powser_ms_aux' (MSSCons c cs) xs = 
 11.3634 +     MSLCons (const_expansion c, 0) (times_ms_aux xs (powser_ms_aux' cs xs))"
 11.3635 +  by (simp add: powser_ms_aux'_def powser_ms_aux_MSLCons)
 11.3636 +
 11.3637 +lemma sin_ms_aux'_altdef:
 11.3638 +  "sin_ms_aux' xs = times_ms_aux xs (powser_ms_aux' sin_series_stream (times_ms_aux xs xs))"
 11.3639 +  by (simp add: sin_ms_aux'_def powser_ms_aux'_def)
 11.3640 +
 11.3641 +lemma cos_ms_aux'_altdef:
 11.3642 +  "cos_ms_aux' xs = powser_ms_aux' cos_series_stream (times_ms_aux xs xs)"
 11.3643 +  by (simp add: cos_ms_aux'_def powser_ms_aux'_def)
 11.3644 +
 11.3645 +lemma sin_series_stream_aux_code:
 11.3646 +  "sin_series_stream_aux True acc m = 
 11.3647 +     MSSCons (-inverse acc) (sin_series_stream_aux False (acc * (m + 1) * (m + 2)) (m + 2))"
 11.3648 +  "sin_series_stream_aux False acc m = 
 11.3649 +     MSSCons (inverse acc) (sin_series_stream_aux True (acc * (m + 1) * (m + 2)) (m + 2))"
 11.3650 +  by (subst sin_series_stream_aux.code; simp)+
 11.3651 +    
 11.3652 +lemma arctan_series_stream_aux_code:
 11.3653 +  "arctan_series_stream_aux True n = MSSCons (-inverse n) (arctan_series_stream_aux False (n + 2))"
 11.3654 +  "arctan_series_stream_aux False n = MSSCons (inverse n) (arctan_series_stream_aux True (n + 2))"
 11.3655 +  by (subst arctan_series_stream_aux.code; simp)+
 11.3656 +
 11.3657 +
 11.3658 +subsubsection \<open>Composition with an asymptotic power series\<close>
 11.3659 +
 11.3660 +context
 11.3661 +  fixes h :: "real \<Rightarrow> real" and F :: "real filter"
 11.3662 +begin
 11.3663 +  
 11.3664 +coinductive asymp_powser :: 
 11.3665 +    "(real \<Rightarrow> real) \<Rightarrow> real msstream \<Rightarrow> bool" where
 11.3666 +  "asymp_powser f cs \<Longrightarrow> f' \<in> O[F](\<lambda>_. 1) \<Longrightarrow>
 11.3667 +     eventually (\<lambda>x. f' x = c + f x * h x) F \<Longrightarrow> asymp_powser f' (MSSCons c cs)"
 11.3668 +
 11.3669 +lemma asymp_powser_coinduct [case_names asymp_powser]:
 11.3670 +  "P x1 x2 \<Longrightarrow> (\<And>x1 x2.  P x1 x2 \<Longrightarrow> \<exists>f cs c.
 11.3671 +       x2 = MSSCons c cs \<and> asymp_powser f cs \<and>
 11.3672 +       x1 \<in> O[F](\<lambda>_. 1) \<and> (\<forall>\<^sub>F x in F. x1 x = c + f x * h x)) \<Longrightarrow> asymp_powser x1 x2"
 11.3673 +  using asymp_powser.coinduct[of P x1 x2] by blast
 11.3674 +    
 11.3675 +lemma asymp_powser_coinduct' [case_names asymp_powser]:
 11.3676 +  "P x1 x2 \<Longrightarrow> (\<And>x1 x2.  P x1 x2 \<Longrightarrow> \<exists>f cs c.
 11.3677 +       x2 = MSSCons c cs \<and> P f cs \<and>
 11.3678 +       x1 \<in> O[F](\<lambda>_. 1) \<and> (\<forall>\<^sub>F x in F. x1 x = c + f x * h x)) \<Longrightarrow> asymp_powser x1 x2"
 11.3679 +  using asymp_powser.coinduct[of P x1 x2] by blast
 11.3680 +  
 11.3681 +lemma asymp_powser_transfer:
 11.3682 +  assumes "asymp_powser f cs" "eventually (\<lambda>x. f x = f' x) F"
 11.3683 +  shows   "asymp_powser f' cs"
 11.3684 +  using assms(1)
 11.3685 +proof (cases rule: asymp_powser.cases)
 11.3686 +  case (1 f cs' c)
 11.3687 +  have "asymp_powser f' (MSSCons c cs')"
 11.3688 +    by (rule asymp_powser.intros) 
 11.3689 +       (insert 1 assms(2), auto elim: eventually_elim2 dest: landau_o.big.in_cong)
 11.3690 +  thus ?thesis by (simp add: 1)
 11.3691 +qed
 11.3692 +
 11.3693 +lemma sum_bigo_imp_asymp_powser:
 11.3694 +  assumes filterlim_h: "filterlim h (at 0) F"
 11.3695 +  assumes "(\<And>n. (\<lambda>x. f x - (\<Sum>k<n. mssnth cs k * h x ^ k)) \<in> O[F](\<lambda>x. h x ^ n))"
 11.3696 +  shows   "asymp_powser f cs"
 11.3697 +  using assms(2)
 11.3698 +proof (coinduction arbitrary: f cs rule: asymp_powser_coinduct')
 11.3699 +  case (asymp_powser f cs)
 11.3700 +  from filterlim_h have h_nz:"eventually (\<lambda>x. h x \<noteq> 0) F"
 11.3701 +    by (auto simp: filterlim_at)
 11.3702 +  show ?case
 11.3703 +  proof (cases cs)
 11.3704 +    case (MSSCons c cs')
 11.3705 +    define f' where "f' = (\<lambda>x. (f x - c) / h x)"  
 11.3706 +    have "(\<lambda>x. f' x - (\<Sum>k<n. mssnth cs' k * h x ^ k)) \<in> O[F](\<lambda>x. h x ^ n)" for n
 11.3707 +    proof -
 11.3708 +      have "(\<lambda>x. h x * (f' x - (\<Sum>i<n. mssnth cs' i * h x ^ i))) \<in>
 11.3709 +                \<Theta>[F](\<lambda>x. f x - c - h x * (\<Sum>i<n. mssnth cs' i * h x ^ i))"
 11.3710 +        using h_nz by (intro bigthetaI_cong) (auto elim!: eventually_mono simp: f'_def field_simps)
 11.3711 +      also from spec[OF asymp_powser, of "Suc n"]
 11.3712 +        have "(\<lambda>x. f x - c - h x * (\<Sum>i<n. mssnth cs' i * h x ^ i)) \<in> O[F](\<lambda>x. h x * h x ^ n)"
 11.3713 +        unfolding sum_lessThan_Suc_shift
 11.3714 +        by (simp add: MSSCons algebra_simps sum_distrib_left sum_distrib_right)
 11.3715 +      finally show ?thesis
 11.3716 +        by (subst (asm) landau_o.big.mult_cancel_left) (insert h_nz, auto)
 11.3717 +    qed
 11.3718 +    moreover from h_nz have "\<forall>\<^sub>F x in F. f x = c + f' x * h x"
 11.3719 +      by eventually_elim (simp add: f'_def)
 11.3720 +    ultimately show ?thesis using spec[OF asymp_powser, of 0]
 11.3721 +      by (auto simp: MSSCons intro!: exI[of _ f'])
 11.3722 +  qed
 11.3723 +qed
 11.3724 +
 11.3725 +end
 11.3726 +
 11.3727 +
 11.3728 +lemma asymp_powser_o:
 11.3729 +  assumes "asymp_powser h F f cs" assumes "filterlim g F G"
 11.3730 +  shows   "asymp_powser (h \<circ> g) G (f \<circ> g) cs"
 11.3731 +using assms(1)
 11.3732 +proof (coinduction arbitrary: f cs rule: asymp_powser_coinduct')
 11.3733 +  case (asymp_powser f cs)
 11.3734 +  thus ?case
 11.3735 +  proof (cases rule: asymp_powser.cases)
 11.3736 +    case (1 f' cs' c)
 11.3737 +    from assms(2) have "filtermap g G \<le> F" by (simp add: filterlim_def)
 11.3738 +    moreover have "eventually (\<lambda>x. f x = c + f' x * h x) F" by fact
 11.3739 +    ultimately have "eventually (\<lambda>x. f x = c + f' x * h x) (filtermap g G)" by (rule filter_leD)
 11.3740 +    hence "eventually (\<lambda>x. f (g x) = c + f' (g x) * h (g x)) G" by (simp add: eventually_filtermap)
 11.3741 +    moreover from 1 have "f \<circ> g \<in> O[G](\<lambda>_. 1)" unfolding o_def
 11.3742 +      by (intro landau_o.big.compose[OF _ assms(2)]) auto
 11.3743 +    ultimately show ?thesis using 1 by force
 11.3744 +  qed
 11.3745 +qed
 11.3746 +
 11.3747 +lemma asymp_powser_compose:
 11.3748 +  assumes "asymp_powser h F f cs" assumes "filterlim g F G"
 11.3749 +  shows   "asymp_powser (\<lambda>x. h (g x)) G (\<lambda>x. f (g x)) cs"
 11.3750 +  using asymp_powser_o[OF assms] by (simp add: o_def)
 11.3751 +
 11.3752 +lemma hd_exp_powser': "ms_aux_hd_exp (powser_ms_aux' cs f) = Some 0"
 11.3753 +  by (simp add: powser_ms_aux'_def hd_exp_powser)
 11.3754 +
 11.3755 +lemma powser_ms_aux_asymp_powser:
 11.3756 +  assumes "asymp_powser h at_top f cs" and basis: "basis_wf bs"
 11.3757 +  assumes "is_expansion_aux xs h bs" "ms_exp_gt 0 (ms_aux_hd_exp xs)"
 11.3758 +  shows   "is_expansion_aux (powser_ms_aux' cs xs) f bs"
 11.3759 +using assms(1)
 11.3760 +proof (coinduction arbitrary: cs f rule: is_expansion_aux_coinduct_upto)
 11.3761 +  show "basis_wf bs" by fact
 11.3762 +next
 11.3763 +  case (B cs f)
 11.3764 +  thus ?case
 11.3765 +  proof (cases rule: asymp_powser.cases)
 11.3766 +    case (1 f' cs' c)
 11.3767 +    from assms(3) obtain b bs' where [simp]: "bs = b # bs'"
 11.3768 +      by (cases bs) (auto dest: is_expansion_aux_basis_nonempty)
 11.3769 +    from basis have b_at_top: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.3770 +    hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (auto simp: filterlim_at_top_dense)
 11.3771 +    
 11.3772 +    have A: "f \<in> o(\<lambda>x. b x powr e)" if "e > 0" for e :: real
 11.3773 +    proof -
 11.3774 +      have "f \<in> O(\<lambda>_. 1)" by fact
 11.3775 +      also have "(\<lambda>_::real. 1) \<in> o(\<lambda>x. b x powr e)"
 11.3776 +        by (rule landau_o.small.compose[OF _ b_at_top]) (insert that, simp_all add: one_smallo_powr)
 11.3777 +      finally show ?thesis .
 11.3778 +    qed
 11.3779 +    have "ms_closure (\<lambda>xsa'' fa'' basis''.
 11.3780 +            \<exists>cs. xsa'' = powser_ms_aux' cs xs \<and> basis'' = b # bs' \<and> asymp_powser h at_top fa'' cs)
 11.3781 +           (times_ms_aux xs (powser_ms_aux' cs' xs)) (\<lambda>x. h x * f' x) bs" 
 11.3782 +      (is "ms_closure ?Q ?ys _ _")
 11.3783 +      by (rule ms_closure_mult[OF ms_closure_embed' ms_closure_embed])
 11.3784 +         (insert assms 1, auto intro!: exI[of _ cs'])
 11.3785 +    moreover have "eventually (\<lambda>x. h x * f' x = f x - c * b x powr 0) at_top"
 11.3786 +      using b_pos and \<open>\<forall>\<^sub>F x in at_top. f x = c + f' x * h x\<close>
 11.3787 +      by eventually_elim simp
 11.3788 +    ultimately have "ms_closure ?Q ?ys (\<lambda>x. f x - c * b x powr 0) bs"
 11.3789 +      by (rule ms_closure_cong)
 11.3790 +    with 1 assms A show ?thesis
 11.3791 +      using is_expansion_aux_expansion_level[OF assms(3)]
 11.3792 +      by (auto simp: powser_ms_aux'_MSSCons basis_wf_Cons hd_exp_times hd_exp_powser'
 11.3793 +               intro!: is_expansion_const ms_closure_add ms_closure_mult split: option.splits)
 11.3794 +  qed
 11.3795 +qed
 11.3796 +
 11.3797 +
 11.3798 +subsubsection \<open>Arc tangent\<close>
 11.3799 +
 11.3800 +definition arctan_ms_aux where
 11.3801 +  "arctan_ms_aux xs = times_ms_aux xs (powser_ms_aux' arctan_series_stream (times_ms_aux xs xs))"
 11.3802 +
 11.3803 +lemma arctan_ms_aux_0:
 11.3804 +  assumes "ms_exp_gt 0 (ms_aux_hd_exp xs)" "basis_wf basis" "is_expansion_aux xs f basis"
 11.3805 +  shows   "is_expansion_aux (arctan_ms_aux xs) (\<lambda>x. arctan (f x)) basis" 
 11.3806 +proof (rule is_expansion_aux_cong)
 11.3807 +  let ?g = "powser (msllist_of_msstream arctan_series_stream)"
 11.3808 +  show "is_expansion_aux (arctan_ms_aux xs)
 11.3809 +          (\<lambda>x. f x * (?g \<circ> (\<lambda>x. f x * f x)) x) basis"
 11.3810 +    unfolding arctan_ms_aux_def powser_ms_aux'_def using assms
 11.3811 +    by (intro times_ms_aux powser_ms_aux powser_ms_aux convergent_powser_arctan)
 11.3812 +       (auto simp: hd_exp_times add_neg_neg split: option.splits)
 11.3813 +  
 11.3814 +  have "f \<in> o(\<lambda>x. hd basis x powr 0)" using assms
 11.3815 +    by (intro is_expansion_aux_imp_smallo[OF assms(3)]) auto
 11.3816 +  also have "(\<lambda>x. hd basis x powr 0) \<in> O(\<lambda>_. 1)"
 11.3817 +    by (intro bigoI[of _ 1]) auto
 11.3818 +  finally have "filterlim f (nhds 0) at_top"
 11.3819 +    by (auto dest!: smalloD_tendsto)
 11.3820 +  from order_tendstoD(2)[OF tendsto_norm [OF this], of 1]
 11.3821 +    have "eventually (\<lambda>x. norm (f x) < 1) at_top" by simp
 11.3822 +  thus "eventually (\<lambda>x. f x * (?g \<circ> (\<lambda>x. f x * f x)) x = arctan (f x)) at_top"
 11.3823 +    by eventually_elim (simp add: arctan_conv_pre_arctan power2_eq_square)
 11.3824 +qed
 11.3825 +
 11.3826 +lemma arctan_ms_aux_inf:
 11.3827 +  assumes "\<exists>e>0. ms_aux_hd_exp xs = Some e" "fst (dominant_term_ms_aux xs) > 0" "trimmed_ms_aux xs" 
 11.3828 +          "basis_wf basis" "is_expansion_aux xs f basis"
 11.3829 +  shows   "is_expansion_aux (minus_ms_aux (const_ms_aux (pi / 2))
 11.3830 +             (arctan_ms_aux (inverse_ms_aux xs))) (\<lambda>x. arctan (f x)) basis"
 11.3831 +    (is "is_expansion_aux ?xs' _ _")
 11.3832 +proof (rule is_expansion_aux_cong)
 11.3833 +  from \<open>trimmed_ms_aux xs\<close> have [simp]: "xs \<noteq> MSLNil" by auto
 11.3834 +  thus "is_expansion_aux ?xs' (\<lambda>x. pi / 2 - arctan (inverse (f x))) basis" using assms
 11.3835 +    by (intro minus_ms_aux arctan_ms_aux_0 inverse_ms_aux const_ms_aux)
 11.3836 +       (auto simp: hd_exp_inverse is_expansion_aux_expansion_level)
 11.3837 +next
 11.3838 +  from assms(2-5) have "eventually (\<lambda>x. f x > 0) at_top"
 11.3839 +    by (intro eval_pos_if_dominant_term_pos') simp_all
 11.3840 +  thus "eventually (\<lambda>x. ((\<lambda>x. pi/2 - arctan (inverse (f x)))) x = arctan (f x)) at_top"
 11.3841 +    unfolding o_def by eventually_elim (subst arctan_inverse_pos, simp_all)
 11.3842 +qed
 11.3843 +
 11.3844 +lemma arctan_ms_aux_neg_inf:
 11.3845 +  assumes "\<exists>e>0. ms_aux_hd_exp xs = Some e" "fst (dominant_term_ms_aux xs) < 0" "trimmed_ms_aux xs" 
 11.3846 +          "basis_wf basis" "is_expansion_aux xs f basis"
 11.3847 +  shows   "is_expansion_aux (minus_ms_aux (const_ms_aux (-pi / 2))
 11.3848 +             (arctan_ms_aux (inverse_ms_aux xs))) (\<lambda>x. arctan (f x)) basis"
 11.3849 +    (is "is_expansion_aux ?xs' _ _")
 11.3850 +proof (rule is_expansion_aux_cong)
 11.3851 +  from \<open>trimmed_ms_aux xs\<close> have [simp]: "xs \<noteq> MSLNil" by auto
 11.3852 +  thus "is_expansion_aux ?xs' (\<lambda>x. -pi / 2 - arctan (inverse (f x))) basis" using assms
 11.3853 +    by (intro minus_ms_aux arctan_ms_aux_0 inverse_ms_aux const_ms_aux)
 11.3854 +       (auto simp: hd_exp_inverse is_expansion_aux_expansion_level)
 11.3855 +next
 11.3856 +  from assms(2-5) have "eventually (\<lambda>x. f x < 0) at_top"
 11.3857 +    by (intro eval_neg_if_dominant_term_neg') simp_all
 11.3858 +  thus "eventually (\<lambda>x. ((\<lambda>x. -pi/2 - arctan (inverse (f x)))) x = arctan (f x)) at_top"
 11.3859 +    unfolding o_def by eventually_elim (subst arctan_inverse_neg, simp_all)
 11.3860 +qed
 11.3861 +
 11.3862 +lemma expands_to_arctan_zero:
 11.3863 +  assumes "((\<lambda>_::real. 0::real) expands_to C) bs" "eventually (\<lambda>x. f x = 0) at_top"
 11.3864 +  shows   "((\<lambda>x::real. arctan (f x)) expands_to C) bs"
 11.3865 +  using assms by (auto simp: expands_to.simps elim: eventually_elim2)
 11.3866 +
 11.3867 +lemma expands_to_arctan_ms_neg_exp: 
 11.3868 +  assumes "e < 0" "basis_wf basis" "(f expands_to MS (MSLCons (C, e) xs) g) basis"
 11.3869 +  shows   "((\<lambda>x. arctan (f x)) expands_to
 11.3870 +               MS (arctan_ms_aux (MSLCons (C, e) xs)) (\<lambda>x. arctan (g x))) basis"
 11.3871 +  using assms by (auto simp: expands_to.simps snd_dominant_term_ms_aux_MSLCons o_def
 11.3872 +                       intro!: arctan_ms_aux_0 elim: eventually_mono)
 11.3873 +
 11.3874 +lemma expands_to_arctan_ms_pos_exp_pos: 
 11.3875 +  assumes "e > 0" "trimmed_pos (MS (MSLCons (C, e) xs) g)" "basis_wf basis" 
 11.3876 +          "(f expands_to MS (MSLCons (C, e) xs) g) basis"
 11.3877 +  shows   "((\<lambda>x. arctan (f x)) expands_to MS (minus_ms_aux (const_ms_aux (pi / 2))
 11.3878 +             (arctan_ms_aux (inverse_ms_aux (MSLCons (C, e) xs))))
 11.3879 +               (\<lambda>x. arctan (g x))) basis"
 11.3880 +  using arctan_ms_aux_inf[of "MSLCons (C, e) xs" basis g] assms
 11.3881 +  by (auto simp: expands_to.simps snd_dominant_term_ms_aux_MSLCons o_def
 11.3882 +                 dominant_term_ms_aux_MSLCons trimmed_pos_def elim: eventually_mono)
 11.3883 +
 11.3884 +lemma expands_to_arctan_ms_pos_exp_neg: 
 11.3885 +  assumes "e > 0" "trimmed_neg (MS (MSLCons (C, e) xs) g)" "basis_wf basis" 
 11.3886 +          "(f expands_to MS (MSLCons (C, e) xs) g) basis"
 11.3887 +  shows   "((\<lambda>x. arctan (f x)) expands_to MS (minus_ms_aux (const_ms_aux (-pi/2))
 11.3888 +             (arctan_ms_aux (inverse_ms_aux (MSLCons (C, e) xs))))
 11.3889 +               (\<lambda>x. arctan (g x))) basis"
 11.3890 +  using arctan_ms_aux_neg_inf[of "MSLCons (C, e) xs" basis g] assms
 11.3891 +  by (auto simp: expands_to.simps snd_dominant_term_ms_aux_MSLCons o_def
 11.3892 +                 dominant_term_ms_aux_MSLCons trimmed_neg_def elim: eventually_mono)                     
 11.3893 +
 11.3894 +
 11.3895 +subsubsection \<open>Exponential function\<close>
 11.3896 +
 11.3897 +(* TODO: Move *)
 11.3898 +lemma ln_smallo_powr:
 11.3899 +  assumes "(e::real) > 0"
 11.3900 +  shows   "(\<lambda>x. ln x) \<in> o(\<lambda>x. x powr e)"
 11.3901 +proof -
 11.3902 +  have *: "ln \<in> o(\<lambda>x::real. x)"
 11.3903 +    using ln_x_over_x_tendsto_0 by (intro smalloI_tendsto) auto
 11.3904 +  have "(\<lambda>x. ln x) \<in> \<Theta>(\<lambda>x::real. ln x powr 1)"
 11.3905 +    by (intro bigthetaI_cong eventually_mono[OF eventually_gt_at_top[of 1]]) auto
 11.3906 +  also have "(\<lambda>x::real. ln x powr 1) \<in> o(\<lambda>x. x powr e)"
 11.3907 +    by (intro ln_smallo_imp_flat filterlim_ident ln_at_top assms
 11.3908 +              landau_o.small.compose[of _ at_top _ ln] *)
 11.3909 +  finally show ?thesis .
 11.3910 +qed
 11.3911 +
 11.3912 +lemma basis_wf_insert_exp_pos:
 11.3913 +  assumes "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)" 
 11.3914 +          "basis_wf (b # basis)" "trimmed (MS (MSLCons (C, e) xs) g)" "e - 0 > 0"
 11.3915 +  shows   "(\<lambda>x. ln (b x)) \<in> o(f)"
 11.3916 +proof -
 11.3917 +  from assms have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.3918 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" by (simp add: filterlim_at_top_dense)
 11.3919 +
 11.3920 +  from assms have "is_expansion_aux xs (\<lambda>x. g x - eval C x * b x powr e) (b # basis)" 
 11.3921 +                  "ms_exp_gt e (ms_aux_hd_exp xs)"
 11.3922 +      by (auto elim!: is_expansion_aux_MSLCons simp: expands_to.simps)
 11.3923 +  from is_expansion_aux_imp_smallo''[OF this] obtain e' where e':
 11.3924 +    "e' < e" "(\<lambda>x. g x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr e')" unfolding list.sel .
 11.3925 +  
 11.3926 +  define eps where "eps = e/2"
 11.3927 +  have "(\<lambda>x. ln (b x)) \<in> o(\<lambda>x. b x powr (e - eps))" unfolding eps_def
 11.3928 +    by (rule landau_o.small.compose[OF _ b_limit])
 11.3929 +       (insert e'(1) \<open>e - 0 > 0\<close>, simp add: ln_smallo_powr)
 11.3930 +  also from assms e'(1) have "eval C \<in> \<omega>(\<lambda>x. b x powr -eps)" unfolding eps_def
 11.3931 +    by (intro is_expansion_imp_smallomega[of basis])
 11.3932 +       (auto simp: basis_wf_Cons expands_to.simps trimmed_pos_def trimmed_ms_aux_MSLCons
 11.3933 +             elim!: is_expansion_aux_MSLCons)
 11.3934 +  hence "(\<lambda>x. b x powr -eps * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.3935 +    by (intro landau_o.small_big_mult) (simp_all add: smallomega_iff_smallo)
 11.3936 +  hence "(\<lambda>x. b x powr (e - eps)) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.3937 +    by (simp add: powr_add [symmetric] field_simps)
 11.3938 +  finally have "(\<lambda>x. ln (b x)) \<in> o(\<lambda>x. eval C x * b x powr e)" .
 11.3939 +  also {
 11.3940 +    from e' have "(\<lambda>x. g x - eval C x * b x powr e) \<in> o(\<lambda>x. b x powr (e' - e) * b x powr e)"
 11.3941 +      by (simp add: powr_add [symmetric])
 11.3942 +    also from assms e'(1) have "eval C \<in> \<omega>(\<lambda>x. b x powr (e' - e))" unfolding eps_def
 11.3943 +      by (intro is_expansion_imp_smallomega[of basis])
 11.3944 +         (auto simp: basis_wf_Cons expands_to.simps trimmed_pos_def trimmed_ms_aux_MSLCons
 11.3945 +               elim!: is_expansion_aux_MSLCons)
 11.3946 +    hence "(\<lambda>x. b x powr (e' - e) * b x powr e) \<in> o(\<lambda>x. eval C x * b x powr e)"
 11.3947 +      by (intro landau_o.small_big_mult is_expansion_imp_smallo) 
 11.3948 +         (simp_all add: smallomega_iff_smallo)
 11.3949 +    finally have "o(\<lambda>x. eval C x * b x powr e) = 
 11.3950 +                    o(\<lambda>x. g x - eval C x * b x powr e + eval C x * b x powr e)"
 11.3951 +      by (intro landau_o.small.plus_absorb1 [symmetric]) simp_all
 11.3952 +  }
 11.3953 +  also have "o(\<lambda>x. g x - eval C x * b x powr e + eval C x * b x powr e) = o(g)" by simp
 11.3954 +  also from assms have "g \<in> \<Theta>(f)" by (intro bigthetaI_cong) (simp add: expands_to.simps)
 11.3955 +  finally show "(\<lambda>x. ln (b x)) \<in> o(f)" .
 11.3956 +qed
 11.3957 +
 11.3958 +lemma basis_wf_insert_exp_uminus:
 11.3959 +  "(\<lambda>x. ln (b x)) \<in> o(f) \<Longrightarrow> (\<lambda>x. ln (b x)) \<in> o(\<lambda>x. -f x :: real)"
 11.3960 +  by simp
 11.3961 +
 11.3962 +lemma basis_wf_insert_exp_uminus':
 11.3963 +  "f \<in> o(\<lambda>x. ln (b x)) \<Longrightarrow> (\<lambda>x. -f x) \<in> o(\<lambda>x. ln (b x))"
 11.3964 +  by simp
 11.3965 +    
 11.3966 +lemma expands_to_exp_insert_pos:
 11.3967 +  fixes C :: "'a :: multiseries"
 11.3968 +  assumes "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)" 
 11.3969 +          "basis_wf (b # basis)" "trimmed_pos (MS (MSLCons (C, e) xs) g)" 
 11.3970 +          "(\<lambda>x. ln (b x)) \<in> o(f)"
 11.3971 +  shows   "filterlim (\<lambda>x. exp (f x)) at_top at_top"
 11.3972 +          "((\<lambda>x. ln (exp (f x))) expands_to MS (MSLCons (C, e) xs) g) (b # basis)"
 11.3973 +          "((\<lambda>x. exp (f x)) expands_to 
 11.3974 +             MS (MSLCons (const_expansion 1 :: 'a ms, 1) MSLNil) (\<lambda>x. exp (g x)))
 11.3975 +             ((\<lambda>x. exp (f x)) # b # basis)" (is ?thesis3)
 11.3976 +proof -
 11.3977 +  have "ln \<in> \<omega>(\<lambda>x::real. 1)"
 11.3978 +    by (intro smallomegaI_filterlim_at_top_norm)
 11.3979 +       (auto intro!: filterlim_compose[OF filterlim_abs_real] ln_at_top)
 11.3980 +  with assms have "(\<lambda>x. 1) \<in> o(\<lambda>x. ln (b x))"
 11.3981 +    by (intro landau_o.small.compose[of _ at_top _ b])
 11.3982 +       (simp_all add: basis_wf_Cons smallomega_iff_smallo)
 11.3983 +  also note \<open>(\<lambda>x. ln (b x)) \<in> o(f)\<close>
 11.3984 +  finally have f: "f \<in> \<omega>(\<lambda>_. 1)" by (simp add: smallomega_iff_smallo)
 11.3985 +  hence f: "filterlim (\<lambda>x. abs (f x)) at_top at_top"
 11.3986 +    by (auto dest: smallomegaD_filterlim_at_top_norm)
 11.3987 +  
 11.3988 +  define c where "c = fst (dominant_term C)"
 11.3989 +  define es where "es = snd (dominant_term C)"
 11.3990 +  from trimmed_imp_eventually_sgn[OF assms(2), of "MS (MSLCons (C, e) xs) g"] assms 
 11.3991 +    have "\<forall>\<^sub>F x in at_top. abs (f x) = f x"
 11.3992 +      by (auto simp: dominant_term_ms_aux_MSLCons trimmed_pos_def expands_to.simps sgn_if 
 11.3993 +               split: if_splits elim: eventually_elim2)
 11.3994 +  from filterlim_cong[OF refl refl this] f 
 11.3995 +    show *: "filterlim (\<lambda>x. exp (f x)) at_top at_top" 
 11.3996 +    by (auto intro: filterlim_compose[OF exp_at_top])
 11.3997 +  
 11.3998 +  {
 11.3999 +    fix e' :: real assume e': "e' > 1"
 11.4000 +    from assms have "(\<lambda>x. exp (g x)) \<in> \<Theta>(\<lambda>x. exp (f x) powr 1)"
 11.4001 +      by (intro bigthetaI_cong) (auto elim: eventually_mono simp: expands_to.simps)
 11.4002 +    also from e' * have "(\<lambda>x. exp (f x) powr 1) \<in> o(\<lambda>x. exp (f x) powr e')"
 11.4003 +      by (subst powr_smallo_iff) (insert *, simp_all)
 11.4004 +    finally have "(\<lambda>x. exp (g x)) \<in> o(\<lambda>x. exp (f x) powr e')" .
 11.4005 +  }
 11.4006 +  with assms show ?thesis3
 11.4007 +    by (auto intro!: is_expansion_aux.intros is_expansion_const 
 11.4008 +             simp: expands_to.simps is_expansion_aux_expansion_level
 11.4009 +             dest: is_expansion_aux_expansion_level)
 11.4010 +qed (insert assms, simp_all)
 11.4011 +    
 11.4012 +lemma expands_to_exp_insert_neg:
 11.4013 +  fixes C :: "'a :: multiseries"
 11.4014 +  assumes "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)" 
 11.4015 +          "basis_wf (b # basis)" "trimmed_neg (MS (MSLCons (C, e) xs) g)" 
 11.4016 +          "(\<lambda>x. ln (b x)) \<in> o(f)"
 11.4017 +  shows   "filterlim (\<lambda>x. exp (-f x)) at_top at_top" (is ?thesis1)
 11.4018 +          "((\<lambda>x. ln (exp (-f x))) expands_to MS (MSLCons (-C, e) (uminus_ms_aux xs)) (\<lambda>x. - g x)) 
 11.4019 +             (b # basis)"
 11.4020 +          "trimmed_pos (MS (MSLCons (-C, e) (uminus_ms_aux xs)) (\<lambda>x. - g x))"
 11.4021 +          "((\<lambda>x. exp (f x)) expands_to 
 11.4022 +             MS (MSLCons (const_expansion 1 :: 'a ms, -1) MSLNil) (\<lambda>x. exp (g x)))
 11.4023 +             ((\<lambda>x. exp (-f x)) # b # basis)" (is ?thesis3)
 11.4024 +proof -
 11.4025 +  have "ln \<in> \<omega>(\<lambda>x::real. 1)"
 11.4026 +    by (intro smallomegaI_filterlim_at_top_norm)
 11.4027 +       (auto intro!: filterlim_compose[OF filterlim_abs_real] ln_at_top)
 11.4028 +  with assms have "(\<lambda>x. 1) \<in> o(\<lambda>x. ln (b x))"
 11.4029 +    by (intro landau_o.small.compose[of _ at_top _ b])
 11.4030 +       (simp_all add: basis_wf_Cons smallomega_iff_smallo)
 11.4031 +  also note \<open>(\<lambda>x. ln (b x)) \<in> o(f)\<close>
 11.4032 +  finally have f: "f \<in> \<omega>(\<lambda>_. 1)" by (simp add: smallomega_iff_smallo)
 11.4033 +  hence f: "filterlim (\<lambda>x. abs (f x)) at_top at_top" 
 11.4034 +    by (auto dest: smallomegaD_filterlim_at_top_norm)
 11.4035 +  from trimmed_imp_eventually_sgn[OF assms(2), of "MS (MSLCons (C, e) xs) g"] assms 
 11.4036 +    have "\<forall>\<^sub>F x in at_top. abs (f x) = -f x"
 11.4037 +      by (auto simp: dominant_term_ms_aux_MSLCons trimmed_neg_def expands_to.simps sgn_if 
 11.4038 +               split: if_splits elim: eventually_elim2)
 11.4039 +  from filterlim_cong[OF refl refl this] f 
 11.4040 +    show *: "filterlim (\<lambda>x. exp (-f x)) at_top at_top" 
 11.4041 +    by (auto intro: filterlim_compose[OF exp_at_top])
 11.4042 +  
 11.4043 +  have "((\<lambda>x. -f x) expands_to -MS (MSLCons (C, e) xs) g) (b # basis)"
 11.4044 +    by (intro expands_to_uminus assms)
 11.4045 +  thus "((\<lambda>x. ln (exp (-f x))) expands_to MS (MSLCons (-C, e) (uminus_ms_aux xs)) (\<lambda>x. - g x)) 
 11.4046 +          (b # basis)"
 11.4047 +    by (simp add: uminus_ms_aux_MSLCons)
 11.4048 +      
 11.4049 +  {
 11.4050 +    fix e' :: real assume e': "e' > -1"
 11.4051 +    from assms have "(\<lambda>x. exp (g x)) \<in> \<Theta>(\<lambda>x. exp (-f x) powr -1)"
 11.4052 +      by (intro bigthetaI_cong) 
 11.4053 +         (auto elim: eventually_mono simp: expands_to.simps powr_minus exp_minus)
 11.4054 +    also from e' * have "(\<lambda>x. exp (-f x) powr -1) \<in> o(\<lambda>x. exp (-f x) powr e')"
 11.4055 +      by (subst powr_smallo_iff) (insert *, simp_all)
 11.4056 +    finally have "(\<lambda>x. exp (g x)) \<in> o(\<lambda>x. exp (-f x) powr e')" .
 11.4057 +  }
 11.4058 +  with assms show ?thesis3
 11.4059 +    by (auto intro!: is_expansion_aux.intros is_expansion_const 
 11.4060 +             simp: expands_to.simps is_expansion_aux_expansion_level powr_minus exp_minus
 11.4061 +             dest: is_expansion_aux_expansion_level)
 11.4062 +qed (insert assms, simp_all add: trimmed_pos_def trimmed_neg_def 
 11.4063 +       trimmed_ms_aux_MSLCons dominant_term_ms_aux_MSLCons)
 11.4064 +
 11.4065 +lemma is_expansion_aux_exp_neg:
 11.4066 +  assumes "is_expansion_aux F f basis" "basis_wf basis" "ms_exp_gt 0 (ms_aux_hd_exp F)"
 11.4067 +  shows   "is_expansion_aux (powser_ms_aux' exp_series_stream F) (\<lambda>x. exp (f x)) basis"
 11.4068 +  using powser_ms_aux'[OF convergent_powser'_exp assms(2,1,3)]
 11.4069 +  by (simp add: o_def powser_ms_aux'_def)
 11.4070 +
 11.4071 +lemma is_expansion_exp_neg:
 11.4072 +  assumes "is_expansion (MS (MSLCons (C, e) xs) f) basis" "basis_wf basis" "e < 0"
 11.4073 +  shows   "is_expansion (MS (powser_ms_aux' exp_series_stream (MSLCons (C, e) xs)) 
 11.4074 +             (\<lambda>x. exp (f x))) basis"
 11.4075 +  using is_expansion_aux_exp_neg[of "MSLCons (C, e) xs" f basis] assms by simp
 11.4076 +
 11.4077 +lemma expands_to_exp_neg:
 11.4078 +  assumes "(f expands_to MS (MSLCons (C, e) xs) g) basis" "basis_wf basis" "e - 0 < 0"
 11.4079 +  shows   "((\<lambda>x. exp (f x)) expands_to MS (powser_ms_aux' exp_series_stream (MSLCons (C, e) xs)) 
 11.4080 +             (\<lambda>x. exp (g x))) basis"
 11.4081 +  using assms is_expansion_exp_neg[of C e xs g basis] by (auto simp: expands_to.simps)
 11.4082 +
 11.4083 +lemma basis_wf_insert_exp_near:
 11.4084 +  assumes "basis_wf (b # basis)" "basis_wf ((\<lambda>x. exp (f x)) # basis)" "f \<in> o(\<lambda>x. ln (b x))"
 11.4085 +  shows   "basis_wf (b # (\<lambda>x. exp (f x)) # basis)"
 11.4086 +  using assms by (simp_all add: basis_wf_Cons)
 11.4087 +
 11.4088 +
 11.4089 +definition scale_ms_aux' where "scale_ms_aux' c F = scale_shift_ms_aux (c, 0) F"
 11.4090 +definition shift_ms_aux where "shift_ms_aux e F = scale_shift_ms_aux (const_expansion 1, e) F"
 11.4091 +
 11.4092 +lemma scale_ms_1 [simp]: "scale_ms 1 F = F"
 11.4093 +  by (simp add: scale_ms_def times_const_expansion_1)
 11.4094 +
 11.4095 +lemma scale_ms_aux_1 [simp]: "scale_ms_aux 1 xs = xs"
 11.4096 +  by (simp add: scale_ms_aux_def scale_shift_ms_aux_def map_prod_def msllist.map_ident
 11.4097 +        case_prod_unfold times_const_expansion_1)
 11.4098 +    
 11.4099 +lemma scale_ms_aux'_1 [simp]: "scale_ms_aux' (const_expansion 1) xs = xs"
 11.4100 +  by (simp add: scale_ms_aux'_def scale_shift_ms_aux_def map_prod_def msllist.map_ident
 11.4101 +        case_prod_unfold times_const_expansion_1)
 11.4102 +    
 11.4103 +lemma shift_ms_aux_0 [simp]: "shift_ms_aux 0 xs = xs"
 11.4104 +  by (simp add: shift_ms_aux_def scale_shift_ms_aux_def map_prod_def case_prod_unfold 
 11.4105 +        times_const_expansion_1 msllist.map_ident)
 11.4106 +  
 11.4107 +lemma scale_ms_aux'_MSLNil [simp]: "scale_ms_aux' C MSLNil = MSLNil"
 11.4108 +  by (simp add: scale_ms_aux'_def)
 11.4109 +
 11.4110 +lemma scale_ms_aux'_MSLCons [simp]: 
 11.4111 +  "scale_ms_aux' C (MSLCons (C', e) xs) = MSLCons (C * C', e) (scale_ms_aux' C xs)"
 11.4112 +  by (simp add: scale_ms_aux'_def scale_shift_ms_aux_MSLCons)
 11.4113 +
 11.4114 +lemma shift_ms_aux_MSLNil [simp]: "shift_ms_aux e MSLNil = MSLNil"
 11.4115 +  by (simp add: shift_ms_aux_def)
 11.4116 +
 11.4117 +lemma shift_ms_aux_MSLCons [simp]: 
 11.4118 +  "shift_ms_aux e (MSLCons (C, e') xs) = MSLCons (C, e' + e) (shift_ms_aux e xs)"
 11.4119 +  by (simp add: shift_ms_aux_def scale_shift_ms_aux_MSLCons times_const_expansion_1)
 11.4120 +
 11.4121 +lemma scale_ms_aux:
 11.4122 +  fixes xs :: "('a :: multiseries \<times> real) msllist"
 11.4123 +  assumes "is_expansion_aux xs f basis" "basis_wf basis"
 11.4124 +  shows   "is_expansion_aux (scale_ms_aux c xs) (\<lambda>x. c * f x) basis"
 11.4125 +proof (cases basis)
 11.4126 +  case (Cons b basis')
 11.4127 +  show ?thesis
 11.4128 +  proof (rule is_expansion_aux_cong)
 11.4129 +    show "is_expansion_aux (scale_ms_aux c xs) 
 11.4130 +            (\<lambda>x. eval (const_expansion c :: 'a) x * b x powr 0 * f x) basis"
 11.4131 +      using assms unfolding scale_ms_aux_def Cons
 11.4132 +      by (intro scale_shift_ms_aux is_expansion_const) 
 11.4133 +         (auto simp: basis_wf_Cons dest: is_expansion_aux_expansion_level)
 11.4134 +  next
 11.4135 +    from assms have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4136 +      by (simp add: basis_wf_Cons Cons filterlim_at_top_dense)
 11.4137 +    thus "eventually (\<lambda>x. eval (const_expansion c :: 'a) x * b x powr 0 * f x = c * f x) at_top"
 11.4138 +      by eventually_elim simp
 11.4139 +  qed
 11.4140 +qed (insert assms, auto dest: is_expansion_aux_basis_nonempty)
 11.4141 +
 11.4142 +lemma scale_ms_aux':
 11.4143 +  assumes "is_expansion_aux xs f (b # basis)" "is_expansion C basis" "basis_wf (b # basis)"
 11.4144 +  shows   "is_expansion_aux (scale_ms_aux' C xs) (\<lambda>x. eval C x * f x) (b # basis)"
 11.4145 +proof (rule is_expansion_aux_cong)
 11.4146 +  show "is_expansion_aux (scale_ms_aux' C xs) (\<lambda>x. eval C x * b x powr 0 * f x) (b # basis)"
 11.4147 +    using assms unfolding scale_ms_aux'_def Cons by (intro scale_shift_ms_aux) simp_all
 11.4148 +next
 11.4149 +  from assms have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4150 +    by (simp add: basis_wf_Cons filterlim_at_top_dense)
 11.4151 +  thus "eventually (\<lambda>x. eval C x * b x powr 0 * f x = eval C x * f x) at_top"
 11.4152 +    by eventually_elim simp
 11.4153 +qed
 11.4154 +
 11.4155 +lemma shift_ms_aux:
 11.4156 +  fixes xs :: "('a :: multiseries \<times> real) msllist"
 11.4157 +  assumes "is_expansion_aux xs f (b # basis)" "basis_wf (b # basis)"
 11.4158 +  shows   "is_expansion_aux (shift_ms_aux e xs) (\<lambda>x. b x powr e * f x) (b # basis)"
 11.4159 +  unfolding shift_ms_aux_def 
 11.4160 +  using scale_shift_ms_aux[OF assms(2,1) is_expansion_const[of _ 1], of e] assms
 11.4161 +  by (auto dest!: is_expansion_aux_expansion_level simp: basis_wf_Cons)
 11.4162 +  
 11.4163 +lemma expands_to_exp_0:
 11.4164 +  assumes "(f expands_to MS (MSLCons (MS ys c, e) xs) g) (b # basis)"
 11.4165 +          "basis_wf (b # basis)" "e - 0 = 0" "((\<lambda>x. exp (c x)) expands_to E) basis"
 11.4166 +  shows   "((\<lambda>x. exp (f x)) expands_to
 11.4167 +             MS (scale_ms_aux' E (powser_ms_aux' exp_series_stream xs)) (\<lambda>x. exp (g x))) (b # basis)"
 11.4168 +          (is "(_ expands_to MS ?H _) _")
 11.4169 +proof -
 11.4170 +  from assms have "is_expansion_aux ?H (\<lambda>x. eval E x * exp (g x - c x * b x powr 0)) (b # basis)"
 11.4171 +    by (intro scale_ms_aux' is_expansion_aux_exp_neg)
 11.4172 +       (auto elim!: is_expansion_aux_MSLCons simp: expands_to.simps)
 11.4173 +  moreover {
 11.4174 +    from \<open>basis_wf (b # basis)\<close> have "eventually (\<lambda>x. b x > 0) at_top"
 11.4175 +      by (simp add: filterlim_at_top_dense basis_wf_Cons)
 11.4176 +    moreover from assms(4) have "eventually (\<lambda>x. eval E x = exp (c x)) at_top"
 11.4177 +      by (simp add: expands_to.simps)
 11.4178 +    ultimately have "eventually (\<lambda>x. eval E x * exp (g x - c x * b x powr 0) = exp (g x)) at_top"
 11.4179 +      by eventually_elim (simp add: exp_diff)
 11.4180 +  }
 11.4181 +  ultimately have "is_expansion_aux ?H (\<lambda>x. exp (g x)) (b # basis)"
 11.4182 +    by (rule is_expansion_aux_cong)
 11.4183 +  with assms(1) show ?thesis by (simp add: expands_to.simps)
 11.4184 +qed
 11.4185 +
 11.4186 +lemma expands_to_exp_0_real:
 11.4187 +  assumes "(f expands_to MS (MSLCons (c::real, e) xs) g) [b]" "basis_wf [b]" "e - 0 = 0"
 11.4188 +  shows   "((\<lambda>x. exp (f x)) expands_to 
 11.4189 +             MS (scale_ms_aux (exp c) (powser_ms_aux' exp_series_stream xs)) (\<lambda>x. exp (g x))) [b]"
 11.4190 +          (is "(_ expands_to MS ?H _) _")
 11.4191 +proof -
 11.4192 +  from assms have "is_expansion_aux ?H (\<lambda>x. exp c * exp (g x - c * b x powr 0)) [b]"
 11.4193 +    by (intro scale_ms_aux is_expansion_aux_exp_neg)
 11.4194 +       (auto elim!: is_expansion_aux_MSLCons simp: expands_to.simps)
 11.4195 +  moreover from \<open>basis_wf [b]\<close> have "eventually (\<lambda>x. b x > 0) at_top"
 11.4196 +    by (simp add: filterlim_at_top_dense basis_wf_Cons)
 11.4197 +  hence "eventually (\<lambda>x. exp c * exp (g x - c * b x powr 0) = exp (g x)) at_top"
 11.4198 +    by eventually_elim (simp add: exp_diff)
 11.4199 +  ultimately have "is_expansion_aux ?H (\<lambda>x. exp (g x)) [b]"
 11.4200 +    by (rule is_expansion_aux_cong)
 11.4201 +  with assms(1) show ?thesis by (simp add: expands_to.simps)
 11.4202 +qed
 11.4203 +
 11.4204 +lemma expands_to_exp_0_pull_out1:
 11.4205 +  assumes "(f expands_to MS (MSLCons (C, e) xs) g) (b # basis)"
 11.4206 +  assumes "((\<lambda>x. ln (b x)) expands_to L) basis" "basis_wf (b # basis)" "e - 0 = 0" "c \<equiv> c"
 11.4207 +  shows   "((\<lambda>x. f x - c * ln (b x)) expands_to 
 11.4208 +             MS (MSLCons (C - scale_ms c L, e) xs) (\<lambda>x. g x - c * ln (b x))) (b # basis)"
 11.4209 +proof -
 11.4210 +  from \<open>basis_wf (b # basis)\<close> have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.4211 +  have "(\<lambda>x. c * ln (b x)) \<in> o(\<lambda>x. b x powr e')" if "e' > 0" for e'
 11.4212 +    using that by (intro landau_o.small.compose[OF _ b_limit]) (simp add: ln_smallo_powr)
 11.4213 +  hence *: "(\<lambda>x. g x - c * ln (b x)) \<in> o(\<lambda>x. b x powr e')" if "e' > 0" for e' using assms(1,4) that
 11.4214 +    by (intro sum_in_smallo) (auto simp: expands_to.simps elim!: is_expansion_aux_MSLCons)
 11.4215 +  
 11.4216 +  have "is_expansion_aux xs (\<lambda>x. (g x - c * b x powr 0 * eval L x) -
 11.4217 +           eval (C - scale_ms c L) x * b x powr e) (b # basis)" 
 11.4218 +    (is "is_expansion_aux _ ?h _") using assms
 11.4219 +    by (auto simp: expands_to.simps algebra_simps scale_ms_def elim!: is_expansion_aux_MSLCons)
 11.4220 +  moreover from b_limit have "eventually (\<lambda>x. b x > 0) at_top"
 11.4221 +    by (simp add: filterlim_at_top_dense)
 11.4222 +  hence "eventually (\<lambda>x. ?h x = g x - c * ln (b x) - 
 11.4223 +           eval (C - const_expansion c * L) x * b x powr e) at_top" 
 11.4224 +    (is "eventually (\<lambda>x. _ = ?h x) _") using assms(2)
 11.4225 +    by (auto simp: expands_to.simps scale_ms_def elim: eventually_elim2)
 11.4226 +  ultimately have **: "is_expansion_aux xs ?h (b # basis)" by (rule is_expansion_aux_cong)
 11.4227 +  from assms(1,4) have "ms_exp_gt 0 (ms_aux_hd_exp xs)" "is_expansion C basis"
 11.4228 +    by (auto simp: expands_to.simps elim!: is_expansion_aux_MSLCons)
 11.4229 +  moreover from assms(1) have "length basis = expansion_level TYPE('a)"
 11.4230 +    by (auto simp: expands_to.simps dest: is_expansion_aux_expansion_level)
 11.4231 +  ultimately have "is_expansion_aux (MSLCons (C - scale_ms c L, e) xs) 
 11.4232 +                     (\<lambda>x. g x - c * ln (b x)) (b # basis)" using assms unfolding scale_ms_def
 11.4233 +    by (intro is_expansion_aux.intros is_expansion_minus is_expansion_mult is_expansion_const * **)
 11.4234 +       (simp_all add: basis_wf_Cons expands_to.simps)
 11.4235 +  with assms(1) show ?thesis by (auto simp: expands_to.simps)
 11.4236 +qed
 11.4237 +    
 11.4238 +lemma expands_to_exp_0_pull_out2:
 11.4239 +  assumes "((\<lambda>x. exp (f x - c * ln (b x))) expands_to MS xs g) (b # basis)"
 11.4240 +  assumes "basis_wf (b # basis)"
 11.4241 +  shows   "((\<lambda>x. exp (f x)) expands_to MS (shift_ms_aux c xs) 
 11.4242 +             (\<lambda>x. b x powr c * g x)) (b # basis)"
 11.4243 +proof (rule expands_to.intros)
 11.4244 +  show "is_expansion (MS (shift_ms_aux c xs) (\<lambda>x. b x powr c * g x)) (b # basis)"
 11.4245 +    using assms unfolding expands_to.simps by (auto intro!: shift_ms_aux)
 11.4246 +  from assms have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4247 +    by (simp add: basis_wf_Cons filterlim_at_top_dense)
 11.4248 +  with assms(1)
 11.4249 +  show "\<forall>\<^sub>F x in at_top. eval (MS (shift_ms_aux c xs) (\<lambda>x. b x powr c * g x)) x = exp (f x)"
 11.4250 +    by (auto simp: expands_to.simps exp_diff powr_def elim: eventually_elim2)
 11.4251 +qed
 11.4252 +
 11.4253 +lemma expands_to_exp_0_pull_out2_nat:
 11.4254 +  assumes "((\<lambda>x. exp (f x - c * ln (b x))) expands_to MS xs g) (b # basis)"
 11.4255 +  assumes "basis_wf (b # basis)" "c = real n"
 11.4256 +  shows   "((\<lambda>x. exp (f x)) expands_to MS (shift_ms_aux c xs) 
 11.4257 +             (\<lambda>x. b x ^ n * g x)) (b # basis)"
 11.4258 +using expands_to_exp_0_pull_out2[OF assms(1-2)]
 11.4259 +proof (rule expands_to_cong')
 11.4260 +  from assms(2) have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4261 +    by (simp add: filterlim_at_top_dense basis_wf_Cons)
 11.4262 +  with assms(3) show "eventually (\<lambda>x. b x powr c * g x = b x ^ n * g x) at_top"
 11.4263 +    by (auto elim!: eventually_mono simp: powr_realpow)
 11.4264 +qed
 11.4265 +
 11.4266 +lemma expands_to_exp_0_pull_out2_neg_nat:
 11.4267 +  assumes "((\<lambda>x. exp (f x - c * ln (b x))) expands_to MS xs g) (b # basis)"
 11.4268 +  assumes "basis_wf (b # basis)" "c = -real n"
 11.4269 +  shows   "((\<lambda>x. exp (f x)) expands_to MS (shift_ms_aux c xs) 
 11.4270 +             (\<lambda>x. g x / b x ^ n)) (b # basis)"
 11.4271 +using expands_to_exp_0_pull_out2[OF assms(1-2)]
 11.4272 +proof (rule expands_to_cong')
 11.4273 +  from assms(2) have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4274 +    by (simp add: filterlim_at_top_dense basis_wf_Cons)
 11.4275 +  with assms(3) show "eventually (\<lambda>x. b x powr c * g x = g x / b x ^ n) at_top"
 11.4276 +    by (auto elim!: eventually_mono simp: powr_realpow powr_minus divide_simps)
 11.4277 +qed
 11.4278 +
 11.4279 +lemma eval_monom_collapse: "c * eval_monom (c', es) basis x = eval_monom (c * c', es) basis x"
 11.4280 +  by (simp add: eval_monom_def)
 11.4281 +
 11.4282 +lemma eval_monom_1_conv: "eval_monom a basis = (\<lambda>x. fst a * eval_monom (1, snd a) basis x)"
 11.4283 +  by (simp add: eval_monom_def case_prod_unfold)
 11.4284 +
 11.4285 +
 11.4286 +subsubsection \<open>Comparing exponent lists\<close>
 11.4287 +
 11.4288 +primrec flip_cmp_result where
 11.4289 +  "flip_cmp_result LT = GT"
 11.4290 +| "flip_cmp_result GT = LT"
 11.4291 +| "flip_cmp_result EQ = EQ"
 11.4292 +
 11.4293 +fun compare_lists :: "real list \<Rightarrow> real list \<Rightarrow> cmp_result" where
 11.4294 +  "compare_lists [] [] = EQ"
 11.4295 +| "compare_lists (a # as) (b # bs) = 
 11.4296 +     (if a < b then LT else if b < a then GT else compare_lists as bs)"
 11.4297 +| "compare_lists _ _ = undefined"
 11.4298 +
 11.4299 +declare compare_lists.simps [simp del]
 11.4300 +  
 11.4301 +lemma compare_lists_Nil [simp]: "compare_lists [] [] = EQ" by (fact compare_lists.simps)
 11.4302 +
 11.4303 +lemma compare_lists_Cons [simp]:
 11.4304 +  "a < b \<Longrightarrow> compare_lists (a # as) (b # bs) = LT"
 11.4305 +  "a > b \<Longrightarrow> compare_lists (a # as) (b # bs) = GT"
 11.4306 +  "a = b \<Longrightarrow> compare_lists (a # as) (b # bs) = compare_lists as bs"
 11.4307 +  by (simp_all add: compare_lists.simps(2))
 11.4308 +
 11.4309 +lemma flip_compare_lists:
 11.4310 +  "length as = length bs \<Longrightarrow> flip_cmp_result (compare_lists as bs) = compare_lists bs as"
 11.4311 +  by (induction as bs rule: compare_lists.induct) (auto simp: compare_lists.simps(2))
 11.4312 +
 11.4313 +lemma compare_lists_induct [consumes 1, case_names Nil Eq Neq]:
 11.4314 +  fixes as bs :: "real list"
 11.4315 +  assumes "length as = length bs"
 11.4316 +  assumes "P [] []"
 11.4317 +  assumes "\<And>a as bs. P as bs \<Longrightarrow> P (a # as) (a # bs)"
 11.4318 +  assumes "\<And>a as b bs. a \<noteq> b \<Longrightarrow> P (a # as) (b # bs)"
 11.4319 +  shows   "P as bs"
 11.4320 +  using assms(1)
 11.4321 +proof (induction as bs rule: list_induct2)
 11.4322 +  case (Cons a as b bs)
 11.4323 +  thus ?case by (cases "a < b") (auto intro: assms)
 11.4324 +qed (simp_all add: assms)
 11.4325 +  
 11.4326 +
 11.4327 +lemma eval_monom_smallo_eval_monom:
 11.4328 +  assumes "length es1 = length es2" "length es2 = length basis" "basis_wf basis"
 11.4329 +  assumes "compare_lists es1 es2 = LT"
 11.4330 +  shows   "eval_monom (1, es1) basis \<in> o(eval_monom (1, es2) basis)"
 11.4331 +using assms
 11.4332 +proof (induction es1 es2 basis rule: list_induct3)
 11.4333 +  case (Cons e1 es1 e2 es2 b basis)
 11.4334 +  show ?case
 11.4335 +  proof (cases "e1 = e2")
 11.4336 +    case True
 11.4337 +    from Cons.prems have "eventually (\<lambda>x. b x > 0) at_top" 
 11.4338 +      by (simp add: basis_wf_Cons filterlim_at_top_dense)
 11.4339 +    with Cons True show ?thesis
 11.4340 +      by (auto intro: landau_o.small_big_mult simp: eval_monom_Cons basis_wf_Cons)
 11.4341 +  next
 11.4342 +    case False
 11.4343 +    with Cons.prems have "e1 < e2" by (cases e1 e2 rule: linorder_cases) simp_all
 11.4344 +    with Cons.prems have
 11.4345 +       "(\<lambda>x. eval_monom (1, es1) basis x * eval_monom (inverse_monom (1, es2)) basis x *
 11.4346 +           b x powr e1) \<in> o(\<lambda>x. b x powr ((e2 - e1)/2) * b x powr ((e2 - e1)/2) * b x powr e1)"
 11.4347 +      (is "?f \<in> _") by (intro landau_o.small_big_mult[OF _ landau_o.big_refl] landau_o.small.mult 
 11.4348 +                          eval_monom_smallo') simp_all
 11.4349 +    also have "\<dots> = o(\<lambda>x. b x powr e2)" by (simp add: powr_add [symmetric])
 11.4350 +    also have "?f = (\<lambda>x. eval_monom (1, e1 # es1) (b # basis) x / eval_monom (1, es2) basis x)"
 11.4351 +      by (simp add: eval_inverse_monom field_simps eval_monom_Cons)
 11.4352 +    also have "\<dots> \<in> o(\<lambda>x. b x powr e2) \<longleftrightarrow> 
 11.4353 +                 eval_monom (1, e1 # es1) (b # basis) \<in> o(eval_monom (1, e2 # es2) (b # basis))"
 11.4354 +      using Cons.prems 
 11.4355 +      by (subst landau_o.small.divide_eq2)
 11.4356 +         (simp_all add: eval_monom_Cons mult_ac eval_monom_nonzero basis_wf_Cons)
 11.4357 +    finally show ?thesis .
 11.4358 +  qed
 11.4359 +qed simp_all
 11.4360 +
 11.4361 +lemma eval_monom_eq:
 11.4362 +  assumes "length es1 = length es2" "length es2 = length basis" "basis_wf basis"
 11.4363 +  assumes "compare_lists es1 es2 = EQ"
 11.4364 +  shows   "eval_monom (1, es1) basis = eval_monom (1, es2) basis"
 11.4365 +  using assms
 11.4366 +  by (induction es1 es2 basis rule: list_induct3)
 11.4367 +     (auto simp: basis_wf_Cons eval_monom_Cons compare_lists.simps(2) split: if_splits)
 11.4368 +
 11.4369 +definition compare_expansions :: "'a :: multiseries \<Rightarrow> 'a \<Rightarrow> cmp_result \<times> real \<times> real" where
 11.4370 +  "compare_expansions F G =
 11.4371 +     (case compare_lists (snd (dominant_term F)) (snd (dominant_term G)) of
 11.4372 +        LT \<Rightarrow> (LT, 0, 0)
 11.4373 +      | GT \<Rightarrow> (GT, 0, 0)
 11.4374 +      | EQ \<Rightarrow> (EQ, fst (dominant_term F),  fst (dominant_term G)))"
 11.4375 +
 11.4376 +lemma compare_expansions_real:
 11.4377 +  "compare_expansions (c1 :: real) c2 = (EQ, c1, c2)"
 11.4378 +  by (simp add: compare_expansions_def)
 11.4379 +
 11.4380 +lemma compare_expansions_MSLCons_eval:
 11.4381 +  "compare_expansions (MS (MSLCons (C1, e1) xs) f) (MS (MSLCons (C2, e2) ys) g) =
 11.4382 +     CMP_BRANCH (COMPARE e1 e2) (LT, 0, 0) (compare_expansions C1 C2) (GT, 0, 0)"
 11.4383 +  by (simp add: compare_expansions_def dominant_term_ms_aux_def case_prod_unfold 
 11.4384 +        COMPARE_def CMP_BRANCH_def split: cmp_result.splits)
 11.4385 +
 11.4386 +lemma compare_expansions_LT_I:
 11.4387 +  assumes "e1 - e2 < 0"
 11.4388 +  shows   "compare_expansions (MS (MSLCons (C1, e1) xs) f) (MS (MSLCons (C2, e2) ys) g) = (LT, 0, 0)"
 11.4389 +  using assms by (simp add: compare_expansions_MSLCons_eval CMP_BRANCH_def COMPARE_def)
 11.4390 +
 11.4391 +lemma compare_expansions_GT_I:
 11.4392 +  assumes "e1 - e2 > 0"
 11.4393 +  shows   "compare_expansions (MS (MSLCons (C1, e1) xs) f) (MS (MSLCons (C2, e2) ys) g) = (GT, 0, 0)"
 11.4394 +  using assms by (simp add: compare_expansions_MSLCons_eval CMP_BRANCH_def COMPARE_def)
 11.4395 +
 11.4396 +lemma compare_expansions_same_exp:
 11.4397 +  assumes "e1 - e2 = 0" "compare_expansions C1 C2 = res"
 11.4398 +  shows   "compare_expansions (MS (MSLCons (C1, e1) xs) f) (MS (MSLCons (C2, e2) ys) g) = res"
 11.4399 +  using assms by (simp add: compare_expansions_MSLCons_eval CMP_BRANCH_def COMPARE_def)
 11.4400 +  
 11.4401 +
 11.4402 +lemma compare_expansions_GT_flip:
 11.4403 +  "length (snd (dominant_term F)) = length (snd (dominant_term G)) \<Longrightarrow>
 11.4404 +     compare_expansions F G = (GT, c) \<longleftrightarrow> compare_expansions G F = (LT, c)"
 11.4405 +  using flip_compare_lists[of "snd (dominant_term F)" "snd (dominant_term G)"]
 11.4406 +  by (auto simp: compare_expansions_def split: cmp_result.splits)
 11.4407 +
 11.4408 +lemma compare_expansions_LT:
 11.4409 +  assumes "compare_expansions F G = (LT, c, c')" "trimmed G"
 11.4410 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4411 +  shows   "f \<in> o(g)"
 11.4412 +proof -
 11.4413 +  from assms have "f \<in> \<Theta>(eval F)"
 11.4414 +    by (auto simp: expands_to.simps eq_commute intro!: bigthetaI_cong)
 11.4415 +  also have "eval F \<in> O(eval_monom (1, snd (dominant_term F)) basis)"
 11.4416 +    using assms by (intro dominant_term_bigo) (auto simp: expands_to.simps)
 11.4417 +  also have "eval_monom (1, snd (dominant_term F)) basis \<in> 
 11.4418 +               o(eval_monom (1, snd (dominant_term G)) basis)" using assms 
 11.4419 +    by (intro eval_monom_smallo_eval_monom)
 11.4420 +       (auto simp: length_dominant_term expands_to.simps is_expansion_length compare_expansions_def
 11.4421 +             split: cmp_result.splits)
 11.4422 +  also have "eval_monom (1, snd (dominant_term G)) basis \<in> \<Theta>(eval_monom (dominant_term G) basis)"
 11.4423 +    by (subst (2) eval_monom_1_conv, subst landau_theta.cmult)
 11.4424 +       (insert assms, simp_all add: trimmed_imp_dominant_term_nz)    
 11.4425 +  also have "eval_monom (dominant_term G) basis \<in> \<Theta>(g)"
 11.4426 +    by (intro asymp_equiv_imp_bigtheta[OF asymp_equiv_symI] dominant_term_expands_to
 11.4427 +              asymp_equiv_imp_bigtheta assms)
 11.4428 +  finally show ?thesis .
 11.4429 +qed
 11.4430 +
 11.4431 +lemma compare_expansions_GT:
 11.4432 +  assumes "compare_expansions F G = (GT, c, c')" "trimmed F"
 11.4433 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4434 +  shows   "g \<in> o(f)"
 11.4435 +  by (rule compare_expansions_LT[OF _ assms(2,4,3)])
 11.4436 +     (insert assms, simp_all add: compare_expansions_GT_flip length_dominant_term)
 11.4437 +
 11.4438 +lemma compare_expansions_EQ:
 11.4439 +  assumes "compare_expansions F G = (EQ, c, c')" "trimmed F" "trimmed G"
 11.4440 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4441 +  shows   "(\<lambda>x. c' * f x) \<sim>[at_top] (\<lambda>x. c * g x)"
 11.4442 +proof -
 11.4443 +  from assms(1) have c: "c = fst (dominant_term F)" "c' = fst (dominant_term G)"
 11.4444 +    by (auto simp: compare_expansions_def split: cmp_result.splits)
 11.4445 +  have "(\<lambda>x. c' * f x) \<sim>[at_top] (\<lambda>x. c' * (c * eval_monom (1, snd (dominant_term F)) basis x))" 
 11.4446 +    unfolding c by (rule asymp_equiv_mult, rule asymp_equiv_refl, subst eval_monom_collapse)
 11.4447 +                   (auto intro: dominant_term_expands_to assms)
 11.4448 +  also have "eval_monom (1, snd (dominant_term F)) basis =
 11.4449 +               eval_monom (1, snd (dominant_term G)) basis" using assms
 11.4450 +    by (intro eval_monom_eq)
 11.4451 +       (simp_all add: compare_expansions_def length_dominant_term is_expansion_length 
 11.4452 +          expands_to.simps split: cmp_result.splits)
 11.4453 +  also have "(\<lambda>x. c' * (c * \<dots> x)) = (\<lambda>x. c * (c' * \<dots> x))" by (simp add: mult_ac)
 11.4454 +  also have "\<dots> \<sim>[at_top] (\<lambda>x. c * g x)"
 11.4455 +    unfolding c by (rule asymp_equiv_mult, rule asymp_equiv_refl, subst eval_monom_collapse, 
 11.4456 +                       rule asymp_equiv_symI)  (auto intro: dominant_term_expands_to assms)
 11.4457 +  finally show ?thesis by (simp add: asymp_equiv_sym)
 11.4458 +qed
 11.4459 +
 11.4460 +lemma compare_expansions_EQ_imp_bigo:
 11.4461 +  assumes "compare_expansions F G = (EQ, c, c')" "trimmed G"
 11.4462 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4463 +  shows   "f \<in> O(g)"
 11.4464 +proof -
 11.4465 +  from assms(1) have c: "c = fst (dominant_term F)" "c' = fst (dominant_term G)"
 11.4466 +    by (auto simp: compare_expansions_def split: cmp_result.splits)
 11.4467 +  from assms(3) have [simp]: "expansion_level TYPE('a) = length basis"
 11.4468 +    by (auto simp: expands_to.simps is_expansion_length)
 11.4469 +
 11.4470 +  have "f \<in> \<Theta>(eval F)"
 11.4471 +    using assms by (intro bigthetaI_cong) (auto simp: expands_to.simps eq_commute)
 11.4472 +  also have "eval F \<in> O(eval_monom (1, snd (dominant_term F)) basis)"
 11.4473 +    using assms by (intro dominant_term_bigo assms) (auto simp: expands_to.simps)
 11.4474 +  also have "eval_monom (1, snd (dominant_term F)) basis =
 11.4475 +               eval_monom (1, snd (dominant_term G)) basis" using assms
 11.4476 +    by (intro eval_monom_eq) (auto simp: compare_expansions_def case_prod_unfold
 11.4477 +                                length_dominant_term split: cmp_result.splits)
 11.4478 +  also have "\<dots> \<in> O(eval_monom (dominant_term G) basis)" using assms(2)
 11.4479 +    by (auto simp add: eval_monom_def case_prod_unfold dest: trimmed_imp_dominant_term_nz)
 11.4480 +  also have "eval_monom (dominant_term G) basis \<in> \<Theta>(eval G)"
 11.4481 +    by (rule asymp_equiv_imp_bigtheta, rule asymp_equiv_symI, rule dominant_term)
 11.4482 +       (insert assms, auto simp: expands_to.simps)
 11.4483 +  also have "eval G \<in> \<Theta>(g)"
 11.4484 +    using assms by (intro bigthetaI_cong) (auto simp: expands_to.simps)
 11.4485 +  finally show ?thesis .
 11.4486 +qed
 11.4487 +
 11.4488 +lemma compare_expansions_EQ_same:
 11.4489 +  assumes "compare_expansions F G = (EQ, c, c')" "trimmed F" "trimmed G"
 11.4490 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4491 +          "c = c'"
 11.4492 +  shows   "f \<sim>[at_top] g"
 11.4493 +proof -
 11.4494 +  from assms have [simp]: "c' \<noteq> 0" 
 11.4495 +    by (auto simp: compare_expansions_def trimmed_imp_dominant_term_nz split: cmp_result.splits)
 11.4496 +  have "(\<lambda>x. inverse c * (c' * f x)) \<sim>[at_top] (\<lambda>x. inverse c * (c * g x))"
 11.4497 +    by (rule asymp_equiv_mult[OF asymp_equiv_refl]) (rule compare_expansions_EQ[OF assms(1-6)])
 11.4498 +  with assms(7) show ?thesis by (simp add: divide_simps)
 11.4499 +qed
 11.4500 +  
 11.4501 +lemma compare_expansions_EQ_imp_bigtheta:
 11.4502 +  assumes "compare_expansions F G = (EQ, c, c')" "trimmed F" "trimmed G"
 11.4503 +          "(f expands_to F) basis" "(g expands_to G) basis" "basis_wf basis"
 11.4504 +  shows   "f \<in> \<Theta>(g)"
 11.4505 +proof -
 11.4506 +  from assms have "(\<lambda>x. c' * f x) \<in> \<Theta>(\<lambda>x. c * g x)"
 11.4507 +    by (intro asymp_equiv_imp_bigtheta compare_expansions_EQ)
 11.4508 +  moreover from assms have "c \<noteq> 0" "c' \<noteq> 0"
 11.4509 +    by (auto simp: compare_expansions_def trimmed_imp_dominant_term_nz split: cmp_result.splits)
 11.4510 +  ultimately show ?thesis by simp
 11.4511 +qed
 11.4512 +
 11.4513 +lemma expands_to_MSLCons_0_asymp_equiv_hd:
 11.4514 +  assumes "(f expands_to (MS (MSLCons (C, 0) xs) g)) basis" "trimmed (MS (MSLCons (C, 0) xs) f)"
 11.4515 +          "basis_wf basis"
 11.4516 +  shows   "f \<sim>[at_top] eval C"
 11.4517 +proof -
 11.4518 +  from assms(1) is_expansion_aux_basis_nonempty obtain b basis' where [simp]: "basis = b # basis'"
 11.4519 +    by (cases basis) (auto simp: expands_to.simps)
 11.4520 +  from assms have b_pos: "eventually (\<lambda>x. b x > 0) at_top" 
 11.4521 +    by (simp add: filterlim_at_top_dense basis_wf_Cons)
 11.4522 +  from assms have "f \<sim>[at_top] eval_monom (dominant_term (MS (MSLCons (C, 0) xs) g)) basis" 
 11.4523 +    by (intro dominant_term_expands_to) simp_all
 11.4524 +  also have "\<dots> = (\<lambda>x. eval_monom (dominant_term C) basis' x * b x powr 0)"
 11.4525 +    by (simp_all add: dominant_term_ms_aux_def case_prod_unfold eval_monom_Cons)
 11.4526 +  also have "eventually (\<lambda>x. \<dots> x = eval_monom (dominant_term C) basis' x) at_top"
 11.4527 +    using b_pos by eventually_elim simp
 11.4528 +  also from assms have "eval_monom (dominant_term C) basis' \<sim>[at_top] eval C"
 11.4529 +    by (intro asymp_equiv_symI [OF dominant_term_expands_to] 
 11.4530 +          expands_to_hd''[of f C 0 xs g b basis']) (auto simp: trimmed_ms_aux_MSLCons basis_wf_Cons)
 11.4531 +  finally show ?thesis .
 11.4532 +qed
 11.4533 +    
 11.4534 +  
 11.4535 +lemma compare_expansions_LT':
 11.4536 +  assumes "compare_expansions (MS ys h) G \<equiv> (LT, c, c')" "trimmed G"
 11.4537 +          "(f expands_to (MS (MSLCons (MS ys h, e) xs) f')) (b # basis)" "(g expands_to G) basis"
 11.4538 +          "e = 0" "basis_wf (b # basis)"
 11.4539 +  shows   "h \<in> o(g)"   
 11.4540 +proof -
 11.4541 +  from assms show ?thesis
 11.4542 +    by (intro compare_expansions_LT[OF _ assms(2) _ assms(4)])
 11.4543 +       (auto intro: expands_to_hd'' simp: trimmed_ms_aux_MSLCons basis_wf_Cons expands_to.simps 
 11.4544 +             elim!: is_expansion_aux_MSLCons)
 11.4545 +qed
 11.4546 +
 11.4547 +lemma compare_expansions_GT':
 11.4548 +  assumes "compare_expansions C G \<equiv> (GT, c, c')"
 11.4549 +          "trimmed (MS (MSLCons (C, e) xs) f')"
 11.4550 +          "(f expands_to (MS (MSLCons (C, e) xs) f')) (b # basis)" "(g expands_to G) basis"
 11.4551 +          "e = 0" "basis_wf (b # basis)"
 11.4552 +  shows   "g \<in> o(f)"
 11.4553 +proof -
 11.4554 +  from assms have "g \<in> o(eval C)"
 11.4555 +    by (intro compare_expansions_GT[of C G c c' _ basis])
 11.4556 +       (auto intro: expands_to_hd'' simp: trimmed_ms_aux_MSLCons basis_wf_Cons)
 11.4557 +  also from assms have "f \<in> \<Theta>(eval C)"
 11.4558 +    by (intro asymp_equiv_imp_bigtheta expands_to_MSLCons_0_asymp_equiv_hd[of f C xs f' "b#basis"])
 11.4559 +       auto
 11.4560 +  finally show ?thesis .
 11.4561 +qed
 11.4562 +
 11.4563 +lemma compare_expansions_EQ':
 11.4564 +  assumes "compare_expansions C G = (EQ, c, c')" 
 11.4565 +          "trimmed (MS (MSLCons (C, e) xs) f')" "trimmed G"
 11.4566 +          "(f expands_to (MS (MSLCons (C, e) xs) f')) (b # basis)" "(g expands_to G) basis"
 11.4567 +          "e = 0" "basis_wf (b # basis)"
 11.4568 +  shows   "f \<sim>[at_top] (\<lambda>x. c / c' * g x)" 
 11.4569 +proof -
 11.4570 +  from assms have [simp]: "c' \<noteq> 0" 
 11.4571 +    by (auto simp: compare_expansions_def trimmed_imp_dominant_term_nz split: cmp_result.splits)
 11.4572 +  from assms have "f \<sim>[at_top] eval C"
 11.4573 +    by (intro expands_to_MSLCons_0_asymp_equiv_hd[of f C xs f' "b#basis"]) auto
 11.4574 +  also from assms(2,4,7) have *: "(\<lambda>x. c' * eval C x) \<sim>[at_top] (\<lambda>x. c * g x)"
 11.4575 +    by (intro compare_expansions_EQ[OF assms(1) _ assms(3) _ assms(5)])
 11.4576 +       (auto intro: expands_to_hd'' simp: trimmed_ms_aux_MSLCons basis_wf_Cons)
 11.4577 +  have "(\<lambda>x. inverse c' * (c' * eval C x)) \<sim>[at_top] (\<lambda>x. inverse c' * (c * g x))"
 11.4578 +    by (rule asymp_equiv_mult) (insert *, simp_all)
 11.4579 +  hence "eval C \<sim>[at_top] (\<lambda>x. c / c' * g x)" by (simp add: divide_simps)
 11.4580 +  finally show ?thesis .
 11.4581 +qed
 11.4582 +
 11.4583 +lemma expands_to_insert_ln: 
 11.4584 +  assumes "basis_wf [b]"
 11.4585 +  shows   "((\<lambda>x. ln (b x)) expands_to MS (MSLCons (1::real,1) MSLNil) (\<lambda>x. ln (b x))) [\<lambda>x. ln (b x)]"
 11.4586 +proof -
 11.4587 +  from assms have b_limit: "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.4588 +  hence b: "eventually (\<lambda>x. b x > 1) at_top" by (simp add: filterlim_at_top_dense)
 11.4589 +  have "(\<lambda>x::real. x) \<in> \<Theta>(\<lambda>x. x powr 1)"
 11.4590 +    by (intro bigthetaI_cong eventually_mono[OF eventually_gt_at_top[of 0]]) auto
 11.4591 +  also have "(\<lambda>x::real. x powr 1) \<in> o(\<lambda>a. a powr e)" if "e > 1" for e
 11.4592 +    by (subst powr_smallo_iff) (auto simp: that filterlim_ident)
 11.4593 +  finally show ?thesis using b assms
 11.4594 +    by (auto intro!: is_expansion_aux.intros landau_o.small.compose[of _ at_top _ "\<lambda>x. ln (b x)"]
 11.4595 +                     filterlim_compose[OF ln_at_top b_limit] is_expansion_real.intros
 11.4596 +             elim!: eventually_mono simp: expands_to.simps)
 11.4597 +qed
 11.4598 +
 11.4599 +lemma trimmed_pos_insert_ln:
 11.4600 +  assumes "basis_wf [b]"
 11.4601 +  shows   "trimmed_pos (MS (MSLCons (1::real, 1) MSLNil) (\<lambda>x. ln (b x)))"
 11.4602 +  by (simp_all add: trimmed_ms_aux_def)
 11.4603 +
 11.4604 +
 11.4605 +primrec compare_list_0 where
 11.4606 +  "compare_list_0 [] = EQ"
 11.4607 +| "compare_list_0 (c # cs) = CMP_BRANCH (COMPARE c 0) LT (compare_list_0 cs) GT"
 11.4608 +
 11.4609 +
 11.4610 +lemma compare_reals_diff_sgnD:
 11.4611 +  "a - (b :: real) < 0 \<Longrightarrow> a < b" "a - b = 0 \<Longrightarrow> a = b" "a - b > 0 \<Longrightarrow> a > b"
 11.4612 +  by simp_all
 11.4613 +
 11.4614 +lemma expands_to_real_imp_filterlim:
 11.4615 +  assumes "(f expands_to (c :: real)) basis"
 11.4616 +  shows   "(f \<longlongrightarrow> c) at_top"
 11.4617 +  using assms by (auto elim!: expands_to.cases simp: eq_commute[of c] Lim_eventually)
 11.4618 +
 11.4619 +lemma expands_to_MSLNil_imp_filterlim:
 11.4620 +  assumes "(f expands_to MS MSLNil f') basis"
 11.4621 +  shows   "(f \<longlongrightarrow> 0) at_top"
 11.4622 +proof -
 11.4623 +  from assms have "eventually (\<lambda>x. f' x = 0) at_top" "eventually (\<lambda>x. f' x = f x) at_top"
 11.4624 +    by (auto elim!: expands_to.cases is_expansion_aux.cases[of MSLNil])
 11.4625 +  hence "eventually (\<lambda>x. f x = 0) at_top" by eventually_elim auto
 11.4626 +  thus ?thesis by (simp add: Lim_eventually)
 11.4627 +qed
 11.4628 +
 11.4629 +lemma expands_to_neg_exponent_imp_filterlim:
 11.4630 +  assumes "(f expands_to MS (MSLCons (C, e) xs) f') basis" "basis_wf basis" "e < 0"
 11.4631 +  shows   "(f \<longlongrightarrow> 0) at_top"
 11.4632 +proof -
 11.4633 +  let ?F = "MS (MSLCons (C, e) xs) f'"
 11.4634 +  let ?es = "snd (dominant_term ?F)"
 11.4635 +  from assms have exp: "is_expansion ?F basis"
 11.4636 +    by (simp add: expands_to.simps)
 11.4637 +  from assms have "f \<in> \<Theta>(f')" by (intro bigthetaI_cong) (simp add: expands_to.simps eq_commute)
 11.4638 +  also from dominant_term_bigo[OF assms(2) exp]
 11.4639 +    have "f' \<in> O(eval_monom (1, ?es) basis)" by simp
 11.4640 +  also have "(eval_monom (1, ?es) basis) \<in> o(\<lambda>x. hd basis x powr 0)" using exp assms
 11.4641 +    by (intro eval_monom_smallo)
 11.4642 +       (auto simp: is_expansion_aux_basis_nonempty dominant_term_ms_aux_def
 11.4643 +                   case_prod_unfold length_dominant_term is_expansion_aux_expansion_level)
 11.4644 +  also have "(\<lambda>x. hd basis x powr 0) \<in> O(\<lambda>_. 1)"
 11.4645 +    by (intro landau_o.bigI[of 1]) auto
 11.4646 +  finally show ?thesis by (auto dest!: smalloD_tendsto)
 11.4647 +qed
 11.4648 +
 11.4649 +lemma expands_to_pos_exponent_imp_filterlim:
 11.4650 +  assumes "(f expands_to MS (MSLCons (C, e) xs) f') basis" "trimmed (MS (MSLCons (C, e) xs) f')"
 11.4651 +          "basis_wf basis" "e > 0"
 11.4652 +  shows   "filterlim f at_infinity at_top"
 11.4653 +proof -
 11.4654 +  let ?F = "MS (MSLCons (C, e) xs) f'"
 11.4655 +  let ?es = "snd (dominant_term ?F)"
 11.4656 +  from assms have exp: "is_expansion ?F basis"
 11.4657 +    by (simp add: expands_to.simps)
 11.4658 +  with assms have "filterlim (hd basis) at_top at_top"
 11.4659 +    using is_expansion_aux_basis_nonempty[of "MSLCons (C, e) xs" f' basis]
 11.4660 +    by (cases basis) (simp_all add: basis_wf_Cons)
 11.4661 +  hence b_pos: "eventually (\<lambda>x. hd basis x > 0) at_top" using filterlim_at_top_dense by blast
 11.4662 +
 11.4663 +  from assms have "f \<in> \<Theta>(f')" by (intro bigthetaI_cong) (simp add: expands_to.simps eq_commute)
 11.4664 +  also from dominant_term[OF assms(3) exp assms(2)]
 11.4665 +    have "f' \<in> \<Theta>(eval_monom (dominant_term ?F) basis)" by (simp add: asymp_equiv_imp_bigtheta)
 11.4666 +  also have "(eval_monom (dominant_term ?F) basis) \<in> \<Theta>(eval_monom (1, ?es) basis)"
 11.4667 +    using assms by (simp add: eval_monom_def case_prod_unfold dominant_term_ms_aux_def 
 11.4668 +                              trimmed_imp_dominant_term_nz trimmed_ms_aux_def)
 11.4669 +  also have "eval_monom (1, ?es) basis \<in> \<omega>(\<lambda>x. hd basis x powr 0)" using exp assms
 11.4670 +    by (intro eval_monom_smallomega)
 11.4671 +       (auto simp: is_expansion_aux_basis_nonempty dominant_term_ms_aux_def
 11.4672 +                   case_prod_unfold length_dominant_term is_expansion_aux_expansion_level)
 11.4673 +  also have "(\<lambda>x. hd basis x powr 0) \<in> \<Theta>(\<lambda>_. 1)"
 11.4674 +    by (intro bigthetaI_cong eventually_mono[OF b_pos]) auto
 11.4675 +  finally show ?thesis by (auto dest!: smallomegaD_filterlim_at_infinity)
 11.4676 +qed
 11.4677 +
 11.4678 +lemma expands_to_zero_exponent_imp_filterlim:
 11.4679 +  assumes "(f expands_to MS (MSLCons (C, e) xs) f') basis"
 11.4680 +          "basis_wf basis" "e = 0"
 11.4681 +  shows   "filterlim (eval C) at_infinity at_top \<Longrightarrow> filterlim f at_infinity at_top"
 11.4682 +    and   "filterlim (eval C) (nhds L) at_top \<Longrightarrow> filterlim f (nhds L) at_top"
 11.4683 +proof -
 11.4684 +  from assms obtain b basis' where *:
 11.4685 +    "basis = b # basis'" "is_expansion C basis'" "ms_exp_gt 0 (ms_aux_hd_exp xs)"
 11.4686 +    "is_expansion_aux xs (\<lambda>x. f' x - eval C x * b x powr 0) basis"
 11.4687 +    by (auto elim!: expands_to.cases is_expansion_aux_MSLCons)
 11.4688 +
 11.4689 +  from *(1) assms have "filterlim b at_top at_top" by (simp add: basis_wf_Cons)
 11.4690 +  hence b_pos: "eventually (\<lambda>x. b x > 0) at_top" using filterlim_at_top_dense by blast
 11.4691 +
 11.4692 +  from assms(1) have "eventually (\<lambda>x. f' x = f x) at_top" by (simp add: expands_to.simps)
 11.4693 +  hence "eventually (\<lambda>x. f' x - eval C x * b x powr 0 = f x - eval C x) at_top"
 11.4694 +    using b_pos by eventually_elim auto
 11.4695 +  from *(4) and this have "is_expansion_aux xs (\<lambda>x. f x - eval C x) basis"
 11.4696 +    by (rule is_expansion_aux_cong)
 11.4697 +  hence "(\<lambda>x. f x - eval C x) \<in> o(\<lambda>x. hd basis x powr 0)"
 11.4698 +    by (rule is_expansion_aux_imp_smallo) fact
 11.4699 +  also have "(\<lambda>x. hd basis x powr 0) \<in> \<Theta>(\<lambda>_. 1)"
 11.4700 +    by (intro bigthetaI_cong eventually_mono[OF b_pos]) (auto simp: *(1))
 11.4701 +  finally have lim: "filterlim (\<lambda>x. f x - eval C x) (nhds 0) at_top"
 11.4702 +    by (auto dest: smalloD_tendsto)
 11.4703 +
 11.4704 +  show "filterlim f at_infinity at_top" if "filterlim (eval C) at_infinity at_top"
 11.4705 +    using tendsto_add_filterlim_at_infinity[OF lim that] by simp
 11.4706 +  show "filterlim f (nhds L) at_top" if "filterlim (eval C) (nhds L) at_top"
 11.4707 +    using tendsto_add[OF lim that] by simp
 11.4708 +qed
 11.4709 +
 11.4710 +lemma expands_to_lift_function:
 11.4711 +  assumes "eventually (\<lambda>x. f x - eval c x = 0) at_top"
 11.4712 +          "((\<lambda>x. g (eval (c :: 'a :: multiseries) x)) expands_to G) bs'"
 11.4713 +  shows   "((\<lambda>x. g (f x)) expands_to G) bs'"
 11.4714 +  by (rule expands_to_cong[OF assms(2)]) (insert assms, auto elim: eventually_mono) 
 11.4715 +
 11.4716 +lemma drop_zero_ms':
 11.4717 +  fixes c f
 11.4718 +  assumes "c = (0::real)" "(f expands_to MS (MSLCons (c, e) xs) g) basis"
 11.4719 +  shows   "(f expands_to MS xs g) basis"
 11.4720 +  using assms drop_zero_ms[of c e xs g basis] by (simp add: expands_to.simps)
 11.4721 +
 11.4722 +lemma trimmed_realI: "c \<noteq> (0::real) \<Longrightarrow> trimmed c"
 11.4723 +  by simp
 11.4724 +
 11.4725 +lemma trimmed_pos_realI: "c > (0::real) \<Longrightarrow> trimmed_pos c"
 11.4726 +  by simp
 11.4727 +
 11.4728 +lemma trimmed_neg_realI: "c < (0::real) \<Longrightarrow> trimmed_neg c"
 11.4729 +  by (simp add: trimmed_neg_def)
 11.4730 +
 11.4731 +lemma trimmed_pos_hd_coeff: "trimmed_pos (MS (MSLCons (C, e) xs) f) \<Longrightarrow> trimmed_pos C"
 11.4732 +  by simp
 11.4733 +
 11.4734 +lemma lift_trimmed: "trimmed C \<Longrightarrow> trimmed (MS (MSLCons (C, e) xs) f)"
 11.4735 +  by (auto simp: trimmed_ms_aux_def)
 11.4736 +
 11.4737 +lemma lift_trimmed_pos: "trimmed_pos C \<Longrightarrow> trimmed_pos (MS (MSLCons (C, e) xs) f)"
 11.4738 +  by simp
 11.4739 +
 11.4740 +lemma lift_trimmed_neg: "trimmed_neg C \<Longrightarrow> trimmed_neg (MS (MSLCons (C, e) xs) f)"
 11.4741 +  by (simp add: trimmed_neg_def fst_dominant_term_ms_aux_MSLCons trimmed_ms_aux_MSLCons)
 11.4742 +
 11.4743 +lemma lift_trimmed_pos':
 11.4744 +  "trimmed_pos C \<Longrightarrow> MS (MSLCons (C, e) xs) f \<equiv> MS (MSLCons (C, e) xs) f \<Longrightarrow>
 11.4745 +     trimmed_pos (MS (MSLCons (C, e) xs) f)"
 11.4746 +  by simp
 11.4747 +
 11.4748 +lemma lift_trimmed_neg':
 11.4749 +  "trimmed_neg C \<Longrightarrow> MS (MSLCons (C, e) xs) f \<equiv> MS (MSLCons (C, e) xs) f \<Longrightarrow>
 11.4750 +     trimmed_neg (MS (MSLCons (C, e) xs) f)"
 11.4751 +  by (simp add: lift_trimmed_neg)
 11.4752 +
 11.4753 +lemma trimmed_eq_cong: "trimmed C \<Longrightarrow> C \<equiv> C' \<Longrightarrow> trimmed C'"
 11.4754 +  and trimmed_pos_eq_cong: "trimmed_pos C \<Longrightarrow> C \<equiv> C' \<Longrightarrow> trimmed_pos C'"
 11.4755 +  and trimmed_neg_eq_cong: "trimmed_neg C \<Longrightarrow> C \<equiv> C' \<Longrightarrow> trimmed_neg C'"
 11.4756 +  by simp_all
 11.4757 +
 11.4758 +lemma trimmed_hd: "trimmed (MS (MSLCons (C, e) xs) f) \<Longrightarrow> trimmed C"
 11.4759 +  by (simp add: trimmed_ms_aux_MSLCons)
 11.4760 +
 11.4761 +lemma trim_lift_eq:
 11.4762 +  assumes "A \<equiv> MS (MSLCons (C, e) xs) f" "C \<equiv> D"
 11.4763 +  shows   "A \<equiv> MS (MSLCons (D, e) xs) f" 
 11.4764 +  using assms by simp
 11.4765 +
 11.4766 +lemma basis_wf_manyI: 
 11.4767 +  "filterlim b' at_top at_top \<Longrightarrow> (\<lambda>x. ln (b x)) \<in> o(\<lambda>x. ln (b' x)) \<Longrightarrow>
 11.4768 +     basis_wf (b # basis) \<Longrightarrow> basis_wf (b' # b # basis)"
 11.4769 +  by (simp_all add: basis_wf_many)
 11.4770 +
 11.4771 +lemma ln_smallo_ln_exp: "(\<lambda>x. ln (b x)) \<in> o(f) \<Longrightarrow> (\<lambda>x. ln (b x)) \<in> o(\<lambda>x. ln (exp (f x :: real)))"
 11.4772 +  by simp
 11.4773 +
 11.4774 +
 11.4775 +subsection \<open>Reification and other technical details\<close>
 11.4776 +
 11.4777 +text \<open>
 11.4778 +  The following is used by the automation in order to avoid writing terms like $x^2$ or $x^{-2}$
 11.4779 +  as @{term "\<lambda>x::real. x powr 2"} etc.\ but as the more agreeable @{term "\<lambda>x::real. x ^ 2"} or
 11.4780 +  @{term "\<lambda>x::real. inverse (x ^ 2)"}.
 11.4781 +\<close>
 11.4782 +
 11.4783 +lemma intyness_0: "0 \<equiv> real 0"
 11.4784 +  and intyness_1: "1 \<equiv> real 1"
 11.4785 +  and intyness_numeral: "num \<equiv> num \<Longrightarrow> numeral num \<equiv> real (numeral num)"
 11.4786 +  and intyness_uminus:  "x \<equiv> real n \<Longrightarrow> -x \<equiv> -real n"
 11.4787 +  and intyness_of_nat:  "n \<equiv> n \<Longrightarrow> real n \<equiv> real n"
 11.4788 +  by simp_all
 11.4789 +    
 11.4790 +lemma intyness_simps:
 11.4791 +  "real a + real b = real (a + b)"
 11.4792 +  "real a * real b = real (a * b)"
 11.4793 +  "real a ^ n = real (a ^ n)"
 11.4794 +  "1 = real 1" "0 = real 0" "numeral num = real (numeral num)" 
 11.4795 +  by simp_all
 11.4796 +
 11.4797 +lemma odd_Numeral1: "odd (Numeral1)"
 11.4798 +  by simp
 11.4799 +
 11.4800 +lemma even_addI:
 11.4801 +  "even a \<Longrightarrow> even b \<Longrightarrow> even (a + b)"
 11.4802 +  "odd a \<Longrightarrow> odd b \<Longrightarrow> even (a + b)"
 11.4803 +  by auto
 11.4804 +
 11.4805 +lemma odd_addI:
 11.4806 +  "even a \<Longrightarrow> odd b \<Longrightarrow> odd (a + b)"
 11.4807 +  "odd a \<Longrightarrow> even b \<Longrightarrow> odd (a + b)"
 11.4808 +  by auto
 11.4809 +
 11.4810 +lemma even_diffI:
 11.4811 +  "even a \<Longrightarrow> even b \<Longrightarrow> even (a - b :: 'a :: ring_parity)"
 11.4812 +  "odd a \<Longrightarrow> odd b \<Longrightarrow> even (a - b)"
 11.4813 +  by auto
 11.4814 +
 11.4815 +lemma odd_diffI:
 11.4816 +  "even a \<Longrightarrow> odd b \<Longrightarrow> odd (a - b :: 'a :: ring_parity)"
 11.4817 +  "odd a \<Longrightarrow> even b \<Longrightarrow> odd (a - b)"
 11.4818 +  by auto
 11.4819 +
 11.4820 +lemma even_multI: "even a \<Longrightarrow> even (a * b)" "even b \<Longrightarrow> even (a * b)"
 11.4821 +  by auto
 11.4822 +
 11.4823 +lemma odd_multI: "odd a \<Longrightarrow> odd b \<Longrightarrow> odd (a * b)"
 11.4824 +  by auto
 11.4825 +
 11.4826 +lemma even_uminusI: "even a \<Longrightarrow> even (-a :: 'a :: ring_parity)"
 11.4827 +  and odd_uminusI:  "odd a \<Longrightarrow> odd (-a :: 'a :: ring_parity)"
 11.4828 +  by auto
 11.4829 +
 11.4830 +lemma odd_powerI: "odd a \<Longrightarrow> odd (a ^ n)"
 11.4831 +  by auto
 11.4832 +
 11.4833 +
 11.4834 +text \<open>
 11.4835 +  The following theorem collection is used to pre-process functions for multiseries expansion.
 11.4836 +\<close>
 11.4837 +named_theorems real_asymp_reify_simps
 11.4838 +
 11.4839 +lemmas [real_asymp_reify_simps] =
 11.4840 +  sinh_field_def cosh_field_def tanh_real_altdef arsinh_def arcosh_def artanh_def
 11.4841 +
 11.4842 +
 11.4843 +text \<open>
 11.4844 +  This is needed in order to handle things like @{term "\<lambda>n. f n ^ n"}.
 11.4845 +\<close>
 11.4846 +definition powr_nat :: "real \<Rightarrow> real \<Rightarrow> real" where 
 11.4847 +  "powr_nat x y = 
 11.4848 +     (if y = 0 then 1
 11.4849 +      else if x < 0 then cos (pi * y) * (-x) powr y else x powr y)"
 11.4850 +  
 11.4851 +lemma powr_nat_of_nat: "powr_nat x (of_nat n) = x ^ n"
 11.4852 +  by (cases "x > 0") (auto simp: powr_nat_def powr_realpow not_less power_mult_distrib [symmetric])
 11.4853 +
 11.4854 +lemma powr_nat_conv_powr: "x > 0 \<Longrightarrow> powr_nat x y = x powr y"
 11.4855 +  by (simp_all add: powr_nat_def)
 11.4856 +
 11.4857 +lemma reify_power: "x ^ n \<equiv> powr_nat x (of_nat n)"
 11.4858 +  by (simp add: powr_nat_of_nat)
 11.4859 +
 11.4860 +
 11.4861 +lemma sqrt_conv_root [real_asymp_reify_simps]: "sqrt x = root 2 x"
 11.4862 +  by (simp add: sqrt_def)
 11.4863 +
 11.4864 +lemma tan_conv_sin_cos [real_asymp_reify_simps]: "tan x = sin x / cos x"
 11.4865 +  by (simp add: tan_def)
 11.4866 +
 11.4867 +definition rfloor :: "real \<Rightarrow> real" where "rfloor x = real_of_int (floor x)"
 11.4868 +definition rceil :: "real \<Rightarrow> real" where "rceil x = real_of_int (ceiling x)"
 11.4869 +definition rnatmod :: "real \<Rightarrow> real \<Rightarrow> real"
 11.4870 +  where "rnatmod x y = real (nat \<lfloor>x\<rfloor> mod nat \<lfloor>y\<rfloor>)"
 11.4871 +definition rintmod :: "real \<Rightarrow> real \<Rightarrow> real"
 11.4872 +  where "rintmod x y = real_of_int (\<lfloor>x\<rfloor> mod \<lfloor>y\<rfloor>)"
 11.4873 +
 11.4874 +lemmas [real_asymp_reify_simps] =
 11.4875 +  ln_exp log_def rfloor_def [symmetric] rceil_def [symmetric]
 11.4876 +
 11.4877 +lemma expands_to_powr_nat_0_0:
 11.4878 +  assumes "eventually (\<lambda>x. f x = 0) at_top" "eventually (\<lambda>x. g x = 0) at_top"
 11.4879 +          "basis_wf basis" "length basis = expansion_level TYPE('a :: multiseries)"
 11.4880 +  shows   "((\<lambda>x. powr_nat (f x) (g x)) expands_to (const_expansion 1 :: 'a)) basis"
 11.4881 +proof (rule expands_to_cong [OF expands_to_const])
 11.4882 +  from assms(1,2) show "eventually (\<lambda>x. 1 = powr_nat (f x) (g x)) at_top"
 11.4883 +    by eventually_elim (simp add: powr_nat_def)
 11.4884 +qed fact+
 11.4885 +
 11.4886 +lemma expands_to_powr_nat_0:
 11.4887 +  assumes "eventually (\<lambda>x. f x = 0) at_top" "(g expands_to G) basis" "trimmed G"
 11.4888 +          "basis_wf basis" "length basis = expansion_level TYPE('a :: multiseries)"
 11.4889 +  shows   "((\<lambda>x. powr_nat (f x) (g x)) expands_to (zero_expansion :: 'a)) basis"
 11.4890 +proof (rule expands_to_cong [OF expands_to_zero])
 11.4891 +  from assms have "eventually (\<lambda>x. g x \<noteq> 0) at_top"
 11.4892 +    using expands_to_imp_eventually_nz[of basis g G] by auto
 11.4893 +  with assms(1) show "eventually (\<lambda>x. 0 = powr_nat (f x) (g x)) at_top"
 11.4894 +    by eventually_elim (simp add: powr_nat_def)
 11.4895 +qed (insert assms, auto elim!: eventually_mono simp: powr_nat_def)
 11.4896 +
 11.4897 +lemma expands_to_powr_nat:
 11.4898 +  assumes "trimmed_pos F" "basis_wf basis'" "(f expands_to F) basis'"
 11.4899 +  assumes "((\<lambda>x. exp (ln (f x) * g x)) expands_to E) basis"
 11.4900 +  shows   "((\<lambda>x. powr_nat (f x) (g x)) expands_to E) basis"
 11.4901 +using assms(4)
 11.4902 +proof (rule expands_to_cong)
 11.4903 +  from eval_pos_if_dominant_term_pos[of basis' F] assms(1-4)
 11.4904 +    show "eventually (\<lambda>x. exp (ln (f x) * g x) = powr_nat (f x) (g x)) at_top"
 11.4905 +    by (auto simp: expands_to.simps trimmed_pos_def powr_def powr_nat_def elim: eventually_elim2)
 11.4906 +qed
 11.4907 +
 11.4908 +
 11.4909 +subsection \<open>Some technical lemmas\<close>
 11.4910 +
 11.4911 +lemma landau_meta_eq_cong: "f \<in> L(g) \<Longrightarrow> f' \<equiv> f \<Longrightarrow> g' \<equiv> g \<Longrightarrow> f' \<in> L(g')"
 11.4912 +  and asymp_equiv_meta_eq_cong: "f \<sim>[at_top] g \<Longrightarrow> f' \<equiv> f \<Longrightarrow> g' \<equiv> g \<Longrightarrow> f' \<sim>[at_top] g'"
 11.4913 +  by simp_all
 11.4914 +    
 11.4915 +lemma filterlim_mono': "filterlim f F G \<Longrightarrow> F \<le> F' \<Longrightarrow> filterlim f F' G"
 11.4916 +  by (erule (1) filterlim_mono) simp_all
 11.4917 +
 11.4918 +lemma at_within_le_nhds: "at x within A \<le> nhds x"
 11.4919 +  by (simp add: at_within_def)
 11.4920 +
 11.4921 +lemma at_within_le_at: "at x within A \<le> at x"
 11.4922 +  by (rule at_le) simp_all
 11.4923 +
 11.4924 +lemma at_right_to_top': "at_right c = filtermap (\<lambda>x::real. c + inverse x) at_top"
 11.4925 +  by (subst at_right_to_0, subst at_right_to_top) (simp add: filtermap_filtermap add_ac)
 11.4926 +
 11.4927 +lemma at_left_to_top': "at_left c = filtermap (\<lambda>x::real. c - inverse x) at_top"
 11.4928 +  by (subst at_left_minus, subst at_right_to_0, subst at_right_to_top) 
 11.4929 +     (simp add: filtermap_filtermap add_ac)
 11.4930 +
 11.4931 +lemma at_left_to_top: "at_left 0 = filtermap (\<lambda>x::real. - inverse x) at_top"
 11.4932 +  by (simp add: at_left_to_top')
 11.4933 +
 11.4934 +lemma filterlim_conv_filtermap:
 11.4935 +  "G = filtermap g G' \<Longrightarrow>
 11.4936 +     PROP (Trueprop (filterlim f F G)) \<equiv> PROP (Trueprop (filterlim (\<lambda>x. f (g x)) F G'))"
 11.4937 +  by (simp add: filterlim_filtermap)
 11.4938 +
 11.4939 +lemma eventually_conv_filtermap:
 11.4940 +  "G = filtermap g G' \<Longrightarrow> 
 11.4941 +     PROP (Trueprop (eventually P G)) \<equiv> PROP (Trueprop (eventually (\<lambda>x. P (g x)) G'))"
 11.4942 +  by (simp add: eventually_filtermap)
 11.4943 +
 11.4944 +lemma eventually_lt_imp_eventually_le:
 11.4945 +  "eventually (\<lambda>x. f x < (g x :: real)) F \<Longrightarrow> eventually (\<lambda>x. f x \<le> g x) F"
 11.4946 +  by (erule eventually_mono) simp
 11.4947 +    
 11.4948 +lemma smallo_imp_smallomega: "f \<in> o[F](g) \<Longrightarrow> g \<in> \<omega>[F](f)"
 11.4949 +  by (simp add: smallomega_iff_smallo)
 11.4950 +
 11.4951 +lemma bigo_imp_bigomega: "f \<in> O[F](g) \<Longrightarrow> g \<in> \<Omega>[F](f)"
 11.4952 +  by (simp add: bigomega_iff_bigo)
 11.4953 +
 11.4954 +context
 11.4955 +  fixes L L' :: "real filter \<Rightarrow> (real \<Rightarrow> _) \<Rightarrow> _" and Lr :: "real filter \<Rightarrow> (real \<Rightarrow> real) \<Rightarrow> _"
 11.4956 +  assumes LS: "landau_symbol L L' Lr"
 11.4957 +begin
 11.4958 +  
 11.4959 +interpretation landau_symbol L L' Lr by (fact LS)
 11.4960 +
 11.4961 +lemma landau_symbol_at_top_imp_at_bot:
 11.4962 +  "(\<lambda>x. f (-x)) \<in> L' at_top (\<lambda>x. g (-x)) \<Longrightarrow> f \<in> L at_bot g"
 11.4963 +  by (simp add: in_filtermap_iff at_bot_mirror)
 11.4964 +
 11.4965 +lemma landau_symbol_at_top_imp_at_right_0:
 11.4966 +  "(\<lambda>x. f (inverse x)) \<in> L' at_top (\<lambda>x. g (inverse x)) \<Longrightarrow> f \<in> L (at_right 0) g"
 11.4967 +  by (simp add: in_filtermap_iff at_right_to_top')
 11.4968 +    
 11.4969 +lemma landau_symbol_at_top_imp_at_left_0:
 11.4970 +  "(\<lambda>x. f ( -inverse x)) \<in> L' at_top (\<lambda>x. g (-inverse x)) \<Longrightarrow> f \<in> L (at_left 0) g"
 11.4971 +  by (simp add: in_filtermap_iff at_left_to_top')    
 11.4972 +
 11.4973 +lemma landau_symbol_at_top_imp_at_right:
 11.4974 +  "(\<lambda>x. f (a + inverse x)) \<in> L' at_top (\<lambda>x. g (a + inverse x)) \<Longrightarrow> f \<in> L (at_right a) g"
 11.4975 +  by (simp add: in_filtermap_iff at_right_to_top')
 11.4976 +    
 11.4977 +lemma landau_symbol_at_top_imp_at_left:
 11.4978 +  "(\<lambda>x. f (a - inverse x)) \<in> L' at_top (\<lambda>x. g (a - inverse x)) \<Longrightarrow> f \<in> L (at_left a) g"
 11.4979 +  by (simp add: in_filtermap_iff at_left_to_top')
 11.4980 +    
 11.4981 +lemma landau_symbol_at_top_imp_at:
 11.4982 +  "(\<lambda>x. f (a - inverse x)) \<in> L' at_top (\<lambda>x. g (a - inverse x)) \<Longrightarrow>
 11.4983 +   (\<lambda>x. f (a + inverse x)) \<in> L' at_top (\<lambda>x. g (a + inverse x)) \<Longrightarrow>
 11.4984 +   f \<in> L (at a) g"
 11.4985 +  by (simp add: sup at_eq_sup_left_right 
 11.4986 +        landau_symbol_at_top_imp_at_left landau_symbol_at_top_imp_at_right)
 11.4987 +      
 11.4988 +lemma landau_symbol_at_top_imp_at_0:
 11.4989 +  "(\<lambda>x. f (-inverse x)) \<in> L' at_top (\<lambda>x. g (-inverse x)) \<Longrightarrow>
 11.4990 +   (\<lambda>x. f (inverse x)) \<in> L' at_top (\<lambda>x. g (inverse x)) \<Longrightarrow>
 11.4991 +   f \<in> L (at 0) g"
 11.4992 +  by (rule landau_symbol_at_top_imp_at) simp_all
 11.4993 +
 11.4994 +end
 11.4995 +
 11.4996 +
 11.4997 +context
 11.4998 +  fixes f g :: "real \<Rightarrow> real"
 11.4999 +begin
 11.5000 +
 11.5001 +lemma asymp_equiv_at_top_imp_at_bot:
 11.5002 +  "(\<lambda>x. f (- x)) \<sim>[at_top] (\<lambda>x. g (-x)) \<Longrightarrow> f \<sim>[at_bot] g"
 11.5003 +  by (simp add: asymp_equiv_def filterlim_at_bot_mirror)
 11.5004 +
 11.5005 +lemma asymp_equiv_at_top_imp_at_right_0:
 11.5006 +  "(\<lambda>x. f (inverse x)) \<sim>[at_top] (\<lambda>x. g (inverse x)) \<Longrightarrow> f \<sim>[at_right 0] g"
 11.5007 +  by (simp add: at_right_to_top asymp_equiv_filtermap_iff)
 11.5008 +
 11.5009 +lemma asymp_equiv_at_top_imp_at_left_0:
 11.5010 +  "(\<lambda>x. f (-inverse x)) \<sim>[at_top] (\<lambda>x. g (-inverse x)) \<Longrightarrow> f \<sim>[at_left 0] g"
 11.5011 +  by (simp add: at_left_to_top asymp_equiv_filtermap_iff)
 11.5012 +
 11.5013 +lemma asymp_equiv_at_top_imp_at_right:
 11.5014 +  "(\<lambda>x. f (a + inverse x)) \<sim>[at_top] (\<lambda>x. g (a + inverse x)) \<Longrightarrow> f \<sim>[at_right a] g"
 11.5015 +  by (simp add: at_right_to_top' asymp_equiv_filtermap_iff)
 11.5016 +
 11.5017 +lemma asymp_equiv_at_top_imp_at_left:
 11.5018 +  "(\<lambda>x. f (a - inverse x)) \<sim>[at_top] (\<lambda>x. g (a - inverse x)) \<Longrightarrow> f \<sim>[at_left a] g"
 11.5019 +  by (simp add: at_left_to_top' asymp_equiv_filtermap_iff)
 11.5020 +
 11.5021 +lemma asymp_equiv_at_top_imp_at:
 11.5022 +  "(\<lambda>x. f (a - inverse x)) \<sim>[at_top] (\<lambda>x. g (a - inverse x)) \<Longrightarrow>
 11.5023 +   (\<lambda>x. f (a + inverse x)) \<sim>[at_top] (\<lambda>x. g (a + inverse x)) \<Longrightarrow> f \<sim>[at a] g"
 11.5024 +  unfolding asymp_equiv_def
 11.5025 +  using asymp_equiv_at_top_imp_at_left[of a] asymp_equiv_at_top_imp_at_right[of a]
 11.5026 +  by (intro filterlim_split_at) (auto simp: asymp_equiv_def)
 11.5027 +
 11.5028 +lemma asymp_equiv_at_top_imp_at_0:
 11.5029 +  "(\<lambda>x. f (-inverse x)) \<sim>[at_top] (\<lambda>x. g (-inverse x)) \<Longrightarrow>
 11.5030 +   (\<lambda>x. f (inverse x)) \<sim>[at_top] (\<lambda>x. g (inverse x)) \<Longrightarrow> f \<sim>[at 0] g"
 11.5031 +  by (rule asymp_equiv_at_top_imp_at) auto
 11.5032 +
 11.5033 +end
 11.5034 +
 11.5035 +
 11.5036 +lemmas eval_simps =
 11.5037 +  eval_const eval_plus eval_minus eval_uminus eval_times eval_inverse eval_divide
 11.5038 +  eval_map_ms eval_lift_ms eval_real_def eval_ms.simps
 11.5039 +
 11.5040 +lemma real_eqI: "a - b = 0 \<Longrightarrow> a = (b::real)"
 11.5041 +  by simp
 11.5042 +
 11.5043 +lemma lift_ms_simps:
 11.5044 +  "lift_ms (MS xs f) = MS (MSLCons (MS xs f, 0) MSLNil) f"
 11.5045 +  "lift_ms (c :: real) = MS (MSLCons (c, 0) MSLNil) (\<lambda>_. c)"
 11.5046 +  by (simp_all add: lift_ms_def)
 11.5047 +
 11.5048 +lemmas landau_reduce_to_top = 
 11.5049 +  landau_symbols [THEN landau_symbol_at_top_imp_at_bot]
 11.5050 +  landau_symbols [THEN landau_symbol_at_top_imp_at_left_0]
 11.5051 +  landau_symbols [THEN landau_symbol_at_top_imp_at_right_0]
 11.5052 +  landau_symbols [THEN landau_symbol_at_top_imp_at_left]
 11.5053 +  landau_symbols [THEN landau_symbol_at_top_imp_at_right]
 11.5054 +  asymp_equiv_at_top_imp_at_bot
 11.5055 +  asymp_equiv_at_top_imp_at_left_0
 11.5056 +  asymp_equiv_at_top_imp_at_right_0
 11.5057 +  asymp_equiv_at_top_imp_at_left
 11.5058 +  asymp_equiv_at_top_imp_at_right
 11.5059 +
 11.5060 +lemmas landau_at_top_imp_at = 
 11.5061 +  landau_symbols [THEN landau_symbol_at_top_imp_at_0]
 11.5062 +  landau_symbols [THEN landau_symbol_at_top_imp_at]
 11.5063 +  asymp_equiv_at_top_imp_at_0
 11.5064 +  asymp_equiv_at_top_imp_at
 11.5065 +
 11.5066 +
 11.5067 +lemma nhds_leI: "x = y \<Longrightarrow> nhds x \<le> nhds y"
 11.5068 +  by simp
 11.5069 +    
 11.5070 +lemma of_nat_diff_real: "of_nat (a - b) = max (0::real) (of_nat a - of_nat b)"
 11.5071 +  and of_nat_max_real: "of_nat (max a b) = max (of_nat a) (of_nat b :: real)"
 11.5072 +  and of_nat_min_real: "of_nat (min a b) = min (of_nat a) (of_nat b :: real)"
 11.5073 +  and of_int_max_real: "of_int (max c d) = max (of_int c) (of_int d :: real)"
 11.5074 +  and of_int_min_real: "of_int (min c d) = min (of_int c) (of_int d :: real)"
 11.5075 +  by simp_all
 11.5076 +
 11.5077 +named_theorems real_asymp_nat_reify
 11.5078 +
 11.5079 +lemmas [real_asymp_nat_reify] = 
 11.5080 +  of_nat_add of_nat_mult of_nat_diff_real of_nat_max_real of_nat_min_real of_nat_power 
 11.5081 +  of_nat_Suc of_nat_numeral
 11.5082 +
 11.5083 +lemma of_nat_div_real [real_asymp_nat_reify]:
 11.5084 +  "of_nat (a div b) = max 0 (rfloor (of_nat a / of_nat b))"
 11.5085 +  by (simp add: rfloor_def floor_divide_of_nat_eq)
 11.5086 +
 11.5087 +lemma of_nat_mod_real [real_asymp_nat_reify]: "of_nat (a mod b) = rnatmod (of_nat a) (of_nat b)"
 11.5088 +  by (simp add: rnatmod_def)
 11.5089 +
 11.5090 +lemma real_nat [real_asymp_nat_reify]: "real (nat a) = max 0 (of_int a)"
 11.5091 +  by simp
 11.5092 +
 11.5093 +
 11.5094 +named_theorems real_asymp_int_reify
 11.5095 +
 11.5096 +lemmas [real_asymp_int_reify] = 
 11.5097 +  of_int_add of_int_mult of_int_diff of_int_minus of_int_max_real of_int_min_real
 11.5098 +  of_int_power of_int_of_nat_eq of_int_numeral
 11.5099 +
 11.5100 +lemma of_int_div_real [real_asymp_int_reify]:
 11.5101 +  "of_int (a div b) = rfloor (of_int a / of_int b)"
 11.5102 +  by (simp add: rfloor_def floor_divide_of_int_eq)
 11.5103 +
 11.5104 +named_theorems real_asymp_preproc
 11.5105 +
 11.5106 +lemmas [real_asymp_preproc] =
 11.5107 +  of_nat_add of_nat_mult of_nat_diff_real of_nat_max_real of_nat_min_real of_nat_power 
 11.5108 +  of_nat_Suc of_nat_numeral
 11.5109 +  of_int_add of_int_mult of_int_diff of_int_minus of_int_max_real of_int_min_real
 11.5110 +  of_int_power of_int_of_nat_eq of_int_numeral real_nat
 11.5111 +
 11.5112 +lemma of_int_mod_real [real_asymp_int_reify]: "of_int (a mod b) = rintmod (of_int a) (of_int b)"
 11.5113 +  by (simp add: rintmod_def)
 11.5114 +
 11.5115 +
 11.5116 +lemma filterlim_of_nat_at_top:
 11.5117 +  "filterlim f F at_top \<Longrightarrow> filterlim (\<lambda>x. f (of_nat x :: real)) F at_top"
 11.5118 +  by (erule filterlim_compose[OF _filterlim_real_sequentially])
 11.5119 +
 11.5120 +lemma asymp_equiv_real_nat_transfer:
 11.5121 +  "f \<sim>[at_top] g \<Longrightarrow> (\<lambda>x. f (of_nat x :: real)) \<sim>[at_top] (\<lambda>x. g (of_nat x))"
 11.5122 +  unfolding asymp_equiv_def by (rule filterlim_of_nat_at_top)
 11.5123 +
 11.5124 +lemma eventually_nat_real:
 11.5125 +  assumes "eventually P (at_top :: real filter)"
 11.5126 +  shows   "eventually (\<lambda>x. P (real x)) (at_top :: nat filter)"
 11.5127 +  using assms filterlim_real_sequentially
 11.5128 +  unfolding filterlim_def le_filter_def eventually_filtermap by auto
 11.5129 +
 11.5130 +lemmas real_asymp_nat_intros =
 11.5131 +  filterlim_of_nat_at_top eventually_nat_real smallo_real_nat_transfer bigo_real_nat_transfer
 11.5132 +  smallomega_real_nat_transfer bigomega_real_nat_transfer bigtheta_real_nat_transfer
 11.5133 +  asymp_equiv_real_nat_transfer
 11.5134 +
 11.5135 +
 11.5136 +lemma filterlim_of_int_at_top:
 11.5137 +  "filterlim f F at_top \<Longrightarrow> filterlim (\<lambda>x. f (of_int x :: real)) F at_top"
 11.5138 +  by (erule filterlim_compose[OF _ filterlim_real_of_int_at_top])
 11.5139 +
 11.5140 +(* TODO Move *)
 11.5141 +lemma filterlim_real_of_int_at_bot [tendsto_intros]:
 11.5142 +  "filterlim real_of_int at_bot at_bot"
 11.5143 +  unfolding filterlim_at_bot
 11.5144 +proof
 11.5145 +  fix C :: real
 11.5146 +  show "eventually (\<lambda>n. real_of_int n \<le> C) at_bot"
 11.5147 +    using eventually_le_at_bot[of "\<lfloor>C\<rfloor>"] by eventually_elim linarith
 11.5148 +qed
 11.5149 +
 11.5150 +lemma filterlim_of_int_at_bot:
 11.5151 +  "filterlim f F at_bot \<Longrightarrow> filterlim (\<lambda>x. f (of_int x :: real)) F at_bot"
 11.5152 +  by (erule filterlim_compose[OF _ filterlim_real_of_int_at_bot])
 11.5153 +find_theorems of_int at_bot
 11.5154 +
 11.5155 +lemma asymp_equiv_real_int_transfer_at_top:
 11.5156 +  "f \<sim>[at_top] g \<Longrightarrow> (\<lambda>x. f (of_int x :: real)) \<sim>[at_top] (\<lambda>x. g (of_int x))"
 11.5157 +  unfolding asymp_equiv_def by (rule filterlim_of_int_at_top)
 11.5158 +
 11.5159 +lemma asymp_equiv_real_int_transfer_at_bot:
 11.5160 +  "f \<sim>[at_bot] g \<Longrightarrow> (\<lambda>x. f (of_int x :: real)) \<sim>[at_bot] (\<lambda>x. g (of_int x))"
 11.5161 +  unfolding asymp_equiv_def by (rule filterlim_of_int_at_bot)
 11.5162 +
 11.5163 +lemma eventually_int_real_at_top:
 11.5164 +  assumes "eventually P (at_top :: real filter)"
 11.5165 +  shows   "eventually (\<lambda>x. P (of_int x)) (at_top :: int filter)"
 11.5166 +  using assms filterlim_of_int_at_top filterlim_iff filterlim_real_of_int_at_top by blast
 11.5167 +
 11.5168 +lemma eventually_int_real_at_bot:
 11.5169 +  assumes "eventually P (at_bot :: real filter)"
 11.5170 +  shows   "eventually (\<lambda>x. P (of_int x)) (at_bot :: int filter)"
 11.5171 +  using assms filterlim_of_int_at_bot filterlim_iff filterlim_real_of_int_at_bot by blast
 11.5172 +
 11.5173 +
 11.5174 +lemmas real_asymp_int_intros =
 11.5175 +  filterlim_of_int_at_bot filterlim_of_int_at_top
 11.5176 +  landau_symbols[THEN landau_symbol.compose[OF _ _ filterlim_real_of_int_at_top]]
 11.5177 +  landau_symbols[THEN landau_symbol.compose[OF _ _ filterlim_real_of_int_at_bot]]
 11.5178 +  asymp_equiv_real_int_transfer_at_top asymp_equiv_real_int_transfer_at_bot
 11.5179 +
 11.5180 +(* TODO: Move? *)
 11.5181 +lemma tendsto_discrete_iff:
 11.5182 +  "filterlim f (nhds (c :: 'a :: discrete_topology)) F \<longleftrightarrow> eventually (\<lambda>x. f x = c) F"
 11.5183 +  by (auto simp: nhds_discrete filterlim_principal)
 11.5184 +
 11.5185 +lemma tendsto_of_nat_iff:
 11.5186 +  "filterlim (\<lambda>n. of_nat (f n)) (nhds (of_nat c :: 'a :: real_normed_div_algebra)) F \<longleftrightarrow>
 11.5187 +     eventually (\<lambda>n. f n = c) F"
 11.5188 +proof
 11.5189 +  assume "((\<lambda>n. of_nat (f n)) \<longlongrightarrow> (of_nat c :: 'a)) F"
 11.5190 +  hence "eventually (\<lambda>n. \<bar>real (f n) - real c\<bar> < 1/2) F"
 11.5191 +    by (force simp: tendsto_iff dist_of_nat dest: spec[of _ "1/2"])
 11.5192 +  thus "eventually (\<lambda>n. f n = c) F"
 11.5193 +    by eventually_elim (simp add: abs_if split: if_splits)
 11.5194 +next
 11.5195 +  assume "eventually (\<lambda>n. f n = c) F"
 11.5196 +  hence "eventually (\<lambda>n. of_nat (f n) = (of_nat c :: 'a)) F"
 11.5197 +    by eventually_elim simp
 11.5198 +  thus "filterlim (\<lambda>n. of_nat (f n)) (nhds (of_nat c :: 'a)) F"
 11.5199 +    by (rule Lim_eventually)
 11.5200 +qed
 11.5201 +
 11.5202 +lemma tendsto_of_int_iff:
 11.5203 +  "filterlim (\<lambda>n. of_int (f n)) (nhds (of_int c :: 'a :: real_normed_div_algebra)) F \<longleftrightarrow>
 11.5204 +     eventually (\<lambda>n. f n = c) F"
 11.5205 +proof
 11.5206 +  assume "((\<lambda>n. of_int (f n)) \<longlongrightarrow> (of_int c :: 'a)) F"
 11.5207 +  hence "eventually (\<lambda>n. \<bar>real_of_int (f n) - of_int c\<bar> < 1/2) F"
 11.5208 +    by (force simp: tendsto_iff dist_of_int dest: spec[of _ "1/2"])
 11.5209 +  thus "eventually (\<lambda>n. f n = c) F"
 11.5210 +    by eventually_elim (simp add: abs_if split: if_splits)
 11.5211 +next
 11.5212 +  assume "eventually (\<lambda>n. f n = c) F"
 11.5213 +  hence "eventually (\<lambda>n. of_int (f n) = (of_int c :: 'a)) F"
 11.5214 +    by eventually_elim simp
 11.5215 +  thus "filterlim (\<lambda>n. of_int (f n)) (nhds (of_int c :: 'a)) F"
 11.5216 +    by (rule Lim_eventually)
 11.5217 +qed
 11.5218 +
 11.5219 +lemma filterlim_at_top_int_iff_filterlim_real:
 11.5220 +  "filterlim f at_top F \<longleftrightarrow> filterlim (\<lambda>x. real_of_int (f x)) at_top F" (is "?lhs = ?rhs")
 11.5221 +proof
 11.5222 +  assume ?rhs
 11.5223 +  hence "filterlim (\<lambda>x. floor (real_of_int (f x))) at_top F"
 11.5224 +    by (intro filterlim_compose[OF filterlim_floor_sequentially])
 11.5225 +  also have "?this \<longleftrightarrow> ?lhs" by (intro filterlim_cong refl) auto
 11.5226 +  finally show ?lhs .
 11.5227 +qed (auto intro: filterlim_compose[OF filterlim_real_of_int_at_top])
 11.5228 +
 11.5229 +lemma filterlim_floor_at_bot: "filterlim (floor :: real \<Rightarrow> int) at_bot at_bot"
 11.5230 +proof (subst filterlim_at_bot, rule allI)
 11.5231 +  fix C :: int show "eventually (\<lambda>x::real. \<lfloor>x\<rfloor> \<le> C) at_bot"
 11.5232 +    using eventually_le_at_bot[of "real_of_int C"] by eventually_elim linarith
 11.5233 +qed
 11.5234 +
 11.5235 +lemma filterlim_at_bot_int_iff_filterlim_real:
 11.5236 +  "filterlim f at_bot F \<longleftrightarrow> filterlim (\<lambda>x. real_of_int (f x)) at_bot F" (is "?lhs = ?rhs")
 11.5237 +proof
 11.5238 +  assume ?rhs
 11.5239 +  hence "filterlim (\<lambda>x. floor (real_of_int (f x))) at_bot F"
 11.5240 +    by (intro filterlim_compose[OF filterlim_floor_at_bot])
 11.5241 +  also have "?this \<longleftrightarrow> ?lhs" by (intro filterlim_cong refl) auto
 11.5242 +  finally show ?lhs .
 11.5243 +qed (auto intro: filterlim_compose[OF filterlim_real_of_int_at_bot])
 11.5244 +(* END TODO *)
 11.5245 +
 11.5246 +
 11.5247 +lemma real_asymp_real_nat_transfer:
 11.5248 +  "filterlim (\<lambda>n. real (f n)) at_top F \<Longrightarrow> filterlim f at_top F"
 11.5249 +  "filterlim (\<lambda>n. real (f n)) (nhds (real c)) F \<Longrightarrow> eventually (\<lambda>n. f n = c) F"
 11.5250 +  "eventually (\<lambda>n. real (f n) \<le> real (g n)) F \<Longrightarrow> eventually (\<lambda>n. f n \<le> g n) F"
 11.5251 +  "eventually (\<lambda>n. real (f n) < real (g n)) F \<Longrightarrow> eventually (\<lambda>n. f n < g n) F"
 11.5252 +  by (simp_all add: filterlim_sequentially_iff_filterlim_real tendsto_of_nat_iff)
 11.5253 +
 11.5254 +lemma real_asymp_real_int_transfer:
 11.5255 +  "filterlim (\<lambda>n. real_of_int (f n)) at_top F \<Longrightarrow> filterlim f at_top F"
 11.5256 +  "filterlim (\<lambda>n. real_of_int (f n)) at_bot F \<Longrightarrow> filterlim f at_bot F"
 11.5257 +  "filterlim (\<lambda>n. real_of_int (f n)) (nhds (of_int c)) F \<Longrightarrow> eventually (\<lambda>n. f n = c) F"
 11.5258 +  "eventually (\<lambda>n. real_of_int (f n) \<le> real_of_int (g n)) F \<Longrightarrow> eventually (\<lambda>n. f n \<le> g n) F"
 11.5259 +  "eventually (\<lambda>n. real_of_int (f n) < real_of_int (g n)) F \<Longrightarrow> eventually (\<lambda>n. f n < g n) F"
 11.5260 +  by (simp_all add: tendsto_of_int_iff filterlim_at_top_int_iff_filterlim_real
 11.5261 +                    filterlim_at_bot_int_iff_filterlim_real)
 11.5262 +  
 11.5263 +
 11.5264 +lemma eventually_at_left_at_right_imp_at:
 11.5265 +  "eventually P (at_left a) \<Longrightarrow> eventually P (at_right a) \<Longrightarrow> eventually P (at (a::real))"
 11.5266 +  by (simp add: eventually_at_split)
 11.5267 +
 11.5268 +lemma filtermap_at_left_shift: "filtermap (\<lambda>x. x - d) (at_left a) = at_left (a - d)"
 11.5269 +  for a d :: "real"
 11.5270 +  by (simp add: filter_eq_iff eventually_filtermap eventually_at_filter filtermap_nhds_shift[symmetric])
 11.5271 +    
 11.5272 +lemma at_left_to_0: "at_left a = filtermap (\<lambda>x. x + a) (at_left 0)"
 11.5273 +  for a :: real using filtermap_at_left_shift[of "-a" 0] by simp
 11.5274 +    
 11.5275 +lemma filterlim_at_leftI: 
 11.5276 +  assumes "filterlim (\<lambda>x. f x - c) (at_left 0) F"
 11.5277 +  shows   "filterlim f (at_left (c::real)) F"
 11.5278 +proof -
 11.5279 +  from assms have "filtermap (\<lambda>x. f x - c) F \<le> at_left 0" by (simp add: filterlim_def)
 11.5280 +  hence "filtermap (\<lambda>x. x + c) (filtermap (\<lambda>x. f x - c) F) \<le> filtermap (\<lambda>x. x + c) (at_left 0)"
 11.5281 +    by (rule filtermap_mono)
 11.5282 +  thus ?thesis by (subst at_left_to_0) (simp_all add: filterlim_def filtermap_filtermap)
 11.5283 +qed
 11.5284 +
 11.5285 +lemma filterlim_at_rightI: 
 11.5286 +  assumes "filterlim (\<lambda>x. f x - c) (at_right 0) F"
 11.5287 +  shows   "filterlim f (at_right (c::real)) F"
 11.5288 +proof -
 11.5289 +  from assms have "filtermap (\<lambda>x. f x - c) F \<le> at_right 0" by (simp add: filterlim_def)
 11.5290 +  hence "filtermap (\<lambda>x. x + c) (filtermap (\<lambda>x. f x - c) F) \<le> filtermap (\<lambda>x. x + c) (at_right 0)"
 11.5291 +    by (rule filtermap_mono)
 11.5292 +  thus ?thesis by (subst at_right_to_0) (simp_all add: filterlim_def filtermap_filtermap)
 11.5293 +qed
 11.5294 +
 11.5295 +lemma filterlim_atI':
 11.5296 +  assumes "filterlim (\<lambda>x. f x - c) (at 0) F"
 11.5297 +  shows   "filterlim f (at (c::real)) F"
 11.5298 +proof -
 11.5299 +  from assms have "filtermap (\<lambda>x. f x - c) F \<le> at 0" by (simp add: filterlim_def)
 11.5300 +  hence "filtermap (\<lambda>x. x + c) (filtermap (\<lambda>x. f x - c) F) \<le> filtermap (\<lambda>x. x + c) (at 0)"
 11.5301 +    by (rule filtermap_mono)
 11.5302 +  thus ?thesis by (subst at_to_0) (simp_all add: filterlim_def filtermap_filtermap)
 11.5303 +qed
 11.5304 +
 11.5305 +lemma gbinomial_series_aux_altdef:
 11.5306 +  "gbinomial_series_aux False x n acc =
 11.5307 +     MSLCons acc (gbinomial_series_aux False x (n + 1) ((x - n) / (n + 1) * acc))"
 11.5308 +  "gbinomial_series_aux True x n acc =
 11.5309 +     (if acc = 0 then MSLNil else 
 11.5310 +        MSLCons acc (gbinomial_series_aux True x (n + 1) ((x - n) / (n + 1) * acc)))"
 11.5311 +  by (subst gbinomial_series_aux.code, simp)+
 11.5312 +
 11.5313 +
 11.5314 +
 11.5315 +subsection \<open>Proof method setup\<close>
 11.5316 +
 11.5317 +text \<open>
 11.5318 +  The following theorem collection is the list of rewrite equations to be used by the
 11.5319 +  lazy evaluation package. If something is missing here, normalisation of terms into
 11.5320 +  head normal form will fail.
 11.5321 +\<close>
 11.5322 +
 11.5323 +named_theorems real_asymp_eval_eqs
 11.5324 +
 11.5325 +lemmas [real_asymp_eval_eqs] =
 11.5326 +  msllist.sel fst_conv snd_conv CMP_BRANCH.simps plus_ms.simps minus_ms_altdef 
 11.5327 +  minus_ms_aux_MSLNil_left minus_ms_aux_MSLNil_right minus_ms_aux_MSLCons_eval times_ms.simps
 11.5328 +  uminus_ms.simps divide_ms.simps inverse_ms.simps inverse_ms_aux_MSLCons const_expansion_ms_eval
 11.5329 +  const_expansion_real_def times_ms_aux_MSLNil times_ms_aux_MSLCons_eval scale_shift_ms_aux_MSLCons_eval 
 11.5330 +  scale_shift_ms_aux_MSLNil uminus_ms_aux_MSLCons_eval uminus_ms_aux_MSLNil 
 11.5331 +  scale_ms_aux_MSLNil scale_ms_aux_MSLCons scale_ms_def shift_ms_aux_MSLNil shift_ms_aux_MSLCons
 11.5332 +  scale_ms_aux'_MSLNil scale_ms_aux'_MSLCons exp_series_stream_def exp_series_stream_aux.code
 11.5333 +  plus_ms_aux_MSLNil plus_ms_aux_MSLCons_eval map_ms_altdef map_ms_aux_MSLCons
 11.5334 +  map_ms_aux_MSLNil lift_ms_simps powser_ms_aux_MSLNil powser_ms_aux_MSLCons
 11.5335 +  ln_series_stream_aux_code gbinomial_series_def gbinomial_series_aux_altdef
 11.5336 +  mssalternate.code powr_expansion_ms.simps powr_expansion_real_def powr_ms_aux_MSLCons
 11.5337 +  power_expansion_ms.simps power_expansion_real_def power_ms_aux_MSLCons
 11.5338 +  powser_ms_aux'_MSSCons sin_ms_aux'_altdef cos_ms_aux'_altdef const_ms_aux_def
 11.5339 +  compare_expansions_MSLCons_eval compare_expansions_real zero_expansion_ms_def
 11.5340 +  zero_expansion_real_def sin_series_stream_def cos_series_stream_def arctan_series_stream_def
 11.5341 +  arctan_ms_aux_def sin_series_stream_aux_code arctan_series_stream_aux_code if_True if_False
 11.5342 +                                               
 11.5343 +text \<open>
 11.5344 +  The following constant and theorem collection exist in order to register constructors for
 11.5345 +  lazy evaluation. All constants marked in such a way will be passed to the lazy evaluation
 11.5346 +  package as free constructors upon which pattern-matching can be done.
 11.5347 +\<close>
 11.5348 +definition REAL_ASYMP_EVAL_CONSTRUCTOR :: "'a \<Rightarrow> bool"
 11.5349 +  where [simp]: "REAL_ASYMP_EVAL_CONSTRUCTOR x = True"
 11.5350 +
 11.5351 +named_theorems exp_log_eval_constructor
 11.5352 +
 11.5353 +lemma exp_log_eval_constructors [exp_log_eval_constructor]:
 11.5354 +  "REAL_ASYMP_EVAL_CONSTRUCTOR MSLNil"
 11.5355 +  "REAL_ASYMP_EVAL_CONSTRUCTOR MSLCons"
 11.5356 +  "REAL_ASYMP_EVAL_CONSTRUCTOR MSSCons"
 11.5357 +  "REAL_ASYMP_EVAL_CONSTRUCTOR LT"
 11.5358 +  "REAL_ASYMP_EVAL_CONSTRUCTOR EQ"
 11.5359 +  "REAL_ASYMP_EVAL_CONSTRUCTOR GT"
 11.5360 +  "REAL_ASYMP_EVAL_CONSTRUCTOR Pair"
 11.5361 +  "REAL_ASYMP_EVAL_CONSTRUCTOR True"
 11.5362 +  "REAL_ASYMP_EVAL_CONSTRUCTOR False"
 11.5363 +  "REAL_ASYMP_EVAL_CONSTRUCTOR MS"
 11.5364 +  by simp_all
 11.5365 +
 11.5366 +text \<open>
 11.5367 +  The following constant exists in order to mark functions as having plug-in support
 11.5368 +  for multiseries expansions (i.\,e.\ this can be used to add support for arbitrary functions
 11.5369 +  later on)
 11.5370 +\<close>
 11.5371 +definition REAL_ASYMP_CUSTOM :: "'a \<Rightarrow> bool"
 11.5372 +  where [simp]: "REAL_ASYMP_CUSTOM x = True"
 11.5373 +
 11.5374 +lemmas [simp del] = ms.map inverse_ms_aux.simps divide_ms.simps
 11.5375 +
 11.5376 +definition expansion_with_remainder_term :: "(real \<Rightarrow> real) \<Rightarrow> (real \<Rightarrow> real) set \<Rightarrow> bool" where
 11.5377 +  "expansion_with_remainder_term _ _ = True"
 11.5378 +
 11.5379 +notation (output) expansion_with_remainder_term (infixl "+" 10)
 11.5380 +
 11.5381 +ML_file \<open>asymptotic_basis.ML\<close>
 11.5382 +ML_file \<open>exp_log_expression.ML\<close>
 11.5383 +ML_file \<open>expansion_interface.ML\<close>
 11.5384 +ML_file \<open>multiseries_expansion.ML\<close>
 11.5385 +ML_file \<open>real_asymp.ML\<close>
 11.5386 +
 11.5387 +method_setup real_asymp = 
 11.5388 +  \<open>(Scan.lift (Scan.optional (Args.parens (Args.$$$ "verbose") >> K true) false) --|
 11.5389 +    Method.sections Simplifier.simp_modifiers) >> 
 11.5390 +     (fn verbose => fn ctxt => SIMPLE_METHOD' (Real_Asymp_Basic.tac verbose ctxt))\<close>
 11.5391 +  "Semi-automatic decision procedure for asymptotics of exp-log functions"
 11.5392 +
 11.5393 +end
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/HOL/Real_Asymp/Multiseries_Expansion_Bounds.thy	Sun Jul 15 14:46:57 2018 +0200
    12.3 @@ -0,0 +1,699 @@
    12.4 +section \<open>Asymptotic real interval arithmetic\<close>
    12.5 +(*
    12.6 +  File:     Multiseries_Expansion_Bounds.thy
    12.7 +  Author:   Manuel Eberl, TU München
    12.8 +
    12.9 +  Automatic computation of upper and lower expansions for real-valued functions.
   12.10 +  Allows limited handling of functions involving oscillating functions like sin, cos, floor, etc.
   12.11 +*)
   12.12 +theory Multiseries_Expansion_Bounds
   12.13 +imports
   12.14 +  Multiseries_Expansion
   12.15 +begin
   12.16 +
   12.17 +lemma expands_to_cong_reverse:
   12.18 +  "eventually (\<lambda>x. f x = g x) at_top \<Longrightarrow> (g expands_to F) bs \<Longrightarrow> (f expands_to F) bs"
   12.19 +  using expands_to_cong[of g F bs f] by (simp add: eq_commute)
   12.20 +
   12.21 +lemma expands_to_trivial_bounds: "(f expands_to F) bs \<Longrightarrow> eventually (\<lambda>x. f x \<in> {f x..f x}) at_top"
   12.22 +  by simp
   12.23 +
   12.24 +lemma eventually_in_atLeastAtMostI:
   12.25 +  assumes "eventually (\<lambda>x. f x \<ge> l x) at_top" "eventually (\<lambda>x. f x \<le> u x) at_top"
   12.26 +  shows   "eventually (\<lambda>x. f x \<in> {l x..u x}) at_top"
   12.27 +  using assms by eventually_elim simp_all
   12.28 +
   12.29 +lemma tendsto_sandwich':
   12.30 +  fixes l f u :: "'a \<Rightarrow> 'b :: order_topology"
   12.31 +  shows "eventually (\<lambda>x. l x \<le> f x) F \<Longrightarrow> eventually (\<lambda>x. f x \<le> u x) F \<Longrightarrow>
   12.32 +           (l \<longlongrightarrow> L1) F \<Longrightarrow> (u \<longlongrightarrow> L2) F \<Longrightarrow> L1 = L2 \<Longrightarrow> (f \<longlongrightarrow> L1) F"
   12.33 +  using tendsto_sandwich[of l f F u L1] by simp
   12.34 +
   12.35 +(* TODO: Move? *)
   12.36 +lemma filterlim_at_bot_mono:
   12.37 +  fixes l f u :: "'a \<Rightarrow> 'b :: linorder_topology"
   12.38 +  assumes "filterlim u at_bot F" and "eventually (\<lambda>x. f x \<le> u x) F"
   12.39 +  shows   "filterlim f at_bot F"
   12.40 +  unfolding filterlim_at_bot
   12.41 +proof
   12.42 +  fix Z :: 'b
   12.43 +  from assms(1) have "eventually (\<lambda>x. u x \<le> Z) F" by (auto simp: filterlim_at_bot)
   12.44 +  with assms(2) show "eventually (\<lambda>x. f x \<le> Z) F" by eventually_elim simp
   12.45 +qed
   12.46 +
   12.47 +context
   12.48 +begin
   12.49 +
   12.50 +qualified lemma eq_zero_imp_nonneg: "x = (0::real) \<Longrightarrow> x \<ge> 0"
   12.51 +  by simp
   12.52 +
   12.53 +qualified lemma exact_to_bound: "(f expands_to F) bs \<Longrightarrow> eventually (\<lambda>x. f x \<le> f x) at_top"
   12.54 +  by simp
   12.55 +
   12.56 +qualified lemma expands_to_abs_nonneg: "(f expands_to F) bs \<Longrightarrow> eventually (\<lambda>x. abs (f x) \<ge> 0) at_top"
   12.57 +  by simp
   12.58 +
   12.59 +qualified lemma eventually_nonpos_flip: "eventually (\<lambda>x. f x \<le> (0::real)) F \<Longrightarrow> eventually (\<lambda>x. -f x \<ge> 0) F"
   12.60 +  by simp
   12.61 +
   12.62 +qualified lemma bounds_uminus:
   12.63 +  fixes a b :: "real \<Rightarrow> real"
   12.64 +  assumes "eventually (\<lambda>x. a x \<le> b x) at_top"
   12.65 +  shows   "eventually (\<lambda>x. -b x \<le> -a x) at_top"
   12.66 +  using assms by eventually_elim simp
   12.67 +
   12.68 +qualified lemma
   12.69 +  fixes a b c d :: "real \<Rightarrow> real"
   12.70 +  assumes "eventually (\<lambda>x. a x \<le> b x) at_top" "eventually (\<lambda>x. c x \<le> d x) at_top"
   12.71 +  shows   combine_bounds_add:  "eventually (\<lambda>x. a x + c x \<le> b x + d x) at_top"
   12.72 +    and   combine_bounds_diff: "eventually (\<lambda>x. a x - d x \<le> b x - c x) at_top"
   12.73 +  by (use assms in eventually_elim; simp add: add_mono diff_mono)+
   12.74 +
   12.75 +qualified lemma
   12.76 +  fixes a b c d :: "real \<Rightarrow> real"
   12.77 +  assumes "eventually (\<lambda>x. a x \<le> b x) at_top" "eventually (\<lambda>x. c x \<le> d x) at_top"
   12.78 +  shows   combine_bounds_min: "eventually (\<lambda>x. min (a x) (c x) \<le> min (b x) (d x)) at_top"
   12.79 +    and   combine_bounds_max: "eventually (\<lambda>x. max (a x) (c x) \<le> max (b x) (d x)) at_top"
   12.80 +  by (blast intro: eventually_elim2[OF assms] min.mono max.mono)+
   12.81 +
   12.82 +
   12.83 +qualified lemma trivial_bounds_sin:  "\<forall>x::real. sin x \<in> {-1..1}"
   12.84 +  and trivial_bounds_cos:  "\<forall>x::real. cos x \<in> {-1..1}"
   12.85 +  and trivial_bounds_frac: "\<forall>x::real. frac x \<in> {0..1}"
   12.86 +  by (auto simp: less_imp_le[OF frac_lt_1])
   12.87 +
   12.88 +qualified lemma trivial_boundsI:
   12.89 +  fixes f g:: "real \<Rightarrow> real"
   12.90 +  assumes "\<forall>x. f x \<in> {l..u}" and "g \<equiv> g"
   12.91 +  shows   "eventually (\<lambda>x. f (g x) \<ge> l) at_top" "eventually (\<lambda>x. f (g x) \<le> u) at_top"
   12.92 +  using assms by auto
   12.93 +
   12.94 +qualified lemma
   12.95 +  fixes f f' :: "real \<Rightarrow> real"
   12.96 +  shows transfer_lower_bound:
   12.97 +          "eventually (\<lambda>x. g x \<ge> l x) at_top \<Longrightarrow> f \<equiv> g \<Longrightarrow> eventually (\<lambda>x. f x \<ge> l x) at_top"
   12.98 +  and   transfer_upper_bound:
   12.99 +          "eventually (\<lambda>x. g x \<le> u x) at_top \<Longrightarrow> f \<equiv> g \<Longrightarrow> eventually (\<lambda>x. f x \<le> u x) at_top"
  12.100 +  by simp_all  
  12.101 +
  12.102 +qualified lemma mono_bound:
  12.103 +  fixes f g h :: "real \<Rightarrow> real"
  12.104 +  assumes "mono h" "eventually (\<lambda>x. f x \<le> g x) at_top"
  12.105 +  shows   "eventually (\<lambda>x. h (f x) \<le> h (g x)) at_top"
  12.106 +  by (intro eventually_mono[OF assms(2)] monoD[OF assms(1)])
  12.107 +
  12.108 +qualified lemma
  12.109 +  fixes f l :: "real \<Rightarrow> real"
  12.110 +  assumes "(l expands_to L) bs" "trimmed_pos L" "basis_wf bs" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.111 +  shows   expands_to_lb_ln: "eventually (\<lambda>x. ln (l x) \<le> ln (f x)) at_top"
  12.112 +    and   expands_to_ub_ln: 
  12.113 +            "eventually (\<lambda>x. f x \<le> u x) at_top \<Longrightarrow> eventually (\<lambda>x. ln (f x) \<le> ln (u x)) at_top"
  12.114 +proof -
  12.115 +  from assms(3,1,2) have pos: "eventually (\<lambda>x. l x > 0) at_top"
  12.116 +    by (rule expands_to_imp_eventually_pos)  
  12.117 +  from pos and assms(4)
  12.118 +    show "eventually (\<lambda>x. ln (l x) \<le> ln (f x)) at_top" by eventually_elim simp
  12.119 +  assume "eventually (\<lambda>x. f x \<le> u x) at_top"
  12.120 +  with pos and assms(4) show "eventually (\<lambda>x. ln (f x) \<le> ln (u x)) at_top"
  12.121 +    by eventually_elim simp
  12.122 +qed
  12.123 +
  12.124 +qualified lemma eventually_sgn_ge_1D:
  12.125 +  assumes "eventually (\<lambda>x::real. sgn (f x) \<ge> l x) at_top"
  12.126 +          "(l expands_to (const_expansion 1 :: 'a :: multiseries)) bs"
  12.127 +  shows   "((\<lambda>x. sgn (f x)) expands_to (const_expansion 1 :: 'a)) bs"
  12.128 +proof (rule expands_to_cong)
  12.129 +  from assms(2) have "eventually (\<lambda>x. l x = 1) at_top"
  12.130 +    by (simp add: expands_to.simps)
  12.131 +  with assms(1) show "eventually (\<lambda>x. 1 = sgn (f x)) at_top"
  12.132 +    by eventually_elim (auto simp: sgn_if split: if_splits)
  12.133 +qed (insert assms, auto simp: expands_to.simps)
  12.134 +
  12.135 +qualified lemma eventually_sgn_le_neg1D:
  12.136 +  assumes "eventually (\<lambda>x::real. sgn (f x) \<le> u x) at_top"
  12.137 +          "(u expands_to (const_expansion (-1) :: 'a :: multiseries)) bs"
  12.138 +  shows   "((\<lambda>x. sgn (f x)) expands_to (const_expansion (-1) :: 'a)) bs"
  12.139 +proof (rule expands_to_cong)
  12.140 +  from assms(2) have "eventually (\<lambda>x. u x = -1) at_top"
  12.141 +    by (simp add: expands_to.simps eq_commute)
  12.142 +  with assms(1) show "eventually (\<lambda>x. -1 = sgn (f x)) at_top"
  12.143 +    by eventually_elim (auto simp: sgn_if split: if_splits)
  12.144 +qed (insert assms, auto simp: expands_to.simps)
  12.145 +
  12.146 +
  12.147 +qualified lemma expands_to_squeeze:
  12.148 +  assumes "eventually (\<lambda>x. l x \<le> f x) at_top" "eventually (\<lambda>x. f x \<le> g x) at_top"
  12.149 +          "(l expands_to L) bs" "(g expands_to L) bs"
  12.150 +  shows   "(f expands_to L) bs"
  12.151 +proof (rule expands_to_cong[OF assms(3)])
  12.152 +  from assms have "eventually (\<lambda>x. eval L x = l x) at_top" "eventually (\<lambda>x. eval L x = g x) at_top"
  12.153 +    by (simp_all add: expands_to.simps)
  12.154 +  with assms(1,2) show "eventually (\<lambda>x. l x = f x) at_top"
  12.155 +    by eventually_elim simp
  12.156 +qed 
  12.157 +
  12.158 +
  12.159 +qualified lemma mono_exp_real: "mono (exp :: real \<Rightarrow> real)"
  12.160 +  by (auto intro!: monoI)
  12.161 +
  12.162 +qualified lemma mono_sgn_real: "mono (sgn :: real \<Rightarrow> real)"
  12.163 +  by (auto intro!: monoI simp: sgn_if)
  12.164 +
  12.165 +qualified lemma mono_arctan_real: "mono (arctan :: real \<Rightarrow> real)"
  12.166 +  by (auto intro!: monoI arctan_monotone')
  12.167 +
  12.168 +qualified lemma mono_root_real: "n \<equiv> n \<Longrightarrow> mono (root n :: real \<Rightarrow> real)"
  12.169 +  by (cases n) (auto simp: mono_def)
  12.170 +
  12.171 +qualified lemma mono_rfloor: "mono rfloor" and mono_rceil: "mono rceil"
  12.172 +  by (auto intro!: monoI simp: rfloor_def floor_mono rceil_def ceiling_mono)
  12.173 +
  12.174 +qualified lemma lower_bound_cong:
  12.175 +  "eventually (\<lambda>x. f x = g x) at_top \<Longrightarrow> eventually (\<lambda>x. l x \<le> g x) at_top \<Longrightarrow>
  12.176 +     eventually (\<lambda>x. l x \<le> f x) at_top"
  12.177 +  by (erule (1) eventually_elim2) simp
  12.178 +
  12.179 +qualified lemma upper_bound_cong:
  12.180 +  "eventually (\<lambda>x. f x = g x) at_top \<Longrightarrow> eventually (\<lambda>x. g x \<le> u x) at_top \<Longrightarrow>
  12.181 +     eventually (\<lambda>x. f x \<le> u x) at_top"
  12.182 +  by (erule (1) eventually_elim2) simp
  12.183 +
  12.184 +qualified lemma
  12.185 +  assumes "eventually (\<lambda>x. f x = (g x :: real)) at_top"
  12.186 +  shows   eventually_eq_min: "eventually (\<lambda>x. min (f x) (g x) = f x) at_top"
  12.187 +    and   eventually_eq_max: "eventually (\<lambda>x. max (f x) (g x) = f x) at_top"
  12.188 +  by (rule eventually_mono[OF assms]; simp)+
  12.189 +
  12.190 +qualified lemma rfloor_bound:
  12.191 +    "eventually (\<lambda>x. l x \<le> f x) at_top \<Longrightarrow> eventually (\<lambda>x. l x - 1 \<le> rfloor (f x)) at_top"
  12.192 +    "eventually (\<lambda>x. f x \<le> u x) at_top \<Longrightarrow> eventually (\<lambda>x. rfloor (f x) \<le> u x) at_top"
  12.193 +  and rceil_bound:
  12.194 +    "eventually (\<lambda>x. l x \<le> f x) at_top \<Longrightarrow> eventually (\<lambda>x. l x \<le> rceil (f x)) at_top"
  12.195 +    "eventually (\<lambda>x. f x \<le> u x) at_top \<Longrightarrow> eventually (\<lambda>x. rceil (f x) \<le> u x + 1) at_top"
  12.196 +  unfolding rfloor_def rceil_def by (erule eventually_mono, linarith)+
  12.197 +
  12.198 +qualified lemma natmod_trivial_lower_bound:
  12.199 +  fixes f g :: "real \<Rightarrow> real"
  12.200 +  assumes "f \<equiv> f" "g \<equiv> g"
  12.201 +  shows "eventually (\<lambda>x. rnatmod (f x) (g x) \<ge> 0) at_top"
  12.202 +  by (simp add: rnatmod_def)
  12.203 +
  12.204 +qualified lemma natmod_upper_bound:
  12.205 +  fixes f g :: "real \<Rightarrow> real"
  12.206 +  assumes "f \<equiv> f" and "eventually (\<lambda>x. l2 x \<le> g x) at_top" and "eventually (\<lambda>x. g x \<le> u2 x) at_top"
  12.207 +  assumes "eventually (\<lambda>x. l2 x - 1 \<ge> 0) at_top"
  12.208 +  shows "eventually (\<lambda>x. rnatmod (f x) (g x) \<le> u2 x - 1) at_top"
  12.209 +  using assms(2-)
  12.210 +proof eventually_elim
  12.211 +  case (elim x)
  12.212 +  have "rnatmod (f x) (g x) = real (nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor>)"
  12.213 +    by (simp add: rnatmod_def)
  12.214 +  also have "nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor> < nat \<lfloor>g x\<rfloor>"
  12.215 +    using elim by (intro mod_less_divisor) auto
  12.216 +  hence "real (nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor>) \<le> u2 x - 1"
  12.217 +    using elim by linarith
  12.218 +  finally show ?case .
  12.219 +qed
  12.220 +
  12.221 +qualified lemma natmod_upper_bound':
  12.222 +  fixes f g :: "real \<Rightarrow> real"
  12.223 +  assumes "g \<equiv> g" "eventually (\<lambda>x. u1 x \<ge> 0) at_top" and "eventually (\<lambda>x. f x \<le> u1 x) at_top"
  12.224 +  shows "eventually (\<lambda>x. rnatmod (f x) (g x) \<le> u1 x) at_top"
  12.225 +  using assms(2-)
  12.226 +proof eventually_elim
  12.227 +  case (elim x)
  12.228 +  have "rnatmod (f x) (g x) = real (nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor>)"
  12.229 +    by (simp add: rnatmod_def)
  12.230 +  also have "nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor> \<le> nat \<lfloor>f x\<rfloor>"
  12.231 +    by auto
  12.232 +  hence "real (nat \<lfloor>f x\<rfloor> mod nat \<lfloor>g x\<rfloor>) \<le> real (nat \<lfloor>f x\<rfloor>)"
  12.233 +    by simp
  12.234 +  also have "\<dots> \<le> u1 x" using elim by linarith
  12.235 +  finally show "rnatmod (f x) (g x) \<le> \<dots>" .
  12.236 +qed
  12.237 +
  12.238 +qualified lemma expands_to_natmod_nonpos:
  12.239 +  fixes f g :: "real \<Rightarrow> real"
  12.240 +  assumes "g \<equiv> g" "eventually (\<lambda>x. u1 x \<le> 0) at_top" "eventually (\<lambda>x. f x \<le> u1 x) at_top"
  12.241 +          "((\<lambda>_. 0) expands_to C) bs"
  12.242 +  shows "((\<lambda>x. rnatmod (f x) (g x)) expands_to C) bs"
  12.243 +  by (rule expands_to_cong[OF assms(4)])
  12.244 +     (insert assms, auto elim: eventually_elim2 simp: rnatmod_def)
  12.245 +  
  12.246 +
  12.247 +qualified lemma eventually_atLeastAtMostI:
  12.248 +  fixes f l r :: "real \<Rightarrow> real"
  12.249 +  assumes "eventually (\<lambda>x. l x \<le> f x) at_top" "eventually (\<lambda>x. f x \<le> u x) at_top"
  12.250 +  shows   "eventually (\<lambda>x. f x \<in> {l x..u x}) at_top"
  12.251 +  using assms by eventually_elim simp
  12.252 +
  12.253 +qualified lemma eventually_atLeastAtMostD:
  12.254 +  fixes f l r :: "real \<Rightarrow> real"
  12.255 +  assumes "eventually (\<lambda>x. f x \<in> {l x..u x}) at_top"
  12.256 +  shows   "eventually (\<lambda>x. l x \<le> f x) at_top" "eventually (\<lambda>x. f x \<le> u x) at_top" 
  12.257 +  using assms by (simp_all add: eventually_conj_iff)
  12.258 +
  12.259 +qualified lemma eventually_0_imp_prod_zero:
  12.260 +  fixes f g :: "real \<Rightarrow> real"
  12.261 +  assumes "eventually (\<lambda>x. f x = 0) at_top"
  12.262 +  shows   "eventually (\<lambda>x. f x * g x = 0) at_top" "eventually (\<lambda>x. g x * f x = 0) at_top"
  12.263 +  by (use assms in eventually_elim; simp)+
  12.264 +
  12.265 +qualified lemma mult_right_bounds:
  12.266 +  fixes f g :: "real \<Rightarrow> real"
  12.267 +  shows "\<forall>x. f x \<in> {l x..u x} \<longrightarrow> g x \<ge> 0 \<longrightarrow> f x * g x \<in> {l x * g x..u x * g x}"
  12.268 +    and "\<forall>x. f x \<in> {l x..u x} \<longrightarrow> g x \<le> 0 \<longrightarrow> f x * g x \<in> {u x * g x..l x * g x}"
  12.269 +  by (auto intro: mult_right_mono mult_right_mono_neg)
  12.270 +
  12.271 +qualified lemma mult_left_bounds:
  12.272 +  fixes f g :: "real \<Rightarrow> real"
  12.273 +  shows "\<forall>x. g x \<in> {l x..u x} \<longrightarrow> f x \<ge> 0 \<longrightarrow> f x * g x \<in> {f x * l x..f x * u x}"
  12.274 +    and "\<forall>x. g x \<in> {l x..u x} \<longrightarrow> f x \<le> 0 \<longrightarrow> f x * g x \<in> {f x * u x..f x * l x}"
  12.275 +  by (auto intro: mult_left_mono mult_left_mono_neg)
  12.276 +
  12.277 +qualified lemma mult_mono_nonpos_nonneg:
  12.278 +  "a \<le> c \<Longrightarrow> d \<le> b \<Longrightarrow> a \<le> 0 \<Longrightarrow> d \<ge> 0 \<Longrightarrow> a * b \<le> c * (d :: 'a :: linordered_ring)"
  12.279 +  using mult_mono[of "-c" "-a" d b] by simp
  12.280 +
  12.281 +qualified lemma mult_mono_nonneg_nonpos:
  12.282 +  "c \<le> a \<Longrightarrow> b \<le> d \<Longrightarrow> a \<ge> 0 \<Longrightarrow> d \<le> 0 \<Longrightarrow> a * b \<le> c * (d :: 'a :: {comm_ring, linordered_ring})"
  12.283 +  using mult_mono[of c a "-d" "-b"] by (simp add: mult.commute)
  12.284 +
  12.285 +qualified lemma mult_mono_nonpos_nonpos:
  12.286 +  "c \<le> a \<Longrightarrow> d \<le> b \<Longrightarrow> c \<le> 0 \<Longrightarrow> b \<le> 0 \<Longrightarrow> a * b \<le> c * (d :: 'a :: linordered_ring)"
  12.287 +  using mult_mono[of "-a" "-c" "-b" "-d"] by simp
  12.288 +
  12.289 +qualified lemmas mult_monos =
  12.290 +  mult_mono mult_mono_nonpos_nonneg mult_mono_nonneg_nonpos mult_mono_nonpos_nonpos
  12.291 +
  12.292 +
  12.293 +qualified lemma mult_bounds_real:
  12.294 +  fixes f g l1 u1 l2 u2 l u :: "real \<Rightarrow> real"
  12.295 +  defines "P \<equiv> \<lambda>l u x. f x \<in> {l1 x..u1 x} \<longrightarrow> g x \<in> {l2 x..u2 x} \<longrightarrow> f x * g x \<in> {l..u}"
  12.296 +  shows   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x * l2 x) (u1 x * u2 x) x"
  12.297 +    and   "\<forall>x. u1 x \<le> 0 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x * u2 x) (u1 x * l2 x) x"
  12.298 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x * l2 x) (l1 x * u2 x) x"
  12.299 +    and   "\<forall>x. u1 x \<le> 0 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x * u2 x) (l1 x * l2 x) x"
  12.300 +
  12.301 +    and   "\<forall>x. l1 x \<le> 0 \<longrightarrow> u1 x \<ge> 0 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x * u2 x) (u1 x * u2 x) x"
  12.302 +    and   "\<forall>x. l1 x \<le> 0 \<longrightarrow> u1 x \<ge> 0 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x * l2 x) (l1 x * l2 x) x"
  12.303 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> P (u1 x * l2 x) (u1 x * u2 x) x"
  12.304 +    and   "\<forall>x. u1 x \<le> 0 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> P (l1 x * u2 x) (l1 x * l2 x) x"
  12.305 +
  12.306 +    and   "\<forall>x. l1 x \<le> 0 \<longrightarrow> u1 x \<ge> 0 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> l x \<le> l1 x * u2 x \<longrightarrow>
  12.307 +             l x \<le> u1 x * l2 x \<longrightarrow> u x \<ge> l1 x* l2 x \<longrightarrow> u x \<ge> u1 x * u2 x \<longrightarrow> P (l x) (u x) x"
  12.308 +proof goal_cases
  12.309 +  case 1
  12.310 +  show ?case by (auto intro: mult_mono simp: P_def)
  12.311 +next
  12.312 +  case 2
  12.313 +  show ?case by (auto intro: mult_monos(2) simp: P_def)
  12.314 +next
  12.315 +  case 3
  12.316 +  show ?case unfolding P_def
  12.317 +    by (subst (1 2 3) mult.commute) (auto intro: mult_monos(2) simp: P_def)
  12.318 +next
  12.319 +  case 4
  12.320 +  show ?case by (auto intro: mult_monos(4) simp: P_def)
  12.321 +next
  12.322 +  case 5
  12.323 +  show ?case by (auto intro: mult_monos(1,2) simp: P_def)
  12.324 +next
  12.325 +  case 6
  12.326 +  show ?case by (auto intro: mult_monos(3,4) simp: P_def)
  12.327 +next
  12.328 +  case 7
  12.329 +  show ?case unfolding P_def
  12.330 +    by (subst (1 2 3) mult.commute) (auto intro: mult_monos(1,2))
  12.331 +next
  12.332 +  case 8
  12.333 +  show ?case unfolding P_def
  12.334 +    by (subst (1 2 3) mult.commute) (auto intro: mult_monos(3,4))
  12.335 +next
  12.336 +  case 9
  12.337 +  show ?case
  12.338 +  proof (safe, goal_cases)
  12.339 +    case (1 x)
  12.340 +    from 1(1-4) show ?case unfolding P_def
  12.341 +      by (cases "f x \<ge> 0"; cases "g x \<ge> 0";
  12.342 +          fastforce intro: mult_monos 1(5,6)[THEN order.trans] 1(7,8)[THEN order.trans[rotated]])
  12.343 +  qed
  12.344 +qed
  12.345 +
  12.346 +
  12.347 +qualified lemma powr_bounds_real:
  12.348 +  fixes f g l1 u1 l2 u2 l u :: "real \<Rightarrow> real"
  12.349 +  defines "P \<equiv> \<lambda>l u x. f x \<in> {l1 x..u1 x} \<longrightarrow> g x \<in> {l2 x..u2 x} \<longrightarrow> f x powr g x \<in> {l..u}"
  12.350 +  shows   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l1 x \<ge> 1 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x powr l2 x) (u1 x powr u2 x) x"
  12.351 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> u1 x \<le> 1 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x powr u2 x) (u1 x powr l2 x) x"
  12.352 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l1 x \<ge> 1 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x powr l2 x) (l1 x powr u2 x) x"
  12.353 +    and   "\<forall>x. l1 x > 0 \<longrightarrow> u1 x \<le> 1 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x powr u2 x) (l1 x powr l2 x) x"
  12.354 +
  12.355 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l1 x \<le> 1 \<longrightarrow> u1 x \<ge> 1 \<longrightarrow> l2 x \<ge> 0 \<longrightarrow> P (l1 x powr u2 x) (u1 x powr u2 x) x"
  12.356 +    and   "\<forall>x. l1 x > 0 \<longrightarrow> l1 x \<le> 1 \<longrightarrow> u1 x \<ge> 1 \<longrightarrow> u2 x \<le> 0 \<longrightarrow> P (u1 x powr l2 x) (l1 x powr l2 x) x"
  12.357 +    and   "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l1 x \<ge> 1 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> P (u1 x powr l2 x) (u1 x powr u2 x) x"
  12.358 +    and   "\<forall>x. l1 x > 0 \<longrightarrow> u1 x \<le> 1 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> P (l1 x powr u2 x) (l1 x powr l2 x) x"
  12.359 +
  12.360 +    and   "\<forall>x. l1 x > 0 \<longrightarrow> l1 x \<le> 1 \<longrightarrow> u1 x \<ge> 1 \<longrightarrow> l2 x \<le> 0 \<longrightarrow> u2 x \<ge> 0 \<longrightarrow> l x \<le> l1 x powr u2 x \<longrightarrow>
  12.361 +             l x \<le> u1 x powr l2 x \<longrightarrow> u x \<ge> l1 x powr l2 x \<longrightarrow> u x \<ge> u1 x powr u2 x \<longrightarrow> P (l x) (u x) x"
  12.362 +proof goal_cases
  12.363 +  case 1
  12.364 +  show ?case by (auto simp: P_def powr_def intro: mult_monos)
  12.365 +next
  12.366 +  case 2
  12.367 +  show ?case by (auto simp: P_def powr_def intro: mult_monos)
  12.368 +next
  12.369 +  case 3
  12.370 +  show ?case by (auto simp: P_def powr_def intro: mult_monos)
  12.371 +next
  12.372 +  case 4
  12.373 +  show ?case by (auto simp: P_def powr_def intro: mult_monos)
  12.374 +next
  12.375 +  case 5
  12.376 +  note comm = mult.commute[of _ "ln x" for x :: real]
  12.377 +  show ?case by (auto simp: P_def powr_def comm intro: mult_monos)
  12.378 +next
  12.379 +  case 6
  12.380 +  note comm = mult.commute[of _ "ln x" for x :: real]
  12.381 +  show ?case by (auto simp: P_def powr_def comm intro: mult_monos)
  12.382 +next
  12.383 +  case 7
  12.384 +  show ?case by (auto simp: P_def powr_def intro: mult_monos)
  12.385 +next
  12.386 +  case 8  
  12.387 +  show ?case 
  12.388 +    by (auto simp: P_def powr_def intro: mult_monos)
  12.389 +next
  12.390 +  case 9
  12.391 +  show ?case unfolding P_def
  12.392 +  proof (safe, goal_cases)
  12.393 +    case (1 x)
  12.394 +    define l' where "l' = (\<lambda>x. min (ln (l1 x) * u2 x) (ln (u1 x) * l2 x))"
  12.395 +    define u' where "u' = (\<lambda>x. max (ln (l1 x) * l2 x) (ln (u1 x) * u2 x))"
  12.396 +    from 1 spec[OF mult_bounds_real(9)[of "\<lambda>x. ln (l1 x)" "\<lambda>x. ln (u1 x)" l2 u2 l' u' 
  12.397 +                                          "\<lambda>x. ln (f x)" g], of x]
  12.398 +      have "ln (f x) * g x \<in> {l' x..u' x}" by (auto simp: powr_def mult.commute l'_def u'_def)
  12.399 +    with 1 have "f x powr g x \<in> {exp (l' x)..exp (u' x)}"
  12.400 +      by (auto simp: powr_def mult.commute)
  12.401 +    also from 1 have "exp (l' x) = min (l1 x powr u2 x) (u1 x powr l2 x)"
  12.402 +      by (auto simp add: l'_def powr_def min_def mult.commute)
  12.403 +    also from 1 have "exp (u' x) = max (l1 x powr l2 x) (u1 x powr u2 x)"
  12.404 +      by (auto simp add: u'_def powr_def max_def mult.commute)
  12.405 +    finally show ?case using 1(5-9) by auto
  12.406 +  qed
  12.407 +qed
  12.408 +
  12.409 +qualified lemma powr_right_bounds:
  12.410 +  fixes f g :: "real \<Rightarrow> real"
  12.411 +  shows "\<forall>x. l x \<ge> 0 \<longrightarrow> f x \<in> {l x..u x} \<longrightarrow> g x \<ge> 0 \<longrightarrow> f x powr g x \<in> {l x powr g x..u x powr g x}"
  12.412 +    and "\<forall>x. l x > 0 \<longrightarrow> f x \<in> {l x..u x} \<longrightarrow> g x \<le> 0 \<longrightarrow> f x powr g x \<in> {u x powr g x..l x powr g x}"
  12.413 +  by (auto intro: powr_mono2 powr_mono2')
  12.414 +
  12.415 +(* TODO Move *)
  12.416 +lemma powr_mono': "a \<le> (b::real) \<Longrightarrow> x \<ge> 0 \<Longrightarrow> x \<le> 1 \<Longrightarrow> x powr b \<le> x powr a"
  12.417 +  using powr_mono[of "-b" "-a" "inverse x"] by (auto simp: powr_def ln_inverse ln_div divide_simps)
  12.418 +
  12.419 +qualified lemma powr_left_bounds:
  12.420 +  fixes f g :: "real \<Rightarrow> real"
  12.421 +  shows "\<forall>x. f x > 0 \<longrightarrow> g x \<in> {l x..u x} \<longrightarrow> f x \<ge> 1 \<longrightarrow> f x powr g x \<in> {f x powr l x..f x powr u x}"
  12.422 +    and "\<forall>x. f x > 0 \<longrightarrow> g x \<in> {l x..u x} \<longrightarrow> f x \<le> 1 \<longrightarrow> f x powr g x \<in> {f x powr u x..f x powr l x}"
  12.423 +  by (auto intro: powr_mono powr_mono')
  12.424 +
  12.425 +qualified lemma powr_nat_bounds_transfer_ge:
  12.426 +  "\<forall>x. l1 x \<ge> 0 \<longrightarrow> f x \<ge> l1 x \<longrightarrow> f x powr g x \<ge> l x \<longrightarrow> powr_nat (f x) (g x) \<ge> l x"
  12.427 +  by (auto simp: powr_nat_def)
  12.428 +
  12.429 +qualified lemma powr_nat_bounds_transfer_le:
  12.430 +  "\<forall>x. l1 x > 0 \<longrightarrow> f x \<ge> l1 x \<longrightarrow> f x powr g x \<le> u x \<longrightarrow> powr_nat (f x) (g x) \<le> u x"
  12.431 +  "\<forall>x. l1 x \<ge> 0 \<longrightarrow> l2 x > 0 \<longrightarrow> f x \<ge> l1 x \<longrightarrow> g x \<ge> l2 x \<longrightarrow> 
  12.432 +      f x powr g x \<le> u x \<longrightarrow> powr_nat (f x) (g x) \<le> u x"
  12.433 +  "\<forall>x. l1 x \<ge> 0 \<longrightarrow> u2 x < 0 \<longrightarrow> f x \<ge> l1 x \<longrightarrow> g x \<le> u2 x \<longrightarrow>
  12.434 +      f x powr g x \<le> u x \<longrightarrow> powr_nat (f x) (g x) \<le> u x"
  12.435 +  "\<forall>x. l1 x \<ge> 0 \<longrightarrow> f x \<ge> l1 x \<longrightarrow>  f x powr g x \<le> u x \<longrightarrow> u x \<le> u' x \<longrightarrow> 1 \<le> u' x \<longrightarrow> 
  12.436 +     powr_nat (f x) (g x) \<le> u' x"
  12.437 +  by (auto simp: powr_nat_def)
  12.438 +
  12.439 +lemma abs_powr_nat_le: "abs (powr_nat x y) \<le> powr_nat (abs x) y"
  12.440 +  by (simp add: powr_nat_def abs_mult)
  12.441 +
  12.442 +qualified lemma powr_nat_bounds_ge_neg:
  12.443 +  assumes "powr_nat (abs x) y \<le> u"
  12.444 +  shows   "powr_nat x y \<ge> -u" "powr_nat x y \<le> u"
  12.445 +proof -
  12.446 +  have "abs (powr_nat x y) \<le> powr_nat (abs x) y"
  12.447 +    by (rule abs_powr_nat_le)
  12.448 +  also have "\<dots> \<le> u" using assms by auto
  12.449 +  finally show "powr_nat x y \<ge> -u" "powr_nat x y \<le> u" by auto
  12.450 +qed
  12.451 +
  12.452 +qualified lemma powr_nat_bounds_transfer_abs [eventuallized]:
  12.453 +  "\<forall>x. powr_nat (abs (f x)) (g x) \<le> u x \<longrightarrow> powr_nat (f x) (g x) \<ge> -u x"
  12.454 +  "\<forall>x. powr_nat (abs (f x)) (g x) \<le> u x \<longrightarrow> powr_nat (f x) (g x) \<le> u x"
  12.455 +  using powr_nat_bounds_ge_neg by blast+
  12.456 +
  12.457 +qualified lemma eventually_powr_const_nonneg:
  12.458 +  "f \<equiv> f \<Longrightarrow> p \<equiv> p \<Longrightarrow> eventually (\<lambda>x. f x powr p \<ge> (0::real)) at_top"
  12.459 +  by simp
  12.460 +
  12.461 +qualified lemma eventually_powr_const_mono_nonneg:
  12.462 +  assumes "p \<ge> (0 :: real)" "eventually (\<lambda>x. l x \<ge> 0) at_top" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.463 +          "eventually (\<lambda>x. f x \<le> g x) at_top"
  12.464 +  shows   "eventually (\<lambda>x. f x powr p \<le> g x powr p) at_top"
  12.465 +  using assms(2-4) by eventually_elim (auto simp: assms(1) intro!: powr_mono2)
  12.466 +
  12.467 +qualified lemma eventually_powr_const_mono_nonpos:
  12.468 +  assumes "p \<le> (0 :: real)" "eventually (\<lambda>x. l x > 0) at_top" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.469 +          "eventually (\<lambda>x. f x \<le> g x) at_top"
  12.470 +  shows   "eventually (\<lambda>x. f x powr p \<ge> g x powr p) at_top"
  12.471 +  using assms(2-4) by eventually_elim (auto simp: assms(1) intro!: powr_mono2')
  12.472 +
  12.473 +
  12.474 +qualified lemma eventually_power_mono:
  12.475 +  assumes "eventually (\<lambda>x. 0 \<le> l x) at_top" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.476 +          "eventually (\<lambda>x. f x \<le> g x) at_top" "n \<equiv> n"
  12.477 +  shows   "eventually (\<lambda>x. f x ^ n \<le> (g x :: real) ^ n) at_top"
  12.478 +  using assms(1-3) by eventually_elim (auto intro: power_mono)
  12.479 +
  12.480 +qualified lemma eventually_mono_power_odd:
  12.481 +  assumes "odd n" "eventually (\<lambda>x. f x \<le> (g x :: real)) at_top"
  12.482 +  shows   "eventually (\<lambda>x. f x ^ n \<le> g x ^ n) at_top"
  12.483 +  using assms(2) by eventually_elim (insert assms(1), auto intro: power_mono_odd)
  12.484 +
  12.485 +
  12.486 +qualified lemma eventually_lower_bound_power_even_nonpos:
  12.487 +  assumes "even n" "eventually (\<lambda>x. u x \<le> (0::real)) at_top"
  12.488 +          "eventually (\<lambda>x. f x \<le> u x) at_top"
  12.489 +  shows   "eventually (\<lambda>x. u x ^ n \<le> f x ^ n) at_top"
  12.490 +  using assms(2-) by eventually_elim (rule power_mono_even, auto simp: assms(1))
  12.491 +
  12.492 +qualified lemma eventually_upper_bound_power_even_nonpos:
  12.493 +  assumes "even n" "eventually (\<lambda>x. u x \<le> (0::real)) at_top"
  12.494 +          "eventually (\<lambda>x. l x \<le> f x) at_top" "eventually (\<lambda>x. f x \<le> u x) at_top"
  12.495 +  shows   "eventually (\<lambda>x. f x ^ n \<le> l x ^ n) at_top"
  12.496 +  using assms(2-) by eventually_elim (rule power_mono_even, auto simp: assms(1))
  12.497 +
  12.498 +qualified lemma eventually_lower_bound_power_even_indet:
  12.499 +  assumes "even n" "f \<equiv> f"
  12.500 +  shows   "eventually (\<lambda>x. (0::real) \<le> f x ^ n) at_top"
  12.501 +  using assms by (simp add: zero_le_even_power)
  12.502 +
  12.503 +
  12.504 +qualified lemma eventually_lower_bound_power_indet:
  12.505 +  assumes "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.506 +  assumes "eventually (\<lambda>x. l' x \<le> l x ^ n) at_top" "eventually (\<lambda>x. l' x \<le> 0) at_top"
  12.507 +  shows   "eventually (\<lambda>x. l' x \<le> (f x ^ n :: real)) at_top"
  12.508 +  using assms
  12.509 +proof eventually_elim
  12.510 +  case (elim x)
  12.511 +  thus ?case
  12.512 +    using power_mono_odd[of n "l x" "f x"] zero_le_even_power[of n "f x"]
  12.513 +    by (cases "even n") auto
  12.514 +qed
  12.515 +
  12.516 +qualified lemma eventually_upper_bound_power_indet:
  12.517 +  assumes "eventually (\<lambda>x. l x \<le> f x) at_top" "eventually (\<lambda>x. f x \<le> u x) at_top"
  12.518 +          "eventually (\<lambda>x. u' x \<ge> -l x) at_top" "eventually (\<lambda>x. u' x \<ge> u x) at_top" "n \<equiv> n"
  12.519 +  shows   "eventually (\<lambda>x. f x ^ n \<le> (u' x ^ n :: real)) at_top"
  12.520 +  using assms(1-4)
  12.521 +proof eventually_elim
  12.522 +  case (elim x)
  12.523 +  have "f x ^ n \<le> \<bar>f x ^ n\<bar>" by simp
  12.524 +  also have "\<dots> = \<bar>f x\<bar> ^ n" by (simp add: power_abs)
  12.525 +  also from elim have "\<dots> \<le> u' x ^ n" by (intro power_mono) auto
  12.526 +  finally show ?case .
  12.527 +qed
  12.528 +
  12.529 +qualified lemma expands_to_imp_exp_ln_eq:
  12.530 +  assumes "(l expands_to L) bs" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.531 +          "trimmed_pos L" "basis_wf bs"
  12.532 +  shows   "eventually (\<lambda>x. exp (ln (f x)) = f x) at_top"
  12.533 +proof -
  12.534 +  from expands_to_imp_eventually_pos[of bs l L] assms
  12.535 +    have "eventually (\<lambda>x. l x > 0) at_top" by simp
  12.536 +  with assms(2) show ?thesis by eventually_elim simp
  12.537 +qed
  12.538 +
  12.539 +qualified lemma expands_to_imp_ln_powr_eq:
  12.540 +  assumes "(l expands_to L) bs" "eventually (\<lambda>x. l x \<le> f x) at_top"
  12.541 +          "trimmed_pos L" "basis_wf bs"
  12.542 +  shows   "eventually (\<lambda>x. ln (f x powr g x) = ln (f x) * g x) at_top"
  12.543 +proof -
  12.544 +  from expands_to_imp_eventually_pos[of bs l L] assms
  12.545 +    have "eventually (\<lambda>x. l x > 0) at_top" by simp
  12.546 +  with assms(2) show ?thesis by eventually_elim (simp add: powr_def)
  12.547 +qed
  12.548 +
  12.549 +qualified lemma inverse_bounds_real:
  12.550 +  fixes f l u :: "real \<Rightarrow> real"
  12.551 +  shows "\<forall>x. l x > 0 \<longrightarrow> l x \<le> f x \<longrightarrow> f x \<le> u x \<longrightarrow> inverse (f x) \<in> {inverse (u x)..inverse (l x)}"
  12.552 +    and "\<forall>x. u x < 0 \<longrightarrow> l x \<le> f x \<longrightarrow> f x \<le> u x \<longrightarrow> inverse (f x) \<in> {inverse (u x)..inverse (l x)}"
  12.553 +  by (auto simp: field_simps)
  12.554 +
  12.555 +qualified lemma pos_imp_inverse_pos: "\<forall>x::real. f x > 0 \<longrightarrow> inverse (f x) > (0::real)"
  12.556 +  and neg_imp_inverse_neg: "\<forall>x::real. f x < 0 \<longrightarrow> inverse (f x) < (0::real)"
  12.557 +  by auto
  12.558 +
  12.559 +qualified lemma transfer_divide_bounds:
  12.560 +  fixes f g :: "real \<Rightarrow> real"
  12.561 +  shows "Trueprop (eventually (\<lambda>x. f x \<in> {h x * inverse (i x)..j x}) at_top) \<equiv>
  12.562 +         Trueprop (eventually (\<lambda>x. f x \<in> {h x / i x..j x}) at_top)"
  12.563 +    and "Trueprop (eventually (\<lambda>x. f x \<in> {j x..h x * inverse (i x)}) at_top) \<equiv>
  12.564 +         Trueprop (eventually (\<lambda>x. f x \<in> {j x..h x / i x}) at_top)"
  12.565 +    and "Trueprop (eventually (\<lambda>x. f x * inverse (g x) \<in> A x) at_top) \<equiv>
  12.566 +         Trueprop (eventually (\<lambda>x. f x / g x \<in> A x) at_top)"
  12.567 +    and "Trueprop (((\<lambda>x. f x * inverse (g x)) expands_to F) bs) \<equiv>
  12.568 +         Trueprop (((\<lambda>x. f x / g x) expands_to F) bs)"
  12.569 +  by (simp_all add: field_simps)
  12.570 +
  12.571 +qualified lemma eventually_le_self: "eventually (\<lambda>x::real. f x \<le> (f x :: real)) at_top"
  12.572 +  by simp
  12.573 +
  12.574 +qualified lemma max_eventually_eq:
  12.575 +  "eventually (\<lambda>x. f x = (g x :: real)) at_top \<Longrightarrow> eventually (\<lambda>x. max (f x) (g x) = f x) at_top"
  12.576 +  by (erule eventually_mono) simp
  12.577 +
  12.578 +qualified lemma min_eventually_eq:
  12.579 +  "eventually (\<lambda>x. f x = (g x :: real)) at_top \<Longrightarrow> eventually (\<lambda>x. min (f x) (g x) = f x) at_top"
  12.580 +  by (erule eventually_mono) simp
  12.581 +
  12.582 +qualified lemma
  12.583 +  assumes "eventually (\<lambda>x. f x = (g x :: 'a :: preorder)) F"
  12.584 +  shows   eventually_eq_imp_ge: "eventually (\<lambda>x. f x \<ge> g x) F"
  12.585 +    and   eventually_eq_imp_le: "eventually (\<lambda>x. f x \<le> g x) F"
  12.586 +  by (use assms in eventually_elim; simp)+
  12.587 +
  12.588 +qualified lemma eventually_less_imp_le:
  12.589 +  assumes "eventually (\<lambda>x. f x < (g x :: 'a :: order)) F"
  12.590 +  shows   "eventually (\<lambda>x. f x \<le> g x) F"
  12.591 +  using assms by eventually_elim auto
  12.592 +
  12.593 +qualified lemma
  12.594 +  fixes f :: "real \<Rightarrow> real"
  12.595 +  shows eventually_abs_ge_0: "eventually (\<lambda>x. abs (f x) \<ge> 0) at_top"
  12.596 +    and nonneg_abs_bounds: "\<forall>x. l x \<ge> 0 \<longrightarrow> f x \<in> {l x..u x} \<longrightarrow> abs (f x) \<in> {l x..u x}" 
  12.597 +    and nonpos_abs_bounds: "\<forall>x. u x \<le> 0 \<longrightarrow> f x \<in> {l x..u x} \<longrightarrow> abs (f x) \<in> {-u x..-l x}" 
  12.598 +    and indet_abs_bounds:
  12.599 +          "\<forall>x. l x \<le> 0 \<longrightarrow> u x \<ge> 0 \<longrightarrow> f x \<in> {l x..u x} \<longrightarrow> -l x \<le> h x \<longrightarrow> u x \<le> h x \<longrightarrow> 
  12.600 +             abs (f x) \<in> {0..h x}"
  12.601 +  by auto
  12.602 +
  12.603 +qualified lemma eventually_le_abs_nonneg:
  12.604 +  "eventually (\<lambda>x. l x \<ge> 0) at_top \<Longrightarrow> eventually (\<lambda>x. f x \<ge> l x) at_top \<Longrightarrow>
  12.605 +     eventually (\<lambda>x::real. l x \<le> (\<bar>f x\<bar> :: real)) at_top"
  12.606 +  by (auto elim: eventually_elim2)
  12.607 +
  12.608 +qualified lemma eventually_le_abs_nonpos:
  12.609 +  "eventually (\<lambda>x. u x \<le> 0) at_top \<Longrightarrow> eventually (\<lambda>x. f x \<le> u x) at_top \<Longrightarrow>
  12.610 +     eventually (\<lambda>x::real. -u x \<le> (\<bar>f x\<bar> :: real)) at_top"
  12.611 +  by (auto elim: eventually_elim2)
  12.612 +
  12.613 +qualified lemma
  12.614 +  fixes f g h :: "'a \<Rightarrow> 'b :: order"
  12.615 +  shows eventually_le_less:"eventually (\<lambda>x. f x \<le> g x) F \<Longrightarrow> eventually (\<lambda>x. g x < h x) F \<Longrightarrow> 
  12.616 +           eventually (\<lambda>x. f x < h x) F"
  12.617 +  and   eventually_less_le:"eventually (\<lambda>x. f x < g x) F \<Longrightarrow> eventually (\<lambda>x. g x \<le> h x) F \<Longrightarrow>
  12.618 +           eventually (\<lambda>x. f x < h x) F"
  12.619 +  by (erule (1) eventually_elim2; erule (1) order.trans le_less_trans less_le_trans)+
  12.620 +
  12.621 +qualified lemma eventually_pos_imp_nz [eventuallized]: "\<forall>x. f x > 0 \<longrightarrow> f x \<noteq> (0 :: 'a :: linordered_semiring)"
  12.622 +  and eventually_neg_imp_nz [eventuallized]: "\<forall>x. f x < 0 \<longrightarrow> f x \<noteq> 0"
  12.623 +  by auto
  12.624 +
  12.625 +qualified lemma
  12.626 +  fixes f g l1 l2 u1 :: "'a \<Rightarrow> real"
  12.627 +  assumes "eventually (\<lambda>x. l1 x \<le> f x) F"
  12.628 +  assumes "eventually (\<lambda>x. f x \<le> u1 x) F"
  12.629 +  assumes "eventually (\<lambda>x. abs (g x) \<ge> l2 x) F"
  12.630 +  assumes "eventually (\<lambda>x. l2 x \<ge> 0) F"
  12.631 +  shows   bounds_smallo_imp_smallo: "l1 \<in> o[F](l2) \<Longrightarrow> u1 \<in> o[F](l2) \<Longrightarrow> f \<in> o[F](g)"
  12.632 +    and   bounds_bigo_imp_bigo:     "l1 \<in> O[F](l2) \<Longrightarrow> u1 \<in> O[F](l2) \<Longrightarrow> f \<in> O[F](g)"
  12.633 +proof -
  12.634 +  assume *: "l1 \<in> o[F](l2)" "u1 \<in> o[F](l2)"
  12.635 +  show "f \<in> o[F](g)"
  12.636 +  proof (rule landau_o.smallI, goal_cases)
  12.637 +    case (1 c)
  12.638 +    from *[THEN landau_o.smallD[OF _ 1]] and assms show ?case
  12.639 +    proof eventually_elim
  12.640 +      case (elim x)
  12.641 +      from elim have "norm (f x) \<le> c * l2 x" by simp
  12.642 +      also have "\<dots> \<le> c * norm (g x)" using 1 elim by (intro mult_left_mono) auto
  12.643 +      finally show ?case .
  12.644 +    qed
  12.645 +  qed
  12.646 +next
  12.647 +  assume *: "l1 \<in> O[F](l2)" "u1 \<in> O[F](l2)"
  12.648 +  then obtain C1 C2 where **: "C1 > 0" "C2 > 0" "eventually (\<lambda>x. norm (l1 x) \<le> C1 * norm (l2 x)) F"
  12.649 +    "eventually (\<lambda>x. norm (u1 x) \<le> C2 * norm (l2 x)) F" by (auto elim!: landau_o.bigE)
  12.650 +  from this(3,4) and assms have "eventually (\<lambda>x. norm (f x) \<le> max C1 C2 * norm (g x)) F"
  12.651 +  proof eventually_elim
  12.652 +    case (elim x)
  12.653 +    from elim have "norm (f x) \<le> max C1 C2 * l2 x" by (subst max_mult_distrib_right) auto
  12.654 +    also have "\<dots> \<le> max C1 C2 * norm (g x)" using elim ** by (intro mult_left_mono) auto
  12.655 +    finally show ?case .
  12.656 +  qed
  12.657 +  thus "f \<in> O[F](g)" by (rule bigoI)
  12.658 +qed
  12.659 +
  12.660 +qualified lemma real_root_mono: "mono (root n)"
  12.661 +  by (cases n) (auto simp: mono_def)
  12.662 +
  12.663 +(* TODO: support for rintmod *)
  12.664 +
  12.665 +ML_file \<open>multiseries_expansion_bounds.ML\<close>
  12.666 +
  12.667 +method_setup real_asymp = \<open>
  12.668 +let
  12.669 +  type flags = {verbose : bool, fallback : bool}
  12.670 +  fun join_flags
  12.671 +        {verbose = verbose1, fallback = fallback1}
  12.672 +        {verbose = verbose2, fallback = fallback2} =
  12.673 +    {verbose = verbose1 orelse verbose2, fallback = fallback1 orelse fallback2}
  12.674 +  val parse_flag =
  12.675 +    (Args.$$$ "verbose" >> K {verbose = true, fallback = false}) ||
  12.676 +    (Args.$$$ "fallback" >> K {verbose = false, fallback = true})
  12.677 +  val default_flags = {verbose = false, fallback = false}
  12.678 +  val parse_flags =
  12.679 +    Scan.optional (Args.parens (Parse.list1 parse_flag)) [] >>
  12.680 +      (fn xs => fold join_flags xs default_flags)
  12.681 +in
  12.682 +  Scan.lift parse_flags --| Method.sections Simplifier.simp_modifiers >>
  12.683 +    (fn flags => SIMPLE_METHOD' o
  12.684 +      (if #fallback flags then Real_Asymp_Basic.tac else Real_Asymp_Bounds.tac) (#verbose flags))
  12.685 +end
  12.686 +\<close> "Semi-automatic decision procedure for asymptotics of exp-log functions"
  12.687 +
  12.688 +end
  12.689 +
  12.690 +lemma "filterlim (\<lambda>x::real. sin x / x) (nhds 0) at_top"
  12.691 +  by real_asymp
  12.692 +
  12.693 +lemma "(\<lambda>x::real. exp (sin x)) \<in> O(\<lambda>_. 1)"
  12.694 +  by real_asymp
  12.695 +
  12.696 +lemma "(\<lambda>x::real. exp (real_of_int (floor x))) \<in> \<Theta>(\<lambda>x. exp x)"
  12.697 +  by real_asymp
  12.698 +
  12.699 +lemma "(\<lambda>n::nat. n div 2 * ln (n div 2)) \<in> \<Theta>(\<lambda>n::nat. n * ln n)"
  12.700 +  by real_asymp
  12.701 +
  12.702 +end
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/HOL/Real_Asymp/Real_Asymp.thy	Sun Jul 15 14:46:57 2018 +0200
    13.3 @@ -0,0 +1,49 @@
    13.4 +theory Real_Asymp
    13.5 +  imports Multiseries_Expansion_Bounds
    13.6 +keywords
    13.7 +  "real_limit" "real_expansion" :: diag  
    13.8 +begin
    13.9 +
   13.10 +ML_file \<open>real_asymp_diag.ML\<close>
   13.11 +
   13.12 +(*<*)
   13.13 +(* Hide constants and lemmas to avoid polluting global namespace *)
   13.14 +hide_const (open)
   13.15 +gbinomial_series lcoeff mssnth MSSCons MSLNil MSLCons mslmap convergent_powser convergent_powser' 
   13.16 +powser mssalternate basis_wf eval_monom inverse_monom is_expansion expansion_level eval 
   13.17 +zero_expansion const_expansion powr_expansion power_expansion trimmed dominant_term trimmed_pos
   13.18 +trimmed_neg ms_aux_hd_exp ms_exp_gt modify_eval is_lifting expands_to asymp_powser flip_cmp_result
   13.19 +compare_lists compare_expansions compare_list_0 powr_nat rfloor rceil rnatmod
   13.20 +
   13.21 +hide_fact (open)
   13.22 +convergent_powser_stl isCont_powser powser_MSLNil powser_MSLCons