isl_space.c 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366
  1. /*
  2. * Copyright 2008-2009 Katholieke Universiteit Leuven
  3. * Copyright 2010 INRIA Saclay
  4. * Copyright 2013-2014 Ecole Normale Superieure
  5. * Copyright 2018-2019 Cerebras Systems
  6. *
  7. * Use of this software is governed by the MIT license
  8. *
  9. * Written by Sven Verdoolaege, K.U.Leuven, Departement
  10. * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
  11. * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
  12. * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
  13. * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
  14. * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  15. */
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <isl_space_private.h>
  19. #include <isl_id_private.h>
  20. #include <isl_reordering.h>
  21. isl_ctx *isl_space_get_ctx(__isl_keep isl_space *space)
  22. {
  23. return space ? space->ctx : NULL;
  24. }
  25. __isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
  26. unsigned nparam, unsigned n_in, unsigned n_out)
  27. {
  28. isl_space *space;
  29. space = isl_alloc_type(ctx, struct isl_space);
  30. if (!space)
  31. return NULL;
  32. space->ctx = ctx;
  33. isl_ctx_ref(ctx);
  34. space->ref = 1;
  35. space->nparam = nparam;
  36. space->n_in = n_in;
  37. space->n_out = n_out;
  38. space->tuple_id[0] = NULL;
  39. space->tuple_id[1] = NULL;
  40. space->nested[0] = NULL;
  41. space->nested[1] = NULL;
  42. space->n_id = 0;
  43. space->ids = NULL;
  44. return space;
  45. }
  46. /* Mark the space as being that of a set, by setting the domain tuple
  47. * to isl_id_none.
  48. */
  49. static __isl_give isl_space *mark_as_set(__isl_take isl_space *space)
  50. {
  51. space = isl_space_cow(space);
  52. if (!space)
  53. return NULL;
  54. space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
  55. return space;
  56. }
  57. /* Is the space that of a set?
  58. */
  59. isl_bool isl_space_is_set(__isl_keep isl_space *space)
  60. {
  61. if (!space)
  62. return isl_bool_error;
  63. if (space->n_in != 0 || space->nested[0])
  64. return isl_bool_false;
  65. if (space->tuple_id[0] != &isl_id_none)
  66. return isl_bool_false;
  67. return isl_bool_true;
  68. }
  69. /* Check that "space" is a set space.
  70. */
  71. isl_stat isl_space_check_is_set(__isl_keep isl_space *space)
  72. {
  73. isl_bool is_set;
  74. is_set = isl_space_is_set(space);
  75. if (is_set < 0)
  76. return isl_stat_error;
  77. if (!is_set)
  78. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  79. "space is not a set", return isl_stat_error);
  80. return isl_stat_ok;
  81. }
  82. /* Is the given space that of a map?
  83. */
  84. isl_bool isl_space_is_map(__isl_keep isl_space *space)
  85. {
  86. int r;
  87. if (!space)
  88. return isl_bool_error;
  89. r = space->tuple_id[0] != &isl_id_none &&
  90. space->tuple_id[1] != &isl_id_none;
  91. return isl_bool_ok(r);
  92. }
  93. /* Check that "space" is the space of a map.
  94. */
  95. static isl_stat isl_space_check_is_map(__isl_keep isl_space *space)
  96. {
  97. isl_bool is_space;
  98. is_space = isl_space_is_map(space);
  99. if (is_space < 0)
  100. return isl_stat_error;
  101. if (!is_space)
  102. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  103. "expecting map space", return isl_stat_error);
  104. return isl_stat_ok;
  105. }
  106. /* Check that "space" is the space of a map
  107. * where the domain is a wrapped map space.
  108. */
  109. isl_stat isl_space_check_domain_is_wrapping(__isl_keep isl_space *space)
  110. {
  111. isl_bool wrapping;
  112. wrapping = isl_space_domain_is_wrapping(space);
  113. if (wrapping < 0)
  114. return isl_stat_error;
  115. if (!wrapping)
  116. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  117. "domain not a product", return isl_stat_error);
  118. return isl_stat_ok;
  119. }
  120. /* Check that "space" is the space of a map
  121. * where the range is a wrapped map space.
  122. */
  123. isl_stat isl_space_check_range_is_wrapping(__isl_keep isl_space *space)
  124. {
  125. isl_bool wrapping;
  126. wrapping = isl_space_range_is_wrapping(space);
  127. if (wrapping < 0)
  128. return isl_stat_error;
  129. if (!wrapping)
  130. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  131. "range not a product", return isl_stat_error);
  132. return isl_stat_ok;
  133. }
  134. __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
  135. unsigned nparam, unsigned dim)
  136. {
  137. isl_space *space;
  138. space = isl_space_alloc(ctx, nparam, 0, dim);
  139. space = mark_as_set(space);
  140. return space;
  141. }
  142. /* Mark the space as being that of a parameter domain, by setting
  143. * both tuples to isl_id_none.
  144. */
  145. static __isl_give isl_space *mark_as_params(isl_space *space)
  146. {
  147. if (!space)
  148. return NULL;
  149. space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
  150. space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
  151. return space;
  152. }
  153. /* Is the space that of a parameter domain?
  154. */
  155. isl_bool isl_space_is_params(__isl_keep isl_space *space)
  156. {
  157. if (!space)
  158. return isl_bool_error;
  159. if (space->n_in != 0 || space->nested[0] ||
  160. space->n_out != 0 || space->nested[1])
  161. return isl_bool_false;
  162. if (space->tuple_id[0] != &isl_id_none)
  163. return isl_bool_false;
  164. if (space->tuple_id[1] != &isl_id_none)
  165. return isl_bool_false;
  166. return isl_bool_true;
  167. }
  168. /* Create a space for a parameter domain.
  169. */
  170. __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
  171. {
  172. isl_space *space;
  173. space = isl_space_alloc(ctx, nparam, 0, 0);
  174. space = mark_as_params(space);
  175. return space;
  176. }
  177. /* Create a space for a parameter domain, without any parameters.
  178. */
  179. __isl_give isl_space *isl_space_unit(isl_ctx *ctx)
  180. {
  181. return isl_space_params_alloc(ctx, 0);
  182. }
  183. static isl_size global_pos(__isl_keep isl_space *space,
  184. enum isl_dim_type type, unsigned pos)
  185. {
  186. if (isl_space_check_range(space, type, pos, 1) < 0)
  187. return isl_size_error;
  188. switch (type) {
  189. case isl_dim_param:
  190. return pos;
  191. case isl_dim_in:
  192. return pos + space->nparam;
  193. case isl_dim_out:
  194. return pos + space->nparam + space->n_in;
  195. default:
  196. isl_assert(isl_space_get_ctx(space), 0, return isl_size_error);
  197. }
  198. return isl_size_error;
  199. }
  200. /* Extend length of ids array to the total number of dimensions.
  201. */
  202. static __isl_give isl_space *extend_ids(__isl_take isl_space *space)
  203. {
  204. isl_id **ids;
  205. int i;
  206. isl_size dim;
  207. dim = isl_space_dim(space, isl_dim_all);
  208. if (dim < 0)
  209. return isl_space_free(space);
  210. if (dim <= space->n_id)
  211. return space;
  212. if (!space->ids) {
  213. space->ids = isl_calloc_array(space->ctx, isl_id *, dim);
  214. if (!space->ids)
  215. goto error;
  216. } else {
  217. ids = isl_realloc_array(space->ctx, space->ids, isl_id *, dim);
  218. if (!ids)
  219. goto error;
  220. space->ids = ids;
  221. for (i = space->n_id; i < dim; ++i)
  222. space->ids[i] = NULL;
  223. }
  224. space->n_id = dim;
  225. return space;
  226. error:
  227. isl_space_free(space);
  228. return NULL;
  229. }
  230. static __isl_give isl_space *set_id(__isl_take isl_space *space,
  231. enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
  232. {
  233. isl_size gpos;
  234. space = isl_space_cow(space);
  235. gpos = global_pos(space, type, pos);
  236. if (gpos < 0)
  237. goto error;
  238. if (gpos >= space->n_id) {
  239. if (!id)
  240. return space;
  241. space = extend_ids(space);
  242. if (!space)
  243. goto error;
  244. }
  245. space->ids[gpos] = id;
  246. return space;
  247. error:
  248. isl_id_free(id);
  249. isl_space_free(space);
  250. return NULL;
  251. }
  252. static __isl_keep isl_id *get_id(__isl_keep isl_space *space,
  253. enum isl_dim_type type, unsigned pos)
  254. {
  255. isl_size gpos;
  256. gpos = global_pos(space, type, pos);
  257. if (gpos < 0)
  258. return NULL;
  259. if (gpos >= space->n_id)
  260. return NULL;
  261. return space->ids[gpos];
  262. }
  263. /* Return the nested space at the given position.
  264. */
  265. static __isl_keep isl_space *isl_space_peek_nested(__isl_keep isl_space *space,
  266. int pos)
  267. {
  268. if (!space)
  269. return NULL;
  270. if (!space->nested[pos])
  271. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  272. "no nested space", return NULL);
  273. return space->nested[pos];
  274. }
  275. static unsigned offset(__isl_keep isl_space *space, enum isl_dim_type type)
  276. {
  277. switch (type) {
  278. case isl_dim_param: return 0;
  279. case isl_dim_in: return space->nparam;
  280. case isl_dim_out: return space->nparam + space->n_in;
  281. default: return 0;
  282. }
  283. }
  284. static unsigned n(__isl_keep isl_space *space, enum isl_dim_type type)
  285. {
  286. switch (type) {
  287. case isl_dim_param: return space->nparam;
  288. case isl_dim_in: return space->n_in;
  289. case isl_dim_out: return space->n_out;
  290. case isl_dim_all:
  291. return space->nparam + space->n_in + space->n_out;
  292. default: return 0;
  293. }
  294. }
  295. isl_size isl_space_dim(__isl_keep isl_space *space, enum isl_dim_type type)
  296. {
  297. if (!space)
  298. return isl_size_error;
  299. return n(space, type);
  300. }
  301. /* Return the dimensionality of tuple "inner" within the wrapped relation
  302. * inside tuple "outer".
  303. */
  304. isl_size isl_space_wrapped_dim(__isl_keep isl_space *space,
  305. enum isl_dim_type outer, enum isl_dim_type inner)
  306. {
  307. int pos;
  308. if (!space)
  309. return isl_size_error;
  310. if (outer != isl_dim_in && outer != isl_dim_out)
  311. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  312. "only input, output and set tuples "
  313. "can have nested relations", return isl_size_error);
  314. pos = outer - isl_dim_in;
  315. return isl_space_dim(isl_space_peek_nested(space, pos), inner);
  316. }
  317. unsigned isl_space_offset(__isl_keep isl_space *space, enum isl_dim_type type)
  318. {
  319. if (!space)
  320. return 0;
  321. return offset(space, type);
  322. }
  323. static __isl_give isl_space *copy_ids(__isl_take isl_space *dst,
  324. enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_space *src,
  325. enum isl_dim_type src_type)
  326. {
  327. int i;
  328. isl_id *id;
  329. if (!dst)
  330. return NULL;
  331. for (i = 0; i < n(src, src_type); ++i) {
  332. id = get_id(src, src_type, i);
  333. if (!id)
  334. continue;
  335. dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
  336. if (!dst)
  337. return NULL;
  338. }
  339. return dst;
  340. }
  341. __isl_take isl_space *isl_space_dup(__isl_keep isl_space *space)
  342. {
  343. isl_space *dup;
  344. if (!space)
  345. return NULL;
  346. dup = isl_space_alloc(space->ctx,
  347. space->nparam, space->n_in, space->n_out);
  348. if (!dup)
  349. return NULL;
  350. if (space->tuple_id[0] &&
  351. !(dup->tuple_id[0] = isl_id_copy(space->tuple_id[0])))
  352. goto error;
  353. if (space->tuple_id[1] &&
  354. !(dup->tuple_id[1] = isl_id_copy(space->tuple_id[1])))
  355. goto error;
  356. if (space->nested[0] &&
  357. !(dup->nested[0] = isl_space_copy(space->nested[0])))
  358. goto error;
  359. if (space->nested[1] &&
  360. !(dup->nested[1] = isl_space_copy(space->nested[1])))
  361. goto error;
  362. if (!space->ids)
  363. return dup;
  364. dup = copy_ids(dup, isl_dim_param, 0, space, isl_dim_param);
  365. dup = copy_ids(dup, isl_dim_in, 0, space, isl_dim_in);
  366. dup = copy_ids(dup, isl_dim_out, 0, space, isl_dim_out);
  367. return dup;
  368. error:
  369. isl_space_free(dup);
  370. return NULL;
  371. }
  372. __isl_give isl_space *isl_space_cow(__isl_take isl_space *space)
  373. {
  374. if (!space)
  375. return NULL;
  376. if (space->ref == 1)
  377. return space;
  378. space->ref--;
  379. return isl_space_dup(space);
  380. }
  381. __isl_give isl_space *isl_space_copy(__isl_keep isl_space *space)
  382. {
  383. if (!space)
  384. return NULL;
  385. space->ref++;
  386. return space;
  387. }
  388. __isl_null isl_space *isl_space_free(__isl_take isl_space *space)
  389. {
  390. int i;
  391. if (!space)
  392. return NULL;
  393. if (--space->ref > 0)
  394. return NULL;
  395. isl_id_free(space->tuple_id[0]);
  396. isl_id_free(space->tuple_id[1]);
  397. isl_space_free(space->nested[0]);
  398. isl_space_free(space->nested[1]);
  399. for (i = 0; i < space->n_id; ++i)
  400. isl_id_free(space->ids[i]);
  401. free(space->ids);
  402. isl_ctx_deref(space->ctx);
  403. free(space);
  404. return NULL;
  405. }
  406. /* Check if "s" is a valid dimension or tuple name.
  407. * We currently only forbid names that look like a number.
  408. *
  409. * s is assumed to be non-NULL.
  410. */
  411. static int name_ok(isl_ctx *ctx, const char *s)
  412. {
  413. char *p;
  414. long dummy;
  415. dummy = strtol(s, &p, 0);
  416. if (p != s)
  417. isl_die(ctx, isl_error_invalid, "name looks like a number",
  418. return 0);
  419. return 1;
  420. }
  421. /* Return a copy of the nested space at the given position.
  422. */
  423. static __isl_keep isl_space *isl_space_get_nested(__isl_keep isl_space *space,
  424. int pos)
  425. {
  426. return isl_space_copy(isl_space_peek_nested(space, pos));
  427. }
  428. /* Return the nested space at the given position.
  429. * This may be either a copy or the nested space itself
  430. * if there is only one reference to "space".
  431. * This allows the nested space to be modified inplace
  432. * if both "space" and the nested space have only a single reference.
  433. * The caller is not allowed to modify "space" between this call and
  434. * a subsequent call to isl_space_restore_nested.
  435. * The only exception is that isl_space_free can be called instead.
  436. */
  437. static __isl_give isl_space *isl_space_take_nested(__isl_keep isl_space *space,
  438. int pos)
  439. {
  440. isl_space *nested;
  441. if (!space)
  442. return NULL;
  443. if (space->ref != 1)
  444. return isl_space_get_nested(space, pos);
  445. nested = space->nested[pos];
  446. space->nested[pos] = NULL;
  447. return nested;
  448. }
  449. /* Replace the nested space at the given position by "nested",
  450. * where this nested space of "space" may be missing
  451. * due to a preceding call to isl_space_take_nested.
  452. * However, in this case, "space" only has a single reference and
  453. * then the call to isl_space_cow has no effect.
  454. */
  455. static __isl_give isl_space *isl_space_restore_nested(
  456. __isl_take isl_space *space, int pos, __isl_take isl_space *nested)
  457. {
  458. if (!space || !nested)
  459. goto error;
  460. if (space->nested[pos] == nested) {
  461. isl_space_free(nested);
  462. return space;
  463. }
  464. space = isl_space_cow(space);
  465. if (!space)
  466. goto error;
  467. isl_space_free(space->nested[pos]);
  468. space->nested[pos] = nested;
  469. return space;
  470. error:
  471. isl_space_free(space);
  472. isl_space_free(nested);
  473. return NULL;
  474. }
  475. /* Is it possible for the given dimension type to have a tuple id?
  476. */
  477. static int space_can_have_id(__isl_keep isl_space *space,
  478. enum isl_dim_type type)
  479. {
  480. if (!space)
  481. return 0;
  482. if (isl_space_is_params(space))
  483. isl_die(space->ctx, isl_error_invalid,
  484. "parameter spaces don't have tuple ids", return 0);
  485. if (isl_space_is_set(space) && type != isl_dim_set)
  486. isl_die(space->ctx, isl_error_invalid,
  487. "set spaces can only have a set id", return 0);
  488. if (type != isl_dim_in && type != isl_dim_out)
  489. isl_die(space->ctx, isl_error_invalid,
  490. "only input, output and set tuples can have ids",
  491. return 0);
  492. return 1;
  493. }
  494. /* Does the tuple have an id?
  495. */
  496. isl_bool isl_space_has_tuple_id(__isl_keep isl_space *space,
  497. enum isl_dim_type type)
  498. {
  499. if (!space_can_have_id(space, type))
  500. return isl_bool_error;
  501. return isl_bool_ok(space->tuple_id[type - isl_dim_in] != NULL);
  502. }
  503. /* Does the domain tuple of the map space "space" have an identifier?
  504. */
  505. isl_bool isl_space_has_domain_tuple_id(__isl_keep isl_space *space)
  506. {
  507. if (isl_space_check_is_map(space) < 0)
  508. return isl_bool_error;
  509. return isl_space_has_tuple_id(space, isl_dim_in);
  510. }
  511. /* Does the range tuple of the map space "space" have an identifier?
  512. */
  513. isl_bool isl_space_has_range_tuple_id(__isl_keep isl_space *space)
  514. {
  515. if (isl_space_check_is_map(space) < 0)
  516. return isl_bool_error;
  517. return isl_space_has_tuple_id(space, isl_dim_out);
  518. }
  519. __isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *space,
  520. enum isl_dim_type type)
  521. {
  522. int has_id;
  523. if (!space)
  524. return NULL;
  525. has_id = isl_space_has_tuple_id(space, type);
  526. if (has_id < 0)
  527. return NULL;
  528. if (!has_id)
  529. isl_die(space->ctx, isl_error_invalid,
  530. "tuple has no id", return NULL);
  531. return isl_id_copy(space->tuple_id[type - isl_dim_in]);
  532. }
  533. /* Return the identifier of the domain tuple of the map space "space",
  534. * assuming it has one.
  535. */
  536. __isl_give isl_id *isl_space_get_domain_tuple_id(
  537. __isl_keep isl_space *space)
  538. {
  539. if (isl_space_check_is_map(space) < 0)
  540. return NULL;
  541. return isl_space_get_tuple_id(space, isl_dim_in);
  542. }
  543. /* Return the identifier of the range tuple of the map space "space",
  544. * assuming it has one.
  545. */
  546. __isl_give isl_id *isl_space_get_range_tuple_id(
  547. __isl_keep isl_space *space)
  548. {
  549. if (isl_space_check_is_map(space) < 0)
  550. return NULL;
  551. return isl_space_get_tuple_id(space, isl_dim_out);
  552. }
  553. __isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *space,
  554. enum isl_dim_type type, __isl_take isl_id *id)
  555. {
  556. space = isl_space_cow(space);
  557. if (!space || !id)
  558. goto error;
  559. if (type != isl_dim_in && type != isl_dim_out)
  560. isl_die(space->ctx, isl_error_invalid,
  561. "only input, output and set tuples can have names",
  562. goto error);
  563. isl_id_free(space->tuple_id[type - isl_dim_in]);
  564. space->tuple_id[type - isl_dim_in] = id;
  565. return space;
  566. error:
  567. isl_id_free(id);
  568. isl_space_free(space);
  569. return NULL;
  570. }
  571. /* Replace the identifier of the domain tuple of the map space "space"
  572. * by "id".
  573. */
  574. __isl_give isl_space *isl_space_set_domain_tuple_id(
  575. __isl_take isl_space *space, __isl_take isl_id *id)
  576. {
  577. if (isl_space_check_is_map(space) < 0)
  578. space = isl_space_free(space);
  579. return isl_space_set_tuple_id(space, isl_dim_in, id);
  580. }
  581. /* Replace the identifier of the range tuple of the map space "space"
  582. * by "id".
  583. */
  584. __isl_give isl_space *isl_space_set_range_tuple_id(
  585. __isl_take isl_space *space, __isl_take isl_id *id)
  586. {
  587. if (isl_space_check_is_map(space) < 0)
  588. space = isl_space_free(space);
  589. return isl_space_set_tuple_id(space, isl_dim_out, id);
  590. }
  591. __isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *space,
  592. enum isl_dim_type type)
  593. {
  594. space = isl_space_cow(space);
  595. if (!space)
  596. return NULL;
  597. if (type != isl_dim_in && type != isl_dim_out)
  598. isl_die(space->ctx, isl_error_invalid,
  599. "only input, output and set tuples can have names",
  600. goto error);
  601. isl_id_free(space->tuple_id[type - isl_dim_in]);
  602. space->tuple_id[type - isl_dim_in] = NULL;
  603. return space;
  604. error:
  605. isl_space_free(space);
  606. return NULL;
  607. }
  608. /* Set the id of the given dimension of "space" to "id".
  609. * If the dimension already has an id, then it is replaced.
  610. * If the dimension is a parameter, then we need to change it
  611. * in the nested spaces (if any) as well.
  612. */
  613. __isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space,
  614. enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
  615. {
  616. space = isl_space_cow(space);
  617. if (!space || !id)
  618. goto error;
  619. if (type == isl_dim_param) {
  620. int i;
  621. for (i = 0; i < 2; ++i) {
  622. if (!space->nested[i])
  623. continue;
  624. space->nested[i] =
  625. isl_space_set_dim_id(space->nested[i],
  626. type, pos, isl_id_copy(id));
  627. if (!space->nested[i])
  628. goto error;
  629. }
  630. }
  631. isl_id_free(get_id(space, type, pos));
  632. return set_id(space, type, pos, id);
  633. error:
  634. isl_id_free(id);
  635. isl_space_free(space);
  636. return NULL;
  637. }
  638. /* Reset the id of the given dimension of "space".
  639. * If the dimension already has an id, then it is removed.
  640. * If the dimension is a parameter, then we need to reset it
  641. * in the nested spaces (if any) as well.
  642. */
  643. __isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space,
  644. enum isl_dim_type type, unsigned pos)
  645. {
  646. space = isl_space_cow(space);
  647. if (!space)
  648. goto error;
  649. if (type == isl_dim_param) {
  650. int i;
  651. for (i = 0; i < 2; ++i) {
  652. if (!space->nested[i])
  653. continue;
  654. space->nested[i] =
  655. isl_space_reset_dim_id(space->nested[i],
  656. type, pos);
  657. if (!space->nested[i])
  658. goto error;
  659. }
  660. }
  661. isl_id_free(get_id(space, type, pos));
  662. return set_id(space, type, pos, NULL);
  663. error:
  664. isl_space_free(space);
  665. return NULL;
  666. }
  667. isl_bool isl_space_has_dim_id(__isl_keep isl_space *space,
  668. enum isl_dim_type type, unsigned pos)
  669. {
  670. if (!space)
  671. return isl_bool_error;
  672. return isl_bool_ok(get_id(space, type, pos) != NULL);
  673. }
  674. __isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *space,
  675. enum isl_dim_type type, unsigned pos)
  676. {
  677. if (!space)
  678. return NULL;
  679. if (!get_id(space, type, pos))
  680. isl_die(space->ctx, isl_error_invalid,
  681. "dim has no id", return NULL);
  682. return isl_id_copy(get_id(space, type, pos));
  683. }
  684. __isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *space,
  685. enum isl_dim_type type, const char *s)
  686. {
  687. isl_id *id;
  688. if (!space)
  689. return NULL;
  690. if (!s)
  691. return isl_space_reset_tuple_id(space, type);
  692. if (!name_ok(space->ctx, s))
  693. goto error;
  694. id = isl_id_alloc(space->ctx, s, NULL);
  695. return isl_space_set_tuple_id(space, type, id);
  696. error:
  697. isl_space_free(space);
  698. return NULL;
  699. }
  700. /* Does the tuple have a name?
  701. */
  702. isl_bool isl_space_has_tuple_name(__isl_keep isl_space *space,
  703. enum isl_dim_type type)
  704. {
  705. isl_id *id;
  706. if (!space_can_have_id(space, type))
  707. return isl_bool_error;
  708. id = space->tuple_id[type - isl_dim_in];
  709. return isl_bool_ok(id && id->name);
  710. }
  711. __isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *space,
  712. enum isl_dim_type type)
  713. {
  714. isl_id *id;
  715. if (!space)
  716. return NULL;
  717. if (type != isl_dim_in && type != isl_dim_out)
  718. return NULL;
  719. id = space->tuple_id[type - isl_dim_in];
  720. return id ? id->name : NULL;
  721. }
  722. __isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *space,
  723. enum isl_dim_type type, unsigned pos,
  724. const char *s)
  725. {
  726. isl_id *id;
  727. if (!space)
  728. return NULL;
  729. if (!s)
  730. return isl_space_reset_dim_id(space, type, pos);
  731. if (!name_ok(space->ctx, s))
  732. goto error;
  733. id = isl_id_alloc(space->ctx, s, NULL);
  734. return isl_space_set_dim_id(space, type, pos, id);
  735. error:
  736. isl_space_free(space);
  737. return NULL;
  738. }
  739. /* Does the given dimension have a name?
  740. */
  741. isl_bool isl_space_has_dim_name(__isl_keep isl_space *space,
  742. enum isl_dim_type type, unsigned pos)
  743. {
  744. isl_id *id;
  745. if (!space)
  746. return isl_bool_error;
  747. id = get_id(space, type, pos);
  748. return isl_bool_ok(id && id->name);
  749. }
  750. __isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *space,
  751. enum isl_dim_type type, unsigned pos)
  752. {
  753. isl_id *id = get_id(space, type, pos);
  754. return id ? id->name : NULL;
  755. }
  756. int isl_space_find_dim_by_id(__isl_keep isl_space *space,
  757. enum isl_dim_type type, __isl_keep isl_id *id)
  758. {
  759. int i;
  760. int offset;
  761. isl_size n;
  762. n = isl_space_dim(space, type);
  763. if (n < 0 || !id)
  764. return -1;
  765. offset = isl_space_offset(space, type);
  766. for (i = 0; i < n && offset + i < space->n_id; ++i)
  767. if (space->ids[offset + i] == id)
  768. return i;
  769. return -1;
  770. }
  771. int isl_space_find_dim_by_name(__isl_keep isl_space *space,
  772. enum isl_dim_type type, const char *name)
  773. {
  774. int i;
  775. int offset;
  776. isl_size n;
  777. n = isl_space_dim(space, type);
  778. if (n < 0 || !name)
  779. return -1;
  780. offset = isl_space_offset(space, type);
  781. for (i = 0; i < n && offset + i < space->n_id; ++i) {
  782. isl_id *id = get_id(space, type, i);
  783. if (id && id->name && !strcmp(id->name, name))
  784. return i;
  785. }
  786. return -1;
  787. }
  788. /* Reset the user pointer on all identifiers of parameters and tuples
  789. * of "space".
  790. */
  791. __isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space)
  792. {
  793. int i;
  794. isl_ctx *ctx;
  795. isl_id *id;
  796. const char *name;
  797. if (!space)
  798. return NULL;
  799. ctx = isl_space_get_ctx(space);
  800. for (i = 0; i < space->nparam && i < space->n_id; ++i) {
  801. if (!isl_id_get_user(space->ids[i]))
  802. continue;
  803. space = isl_space_cow(space);
  804. if (!space)
  805. return NULL;
  806. name = isl_id_get_name(space->ids[i]);
  807. id = isl_id_alloc(ctx, name, NULL);
  808. isl_id_free(space->ids[i]);
  809. space->ids[i] = id;
  810. if (!id)
  811. return isl_space_free(space);
  812. }
  813. for (i = 0; i < 2; ++i) {
  814. if (!space->tuple_id[i])
  815. continue;
  816. if (!isl_id_get_user(space->tuple_id[i]))
  817. continue;
  818. space = isl_space_cow(space);
  819. if (!space)
  820. return NULL;
  821. name = isl_id_get_name(space->tuple_id[i]);
  822. id = isl_id_alloc(ctx, name, NULL);
  823. isl_id_free(space->tuple_id[i]);
  824. space->tuple_id[i] = id;
  825. if (!id)
  826. return isl_space_free(space);
  827. }
  828. for (i = 0; i < 2; ++i) {
  829. isl_space *nested;
  830. if (!space->nested[i])
  831. continue;
  832. nested = isl_space_take_nested(space, i);
  833. nested = isl_space_reset_user(nested);
  834. space = isl_space_restore_nested(space, i, nested);
  835. if (!space)
  836. return NULL;
  837. }
  838. return space;
  839. }
  840. static __isl_keep isl_id *tuple_id(__isl_keep isl_space *space,
  841. enum isl_dim_type type)
  842. {
  843. if (!space)
  844. return NULL;
  845. if (type == isl_dim_in)
  846. return space->tuple_id[0];
  847. if (type == isl_dim_out)
  848. return space->tuple_id[1];
  849. return NULL;
  850. }
  851. static __isl_keep isl_space *nested(__isl_keep isl_space *space,
  852. enum isl_dim_type type)
  853. {
  854. if (!space)
  855. return NULL;
  856. if (type == isl_dim_in)
  857. return space->nested[0];
  858. if (type == isl_dim_out)
  859. return space->nested[1];
  860. return NULL;
  861. }
  862. /* Are the two spaces the same, apart from positions and names of parameters?
  863. */
  864. isl_bool isl_space_has_equal_tuples(__isl_keep isl_space *space1,
  865. __isl_keep isl_space *space2)
  866. {
  867. if (!space1 || !space2)
  868. return isl_bool_error;
  869. if (space1 == space2)
  870. return isl_bool_true;
  871. return isl_space_tuple_is_equal(space1, isl_dim_in,
  872. space2, isl_dim_in) &&
  873. isl_space_tuple_is_equal(space1, isl_dim_out,
  874. space2, isl_dim_out);
  875. }
  876. /* Check that a match involving "space" was successful.
  877. * That is, check that "match" is equal to isl_bool_true.
  878. */
  879. static isl_stat check_match(__isl_keep isl_space *space, isl_bool match)
  880. {
  881. if (match < 0)
  882. return isl_stat_error;
  883. if (!match)
  884. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  885. "incompatible spaces", return isl_stat_error);
  886. return isl_stat_ok;
  887. }
  888. /* Check that the two spaces are the same,
  889. * apart from positions and names of parameters.
  890. */
  891. isl_stat isl_space_check_equal_tuples(__isl_keep isl_space *space1,
  892. __isl_keep isl_space *space2)
  893. {
  894. isl_bool is_equal;
  895. is_equal = isl_space_has_equal_tuples(space1, space2);
  896. return check_match(space1, is_equal);
  897. }
  898. /* Check if the tuple of type "type1" of "space1" is the same as
  899. * the tuple of type "type2" of "space2".
  900. *
  901. * That is, check if the tuples have the same identifier, the same dimension
  902. * and the same internal structure.
  903. * The identifiers of the dimensions inside the tuples do not affect the result.
  904. *
  905. * Note that this function only checks the tuples themselves.
  906. * If nested tuples are involved, then we need to be careful not
  907. * to have result affected by possibly differing parameters
  908. * in those nested tuples.
  909. */
  910. isl_bool isl_space_tuple_is_equal(__isl_keep isl_space *space1,
  911. enum isl_dim_type type1, __isl_keep isl_space *space2,
  912. enum isl_dim_type type2)
  913. {
  914. isl_id *id1, *id2;
  915. isl_space *nested1, *nested2;
  916. if (!space1 || !space2)
  917. return isl_bool_error;
  918. if (space1 == space2 && type1 == type2)
  919. return isl_bool_true;
  920. if (n(space1, type1) != n(space2, type2))
  921. return isl_bool_false;
  922. id1 = tuple_id(space1, type1);
  923. id2 = tuple_id(space2, type2);
  924. if (!id1 ^ !id2)
  925. return isl_bool_false;
  926. if (id1 && id1 != id2)
  927. return isl_bool_false;
  928. nested1 = nested(space1, type1);
  929. nested2 = nested(space2, type2);
  930. if (!nested1 ^ !nested2)
  931. return isl_bool_false;
  932. if (nested1 && !isl_space_has_equal_tuples(nested1, nested2))
  933. return isl_bool_false;
  934. return isl_bool_true;
  935. }
  936. /* Is the tuple "inner" within the wrapped relation inside tuple "outer"
  937. * of "space1" equal to tuple "type2" of "space2"?
  938. */
  939. isl_bool isl_space_wrapped_tuple_is_equal(__isl_keep isl_space *space1,
  940. enum isl_dim_type outer, enum isl_dim_type inner,
  941. __isl_keep isl_space *space2, enum isl_dim_type type2)
  942. {
  943. int pos;
  944. isl_space *nested;
  945. if (!space1)
  946. return isl_bool_error;
  947. if (outer != isl_dim_in && outer != isl_dim_out)
  948. isl_die(isl_space_get_ctx(space1), isl_error_invalid,
  949. "only input, output and set tuples "
  950. "can have nested relations", return isl_bool_error);
  951. pos = outer - isl_dim_in;
  952. nested = isl_space_peek_nested(space1, pos);
  953. return isl_space_tuple_is_equal(nested, inner, space2, type2);
  954. }
  955. /* Check that the tuple "inner" within the wrapped relation inside tuple "outer"
  956. * of "space1" is equal to tuple "type2" of "space2".
  957. */
  958. isl_stat isl_space_check_wrapped_tuple_is_equal(__isl_keep isl_space *space1,
  959. enum isl_dim_type outer, enum isl_dim_type inner,
  960. __isl_keep isl_space *space2, enum isl_dim_type type2)
  961. {
  962. isl_bool is_equal;
  963. is_equal = isl_space_wrapped_tuple_is_equal(space1, outer, inner,
  964. space2, type2);
  965. return check_match(space1, is_equal);
  966. }
  967. static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
  968. __isl_keep isl_space *space2, enum isl_dim_type type2)
  969. {
  970. int i;
  971. isl_bool equal;
  972. if (!space1 || !space2)
  973. return isl_bool_error;
  974. if (space1 == space2 && type1 == type2)
  975. return isl_bool_true;
  976. equal = isl_space_tuple_is_equal(space1, type1, space2, type2);
  977. if (equal < 0 || !equal)
  978. return equal;
  979. if (!space1->ids && !space2->ids)
  980. return isl_bool_true;
  981. for (i = 0; i < n(space1, type1); ++i) {
  982. if (get_id(space1, type1, i) != get_id(space2, type2, i))
  983. return isl_bool_false;
  984. }
  985. return isl_bool_true;
  986. }
  987. /* Do "space1" and "space2" have the same parameters?
  988. */
  989. isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
  990. __isl_keep isl_space *space2)
  991. {
  992. return match(space1, isl_dim_param, space2, isl_dim_param);
  993. }
  994. /* Do "space1" and "space2" have the same identifiers for all
  995. * the tuple variables?
  996. */
  997. isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
  998. __isl_keep isl_space *space2)
  999. {
  1000. isl_bool equal;
  1001. equal = match(space1, isl_dim_in, space2, isl_dim_in);
  1002. if (equal < 0 || !equal)
  1003. return equal;
  1004. return match(space1, isl_dim_out, space2, isl_dim_out);
  1005. }
  1006. isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
  1007. __isl_keep isl_space *space2, enum isl_dim_type type2)
  1008. {
  1009. return match(space1, type1, space2, type2);
  1010. }
  1011. static void get_ids(__isl_keep isl_space *space, enum isl_dim_type type,
  1012. unsigned first, unsigned n, __isl_keep isl_id **ids)
  1013. {
  1014. int i;
  1015. for (i = 0; i < n ; ++i)
  1016. ids[i] = get_id(space, type, first + i);
  1017. }
  1018. static __isl_give isl_space *space_extend(__isl_take isl_space *space,
  1019. unsigned nparam, unsigned n_in, unsigned n_out)
  1020. {
  1021. isl_id **ids = NULL;
  1022. if (!space)
  1023. return NULL;
  1024. if (space->nparam == nparam &&
  1025. space->n_in == n_in && space->n_out == n_out)
  1026. return space;
  1027. isl_assert(space->ctx, space->nparam <= nparam, goto error);
  1028. isl_assert(space->ctx, space->n_in <= n_in, goto error);
  1029. isl_assert(space->ctx, space->n_out <= n_out, goto error);
  1030. space = isl_space_cow(space);
  1031. if (!space)
  1032. goto error;
  1033. if (space->ids) {
  1034. unsigned n;
  1035. n = nparam + n_in + n_out;
  1036. if (n < nparam || n < n_in || n < n_out)
  1037. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1038. "overflow in total number of dimensions",
  1039. goto error);
  1040. ids = isl_calloc_array(space->ctx, isl_id *, n);
  1041. if (!ids)
  1042. goto error;
  1043. get_ids(space, isl_dim_param, 0, space->nparam, ids);
  1044. get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
  1045. get_ids(space, isl_dim_out, 0, space->n_out,
  1046. ids + nparam + n_in);
  1047. free(space->ids);
  1048. space->ids = ids;
  1049. space->n_id = nparam + n_in + n_out;
  1050. }
  1051. space->nparam = nparam;
  1052. space->n_in = n_in;
  1053. space->n_out = n_out;
  1054. return space;
  1055. error:
  1056. free(ids);
  1057. isl_space_free(space);
  1058. return NULL;
  1059. }
  1060. __isl_give isl_space *isl_space_extend(__isl_take isl_space *space,
  1061. unsigned nparam, unsigned n_in, unsigned n_out)
  1062. {
  1063. return space_extend(space, nparam, n_in, n_out);
  1064. }
  1065. __isl_give isl_space *isl_space_add_dims(__isl_take isl_space *space,
  1066. enum isl_dim_type type, unsigned n)
  1067. {
  1068. space = isl_space_reset(space, type);
  1069. if (!space)
  1070. return NULL;
  1071. switch (type) {
  1072. case isl_dim_param:
  1073. space = space_extend(space,
  1074. space->nparam + n, space->n_in, space->n_out);
  1075. if (space && space->nested[0] &&
  1076. !(space->nested[0] = isl_space_add_dims(space->nested[0],
  1077. isl_dim_param, n)))
  1078. goto error;
  1079. if (space && space->nested[1] &&
  1080. !(space->nested[1] = isl_space_add_dims(space->nested[1],
  1081. isl_dim_param, n)))
  1082. goto error;
  1083. return space;
  1084. case isl_dim_in:
  1085. return space_extend(space,
  1086. space->nparam, space->n_in + n, space->n_out);
  1087. case isl_dim_out:
  1088. return space_extend(space,
  1089. space->nparam, space->n_in, space->n_out + n);
  1090. default:
  1091. isl_die(space->ctx, isl_error_invalid,
  1092. "cannot add dimensions of specified type", goto error);
  1093. }
  1094. error:
  1095. isl_space_free(space);
  1096. return NULL;
  1097. }
  1098. /* Add a parameter with identifier "id" to "space", provided
  1099. * it does not already appear in "space".
  1100. */
  1101. __isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
  1102. __isl_take isl_id *id)
  1103. {
  1104. isl_size pos;
  1105. if (!space || !id)
  1106. goto error;
  1107. if (isl_space_find_dim_by_id(space, isl_dim_param, id) >= 0) {
  1108. isl_id_free(id);
  1109. return space;
  1110. }
  1111. pos = isl_space_dim(space, isl_dim_param);
  1112. if (pos < 0)
  1113. goto error;
  1114. space = isl_space_add_dims(space, isl_dim_param, 1);
  1115. space = isl_space_set_dim_id(space, isl_dim_param, pos, id);
  1116. return space;
  1117. error:
  1118. isl_space_free(space);
  1119. isl_id_free(id);
  1120. return NULL;
  1121. }
  1122. static int valid_dim_type(enum isl_dim_type type)
  1123. {
  1124. switch (type) {
  1125. case isl_dim_param:
  1126. case isl_dim_in:
  1127. case isl_dim_out:
  1128. return 1;
  1129. default:
  1130. return 0;
  1131. }
  1132. }
  1133. #undef TYPE
  1134. #define TYPE isl_space
  1135. #include "check_type_range_templ.c"
  1136. /* Insert "n" dimensions of type "type" at position "pos".
  1137. * If we are inserting parameters, then they are also inserted in
  1138. * any nested spaces.
  1139. */
  1140. __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
  1141. enum isl_dim_type type, unsigned pos, unsigned n)
  1142. {
  1143. isl_ctx *ctx;
  1144. isl_id **ids = NULL;
  1145. if (!space)
  1146. return NULL;
  1147. if (n == 0)
  1148. return isl_space_reset(space, type);
  1149. ctx = isl_space_get_ctx(space);
  1150. if (!valid_dim_type(type))
  1151. isl_die(ctx, isl_error_invalid,
  1152. "cannot insert dimensions of specified type",
  1153. goto error);
  1154. if (isl_space_check_range(space, type, pos, 0) < 0)
  1155. return isl_space_free(space);
  1156. space = isl_space_cow(space);
  1157. if (!space)
  1158. return NULL;
  1159. if (space->ids) {
  1160. enum isl_dim_type t, o = isl_dim_param;
  1161. int off;
  1162. int s[3];
  1163. ids = isl_calloc_array(ctx, isl_id *,
  1164. space->nparam + space->n_in + space->n_out + n);
  1165. if (!ids)
  1166. goto error;
  1167. off = 0;
  1168. s[isl_dim_param - o] = space->nparam;
  1169. s[isl_dim_in - o] = space->n_in;
  1170. s[isl_dim_out - o] = space->n_out;
  1171. for (t = isl_dim_param; t <= isl_dim_out; ++t) {
  1172. if (t != type) {
  1173. get_ids(space, t, 0, s[t - o], ids + off);
  1174. off += s[t - o];
  1175. } else {
  1176. get_ids(space, t, 0, pos, ids + off);
  1177. off += pos + n;
  1178. get_ids(space, t, pos, s[t - o] - pos,
  1179. ids + off);
  1180. off += s[t - o] - pos;
  1181. }
  1182. }
  1183. free(space->ids);
  1184. space->ids = ids;
  1185. space->n_id = space->nparam + space->n_in + space->n_out + n;
  1186. }
  1187. switch (type) {
  1188. case isl_dim_param: space->nparam += n; break;
  1189. case isl_dim_in: space->n_in += n; break;
  1190. case isl_dim_out: space->n_out += n; break;
  1191. default: ;
  1192. }
  1193. space = isl_space_reset(space, type);
  1194. if (type == isl_dim_param) {
  1195. if (space && space->nested[0] &&
  1196. !(space->nested[0] = isl_space_insert_dims(space->nested[0],
  1197. isl_dim_param, pos, n)))
  1198. goto error;
  1199. if (space && space->nested[1] &&
  1200. !(space->nested[1] = isl_space_insert_dims(space->nested[1],
  1201. isl_dim_param, pos, n)))
  1202. goto error;
  1203. }
  1204. return space;
  1205. error:
  1206. isl_space_free(space);
  1207. return NULL;
  1208. }
  1209. __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
  1210. enum isl_dim_type dst_type, unsigned dst_pos,
  1211. enum isl_dim_type src_type, unsigned src_pos, unsigned n)
  1212. {
  1213. int i;
  1214. space = isl_space_reset(space, src_type);
  1215. space = isl_space_reset(space, dst_type);
  1216. if (!space)
  1217. return NULL;
  1218. if (n == 0)
  1219. return space;
  1220. if (isl_space_check_range(space, src_type, src_pos, n) < 0)
  1221. return isl_space_free(space);
  1222. if (dst_type == src_type && dst_pos == src_pos)
  1223. return space;
  1224. isl_assert(space->ctx, dst_type != src_type, goto error);
  1225. space = isl_space_cow(space);
  1226. if (!space)
  1227. return NULL;
  1228. if (space->ids) {
  1229. isl_id **ids;
  1230. enum isl_dim_type t, o = isl_dim_param;
  1231. int off;
  1232. int s[3];
  1233. ids = isl_calloc_array(space->ctx, isl_id *,
  1234. space->nparam + space->n_in + space->n_out);
  1235. if (!ids)
  1236. goto error;
  1237. off = 0;
  1238. s[isl_dim_param - o] = space->nparam;
  1239. s[isl_dim_in - o] = space->n_in;
  1240. s[isl_dim_out - o] = space->n_out;
  1241. for (t = isl_dim_param; t <= isl_dim_out; ++t) {
  1242. if (t == dst_type) {
  1243. get_ids(space, t, 0, dst_pos, ids + off);
  1244. off += dst_pos;
  1245. get_ids(space, src_type, src_pos, n, ids + off);
  1246. off += n;
  1247. get_ids(space, t, dst_pos, s[t - o] - dst_pos,
  1248. ids + off);
  1249. off += s[t - o] - dst_pos;
  1250. } else if (t == src_type) {
  1251. get_ids(space, t, 0, src_pos, ids + off);
  1252. off += src_pos;
  1253. get_ids(space, t, src_pos + n,
  1254. s[t - o] - src_pos - n, ids + off);
  1255. off += s[t - o] - src_pos - n;
  1256. } else {
  1257. get_ids(space, t, 0, s[t - o], ids + off);
  1258. off += s[t - o];
  1259. }
  1260. }
  1261. free(space->ids);
  1262. space->ids = ids;
  1263. space->n_id = space->nparam + space->n_in + space->n_out;
  1264. }
  1265. switch (dst_type) {
  1266. case isl_dim_param: space->nparam += n; break;
  1267. case isl_dim_in: space->n_in += n; break;
  1268. case isl_dim_out: space->n_out += n; break;
  1269. default: ;
  1270. }
  1271. switch (src_type) {
  1272. case isl_dim_param: space->nparam -= n; break;
  1273. case isl_dim_in: space->n_in -= n; break;
  1274. case isl_dim_out: space->n_out -= n; break;
  1275. default: ;
  1276. }
  1277. if (dst_type != isl_dim_param && src_type != isl_dim_param)
  1278. return space;
  1279. for (i = 0; i < 2; ++i) {
  1280. isl_space *nested;
  1281. if (!space->nested[i])
  1282. continue;
  1283. nested = isl_space_take_nested(space, i);
  1284. nested = isl_space_replace_params(nested, space);
  1285. space = isl_space_restore_nested(space, i, nested);
  1286. if (!space)
  1287. return NULL;
  1288. }
  1289. return space;
  1290. error:
  1291. isl_space_free(space);
  1292. return NULL;
  1293. }
  1294. /* Check that "space1" and "space2" have the same parameters,
  1295. * reporting an error if they do not.
  1296. */
  1297. isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
  1298. __isl_keep isl_space *space2)
  1299. {
  1300. isl_bool equal;
  1301. equal = isl_space_has_equal_params(space1, space2);
  1302. if (equal < 0)
  1303. return isl_stat_error;
  1304. if (!equal)
  1305. isl_die(isl_space_get_ctx(space1), isl_error_invalid,
  1306. "parameters need to match", return isl_stat_error);
  1307. return isl_stat_ok;
  1308. }
  1309. __isl_give isl_space *isl_space_join(__isl_take isl_space *left,
  1310. __isl_take isl_space *right)
  1311. {
  1312. isl_space *space;
  1313. if (isl_space_check_equal_params(left, right) < 0)
  1314. goto error;
  1315. isl_assert(left->ctx,
  1316. isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
  1317. goto error);
  1318. space = isl_space_alloc(left->ctx,
  1319. left->nparam, left->n_in, right->n_out);
  1320. if (!space)
  1321. goto error;
  1322. space = copy_ids(space, isl_dim_param, 0, left, isl_dim_param);
  1323. space = copy_ids(space, isl_dim_in, 0, left, isl_dim_in);
  1324. space = copy_ids(space, isl_dim_out, 0, right, isl_dim_out);
  1325. if (space && left->tuple_id[0] &&
  1326. !(space->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
  1327. goto error;
  1328. if (space && right->tuple_id[1] &&
  1329. !(space->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
  1330. goto error;
  1331. if (space && left->nested[0] &&
  1332. !(space->nested[0] = isl_space_copy(left->nested[0])))
  1333. goto error;
  1334. if (space && right->nested[1] &&
  1335. !(space->nested[1] = isl_space_copy(right->nested[1])))
  1336. goto error;
  1337. isl_space_free(left);
  1338. isl_space_free(right);
  1339. return space;
  1340. error:
  1341. isl_space_free(left);
  1342. isl_space_free(right);
  1343. return NULL;
  1344. }
  1345. /* Given two map spaces { A -> C } and { B -> D }, construct the space
  1346. * { [A -> B] -> [C -> D] }.
  1347. * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
  1348. */
  1349. __isl_give isl_space *isl_space_product(__isl_take isl_space *left,
  1350. __isl_take isl_space *right)
  1351. {
  1352. isl_space *dom1, *dom2, *nest1, *nest2;
  1353. int is_set;
  1354. if (!left || !right)
  1355. goto error;
  1356. is_set = isl_space_is_set(left);
  1357. if (is_set != isl_space_is_set(right))
  1358. isl_die(isl_space_get_ctx(left), isl_error_invalid,
  1359. "expecting either two set spaces or two map spaces",
  1360. goto error);
  1361. if (is_set)
  1362. return isl_space_range_product(left, right);
  1363. if (isl_space_check_equal_params(left, right) < 0)
  1364. goto error;
  1365. dom1 = isl_space_domain(isl_space_copy(left));
  1366. dom2 = isl_space_domain(isl_space_copy(right));
  1367. nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
  1368. dom1 = isl_space_range(left);
  1369. dom2 = isl_space_range(right);
  1370. nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
  1371. return isl_space_join(isl_space_reverse(nest1), nest2);
  1372. error:
  1373. isl_space_free(left);
  1374. isl_space_free(right);
  1375. return NULL;
  1376. }
  1377. /* Given two spaces { A -> C } and { B -> C }, construct the space
  1378. * { [A -> B] -> C }
  1379. */
  1380. __isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
  1381. __isl_take isl_space *right)
  1382. {
  1383. isl_space *ran, *dom1, *dom2, *nest;
  1384. if (isl_space_check_equal_params(left, right) < 0)
  1385. goto error;
  1386. if (!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out))
  1387. isl_die(left->ctx, isl_error_invalid,
  1388. "ranges need to match", goto error);
  1389. ran = isl_space_range(isl_space_copy(left));
  1390. dom1 = isl_space_domain(left);
  1391. dom2 = isl_space_domain(right);
  1392. nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
  1393. return isl_space_join(isl_space_reverse(nest), ran);
  1394. error:
  1395. isl_space_free(left);
  1396. isl_space_free(right);
  1397. return NULL;
  1398. }
  1399. __isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
  1400. __isl_take isl_space *right)
  1401. {
  1402. isl_space *dom, *ran1, *ran2, *nest;
  1403. if (isl_space_check_equal_params(left, right) < 0)
  1404. goto error;
  1405. if (!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in))
  1406. isl_die(left->ctx, isl_error_invalid,
  1407. "domains need to match", goto error);
  1408. dom = isl_space_domain(isl_space_copy(left));
  1409. ran1 = isl_space_range(left);
  1410. ran2 = isl_space_range(right);
  1411. nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
  1412. return isl_space_join(isl_space_reverse(dom), nest);
  1413. error:
  1414. isl_space_free(left);
  1415. isl_space_free(right);
  1416. return NULL;
  1417. }
  1418. /* Given a space of the form [A -> B] -> C, return the space A -> C.
  1419. */
  1420. __isl_give isl_space *isl_space_domain_factor_domain(
  1421. __isl_take isl_space *space)
  1422. {
  1423. isl_space *nested;
  1424. isl_space *domain;
  1425. if (isl_space_check_domain_is_wrapping(space) < 0)
  1426. return isl_space_free(space);
  1427. nested = space->nested[0];
  1428. domain = isl_space_copy(space);
  1429. domain = isl_space_drop_dims(domain, isl_dim_in,
  1430. nested->n_in, nested->n_out);
  1431. if (!domain)
  1432. return isl_space_free(space);
  1433. if (nested->tuple_id[0]) {
  1434. domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
  1435. if (!domain->tuple_id[0])
  1436. goto error;
  1437. }
  1438. if (nested->nested[0]) {
  1439. domain->nested[0] = isl_space_copy(nested->nested[0]);
  1440. if (!domain->nested[0])
  1441. goto error;
  1442. }
  1443. isl_space_free(space);
  1444. return domain;
  1445. error:
  1446. isl_space_free(space);
  1447. isl_space_free(domain);
  1448. return NULL;
  1449. }
  1450. /* Given a space of the form [A -> B] -> C, return the space B -> C.
  1451. */
  1452. __isl_give isl_space *isl_space_domain_factor_range(
  1453. __isl_take isl_space *space)
  1454. {
  1455. isl_space *nested;
  1456. isl_space *range;
  1457. if (isl_space_check_domain_is_wrapping(space) < 0)
  1458. return isl_space_free(space);
  1459. nested = space->nested[0];
  1460. range = isl_space_copy(space);
  1461. range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
  1462. if (!range)
  1463. return isl_space_free(space);
  1464. if (nested->tuple_id[1]) {
  1465. range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
  1466. if (!range->tuple_id[0])
  1467. goto error;
  1468. }
  1469. if (nested->nested[1]) {
  1470. range->nested[0] = isl_space_copy(nested->nested[1]);
  1471. if (!range->nested[0])
  1472. goto error;
  1473. }
  1474. isl_space_free(space);
  1475. return range;
  1476. error:
  1477. isl_space_free(space);
  1478. isl_space_free(range);
  1479. return NULL;
  1480. }
  1481. /* Internal function that selects the domain of the map that is
  1482. * embedded in either a set space or the range of a map space.
  1483. * In particular, given a space of the form [A -> B], return the space A.
  1484. * Given a space of the form A -> [B -> C], return the space A -> B.
  1485. */
  1486. static __isl_give isl_space *range_factor_domain(__isl_take isl_space *space)
  1487. {
  1488. isl_space *nested;
  1489. isl_space *domain;
  1490. if (!space)
  1491. return NULL;
  1492. nested = space->nested[1];
  1493. domain = isl_space_copy(space);
  1494. domain = isl_space_drop_dims(domain, isl_dim_out,
  1495. nested->n_in, nested->n_out);
  1496. if (!domain)
  1497. return isl_space_free(space);
  1498. if (nested->tuple_id[0]) {
  1499. domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
  1500. if (!domain->tuple_id[1])
  1501. goto error;
  1502. }
  1503. if (nested->nested[0]) {
  1504. domain->nested[1] = isl_space_copy(nested->nested[0]);
  1505. if (!domain->nested[1])
  1506. goto error;
  1507. }
  1508. isl_space_free(space);
  1509. return domain;
  1510. error:
  1511. isl_space_free(space);
  1512. isl_space_free(domain);
  1513. return NULL;
  1514. }
  1515. /* Given a space of the form A -> [B -> C], return the space A -> B.
  1516. */
  1517. __isl_give isl_space *isl_space_range_factor_domain(
  1518. __isl_take isl_space *space)
  1519. {
  1520. if (isl_space_check_range_is_wrapping(space) < 0)
  1521. return isl_space_free(space);
  1522. return range_factor_domain(space);
  1523. }
  1524. /* Given a space of the form [A -> B], return the space A.
  1525. */
  1526. static __isl_give isl_space *set_factor_domain(__isl_take isl_space *space)
  1527. {
  1528. if (!space)
  1529. return NULL;
  1530. if (!isl_space_is_wrapping(space))
  1531. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1532. "not a product", return isl_space_free(space));
  1533. return range_factor_domain(space);
  1534. }
  1535. /* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
  1536. * Given a space of the form [A -> B], return the space A.
  1537. */
  1538. __isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
  1539. {
  1540. if (!space)
  1541. return NULL;
  1542. if (isl_space_is_set(space))
  1543. return set_factor_domain(space);
  1544. space = isl_space_domain_factor_domain(space);
  1545. space = isl_space_range_factor_domain(space);
  1546. return space;
  1547. }
  1548. /* Internal function that selects the range of the map that is
  1549. * embedded in either a set space or the range of a map space.
  1550. * In particular, given a space of the form [A -> B], return the space B.
  1551. * Given a space of the form A -> [B -> C], return the space A -> C.
  1552. */
  1553. static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
  1554. {
  1555. isl_space *nested;
  1556. isl_space *range;
  1557. if (!space)
  1558. return NULL;
  1559. nested = space->nested[1];
  1560. range = isl_space_copy(space);
  1561. range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
  1562. if (!range)
  1563. return isl_space_free(space);
  1564. if (nested->tuple_id[1]) {
  1565. range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
  1566. if (!range->tuple_id[1])
  1567. goto error;
  1568. }
  1569. if (nested->nested[1]) {
  1570. range->nested[1] = isl_space_copy(nested->nested[1]);
  1571. if (!range->nested[1])
  1572. goto error;
  1573. }
  1574. isl_space_free(space);
  1575. return range;
  1576. error:
  1577. isl_space_free(space);
  1578. isl_space_free(range);
  1579. return NULL;
  1580. }
  1581. /* Given a space of the form A -> [B -> C], return the space A -> C.
  1582. */
  1583. __isl_give isl_space *isl_space_range_factor_range(
  1584. __isl_take isl_space *space)
  1585. {
  1586. if (isl_space_check_range_is_wrapping(space) < 0)
  1587. return isl_space_free(space);
  1588. return range_factor_range(space);
  1589. }
  1590. /* Given a space of the form [A -> B], return the space B.
  1591. */
  1592. static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
  1593. {
  1594. if (!space)
  1595. return NULL;
  1596. if (!isl_space_is_wrapping(space))
  1597. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1598. "not a product", return isl_space_free(space));
  1599. return range_factor_range(space);
  1600. }
  1601. /* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
  1602. * Given a space of the form [A -> B], return the space B.
  1603. */
  1604. __isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
  1605. {
  1606. if (!space)
  1607. return NULL;
  1608. if (isl_space_is_set(space))
  1609. return set_factor_range(space);
  1610. space = isl_space_domain_factor_range(space);
  1611. space = isl_space_range_factor_range(space);
  1612. return space;
  1613. }
  1614. __isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space)
  1615. {
  1616. isl_ctx *ctx;
  1617. isl_id **ids = NULL;
  1618. int n_id;
  1619. if (!space)
  1620. return NULL;
  1621. ctx = isl_space_get_ctx(space);
  1622. if (!isl_space_is_set(space))
  1623. isl_die(ctx, isl_error_invalid, "not a set space", goto error);
  1624. space = isl_space_cow(space);
  1625. if (!space)
  1626. return NULL;
  1627. n_id = space->nparam + space->n_out + space->n_out;
  1628. if (n_id > 0 && space->ids) {
  1629. ids = isl_calloc_array(space->ctx, isl_id *, n_id);
  1630. if (!ids)
  1631. goto error;
  1632. get_ids(space, isl_dim_param, 0, space->nparam, ids);
  1633. get_ids(space, isl_dim_out, 0, space->n_out,
  1634. ids + space->nparam);
  1635. }
  1636. space->n_in = space->n_out;
  1637. if (ids) {
  1638. free(space->ids);
  1639. space->ids = ids;
  1640. space->n_id = n_id;
  1641. space = copy_ids(space, isl_dim_out, 0, space, isl_dim_in);
  1642. }
  1643. isl_id_free(space->tuple_id[0]);
  1644. space->tuple_id[0] = isl_id_copy(space->tuple_id[1]);
  1645. isl_space_free(space->nested[0]);
  1646. space->nested[0] = isl_space_copy(space->nested[1]);
  1647. return space;
  1648. error:
  1649. isl_space_free(space);
  1650. return NULL;
  1651. }
  1652. __isl_give isl_space *isl_space_map_from_domain_and_range(
  1653. __isl_take isl_space *domain, __isl_take isl_space *range)
  1654. {
  1655. if (!domain || !range)
  1656. goto error;
  1657. if (!isl_space_is_set(domain))
  1658. isl_die(isl_space_get_ctx(domain), isl_error_invalid,
  1659. "domain is not a set space", goto error);
  1660. if (!isl_space_is_set(range))
  1661. isl_die(isl_space_get_ctx(range), isl_error_invalid,
  1662. "range is not a set space", goto error);
  1663. return isl_space_join(isl_space_reverse(domain), range);
  1664. error:
  1665. isl_space_free(domain);
  1666. isl_space_free(range);
  1667. return NULL;
  1668. }
  1669. static __isl_give isl_space *set_ids(__isl_take isl_space *space,
  1670. enum isl_dim_type type,
  1671. unsigned first, unsigned n, __isl_take isl_id **ids)
  1672. {
  1673. int i;
  1674. for (i = 0; i < n ; ++i)
  1675. space = set_id(space, type, first + i, ids[i]);
  1676. return space;
  1677. }
  1678. __isl_give isl_space *isl_space_reverse(__isl_take isl_space *space)
  1679. {
  1680. unsigned t;
  1681. isl_bool equal;
  1682. isl_space *nested;
  1683. isl_id **ids = NULL;
  1684. isl_id *id;
  1685. equal = match(space, isl_dim_in, space, isl_dim_out);
  1686. if (equal < 0)
  1687. return isl_space_free(space);
  1688. if (equal)
  1689. return space;
  1690. space = isl_space_cow(space);
  1691. if (!space)
  1692. return NULL;
  1693. id = space->tuple_id[0];
  1694. space->tuple_id[0] = space->tuple_id[1];
  1695. space->tuple_id[1] = id;
  1696. nested = space->nested[0];
  1697. space->nested[0] = space->nested[1];
  1698. space->nested[1] = nested;
  1699. if (space->ids) {
  1700. int n_id = space->n_in + space->n_out;
  1701. ids = isl_alloc_array(space->ctx, isl_id *, n_id);
  1702. if (n_id && !ids)
  1703. goto error;
  1704. get_ids(space, isl_dim_in, 0, space->n_in, ids);
  1705. get_ids(space, isl_dim_out, 0, space->n_out, ids + space->n_in);
  1706. }
  1707. t = space->n_in;
  1708. space->n_in = space->n_out;
  1709. space->n_out = t;
  1710. if (space->ids) {
  1711. space = set_ids(space, isl_dim_out, 0, space->n_out, ids);
  1712. space = set_ids(space, isl_dim_in, 0, space->n_in,
  1713. ids + space->n_out);
  1714. free(ids);
  1715. }
  1716. return space;
  1717. error:
  1718. free(ids);
  1719. isl_space_free(space);
  1720. return NULL;
  1721. }
  1722. /* Given a space A -> (B -> C), return the corresponding space
  1723. * A -> (C -> B).
  1724. *
  1725. * If the range tuple is named, then the name is only preserved
  1726. * if B and C are equal tuples, in which case the output
  1727. * of this function is identical to the input.
  1728. */
  1729. __isl_give isl_space *isl_space_range_reverse(__isl_take isl_space *space)
  1730. {
  1731. isl_space *nested;
  1732. isl_bool equal;
  1733. if (isl_space_check_range_is_wrapping(space) < 0)
  1734. return isl_space_free(space);
  1735. nested = isl_space_peek_nested(space, 1);
  1736. equal = isl_space_tuple_is_equal(nested, isl_dim_in,
  1737. nested, isl_dim_out);
  1738. if (equal < 0)
  1739. return isl_space_free(space);
  1740. nested = isl_space_take_nested(space, 1);
  1741. nested = isl_space_reverse(nested);
  1742. space = isl_space_restore_nested(space, 1, nested);
  1743. if (!equal)
  1744. space = isl_space_reset_tuple_id(space, isl_dim_out);
  1745. return space;
  1746. }
  1747. __isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *space,
  1748. enum isl_dim_type type, unsigned first, unsigned num)
  1749. {
  1750. int i;
  1751. if (!space)
  1752. return NULL;
  1753. if (num == 0)
  1754. return isl_space_reset(space, type);
  1755. if (!valid_dim_type(type))
  1756. isl_die(space->ctx, isl_error_invalid,
  1757. "cannot drop dimensions of specified type", goto error);
  1758. if (isl_space_check_range(space, type, first, num) < 0)
  1759. return isl_space_free(space);
  1760. space = isl_space_cow(space);
  1761. if (!space)
  1762. goto error;
  1763. if (space->ids) {
  1764. space = extend_ids(space);
  1765. if (!space)
  1766. goto error;
  1767. for (i = 0; i < num; ++i)
  1768. isl_id_free(get_id(space, type, first + i));
  1769. for (i = first+num; i < n(space, type); ++i)
  1770. set_id(space, type, i - num, get_id(space, type, i));
  1771. switch (type) {
  1772. case isl_dim_param:
  1773. get_ids(space, isl_dim_in, 0, space->n_in,
  1774. space->ids + offset(space, isl_dim_in) - num);
  1775. case isl_dim_in:
  1776. get_ids(space, isl_dim_out, 0, space->n_out,
  1777. space->ids + offset(space, isl_dim_out) - num);
  1778. default:
  1779. ;
  1780. }
  1781. space->n_id -= num;
  1782. }
  1783. switch (type) {
  1784. case isl_dim_param: space->nparam -= num; break;
  1785. case isl_dim_in: space->n_in -= num; break;
  1786. case isl_dim_out: space->n_out -= num; break;
  1787. default: ;
  1788. }
  1789. space = isl_space_reset(space, type);
  1790. if (type == isl_dim_param) {
  1791. if (space && space->nested[0] &&
  1792. !(space->nested[0] = isl_space_drop_dims(space->nested[0],
  1793. isl_dim_param, first, num)))
  1794. goto error;
  1795. if (space && space->nested[1] &&
  1796. !(space->nested[1] = isl_space_drop_dims(space->nested[1],
  1797. isl_dim_param, first, num)))
  1798. goto error;
  1799. }
  1800. return space;
  1801. error:
  1802. isl_space_free(space);
  1803. return NULL;
  1804. }
  1805. __isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *space,
  1806. unsigned first, unsigned n)
  1807. {
  1808. if (!space)
  1809. return NULL;
  1810. return isl_space_drop_dims(space, isl_dim_in, first, n);
  1811. }
  1812. __isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *space,
  1813. unsigned first, unsigned n)
  1814. {
  1815. if (!space)
  1816. return NULL;
  1817. return isl_space_drop_dims(space, isl_dim_out, first, n);
  1818. }
  1819. /* Remove all parameters from "space".
  1820. */
  1821. __isl_give isl_space *isl_space_drop_all_params(__isl_take isl_space *space)
  1822. {
  1823. isl_size nparam;
  1824. nparam = isl_space_dim(space, isl_dim_param);
  1825. if (nparam < 0)
  1826. return isl_space_free(space);
  1827. return isl_space_drop_dims(space, isl_dim_param, 0, nparam);
  1828. }
  1829. __isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
  1830. {
  1831. if (!space)
  1832. return NULL;
  1833. space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
  1834. space = isl_space_reverse(space);
  1835. space = mark_as_set(space);
  1836. return space;
  1837. }
  1838. __isl_give isl_space *isl_space_from_domain(__isl_take isl_space *space)
  1839. {
  1840. if (!space)
  1841. return NULL;
  1842. if (!isl_space_is_set(space))
  1843. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1844. "not a set space", goto error);
  1845. space = isl_space_reverse(space);
  1846. space = isl_space_reset(space, isl_dim_out);
  1847. return space;
  1848. error:
  1849. isl_space_free(space);
  1850. return NULL;
  1851. }
  1852. __isl_give isl_space *isl_space_range(__isl_take isl_space *space)
  1853. {
  1854. if (!space)
  1855. return NULL;
  1856. space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
  1857. space = mark_as_set(space);
  1858. return space;
  1859. }
  1860. __isl_give isl_space *isl_space_from_range(__isl_take isl_space *space)
  1861. {
  1862. if (!space)
  1863. return NULL;
  1864. if (!isl_space_is_set(space))
  1865. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1866. "not a set space", goto error);
  1867. return isl_space_reset(space, isl_dim_in);
  1868. error:
  1869. isl_space_free(space);
  1870. return NULL;
  1871. }
  1872. /* Given a map space A -> B, return the map space [A -> B] -> A.
  1873. */
  1874. __isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
  1875. {
  1876. isl_space *domain;
  1877. domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
  1878. space = isl_space_from_domain(isl_space_wrap(space));
  1879. space = isl_space_join(space, domain);
  1880. return space;
  1881. }
  1882. /* Given a map space A -> B, return the map space [A -> B] -> B.
  1883. */
  1884. __isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
  1885. {
  1886. isl_space *range;
  1887. range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
  1888. space = isl_space_from_domain(isl_space_wrap(space));
  1889. space = isl_space_join(space, range);
  1890. return space;
  1891. }
  1892. __isl_give isl_space *isl_space_params(__isl_take isl_space *space)
  1893. {
  1894. isl_size n_in, n_out;
  1895. if (isl_space_is_params(space))
  1896. return space;
  1897. n_in = isl_space_dim(space, isl_dim_in);
  1898. n_out = isl_space_dim(space, isl_dim_out);
  1899. if (n_in < 0 || n_out < 0)
  1900. return isl_space_free(space);
  1901. space = isl_space_drop_dims(space, isl_dim_in, 0, n_in);
  1902. space = isl_space_drop_dims(space, isl_dim_out, 0, n_out);
  1903. space = mark_as_params(space);
  1904. return space;
  1905. }
  1906. __isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
  1907. {
  1908. if (!space)
  1909. return NULL;
  1910. if (!isl_space_is_params(space))
  1911. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1912. "not a parameter space", goto error);
  1913. return isl_space_reset(space, isl_dim_set);
  1914. error:
  1915. isl_space_free(space);
  1916. return NULL;
  1917. }
  1918. /* Add an unnamed tuple of dimension "dim" to "space".
  1919. * This requires "space" to be a parameter or set space.
  1920. *
  1921. * In particular, if "space" is a parameter space, then return
  1922. * a set space with the given dimension.
  1923. * If "space" is a set space, then return a map space
  1924. * with "space" as domain and a range of the given dimension.
  1925. */
  1926. __isl_give isl_space *isl_space_add_unnamed_tuple_ui(
  1927. __isl_take isl_space *space, unsigned dim)
  1928. {
  1929. isl_bool is_params, is_set;
  1930. is_params = isl_space_is_params(space);
  1931. is_set = isl_space_is_set(space);
  1932. if (is_params < 0 || is_set < 0)
  1933. return isl_space_free(space);
  1934. if (!is_params && !is_set)
  1935. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1936. "cannot add tuple to map space",
  1937. return isl_space_free(space));
  1938. if (is_params)
  1939. space = isl_space_set_from_params(space);
  1940. else
  1941. space = isl_space_from_domain(space);
  1942. space = isl_space_add_dims(space, isl_dim_out, dim);
  1943. return space;
  1944. }
  1945. /* Add a tuple of dimension "dim" and with tuple identifier "tuple_id"
  1946. * to "space".
  1947. * This requires "space" to be a parameter or set space.
  1948. */
  1949. __isl_give isl_space *isl_space_add_named_tuple_id_ui(
  1950. __isl_take isl_space *space, __isl_take isl_id *tuple_id, unsigned dim)
  1951. {
  1952. space = isl_space_add_unnamed_tuple_ui(space, dim);
  1953. space = isl_space_set_tuple_id(space, isl_dim_out, tuple_id);
  1954. return space;
  1955. }
  1956. /* Check that the identifiers in "tuple" do not appear as parameters
  1957. * in "space".
  1958. */
  1959. static isl_stat check_fresh_params(__isl_keep isl_space *space,
  1960. __isl_keep isl_multi_id *tuple)
  1961. {
  1962. int i;
  1963. isl_size n;
  1964. n = isl_multi_id_size(tuple);
  1965. if (n < 0)
  1966. return isl_stat_error;
  1967. for (i = 0; i < n; ++i) {
  1968. isl_id *id;
  1969. int pos;
  1970. id = isl_multi_id_get_at(tuple, i);
  1971. if (!id)
  1972. return isl_stat_error;
  1973. pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
  1974. isl_id_free(id);
  1975. if (pos >= 0)
  1976. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  1977. "parameters not unique", return isl_stat_error);
  1978. }
  1979. return isl_stat_ok;
  1980. }
  1981. /* Add the identifiers in "tuple" as parameters of "space"
  1982. * that are known to be fresh.
  1983. */
  1984. static __isl_give isl_space *add_bind_params(__isl_take isl_space *space,
  1985. __isl_keep isl_multi_id *tuple)
  1986. {
  1987. int i;
  1988. isl_size first, n;
  1989. first = isl_space_dim(space, isl_dim_param);
  1990. n = isl_multi_id_size(tuple);
  1991. if (first < 0 || n < 0)
  1992. return isl_space_free(space);
  1993. space = isl_space_add_dims(space, isl_dim_param, n);
  1994. for (i = 0; i < n; ++i) {
  1995. isl_id *id;
  1996. id = isl_multi_id_get_at(tuple, i);
  1997. space = isl_space_set_dim_id(space,
  1998. isl_dim_param, first + i, id);
  1999. }
  2000. return space;
  2001. }
  2002. /* Internal function that removes the set tuple of "space",
  2003. * which is assumed to correspond to the range space of "tuple", and
  2004. * adds the identifiers in "tuple" as fresh parameters.
  2005. * In other words, the set dimensions of "space" are reinterpreted
  2006. * as parameters, but stay in the same global positions.
  2007. */
  2008. __isl_give isl_space *isl_space_bind_set(__isl_take isl_space *space,
  2009. __isl_keep isl_multi_id *tuple)
  2010. {
  2011. isl_space *tuple_space;
  2012. if (isl_space_check_is_set(space) < 0)
  2013. return isl_space_free(space);
  2014. tuple_space = isl_multi_id_peek_space(tuple);
  2015. if (isl_space_check_equal_tuples(tuple_space, space) < 0)
  2016. return isl_space_free(space);
  2017. if (check_fresh_params(space, tuple) < 0)
  2018. return isl_space_free(space);
  2019. space = isl_space_params(space);
  2020. space = add_bind_params(space, tuple);
  2021. return space;
  2022. }
  2023. /* Internal function that removes the domain tuple of the map space "space",
  2024. * which is assumed to correspond to the range space of "tuple", and
  2025. * adds the identifiers in "tuple" as fresh parameters.
  2026. * In other words, the domain dimensions of "space" are reinterpreted
  2027. * as parameters, but stay in the same global positions.
  2028. */
  2029. __isl_give isl_space *isl_space_bind_map_domain(__isl_take isl_space *space,
  2030. __isl_keep isl_multi_id *tuple)
  2031. {
  2032. isl_space *tuple_space;
  2033. if (isl_space_check_is_map(space) < 0)
  2034. return isl_space_free(space);
  2035. tuple_space = isl_multi_id_peek_space(tuple);
  2036. if (isl_space_check_domain_tuples(tuple_space, space) < 0)
  2037. return isl_space_free(space);
  2038. if (check_fresh_params(space, tuple) < 0)
  2039. return isl_space_free(space);
  2040. space = isl_space_range(space);
  2041. space = add_bind_params(space, tuple);
  2042. return space;
  2043. }
  2044. /* Internal function that, given a space of the form [A -> B] -> C and
  2045. * a tuple of identifiers in A, returns a space B -> C with
  2046. * the identifiers in "tuple" added as fresh parameters.
  2047. * In other words, the domain dimensions of the wrapped relation
  2048. * in the domain of "space" are reinterpreted
  2049. * as parameters, but stay in the same global positions.
  2050. */
  2051. __isl_give isl_space *isl_space_bind_domain_wrapped_domain(
  2052. __isl_take isl_space *space, __isl_keep isl_multi_id *tuple)
  2053. {
  2054. isl_space *tuple_space;
  2055. if (isl_space_check_is_map(space) < 0)
  2056. return isl_space_free(space);
  2057. tuple_space = isl_multi_id_peek_space(tuple);
  2058. if (isl_space_check_domain_wrapped_domain_tuples(tuple_space,
  2059. space) < 0)
  2060. return isl_space_free(space);
  2061. if (check_fresh_params(space, tuple) < 0)
  2062. return isl_space_free(space);
  2063. space = isl_space_domain_factor_range(space);
  2064. space = add_bind_params(space, tuple);
  2065. return space;
  2066. }
  2067. /* Insert a domain tuple in "space" corresponding to the set space "domain".
  2068. * In particular, if "space" is a parameter space, then the result
  2069. * is the set space "domain" combined with the parameters of "space".
  2070. * If "space" is a set space, then the result
  2071. * is a map space with "domain" as domain and the original space as range.
  2072. */
  2073. static __isl_give isl_space *isl_space_insert_domain(
  2074. __isl_take isl_space *space, __isl_take isl_space *domain)
  2075. {
  2076. isl_bool is_params;
  2077. domain = isl_space_replace_params(domain, space);
  2078. is_params = isl_space_is_params(space);
  2079. if (is_params < 0) {
  2080. isl_space_free(domain);
  2081. space = isl_space_free(space);
  2082. } else if (is_params) {
  2083. isl_space_free(space);
  2084. space = domain;
  2085. } else {
  2086. space = isl_space_map_from_domain_and_range(domain, space);
  2087. }
  2088. return space;
  2089. }
  2090. /* Internal function that introduces a domain in "space"
  2091. * corresponding to the range space of "tuple".
  2092. * In particular, if "space" is a parameter space, then the result
  2093. * is a set space. If "space" is a set space, then the result
  2094. * is a map space with the original space as range.
  2095. * Parameters that correspond to the identifiers in "tuple" are removed.
  2096. *
  2097. * The parameters are removed in reverse order (under the assumption
  2098. * that they appear in the same order in "multi") because
  2099. * it is slightly more efficient to remove parameters at the end.
  2100. *
  2101. * For pretty-printing purposes, the identifiers of the set dimensions
  2102. * of the introduced domain are set to the identifiers in "tuple".
  2103. */
  2104. __isl_give isl_space *isl_space_unbind_params_insert_domain(
  2105. __isl_take isl_space *space, __isl_keep isl_multi_id *tuple)
  2106. {
  2107. int i;
  2108. isl_size n;
  2109. isl_space *tuple_space;
  2110. n = isl_multi_id_size(tuple);
  2111. if (!space || n < 0)
  2112. return isl_space_free(space);
  2113. for (i = n - 1; i >= 0; --i) {
  2114. isl_id *id;
  2115. int pos;
  2116. id = isl_multi_id_get_id(tuple, i);
  2117. if (!id)
  2118. return isl_space_free(space);
  2119. pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
  2120. isl_id_free(id);
  2121. if (pos < 0)
  2122. continue;
  2123. space = isl_space_drop_dims(space, isl_dim_param, pos, 1);
  2124. }
  2125. tuple_space = isl_multi_id_get_space(tuple);
  2126. for (i = 0; i < n; ++i) {
  2127. isl_id *id;
  2128. id = isl_multi_id_get_id(tuple, i);
  2129. tuple_space = isl_space_set_dim_id(tuple_space,
  2130. isl_dim_set, i, id);
  2131. }
  2132. return isl_space_insert_domain(space, tuple_space);
  2133. }
  2134. __isl_give isl_space *isl_space_underlying(__isl_take isl_space *space,
  2135. unsigned n_div)
  2136. {
  2137. int i;
  2138. isl_bool is_set;
  2139. is_set = isl_space_is_set(space);
  2140. if (is_set < 0)
  2141. return isl_space_free(space);
  2142. if (n_div == 0 && is_set &&
  2143. space->nparam == 0 && space->n_in == 0 && space->n_id == 0)
  2144. return isl_space_reset(space, isl_dim_out);
  2145. space = isl_space_cow(space);
  2146. if (!space)
  2147. return NULL;
  2148. space->n_out += space->nparam + space->n_in + n_div;
  2149. space->nparam = 0;
  2150. space->n_in = 0;
  2151. for (i = 0; i < space->n_id; ++i)
  2152. isl_id_free(get_id(space, isl_dim_out, i));
  2153. space->n_id = 0;
  2154. space = isl_space_reset(space, isl_dim_in);
  2155. space = isl_space_reset(space, isl_dim_out);
  2156. space = mark_as_set(space);
  2157. return space;
  2158. }
  2159. /* Are the two spaces the same, including positions and names of parameters?
  2160. */
  2161. isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
  2162. __isl_keep isl_space *space2)
  2163. {
  2164. isl_bool equal;
  2165. if (!space1 || !space2)
  2166. return isl_bool_error;
  2167. if (space1 == space2)
  2168. return isl_bool_true;
  2169. equal = isl_space_has_equal_params(space1, space2);
  2170. if (equal < 0 || !equal)
  2171. return equal;
  2172. return isl_space_has_equal_tuples(space1, space2);
  2173. }
  2174. /* Do the tuples of "space1" correspond to those of the domain of "space2"?
  2175. * That is, is "space1" equal to the domain of "space2", ignoring parameters.
  2176. *
  2177. * "space2" is allowed to be a set space, in which case "space1"
  2178. * should be a parameter space.
  2179. */
  2180. isl_bool isl_space_has_domain_tuples(__isl_keep isl_space *space1,
  2181. __isl_keep isl_space *space2)
  2182. {
  2183. isl_bool is_set;
  2184. is_set = isl_space_is_set(space1);
  2185. if (is_set < 0 || !is_set)
  2186. return is_set;
  2187. return isl_space_tuple_is_equal(space1, isl_dim_set,
  2188. space2, isl_dim_in);
  2189. }
  2190. /* Do the tuples of "space1" correspond to those of the range of "space2"?
  2191. * That is, is "space1" equal to the range of "space2", ignoring parameters.
  2192. *
  2193. * "space2" is allowed to be the space of a set,
  2194. * in which case it should be equal to "space1", ignoring parameters.
  2195. */
  2196. isl_bool isl_space_has_range_tuples(__isl_keep isl_space *space1,
  2197. __isl_keep isl_space *space2)
  2198. {
  2199. isl_bool is_set;
  2200. is_set = isl_space_is_set(space1);
  2201. if (is_set < 0 || !is_set)
  2202. return is_set;
  2203. return isl_space_tuple_is_equal(space1, isl_dim_set,
  2204. space2, isl_dim_out);
  2205. }
  2206. /* Check that the tuples of "space1" correspond to those
  2207. * of the domain of "space2".
  2208. * That is, check that "space1" is equal to the domain of "space2",
  2209. * ignoring parameters.
  2210. */
  2211. isl_stat isl_space_check_domain_tuples(__isl_keep isl_space *space1,
  2212. __isl_keep isl_space *space2)
  2213. {
  2214. isl_bool is_equal;
  2215. is_equal = isl_space_has_domain_tuples(space1, space2);
  2216. return check_match(space1, is_equal);
  2217. }
  2218. /* Check that the tuples of "space1" correspond to those
  2219. * of the domain of the wrapped relation in the domain of "space2".
  2220. * That is, check that "space1" is equal to this domain,
  2221. * ignoring parameters.
  2222. */
  2223. isl_stat isl_space_check_domain_wrapped_domain_tuples(
  2224. __isl_keep isl_space *space1, __isl_keep isl_space *space2)
  2225. {
  2226. isl_space *domain;
  2227. isl_stat r;
  2228. domain = isl_space_unwrap(isl_space_domain(isl_space_copy(space2)));
  2229. r = isl_space_check_domain_tuples(space1, domain);
  2230. isl_space_free(domain);
  2231. return r;
  2232. }
  2233. /* Is space1 equal to the domain of space2?
  2234. *
  2235. * In the internal version we also allow space2 to be the space of a set,
  2236. * provided space1 is a parameter space.
  2237. */
  2238. isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
  2239. __isl_keep isl_space *space2)
  2240. {
  2241. isl_bool equal_params;
  2242. if (!space1 || !space2)
  2243. return isl_bool_error;
  2244. equal_params = isl_space_has_equal_params(space1, space2);
  2245. if (equal_params < 0 || !equal_params)
  2246. return equal_params;
  2247. return isl_space_has_domain_tuples(space1, space2);
  2248. }
  2249. /* Is space1 equal to the domain of space2?
  2250. */
  2251. isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
  2252. __isl_keep isl_space *space2)
  2253. {
  2254. if (!space2)
  2255. return isl_bool_error;
  2256. if (!isl_space_is_map(space2))
  2257. return isl_bool_false;
  2258. return isl_space_is_domain_internal(space1, space2);
  2259. }
  2260. /* Is space1 equal to the range of space2?
  2261. *
  2262. * In the internal version, space2 is allowed to be the space of a set,
  2263. * in which case it should be equal to space1.
  2264. */
  2265. isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
  2266. __isl_keep isl_space *space2)
  2267. {
  2268. isl_bool equal_params;
  2269. if (!space1 || !space2)
  2270. return isl_bool_error;
  2271. equal_params = isl_space_has_equal_params(space1, space2);
  2272. if (equal_params < 0 || !equal_params)
  2273. return equal_params;
  2274. return isl_space_has_range_tuples(space1, space2);
  2275. }
  2276. /* Is space1 equal to the range of space2?
  2277. */
  2278. isl_bool isl_space_is_range(__isl_keep isl_space *space1,
  2279. __isl_keep isl_space *space2)
  2280. {
  2281. if (!space2)
  2282. return isl_bool_error;
  2283. if (!isl_space_is_map(space2))
  2284. return isl_bool_false;
  2285. return isl_space_is_range_internal(space1, space2);
  2286. }
  2287. /* Update "hash" by hashing in the parameters of "space".
  2288. */
  2289. static uint32_t isl_hash_params(uint32_t hash, __isl_keep isl_space *space)
  2290. {
  2291. int i;
  2292. isl_id *id;
  2293. if (!space)
  2294. return hash;
  2295. isl_hash_byte(hash, space->nparam % 256);
  2296. for (i = 0; i < space->nparam; ++i) {
  2297. id = get_id(space, isl_dim_param, i);
  2298. hash = isl_hash_id(hash, id);
  2299. }
  2300. return hash;
  2301. }
  2302. /* Update "hash" by hashing in the tuples of "space".
  2303. * Changes in this function should be reflected in isl_hash_tuples_domain.
  2304. */
  2305. static uint32_t isl_hash_tuples(uint32_t hash, __isl_keep isl_space *space)
  2306. {
  2307. isl_id *id;
  2308. if (!space)
  2309. return hash;
  2310. isl_hash_byte(hash, space->n_in % 256);
  2311. isl_hash_byte(hash, space->n_out % 256);
  2312. id = tuple_id(space, isl_dim_in);
  2313. hash = isl_hash_id(hash, id);
  2314. id = tuple_id(space, isl_dim_out);
  2315. hash = isl_hash_id(hash, id);
  2316. hash = isl_hash_tuples(hash, space->nested[0]);
  2317. hash = isl_hash_tuples(hash, space->nested[1]);
  2318. return hash;
  2319. }
  2320. /* Update "hash" by hashing in the domain tuple of "space".
  2321. * The result of this function is equal to the result of applying
  2322. * isl_hash_tuples to the domain of "space".
  2323. */
  2324. static uint32_t isl_hash_tuples_domain(uint32_t hash,
  2325. __isl_keep isl_space *space)
  2326. {
  2327. isl_id *id;
  2328. if (!space)
  2329. return hash;
  2330. isl_hash_byte(hash, 0);
  2331. isl_hash_byte(hash, space->n_in % 256);
  2332. hash = isl_hash_id(hash, &isl_id_none);
  2333. id = tuple_id(space, isl_dim_in);
  2334. hash = isl_hash_id(hash, id);
  2335. hash = isl_hash_tuples(hash, space->nested[0]);
  2336. return hash;
  2337. }
  2338. /* Return a hash value that digests the tuples of "space",
  2339. * i.e., that ignores the parameters.
  2340. * Changes in this function should be reflected
  2341. * in isl_space_get_tuple_domain_hash.
  2342. */
  2343. uint32_t isl_space_get_tuple_hash(__isl_keep isl_space *space)
  2344. {
  2345. uint32_t hash;
  2346. if (!space)
  2347. return 0;
  2348. hash = isl_hash_init();
  2349. hash = isl_hash_tuples(hash, space);
  2350. return hash;
  2351. }
  2352. /* Return the hash value of "space".
  2353. */
  2354. uint32_t isl_space_get_full_hash(__isl_keep isl_space *space)
  2355. {
  2356. uint32_t hash;
  2357. if (!space)
  2358. return 0;
  2359. hash = isl_hash_init();
  2360. hash = isl_hash_params(hash, space);
  2361. hash = isl_hash_tuples(hash, space);
  2362. return hash;
  2363. }
  2364. /* Return the hash value of the domain tuple of "space".
  2365. * That is, isl_space_get_tuple_domain_hash(space) is equal to
  2366. * isl_space_get_tuple_hash(isl_space_domain(space)).
  2367. */
  2368. uint32_t isl_space_get_tuple_domain_hash(__isl_keep isl_space *space)
  2369. {
  2370. uint32_t hash;
  2371. if (!space)
  2372. return 0;
  2373. hash = isl_hash_init();
  2374. hash = isl_hash_tuples_domain(hash, space);
  2375. return hash;
  2376. }
  2377. /* Is "space" the space of a set wrapping a map space?
  2378. */
  2379. isl_bool isl_space_is_wrapping(__isl_keep isl_space *space)
  2380. {
  2381. if (!space)
  2382. return isl_bool_error;
  2383. if (!isl_space_is_set(space))
  2384. return isl_bool_false;
  2385. return isl_bool_ok(space->nested[1] != NULL);
  2386. }
  2387. /* Is "space" the space of a map where the domain is a wrapped map space?
  2388. */
  2389. isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
  2390. {
  2391. if (!space)
  2392. return isl_bool_error;
  2393. if (isl_space_is_set(space))
  2394. return isl_bool_false;
  2395. return isl_bool_ok(space->nested[0] != NULL);
  2396. }
  2397. /* Is "space" the space of a map where the range is a wrapped map space?
  2398. */
  2399. isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
  2400. {
  2401. if (!space)
  2402. return isl_bool_error;
  2403. if (isl_space_is_set(space))
  2404. return isl_bool_false;
  2405. return isl_bool_ok(space->nested[1] != NULL);
  2406. }
  2407. /* Is "space" a product of two spaces?
  2408. * That is, is it a wrapping set space or a map space
  2409. * with wrapping domain and range?
  2410. */
  2411. isl_bool isl_space_is_product(__isl_keep isl_space *space)
  2412. {
  2413. isl_bool is_set;
  2414. isl_bool is_product;
  2415. is_set = isl_space_is_set(space);
  2416. if (is_set < 0)
  2417. return isl_bool_error;
  2418. if (is_set)
  2419. return isl_space_is_wrapping(space);
  2420. is_product = isl_space_domain_is_wrapping(space);
  2421. if (is_product < 0 || !is_product)
  2422. return is_product;
  2423. return isl_space_range_is_wrapping(space);
  2424. }
  2425. __isl_give isl_space *isl_space_wrap(__isl_take isl_space *space)
  2426. {
  2427. isl_space *wrap;
  2428. if (!space)
  2429. return NULL;
  2430. wrap = isl_space_set_alloc(space->ctx,
  2431. space->nparam, space->n_in + space->n_out);
  2432. wrap = copy_ids(wrap, isl_dim_param, 0, space, isl_dim_param);
  2433. wrap = copy_ids(wrap, isl_dim_set, 0, space, isl_dim_in);
  2434. wrap = copy_ids(wrap, isl_dim_set, space->n_in, space, isl_dim_out);
  2435. if (!wrap)
  2436. goto error;
  2437. wrap->nested[1] = space;
  2438. return wrap;
  2439. error:
  2440. isl_space_free(space);
  2441. return NULL;
  2442. }
  2443. __isl_give isl_space *isl_space_unwrap(__isl_take isl_space *space)
  2444. {
  2445. isl_space *unwrap;
  2446. if (!space)
  2447. return NULL;
  2448. if (!isl_space_is_wrapping(space))
  2449. isl_die(space->ctx, isl_error_invalid, "not a wrapping space",
  2450. goto error);
  2451. unwrap = isl_space_copy(space->nested[1]);
  2452. isl_space_free(space);
  2453. return unwrap;
  2454. error:
  2455. isl_space_free(space);
  2456. return NULL;
  2457. }
  2458. isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
  2459. enum isl_dim_type type)
  2460. {
  2461. if (type != isl_dim_in && type != isl_dim_out)
  2462. return isl_bool_false;
  2463. if (!space)
  2464. return isl_bool_error;
  2465. if (space->tuple_id[type - isl_dim_in])
  2466. return isl_bool_true;
  2467. if (space->nested[type - isl_dim_in])
  2468. return isl_bool_true;
  2469. return isl_bool_false;
  2470. }
  2471. isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
  2472. {
  2473. isl_bool nested;
  2474. isl_size n_in;
  2475. if (!space)
  2476. return isl_bool_error;
  2477. if (isl_space_is_set(space))
  2478. return isl_bool_true;
  2479. n_in = isl_space_dim(space, isl_dim_in);
  2480. if (n_in < 0)
  2481. return isl_bool_error;
  2482. if (n_in != 0)
  2483. return isl_bool_false;
  2484. nested = isl_space_is_named_or_nested(space, isl_dim_in);
  2485. if (nested < 0 || nested)
  2486. return isl_bool_not(nested);
  2487. return isl_bool_true;
  2488. }
  2489. __isl_give isl_space *isl_space_reset(__isl_take isl_space *space,
  2490. enum isl_dim_type type)
  2491. {
  2492. if (!isl_space_is_named_or_nested(space, type))
  2493. return space;
  2494. space = isl_space_cow(space);
  2495. if (!space)
  2496. return NULL;
  2497. isl_id_free(space->tuple_id[type - isl_dim_in]);
  2498. space->tuple_id[type - isl_dim_in] = NULL;
  2499. isl_space_free(space->nested[type - isl_dim_in]);
  2500. space->nested[type - isl_dim_in] = NULL;
  2501. return space;
  2502. }
  2503. __isl_give isl_space *isl_space_flatten(__isl_take isl_space *space)
  2504. {
  2505. if (!space)
  2506. return NULL;
  2507. if (!space->nested[0] && !space->nested[1])
  2508. return space;
  2509. if (space->nested[0])
  2510. space = isl_space_reset(space, isl_dim_in);
  2511. if (space && space->nested[1])
  2512. space = isl_space_reset(space, isl_dim_out);
  2513. return space;
  2514. }
  2515. __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space)
  2516. {
  2517. if (!space)
  2518. return NULL;
  2519. if (!space->nested[0])
  2520. return space;
  2521. return isl_space_reset(space, isl_dim_in);
  2522. }
  2523. __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space)
  2524. {
  2525. if (!space)
  2526. return NULL;
  2527. if (!space->nested[1])
  2528. return space;
  2529. return isl_space_reset(space, isl_dim_out);
  2530. }
  2531. /* Replace the parameters of dst by those of src.
  2532. */
  2533. __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
  2534. __isl_keep isl_space *src)
  2535. {
  2536. isl_size dst_dim, src_dim;
  2537. isl_bool equal_params;
  2538. enum isl_dim_type type = isl_dim_param;
  2539. equal_params = isl_space_has_equal_params(dst, src);
  2540. if (equal_params < 0)
  2541. return isl_space_free(dst);
  2542. if (equal_params)
  2543. return dst;
  2544. dst = isl_space_cow(dst);
  2545. dst_dim = isl_space_dim(dst, type);
  2546. src_dim = isl_space_dim(src, type);
  2547. if (dst_dim < 0 || src_dim < 0)
  2548. goto error;
  2549. dst = isl_space_drop_dims(dst, type, 0, dst_dim);
  2550. dst = isl_space_add_dims(dst, type, src_dim);
  2551. dst = copy_ids(dst, type, 0, src, type);
  2552. if (dst) {
  2553. int i;
  2554. for (i = 0; i <= 1; ++i) {
  2555. isl_space *nested;
  2556. if (!dst->nested[i])
  2557. continue;
  2558. nested = isl_space_take_nested(dst, i);
  2559. nested = isl_space_replace_params(nested, src);
  2560. dst = isl_space_restore_nested(dst, i, nested);
  2561. if (!dst)
  2562. return NULL;
  2563. }
  2564. }
  2565. return dst;
  2566. error:
  2567. isl_space_free(dst);
  2568. return NULL;
  2569. }
  2570. /* Given two tuples ("dst_type" in "dst" and "src_type" in "src")
  2571. * of the same size, check if any of the dimensions in the "dst" tuple
  2572. * have no identifier, while the corresponding dimensions in "src"
  2573. * does have an identifier,
  2574. * If so, copy the identifier over to "dst".
  2575. */
  2576. __isl_give isl_space *isl_space_copy_ids_if_unset(__isl_take isl_space *dst,
  2577. enum isl_dim_type dst_type, __isl_keep isl_space *src,
  2578. enum isl_dim_type src_type)
  2579. {
  2580. int i;
  2581. isl_size n;
  2582. n = isl_space_dim(dst, dst_type);
  2583. if (n < 0)
  2584. return isl_space_free(dst);
  2585. for (i = 0; i < n; ++i) {
  2586. isl_bool set;
  2587. isl_id *id;
  2588. set = isl_space_has_dim_id(dst, dst_type, i);
  2589. if (set < 0)
  2590. return isl_space_free(dst);
  2591. if (set)
  2592. continue;
  2593. set = isl_space_has_dim_id(src, src_type, i);
  2594. if (set < 0)
  2595. return isl_space_free(dst);
  2596. if (!set)
  2597. continue;
  2598. id = isl_space_get_dim_id(src, src_type, i);
  2599. dst = isl_space_set_dim_id(dst, dst_type, i, id);
  2600. }
  2601. return dst;
  2602. }
  2603. /* Given a space "space" of a set, create a space
  2604. * for the lift of the set. In particular, the result
  2605. * is of the form lifted[space -> local[..]], with n_local variables in the
  2606. * range of the wrapped map.
  2607. */
  2608. __isl_give isl_space *isl_space_lift(__isl_take isl_space *space,
  2609. unsigned n_local)
  2610. {
  2611. isl_space *local_space;
  2612. if (!space)
  2613. return NULL;
  2614. local_space = isl_space_dup(space);
  2615. local_space = isl_space_drop_dims(local_space, isl_dim_set, 0,
  2616. space->n_out);
  2617. local_space = isl_space_add_dims(local_space, isl_dim_set, n_local);
  2618. local_space = isl_space_set_tuple_name(local_space,
  2619. isl_dim_set, "local");
  2620. space = isl_space_join(isl_space_from_domain(space),
  2621. isl_space_from_range(local_space));
  2622. space = isl_space_wrap(space);
  2623. space = isl_space_set_tuple_name(space, isl_dim_set, "lifted");
  2624. return space;
  2625. }
  2626. isl_bool isl_space_can_zip(__isl_keep isl_space *space)
  2627. {
  2628. isl_bool is_set;
  2629. is_set = isl_space_is_set(space);
  2630. if (is_set < 0)
  2631. return isl_bool_error;
  2632. if (is_set)
  2633. return isl_bool_false;
  2634. return isl_space_is_product(space);
  2635. }
  2636. __isl_give isl_space *isl_space_zip(__isl_take isl_space *space)
  2637. {
  2638. isl_space *dom, *ran;
  2639. isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
  2640. if (!isl_space_can_zip(space))
  2641. isl_die(space->ctx, isl_error_invalid, "space cannot be zipped",
  2642. goto error);
  2643. if (!space)
  2644. return NULL;
  2645. dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
  2646. ran = isl_space_unwrap(isl_space_range(space));
  2647. dom_dom = isl_space_domain(isl_space_copy(dom));
  2648. dom_ran = isl_space_range(dom);
  2649. ran_dom = isl_space_domain(isl_space_copy(ran));
  2650. ran_ran = isl_space_range(ran);
  2651. dom = isl_space_join(isl_space_from_domain(dom_dom),
  2652. isl_space_from_range(ran_dom));
  2653. ran = isl_space_join(isl_space_from_domain(dom_ran),
  2654. isl_space_from_range(ran_ran));
  2655. return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
  2656. isl_space_from_range(isl_space_wrap(ran)));
  2657. error:
  2658. isl_space_free(space);
  2659. return NULL;
  2660. }
  2661. /* Can we apply isl_space_curry to "space"?
  2662. * That is, does is it have a map space with a nested relation in its domain?
  2663. */
  2664. isl_bool isl_space_can_curry(__isl_keep isl_space *space)
  2665. {
  2666. return isl_space_domain_is_wrapping(space);
  2667. }
  2668. /* Given a space (A -> B) -> C, return the corresponding space
  2669. * A -> (B -> C).
  2670. */
  2671. __isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
  2672. {
  2673. isl_space *dom, *ran;
  2674. isl_space *dom_dom, *dom_ran;
  2675. if (!space)
  2676. return NULL;
  2677. if (!isl_space_can_curry(space))
  2678. isl_die(space->ctx, isl_error_invalid,
  2679. "space cannot be curried", goto error);
  2680. dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
  2681. ran = isl_space_range(space);
  2682. dom_dom = isl_space_domain(isl_space_copy(dom));
  2683. dom_ran = isl_space_range(dom);
  2684. ran = isl_space_join(isl_space_from_domain(dom_ran),
  2685. isl_space_from_range(ran));
  2686. return isl_space_join(isl_space_from_domain(dom_dom),
  2687. isl_space_from_range(isl_space_wrap(ran)));
  2688. error:
  2689. isl_space_free(space);
  2690. return NULL;
  2691. }
  2692. /* Can isl_space_range_curry be applied to "space"?
  2693. * That is, does it have a nested relation in its range,
  2694. * the domain of which is itself a nested relation?
  2695. */
  2696. isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
  2697. {
  2698. isl_bool can;
  2699. if (!space)
  2700. return isl_bool_error;
  2701. can = isl_space_range_is_wrapping(space);
  2702. if (can < 0 || !can)
  2703. return can;
  2704. return isl_space_can_curry(space->nested[1]);
  2705. }
  2706. /* Given a space A -> ((B -> C) -> D), return the corresponding space
  2707. * A -> (B -> (C -> D)).
  2708. */
  2709. __isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
  2710. {
  2711. isl_space *nested;
  2712. if (!space)
  2713. return NULL;
  2714. if (!isl_space_can_range_curry(space))
  2715. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  2716. "space range cannot be curried",
  2717. return isl_space_free(space));
  2718. nested = isl_space_take_nested(space, 1);
  2719. nested = isl_space_curry(nested);
  2720. space = isl_space_restore_nested(space, 1, nested);
  2721. return space;
  2722. }
  2723. /* Can we apply isl_space_uncurry to "space"?
  2724. * That is, does it have a map space with a nested relation in its range?
  2725. */
  2726. isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
  2727. {
  2728. return isl_space_range_is_wrapping(space);
  2729. }
  2730. /* Given a space A -> (B -> C), return the corresponding space
  2731. * (A -> B) -> C.
  2732. */
  2733. __isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
  2734. {
  2735. isl_space *dom, *ran;
  2736. isl_space *ran_dom, *ran_ran;
  2737. if (!space)
  2738. return NULL;
  2739. if (!isl_space_can_uncurry(space))
  2740. isl_die(space->ctx, isl_error_invalid,
  2741. "space cannot be uncurried",
  2742. return isl_space_free(space));
  2743. dom = isl_space_domain(isl_space_copy(space));
  2744. ran = isl_space_unwrap(isl_space_range(space));
  2745. ran_dom = isl_space_domain(isl_space_copy(ran));
  2746. ran_ran = isl_space_range(ran);
  2747. dom = isl_space_join(isl_space_from_domain(dom),
  2748. isl_space_from_range(ran_dom));
  2749. return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
  2750. isl_space_from_range(ran_ran));
  2751. }
  2752. isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
  2753. {
  2754. int i;
  2755. unsigned off;
  2756. if (!space)
  2757. return isl_bool_error;
  2758. if (space->nparam == 0)
  2759. return isl_bool_true;
  2760. off = isl_space_offset(space, isl_dim_param);
  2761. if (off + space->nparam > space->n_id)
  2762. return isl_bool_false;
  2763. for (i = 0; i < space->nparam; ++i)
  2764. if (!space->ids[off + i])
  2765. return isl_bool_false;
  2766. return isl_bool_true;
  2767. }
  2768. /* Check that "space" has only named parameters, reporting an error
  2769. * if it does not.
  2770. */
  2771. isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
  2772. {
  2773. isl_bool named;
  2774. named = isl_space_has_named_params(space);
  2775. if (named < 0)
  2776. return isl_stat_error;
  2777. if (!named)
  2778. isl_die(isl_space_get_ctx(space), isl_error_invalid,
  2779. "unexpected unnamed parameters", return isl_stat_error);
  2780. return isl_stat_ok;
  2781. }
  2782. /* Align the initial parameters of space1 to match the order in space2.
  2783. */
  2784. __isl_give isl_space *isl_space_align_params(__isl_take isl_space *space1,
  2785. __isl_take isl_space *space2)
  2786. {
  2787. isl_reordering *exp;
  2788. if (isl_space_check_named_params(space1) < 0 ||
  2789. isl_space_check_named_params(space2) < 0)
  2790. goto error;
  2791. exp = isl_parameter_alignment_reordering(space1, space2);
  2792. exp = isl_reordering_extend_space(exp, space1);
  2793. isl_space_free(space2);
  2794. space1 = isl_reordering_get_space(exp);
  2795. isl_reordering_free(exp);
  2796. return space1;
  2797. error:
  2798. isl_space_free(space1);
  2799. isl_space_free(space2);
  2800. return NULL;
  2801. }
  2802. /* Given the space of set (domain), construct a space for a map
  2803. * with as domain the given space and as range the range of "model".
  2804. */
  2805. __isl_give isl_space *isl_space_extend_domain_with_range(
  2806. __isl_take isl_space *space, __isl_take isl_space *model)
  2807. {
  2808. isl_size n_out;
  2809. if (!model)
  2810. goto error;
  2811. space = isl_space_from_domain(space);
  2812. n_out = isl_space_dim(model, isl_dim_out);
  2813. if (n_out < 0)
  2814. goto error;
  2815. space = isl_space_add_dims(space, isl_dim_out, n_out);
  2816. if (isl_space_has_tuple_id(model, isl_dim_out))
  2817. space = isl_space_set_tuple_id(space, isl_dim_out,
  2818. isl_space_get_tuple_id(model, isl_dim_out));
  2819. if (!space)
  2820. goto error;
  2821. if (model->nested[1]) {
  2822. isl_space *nested = isl_space_copy(model->nested[1]);
  2823. isl_size n_nested, n_space;
  2824. nested = isl_space_align_params(nested, isl_space_copy(space));
  2825. n_nested = isl_space_dim(nested, isl_dim_param);
  2826. n_space = isl_space_dim(space, isl_dim_param);
  2827. if (n_nested < 0 || n_space < 0)
  2828. goto error;
  2829. if (n_nested > n_space)
  2830. nested = isl_space_drop_dims(nested, isl_dim_param,
  2831. n_space, n_nested - n_space);
  2832. if (!nested)
  2833. goto error;
  2834. space->nested[1] = nested;
  2835. }
  2836. isl_space_free(model);
  2837. return space;
  2838. error:
  2839. isl_space_free(model);
  2840. isl_space_free(space);
  2841. return NULL;
  2842. }
  2843. /* Compare the "type" dimensions of two isl_spaces.
  2844. *
  2845. * The order is fairly arbitrary.
  2846. */
  2847. static int isl_space_cmp_type(__isl_keep isl_space *space1,
  2848. __isl_keep isl_space *space2, enum isl_dim_type type)
  2849. {
  2850. int cmp;
  2851. isl_size dim1, dim2;
  2852. isl_space *nested1, *nested2;
  2853. dim1 = isl_space_dim(space1, type);
  2854. dim2 = isl_space_dim(space2, type);
  2855. if (dim1 < 0 || dim2 < 0)
  2856. return 0;
  2857. if (dim1 != dim2)
  2858. return dim1 - dim2;
  2859. cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
  2860. if (cmp != 0)
  2861. return cmp;
  2862. nested1 = nested(space1, type);
  2863. nested2 = nested(space2, type);
  2864. if (!nested1 != !nested2)
  2865. return !nested1 - !nested2;
  2866. if (nested1)
  2867. return isl_space_cmp(nested1, nested2);
  2868. return 0;
  2869. }
  2870. /* Compare two isl_spaces.
  2871. *
  2872. * The order is fairly arbitrary.
  2873. */
  2874. int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
  2875. {
  2876. int i;
  2877. int cmp;
  2878. if (space1 == space2)
  2879. return 0;
  2880. if (!space1)
  2881. return -1;
  2882. if (!space2)
  2883. return 1;
  2884. cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
  2885. if (cmp != 0)
  2886. return cmp;
  2887. cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
  2888. if (cmp != 0)
  2889. return cmp;
  2890. cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
  2891. if (cmp != 0)
  2892. return cmp;
  2893. if (!space1->ids && !space2->ids)
  2894. return 0;
  2895. for (i = 0; i < n(space1, isl_dim_param); ++i) {
  2896. cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
  2897. get_id(space2, isl_dim_param, i));
  2898. if (cmp != 0)
  2899. return cmp;
  2900. }
  2901. return 0;
  2902. }