ratint.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. % -------------------------------------------------------------------------
  2. % Neil Langmead
  3. % ZIB Berlin, December 1996 / January 1997
  4. %
  5. % Package to integrate rational functions. Uses the Hermite Horowitz Rothstein
  6. % Trager algorithms to determine firstly, the reduction of the rational fn
  7. % into its polynomial and logarithmic parts, then the integration of these
  8. % parts seperately.
  9. create!-package('(ratint convert),nil);
  10. global '(traceratint!*); % for the tracing facility
  11. switch traceratint;
  12. off traceratint; % set to off by default
  13. algebraic;
  14. % We first need a few utility functions, given below
  15. %
  16. % -------------------------------------------------------------------------
  17. % routine to return the square free factorisation of a polynomial
  18. % outputs factors in a list, coupled with their exponents.
  19. % However, such a function is already defined in poly/facform.
  20. % expr procedure square_free(poly,x);
  21. % begin scalar !*EXP, !*FACTOR, !*DIV, !*RATARG, !*GCD, !*RATIONAL,
  22. % l,k,c,w,z,y,output, answer, result;
  23. % on exp; on div; on ratarg; off factor; on rational;
  24. % k:=1; output:={}; answer:= df(poly,x);
  25. % poly:=poly;
  26. % c:=gcd(poly,answer);
  27. % w:=poly/c;
  28. % while (c neq 1) do
  29. % <<
  30. % y:=gcd(w,c);
  31. % z:=w/y;
  32. % if (z neq 1) then
  33. % output:=append({{z,k}},output);
  34. % k:=k+1;
  35. % w:=y; c:=c/y;
  36. % >>;
  37. % output:=append({{w,k}},output);
  38. % return output;
  39. % end;
  40. % expr procedure eval_square_free(list,var);
  41. % begin scalar output;
  42. % off exp;
  43. % output:= for l:=1:arglength(list)
  44. % product(part(part(list,l),1)^(part(part(list,l),2)));
  45. % return output;
  46. % end;
  47. expr procedure make_mon(li,var);
  48. begin scalar current, li2;
  49. li2:={};
  50. for k:=1:arglength(li) do
  51. <<
  52. current:=part(li,k);
  53. current:=monic(current,var);
  54. li2:=append(li2,{current});
  55. >>;
  56. return(li2);
  57. end;
  58. expr procedure monic(exp,var);
  59. begin scalar lecof, temp;
  60. lecof:=lcof(exp,var);
  61. exp:=exp/lecof;
  62. return exp;
  63. end;
  64. %x^8-2*x^6+2*x^2-1;
  65. %z:=square_free(x^8-2*x^6+2*x^2-1,x);
  66. %res:= for l:=1:2 product(part(part(z,l),1)^(part(part(z,l),2)));
  67. % -------------------------------------------------------------------------
  68. % An implementation of the extended Eucledian algorithm. Given polynomials
  69. % a and b in the variable x in a Euclidean domain D, this computes elements
  70. % s and t in D such that g:=gcd(a,b)=sa+tb
  71. %off factor;
  72. % input is polynomials a and b, in variable var
  73. on rational;
  74. %expr procedure u(exp,var);
  75. %lcof(exp,var);
  76. expr procedure norm(exp,var);
  77. exp/lcof(exp,var);
  78. expr procedure gcd_ex(a,b,var);
  79. begin scalar c, c1, c2,d,d1,d2,q,r,m,r1,r2,g,s,b;
  80. on rational;
  81. c:=norm(a,var); d:=norm(b,var);
  82. c1:=1; d1:=0; c2:=0; d2:=1;
  83. while(d neq 0) do
  84. <<
  85. on rational;
  86. m:=pseudorem(c,d,var);
  87. q:=part(pseudorem(c,d,var),3)/part(pseudorem(c,d,var),2);
  88. %q:=part(pf(c/d,var),1); q should be quo(c,d)
  89. %off rational;
  90. r:=c-q*d;
  91. %r:=part(m,1);
  92. r1:=c1-q*d1; r2:=c2-q*d2;
  93. c:=d; c1:=d1; c2:=d2;
  94. d:=r; d1:=r1; d2:=r2;
  95. >>;
  96. s:=c1/(u(a,var)*u(c,var));
  97. b:=c2/(u(b,var)*u(c,var));
  98. return({s,b});
  99. end;
  100. expr procedure u(exp,var);
  101. if(numberp(exp)) then exp else
  102. lcof(exp,var);
  103. %l:=3*x^3+x^2+x+5;% p:=5*x^2-3*x+1
  104. %pseudorem(l,p,x);
  105. %quote:=part(pseudorem(o,p,x),3)/part(pseudorem(o,p,x),2);
  106. %gcd_ex(x^2-1,x+1,x);
  107. %a:=x^2+(7/6)*x+(1/3); b:=2*x+(7/6);
  108. %gcd_ex(a,b,x);
  109. %f:=48*x^3-84*x^2+42*x-36; g:=-4*x^3-10*x^2+44*x-30;
  110. %gcd_ex(f,g,x);
  111. % -------------------------------------------------------------------------
  112. % routine to remove elements from a list which are zero
  113. expr procedure rem_zero(li);
  114. begin scalar k,j,l,li1,li2;
  115. for k:=1:arglength(li) do
  116. <<
  117. j:=part(li,k);
  118. if(j neq 0) then nil else
  119. <<
  120. li1:=for l:=1:k-1 collect part(li,l);
  121. li2:=for l:=k+1:arglength(li) collect part(li,l);
  122. li:=append(li1,li2);
  123. >>;
  124. >>;
  125. return li;
  126. end;
  127. % --------------------------------------------------------------------------
  128. % This routine takes as input a rational function p/q^(expt), returning p, q
  129. % and expt seperately in a list
  130. expr procedure hr_monic_den(li,x);
  131. begin scalar !*EXP, !*FACTOR, q, lc;
  132. on EXP;
  133. li:= (for each r in li collect << lc:=lcof(den(r),x);
  134. {num(r)/lc, den(r)/lc} >> );
  135. on FACTOR;
  136. li:= (for each r in li collect
  137. << q:=part(r,2);
  138. if(arglength(q) > -1 and part(q,0)=expt) then
  139. {part(r,1),part(q,1),part(q,2)} else
  140. {part(r,1),part(q,1),1} >> ) ; return li;
  141. end;
  142. %q:={3/(x+3)^2,4/(x+1)^5};
  143. %hr_monic_den(q,x);
  144. %in "monic";
  145. % -------------------------------------------------------------------------
  146. % The implementation of the Rostein Trager algorithm
  147. % Takes as input a/b in x, and returns a two element list, with the polynomial
  148. % and logarithmic parts of the integral. For aesthetic reasons in REDUCE, the
  149. % values aren't added. This should be done manually by the user, but is a
  150. % trivial task.
  151. % in "mkmonic.red";
  152. operator c, rtof,v, alpha;
  153. load_package arnum;
  154. load_package assist;
  155. expr procedure not_numberp(x);
  156. if (not numberp(x)) then t else nil;
  157. expr procedure rt(a,b,x);
  158. begin scalar vv, j,k,i,current,sol,res,cc,b_prime,extra_term,
  159. current1,vvv,integral, eqn,d,v_list, sol1,sol2, temp, temp2;
  160. b_prime:=df(b,x);
  161. v_list:={};
  162. on rational;
  163. res:=resultant(a-z*b_prime,b,x);
  164. on rational; on ifactor;
  165. res:= old_factorize(res);
  166. res:=extractlist(res, not_numberp);
  167. res:=make_mon(res,z);
  168. res:=mkset(res); % removes duplicates by turning list into a set
  169. %write "res is ", res;
  170. integral:=0;
  171. for k:=1:arglength(res) do
  172. <<
  173. current:=part(res,k);% write "current is ", current;
  174. d:=deg(current,z); %write "d is ", d;
  175. if(d=1) then
  176. <<
  177. sol:=solve(current=0,z);
  178. sol:=part(sol,1);
  179. cc:=part(sol,2);% write "cc is ", cc;
  180. vv:=gcd(a-cc*b_prime,b);% write "vv is " , vv;
  181. vv:=vv/(lcof(vv,x));
  182. extra_term:=append({cc},{log(vv)});% write extra_term;
  183. extra_term:=part(extra_term,1)*part(extra_term,2); %write extra_term;
  184. integral:=extra_term+integral; %write "integral is ", integral;
  185. >>
  186. else
  187. <<
  188. current:=sub(z=alpha,current);% write "current is ", current;
  189. current1:=sub(alpha=alp,current);% write "current1 is ", current1;
  190. defpoly(current);
  191. %write "alpha is ", alpha;
  192. a:=sub(x=z,a); b:=sub(x=z,b); b_prime:=sub(x=z,b_prime);
  193. vv:=gcd(a-alpha*b_prime,b);% write "vv is ", vv; % OK up to here
  194. off arnum;
  195. on fullroots;
  196. vv:=sub(a1=alpha*8,vv);
  197. vv:=sub(z=x,vv);
  198. vvv:=solve(vv=0,x);
  199. vvv:=sub(a1=1/alp,vvv);% write "vvv is ", vvv;
  200. eqn:=part(part(vvv,1),1)-part(part(vvv,1),2);
  201. %write "eqn is ", eqn;
  202. if(d=2) then
  203. <<
  204. sol:=solve(current1=0,alp);
  205. sol1:=part(sol,1); sol2:=part(sol,2);
  206. %write "sol1, 2 are ", sol1, sol2;
  207. c(1):=part(sol1,2); c(2):=part(sol2,2);
  208. %write "c(1), c(2) are ", c(1), c(2);
  209. for j:=1:2 do
  210. <<
  211. v(j):=sub(alp=c(j),eqn);
  212. integral:=integral+c(j)*log(v(j));
  213. %write "integral is ", integral;
  214. >>;
  215. >>
  216. else
  217. <<
  218. k:=1;
  219. %write "d is ", d;
  220. while (k<=d) do
  221. %for k:=1:3 do
  222. <<
  223. c(k):=rtof(current1);% write "c(k) is ", c(k);
  224. v(k):=sub({alp=c(k)},eqn);% write "v(k) is ", v(k);
  225. integral:=integral+c(k)*log(v(k));
  226. %write "integral is ", integral;
  227. k:=k+1;
  228. >>;
  229. >>;
  230. >>;
  231. lisp null remprop ('alpha,'currep);
  232. lisp null remprop ('alpha,'idvalfn);
  233. >>;
  234. return(integral);
  235. end;
  236. % -------------------------------------------------------------------------
  237. % This piece of code was written by Matt Rebeck. Input are the functions
  238. % p, q and variable x. It returns the pseudo remainder of p and q, and the
  239. % quotient.
  240. symbolic procedure prem(r,v,var);
  241. begin
  242. scalar d,dr,dv,l,n,tt,rule_list,m,q,input1,input2,rr,vv;
  243. on rational; off factor;
  244. rr := r;
  245. vv := v;
  246. dr := deg(r,var);
  247. dv := deg(v,var);
  248. if dv <= dr then
  249. <<
  250. l := reval coeffn(v,var,dv);
  251. v := reval{'plus,v,{'minus,{'times,l,{'expt,var,dv}}}};
  252. >>
  253. else l := 1;
  254. d := dr-dv+1;
  255. n := 0;
  256. while dv<=dr and r neq 0 do
  257. <<
  258. tt := reval{'times,{'expt,var,(dr-dv)},v,coeffn(r,var,dr)};
  259. if dr = 0 then r := 0
  260. else
  261. <<
  262. rule_list := {'expt,var,dr}=>0;
  263. let rule_list;
  264. r := reval r;
  265. clearrules rule_list;
  266. >>;
  267. r := reval{'plus,{'times,l,r},{'minus,tt}};
  268. dr := deg(r,var);
  269. n := n+1;
  270. >>;
  271. r := reval{'times,{'expt,l,(d-n)},r};
  272. m := reval{'expt,l,d};
  273. input1 := reval{'plus,{'times,{'expt,l,d},rr},{'minus,r}};
  274. input2 := vv;
  275. q := reval{'quotient,input1,input2};
  276. return {r,m,q};
  277. end;
  278. procedure pseudorem(x,y,var); lisp ('list . prem(x,y,var));
  279. %e.g.
  280. %pseudorem(3x^5+4,x^2+1,x);
  281. %exp1:=441*x^7+780*x^6-2861*x^5+4085*x^4+7695*x^3+3713*x^2-43253*x+24500;
  282. %exp2:=9*x^6+6*x^5-65*x^4+20*x^3+135*x^2-154*x+49;
  283. %pseudorem(exp1,exp2,x);
  284. %a:=x^8+x^6-3*x^4-3*x^3+8*x^2+2*x-5;
  285. %b:=3*x^6+5*x^4-4*x^2-9*x+21;
  286. %pseudorem(a,b,x);
  287. %r:=-15*x^4+3*x^2-9;
  288. %rr:=
  289. %operator a,c, neil;
  290. %in "rem";
  291. % -------------------------------------------------------------------------
  292. % this routine is the implementation of Horowitz' method of reducing the
  293. % rational function into a polynomial and logarithmic part.
  294. operator a,c, neil ;
  295. expr procedure howy(p,q,x);
  296. begin
  297. scalar pseudo, quo,rem,pp, poly_part,d,mm,b,nn,j,k,aa,cc,
  298. pseudo3,i,quo3,r,pseudo2,eqn,l,neil1,sol, var1, temp,var2,var3,p,test,output;
  299. pseudo:=pseudorem(p,q,x);
  300. quo:=part(pseudo,3)/part(pseudo,2);
  301. rem:=part(pseudo,1)/part(pseudo,2);
  302. poly_part:=quo;
  303. pp:=rem;% write "pp is ", pp;
  304. d:=gcd(q,df(q,x));
  305. pseudo2:=pseudorem(q,d,x);
  306. b:=part(pseudo2,3)/part(pseudo2,2);
  307. mm:=deg(b,x);
  308. nn:=deg(d,x);
  309. aa:=for k:=0:(mm-1) sum (a(k))*(x^(k));
  310. cc:=for j:=0:(nn-1) sum (c(j))*(x^(j));
  311. var1:=for i:=0:(mm-1) collect a(i);
  312. var2:=for k:=0:(nn-1) collect c(k);
  313. var3:=append(var1,var2);
  314. %write var3;
  315. on rational;
  316. pseudo3:=pseudorem(b*df(d,x),d,x);
  317. quo3:=part(pseudo3,3)/part(pseudo3,2);
  318. temp:=b*df(d,x)/d;
  319. temp:=pseudorem(num(temp),den(temp),x);
  320. temp:=part(temp,3)/part(temp,2);
  321. %write "temp is ", temp;
  322. r:=b*df(cc,x)-cc*temp+d*aa;% write "r is: ", r;
  323. for k:=0:(mm+nn-1) do
  324. <<
  325. %on factor;
  326. neil(k):=coeffn(pp,x,k)-coeffn(r,x,k);
  327. %write "neil(k)= ", neil(k);
  328. >>;
  329. neil1:=for k:=0:(mm+nn-1) collect neil(k)=0;
  330. %write "neil1= ", neil1;
  331. sol:=solve(neil1,var3);% write "sol= ", sol;
  332. sol:=first(sol);% write "sol= ", sol;
  333. aa:=sub(sol,aa);
  334. %write "aa= ", aa;
  335. %aa:=for k:=1:mm sum(part(sol,k));
  336. cc:=sub(sol,cc);% write "cc is ", cc;
  337. ans1:=cc/d;
  338. ans2:=int(poly_part,x);
  339. ans3:=(aa/b);
  340. output:={ans1,ans2,ans3};
  341. return output;
  342. end;
  343. % -------------------------------------------------------------------------
  344. %in "eea"; in "rem"; in "phi";
  345. expr procedure newton(a,p,u1,w1,B);
  346. begin scalar alpha,gamma,eea_result,s,tt,u,w,ef,modulus,c,sigma,
  347. sigma_tilde,tau, tau_tilde,re,r,quo;
  348. alpha:=lcof(a,x);
  349. a:=alpha*a;
  350. gamma:=alpha;
  351. %a:=gamma*a;
  352. %u1:=n(u1,x);
  353. u1:=phi(u1,x,p); write "u1 is ", u1;
  354. off modular;
  355. w1:=phi(alpha*w1,x,p); off modular;% write "w1 is ", w1;
  356. %w1:=phi(alpha*w1,x,p); off modular;% write "w1 is ",w1;
  357. eea_result:=gcd_ex(u1,w1,x);
  358. on modular; setmod p;
  359. s:=part(eea_result,1); tt:=part(eea_result,2);
  360. on modular; setmod p;
  361. u:=replace_lc(u1,x,gamma); w:=replace_lc(w1,x,alpha);
  362. off modular;
  363. ef:=a-u*w; off modular; modulus:=p;
  364. %write "ef is ", ef; write "u,w are ", u,w;
  365. % iterate until either the factorisation in Z[x] is obtained, or else
  366. % the bound on modulus is reached
  367. on modular; setmod p;
  368. while(ef neq 0 and modulus<2*B*gamma) do
  369. <<
  370. c:=ef/modulus;% write "c is ", c; off modular;
  371. sigma_tilde:=phi(s*c,x,p); off modular;
  372. tau_tilde:=phi(tt*c,x,p); off modular;
  373. %
  374. re:=pseudorem(sigma_tilde,w1,x);
  375. r:=part(re,1)/part(re,2); quo:=part(re,3)/part(re,2);
  376. sigma:=re; tau:=phi(tau_tilde+quo*u1,x,p); off modular;
  377. % update the factors and compute the error
  378. u:=u+tau*modulus; w:=w+sigma*modulus;
  379. % write "u is ",u; write "w is ",w; write "ef is ", ef;
  380. ef:=a-u*w; modulus:=modulus*p;
  381. >>;
  382. % check termination status
  383. if(ef=0) then << u:=u; w:=w/gamma; >>
  384. else rederr "nsfe";
  385. return {u,w};
  386. end;
  387. %trst newton;
  388. %newton(12*x^3+10*x^2-36*x+35,5,x,x^2+3,10000);
  389. % in "phi.red";
  390. % in "eea.red"; in "rem.red"; %in "replace_lc";
  391. clear p;
  392. %trst newton;trst newton;
  393. %newton(12*x^3+10*x^2-36*x+35,5,2*x,x^2+2,10000)
  394. % -------------------------------------------------------------------------
  395. expr procedure replace_lc(exp,var,val);
  396. begin scalar lead_term, new_lead_term,red;
  397. lead_term:=lterm(exp,var);
  398. red:=reduct(exp,var);
  399. new_lead_term:=lead_term/lcof(exp,var);
  400. new_lead_term:=new_lead_term*val;
  401. new_exp:=new_lead_term+red;
  402. return new_exp;
  403. end;
  404. % -------------------------------------------------------------------------
  405. % in "rem"; in "eea";
  406. % routine to solve the polynomial diophantine equation
  407. % s(x)a(x)+t(x)b(x)=c(x) for the unknown polynomials s and t
  408. expr procedure polydi(a,b,c,x);
  409. begin scalar q,r, sigma,tau, s,tt,sol,sigma_tilde,tau_tilde,g;
  410. on rational;
  411. g:=gcd(a,b);
  412. s:=part(gcd_ex(a,b,x),1);
  413. tt:=part(gcd_ex(a,b,x),2);
  414. sol:=(s*c/g)*a+(tt*c/g)*b;
  415. % here, sol=c(x), our right hand side
  416. sigma_tilde:=s*c/g;
  417. tau_tilde:=tt*c/g;
  418. result:=pseudorem(sigma_tilde,b/g,x);
  419. q:=part(result,3)/part(result,2);
  420. r:=part(result,1)/part(result,2);
  421. sigma:=r;
  422. tau:=tau_tilde+(q*(a/g));
  423. return {sigma,tau};
  424. end;
  425. %in "rem"; in "eea";
  426. %trst polydi;
  427. %polydi(x+(7/3),1,294,x);
  428. %polydi(x^2+(7/6)*x+(1/3),2*x+(7/6),-(4425/2)*x-(5525/4),x);
  429. % -------------------------------------------------------------------------
  430. expr procedure phi(exp,var,p);
  431. begin scalar prime;
  432. prime:=p;
  433. if(primep p) then << on modular;
  434. setmod p;
  435. exp:=exp mod p;% off modular;
  436. >> else rederr "p sahould be prime";
  437. return exp;
  438. end;
  439. expr procedure nn(exp,var,p);
  440. begin scalar lcoef;
  441. lcoef:=lcof(exp,var);
  442. if(primep p) then << on modular; setmod p;
  443. exp:=exp/lcoef;
  444. >> else rederr "p should be prime";
  445. return exp;
  446. end;
  447. off modular;
  448. %in "ratint" %in "examples"
  449. %in "make_monic"
  450. %operator c, rtof,v, alpha;
  451. load_package arnum;
  452. %load_package assist
  453. expr procedure not_numberp(x);
  454. if (not numberp(x)) then t else nil;
  455. operator log_sum;
  456. expr procedure rt(a,b,x);
  457. begin scalar vv, j,k,i,current,sol,res,cc,b_prime,extra_term,
  458. current1,vvv,integral, eqn,d,v_list, sol1,sol2, temp, temp2;
  459. b_prime:=df(b,x);
  460. v_list:={};
  461. on rational;
  462. res:=resultant(a-z*b_prime,b,x);
  463. on rational; on ifactor;
  464. res:= old_factorize(res);
  465. res:=extractlist(res, not_numberp);
  466. res:=make_mon(res,z);
  467. res:=mkset(res); % removes duplicates by turning list into a set
  468. %write "res is ", res;
  469. integral:=0;
  470. for k:=1:arglength(res) do
  471. <<
  472. current:=part(res,k); %write "current is ", current;
  473. d:=deg(current,z); %write "d is ", d;
  474. if(d=1) then
  475. <<
  476. sol:=solve(current=0,z);
  477. sol:=part(sol,1);
  478. cc:=part(sol,2);% write "cc is ", cc;
  479. vv:=gcd(a-cc*b_prime,b);% write "vv is " , vv;
  480. vv:=vv/(lcof(vv,x));
  481. extra_term:=append({cc},{log(vv)});% write extra_term;
  482. extra_term:=part(extra_term,1)*part(extra_term,2);%write extra_term;
  483. integral:=extra_term+integral; %write "integral is ", integral
  484. if(lisp !*traceratint) then write "integral in Rothstein T is ", integral;
  485. >>
  486. else
  487. <<
  488. current:=sub(z=alpha,current);% write "current is ", current;
  489. current1:=sub(alpha=alp,current);% write "current1 is ", current1;
  490. off mcd; current:=current;
  491. defpoly(current);
  492. on mcd;
  493. %write "alpha is ", alpha; %write part(alpha,1);
  494. a:=sub(x=z,a); b:=sub(x=z,b); b_prime:=sub(x=z,b_prime);
  495. vv:=gcd(a-alpha*b_prime,b); % write "vv is ", vv; % OK up to here
  496. off arnum;
  497. on fullroots;
  498. %vv:=sub(a1=alpha*(1/part(alpha,1)),vv);
  499. vv:=sub(z=x,vv); % vv:=sub(a1=part(alpha,1)*alpha,vv);
  500. %write "vv is ", vv;
  501. %write "deg is ", deg(vv,x);
  502. on rational; on ratarg;
  503. % write "deg is ", deg(vv,x);
  504. if(deg(vv,x)>2) then
  505. <<
  506. % we want to give the answer not in terms of a complete pf decomposition,
  507. % but without splitting the field
  508. integral:=integral+log_sum(alpha_a,current1,0,alpha_a*log(vv),x);
  509. integral:=sub(alpha_a=alpha,integral);
  510. %integral:=sub(a1=part(alpha,1)*alpha,integral)
  511. integral:=sub(alp=alpha,integral);
  512. if(lisp !*traceratint) then write "integral in Rothstein T is ", integral;
  513. >>
  514. else % degree less than or eq to 2, so no problem solving vv=0
  515. <<
  516. % write "current is ", current;
  517. current:=sub(alpha=beta,current);
  518. vv:=sub(alpha=beta,vv);
  519. integral:=integral+log_sum(beta,current,0,beta*log(vv));
  520. % vvv:=solve(vv=0,x);
  521. %vvv:=sub(a1=1/alp,vvv); write "vvv is ", vvv;
  522. %eqn:=part(part(vvv,1),1)-part(part(vvv,1),2);
  523. %write "eqn is ", eqn;
  524. if(d=2) then
  525. <<
  526. sol:=solve(current1=0,alp);
  527. sol1:=part(sol,1); sol2:=part(sol,2);
  528. %write "sol1, 2 are ", sol1, sol2;
  529. c(1):=part(sol1,2); c(2):=part(sol2,2);
  530. %write "c(1), c(2) are ", c(1), c(2)
  531. for j:=1:2 do
  532. <<
  533. v(j):=sub(alp=c(j),eqn);
  534. %integral:=integral+c(j)*log(v(j));
  535. % write "integral is ", integral;
  536. >>;
  537. >>
  538. else
  539. <<
  540. k:=1;
  541. %write "d is ", d;
  542. while (k<=d) do
  543. %for k:=1:3 do
  544. <<
  545. c(k):=rtof(current1); % write "c(k) is ", c(k);
  546. v(k):=sub({alp=c(k)},eqn); % write "v(k) is ", v(k);
  547. %integral:=integral+c(k)*log(v(k));
  548. %write "integral is ", integral;
  549. k:=k+1;
  550. >>;
  551. >>;
  552. >>;
  553. >>;
  554. lisp null remprop ('alpha,'currep);
  555. lisp null remprop ('alpha,'idvalfn);
  556. >>;
  557. return(integral);
  558. end;
  559. expr procedure dependp(exp,x);
  560. if(freeof(exp,x) and not numberp(exp)) then nil else t ;
  561. % -------------------------------------------------------------------------
  562. % procedure to integrate any rational function, using the implementations of
  563. % the above algorithms.
  564. expr procedure ratint(p,q,x);
  565. begin scalar s_list,first_term, second_term, r_part, answer;
  566. % check input carefully
  567. if(not dependp(p,x) and not dependp(q,x)) then
  568. return (p/q)*x
  569. else <<
  570. if(not dependp(p,x) and dependp(q,x)) then return
  571. p*ratint(1,q,x)
  572. else <<
  573. if( dependp(p,x) and not dependp(q,x)) then return
  574. (1/q)*int(p,x);
  575. >>;
  576. >>;
  577. if(numberp p and numberp q) then return (p/q)*x;
  578. %if(not polynomp p or not polynomp q) then rederr "input must be polynomials"
  579. if(lisp !*traceratint) then write "performing Howoritz reduction on ", p/q;
  580. s_list:=howy(p,q,x);
  581. if(lisp !*traceratint) then write "Howoritz gives: ", s_list;
  582. first_term:=part(s_list,1);
  583. second_term:=part(s_list,2);
  584. r_part:=part(s_list,3);% write "r_part is ", r_part;
  585. if(lisp !*traceratint) then write "computing Rothstein Trager on ", r_part;
  586. r_part:=rt(num(r_part),den(r_part),x);
  587. answer:={first_term+second_term,r_part};
  588. return (answer);
  589. end;
  590. % examples
  591. %exp1:=441*x^7+780*x^6-2861*x^5+4085*x^4+7695*x^3+3713*x^2-43253*x+24500;
  592. %exp2:=9*x^6+6*x^5-65*x^4+20*x^3+135*x^2-154*x+49;
  593. %k:=36*x^6+126*x^5+183*x^4+(13807/6)*x^3-407*x^2-(3242/5)*x+(3044/15);
  594. %l:=(x^2+(7/6)*x+(1/3))^2*(x-(2/5))^3;
  595. %ratint(k,l,x);
  596. %aa:=7*x^13+10*x^8+4*x^7-7*x^6-4*x^3-4*x^2+3*x+3;
  597. %bb:=x^14-2*x^8-2*x^7-2*x^4-4*x^3-x^2+2*x+1;
  598. %trst ratint;
  599. %ratint(aa,bb,x);
  600. %-----------------------------------------------------------------------------
  601. end;