|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316 |
- /* optimal cube solver by michael reid reid@math.ucf.edu */
- /* version 2.1 june 3, 2004 */
- /* symmetry mechanism added */
- /* malloc.h removed, long string fixed */
-
-
- #define USE_METRIC QUARTER_TURN_METRIC
- #define SEARCH_LIMIT 0
- #define USE_SYMMETRY 1
- #define ONE_SOLUTION_ONLY 0
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <setjmp.h>
- #include <signal.h>
-
-
- #define QUARTER_TURN_METRIC 0
- #define FACE_TURN_METRIC 1
-
- #define N_SYM 16
- #define N_TWIST 18
- #define N_CORNER 2187
- #define N_ELOC 495
- #define N_ELOC_CONV 4096
- #define N_EFLIP 2048
- #define N_FULLEDGE (N_ELOC * N_EFLIP)
- #define N_EDGEQUOT 64430
- #define N_CORNERPERM 40320
- #define N_SLICEEDGE 11880
-
- #define N_CUBESYM 48
- #define N_SYMSUBGRP 98
- #define SUBGRP_TRIVIAL 97
-
- #define N_DIST_CHARS ((N_EDGEQUOT * N_CORNER) / 2)
- #define BACKWARDS_SWITCH_POINT ((2 * N_EDGEQUOT * N_CORNER) / 5)
-
- #define CORNER_START 0
- #define EDGE_START 64244
- #define CORNERPERM_START 0
- #define UD_SLICEEDGE_START 494
- #define RL_SLICEEDGE_START 54
- #define FB_SLICEEDGE_START 209
-
- #define MAX_PERM_N 12
- #define MAX_CHECK_PERM_N 24
-
- #define MAX_TWISTS 43
-
- #define TWIST_F 0
- #define TWIST_F2 1
- #define TWIST_F3 2
- #define TWIST_R 3
- #define TWIST_R2 4
- #define TWIST_R3 5
- #define TWIST_U 6
- #define TWIST_U2 7
- #define TWIST_U3 8
- #define TWIST_B 9
- #define TWIST_B2 10
- #define TWIST_B3 11
- #define TWIST_L 12
- #define TWIST_L2 13
- #define TWIST_L3 14
- #define TWIST_D 15
- #define TWIST_D2 16
- #define TWIST_D3 17
-
- #define CORNER_UFR 0
- #define CORNER_URB 1
- #define CORNER_UBL 2
- #define CORNER_ULF 3
- #define CORNER_DRF 4
- #define CORNER_DFL 5
- #define CORNER_DLB 6
- #define CORNER_DBR 7
-
- #define CORNER_FRU 8
- #define CORNER_RBU 9
- #define CORNER_BLU 10
- #define CORNER_LFU 11
- #define CORNER_RFD 12
- #define CORNER_FLD 13
- #define CORNER_LBD 14
- #define CORNER_BRD 15
-
- #define CORNER_RUF 16
- #define CORNER_BUR 17
- #define CORNER_LUB 18
- #define CORNER_FUL 19
- #define CORNER_FDR 20
- #define CORNER_LDF 21
- #define CORNER_BDL 22
- #define CORNER_RDB 23
-
-
- #define EDGE_UF 0
- #define EDGE_UR 1
- #define EDGE_UB 2
- #define EDGE_UL 3
- #define EDGE_DF 4
- #define EDGE_DR 5
- #define EDGE_DB 6
- #define EDGE_DL 7
- #define EDGE_FR 8
- #define EDGE_FL 9
- #define EDGE_BR 10
- #define EDGE_BL 11
-
- #define EDGE_FU 12
- #define EDGE_RU 13
- #define EDGE_BU 14
- #define EDGE_LU 15
- #define EDGE_FD 16
- #define EDGE_RD 17
- #define EDGE_BD 18
- #define EDGE_LD 19
- #define EDGE_RF 20
- #define EDGE_LF 21
- #define EDGE_RB 22
- #define EDGE_LB 23
-
-
- #define FACE_F 0
- #define FACE_R 1
- #define FACE_U 2
- #define FACE_B 3
- #define FACE_L 4
- #define FACE_D 5
-
-
- #define N_FOLLOW 873
-
- #define FOLLOW_INVALID 0
-
- #define N_SYLLABLE 32
-
- #define SYLLABLE_INVALID 0
- #define SYLLABLE_NONE 1
- #define SYLLABLE_F 2
- #define SYLLABLE_F2 3
- #define SYLLABLE_F3 4
- #define SYLLABLE_R 5
- #define SYLLABLE_R2 6
- #define SYLLABLE_R3 7
- #define SYLLABLE_U 8
- #define SYLLABLE_U2 9
- #define SYLLABLE_U3 10
- #define SYLLABLE_B 11
- #define SYLLABLE_B2 12
- #define SYLLABLE_B3 13
- #define SYLLABLE_L 14
- #define SYLLABLE_L2 15
- #define SYLLABLE_L3 16
- #define SYLLABLE_D 17
- #define SYLLABLE_D2 18
- #define SYLLABLE_D3 19
- #define SYLLABLE_FB 20
- #define SYLLABLE_FB2 21
- #define SYLLABLE_FB3 22
- #define SYLLABLE_F2B2 23
- #define SYLLABLE_RL 24
- #define SYLLABLE_RL2 25
- #define SYLLABLE_RL3 26
- #define SYLLABLE_R2L2 27
- #define SYLLABLE_UD 28
- #define SYLLABLE_UD2 29
- #define SYLLABLE_UD3 30
- #define SYLLABLE_U2D2 31
-
-
-
- #define DIST(c, e) (((e) & 0x1) ? (((int)distance[c][(e) >> 1]) >> 4) \
- : (((int)distance[c][(e) >> 1]) & 0xF))
-
-
- typedef struct cube
- {
- int edges[24];
- int corners[24];
- }
- Cube;
-
-
- typedef struct coset_coord
- {
- int corner_state;
- int edge_state;
- int sym_state;
- }
- Coset_coord;
-
-
- typedef struct full_cube
- {
- Cube cubies;
- int cornerperm;
- int ud_sliceedge;
- int rl_sliceedge;
- int fb_sliceedge;
- Coset_coord ud;
- Coset_coord rl;
- Coset_coord fb;
- int parity;
- int sym_subgrp;
- }
- Full_cube;
-
-
- typedef struct search_data
- {
- int depth;
- int found;
- int found_quot;
- int *multiplicities;
- int *stabilizers;
- }
- Search_data;
-
-
- typedef struct search_node
- {
- int remain_depth;
- int twist;
- int follow_type;
- Coset_coord ud;
- Coset_coord rl;
- Coset_coord fb;
- }
- Search_node;
-
-
- typedef struct metric_data
- {
- int metric;
- char metric_char;
- int twist_length[N_TWIST];
- int increment;
- }
- Metric_data;
-
-
- typedef struct options
- {
- int use_symmetry;
- int search_limit;
- int one_solution_only;
- }
- Options;
-
-
- typedef struct subgroup_list
- {
- int n_subgroups;
- int (*subgroups)[N_CUBESYM];
- }
- Subgroup_list;
-
-
-
- static unsigned char *sym_x_invsym_to_sym[N_SYM];
-
- static unsigned char *invsym_on_twist_ud[N_SYM];
- static unsigned char *invsym_on_twist_rl[N_SYM];
- static unsigned char *invsym_on_twist_fb[N_SYM];
-
- static unsigned short *twist_on_corner[N_TWIST];
- static unsigned short *sym_on_corner[N_SYM];
-
- static unsigned short *fulledge_to_edge;
- static unsigned char *fulledge_to_sym;
-
- static unsigned short *twist_on_edge[N_TWIST];
- static unsigned char *twist_x_edge_to_sym[N_TWIST];
-
- static unsigned short *twist_on_cornerperm[N_TWIST];
- static unsigned short *twist_on_sliceedge[N_TWIST];
-
- static unsigned short *twist_on_follow[N_TWIST];
-
- static unsigned char *distance[N_CORNER];
-
- static char *edge_cubie_str[] = {"UF", "UR", "UB", "UL",
- "DF", "DR", "DB", "DL",
- "FR", "FL", "BR", "BL",
- "FU", "RU", "BU", "LU",
- "FD", "RD", "BD", "LD",
- "RF", "LF", "RB", "LB"};
-
- static char *corner_cubie_str[] = {"UFR", "URB", "UBL", "ULF",
- "DRF", "DFL", "DLB", "DBR",
- "FRU", "RBU", "BLU", "LFU",
- "RFD", "FLD", "LBD", "BRD",
- "RUF", "BUR", "LUB", "FUL",
- "FDR", "LDF", "BDL", "RDB"};
-
- static Metric_data *p_current_metric;
- static Options *p_current_options;
-
- static unsigned int n_nodes;
- static unsigned int n_tests;
- static int sol_found;
-
- static sigjmp_buf jump_env;
-
-
- /* ========================================================================= */
- void exit_w_error_message(char *msg)
- /* ------------------------------------------------------------------------- */
-
- {
- printf("\n%s\n", msg);
- exit(EXIT_FAILURE);
-
- return;
- }
-
-
- /* ========================================================================= */
- void user_interrupt(int unused_arg)
- /* ------------------------------------------------------------------------- */
-
- {
- printf("\n-- user interrupt --\n");
- fflush(stdout);
- siglongjmp(jump_env, 1);
-
- return;
- }
-
-
- /* ========================================================================= */
- void perm_n_unpack(int nn, int indx, int array_out[])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii, jj;
-
-
- for (ii = nn - 1; ii >= 0; ii--)
- {
- array_out[ii] = indx % (nn - ii);
- indx /= (nn - ii);
-
- for (jj = ii + 1; jj < nn; jj++)
- if (array_out[jj] >= array_out[ii])
- array_out[jj]++;
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int perm_n_pack(int nn, int array_in[])
- /* ------------------------------------------------------------------------- */
-
- {
- int indx, ii, jj;
-
-
- indx = 0;
-
- for (ii = 0; ii < nn; ii++)
- {
- indx *= (nn - ii);
-
- for (jj = ii + 1; jj < nn; jj++)
- if (array_in[jj] < array_in[ii])
- indx++;
- }
-
- return indx;
- }
-
-
- /* ========================================================================= */
- int perm_n_check(int nn, int array_in[])
- /* ------------------------------------------------------------------------- */
-
- {
- int count[MAX_CHECK_PERM_N], ii;
-
-
- for (ii = 0; ii < nn; ii++)
- count[ii] = 0;
-
- for (ii = 0; ii < nn; ii++)
- {
- if ((array_in[ii] < 0) || (array_in[ii] >= nn))
- return 1;
-
- count[array_in[ii]]++;
- }
-
- for (ii = 0; ii < nn; ii++)
- if (count[ii] != 1)
- return 1;
-
- return 0;
- }
-
-
- /* ========================================================================= */
- int perm_n_parity(int nn, int array_in[])
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_array[MAX_CHECK_PERM_N];
- int ii, jj, n_cycles;
-
-
- for (ii = 0; ii < nn; ii++)
- temp_array[ii] = 0;
-
- n_cycles = 0;
-
- for (ii = 0; ii < nn; ii++)
- if (temp_array[ii] == 0)
- {
- n_cycles++;
- jj = ii;
- while (temp_array[jj] == 0)
- {
- temp_array[jj] = 1;
- jj = array_in[jj];
- }
- }
-
- return (n_cycles + nn) % 2;
- }
-
-
- /* ========================================================================= */
- void perm_n_init(int nn, int array_out[])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 0; ii < nn; ii++)
- array_out[ii] = ii;
-
- return;
- }
-
-
- /* ========================================================================= */
- void perm_n_compose(int nn, int perm0_in[], int perm1_in[],
- int perm_out[])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 0; ii < nn; ii++)
- perm_out[ii] = perm0_in[perm1_in[ii]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void perm_n_conjugate(int nn, int arr_in[], int conjugator[],
- int array_out[])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 0; ii < nn; ii++)
- array_out[conjugator[ii]] = conjugator[arr_in[ii]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void two_cycle(int array[], int ind0, int ind1)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void three_cycle(int array[], int ind0, int ind1, int ind2)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = array[ind2];
- array[ind2] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void four_cycle(int array[], int ind0, int ind1, int ind2, int ind3)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = array[ind2];
- array[ind2] = array[ind3];
- array[ind3] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void print_cube(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
- edge_cubie_str[p_cube->edges[0]], edge_cubie_str[p_cube->edges[1]],
- edge_cubie_str[p_cube->edges[2]], edge_cubie_str[p_cube->edges[3]],
- edge_cubie_str[p_cube->edges[4]], edge_cubie_str[p_cube->edges[5]],
- edge_cubie_str[p_cube->edges[6]], edge_cubie_str[p_cube->edges[7]],
- edge_cubie_str[p_cube->edges[8]], edge_cubie_str[p_cube->edges[9]],
- edge_cubie_str[p_cube->edges[10]], edge_cubie_str[p_cube->edges[11]],
- corner_cubie_str[p_cube->corners[0]], corner_cubie_str[p_cube->corners[1]],
- corner_cubie_str[p_cube->corners[2]], corner_cubie_str[p_cube->corners[3]],
- corner_cubie_str[p_cube->corners[4]], corner_cubie_str[p_cube->corners[5]],
- corner_cubie_str[p_cube->corners[6]], corner_cubie_str[p_cube->corners[7]]);
-
- return;
- }
-
-
- /* ========================================================================= */
- void cube_init(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- perm_n_init(24, p_cube->edges);
- perm_n_init(24, p_cube->corners);
-
- return;
- }
-
-
- /* ========================================================================= */
- int cube_compare(Cube *cube0, Cube *cube1)
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
- for (ii = 0; ii < 24; ii++)
- {
- if (cube0->edges[ii] < cube1->edges[ii])
- return -1;
- else if (cube0->edges[ii] > cube1->edges[ii])
- return 1;
- }
-
- for (ii = 0; ii < 24; ii++)
- {
- if (cube0->corners[ii] < cube1->corners[ii])
- return -1;
- else if (cube0->corners[ii] > cube1->corners[ii])
- return 1;
- }
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void cube_compose(Cube *in_cube0, Cube *in_cube1, Cube *out_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- perm_n_compose(24, in_cube0->edges, in_cube1->edges, out_cube->edges);
- perm_n_compose(24, in_cube0->corners, in_cube1->corners, out_cube->corners);
-
- return;
- }
-
-
- /* ========================================================================= */
- void cube_conjugate(Cube *p_cube_in, Cube *p_conjugator,
- Cube *p_cube_out)
- /* ------------------------------------------------------------------------- */
-
- {
- perm_n_conjugate(24, p_cube_in->edges, p_conjugator->edges, p_cube_out->edges);
- perm_n_conjugate(24, p_cube_in->corners, p_conjugator->corners,
- p_cube_out->corners);
-
- return;
- }
-
-
- /* ========================================================================= */
- int cube_is_solved(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- Cube temp_cube;
-
-
- cube_init(&temp_cube);
-
- return (cube_compare(p_cube, &temp_cube) == 0);
- }
-
-
- /* ========================================================================= */
- int metric_q_length(int twist)
- /* ------------------------------------------------------------------------- */
-
- {
- if ((twist == TWIST_F) || (twist == TWIST_F3) ||
- (twist == TWIST_R) || (twist == TWIST_R3) ||
- (twist == TWIST_U) || (twist == TWIST_U3) ||
- (twist == TWIST_B) || (twist == TWIST_B3) ||
- (twist == TWIST_L) || (twist == TWIST_L3) ||
- (twist == TWIST_D) || (twist == TWIST_D3))
- return 1;
- else if ((twist == TWIST_F2) || (twist == TWIST_R2) || (twist == TWIST_U2) ||
- (twist == TWIST_B2) || (twist == TWIST_L2) || (twist == TWIST_D2))
- return 2;
- else
- exit_w_error_message("metric_q_length : invalid twist");
-
- return 0;
- }
-
-
- /* ========================================================================= */
- int metric_f_length(int twist)
- /* ------------------------------------------------------------------------- */
-
- {
- if ((twist == TWIST_F) || (twist == TWIST_F2) || (twist == TWIST_F3) ||
- (twist == TWIST_R) || (twist == TWIST_R2) || (twist == TWIST_R3) ||
- (twist == TWIST_U) || (twist == TWIST_U2) || (twist == TWIST_U3) ||
- (twist == TWIST_B) || (twist == TWIST_B2) || (twist == TWIST_B3) ||
- (twist == TWIST_L) || (twist == TWIST_L2) || (twist == TWIST_L3) ||
- (twist == TWIST_D) || (twist == TWIST_D2) || (twist == TWIST_D3))
- return 1;
- else
- exit_w_error_message("metric_f_length : invalid twist");
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void calc_metric_q_length(int lengths[N_TWIST])
- /* ------------------------------------------------------------------------- */
-
- {
- int twist;
-
-
- for (twist = 0; twist < N_TWIST; twist++)
- lengths[twist] = metric_q_length(twist);
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_metric_f_length(int lengths[N_TWIST])
- /* ------------------------------------------------------------------------- */
-
- {
- int twist;
-
-
- for (twist = 0; twist < N_TWIST; twist++)
- lengths[twist] = metric_f_length(twist);
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_metric(Metric_data *p_metric_data, int use_metric)
- /* ------------------------------------------------------------------------- */
-
- {
- if ((use_metric != QUARTER_TURN_METRIC) && (use_metric != FACE_TURN_METRIC))
- exit_w_error_message("init_metric : unknown metric");
-
- p_metric_data->metric = use_metric;
-
- if (p_metric_data->metric == QUARTER_TURN_METRIC)
- {
- printf("using quarter turn metric\n");
- p_metric_data->metric_char = 'q';
- calc_metric_q_length(p_metric_data->twist_length);
- p_metric_data->increment = 2;
- }
- else
- {
- printf("using face turn metric\n");
- p_metric_data->metric_char = 'f';
- calc_metric_f_length(p_metric_data->twist_length);
- p_metric_data->increment = 1;
- }
-
- p_current_metric = p_metric_data;
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_options(Metric_data *p_metric_data, Options *p_user_options)
- /* ------------------------------------------------------------------------- */
-
- {
- init_metric(p_metric_data, USE_METRIC);
-
- p_user_options->search_limit = SEARCH_LIMIT;
- if (p_user_options->search_limit <= 0)
- printf("no search limit\n");
- else
- printf("search limit: %d%c\n", p_user_options->search_limit,
- p_current_metric->metric_char);
-
- p_user_options->use_symmetry = USE_SYMMETRY;
- if (p_user_options->use_symmetry)
- printf("using symmetry reductions\n");
- else
- printf("not using symmetry reductions\n");
-
- p_user_options->one_solution_only = ONE_SOLUTION_ONLY;
- if (p_user_options->one_solution_only)
- printf("only finding one solution\n");
- else
- printf("finding all solutions\n");
-
- printf("\n");
- p_current_options = p_user_options;
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_group_table(int group_table[N_CUBESYM][N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- {
- int sym_array[N_CUBESYM][6];
- int sym_pack[N_CUBESYM];
- int temp_array[6];
- int ii, jj, kk, pack;
-
-
- perm_n_init(6, sym_array[0]);
- perm_n_init(6, sym_array[1]);
-
- four_cycle(sym_array[1], FACE_F, FACE_L, FACE_B, FACE_R);
-
- for (ii = 2; ii < 4; ii++)
- perm_n_compose(6, sym_array[1], sym_array[ii - 1], sym_array[ii]);
-
- perm_n_init(6, sym_array[4]);
-
- two_cycle(sym_array[4], FACE_U, FACE_D);
- two_cycle(sym_array[4], FACE_R, FACE_L);
-
- for (ii = 5; ii < 8; ii++)
- perm_n_compose(6, sym_array[4], sym_array[ii - 4], sym_array[ii]);
-
- perm_n_init(6, sym_array[8]);
-
- two_cycle(sym_array[8], FACE_U, FACE_D);
-
- for (ii = 9; ii < 16; ii++)
- perm_n_compose(6, sym_array[8], sym_array[ii - 8], sym_array[ii]);
-
- perm_n_init(6, sym_array[16]);
-
- three_cycle(sym_array[16], FACE_U, FACE_F, FACE_R);
- three_cycle(sym_array[16], FACE_D, FACE_B, FACE_L);
-
- for (ii = 17; ii < 48; ii++)
- perm_n_compose(6, sym_array[16], sym_array[ii - 16], sym_array[ii]);
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- sym_pack[ii] = perm_n_pack(6, sym_array[ii]);
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- for (jj = 0; jj < N_CUBESYM; jj++)
- {
- perm_n_compose(6, sym_array[ii], sym_array[jj], temp_array);
- pack = perm_n_pack(6, temp_array);
-
- for (kk = 0; kk < N_CUBESYM; kk++)
- if (sym_pack[kk] == pack)
- {
- group_table[ii][jj] = kk;
- break;
- }
-
- if (kk == N_CUBESYM)
- exit_w_error_message("calc_group_table : product not found");
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_sym_x_invsym_to_sym(void)
- /* ------------------------------------------------------------------------- */
-
- {
- unsigned char (*mem_ptr)[N_SYM];
- int group_table[N_CUBESYM][N_CUBESYM];
- int group_inverse[N_CUBESYM];
- int ii, jj;
-
-
- /* initialize global array sym_x_invsym_to_sym */
-
- mem_ptr =
- (unsigned char (*)[N_SYM])malloc(sizeof(unsigned char [N_SYM][N_SYM]));
- if (mem_ptr == NULL)
- exit_w_error_message("init_sym_x_invsym_to_sym : couldn't get memory");
-
- for (ii = 0; ii < N_SYM; ii++)
- sym_x_invsym_to_sym[ii] = mem_ptr[ii];
-
- calc_group_table(group_table);
-
- for (ii = 0; ii < N_SYM; ii++)
- {
- for (jj = 0; jj < N_SYM; jj++)
- if (group_table[ii][jj] == 0)
- {
- group_inverse[ii] = jj;
- break;
- }
-
- if (jj == N_SYM)
- exit_w_error_message("init_sym_x_invsym_to_sym : inverse not found");
- }
-
- for (ii = 0; ii < N_SYM; ii++)
- for (jj = 0; jj < N_SYM; jj++)
- sym_x_invsym_to_sym[ii][jj] =
- (unsigned char)group_table[ii][group_inverse[jj]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_sym_on_twist(int sym_on_twist[N_CUBESYM][N_TWIST])
- /* ------------------------------------------------------------------------- */
-
- {
- int sym;
-
-
- perm_n_init(N_TWIST, sym_on_twist[0]);
- perm_n_init(N_TWIST, sym_on_twist[1]);
-
- four_cycle(sym_on_twist[1], TWIST_F , TWIST_L , TWIST_B , TWIST_R );
- four_cycle(sym_on_twist[1], TWIST_F2, TWIST_L2, TWIST_B2, TWIST_R2);
- four_cycle(sym_on_twist[1], TWIST_F3, TWIST_L3, TWIST_B3, TWIST_R3);
-
- for (sym = 2; sym < 4; sym++)
- perm_n_compose(N_TWIST, sym_on_twist[1], sym_on_twist[sym - 1],
- sym_on_twist[sym]);
-
- perm_n_init(N_TWIST, sym_on_twist[4]);
-
- two_cycle(sym_on_twist[4], TWIST_R , TWIST_L );
- two_cycle(sym_on_twist[4], TWIST_R2, TWIST_L2);
- two_cycle(sym_on_twist[4], TWIST_R3, TWIST_L3);
- two_cycle(sym_on_twist[4], TWIST_U , TWIST_D );
- two_cycle(sym_on_twist[4], TWIST_U2, TWIST_D2);
- two_cycle(sym_on_twist[4], TWIST_U3, TWIST_D3);
-
- for (sym = 5; sym < 8; sym++)
- perm_n_compose(N_TWIST, sym_on_twist[4], sym_on_twist[sym - 4],
- sym_on_twist[sym]);
-
- perm_n_init(N_TWIST, sym_on_twist[8]);
-
- two_cycle(sym_on_twist[8], TWIST_F, TWIST_F3);
- two_cycle(sym_on_twist[8], TWIST_R, TWIST_R3);
- two_cycle(sym_on_twist[8], TWIST_B, TWIST_B3);
- two_cycle(sym_on_twist[8], TWIST_L, TWIST_L3);
- two_cycle(sym_on_twist[8], TWIST_U , TWIST_D3);
- two_cycle(sym_on_twist[8], TWIST_U2, TWIST_D2);
- two_cycle(sym_on_twist[8], TWIST_U3, TWIST_D );
-
- for (sym = 9; sym < 16; sym++)
- perm_n_compose(N_TWIST, sym_on_twist[8], sym_on_twist[sym - 8],
- sym_on_twist[sym]);
-
- perm_n_init(N_TWIST, sym_on_twist[16]);
-
- three_cycle(sym_on_twist[16], TWIST_F , TWIST_R , TWIST_U );
- three_cycle(sym_on_twist[16], TWIST_F2, TWIST_R2, TWIST_U2);
- three_cycle(sym_on_twist[16], TWIST_F3, TWIST_R3, TWIST_U3);
- three_cycle(sym_on_twist[16], TWIST_B , TWIST_L , TWIST_D );
- three_cycle(sym_on_twist[16], TWIST_B2, TWIST_L2, TWIST_D2);
- three_cycle(sym_on_twist[16], TWIST_B3, TWIST_L3, TWIST_D3);
-
- for (sym = 17; sym < 48; sym++)
- perm_n_compose(N_TWIST, sym_on_twist[16], sym_on_twist[sym - 16],
- sym_on_twist[sym]);
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_invsym_on_twist(void)
- /* ------------------------------------------------------------------------- */
-
- {
- unsigned char (*mem_ptr)[N_SYM][N_TWIST];
- int sym_on_twist[N_CUBESYM][N_TWIST];
- int ud_to_rl[N_TWIST], sym, twist;
-
-
- /* allocate and initialize global arrays */
- /* invsym_on_twist_ud , invsym_on_twist_fb and invsym_on_twist_rl */
-
- mem_ptr = (unsigned char (*)[N_SYM][N_TWIST])
- malloc(sizeof(unsigned char [3][N_SYM][N_TWIST]));
- if (mem_ptr == NULL)
- exit_w_error_message("init_invsym_on_twist : couldn't get memory");
-
- for (sym = 0; sym < N_SYM; sym++)
- {
- invsym_on_twist_ud[sym] = mem_ptr[0][sym];
- invsym_on_twist_rl[sym] = mem_ptr[1][sym];
- invsym_on_twist_fb[sym] = mem_ptr[2][sym];
- }
-
- calc_sym_on_twist(sym_on_twist);
-
- for (sym = 0; sym < N_SYM; sym++)
- for (twist = 0; twist < N_TWIST; twist++)
- invsym_on_twist_ud[sym][twist] =
- (unsigned char)sym_on_twist[(int)sym_x_invsym_to_sym[0][sym]][twist];
-
- perm_n_init(N_TWIST, ud_to_rl);
-
- three_cycle(ud_to_rl, TWIST_F , TWIST_R , TWIST_U );
- three_cycle(ud_to_rl, TWIST_F2, TWIST_R2, TWIST_U2);
- three_cycle(ud_to_rl, TWIST_F3, TWIST_R3, TWIST_U3);
- three_cycle(ud_to_rl, TWIST_B , TWIST_L , TWIST_D );
- three_cycle(ud_to_rl, TWIST_B2, TWIST_L2, TWIST_D2);
- three_cycle(ud_to_rl, TWIST_B3, TWIST_L3, TWIST_D3);
-
- for (sym = 0; sym < N_SYM; sym++)
- for (twist = 0; twist < N_TWIST; twist++)
- invsym_on_twist_rl[sym][twist] =
- invsym_on_twist_ud[sym][ud_to_rl[twist]];
-
- for (sym = 0; sym < N_SYM; sym++)
- for (twist = 0; twist < N_TWIST; twist++)
- invsym_on_twist_fb[sym][twist] =
- invsym_on_twist_rl[sym][ud_to_rl[twist]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void generate_subgroup(int group_table[N_CUBESYM][N_CUBESYM],
- int gen_set[N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- /* gen_set[] is both input and output */
-
- {
- int found, ii, jj;
-
-
- gen_set[0] = 1;
- found = 1;
-
- while (found)
- {
- found = 0;
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- if (gen_set[ii] != 0)
- for (jj = 0; jj < N_CUBESYM; jj++)
- if ((gen_set[jj] != 0) && (gen_set[group_table[ii][jj]] == 0))
- {
- gen_set[group_table[ii][jj]] = 1;
- found = 1;
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_subgroups_recursive(int group_table[N_CUBESYM][N_CUBESYM],
- int contain_list[N_CUBESYM],
- int avoid_list[N_CUBESYM],
- Subgroup_list *p_output)
- /* ------------------------------------------------------------------------- */
-
- {
- int local_contain_list[N_CUBESYM], ii, jj;
-
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- if (contain_list[ii] && avoid_list[ii])
- return;
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- if ((contain_list[ii] == 0) && (avoid_list[ii] == 0))
- break;
-
- if (ii < N_CUBESYM)
- {
- for (jj = 0; jj < N_CUBESYM; jj++)
- local_contain_list[jj] = contain_list[jj];
- local_contain_list[ii] = 1;
- generate_subgroup(group_table, local_contain_list);
- calc_subgroups_recursive(group_table, local_contain_list, avoid_list,
- p_output);
- avoid_list[ii] = 1;
- calc_subgroups_recursive(group_table, contain_list, avoid_list, p_output);
- avoid_list[ii] = 0;
- }
- else
- {
- if (p_output->n_subgroups >= N_SYMSUBGRP)
- exit_w_error_message("calc_subgroups_recursive : too many subgroups");
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- p_output->subgroups[p_output->n_subgroups][ii] = contain_list[ii];
-
- p_output->n_subgroups++;
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_subgroup_list(int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- {
- Subgroup_list output_list;
- int group_table[N_CUBESYM][N_CUBESYM];
- int contain_list[N_CUBESYM];
- int avoid_list[N_CUBESYM];
- int ii;
-
-
- calc_group_table(group_table);
-
- output_list.n_subgroups = 0;
- output_list.subgroups = subgroup_list;
-
- contain_list[0] = 1;
-
- for (ii = 1; ii < N_CUBESYM; ii++)
- contain_list[ii] = 0;
-
- for (ii = 0; ii < N_CUBESYM; ii++)
- avoid_list[ii] = 0;
-
- calc_subgroups_recursive(group_table, contain_list, avoid_list, &output_list);
-
- if (output_list.n_subgroups != N_SYMSUBGRP)
- exit_w_error_message("calc_subgroup_list : wrong number of subgroups");
-
- return;
- }
-
-
- /* ========================================================================= */
- int is_single_twist(int syllable)
- /* ------------------------------------------------------------------------- */
-
- {
- if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
- (syllable == SYLLABLE_F3) ||
- (syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
- (syllable == SYLLABLE_R3) ||
- (syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
- (syllable == SYLLABLE_U3) ||
- (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3))
- return 1;
-
- return 0;
- }
-
-
- /* ========================================================================= */
- int syllable_to_twist(int syllable)
- /* ------------------------------------------------------------------------- */
-
- {
- if (syllable == SYLLABLE_F)
- return TWIST_F;
- else if (syllable == SYLLABLE_F2)
- return TWIST_F2;
- else if (syllable == SYLLABLE_F3)
- return TWIST_F3;
- else if (syllable == SYLLABLE_R)
- return TWIST_R;
- else if (syllable == SYLLABLE_R2)
- return TWIST_R2;
- else if (syllable == SYLLABLE_R3)
- return TWIST_R3;
- else if (syllable == SYLLABLE_U)
- return TWIST_U;
- else if (syllable == SYLLABLE_U2)
- return TWIST_U2;
- else if (syllable == SYLLABLE_U3)
- return TWIST_U3;
- else if (syllable == SYLLABLE_B)
- return TWIST_B;
- else if (syllable == SYLLABLE_B2)
- return TWIST_B2;
- else if (syllable == SYLLABLE_B3)
- return TWIST_B3;
- else if (syllable == SYLLABLE_L)
- return TWIST_L;
- else if (syllable == SYLLABLE_L2)
- return TWIST_L2;
- else if (syllable == SYLLABLE_L3)
- return TWIST_L3;
- else if (syllable == SYLLABLE_D)
- return TWIST_D;
- else if (syllable == SYLLABLE_D2)
- return TWIST_D2;
- else if (syllable == SYLLABLE_D3)
- return TWIST_D3;
- else
- exit_w_error_message("syllable_to_twist : invalid input");
-
- return -1;
- }
-
-
- /* ========================================================================= */
- void syllable_to_two_twists(int syllable, int twists_out[2])
- /* ------------------------------------------------------------------------- */
-
- {
- if (syllable == SYLLABLE_FB)
- {
- twists_out[0] = TWIST_F;
- twists_out[1] = TWIST_B;
- }
- else if (syllable == SYLLABLE_FB2)
- {
- twists_out[0] = TWIST_F;
- twists_out[1] = TWIST_B2;
- }
- else if (syllable == SYLLABLE_FB3)
- {
- twists_out[0] = TWIST_F;
- twists_out[1] = TWIST_B3;
- }
- else if (syllable == SYLLABLE_F2B2)
- {
- twists_out[0] = TWIST_F2;
- twists_out[1] = TWIST_B2;
- }
- else if (syllable == SYLLABLE_RL)
- {
- twists_out[0] = TWIST_R;
- twists_out[1] = TWIST_L;
- }
- else if (syllable == SYLLABLE_RL2)
- {
- twists_out[0] = TWIST_R;
- twists_out[1] = TWIST_L2;
- }
- else if (syllable == SYLLABLE_RL3)
- {
- twists_out[0] = TWIST_R;
- twists_out[1] = TWIST_L3;
- }
- else if (syllable == SYLLABLE_R2L2)
- {
- twists_out[0] = TWIST_R2;
- twists_out[1] = TWIST_L2;
- }
- else if (syllable == SYLLABLE_UD)
- {
- twists_out[0] = TWIST_U;
- twists_out[1] = TWIST_D;
- }
- else if (syllable == SYLLABLE_UD2)
- {
- twists_out[0] = TWIST_U;
- twists_out[1] = TWIST_D2;
- }
- else if (syllable == SYLLABLE_UD3)
- {
- twists_out[0] = TWIST_U;
- twists_out[1] = TWIST_D3;
- }
- else if (syllable == SYLLABLE_U2D2)
- {
- twists_out[0] = TWIST_U2;
- twists_out[1] = TWIST_D2;
- }
- else
- exit_w_error_message("syllable_to_two_twists : invalid input");
-
- return;
- }
-
-
- /* ========================================================================= */
- int twists_in_wrong_order(int twists[2])
- /* ------------------------------------------------------------------------- */
-
- {
- if (((twists[0] == TWIST_B) || (twists[0] == TWIST_B2) ||
- (twists[0] == TWIST_B3)) &&
- ((twists[1] == TWIST_F) || (twists[1] == TWIST_F2) ||
- (twists[1] == TWIST_F3)))
- return 1;
-
- if (((twists[0] == TWIST_L) || (twists[0] == TWIST_L2) ||
- (twists[0] == TWIST_L3)) &&
- ((twists[1] == TWIST_R) || (twists[1] == TWIST_R2) ||
- (twists[1] == TWIST_R3)))
- return 1;
-
- if (((twists[0] == TWIST_D) || (twists[0] == TWIST_D2) ||
- (twists[0] == TWIST_D3)) &&
- ((twists[1] == TWIST_U) || (twists[1] == TWIST_U2) ||
- (twists[1] == TWIST_U3)))
- return 1;
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void clean_up_sequence(int twist_sequence[], int n_twists)
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 1; ii < n_twists; ii++)
- if (twists_in_wrong_order(&twist_sequence[ii - 1]) != 0)
- two_cycle(twist_sequence, ii - 1, ii);
-
- return;
- }
-
-
- /* ========================================================================= */
- int which_subgroup(int subgroup[N_CUBESYM],
- int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- {
- int subgrp, sym;
-
-
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- {
- for (sym = 0; sym < N_CUBESYM; sym++)
- if ((subgroup[sym] == 0) != (subgroup_list[subgrp][sym] == 0))
- break;
-
- if (sym == N_CUBESYM)
- return subgrp;
- }
-
- return -1;
- }
-
-
- /* ========================================================================= */
- void calc_syllable_on_sym(int subgroup_list[N_SYMSUBGRP][N_CUBESYM],
- int sym_on_twist[N_CUBESYM][N_TWIST],
- int syllable_on_sym[N_SYLLABLE][N_SYMSUBGRP])
- /* ------------------------------------------------------------------------- */
-
- {
- int subgroup[N_CUBESYM], temp_subgroup[N_CUBESYM];
- int twist_arr[2], temp_arr[2];
- int syllable, sym, subgrp, twist;
-
-
- for (syllable = 0; syllable < N_SYLLABLE; syllable++)
- {
- if ((syllable == SYLLABLE_INVALID) || (syllable == SYLLABLE_NONE))
- {
- subgroup[0] = 1;
- for (sym = 1; sym < N_CUBESYM; sym++)
- subgroup[sym] = 0;
- }
- else if (is_single_twist(syllable))
- {
- twist = syllable_to_twist(syllable);
- for (sym = 0; sym < N_CUBESYM; sym++)
- subgroup[sym] = (sym_on_twist[sym][twist] == twist);
- }
- else
- {
- syllable_to_two_twists(syllable, twist_arr);
-
- for (sym = 0; sym < N_CUBESYM; sym++)
- {
- temp_arr[0] = sym_on_twist[sym][twist_arr[0]];
- temp_arr[1] = sym_on_twist[sym][twist_arr[1]];
- clean_up_sequence(temp_arr, 2);
- if ((temp_arr[0] == twist_arr[0]) &&
- (temp_arr[1] == twist_arr[1]))
- subgroup[sym] = 1;
- else
- subgroup[sym] = 0;
- }
- }
-
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- {
- for (sym = 0; sym < N_CUBESYM; sym++)
- temp_subgroup[sym] = (subgroup[sym] && subgroup_list[subgrp][sym]);
-
- syllable_on_sym[syllable][subgrp] = which_subgroup(temp_subgroup,
- subgroup_list);
- if (syllable_on_sym[syllable][subgrp] < 0)
- exit_w_error_message("calc_syllable_on_sym : subgroup not found");
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int twist_on_syllable(int twist, int syllable)
- /* ------------------------------------------------------------------------- */
-
- {
- if (syllable == SYLLABLE_INVALID)
- return SYLLABLE_INVALID;
-
- if (twist == TWIST_F)
- {
- if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
- (syllable == SYLLABLE_F3) ||
- (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_F;
- }
- else if (twist == TWIST_F2)
- {
- if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
- (syllable == SYLLABLE_F3) ||
- (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_F2;
- }
- else if (twist == TWIST_F3)
- {
- if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F2) ||
- (syllable == SYLLABLE_F3) ||
- (syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_F3;
- }
- else if (twist == TWIST_R)
- {
- if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
- (syllable == SYLLABLE_R3) ||
- (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_R;
- }
- else if (twist == TWIST_R2)
- {
- if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
- (syllable == SYLLABLE_R3) ||
- (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_R2;
- }
- else if (twist == TWIST_R3)
- {
- if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R2) ||
- (syllable == SYLLABLE_R3) ||
- (syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_R3;
- }
- else if (twist == TWIST_U)
- {
- if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
- (syllable == SYLLABLE_U3) ||
- (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_U;
- }
- else if (twist == TWIST_U2)
- {
- if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
- (syllable == SYLLABLE_U3) ||
- (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_U2;
- }
- else if (twist == TWIST_U3)
- {
- if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U2) ||
- (syllable == SYLLABLE_U3) ||
- (syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else
- return SYLLABLE_U3;
- }
- else if (twist == TWIST_B)
- {
- if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_F)
- return SYLLABLE_FB;
- else if (syllable == SYLLABLE_F2)
- return SYLLABLE_FB2;
- else if (syllable == SYLLABLE_F3)
- return SYLLABLE_FB3;
- else
- return SYLLABLE_B;
- }
- else if (twist == TWIST_B2)
- {
- if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else if ((syllable == SYLLABLE_F) || (syllable == SYLLABLE_F3))
- return SYLLABLE_FB2;
- else if (syllable == SYLLABLE_F2)
- return SYLLABLE_F2B2;
- else
- return SYLLABLE_B2;
- }
- else if (twist == TWIST_B3)
- {
- if ((syllable == SYLLABLE_B) || (syllable == SYLLABLE_B2) ||
- (syllable == SYLLABLE_B3) ||
- (syllable == SYLLABLE_FB) || (syllable == SYLLABLE_FB2) ||
- (syllable == SYLLABLE_FB3) || (syllable == SYLLABLE_F2B2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_F)
- return SYLLABLE_FB3;
- else if (syllable == SYLLABLE_F2)
- return SYLLABLE_FB2;
- else if (syllable == SYLLABLE_F3)
- return SYLLABLE_FB;
- else
- return SYLLABLE_B3;
- }
- else if (twist == TWIST_L)
- {
- if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_R)
- return SYLLABLE_RL;
- else if (syllable == SYLLABLE_R2)
- return SYLLABLE_RL2;
- else if (syllable == SYLLABLE_R3)
- return SYLLABLE_RL3;
- else
- return SYLLABLE_L;
- }
- else if (twist == TWIST_L2)
- {
- if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else if ((syllable == SYLLABLE_R) || (syllable == SYLLABLE_R3))
- return SYLLABLE_RL2;
- else if (syllable == SYLLABLE_R2)
- return SYLLABLE_R2L2;
- else
- return SYLLABLE_L2;
- }
- else if (twist == TWIST_L3)
- {
- if ((syllable == SYLLABLE_L) || (syllable == SYLLABLE_L2) ||
- (syllable == SYLLABLE_L3) ||
- (syllable == SYLLABLE_RL) || (syllable == SYLLABLE_RL2) ||
- (syllable == SYLLABLE_RL3) || (syllable == SYLLABLE_R2L2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_R)
- return SYLLABLE_RL3;
- else if (syllable == SYLLABLE_R2)
- return SYLLABLE_RL2;
- else if (syllable == SYLLABLE_R3)
- return SYLLABLE_RL;
- else
- return SYLLABLE_L3;
- }
- else if (twist == TWIST_D)
- {
- if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_U)
- return SYLLABLE_UD;
- else if (syllable == SYLLABLE_U2)
- return SYLLABLE_UD2;
- else if (syllable == SYLLABLE_U3)
- return SYLLABLE_UD3;
- else
- return SYLLABLE_D;
- }
- else if (twist == TWIST_D2)
- {
- if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else if ((syllable == SYLLABLE_U) || (syllable == SYLLABLE_U3))
- return SYLLABLE_UD2;
- else if (syllable == SYLLABLE_U2)
- return SYLLABLE_U2D2;
- else
- return SYLLABLE_D2;
- }
- else if (twist == TWIST_D3)
- {
- if ((syllable == SYLLABLE_D) || (syllable == SYLLABLE_D2) ||
- (syllable == SYLLABLE_D3) ||
- (syllable == SYLLABLE_UD) || (syllable == SYLLABLE_UD2) ||
- (syllable == SYLLABLE_UD3) || (syllable == SYLLABLE_U2D2))
- return SYLLABLE_INVALID;
- else if (syllable == SYLLABLE_U)
- return SYLLABLE_UD3;
- else if (syllable == SYLLABLE_U2)
- return SYLLABLE_UD2;
- else if (syllable == SYLLABLE_U3)
- return SYLLABLE_UD;
- else
- return SYLLABLE_D3;
- }
- else
- exit_w_error_message("twist_on_syllable : invalid twist");
-
- return SYLLABLE_INVALID;
- }
-
-
- /* ========================================================================= */
- int not_minimal_one_twist(int subgroup[N_CUBESYM],
- int sym_on_twist[N_CUBESYM][N_TWIST],
- int twist)
- /* ------------------------------------------------------------------------- */
-
- {
- int sym;
-
-
- for (sym = 0; sym < N_CUBESYM; sym++)
- if (subgroup[sym] && (sym_on_twist[sym][twist] < twist))
- return 1;
-
- return 0;
- }
-
-
- /* ========================================================================= */
- int not_minimal_two_twists(int subgroup[N_CUBESYM],
- int sym_on_twist[N_CUBESYM][N_TWIST],
- int twist0, int twist1)
- /* ------------------------------------------------------------------------- */
-
- {
- int twist_arr[2], sym;
-
-
- for (sym = 0; sym < N_CUBESYM; sym++)
- if (subgroup[sym])
- {
- twist_arr[0] = sym_on_twist[sym][twist0];
- twist_arr[1] = sym_on_twist[sym][twist1];
- clean_up_sequence(twist_arr, 2);
- if ((twist_arr[0] < twist0) ||
- ((twist_arr[0] == twist0) && (twist_arr[1] < twist1)))
- return 1;
- }
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void calc_twist_on_sylsubgrp(int
- tw_on_sylsubgrp[N_TWIST][N_SYLLABLE * N_SYMSUBGRP])
- /* ------------------------------------------------------------------------- */
-
- {
- int subgroup_list[N_SYMSUBGRP][N_CUBESYM];
- int sym_on_twist[N_CUBESYM][N_TWIST];
- int syllable_on_subgrp[N_SYLLABLE][N_SYMSUBGRP];
- int syllable, subgrp, subgrp_before, subgrp_after, twist;
- int new_syllable, new_subgrp;
-
-
- calc_subgroup_list(subgroup_list);
- calc_sym_on_twist(sym_on_twist);
- calc_syllable_on_sym(subgroup_list, sym_on_twist, syllable_on_subgrp);
-
- for (syllable = 0; syllable < N_SYLLABLE; syllable++)
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- {
- if (is_single_twist(syllable))
- {
- subgrp_before = subgrp;
- subgrp_after = syllable_on_subgrp[syllable][subgrp];
- }
- else
- {
- subgrp_before = SUBGRP_TRIVIAL;
-
- if (syllable == SYLLABLE_INVALID)
- subgrp_after = SUBGRP_TRIVIAL;
- else
- subgrp_after = subgrp;
- }
-
- for (twist = 0; twist < N_TWIST; twist++)
- {
- new_syllable = twist_on_syllable(twist, syllable);
-
- if (is_single_twist(new_syllable))
- {
- if (not_minimal_one_twist(subgroup_list[subgrp_after],
- sym_on_twist, syllable_to_twist(new_syllable)))
- new_syllable = SYLLABLE_INVALID;
- }
- else if (new_syllable != SYLLABLE_INVALID)
- {
- if (not_minimal_two_twists(subgroup_list[subgrp_before],
- sym_on_twist, syllable_to_twist(syllable), twist))
- new_syllable = SYLLABLE_INVALID;
- }
-
- if (new_syllable == SYLLABLE_INVALID)
- new_subgrp = SUBGRP_TRIVIAL;
- else if (is_single_twist(new_syllable))
- new_subgrp = subgrp_after;
- else
- new_subgrp = syllable_on_subgrp[new_syllable][subgrp_before];
-
- tw_on_sylsubgrp[twist][syllable * N_SYMSUBGRP + subgrp] =
- new_syllable * N_SYMSUBGRP + new_subgrp;
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_twist_on_follow(void)
- /* ------------------------------------------------------------------------- */
-
- {
- unsigned short (*mem_ptr)[N_FOLLOW];
- int tw_on_sylsubgrp[N_TWIST][N_SYLLABLE * N_SYMSUBGRP];
- int occurs[N_SYLLABLE * N_SYMSUBGRP];
- int sylsubgrp_to_follow[N_SYLLABLE * N_SYMSUBGRP];
- int follow_to_sylsubgrp[N_FOLLOW];
- int syllable, subgrp, found, twist, count, follow;
-
-
- calc_twist_on_sylsubgrp(tw_on_sylsubgrp);
-
- for (syllable = 0; syllable < N_SYLLABLE; syllable++)
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- occurs[syllable * N_SYMSUBGRP + subgrp] = 0;
-
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- occurs[SYLLABLE_NONE * N_SYMSUBGRP + subgrp] = 1;
-
- found = 1;
-
- while (found)
- {
- found = 0;
- for (syllable = 0; syllable < N_SYLLABLE; syllable++)
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- for (twist = 0; twist < N_TWIST; twist++)
- if (occurs[tw_on_sylsubgrp[twist]
- [syllable * N_SYMSUBGRP + subgrp]] == 0)
- {
- occurs[tw_on_sylsubgrp[twist]
- [syllable * N_SYMSUBGRP + subgrp]] = 1;
- found = 1;
- }
- }
-
- count = 0;
-
- for (syllable = 0; syllable < N_SYLLABLE; syllable++)
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- {
- if (occurs[syllable * N_SYMSUBGRP + subgrp] == 0)
- sylsubgrp_to_follow[syllable * N_SYMSUBGRP + subgrp] = -1;
- else
- {
- sylsubgrp_to_follow[syllable * N_SYMSUBGRP + subgrp] = count;
- follow_to_sylsubgrp[count] = syllable * N_SYMSUBGRP + subgrp;
- count++;
- }
- }
-
- if (count != N_FOLLOW)
- exit_w_error_message("init_twist_on_follow : wrong number of follow's");
-
- for (subgrp = 0; subgrp < N_SYMSUBGRP; subgrp++)
- if (sylsubgrp_to_follow[SYLLABLE_NONE * N_SYMSUBGRP + subgrp]
- != 1 + subgrp)
- exit_w_error_message("init_twist_on_follow : indexing error");
-
- mem_ptr = (unsigned short (*)[N_FOLLOW])
- malloc(sizeof(unsigned short [N_TWIST][N_FOLLOW]));
- if (mem_ptr == NULL)
- exit_w_error_message("init_twist_on_follow : couldn't get memory");
-
- for (twist = 0; twist < N_TWIST; twist++)
- twist_on_follow[twist] = mem_ptr[twist];
-
- for (twist = 0; twist < N_TWIST; twist++)
- for (follow = 0; follow < N_FOLLOW; follow++)
- twist_on_follow[twist][follow] =
- (unsigned short)sylsubgrp_to_follow[tw_on_sylsubgrp[twist]
- [follow_to_sylsubgrp[follow]]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void corner_unpack(int corner, int array_out[8])
- /* ------------------------------------------------------------------------- */
-
- /* input: corner
- output: array_out[] */
-
- {
- int ii;
-
-
- for (ii = 0; ii < 7; ii++)
- {
- array_out[ii] = corner % 3;
- corner = corner / 3;
- }
-
- array_out[7] = (2 * (array_out[0] + array_out[1] + array_out[2] + array_out[3]
- + array_out[4] + array_out[5] + array_out[6])) % 3;
-
- return;
- }
-
-
- /* ========================================================================= */
- int corner_pack(int array_in[8])
- /* ------------------------------------------------------------------------- */
-
- /* input: array_in[] */
-
- {
- int corner, ii;
-
-
- corner = 0;
- for (ii = 6; ii >= 0; ii--)
- corner = 3 * corner + array_in[ii];
-
- return corner;
- }
-
-
- /* ========================================================================= */
- void corner_adjust(int array[8], int ind0, int ind1, int ind2,
- int ind3)
- /* ------------------------------------------------------------------------- */
-
- {
- array[ind0] = (array[ind0] + 1) % 3;
- array[ind1] = (array[ind1] + 2) % 3;
- array[ind2] = (array[ind2] + 1) % 3;
- array[ind3] = (array[ind3] + 2) % 3;
-
- return;
- }
-
-
- /* ========================================================================= */
- int twist_f_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
- corner_adjust(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_r_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
- corner_adjust(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_u_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_UFR, CORNER_URB, CORNER_UBL, CORNER_ULF);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_b_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
- corner_adjust(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_l_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
- corner_adjust(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_d_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_DFL, CORNER_DLB, CORNER_DBR, CORNER_DRF);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void init_twist_on_corner(void)
- /* ------------------------------------------------------------------------- */
-
- {
- int twist, corner;
-
-
- /* allocate and initialize global array twist_on_corner */
-
- twist_on_corner[0] =
- (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_CORNER]));
- if (twist_on_corner[0] == NULL)
- exit_w_error_message("init_twist_on_corner : couldn't get memory");
-
- for (twist = 1; twist < N_TWIST; twist++)
- twist_on_corner[twist] = &twist_on_corner[0][twist * N_CORNER];
-
- for (corner = 0; corner < N_CORNER; corner++)
- {
- twist_on_corner[TWIST_F][corner] =
- (unsigned short)twist_f_on_corner(corner);
- twist_on_corner[TWIST_R][corner] =
- (unsigned short)twist_r_on_corner(corner);
- twist_on_corner[TWIST_U][corner] =
- (unsigned short)twist_u_on_corner(corner);
- twist_on_corner[TWIST_B][corner] =
- (unsigned short)twist_b_on_corner(corner);
- twist_on_corner[TWIST_L][corner] =
- (unsigned short)twist_l_on_corner(corner);
- twist_on_corner[TWIST_D][corner] =
- (unsigned short)twist_d_on_corner(corner);
- }
- for (corner = 0; corner < N_CORNER; corner++)
- {
- twist_on_corner[TWIST_F2][corner] =
- twist_on_corner[TWIST_F][(int)twist_on_corner[TWIST_F][corner]];
- twist_on_corner[TWIST_R2][corner] =
- twist_on_corner[TWIST_R][(int)twist_on_corner[TWIST_R][corner]];
- twist_on_corner[TWIST_U2][corner] =
- twist_on_corner[TWIST_U][(int)twist_on_corner[TWIST_U][corner]];
- twist_on_corner[TWIST_B2][corner] =
- twist_on_corner[TWIST_B][(int)twist_on_corner[TWIST_B][corner]];
- twist_on_corner[TWIST_L2][corner] =
- twist_on_corner[TWIST_L][(int)twist_on_corner[TWIST_L][corner]];
- twist_on_corner[TWIST_D2][corner] =
- twist_on_corner[TWIST_D][(int)twist_on_corner[TWIST_D][corner]];
- }
- for (corner = 0; corner < N_CORNER; corner++)
- {
- twist_on_corner[TWIST_F3][corner] =
- twist_on_corner[TWIST_F2][(int)twist_on_corner[TWIST_F][corner]];
- twist_on_corner[TWIST_R3][corner] =
- twist_on_corner[TWIST_R2][(int)twist_on_corner[TWIST_R][corner]];
- twist_on_corner[TWIST_U3][corner] =
- twist_on_corner[TWIST_U2][(int)twist_on_corner[TWIST_U][corner]];
- twist_on_corner[TWIST_B3][corner] =
- twist_on_corner[TWIST_B2][(int)twist_on_corner[TWIST_B][corner]];
- twist_on_corner[TWIST_L3][corner] =
- twist_on_corner[TWIST_L2][(int)twist_on_corner[TWIST_L][corner]];
- twist_on_corner[TWIST_D3][corner] =
- twist_on_corner[TWIST_D2][(int)twist_on_corner[TWIST_D][corner]];
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int sym_cu_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- four_cycle(temp_arr, CORNER_UFR, CORNER_URB, CORNER_UBL, CORNER_ULF);
- four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_DLB, CORNER_DFL);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_cf2_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- corner_unpack(corner, temp_arr);
- two_cycle(temp_arr, CORNER_UFR, CORNER_DFL);
- two_cycle(temp_arr, CORNER_ULF, CORNER_DRF);
- two_cycle(temp_arr, CORNER_UBL, CORNER_DBR);
- two_cycle(temp_arr, CORNER_URB, CORNER_DLB);
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_rud_on_corner(int corner)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8], ii;
-
-
- corner_unpack(corner, temp_arr);
- two_cycle(temp_arr, CORNER_UFR, CORNER_DRF);
- two_cycle(temp_arr, CORNER_ULF, CORNER_DFL);
- two_cycle(temp_arr, CORNER_UBL, CORNER_DLB);
- two_cycle(temp_arr, CORNER_URB, CORNER_DBR);
-
- for (ii = 0; ii < 8; ii++)
- temp_arr[ii] = (2 * temp_arr[ii]) % 3;
-
- return corner_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void init_sym_on_corner(void)
- /* ------------------------------------------------------------------------- */
-
- {
- int corner, sym;
-
-
- /* allocate and initialize global array sym_on_corner */
-
- sym_on_corner[0] =
- (unsigned short *)malloc(sizeof(unsigned short [N_SYM][N_CORNER]));
- if (sym_on_corner[0] == NULL)
- exit_w_error_message("init_sym_on_corner : couldn't get memory");
-
- for (sym = 1; sym < N_SYM; sym++)
- sym_on_corner[sym] = &sym_on_corner[0][sym * N_CORNER];
-
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[0][corner] = (unsigned short)corner;
-
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[1][corner] = (unsigned short)sym_cu_on_corner(corner);
-
- for (sym = 2; sym < 4; sym++)
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[sym][corner] =
- sym_on_corner[1][(int)sym_on_corner[sym - 1][corner]];
-
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[4][corner] = (unsigned short)sym_cf2_on_corner(corner);
-
- for (sym = 5; sym < 8; sym++)
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[sym][corner] =
- sym_on_corner[4][(int)sym_on_corner[sym - 4][corner]];
-
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[8][corner] = (unsigned short)sym_rud_on_corner(corner);
-
- for (sym = 9; sym < 16; sym++)
- for (corner = 0; corner < N_CORNER; corner++)
- sym_on_corner[sym][corner] =
- sym_on_corner[8][(int)sym_on_corner[sym - 8][corner]];
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_edgeloc_conv(int conv_tab[N_ELOC], int unconv_tab[N_ELOC_CONV])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii, loc0, loc1, loc2, loc3, count;
-
-
- for (ii = 0; ii < N_ELOC; ii++)
- conv_tab[ii] = -1;
-
- for (ii = 0; ii < N_ELOC_CONV; ii++)
- unconv_tab[ii] = -1;
-
- count = 0;
- for (loc0 = 0; loc0 < 9; loc0++)
- for (loc1 = loc0 + 1; loc1 < 10; loc1++)
- for (loc2 = loc1 + 1; loc2 < 11; loc2++)
- for (loc3 = loc2 + 1; loc3 < 12; loc3++)
- {
- if (count >= N_ELOC)
- exit_w_error_message("calc_edgeloc_conv : too many eloc's");
- conv_tab[count] = (1 << loc0) | (1 << loc1) |
- (1 << loc2) | (1 << loc3);
- unconv_tab[conv_tab[count]] = count;
- count++;
- }
-
- if (count != N_ELOC)
- exit_w_error_message("calc_edgeloc_conv : wrong number of eloc's");
-
- return;
- }
-
-
- /* ========================================================================= */
- int edgeloc_conv_or_unconv(int eloc_conv_or_unconv, int convert_flag)
- /* ------------------------------------------------------------------------- */
-
- {
- static int eloc_conv[N_ELOC];
- static int eloc_unconv[N_ELOC_CONV];
- static int initialized = 0;
- int el_conv, el_unconv;
-
-
- if (initialized == 0)
- {
- calc_edgeloc_conv(eloc_conv, eloc_unconv);
- initialized = 1;
- }
-
- if (convert_flag)
- {
- if ((eloc_conv_or_unconv < 0) || (eloc_conv_or_unconv >= N_ELOC))
- exit_w_error_message("edgeloc_conv_or_unconv : invalid input");
-
- el_conv = eloc_conv[eloc_conv_or_unconv];
-
- if (el_conv < 0)
- exit_w_error_message("edgeloc_conv_or_unconv : corrupted data");
-
- return el_conv;
- }
- else
- {
- if ((eloc_conv_or_unconv < 0) || (eloc_conv_or_unconv >= N_ELOC_CONV))
- exit_w_error_message("edgeloc_conv_or_unconv : invalid input");
-
- el_unconv = eloc_unconv[eloc_conv_or_unconv];
-
- if (el_unconv < 0)
- exit_w_error_message("edgeloc_conv_or_unconv : corrupted data");
-
- return el_unconv;
- }
- }
-
-
- /* ========================================================================= */
- int edgeloc_conv(int eloc_unconv)
- /* ------------------------------------------------------------------------- */
-
- {
- return edgeloc_conv_or_unconv(eloc_unconv, 1);
- }
-
-
- /* ========================================================================= */
- int edgeloc_unconv(int eloc_conv)
- /* ------------------------------------------------------------------------- */
-
- {
- return edgeloc_conv_or_unconv(eloc_conv, 0);
- }
-
-
- /* ========================================================================= */
- void eloc_unpack(int eloc, int array_out[12])
- /* ------------------------------------------------------------------------- */
-
- /* input: eloc
- output: array_out[] */
-
- {
- int conv, ii;
-
-
- conv = edgeloc_conv(eloc);
-
- for (ii = 0; ii < 12; ii++)
- {
- array_out[ii] = conv % 2;
- conv = conv / 2;
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int eloc_pack(int array_in[12])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii, conv;
-
-
- conv = 0;
- for (ii = 11; ii >= 0; ii--)
- conv = 2 * conv + array_in[ii];
-
- return edgeloc_unconv(conv);
- }
-
-
- /* ========================================================================= */
- int twist_f_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_r_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_u_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_UF, EDGE_UR, EDGE_UB, EDGE_UL);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_b_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_l_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_d_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_DF, EDGE_DL, EDGE_DB, EDGE_DR);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void calc_twist_on_eloc(int table[N_TWIST][N_ELOC])
- /* ------------------------------------------------------------------------- */
-
- {
- int edgeloc;
-
-
- for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
- {
- table[TWIST_F][edgeloc] = twist_f_on_eloc(edgeloc);
- table[TWIST_R][edgeloc] = twist_r_on_eloc(edgeloc);
- table[TWIST_U][edgeloc] = twist_u_on_eloc(edgeloc);
- table[TWIST_B][edgeloc] = twist_b_on_eloc(edgeloc);
- table[TWIST_L][edgeloc] = twist_l_on_eloc(edgeloc);
- table[TWIST_D][edgeloc] = twist_d_on_eloc(edgeloc);
- }
-
- perm_n_compose(N_ELOC, table[TWIST_F], table[TWIST_F], table[TWIST_F2]);
- perm_n_compose(N_ELOC, table[TWIST_R], table[TWIST_R], table[TWIST_R2]);
- perm_n_compose(N_ELOC, table[TWIST_U], table[TWIST_U], table[TWIST_U2]);
- perm_n_compose(N_ELOC, table[TWIST_B], table[TWIST_B], table[TWIST_B2]);
- perm_n_compose(N_ELOC, table[TWIST_L], table[TWIST_L], table[TWIST_L2]);
- perm_n_compose(N_ELOC, table[TWIST_D], table[TWIST_D], table[TWIST_D2]);
-
- perm_n_compose(N_ELOC, table[TWIST_F2], table[TWIST_F], table[TWIST_F3]);
- perm_n_compose(N_ELOC, table[TWIST_R2], table[TWIST_R], table[TWIST_R3]);
- perm_n_compose(N_ELOC, table[TWIST_U2], table[TWIST_U], table[TWIST_U3]);
- perm_n_compose(N_ELOC, table[TWIST_B2], table[TWIST_B], table[TWIST_B3]);
- perm_n_compose(N_ELOC, table[TWIST_L2], table[TWIST_L], table[TWIST_L3]);
- perm_n_compose(N_ELOC, table[TWIST_D2], table[TWIST_D], table[TWIST_D3]);
-
- return;
- }
-
-
- /* ========================================================================= */
- int sym_cu_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- four_cycle(temp_arr, EDGE_UF, EDGE_UR, EDGE_UB, EDGE_UL);
- four_cycle(temp_arr, EDGE_DF, EDGE_DR, EDGE_DB, EDGE_DL);
- four_cycle(temp_arr, EDGE_FR, EDGE_BR, EDGE_BL, EDGE_FL);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_cf2_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- two_cycle(temp_arr, EDGE_UF, EDGE_DF);
- two_cycle(temp_arr, EDGE_UR, EDGE_DL);
- two_cycle(temp_arr, EDGE_UB, EDGE_DB);
- two_cycle(temp_arr, EDGE_UL, EDGE_DR);
- two_cycle(temp_arr, EDGE_FR, EDGE_FL);
- two_cycle(temp_arr, EDGE_BR, EDGE_BL);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_rud_on_eloc(int eloc)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eloc_unpack(eloc, temp_arr);
- two_cycle(temp_arr, EDGE_UF, EDGE_DF);
- two_cycle(temp_arr, EDGE_UR, EDGE_DR);
- two_cycle(temp_arr, EDGE_UB, EDGE_DB);
- two_cycle(temp_arr, EDGE_UL, EDGE_DL);
-
- return eloc_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void calc_sym_on_eloc(int table[N_SYM][N_ELOC])
- /* ------------------------------------------------------------------------- */
-
- {
- int edgeloc, sym;
-
-
- perm_n_init(N_ELOC, table[0]);
-
- for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
- table[1][edgeloc] = sym_cu_on_eloc(edgeloc);
-
- for (sym = 2; sym < 4; sym++)
- perm_n_compose(N_ELOC, table[1], table[sym - 1], table[sym]);
-
- for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
- table[4][edgeloc] = sym_cf2_on_eloc(edgeloc);
-
- for (sym = 5; sym < 8; sym++)
- perm_n_compose(N_ELOC, table[4], table[sym - 4], table[sym]);
-
- for (edgeloc = 0; edgeloc < N_ELOC; edgeloc++)
- table[8][edgeloc] = sym_rud_on_eloc(edgeloc);
-
- for (sym = 9; sym < 16; sym++)
- perm_n_compose(N_ELOC, table[8], table[sym - 8], table[sym]);
-
- return;
- }
-
-
- /* ========================================================================= */
- void eflip_unpack(int eflip, int array_out[12])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 0; ii < 11; ii++)
- {
- array_out[ii] = eflip % 2;
- eflip = eflip / 2;
- }
-
- array_out[11] = (array_out[0] + array_out[1] + array_out[2] + array_out[3] +
- array_out[4] + array_out[5] + array_out[6] + array_out[7] +
- array_out[8] + array_out[9] + array_out[10]) % 2;
-
- return;
- }
-
-
- /* ========================================================================= */
- int eflip_pack(int array_in[12])
- /* ------------------------------------------------------------------------- */
-
- {
- int eflip, ii;
-
-
- eflip = 0;
- for (ii = 10; ii >= 0; ii--)
- eflip = 2 * eflip + array_in[ii];
-
- return eflip;
- }
-
-
- /* ========================================================================= */
- void eflip_adjust(int array[12], int ind0, int ind1, int ind2,
- int ind3)
- /* ------------------------------------------------------------------------- */
-
- {
- array[ind0] = 1 - array[ind0];
- array[ind1] = 1 - array[ind1];
- array[ind2] = 1 - array[ind2];
- array[ind3] = 1 - array[ind3];
-
- return;
- }
-
-
- /* ========================================================================= */
- int twist_f_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
- eflip_adjust(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_r_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_u_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_b_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
- eflip_adjust(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_l_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_d_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- four_cycle(temp_arr, EDGE_DL, EDGE_DB, EDGE_DR, EDGE_DF);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void calc_twist_on_eflip(int table[N_TWIST][N_EFLIP])
- /* ------------------------------------------------------------------------- */
-
- {
- int edgeflip;
-
-
- for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
- {
- table[TWIST_F][edgeflip] = twist_f_on_eflip(edgeflip);
- table[TWIST_R][edgeflip] = twist_r_on_eflip(edgeflip);
- table[TWIST_U][edgeflip] = twist_u_on_eflip(edgeflip);
- table[TWIST_B][edgeflip] = twist_b_on_eflip(edgeflip);
- table[TWIST_L][edgeflip] = twist_l_on_eflip(edgeflip);
- table[TWIST_D][edgeflip] = twist_d_on_eflip(edgeflip);
- }
-
- perm_n_compose(N_EFLIP, table[TWIST_F], table[TWIST_F], table[TWIST_F2]);
- perm_n_compose(N_EFLIP, table[TWIST_R], table[TWIST_R], table[TWIST_R2]);
- perm_n_compose(N_EFLIP, table[TWIST_U], table[TWIST_U], table[TWIST_U2]);
- perm_n_compose(N_EFLIP, table[TWIST_B], table[TWIST_B], table[TWIST_B2]);
- perm_n_compose(N_EFLIP, table[TWIST_L], table[TWIST_L], table[TWIST_L2]);
- perm_n_compose(N_EFLIP, table[TWIST_D], table[TWIST_D], table[TWIST_D2]);
-
- perm_n_compose(N_EFLIP, table[TWIST_F2], table[TWIST_F], table[TWIST_F3]);
- perm_n_compose(N_EFLIP, table[TWIST_R2], table[TWIST_R], table[TWIST_R3]);
- perm_n_compose(N_EFLIP, table[TWIST_U2], table[TWIST_U], table[TWIST_U3]);
- perm_n_compose(N_EFLIP, table[TWIST_B2], table[TWIST_B], table[TWIST_B3]);
- perm_n_compose(N_EFLIP, table[TWIST_L2], table[TWIST_L], table[TWIST_L3]);
- perm_n_compose(N_EFLIP, table[TWIST_D2], table[TWIST_D], table[TWIST_D3]);
-
- return;
- }
-
-
- /* ========================================================================= */
- int sym_cu2_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- two_cycle(temp_arr, EDGE_UF, EDGE_UB);
- two_cycle(temp_arr, EDGE_UR, EDGE_UL);
- two_cycle(temp_arr, EDGE_DF, EDGE_DB);
- two_cycle(temp_arr, EDGE_DR, EDGE_DL);
- two_cycle(temp_arr, EDGE_FR, EDGE_BL);
- two_cycle(temp_arr, EDGE_FL, EDGE_BR);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_cf2_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- two_cycle(temp_arr, EDGE_UF, EDGE_DF);
- two_cycle(temp_arr, EDGE_UR, EDGE_DL);
- two_cycle(temp_arr, EDGE_UB, EDGE_DB);
- two_cycle(temp_arr, EDGE_UL, EDGE_DR);
- two_cycle(temp_arr, EDGE_FR, EDGE_FL);
- two_cycle(temp_arr, EDGE_BR, EDGE_BL);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int sym_rud_on_eflip(int eflip)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- eflip_unpack(eflip, temp_arr);
- two_cycle(temp_arr, EDGE_UF, EDGE_DF);
- two_cycle(temp_arr, EDGE_UR, EDGE_DR);
- two_cycle(temp_arr, EDGE_UB, EDGE_DB);
- two_cycle(temp_arr, EDGE_UL, EDGE_DL);
-
- return eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void calc_sym_on_eflip(int table[N_SYM / 2][N_EFLIP])
- /* ------------------------------------------------------------------------- */
-
- {
- int edgeflip, sym;
-
-
- perm_n_init(N_EFLIP, table[0]);
-
- for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
- table[1][edgeflip] = sym_cu2_on_eflip(edgeflip);
-
- for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
- table[2][edgeflip] = sym_cf2_on_eflip(edgeflip);
-
- perm_n_compose(N_EFLIP, table[2], table[1], table[3]);
-
- for (edgeflip = 0; edgeflip < N_EFLIP; edgeflip++)
- table[4][edgeflip] = sym_rud_on_eflip(edgeflip);
-
- for (sym = 5; sym < 8; sym++)
- perm_n_compose(N_EFLIP, table[4], table[sym - 4], table[sym]);
-
- return;
- }
-
-
- /* ========================================================================= */
- int sym_cu_on_fulledge(int fulledge)
- /* ------------------------------------------------------------------------- */
-
- {
- int edgeloc_arr[12], edgeflip_arr[12], temp_arr[12], ii;
-
-
- eloc_unpack(fulledge / N_EFLIP, edgeloc_arr);
- eflip_unpack(fulledge % N_EFLIP, edgeflip_arr);
-
- for (ii = 0; ii < 12; ii++)
- temp_arr[ii] = (edgeloc_arr[ii] != edgeflip_arr[ii]);
-
- four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
- four_cycle(temp_arr, EDGE_DR, EDGE_DB, EDGE_DL, EDGE_DF);
- four_cycle(temp_arr, EDGE_BR, EDGE_BL, EDGE_FL, EDGE_FR);
- eflip_adjust(temp_arr, EDGE_FR, EDGE_FL, EDGE_BR, EDGE_BL);
-
- return sym_cu_on_eloc(fulledge / N_EFLIP) * N_EFLIP + eflip_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void init_fulledge_to_edgequot(int sym_on_eloc[N_SYM][N_ELOC],
- int sym_on_eflip[N_SYM / 2][N_EFLIP],
- int edge_to_fulledge[N_EDGEQUOT],
- int stabilizers[N_EDGEQUOT],
- int multiplicities[N_EDGEQUOT])
- /* ------------------------------------------------------------------------- */
-
- {
- int count, sym_count, fulledge, cu_fulledge, sym, min_sym;
- int min_full, new_full, stab;
-
-
- fulledge_to_edge =
- (unsigned short *)malloc(sizeof(unsigned short [N_FULLEDGE]));
- fulledge_to_sym = (unsigned char *)malloc(sizeof(unsigned char [N_FULLEDGE]));
-
- if ((fulledge_to_edge == NULL) || (fulledge_to_sym == NULL))
- exit_w_error_message("init_fulledge_to_edgequot : couldn't get memory");
-
- count = 0;
-
- for (fulledge = 0; fulledge < N_FULLEDGE; fulledge++)
- {
- min_full = fulledge;
- min_sym = 0;
- stab = 0;
- sym_count = 0;
- cu_fulledge = sym_cu_on_fulledge(fulledge);
-
- for (sym = 0; sym < (N_SYM / 2); sym++)
- {
- new_full = sym_on_eloc[2 * sym][fulledge / N_EFLIP] * N_EFLIP +
- sym_on_eflip[sym][fulledge % N_EFLIP];
- if (min_full > new_full)
- {
- min_full = new_full;
- min_sym = 2 * sym;
- }
- else if (min_full == new_full)
- {
- stab |= (1 << (2 * sym));
- sym_count++;
- }
-
- new_full = sym_on_eloc[2 * sym][cu_fulledge / N_EFLIP] * N_EFLIP +
- sym_on_eflip[sym][cu_fulledge % N_EFLIP];
- if (min_full > new_full)
- {
- min_full = new_full;
- min_sym = 2 * sym + 1;
- }
- else if (min_full == new_full)
- {
- stab |= (1 << (2 * sym + 1));
- sym_count++;
- }
- }
-
- if (min_sym == 0)
- {
- if (count >= N_EDGEQUOT)
- exit_w_error_message(
- "init_fulledge_to_edgequot : too many edgequot's");
- edge_to_fulledge[count] = fulledge;
- stabilizers[count] = stab;
- multiplicities[count] = N_SYM / sym_count;
- fulledge_to_edge[fulledge] = (unsigned short)count;
- fulledge_to_sym[fulledge] = sym_x_invsym_to_sym[0][0];
- count++;
- }
- else
- {
- fulledge_to_edge[fulledge] = fulledge_to_edge[min_full];
- fulledge_to_sym[fulledge] = sym_x_invsym_to_sym[0][min_sym];
- }
- }
-
- if (count != N_EDGEQUOT)
- exit_w_error_message(
- "init_fulledge_to_edgequot : wrong number of edgequot's");
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_twist_on_edge(int twist_on_eloc[N_TWIST][N_ELOC],
- int twist_on_eflip[N_TWIST][N_EFLIP],
- int edge_to_fulledge[N_EDGEQUOT])
- /* ------------------------------------------------------------------------- */
-
- {
- int twist, edge, fulledge, new_edge;
-
-
- /* allocate and initialize global arrays */
- /* twist_on_edge and twist_x_edge_to_sym */
-
- twist_on_edge[0] =
- (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_EDGEQUOT]));
- twist_x_edge_to_sym[0] =
- (unsigned char *)malloc(sizeof(unsigned char [N_TWIST][N_EDGEQUOT]));
-
- if ((twist_on_edge[0] == NULL) || (twist_x_edge_to_sym[0] == NULL))
- exit_w_error_message("init_twist_on_edge : couldn't get memory");
-
- for (twist = 1; twist < N_TWIST; twist++)
- {
- twist_on_edge[twist] = &twist_on_edge[0][twist * N_EDGEQUOT];
- twist_x_edge_to_sym[twist] = &twist_x_edge_to_sym[0][twist * N_EDGEQUOT];
- }
-
- for (twist = 0; twist < N_TWIST; twist++)
- for (edge = 0; edge < N_EDGEQUOT; edge++)
- {
- fulledge = edge_to_fulledge[edge];
- new_edge = twist_on_eloc[twist][fulledge / N_EFLIP] * N_EFLIP +
- twist_on_eflip[twist][fulledge % N_EFLIP];
- twist_on_edge[twist][edge] = fulledge_to_edge[new_edge];
- twist_x_edge_to_sym[twist][edge] =
- sym_x_invsym_to_sym[0][(int)fulledge_to_sym[new_edge]];
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_edge_quotient(int stabilizers[N_EDGEQUOT],
- int multiplicities[N_EDGEQUOT])
- /* ------------------------------------------------------------------------- */
-
- {
- int twist_on_eloc[N_TWIST][N_ELOC];
- int twist_on_eflip[N_TWIST][N_EFLIP];
- int sym_on_eloc[N_SYM][N_ELOC];
- int sym_on_eflip[N_SYM / 2][N_EFLIP];
- int edge_to_fulledge[N_EDGEQUOT];
-
-
- calc_twist_on_eloc(twist_on_eloc);
- calc_sym_on_eloc(sym_on_eloc);
- calc_twist_on_eflip(twist_on_eflip);
- calc_sym_on_eflip(sym_on_eflip);
- init_fulledge_to_edgequot(sym_on_eloc, sym_on_eflip, edge_to_fulledge,
- stabilizers, multiplicities);
- init_twist_on_edge(twist_on_eloc, twist_on_eflip, edge_to_fulledge);
-
- return;
- }
-
-
- /* ========================================================================= */
- void cornerperm_unpack(int cperm, int array_out[8])
- /* ------------------------------------------------------------------------- */
-
- {
- perm_n_unpack(8, cperm, array_out);
-
- return;
- }
-
-
- /* ========================================================================= */
- int cornerperm_pack(int array_in[8])
- /* ------------------------------------------------------------------------- */
-
- {
- return perm_n_pack(8, array_in);
- }
-
-
- /* ========================================================================= */
- int twist_f_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_DFL, CORNER_DRF, CORNER_UFR, CORNER_ULF);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_r_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_DRF, CORNER_DBR, CORNER_URB, CORNER_UFR);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_u_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_URB, CORNER_UBL, CORNER_ULF, CORNER_UFR);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_b_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_DBR, CORNER_DLB, CORNER_UBL, CORNER_URB);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_l_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_DLB, CORNER_DFL, CORNER_ULF, CORNER_UBL);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_d_on_cperm(int cperm)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[8];
-
-
- cornerperm_unpack(cperm, temp_arr);
- four_cycle(temp_arr, CORNER_DFL, CORNER_DLB, CORNER_DBR, CORNER_DRF);
-
- return cornerperm_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void init_twist_on_cornerperm(void)
- /* ------------------------------------------------------------------------- */
-
- {
- int cp, twist;
-
-
- /* allocate and initialize global array twist_on_cornerperm */
-
- twist_on_cornerperm[0] =
- (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_CORNERPERM]));
- if (twist_on_cornerperm[0] == NULL)
- exit_w_error_message("init_twist_on_cornerperm : couldn't get memory");
-
- for (twist = 1; twist < N_TWIST; twist++)
- twist_on_cornerperm[twist] = &twist_on_cornerperm[0][twist * N_CORNERPERM];
-
- for (cp = 0; cp < N_CORNERPERM; cp++)
- {
- twist_on_cornerperm[TWIST_F][cp] = (unsigned short)twist_f_on_cperm(cp);
- twist_on_cornerperm[TWIST_R][cp] = (unsigned short)twist_r_on_cperm(cp);
- twist_on_cornerperm[TWIST_U][cp] = (unsigned short)twist_u_on_cperm(cp);
- twist_on_cornerperm[TWIST_B][cp] = (unsigned short)twist_b_on_cperm(cp);
- twist_on_cornerperm[TWIST_L][cp] = (unsigned short)twist_l_on_cperm(cp);
- twist_on_cornerperm[TWIST_D][cp] = (unsigned short)twist_d_on_cperm(cp);
- }
- for (cp = 0; cp < N_CORNERPERM; cp++)
- {
- twist_on_cornerperm[TWIST_F2][cp] =
- twist_on_cornerperm[TWIST_F][(int)twist_on_cornerperm[TWIST_F][cp]];
- twist_on_cornerperm[TWIST_R2][cp] =
- twist_on_cornerperm[TWIST_R][(int)twist_on_cornerperm[TWIST_R][cp]];
- twist_on_cornerperm[TWIST_U2][cp] =
- twist_on_cornerperm[TWIST_U][(int)twist_on_cornerperm[TWIST_U][cp]];
- twist_on_cornerperm[TWIST_B2][cp] =
- twist_on_cornerperm[TWIST_B][(int)twist_on_cornerperm[TWIST_B][cp]];
- twist_on_cornerperm[TWIST_L2][cp] =
- twist_on_cornerperm[TWIST_L][(int)twist_on_cornerperm[TWIST_L][cp]];
- twist_on_cornerperm[TWIST_D2][cp] =
- twist_on_cornerperm[TWIST_D][(int)twist_on_cornerperm[TWIST_D][cp]];
- }
- for (cp = 0; cp < N_CORNERPERM; cp++)
- {
- twist_on_cornerperm[TWIST_F3][cp] =
- twist_on_cornerperm[TWIST_F2][(int)twist_on_cornerperm[TWIST_F][cp]];
- twist_on_cornerperm[TWIST_R3][cp] =
- twist_on_cornerperm[TWIST_R2][(int)twist_on_cornerperm[TWIST_R][cp]];
- twist_on_cornerperm[TWIST_U3][cp] =
- twist_on_cornerperm[TWIST_U2][(int)twist_on_cornerperm[TWIST_U][cp]];
- twist_on_cornerperm[TWIST_B3][cp] =
- twist_on_cornerperm[TWIST_B2][(int)twist_on_cornerperm[TWIST_B][cp]];
- twist_on_cornerperm[TWIST_L3][cp] =
- twist_on_cornerperm[TWIST_L2][(int)twist_on_cornerperm[TWIST_L][cp]];
- twist_on_cornerperm[TWIST_D3][cp] =
- twist_on_cornerperm[TWIST_D2][(int)twist_on_cornerperm[TWIST_D][cp]];
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void sliceedge_unpack(int sliceedge, int array_out[12])
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[4], ii, count;
-
-
- eloc_unpack(sliceedge % N_ELOC, array_out);
- perm_n_unpack(4, sliceedge / N_ELOC, temp_arr);
-
- count = 0;
- for (ii = 0; ii < 12; ii++)
- if (array_out[ii] != 0)
- {
- if (count >= 4)
- exit_w_error_message("sliceedge_unpack : corrupted data");
-
- array_out[ii] = 1 + temp_arr[count++];
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int sliceedge_pack(int array_in[12])
- /* ------------------------------------------------------------------------- */
-
- {
- int eloc_arr[12], temp_arr[4], ii, count;
-
-
- count = 0;
- for (ii = 0; ii < 12; ii++)
- {
- if (array_in[ii] != 0)
- {
- if (count >= 4)
- exit_w_error_message("sliceedge_pack : invalid input");
-
- temp_arr[count++] = array_in[ii] - 1;
- }
-
- eloc_arr[ii] = (array_in[ii] != 0);
- }
-
- return perm_n_pack(4, temp_arr) * N_ELOC + eloc_pack(eloc_arr);
- }
-
-
- /* ========================================================================= */
- int twist_f_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_FL, EDGE_DF, EDGE_FR, EDGE_UF);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_r_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_FR, EDGE_DR, EDGE_BR, EDGE_UR);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_u_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_UR, EDGE_UB, EDGE_UL, EDGE_UF);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_b_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_BR, EDGE_DB, EDGE_BL, EDGE_UB);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_l_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_BL, EDGE_DL, EDGE_FL, EDGE_UL);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- int twist_d_on_sliceedge(int sliceedge)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_arr[12];
-
-
- sliceedge_unpack(sliceedge, temp_arr);
- four_cycle(temp_arr, EDGE_DL, EDGE_DB, EDGE_DR, EDGE_DF);
-
- return sliceedge_pack(temp_arr);
- }
-
-
- /* ========================================================================= */
- void init_twist_on_sliceedge(void)
- /* ------------------------------------------------------------------------- */
-
- {
- int twist, sl;
-
-
- /* allocate and initialize global array twist_on_sliceedge */
-
- twist_on_sliceedge[0] =
- (unsigned short *)malloc(sizeof(unsigned short [N_TWIST][N_SLICEEDGE]));
- if (twist_on_sliceedge[0] == NULL)
- exit_w_error_message("init_twist_on_sliceedge : couldn't get memory");
-
- for (twist = 1; twist < N_TWIST; twist++)
- twist_on_sliceedge[twist] = &twist_on_sliceedge[0][twist * N_SLICEEDGE];
-
- for (sl = 0; sl < N_SLICEEDGE; sl++)
- {
- twist_on_sliceedge[TWIST_F][sl] = (unsigned short)twist_f_on_sliceedge(sl);
- twist_on_sliceedge[TWIST_R][sl] = (unsigned short)twist_r_on_sliceedge(sl);
- twist_on_sliceedge[TWIST_U][sl] = (unsigned short)twist_u_on_sliceedge(sl);
- twist_on_sliceedge[TWIST_B][sl] = (unsigned short)twist_b_on_sliceedge(sl);
- twist_on_sliceedge[TWIST_L][sl] = (unsigned short)twist_l_on_sliceedge(sl);
- twist_on_sliceedge[TWIST_D][sl] = (unsigned short)twist_d_on_sliceedge(sl);
- }
- for (sl = 0; sl < N_SLICEEDGE; sl++)
- {
- twist_on_sliceedge[TWIST_F2][sl] =
- twist_on_sliceedge[TWIST_F][(int)twist_on_sliceedge[TWIST_F][sl]];
- twist_on_sliceedge[TWIST_R2][sl] =
- twist_on_sliceedge[TWIST_R][(int)twist_on_sliceedge[TWIST_R][sl]];
- twist_on_sliceedge[TWIST_U2][sl] =
- twist_on_sliceedge[TWIST_U][(int)twist_on_sliceedge[TWIST_U][sl]];
- twist_on_sliceedge[TWIST_B2][sl] =
- twist_on_sliceedge[TWIST_B][(int)twist_on_sliceedge[TWIST_B][sl]];
- twist_on_sliceedge[TWIST_L2][sl] =
- twist_on_sliceedge[TWIST_L][(int)twist_on_sliceedge[TWIST_L][sl]];
- twist_on_sliceedge[TWIST_D2][sl] =
- twist_on_sliceedge[TWIST_D][(int)twist_on_sliceedge[TWIST_D][sl]];
- }
- for (sl = 0; sl < N_SLICEEDGE; sl++)
- {
- twist_on_sliceedge[TWIST_F3][sl] =
- twist_on_sliceedge[TWIST_F2][(int)twist_on_sliceedge[TWIST_F][sl]];
- twist_on_sliceedge[TWIST_R3][sl] =
- twist_on_sliceedge[TWIST_R2][(int)twist_on_sliceedge[TWIST_R][sl]];
- twist_on_sliceedge[TWIST_U3][sl] =
- twist_on_sliceedge[TWIST_U2][(int)twist_on_sliceedge[TWIST_U][sl]];
- twist_on_sliceedge[TWIST_B3][sl] =
- twist_on_sliceedge[TWIST_B2][(int)twist_on_sliceedge[TWIST_B][sl]];
- twist_on_sliceedge[TWIST_L3][sl] =
- twist_on_sliceedge[TWIST_L2][(int)twist_on_sliceedge[TWIST_L][sl]];
- twist_on_sliceedge[TWIST_D3][sl] =
- twist_on_sliceedge[TWIST_D2][(int)twist_on_sliceedge[TWIST_D][sl]];
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int make_current(int corner, int edge, Search_data *p_data)
- /* ------------------------------------------------------------------------- */
-
- {
- if (DIST(corner, edge) > p_data->depth)
- {
- if (edge & 0x1)
- {
- distance[corner][edge >> 1] &= 0x0F;
- distance[corner][edge >> 1] |= (unsigned char)((p_data->depth) << 4);
- }
- else
- {
- distance[corner][edge >> 1] &= 0xF0;
- distance[corner][edge >> 1] |= (unsigned char)(p_data->depth);
- }
-
- p_data->found_quot++;
- p_data->found += (p_data->multiplicities)[edge];
-
- return 1;
- }
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void make_current_all(int corner, int edge, Search_data *p_data)
- /* ------------------------------------------------------------------------- */
-
- {
- int sym, stab;
-
-
- if (make_current(corner, edge, p_data))
- {
- stab = (p_data->stabilizers)[edge];
- for (sym = 1; sym < N_SYM; sym++)
- {
- stab /= 2;
-
- if (stab % 2)
- make_current((int)sym_on_corner[sym][corner], edge, p_data);
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void make_neighbors_current(int corner, int edge, Search_data *p_data)
- /* ------------------------------------------------------------------------- */
-
- {
- int twist, new_edge, new_corner, sym;
-
-
- for (twist = 0; twist < N_TWIST; twist++)
- {
- if (p_current_metric->twist_length[twist] != 1)
- continue;
-
- new_edge = (int)twist_on_edge[twist][edge];
- sym = (int)twist_x_edge_to_sym[twist][edge];
- new_corner = (int)sym_on_corner[sym][(int)twist_on_corner[twist][corner]];
- make_current_all(new_corner, new_edge, p_data);
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int neighbors_are_previous(int corner, int edge, Search_data *p_data)
- /* ------------------------------------------------------------------------- */
-
- {
- int twist, new_edge, sym, new_corner;
-
-
- for (twist = 0; twist < N_TWIST; twist++)
- {
- if (p_current_metric->twist_length[twist] != 1)
- continue;
-
- new_edge = (int)twist_on_edge[twist][edge];
- sym = (int)twist_x_edge_to_sym[twist][edge];
- new_corner = (int)sym_on_corner[sym][(int)twist_on_corner[twist][corner]];
-
- if (DIST(new_corner, new_edge) < p_data->depth)
- return 1;
- }
-
- return 0;
- }
-
-
- /* ========================================================================= */
- void init_distance_table(int edge_stabilizers[N_EDGEQUOT],
- int edge_multiplicities[N_EDGEQUOT])
- /* ------------------------------------------------------------------------- */
-
- {
- Search_data sdata_struc;
- int total_found_quot, corner, edge, ii, msg_given;
-
-
- /* allocate and initialize global array distance */
-
- distance[0] = (unsigned char *)malloc(sizeof(unsigned char [N_DIST_CHARS]));
- if (distance[0] == NULL)
- exit_w_error_message("init_distance_table : couldn't get memory");
-
- for (corner = 1; corner < N_CORNER; corner++)
- distance[corner] = &distance[0][corner * (N_EDGEQUOT / 2)];
-
- for (ii = 0; ii < N_DIST_CHARS; ii++)
- distance[0][ii] = (unsigned char)255;
-
- msg_given = 0;
-
- sdata_struc.depth = 0;
- sdata_struc.found_quot = 0;
- sdata_struc.found = 0;
- sdata_struc.stabilizers = edge_stabilizers;
- sdata_struc.multiplicities = edge_multiplicities;
- total_found_quot = 0;
-
- printf("distance positions (quotient)\n");
-
- make_current_all(CORNER_START, EDGE_START, &sdata_struc);
-
- while (sdata_struc.found)
- {
- printf("%7d%c %13d (%8d)\n", sdata_struc.depth,
- p_current_metric->metric_char, sdata_struc.found,
- sdata_struc.found_quot);
- total_found_quot += sdata_struc.found_quot;
- sdata_struc.found_quot = 0;
- sdata_struc.found = 0;
-
- if (++(sdata_struc.depth) == 15)
- break; /* shouldn't happen */
-
- if (total_found_quot == 2 * N_DIST_CHARS)
- break;
-
- if (total_found_quot < BACKWARDS_SWITCH_POINT) /* search forward */
- {
- for (corner = 0; corner < N_CORNER; corner++)
- for (edge = 0; edge < N_EDGEQUOT; edge++)
- if (DIST(corner, edge) == sdata_struc.depth - 1)
- make_neighbors_current(corner, edge, &sdata_struc);
- }
- else /* search backward */
- {
- if (msg_given == 0)
- {
- printf(" switching to backwards searching\n");
- msg_given = 1;
- }
-
- for (corner = 0; corner < N_CORNER; corner++)
- for (edge = 0; edge < N_EDGEQUOT; edge++)
- if ((DIST(corner, edge) == 15) &&
- neighbors_are_previous(corner, edge, &sdata_struc))
- make_current_all(corner, edge, &sdata_struc);
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void init_globals(void)
- /* ------------------------------------------------------------------------- */
-
- {
- int *edge_stabilizers;
- int *edge_multiplicities;
-
-
- printf("initializing transformation tables\n");
- init_sym_x_invsym_to_sym();
- init_invsym_on_twist();
- init_twist_on_follow();
- init_twist_on_corner();
- init_sym_on_corner();
-
- edge_stabilizers = (int *)malloc(sizeof(int [2 * N_EDGEQUOT]));
- if (edge_stabilizers == NULL)
- exit_w_error_message("init_globals : couldn't get memory");
-
- edge_multiplicities = &edge_stabilizers[N_EDGEQUOT];
-
- init_edge_quotient(edge_stabilizers, edge_multiplicities);
- init_twist_on_cornerperm();
- init_twist_on_sliceedge();
- printf("initializing distance table ... this will take several minutes\n");
- init_distance_table(edge_stabilizers, edge_multiplicities);
-
- free((void *)edge_stabilizers);
-
- return;
- }
-
-
- /* ========================================================================= */
- int string_to_cube(char string[], Cube *p_cube, int give_err_msg)
- /* ------------------------------------------------------------------------- */
-
- /* input: string[] */
-
- {
- char edge_str[12][3], corner_str[8][4];
- int edge_arr[12], corner_arr[8];
- int ii, jj, twist, flip, edge_par, corner_par, stat;
-
-
- stat = 0;
-
- if (sscanf(string, "%2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %3s %3s %3s %3s %3s %3s %3s %3s",
- edge_str[0], edge_str[1], edge_str[2], edge_str[3],
- edge_str[4], edge_str[5], edge_str[6], edge_str[7],
- edge_str[8], edge_str[9], edge_str[10], edge_str[11],
- corner_str[0], corner_str[1], corner_str[2], corner_str[3],
- corner_str[4], corner_str[5], corner_str[6], corner_str[7]) < 20)
- {
- if (give_err_msg)
- printf("invalid input!\n");
- return 1;
- }
-
- for (ii = 0; ii < 12; ii++)
- {
- for (jj = 0; jj < 24; jj++)
- if (strcmp(edge_str[ii], edge_cubie_str[jj]) == 0)
- {
- p_cube->edges[ii] = jj;
- break;
- }
- if (jj == 24)
- {
- if (give_err_msg)
- printf("invalid edge cubie: %s\n", edge_str[ii]);
- stat = 1;
- }
- }
-
- for (ii = 0; ii < 8; ii++)
- {
- for (jj = 0; jj < 24; jj++)
- if (strcmp(corner_str[ii], corner_cubie_str[jj]) == 0)
- {
- p_cube->corners[ii] = jj;
- break;
- }
- if (jj == 24)
- {
- if (give_err_msg)
- printf("invalid corner cubie: %s\n", corner_str[ii]);
- stat = 1;
- }
- }
-
- if (stat)
- return stat;
-
- /* fill out the remaining oriented edges and corners */
-
- for (ii = 12; ii < 24; ii++)
- p_cube->edges[ii] = (12 + p_cube->edges[ii - 12]) % 24;
-
- for (ii = 8; ii < 24; ii++)
- p_cube->corners[ii] = (8 + p_cube->corners[ii - 8]) % 24;
-
- /* now check to see that it's a legal cube */
-
- if (perm_n_check(24, p_cube->edges))
- {
- if (give_err_msg)
- printf("bad edge cubies\n");
- stat = 1;
- }
-
- if (perm_n_check(24, p_cube->corners))
- {
- if (give_err_msg)
- printf("bad corner cubies\n");
- stat = 1;
- }
-
- if (stat)
- return stat;
-
- flip = 0;
- for (ii = 0; ii < 12; ii++)
- flip += (p_cube->edges[ii] / 12);
-
- if ((flip % 2) != 0)
- {
- if (give_err_msg)
- printf("flip any edge cubie!\n");
- stat = 1;
- }
-
- twist = 0;
- for (ii = 0; ii < 8; ii++)
- twist += (p_cube->corners[ii] / 8);
-
- twist %= 3;
-
- if (twist != 0)
- {
- if (give_err_msg)
- printf("twist any corner cubie %sclockwise!\n",
- (twist == 1) ? "counter" : "");
- stat = 1;
- }
-
- for (ii = 0; ii < 12; ii++)
- edge_arr[ii] = p_cube->edges[ii] % 12;
-
- edge_par = perm_n_parity(12, edge_arr);
-
- for (ii = 0; ii < 8; ii++)
- corner_arr[ii] = p_cube->corners[ii] % 8;
-
- corner_par = perm_n_parity(8, corner_arr);
-
- if (edge_par != corner_par)
- {
- if (give_err_msg)
- printf("swap any two edge cubies or any two corner cubies!\n");
- stat = 1;
- }
-
- return stat;
- }
-
-
- /* ========================================================================= */
- int user_enters_cube(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- char line_str[256];
-
-
- printf("\nenter cube (Ctrl-D to exit):\n");
-
- line_str[0] = '\n';
-
- while (line_str[0] == '\n') /* ignore blank lines */
- {
- if (fgets(line_str, 256, stdin) == NULL)
- return -1;
-
- if (line_str[0] == '%') /* echo comments */
- {
- printf("%s", line_str);
- line_str[0] = '\n';
- }
- }
-
- return string_to_cube(line_str, p_cube, 1);
- }
-
-
- /* ========================================================================= */
- void calc_cube_urf(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- cube_init(p_cube);
- three_cycle(p_cube->edges, EDGE_UF, EDGE_FR, EDGE_RU);
- three_cycle(p_cube->edges, EDGE_UB, EDGE_FL, EDGE_RD);
- three_cycle(p_cube->edges, EDGE_DB, EDGE_BL, EDGE_LD);
- three_cycle(p_cube->edges, EDGE_DF, EDGE_BR, EDGE_LU);
- three_cycle(p_cube->edges, EDGE_FU, EDGE_RF, EDGE_UR);
- three_cycle(p_cube->edges, EDGE_BU, EDGE_LF, EDGE_DR);
- three_cycle(p_cube->edges, EDGE_BD, EDGE_LB, EDGE_DL);
- three_cycle(p_cube->edges, EDGE_FD, EDGE_RB, EDGE_UL);
- three_cycle(p_cube->corners, CORNER_UFR, CORNER_FRU, CORNER_RUF);
- three_cycle(p_cube->corners, CORNER_DLB, CORNER_BDL, CORNER_LBD);
- three_cycle(p_cube->corners, CORNER_URB, CORNER_FUL, CORNER_RFD);
- three_cycle(p_cube->corners, CORNER_UBL, CORNER_FLD, CORNER_RDB);
- three_cycle(p_cube->corners, CORNER_RBU, CORNER_ULF, CORNER_FDR);
- three_cycle(p_cube->corners, CORNER_BLU, CORNER_LDF, CORNER_DBR);
- three_cycle(p_cube->corners, CORNER_BUR, CORNER_LFU, CORNER_DRF);
- three_cycle(p_cube->corners, CORNER_LUB, CORNER_DFL, CORNER_BRD);
-
- return;
- }
-
-
- /* ========================================================================= */
- void cube_to_coset_coord(Cube *p_cube, Coset_coord *p_coset_coord)
- /* ------------------------------------------------------------------------- */
-
- /* output: *p_coset_coord */
-
- {
- int corner_arr[8], edge_arr[12];
- int ii, eflip, eloc, sym, corner;
-
-
- for (ii = 0; ii < 12; ii++)
- edge_arr[ii] = p_cube->edges[ii] / 12;
- eflip = eflip_pack(edge_arr);
-
- for (ii = 0; ii < 12; ii++)
- edge_arr[ii] = (p_cube->edges[ii] % 12) / 8;
- eloc = eloc_pack(edge_arr);
-
- p_coset_coord->edge_state = (int)fulledge_to_edge[eloc * N_EFLIP + eflip];
- p_coset_coord->sym_state = sym = (int)fulledge_to_sym[eloc * N_EFLIP + eflip];
-
- for (ii = 0; ii < 8; ii++)
- corner_arr[ii] = p_cube->corners[ii] / 8;
-
- corner = corner_pack(corner_arr);
- p_coset_coord->corner_state =
- (int)sym_on_corner[(int)sym_x_invsym_to_sym[0][sym]][corner];
-
- return;
- }
-
-
- /* ========================================================================= */
- void process_full_cube(Full_cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- Cube cube1, cube2, cube_urf;
- int edges_to_ud[12], edges_to_rl[12], edges_to_fb[12];
- int cornerperm_arr[8], sliceedge_arr[12], ii;
-
-
- /* p_cube->cubies already filled in */
- /* fill in other fields of p_cube */
-
- for (ii = 0; ii < 8; ii++)
- cornerperm_arr[ii] = p_cube->cubies.corners[ii] % 8;
-
- p_cube->cornerperm = cornerperm_pack(cornerperm_arr);
- p_cube->parity = perm_n_parity(8, cornerperm_arr);
-
-
- for (ii = 0; ii < 12; ii++)
- edges_to_ud[ii] = edges_to_fb[ii] = edges_to_rl[ii] = 0;
-
- edges_to_ud[EDGE_FR] = 1;
- edges_to_ud[EDGE_FL] = 2;
- edges_to_ud[EDGE_BR] = 3;
- edges_to_ud[EDGE_BL] = 4;
-
- edges_to_rl[EDGE_UF] = 1;
- edges_to_rl[EDGE_UB] = 2;
- edges_to_rl[EDGE_DF] = 3;
- edges_to_rl[EDGE_DB] = 4;
-
- edges_to_fb[EDGE_UR] = 1;
- edges_to_fb[EDGE_UL] = 2;
- edges_to_fb[EDGE_DR] = 3;
- edges_to_fb[EDGE_DL] = 4;
-
-
- for (ii = 0; ii < 12; ii++)
- sliceedge_arr[ii] = edges_to_ud[(p_cube->cubies.edges[ii]) % 12];
- p_cube->ud_sliceedge = sliceedge_pack(sliceedge_arr);
-
- for (ii = 0; ii < 12; ii++)
- sliceedge_arr[ii] = edges_to_fb[(p_cube->cubies.edges[ii]) % 12];
- p_cube->fb_sliceedge = sliceedge_pack(sliceedge_arr);
-
- for (ii = 0; ii < 12; ii++)
- sliceedge_arr[ii] = edges_to_rl[(p_cube->cubies.edges[ii]) % 12];
- p_cube->rl_sliceedge = sliceedge_pack(sliceedge_arr);
-
-
- cube_to_coset_coord(&p_cube->cubies, &p_cube->ud);
-
- calc_cube_urf(&cube_urf);
-
- cube_conjugate(&p_cube->cubies, &cube_urf, &cube1);
- cube_to_coset_coord(&cube1, &p_cube->rl);
-
- cube_conjugate(&cube1, &cube_urf, &cube2);
- cube_to_coset_coord(&cube2, &p_cube->fb);
-
- return;
- }
-
-
- /* ========================================================================= */
- void set_cube_symmetry(Full_cube *p_cube, Cube sym_cubes[N_CUBESYM],
- int subgroup_list[N_SYMSUBGRP][N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- {
- Cube temp_cube;
- int subgroup[N_CUBESYM], sym, count;
-
-
- if (p_current_options->use_symmetry)
- {
- count = 0;
-
- for (sym = 0; sym < N_CUBESYM; sym++)
- {
- cube_conjugate(&p_cube->cubies, &sym_cubes[sym], &temp_cube);
- subgroup[sym] = (cube_compare(&p_cube->cubies, &temp_cube) == 0);
- if (subgroup[sym])
- count++;
- }
-
- p_cube->sym_subgrp = which_subgroup(subgroup, subgroup_list);
-
- if (p_cube->sym_subgrp < 0)
- exit_w_error_message("set_cube_symmetry : unknown symmetry group");
-
- if (count > 1)
- printf("position has %d-fold symmetry (subgroup #%d)\n", count,
- p_cube->sym_subgrp);
- else
- printf("asymmetric position\n");
- }
- else
- p_cube->sym_subgrp = SUBGRP_TRIVIAL;
-
- return;
- }
-
-
- /* ========================================================================= */
- void output_solution(Search_node *node_arr)
- /* ------------------------------------------------------------------------- */
-
- {
- static char *twist_string[] = {"F ", "F2", "F'", "R ", "R2", "R'",
- "U ", "U2", "U'", "B ", "B2", "B'",
- "L ", "L2", "L'", "D ", "D2", "D'"};
- Search_node *p_node;
- int turn_list[MAX_TWISTS];
- int ii, count, q_length, f_length;
-
-
- count = 0;
-
- for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
- turn_list[count++] = p_node[1].twist;
-
- q_length = f_length = 0;
-
- for (ii = 0; ii < count; ii++)
- {
- q_length += metric_q_length(turn_list[ii]);
- f_length += metric_f_length(turn_list[ii]);
- }
-
- for (ii = 0; ii < count; ii++)
- printf(" %s", twist_string[turn_list[ii]]);
-
- if (p_current_metric->metric == QUARTER_TURN_METRIC)
- printf(" (%dq*, %df)\n", q_length, f_length);
- else
- printf(" (%df*, %dq)\n", f_length, q_length);
- fflush(stdout);
-
- sol_found = 1;
-
- return;
- }
-
-
- /* ========================================================================= */
- int test_for_solution(Full_cube *p_cube, Search_node *node_arr)
- /* ------------------------------------------------------------------------- */
-
- {
- register Search_node *p_node;
- register int cornerperm, sliceedge;
-
-
- n_tests++;
-
- cornerperm = p_cube->cornerperm;
- for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
- cornerperm = (int)twist_on_cornerperm[p_node[1].twist][cornerperm];
-
- if (cornerperm != CORNERPERM_START)
- return 0; /* not a solution */
-
- sliceedge = p_cube->ud_sliceedge;
- for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
- sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
-
- if (sliceedge != UD_SLICEEDGE_START)
- return 0; /* not a solution */
-
- sliceedge = p_cube->rl_sliceedge;
- for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
- sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
-
- if (sliceedge != RL_SLICEEDGE_START)
- return 0; /* not a solution */
-
- sliceedge = p_cube->fb_sliceedge;
- for (p_node = node_arr; p_node->remain_depth > 0; p_node++)
- sliceedge = (int)twist_on_sliceedge[p_node[1].twist][sliceedge];
-
- if (sliceedge != FB_SLICEEDGE_START)
- return 0; /* not a solution */
-
- output_solution(node_arr); /* solution ! */
-
- return 1;
- }
-
-
- /* ========================================================================= */
- void search_tree(Full_cube *p_cube, Search_node *node_arr)
- /* ------------------------------------------------------------------------- */
-
- {
- register Search_node *p_node;
- register int twist, virtual_twist, new_sym_factor;
-
-
- p_node = node_arr;
-
- while (p_node >= node_arr)
- {
- if (p_node->remain_depth == 0)
- {
- if (test_for_solution(p_cube, node_arr) &&
- p_current_options->one_solution_only)
- return;
- p_node--;
- }
- else
- {
- for (twist = p_node[1].twist + 1; twist < N_TWIST; twist++)
- {
- p_node[1].follow_type =
- (int)twist_on_follow[twist][p_node->follow_type];
-
- if (p_node[1].follow_type == FOLLOW_INVALID)
- continue;
-
- p_node[1].remain_depth = p_node->remain_depth -
- p_current_metric->twist_length[twist];
- if (p_node[1].remain_depth < 0)
- continue;
-
- n_nodes++;
-
- virtual_twist =
- (int)invsym_on_twist_ud[p_node->ud.sym_state][twist];
- new_sym_factor =
- (int)twist_x_edge_to_sym[virtual_twist][p_node->ud.edge_state];
- p_node[1].ud.edge_state =
- (int)twist_on_edge[virtual_twist][p_node->ud.edge_state];
- p_node[1].ud.sym_state =
- (int)sym_x_invsym_to_sym[p_node->ud.sym_state][new_sym_factor];
- p_node[1].ud.corner_state = (int)sym_on_corner[new_sym_factor]
- [(int)twist_on_corner[virtual_twist][p_node->ud.corner_state]];
-
- if (p_node[1].remain_depth <
- DIST(p_node[1].ud.corner_state, p_node[1].ud.edge_state))
- continue;
-
-
- virtual_twist =
- (int)invsym_on_twist_rl[p_node->rl.sym_state][twist];
- new_sym_factor =
- (int)twist_x_edge_to_sym[virtual_twist][p_node->rl.edge_state];
- p_node[1].rl.edge_state =
- (int)twist_on_edge[virtual_twist][p_node->rl.edge_state];
- p_node[1].rl.sym_state =
- (int)sym_x_invsym_to_sym[p_node->rl.sym_state][new_sym_factor];
- p_node[1].rl.corner_state = (int)sym_on_corner[new_sym_factor]
- [(int)twist_on_corner[virtual_twist][p_node->rl.corner_state]];
-
- if (p_node[1].remain_depth <
- DIST(p_node[1].rl.corner_state, p_node[1].rl.edge_state))
- continue;
-
-
- virtual_twist =
- (int)invsym_on_twist_fb[p_node->fb.sym_state][twist];
- new_sym_factor =
- (int)twist_x_edge_to_sym[virtual_twist][p_node->fb.edge_state];
- p_node[1].fb.edge_state =
- (int)twist_on_edge[virtual_twist][p_node->fb.edge_state];
- p_node[1].fb.sym_state =
- (int)sym_x_invsym_to_sym[p_node->fb.sym_state][new_sym_factor];
- p_node[1].fb.corner_state = (int)sym_on_corner[new_sym_factor]
- [(int)twist_on_corner[virtual_twist][p_node->fb.corner_state]];
-
- if (p_node[1].remain_depth <
- DIST(p_node[1].fb.corner_state, p_node[1].fb.edge_state))
- continue;
-
-
- p_node[1].twist = twist;
- break;
- }
-
- if (twist == N_TWIST)
- p_node--;
- else
- {
- p_node++;
- p_node[1].twist = -1;
- }
- }
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void calc_sym_cubes(Cube sym_conj[N_CUBESYM])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- cube_init(&sym_conj[0]);
- cube_init(&sym_conj[1]);
-
- four_cycle(sym_conj[1].edges, EDGE_UF, EDGE_UL, EDGE_UB, EDGE_UR);
- four_cycle(sym_conj[1].edges, EDGE_DF, EDGE_DL, EDGE_DB, EDGE_DR);
- four_cycle(sym_conj[1].edges, EDGE_FR, EDGE_LF, EDGE_BL, EDGE_RB);
- four_cycle(sym_conj[1].edges, EDGE_FU, EDGE_LU, EDGE_BU, EDGE_RU);
- four_cycle(sym_conj[1].edges, EDGE_FD, EDGE_LD, EDGE_BD, EDGE_RD);
- four_cycle(sym_conj[1].edges, EDGE_RF, EDGE_FL, EDGE_LB, EDGE_BR);
- four_cycle(sym_conj[1].corners, CORNER_UFR, CORNER_ULF, CORNER_UBL, CORNER_URB);
- four_cycle(sym_conj[1].corners, CORNER_DRF, CORNER_DFL, CORNER_DLB, CORNER_DBR);
- four_cycle(sym_conj[1].corners, CORNER_FRU, CORNER_LFU, CORNER_BLU, CORNER_RBU);
- four_cycle(sym_conj[1].corners, CORNER_RFD, CORNER_FLD, CORNER_LBD, CORNER_BRD);
- four_cycle(sym_conj[1].corners, CORNER_RUF, CORNER_FUL, CORNER_LUB, CORNER_BUR);
- four_cycle(sym_conj[1].corners, CORNER_FDR, CORNER_LDF, CORNER_BDL, CORNER_RDB);
-
- for (ii = 2; ii < 4; ii++)
- cube_compose(&sym_conj[1], &sym_conj[ii - 1], &sym_conj[ii]);
-
- cube_init(&sym_conj[4]);
-
- two_cycle(sym_conj[4].edges, EDGE_UF, EDGE_DF);
- two_cycle(sym_conj[4].edges, EDGE_UR, EDGE_DL);
- two_cycle(sym_conj[4].edges, EDGE_UB, EDGE_DB);
- two_cycle(sym_conj[4].edges, EDGE_UL, EDGE_DR);
- two_cycle(sym_conj[4].edges, EDGE_FR, EDGE_FL);
- two_cycle(sym_conj[4].edges, EDGE_BR, EDGE_BL);
- two_cycle(sym_conj[4].edges, EDGE_FU, EDGE_FD);
- two_cycle(sym_conj[4].edges, EDGE_RU, EDGE_LD);
- two_cycle(sym_conj[4].edges, EDGE_BU, EDGE_BD);
- two_cycle(sym_conj[4].edges, EDGE_LU, EDGE_RD);
- two_cycle(sym_conj[4].edges, EDGE_RF, EDGE_LF);
- two_cycle(sym_conj[4].edges, EDGE_RB, EDGE_LB);
- two_cycle(sym_conj[4].corners, CORNER_UFR, CORNER_DFL);
- two_cycle(sym_conj[4].corners, CORNER_ULF, CORNER_DRF);
- two_cycle(sym_conj[4].corners, CORNER_UBL, CORNER_DBR);
- two_cycle(sym_conj[4].corners, CORNER_URB, CORNER_DLB);
- two_cycle(sym_conj[4].corners, CORNER_FRU, CORNER_FLD);
- two_cycle(sym_conj[4].corners, CORNER_LFU, CORNER_RFD);
- two_cycle(sym_conj[4].corners, CORNER_BLU, CORNER_BRD);
- two_cycle(sym_conj[4].corners, CORNER_RBU, CORNER_LBD);
- two_cycle(sym_conj[4].corners, CORNER_RUF, CORNER_LDF);
- two_cycle(sym_conj[4].corners, CORNER_FUL, CORNER_FDR);
- two_cycle(sym_conj[4].corners, CORNER_LUB, CORNER_RDB);
- two_cycle(sym_conj[4].corners, CORNER_BUR, CORNER_BDL);
-
- for (ii = 5; ii < 8; ii++)
- cube_compose(&sym_conj[4], &sym_conj[ii - 4], &sym_conj[ii]);
-
- cube_init(&sym_conj[8]);
-
- two_cycle(sym_conj[8].edges, EDGE_UF, EDGE_DF);
- two_cycle(sym_conj[8].edges, EDGE_UR, EDGE_DR);
- two_cycle(sym_conj[8].edges, EDGE_UB, EDGE_DB);
- two_cycle(sym_conj[8].edges, EDGE_UL, EDGE_DL);
- two_cycle(sym_conj[8].edges, EDGE_FU, EDGE_FD);
- two_cycle(sym_conj[8].edges, EDGE_RU, EDGE_RD);
- two_cycle(sym_conj[8].edges, EDGE_BU, EDGE_BD);
- two_cycle(sym_conj[8].edges, EDGE_LU, EDGE_LD);
- two_cycle(sym_conj[8].corners, CORNER_UFR, CORNER_DRF);
- two_cycle(sym_conj[8].corners, CORNER_ULF, CORNER_DFL);
- two_cycle(sym_conj[8].corners, CORNER_UBL, CORNER_DLB);
- two_cycle(sym_conj[8].corners, CORNER_URB, CORNER_DBR);
- two_cycle(sym_conj[8].corners, CORNER_FRU, CORNER_FDR);
- two_cycle(sym_conj[8].corners, CORNER_LFU, CORNER_LDF);
- two_cycle(sym_conj[8].corners, CORNER_BLU, CORNER_BDL);
- two_cycle(sym_conj[8].corners, CORNER_RBU, CORNER_RDB);
- two_cycle(sym_conj[8].corners, CORNER_RUF, CORNER_RFD);
- two_cycle(sym_conj[8].corners, CORNER_FUL, CORNER_FLD);
- two_cycle(sym_conj[8].corners, CORNER_LUB, CORNER_LBD);
- two_cycle(sym_conj[8].corners, CORNER_BUR, CORNER_BRD);
-
- for (ii = 9; ii < 16; ii++)
- cube_compose(&sym_conj[8], &sym_conj[ii - 8], &sym_conj[ii]);
-
- calc_cube_urf(&sym_conj[16]);
-
- for (ii = 17; ii < 48; ii++)
- cube_compose(&sym_conj[16], &sym_conj[ii - 16], &sym_conj[ii]);
-
- return;
- }
-
-
- /* ========================================================================= */
- void pretty_print_unsigned_int(unsigned int nn)
- /* ------------------------------------------------------------------------- */
-
- {
- int digits[4], ii, started;
-
-
- for (ii = 0; ii < 4; ii++)
- {
- digits[ii] = nn % 1000;
- nn /= 1000;
- }
-
- started = 0;
-
- for (ii = 3; ii >= 0; ii--)
- {
- if (started)
- {
- if (digits[ii] >= 100)
- printf("%3d", digits[ii]);
- else if (digits[ii] >= 10)
- printf("0%2d", digits[ii]);
- else
- printf("00%1d", digits[ii]);
- }
- else
- {
- if (digits[ii] >= 100)
- {
- printf("%3d", digits[ii]);
- started = 1;
- }
- else if (digits[ii] >= 10)
- {
- printf(" %2d", digits[ii]);
- started = 1;
- }
- else if ((digits[ii] >= 1) || (ii == 0))
- {
- printf(" %1d", digits[ii]);
- started = 1;
- }
- else
- printf(" ");
- }
-
- if (ii > 0)
- printf("%c", started ? ',' : ' ');
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- void solve_cube(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- static Cube sym_cubes[N_CUBESYM];
- static int subgroup_list[N_SYMSUBGRP][N_CUBESYM];
- static int initialized = 0;
- Full_cube full_cube_struct;
- Search_node node_arr[MAX_TWISTS];
- int ii, start_depth, search_limit;
-
-
- if (initialized == 0)
- {
- calc_sym_cubes(sym_cubes);
- calc_subgroup_list(subgroup_list);
- initialized = 1;
- }
-
- print_cube(p_cube);
- if (cube_is_solved(p_cube))
- {
- printf("cube is already solved!\n");
- return;
- }
-
- cube_conjugate(p_cube, &sym_cubes[0], &full_cube_struct.cubies);
- process_full_cube(&full_cube_struct);
-
- set_cube_symmetry(&full_cube_struct, sym_cubes, subgroup_list);
-
- node_arr[0].follow_type = 1 + full_cube_struct.sym_subgrp;
- node_arr[0].ud.corner_state = full_cube_struct.ud.corner_state;
- node_arr[0].ud.edge_state = full_cube_struct.ud.edge_state;
- node_arr[0].ud.sym_state = full_cube_struct.ud.sym_state;
-
- node_arr[0].rl.corner_state = full_cube_struct.rl.corner_state;
- node_arr[0].rl.edge_state = full_cube_struct.rl.edge_state;
- node_arr[0].rl.sym_state = full_cube_struct.rl.sym_state;
-
- node_arr[0].fb.corner_state = full_cube_struct.fb.corner_state;
- node_arr[0].fb.edge_state = full_cube_struct.fb.edge_state;
- node_arr[0].fb.sym_state = full_cube_struct.fb.sym_state;
-
- sol_found = 0;
- if ((p_current_metric->metric == QUARTER_TURN_METRIC) &&
- (full_cube_struct.parity == 0))
- start_depth = 2;
- else
- start_depth = 1;
-
- search_limit = p_current_options->search_limit;
- if ((search_limit <= 0) || (search_limit >= MAX_TWISTS))
- search_limit = MAX_TWISTS - 1;
-
- for (ii = start_depth; ii <= search_limit; ii += p_current_metric->increment)
- {
- n_nodes = (long long int)0;
- n_tests = (unsigned int)0;
- node_arr[0].remain_depth = ii;
- node_arr[1].twist = -1;
- search_tree(&full_cube_struct, node_arr);
-
- if ((p_current_options->one_solution_only == 0) || (sol_found == 0))
- {
- printf("depth %2d%c completed (", ii, p_current_metric->metric_char);
- pretty_print_unsigned_int(n_nodes);
- printf(" nodes, ");
- pretty_print_unsigned_int(n_tests);
- printf(" tests)\n");
- fflush(stdout);
- }
-
- if (sol_found)
- break;
- }
-
- return;
- }
-
-
- /* ========================================================================= */
- int main(void)
- /* ------------------------------------------------------------------------- */
-
- {
- Metric_data metric_data;
- Options user_options;
- Cube cube_struct;
- int stat;
-
-
- init_options(&metric_data, &user_options);
- init_globals();
-
- signal(SIGINT, SIG_IGN);
-
- while (1)
- {
- stat = user_enters_cube(&cube_struct);
- if (stat < 0)
- break;
-
- if (stat == 0)
- {
- if (sigsetjmp(jump_env, 1) == 0)
- {
- signal(SIGINT, user_interrupt);
- solve_cube(&cube_struct);
- }
-
- signal(SIGINT, SIG_IGN);
- }
- }
-
- exit(EXIT_SUCCESS);
-
- return 0; /* haha */
- }
|