%---------------------------------------------------------------------------- % % these programs are written to sort the Taylor problem out; namely, the % problem of extracting the leading exponent together with its sign from % a taylor expression. % %---------------------------------------------------------------------------- % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the relevant copyright % notice, this list of conditions and the following disclaimer. % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, % THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR % PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR % CONTRIBUTORS % BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. % module expon; load_package taylor; algebraic; expr procedure mrv_split(exp); begin scalar temp,current,ans; off mcd; ans:={}; if lisp(atom exp) then temp:={exp} else temp:=for k:=1:arglength(exp) collect part(exp,k); write "temp is ", temp; for k:=1:arglength(temp) do << current:=part(temp,k); if (lisp atom current) then << if(not freeof(current,ww)) then ans:=append(ans,{current}) else nil; >> else if (not freeof(current,expt)) then ans:=append(ans,{current}) else nil; >>; return ans; end; %load_package taylor; expr procedure collect_power(li); begin scalar ans; on rational; on exp; ans:=for k:=1:length(li) collect lpower(part(li,k),ww); return ans; end; %collect_power(mrv_split(1/2*(ww+x*ww^-1+2))); expr procedure mrv_conv(li); % converts our list of powers to exponents begin scalar ans,current; ans:={}; for k:=1:length(li) do << current:=part(li,k); %write "current is ", current; if (lisp atom current) then << if (not freeof(current,ww)) then ans:=append(ans,{1}) else nil; >> else if (part(current,0)=expt) then ans:=append(ans,{part(current,2)}) else nil; >>; return ans; end; %collect_power(mrv_split(1/2*(ww+x*ww^-1+2))); %mrv_conv(ws); %load_package assist; expr procedure mrv_find_expt(exp); begin scalar spli, coll, con, ans,ans2; %spli:=mrv_split(exp); %write "split is ", spli; coll:=collect_power(spli); write "collect is "; coll; con:=mrv_conv(coll); write "con is ", con; ans:=sortnumlist(con); write "ans is ", ans; ans2:=part(ans,1); return ans2; end; % we get something like % (expt(ww -1) %-------------------------------------------------------------------------- symbolic procedure mrv_find(u); begin off mcd; off factor; off exp; if atom u then << if (freeof(u,'ww)) then << if(numberp(u)) then return {'number,u} else if (u='e) then return {'number,'e} else return {'x_exp,u}; >> else return {'expt,'ww,1} >> else if (car u='expt) then return {'expt, cadr u, caddr u} else if (car u='plus) then << if (atom cadr u and atom caddr u) then << if (length(cdr u)>2) then << if ((cadr u='ww) and freeof(caddr u,'ww)) then return append({'expt,cadr u,1},mrv_find('plus . cddr u)) else return append(mrv_find(cadr u), 'plus . cddr u) >> else if (caddr u='ww) and freeof(cadr u,'ww) then return {'x_exp,cadr u,'expt,'ww,1} else if (cadr u='ww and freeof(caddr u,'ww)) then return append({'expt,cadr u,1},mrv_find caddr u) else return append(mrv_find(cadr u),mrv_find(caddr u)) >> else if (atom cadr u and pairp caddr u) then << if (length(cdr u)>2) then << if (cadr u='ww) then return append({'expt,'ww,1},mrv_find('plus . cddr u)) else return append(mrv_find(cadr u),mrv_find('plus . cddr u)) >> else return append(mrv_find(cadr u),mrv_find(caddr u)) >> else if (pairp cadr u and pairp caddr u) then << if (length(cdr u)>2) % plus has more than 2 args then return append(mrv_find(cadr u),mrv_find('plus . cddr u)) else return append(mrv_find(cadr u),mrv_find(caddr u)) >> else if (pairp cadr u and atom caddr u) then << if (length(cdr u)>2) %plus has more than two args then << if (caddr u='ww) then return mrv_find(cadr u).{'expt,'ww,1}.mrv_find('plus . cddr u) else if (numberp(caddr u)) then return mrv_find(cadr u).({'number,caddr u}.mrv_find('plus . cdr u)) else nil >> else return append(mrv_find(cadr u),mrv_find(caddr u)) >> else return append(mrv_find(cadr u),{caddr u}) >> else if (car u='lminus) then << if (numberp cadr u) then return {'number,u} else return mrv_find(cadr u) >> else if (car u='quotient) then << if (numberp(cadr u) and numberp(caddr u)) then return {'number,cadr u, caddr u} else return append(mrv_find(cadr u), mrv_find(caddr u)) >> else if (car u='minus) then << if (atom cdr u) then return mrv_find(cadr u) else if (cadr u='expt and caddr u='ww) then return append('minus . mrv_find(cadr u),mrv_find(caddr u)) else return ('minus . mrv_find(cadr u)) >> else if (car u='times) then << if (atom cadr u and atom caddr u) then <> else if (atom cadr u and pairp caddr u) then <> else if (pairp cadr u and pairp caddr u) then <2 % times has +2 args then return append(mrv_find(cadr u),mrv_find('times . cddr u)) else return append(mrv_find(cadr u),mrv_find(caddr u)) >> else if (pairp cadr u and atom caddr u) then <> %else nil >> %else return mrv_find(cdr u) end; algebraic; algebraic procedure mrv_fin(u); lisp ('list.mrv_find(u)); %---------------------------------------------------------------------------- % input to this procedure is a list % output is a list, containing all the exponents, marked expt, and any % numbers, flagged number % e.g. ww^-1+ww^-2 +2 % apply fin yields {expt,ww,-1,expt,ww,-2,number,2} % now apply mrv_find_numbers to this gives % {expt,-1,expt,-2,number,2} % the presence of the number means that there is a power of ww^0 present, % ie a constant term. If any of the expoents in the list are less than zero, % then we require the lowest one; if they are all positive, then zero is the % answer to be returned expr procedure mrv_find_numbers(li); begin scalar current,expt_list,ans,l,finished; % first, second, third; off mcd; on rational; on exp; li:=li; expt_list:={}; ans:={}; for k:=1:(length(li)-1) do << current:=part(li,k); if(current=expt) then << if (part(li,k+1)=ww) then expt_list:=append(expt_list,{expt,part(li,k+2)}); >> else <>; >>; % there is no x terms or numbers in the series exp return expt_list; end; %---------------------------------------------------------------------------- expr procedure mrv_find_least_expt(exp); begin scalar ans,find, current,result,expt_list,expt_list2,num_list, x_list; off mcd; % this causes a lot of problems when on, and some problems when off, % so I don't think I can win!!! expt_list:={}; num_list:={}; % initialisations x_list:={}; find:=mrv_fin(exp); ans:=mrv_find_numbers(find); if(lisp !*tracelimit) then write "exponent list is ", ans; %ans:=delete_all(-x,ans); if(freeof(ans,number)) then % there were no numbers in series exp, only % exponents << for k:=1:(arglength(ans)-1) do <>; >> else if ((part(ans,k)=expt) and part(ans,k-1) neq (lisp mk!*sq simp 'minus)) then <> else nil; >>; %ans:=sortnumlist(ans); %result:=part(ans,1); %write "got up to here OK"; >> else << for k:=1:arglength(ans)-1 do <> else if (current=number) then num_list:=append(num_list,{part(ans,k+1)}) else if ((current=lisp mk!*sq simp 'minus) and numberp(part(ans,k+2)) and part(ans,k+2)<0) then expt_list:=append(expt_list,{lisp mk!*sq simp 'minus,part(ans,k+2)}) else nil; >>; >>; if (expt_list={}) % we have only a number to deal with; ie power of % ww in series is 0 then return append({number},num_list) else if (num_list={}) then <> else << % our list contains a power with a minus sign % want to find the least exponent, and then see if it is tagged % with a minus sign expt_list2:=expt_list; expt_list2:=delete_all((lisp mk!*sq simp 'minus),expt_list2); % list is now without minus expt_list2:=sortnumlist(expt_list2); expt_list2:=part(expt_list2,1); % smallest element, this is our expt % now want to check the sign of w with this exponent l:=0; finished:=0; while (l<=(arglength(expt_list)-1) and finished=0) do << if ((part(expt_list,l)=(lisp mk!*sq simp 'minus)) and (part(expt_list,l+1)=expt_list2)) then << finished:=1; expt_list2:=append({lisp 'minus},{expt_list2}); >> else l:=l+1; >>; return expt_list2; >>; >> else <> else << % doesn't matter what is in the number list, as minus is % present, meaning there is a negative exponent here expt_list:=delete_all(lisp mk!*sq simp 'minus, expt_list); expt_list:=sortnumlist(expt_list); return {lisp 'minus,part(expt_list,1)}; >>; >>; end; endmodule; end;