Movatterモバイル変換
[0]ホーム
moduleFractal.RUFF.Mandelbrot.Address(Angle,double,wrap,prettyAngle,prettyAngles,Knead(..),kneadChar,Kneading(..),prettyKneading,kneading,period,unwrap,associated,upper,lower,InternalAddress(..),prettyInternalAddress,internalAddress,internalFromList,internalToList,AngledInternalAddress(..),prettyAngledInternalAddress,angledInternalAddress,angledFromList,angledToList,externalAngles,stripAngles,splitAddress,joinAddress,addressPeriod,parseAngle,parseAngles,parseKnead,parseKneading,parseInternalAddress,parseAngledInternalAddress)whereimportData.Data(Data())importData.Typeable(Typeable())importControl.Monad(guard)importControl.Monad.Identity(Identity())importData.Char(digitToInt)importData.Bits(testBit)importData.List(genericDrop,genericIndex,genericLength,genericReplicate,genericSplitAt,genericTake,foldl')importData.Maybe(isJust,listToMaybe)importData.Ratio((%),numerator,denominator)importText.Parsec(ParsecT(),choice,digit,eof,many,many1,runP,sepEndBy,string,try)typeAngle=RationalprettyAngle::Angle->StringprettyAnglea=show(numeratora)++" / "++show(denominatora)prettyAngles::[Angle]->StringprettyAngles[]=""prettyAngles[a]=show(numeratora)++"/"++show(denominatora)prettyAngles(a:as)=show(numeratora)++"/"++show(denominatora)++" "++prettyAnglesaswrap::Angle->Anglewrapa|f<0=1+f|otherwise=fwhere(_,f)=properFractiona::(Integer,Angle)double::Angle->Angledoublea=wrap(2*a)typeBinAngle=([Bool],[Bool])unbinary::BinAngle->Angleunbinary(pre,per)|n==0=bitspre%(2^m)|otherwise=(bitspre%(2^m))+(bitsper%(2^m*(2^n1)))wherem=lengthpren=lengthperbits::[Bool]->Integerbits=foldl'(\ab->2*a+ifbthen1else0)0binary::Angle->BinAnglebinarya|a==0=([],[])|even(denominatora)=let(pre,per)=binary(doublea)b=a>=1/2in(b:pre,per)|otherwise=let(t,p)=head.dropWhile((1/=).denominator.fst).map(\q->(a*(2^q1),q))$[(1::Int)..]s=numeratortn=fromIntegralpper=[s`testBit`i|i<-[n1,n2..0]]in([],per)btune::BinAngle->(BinAngle,BinAngle)->BinAnglebtune(tpre,tper)(([],per0),([],per1))=(concatMapftpre,concatMapftper)wherefFalse=per0fTrue=per1btune__=error"btune: can't handle pre-periods"tune::Angle->(Angle,Angle)->Angletunet(t0,t1)=unbinary$btune(binaryt)(binaryt0,binaryt1)dataKnead=Zero|One|Starderiving(Read,Show,Eq,Ord,Enum,Bounded,Data,Typeable)kneadChar::Knead->CharkneadCharZero='0'kneadCharOne='1'kneadCharStar='*'dataKneading=Aperiodic[Knead]|PrePeriodic[Knead][Knead]|StarPeriodic[Knead]|Periodic[Knead]deriving(Read,Show,Eq,Ord,Data,Typeable)prettyKneading::Kneading->StringprettyKneading(Aperiodicks)=mapkneadChar(take17ks)++"..."prettyKneading(PrePeriodicusvs)=mapkneadCharus++"("++mapkneadCharvs++")"prettyKneading(StarPeriodicvs)="("++mapkneadCharvs++")"prettyKneading(Periodicvs)="("++mapkneadCharvs++")"kneading::Angle->Kneadingkneadinga0'|a0==0=StarPeriodic[Star]|otherwise=fstkneadswherea0=wrapa0'lo=a0/2hi=(a0+1)/2kneads=kneading'1(doublea0)ks=(a0,One):sndkneadskneading'::Integer->Angle->(Kneading,[(Angle,Knead)])kneading'na|isJusti=caseiofJust0->caselastqsofStar->(StarPeriodicqs,[])_->(Periodicqs,[])Justj->let(p,q)=genericSplitAtjqsin(PrePeriodicpq,[])_->error"Fractal.Mandelbrot.Address.kneading (isJust -> Nothing?)"|a==lo=((a,Star):)`mapP`k|a==hi=((a,Star):)`mapP`k|lo<a&&a<hi=((a,One):)`mapP`k|hi<a||a<lo=((a,Zero):)`mapP`k|otherwise=error"Fractal.Mandelbrot.Address.kneading (unmatched?)"wherek=kneading'(n+1)(doublea)ps=genericTakenksqs=mapsndpsi=fmapfst.listToMaybe.filter((a==).fst.snd).zip[(0::Integer)..]$psmapPf~(x,y)=(x,fy)period::Kneading->MaybeIntegerperiod(StarPeriodick)=Just(genericLengthk)period(Periodick)=Just(genericLengthk)period_=Nothingrho::Kneading->Integer->Integerrhovr|r>=1&&fmap(r`mod`)(periodv)/=Just0=((1+r)+).genericLength.takeWhileid.zipWith(==)vs.genericDropr$vs|otherwise=rhov(r+1)wherevs=unwrapvunwrap::Kneading->[Knead]unwrap(Aperiodicvs)=vsunwrap(PrePeriodicusvs)=us++cyclevsunwrap(StarPeriodicvs)=cyclevsunwrap(Periodicvs)=cyclevsorbit::(a->a)->a->[a]orbit=iteratedataInternalAddress=InternalAddress[Integer]deriving(Read,Show,Eq,Ord,Data,Typeable)prettyInternalAddress::InternalAddress->StringprettyInternalAddress(InternalAddress[])=error"Fractal.Mandelbrot.Address.InternalAddress.pretty"prettyInternalAddress(InternalAddress[x])=showxprettyInternalAddress(InternalAddress(x:ys))=showx++" "++prettyInternalAddress(InternalAddressys)internalFromList::[Integer]->MaybeInternalAddressinternalFromListx0s@(1:_)=InternalAddress`fmap`fromList'0x0swherefromList'n[x]|x>n=Just[x]fromList'n(x:xs)|x>n=(x:)`fmap`fromList'xxsfromList'__=NothinginternalFromList_=NothinginternalToList::InternalAddress->[Integer]internalToList(InternalAddressxs)=xsinternalAddress::Kneading->MaybeInternalAddressinternalAddress(StarPeriodic[Star])=Just(InternalAddress[1])internalAddress(StarPeriodicv@(One:_))=Just.InternalAddress.address'per(genericLengthv)$vinternalAddress(Periodicv@(One:_))=Just.InternalAddress.address'per(genericLengthv)$vinternalAddressk@(Aperiodic(One:_))=Just.InternalAddress.address'inf.unwrap$kinternalAddress_=Nothingaddress'inf::[Knead]->[Integer]address'infv=address'vaddress'per::Integer->[Knead]->[Integer]address'perpv=takeWhile(<=p)$address'vaddress'::[Knead]->[Integer]address'v=address''1[One]whereaddress''skvk=sk:address''sk'vk'wheresk'=(1+).genericLength.takeWhileid.zipWith(==)v.cycle$vkvk'=genericTakesk'(cyclev)associated::Kneading->Maybe(Kneading,Kneading)associated(StarPeriodick)=Just(Periodica,Periodicabar)wheren=genericLengthkdivisors=[m|m<-[1..n],n`mod`m==0]abar=head.filter(and.zipWith(==)a'.cycle).map(`genericTake`a')$divisors(a,a')=if((n`elem`).internalToList)`fmap`internalAddress(Periodica1)==JustTruethen(a1,a2)else(a2,a1)a1=map(\s->casesofStar->Zero;t->t)ka2=map(\s->casesofStar->One;t->t)kassociated_=Nothingupper::Kneading->MaybeKneadingupper=fmapfst.associatedlower::Kneading->MaybeKneadinglower=fmapsnd.associateddataAngledInternalAddress=UnangledInteger|AngledIntegerAngleAngledInternalAddressderiving(Read,Show,Eq,Ord,Data,Typeable)prettyAngledInternalAddress::AngledInternalAddress->StringprettyAngledInternalAddress(Unangledn)=shownprettyAngledInternalAddress(Anglednra)|r/=1/2=shown++" "++show(numeratorr)++"/"++show(denominatorr)++" "++prettyAngledInternalAddressa|otherwise=shown++" "++prettyAngledInternalAddressaangledFromList::[(Integer,MaybeAngle)]->MaybeAngledInternalAddressangledFromList=fromList'0wherefromList'x[(n,Nothing)]|n>x=Just(Unangledn)fromList'x((n,Justr):xs)|n>x&&0<r&&r<1=Anglednr`fmap`fromList'nxsfromList'__=NothingunsafeAngledFromList::[(Integer,MaybeAngle)]->AngledInternalAddressunsafeAngledFromList=fromList'0wherefromList'x[(n,Nothing)]|n>x=UnanglednfromList'x((n,Justr):xs)|n>x&&0<r&&r<1=Anglednr(fromList'nxs)fromList'__=error"Fractal.Mandelbrot.Address.unsafeAngledFromList"angledToList::AngledInternalAddress->[(Integer,MaybeAngle)]angledToList(Unangledn)=[(n,Nothing)]angledToList(Anglednra)=(n,Justr):angledToListadenominators::InternalAddress->Kneading->[Integer]denominatorsav=denominators'(internalToLista)wheredenominators'(s0:ss@(s1:_))=letrr=rs0s1in(((s1rr)`div`s0)+ifs0`elem`takeWhile(<=s0)(orbitprr)then1else2):denominators'ssdenominators'_=[]rss'=cases'`mod`sof0->st->tp=rhovnumerators::Angle->InternalAddress->[Integer]->[Integer]numeratorsraqs=zipWithnum(internalToLista)qswherenumsq=genericLength.filter(<=r).map(genericIndexrs)$[0..q2]wherers=iterate(foldr(.)id.genericReplicates$double)rangledInternalAddress::Angle->MaybeAngledInternalAddressangledInternalAddressr0=doletr=wrapr0k=kneadingri<-internalAddresskletd=denominatorsikn=numeratorsridreturn.unsafeAngledFromList.zip(internalToListi).(++[Nothing]).mapJust.zipWith(%)n$dsplitAddress::AngledInternalAddress->(AngledInternalAddress,[Angle])splitAddressa=let(ps0,rs0)=unzip$angledToListaps1=reverseps0rs1=reverse(Nothing:initrs0)prs1=zipps1rs1f((p,Justr):qrs@((q,_):_))acc|p==denominatorr*q=fqrs(r:acc)fprsacc=gprsaccgprsacc=let(ps2,rs2)=unzipprsps3=reverseps2rs3=reverse(Nothing:initrs2)prs3=zipps3rs3aa=unsafeAngledFromListprs3in(aa,acc)infprs1[]joinAddress::AngledInternalAddress->[Angle]->AngledInternalAddressjoinAddress(Unangledp)[]=UnangledpjoinAddress(Unangledp)(r:rs)=Angledpr(joinAddress(Unangled$p*denominatorr)rs)joinAddress(Angledpra)rs=Angledpr(joinAddressars)addressPeriod::AngledInternalAddress->IntegeraddressPeriod(Unangledp)=paddressPeriod(Angled__a)=addressPeriodastripAngles::AngledInternalAddress->InternalAddressstripAngles=InternalAddress.mapfst.angledToListexternalAngles::AngledInternalAddress->Maybe(Rational,Rational)externalAngles=externalAngles'1(0,1)externalAngles'::Integer->(Rational,Rational)->AngledInternalAddress->Maybe(Rational,Rational)externalAngles'p0lohia0@(Unangledp)|p0/=p=casewakeeslohipof[lh]->externalAngles'plha0_->Nothing|otherwise=JustlohiexternalAngles'p0lohia0@(Angledpra)|p0/=p=casewakeeslohipof[lh]->externalAngles'plha0_->Nothing|otherwise=doletnum=numeratorrden=denominatorrws=wakees(0,1)dennums=[num'|num'<-[1..den1],letr'=num'%den,denominatorr'==den]nws,nnums::Integernws=genericLengthwsnnums=genericLengthnumsguard(nws==nnums)i<-genericElemIndexnumnums(l,h)<-safeGenericIndexws(i::Integer)externalAngles'(p*den)(ifp>1then(tunellohi,tunehlohi)else(l,h))awakees::(Rational,Rational)->Integer->[(Rational,Rational)]wakees(lo,hi)q=letgaps(l,h)n|n==0=[(l,h)]|n>0=letgs=gaps(l,h)(n1)cs=candidatesngsinaccumulatecsgs|otherwise=error"Fractal.Mandelbrot.Address.gaps !(n >= 0)"candidatesngs=letden=2^n1in[r|(l,h)<-gs,num<-[ceiling(l*fromIntegerden)..floor(h*fromIntegerden)],letr=num%den,l<r,r<h,period(kneadingr)==Justn]accumulate[]ws=wsaccumulate(l:h:lhs)ws=let(ls,ms@((ml,_):_))=break(l`inside`)ws(_s,(_,rh):rs)=break(h`inside`)msinls++[(ml,l)]++accumulatelhs((h,rh):rs)accumulate__=error"Fractal.Mandelbrot.Address.gaps !even"insidex(l,h)=l<x&&x<hinchunk2.candidatesq.gaps(lo,hi)$(q1)chunk2::[t]->[(t,t)]chunk2[]=[]chunk2(x:y:zs)=(x,y):chunk2zschunk2_=error"Fractal.Mandelbrot.Address.chunk2 !even"genericElemIndex::(Eqa,Integralb)=>a->[a]->MaybebgenericElemIndex_[]=NothinggenericElemIndexe(f:fs)|e==f=Just0|otherwise=(1+)`fmap`genericElemIndexefssafeGenericIndex::Integralb=>[a]->b->MaybeasafeGenericIndex[]_=NothingsafeGenericIndex(x:xs)i|i<0=Nothing|i>0=safeGenericIndexxs(i1)|otherwise=JustxparseAngle::String->MaybeAngleparseAngles=caserunPpFraction()""sofLeft_->NothingRightf->Just(unFractionf)parseAngles::String->Maybe[Angle]parseAngless=caserunP(manypFraction)()""sofLeft_->NothingRightfs->Just(mapunFractionfs)parseKnead::String->MaybeKneadparseKneads=caserunPpKnead()""sofLeft_->NothingRightk->JustkparseKneading::String->MaybeKneadingparseKneadings=caserunPpKneading()""sofLeft_->NothingRightks->JustksparseInternalAddress::String->MaybeInternalAddressparseInternalAddresss=caserunP(manypNumber)()""sofLeft_->NothingRightns->internalFromList(mapunNumberns)parseAngledInternalAddress::String->MaybeAngledInternalAddressparseAngledInternalAddresss=caserunPparser()""sofLeft_->NothingRighta->JustadataToken=NumberInteger|FractionIntegerIntegerunFraction::Token->AngleunFraction(Fractiontb)=t%bunFraction_=error"Fractal.Mandelbrot.Address.unFraction"unNumber::Token->IntegerunNumber(Numbern)=nunNumber_=error"Fractal.Mandelbrot.Address.unNumber"typeParset=ParsecTString()Identitytparser::ParseAngledInternalAddressparser=dots<-pTokensaccum1tswhereaccump[]=return$Unangledpaccum_[Numbern]=return$Unanglednaccum_(Numbern:ts@(Number_:_))=doa<-accumntsreturn$Angledn(1%2)aaccum_(Numbern:Fractiontb:ts)=doa<-accum(n*b)tsreturn$Angledn(t%b)aaccump(Fractiontb:ts)=doa<-accum(p*b)tsreturn$Angledp(t%b)apTokens::Parse[Token]pTokens=do_<-pOptionalSpacets<-pToken`sepEndBy`pSpaceeofreturntspToken::ParseTokenpToken=choice[trypFraction,pNumber]pFraction::ParseTokenpFraction=doNumbertop<-pNumber_<-pOptionalSpace_<-string"/"_<-pOptionalSpaceNumberbottom<-pNumberguard$top<bottomreturn$FractiontopbottompNumber::ParseTokenpNumber=don<-foldl(\xy->10*x+y)0`fmap`map(toInteger.digitToInt)`fmap`many1digitguard$0<nreturn$NumbernpSpace::Parse[String]pSpace=many1(string" ")pOptionalSpace::Parse[String]pOptionalSpace=many(string" ")pKnead::ParseKneadpKnead=choice[string"0">>returnZero,string"1">>returnOne,string"*">>returnStar]pKneading::ParseKneadingpKneading=dopre<-manypKnead_<-string"("per<-many1pKnead_<-string")"return$case(nullpre,lastper)of(False,_)->PrePeriodicpreper(True,Star)->StarPeriodicper_->Periodicper
[8]ページ先頭