1module ofsfdpep;
2
3revision('ofsfdpep, "$Id: ofsfdpep.red 4058 2017-05-23 17:12:59Z thomas-sturm $");
4
5copyright('ofsfdpep, "(c) 1995-2013 A. Dolzmann, T. Sturm");
6
7% Redistribution and use in source and binary forms, with or without
8% modification, are permitted provided that the following conditions
9% are met:
10%
11%    * Redistributions of source code must retain the relevant
12%      copyright notice, this list of conditions and the following
13%      disclaimer.
14%    * Redistributions in binary form must reproduce the above
15%      copyright notice, this list of conditions and the following
16%      disclaimer in the documentation and/or other materials provided
17%      with the distribution.
18%
19% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23% OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30%
31
32switch rldpepverbose,rldpepiverbose;
33
34on1 'rldpepverbose;
35off1 'rldpepiverbose;
36
37fluid '(!*ofsf_expf !*rlpepeval);
38
39procedure ofsf_dpepverbosep();
40   % PEP verbose predicate.
41   !*rlverbose and !*rldpepverbose;
42
43procedure ofsf_dpepiverbosep();
44   % PEP verbose predicate.
45   !*rlverbose and !*rldpepiverbose;
46
47procedure ofsf_dpep(ophi,k);
48   begin scalar qexp,ophiexp,phi,psiprime,phiprime,k;
49        !*ofsf_expf := intern gensym();
50        !*rlpepeval := nil;
51
52        % Verify if k positive.
53        if minusf k
54        then
55           rederr "Accuracy value has to be positive.";
56
57        % Verify ophi.
58        ofsf_pepcheck(ophi);
59
60        if ofsf_expfree(ophi)
61        then
62           return ofsf_cad(ophi,nil,nil);
63
64	% Preparation of the original phi
65        if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
66        then
67           ioto_tprin2t "++++ DPEP Preparation Phase";
68
69        % dotted pair (x_1.Q_1), where exp(x_1)
70        qexp := rl_var ophi.rl_op ophi;
71
72        % substitute in ophi the exponential function by
73        % the variable !*ofsf_expf
74        ophiexp := cl_apply2ats1(ophi,
75                 function(lambda x,qexp; ofsf_0mk2(ofsf_op x,
76                    ofsf_pepsubf(ofsf_arg2l x,{'expt,'e,car qexp},
77                                 !*ofsf_expf))),{qexp});
78
79        phi := rl_mat ophiexp; % phi = Q_2 x_2 ... Q_n x_n psi
80
81	% QE of phi (by CAD) if phi is not quantifier-free.
82        if cl_qvarl1 phi
83        then <<
84           if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
85           then <<
86              ioto_tprin2t "++++ DPEP QE by CAD";
87              % QE of phi (by CAD)
88	      psiprime := ofsf_cad(phi,nil,nil)
89           >> else <<
90              if !*rlverbose and !*rlcadverbose
91              then <<
92                 off1 'rlverbose;
93                 off1 'rlcadverbose;
94                 % QE of phi (by CAD)
95	         psiprime := ofsf_cad(phi,nil,nil);
96                 on1 'rlverbose;
97	         on1 'rlcadverbose
98              >> else
99	         % QE of phi (by CAD)
100	         psiprime := ofsf_cad(phi,nil,nil);
101           >>
102        >> else psiprime := phi;
103
104	% Combine Q_1x_1 with q.-free formula psiprime
105	phiprime := rl_mkq(cdr qexp,car qexp,psiprime);
106
107        % If QE by CAD fails, i.e. if phiprime is not
108        % an univariate poly.-expon. decision problem.
109        if null (length cl_qvarl1 phiprime eq 1 or
110           rl_mat phiprime eq 'false or
111           rl_mat phiprime eq 'true)
112        then
113           rederr "QE by CAD and decision procedure failed.";
114
115	% Decide univariate polynomial-exponential problem
116	return
117           (if rl_mat phiprime eq 'false or
118               rl_mat phiprime eq 'true
119            then
120	       cl_simpl(rl_mat phiprime,nil,-1)
121	    else
122	       ofsf_dupep(phiprime,k))
123   end;
124
125procedure ofsf_dupep(phiprime,k);
126   % Deciding univariate exponential problem. [phiprime] is a formula
127   % in the following form: Qx psi(x) , where psi is a qu.-free formula
128   % of the extension of the first-order theory of the real closed field
129   % and Qx is a quantifier. See thesis. [k] is an integer, which
130   % denotes the accuracy by the computation of the exponential
131   % function. Returns the truth value of phiprime.
132   begin scalar qexp,ccr,ppr,csb,cbases,contsb,pprtsb,pbases,psb,ilist,
133                isol,hatlist,splist,cellstogo,tv;
134      % dotted pair (x_1.Q_1), where exp(x_1).
135      qexp := rl_var phiprime . rl_op phiprime;
136
137      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
138      then <<
139         terpri();
140         ioto_prin2t{"++++ Decide UPEP"}
141      >>;
142
143      % reordering wrt. !*ofsf_expf,x_1
144      setkorder {!*ofsf_expf,car qexp};
145      phiprime := cl_apply2ats(phiprime,
146         function(lambda(x);ofsf_0mk2(ofsf_op x,reorder ofsf_arg2l x)));
147
148      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
149      then <<
150         maprint("P := ",0);
151         maprint('list .for each f in cl_terml phiprime collect
152                prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,car qexp}),0);
153         terpri!*(nil)
154      >>;
155      % contents and primitive parts.
156      ccr := for each c in cl_terml phiprime collect
157                ofsf_contenty(c,!*ofsf_expf);
158      ppr := for each p in cl_terml phiprime collect
159                ofsf_prparty(p,!*ofsf_expf);
160
161      % squarefree bases.
162      csb := for each c in ccr collect sfto_sqfdecf(c);
163      psb := for each p in ppr collect sfto_sqfdecf(p);
164
165      % csb, and psb are a list which contain for
166      % each c/p in ccr/ppr a list $((q_1 . 1),(q_2 . 2),...,(q_n . n))$
167      % such that $\prod q_i^i = c$/ $\prod q_i^i = p$ with the
168      % $q_i$ square-free and pairwise relatively prime.
169      % Collect the q_i of each list.
170
171      for each c in csb do
172         for each i in c do contsb := cons(car i,contsb);
173
174      for each p in psb do
175         for each i in p do pprtsb := cons(car i,pprtsb);
176
177      % Eliminate duplicates in contsb and pprtsb.
178      while contsb do
179         if member(car contsb,cdr contsb)
180         then
181            contsb := cdr contsb
182         else <<
183            cbases := cons(car contsb,cbases);
184            contsb := cdr contsb
185         >>;
186
187      while pprtsb do
188         if member(car pprtsb,cdr pprtsb)
189         then
190            pprtsb := cdr pprtsb
191         else <<
192            pbases := cons(car pprtsb,pbases);
193            pprtsb := cdr pprtsb
194         >>;
195
196      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
197      then <<
198         maprint("K := ",0);
199         maprint('list . for each f in cbases collect
200               prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,car qexp}),0);
201         terpri!*(nil);
202         maprint("Q := ",0);
203         maprint('list . for each f in pbases collect
204               prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,car qexp}),0);
205         terpri!*(nil)
206      >>;
207
208      % isolation list for each polynomial in K, and Q.
209      for each c in cbases do <<
210         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
211         then <<
212            terpri();
213            maprint("+++ ISOL(",0);
214            maprint(prepf ofsf_pepsubf(c,!*ofsf_expf,{'expt,'e,car qexp}),0);
215            maprint(")",0);
216            terpri!*(nil)
217         >>;
218         ilist := ofsf_pepisolate(c,car qexp,!*ofsf_expf,k);
219         % c is aex.
220         c := aex_fromsf ofsf_pepsubf(c,!*ofsf_expf,{'expt,'e,car qexp});
221         ilist := for each i in ilist join {{'anu,c,i}};
222         for each i in ilist do
223            isol := cons(i,isol)
224      >>;
225
226      for each p in pbases do <<
227         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
228         then <<
229            terpri();
230            maprint("+++ ISOL(",0);
231            maprint(prepf ofsf_pepsubf(p,!*ofsf_expf,{'expt,'e,car qexp}),0);
232            maprint(")",0);
233            terpri!*(nil)
234         >>;
235         ilist := ofsf_pepisolate(p,car qexp,!*ofsf_expf,k);
236         % p is aex.
237         p := aex_fromsf ofsf_pepsubf(p,!*ofsf_expf,{'expt,'e,car qexp});
238         ilist := for each i in ilist join {{'anu,p,i}};
239         for each i in ilist do isol :=
240            cons(i,isol)
241      >>;
242      isol := reverse isol;
243
244      % sort isol by its intervals.
245      if isol
246      then
247         isol := anu_sortlist(isol);
248
249      % Refine the isolating intervals in the list of the ANUs for
250      % the zeros of all the p*(x) \in isolc \union isolp such that
251      % we obtain an isolation list for the product q^(x) of all p*(x)
252      % in the list of ANUs.
253      if isol
254      then
255         hatlist := anu_refinelist(isol,car qexp,k);
256
257      % Construct sample points for all of the cells
258      % of the decomposition of the real line.
259      % For the representation of sample points see thesis.
260      if hatlist
261      then
262         splist := ofsf_pepsplist(hatlist)
263      else
264         splist := {{'anu,aex_fromsf nil,iv_mk(negsq rat_1 (),rat_1 ())}};
265
266      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
267      then <<
268         terpri();
269         ioto_prin2t{"+++ Cell Decomposition: ",length splist," cells"};
270         for each sp in splist do
271            iv_pepprint(anu_iv sp);
272         terpri!*(nil)
273      >>;
274
275      % Evaluate the truth value of phiprime by using the sample points.
276      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
277      then <<
278         terpri();
279         ioto_prin2t {"+++ Sign-Evaluation for ",cl_atnum(phiprime),
280                      " polynomials in ",length splist," cells"}
281      >>;
282
283      !*rlpepeval := t;
284
285      % substitute !*ofsf_expf with '(expt e x_1) in phiprime
286      phiprime := cl_apply2ats1(phiprime,
287              function (lambda x,qexp; ofsf_0mk2(ofsf_op x,
288              ofsf_pepsubf(ofsf_arg2l x,!*ofsf_expf,
289                           {'expt,'e,car qexp}))),
290              {qexp});
291
292      cellstogo := length splist; % for verbose output
293      for each sp in splist do <<
294         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
295         then <<
296            maprint("[",0);
297            maprint(cellstogo,0);
298            maprint("sgn(",0)
299         >>;
300         tv := tv.ofsf_pepevalqff(cl_nnf rl_mat phiprime,sp,car qexp,k);
301         cellstogo := cellstogo-1
302      >>;
303
304      if tv
305      then
306         if cdr qexp eq 'all
307         then
308            if smember('false,tv)
309            then
310               return cl_simpl('false,nil,-1)
311            else
312               return cl_simpl('true,nil,-1)
313         else
314            if smember('true,tv)
315            then
316               return cl_simpl('true,nil,-1)
317            else
318               return cl_simpl('false,nil,-1);
319      return cl_simpl(phiprime,nil,-1)
320   end;
321
322procedure ofsf_pepevalqff(f,sp,id,k);
323   % Evaluate quantifier-free formula at sample point. [f] is a
324   % quantifier-free OFSF formula; [sp] is a sample point.
325   % [k] is an integer, which denotes the accuracy by the
326   % computation of the exponential function.Returns
327   % ['true] or ['false]. Returns the truth value of
328   % $f(id)$ at point [sp].
329   begin scalar r;
330      r := cl_simpl(cl_apply2ats1(f,
331                    function ofsf_pepsubsignat,{sp,id,k}),nil,-1);
332      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
333      then
334         if r eq 'true
335         then
336            maprint(") tt]",0)
337         else
338            maprint(") ff]",0);
339      return r
340   end;
341
342
343procedure ofsf_pepsubsignat(at,sp,id,k);
344   % Substitute sign in atomic formula. [at] is an OFSF atomic
345   % formula; [sp] is a sample point. Returns an OFSF atomic formula.
346   % [k] is an integer, which denotes the accuracy by the computation
347   % of the exponential function.
348   % Returns [at] with the left-hand side $f$ replaced by the sign of
349   % $f([sp])$.
350   ofsf_0mk2(ofsf_op at,ofsf_pepevalsignf(ofsf_arg2l at,sp,id,k));
351
352
353procedure ofsf_pepevalsignf(f,sp,id,k);
354   % Evaluate sign of standard form at sample point.
355   % f is a SF, a polynomial in [id], [sp] is a Samplepoint.
356   % [k] is an integer, which denotes the accuracy by the
357   % computation of the exponential function. Returns
358   % [-1,0,1], the sign of f(sp).
359   begin scalar sgnf,sqfdecf,decf,prodf;
360      sgnf := rat_1 ();
361      prodf := numr simp 1;
362
363      % sp is exceptional point and f(sp)=0.
364      if iv_containszero(anu_iv sp) and
365         null numr simp rat_sgn
366         ofsf_pepsubsq(numr simp prepsq aex_ex anu_dp sp,id,rat_0 (),k)
367         and
368         null numr simp rat_sgn ofsf_pepsubsq(f,id,rat_0 (),k)
369      then <<
370         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
371         then
372            maprint("0 ",0);
373         return numr simp 0
374      >>;
375
376      % sp is 1-cell, i.e. a rational point.
377      if null numr simp prepsq aex_ex anu_dp sp
378      then <<
379         sgnf := numr simp rat_sgn ofsf_pepsubsq(f,id,iv_rb anu_iv sp,k);
380         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
381         then <<
382            maprint(sgnf,0);
383            maprint(" ",0)
384         >>;
385         return sgnf
386      >>;
387
388      % square-free decomposition of f := (p_1.1)(p_2.2)...(p_n.n)
389      sqfdecf := sfto_sqfdecf(f);
390      % decf is a list of all factors of sqfdecf i.e. p_1,p_2,...,p_n
391      decf := for each i in sqfdecf collect car i;
392      for each i in decf do
393         prodf := multf(prodf,i);
394
395      if member(numr simp prepsq aex_ex anu_dp sp,decf) or
396         member(multf(negf numr simp 1,
397                      numr simp prepsq aex_ex anu_dp sp),decf)
398      then <<
399         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
400         then
401            maprint("0 ",0);
402         return numr simp 0
403      >> else <<
404         decf := for each p in decf collect ofsf_pepevalsgnp(p,sp,id,k);
405         for each i in sqfdecf do <<
406            sgnf := multsq(sgnf,exptsq(!*f2q car decf,cdr i));
407            decf := cdr decf
408         >>;
409         if minusf quotfx(f,prodf)
410         then <<
411            sgnf := numr simp prepsq multsq(sgnf,negsq rat_1());
412            if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
413            then <<
414               maprint(sgnf,0);
415               maprint(" ",0)
416            >>;
417            return sgnf
418         >> else <<
419            sgnf := numr simp prepsq sgnf;
420            if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
421            then <<
422               maprint(sgnf,0);
423               maprint(" ",0)
424            >>;
425            return sgnf
426         >>
427      >>
428   end;
429
430procedure ofsf_pepevalsgnp(f,sp,id,k);
431   % Evaluate sign of (exponential) polynomial at sample point.
432   % f is a SF, a (exponential) polynomial in [id], [sp] is a
433   % Samplepoint. [k] is an integer, which denotes the accuracy
434   % by the computation of the exponential function. Returns
435   % [-1,0,1], the sign of f(sp).
436   begin
437      % f is a polynomial in x without exp(x), and sp is algebraic.
438      if not member({'expt,'e,id},kernels f) and
439         not member({'expt,'e,id},
440                    kernels numr simp prepsq aex_ex anu_dp sp)
441      then
442         return ofsf_evalsignf(f,{sp},{id}); % use cad-evaluation!
443
444      % sp is transcendental.
445      if member({'expt,'e,id},kernels numr simp prepsq aex_ex anu_dp sp)
446      then
447         return ofsf_pepevalsigntrans(f,sp,id,k)
448      else % sp is algebraic.
449         return ofsf_pepevalsignalg(f,sp,id,k)
450   end;
451
452procedure ofsf_pepevalsigntrans(f,sp,id,k);
453   begin scalar iv,sqff,ivrefined;
454      iv := anu_iv sp;
455      if null f
456      then
457         return numr simp 0;
458
459      % case: f and polynomial of sp are identically.
460      if cdr qremf(f,numr simp prepsq aex_ex anu_dp sp) eq nil
461      then
462         return numr simp 0;
463
464      % case: f and polynomial of sp are relatively prime.
465      sqff := ofsf_sqfparty(ofsf_pepsubf(f,{'expt,'e,id},!*ofsf_expf),
466                            !*ofsf_expf);
467      sqff := ofsf_pepsubf(sqff,!*ofsf_expf,{'expt,'e,id});
468      ivrefined := ofsf_peprefine(sqff,
469                   numr simp prepsq aex_ex anu_dp sp,id,iv,k);
470      return numr simp rat_sgn ofsf_pepsubsq(f,id,iv_rb ivrefined,k)
471   end;
472
473procedure ofsf_pepevalsignalg(f,sp,id,k);
474   begin scalar iv,sqff,ivrefined,ef;
475      iv := anu_iv sp;
476      if null f
477      then
478         return numr simp 0;
479
480      % case:f(sp)=0
481      ef := ofsf_pepsubf(f,{'expt,'e,id},!*ofsf_expf);
482      setkorder {!*ofsf_expf,id};
483      ef := reorder ef;
484      if ofsf_pepevalsign0alg(ef,sp,id)
485      then
486         return numr simp 0;
487
488      % case: f and polynomial of sp are relatively prime.
489      sqff := ofsf_sqfparty(ofsf_pepsubf(f,{'expt,'e,id},!*ofsf_expf),
490                            !*ofsf_expf);
491      sqff := ofsf_pepsubf(sqff,!*ofsf_expf,{'expt,'e,id});
492      ivrefined := ofsf_peprefine(sqff,
493                                  numr simp prepsq aex_ex anu_dp sp,
494                                  id,iv,k);
495      return numr simp rat_sgn ofsf_pepsubsq(f,id,iv_rb ivrefined,k)
496   end;
497
498procedure ofsf_pepevalsign0alg(f,sp,id);
499   % Zero sign of an exponential polynomial at algebraic point.
500   % [f] is SF, a polynomial in [id] and [y], represented in y,
501   % and where y denotes the exponential function. [sp] is an ANU,
502   % the sample point. Returns 'true if f(sp,exp(sp))=0,
503   % and otherwise 'false.
504   if domainp f or mvar f eq id
505   then
506      if domainp f
507      then
508         null f
509      else
510         null(cdr qremf(f,numr simp prepsq aex_ex anu_dp sp))
511   else
512      null(cdr qremf(lc f,numr simp prepsq aex_ex anu_dp sp))
513      and ofsf_pepsgn0rat(red f,sp,id);
514
515procedure ofsf_pepsplist(anul);
516   % Sample point list. [anul] is a list of ANUs, where the
517   % intervals are an isolation list for the product q^ of all the
518   % polynomials in the ANUs.
519   % Returns a list of sample points for all the cells of the
520   % decomposition of the real line determined by the zeros of q^.
521   begin scalar spl;
522      spl := {{'anu,aex_fromsf nil,
523               iv_mk(subtrsq(iv_lb anu_iv car anul,rat_1 ()),
524               iv_lb anu_iv car anul)}};
525      while anul do <<
526         % sample point for 0-cell.
527         spl := cons(car anul,spl);
528         % sample point for 1-cell i.e. between two successive 0-cells.
529         if cdr anul
530         then
531            spl := cons({'anu,aex_fromsf nil,
532                   iv_mk(iv_rb anu_iv car anul,iv_lb anu_iv cadr anul)},
533                   spl)
534         else % last sample point.
535            spl := cons({'anu,aex_fromsf nil,
536                   iv_mk(iv_rb anu_iv car anul,
537                         addsq(iv_rb anu_iv car anul,rat_1 ()))},spl);
538         anul := cdr anul
539      >>;
540      return reverse spl
541   end;
542
543procedure ofsf_pepsubsq(f,id,r,k);
544   % PEP substitution SQ. [f] is a SF,a polynomial in [id].
545   % [id] an identifier (the kernel to be replaced) and [r] is a SQ
546   % (the replacement). [k] is an integer, which denotes
547   % the accuracy by the computation of the exponential
548   % function.Returns a SQ.
549   begin scalar ub,lb,ef,ubexpf,lbexpf;
550      ef := ofsf_pepsubf(f,{'expt,'e,id},!*ofsf_expf);
551      setkorder {!*ofsf_expf,id};
552      ef := reorder ef;
553
554      if ofsf_pepsgn0rat(ef,id,r)
555      then
556         return rat_0 ()
557      else <<
558         % Bounds for the exponential function.
559         ubexpf := ofsf_pepuboundexpf(r,k);
560         lbexpf := ofsf_peplboundexpf(r,k);
561         % Bounds for the (exponential) polynomial f.
562         ub := ofsf_pepuboundepoly(ef,id,r,ubexpf,lbexpf);
563         lb := ofsf_peplboundepoly(ef,id,r,ubexpf,lbexpf);
564         if rat_sgn ub neq rat_sgn lb
565         then <<
566            rederr{"Approximation error too high. Accuracy has to be higher than"
567                   ,k}>>;
568      return ub >>
569   end;
570
571procedure ofsf_pepsgn0rat(f,x,v);
572   % Zero sign of an exponential polynomial at rational point.
573   % [f] is SF, a polynomial in [x] and [y], represented in y,
574   % and where y denotes the exponential function. [v] is SQ,
575   % rational numbers. Returns 'true if f(v,exp(v))=0,
576   % and otherwise 'false.
577   if domainp f or mvar f eq x
578   then
579      if domainp f
580      then
581         null f
582      else
583	 null numr ofsf_subf(f,x,v)
584   else
585      null numr ofsf_subf(lc f,x,v) and
586      ofsf_pepsgn0rat(red f,x,v);
587
588procedure ofsf_pepuboundepoly(f,id,r,lbexpf,ubexpf);
589   % PEP upper bound exponential polynomial.
590   % [f] is SF, a polynomial in [id] and [y], represented in y,
591   % and where y denotes the exponential function.[id] an identifier
592   % (the kernel to be replaced) and [r] is a SQ (the replacement).
593   % [lbexpf]/[ubexpf] the lower/upper bound for exp. Returns SQ, which
594   % is the upper bound for f.
595   if domainp f or mvar f eq id
596   then
597      if domainp f
598      then
599         !*f2q f
600      else
601	 ofsf_subf(f,id,r)
602   else
603      begin scalar tmp;
604         tmp := ofsf_subf(lc f,id,r);
605         if minusf numr simp rat_sgn tmp
606         then
607            return addsq(multsq(tmp,exptsq(lbexpf,ldeg f)),
608                         ofsf_pepuboundepoly(red f,id,r,lbexpf,ubexpf))
609         else
610            return addsq(multsq(tmp,exptsq(ubexpf,ldeg f)),
611                         ofsf_pepuboundepoly(red f,id,r,lbexpf,ubexpf))
612      end;
613
614procedure ofsf_peplboundepoly(f,id,r,lbexpf,ubexpf);
615   % PEP lower bound exponential polynomial.
616   % [f] is SF, a polynomial in [id] and [y], represented in y,
617   % and where y denotes the exponential function.[id] an identifier
618   % (the kernel to be replaced) and [r] is a SQ (the replacement).
619   % [lbexpf]/[ubexpf] the lower/upper bound for exp. Returns SQ, which
620   % is the lower bound for f.
621   if domainp f or mvar f eq id
622   then
623      if domainp f
624      then
625         !*f2q f
626      else
627	 ofsf_subf(f,id,r)
628   else
629      begin scalar tmp;
630         tmp := ofsf_subf(lc f,id,r);
631         if minusf numr simp rat_sgn tmp
632         then
633            return addsq(multsq(tmp,exptsq(ubexpf,ldeg f)),
634                         ofsf_pepuboundepoly(red f,id,r,lbexpf,ubexpf))
635         else
636            return addsq(multsq(tmp,exptsq(lbexpf,ldeg f)),
637                         ofsf_pepuboundepoly(red f,id,r,lbexpf,ubexpf))
638      end;
639
640
641procedure ofsf_pepsubf(f,id,r);
642   % PEP substitution. [f] is a SF, [id] an identifier
643   % (the kernel to be replaced) and [r] is a variable
644   % (the replacement). Returns a SF.
645   numr simp prepsq subf(f, {id . r});
646
647
648procedure ofsf_pepisolate(f,x,y,k);
649   % Real root isolation. [f] is SF, a nonzero squarefree
650   % polynomial in [x] and [y], represented in y, and where
651   % y denotes the exponential function. [k] is an integer,
652   % which denotes the accuracy by the computation of the
653   % exponential function. Returns an isolation list for
654   % f(x)=f(x,y), where y=exp(x).
655   begin scalar psdeg,prediff,s,lprime,posb,negb,f0,f1,isol,
656                lprefined,ef,es;
657      psdeg := ofsf_psdegree(f,x,y);
658
659      %Basis.
660      if car psdeg eq 0 and cdr psdeg eq 0
661      then <<
662         if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
663         then <<
664            maprint("L(",0);
665            maprint(prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,x}),0);
666            maprint(") := ",0);
667            maprint("{}",0);
668            terpri!*(nil)
669         >>;
670         return nil
671      >>;
672
673      % Recursion.
674      prediff := ofsf_diff(f,x,y);
675      if cdr psdeg > 0
676      then
677         s := ofsf_sqfparty(prediff,y)
678      else
679         s := ofsf_sqfparty(quotf(prediff,numr simp y),y);
680
681      lprime := ofsf_pepisolate(s,x,y,k);
682
683      % Calculate a real root bound.
684      if mvar f eq y
685      then <<
686         posb := !*f2q ofsf_peppositivebound(f,k);
687         negb := !*f2q ofsf_pepnegativebound(f,k)
688      >> else
689         if domainp f
690         then
691            posb := negb := 0
692         else <<
693            posb := addsq(aex_cauchybound(aex_fromsf f,mvar f),simp 1);
694            negb := negsq posb
695         >>;
696      if ofsf_dpepiverbosep()
697      then <<
698         maprint("++ ISOL(",0);
699         maprint(prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,x}),0);
700         maprint(")",0);
701         terpri!*(nil);
702         maprint("+ Real root bounds: ",0);
703         maprint(numr simp prepsq negb,0);
704         maprint(", ",0);
705         maprint(numr simp prepsq posb,0);
706         terpri!*(nil)
707      >>;
708
709      % Interval refinement.
710
711      % calculate f(0,1).
712      f1 := ofsf_pepsubf(f,!*ofsf_expf,1);
713      if domainp f1 then f0 := f1
714      else f0 := ofsf_pepsubf(f1,mvar f1,0);
715
716      % collect interval which have the exceptional point 0 and
717      % for which f(0,1)=0, and refine all other intervals.
718      ef := ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,x});
719      es := ofsf_pepsubf(s,!*ofsf_expf,{'expt,'e,x});
720      lprefined := for each iv in lprime join
721                 if iv_containszero iv and null f0
722                 then
723                    {iv_mk(-1 ./ 1024, 1 ./ 1024)}
724                 else
725                    {ofsf_peprefine(ef,es,x,iv,k)};
726
727      % Completion of the induction step.
728      isol := reverse ofsf_pepcompletion(ef,x,lprefined,negb,posb,k);
729
730      if ofsf_dpepverbosep() or ofsf_dpepiverbosep()
731      then <<
732         maprint("L(",0);
733         maprint(prepf ofsf_pepsubf(f,!*ofsf_expf,{'expt,'e,x}),0);
734         maprint(") := ",0);
735         if null isol
736         then <<
737            maprint("{}",0);
738            terpri!*(nil)
739         >> else
740            for each i in isol do
741               iv_pepprint(i);
742         terpri!*(nil)
743      >>;
744      return isol
745   end;
746
747procedure iv_pepprint(iv);
748   << maprint("]",0);
749      rat_pepprint iv_lb iv;
750      maprint(",",0);
751      rat_pepprint iv_rb iv;
752      maprint("[",0)
753   >>;
754
755procedure rat_pepprint r;
756   if numr r
757   then <<
758     maprint(numr r,0);
759     maprint("/",0);
760     maprint(denr r,0)
761   >> else
762     maprint("0",0);
763
764procedure ofsf_pepcompletion(f,x,ivl,b,a,k);
765   % Completion of induction step of algorithm isolate.
766   % [f] is SF, an exponential polynomial in [x]. [ivl] is a
767   % list of intervals and [b],[a] are integers. [k] is an
768   % integer, which denotes the accuracy by the computation
769   % of the exponential function.
770   begin scalar f0,ivlist,r;
771      % compute f(0).
772      f0 := numr simp rat_sgn ofsf_pepsubsq(f,x,rat_0 (),k);
773
774      if ivl = nil
775      then <<
776         if ofsf_pepsgnch(f,x,b,a,k) eq 'true
777         then
778            ivlist := cons(iv_mk(b,a),ivlist);
779         return ivlist
780      >>;
781
782      if cdr ivl = nil
783      then <<
784         if ofsf_pepsgnch(f,x,b,iv_lb car ivl,k) eq 'true
785         then
786            ivlist := cons(iv_mk(b,iv_lb car ivl),ivlist);
787         if iv_containszero car ivl and null f0
788         then
789            ivlist := cons(iv_mk(iv_lb car ivl,iv_rb car ivl),ivlist);
790         if ofsf_pepsgnch(f,x,iv_rb car ivl,a,k) eq 'true
791         then
792            ivlist := cons(iv_mk(iv_rb car ivl,a),ivlist);
793         return ivlist
794      >>;
795
796      if ofsf_pepsgnch(f,x,b,iv_lb car ivl,k) eq 'true
797      then
798         ivlist := cons(iv_mk(b,iv_lb car ivl),ivlist);
799      if iv_containszero car ivl and null f0
800      then
801         ivlist := cons(iv_mk(iv_lb car ivl,iv_rb car ivl),ivlist);
802
803      r := cons(ofsf_pepcompletion(f,x,cdr ivl,iv_rb car ivl,a,k),
804                ivlist);
805      r := for each i in r join
806              if listp i then for each j in i join {j}
807              else {i};
808      return r
809   end;
810
811procedure ofsf_pepsgnch(f,x,v1,v2,k);
812   % Sign change. [f] is SF, an exponential polynomial in [x].
813   % [v1],[v2] are SQ, rational numbers. [k] is an integer,
814   % which denotes the accuracy by the computation of the
815   % exponential function.Returns true if f(v1) has another
816   % sign than f(v2) (i.e. f(v1)*f(v2)<0 ).
817   % Otherwise return false.
818   if minusf multf(numr simp rat_sgn ofsf_pepsubsq(f,x,v1,k),
819                   numr simp rat_sgn ofsf_pepsubsq(f,x,v2,k))
820   then
821      'true
822   else
823      'false;
824
825procedure ofsf_peprefine(f,s,x,iv,k);
826   % Interval refinement. [f],[s] are SF, nonzero squarefree
827   % exponential polynomials in [x], and s has the same zeros
828   % as f. [iv] is an isolating interval for alpha,
829   % where alpha neq 0 and f'(alpha)=0. [k] is an integer,
830   % which denotes the accuracy by the computation of the
831   % exponential function.Returns an interval
832   % such that it does not contain any root of f(x).
833   begin scalar d,m,ivl,ivr,fivl,fivr,epsilon,diff,delta,
834                sgnsm,sgnsivl,sgnss,maxcoeffl;
835      if ofsf_dpepiverbosep() and null !*rlpepeval
836      then <<
837         maprint("+ Interval refinement of ",0);
838         iv_pepprint iv;
839         terpri!*(nil)
840      >>;
841      % calculate a list which contains max{|a_i|} of each coefficient
842      % p_j(x)=\sum_i^n a_ix^i of the derivation d of the inserted
843      % exponential polynomial f(x,exp(x))=\sum_j^m p_j(x)exp(jx).
844      d := numr simp prepsq diffsq(!*f2q f,x);
845      d := ofsf_pepsubf(d,{'expt,'e,x},!*ofsf_expf);
846      setkorder {!*ofsf_expf,x};
847      d := reorder d;
848      maxcoeffl := ofsf_maxcoefflist(d,x);
849
850      repeat <<
851         if ofsf_dpepiverbosep() and null !*rlpepeval
852         then
853            iv_pepprint iv;
854
855         % bisect the interval.
856         m := iv_med(iv);
857
858         % evaluate the sign of s(m),s(left border of iv),
859         % and s(m)*s(left border of iv).
860         sgnsm := numr simp rat_sgn ofsf_pepsubsq(s,x,m,k);
861         sgnsivl := numr simp rat_sgn ofsf_pepsubsq(s,x,iv_lb iv,k);
862         sgnss := multf(sgnsivl,sgnsm);
863
864         % set the new borders of the interval.
865         if null sgnsm
866         then <<
867            ivl := addsq(iv_lb iv,quotsq(subtrsq(iv_rb iv,iv_lb iv),
868                                         simp 4));
869            ivr := addsq(iv_lb iv,quotsq(multsq(simp 3,
870                         subtrsq(iv_rb iv,iv_lb iv)),simp 4));
871            iv := iv_mk(ivl,ivr)
872         >> else
873            if minusf sgnss then iv := iv_mk(iv_lb iv,m)
874            else iv := iv_mk(m,iv_rb iv);
875
876         % calculate epsilon = min{|f(ivl)|,|f(ivr)|}/2
877         fivl := rat_abs ofsf_pepsubsq(f,x,iv_lb iv,k);
878         fivr := rat_abs ofsf_pepsubsq(f,x,iv_rb iv,k);
879         epsilon := quotsq(rat_min(fivl,fivr),simp 2);
880
881         % calculate the difference of the right border of the
882         % new interval and the left border of the new interval.
883         % calculate delta = epsilon*moc.
884         diff := subtrsq(iv_rb iv,iv_lb iv);
885         % calculate delta = epsilon*moc, moc is the linear modulus
886         % of continuity.
887         delta := multsq(epsilon,ofsf_pepmoc(d,x,iv,maxcoeffl,k))
888      >> until rat_leq(diff,delta) and rat_greater(epsilon,rat_0 ());
889
890      if ofsf_dpepiverbosep() and null !*rlpepeval
891      then <<
892         terpri!*(nil);
893         maprint("+ Refined interval: ",0);
894         iv_pepprint iv;
895         terpri!*(nil)
896      >>;
897      return iv_mk(iv_lb iv,iv_rb iv)
898   end;
899
900procedure ofsf_pepmoc(f,x,iv,cl,k);
901   % Linear moc (modulus of continuity). [f] is SF, a
902   % polynomial in [x] and [y], represented in y i.e.
903   % f(x,y) := f_0(x)+f_1(x)y+...+f_m(x)y^m, and where y
904   % denotes the exponential function. [iv] is an interval.
905   % [k] is an integer, which denotes the accuracy by the
906   % computation of the exponential function. Returns
907   % integer which is a linear modulus of continuity
908   % for the interval [iv] and for g(x), with g'(x)=f.
909   begin scalar m,mbound,bound;
910      mbound := ofsf_pepmocbound(f,x,iv,cl);
911      if member(!*ofsf_expf,kernels f)
912      then <<
913         m := !*f2q ldeg f;
914         bound := multsq(addsq(m,rat_1 ()),
915                  ofsf_pepuboundexpf(multsq(m,iv_rb iv),k));
916         bound := multsq(bound,mbound)
917      >> else
918         bound := mbound;
919      return quotsq(rat_1 (),bound)
920   end;
921
922procedure ofsf_pepmocbound(f,x,iv,cl);
923   % [f] is SF, an exponential polynomial i.e. polynomial
924   % in [x] and [y], represented in y i.e.
925   % f(x,y) := f_0(x)+f_1(x)y+...+f_m(x)y^m, and where y
926   % denotes the exponential function. [iv] is an interval.
927   % Returns SQ, which is max_x\in iv{|f(x)|}.
928   if domainp f or mvar f eq x
929   then
930      if domainp f         % case: last coeff of f is a constant.
931      then
932         rat_abs !*f2q f
933      else % case: last coeff of f is a polynomial.
934         begin scalar a,c,sum;
935            a := !*f2q car cl;
936            c := rat_max(rat_abs iv_lb iv,rat_abs iv_rb iv);
937            % mocbound = a*(1+c+c^2+...+c^ldeg f).
938            sum := rat_1 ();
939            for i := 1:ldeg f do
940               sum := addsq(sum,exptsq(c,i));
941            return multsq(a,sum)
942         end
943   else
944      begin scalar a,c,degree,sum;
945         if domainp lc f
946         then
947            degree := 0
948         else
949            degree := ldeg lc f;
950         a := !*f2q car cl;
951         cl := cdr cl;
952         c := rat_max(rat_abs iv_lb iv,rat_abs iv_rb iv);
953         % mocbound = a*(1+c+c^2+...+c^degree).
954         sum := rat_1 ();
955         for i := 1:degree do
956            sum := addsq(sum,exptsq(c,i));
957         return rat_max(multsq(a,sum),ofsf_pepmocbound(red f,x,iv,cl))
958      end;
959
960procedure ofsf_maxcoefflist(f,x);
961   % Maximal coefficient list. [f] is SF, polynomial in [x], and [y],
962   % and represented in y i.e. f(x,y) := f_0(x)+f_1(x)y+...+f_m(x)y^m,
963   % and where y denotes the exponential function. Returns a list
964   % which contains max{|a_j|} of each f_i(x)=\sum_j^na_jx^j
965   % of f(x,y).
966   if domainp f or mvar f eq x
967   then
968      if domainp f
969      then
970         {absf f}
971      else
972         {ofsf_maxcoeff(f)}
973   else
974      append({ofsf_maxcoeff(lc f)},ofsf_maxcoefflist(red f,x));
975
976procedure ofsf_maxcoeff(f);
977   % Maximal coefficient. [f] is SF, an univariate integral polynomial.
978   % Returns an integer that is the maximum of the coefficients in
979   % absolute value.
980   if domainp f
981   then
982      if f eq nil
983      then
984         0
985      else
986         absf f
987   else
988      max(absf lc f,absf ofsf_maxcoeff(red f));
989
990
991procedure ofsf_peppositivebound(f,k);
992   % Positive real root bound for exponential polynomials.
993   % [f] is SF, a polynomial in x and y, and represented in y,
994   % i.e. f(x,y) := f_0(x)+f_1(x)y+...+f_m(x)y^m, and where
995   % y denotes the exponential function. [k] is an integer,
996   % which denotes the accuracy by the computation of the
997   % exponential function. Returns an integer c such
998   % that if alpha > 0 is any positive real root of
999   % f(x) := f(x,y), where y = exp(x) then alpha < c.
1000   begin scalar c1,ac2,a,c2,c3;
1001      % compute cauchybound c1 for f_m+1 (f_m := leading coeff of f,
1002      % an univariate polynomial in x) such that
1003      % for all x>c1, |f_m(x)|>1.
1004      c1 := ofsf_pepbound1 lc f;
1005      % compute c2 and a>0 such that for all x>c2,
1006      % for all 0<=i<m, |f_i(x)|<=x^a/m.
1007      ac2 := ofsf_pepbound2(red f,!*ofsf_expf,ldeg f);
1008      a := addf(1,car ac2);
1009      c2 := cdr ac2;
1010      % compute c3 such that for x>c3, x^a<exp(x/2).
1011      c3 := ofsf_pepbound3(a,k);
1012      return max(c1,max(c2,c3))
1013   end;
1014
1015procedure ofsf_pepnegativebound(f,k);
1016   % Negative real root bound for exponential polynomials.
1017   % [f] is SF, a polynomial in x and y, and represented in y,
1018   % i.e. f(x) := f_0(x)+f_1(x)y+...+f_m(x)y^m, and where
1019   % y denotes the exponential function. [k] is an integer,
1020   % which denotes the accuracy by the computation of the
1021   % exponential function. Returns an integer c such
1022   % that if alpha < 0 is any negative real root of
1023   % f := f(x,y), where y = exp(x) then alpha > c.
1024   begin scalar f0,c1,ac2,a,c2,c3;
1025      f0 := ofsf_peplowestcoeff(f,!*ofsf_expf);
1026      c1 := ofsf_pepbound1 f0;
1027      ac2 := ofsf_pepbound2(addf(addf(f,negf f0),1),!*ofsf_expf,ldeg f);
1028      a := addf(1,car ac2);
1029      c2 := cdr ac2;
1030      c3 := ofsf_pepbound3(a,k);
1031      return negf(max(c1,max(c2,c3)))
1032   end;
1033
1034procedure ofsf_peplowestcoeff(f,y);
1035   % Lowest coefficient. [f] is SF, a polynomial in x and [y],
1036   % represented in y. Returns the lowest coefficient of f which
1037   % is an univariate polynomial in x.
1038   if domainp f or mvar f neq y
1039   then
1040      f
1041   else
1042      ofsf_peplowestcoeff(red f,y);
1043
1044
1045procedure ofsf_pepbound1(f);
1046   % Bound1 for cauchybound for exponential polynomials.
1047   % [f] is SF, an univariate polynomial. Returns the
1048   % cauchybound for f+1.
1049   begin scalar fp1,aefp1,cbp1,fm1,aefm1,cbm1;
1050      fp1 := addf(f,1);
1051      aefp1 := aex_fromsf fp1;
1052      if domainp fp1
1053      then
1054         cbp1 := 0
1055      else
1056         cbp1 := numr simp prepsq aex_cauchybound(aefp1,mvar fp1);
1057      fm1 := addf(f,negf 1);
1058      aefm1 := aex_fromsf fm1;
1059      if domainp fm1
1060      then
1061         cbm1 := 0
1062      else
1063         cbm1 := numr simp prepsq aex_cauchybound(aefm1,mvar fm1);
1064      return min(cbp1,cbm1)
1065   end;
1066
1067
1068procedure ofsf_pepbound2(f,y,mdeg);
1069   % Bound2 for cauchybound for exponential polynomials.
1070   % [f] is SF, a bivariate polynomial in [y].
1071   % [mdeg] is an integer. Returns a dotted pair.
1072   if domainp f or mvar f neq y
1073   then
1074      if domainp f
1075      then <<
1076         if f eq nil
1077         then
1078            f := 0;
1079         0 . multf(multf(2,mdeg),absf!* f)
1080      >> else
1081         ldeg f . multf(multf(2,mdeg),absf!* lc f)
1082   else
1083      begin scalar aepm,cb,b,m,pmdeg;
1084         aepm := aex_fromsf lc f;
1085         if domainp lc f
1086         then <<
1087            cb := 0;
1088            b := multf(multf(2,mdeg),absf!* lc f);
1089            pmdeg := 0
1090         >> else <<
1091            cb := numr simp prepsq aex_cauchybound(aepm,mvar lc f);
1092            b := multf(multf(2,mdeg),absf!* lc lc f);
1093            pmdeg := ldeg lc f
1094         >>;
1095         if cb < b
1096         then
1097            m:= b
1098         else
1099            m := cb;
1100         return max(pmdeg,car ofsf_pepbound2(red f,y,mdeg)).
1101                max(m,cdr ofsf_pepbound2(red f,y,mdeg))
1102      end;
1103
1104procedure ofsf_pepbound3(a,k);
1105   % Bound3 for cauchybound for exponential polynomials.
1106   % [a] is an integer.[k] is an integer, which denotes
1107   % the accuracy by the computation of the exponential
1108   % function. Returns an integer b, such that
1109   % for all x>b, x^a < exp(x/2).
1110   begin integer b,ba,bexp;
1111      b := simp 2;
1112      repeat <<
1113         b := addsq(b,simp 1);
1114         ba := exptsq(b,a);
1115         bexp := ofsf_pepuboundexpf(quotsq(b,simp 2),k)
1116      >> until rat_max(ba,bexp) eq bexp;
1117      return numr simp prepsq b
1118   end;
1119
1120procedure ofsf_diff(f,x,y);
1121   % Derivation. [f] is SF, a polynomial in [x] and [y]
1122   % and represented in [y].
1123   % f(x,y) = f_0(x)+f_1(x)y+f_2(x)y^2+...+f_m(x)y^m.
1124   % f'(x,y) = f_0'(x)+(f_1'(x)+f_1(x))y+(f_2'(x)+2f_2(x))y^2+...
1125   % ...+(f_m'(x)+mf_m(x))f_m(x)y^m.
1126   % Returns a SF which is the derivative of f := f'(x,y).
1127   if domainp f or mvar f eq x
1128   then
1129      if domainp f
1130      then
1131         nil
1132      else
1133         diff(f,mvar f)
1134   else
1135      begin scalar d,l,k,m;
1136         if domainp lc f
1137         then
1138            d := 0
1139         else
1140            d := numr simp prepsq diffsq(!*f2q lc f,mvar lc f);
1141         l := addf(d,multf(ldeg f,lc f));
1142	 if mvar f eq y
1143         then <<
1144	    k := !*k2f mvar f;
1145            m := multf(exptf(k, ldeg f), l)
1146         >> else
1147            m := l;
1148	 return addf(m,ofsf_diff(red f,x,y))
1149      end;
1150
1151procedure ofsf_psdegree(f,x,y);
1152   % psdegree. [f] is SF, a polynomial in [x] and [y]
1153   % and represented in [y]. Returns dotted pair (m.n)
1154   % where m = deg_y f(x,y) ,and n = deg_x f(x,0).
1155   if domainp f
1156   then
1157      0 . 0
1158   else
1159      begin scalar m,n;
1160	 if mvar f eq y
1161         then
1162            m := ldeg f
1163	 else
1164            m := 0;
1165   	 n := ofsf_degx(f,x);
1166	 return m . n
1167      end;
1168
1169procedure ofsf_degx(f,x);
1170   % Degree wrt. x. [f] is SF, a polynomial in [x] and y
1171   % and represented in y. Returns deg_x f(x,0).
1172   if domainp f
1173   then
1174      0
1175   else
1176      if mvar f eq x
1177      then
1178         ldeg f
1179      else
1180         ofsf_degx(red f,x);
1181
1182procedure ofsf_contenty(f,y);
1183   % Content wrt y. [f] is SF, a bivariate polynomial
1184   % represented in [y]. Returns a SF which is the
1185   % content of [f] as an univariate polynomial.
1186   if domainp f or mvar f neq y
1187   then
1188      f
1189   else
1190      sfto_gcdf!*(lc f,ofsf_contenty(red f,y));
1191
1192procedure ofsf_prparty(f,y);
1193   % Primitive part wrt y. [f] is SF, a bivariate
1194   % polynomial represented in [y]. Returns a SF which is
1195   % the primitive part of [f] as a bivariate polynomial.
1196   quotf(f,ofsf_contenty (f,y));
1197
1198procedure ofsf_sqfparty(f,y);
1199   % Squarefree part. [f] is SF, a bivariate polynomial
1200   % represented in [y]. Returns a SF which is the squarefree
1201   % part of [f] as a bivariate polynomial.
1202   begin scalar c,pp,cdec1,cdec2,ppdec1,ppdec2;
1203      cdec2 := ppdec2 := 1;
1204      if domainp f
1205      then
1206         return 1;
1207      % compute square-free decomposition of the content
1208      c := ofsf_contenty(f,y);
1209      cdec1 := sfto_sqfdecf(c);
1210      cdec1 := for each c in cdec1 collect car c;
1211      while cdec1 do <<
1212         cdec2 := multf(cdec2,car cdec1);
1213         cdec1 := cdr cdec1 >>;
1214
1215      % compute square-free decomposition of the primitive part
1216      pp := ofsf_prparty(f,y);
1217      ppdec1 := sfto_sqfdecf(pp);
1218      ppdec1 := for each p in ppdec1 collect car p;
1219      while ppdec1 do <<
1220         ppdec2 := multf(ppdec2,car ppdec1);
1221         ppdec1 := cdr ppdec1 >>;
1222
1223      return multf(cdec2,ppdec2)
1224   end;
1225
1226procedure ofsf_pepcheck(ophi);
1227   % Check formula. [ophi] is a formula. Returns true if
1228   % ophi is a prenex sentence Q_1x_1...Q_nx_n psi(x_1,...,x_n)
1229   % where psi is a quantifier-free formula of the extension of the
1230   % first-order theory of the real closed field, and Q_ix_i are
1231   % quantifiers. See thesis.
1232   begin scalar idexp,psi,kerns;
1233      if null car cl_splt(ophi)
1234      then
1235         rederr "Input is not a prenex sentence";
1236      idexp := rl_var ophi;
1237      psi := rl_mat ophi;
1238      for each term in cl_terml psi do <<
1239         % Verify if exp occurs in the correct variable.
1240         kerns := kernels term;
1241         for each k in kerns do
1242            if member('expt,k) and member('e,k)
1243            then
1244               if idexp neq caddr k then
1245                  rederr {"Exponential function has to occur in",idexp}
1246      >>;
1247      % Verify if input is a prenex sentence.
1248      if null (length cl_fvarl1 ophi eq 1 and
1249         smember({'expt,'e,idexp},cl_fvarl1 ophi))
1250      then
1251         if null ofsf_expfree(ophi)
1252         then
1253            rederr "Input is not a prenex sentence";
1254      return nil
1255   end;
1256
1257procedure ofsf_expfree(f);
1258   % Exponential free. [f] is a formula. Returns true if
1259   % the terms of f does not involve the exponential function,
1260   % and nil otherwise.
1261   begin scalar esf,expfree;
1262      expfree := 'true;
1263      esf := {'expt,'e,rl_var f};
1264      for each term in cl_terml f do
1265          if member(esf,kernels term)
1266          then
1267             expfree := nil;
1268      return expfree
1269   end;
1270
1271%% Exponential Function Approximation.
1272
1273procedure ofsf_pepuboundexpf(x,k);
1274   % Upper bound exponential function. [x] is SQ, [k] is SF.
1275   % Returns SQ, the upper bound for exp(x) i.e.
1276   % x>0 : exp(x)<=\sum_i=0^k x^i/i! + 3^(ceiling x)/(k+1)! * x^(k+1).
1277   % x<0 : 1/(\sum_i=0^k x^i/i!).
1278   if rat_less(x,rat_0 ())
1279   then
1280      quotsq(rat_1 (),ofsf_pepexpf(rat_abs x,k))
1281   else
1282      addsq(ofsf_pepexpf(x,k),
1283            multsq(quotsq(exptsq(simp 3,ofsf_pepceiling rat_abs x),
1284                          simp ofsf_factsf addf(k,1)),exptsq(x,addf(k,1))));
1285
1286
1287
1288procedure ofsf_peplboundexpf(x,k);
1289   % Lower bound exponential function. [x] is SQ, [k] is an
1290   % integer, which denotes the accuracy by the computation
1291   % of the exponential function. Returns SQ, the lower bound
1292   % for exp(x) i.e.
1293   % x>0 :\sum_i=0^k x^i/i.
1294   % x<0 :1/(\sum_i=0^k x^i/i! + 3^(ceiling x)/(k+1)! * x^(k+1)).
1295   if rat_less(x,rat_0 ())
1296   then
1297      quotsq(rat_1 (),addsq(ofsf_pepexpf(rat_abs x,k),
1298             multsq(quotsq(exptsq(simp 3,ofsf_pepceiling rat_abs x),
1299                           simp ofsf_factsf addf(k,1)),exptsq(x,addf(k,1)))))
1300   else
1301      ofsf_pepexpf(x,k);
1302
1303
1304procedure ofsf_pepexpf(x,k);
1305   % PEP Exponential function approximation. [x] is SQ.
1306   % [k] is an integer which denotes with how many summands
1307   % the Taylor polynomial is computed.
1308   % Returns a SQ which is exp(x) approximated.
1309   % Approximate exp(x) by its Taylorpolynomial by
1310   % using repeated squaring.
1311   expApproxRed(x,k);
1312
1313procedure expApproxRed(x,k);
1314   % [x] is SQ
1315   begin scalar sr;
1316      if rat_leq(x,lnApprox(simp 1))
1317      then
1318         return expApprox(x,k)
1319      else <<
1320         sr := findsr x;
1321         return multsq(exptsq(simp 2,car sr),expApproxRed(cdr sr,k))
1322      >>
1323   end;
1324
1325procedure findsr(x);
1326   findsr_helper(x,0);
1327
1328procedure findsr_helper(x,s);
1329   % [x] is SQ, [s] is SF. Return SF.SQ.
1330   if rat_leq(x,lnApprox(simp 1))
1331   then
1332      s . x
1333   else
1334      findsr_helper(subtrsq(x,lnApprox(simp 1)),addf(s,1));
1335
1336procedure lnApprox(x);
1337   % Ln Approximation. [x] is SQ, -1<x<=1. REturns SQ which
1338   % is ln(x+1) approximated by its power serie.
1339   begin scalar n,g,sum;
1340      n := 20;
1341      g := 0; % bei 0 minus
1342      sum := x;
1343      for i := 2:n do
1344         if g eq 0
1345         then <<
1346            sum := subtrsq(sum,quotsq(exptsq(x,i),simp i));g:=1
1347         >> else <<
1348            sum := addsq(sum,quotsq(exptsq(x,i),simp i));g:=0
1349         >>;
1350      return sum
1351   end;
1352
1353procedure expApprox(x,k);
1354   % Exponential function approximation. [x] is SQ.
1355   % Returns a SQ which is exp(x) approximated.
1356   % Approximate exp(x) by its Taylorpolynomial of n-degree.
1357   begin scalar sum,xi,fi;
1358      if rat_nullp x then return simp 1;
1359      sum := simp 1;
1360      for i := 1:k do <<
1361         xi := exptsq(rat_abs x,i);
1362         fi := ofsf_factsf(i);
1363         sum := addsq(sum,quotsq(xi,simp fi))
1364      >>;
1365      if rat_less(x,rat_0 ())
1366      then
1367         sum := quotsq(rat_1 (),sum);
1368      return sum
1369   end;
1370
1371procedure ofsf_factsf(x);
1372   % Factorial Standard Form. [x] is SF.
1373   % Returns SF which is the factorial of x.
1374   if x <= 1
1375   then
1376      1
1377   else
1378      multf(x,ofsf_factsf(addf(x,negf 1)));
1379
1380procedure ofsf_pepceiling(x);
1381   % Ceiling. [x] is SQ. Returns a SF, which is the ceiling of x.
1382   begin
1383      !*rounded := t;
1384      setdmode('rounded,t);
1385      x := numr simp prepsq x;
1386      if pairp x
1387      then
1388         x := ceiling cdr x
1389      else
1390         if null x
1391         then
1392            x := 0
1393         else
1394            x := ceiling x;
1395      setdmode('rounded,nil);
1396      !*rounded := nil;
1397      return x
1398   end;
1399
1400%% ANU
1401
1402procedure anu_refinelist(anul,x,k);
1403   % Refine list. [anul] is a list of ANUs where
1404   % the intervals of the ANUs are an isolating interval
1405   % corresponding to the polynomial in its ANU. [k] is an integer,
1406   % which denotes the accuracy by the computation of the
1407   % exponential function. Refines the intervals of ivl such that
1408   % they have no intersection i.e. the intervals are an isolation
1409   % list for the product of the polynomials.
1410   begin scalar canu,a,l;
1411      canu := car anul;
1412      l := {canu};
1413      anul := cdr anul;
1414      while anul do <<
1415         if iv_comp(anu_iv canu,anu_iv car anul) eq 0
1416         then <<
1417            % if exceptional point then do not refine.
1418            if not (iv_containszero(anu_iv canu) and
1419               iv_containszero(anu_iv car anul) and
1420               null numr simp rat_sgn
1421               ofsf_pepsubsq(numr simp prepsq aex_ex anu_dp canu,
1422                             x,rat_0 (),k) and
1423               null numr simp rat_sgn
1424               ofsf_pepsubsq(numr simp prepsq aex_ex anu_dp car anul,
1425                             x,rat_0 (),k))
1426            then <<
1427               a := dpep_anu_refine(canu,car anul,x,k);
1428               l := anu_delete(canu,l);
1429               % Insert the smaller interval at first.
1430               if iv_comp(anu_iv car a,anu_iv cdr a) eq -1
1431               then <<
1432                  l := cons(car a,l);
1433                  l := cons(cdr a,l)
1434               >> else <<
1435                  l := cons(cdr a,l);
1436                  l := cons(car a,l)
1437               >>
1438            >>
1439         >> else
1440            l := cons(car anul,l);
1441         canu := car l;
1442         anul := cdr anul
1443      >>;
1444      return reverse l
1445   end;
1446
1447procedure dpep_anu_refine(anu1,anu2,x,k);
1448   % Refine. [anu1],[anu2] are two ANUs where their interval
1449   % are isolation intervals for their polynomial and these
1450   % intervals intersect. [k] is an integer, which denotes
1451   % the accuracy by the computation of the exponential function.
1452   % Refines the intervals of the ANUs such that they have no
1453   % intersection and remain as isolation
1454   % intervals. Returns a dotted pair with two intervals.
1455   begin scalar iv1,iv2,m1,m2,p1,p2,sgnp1m,sgnp2m,sgnp1ivl,
1456                sgnp2ivl,sgnpp1,sgnpp2,ivl,ivr;
1457      iv1 := anu_iv anu1;
1458      iv2 := anu_iv anu2;
1459      p1 := numr simp prepsq aex_ex anu_dp anu1;
1460      p2 := numr simp prepsq aex_ex anu_dp anu2;
1461      repeat <<
1462         % bisect the intervals.
1463         m1 := iv_med(iv1);
1464         m2 := iv_med(iv2);
1465
1466         % evaluate the signs of p1(m1),p1(left border of iv1),
1467         % and p1(m1)*p1(left border of iv1).
1468         sgnp1m := numr simp rat_sgn ofsf_pepsubsq(p1,x,m1,k);
1469         sgnp1ivl := numr simp rat_sgn ofsf_pepsubsq(p1,x,iv_lb iv1,k);
1470         sgnpp1 := multf(sgnp1ivl,sgnp1m);
1471
1472         % evaluate the signs of p2(m2),p2(left border of iv2),
1473         % and p2(m2)*p2(left border of iv2).
1474         sgnp2m := numr simp rat_sgn ofsf_pepsubsq(p2,x,m2,k);
1475         sgnp2ivl := numr simp rat_sgn ofsf_pepsubsq(p2,x,iv_lb iv2,k);
1476         sgnpp2 := multf(sgnp2ivl,sgnp2m);
1477
1478         % set the new borders of the first interval.
1479         if null sgnp1m
1480         then <<
1481            ivl := addsq(iv_lb iv1,
1482                         quotsq(subtrsq(iv_rb iv1,iv_lb iv1),simp 4));
1483            ivr := addsq(iv_lb iv1,
1484                         quotsq(multsq(simp 3,subtrsq(iv_rb iv1,
1485                                iv_lb iv1)),simp 4));
1486            iv1 := iv_mk(ivl,ivr)
1487         >> else
1488            if minusf sgnpp1
1489            then
1490               iv1 := iv_mk(iv_lb iv1,m1)
1491            else
1492               iv1 := iv_mk(m1,iv_rb iv1);
1493
1494         % set the new borders of the second interval.
1495         if null sgnp2m
1496         then <<
1497            ivl := addsq(iv_lb iv2,
1498                         quotsq(subtrsq(iv_rb iv2,iv_lb iv2),simp 4));
1499            ivr := addsq(iv_lb iv2,
1500                         quotsq(multsq(simp 3,subtrsq(iv_rb iv2,
1501                                iv_lb iv2)),simp 4));
1502            iv2 := iv_mk(ivl,ivr)
1503         >> else
1504            if minusf sgnpp2
1505            then
1506               iv2 := iv_mk(iv_lb iv2,m2)
1507            else
1508               iv2 := iv_mk(m2,iv_rb iv2)
1509      >> until iv_comp(iv1,iv2) neq 0;
1510      anu1 := {'anu,aex_ex anu1,iv1};
1511      anu2 := {'anu,aex_ex anu2,iv2};
1512      return anu1 . anu2
1513   end;
1514
1515
1516procedure anu_sortlist(anul);
1517   % ANU sortlist. [anul] is a list of ANUs.
1518   % Returns the a list of ANUs which is anul
1519   % sorted by the intervals of its ANUs.
1520   begin scalar anumin,sort;
1521      while anul do <<
1522         anumin := anu_min(anul);
1523         sort := cons(anumin,sort);
1524         anul := anu_delete(anumin,anul)
1525      >>;
1526      sort := reverse(sort);
1527      return sort
1528   end;
1529
1530procedure anu_delete(anu,anul);
1531   % ANU delete. [anu] is an ANU (the one to delete),
1532   % [anul] is a list of ANUs. Returns a list of ANUs
1533   % which is anul without anu.
1534   <<
1535      anul := for each i in anul join
1536                if i neq anu
1537                then {i};
1538      anul
1539   >>;
1540
1541procedure anu_min(anul);
1542  % ANU minimum. [anul] is a list of ANUs. Returns
1543  % an ANU which has the interval with the smallest
1544  % interval borders.
1545  begin scalar anumin;
1546      anumin := car anul;
1547      anul := cdr anul;
1548      while anul do <<
1549         if iv_comp(anu_iv car anul,anu_iv anumin) eq -1
1550         then
1551            anumin := car anul;
1552         if iv_comp(anu_iv car anul,anu_iv anumin) eq 0
1553         then
1554            if rat_less(iv_lb anu_iv car anul,iv_lb anu_iv anumin)
1555            then
1556               anumin := car anul;
1557         anul := cdr anul;
1558      >>;
1559      return anumin
1560   end;
1561
1562endmodule; %[dpep]
1563
1564end;  % of file
1565