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