multiTransitionHelpers.I 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // Filename: multiTransitionHelpers.I
  2. // Created by: drose (15Feb99)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. ////////////////////////////////////////////////////////////////////
  6. // Function: dmap_compose
  7. // Description: Accepts two DirectionMaps, and builds a new
  8. // list (another DirectionMap) which represents the
  9. // memberwise composition of the two input maps.
  10. ////////////////////////////////////////////////////////////////////
  11. template<class InputIterator1, class InputIterator2, class OutputIterator>
  12. OutputIterator
  13. dmap_compose(InputIterator1 first1, InputIterator1 last1,
  14. InputIterator2 first2, InputIterator2 last2,
  15. OutputIterator result) {
  16. while (first1 != last1 && first2 != last2) {
  17. if ((*first1).first < (*first2).first) {
  18. *result = *first1;
  19. ++first1;
  20. ++result;
  21. } else if ((*first2).first < (*first1).first) {
  22. *result = *first2;
  23. ++first2;
  24. ++result;
  25. } else {
  26. // If the second Transition is identity, it has no effect.
  27. // Otherwise, it replaces us.
  28. if ((*first2).second != TD_identity) {
  29. *result = *first2;
  30. } else {
  31. *result = *first1;
  32. }
  33. ++first1;
  34. ++first2;
  35. ++result;
  36. }
  37. }
  38. while (first1 != last1) {
  39. *result = *first1;
  40. ++first1;
  41. ++result;
  42. }
  43. while (first2 != last2) {
  44. *result = *first2;
  45. ++first2;
  46. ++result;
  47. }
  48. return result;
  49. }
  50. ////////////////////////////////////////////////////////////////////
  51. // Function: dmap_invert_compose
  52. // Description: Accepts two DirectionMaps, and builds a new
  53. // list (another DirectionMap) which represents the
  54. // memberwise result inverting and composing.
  55. ////////////////////////////////////////////////////////////////////
  56. template<class InputIterator1, class InputIterator2, class OutputIterator>
  57. OutputIterator
  58. dmap_invert_compose(InputIterator1 first1, InputIterator1 last1,
  59. InputIterator2 first2, InputIterator2 last2,
  60. OutputIterator result) {
  61. typedef TYPENAME InputIterator1::value_type OutputType;
  62. while (first1 != last1 && first2 != last2) {
  63. if ((*first1).first < (*first2).first) {
  64. (*result) = OutputType((*first1).first, TD_inverse);
  65. ++first1;
  66. ++result;
  67. } else if ((*first2).first < (*first1).first) {
  68. *result = *first2;
  69. ++first2;
  70. ++result;
  71. } else {
  72. TransitionDirection dir1 = (*first1).second;
  73. TransitionDirection dir2 = (*first2).second;
  74. if (dir1 == dir2 &&
  75. (dir1 != TD_normal || (*first1).first == (*first2).first)) {
  76. // The two transitions are equivalent, so the invert_compose
  77. // will be identity. Don't bother to store it.
  78. } else {
  79. if ((*first2).second != TD_identity) {
  80. *result = *first2;
  81. } else {
  82. (*result) = OutputType((*first1).first, TD_inverse);
  83. }
  84. ++result;
  85. }
  86. ++first1;
  87. ++first2;
  88. }
  89. }
  90. while (first1 != last1) {
  91. (*result) = OutputType((*first1).first, TD_inverse);
  92. ++first1;
  93. ++result;
  94. }
  95. while (first2 != last2) {
  96. *result = *first2;
  97. ++first2;
  98. ++result;
  99. }
  100. return result;
  101. }
  102. ////////////////////////////////////////////////////////////////////
  103. // Function: dmap_invert
  104. // Description: Accepts a DirectionMap, and builds a new list
  105. // which represents the memberwise inversion of the
  106. // input. Guarantees that the new list will have
  107. // exactly the same length as the input list.
  108. ////////////////////////////////////////////////////////////////////
  109. template<class InputIterator, class OutputIterator>
  110. OutputIterator
  111. dmap_invert(InputIterator first, InputIterator last,
  112. OutputIterator result) {
  113. typedef TYPENAME InputIterator::value_type OutputType;
  114. while (first != last) {
  115. switch ((*first).second) {
  116. case TD_identity:
  117. (*result) = OutputType((*first).first, TD_identity);
  118. ++result;
  119. break;
  120. case TD_on:
  121. (*result) = OutputType((*first).first, TD_off);
  122. ++result;
  123. break;
  124. case TD_off:
  125. (*result) = OutputType((*first).first, TD_on);
  126. ++result;
  127. break;
  128. }
  129. ++first;
  130. }
  131. return result;
  132. }
  133. ////////////////////////////////////////////////////////////////////
  134. // Function: dmap_equiv
  135. // Description: Accepts a pair of DirectionMaps, and returns
  136. // true if they are equivalent, false otherwise. Two
  137. // DirectionMaps are defined to be equivalent if
  138. // all nonidentity members present in one set are
  139. // present and equivalent in the other set,
  140. ////////////////////////////////////////////////////////////////////
  141. template<class InputIterator1, class InputIterator2>
  142. bool
  143. dmap_equiv(InputIterator1 first1, InputIterator1 last1,
  144. InputIterator2 first2, InputIterator2 last2) {
  145. while (first1 != last1 && first2 != last2) {
  146. if ((*first1).first < (*first2).first) {
  147. if ((*first1).second != TD_identity) {
  148. return false;
  149. }
  150. ++first1;
  151. } else if ((*first2).first < (*first1).first) {
  152. if ((*first2).second != TD_identity) {
  153. return false;
  154. }
  155. ++first2;
  156. } else {
  157. TransitionDirection dir1 = (*first1).second;
  158. TransitionDirection dir2 = (*first2).second;
  159. if (dir1 != dir2) {
  160. return false;
  161. }
  162. ++first1;
  163. ++first2;
  164. }
  165. }
  166. while (first1 != last1) {
  167. if ((*first1).second != TD_identity) {
  168. return false;
  169. }
  170. ++first1;
  171. }
  172. while (first2 != last2) {
  173. if ((*first2).second != TD_identity) {
  174. return false;
  175. }
  176. ++first2;
  177. }
  178. return true;
  179. }
  180. ////////////////////////////////////////////////////////////////////
  181. // Function: dmap_compare
  182. // Description: Accepts a pair of DirectionMaps, and returns
  183. // < 0 if the first one sorts before the second one, > 0
  184. // if the first one sorts after, 0 if they are
  185. // equivalent.
  186. ////////////////////////////////////////////////////////////////////
  187. template<class InputIterator1, class InputIterator2>
  188. int
  189. dmap_compare(InputIterator1 first1, InputIterator1 last1,
  190. InputIterator2 first2, InputIterator2 last2) {
  191. while (first1 != last1 && first2 != last2) {
  192. if ((*first1).first < (*first2).first) {
  193. if ((*first1).second != TD_identity) {
  194. // list1 has the first value that does not appear in list2.
  195. return 1;
  196. }
  197. ++first1;
  198. } else if ((*first2).first < (*first1).first) {
  199. if ((*first2).second != TD_identity) {
  200. // list2 has the first value that does not appear in list1.
  201. return -1;
  202. }
  203. ++first2;
  204. } else {
  205. TransitionDirection dir1 = (*first1).second;
  206. TransitionDirection dir2 = (*first2).second;
  207. if (dir1 != dir2) {
  208. if (dir1 == TD_identity) {
  209. // list1 has the first value that does not appear in list2.
  210. return 1;
  211. } else if (dir2 == TD_identity) {
  212. // list2 has the first value that does not appear in list1.
  213. return -1;
  214. }
  215. // This value appears in both lists, but it is TD_normal in
  216. // one and TD_inverse in the other.
  217. return (dir1 < dir2) ? -1 : 1;
  218. }
  219. ++first1;
  220. ++first2;
  221. }
  222. }
  223. while (first1 != last1) {
  224. if ((*first1).second != TD_identity) {
  225. // list1 is longer.
  226. return -1;
  227. }
  228. ++first1;
  229. }
  230. while (first2 != last2) {
  231. if ((*first2).second != TD_identity) {
  232. // list2 is longer.
  233. return 1;
  234. }
  235. ++first2;
  236. }
  237. return 0;
  238. }
  239. ////////////////////////////////////////////////////////////////////
  240. // Function: dmap_is_identity
  241. // Description: Accepts a DirectionMap, and returns true if all
  242. // elements in the map correspond to the identity
  243. // transition, false otherwise.
  244. ////////////////////////////////////////////////////////////////////
  245. template<class InputIterator>
  246. bool
  247. dmap_is_identity(InputIterator first, InputIterator last) {
  248. while (first != last) {
  249. if ((*first).second != TD_identity) {
  250. return false;
  251. }
  252. ++first;
  253. }
  254. return true;
  255. }
  256. ////////////////////////////////////////////////////////////////////
  257. // Function: bmap_equiv
  258. // Description: Accepts a pair of BoolMaps, and returns true if they
  259. // are equivalent, false otherwise. Two BoolMaps are
  260. // defined to be equivalent if all 'on' members present
  261. // in one set are present and equivalent in the other
  262. // set,
  263. ////////////////////////////////////////////////////////////////////
  264. template<class InputIterator1, class InputIterator2>
  265. bool
  266. bmap_equiv(InputIterator1 first1, InputIterator1 last1,
  267. InputIterator2 first2, InputIterator2 last2) {
  268. while (first1 != last1 && first2 != last2) {
  269. if ((*first1) < (*first2)) {
  270. return false;
  271. } else if ((*first2) < (*first1)) {
  272. return false;
  273. } else {
  274. ++first1;
  275. ++first2;
  276. }
  277. }
  278. if (first1 != last1 || first2 != last2) {
  279. return false;
  280. }
  281. return true;
  282. }
  283. ////////////////////////////////////////////////////////////////////
  284. // Function: bmap_compare
  285. // Description: Accepts a pair of BoolMaps, and returns < 0 if the
  286. // first one sorts first, > 0 if the second one sorts
  287. // first, 0 if they are equivalent.
  288. ////////////////////////////////////////////////////////////////////
  289. template<class InputIterator1, class InputIterator2>
  290. int
  291. bmap_compare(InputIterator1 first1, InputIterator1 last1,
  292. InputIterator2 first2, InputIterator2 last2) {
  293. while (first1 != last1 && first2 != last2) {
  294. if ((*first1) < (*first2)) {
  295. return -1;
  296. } else if ((*first2) < (*first1)) {
  297. return 1;
  298. } else {
  299. ++first1;
  300. ++first2;
  301. }
  302. }
  303. if (first1 != last1) {
  304. // list 1 is longer.
  305. return -1;
  306. }
  307. if (first2 != last2) {
  308. // list 2 is longer.
  309. return 1;
  310. }
  311. return 0;
  312. }
  313. ////////////////////////////////////////////////////////////////////
  314. // Function: bmap_apply
  315. // Description: Accepts a BoolMap and a DirectionMap, and builds a
  316. // new list (another BoolMap) which represents the
  317. // memberwise application of the two input maps.
  318. ////////////////////////////////////////////////////////////////////
  319. template<class InputIterator1, class InputIterator2, class OutputIterator>
  320. OutputIterator
  321. bmap_apply(InputIterator1 first1, InputIterator1 last1,
  322. InputIterator2 first2, InputIterator2 last2,
  323. bool complete_transition, TransitionDirection want_dirs,
  324. OutputIterator result) {
  325. while (first1 != last1 && first2 != last2) {
  326. if ((*first1) < (*first2).first) {
  327. // Here's an attribute property that wasn't mentioned by the
  328. // transition. It stays, unless the transition is "complete".
  329. if (!complete_transition) {
  330. *result = *first1;
  331. ++result;
  332. }
  333. ++first1;
  334. } else if ((*first2).first < (*first1)) {
  335. // The transition mentions this property that wasn't previously
  336. // in the attribute. It becomes a member of the attribute only
  337. // if the transition explicitly turned it on.
  338. if ((*first2).second == want_dirs) {
  339. *result = (*first2).first;
  340. ++result;
  341. break;
  342. }
  343. ++first2;
  344. } else { // ((*first2).first == (*first1))
  345. // The transition mentions this property that was already in the
  346. // attribute. Does the transition replace, preserve, or delete
  347. // the attribute?
  348. if ((*first2).second == TD_identity) {
  349. // Preserve.
  350. *result = *first1;
  351. ++result;
  352. } else if ((*first2).second == want_dirs) {
  353. // Replace.
  354. *result = (*first2).first;
  355. ++result;
  356. } else {
  357. // Omit.
  358. }
  359. ++first1;
  360. ++first2;
  361. }
  362. }
  363. while (first1 != last1) {
  364. // Here's an attribute property that wasn't mentioned by the
  365. // transition. It stays, unless the transition is "complete".
  366. if (!complete_transition) {
  367. *result = *first1;
  368. ++result;
  369. }
  370. ++first1;
  371. }
  372. while (first2 != last2) {
  373. // The transition mentions this property that wasn't previously
  374. // in the attribute. It becomes a member of the attribute only
  375. // if the transition explicitly turned it on.
  376. if ((*first2).second == want_dirs) {
  377. *result = (*first2).first;
  378. ++result;
  379. break;
  380. }
  381. ++first2;
  382. }
  383. return result;
  384. }