437 lines
12 KiB
Plaintext
437 lines
12 KiB
Plaintext
// Filename: multiTransitionHelpers.I
|
|
// Created by: drose (15Feb99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_compose
|
|
// Description: Accepts two DirectionMaps, and builds a new
|
|
// list (another DirectionMap) which represents the
|
|
// memberwise composition of the two input maps.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2, class OutputIterator>
|
|
OutputIterator
|
|
dmap_compose(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2,
|
|
OutputIterator result) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1).first < (*first2).first) {
|
|
*result = *first1;
|
|
++first1;
|
|
++result;
|
|
} else if ((*first2).first < (*first1).first) {
|
|
*result = *first2;
|
|
++first2;
|
|
++result;
|
|
} else {
|
|
// If the second Transition is identity, it has no effect.
|
|
// Otherwise, it replaces us.
|
|
if ((*first2).second != TD_identity) {
|
|
*result = *first2;
|
|
} else {
|
|
*result = *first1;
|
|
}
|
|
++first1;
|
|
++first2;
|
|
++result;
|
|
}
|
|
}
|
|
|
|
while (first1 != last1) {
|
|
*result = *first1;
|
|
++first1;
|
|
++result;
|
|
}
|
|
|
|
while (first2 != last2) {
|
|
*result = *first2;
|
|
++first2;
|
|
++result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_invert_compose
|
|
// Description: Accepts two DirectionMaps, and builds a new
|
|
// list (another DirectionMap) which represents the
|
|
// memberwise result inverting and composing.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2, class OutputIterator>
|
|
OutputIterator
|
|
dmap_invert_compose(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2,
|
|
OutputIterator result) {
|
|
typedef TYPENAME InputIterator1::value_type OutputType;
|
|
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1).first < (*first2).first) {
|
|
(*result) = OutputType((*first1).first, TD_inverse);
|
|
++first1;
|
|
++result;
|
|
} else if ((*first2).first < (*first1).first) {
|
|
*result = *first2;
|
|
++first2;
|
|
++result;
|
|
} else {
|
|
TransitionDirection dir1 = (*first1).second;
|
|
TransitionDirection dir2 = (*first2).second;
|
|
|
|
if (dir1 == dir2 &&
|
|
(dir1 != TD_normal || (*first1).first == (*first2).first)) {
|
|
// The two transitions are equivalent, so the invert_compose
|
|
// will be identity. Don't bother to store it.
|
|
|
|
} else {
|
|
if ((*first2).second != TD_identity) {
|
|
*result = *first2;
|
|
} else {
|
|
(*result) = OutputType((*first1).first, TD_inverse);
|
|
}
|
|
++result;
|
|
}
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
while (first1 != last1) {
|
|
(*result) = OutputType((*first1).first, TD_inverse);
|
|
++first1;
|
|
++result;
|
|
}
|
|
|
|
while (first2 != last2) {
|
|
*result = *first2;
|
|
++first2;
|
|
++result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_invert
|
|
// Description: Accepts a DirectionMap, and builds a new list
|
|
// which represents the memberwise inversion of the
|
|
// input. Guarantees that the new list will have
|
|
// exactly the same length as the input list.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator, class OutputIterator>
|
|
OutputIterator
|
|
dmap_invert(InputIterator first, InputIterator last,
|
|
OutputIterator result) {
|
|
typedef TYPENAME InputIterator::value_type OutputType;
|
|
|
|
while (first != last) {
|
|
switch ((*first).second) {
|
|
case TD_identity:
|
|
(*result) = OutputType((*first).first, TD_identity);
|
|
++result;
|
|
break;
|
|
|
|
case TD_on:
|
|
(*result) = OutputType((*first).first, TD_off);
|
|
++result;
|
|
break;
|
|
|
|
case TD_off:
|
|
(*result) = OutputType((*first).first, TD_on);
|
|
++result;
|
|
break;
|
|
}
|
|
++first;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_equiv
|
|
// Description: Accepts a pair of DirectionMaps, and returns
|
|
// true if they are equivalent, false otherwise. Two
|
|
// DirectionMaps are defined to be equivalent if
|
|
// all nonidentity members present in one set are
|
|
// present and equivalent in the other set,
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2>
|
|
bool
|
|
dmap_equiv(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1).first < (*first2).first) {
|
|
if ((*first1).second != TD_identity) {
|
|
return false;
|
|
}
|
|
++first1;
|
|
} else if ((*first2).first < (*first1).first) {
|
|
if ((*first2).second != TD_identity) {
|
|
return false;
|
|
}
|
|
++first2;
|
|
} else {
|
|
TransitionDirection dir1 = (*first1).second;
|
|
TransitionDirection dir2 = (*first2).second;
|
|
|
|
if (dir1 != dir2) {
|
|
return false;
|
|
}
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
while (first1 != last1) {
|
|
if ((*first1).second != TD_identity) {
|
|
return false;
|
|
}
|
|
++first1;
|
|
}
|
|
|
|
while (first2 != last2) {
|
|
if ((*first2).second != TD_identity) {
|
|
return false;
|
|
}
|
|
++first2;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_compare
|
|
// Description: Accepts a pair of DirectionMaps, and returns
|
|
// < 0 if the first one sorts before the second one, > 0
|
|
// if the first one sorts after, 0 if they are
|
|
// equivalent.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2>
|
|
int
|
|
dmap_compare(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1).first < (*first2).first) {
|
|
if ((*first1).second != TD_identity) {
|
|
// list1 has the first value that does not appear in list2.
|
|
return 1;
|
|
}
|
|
++first1;
|
|
} else if ((*first2).first < (*first1).first) {
|
|
if ((*first2).second != TD_identity) {
|
|
// list2 has the first value that does not appear in list1.
|
|
return -1;
|
|
}
|
|
++first2;
|
|
} else {
|
|
TransitionDirection dir1 = (*first1).second;
|
|
TransitionDirection dir2 = (*first2).second;
|
|
|
|
if (dir1 != dir2) {
|
|
if (dir1 == TD_identity) {
|
|
// list1 has the first value that does not appear in list2.
|
|
return 1;
|
|
} else if (dir2 == TD_identity) {
|
|
// list2 has the first value that does not appear in list1.
|
|
return -1;
|
|
}
|
|
|
|
// This value appears in both lists, but it is TD_normal in
|
|
// one and TD_inverse in the other.
|
|
return (dir1 < dir2) ? -1 : 1;
|
|
}
|
|
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
while (first1 != last1) {
|
|
if ((*first1).second != TD_identity) {
|
|
// list1 is longer.
|
|
return -1;
|
|
}
|
|
++first1;
|
|
}
|
|
|
|
while (first2 != last2) {
|
|
if ((*first2).second != TD_identity) {
|
|
// list2 is longer.
|
|
return 1;
|
|
}
|
|
++first2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: dmap_is_identity
|
|
// Description: Accepts a DirectionMap, and returns true if all
|
|
// elements in the map correspond to the identity
|
|
// transition, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator>
|
|
bool
|
|
dmap_is_identity(InputIterator first, InputIterator last) {
|
|
while (first != last) {
|
|
if ((*first).second != TD_identity) {
|
|
return false;
|
|
}
|
|
++first;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: bmap_equiv
|
|
// Description: Accepts a pair of BoolMaps, and returns true if they
|
|
// are equivalent, false otherwise. Two BoolMaps are
|
|
// defined to be equivalent if all 'on' members present
|
|
// in one set are present and equivalent in the other
|
|
// set,
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2>
|
|
bool
|
|
bmap_equiv(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1) < (*first2)) {
|
|
return false;
|
|
} else if ((*first2) < (*first1)) {
|
|
return false;
|
|
} else {
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
if (first1 != last1 || first2 != last2) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: bmap_compare
|
|
// Description: Accepts a pair of BoolMaps, and returns < 0 if the
|
|
// first one sorts first, > 0 if the second one sorts
|
|
// first, 0 if they are equivalent.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2>
|
|
int
|
|
bmap_compare(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1) < (*first2)) {
|
|
return -1;
|
|
} else if ((*first2) < (*first1)) {
|
|
return 1;
|
|
} else {
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
if (first1 != last1) {
|
|
// list 1 is longer.
|
|
return -1;
|
|
}
|
|
if (first2 != last2) {
|
|
// list 2 is longer.
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: bmap_apply
|
|
// Description: Accepts a BoolMap and a DirectionMap, and builds a
|
|
// new list (another BoolMap) which represents the
|
|
// memberwise application of the two input maps.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class InputIterator1, class InputIterator2, class OutputIterator>
|
|
OutputIterator
|
|
bmap_apply(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2,
|
|
bool complete_transition, TransitionDirection want_dirs,
|
|
OutputIterator result) {
|
|
while (first1 != last1 && first2 != last2) {
|
|
if ((*first1) < (*first2).first) {
|
|
// Here's an attribute property that wasn't mentioned by the
|
|
// transition. It stays, unless the transition is "complete".
|
|
if (!complete_transition) {
|
|
*result = *first1;
|
|
++result;
|
|
}
|
|
++first1;
|
|
|
|
} else if ((*first2).first < (*first1)) {
|
|
// The transition mentions this property that wasn't previously
|
|
// in the attribute. It becomes a member of the attribute only
|
|
// if the transition explicitly turned it on.
|
|
|
|
if ((*first2).second == want_dirs) {
|
|
*result = (*first2).first;
|
|
++result;
|
|
break;
|
|
}
|
|
|
|
++first2;
|
|
|
|
} else { // ((*first2).first == (*first1))
|
|
|
|
// The transition mentions this property that was already in the
|
|
// attribute. Does the transition replace, preserve, or delete
|
|
// the attribute?
|
|
|
|
if ((*first2).second == TD_identity) {
|
|
// Preserve.
|
|
*result = *first1;
|
|
++result;
|
|
|
|
} else if ((*first2).second == want_dirs) {
|
|
// Replace.
|
|
*result = (*first2).first;
|
|
++result;
|
|
|
|
} else {
|
|
// Omit.
|
|
}
|
|
|
|
++first1;
|
|
++first2;
|
|
}
|
|
}
|
|
|
|
while (first1 != last1) {
|
|
// Here's an attribute property that wasn't mentioned by the
|
|
// transition. It stays, unless the transition is "complete".
|
|
if (!complete_transition) {
|
|
*result = *first1;
|
|
++result;
|
|
}
|
|
++first1;
|
|
}
|
|
|
|
while (first2 != last2) {
|
|
// The transition mentions this property that wasn't previously
|
|
// in the attribute. It becomes a member of the attribute only
|
|
// if the transition explicitly turned it on.
|
|
|
|
if ((*first2).second == want_dirs) {
|
|
*result = (*first2).first;
|
|
++result;
|
|
break;
|
|
}
|
|
|
|
++first2;
|
|
}
|
|
return result;
|
|
}
|