algint.red 163 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120
  1. module afactor;
  2. % Author: James H. Davenport.
  3. fluid '(!*galois !*noextend !*sqfree afactorvar listofnewsqrts
  4. monicpart);
  5. global '(!*trfield);
  6. exports afactor;
  7. imports exptf,ordop,!*multf,addf,makemainvar,algebraicsf,divsf,contents;
  8. imports quotf!*,negf,sqfr!-norm2,prepf,gcdinonevar,algint!-subf,!*q2f;
  9. imports jfactor,printsf;
  10. % internal!-fluid '(monicpart);
  11. symbolic procedure afactor(u,v);
  12. % Factorises U over the algebraics as a polynomial in V (=afactorvar).
  13. begin
  14. scalar afactorvar,!*noextend,!*sqfree;
  15. % !*sqfree is known to be square free (from sqfr-norm).
  16. !*noextend:=t; % else we get recursion.
  17. afactorvar:=v;
  18. if !*trfield
  19. then <<
  20. princ "We must factorise the following over: ";
  21. for each u in listofnewsqrts do <<princ u; princ " " >>;
  22. terpri();
  23. printsf u >>;
  24. v:=algfactor u;
  25. if !*trfield then <<
  26. printc "factorises as ";
  27. mapc(v,function printsf) >>;
  28. return v
  29. end;
  30. symbolic procedure algfactor2(f,a);
  31. if null a
  32. then for each u in jfactor(f,mvar f) collect numr u
  33. else if algebraicsf f
  34. then algfactor3(f,a)
  35. else begin
  36. scalar w;
  37. if !*trfield then <<
  38. princ "to be factorized over ";
  39. for each u in a do << princ u; princ " " >>;
  40. terpri();
  41. printsf f >>;
  42. if (!*galois neq 2) and
  43. (numberp red f) and
  44. (not numberp argof car a)
  45. then return algfactor2(f,cdr a);
  46. % assumes we need never express a root of a number in terms of
  47. % non-numbers.
  48. w:=algfactor2(f,nil);
  49. if null cdr w
  50. then return algfactor3(f,a)
  51. else return 'partial.w
  52. end;
  53. symbolic procedure algfactor3(f,a);
  54. begin
  55. scalar ff,w,gg,h,p;
  56. w:=sqfr!-norm2(f,mvar f,car a);
  57. !*sqfree:=car w;
  58. w:=cdr w;
  59. ff:=algfactor2(!*sqfree,cdr a);
  60. if car ff eq 'partial then <<
  61. p:='partial;
  62. ff:=cdr ff >>;
  63. if null cdr ff
  64. then return list f;
  65. %does not factor.
  66. a:=car a;
  67. gg:=cadr w;
  68. w:=list list(afactorvar,'plus,afactorvar,prepf car w);
  69. h:=for each u in ff
  70. collect (!*q2f algint!-subf(gcdinonevar(u,gg,afactorvar),w));
  71. if p eq 'partial
  72. then h:=p.h;
  73. return h
  74. end;
  75. symbolic procedure algfactor u;
  76. begin
  77. scalar a,aa,z,w,monicpart;
  78. z:= makemainvar(u,afactorvar);
  79. if ldeg z iequal 1
  80. then return list u;
  81. z:=lc z;
  82. if z iequal 1
  83. then go to monic;
  84. if algebraicsf z
  85. then u:=!*multf(u,numr divsf(1,z));
  86. % this de-algebraicises the top coefficient.
  87. u:=quotf!*(u,contents(u,afactorvar));
  88. z:=makemainvar(u,afactorvar);
  89. if lc z neq 1
  90. then if lc z iequal -1
  91. then u:=negf u
  92. else <<
  93. w:=lc z;
  94. u:=makemonic z >>;
  95. monic:
  96. aa:=listofnewsqrts;
  97. if algebraicsf u
  98. then go to normal;
  99. a:=cdr aa;
  100. % we need not try for the first one, since algfactor2
  101. % will do this for us.
  102. z:=t;
  103. while a and z do begin
  104. scalar alg,v;
  105. alg:=car a;
  106. a:=cdr a;
  107. v:=algfactor3(u,list alg);
  108. if null cdr v
  109. then return;
  110. if car v eq 'partial
  111. then v:=cdr v;
  112. % we do not mind if the factorisation is only partial.
  113. a:=mapcan(v,function algfactor);
  114. z:=nil
  115. end;
  116. monicpart:=w;
  117. if null z
  118. then if null w
  119. then return a
  120. else return mapcar(a,function demonise);
  121. normal:
  122. z:=algfactor2(u,aa);
  123. monicpart:=w;
  124. if null cdr z or (car z neq 'partial)
  125. then if null w
  126. then return z
  127. else return mapcar(z,function demonise);
  128. % does not factor.
  129. if null w
  130. then return mapcan(cdr z,function algfactor)
  131. else return for each u in z conc
  132. algfactor demonise u;
  133. end;
  134. symbolic procedure demonise u;
  135. % Replaces afactorvar by afactorvar*monicpart in u.
  136. if atom u
  137. then u
  138. else if afactorvar eq mvar u
  139. then addf(demonise red u,
  140. !*multf(lt u .+ nil,exptf(monicpart,ldeg u)))
  141. else if ordop(afactorvar,mvar u)
  142. then u
  143. else addf(demonise red u,
  144. !*multf(!*p2f lpow u,demonise lc u));
  145. symbolic procedure makemonic u;
  146. % U is a makemainvar'd polynomial.
  147. begin
  148. scalar v,w,x,xx;
  149. v:=mvar u;
  150. x:=lc u;
  151. xx:=1;
  152. w:=!*p2f lpow u;% the monic term.
  153. u:=red u;
  154. for i:=(isub1 ldeg w) step -1 until 1 do begin
  155. if atom u
  156. then go to next;
  157. if mvar u neq v
  158. then go to next;
  159. if ldeg u iequal i
  160. then w:=addf(w,!*multf(lc u,
  161. !*multf(!*p2f lpow u,xx)));
  162. u:=red u;
  163. next:
  164. xx:=!*multf(x,xx)
  165. end;
  166. w:=addf(w,!*multf(u,xx));
  167. return w
  168. end;
  169. % unfluid '(monicpart);
  170. endmodule;
  171. module algfn;
  172. % Author: James H. Davenport.
  173. % Check if an expression is in a pure algebraic extension of
  174. % Q(all "constants")(var).
  175. exports algfnpl,algebraicsf;
  176. imports simp,interr,dependsp,dependspl;
  177. symbolic procedure algfnp(pf,var);
  178. if atom pf then t
  179. else if not atom car pf then interr "Not prefix form"
  180. else if car pf eq '!*sq then algfnsq(cadr pf,var)
  181. else if car pf eq 'expt
  182. then if not algint!-ratnump caddr pf
  183. then (not dependsp(cadr pf,var))
  184. and (not dependsp(caddr pf,var))
  185. else algfnp(cadr pf,var)
  186. else if not memq(car pf,'(minus plus times quotient sqrt))
  187. % JPff fiddle
  188. then not dependspl(cdr pf,var)
  189. else algfnpl(cdr pf,var);
  190. symbolic procedure algfnpl(p!-list,var);
  191. null p!-list or algfnp(car p!-list,var) and algfnpl(cdr p!-list,var);
  192. symbolic procedure algfnsq(sq,var);
  193. algfnsf(numr sq,var) and algfnsf(denr sq,var);
  194. symbolic procedure algfnsf(sf,var);
  195. atom sf
  196. or algfnp(mvar sf,var) and algfnsf(lc sf,var) and algfnsf(red sf,var);
  197. symbolic procedure algint!-ratnump q;
  198. if atom q then numberp q
  199. else car q eq 'quotient and (numberp cadr q) and (numberp caddr q);
  200. symbolic procedure algebraicsf u;
  201. if atom u then nil
  202. else algebraicp mvar u or algebraicsf lc u or algebraicsf red u;
  203. symbolic procedure algebraicp u;
  204. if atom u then nil
  205. else if car u eq 'expt then 1 neq denr simp caddr u
  206. else car u eq 'sqrt;
  207. endmodule;
  208. module algnums;
  209. % Author: James H. Davenport.
  210. exports denr!-algno;
  211. symbolic procedure denr!-algno u;
  212. % Returns the true denominator of the algebraic number u.
  213. begin
  214. scalar sqlist,n,m,u!*!*j,d,isub1n;
  215. u!*!*j:=1 ./ 1;
  216. sqlist:=sqrtsinsq(u,nil);
  217. sqlist:=multbyallcombinations(list(1 ./ 1),
  218. for each u in sqlist
  219. collect !*kk2q u);
  220. n:=0;
  221. sqlist:=for each u in sqlist collect
  222. (numr u) . (n:=iadd1 n);
  223. % format is of an associtaion list.
  224. n:=length sqlist;
  225. m:=mkvect n;
  226. isub1n:=isub1 n;
  227. for i:=0:n do
  228. putv(m,i,mkvect2(n,nil ./ 1));
  229. putv(getv(m,0),cdr assoc(1,sqlist),1 ./ 1);
  230. % initial matrix is now set up.
  231. for j:=1:n do begin
  232. scalar v,w;
  233. u!*!*j:=!*multsq(u!*!*j,u);
  234. dump!-sqrts!-coeffs(u!*!*j,sqlist,getv(m,j));
  235. v:=firstlinearrelation(m,n);
  236. if null v
  237. then return;
  238. if last!-non!-zero v > j
  239. then return;
  240. if (w:=getv(v,j)) neq (1 ./ 1)
  241. then <<
  242. w:=!*invsq w;
  243. for i:=0:j do
  244. putv(v,i,!*multsq(w,getv(v,i))) >>;
  245. m:=v;
  246. n:=j;
  247. return
  248. end;
  249. % Now m is a monic polynomial, minimal for u, of degree n.
  250. d:=1;
  251. for i:=0:isub1 n do begin
  252. scalar v,prime;
  253. v:=denr getv(m,i);
  254. prime:=2;
  255. loop:
  256. if v = 1
  257. then return;
  258. if not zerop cdr divide(v,prime)
  259. then prime:=nextprime(prime)
  260. else <<
  261. d:=d*prime;
  262. for i:=0:n do
  263. putv(v,i,multsq(getv(v,i),1 ./ (prime ** (n-i)) )) >>;
  264. go to loop;
  265. end;
  266. return d;
  267. end;
  268. symbolic procedure dump!-sqrts!-coeffs(u,sqlist,vec);
  269. begin
  270. scalar w;
  271. dump!-sqrts!-coeffs2(numr u,sqlist,vec,1);
  272. u:=1 ./ denr u;
  273. if denr u neq 1
  274. then for i:=0:upbv vec do
  275. if numr(w:=getv(vec,i))
  276. then putv(vec,i,!*multsq(u,w));
  277. end;
  278. symbolic procedure dump!-sqrts!-coeffs2(u,sqlist,vec,sqrtssofar);
  279. if null u
  280. then nil
  281. else if numberp u
  282. then putv(vec,cdr assoc(sqrtssofar,sqlist),u)
  283. else <<
  284. dump!-sqrts!-coeffs2(red u,sqlist,vec,sqrtssofar);
  285. dump!-sqrts!-coeffs2(lc u,sqlist,vec,!*multf(sqrtssofar,
  286. !*k2f mvar u)) >>;
  287. symbolic procedure last!-non!-zero vec;
  288. begin
  289. scalar n;
  290. for i:=0:upbv vec do
  291. if numr getv(vec,i)
  292. then n:=i;
  293. return n
  294. end;
  295. endmodule;
  296. module antisubs;
  297. % Author: James H. Davenport.
  298. exports antisubs;
  299. imports purge,interr,dependsp;
  300. symbolic procedure antisubs(place,x);
  301. % Produces the inverse substitution to a substitution list.
  302. begin
  303. scalar answer,w;
  304. while place and
  305. (x=caar place) do<<
  306. w:=cdar place;
  307. % w is the substitution rule.
  308. if atom w
  309. then if w neq x
  310. then interr "False atomic substitution"
  311. else nil
  312. else answer:=(x.anti2(w,x)).answer;
  313. place:=cdr place>>;
  314. if null answer
  315. then answer:=(x.x).answer;
  316. return answer
  317. end;
  318. symbolic procedure anti2(eexpr,x);
  319. %Produces the function inverse to the eexpr provided.
  320. if atom eexpr
  321. then if eexpr eq x
  322. then x
  323. else interr "False atom"
  324. else if car eexpr eq 'plus
  325. then deplus(cdr eexpr,x)
  326. else if car eexpr eq 'minus
  327. then subst(list('minus,x),x,anti2(cadr eexpr,x))
  328. else if car eexpr eq 'quotient
  329. then if dependsp(cadr eexpr,x)
  330. then if dependsp(caddr eexpr,x)
  331. then interr "Complicated division"
  332. else subst(list('times,caddr eexpr,x),x,anti2(cadr eexpr,x))
  333. else if dependsp(caddr eexpr,x)
  334. then subst(list('quotient,cadr eexpr,x),x,
  335. anti2(caddr eexpr,x))
  336. else interr "No division"
  337. else if car eexpr eq 'expt
  338. then if caddr eexpr iequal 2
  339. then subst(list('sqrt,x),x,anti2(cadr eexpr,x))
  340. else interr "Unknown root"
  341. else if car eexpr eq 'times
  342. then detimes(cdr eexpr,x)
  343. else if car eexpr eq 'difference
  344. then deplus(list(cadr eexpr,list('minus,caddr eexpr)),x)
  345. else interr "Unrecognised form in antisubs";
  346. symbolic procedure detimes(p!-list,var);
  347. % Copes with lists 'times.
  348. begin
  349. scalar u,v;
  350. u:=deplist(p!-list,var);
  351. v:=purge(u,p!-list);
  352. if null v
  353. then v:=var
  354. else if null cdr v
  355. then v:=list('quotient,var,car v)
  356. else v:=list('quotient,var,'times.v);
  357. if (null u) or
  358. (cdr u)
  359. then interr "Weird multiplication";
  360. return subst(v,var,anti2(car u,var))
  361. end;
  362. symbolic procedure deplist(p!-list,var);
  363. % Returns a list of those elements of p!-list which depend on var.
  364. if null p!-list
  365. then nil
  366. else if dependsp(car p!-list,var)
  367. then (car p!-list).deplist(cdr p!-list,var)
  368. else deplist(cdr p!-list,var);
  369. symbolic procedure deplus(p!-list,var);
  370. % Copes with lists 'plus.
  371. begin
  372. scalar u,v;
  373. u:=deplist(p!-list,var);
  374. v:=purge(u,p!-list);
  375. if null v
  376. then v=var
  377. else if null cdr v
  378. then v:=list('plus,var,list('minus,car v))
  379. else v:=list('plus,var,list('minus,'plus.v));
  380. if (null u) or
  381. (cdr u)
  382. then interr "Weird addition";
  383. return subst(v,var,anti2(car u,var))
  384. end;
  385. endmodule;
  386. module coates;
  387. % Author: James H. Davenport.
  388. fluid '(intvar magiclist nestedsqrts previousbasis sqrt!-intvar
  389. taylorasslist thisplace);
  390. global '(!*tra !*trmin coates!-fdi);
  391. exports coates,makeinitialbasis,checkpoles,multbyallcombinations;
  392. symbolic procedure coates(places,mults,x);
  393. begin
  394. scalar u,tt;
  395. tt:=readclock();
  396. u:=coates!-hpfsd(places,mults);
  397. if !*tra or !*trmin then
  398. printc list ('coates,'time,readclock()-tt,'milliseconds);
  399. return u
  400. end;
  401. symbolic procedure coates!-real(places,mults);
  402. begin
  403. scalar thisplace,u,v,save;
  404. if !*tra or !*trmin then <<
  405. princ "Find function with zeros of order:";
  406. printc mults;
  407. if !*tra then
  408. princ " at ";
  409. terpri!*(t);
  410. if !*tra then
  411. mapc(places,function printplace) >>;
  412. % v:=placesindiv places;
  413. % V is a list of all the substitutors in PLACES;
  414. % u:=mkunique sqrtsintree(v,intvar,nil);
  415. % if !*tra then <<
  416. % princ "Sqrts on this curve:";
  417. % terpri!*(t);
  418. % superprint u >>;
  419. % algnos:=mkunique mapcar(places,function basicplace);
  420. % if !*tra then <<
  421. % printc "Algebraic numbers where residues occur:";
  422. % superprint algnos >>;
  423. v:=mults;
  424. for each uu in places do <<
  425. if (car v) < 0
  426. then u:=(rfirstsubs uu).u;
  427. v:=cdr v >>;
  428. thisplace:=list('quotient,1,intvar);
  429. if member(thisplace,u)
  430. then <<
  431. v:= finitise(places,mults);
  432. % returns list (places,mults,power of intvar to remove.
  433. u:=coates!-real(car v,cadr v);
  434. if atom u
  435. then return u;
  436. return multsq(u,!*p2q mksp(intvar,caddr v)) >>;
  437. % It is not sufficient to check the current value of U in FRACTIONAL...
  438. % as we could have zeros over infinity JHD 18/8/86;
  439. for each uu in places do
  440. if rfirstsubs uu = thisplace
  441. then u:=append(u,mapcar(cdr uu,function car));
  442. coates!-fdi:=fractional!-degree!-at!-infinity u;
  443. % Do we need to blow everything up by a factor of two (or more)
  444. % to avoid fractional powers at infinity?
  445. if coates!-fdi iequal 1
  446. then return coatesmodule(places,mults,intvar);
  447. if !*tra
  448. then fdi!-print();
  449. places:=mapcar(places,function fdi!-upgrade);
  450. save:=taylorasslist;
  451. u:=coatesmodule(places,
  452. mapcar(mults,function (lambda u;u*coates!-fdi)),
  453. intvar);
  454. taylorasslist:=save;
  455. % u:=fdi!-revertsq u;
  456. % That previous line is junk, I think (JHD 22.8.86)
  457. % just because we blew up the places doesn't mean that
  458. % we should deflate the function, because that has already been done.
  459. return u
  460. end;
  461. symbolic procedure coatesmodule(places,mults,x);
  462. begin
  463. scalar pzero,mzero,u,v,basis,sqrts,magiclist,mpole,ppole;
  464. % MAGICLIST holds the list of extra unknowns created in JHDSOLVE
  465. % which must be found in CHECKPOLES (calling FINDMAGIC).
  466. sqrts:=sqrtsinplaces places;
  467. if !*tra then <<
  468. princ "Sqrts on this curve:";
  469. superprint sqrts >>;
  470. u:=places;
  471. v:=mults;
  472. while u do <<
  473. if 0<car v
  474. then <<
  475. mzero:=(car v).mzero;
  476. pzero:=(car u).pzero >>
  477. else <<
  478. mpole:=(car v).mpole;
  479. ppole:=(car u).ppole >>;
  480. u:=cdr u;
  481. v:=cdr v >>;
  482. % ***time-hack-2***;
  483. if previousbasis then basis:=previousbasis
  484. else basis:=mkvec makeinitialbasis ppole;
  485. u:=completeplaces(ppole,mpole);
  486. basis:=integralbasis(basis,car u,cdr u,x);
  487. basis:=normalbasis(basis,x,0);
  488. u:=coatessolve(mzero,pzero,basis,nil);
  489. % The NIL is the list of special constraints needed
  490. % to force certain poles to occur in the answer.
  491. if atom u
  492. then return u;
  493. v:= checkpoles(list u,places,mults);
  494. if null v
  495. then return 'failed;
  496. if not magiclist
  497. then return u;
  498. u:=removecmsq substitutesq(u,v);
  499. % Apply the values from FINDMAGIC.
  500. if !*tra or !*trmin then <<
  501. printc "These values give the function";
  502. printsq u >>;
  503. magiclist:=nil;
  504. if checkpoles(list u,places,mults)
  505. then return u
  506. else interr "Inconsistent checkpoles"
  507. end;
  508. symbolic procedure makeinitialbasis places;
  509. begin
  510. scalar u;
  511. u:=multbyallcombinations(list(1 ./ 1),
  512. for each u in getsqrtsfromplaces places
  513. collect !*kk2q u);
  514. if !*tra then <<
  515. printc "Initial basis for the space m(x)";
  516. mapc(u,function printsq) >>;
  517. return u
  518. end;
  519. symbolic procedure multbyallcombinations(u,l);
  520. % Produces a list of all elements of u,
  521. % each multiplied by every combination of elements of l.
  522. if null l
  523. then u
  524. else multbyallcombinations(nconc(multsql(car l,u),u),cdr l);
  525. symbolic procedure checkpoles(basis,places,mults);
  526. % Checks that the BASIS really does have all the
  527. % poles in (PLACES.MULTS).
  528. begin
  529. scalar u,v,l;
  530. go to outer2;
  531. outer:
  532. places:=cdr places;
  533. mults:=cdr mults;
  534. outer2:
  535. if null places
  536. then return if magiclist
  537. then findmagic l
  538. else t;
  539. if 0 leq car mults
  540. then go to outer;
  541. u:=basis;
  542. inner:
  543. if null u
  544. then <<
  545. if !*tra
  546. then <<
  547. princ "The answer from the linear equations did";
  548. printc " not have the poles at:";
  549. printplace car places >>;
  550. return nil >>;
  551. v:=taylorform xsubstitutesq(car u,car places);
  552. if taylorfirst v=car mults
  553. then <<
  554. if magiclist
  555. then l:=taylorevaluate(v,car mults) . l;
  556. go to outer >>;
  557. if taylorfirst v < car mults
  558. then interr "Extraneous pole introduced";
  559. u:=cdr u;
  560. go to inner
  561. end;
  562. symbolic procedure coates!-hpfsd(oplaces,omults);
  563. begin
  564. scalar mzero,pzero,mpole,ppole,fun,summzero,answer,places,mults;
  565. places:=oplaces;
  566. mults:=omults;
  567. % Keep originals in case need to use COATES!-REAL directly.
  568. summzero:=0;
  569. % holds the sum of all the mzero's.
  570. while places do <<
  571. if 0<car mults
  572. then <<
  573. summzero:=summzero + car mults;
  574. mzero:=(car mults).mzero;
  575. pzero:=(car places).pzero >>
  576. else <<
  577. mpole:=(car mults).mpole;
  578. ppole:=(car places).ppole >>;
  579. places:=cdr places;
  580. mults:=cdr mults >>;
  581. if summzero > 2 then begin
  582. % We want to combine a zero/pole pair
  583. % so as to reduce the total index before calling coates!-real
  584. % on the remaining zeros/poles.
  585. scalar nplaces,nmults,f,multiplicity,newpole,sqrts,fz,zfound,mult1;
  586. sqrts:=getsqrtsfromplaces ppole;
  587. if !*tra or !*trmin then <<
  588. princ "Operate on divisor:";
  589. printc append(mzero,mpole);
  590. printc "at";
  591. mapc(pzero,function printplace);
  592. mapc(ppole,function printplace) >>;
  593. iterate:
  594. nplaces:=list car pzero;
  595. multiplicity:=car mzero;
  596. nmults:=list 1;
  597. if cdr ppole
  598. then <<
  599. nplaces:=(car ppole) . ( (cadr ppole) . nplaces);
  600. multiplicity:=min(multiplicity,- car mpole,- cadr mpole);
  601. nmults:=(-1) .((-1) . nmults) >>
  602. else <<
  603. nplaces:=(car ppole) . nplaces;
  604. multiplicity:=min(multiplicity,(- car mpole)/2);
  605. nmults:=(-2) . nmults >>;
  606. previousbasis:=nil;
  607. f:=coates!-real(nplaces,nmults);
  608. if atom f
  609. then <<
  610. if !*tra or !*trmin then
  611. printc "Failure: must try whole divisor";
  612. return coates!-real(oplaces,omults) >>;
  613. % newpole:=removezero(findzeros(f,sqrts),car pzero).
  614. fz:=findzeros(f,sqrts);
  615. zfound:=assoc(car pzero,fz);
  616. if not zfound
  617. then interr "Didn't seem to find the zeros we looked for";
  618. if cdr zfound > car mzero
  619. then interr "We found too many zeros";
  620. fz:=delete(zfound,fz);
  621. if !*tra or !*trmin then <<
  622. printc "Replaced by the pole";
  623. if fz then prettyprint fz
  624. else <<terpri(); prin2t "The zero we were already looking for">>;
  625. princ multiplicity;
  626. printc " times" >>;
  627. mult1:=car mzero - multiplicity * cdr zfound;
  628. if mult1 < 0
  629. then << printc "A zero has turned into a pole";
  630. multiplicity:= car mzero / cdr zfound ;
  631. mult1:=remainder(car mzero, cdr zfound); >>;
  632. if zerop mult1
  633. then <<
  634. mzero:=cdr mzero;
  635. pzero:=cdr pzero >>
  636. else rplaca(mzero,mult1);
  637. if null cdr ppole
  638. then <<
  639. if zerop (car mpole + 2*multiplicity)
  640. then <<
  641. ppole:=cdr ppole;
  642. mpole:=cdr mpole >>
  643. else rplaca(mpole,car mpole + 2 * multiplicity) >>
  644. else <<
  645. if zerop (cadr mpole + multiplicity)
  646. then <<
  647. ppole:=(car ppole) . (cddr ppole);
  648. mpole:=(car mpole) . (cddr mpole) >>
  649. else rplaca(cdr mpole,cadr mpole + multiplicity);
  650. if zerop (car mpole + multiplicity)
  651. then <<
  652. ppole:=cdr ppole;
  653. mpole:=cdr mpole >>
  654. else rplaca(mpole,car mpole + multiplicity) >>;
  655. while fz do <<
  656. newpole:=caar fz;
  657. mult1:=multiplicity*(cdar fz);
  658. if newpole member pzero
  659. then begin
  660. scalar m,p;
  661. while newpole neq car pzero do <<
  662. m:=(car mzero).m;
  663. mzero:=cdr mzero;
  664. p:=(car pzero).p;
  665. pzero:=cdr pzero >>;
  666. if mult1 < car mzero then <<
  667. mzero:=(car mzero - mult1) . cdr mzero;
  668. mzero:=nconc(m,mzero);
  669. pzero:=nconc(p,pzero);
  670. return >>;
  671. if mult1 > car mzero then <<
  672. ppole:=newpole.ppole;
  673. mpole:=(car mzero - mult1) . mpole >>;
  674. mzero:=nconc(m,cdr mzero);
  675. pzero:=nconc(p,cdr pzero)
  676. end
  677. else if newpole member ppole then begin
  678. scalar m,p;
  679. m:=mpole;
  680. p:=ppole;
  681. while newpole neq car p do <<
  682. p:=cdr p;
  683. m:=cdr m >>;
  684. rplaca(m,car m - mult1)
  685. end
  686. else <<
  687. mpole:=nconc(mpole,list(-mult1));
  688. ppole:=nconc(ppole,list newpole) >>;
  689. fz:=cdr fz >>;
  690. f:=mk!*sq f;
  691. if multiplicity > 1
  692. then answer:=list('expt,f,multiplicity).answer
  693. else answer:=f.answer;
  694. summzero:=0;
  695. for each x in mzero do summzero:=summzero+x;
  696. if !*tra then <<
  697. princ "Function is now: ";
  698. printc append(mzero,mpole);
  699. printc "at";
  700. mapc(pzero,function printplace);
  701. mapc(ppole,function printplace) >>;
  702. if summzero > 2
  703. then go to iterate;
  704. end;
  705. fun:=coates!-real(nconc(pzero,ppole),
  706. nconc(mzero,mpole));
  707. if null answer
  708. then return fun
  709. else answer:=(mk!*sq fun).answer;
  710. return !*k2q('times.answer);
  711. % This is not valid, but we hope that it will be unpicked;
  712. % (e.g. by SIMPLOG) before too much damage is caused.
  713. end;
  714. symbolic procedure removezero(l,place);
  715. if place member l
  716. then (lambda u; if null cdr u
  717. then car u
  718. else interr "Removezero") delete(place,l)
  719. else interr "Error in removezeros";
  720. symbolic procedure findzeros(sq,sqrts);
  721. begin
  722. scalar u,potentials,answer,n;
  723. u:=denr sqrt2top invsq sq;
  724. potentials:=for each v in jfactor(u,intvar) collect begin
  725. scalar w,place;
  726. w:=makemainvar(numr v,intvar);
  727. if ldeg w neq 1
  728. then interr "Can't cope";
  729. if red w
  730. then place:=list(intvar,'plus,intvar,prepsq(negf red w ./ lc w))
  731. else place:=intvar . intvar;
  732. % This IF .. ELSE .. added JHD 3 Sept 1980.
  733. return place
  734. end;
  735. potentials:=list(intvar,'quotient,1,intvar).potentials;
  736. for each place in potentials do begin
  737. scalar slist,nestedsqrts;
  738. place:=list place;
  739. newplace place;
  740. u:=substitutesq(sq,place);
  741. while involvesq(u,sqrt!-intvar) do begin
  742. scalar z;
  743. z:=list list(intvar,'expt,intvar,2);
  744. place:=nconc(place,z);
  745. newplace place;
  746. u:=substitutesq(u,z);
  747. end;
  748. slist:=sqrtsinsq(u,intvar);
  749. for each v in sqrts do
  750. slist:=union(slist,sqrtsinsq(xsubstitutesq(!*kk2q v,place),
  751. intvar));
  752. slist:=sqrtsign(slist,intvar);
  753. for each s in slist do
  754. if (n:=taylorfirst taylorform substitutesq(u,s)) > 0
  755. then answer:=(append(place,s).n).answer;
  756. return answer;
  757. end;
  758. if null answer
  759. then interr "No zero found";
  760. return answer
  761. end;
  762. endmodule;
  763. module coatesid;
  764. % Author: James H. Davenport.
  765. fluid '(intvar magiclist nnn taylorasslist taylorvariable);
  766. global '(!*tra);
  767. exports coatessolve,vecprod,coates!-lineq;
  768. imports !*invsq,!*multsq,negsq,!*addsq,swap,check!-lineq,non!-null!-vec,
  769. printsq,sqrt2top,mapvec,mksp,vecsort,addsq,mkilist,mkvec,mapply,
  770. taylorformp,xsubstitutesq,taylorform,taylorevaluate,multsq,
  771. invsq,removecmsq;
  772. symbolic procedure coatessolve(mzero,pzero,basis,normals);
  773. begin
  774. scalar m,n,rightside,nnn;
  775. % if null normals
  776. % then normals:=list mkilist(basis,1 ./ 1);
  777. % This provides the default normalisation,
  778. % viz merely a de-homogenising constraint;
  779. % No it doesn't - JHD May 1983 and August 1986.
  780. % This may be precisely the wrong constraint, as can be seen from
  781. % the example of SQRT(X**2-1). Fixed 19/8/86 to amend COATESMATRIX
  782. % to insert a normalising constraint if none is provided.
  783. nnn:=max(length normals,1);
  784. basis:=mkvec basis;
  785. m:=coatesmatrix(mzero,pzero,basis,normals);
  786. n:=upbv m;
  787. rightside:=mkvect n;
  788. for i:=0:n do
  789. putv(rightside,n-i,(if i < nnn
  790. then 1
  791. else nil) ./ 1);
  792. n:=coates!-lineq(m,rightside);
  793. if n eq 'failed
  794. then return 'failed;
  795. n:=removecmsq vecprod(n,basis);
  796. if !*tra then <<
  797. printc "Answer from linear equation solving is ";
  798. printsq n >>;
  799. return n
  800. end;
  801. symbolic procedure coatesmatrix(mzero,pzero,basis,normals);
  802. % NORMALS is a list of the normalising constraints
  803. % that we must apply. Thypically, this is NIL, and we have to
  804. % invent one - see the code IF NULL NORMALS ...
  805. begin
  806. scalar ans,n1,n2,j,w,save,nextflag,save!-taylors,x!-factors,
  807. normals!-ok,temp;
  808. save!-taylors:=mkvect isub1 length pzero;
  809. save:=taylorasslist;
  810. normals!-ok:=nil;
  811. n1:=upbv basis;
  812. n2:=isub1 mapply(function plus2,mzero) + max(length normals,1);
  813. % the number of constaints in all (counting from 0).
  814. taylorvariable:=intvar;
  815. if !*tra then <<
  816. printc "Basis for the functions with precisely the correct poles";
  817. mapvec(basis,function printsq) >>;
  818. ans:=mkvect n2;
  819. for i:=0:n2 do
  820. putv(ans,i,mkvect n1);
  821. for i:=0:n1 do begin
  822. scalar xmz,xpz,k;
  823. xmz:=mzero;
  824. k:=j:=0;
  825. xpz:=pzero;
  826. while xpz do <<
  827. newplace basicplace car xpz;
  828. if nextflag
  829. then w:=taylorformp list('binarytimes,
  830. getv(save!-taylors,k),
  831. getv(x!-factors,k))
  832. else if not !*tra
  833. then w:=taylorform xsubstitutesq(getv(basis,i),car xpz)
  834. else begin
  835. scalar flg,u,slists;
  836. u:=xsubstitutesq(getv(basis,i),basicplace car xpz);
  837. slists:=extenplace car xpz;
  838. for each w in sqrtsinsq(u,intvar) do
  839. if not assoc(w,slists)
  840. then flg:=w.flg;
  841. if flg then <<
  842. printc "The following square roots were not expected";
  843. mapc(flg,function superprint);
  844. printc "in the substitution";
  845. superprint car xpz;
  846. printsq getv(basis,i) >>;
  847. w:=taylorform xsubstitutesq(u,slists)
  848. end;
  849. putv(save!-taylors,k,w);
  850. k:=iadd1 k;
  851. for l:=0 step 1 until isub1 car xmz do <<
  852. astore(ans,j,i,taylorevaluate(w,l));
  853. j:=iadd1 j >>;
  854. if null normals and j=n2 then <<
  855. temp:=taylorevaluate(w,car xmz);
  856. astore(ans,j,i,temp);
  857. % The defaults normalising condition is that the coefficient
  858. % after the last zero be a non-zero.
  859. % Unfortunately this too may fail (JHD 21.3.87) - check for it later
  860. normals!-ok:=normals!-ok or numr temp >>;
  861. xpz:=cdr xpz;
  862. xmz:=cdr xmz >>;
  863. nextflag:=(i < n1) and
  864. (getv(basis,i) = multsq(!*kk2q intvar,getv(basis,i+1)));
  865. if nextflag and null x!-factors then <<
  866. x!-factors:=mkvect upbv save!-taylors;
  867. xpz:=pzero;
  868. k:=0;
  869. xmz:=invsq !*kk2q intvar;
  870. while xpz do <<
  871. putv(x!-factors,k,taylorform xsubstitutesq(xmz,car xpz));
  872. xpz:=cdr xpz;
  873. k:=iadd1 k >> >>
  874. end;
  875. if null normals and null normals!-ok then <<
  876. if !*tra
  877. then printc "Our default normalisation condition was vacuous";
  878. astore(ans,n2,n1,1 ./ 1)>>;
  879. while normals do <<
  880. w:=car normals;
  881. for k:=0:n1 do <<
  882. astore(ans,j,k,car w);
  883. w:=cdr w >>;
  884. j:=iadd1 j;
  885. normals:=cdr normals >>;
  886. tayshorten save;
  887. return ans
  888. end;
  889. symbolic procedure printmatrix(ans,n2,n1);
  890. if !*tra
  891. then <<
  892. printc "Equations to be solved:";
  893. for i:=0:n2 do begin
  894. if null getv(ans,i)
  895. then return;
  896. princ "Row number ";
  897. princ i;
  898. for j:=0:n1 do
  899. printsq getv(getv(ans,i),j)
  900. end >>;
  901. symbolic procedure vecprod(u,v);
  902. begin
  903. scalar w,n;
  904. w:=nil ./ 1;
  905. n:=upbv u;
  906. for i:=0:n do
  907. w:=addsq(w,!*multsq(getv(u,i),getv(v,i)));
  908. return w
  909. end;
  910. symbolic procedure coates!-lineq(m,rightside);
  911. begin
  912. scalar nnn,n;
  913. nnn:=desparse(m,rightside);
  914. if nnn eq 'failed
  915. then return 'failed;
  916. m:=car nnn;
  917. if null m
  918. then <<
  919. n:=cddr nnn;
  920. goto vecprod >>;
  921. rightside:=cadr nnn;
  922. nnn:=cddr nnn;
  923. n:=check!-lineq(m,rightside);
  924. if n eq 'failed
  925. then return n;
  926. n:=jhdsolve(m,rightside,non!-null!-vec nnn);
  927. if n eq 'failed
  928. then return n;
  929. for i:=0:upbv n do
  930. if (m:=getv(nnn,i))
  931. then putv(n,i,m);
  932. vecprod:
  933. for i:=0:upbv n do
  934. if null getv(n,i) then putv(n,i,nil ./ 1);
  935. return n
  936. end;
  937. symbolic procedure jhdsolve(m,rightside,ignore);
  938. % Returns answer to m.answer=rightside.
  939. % Matrix m not necessarily square.
  940. begin
  941. scalar n1,n2,ans,u,row,swapflg,swaps;
  942. % The SWAPFLG is true if we have changed the order of the
  943. % columns and need later to invert this via SWAPS.
  944. n1:=upbv m;
  945. for i:=0:n1 do
  946. if (u:=getv(m,i))
  947. then (n2:=upbv u);
  948. printmatrix(m,n1,n2);
  949. swaps:=mkvect n2;
  950. for i:=0:n2 do
  951. putv(swaps,i,n2-i);
  952. % We have the SWAPS vector, which should be a vector of indices,
  953. % arranged like this because VECSORT sorts in decreasing order.
  954. for i:=0:isub1 n1 do begin
  955. scalar k,v,pivot;
  956. tryagain:
  957. row:=getv(m,i);
  958. if null row
  959. then go to interchange;
  960. % look for a pivot in row.
  961. k:=-1;
  962. for j:=0:n2 do
  963. if numr (pivot:=getv(row,j))
  964. then <<
  965. k:=j;
  966. j:=n2 >>;
  967. if k neq -1
  968. then goto newrow;
  969. if numr getv(rightside,i)
  970. then <<
  971. m:='failed;
  972. i:=sub1 n1; %Force end of loop.
  973. go to finished >>;
  974. % now interchange i and last element.
  975. interchange:
  976. swap(m,i,n1);
  977. swap(rightside,i,n1);
  978. n1:=isub1 n1;
  979. if i iequal n1
  980. then goto finished
  981. else goto tryagain;
  982. newrow:
  983. if i neq k
  984. then <<
  985. swapflg:=t;
  986. swap(swaps,i,k);
  987. % record what we have done.
  988. for l:=0:n1 do
  989. swap(getv(m,l),i,k) >>;
  990. % place pivot on diagonal.
  991. pivot:=sqrt2top negsq !*invsq pivot;
  992. for j:=iadd1 i:n1 do begin
  993. u:=getv(m,j);
  994. if null u
  995. then return;
  996. v:=!*multsq(getv(u,i),pivot);
  997. if numr v then <<
  998. putv(rightside,j,
  999. !*addsq(getv(rightside,j),!*multsq(v,getv(rightside,i))));
  1000. for l:=0:n2 do
  1001. putv(u,l,!*addsq(getv(u,l),!*multsq(v,getv(row,l)))) >>
  1002. end;
  1003. finished:
  1004. end;
  1005. if m eq 'failed
  1006. then go to failed;
  1007. % Equations were inconsistent.
  1008. while null (row:=getv(m,n1)) do
  1009. n1:=isub1 n1;
  1010. u:=nil;
  1011. for i:=0:n2 do
  1012. if numr getv(row,i)
  1013. then u:='t;
  1014. if null u
  1015. then if numr getv(rightside,n1)
  1016. then go to failed
  1017. else n1:=isub1 n1;
  1018. % Deals with a last equation which is all zero.
  1019. if n1 > n2
  1020. then go to failed;
  1021. % Too many equations to satisfy.
  1022. ans:=mkvect n2;
  1023. n2:=n2 - ignore;
  1024. if n1 < n2 then <<
  1025. if !*tra then <<
  1026. printc "The equations do not completely determine the functions";
  1027. printc "Matrix:";
  1028. mapvec(m,function superprint);
  1029. printc "Right-hand side:";
  1030. superprint rightside >>;
  1031. for i:=iadd1 n1:n2 do <<
  1032. u:=gensym();
  1033. magiclist:=u.magiclist;
  1034. putv(ans,i,!*kk2q u) >>;
  1035. if !*tra then printc "If in doubt consult an expert">>;
  1036. % now to do the back-substitution.
  1037. for i:=n1 step -1 until 0 do begin
  1038. row:=getv(m,i);
  1039. if null row
  1040. then return;
  1041. u:=getv(rightside,i);
  1042. for j:=iadd1 i:n2 do
  1043. u:=!*addsq(u,!*multsq(getv(row,j),negsq getv(ans,j)));
  1044. putv(ans,i,!*multsq(u,sqrt2top !*invsq getv(row,i)))
  1045. end;
  1046. if swapflg
  1047. then vecsort(swaps,list ans);
  1048. return ans;
  1049. failed:
  1050. if !*tra then printc "Unable to force correct zeroes";
  1051. return 'failed
  1052. end;
  1053. symbolic procedure desparse(matrx,rightside);
  1054. begin
  1055. scalar vec,changed,n,m,zero,failed;
  1056. zero := nil ./ 1;
  1057. n:=upbv matrx;
  1058. m:=upbv getv(matrx,0);
  1059. vec:=mkvect m;
  1060. % for i:=0:m do putv(vec,i,zero); %%% initialize - ach
  1061. changed:=t;
  1062. while changed and not failed do begin
  1063. changed:=nil;
  1064. for i:=0:n do
  1065. if changed or failed
  1066. then i:=n % and hence quit the loop.
  1067. else begin
  1068. scalar nzcount,row,pivot;
  1069. row:=getv(matrx,i);
  1070. if null row
  1071. then return;
  1072. nzcount:=0;
  1073. for j:=0:m do
  1074. if numr getv(row,j)
  1075. then <<
  1076. nzcount:=iadd1 nzcount;
  1077. pivot:=j >>;
  1078. if nzcount = 0
  1079. then if null numr getv(rightside,i)
  1080. then return putv(matrx,i,nil)
  1081. else return (failed:='failed);
  1082. if nzcount > 1
  1083. then return nil;
  1084. nzcount:=getv(rightside,i);
  1085. if null numr nzcount
  1086. then <<
  1087. putv(vec,pivot,zero);
  1088. go to was!-zero >>;
  1089. nzcount:=!*multsq(nzcount,!*invsq getv(row,pivot));
  1090. putv(vec,pivot,nzcount);
  1091. nzcount:=negsq nzcount;
  1092. for i:=0:n do
  1093. if (row:=getv(matrx,i))
  1094. then if numr (row:=getv(row,pivot))
  1095. then putv(rightside,i,!*addsq(getv(rightside,i),
  1096. !*multsq(row,nzcount)));
  1097. was!-zero:
  1098. for i:=0:n do
  1099. if (row:=getv(matrx,i))
  1100. then putv(row,pivot,zero);
  1101. changed:=t;
  1102. putv(matrx,i,nil);
  1103. swap(matrx,i,n);
  1104. swap(rightside,i,n);
  1105. end;
  1106. end;
  1107. if failed
  1108. then return 'failed;
  1109. changed:=t;
  1110. for i:=0:n do
  1111. if getv(matrx,i)
  1112. then changed:=nil;
  1113. if changed
  1114. then matrx:=nil;
  1115. % We have completely solved the equations by these machinations.
  1116. return matrx.(rightside.vec)
  1117. end;
  1118. symbolic procedure astore(a,i,j,val);
  1119. putv(getv(a,i),j,val);
  1120. endmodule;
  1121. module findmagc;
  1122. % Author: James H. Davenport.
  1123. fluid '(magiclist);
  1124. global '(!*tra);
  1125. symbolic procedure findmagic l;
  1126. begin
  1127. scalar p,n,pvec,m,intvec,mcount,temp;
  1128. % L is a list of things which must be made non-zero by means of
  1129. % a suitable choice of values for the variables in MAGICLIST;
  1130. l:=for each u in l collect
  1131. << mapc(magiclist,function (lambda v;
  1132. if involvesf(denr u,v)
  1133. then interr "Hard findmagic"));
  1134. numr u >>;
  1135. if !*tra then <<
  1136. printc "We must make the following non-zero:";
  1137. mapc(l,function printsf);
  1138. princ "by suitable choice of ";
  1139. printc magiclist >>;
  1140. % Strategy is random choice in a space which has only finitely
  1141. % many singular points;
  1142. p:=0;
  1143. n:=isub1 length magiclist;
  1144. pvec:=mkvect n;
  1145. putv(pvec,0,2);
  1146. for i:=1:n do
  1147. putv(pvec,i,nextprime getv(pvec,isub1 i));
  1148. % Tactics are based on Godel (is this a mistake ??) and let P run
  1149. % through numbers and take the prime factorization of them;
  1150. intvec:=mkvect n;
  1151. loop:
  1152. p:=iadd1 p;
  1153. if !*tra then <<
  1154. princ "We try the number ";
  1155. printc p >>;
  1156. m:=p;
  1157. for i:=0:n do <<
  1158. mcount:=0;
  1159. while zerop cdr (temp:=divide(m,getv(pvec,i)) ) do <<
  1160. mcount:=iadd1 mcount;
  1161. m:=car temp >>;
  1162. putv(intvec,i,mcount) >>;
  1163. if m neq 1
  1164. then go to loop;
  1165. if !*tra then <<
  1166. printc "which corresponds to ";
  1167. superprint intvec >>;
  1168. m:=nil;
  1169. temp:=magiclist;
  1170. for i:=0:n do <<
  1171. m:=((car temp).getv(intvec,i)).m;
  1172. temp:=cdr temp >>;
  1173. % M is the list of substitutions corresponding to this value of P;
  1174. temp:=l;
  1175. loop2:
  1176. if null numr algint!-subf(car temp,m)
  1177. then go to loop;
  1178. temp:=cdr temp;
  1179. if temp
  1180. then go to loop2;
  1181. if !*tra then <<
  1182. printc "which corresponds to the values:";
  1183. superprint m >>;
  1184. return m
  1185. end;
  1186. endmodule;
  1187. module findres;
  1188. % Author: James H. Davenport.
  1189. fluid '(!*gcd
  1190. basic!-listofallsqrts
  1191. basic!-listofnewsqrts
  1192. intvar
  1193. listofallsqrts
  1194. listofnewsqrts
  1195. nestedsqrts
  1196. sqrt!-intvar
  1197. taylorvariable);
  1198. global '(!*tra !*trmin);
  1199. exports find!-residue,findpoles;
  1200. imports sqrt2top,jfactor,prepsq,printplace,simpdf,involvesf,simp;
  1201. imports stt,interr,mksp,negf,multf,addf,let2,substitutesq,subs2q,quotf;
  1202. imports printsq,clear,taylorform,taylorevaluate,involvesf,!*multsq;
  1203. imports sqrtsave,sqrtsinsq,sqrtsign;
  1204. symbolic procedure find!-residue(simpdl,x,place);
  1205. % evaluates residue of simpdl*dx at place given by x=place(y).
  1206. begin
  1207. scalar deriv,nsd,poss,slist;
  1208. listofallsqrts:=basic!-listofallsqrts;
  1209. listofnewsqrts:=basic!-listofnewsqrts;
  1210. deriv:=simpdf(list(place,x));
  1211. if involvesf(numr deriv,intvar)
  1212. then return residues!-at!-new!-point(simpdl,x,place);
  1213. if eqcar(place,'quotient) and (cadr place iequal 1)
  1214. then goto place!-correct;
  1215. place:=simp list('difference,intvar,place);
  1216. if involvesq(place,intvar)
  1217. then interr "Place wrongly formatted";
  1218. place:=list('plus,intvar,prepsq place);
  1219. place!-correct:
  1220. if car place eq 'plus and caddr place = 0
  1221. then place:=list(x.x)
  1222. else place:=list(x.place);
  1223. % the substitution required.
  1224. nsd:=substitutesq(simpdl,place);
  1225. deriv:=!*multsq(nsd,deriv);
  1226. % differential is deriv * dy, where x=place(y).
  1227. if !*tra then <<
  1228. printc "Differential after first substitution is ";
  1229. printsq deriv >>;
  1230. while involvesq(deriv,sqrt!-intvar)
  1231. do <<
  1232. sqrtsave(basic!-listofallsqrts,basic!-listofnewsqrts,place);
  1233. nsd:=list(list(x,'expt,x,2));
  1234. deriv:=!*multsq(substitutesq(deriv,nsd),!*kk2q x);
  1235. % derivative of x**2 is 2x, but there's a jacobian of 2 to
  1236. % consider.
  1237. place:=nconc(place,nsd) >>;
  1238. % require coeff x**-1 in deriv.
  1239. nestedsqrts:=nil;
  1240. slist:=sqrtsinsq(deriv,x);
  1241. if !*tra and nestedsqrts
  1242. then printc "We have nested square roots";
  1243. slist:=sqrtsign(slist,intvar);
  1244. % The reversewoc is to ensure that the simpler sqrts are at
  1245. % the front of the list.
  1246. % Slist is a list of all combinations of signs of sqrts.
  1247. taylorvariable:=x;
  1248. for each branch in slist do <<
  1249. nsd:=taylorevaluate(taylorform substitutesq(deriv,branch),-1);
  1250. if numr nsd
  1251. then poss:=(append(place,branch).nsd).poss >>;
  1252. poss:=reversewoc poss;
  1253. if null poss
  1254. then go to finished;
  1255. % poss is a list of all possible residues at this place.
  1256. if !*tra
  1257. then <<
  1258. princ "Residues at ";
  1259. printplace place;
  1260. printc " are ";
  1261. mapc(poss, function (lambda u; <<
  1262. printplace car u;
  1263. printsq cdr u >>)) >>;
  1264. finished:
  1265. sqrtsave(basic!-listofallsqrts,basic!-listofnewsqrts,place);
  1266. return poss
  1267. end;
  1268. symbolic procedure residues!-at!-new!-point(func,x,place);
  1269. begin
  1270. scalar place2,tempvar,topterm,a,b,xx;
  1271. if !*tra then <<
  1272. printc "Find residues at all roots of";
  1273. superprint place >>;
  1274. place2:=numr simp place;
  1275. topterm:=stt(place2,x);
  1276. if car topterm = 0
  1277. then interr "Why are we here?";
  1278. tempvar:=gensym();
  1279. place2:=addf(place2,
  1280. multf(!*p2f mksp(x,car topterm),negf cdr topterm));
  1281. % The remainder of PLACE2.
  1282. let2(list('expt,tempvar,car topterm),
  1283. subst(tempvar,x,prepsq(place2 ./ cdr topterm)),
  1284. nil,t);
  1285. place2:=list list(x,'plus,x,tempvar);
  1286. !*gcd:=nil;
  1287. % No unnecessary work: only factors of X worry us.
  1288. func:=subs2q substitutesq(func,place2);
  1289. !*gcd:=t;
  1290. xx:=!*k2f x;
  1291. while (a:=quotf(numr func,xx)) and (b:=quotf(denr func,xx))
  1292. do func:=a ./ b;
  1293. if !*tra then <<
  1294. printc "which gives rise to ";
  1295. printsq func >>;
  1296. if null a
  1297. then b:=quotf(denr func,xx);
  1298. % because B goes back to the last time round that WHILE loop.
  1299. if b then go to hard;
  1300. if !*tra then printc "There were no residues";
  1301. clear tempvar;
  1302. return nil;
  1303. % *** thesis remark ***
  1304. % This test for having an X in the denominator only works
  1305. % because we are at a new place, and hence (remark of Trager)
  1306. % if we have a residue at one place over this point, we must have one
  1307. % at them all, since the places are indistinguishable;
  1308. hard:
  1309. taylorvariable:=x;
  1310. func:=taylorevaluate(taylorform func,-1);
  1311. printsq func;
  1312. interr "so far"
  1313. end;
  1314. symbolic procedure findpoles(simpdl,x);
  1315. begin
  1316. scalar simpdl2,poles;
  1317. % finds possible poles of simpdl * dx.
  1318. simpdl2:=sqrt2top simpdl;
  1319. poles:=jfactor(denr simpdl2,x);
  1320. poles:=mapcar(poles,function prepsq);
  1321. % what about the place at infinity.
  1322. poles:=list('quotient,1,x).poles;
  1323. if !*tra or !*trmin
  1324. then <<
  1325. printc "Places at which poles could occur ";
  1326. for each u in poles do
  1327. printplace list(intvar.u) >>;
  1328. return poles
  1329. end;
  1330. endmodule;
  1331. module finitise;
  1332. % Author: James H. Davenport.
  1333. fluid '(intvar);
  1334. global '(!*tra);
  1335. exports finitise;
  1336. imports newplace,getsqrtsfromplaces,interr,completeplaces2,sqrtsign;
  1337. imports mkilist,extenplace;
  1338. symbolic procedure finitise(places,mults);
  1339. begin
  1340. scalar placesmisc,multsmisc,m,n,sqrts;
  1341. scalar places0,mults0,placesinf,multsinf;
  1342. newplace list (intvar.intvar);
  1343. % fix the disaster with 1/sqrt(x**2-1)
  1344. % (but with no other 1/sqrt(x**2-k).
  1345. sqrts:=getsqrtsfromplaces places;
  1346. placesmisc:=places;
  1347. multsmisc:=mults;
  1348. n:=0;
  1349. while placesmisc do <<
  1350. if eqcar(rfirstsubs car placesmisc,'quotient)
  1351. and (n > car multsmisc)
  1352. then <<
  1353. n:=car multsmisc;
  1354. m:=multiplicity!-factor car placesmisc >>;
  1355. placesmisc:=cdr placesmisc;
  1356. multsmisc:=cdr multsmisc >>;
  1357. if n = 0
  1358. then interr "Why did we call finitise ??";
  1359. % N must be corrected to allow for our representation of
  1360. % multiplicities at places where X is not the local parameter.
  1361. n:=divide(n,m);
  1362. if not zerop cdr n and !*tra
  1363. then printc
  1364. "Cannot get the poles moved precisely because of ramification";
  1365. if (cdr n) < 0
  1366. then n:=(-1) + car n
  1367. else n:=car n;
  1368. % The above 3 lines (as a replacement for the line below)
  1369. % inserted JHD 06 SEPT 80.
  1370. % n:=car n;
  1371. % ***** not true jhd 06 sept 80 *****;
  1372. % This works because, e.g., DIVIDE(-1,2) is -1 remainder 1.
  1373. % Note that N is actually negative.
  1374. % We now wish to divide by X**N, thus increasing
  1375. % the degrees of all infinite places by N and
  1376. % decreasing the degrees of all places lying over 0.
  1377. while places do <<
  1378. if atom rfirstsubs car places
  1379. then <<
  1380. places0:=(car places).places0;
  1381. mults0:=(car mults).mults0 >>
  1382. else if car rfirstsubs car places eq 'quotient
  1383. then <<
  1384. placesinf:=(car places).placesinf;
  1385. multsinf:=(car mults).multsinf >>
  1386. else <<
  1387. placesmisc:=(car places).placesmisc;
  1388. multsmisc:=(car mults).multsmisc >>;
  1389. places:=cdr places;
  1390. mults:=cdr mults >>;
  1391. if places0
  1392. then <<
  1393. places0:=completeplaces2(places0,mults0,sqrts);
  1394. mults0:=cdr places0;
  1395. places0:=car places0;
  1396. m:=multiplicity!-factor car places0;
  1397. mults0:=for each u in mults0 collect u+n*m >>
  1398. else <<
  1399. places0:=for each u in sqrtsign(sqrts,intvar)
  1400. collect (intvar.intvar).u;
  1401. mults0:=mkilist(places0,n * (multiplicity!-factor car places0))>>;
  1402. placesinf:=completeplaces2(placesinf,
  1403. multsinf,
  1404. for each u in extenplace car placesinf
  1405. collect lsubs u);
  1406. multsinf:=cdr placesinf;
  1407. placesinf:=car placesinf;
  1408. while placesinf do <<
  1409. m:=multiplicity!-factor car placesinf;
  1410. if (car multsinf) neq n*m
  1411. then <<
  1412. placesmisc:=(car placesinf).placesmisc;
  1413. multsmisc:=(car multsinf -n*m).multsmisc >>;
  1414. % This test ensures that we do not add places
  1415. % with a multiplicity of zero.
  1416. placesinf:=cdr placesinf;
  1417. multsinf:=cdr multsinf >>;
  1418. return list(nconc(places0,placesmisc),
  1419. nconc(mults0,multsmisc),
  1420. -n)
  1421. end;
  1422. symbolic procedure multiplicity!-factor place;
  1423. begin
  1424. scalar n;
  1425. n:=1;
  1426. for each u in place do
  1427. if (lsubs u eq intvar) and
  1428. eqcar(rsubs u,'expt)
  1429. then n:=n*(caddr rsubs u);
  1430. return n
  1431. end;
  1432. endmodule;
  1433. module fixes;
  1434. % Author: James H. Davenport.
  1435. fluid '(!*nosubs asymplis!* dmode!*);
  1436. global '(ncmp!*);
  1437. % The standard version of SUBF messes with the order of variables before
  1438. % calling SUBF1, something we can't afford, so we define a new version.
  1439. symbolic procedure algint!-subf(a,b); algint!-subf1(a,b);
  1440. symbolic procedure algint!-subsq(u,v);
  1441. quotsq(algint!-subf(numr u,v),algint!-subf(denr u,v));
  1442. symbolic procedure algint!-subf1(u,l);
  1443. %U is a standard form,
  1444. %L an association list of substitutions of the form
  1445. %(<kernel> . <substitution>).
  1446. %Value is the standard quotient for substituted expression.
  1447. %Algorithm used is essentially the straight method.
  1448. %Procedure depends on explicit data structure for standard form;
  1449. if domainp u
  1450. then if atom u then if null dmode!* then u ./ 1 else simpatom u
  1451. else if dmode!* eq car u then !*d2q u
  1452. else simp prepf u
  1453. else begin integer n; scalar kern,m,w,x,xexp,y,y1,z;
  1454. z := nil ./ 1;
  1455. a0: kern := mvar u;
  1456. if m := assoc(kern,asymplis!*) then m := cdr m;
  1457. a: if null u or (n := degr(u,kern))=0 then go to b
  1458. else if null m or n<m then y := lt u . y;
  1459. u := red u;
  1460. go to a;
  1461. b: if not atom kern and not atom car kern then kern := prepf kern;
  1462. if null l then xexp := if kern eq 'k!* then 1 else kern
  1463. else if (xexp := algint!-subsublis(l,kern)) = kern
  1464. and not assoc(kern,asymplis!*)
  1465. then go to f;
  1466. c: w := 1 ./ 1;
  1467. n := 0;
  1468. if y and cdaar y<0 then go to h;
  1469. if (x := getrtype xexp) then typerr(x,"substituted expression");
  1470. x := simp xexp;
  1471. % SIMP!* here causes problem with HE package;
  1472. x := reorder numr x ./ reorder denr x;
  1473. % needed in case substitution variable is in XEXP;
  1474. if null l and kernp x and mvar numr x eq kern then go to f
  1475. else if null numr x then go to e; %Substitution of 0;
  1476. for each j in y do
  1477. <<m := cdar j;
  1478. w := multsq(exptsq(x,m-n),w);
  1479. n := m;
  1480. z := addsq(multsq(w,algint!-subf1(cdr j,l)),z)>>;
  1481. e: y := nil;
  1482. if null u then return z
  1483. else if domainp u then return addsq(algint!-subf1(u,l),z);
  1484. go to a0;
  1485. f: sub2chk kern;
  1486. for each j in y do
  1487. z := addsq(multpq(car j,algint!-subf1(cdr j,l)),z);
  1488. go to e;
  1489. h: %Substitution for negative powers;
  1490. x := simprecip list xexp;
  1491. j: y1 := car y . y1;
  1492. y := cdr y;
  1493. if y and cdaar y<0 then go to j;
  1494. k: m := -cdaar y1;
  1495. w := multsq(exptsq(x,m-n),w);
  1496. n := m;
  1497. z := addsq(multsq(w,algint!-subf1(cdar y1,l)),z);
  1498. y1 := cdr y1;
  1499. if y1 then go to k else if y then go to c else go to e
  1500. end;
  1501. symbolic procedure algint!-subsublis(u,v);
  1502. begin scalar x;
  1503. return if x := assoc(v,u) then cdr x
  1504. else if atom v then v
  1505. else if car v eq '!*sq then
  1506. list('!*sq,algint!-subsq(cadr v,u),caddr v)
  1507. % Previous two lines added by JHD 7 July 1982.
  1508. % without them, CDRs in SQ expressions buried inside;
  1509. % !*SQ forms are lost;
  1510. else if flagp!*!*(car v,'subfn)
  1511. then algint!-subsubf(u,v)
  1512. else for each j in v collect algint!-subsublis(u,j)
  1513. end;
  1514. symbolic procedure algint!-subsubf(l,expn);
  1515. %Sets up a formal SUB expression when necessary;
  1516. begin scalar x,y;
  1517. for each j in cddr expn do
  1518. if (x := assoc(j,l)) then <<y := x . y; l := delete(x,l)>>;
  1519. expn := sublis(l,car expn)
  1520. . for each j in cdr expn
  1521. collect algint!-subsublis(l,j);
  1522. %to ensure only opr and individual args are transformed;
  1523. if null y then return expn;
  1524. expn := aconc!*(for each j in reversip!* y
  1525. collect list('equal,car j,aeval cdr j),expn);
  1526. return mk!*sq if l then algint!-simpsub expn
  1527. else !*p2q mksp('sub . expn,1)
  1528. end;
  1529. symbolic procedure algint!-simpsub u;
  1530. begin scalar !*nosubs,w,x,z;
  1531. a: if null cdr u
  1532. then <<if getrtype car u or eqcar(car u,'equal)
  1533. then typerr(car u,"scalar");
  1534. u := simp!* car u;
  1535. z := reversip!* z; % to put replacements in same
  1536. % order as input.
  1537. return quotsq(algint!-subf(numr u,z),
  1538. algint!-subf(denr u,z))>>;
  1539. !*nosubs := t; % We don't want left side of eqns to change.
  1540. w := reval car u;
  1541. !*nosubs := nil;
  1542. if getrtype w eq 'list
  1543. then <<u := append(cdr w,cdr u); go to a>>
  1544. else if not eqexpr w then errpri2(car u,t);
  1545. x := cadr w;
  1546. if null getrtype x then x := !*a2k x;
  1547. z := (x . caddr w) . z;
  1548. u := cdr u;
  1549. go to a;
  1550. end;
  1551. endmodule;
  1552. module fracdi;
  1553. % Author: James H. Davenport.
  1554. fluid '(basic!-listofallsqrts basic!-listofnewsqrts expsub intvar
  1555. sqrt!-intvar);
  1556. global '(coates!-fdi);
  1557. exports fdi!-print,fdi!-revertsq,fdi!-upgrade,
  1558. fractional!-degree!-at!-infinity;
  1559. % internal!-fluid '(expsub);
  1560. symbolic procedure fdi!-print();
  1561. << princ "We substitute";
  1562. princ intvar;
  1563. princ "**";
  1564. princ coates!-fdi;
  1565. princ " for ";
  1566. princ intvar;
  1567. printc " in order to avoid fractional degrees at infinity" >>;
  1568. symbolic procedure fdi!-revertsq u;
  1569. if coates!-fdi iequal 1
  1570. then u
  1571. else (fdi!-revert numr u) ./ (fdi!-revert denr u);
  1572. symbolic procedure fdi!-revert u;
  1573. if not involvesf(u,intvar)
  1574. then u
  1575. else addf(fdi!-revert red u,
  1576. !*multf(fdi!-revertpow lpow u,
  1577. fdi!-revert lc u));
  1578. symbolic procedure fdi!-revertpow pow;
  1579. if not dependsp(car pow,intvar)
  1580. then (pow .* 1) .+ nil
  1581. else if car pow eq intvar
  1582. then begin
  1583. scalar v;
  1584. v:=divide(cdr pow,coates!-fdi);
  1585. if zerop cdr pow
  1586. then return (mksp(intvar,car pow) .* 1) .+ nil
  1587. else interr "Unable to revert fdi";
  1588. end
  1589. else if eq(car pow,'sqrt)
  1590. then simpsqrt2 fdi!-revert !*q2f simp argof car pow
  1591. else interr "Unrecognised term to revert";
  1592. symbolic procedure fdi!-upgrade place;
  1593. begin
  1594. scalar ans,u,expsub,n;
  1595. n:=coates!-fdi;
  1596. for each u in place do
  1597. if eqcar(u:=rsubs u,'expt)
  1598. then n:=n / caddr u;
  1599. % if already upgraded, we must take account of this.
  1600. if n = 1
  1601. then return place;
  1602. expsub:=list(intvar,'expt,intvar,n);
  1603. ans:=nconc(basicplace place,list expsub);
  1604. expsub:=list expsub; % this prevents later nconc from causing trouble.
  1605. u:=extenplace place;
  1606. while u do begin
  1607. scalar v,w,rfu;
  1608. v:=fdi!-upgr2 lfirstsubs u;
  1609. if v iequal 1
  1610. then return (u:=cdr u);
  1611. if eqcar(rfu:=rfirstsubs u,'minus)
  1612. then w:=argof rfu
  1613. else if eqcar(rfu,'sqrt)
  1614. then w:=rfu
  1615. else interr "Unknown place format";
  1616. w:=fdi!-upgr2 w;
  1617. if w iequal 1
  1618. then interr "Place collapses under rewriting";
  1619. if eqcar(rfu,'minus)
  1620. then ans:=nconc(ans,list list(v,'minus,w))
  1621. else ans:=nconc(ans,list(v.w));
  1622. u:=cdr u;
  1623. return
  1624. end;
  1625. sqrtsave(basic!-listofallsqrts,
  1626. basic!-listofnewsqrts,
  1627. basicplace ans);
  1628. return ans
  1629. end;
  1630. symbolic procedure fdi!-upgr2 u;
  1631. begin
  1632. scalar v,mv;
  1633. v:=substitutesq(simp u,expsub);
  1634. if denr v neq 1
  1635. then goto error;
  1636. v:=numr v;
  1637. loop:
  1638. if atom v
  1639. then return v;
  1640. if red v
  1641. then go to error;
  1642. mv:=mvar v;
  1643. if (not dependsp(mv,intvar)) or (mv eq intvar)
  1644. then <<
  1645. v:=lc v;
  1646. goto loop >>;
  1647. if eqcar(mv,'sqrt)
  1648. then if sqrtsinsf(lc v,nil,intvar)
  1649. then go to error
  1650. else return mv
  1651. else go to error;
  1652. error:
  1653. printc "*** Format error ***";
  1654. princ "unable to go x:=x**";
  1655. printc coates!-fdi;
  1656. superprint u;
  1657. rederr "Failure to make integral at infinity"
  1658. end;
  1659. symbolic procedure fractional!-degree!-at!-infinity sqrts;
  1660. if sqrts
  1661. then lcmn(fdi2 car sqrts,fractional!-degree!-at!-infinity cdr sqrts)
  1662. else 1;
  1663. symbolic procedure fdi2 u;
  1664. % Returns the denominator of the degree of x at infinity
  1665. % in the sqrt expression u.
  1666. begin
  1667. scalar n;
  1668. u:=substitutesq(simp u,list list(intvar,'quotient,1,intvar));
  1669. n:=0;
  1670. while involvesq(u,sqrt!-intvar) do <<
  1671. n:=iadd1 n;
  1672. u:=substitutesq(u,list list(intvar,'expt,intvar,2)) >>;
  1673. return (2**n)
  1674. end;
  1675. symbolic procedure lcmn(i,j);
  1676. i*j/gcdn(i,j);
  1677. % unfluid '(expsub);
  1678. endmodule;
  1679. module genus;
  1680. % Author: James H. Davenport.
  1681. fluid '(!*galois
  1682. gaussiani
  1683. intvar
  1684. listofallsqrts
  1685. listofnewsqrts
  1686. nestedsqrts
  1687. previousbasis
  1688. sqrt!-intvar
  1689. sqrt!-places!-alist
  1690. sqrtflag
  1691. sqrts!-in!-integrand
  1692. taylorasslist
  1693. taylorvariable);
  1694. global '(!*tra !*trmin);
  1695. symbolic procedure simpgenus u;
  1696. begin
  1697. scalar intvar,sqrt!-intvar,taylorvariable,taylorasslist;
  1698. scalar listofnewsqrts,listofallsqrts,sqrt!-places!-alist;
  1699. scalar list!-of!-all!-sqrts,list!-of!-new!-sqrts;
  1700. scalar sqrtflag,sqrts!-in!-integrand,tt,u,simpfn;
  1701. tt:=readclock();
  1702. sqrtflag:=t;
  1703. taylorvariable:=intvar:=car u;
  1704. simpfn:=get('sqrt,'simpfn);
  1705. put('sqrt,'simpfn,'proper!-simpsqrt);
  1706. sqrt!-intvar:=mvar !*q2f simpsqrti intvar;
  1707. listofnewsqrts:= list mvar gaussiani; % Initialise the SQRT world.
  1708. listofallsqrts:= list (argof mvar gaussiani . gaussiani);
  1709. u:=for each v in cdr u
  1710. collect simp!* v;
  1711. sqrts!-in!-integrand:=sqrtsinsql(u,intvar);
  1712. u:=!*n2sq length differentials!-1 sqrts!-in!-integrand;
  1713. put('sqrt,'simpfn,simpfn);
  1714. printc list('time,'taken,readclock()-tt,'milliseconds);
  1715. return u
  1716. end;
  1717. put('genus,'simpfn,'simpgenus);
  1718. symbolic procedure differentials!-1 sqrtl;
  1719. begin
  1720. scalar asqrtl,faclist,places,v,nestedsqrts,basis,
  1721. u,n,hard!-ones,sqrts!-in!-problem;
  1722. % HARD!-ONES A list of all the factors of our equations which do
  1723. % not factor, and therefore such that we can divide the whole of
  1724. % our INTBASIS by their product in order to get the true INTBASIS,
  1725. % since these ones can cause no complications.
  1726. asqrtl:=for each u in sqrtl
  1727. collect !*q2f simp argof u;
  1728. if !*tra or !*trmin then <<
  1729. printc
  1730. "Find the differentials of the first kind on curve defined by:";
  1731. mapc(asqrtl,function printsf) >>;
  1732. for each s in asqrtl do <<
  1733. faclist:=for each u in jfactor(s,intvar)
  1734. collect numr u;
  1735. if !*tra then <<
  1736. princ intvar;
  1737. printc " is not a local variable at the roots of:";
  1738. mapc(faclist,function printsf) >>;
  1739. for each uu in faclist do <<
  1740. v:=stt(uu,intvar);
  1741. if 1 neq car v
  1742. then hard!-ones:=uu.hard!-ones
  1743. else <<
  1744. u:=addf(uu,(mksp(intvar,1) .* (negf cdr v)) .+ nil) ./ cdr v;
  1745. % U is now the value at which this SQRT has a zero.
  1746. u:=list(list(intvar,'difference,intvar,prepsq u),
  1747. list(intvar,'expt,intvar,2));
  1748. for each w in sqrtsign(for each w in union(delete(s,asqrtl),
  1749. delete(uu,faclist))
  1750. conc sqrtsinsq(simpsqrtsq
  1751. multsq(substitutesq(w ./ 1,u),
  1752. 1 ./ !*p2f mksp(intvar,2)),
  1753. intvar),
  1754. intvar)
  1755. do places:=append(u,w).places >> >> >>;
  1756. sqrts!-in!-problem:=nconc(for each u in hard!-ones
  1757. collect list(intvar.intvar,
  1758. (lambda u;u.u) list('sqrt,prepf u)),
  1759. places);
  1760. basis:=makeinitialbasis sqrts!-in!-problem;
  1761. % Bodge in any extra SQRTS that we will require later.
  1762. % u:=1 ./ mapply(function multf,
  1763. % for each u in sqrtl collect !*kk2f u);
  1764. % basis:=for each v in basis collect multsq(u,v);
  1765. basis:=integralbasis(mkvec basis,places,mkilist(places,-1),intvar);
  1766. if not !*galois
  1767. then basis:=combine!-sqrts(basis,
  1768. getsqrtsfromplaces sqrts!-in!-problem);
  1769. if hard!-ones
  1770. then <<
  1771. v:=upbv basis;
  1772. u:=1;
  1773. for each v in hard!-ones do
  1774. u:=multf(u,!*kk2f list('sqrt,prepf v));
  1775. hard!-ones:=1 ./ u;
  1776. for i:=0:v do
  1777. putv(basis,i,multsq(getv(basis,i),hard!-ones)) >>;
  1778. if not !*galois
  1779. then basis:=modify!-sqrts(basis,sqrtl);
  1780. v:=fractional!-degree!-at!-infinity sqrtl;
  1781. if v iequal 1
  1782. then n:=2
  1783. else n:=2*v-1;
  1784. % N is the degree of the zero we need at INFINITY.
  1785. basis:=normalbasis(basis,intvar,n);
  1786. previousbasis:=nil;
  1787. % it might have been set before, and we have changed its meaning.
  1788. if !*tra or !*trmin then <<
  1789. printc "Differentials are:";
  1790. mapc(basis,function printsq) >>;
  1791. return basis;
  1792. end;
  1793. endmodule;
  1794. module intbasis;
  1795. % Author: James H. Davenport.
  1796. fluid '(excoatespoles intvar previousbasis taylorasslist
  1797. taylorvariable);
  1798. global '(!*tra !*trmin);
  1799. exports completeplaces,completeplaces2,integralbasis;
  1800. symbolic procedure deleteplace(a,b);
  1801. if null b
  1802. then nil
  1803. else if equalplace(a,car b)
  1804. then cdr b
  1805. else (car b).deleteplace(a,cdr b);
  1806. symbolic procedure completeplaces(places,mults);
  1807. begin
  1808. scalar current,cp,cm,op,om,ansp,ansm;
  1809. if null places then return nil; %%% ACH
  1810. loop:
  1811. current:=basicplace car places;
  1812. while places do <<
  1813. if current = (basicplace car places)
  1814. then <<
  1815. cp:=(car places).cp;
  1816. cm:=(car mults ).cm >>
  1817. else <<
  1818. op:=(car places).op;
  1819. om:=(car mults ).om >>;
  1820. places:=cdr places;
  1821. mults:=cdr mults >>;
  1822. cp:=completeplaces2(cp,cm,sqrtsinplaces cp);
  1823. ansp:=append(car cp,ansp);
  1824. ansm:=append(cdr cp,ansm);
  1825. places:=op;
  1826. mults:=om;
  1827. cp:=op:=cm:=om:=nil;
  1828. if places
  1829. then go to loop
  1830. else return ansp.ansm
  1831. end;
  1832. symbolic procedure completeplaces2(places,mults,sqrts);
  1833. % Adds extra places with multiplicities of 0 as necessary.
  1834. begin scalar b,p;
  1835. sqrts:=sqrtsign(sqrts,intvar);
  1836. b:=basicplace car places;
  1837. p:=places;
  1838. while p do <<
  1839. if not(b = (basicplace car p))
  1840. then interr "Multiple places not supported";
  1841. sqrts:=deleteplace(extenplace car p,sqrts);
  1842. p:=cdr p >>;
  1843. mults:=nconc(nlist(0,length sqrts),mults);
  1844. places:=nconc(mappend(sqrts,b),places);
  1845. return places.mults
  1846. end;
  1847. symbolic procedure intbasisreduction(zbasis,places,mults);
  1848. begin
  1849. scalar i,m,n,v,w,substn,basis;
  1850. substn:=list(intvar.intvar);
  1851. % The X=X substitution.
  1852. n:=upbv zbasis;
  1853. basis:=copyvec(zbasis,n);
  1854. taylorvariable:=intvar;
  1855. v:=sqrtsinplaces places;
  1856. for i:=0:n do
  1857. w:=union(w,sqrtsinsq(getv(basis,i),intvar));
  1858. m:=intersect(v,w);
  1859. v:=purge(m,v);
  1860. w:=purge(m,w);
  1861. for each u in v do <<
  1862. if !*tra or !*trmin then <<
  1863. printc u;
  1864. printc "does not occur in the functions";
  1865. mapvec(basis,function printsq) >>;
  1866. m:=!*q2f simp argof u;
  1867. i:=w;
  1868. while i and not quotf(m,!*q2f simp argof car i)
  1869. do i:=cdr i;
  1870. if null i
  1871. then interr
  1872. "Unable to find equivalent representation of branches";
  1873. i:=car i;
  1874. w:=delete(i,w);
  1875. places:=subst(i,u,places);
  1876. if !*tra or !*trmin then <<
  1877. printc "replaced by";
  1878. printc i >> >>;
  1879. if (length places) neq (iadd1 n) then <<
  1880. if !*tra
  1881. then printc "Too many functions";
  1882. basis := shorten!-basis basis;
  1883. n:=upbv basis >>;
  1884. m:=mkvect n;
  1885. for i:=0:n do
  1886. putv(m,i,cl6roweval(basis.i,places,mults,substn));
  1887. reductionloop:
  1888. if !*tra then <<
  1889. printc "Matrix before a reduction step:";
  1890. mapvec(m,function printc) >>;
  1891. v:=firstlinearrelation(m,iadd1 n);
  1892. if null v
  1893. then return replicatebasis(basis,(iadd1 upbv zbasis)/(n+1));
  1894. i:=n;
  1895. while null numr getv(v,i) do
  1896. i:=isub1 i;
  1897. w:=nil ./ 1;
  1898. for j:=0:i do
  1899. w:=!*addsq(w,!*multsq(getv(basis,j),getv(v,j)));
  1900. w:=removecmsq multsq(w,1 ./ !*p2f mksp(intvar,1));
  1901. if null numr w
  1902. then <<
  1903. mapvec(basis,function printsq);
  1904. printc iadd1 i;
  1905. interr "Basis collapses" >>;
  1906. if !*tra then <<
  1907. princ "Element ";
  1908. princ iadd1 i;
  1909. printc " of the basis replaced by ";
  1910. if !*tra then
  1911. printsq w >>;
  1912. putv(basis,i,w);
  1913. putv(m,i,cl6roweval(basis.i,places,mults,substn));
  1914. goto reductionloop
  1915. end;
  1916. symbolic procedure integralbasis(basis,places,mults,x);
  1917. begin
  1918. scalar z,save,points,p,m,princilap!-part,mm;
  1919. if null places
  1920. then return basis;
  1921. mults:=mapcar(mults,function (lambda u;min(u,0)));
  1922. % this makes sure that we impose constraints only on
  1923. % poles, not on zeroes.
  1924. points:=removeduplicates mapcar(places,function basicplace);
  1925. if points = list(x.x)
  1926. then basis:=intbasisreduction(basis,places,mults)
  1927. else if cdr points
  1928. then go complex
  1929. else <<
  1930. substitutevec(basis,car points);
  1931. if !*tra then <<
  1932. printc "Integral basis reduction at";
  1933. printc car points >>;
  1934. basis:=intbasisreduction(basis,
  1935. mapcar(places,function extenplace),
  1936. mults);
  1937. substitutevec(basis,antisubs(car points,x)) >>;
  1938. join:
  1939. save:=taylorasslist;
  1940. % we will not need te taylorevaluates at gensym.
  1941. z:=gensym();
  1942. places:=mapcons(places,x.list('difference,x,z));
  1943. z:=list(x . z);
  1944. % basis:=intbasisreduction(basis,
  1945. % places,
  1946. % nlist(0,length places),
  1947. % x,z);
  1948. taylorasslist:=save;
  1949. % ***time-hack-2***;
  1950. if not excoatespoles
  1951. then previousbasis:=copyvec(basis,upbv basis);
  1952. % Save only if in COATES/FINDFUNCTION, not if in EXCOATES.
  1953. return basis;
  1954. complex:
  1955. while points do <<
  1956. p:=places;
  1957. m:=mults;
  1958. princilap!-part:=mm:=nil;
  1959. while p do <<
  1960. if (car points) = (basicplace car p)
  1961. then <<
  1962. princilap!-part:=(extenplace car p).princilap!-part;
  1963. mm:=(car m).mm >>;
  1964. p:=cdr p;
  1965. m:=cdr m >>;
  1966. substitutevec(basis,car points);
  1967. if !*tra then <<
  1968. printc "Integral basis reduction at";
  1969. printc car points >>;
  1970. basis:=intbasisreduction(basis,princilap!-part,mm);
  1971. substitutevec(basis,antisubs(car points,x));
  1972. points:=cdr points >>;
  1973. go to join
  1974. end;
  1975. symbolic procedure cl6roweval(basisloc,places,mults,x!-alpha);
  1976. % Evaluates a row of the matrix in coates lemma 6.
  1977. begin
  1978. scalar i,v,w,save,basiselement,taysave,mmults,flg;
  1979. i:=isub1 length places;
  1980. v:=mkvect i;
  1981. taysave:=mkvect i;
  1982. i:=0;
  1983. basiselement:=getv(car basisloc,cdr basisloc);
  1984. mmults:=mults;
  1985. while places do <<
  1986. w:=substitutesq(basiselement,car places);
  1987. w:=taylorform substitutesq(w,x!-alpha);
  1988. % The separation of these 2 is essential since the x->x-a
  1989. % must occur after the places are chosen.
  1990. save:=taylorasslist;
  1991. if not flg
  1992. then putv(taysave,i,w);
  1993. w:=taylorevaluate(w,car mmults);
  1994. tayshorten save;
  1995. putv(v,i,w);
  1996. i:=iadd1 i;
  1997. flg:=flg or numr w;
  1998. mmults:=cdr mmults;
  1999. places:=cdr places >>;
  2000. if flg
  2001. then return v;
  2002. % There was a non-zero element in this row.
  2003. save:=0;
  2004. loop:
  2005. save:=iadd1 save;
  2006. mmults:=mults;
  2007. i:=0;
  2008. while mmults do <<
  2009. w:=taylorevaluate(getv(taysave,i),save + car mmults);
  2010. flg:=flg or numr w;
  2011. mmults:=cdr mmults;
  2012. putv(v,i,w);
  2013. i:=iadd1 i >>;
  2014. if not flg
  2015. then go to loop;
  2016. % Another zero row.
  2017. putv(car basisloc,cdr basisloc,multsq(basiselement,
  2018. 1 ./ !*p2f mksp(intvar,save)));
  2019. return v
  2020. end;
  2021. symbolic procedure replicatebasis(basis,n);
  2022. if n = 1
  2023. then basis
  2024. else if n = 2
  2025. then begin
  2026. scalar b,sqintvar,len;
  2027. len:=upbv basis;
  2028. sqintvar:=!*kk2q intvar;
  2029. b:=mkvect(2*len+1);
  2030. for i:=0:len do <<
  2031. putv(b,i,getv(basis,i));
  2032. putv(b,i+len+1,multsq(sqintvar,getv(basis,i))) >>;
  2033. return b
  2034. end
  2035. else interr "Unexpected replication request";
  2036. symbolic procedure shorten!-basis v;
  2037. begin
  2038. scalar u,n,sfintvar;
  2039. sfintvar:=!*kk2f intvar;
  2040. n:=upbv v;
  2041. for i:=0:n do begin
  2042. scalar uu;
  2043. uu:=getv(v,i);
  2044. if not quotf(numr uu,sfintvar)
  2045. then u:=uu.u
  2046. end;
  2047. return mkvec u
  2048. end;
  2049. endmodule;
  2050. module jhddiff;
  2051. % Author: James H. Davenport.
  2052. fluid '(dw);
  2053. % Differentiation routines for algebraic expressions;
  2054. symbolic procedure !*diffsq(u,v);
  2055. %U is a standard quotient, V a kernel.
  2056. %Value is the standard quotient derivative of U wrt V.
  2057. %Algorithm: df(x/y,z)= (x'-(x/y)*y')/y;
  2058. !*multsq(!*addsq(!*difff(numr u,v),
  2059. negsq !*multsq(u,!*difff(denr u,v))),
  2060. 1 ./ denr u);
  2061. symbolic procedure !*difff(u,v);
  2062. %U is a standard form, V a kernel.
  2063. %Value is the standard quotient derivative of U wrt V;
  2064. if domainp u then nil ./ 1
  2065. else !*addsq(!*addsq(multpq(lpow u,!*difff(lc u,v)),
  2066. !*multsq(lc u ./ 1,!*diffp(lpow u,v))),
  2067. !*difff(red u,v));
  2068. symbolic procedure !*diffp(u,v);
  2069. % Special treatment of SQRT's (JHD is not sure why,
  2070. % but it seems to be necessary);
  2071. if atom (car u) then diffp(u,v)
  2072. else if not (caar u) eq 'sqrt then diffp(u,v)
  2073. else begin
  2074. scalar w,dw;
  2075. w:=simp argof car u;
  2076. dw:= !*diffsq(w,v);
  2077. if null numr dw then return dw;
  2078. return !*multsq(!*multsq(dw,invsq w),
  2079. !*multf(cdr u,mksp(car u,1) .* 1 .+ nil)./ 2)
  2080. end;
  2081. endmodule;
  2082. module jhdriver;
  2083. % Author: James H. Davenport.
  2084. fluid '(!*backtrace
  2085. basic!-listofallsqrts
  2086. basic!-listofnewsqrts
  2087. expression
  2088. gaussiani
  2089. intvar
  2090. listofallsqrts
  2091. listofnewsqrts
  2092. previousbasis
  2093. sqrt!-intvar
  2094. sqrtflag
  2095. sqrts!-in!-integrand
  2096. sqrts!-mod!-prime
  2097. taylorasslist
  2098. varlist
  2099. zlist);
  2100. global '(!*algint !*coates !*noacn !*tra !*trmin btrlevel tryharder);
  2101. switch algint,coates,noacn,tra,trmin;
  2102. exports algebraiccase,doalggeom,coates!-multiple;
  2103. !*algint := t; % Assume algebraic integration wanted if this module
  2104. % is loaded.
  2105. symbolic procedure operateon(reslist,x);
  2106. begin
  2107. scalar u,v,answer,save;
  2108. scalar sqrts!-mod!-prime;
  2109. u:=zmodule(reslist);
  2110. v:=answer:=nil ./ 1;
  2111. while u and not atom v do <<
  2112. v:=findfunction cdar u;
  2113. if not atom v then <<
  2114. if !*tra or !*trmin then <<
  2115. printc "Extension logarithm is ";
  2116. printsq v >>;
  2117. save:=tryharder;
  2118. tryharder:=x;
  2119. v:= !*multsq(simp!* caar u,
  2120. simplogsq v);
  2121. tryharder:=save;
  2122. answer:=addsq(answer,v);
  2123. u:=cdr u >> >>;
  2124. if atom v
  2125. then return v
  2126. else return answer
  2127. end;
  2128. symbolic procedure findfunction divisor;
  2129. begin
  2130. scalar v,places,mults,ans,dof1k;
  2131. scalar previousbasis;
  2132. % ***time-hack-2 :::
  2133. % A hack for decreasing the amount of work done in COATES.
  2134. divisor:=for each u in divisor collect
  2135. correct!-mults u;
  2136. if !*coates
  2137. then go to nohack;
  2138. v:=precoates(divisor,intvar,nil);
  2139. if not atom v
  2140. then return v;
  2141. nohack:
  2142. for each u in divisor do <<
  2143. places:=(car u).places;
  2144. mults :=(cdr u).mults >>;
  2145. v:=coates(places,mults,intvar);
  2146. if not atom v
  2147. then return v;
  2148. dof1k:=differentials!-1 getsqrtsfromplaces places;
  2149. if null dof1k
  2150. then interr "Must be able to integrate over curves of genus 0";
  2151. if not mazurp(places,dof1k)
  2152. then go to general;
  2153. ans:='provably!-impossible;
  2154. for i:=2:12 do
  2155. if (i neq 11) and
  2156. not atom (ans:=coates!-multiple(places,mults,i))
  2157. then i:=12; % leave the loop - we have an answer.
  2158. return ans;
  2159. general:
  2160. v:=findmaninparm places;
  2161. if null v
  2162. then return algebraic!-divisor(divisor,dof1k);
  2163. if not maninp(divisor,v,dof1k)
  2164. then return 'provably!-impossible;
  2165. v:=1;
  2166. loop:
  2167. v:=iadd1 v;
  2168. if not atom (ans:=coates!-multiple(places,mults,v))
  2169. then return ans;
  2170. go to loop
  2171. end;
  2172. symbolic procedure correct!-mults u;
  2173. begin
  2174. scalar multip;
  2175. multip:=cdr u;
  2176. for each v in car u do
  2177. if (lsubs v eq intvar) and
  2178. eqcar(rsubs v,'expt)
  2179. then multip:=multip * (caddr rsubs v);
  2180. return (car u).multip
  2181. end;
  2182. symbolic procedure algebraiccase
  2183. (expression,zlist,varlist);
  2184. begin
  2185. scalar rischpart,deriv,w,firstterm;
  2186. scalar sqrtflag;
  2187. sqrtflag:=t;
  2188. sqrtsave(listofallsqrts,listofnewsqrts,list(intvar . intvar));
  2189. rischpart:=errorset('(doalggeom expression),
  2190. if !*tra or !*trmin then t else btrlevel,
  2191. !*backtrace);
  2192. newplace list (intvar.intvar);
  2193. if atom rischpart
  2194. then <<
  2195. if !*tra then printc "Inner integration failed";
  2196. deriv:=nil ./ 1;
  2197. % assume no answer.
  2198. rischpart:=deriv >>
  2199. else
  2200. if atom car rischpart
  2201. then <<
  2202. if !*tra or !*trmin then
  2203. printc "The 'logarithmic part' is not elementary";
  2204. return simpint1 list ('int,prepsq expression,intvar) >>
  2205. else <<
  2206. rischpart:=car rischpart;
  2207. deriv:=!*diffsq(rischpart,intvar);
  2208. % deriv := squashsqrt deriv;
  2209. % Should no longer be necessary.
  2210. if !*tra or !*trmin then <<
  2211. printc "Inner working yields";
  2212. printsq rischpart;
  2213. printc "with derivative";
  2214. printsq deriv >> >>;
  2215. deriv:=!*addsq(expression,negsq deriv);
  2216. if null numr deriv
  2217. then return rischpart; % no algebraic part.
  2218. if null involvesq(deriv,intvar)
  2219. then return !*addsq(rischpart,
  2220. !*multsq(deriv,((mksp(intvar,1) .* 1) .+ nil) ./ 1));
  2221. % if the difference is merely a constant.
  2222. varlist:=getvariables deriv;
  2223. zlist:=findzvars(varlist,list intvar,intvar,nil);
  2224. varlist:=purge(zlist,varlist);
  2225. firstterm:=simp!* car zlist; % this may crop up.
  2226. w:=sqrt2top !*multsq(deriv,invsq !*diffsq(firstterm,intvar));
  2227. if null involvesq(w,intvar)
  2228. then return !*addsq(rischpart,!*multsq(w,firstterm));
  2229. if !*noacn then interr "Testing only logarithmic code";
  2230. deriv:=transcendentalcase(deriv,intvar,nil,zlist,varlist);
  2231. return !*addsq(deriv,rischpart)
  2232. end;
  2233. symbolic procedure doalggeom(differential);
  2234. begin
  2235. scalar reslist,place,placelist,
  2236. savetaylorasslist,sqrts!-in!-integrand,
  2237. taylorasslist;
  2238. placelist:=findpoles(differential,intvar);
  2239. reslist:=nil;
  2240. sqrts!-in!-integrand:=sqrtsinsq (differential,intvar);
  2241. while placelist do <<
  2242. place:=car placelist;
  2243. placelist:=cdr placelist;
  2244. savetaylorasslist:=taylorasslist;
  2245. place:=find!-residue(differential,intvar,place);
  2246. if place
  2247. then reslist:=append(place,reslist)
  2248. else taylorasslist:=savetaylorasslist >>;
  2249. if reslist
  2250. then go to serious;
  2251. if !*tra or !*trmin
  2252. then printc "No residues => no logs";
  2253. return nil ./ 1;
  2254. serious:
  2255. placelist:=operateon(reslist,intvar);
  2256. if placelist eq 'failed
  2257. then interr "Divisor operations failed";
  2258. return placelist
  2259. end;
  2260. symbolic procedure algebraic!-divisor(divisor,dof1k);
  2261. if length dof1k = 1
  2262. then lutz!-nagell(divisor)
  2263. else bound!-torsion(divisor,dof1k);
  2264. symbolic procedure coates!-multiple(places,mults,v);
  2265. begin
  2266. scalar ans;
  2267. if not atom (ans:=coates(places,
  2268. for each u in mults collect v*u,
  2269. intvar))
  2270. then <<
  2271. if !*tra or !*trmin then <<
  2272. princ "Divisor has order ";
  2273. printc v >>;
  2274. return !*kk2q list('nthroot,mk!*sq ans,v) >>
  2275. else return ans
  2276. end;
  2277. symbolic procedure mazurp(places,dof1k);
  2278. % Checks to ensure we have an elliptic curve over the rationals.
  2279. begin
  2280. % scalar sqrt2,sqrt4,v;
  2281. % sqrt2:=0;
  2282. % % Number of SQRTs of things of degree 1 or 2;
  2283. % sqrt4:=0;
  2284. % % " " " 3 or 4;
  2285. % for each u in getsqrtsfromplaces places do <<
  2286. % v:=!*q2f simp u;
  2287. % if sqrtsinsq(v,intvar)
  2288. % then return nil;
  2289. % % Cannot use nested SQRTs;
  2290. % v:=car stt(v,intvar);
  2291. % if v < 3
  2292. % then if sqrt4>0
  2293. % then return nil
  2294. % else if sqrt2>1
  2295. % then return nil
  2296. % else sqrt2:=iadd1 sqrt2
  2297. % else if v < 5
  2298. % then if sqrt2>0 or sqrt4>0
  2299. % then return nil
  2300. % else sqrt4:=1
  2301. % else return nil >>;
  2302. scalar answer;
  2303. if length dof1k neq 1
  2304. then return nil;
  2305. % Genus = # linearly independent differentials of 1st kind;
  2306. % We know know that it is of genus = 1.
  2307. answer:=t;
  2308. while answer and places do
  2309. if sqrtsintree(basicplace car places,nil,nil)
  2310. then answer:= nil
  2311. else places:=cdr places;
  2312. if null answer then return nil;
  2313. if !*tra then
  2314. <<prin2 "*** We can apply Mazur's bound on the torsion of";
  2315. prin2t "elliptic curves over the rationals">>;
  2316. return t
  2317. end;
  2318. endmodule;
  2319. module linrel;
  2320. % Author: James H. Davenport.
  2321. symbolic procedure firstlinearrelation(m,n);
  2322. % Returns vector giving first linear relation between
  2323. % the rows of n*n matrix m.
  2324. begin
  2325. scalar mm,u,uu,v,w,x,xx,i,j,isub1n,ans;
  2326. isub1n:=isub1 n;
  2327. mm:=mkvect(isub1n);
  2328. for i:=0 step 1 until isub1n do
  2329. putv(mm,i,copyvec(getv(m,i),isub1n));
  2330. % mm is a copy of m which we can afford to destroy.
  2331. ans:=mkidenm isub1n;
  2332. i:=0;
  2333. outerloop:
  2334. u:=getv(mm,i);
  2335. uu:=getv(ans,i);
  2336. j:=0;
  2337. pivotsearch:
  2338. if j iequal n
  2339. then goto zerorow;
  2340. v:=getv(u,j);
  2341. if null numr v then << j:=iadd1 j; goto pivotsearch >>;
  2342. % we now use the j-th element of row i to flatten the j-th
  2343. % element of all later rows.
  2344. if i iequal isub1n then return nil;
  2345. %no further rows to flatten, so no relationships.
  2346. v:=!*invsq negsq v;
  2347. for k:=iadd1 i step 1 until isub1n do <<
  2348. xx:=getv(ans,k);
  2349. x:=getv(mm,k);
  2350. w:=!*multsq(v,getv(x,j));
  2351. for l:=0:isub1n do <<
  2352. putv(x,l,addsq(getv(x,l),!*multsq(w,getv(u,l))));
  2353. putv(xx,l,addsq(getv(xx,l),!*multsq(w,getv(uu,l)))) >> >>;
  2354. i:=iadd1 i;
  2355. if i < n then goto outerloop;
  2356. % no zero rows found at all.
  2357. return nil;
  2358. zerorow:
  2359. % the i-t row is all zero, i.e. rows 1...i are dependent.
  2360. return getv(ans,i)
  2361. end;
  2362. endmodule;
  2363. module maninp;
  2364. % Author: James H. Davenport.
  2365. fluid '(intvar);
  2366. symbolic procedure findmaninparm places;
  2367. begin
  2368. scalar sqrts,vars,u;
  2369. sqrts:=sqrtsinplaces places;
  2370. loop:
  2371. if null sqrts then return nil;
  2372. vars:=getvariables simp argof car sqrts;
  2373. innerloop:
  2374. if null vars
  2375. then <<
  2376. sqrts:=cdr sqrts;
  2377. go to loop >>;
  2378. u:=car vars;
  2379. vars:=cdr vars;
  2380. if u eq intvar
  2381. then go to innerloop;
  2382. if atom u
  2383. then return u;
  2384. if car u eq 'sqrt
  2385. then << u:=simp argof u;
  2386. vars:=varsinsf(numr u,varsinsf(denr u,vars));
  2387. go to innerloop >>;
  2388. interr "Unrecognised differentiation candidate"
  2389. end;
  2390. endmodule;
  2391. module modify;
  2392. % Author: James H. Davenport.
  2393. fluid '(intvar);
  2394. global '(!*tra);
  2395. exports modify!-sqrts,combine!-sqrts;
  2396. symbolic procedure modify!-sqrts(basis,sqrtl);
  2397. begin
  2398. scalar sqrtl!-in!-sf,n,u,v,f;
  2399. n:=upbv basis;
  2400. sqrtl!-in!-sf:=for each u in sqrtl collect
  2401. !*q2f simp argof u;
  2402. for i:=0:n do begin
  2403. u:=getv(basis,i);
  2404. v:=sqrtsinsq(u,intvar);
  2405. % We have two tasks to perform,
  2406. % the replacing of SQRT(A)*SQRT(B) by SQRT(A*B)
  2407. % where relevant and the replacing of SQRT(A)
  2408. % by SQRT(A*B) or 1 (depending on whether it occurs in
  2409. % the numerator or the denominator).
  2410. v:=purge(sqrtl,v);
  2411. if null v
  2412. then go to nochange;
  2413. u:=sqrt2top u;
  2414. u:=multsq(modify2(numr u,v,sqrtl!-in!-sf) ./ 1,
  2415. 1 ./ modify2(denr u,v,sqrtl!-in!-sf));
  2416. v:=sqrtsinsq(u,intvar);
  2417. v:=purge(sqrtl,v);
  2418. if v then <<
  2419. if !*tra then <<
  2420. printc "Discarding element";
  2421. printsq u >>;
  2422. putv(basis,i,1 ./ 1) >>
  2423. else putv(basis,i,removecmsq u);
  2424. f:=t;
  2425. nochange:
  2426. end;
  2427. basis:=mkuniquevect basis;
  2428. if f and !*tra then <<
  2429. printc "Basis replaced by";
  2430. mapvec(basis,function printsq) >>;
  2431. return basis
  2432. end;
  2433. symbolic procedure combine!-sqrts(basis,sqrtl);
  2434. begin
  2435. scalar sqrtl!-in!-sf,n,u,v,f;
  2436. n:=upbv basis;
  2437. sqrtl!-in!-sf:=for each u in sqrtl collect
  2438. !*q2f simp argof u;
  2439. for i:=0:n do begin
  2440. u:=getv(basis,i);
  2441. v:=sqrtsinsq(u,intvar);
  2442. % We have one task to perform,
  2443. % the replacing of SQRT(A)*SQRT(B) by SQRT(A*B)
  2444. % where relevant.
  2445. v:=purge(sqrtl,v);
  2446. if null v
  2447. then go to nochange;
  2448. u:=multsq(modify2(numr u,v,sqrtl!-in!-sf) ./ 1,
  2449. 1 ./ modify2(denr u,v,sqrtl!-in!-sf));
  2450. putv(basis,i,u);
  2451. f:=t;
  2452. nochange:
  2453. end;
  2454. if f and !*tra then <<
  2455. printc "Basis replaced by";
  2456. mapvec(basis,function printsq) >>;
  2457. return basis
  2458. end;
  2459. symbolic procedure modify2(sf,sqrtsin,realsqrts);
  2460. if atom sf
  2461. then sf
  2462. else if atom mvar sf
  2463. then sf
  2464. else if eqcar(mvar sf,'sqrt) and dependsp(mvar sf,intvar)
  2465. then begin
  2466. scalar u,v,w,lcsf,sqrtsin2,w2,lcsf2,temp;
  2467. u:=!*q2f simp argof mvar sf;
  2468. v:=realsqrts;
  2469. while v and null (w:=modify!-quotf(car v,u))
  2470. do v:=cdr v;
  2471. if null v
  2472. then <<
  2473. if !*tra then <<
  2474. printc "Unable to modify (postponed)";
  2475. printsf !*kk2f mvar sf >>;
  2476. return sf >>;
  2477. v:=car v;
  2478. % We must modify SQRT(U) into SQRT(V) if possible.
  2479. lcsf:=lc sf;
  2480. sqrtsin2:=delete(mvar sf,sqrtsin);
  2481. while sqrtsin2 and (w neq 1) do <<
  2482. temp:=!*q2f simp argof car sqrtsin2;
  2483. if (w2:=modify!-quotf(w,temp)) and
  2484. (lcsf2:=modify!-quotf(lcsf,!*kk2f car sqrtsin2))
  2485. then <<
  2486. w:=w2;
  2487. lcsf:=lcsf2 >>;
  2488. sqrtsin2:=cdr sqrtsin2 >>;
  2489. if w = 1
  2490. then return addf(multf(lcsf,formsqrt v),
  2491. modify2(red sf,sqrtsin,realsqrts));
  2492. % It is important to use FORMSQRT here since
  2493. % SIMPSQRT will recreate the factorisation
  2494. % we are trying to destroy.
  2495. % Satisfactorily explained away.
  2496. return addf(multf(!*p2f lpow sf,
  2497. modify2(lc sf,sqrtsin,realsqrts)),
  2498. modify2(red sf,sqrtsin,realsqrts))
  2499. end
  2500. else addf(multf(!*p2f lpow sf,
  2501. modify2(lc sf,sqrtsin,realsqrts)),
  2502. modify2(red sf,sqrtsin,realsqrts));
  2503. %symbolic procedure modifydown(sf,sqrtl);
  2504. %if atom sf
  2505. % then sf
  2506. % else if atom mvar sf
  2507. % then sf
  2508. % else if eqcar(mvar sf,'sqrt) and
  2509. % dependsp(mvar sf,intvar) and
  2510. % not member(!*q2f simp argof mvar sf,sqrtl)
  2511. % then addf(modifydown(lc sf,sqrtl),
  2512. % modifydown(red sf,sqrtl))
  2513. % else addf(multf(!*p2f lpow sf,
  2514. % modifydown(lc sf,sqrtl)),
  2515. % modifydown(red sf,sqrtl));
  2516. % symbolic procedure modifyup(sf,sqrtl);
  2517. % if atom sf
  2518. % then sf
  2519. % else if atom mvar sf
  2520. % then sf
  2521. % else if eqcar(mvar sf,'sqrt) and
  2522. % dependsp(mvar sf,intvar)
  2523. % then begin
  2524. % scalar u,v;
  2525. % u:=!*q2f simp argof mvar sf;
  2526. % if u member sqrtl
  2527. % then return addf(multf(!*p2f lpow sf,
  2528. % modifyup(lc sf,sqrtl)),
  2529. % modifyup(red sf,sqrtl));
  2530. % v:=sqrtl;
  2531. % while v and not modify!-quotf(car v,u)
  2532. % do v:=cdr v;
  2533. % if null v
  2534. % then interr "No sqrt to upgrade to";
  2535. % return addf(multf(!*kk2f simpsqrt2 car v,
  2536. % modifyup(lc sf,sqrtl)),
  2537. % modifyup(red sf,sqrtl))
  2538. % end
  2539. % else addf(multf(!*p2f lpow sf,
  2540. % modifyup(lc sf,sqrtl)),
  2541. % modifyup(red sf,sqrtl));
  2542. symbolic procedure modify!-quotf(u,v);
  2543. % Replacement for quotf, in that it gets sqrts right.
  2544. if atom v or atom mvar v
  2545. then quotf(u,v)
  2546. else if u=v then 1
  2547. else begin
  2548. scalar sq;
  2549. sq:=sqrt2top(u ./ v);
  2550. if involvesf(denr sq,intvar)
  2551. then return nil;
  2552. if not onep denr sq
  2553. then if not numberp denr sq
  2554. then interr "Gauss' lemma violated in modify"
  2555. else if !*tra
  2556. then <<
  2557. printc "*** Denominator ignored in modify";
  2558. printc denr sq >>;
  2559. return numr sq
  2560. end;
  2561. endmodule;
  2562. module modlineq;
  2563. % Author: James H. Davenport.
  2564. fluid '(current!-modulus sqrts!-mod!-prime);
  2565. global '(!*tra !*trmin list!-of!-medium!-primes sqrts!-mod!-8);
  2566. exports check!-lineq;
  2567. list!-of!-medium!-primes:='(101 103 107 109);
  2568. sqrts!-mod!-8:=mkvect 7;
  2569. putv(sqrts!-mod!-8,0,t);
  2570. putv(sqrts!-mod!-8,1,t);
  2571. putv(sqrts!-mod!-8,4,t);
  2572. symbolic procedure modp!-nth!-root(m,n,p);
  2573. begin
  2574. scalar j,p2;
  2575. p2:=p/2;
  2576. for i:=-p2 step 1 until p2 do
  2577. if modular!-expt(i,n) iequal m
  2578. then << j:=i; i:=p2 >>;
  2579. return j
  2580. end;
  2581. symbolic procedure modp!-sqrt(n,p);
  2582. begin
  2583. scalar p2,s,tt;
  2584. p2:=p/2;
  2585. if n < 0
  2586. then n:=n+p;
  2587. for i:=0:p2 do begin
  2588. tt:=n+p*i;
  2589. if null getv(sqrts!-mod!-8,tt irem 8)
  2590. then return;
  2591. % mod 8 test for perfect squares.
  2592. if (iadd1 tt irem 5) > 2
  2593. then return;
  2594. % squares are -1,0,1 mod 5.
  2595. s:=int!-sqrt tt;
  2596. if fixp s then <<
  2597. p2:=0;
  2598. return >>
  2599. end;
  2600. if (not fixp s) or null s
  2601. then return nil
  2602. else return s
  2603. end;
  2604. symbolic procedure subsetp(a,b);
  2605. %True if all members of a are also members of b.
  2606. if null a then t
  2607. else if member(car a,b) then subsetp(cdr a,b)
  2608. else nil;
  2609. symbolic procedure check!-lineq(m,rightside);
  2610. begin
  2611. scalar vlist,n1,n2,u,primelist,mm,v,modp!-subs,atoms;
  2612. n1:=upbv m;
  2613. for i:=0:n1 do <<
  2614. u:=getv(m,i);
  2615. if u
  2616. then for j:=0:(n2:=upbv u) do
  2617. vlist:=varsinsq(getv(u,j),vlist) >>;
  2618. u:=vlist;
  2619. while u do <<
  2620. v:=car u;
  2621. u:=cdr u;
  2622. if atom v
  2623. then atoms:=v.atoms
  2624. else if (car v eq 'sqrt) or (car v eq 'expt)
  2625. then for each w in varsinsf(!*q2f simp argof v,nil) do
  2626. if not (w member vlist)
  2627. then <<
  2628. u:=w.u;
  2629. vlist:=w.vlist >>
  2630. else nil
  2631. else interr "Unexpected item" >>;
  2632. if sqrts!-mod!-prime and
  2633. subsetp(vlist,for each u in cdr sqrts!-mod!-prime
  2634. collect car u)
  2635. then go to end!-of!-loop;
  2636. vlist:=purge(atoms,vlist);
  2637. u:=nil;
  2638. for each v in vlist do
  2639. if car v neq 'sqrt
  2640. then u:=v.u;
  2641. vlist:=nconc(u,sortsqrts(purge(u,vlist),nil));
  2642. % NIL is the variable to measure nesting on:
  2643. % therefore all nesting is being caught.
  2644. primelist:=list!-of!-medium!-primes;
  2645. set!-modulus car primelist;
  2646. atoms:=for each u in atoms collect
  2647. u . modular!-number random car primelist;
  2648. goto try!-prime;
  2649. next!-prime:
  2650. primelist:=cdr primelist;
  2651. if null primelist and !*tra
  2652. then printc "Ran out of primes in check!-lineq";
  2653. if null primelist
  2654. then return t;
  2655. set!-modulus car primelist;
  2656. try!-prime:
  2657. modp!-subs:=atoms;
  2658. v:=vlist;
  2659. loop:
  2660. if null v
  2661. then go to end!-of!-loop;
  2662. u:=modp!-subst(simp argof car v,modp!-subs);
  2663. if caar v eq 'sqrt
  2664. then u:=modp!-sqrt(u,car primelist)
  2665. else if caar v eq 'expt
  2666. then u:=modp!-nth!-root(modular!-expt(u,cadr caddr car v),
  2667. caddr caddr car v,car primelist)
  2668. else interr "Unexpected item";
  2669. if null u
  2670. then go to next!-prime;
  2671. modp!-subs:=(car v . u) . modp!-subs;
  2672. v:=cdr v;
  2673. go to loop;
  2674. end!-of!-loop:
  2675. if null primelist
  2676. then <<
  2677. setmod(car sqrts!-mod!-prime);
  2678. modp!-subs:=cdr sqrts!-mod!-prime >>
  2679. else sqrts!-mod!-prime:=(car primelist).modp!-subs;
  2680. mm:=mkvect n1;
  2681. for i:=0:n1 do begin
  2682. u:=getv(m,i);
  2683. if null u
  2684. then return;
  2685. putv(mm,i,v:=mkvect n2);
  2686. for j:=0:n2 do
  2687. putv(v,j,modp!-subst(getv(u,j),modp!-subs))
  2688. end;
  2689. v:=mkvect n1;
  2690. for i:=0:n1 do
  2691. putv(v,i,modp!-subst(getv(rightside,i),modp!-subs));
  2692. u:=mod!-jhdsolve(mm,v);
  2693. if (u eq 'failed) and (!*tra or !*trmin)
  2694. then <<
  2695. princ "Proved insoluble mod ";
  2696. printc car sqrts!-mod!-prime >>;
  2697. return u
  2698. end;
  2699. symbolic procedure modp!-subst(sq,slist);
  2700. modular!-quotient(modp!-subf(numr sq,slist),
  2701. modp!-subf(denr sq,slist));
  2702. symbolic procedure modp!-subf(sf,slist);
  2703. if atom sf
  2704. then if null sf
  2705. then 0
  2706. else modular!-number sf
  2707. else begin
  2708. scalar u;
  2709. u:=assoc(mvar sf,slist);
  2710. if null u
  2711. then interr "Unexpected variable";
  2712. return modular!-plus(modular!-times(modular!-expt(cdr u,ldeg sf),
  2713. modp!-subf(lc sf,slist)),
  2714. modp!-subf(red sf,slist))
  2715. end;
  2716. symbolic procedure mod!-jhdsolve(m,rightside);
  2717. % Returns answer to m.answer=rightside.
  2718. % Matrix m not necessarily square.
  2719. begin
  2720. scalar n1,n2,ans,u,row,swapflg,swaps;
  2721. % The SWAPFLG is true if we have changed the order of the
  2722. % columns and need later to invert this via SWAPS.
  2723. n1:=upbv m;
  2724. for i:=0:n1 do
  2725. if (u:=getv(m,i))
  2726. then (n2:=upbv u);
  2727. swaps:=mkvect n2;
  2728. for i:=0:n2 do
  2729. putv(swaps,i,n2-i);
  2730. % We have the SWAPS vector, which should be a vector of indices,
  2731. % arranged like this because VECSORT sorts in decreasing order.
  2732. for i:=0:isub1 n1 do begin
  2733. scalar k,v,pivot;
  2734. tryagain:
  2735. row:=getv(m,i);
  2736. if null row
  2737. then go to interchange;
  2738. % look for a pivot in row.
  2739. k:=-1;
  2740. for j:=0:n2 do
  2741. if not zerop (pivot:=getv(row,j))
  2742. then <<
  2743. k:=j;
  2744. j:=n2 >>;
  2745. if k neq -1
  2746. then goto newrow;
  2747. if not zerop getv(rightside,i)
  2748. then <<
  2749. m:='failed;
  2750. i:=sub1 n1; %Force end of loop.
  2751. go to finished >>;
  2752. interchange:
  2753. % now interchange i and last element.
  2754. swap(m,i,n1);
  2755. swap(rightside,i,n1);
  2756. n1:=isub1 n1;
  2757. if i iequal n1
  2758. then goto finished
  2759. else goto tryagain;
  2760. newrow:
  2761. if i neq k
  2762. then <<
  2763. swapflg:=t;
  2764. swap(swaps,i,k);
  2765. % record what we have done.
  2766. for l:=0:n1 do
  2767. swap(getv(m,l),i,k) >>;
  2768. % place pivot on diagonal.
  2769. pivot:=modular!-minus modular!-reciprocal pivot;
  2770. for j:=iadd1 i:n1 do begin
  2771. u:=getv(m,j);
  2772. if null u
  2773. then return;
  2774. v:=modular!-times(getv(u,i),pivot);
  2775. if not zerop v then <<
  2776. putv(rightside,j,
  2777. modular!-plus(getv(rightside,j),
  2778. modular!-times(v,getv(rightside,i))));
  2779. for l:=0:n2 do
  2780. putv(u,l,
  2781. modular!-plus(getv(u,l),
  2782. modular!-times(v,getv(row,l)))) >>
  2783. end;
  2784. finished:
  2785. end;
  2786. if m eq 'failed
  2787. then go to failed;
  2788. % Equations were inconsistent.
  2789. while null (row:=getv(m,n1)) do
  2790. n1:=isub1 n1;
  2791. u:=nil;
  2792. for i:=0:n2 do
  2793. if not zerop getv(row,i)
  2794. then u:='t;
  2795. if null u
  2796. then if not zerop getv(rightside,n1)
  2797. then go to failed
  2798. else n1:=isub1 n1;
  2799. % Deals with a last equation which is all zero.
  2800. if n1 > n2
  2801. then go to failed;
  2802. % Too many equations to satisfy.
  2803. ans:=mkvect n2;
  2804. for i:=0:n2 do
  2805. putv(ans,i,0);
  2806. % now to do the back-substitution.
  2807. for i:=n1 step -1 until 0 do begin
  2808. row:=getv(m,i);
  2809. if null row
  2810. then return;
  2811. u:=getv(rightside,i);
  2812. for j:=iadd1 i:n2 do
  2813. u:=modular!-plus(u,
  2814. modular!-times(getv(row,j),modular!-minus getv(ans,j)));
  2815. putv(ans,i,modular!-times(u,modular!-reciprocal getv(row,i)))
  2816. end;
  2817. if swapflg
  2818. then vecsort(swaps,list ans);
  2819. return ans;
  2820. failed:
  2821. if !*tra
  2822. then printc "Unable to force correct zeroes";
  2823. return 'failed
  2824. end;
  2825. endmodule;
  2826. module nagell;
  2827. % Author: James H. Davenport.
  2828. fluid '(intvar);
  2829. global '(!*tra !*trmin);
  2830. exports lutz!-nagell;
  2831. symbolic procedure lutz!-nagell(divisor);
  2832. begin
  2833. scalar ans,places,mults,save!*tra;
  2834. for each u in divisor do <<
  2835. places:=(car u).places;
  2836. mults :=(cdr u).mults >>;
  2837. ans:=lutz!-nagell!-2(places,mults);
  2838. save!*tra:=!*tra;
  2839. if !*trmin
  2840. then !*tra:=nil;
  2841. ans:=coates!-multiple(places,mults,ans);
  2842. !*tra:=save!*tra;
  2843. return ans
  2844. end;
  2845. symbolic procedure lutz!-nagell!-2(places,mults);
  2846. begin
  2847. scalar wst,x,y,equation,point,a;
  2848. wst:=weierstrass!-form getsqrtsfromplaces places;
  2849. x:=car wst;
  2850. y:=cadr wst;
  2851. equation:=caddr wst;
  2852. equation:=!*q2f !*multsq(equation,equation);
  2853. equation:=makemainvar(equation,intvar);
  2854. if ldeg equation = 3
  2855. then equation:=red equation
  2856. else interr "Equation not of correct form";
  2857. if mvar equation eq intvar
  2858. then if ldeg equation = 1
  2859. then <<
  2860. a:=(lc equation) ./ 1;
  2861. equation:=red equation >>
  2862. else interr "Equation should not have a x**2 term"
  2863. else a:=nil ./ 1;
  2864. equation:= a . (equation ./ 1);
  2865. places:=for each u in places collect
  2866. wst!-convert(u,x,y);
  2867. point:=elliptic!-sum(places,mults,equation);
  2868. a:=lutz!-nagell!-bound(point,equation);
  2869. if !*tra or !*trmin then <<
  2870. princ "Point actually is of order ";
  2871. printc a >>;
  2872. return a
  2873. end;
  2874. symbolic procedure wst!-convert(place,x,y);
  2875. begin
  2876. x:=subzero(xsubstitutesq(x,place),intvar);
  2877. y:=subzero(xsubstitutesq(y,place),intvar);
  2878. return x.y
  2879. end;
  2880. symbolic procedure elliptic!-sum(places,mults,equation);
  2881. begin
  2882. scalar point;
  2883. point:=elliptic!-multiply(car places,car mults,equation);
  2884. places:=cdr places;
  2885. mults:=cdr mults;
  2886. while places do <<
  2887. point:=elliptic!-add(point,
  2888. elliptic!-multiply(car places,car mults,
  2889. equation),
  2890. equation);
  2891. places:=cdr places;
  2892. mults:=cdr mults >>;
  2893. return point
  2894. end;
  2895. symbolic procedure elliptic!-multiply(point,n,equation);
  2896. if n < 0
  2897. then elliptic!-multiply( (car point) . (negsq cdr point),
  2898. -n,
  2899. equation)
  2900. else if n = 0
  2901. then interr "N=0 in elliptic!-multiply"
  2902. else if n = 1
  2903. then point
  2904. else begin
  2905. scalar q,r;
  2906. q:=divide(n,2);
  2907. r:=cdr q;
  2908. q:=car q;
  2909. q:=elliptic!-multiply(elliptic!-add(point,point,equation),q,
  2910. equation);
  2911. if r = 0
  2912. then return q
  2913. else return elliptic!-add(point,q,equation)
  2914. end;
  2915. symbolic procedure elliptic!-add(p1,p2,equation);
  2916. begin
  2917. scalar x1,x2,y1,y2,x3,y3,inf,a,b,lhs,rhs;
  2918. a:=car equation;
  2919. b:=cdr equation;
  2920. inf:=!*kk2q 'infinity;
  2921. x1:=car p1;
  2922. y1:=cdr p1;
  2923. x2:=car p2;
  2924. y2:=cdr p2;
  2925. if x1 = x2
  2926. then if y1 = y2
  2927. then <<
  2928. % this is the doubling case.
  2929. x3:=!*multsq(!*addsq(!*addsq(!*multsq(a,a),
  2930. !*exptsq(x1,4)),
  2931. !*addsq(multsq(-8 ./ 1,!*multsq(x1,b)),
  2932. !*multsq(!*multsq(x1,x1),
  2933. multsq(-2 ./ 1,a)))),
  2934. !*invsq multsq(4 ./ 1,
  2935. !*addsq(b,!*multsq(x1,!*addsq(a,
  2936. !*exptsq(x1,2))))));
  2937. y3:=!*addsq(y1,!*multsq(!*multsq(!*addsq(x3,negsq x1),
  2938. !*addsq(a,multsq(3 ./ 1,
  2939. !*multsq(x1,x1)))),
  2940. !*invsq multsq(2 ./ 1,
  2941. y1))) >>
  2942. else x3:=(y3:=inf)
  2943. else if x1 = inf
  2944. then <<
  2945. x3:=x2;
  2946. y3:=y2 >>
  2947. else if x2 = inf
  2948. then <<
  2949. x3:=x1;
  2950. y3:=y1 >>
  2951. else <<
  2952. x3:=!*multsq(!*addsq(!*multsq(a,!*addsq(x1,x2)),
  2953. !*addsq(multsq(2 ./ 1,b),
  2954. !*addsq(!*multsq(!*multsq(x1,x2),
  2955. !*addsq(x1,x2)),
  2956. multsq(-2 ./ 1,
  2957. !*multsq(y1,y2))))),
  2958. !*invsq !*exptsq(!*addsq(x1,negsq x2),2));
  2959. y3:=!*multsq(!*addsq(!*multsq(!*addsq(y2,negsq y1),x3),
  2960. !*addsq(!*multsq(x2,y1),
  2961. !*multsq(x1,negsq y2))),
  2962. !*invsq !*addsq(x1,negsq x2)) >>;
  2963. if x3 = inf
  2964. then return x3.y3;
  2965. lhs:=!*multsq(y3,y3);
  2966. rhs:=!*addsq(b,!*multsq(x3,!*addsq(a,!*multsq(x3,x3))));
  2967. if numr !*addsq(lhs,negsq rhs) % We can't just compare them
  2968. % since they're algebraic numbers.
  2969. % JHD Jan 14th. 1987.
  2970. then <<
  2971. prin2t "Point defined by X and Y as follows:";
  2972. printsq x3;
  2973. printsq y3;
  2974. prin2t "on the curve defined by A and B as follows:";
  2975. printsq a;
  2976. printsq b;
  2977. prin2t "gives a consistency check between:";
  2978. printsq lhs;
  2979. printsq rhs;
  2980. interr "Consistency check failed in elliptic!-add" >>;
  2981. return x3.y3
  2982. end;
  2983. symbolic procedure infinitep u;
  2984. kernp u and (mvar numr u eq 'infinite);
  2985. symbolic procedure lutz!-nagell!-bound(point,equation);
  2986. begin
  2987. scalar x,y,a,b,lutz!-alist,n,point2,p,l,ans;
  2988. % THE LUTZ!-ALIST is an association list of elements of the form
  2989. % [X-value].([Y-value].[value of N for this point])
  2990. % See thesis, chapter 7, algorithm LUTZ!-NAGELL, step [1].
  2991. x:=car point;
  2992. y:=cdr point;
  2993. if !*tra or !*trmin then <<
  2994. printc "Point to have torsion investigated is";
  2995. printsq x;
  2996. printsq y >>;
  2997. a:=car equation;
  2998. b:=cdr equation;
  2999. if denr y neq 1 then <<
  3000. l:=denr y;
  3001. % we can in fact make l an item whose cube is > denr y.
  3002. y:=!*multsq(y,!*exptf(l,3) ./ 1);
  3003. x:=!*multsq(x,!*exptf(l,2) ./ 1);
  3004. a:=!*multsq(a,!*exptf(l,4) ./ 1);
  3005. b:=!*multsq(b,!*exptf(l,6) ./ 1) >>;
  3006. if denr x neq 1 then <<
  3007. l:=denr x;
  3008. % we can in fact make l an item whose square is > denr x.
  3009. y:=!*multsq(y,!*exptf(l,3) ./ 1);
  3010. x:=!*multsq(x,!*exptf(l,2) ./ 1);
  3011. a:=!*multsq(a,!*exptf(l,4) ./ 1);
  3012. b:=!*multsq(b,!*exptf(l,6) ./ 1) >>;
  3013. % we now have integral co-ordinates for x,y.
  3014. lutz!-alist:=list (x . (y . 0));
  3015. if (x neq car point) and (!*tra or !*trmin) then <<
  3016. printc "Point made integral as ";
  3017. printsq x;
  3018. printsq y;
  3019. printc "on the curve with coefficients";
  3020. printsq a;
  3021. printsq b >>;
  3022. point:=x.y;
  3023. equation:=a.b;
  3024. n:=0;
  3025. loop:
  3026. n:=n+1;
  3027. point2:=elliptic!-multiply(x.y,2,equation);
  3028. x:=car point2;
  3029. y:=cdr point2;
  3030. if infinitep x
  3031. then return 2**n;
  3032. if denr x neq 1
  3033. then go to special!-denr;
  3034. if a:=assoc(x,lutz!-alist)
  3035. then if y = cadr a
  3036. then return (ans:=lutz!-reduce(point,equation,2**n-2**(cddr a)))
  3037. else if null numr !*addsq(y,cadr a)
  3038. then return (ans:=lutz!-reduce(point,equation,2**n+2**(cddr a)))
  3039. else interr "Cannot have 3 points here";
  3040. lutz!-alist:=(x.(y.n)).lutz!-alist;
  3041. if ans
  3042. then return ans;
  3043. go to loop;
  3044. special!-denr:
  3045. p:=denr x;
  3046. if not jhd!-primep p
  3047. then return 'infinite;
  3048. n:=1;
  3049. n:=1;
  3050. loop2:
  3051. point:=elliptic!-multiply(point,p,equation);
  3052. n:=n*p;
  3053. if infinitep car point
  3054. then return n;
  3055. if quotf(p,denr car point)
  3056. then go to loop2;
  3057. return 'infinite
  3058. end;
  3059. symbolic procedure lutz!-reduce(point,equation,power);
  3060. begin
  3061. scalar n;
  3062. if !*tra or !*trmin then <<
  3063. princ "Point is of order dividing ";
  3064. printc power >>;
  3065. n:=1;
  3066. while evenp power do <<
  3067. power:=power/2;
  3068. n:=n*2;
  3069. point:=elliptic!-add(point,point,equation) >>;
  3070. % we know that all the powers of 2 must appear in the answer.
  3071. if power = 1
  3072. then return n;
  3073. if jhd!-primep power
  3074. then return n*power;
  3075. return n*lutz!-reduce2(point,equation,power,3)
  3076. end;
  3077. symbolic procedure lutz!-reduce2(point,equation,power,prime);
  3078. if power = 1
  3079. then if infinitep car point
  3080. then 1
  3081. else nil
  3082. else if infinitep car point
  3083. then power
  3084. else begin
  3085. scalar n,prime2,u,ans;
  3086. n:=0;
  3087. while zerop cdr divide(power,prime) do <<
  3088. n:=n+1;
  3089. power:=power/prime >>;
  3090. prime2:=nextprime prime;
  3091. for i:=0:n do <<
  3092. u:=lutz!-reduce2(point,equation,power,prime2);
  3093. if u
  3094. then <<
  3095. ans:=u*prime**i;
  3096. i:=n >>
  3097. else <<
  3098. power:=power*prime;
  3099. point:=elliptic!-multiply(point,prime,equation) >> >>;
  3100. if ans
  3101. then return ans
  3102. else return nil
  3103. end;
  3104. endmodule;
  3105. module nbasis;
  3106. % Author: James H. Davenport.
  3107. fluid '(nestedsqrts sqrt!-intvar taylorasslist);
  3108. global '(!*tra);
  3109. exports normalbasis;
  3110. imports substitutesq,taylorform,printsq,newplace,sqrtsinsq,union,
  3111. sqrtsign,interr,vecsort,mapvec,firstlinearrelation,mksp,multsq,
  3112. !*multsq,addsq,removecmsq,antisubs,involvesq;
  3113. symbolic procedure normalbasis(zbasis,x,infdegree);
  3114. begin
  3115. scalar n,nestedsqrts,sqrts,u,v,w,li,m,lam,i,inf,basis,save;
  3116. save:=taylorasslist;
  3117. inf:=list list(x,'quotient,1,x);
  3118. n:=upbv zbasis;
  3119. basis:=mkvect n;
  3120. lam:=mkvect n;
  3121. m:=mkvect n;
  3122. goto a;
  3123. square:
  3124. sqrts:=nil;
  3125. inf:=append(inf,list list(x,'expt,x,2));
  3126. % we were in danger of getting sqrt(x) where we didnt want it.
  3127. a:
  3128. newplace(inf);
  3129. for i:=0:n do <<
  3130. v:=substitutesq(getv(zbasis,i),inf);
  3131. putv(basis,i,v);
  3132. sqrts:=union(sqrts,sqrtsinsq(v,x)) >>;
  3133. if !*tra then <<
  3134. princ "Normal integral basis reduction with the";
  3135. printc " following sqrts lying over infinity:";
  3136. superprint sqrts >>;
  3137. if member(list('sqrt,x),sqrts)
  3138. then goto square;
  3139. sqrts:=sqrtsign(sqrts,x);
  3140. if iadd1 n neq length sqrts
  3141. then interr "Length mismatch in normalbasis";
  3142. for i:=0:n do <<
  3143. v:=cl8roweval(getv(basis,i),sqrts);
  3144. putv(m,i,cdr v);
  3145. putv(lam,i,car v) >>;
  3146. reductionloop:
  3147. vecsort(lam,list(basis,m));
  3148. if !*tra then <<
  3149. printc "Matrix before a reduction step at infinity is:";
  3150. mapvec(m,function printc) >>;
  3151. v:=firstlinearrelation(m,iadd1 n);
  3152. if null v
  3153. then goto ret;
  3154. i:=n;
  3155. while null numr getv(v,i) do
  3156. i:=isub1 i;
  3157. li:=getv(lam,i);
  3158. w:=nil ./ 1;
  3159. for j:=0:i do
  3160. w:=addsq(w,!*multsq(getv(basis,j),
  3161. multsq(getv(v,j),1 ./ !*fmksp(x,-li+getv(lam,j)) )));
  3162. % note the change of sign. my x is coates 1/x at this point!.
  3163. if !*tra then <<
  3164. princ "Element ";
  3165. princ i;
  3166. printc " replaced by the function printed below:" >>;
  3167. w:=removecmsq w;
  3168. putv(basis,i,w);
  3169. w:=cl8roweval(w,sqrts);
  3170. if car w <= li
  3171. then interr "Normal basis reduction did not work";
  3172. putv(lam,i,car w);
  3173. putv(m,i,cdr w);
  3174. goto reductionloop;
  3175. ret:
  3176. newplace list (x.x);
  3177. u:= 1 ./ !*p2f mksp(x,1);
  3178. inf:=antisubs(inf,x);
  3179. u:=substitutesq(u,inf);
  3180. m:=nil;
  3181. for i:=0:n do begin
  3182. v:=getv(lam,i)-infdegree;
  3183. if v < 0
  3184. then goto next;
  3185. w:=substitutesq(getv(basis,i),inf);
  3186. for j:=0:v do <<
  3187. if not involvesq(w,sqrt!-intvar)
  3188. then m:=w.m;
  3189. w:=!*multsq(w,u) >>;
  3190. next:
  3191. end;
  3192. tayshorten save;
  3193. return m
  3194. end;
  3195. symbolic procedure !*fmksp(x,i);
  3196. % sf for x**i.
  3197. if i iequal 0
  3198. then 1
  3199. else !*p2f mksp(x,i);
  3200. symbolic procedure cl8roweval(basiselement,sqrts);
  3201. begin
  3202. scalar lam,row,i,v,minimum,n;
  3203. n:=isub1 length sqrts;
  3204. lam:=mkvect n;
  3205. row:=mkvect n;
  3206. i:=0;
  3207. minimum:=1000000;
  3208. while sqrts do <<
  3209. v:=taylorform substitutesq(basiselement,car sqrts);
  3210. v:=assoc(taylorfirst v,taylorlist v);
  3211. putv(row,i,cdr v);
  3212. v:=car v;
  3213. putv(lam,i,v);
  3214. if v < minimum
  3215. then minimum:=v;
  3216. i:=iadd1 i;
  3217. sqrts:=cdr sqrts >>;
  3218. if !*tra then <<
  3219. princ "Evaluating ";
  3220. printsq basiselement;
  3221. printc lam;
  3222. printc row >>;
  3223. v:=1000000;
  3224. for i:=0:n do <<
  3225. v:=getv(lam,i);
  3226. if v > minimum
  3227. then putv(row,i,nil ./ 1) >>;
  3228. return minimum.row
  3229. end;
  3230. endmodule;
  3231. module places;
  3232. % Author: James H. Davenport.
  3233. fluid '(basic!-listofallsqrts
  3234. basic!-listofnewsqrts
  3235. intvar
  3236. listofallsqrts
  3237. listofnewsqrts
  3238. sqrt!-intvar
  3239. sqrt!-places!-alist
  3240. sqrts!-in!-integrand);
  3241. exports getsqrtsfromplaces,sqrtsinplaces,get!-correct!-sqrts,basicplace,
  3242. extenplace,equalplace,printplace;
  3243. % Function to manipulate places
  3244. % a place is stored as a list of substitutions
  3245. % substitutions (x.f(x)) define the algrbraic number
  3246. % of which this place is an extension,
  3247. % while places (f(x).g(x)) define the extension.
  3248. % currently g(x( is list ('minus,f(x))
  3249. % or similar,e.g. (sqrt(sqrt x)).(sqrt(-sqrt x)).
  3250. % Given a list of places, produces a list of all
  3251. % the SQRTs in it that depend on INTVAR.
  3252. symbolic procedure getsqrtsfromplaces places;
  3253. % The following loop finds all the SQRTs for a basis,
  3254. % taking account of BASICPLACEs.
  3255. begin
  3256. scalar basis,v,b,c,vv;
  3257. for each u in places do <<
  3258. v:=antisubs(basicplace u,intvar);
  3259. vv:=sqrtsinsq (substitutesq(!*kk2q intvar,v),intvar);
  3260. % We must go via SUBSTITUTESQ to get parallel
  3261. % substitutions performed correctly.
  3262. if vv
  3263. then vv:=simp argof car vv;
  3264. for each w in extenplace u do <<
  3265. b:=substitutesq(simp lsubs w,v);
  3266. b:=delete(sqrt!-intvar,sqrtsinsq(b,intvar));
  3267. for each u in b do
  3268. for each v in delete(u,b) do
  3269. if dependsp(v,u)
  3270. then b:=delete(u,b);
  3271. % remove all the "inner" items, since they will
  3272. % be accounted for anyway.
  3273. if length b iequal 1
  3274. then b:=car b
  3275. else b:=mvar numr simpsqrtsq mapply(function !*multsq,
  3276. for each u in b collect simp argof u);
  3277. if vv and not (b member sqrts!-in!-integrand)
  3278. then <<
  3279. c:=numr multsq(simp argof b,vv);
  3280. c:=car sqrtsinsf(simpsqrt2 c,nil,intvar);
  3281. if c member sqrts!-in!-integrand
  3282. then b:=c >>;
  3283. if not (b member basis)
  3284. then basis:=b.basis >> >>;
  3285. % The following loop deals with the annoying case of, say,
  3286. % (X DIFFERENCE X 1) (X EXPT X 2) which should give rise to
  3287. % SQRT(X-1).
  3288. for each u in places do begin
  3289. v:=cdr u;
  3290. if null v or (car rfirstsubs v neq 'expt)
  3291. then return;
  3292. u:=simp!* subst(list('minus,intvar),intvar,rfirstsubs u);
  3293. while v and (car rfirstsubs v eq 'expt) do <<
  3294. u:=simpsqrtsq u;
  3295. v:=cdr v;
  3296. basis:=union(basis,delete(sqrt!-intvar,sqrtsinsq(u,intvar))) >>
  3297. end;
  3298. return remove!-extra!-sqrts basis
  3299. end;
  3300. symbolic procedure sqrtsinplaces u;
  3301. % Note the difference between this procedure and
  3302. % the previous one: this one does not take account
  3303. % of the BASICPLACE component (& is pretty useless).
  3304. if null u
  3305. then nil
  3306. else sqrtsintree(for each v in car u collect lsubs v,
  3307. intvar,
  3308. sqrtsinplaces cdr u);
  3309. %symbolic procedure placesindiv places;
  3310. % Given a list of places (i.e. a divisor),
  3311. % produces a list of all the SQRTs on which the places
  3312. % explicitly depend.
  3313. %begin scalar v;
  3314. % for each u in places do
  3315. % for each uu in u do
  3316. % if not (lsubs uu member v)
  3317. % then v:=(lsubs uu) . v;
  3318. % return v
  3319. % end;
  3320. symbolic procedure get!-correct!-sqrts u;
  3321. % u is a basicplace.
  3322. begin
  3323. scalar v;
  3324. v:=assoc(u,sqrt!-places!-alist);
  3325. if v
  3326. then <<
  3327. v:=cdr v;
  3328. listofallsqrts:=cdr v;
  3329. listofnewsqrts:=car v
  3330. >>
  3331. else <<
  3332. listofnewsqrts:=basic!-listofnewsqrts;
  3333. listofallsqrts:=basic!-listofallsqrts
  3334. >>;
  3335. return nil
  3336. end;
  3337. %symbolic procedure change!-place(old,new);
  3338. %% old and new are basicplaces;
  3339. %begin
  3340. % scalar v;
  3341. % v:=assoc(new,sqrt!-places!-alist);
  3342. % if v
  3343. % then sqrtsave(cddr v,cadr v,old)
  3344. % else <<
  3345. % listofnewsqrts:=basic!-listofnewsqrts;
  3346. % listofallsqrts:=basic!-listofallsqrts
  3347. % >>;
  3348. % return nil
  3349. % end;
  3350. symbolic procedure basicplace(u);
  3351. % Returns the basic part of a place.
  3352. if null u
  3353. then nil
  3354. else if atom caar u
  3355. then (car u).basicplace cdr u
  3356. else nil;
  3357. symbolic procedure extenplace(u);
  3358. % Returns the extension part of a place.
  3359. if u and atom caar u
  3360. then extenplace cdr u
  3361. else u;
  3362. symbolic procedure equalplace(a,b);
  3363. % Sees if two extension places represent the same place or not.
  3364. if null a
  3365. then if null b
  3366. then t
  3367. else nil
  3368. else if null b
  3369. then nil
  3370. else if member(car a,b)
  3371. then equalplace(cdr a,delete(car a,b))
  3372. else nil;
  3373. symbolic procedure remove!-extra!-sqrts basis;
  3374. begin
  3375. scalar basis2,save;
  3376. save:=basis2:=for each u in basis collect !*q2f simp argof u;
  3377. for each u in basis2 do
  3378. for each v in delete(u,basis2) do
  3379. if quotf(v,u)
  3380. then basis2:=delete(v,basis2);
  3381. if basis2 eq save
  3382. then return basis
  3383. else return for each u in basis2 collect list('sqrt,prepf u)
  3384. end;
  3385. symbolic procedure printplace u;
  3386. begin
  3387. scalar a,n,v;
  3388. a:=rfirstsubs u;
  3389. princ (v:=lfirstsubs u);
  3390. princ "=";
  3391. if atom a
  3392. then princ "0"
  3393. else if (car a eq 'quotient) and (cadr a=1)
  3394. then princ "infinity"
  3395. else <<
  3396. n:=negsq addsq(!*kk2q v,negsq simp!* a);
  3397. % NEGSQ added JHD 22.3.87 - the previous value was wrong.
  3398. % If the substitution is (X-v) then this takes -v to 0,
  3399. % so the place was at -v.
  3400. if (numberp numr n) and (numberp denr n)
  3401. then <<
  3402. princ numr n;
  3403. if not onep denr n
  3404. then <<
  3405. princ " / ";
  3406. princ denr n >> >>
  3407. else <<
  3408. if degreein(numr n,intvar) > 1
  3409. then printc "Any root of:";
  3410. printsq n;
  3411. if cdr u
  3412. then princ "at the place " >> >>;
  3413. u:=cdr u;
  3414. if null u
  3415. then goto nl!-return;
  3416. n:=1;
  3417. while u and (car rfirstsubs u eq 'expt) do <<
  3418. n:=n * caddr rfirstsubs u;
  3419. u:=cdr u >>;
  3420. if n neq 1 then <<
  3421. terpri!* nil;
  3422. prin2 " ";
  3423. princ v;
  3424. princ "=>";
  3425. princ v;
  3426. princ "**";
  3427. princ n >>;
  3428. while u do <<
  3429. if car rfirstsubs u eq 'minus
  3430. then princ "-"
  3431. else princ "+";
  3432. u:=cdr u >>;
  3433. nl!-return:
  3434. terpri();
  3435. return
  3436. end;
  3437. symbolic procedure degreein(sf,var);
  3438. if atom sf
  3439. then 0
  3440. else if mvar sf eq var
  3441. then ldeg sf
  3442. else max(degreein(lc sf,var),degreein(red sf,var));
  3443. endmodule;
  3444. module precoats;
  3445. % Author: James H. Davenport.
  3446. fluid '(basic!-listofallsqrts
  3447. basic!-listofnewsqrts
  3448. sqrt!-intvar
  3449. taylorvariable
  3450. thisplace);
  3451. global '(!*tra);
  3452. exports precoates;
  3453. imports mksp,algint!-subf,subzero2,substitutesq,removeduplicates,
  3454. printsq,basicplace,extenplace,interr,get!-correct!-sqrts,
  3455. printplace,simptimes,subzero,negsq,addsq,involvesq,taylorform,
  3456. taylorevaluate,mk!*sq,!*exptsq,!*multsq,!*invsq,sqrt2top,
  3457. jfactor,sqrtsave,antisubs;
  3458. symbolic procedure infsubs(w);
  3459. if caar w = thisplace
  3460. then (cdar w).(cdr w)
  3461. else (thisplace.(car w)).(cdr w);
  3462. % thisplace is (z quotient 1 z) so we are moving to infinity.
  3463. symbolic procedure precoates(residues,x,movedtoinfinity);
  3464. begin
  3465. scalar answer,placeval,reslist,placelist,placelist2,thisplace;
  3466. reslist:=residues;
  3467. placelist:=nil;
  3468. while reslist do <<
  3469. % car reslist = <substitution list>.<value>;
  3470. placeval:=algint!-subf((mksp(x,1) .* 1) .+ nil,caar reslist);
  3471. if 0 neq cdar reslist
  3472. then if null numr subzero2(denr placeval,x)
  3473. then <<
  3474. if null answer
  3475. then answer:='infinity
  3476. else if answer eq 'finite
  3477. then answer:='mixed;
  3478. if !*tra
  3479. then printc "We have an residue at infinity" >>
  3480. else <<
  3481. if null answer
  3482. then answer:='finite
  3483. else if answer eq 'infinity
  3484. then answer:='mixed;
  3485. placelist:=placeval.placelist;
  3486. if !*tra
  3487. then printc "This is a finite residue" >>;
  3488. reslist:=cdr reslist >>;
  3489. if answer eq 'mixed
  3490. then return answer;
  3491. if answer eq 'infinity
  3492. then <<
  3493. thisplace:=list(x,'quotient,1,x);
  3494. % maps x to 1/x.
  3495. answer:=precoates(for each u in residues collect infsubs u,x,t);
  3496. % derivative of 1/x is -1/x**2.
  3497. if atom answer
  3498. then return answer
  3499. else return substitutesq(answer,list(thisplace)) >>;
  3500. placelist2:=removeduplicates placelist;
  3501. answer := 1 ./ 1;
  3502. % the null divisor.
  3503. if !*tra then <<
  3504. printc "The divisor has elements at:";
  3505. mapcar(placelist2,function printsq) >>;
  3506. while placelist2 do begin
  3507. scalar placelist3,extrasubs,u,bplace;
  3508. % loop over all distinct places.
  3509. reslist:=residues;
  3510. placelist3:=placelist;
  3511. placeval:=nil;
  3512. while reslist do <<
  3513. if car placelist2 = car placelist3
  3514. then <<
  3515. placeval:=(cdar reslist).placeval;
  3516. thisplace:= caar reslist;
  3517. % the substitutions defining car placelist.
  3518. u:=caar reslist;
  3519. bplace:=basicplace u;
  3520. u:=extenplace u;
  3521. extrasubs:=u.extrasubs >>;
  3522. reslist:=cdr reslist;
  3523. placelist3:=cdr placelist3 >>;
  3524. % placeval is a list of all the residues at this place.
  3525. if !*tra then <<
  3526. princ "List of multiplicities at this place:";
  3527. printc placeval;
  3528. princ "with substitutions:";
  3529. superprint extrasubs >>;
  3530. if 0 neq mapply(function plus2,placeval)
  3531. then interr "Divisor not effective";
  3532. get!-correct!-sqrts bplace;
  3533. u:=pbuild(x,extrasubs,placeval);
  3534. sqrtsave(basic!-listofallsqrts,basic!-listofnewsqrts,bplace);
  3535. if atom u
  3536. then <<
  3537. placelist2:=nil;
  3538. % set to terminate loop.
  3539. answer:=u >>
  3540. else <<
  3541. answer:=substitutesq(!*multsq(answer,u),antisubs(thisplace,x));
  3542. placelist2:=cdr placelist2 >>
  3543. end;
  3544. % loaded in pbuild to check for poles at the correct places.
  3545. return answer
  3546. end;
  3547. symbolic procedure dlist(u);
  3548. % Given a list of lists,converts to a list.
  3549. if null u
  3550. then nil
  3551. else if null car u
  3552. then dlist cdr u
  3553. else append(car u,dlist cdr u);
  3554. symbolic procedure debranch(extrasubs,reslist);
  3555. begin
  3556. scalar substlist;
  3557. % remove spurious substitutions.
  3558. for each u in dlist extrasubs do
  3559. if not ((car u) member substlist)
  3560. then substlist:=(car u).substlist;
  3561. % substlist is a list of all the possible substitutions).
  3562. while substlist do
  3563. begin scalar tsqrt,usqrt;
  3564. scalar with1,with2,without1,without2,wres;
  3565. scalar a1,a2,b1,b2;
  3566. % decide if tsqrt is redundant.
  3567. tsqrt:=car substlist;
  3568. substlist:=cdr substlist;
  3569. wres:=reslist;
  3570. for each place in extrasubs do <<
  3571. usqrt:=assoc(tsqrt,place);
  3572. % usqrt is s.s' or s.(minus s').
  3573. if null usqrt
  3574. then interr "Places not all there";
  3575. if cadr usqrt eq 'sqrt
  3576. then<<
  3577. with2:=(car wres).with2;
  3578. with1:=delete(usqrt,place).with1>>
  3579. else<<
  3580. if not (cadr usqrt eq 'minus)
  3581. then interr "Ramification format error";
  3582. without2:=(car wres).without2;
  3583. without1:=delete(usqrt,place).without1 >>;
  3584. wres:=cdr wres>>;
  3585. % first see if one item appears passim.
  3586. if null with1
  3587. then go to itswithout;
  3588. if null without1
  3589. then go to itswith;
  3590. % Now must see if WITH2 matches WITHOUT2 in order WITH1/WITHOUT1.
  3591. a1:=with1;
  3592. a2:=with2;
  3593. outerloop:
  3594. b1:=without1;
  3595. b2:=without2;
  3596. innerloop:
  3597. if (car a1) = (car b1)
  3598. then << if (car a2) neq (car b2)
  3599. then return;
  3600. else go to outeriterate >>;
  3601. b1:=cdr b1;
  3602. b2:=cdr b2;
  3603. if null b1
  3604. then return
  3605. else go to innerloop;
  3606. % null b1 => lists do not match at all.
  3607. outeriterate:
  3608. a1:=cdr a1;
  3609. a2:=cdr a2;
  3610. if a1
  3611. then go to outerloop;
  3612. if !*tra then <<
  3613. princ "Residues reduce to:";
  3614. printc without2;
  3615. printc "at ";
  3616. mapc(without1,function printplace) >>;
  3617. extrasubs:=without1;
  3618. reslist:=without2;
  3619. return;
  3620. itswithout:
  3621. % everything is in the "without" list.
  3622. with1:=without1;
  3623. with2:=without2;
  3624. itswith:
  3625. % remove usqrt from the with lists.
  3626. extrasubs:=for each u in with1 collect delete(assoc(tsqrt,u),u);
  3627. if !*tra then <<
  3628. printc "The following appears throughout the list ";
  3629. printc tsqrt >>;
  3630. reslist:=with2
  3631. end;
  3632. return extrasubs.reslist
  3633. end;
  3634. symbolic procedure pbuild(x,extrasubs,placeval);
  3635. begin
  3636. scalar multivals,u,v,answer;
  3637. u:=debranch(extrasubs,placeval);
  3638. extrasubs:=car u;
  3639. placeval:=cdr u;
  3640. % remove spurious entries.
  3641. if (length car extrasubs) > 1
  3642. then return 'difficult;
  3643. % hard cases not allowed for.
  3644. multivals:=mapcar(dlist extrasubs,function car);
  3645. u:=simptimes removeduplicates multivals;
  3646. answer:= 1 ./ 1;
  3647. while extrasubs do <<
  3648. v:=substitutesq(u,car extrasubs);
  3649. v:=addsq(u,negsq subzero(v,x));
  3650. v:=mkord1(v,x);
  3651. if !*tra then <<
  3652. princ "Required component is ";
  3653. printsq v >>;
  3654. answer:=!*multsq(answer,!*exptsq(v,car placeval));
  3655. % place introduced with correct multiplicity.
  3656. extrasubs:=cdr extrasubs;
  3657. placeval:=cdr placeval >>;
  3658. if length jfactor(denr sqrt2top !*invsq answer,x) > 1
  3659. then return 'many!-poles
  3660. else return answer
  3661. end;
  3662. symbolic procedure findord(v,x);
  3663. begin
  3664. scalar nord,vd;
  3665. %given v(x) with v(0)=0, makes v'(0) nonzero.
  3666. nord:=0;
  3667. taylorvariable:=x;
  3668. while involvesq(v,sqrt!-intvar) do
  3669. v:=substitutesq(v,list(x.list('expt,x,2)));
  3670. vd:=taylorform v;
  3671. loop:
  3672. nord:=nord+1;
  3673. if null numr taylorevaluate(vd,nord)
  3674. then go to loop;
  3675. return nord
  3676. end;
  3677. symbolic procedure mkord1(v,x);
  3678. begin
  3679. scalar nord;
  3680. nord:=findord(v,x);
  3681. if nord iequal 1
  3682. then return v;
  3683. if !*tra then <<
  3684. princ "Order reduction: ";
  3685. printsq v;
  3686. princ "from order ";
  3687. princ nord;
  3688. printc " to order 1" >>;
  3689. % Note that here we do not need to simplify, since SIMPLOG will
  3690. % remove all these SQRTs or EXPTs later.
  3691. return !*p2q mksp(list('nthroot,mk!*sq v,nord),1)
  3692. end;
  3693. endmodule;
  3694. module primes;
  3695. % Author: James H. Davenport.
  3696. exports nextprime,jhd!-primep;
  3697. symbolic procedure nextprime p;
  3698. % Returns the next prime number bigger than p.
  3699. if p=0 then 1
  3700. else if p=1 then 2
  3701. else begin
  3702. if evenp p then p:=p+1 else p:=p+2;
  3703. test: if jhd!-primep p then return p;
  3704. p:=p+2;
  3705. go to test end;
  3706. symbolic procedure jhd!-primep p;
  3707. if p < 4 then t
  3708. else if evenp p then nil
  3709. else begin
  3710. scalar n;
  3711. n:=3; %trial factor.
  3712. top: if n*n>p then return t
  3713. else if remainder(p,n)=0 then return nil;
  3714. n:=n+2;
  3715. go to top end;
  3716. endmodule;
  3717. module removecm; % Routines to remove constant factors from expresions.
  3718. % Author: James H. Davenport.
  3719. fluid '(intvar);
  3720. % New improved REMOVECOMMOMMULTIPLES routines.
  3721. % These routines replace a straightforward pair with GCDF instead of
  3722. % CMGCDF and its associates. The saving is large in complicated
  3723. % expressions (in the "general point of order 7" calculations, they
  3724. % exceeded 90% in some cases, being 1.5 secs as opposed to > 15 secs.).
  3725. % They are about 1K larger, but this seems a small price to pay.
  3726. exports removecmsq,removeconstantsf;
  3727. imports ordop,addf,gcdn,gcdf,gcdk,involvesf,dependsp,makemainvar,quotf;
  3728. symbolic procedure removecmsq sq;
  3729. (removecmsf numr sq) ./ (removecmsf denr sq);
  3730. symbolic procedure removecmsf sf;
  3731. if atom sf or not ordop(mvar sf,intvar) or not involvesf(sf,intvar)
  3732. then if sf
  3733. then 1
  3734. else nil
  3735. else if null red sf
  3736. then if dependsp(mvar sf,intvar)
  3737. then (lpow sf .* removecmsf lc sf) .+ nil
  3738. else removecmsf lc sf
  3739. else begin
  3740. scalar u,v;
  3741. % The general principle here is to find a (non-INTVAR-depending)
  3742. % coefficient of a purely INTVAR-depending monomial, and then
  3743. % perform a g.c.d. to discover that factor of this which is a CM.
  3744. u:=sf;
  3745. while (v:=involvesf(u,intvar)) do u:=lc makemainvar(u,v);
  3746. if u iequal 1
  3747. then return sf;
  3748. return quotf(sf,cmgcdf(sf,u))
  3749. end;
  3750. symbolic procedure cmgcdf(sf,u);
  3751. if numberp u
  3752. then if atom sf
  3753. then if null sf
  3754. then u
  3755. else gcdn(sf,u)
  3756. else if u = 1
  3757. then 1
  3758. else cmgcdf(red sf,cmgcdf(lc sf,u))
  3759. else if atom sf
  3760. then gcdf(sf,u)
  3761. else if mvar u eq mvar sf
  3762. then if ordop(intvar,mvar u)
  3763. then gcdf(sf,u)
  3764. else cmgcdf2(sf,u)
  3765. else if ordop(mvar sf,mvar u)
  3766. then cmgcdf(red sf,cmgcdf(lc sf,u))
  3767. else cmgcdf(u,sf);
  3768. symbolic procedure remove!-maxdeg(sf,var);
  3769. if atom sf
  3770. then 0
  3771. else if mvar sf eq var
  3772. then ldeg sf
  3773. else if ordop(var,mvar sf)
  3774. then 0
  3775. else max(remove!-maxdeg(lc sf,var),remove!-maxdeg(red sf,var));
  3776. symbolic procedure cmgcdf2(sf,u);
  3777. % SF and U have the same MVAR, but INTVAR comes somewhere
  3778. % down in SF. Therefore we can do better than a straight
  3779. % GCDK, or even a straight MAKEMAINVAR.
  3780. begin
  3781. scalar n;
  3782. n:=remove!-maxdeg(sf,intvar);
  3783. if n = 0
  3784. then return gcdf(sf,u);
  3785. % Doesn't actually depend on INTVAR.
  3786. loop:
  3787. if u = 1
  3788. then return 1;
  3789. u:=gcdf(u,collectterms(sf,intvar,n));
  3790. n:=isub1 n;
  3791. if n < 0
  3792. then return u
  3793. else go loop
  3794. end;
  3795. symbolic procedure collectterms(sf,var,n);
  3796. if atom sf
  3797. then if n = 0
  3798. then sf
  3799. else nil
  3800. else if mvar sf eq var
  3801. then if ldeg sf = n
  3802. then lc sf
  3803. else if ldeg sf > n
  3804. then collectterms(red sf,var,n)
  3805. else nil
  3806. else if ordop(var,mvar sf)
  3807. then if n = 0
  3808. then sf
  3809. else nil
  3810. else begin
  3811. scalar v,w;
  3812. v:=collectterms(lc sf,var,n);
  3813. w:=collectterms(red sf,var,n);
  3814. if null v
  3815. then return w
  3816. else return addf(w,(lpow sf .* v) .+ nil)
  3817. end;
  3818. symbolic procedure removeconstantsf sf;
  3819. % Very simple version for now.
  3820. begin
  3821. scalar u;
  3822. if null sf
  3823. then return nil
  3824. else if atom sf
  3825. then return 1;
  3826. while (null red sf) and (remove!-constantp mvar sf) do
  3827. sf:=lc sf;
  3828. u:=remove!-const!-content sf;
  3829. if u = 1
  3830. then return sf
  3831. else return quotf!*(sf,u)
  3832. end;
  3833. symbolic procedure remove!-constantp pf;
  3834. if numberp pf
  3835. then t
  3836. else if atom pf
  3837. then nil
  3838. else if car pf eq 'sqrt
  3839. then remove!-constantp argof pf
  3840. else if (car pf eq 'expt) or (car pf eq 'quotient)
  3841. then (remove!-constantp argof pf)
  3842. and (remove!-constantp caddr pf)
  3843. else nil;
  3844. symbolic procedure remove!-const!-content sf;
  3845. if numberp sf
  3846. then sf
  3847. else if null red sf
  3848. then if remove!-constantp mvar sf
  3849. then (lpow sf .* remove!-const!-content lc sf) .+ nil
  3850. else remove!-const!-content lc sf
  3851. else begin
  3852. scalar u;
  3853. u:=remove!-const!-content lc sf;
  3854. if u = 1
  3855. then return u;
  3856. return gcdf(u,remove!-const!-content red sf)
  3857. end;
  3858. endmodule;
  3859. module sqfrnorm;
  3860. % Author: James H. Davenport.
  3861. fluid '(!*pvar listofallsqrts);
  3862. global '(modevalcount);
  3863. modevalcount:=1;
  3864. exports sqfr!-norm2,res!-sqrt;
  3865. %symbolic procedure resultant(u,v);
  3866. %begin
  3867. % scalar maxdeg,zeroes,ldegu,ldegv,m;
  3868. % % we can have gone makemainvar on u and v;
  3869. % ldegu:=ldeg u;
  3870. % ldegv:=ldeg v;
  3871. % maxdeg:=isub1 max2(ldegu,ldegv);
  3872. % zeroes:=nlist(nil,maxdeg);
  3873. % u:=remake(u,mvar u,ldegu);
  3874. % v:=remake(v,mvar v,ldegv);
  3875. % m:=nil;
  3876. % ldegu:=isub1 ldegu;
  3877. % ldegv:=isub1 ldegv;
  3878. % for i:=0 step 1 until ldegv do
  3879. % m:=append(ncdr(zeroes,maxdeg-ldegv+i),
  3880. % append(u,ncdr(zeroes,maxdeg-i))).m;
  3881. % for i:=0 step 1 until ldegu do
  3882. % m:=append(ncdr(zeroes,maxdeg-ldegu+i),
  3883. % append(v,ncdr(zeroes,maxdeg-i))).m;
  3884. % return detqf m
  3885. % end;
  3886. %symbolic procedure remake(u,v,w);
  3887. %% remakes u into a list of sf's representing its coefficients;
  3888. %if w iequal 0 then list u
  3889. % else if (pairp u) and (mvar u eq v) and (ldeg u iequal w)
  3890. % then (lc u).remake(red u,v,isub1 w)
  3891. % else (nil ).remake( u,v,isub1 w);
  3892. %fluid '(n); %needed for the mapcar;
  3893. %symbolic procedure detqf u;
  3894. % %u is a square matrix standard form.
  3895. %% %value is the determinant of u.
  3896. %% %algorithm is expansion by minors of first row/column;
  3897. % begin integer n;
  3898. % scalar x,y,z;
  3899. % if length u neq length car u then rederr "Non square matrix"
  3900. % else if null cdr u then return caar u;
  3901. % if length u < 3
  3902. % then go to noopt;
  3903. % % try to remove a row with only one non-zero in it;
  3904. % z:=1;
  3905. % x:=u;
  3906. % loop:
  3907. % n:=posnnonnull car x;
  3908. % if n eq t
  3909. % then return nil;
  3910. % % special test for all null;
  3911. % if n then <<
  3912. % y:=nth(car x,n);
  3913. % % next line is equivalent to:
  3914. %% onne of n,z is even;
  3915. % if evenp (n+z-1)
  3916. % then y:=negf y;
  3917. % u:=remove(u,z);
  3918. % return !*multf(y,detqf remove2 u) >>;
  3919. % x:=cdr x;
  3920. % z:=z+1;
  3921. % if x
  3922. % then go to loop;
  3923. % noopt:
  3924. % x := u;
  3925. % n := 1; %number of current row/column;
  3926. % z := nil;
  3927. % if nonnull car u < nonnullcar u
  3928. % then go to row!-expand;
  3929. % u:=mapcar(u,function cdr);
  3930. % a: if null x then return z;
  3931. % y := caar x;
  3932. % if null y then go to b
  3933. % else if evenp n then y := negf y;
  3934. % z := addf(!*multf(y,detqf remove(u,n)),z);
  3935. % b: x := cdr x;
  3936. % n := iadd1 n;
  3937. % go to a;
  3938. % row!-expand:
  3939. % u:=cdr u;
  3940. % x:=car x;
  3941. % aa:
  3942. % if null x then return z;
  3943. % y:=car x;
  3944. % if null y
  3945. % then go to bb
  3946. % else if evenp n then y:=negf y;
  3947. % z:=addf(!*multf(y,detqf remove2 u),z);
  3948. % bb:
  3949. % x:=cdr x;
  3950. % n:=iadd1 n;
  3951. % go to aa
  3952. % end;
  3953. %
  3954. %
  3955. %symbolic procedure remove2 u;
  3956. %mapcar(u,function (lambda x;
  3957. % remove(x,n)));
  3958. %
  3959. %unfluid '(n);
  3960. %
  3961. %symbolic procedure nonnull u;
  3962. %if null u
  3963. % then 0
  3964. % else if null car u
  3965. % then nonnull cdr u
  3966. % else iadd1 (nonnull cdr u);
  3967. %
  3968. %
  3969. %symbolic procedure nonnullcar u;
  3970. %if null u
  3971. % then 0
  3972. % else if null caar u
  3973. % then nonnullcar cdr u
  3974. % else iadd1 (nonnullcar cdr u);
  3975. %
  3976. %
  3977. %
  3978. %symbolic procedure posnnonnull u;
  3979. %% returns t if u has no non-null elements
  3980. %% nil if more than one
  3981. %% else position of the first;
  3982. %begin
  3983. % scalar n,x;
  3984. % n:=1;
  3985. %loop:
  3986. % if null u
  3987. % then return
  3988. % if x
  3989. % then x
  3990. % else t;
  3991. % if car u
  3992. % then if x
  3993. % then return nil
  3994. % else x:=n;
  3995. % n:=iadd1 n;
  3996. % u:=cdr u;
  3997. % go to loop
  3998. % end;
  3999. symbolic procedure res!-sqrt(u,a);
  4000. % Evaluates resultant of u ( as a poly in its mvar) and x**-a.
  4001. begin
  4002. scalar x,n,v,k,l;
  4003. x:=mvar u;
  4004. n:=ldeg u;
  4005. n:=quotient(n,2);
  4006. v:=mkvect n;
  4007. putv(v,0,1);
  4008. for i:=1:n do
  4009. putv(v,i,!*multf(a,getv(v,i-1)));
  4010. % now substitute for x**2 in u leaving k*x+l.
  4011. k:=l:=nil;
  4012. while u do
  4013. if mvar u neq x
  4014. then <<
  4015. l:=addf(l,u);
  4016. u:=nil >>
  4017. else <<
  4018. if evenp ldeg u
  4019. then l:=addf(l,!*multf(lc u,getv(v,(ldeg u)/2)))
  4020. else k:=addf(k,!*multf(lc u,getv(v,(ldeg u -1)/2)));
  4021. u:=red u >>;
  4022. % now have k*x+l,x**2-a, giving l*l-a*k*k.
  4023. return addf(!*multf(l,l),!*multf(negf a,multf(k,k)))
  4024. end;
  4025. symbolic procedure sqfr!-norm2 (f,mvarf,a);
  4026. begin
  4027. scalar u,w,aa,ff,resfn;
  4028. resfn:='resultant;
  4029. if eqcar(a,'sqrt)
  4030. then <<
  4031. resfn:='res!-sqrt;
  4032. aa:=!*q2f simp argof a >>
  4033. else rederr "Norms over transcendental extensions";
  4034. f:=pvarsub(f,a,'! gerbil);
  4035. w:=nil;
  4036. if involvesf(f,'! gerbil) then goto l1;
  4037. increase:
  4038. w:=addf(w,!*p2f mksp(a,1));
  4039. f:=!*q2f algint!-subf(f,list(mvarf . list('plus,mvarf,
  4040. list('minus,'! gerbil))));
  4041. l1:
  4042. u:=apply(resfn,list(makemainvar(f,'! gerbil),aa));
  4043. ff:=nsqfrp(u,mvarf);
  4044. if ff
  4045. then go to increase;
  4046. f:=!*q2f algint!-subf(f,list('! gerbil.a));
  4047. % cannot use pvarsub since want to squash higher powers.
  4048. return list(u,w,f)
  4049. end;
  4050. symbolic procedure nsqfrp(u,v);
  4051. begin
  4052. scalar w;
  4053. w:=modeval(u,v);
  4054. if w eq 'failed
  4055. then go to normal;
  4056. if atom w
  4057. then go to normal;
  4058. if ldegvar(w,v) neq ldegvar(u,v)
  4059. then go to normal;
  4060. % printc "Modular image is:";
  4061. % printsf w;
  4062. w:=gcdf(w,partialdiff(w,v));
  4063. % printc "Answer is:";
  4064. % printsf w;
  4065. if w iequal 1
  4066. then return nil;
  4067. normal;
  4068. w:=gcdf(u,partialdiff(u,v));
  4069. if involvesf(w,v)
  4070. then return w
  4071. else return nil
  4072. end;
  4073. symbolic procedure ldegvar(u,v);
  4074. if atom u
  4075. then 0
  4076. else if mvar u eq v
  4077. then ldeg u
  4078. else if ordop(v,mvar u)
  4079. then 0
  4080. else max2(ldegvar(lc u,v),ldegvar(red u,v));
  4081. symbolic procedure modeval(u,v);
  4082. if atom u
  4083. then u
  4084. else if v eq mvar u
  4085. then begin
  4086. scalar w,x;
  4087. w:=modeval(lc u,v);
  4088. if w eq 'failed
  4089. then return w;
  4090. x:=modeval(red u,v);
  4091. if x eq 'failed
  4092. then return x;
  4093. if null w
  4094. then return x
  4095. else return (lpow u .* w) .+ x
  4096. end
  4097. else begin
  4098. scalar w,x;
  4099. x:=mvar u;
  4100. if not atom x
  4101. then if dependsp(x,v)
  4102. then return 'failed;
  4103. x:=modevalvar x;
  4104. if x eq 'failed
  4105. then return x;
  4106. w:=modeval(lc u,v);
  4107. if w eq 'failed
  4108. then return w;
  4109. if x
  4110. then w:=multf(w,exptf(x,ldeg u));
  4111. x:=modeval(red u,v);
  4112. if x eq 'failed
  4113. then return x;
  4114. return addf(w,x)
  4115. end;
  4116. symbolic procedure modevalvar v;
  4117. begin
  4118. scalar w,x;
  4119. if not atom v
  4120. then go to alg;
  4121. w:=get(v,'modvalue);
  4122. if w
  4123. then return w;
  4124. put(v,'modvalue,modevalcount);
  4125. modevalcount:=modevalcount+1;
  4126. return modevalcount-1;
  4127. alg:
  4128. if car v neq 'sqrt
  4129. then rederr "Unexpected algebraic";
  4130. if numberp argof v
  4131. then return (mksp(v,1) .* 1) .+ nil;
  4132. w:=modeval(!*q2f simp argof v,!*pvar);
  4133. w:=assoc(w,listofallsqrts);
  4134. % the variable does not matter, since we know that it does not depend.
  4135. if w
  4136. then return cdr w
  4137. else return 'failed
  4138. end;
  4139. % unglobal '(modevalcount);
  4140. endmodule;
  4141. module substns;
  4142. % Author: James H. Davenport.
  4143. exports xsubstitutep,xsubstitutesq,substitutevec,substitutesq,subzero,
  4144. subzero2,pvarsub;
  4145. symbolic procedure xsubstitutep(pf,slist);
  4146. simp xsubstitutep2(pf,slist);
  4147. symbolic procedure xsubstitutep2(pf,slist);
  4148. if null slist
  4149. then pf
  4150. else xsubstitutep2(subst(rfirstsubs slist,
  4151. lfirstsubs slist,
  4152. pf),
  4153. cdr slist);
  4154. symbolic procedure xsubstitutesq(sq,slist);
  4155. substitutesq(substitutesq(sq,basicplace slist),extenplace slist);
  4156. symbolic procedure substitutevec(v,slist);
  4157. for i:=0:upbv v do
  4158. putv(v,i,substitutesq(getv(v,i),slist));
  4159. symbolic procedure substitutesq(sq,slist);
  4160. begin
  4161. scalar list2,nm;
  4162. list2:=nil;
  4163. while slist do <<
  4164. if cdar slist iequal 0
  4165. then <<
  4166. if list2
  4167. then sq:=substitutesq(sq,reversewoc list2);
  4168. list2:=nil;
  4169. sq:=subzero(sq,caar slist) >>
  4170. else if not (caar slist = cdar slist)
  4171. then if assoc(caar slist,list2)
  4172. then list2:=for each u in list2 collect
  4173. (car u).subst(cdar slist,caar slist,cdr u)
  4174. else list2:=(car slist).list2;
  4175. % don't bother with the null substitution.
  4176. slist:=cdr slist >>;
  4177. list2:=reversewoc list2;
  4178. if null list2
  4179. then return sq;
  4180. nm:=algint!-subf(numr sq,list2);
  4181. if numr nm
  4182. then nm:=!*multsq(nm,invsq algint!-subf(denr sq,list2));
  4183. return nm
  4184. end;
  4185. % standard interface.
  4186. symbolic procedure subzero(exprn,var);
  4187. begin
  4188. scalar top;
  4189. top:=subzero2(numr exprn,var);
  4190. if null numr top
  4191. then return nil ./ 1;
  4192. return !*multsq(top,!*invsq subzero2(denr exprn,var))
  4193. end;
  4194. symbolic procedure subzero2(sf,var);
  4195. if not involvesf(sf,var)
  4196. then sf ./ 1
  4197. else if var eq mvar sf
  4198. then subzero2(red sf,var)
  4199. else if ordop(var,mvar sf)
  4200. then sf ./ 1
  4201. else begin
  4202. scalar u,v;
  4203. if dependsp(mvar sf,var)
  4204. then <<
  4205. u:=simp subst(0,var,mvar sf);
  4206. if numr u
  4207. then u:=!*exptsq(u,ldeg sf) >>
  4208. else u:=((lpow sf .* 1) .+ nil) ./ 1;
  4209. if null numr u
  4210. then return subzero2(red sf,var);
  4211. v:=subzero2(lc sf,var);
  4212. if null numr v
  4213. then return subzero2(red sf,var);
  4214. return !*addsq(subzero2(red sf,var),
  4215. !*multsq(u,v))
  4216. end;
  4217. symbolic procedure pvarsub(f,u,v);
  4218. % Changes u to v in polynomial f. No proper substitutions at all.
  4219. if atom f
  4220. then f
  4221. else if mvar f equal u
  4222. then addf(multf(lc f,!*p2f mksp(v,ldeg f)),
  4223. pvarsub(red f,u,v))
  4224. else if ordop(u,mvar f)
  4225. then f
  4226. else addf(multf(pvarsub(lc f,u,v),!*p2f lpow f),
  4227. pvarsub(red f,u,v));
  4228. endmodule;
  4229. module taylor;
  4230. % Author: James H. Davenport.
  4231. fluid '(const taylorasslist taylorvariable);
  4232. exports taylorform,taylorformp,taylorevaluate,return0,taylorplus,
  4233. initialtaylorplus,taylorminus,initialtaylorminus,
  4234. tayloroptminus,tayloroptplus,taylorctimes,initialtaylortimes,
  4235. tayloroptctimes,taylorsqrtx,initialtaylorsqrtx,
  4236. taylorquotient,initialtaylorquotient,taylorformersqrt,
  4237. taylorbtimes,taylorformertimes,taylorformerexpt;
  4238. symbolic procedure taylorform sq;
  4239. if involvesf(denr sq,taylorvariable)
  4240. then taylorformp list('quotient,tayprepf numr sq,tayprepf denr sq)
  4241. else if 1 iequal denr sq
  4242. then taylorformp tayprepf numr sq
  4243. else taylorformp list('constanttimes,
  4244. tayprepf numr sq,
  4245. mk!*sq(1 ./ (denr sq)));
  4246. % get division by a constant right.
  4247. symbolic procedure taylorformp pf;
  4248. if null pf
  4249. then nil
  4250. else if not dependsp(pf,taylorvariable)
  4251. then taylorconst simp pf
  4252. else begin
  4253. scalar fn,initial,args;
  4254. if atom pf
  4255. then if pf eq taylorvariable
  4256. then return taylorformp list ('expt,pf,1)
  4257. else interr "False atom in taylorformp";
  4258. % get 'x right as reduce shorthand for x**1.
  4259. if taylorp pf
  4260. then return pf;
  4261. % cope with pre-expressed cases.
  4262. % ***store-hack-1***
  4263. % remove the (car pf eq 'sqrt) if more store is available.
  4264. if (car pf eq 'sqrt) and
  4265. (fn:=assoc(pf,taylorasslist))
  4266. then go to lookupok;
  4267. % look it up first.
  4268. fn:=get(car pf,'taylorformer);
  4269. if null fn
  4270. then go to ordinary;
  4271. fn:=apply(fn,list cdr pf);
  4272. % ***store-hack-1***
  4273. % remove the test if more store is available.
  4274. if car pf eq 'sqrt
  4275. then taylorasslist:=(pf.fn).taylorasslist;
  4276. return fn;
  4277. % cope with the special cases.
  4278. ordinary:
  4279. args:=mapcar(cdr pf,function taylorformp);
  4280. fn:=get(car pf,'tayloropt);
  4281. if null fn
  4282. then go to nooptimisation;
  4283. fn:=apply(fn,list args);
  4284. if fn
  4285. then go to ananswer;
  4286. % an optimisation has been made.
  4287. nooptimisation:
  4288. fn:=get(car pf,'taylorfunction);
  4289. if null fn
  4290. then interr "No Taylor function provided";
  4291. fn:=fn.args;
  4292. % fn is now the "how to compute" code.
  4293. initial:=get(car pf,'initialtaylorfunction);
  4294. if null initial
  4295. then interr "No initial Taylor function";
  4296. initial:=apply(initial,
  4297. list for each u in cdr fn collect firstterm u);
  4298. % the first term in the expansion.
  4299. fn:=list(fn,(car initial).(car initial),initial);
  4300. ananswer:
  4301. % ***store-hack-1***
  4302. % uncomment this if more store is available;
  4303. % taylorasslist:=(pf.fn).taylorasslist;
  4304. return fn;
  4305. lookupok:
  4306. % These PRINT statements can be enabled in order to test the
  4307. % efficacy of the association list
  4308. % printc "Taylor lookup succeeded";
  4309. % superprint car fn;
  4310. % printc length taylorasslist;
  4311. return cdr fn
  4312. end;
  4313. symbolic procedure taylorevaluate(texpr,n);
  4314. if n<taylorfirst texpr
  4315. then nil ./ 1
  4316. else if n>taylorlast texpr
  4317. then tayloreval2(texpr,n)
  4318. else begin
  4319. scalar u;
  4320. u:=assoc(n,taylorlist texpr);
  4321. if u
  4322. then return cdr u
  4323. else return tayloreval2(texpr,n)
  4324. end;
  4325. symbolic procedure tayloreval2(texpr,n);
  4326. begin
  4327. scalar u;
  4328. % actually evaluates from scratch.
  4329. u:=apply(taylorfunction texpr, list(n,texpr,cdr taylordefn texpr));
  4330. if 'return0 eq taylorfunction texpr
  4331. then return u;
  4332. % no need to update with trivial zeroes.
  4333. rplacd(cdr texpr,(n.u).taylorlist texpr);
  4334. % update the association list.
  4335. if n>taylorlast texpr
  4336. then rplacd(taylornumbers texpr,n);
  4337. % update the first/last pointer.
  4338. return u
  4339. end;
  4340. symbolic procedure taylorconst sq;
  4341. list('return0 . nil,0 . 0,0 . sq);
  4342. symbolic procedure return0 (a,b,c);
  4343. nil ./ 1;
  4344. flag('(return0),'taylor);
  4345. symbolic procedure firstterm texpr;
  4346. begin
  4347. scalar n,i;
  4348. i:=taylorfirst texpr;
  4349. trynext:
  4350. n:=taylorevaluate(texpr,i);
  4351. if numr n
  4352. then return i.n;
  4353. if i > 50
  4354. then interr "Potentially zero Taylor series";
  4355. i:=iadd1 i;
  4356. rplaca(taylornumbers texpr,i);
  4357. go to trynext
  4358. end;
  4359. symbolic procedure tayloroneterm u;
  4360. % See if a Taylor expression has only one term.
  4361. 'return0 eq taylorfunction u and taylorfirst u=taylorlast u;
  4362. % ***store-hack-1***;
  4363. % uncomment this procedure if more store is available;
  4364. % there is a smacro for this at the start of the file
  4365. % for use if no store can be spared;
  4366. %symbolic procedure tayshorten(save);
  4367. %begin
  4368. % scalar z;
  4369. % % shortens the association list back to save,
  4370. % removing all the non-sqrts from it;
  4371. % while taylorasslist neq save do <<
  4372. % if caar taylorasslist eq 'sqrt
  4373. % then z:=(car taylorasslist).z;
  4374. % taylorasslist:=cdr taylorasslist >>;
  4375. % taylorasslist:=nconc(z,taylorasslist);
  4376. % return nil
  4377. % end;
  4378. symbolic procedure tayprepf sf;
  4379. if atom sf
  4380. then sf
  4381. else if atom mvar sf
  4382. then taylorpoly makemainvar(sf,taylorvariable)
  4383. else if null red sf
  4384. then tayprept lt sf
  4385. else list('plus,tayprept lt sf,tayprepf red sf);
  4386. symbolic procedure tayprept term;
  4387. if tdeg term = 1
  4388. then if tc term = 1
  4389. then tvar term
  4390. else list('times,tvar term,tayprepf tc term)
  4391. else if tc term = 1
  4392. then list ('expt,tvar term,tdeg term)
  4393. else list('times,list('expt,tvar term,tdeg term),
  4394. tayprepf tc term);
  4395. symbolic procedure taylorpoly sf;
  4396. % SF is a poly with MVAR = TAYLORVARIABLE.
  4397. begin
  4398. scalar tmax,tmin,u;
  4399. tmax:=tmin:=ldeg sf;
  4400. while sf do
  4401. if atom sf or (mvar sf neq taylorvariable)
  4402. then <<
  4403. tmin:=0;
  4404. u:=(0 . !*f2q sf).u;
  4405. sf:=nil >>
  4406. else <<
  4407. u:=((tmin:=ldeg sf) . !*f2q lc sf) . u;
  4408. sf:=red sf >>;
  4409. return (list 'return0) . ((tmin.tmax).u)
  4410. end;
  4411. symbolic procedure taylorplus(n,texpr,args);
  4412. mapply(function addsq,
  4413. for each u in args collect taylorevaluate(u,n));
  4414. symbolic procedure initialtaylorplus slist;
  4415. begin
  4416. scalar n,numlst;
  4417. n:=mapply(function min2,mapcar(slist,function car));
  4418. % the least of the degrees.
  4419. numlst:=nil;
  4420. while slist do <<
  4421. if caar slist iequal n
  4422. then numlst:=(cdar slist).numlst;
  4423. slist:=cdr slist >>;
  4424. return n.mapply(function addsq,numlst)
  4425. end;
  4426. put ('plus,'taylorfunction,'taylorplus);
  4427. put ('plus,'initialtaylorfunction,'initialtaylorplus);
  4428. symbolic procedure taylorminus(n,texpr,args);
  4429. negsq taylorevaluate(car args,n);
  4430. symbolic procedure initialtaylorminus slist;
  4431. (caar slist).(negsq cdar slist);
  4432. put('minus,'taylorfunction,'taylorminus);
  4433. put('minus,'initialtaylorfunction,'initialtaylorminus);
  4434. flag('(taylorplus taylorminus),'taylor);
  4435. symbolic procedure tayloroptminus(u);
  4436. if 'return0 eq taylorfunction car u
  4437. then taylormake(taylordefn car u,
  4438. taylornumbers car u,
  4439. taylorneglist taylorlist car u)
  4440. else if 'taylorctimes eq taylorfunction car u
  4441. then begin
  4442. scalar const;
  4443. u:=car u;
  4444. const:=caddr taylordefn u;
  4445. % the item to be negated.
  4446. const:=taylormake(taylordefn const,
  4447. taylornumbers const,
  4448. taylorneglist taylorlist const);
  4449. return taylormake(list(taylorfunction u,
  4450. argof taylordefn u,
  4451. const),
  4452. taylornumbers u,
  4453. taylorneglist taylorlist u)
  4454. end
  4455. else nil;
  4456. put('minus,'tayloropt,'tayloroptminus);
  4457. symbolic procedure taylorneglist u;
  4458. mapcar(u,function (lambda v;
  4459. (car v).(negsq cdr v)));
  4460. symbolic procedure tayloroptplus args;
  4461. begin
  4462. scalar ret,hard,u;
  4463. u:=args;
  4464. while u do <<
  4465. if 'return0 eq taylorfunction car u
  4466. then ret:=(car u).ret
  4467. else hard:=(car u).hard;
  4468. u:=cdr u >>;
  4469. if null ret or
  4470. null cdr ret
  4471. then return nil;
  4472. ret:=mapply(function joinret,ret);
  4473. if null hard
  4474. then return ret;
  4475. rplaca(args,ret);
  4476. rplacd(args,hard);
  4477. return nil
  4478. end;
  4479. put('plus,'tayloropt,'tayloroptplus);
  4480. symbolic procedure joinret(u,v);
  4481. begin
  4482. scalar nums,a,b,al;
  4483. nums:=(min2(taylorfirst u,taylorfirst v).
  4484. max2(taylorlast u,taylorlast v));
  4485. al:=nil;
  4486. u:=taylorlist u;
  4487. v:=taylorlist v;
  4488. for i:=(car nums) step 1 until (cdr nums) do <<
  4489. a:=assoc(i,u);
  4490. b:=assoc(i,v);
  4491. if a
  4492. then if b
  4493. then al:=(i.addsq(cdr a,cdr b)).al
  4494. else al:=a.al
  4495. else if b
  4496. then al:=b.al >>;
  4497. return taylormake(list 'return0,nums,al)
  4498. end;
  4499. % the operator constanttimes
  4500. % has two arguments (actually a list)
  4501. % 1) a form dependent on the taylorvariable
  4502. % 2) a form which is not.
  4503. % the operator binarytimes has two arguments (actually a list)
  4504. % but behaves like times otherwise.
  4505. symbolic procedure taylorctimes(n,texpr,args);
  4506. !*multsq(taylorevaluate(car args,n-(taylorfirst cadr args)),
  4507. taylorevaluate(cadr args,taylorfirst cadr args));
  4508. symbolic procedure initialtaylortimes slist;
  4509. % Multiply the variable by the constant.
  4510. ((caar slist)+(caadr slist)). !*multsq(cdar slist,cdadr slist);
  4511. symbolic procedure tayloroptctimes u;
  4512. if 'taylorctimes eq taylorfunction car u
  4513. then begin
  4514. scalar reala,const,iconst,degg;
  4515. % we have nested multiplication.
  4516. reala:=argof taylordefn car u;
  4517. % the thing to be multiplied by the two constants.
  4518. const:=car taylorlist cadr u;
  4519. %the actual outer constant: deg.sq.
  4520. iconst:=caddr taylordefn car u;
  4521. %the inner constant.
  4522. degg:=(taylorfirst iconst)+(car const);
  4523. iconst:=list(taylordefn iconst,
  4524. degg.degg,
  4525. degg.!*multsq(cdar taylorlist iconst,cdr const));
  4526. return list('taylorctimes,reala,iconst).
  4527. ((((taylorfirst car u) + (car const)).
  4528. ((taylorlast car u) + (car const))).
  4529. mapcar(taylorlist car u,function multconst))
  4530. end
  4531. else if 'return0 eq taylorfunction car u
  4532. then begin
  4533. scalar const;
  4534. const:=car taylorlist cadr u;
  4535. % the actual constant:deg.sq.
  4536. u:=car u;
  4537. return (taylordefn u).
  4538. ((((taylorfirst u)+car const).
  4539. ((taylorlast u)+car const)).
  4540. mapcar(taylorlist u,function multconst))
  4541. end
  4542. else nil;
  4543. symbolic procedure multconst v;
  4544. % Multiplies v by const in deg.sq form.
  4545. ((car v)+(car const)) . !*multsq(cdr v,cdr const);
  4546. put('constanttimes,'tayloropt,'tayloroptctimes);
  4547. put('constanttimes,'simpfn,'simptimes);
  4548. put('constanttimes,'taylorfunction,'taylorctimes);
  4549. put('constanttimes,'initialtaylorfunction,'initialtaylortimes);
  4550. symbolic procedure taylorbtimes(n,texpr,args);
  4551. begin
  4552. scalar answer,i,n1,n2;
  4553. answer:= nil ./ 1;
  4554. n1:=car firstterm car args;
  4555. % the first term in one argument.
  4556. n2:=car firstterm cadr args;
  4557. % the first term in the other.
  4558. for i:=n1 step 1 until (n-n2) do
  4559. answer:=addsq(answer,!*multsq(taylorevaluate(cadr args,n-i),
  4560. taylorevaluate(car args,i)));
  4561. return answer
  4562. end;
  4563. put('binarytimes,'taylorfunction,'taylorbtimes);
  4564. put('binarytimes,'initialtaylorfunction,'initialtaylortimes);
  4565. put('binarytimes,'simpfn,'simptimes);
  4566. symbolic procedure taylorformertimes arglist;
  4567. begin
  4568. scalar const,var,degg,wsqrt,negcount,u;
  4569. negcount:=0;
  4570. degg:=0;% the deggrees of any solitary x we may meet.
  4571. const:=nil;
  4572. var:=nil;
  4573. wsqrt:=nil;
  4574. while arglist do <<
  4575. if dependsp(car arglist,taylorvariable)
  4576. then if and(eqcar(car arglist,'expt),
  4577. cadar arglist eq taylorvariable,
  4578. numberp caddar arglist)
  4579. then degg:=degg+caddar arglist
  4580. % removed JHD 21.8.86 - while it is anoptimisation,
  4581. % it runs the risk of proving that -1 = +1 by ignoring the
  4582. % number of "i" needed - despite the attempts we went to.
  4583. % else if eqcar(car arglist,'sqrt)
  4584. % then <<
  4585. % u:=argof car arglist;
  4586. % wsqrt:=u.wsqrt;
  4587. % if minusq cdr firstterm taylorformp u
  4588. % then negcount:=1+negcount >>
  4589. else if car arglist eq taylorvariable
  4590. then degg:=degg + 1
  4591. else var:=(car arglist).var
  4592. else const:=(car arglist).const;
  4593. arglist:=cdr arglist >>;
  4594. if wsqrt
  4595. then if cdr wsqrt
  4596. then var:=list('sqrt,prepsq simptimes wsqrt).var
  4597. else var:=('sqrt.wsqrt).var;
  4598. if var
  4599. then var:=mapply(function (lambda u,v;
  4600. list('binarytimes,u,v)),var);
  4601. % insert binary multiplications.
  4602. negcount:=negcount/2;
  4603. if onep cdr divide(negcount,2)
  4604. then const:= (-1).const;
  4605. % we had an odd number of (-1) from i*i.
  4606. if const or (degg neq 0)
  4607. then <<
  4608. if const
  4609. then const:=simptimes const
  4610. else const:=1 ./ 1;
  4611. const:=taylormake(list 'return0,degg.degg,list(degg.const));
  4612. if null var
  4613. then var:=const
  4614. else var:=list('constanttimes,var,const) >>;
  4615. return taylorformp var
  4616. end;
  4617. put('times,'taylorformer,'taylorformertimes);
  4618. flag('(taylorbtimes taylorctimes taylorquotient),'taylor);
  4619. symbolic procedure taylorformerexpt arglist;
  4620. begin
  4621. scalar base,expon;
  4622. base:=car arglist;
  4623. expon:=simpcar cdr arglist;
  4624. if (denr expon neq 1) or
  4625. (not numberp numr expon)
  4626. then interr "Hard exponent";
  4627. expon:=numr expon;
  4628. if base neq taylorvariable
  4629. then interr "Hard base";
  4630. return list('return0 . nil,expon.expon,expon.(1 ./ 1))
  4631. end;
  4632. put ('expt,'taylorformer,'taylorformerexpt);
  4633. symbolic procedure initialtaylorquotient slist;
  4634. (caar slist - caadr slist).!*multsq(cdar slist,!*invsq cdadr slist);
  4635. symbolic procedure taylorquotient(n,texpr,args);
  4636. begin
  4637. % problem is texpr=b/c or c*texpr=b.
  4638. scalar sofar,b,c,cfirst;
  4639. b:=car args;
  4640. c:=cadr args;
  4641. cfirst:=taylorfirst c;
  4642. sofar:=taylorevaluate(b,n+cfirst);
  4643. for i:=taylorfirst texpr step 1 until n-1 do
  4644. sofar:=addsq(sofar,!*multsq(taylorevaluate(texpr,i),
  4645. negsq taylorevaluate(c,n+cfirst-i)));
  4646. return !*multsq(sofar,!*invsq taylorevaluate(c,cfirst))
  4647. end;
  4648. put('quotient,'taylorfunction,'taylorquotient);
  4649. put('quotient,'initialtaylorfunction,'initialtaylorquotient);
  4650. symbolic procedure minusq sq;
  4651. if null sq
  4652. then nil
  4653. else if minusf numr sq
  4654. then not minusf denr sq
  4655. else minusf denr sq;
  4656. % This is wrapped round TAYLORFORMERSQRT2 in order to
  4657. % remove the innards of the SQRT from the asslist.
  4658. % note the precautions for nested SQRTs.
  4659. symbolic procedure taylorformersqrt arglist;
  4660. % ***store-hack-1***;
  4661. % Uncomment these lines if more store is available.
  4662. %begin
  4663. % scalar z;
  4664. % z:=taylorasslist;
  4665. % if sqrtsintree(car arglist,taylorvariable)
  4666. % then return taylorformersqrt2 arglist;
  4667. % arglist:=taylorformersqrt2 arglist;
  4668. % taylorasslist:=z;
  4669. % return arglist
  4670. % end;
  4671. %
  4672. %
  4673. %symbolic procedure taylorformersqrt2 arglist;
  4674. begin
  4675. scalar f,realargs,ff,realsqrt;
  4676. realargs:=taylorformp carx(arglist,'taylorformersqrt2);
  4677. f:=firstterm realargs;
  4678. if not evenp car f
  4679. then interr "Extra sqrt substitution needed";
  4680. if and(0 iequal car f,
  4681. 1 iequal numr cdr f,
  4682. 1 iequal denr cdr f)
  4683. then return taylorformp list('sqrtx,realargs);
  4684. % if it starts with 1 already then it is easy.
  4685. ff:=- car f;
  4686. ff:=list(list 'return0,ff.ff,ff.(!*invsq cdr f));
  4687. % ff is the leading term in the expansion of realargs.
  4688. realsqrt:=list('sqrtx,list('constanttimes,realargs,ff));
  4689. ff:=(car f)/2;
  4690. return taylorformp list('constanttimes,
  4691. realsqrt,
  4692. list(list 'return0,
  4693. ff.ff,
  4694. ff.(simpsqrtsq cdr f)))
  4695. end;
  4696. put('sqrt,'taylorformer,'taylorformersqrt);
  4697. symbolic procedure initialtaylorsqrtx slist;
  4698. 0 . (1 ./ 1);
  4699. % sqrt(1+ ...) = 1+....
  4700. symbolic procedure taylorsqrtx(n,texpr,args);
  4701. begin
  4702. scalar sofar,i;
  4703. sofar:=taylorevaluate(car args,n);
  4704. % (1+.....+a(n)*x**n)**2
  4705. % = ....+x**n*(2*a(n)+sum(0<i<n,a(i)*a(n-i))).
  4706. % So a(n)=(coeff(x**n)-sum) /2.
  4707. for i:=1 step 1 until (n-1) do
  4708. sofar:=addsq(sofar,negsq !*multsq(taylorevaluate(texpr,i),
  4709. taylorevaluate(texpr,n-i)));
  4710. return multsq(sofar,1 ./ 2)
  4711. end;
  4712. flag('(taylorsqrtx),'taylor);
  4713. put('sqrtx,'taylorfunction,'taylorsqrtx);
  4714. put('sqrtx,'initialtaylorfunction,'initialtaylorsqrtx);
  4715. endmodule;
  4716. module torsionb;
  4717. % Author: James H. Davenport.
  4718. fluid '(intvar nestedsqrts);
  4719. global '(!*tra !*trmin);
  4720. exports bound!-torsion;
  4721. symbolic procedure bound!-torsion(divisor,dof1k);
  4722. % Version 1 (see Trinity Thesis for difference).
  4723. begin
  4724. scalar field,prime1,prime2,prime3,minimum,places;
  4725. scalar non!-p1,non!-p2,non!-p3,curve,curve2,nestedsqrts;
  4726. places:=for each u in divisor
  4727. collect car u;
  4728. curve:=getsqrtsfromplaces places;
  4729. if nestedsqrts
  4730. then rederr "Not yet implemented"
  4731. else curve2:=curve;
  4732. for each u in places do begin
  4733. u:=rfirstsubs u;
  4734. if eqcar(u,'quotient) and cadr u = 1
  4735. then return;
  4736. u:=substitutesq(simp u,list(intvar . 0));
  4737. field:=union(field,sqrtsinsq(u,nil));
  4738. u:=list(intvar . prepsq u);
  4739. for each v in curve2 do
  4740. field:=union(field,sqrtsinsq(substitutesq(v,u),nil));
  4741. end;
  4742. prime1:=2;
  4743. while null (non!-p1:=good!-reduction(curve,dof1k,field,prime1)) do
  4744. prime1:=nextprime prime1;
  4745. prime2:=nextprime prime1;
  4746. while null (non!-p2:=good!-reduction(curve,dof1k,field,prime2)) do
  4747. prime2:=nextprime prime2;
  4748. prime3:=nextprime prime2;
  4749. while null (non!-p3:=good!-reduction(curve,dof1k,field,prime3)) do
  4750. prime3:=nextprime prime3;
  4751. minimum:=fix sqrt float(non!-p1*non!-p2*non!-p3);
  4752. minimum:=min(minimum,non!-p1*max!-power(prime1,min(non!-p2,non!-p3)));
  4753. minimum:=min(minimum,non!-p2*max!-power(prime2,min(non!-p1,non!-p3)));
  4754. minimum:=min(minimum,non!-p3*max!-power(prime3,min(non!-p2,non!-p1)));
  4755. if !*tra or !*trmin then <<
  4756. princ "Torsion is bounded by ";
  4757. printc minimum >>;
  4758. return minimum
  4759. end;
  4760. symbolic procedure max!-power(p,n);
  4761. % Greatest power of p not greater than n.
  4762. begin scalar ans;
  4763. ans:=1;
  4764. while ans<=n do
  4765. ans:=ans*p;
  4766. ans:=ans/p;
  4767. end;
  4768. symbolic procedure good!-reduction(curve,dof1k,field,prime);
  4769. begin
  4770. scalar u;
  4771. u:=algebraic!-factorise(prime,field);
  4772. interr "Good reduction not finished";
  4773. end;
  4774. endmodule;
  4775. module wstrass;
  4776. % Author: James H. Davenport.
  4777. fluid '(!*backtrace
  4778. intvar
  4779. listofallsqrts
  4780. listofnewsqrts
  4781. magiclist
  4782. previousbasis
  4783. sqrt!-intvar
  4784. sqrtflag
  4785. sqrts!-in!-integrand
  4786. taylorasslist
  4787. taylorvariable
  4788. thisplace
  4789. zlist);
  4790. global '(!*tra !*trmin coates!-fdi);
  4791. exports simpwstrass,weierstrass!-form,gcdn,sqrtsinplaces,
  4792. makeinitialbasis,mkvec,completeplaces,integralbasis,
  4793. normalbasis,mksp,multsq,xsubstitutesq,taylorform,taylorevaluate,
  4794. coatessolve,checkpoles,substitutesq,removecmsq,printsq,interr,
  4795. terpri!*,printplace,finitise,fractional!-degree!-at!-infinity,
  4796. !*multsq,fdi!-print,fdi!-upgrade,fdi!-revertsq,simp,newplace,
  4797. xsubstitutep,sqrtsinsq,removeduplicates,!*exptf,!*multf,
  4798. !*multsq,!*q2f,mapvec,upbv,coates!-lineq,addsq,!*addsq;
  4799. symbolic procedure simpwstrass u;
  4800. begin
  4801. scalar intvar,sqrt!-intvar,taylorvariable,taylorasslist;
  4802. scalar listofallsqrts,listofnewsqrts;
  4803. scalar sqrtflag,sqrts!-in!-integrand,tt,u;
  4804. tt:=readclock();
  4805. sqrtflag:=t;
  4806. taylorvariable:=intvar:=car u;
  4807. sqrt!-intvar:=mvar !*q2f simpsqrti intvar;
  4808. u:=for each v in cdr u
  4809. collect simp!* v;
  4810. sqrts!-in!-integrand:=sqrtsinsql(u,intvar);
  4811. u:=errorset('(weierstrass!-form sqrts!-in!-integrand),
  4812. t,!*backtrace);
  4813. if atom u
  4814. then return u
  4815. else u:=car u;
  4816. printc list('time,'taken,readclock()-tt,'milliseconds);
  4817. printc "New x value is:";
  4818. printsq car u;
  4819. u:=cdr u;
  4820. printc "New y value is:";
  4821. printsq car u;
  4822. u:=cdr u;
  4823. printc "Related by the equation";
  4824. printsq car u;
  4825. return car u
  4826. end;
  4827. put('wstrass,'simpfn,'simpwstrass);
  4828. symbolic procedure weierstrass!-form sqrtl;
  4829. begin
  4830. scalar sqrtl2,u,x2,x1,vec,a,b,c,d,lhs,rhs;
  4831. if !*tra or !*trmin then <<
  4832. printc "Find weierstrass form for elliptic curve defined by:";
  4833. for each u in sqrtl do
  4834. printsq simp u >>;
  4835. sqrtl2:=sqrts!-at!-infinity sqrtl;
  4836. sqrtl2:=append(car sqrtl2,
  4837. for each u in cdr sqrtl2 collect
  4838. u.u);
  4839. % one of the places lying over infinity
  4840. % (after deramification as necessary).
  4841. x2:=coates!-wstrass(list sqrtl2,list(-3),intvar);
  4842. % Note that we do not multiply by the MULTIPLICITY!-FACTOR
  4843. % since we genuinely want a pole of order -3 irrespective
  4844. % of any ramification problems.
  4845. if !*tra then <<
  4846. printc "Function with pole of order 3 (x2) is:";
  4847. printsq x2 >>;
  4848. x1:=coates!-wstrass(list sqrtl2,list(-2),intvar);
  4849. if !*tra then <<
  4850. printc "Function with pole of order 2 (x1) is:";
  4851. printsq x1 >>;
  4852. vec:=mkvec list(1 ./ 1,
  4853. x1,
  4854. x2,
  4855. !*multsq(x1,x1),
  4856. !*multsq(x2,x2),
  4857. !*multsq(x1,!*multsq(x1,x1)),
  4858. !*multsq(x1,x2));
  4859. u:=!*lcm!*(!*exptf(denr x1,3),!*multf(denr x2,denr x2)) ./ 1;
  4860. for i:=0:6 do
  4861. putv(vec,i,!*q2f !*multsq(u,getv(vec,i)));
  4862. if !*tra then <<
  4863. printc "List of seven functions in weierstrass!-form:";
  4864. mapvec(vec,function printsf) >>;
  4865. vec:=wstrass!-lineq vec;
  4866. % printsq(addsq(getv(vec,0),addsq(!*multsq(getv(vec,1),x1),
  4867. % addsq(!*multsq(getv(vec,2),x2),
  4868. % addsq(!*multsq(getv(vec,3),!*multsq(x1,x1)),
  4869. % addsq(!*multsq(getv(vec,4),!*multsq(x2,x2)),
  4870. % addsq(!*multsq(getv(vec,5),exptsq(x1,3)),
  4871. % !*multsq(getv(vec,6),
  4872. % !*multsq(x1,x2)))))))));
  4873. x2:=!*addsq(!*multsq(!*multsq(2 ./ 1,getv(vec,4)),x2),
  4874. addsq(!*multsq(x1,getv(vec,6)),
  4875. getv(vec,2)));
  4876. putv(vec,4,!*multsq(-4 ./ 1,getv(vec,4)));
  4877. a:=!*multsq(getv(vec,4),getv(vec,5));
  4878. b:=!*addsq(!*multsq(getv(vec,6),getv(vec,6)),
  4879. !*multsq(getv(vec,3),getv(vec,4)));
  4880. c:=!*addsq(!*multsq(2 ./ 1,!*multsq(getv(vec,2),getv(vec,6))),
  4881. !*multsq(getv(vec,1),getv(vec,4)));
  4882. d:=!*addsq(!*multsq(getv(vec,2),getv(vec,2)),
  4883. !*multsq(getv(vec,0),getv(vec,4)));
  4884. lhs:=!*multsq(x2,x2);
  4885. rhs:=addsq(d,!*multsq(x1,
  4886. addsq(c,!*multsq(x1,addsq(b,!*multsq(x1,a))))));
  4887. if lhs neq rhs then <<
  4888. printsq lhs;
  4889. printsq rhs;
  4890. interr "Previous two unequal - consistency failure 1" >>;
  4891. u:=!*lcm!*(!*lcm!*(denr a,denr b),!*lcm!*(denr c,denr d));
  4892. if u neq 1 then <<
  4893. % for now use u**2 whereas we should be using the least
  4894. % square greater than u**2 (does it really matter).
  4895. x2:=!*multsq(x2,u ./ 1);
  4896. u:=!*multf(u,u) ./ 1;
  4897. a:=!*multsq(a,u);
  4898. b:=!*multsq(b,u);
  4899. c:=!*multsq(c,u);
  4900. d:=!*multsq(d,u) >>;
  4901. if (numr b) and not (quotf(numr b,3)) then <<
  4902. % multiply all through by 9 for the hell of it.
  4903. x2:=multsq(3 ./ 1,x2);
  4904. u:=9 ./ 1;
  4905. a:=multsq(a,u);
  4906. b:=multsq(b,u);
  4907. c:=multsq(c,u);
  4908. d:=multsq(d,u) >>;
  4909. x2:=!*multsq(x2,a);
  4910. x1:=!*multsq(x1,a);
  4911. c:=!*multsq(a,c);
  4912. d:=!*multsq(!*multsq(a,a),d);
  4913. lhs:=!*multsq(x2,x2);
  4914. rhs:=addsq(d,!*multsq(x1,addsq(c,!*multsq(x1,addsq(b,x1)))));
  4915. if lhs neq rhs then <<
  4916. printsq lhs;
  4917. printsq rhs;
  4918. interr "Previous two unequal - consistency failure 2" >>;
  4919. b:=quotf(numr b,3) ./ 1;
  4920. x1:=!*addsq(x1,b);
  4921. d:=!*addsq(d,!*addsq(multsq(2 ./ 1,!*multsq(b,!*multsq(b,b))),
  4922. negsq !*multsq(c,b)));
  4923. c:=!*addsq(c,!*multsq((-3) ./ 1,!*multsq(b,b)) );
  4924. % b:=nil ./ 1; % not used again.
  4925. if !*tra then <<
  4926. printsq x2;
  4927. printsq x1;
  4928. printc "with coefficients";
  4929. printsq c;
  4930. printsq d;
  4931. rhs:=!*addsq(d,
  4932. !*addsq(!*multsq(c,x1),
  4933. !*multsq(x1,!*multsq(x1,x1)) ));
  4934. lhs:=!*multsq(x2,x2);
  4935. if lhs neq rhs then <<
  4936. printsq lhs;
  4937. printsq rhs;
  4938. interr "Previous two unequal - consistency failure 3" >> >>;
  4939. return weierstrass!-form1(c,d,x1,x2)
  4940. end;
  4941. symbolic procedure weierstrass!-form1(c,d,x1,x2);
  4942. begin scalar b,u;
  4943. u:=gcdf(numr c,numr d);
  4944. % We will reduce by anything whose square divides C
  4945. % and whose cube divides D.
  4946. if not numberp u then begin
  4947. scalar cc,dd;
  4948. u:=jsqfree(u,mvar u);
  4949. u:=cdr u;
  4950. if null u
  4951. then return;
  4952. % We found no repeated factors.
  4953. for each v in u do
  4954. for each w in v do
  4955. while (cc:=quotf(numr c,multf(w,w))) and
  4956. (dd:=quotf(numr d,exptf(w,3)))
  4957. do <<
  4958. c:=cc ./ 1;
  4959. d:=dd ./ 1;
  4960. x1:=!*multsq(x1,1 ./ w);
  4961. x2:=!*multsq(x2,1 ./ multf(w,simpsqrt2 w)) >>;
  4962. u:=gcdn(algint!-numeric!-content numr c,
  4963. algint!-numeric!-content numr d)
  4964. end;
  4965. b:=2;
  4966. while not (b*b) > u do begin
  4967. scalar nc,nd,uu;
  4968. nc:=0;
  4969. while zerop cdr (uu:=divide(u,b)) do <<
  4970. nc:=nc+1;
  4971. u:=car uu >>;
  4972. if nc < 2
  4973. then go to next;
  4974. uu:=algint!-numeric!-content numr d;
  4975. nd:=0;
  4976. while zerop cdr (uu:=divide(uu,b)) do <<
  4977. nd:=nd+1;
  4978. uu:=car uu >>;
  4979. if nd < 3
  4980. then go to next;
  4981. nc:=min(nc/2,nd/3);
  4982. % re-normalise by b**nc.
  4983. uu:=b**nc;
  4984. c:=multsq(c,1 ./ (uu**2));
  4985. d:=multsq(d,1 ./ (uu**3));
  4986. x1:=multsq(x1,1 ./ uu);
  4987. x2:=multsq(x2,1 ./ (uu*b**(nc/2)) );
  4988. if not evenp nc
  4989. then x2:=!*multsq(x2,!*invsq simpsqrti b);
  4990. next:
  4991. b:=nextprime(b)
  4992. end;
  4993. u:=!*kk2q intvar;
  4994. u:=addsq(addsq(d,multsq(c,u)),exptsq(u,3));
  4995. if !*tra or !*trmin then <<
  4996. printc "Standard form is y**2 = ";
  4997. printsq u >>;
  4998. return list(x1,x2,simpsqrtsq u)
  4999. end;
  5000. symbolic procedure sqrts!-at!-infinity sqrtl;
  5001. begin
  5002. scalar inf,hack,sqrtl2,repeating;
  5003. hack:=list list(intvar,'expt,intvar,2);
  5004. inf:=list list(intvar,'quotient,1,intvar);
  5005. sqrtl2:=list sqrt!-intvar;
  5006. while sqrt!-intvar member sqrtl2 do <<
  5007. if repeating
  5008. then inf:=append(inf,hack);
  5009. newplace inf;
  5010. sqrtl2:=for each v in sqrtl conc
  5011. sqrtsinsq(xsubstitutep(v,inf),intvar);
  5012. repeating:=t >>;
  5013. sqrtl2:=removeduplicates sqrtl2;
  5014. return inf.sqrtl2
  5015. end;
  5016. symbolic procedure coates!-wstrass(places,mults,x);
  5017. begin
  5018. scalar thisplace,u,finite!-hack,save,places2,mults2;
  5019. if !*tra or !*trmin then <<
  5020. princ "Find function with zeros of order:";
  5021. printc mults;
  5022. if !*tra then
  5023. princ " at ";
  5024. terpri!*(t);
  5025. if !*tra then
  5026. mapc(places,function printplace) >>;
  5027. % finite!-hack:=placesindiv places;
  5028. % FINITE!-HACK is a list of all the substitutors in PLACES;
  5029. % u:=removeduplicates sqrtsintree(finite!-hack,x,nil);
  5030. % if !*tra then <<
  5031. % princ "Sqrts on this curve:";
  5032. % terpri!*(t);
  5033. % superprint u >>;
  5034. % algnos:=removeduplicates mapcar(places,function basicplace);
  5035. % if !*tra then <<
  5036. % printc "Algebraic numbers where residues occur:";
  5037. % superprint algnos >>;
  5038. finite!-hack:= finitise(places,mults);
  5039. % returns list (places,mults,power of x to remove.
  5040. places2:=car finite!-hack;
  5041. mults2:=cadr finite!-hack;
  5042. finite!-hack:=list(places,mults,caddr finite!-hack);
  5043. coates!-fdi:=fractional!-degree!-at!-infinity u;
  5044. if coates!-fdi iequal 1
  5045. then return !*multsq(wstrassmodule(places2,mults2,x,finite!-hack),
  5046. !*p2q mksp(x,caddr finite!-hack));
  5047. if !*tra
  5048. then fdi!-print();
  5049. places2:=mapcar(places2,function fdi!-upgrade);
  5050. save:=taylorasslist;
  5051. u:=wstrassmodule(places2,
  5052. mapcar(mults2,function (lambda u;u*coates!-fdi)),
  5053. x,finite!-hack);
  5054. taylorasslist:=save;
  5055. u:=fdi!-revertsq u;
  5056. return !*multsq(u,!*p2q mksp(x,caddr finite!-hack))
  5057. end;
  5058. symbolic procedure wstrassmodule(places,mults,x,finite!-hack);
  5059. begin
  5060. scalar pzero,mzero,u,v,basis,sqrts,magiclist,mpole,ppole;
  5061. % MAGICLIST holds the list of extra unknowns created in JHDSOLVE
  5062. % which must be found in CHECKPOLES (calling FINDMAGIC).
  5063. sqrts:=sqrtsinplaces places;
  5064. if !*tra then <<
  5065. princ "Sqrts on this curve:";
  5066. superprint sqrts >>;
  5067. u:=places;
  5068. v:=mults;
  5069. while u do <<
  5070. if 0<car v
  5071. then <<
  5072. mzero:=(car v).mzero;
  5073. pzero:=(car u).pzero >>
  5074. else <<
  5075. mpole:=(car v).mpole;
  5076. ppole:=(car u).ppole >>;
  5077. u:=cdr u;
  5078. v:=cdr v >>;
  5079. basis:=mkvec makeinitialbasis ppole;
  5080. u:=completeplaces(ppole,mpole);
  5081. basis:=integralbasis(basis,car u,cdr u,x);
  5082. basis:=normalbasis(basis,x,0);
  5083. u:=coatessolve(mzero,pzero,basis,force!-pole(basis,finite!-hack));
  5084. % This is the list of special constraints needed
  5085. % to force certain poles to occur in the answer.
  5086. previousbasis:=nil;
  5087. if atom u
  5088. then return u;
  5089. v:= checkpoles(list u,places,mults);
  5090. if null v
  5091. then return 'failed;
  5092. if not magiclist
  5093. then return u;
  5094. u:=removecmsq substitutesq(u,v);
  5095. % Apply the values from FINDMAGIC.
  5096. if !*tra or !*trmin then <<
  5097. printc "Function is";
  5098. printsq u >>;
  5099. magiclist:=nil;
  5100. if checkpoles(list u,places,mults)
  5101. then return u
  5102. else interr "Inconsistent checkpoles"
  5103. end;
  5104. symbolic procedure force!-pole(basis,finite!-hack);
  5105. begin
  5106. scalar places,mults,u,ans;
  5107. places:=car finite!-hack;
  5108. mults:=cadr finite!-hack;
  5109. finite!-hack:=caddr finite!-hack;
  5110. u:=!*p2q mksp(intvar,finite!-hack);
  5111. basis:=for each v in basis collect multsq(u,v);
  5112. while places do <<
  5113. u:=for each v in basis collect
  5114. taylorevaluate(taylorform xsubstitutesq(v,car places),
  5115. car mults);
  5116. mults:=cdr mults;
  5117. places:=cdr places;
  5118. ans:=u.ans >>;
  5119. return ans
  5120. end;
  5121. symbolic procedure wstrass!-lineq vec;
  5122. begin
  5123. scalar zlist,powlist,m,rightside,v;
  5124. scalar zero,one;
  5125. zero:=nil ./ 1;
  5126. one:=1 ./ 1;
  5127. for i:=0:6 do
  5128. zlist:=varsinsf(getv(vec,i),zlist);
  5129. zlist:=intvar . findzvars(zlist,nil,intvar,nil);
  5130. for i:=0:6 do
  5131. putv(vec,i,f2df getv(vec,i));
  5132. for i:=0:6 do
  5133. for each u in getv(vec,i) do
  5134. if not ((tpow u) member powlist)
  5135. then powlist:=(tpow u).powlist;
  5136. m:=for each u in powlist collect begin
  5137. scalar v;
  5138. v:=mkvect 6;
  5139. for i:=0:6 do
  5140. putv(v,i,(lambda u;
  5141. if null u
  5142. then zero
  5143. else tc u)
  5144. assoc(u,getv(vec,i)));
  5145. return v
  5146. end;
  5147. v:=mkvect 6;
  5148. for i:=0:6 do
  5149. putv(v,i,zero);
  5150. putv(v,4,one);
  5151. % we know that coefficient e is non-zero.
  5152. m:=mkvec (v.m);
  5153. v:=upbv m;
  5154. rightside:=mkvect v;
  5155. putv(rightside,0,one);
  5156. for i:=1:v do
  5157. putv(rightside,i,zero);
  5158. return coates!-lineq(m,rightside)
  5159. end;
  5160. % This is same as NUMERIC!-CONTENT in the EZGCD module, but is included
  5161. % here so that that module doesn't need to be loaded.
  5162. symbolic procedure algint!-numeric!-content form;
  5163. %Find numeric content of non-zero polynomial.
  5164. if domainp form then abs form
  5165. else if null red form then algint!-numeric!-content lc form
  5166. else begin
  5167. scalar g1;
  5168. g1 := algint!-numeric!-content lc form;
  5169. if not (g1=1)
  5170. then g1 := gcddd(g1,algint!-numeric!-content red form);
  5171. return g1
  5172. end;
  5173. endmodule;
  5174. module zmodule;
  5175. % Author: James H. Davenport.
  5176. fluid '(!*galois
  5177. basic!-listofallsqrts
  5178. basic!-listofnewsqrts
  5179. commonden
  5180. gaussiani
  5181. listofallsqrts
  5182. listofnewsqrts
  5183. sqrt!-places!-alist
  5184. taylorasslist);
  5185. global '(!*tra !*trfield !*trmin);
  5186. exports zmodule;
  5187. imports !*multf,sqrtsinsql,sortsqrts,simp,!*q2f,actualsimpsqrt,printsf;
  5188. imports prepf,substitutesq,printsq,mapply,!*multsq,mkilist;
  5189. imports mkvecf2q,mkvec,mkidenm,invsq,multsq,negsq,addsq,gcdn;
  5190. imports !*invsq,prepsq;
  5191. symbolic procedure zmodule(w);
  5192. begin
  5193. scalar reslist,denlist,u,commonden,basis,p1,p2,hcf;
  5194. % w is a list of elements (place.residue)=sq.
  5195. for each v in w do <<
  5196. u:=cdr v;
  5197. reslist:=u.reslist;
  5198. denlist:=(denr u).denlist >>;
  5199. basis:=sqrtsinsql(reslist,nil);
  5200. if null u or null cdr u or !*galois
  5201. then go to nochange;
  5202. reslist:=check!-sqrts!-dependence(reslist,basis);
  5203. denlist:=for each u in reslist
  5204. collect denr u;
  5205. nochange:
  5206. commonden:=mapply(function(lambda u,v;
  5207. multf(u,quotf(v,gcdf(u,v)))),denlist)./1;
  5208. u:=nil;
  5209. for each v in reslist do
  5210. u:=(numr !*multsq(v,commonden)).u;
  5211. reslist:=u;
  5212. % We have effectively reserves RESLIST twice,
  5213. % so it is in the corect order.
  5214. u:=bexprn(reslist);
  5215. basis:=car u;
  5216. reslist:=cdr u;
  5217. denlist:=nil;
  5218. while basis do <<
  5219. p1:=reslist;
  5220. p2:=w;
  5221. u:=nil;
  5222. hcf:=0;
  5223. while p1 do <<
  5224. if 0 neq caar p1
  5225. then <<
  5226. u:=((caar p2).(caar p1)).u;
  5227. hcf:=gcdn(hcf,caar p1) >>;
  5228. p1:=cdr p1;
  5229. p2:=cdr p2 >>;
  5230. if hcf neq 1
  5231. then u:=for each uu in u collect
  5232. (car uu). ( (cdr uu) / hcf);
  5233. denlist:=(prepsq !*multsq(car basis,
  5234. multsq(!*f2q hcf,!*invsq commonden))
  5235. .u).denlist;
  5236. basis:=cdr basis;
  5237. reslist:=mapcar(reslist,function cdr) >>;
  5238. return denlist
  5239. end;
  5240. symbolic procedure bexprn(wlist);
  5241. begin
  5242. scalar basis,replist,w,w2,w3,p1,p2;
  5243. % wlist is a list of sf.
  5244. w:=reverse wlist;
  5245. replist:=nil;
  5246. while w do <<
  5247. w2:=sf2df car w;
  5248. % now ensure that all elements of w2 are in the basis.
  5249. w3:=w2;
  5250. while w3 do <<
  5251. % caar is the sf,cdar a its coefficient.
  5252. if not member(caar w3,basis)
  5253. then <<
  5254. basis:=(caar w3).basis;
  5255. replist:=mapcons(replist,0) >>;
  5256. % adds car w3 to basis.
  5257. w3:=cdr w3 >>;
  5258. replist:=mkilist(basis,0).replist;
  5259. % builds a new zero representation.
  5260. w3:=w2;
  5261. while w3 do <<
  5262. p1:=basis;
  5263. p2:=car replist;
  5264. %the list for this element.
  5265. while p1 do <<
  5266. if caar w3 = car p1
  5267. then rplaca(p2,cdar w3);
  5268. p1:=cdr p1;
  5269. p2:=cdr p2 >>;
  5270. w3:=cdr w3 >>;
  5271. w:=cdr w >>;
  5272. return mkbasis(basis,replist)
  5273. end;
  5274. symbolic procedure mkbasis(basis,reslist);
  5275. begin
  5276. scalar row,nbasis,nreslist,u,v;
  5277. basis:=for each u in basis collect !*f2q u;
  5278. % basis is a list of sq's
  5279. % reslist is a list of representations in the form
  5280. % ( (coeff1 coeff2 ...) ...).
  5281. nreslist:=mkilist(reslist,nil);
  5282. % initialise our list-of-lists.
  5283. trynewloop:
  5284. row:=mapcar(reslist,function car);
  5285. reslist:=mapcar(reslist,function cdr);
  5286. if obvindep(row,nreslist)
  5287. then u:=nil
  5288. else u:=lindep(row,nreslist);
  5289. if u
  5290. then <<
  5291. % u contains the numbers with which to add this new item into the
  5292. % basis.
  5293. v:=nil;
  5294. while nbasis do <<
  5295. v:=addsq(car nbasis,!*multsq(car basis,car u)).v;
  5296. nbasis:=cdr nbasis;
  5297. u:=cdr u >>;
  5298. nbasis:=reversewoc v >>
  5299. else <<
  5300. nreslist:=pair(row,nreslist);
  5301. nbasis:=(car basis).nbasis
  5302. >>;
  5303. basis:=cdr basis;
  5304. if basis
  5305. then go to trynewloop;
  5306. return nbasis.nreslist
  5307. end;
  5308. symbolic procedure obvindep(row,matrx);
  5309. % True if row is obviously linearly independent of the
  5310. % Rows of the matrix.
  5311. begin scalar u;
  5312. if null car matrx
  5313. then return t;
  5314. % no matrix => no dependence.
  5315. nexttry:
  5316. if null row
  5317. then return nil;
  5318. if 0 iequal car row
  5319. then go to nouse;
  5320. u:=car matrx;
  5321. testloop:
  5322. if 0 neq car u
  5323. then go to nouse;
  5324. u:=cdr u;
  5325. if u
  5326. then go to testloop;
  5327. return t;
  5328. nouse:
  5329. row:=cdr row;
  5330. matrx:=cdr matrx;
  5331. go to nexttry
  5332. end;
  5333. symbolic procedure sf2df sf;
  5334. if null sf
  5335. then nil
  5336. else if numberp sf
  5337. then (1 . sf).nil
  5338. else begin
  5339. scalar a,b,c;
  5340. a:=sf2df lc sf;
  5341. b:=(lpow sf .* 1) .+ nil;
  5342. while a do <<
  5343. c:=(!*multf(caar a,b).(cdar a)).c;
  5344. a :=cdr a >>;
  5345. return nconc(c,sf2df red sf)
  5346. end;
  5347. symbolic procedure check!-sqrts!-dependence(sql,sqrtl);
  5348. % Resimplifies the list of SQs SQL,
  5349. % allowing for all dependencies among the
  5350. % sqrts in SQRTl.
  5351. begin
  5352. scalar !*galois,sublist,sqrtsavelist,changeflag;
  5353. sqrtsavelist:=listofallsqrts.listofnewsqrts;
  5354. listofnewsqrts:=list mvar gaussiani;
  5355. listofallsqrts:=list((argof mvar gaussiani) . gaussiani);
  5356. !*galois:=t;
  5357. for each u in sortsqrts(sqrtl,nil) do begin
  5358. scalar v,uu;
  5359. uu:=!*q2f simp argof u;
  5360. v:=actualsimpsqrt uu;
  5361. listofallsqrts:=(uu.v).listofallsqrts;
  5362. if domainp v or mvar v neq u
  5363. then <<
  5364. if !*tra or !*trfield then <<
  5365. printc u;
  5366. printc "re-expressed as";
  5367. printsf v >>;
  5368. v:=prepf v;
  5369. sublist:=(u.v) . sublist;
  5370. changeflag:=t >>
  5371. end;
  5372. if changeflag then <<
  5373. sql:=for each u in sql collect
  5374. substitutesq(u,sublist);
  5375. taylorasslist:=nil;
  5376. sqrt!-places!-alist:=nil;
  5377. basic!-listofallsqrts:=listofallsqrts;
  5378. basic!-listofnewsqrts:=listofnewsqrts;
  5379. if !*tra or !*trmin then <<
  5380. printc "New set of residues are";
  5381. mapc(sql,function printsq) >> >>
  5382. else <<
  5383. listofallsqrts:=car sqrtsavelist;
  5384. listofnewsqrts:=cdr sqrtsavelist >>;
  5385. return sql
  5386. end;
  5387. symbolic procedure lindep(row,matrx);
  5388. begin
  5389. scalar m,mm,n,i,j,k,u,v,inverse,rowsinuse,failure;
  5390. % Inverse is the answer from the "gaussian elimination"
  5391. % we are doing.
  5392. % Rowsinuse has nil for rows with no "awkward" non-zero entries.
  5393. mm:=length car matrx;
  5394. m:=isub1 mm;
  5395. n:=isub1 length matrx;
  5396. % n=length row.
  5397. row:=mkvecf2q row;
  5398. matrx:=mkvec mapcar(matrx,function mkvecf2q);
  5399. inverse:=mkidenm mm;
  5400. rowsinuse:=mkvect m;
  5401. failure:=t;
  5402. % initialisation complete.
  5403. for i:=0 step 1 until n do begin
  5404. % try to kill off i'th elements in each row.
  5405. u:=nil;
  5406. for j:=0 step 1 until m do <<
  5407. % try to find a pivot element.
  5408. if (null u) and
  5409. (null getv(rowsinuse,j)) and
  5410. (numr getv(getv(matrx,i),j))
  5411. then u:=j >>;
  5412. if null u
  5413. then go to nullu;
  5414. putv(rowsinuse,u,t);
  5415. % it is no use trying this again ---
  5416. % u is our pivot element.
  5417. if u iequal m
  5418. then go to nonetokill;
  5419. for j:=iadd1 u step 1 until m do
  5420. if numr getv(getv(matrx,i),j)
  5421. then <<
  5422. v:=negsq multsq(getv(getv(matrx,i),j),
  5423. invsq getv(getv(matrx,i),u));
  5424. for k:=0 step 1 until mm do
  5425. putv(getv(inverse,k),j,
  5426. addsq(getv(getv(inverse,k),j),
  5427. multsq(v,getv(getv(inverse,k),u))));
  5428. for k:=0 step 1 until n do
  5429. putv(getv(matrx,k),j,
  5430. addsq(getv(getv(matrx,k),j),
  5431. multsq(v,getv(getv(matrx,k),u)))) >>;
  5432. %we have now pivoted throughout matrx.
  5433. nonetokill:
  5434. % now do the same in row if necessary.
  5435. if null numr getv(row,i)
  5436. then go to norowop;
  5437. v:=negsq multsq(getv(row,i),
  5438. invsq getv(getv(matrx,i),u));
  5439. for k:=0 step 1 until mm do
  5440. putv(getv(inverse,k),mm,
  5441. addsq(getv(getv(inverse,k),mm),
  5442. multsq(v,getv(getv(inverse,k),u))));
  5443. for k:=0 step 1 until n do
  5444. putv(row,k,addsq(getv(row,k),
  5445. multsq(v,getv(getv(matrx,k),u))));
  5446. u:=nil;
  5447. for k:=0 step 1 until n do
  5448. if numr getv(row,k)
  5449. then u:=t;
  5450. % if u is null then row is all 0.
  5451. if null u
  5452. then <<
  5453. n:=-1;
  5454. failure:=nil >>;
  5455. norowop:
  5456. if !*tra then <<
  5457. princ "At end of cycle";
  5458. printc row;
  5459. printc matrx;
  5460. printc inverse >>;
  5461. return;
  5462. nullu:
  5463. % there is no pivot for this u.
  5464. if numr getv(row,i)
  5465. then n:=-1;
  5466. % this element cannot be killed.
  5467. end;
  5468. if failure
  5469. then return nil;
  5470. v:=nil;
  5471. for i:=0 step 1 until m do
  5472. v:=(negsq getv(getv(inverse,m-i),mm)).v;
  5473. return v
  5474. end;
  5475. endmodule;
  5476. end;