File indexing completed on 2025-07-01 08:15:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
0016
0017 #include <algorithm>
0018 #include <cstddef>
0019 #include <cstring>
0020 #include <string>
0021 #include <tuple>
0022 #include <type_traits>
0023
0024 #include <boost/throw_exception.hpp>
0025
0026 #include <boost/geometry/core/assert.hpp>
0027 #include <boost/geometry/core/coordinate_dimension.hpp>
0028 #include <boost/geometry/core/exception.hpp>
0029 #include <boost/geometry/core/static_assert.hpp>
0030 #include <boost/geometry/util/constexpr.hpp>
0031 #include <boost/geometry/util/sequence.hpp>
0032
0033 namespace boost { namespace geometry {
0034
0035 #ifndef DOXYGEN_NO_DETAIL
0036 namespace detail { namespace relate {
0037
0038 enum field { interior = 0, boundary = 1, exterior = 2 };
0039
0040
0041
0042
0043
0044
0045
0046
0047 template <typename MatrixOrMask, field F1, field F2>
0048 using fields_in_bounds = util::bool_constant
0049 <
0050 (F1 < MatrixOrMask::static_height && F2 < MatrixOrMask::static_width)
0051 >;
0052
0053
0054
0055
0056
0057 template <std::size_t Height, std::size_t Width = Height>
0058 class matrix
0059 {
0060 public:
0061 typedef char value_type;
0062 typedef std::size_t size_type;
0063 typedef const char * const_iterator;
0064 typedef const_iterator iterator;
0065
0066 static const std::size_t static_width = Width;
0067 static const std::size_t static_height = Height;
0068 static const std::size_t static_size = Width * Height;
0069
0070 inline matrix()
0071 {
0072 std::fill_n(m_array, static_size, 'F');
0073 }
0074
0075 template
0076 <
0077 field F1, field F2,
0078 std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
0079 >
0080 inline char get() const
0081 {
0082 static const std::size_t index = F1 * Width + F2;
0083 BOOST_STATIC_ASSERT(index < static_size);
0084 return m_array[index];
0085 }
0086
0087 template
0088 <
0089 field F1, field F2, char V,
0090 std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
0091 >
0092 inline void set()
0093 {
0094 static const std::size_t index = F1 * Width + F2;
0095 BOOST_STATIC_ASSERT(index < static_size);
0096 m_array[index] = V;
0097 }
0098
0099 inline char operator[](std::size_t index) const
0100 {
0101 BOOST_GEOMETRY_ASSERT(index < static_size);
0102 return m_array[index];
0103 }
0104
0105 inline const_iterator begin() const
0106 {
0107 return m_array;
0108 }
0109
0110 inline const_iterator end() const
0111 {
0112 return m_array + static_size;
0113 }
0114
0115 inline static std::size_t size()
0116 {
0117 return static_size;
0118 }
0119
0120 inline const char * data() const
0121 {
0122 return m_array;
0123 }
0124
0125 inline std::string str() const
0126 {
0127 return std::string(m_array, static_size);
0128 }
0129
0130 private:
0131 char m_array[static_size];
0132 };
0133
0134
0135
0136 template <typename Matrix>
0137 class matrix_handler
0138 {
0139 public:
0140 typedef Matrix result_type;
0141
0142 static const bool interrupt = false;
0143
0144 matrix_handler()
0145 {}
0146
0147 result_type const& result() const
0148 {
0149 return m_matrix;
0150 }
0151
0152 result_type const& matrix() const
0153 {
0154 return m_matrix;
0155 }
0156
0157 result_type & matrix()
0158 {
0159 return m_matrix;
0160 }
0161
0162 template <field F1, field F2, char D>
0163 inline bool may_update() const
0164 {
0165 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
0166 char const c = m_matrix.template get<F1, F2>();
0167 return D > c || c > '9';
0168 }
0169
0170 template <field F1, field F2, char V>
0171 inline void update()
0172 {
0173 BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
0174 char const c = m_matrix.template get<F1, F2>();
0175
0176 if (V > c || c > '9')
0177 {
0178 m_matrix.template set<F1, F2, V>();
0179 }
0180 }
0181
0182 template <field F1, field F2, char V>
0183 inline void set()
0184 {
0185 BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
0186 m_matrix.template set<F1, F2, V>();
0187 }
0188
0189 template <field F1, field F2>
0190 inline char get() const
0191 {
0192 return m_matrix.template get<F1, F2>();
0193 }
0194
0195 private:
0196 Matrix m_matrix;
0197 };
0198
0199
0200
0201
0202
0203 template <std::size_t Height, std::size_t Width = Height>
0204 class mask
0205 {
0206 public:
0207 static const std::size_t static_width = Width;
0208 static const std::size_t static_height = Height;
0209 static const std::size_t static_size = Width * Height;
0210
0211 inline mask(const char * s)
0212 {
0213 char * it = m_array;
0214 char * const last = m_array + static_size;
0215 for ( ; it != last && *s != '\0' ; ++it, ++s )
0216 {
0217 char c = *s;
0218 check_char(c);
0219 *it = c;
0220 }
0221 if ( it != last )
0222 {
0223 std::fill(it, last, '*');
0224 }
0225 }
0226
0227 inline mask(const char * s, std::size_t count)
0228 {
0229 if ( count > static_size )
0230 {
0231 count = static_size;
0232 }
0233 if ( count > 0 )
0234 {
0235 std::for_each(s, s + count, check_char);
0236 std::copy_n(s, count, m_array);
0237 }
0238 if ( count < static_size )
0239 {
0240 std::fill_n(m_array + count, static_size - count, '*');
0241 }
0242 }
0243
0244 template
0245 <
0246 field F1, field F2,
0247 std::enable_if_t<fields_in_bounds<mask, F1, F2>::value, int> = 0
0248 >
0249 inline char get() const
0250 {
0251 static const std::size_t index = F1 * Width + F2;
0252 BOOST_STATIC_ASSERT(index < static_size);
0253 return m_array[index];
0254 }
0255
0256 private:
0257 static inline void check_char(char c)
0258 {
0259 bool const is_valid = c == '*' || c == 'T' || c == 'F'
0260 || ( c >= '0' && c <= '9' );
0261 if ( !is_valid )
0262 {
0263 BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
0264 }
0265 }
0266
0267 char m_array[static_size];
0268 };
0269
0270
0271
0272 template <typename Mask, bool InterruptEnabled>
0273 struct interrupt_dispatch
0274 {
0275 template <field F1, field F2, char V>
0276 static inline bool apply(Mask const&)
0277 {
0278 return false;
0279 }
0280 };
0281
0282 template <typename Mask>
0283 struct interrupt_dispatch<Mask, true>
0284 {
0285 template <field F1, field F2, char V>
0286 static inline bool apply(Mask const& mask)
0287 {
0288 char m = mask.template get<F1, F2>();
0289 return check_element<V>(m);
0290 }
0291
0292 template <char V>
0293 static inline bool check_element(char m)
0294 {
0295 if BOOST_GEOMETRY_CONSTEXPR (V >= '0' && V <= '9')
0296 {
0297 return m == 'F' || ( m < V && m >= '0' && m <= '9' );
0298 }
0299 else if BOOST_GEOMETRY_CONSTEXPR (V == 'T')
0300 {
0301 return m == 'F';
0302 }
0303 else
0304 {
0305 return false;
0306 }
0307 }
0308 };
0309
0310 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
0311 struct interrupt_dispatch_tuple
0312 {
0313 template <field F1, field F2, char V>
0314 static inline bool apply(Masks const& masks)
0315 {
0316 typedef typename std::tuple_element<I, Masks>::type mask_type;
0317 mask_type const& mask = std::get<I>(masks);
0318 return interrupt_dispatch<mask_type, true>::template apply<F1, F2, V>(mask)
0319 && interrupt_dispatch_tuple<Masks, I+1>::template apply<F1, F2, V>(masks);
0320 }
0321 };
0322
0323 template <typename Masks, int N>
0324 struct interrupt_dispatch_tuple<Masks, N, N>
0325 {
0326 template <field F1, field F2, char V>
0327 static inline bool apply(Masks const& )
0328 {
0329 return true;
0330 }
0331 };
0332
0333 template <typename ...Masks>
0334 struct interrupt_dispatch<std::tuple<Masks...>, true>
0335 {
0336 typedef std::tuple<Masks...> mask_type;
0337
0338 template <field F1, field F2, char V>
0339 static inline bool apply(mask_type const& mask)
0340 {
0341 return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
0342 }
0343 };
0344
0345 template <field F1, field F2, char V, bool InterruptEnabled, typename Mask>
0346 inline bool interrupt(Mask const& mask)
0347 {
0348 return interrupt_dispatch<Mask, InterruptEnabled>
0349 ::template apply<F1, F2, V>(mask);
0350 }
0351
0352
0353
0354 template <typename Mask>
0355 struct may_update_dispatch
0356 {
0357 template <field F1, field F2, char D, typename Matrix>
0358 static inline bool apply(Mask const& mask, Matrix const& matrix)
0359 {
0360 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
0361
0362 char const m = mask.template get<F1, F2>();
0363
0364 if ( m == 'F' )
0365 {
0366 return true;
0367 }
0368 else if ( m == 'T' )
0369 {
0370 char const c = matrix.template get<F1, F2>();
0371 return c == 'F';
0372 }
0373 else if ( m >= '0' && m <= '9' )
0374 {
0375 char const c = matrix.template get<F1, F2>();
0376 return D > c || c > '9';
0377 }
0378
0379 return false;
0380 }
0381 };
0382
0383 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
0384 struct may_update_dispatch_tuple
0385 {
0386 template <field F1, field F2, char D, typename Matrix>
0387 static inline bool apply(Masks const& masks, Matrix const& matrix)
0388 {
0389 typedef typename std::tuple_element<I, Masks>::type mask_type;
0390 mask_type const& mask = std::get<I>(masks);
0391 return may_update_dispatch<mask_type>::template apply<F1, F2, D>(mask, matrix)
0392 || may_update_dispatch_tuple<Masks, I+1>::template apply<F1, F2, D>(masks, matrix);
0393 }
0394 };
0395
0396 template <typename Masks, int N>
0397 struct may_update_dispatch_tuple<Masks, N, N>
0398 {
0399 template <field F1, field F2, char D, typename Matrix>
0400 static inline bool apply(Masks const& , Matrix const& )
0401 {
0402 return false;
0403 }
0404 };
0405
0406 template <typename ...Masks>
0407 struct may_update_dispatch<std::tuple<Masks...>>
0408 {
0409 typedef std::tuple<Masks...> mask_type;
0410
0411 template <field F1, field F2, char D, typename Matrix>
0412 static inline bool apply(mask_type const& mask, Matrix const& matrix)
0413 {
0414 return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
0415 }
0416 };
0417
0418 template <field F1, field F2, char D, typename Mask, typename Matrix>
0419 inline bool may_update(Mask const& mask, Matrix const& matrix)
0420 {
0421 return may_update_dispatch<Mask>
0422 ::template apply<F1, F2, D>(mask, matrix);
0423 }
0424
0425
0426
0427 template <typename Mask>
0428 struct check_dispatch
0429 {
0430 template <typename Matrix>
0431 static inline bool apply(Mask const& mask, Matrix const& matrix)
0432 {
0433 return per_one<interior, interior>(mask, matrix)
0434 && per_one<interior, boundary>(mask, matrix)
0435 && per_one<interior, exterior>(mask, matrix)
0436 && per_one<boundary, interior>(mask, matrix)
0437 && per_one<boundary, boundary>(mask, matrix)
0438 && per_one<boundary, exterior>(mask, matrix)
0439 && per_one<exterior, interior>(mask, matrix)
0440 && per_one<exterior, boundary>(mask, matrix)
0441 && per_one<exterior, exterior>(mask, matrix);
0442 }
0443
0444 template <field F1, field F2, typename Matrix>
0445 static inline bool per_one(Mask const& mask, Matrix const& matrix)
0446 {
0447 const char mask_el = mask.template get<F1, F2>();
0448 const char el = matrix.template get<F1, F2>();
0449
0450 if ( mask_el == 'F' )
0451 {
0452 return el == 'F';
0453 }
0454 else if ( mask_el == 'T' )
0455 {
0456 return el == 'T' || ( el >= '0' && el <= '9' );
0457 }
0458 else if ( mask_el >= '0' && mask_el <= '9' )
0459 {
0460 return el == mask_el;
0461 }
0462
0463 return true;
0464 }
0465 };
0466
0467 template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
0468 struct check_dispatch_tuple
0469 {
0470 template <typename Matrix>
0471 static inline bool apply(Masks const& masks, Matrix const& matrix)
0472 {
0473 typedef typename std::tuple_element<I, Masks>::type mask_type;
0474 mask_type const& mask = std::get<I>(masks);
0475 return check_dispatch<mask_type>::apply(mask, matrix)
0476 || check_dispatch_tuple<Masks, I+1>::apply(masks, matrix);
0477 }
0478 };
0479
0480 template <typename Masks, int N>
0481 struct check_dispatch_tuple<Masks, N, N>
0482 {
0483 template <typename Matrix>
0484 static inline bool apply(Masks const&, Matrix const&)
0485 {
0486 return false;
0487 }
0488 };
0489
0490 template <typename ...Masks>
0491 struct check_dispatch<std::tuple<Masks...>>
0492 {
0493 typedef std::tuple<Masks...> mask_type;
0494
0495 template <typename Matrix>
0496 static inline bool apply(mask_type const& mask, Matrix const& matrix)
0497 {
0498 return check_dispatch_tuple<mask_type>::apply(mask, matrix);
0499 }
0500 };
0501
0502 template <typename Mask, typename Matrix>
0503 inline bool check_matrix(Mask const& mask, Matrix const& matrix)
0504 {
0505 return check_dispatch<Mask>::apply(mask, matrix);
0506 }
0507
0508
0509
0510 template <typename MatrixOrMask>
0511 struct matrix_width
0512 {
0513 static const std::size_t value = MatrixOrMask::static_width;
0514 };
0515
0516 template <typename Tuple,
0517 int I = 0,
0518 int N = std::tuple_size<Tuple>::value>
0519 struct matrix_width_tuple
0520 {
0521 static const std::size_t
0522 current = matrix_width<typename std::tuple_element<I, Tuple>::type>::value;
0523 static const std::size_t
0524 next = matrix_width_tuple<Tuple, I+1>::value;
0525
0526 static const std::size_t
0527 value = current > next ? current : next;
0528 };
0529
0530 template <typename Tuple, int N>
0531 struct matrix_width_tuple<Tuple, N, N>
0532 {
0533 static const std::size_t value = 0;
0534 };
0535
0536 template <typename ...Masks>
0537 struct matrix_width<std::tuple<Masks...>>
0538 {
0539 static const std::size_t
0540 value = matrix_width_tuple<std::tuple<Masks...>>::value;
0541 };
0542
0543
0544
0545 template <typename Mask, bool Interrupt>
0546 class mask_handler
0547 : private matrix_handler
0548 <
0549 relate::matrix<matrix_width<Mask>::value>
0550 >
0551 {
0552 typedef matrix_handler
0553 <
0554 relate::matrix<matrix_width<Mask>::value>
0555 > base_t;
0556
0557 public:
0558 typedef bool result_type;
0559
0560 bool interrupt;
0561
0562 inline explicit mask_handler(Mask const& m)
0563 : interrupt(false)
0564 , m_mask(m)
0565 {}
0566
0567 result_type result() const
0568 {
0569 return !interrupt
0570 && check_matrix(m_mask, base_t::matrix());
0571 }
0572
0573 template <field F1, field F2, char D>
0574 inline bool may_update() const
0575 {
0576 return detail::relate::may_update<F1, F2, D>(m_mask, base_t::matrix());
0577 }
0578
0579 template <field F1, field F2, char V>
0580 inline void update()
0581 {
0582 if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
0583 {
0584 interrupt = true;
0585 }
0586 else
0587 {
0588 base_t::template update<F1, F2, V>();
0589 }
0590 }
0591
0592 template <field F1, field F2, char V>
0593 inline void set()
0594 {
0595 if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
0596 {
0597 interrupt = true;
0598 }
0599 else
0600 {
0601 base_t::template set<F1, F2, V>();
0602 }
0603 }
0604
0605 template <field F1, field F2>
0606 inline char get() const
0607 {
0608 return base_t::template get<F1, F2>();
0609 }
0610
0611 private:
0612 Mask const& m_mask;
0613 };
0614
0615
0616
0617 struct false_mask {};
0618
0619
0620
0621
0622 template <typename Seq>
0623 struct static_check_characters {};
0624
0625 template <char C, char ...Cs>
0626 struct static_check_characters<std::integer_sequence<char, C, Cs...>>
0627 : static_check_characters<std::integer_sequence<char, Cs...>>
0628 {
0629 typedef std::integer_sequence<char, C, Cs...> type;
0630 static const bool is_valid = (C >= '0' && C <= '9')
0631 || C == 'T' || C == 'F' || C == '*';
0632 BOOST_GEOMETRY_STATIC_ASSERT((is_valid),
0633 "Invalid static mask character",
0634 type);
0635 };
0636
0637 template <char ...Cs>
0638 struct static_check_characters<std::integral_constant<char, Cs...>>
0639 {};
0640
0641
0642
0643 template <typename Seq, std::size_t Height, std::size_t Width = Height>
0644 struct static_mask
0645 {
0646 static const std::size_t static_width = Width;
0647 static const std::size_t static_height = Height;
0648 static const std::size_t static_size = Width * Height;
0649
0650 BOOST_STATIC_ASSERT(
0651 std::size_t(util::sequence_size<Seq>::value) == static_size);
0652
0653 template <detail::relate::field F1, detail::relate::field F2>
0654 struct static_get
0655 {
0656 BOOST_STATIC_ASSERT(std::size_t(F1) < static_height);
0657 BOOST_STATIC_ASSERT(std::size_t(F2) < static_width);
0658
0659 static const char value
0660 = util::sequence_element<F1 * static_width + F2, Seq>::value;
0661 };
0662
0663 private:
0664
0665 enum { mask_check = sizeof(static_check_characters<Seq>) };
0666 };
0667
0668
0669
0670 template
0671 <
0672 typename StaticMask, field F1, field F2,
0673 bool IsSequence = util::is_sequence<StaticMask>::value
0674 >
0675 struct static_should_handle_element_dispatch
0676 {
0677 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
0678 static const bool value = mask_el == 'F'
0679 || mask_el == 'T'
0680 || ( mask_el >= '0' && mask_el <= '9' );
0681 };
0682
0683 template
0684 <
0685 typename Seq, field F1, field F2,
0686 std::size_t I = 0,
0687 std::size_t N = util::sequence_size<Seq>::value
0688 >
0689 struct static_should_handle_element_sequence
0690 {
0691 typedef typename util::sequence_element<I, Seq>::type StaticMask;
0692
0693 static const bool value
0694 = static_should_handle_element_dispatch
0695 <
0696 StaticMask, F1, F2
0697 >::value
0698 || static_should_handle_element_sequence
0699 <
0700 Seq, F1, F2, I + 1
0701 >::value;
0702 };
0703
0704 template <typename Seq, field F1, field F2, std::size_t N>
0705 struct static_should_handle_element_sequence<Seq, F1, F2, N, N>
0706 {
0707 static const bool value = false;
0708 };
0709
0710 template <typename StaticMask, field F1, field F2>
0711 struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>
0712 {
0713 static const bool value
0714 = static_should_handle_element_sequence
0715 <
0716 StaticMask, F1, F2
0717 >::value;
0718 };
0719
0720 template <typename StaticMask, field F1, field F2>
0721 struct static_should_handle_element
0722 {
0723 static const bool value
0724 = static_should_handle_element_dispatch
0725 <
0726 StaticMask, F1, F2
0727 >::value;
0728 };
0729
0730
0731
0732 template
0733 <
0734 typename StaticMask, char V, field F1, field F2,
0735 bool InterruptEnabled,
0736 bool IsSequence = util::is_sequence<StaticMask>::value
0737 >
0738 struct static_interrupt_dispatch
0739 {
0740 static const bool value = false;
0741 };
0742
0743 template <typename StaticMask, char V, field F1, field F2, bool IsSequence>
0744 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
0745 {
0746 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
0747
0748 static const bool value
0749 = ( V >= '0' && V <= '9' ) ?
0750 ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
0751 ( ( V == 'T' ) ? mask_el == 'F' : false );
0752 };
0753
0754 template
0755 <
0756 typename Seq, char V, field F1, field F2,
0757 std::size_t I = 0,
0758 std::size_t N = util::sequence_size<Seq>::value
0759 >
0760 struct static_interrupt_sequence
0761 {
0762 typedef typename util::sequence_element<I, Seq>::type StaticMask;
0763
0764 static const bool value
0765 = static_interrupt_dispatch
0766 <
0767 StaticMask, V, F1, F2, true
0768 >::value
0769 && static_interrupt_sequence
0770 <
0771 Seq, V, F1, F2, I + 1
0772 >::value;
0773 };
0774
0775 template <typename Seq, char V, field F1, field F2, std::size_t N>
0776 struct static_interrupt_sequence<Seq, V, F1, F2, N, N>
0777 {
0778 static const bool value = true;
0779 };
0780
0781 template <typename StaticMask, char V, field F1, field F2>
0782 struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, true>
0783 {
0784 static const bool value
0785 = static_interrupt_sequence
0786 <
0787 StaticMask, V, F1, F2
0788 >::value;
0789 };
0790
0791 template <typename StaticMask, char V, field F1, field F2, bool EnableInterrupt>
0792 struct static_interrupt
0793 {
0794 static const bool value
0795 = static_interrupt_dispatch
0796 <
0797 StaticMask, V, F1, F2, EnableInterrupt
0798 >::value;
0799 };
0800
0801
0802
0803 template
0804 <
0805 typename StaticMask, char D, field F1, field F2,
0806 bool IsSequence = util::is_sequence<StaticMask>::value
0807 >
0808 struct static_may_update_dispatch
0809 {
0810 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
0811 static const int version
0812 = mask_el == 'F' ? 0
0813 : mask_el == 'T' ? 1
0814 : mask_el >= '0' && mask_el <= '9' ? 2
0815 : 3;
0816
0817
0818
0819 template <typename Matrix>
0820 static inline bool apply(Matrix const& matrix)
0821 {
0822 return apply_dispatch(matrix, std::integral_constant<int, version>());
0823 }
0824
0825
0826 template <typename Matrix>
0827 static inline bool apply_dispatch(Matrix const& , std::integral_constant<int, 0>)
0828 {
0829 return true;
0830 }
0831
0832 template <typename Matrix>
0833 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 1>)
0834 {
0835 char const c = matrix.template get<F1, F2>();
0836 return c == 'F';
0837 }
0838
0839 template <typename Matrix>
0840 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 2>)
0841 {
0842 char const c = matrix.template get<F1, F2>();
0843 return D > c || c > '9';
0844 }
0845
0846 template <typename Matrix>
0847 static inline bool apply_dispatch(Matrix const&, std::integral_constant<int, 3>)
0848 {
0849 return false;
0850 }
0851 };
0852
0853 template
0854 <
0855 typename Seq, char D, field F1, field F2,
0856 std::size_t I = 0,
0857 std::size_t N = util::sequence_size<Seq>::value
0858 >
0859 struct static_may_update_sequence
0860 {
0861 typedef typename util::sequence_element<I, Seq>::type StaticMask;
0862
0863 template <typename Matrix>
0864 static inline bool apply(Matrix const& matrix)
0865 {
0866 return static_may_update_dispatch
0867 <
0868 StaticMask, D, F1, F2
0869 >::apply(matrix)
0870 || static_may_update_sequence
0871 <
0872 Seq, D, F1, F2, I + 1
0873 >::apply(matrix);
0874 }
0875 };
0876
0877 template <typename Seq, char D, field F1, field F2, std::size_t N>
0878 struct static_may_update_sequence<Seq, D, F1, F2, N, N>
0879 {
0880 template <typename Matrix>
0881 static inline bool apply(Matrix const& )
0882 {
0883 return false;
0884 }
0885 };
0886
0887 template <typename StaticMask, char D, field F1, field F2>
0888 struct static_may_update_dispatch<StaticMask, D, F1, F2, true>
0889 {
0890 template <typename Matrix>
0891 static inline bool apply(Matrix const& matrix)
0892 {
0893 return static_may_update_sequence
0894 <
0895 StaticMask, D, F1, F2
0896 >::apply(matrix);
0897 }
0898 };
0899
0900 template <typename StaticMask, char D, field F1, field F2>
0901 struct static_may_update
0902 {
0903 template <typename Matrix>
0904 static inline bool apply(Matrix const& matrix)
0905 {
0906 return static_may_update_dispatch
0907 <
0908 StaticMask, D, F1, F2
0909 >::apply(matrix);
0910 }
0911 };
0912
0913
0914
0915 template
0916 <
0917 typename StaticMask,
0918 bool IsSequence = util::is_sequence<StaticMask>::value
0919 >
0920 struct static_check_dispatch
0921 {
0922 template <typename Matrix>
0923 static inline bool apply(Matrix const& matrix)
0924 {
0925 return per_one<interior, interior>::apply(matrix)
0926 && per_one<interior, boundary>::apply(matrix)
0927 && per_one<interior, exterior>::apply(matrix)
0928 && per_one<boundary, interior>::apply(matrix)
0929 && per_one<boundary, boundary>::apply(matrix)
0930 && per_one<boundary, exterior>::apply(matrix)
0931 && per_one<exterior, interior>::apply(matrix)
0932 && per_one<exterior, boundary>::apply(matrix)
0933 && per_one<exterior, exterior>::apply(matrix);
0934 }
0935
0936 template <field F1, field F2>
0937 struct per_one
0938 {
0939 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
0940 static const int version
0941 = mask_el == 'F' ? 0
0942 : mask_el == 'T' ? 1
0943 : mask_el >= '0' && mask_el <= '9' ? 2
0944 : 3;
0945
0946
0947
0948 template <typename Matrix>
0949 static inline bool apply(Matrix const& matrix)
0950 {
0951 const char el = matrix.template get<F1, F2>();
0952 return apply_dispatch(el, std::integral_constant<int, version>());
0953 }
0954
0955
0956 static inline bool apply_dispatch(char el, std::integral_constant<int, 0>)
0957 {
0958 return el == 'F';
0959 }
0960
0961 static inline bool apply_dispatch(char el, std::integral_constant<int, 1>)
0962 {
0963 return el == 'T' || ( el >= '0' && el <= '9' );
0964 }
0965
0966 static inline bool apply_dispatch(char el, std::integral_constant<int, 2>)
0967 {
0968 return el == mask_el;
0969 }
0970
0971 static inline bool apply_dispatch(char , std::integral_constant<int, 3>)
0972 {
0973 return true;
0974 }
0975 };
0976 };
0977
0978 template
0979 <
0980 typename Seq,
0981 std::size_t I = 0,
0982 std::size_t N = util::sequence_size<Seq>::value
0983 >
0984 struct static_check_sequence
0985 {
0986 typedef typename util::sequence_element<I, Seq>::type StaticMask;
0987
0988 template <typename Matrix>
0989 static inline bool apply(Matrix const& matrix)
0990 {
0991 return static_check_dispatch
0992 <
0993 StaticMask
0994 >::apply(matrix)
0995 || static_check_sequence
0996 <
0997 Seq, I + 1
0998 >::apply(matrix);
0999 }
1000 };
1001
1002 template <typename Seq, std::size_t N>
1003 struct static_check_sequence<Seq, N, N>
1004 {
1005 template <typename Matrix>
1006 static inline bool apply(Matrix const& )
1007 {
1008 return false;
1009 }
1010 };
1011
1012 template <typename StaticMask>
1013 struct static_check_dispatch<StaticMask, true>
1014 {
1015 template <typename Matrix>
1016 static inline bool apply(Matrix const& matrix)
1017 {
1018 return static_check_sequence
1019 <
1020 StaticMask
1021 >::apply(matrix);
1022 }
1023 };
1024
1025 template <typename StaticMask>
1026 struct static_check_matrix
1027 {
1028 template <typename Matrix>
1029 static inline bool apply(Matrix const& matrix)
1030 {
1031 return static_check_dispatch
1032 <
1033 StaticMask
1034 >::apply(matrix);
1035 }
1036 };
1037
1038
1039
1040 template <typename StaticMask, bool Interrupt>
1041 class static_mask_handler
1042 : private matrix_handler< matrix<3> >
1043 {
1044 typedef matrix_handler< relate::matrix<3> > base_type;
1045
1046 public:
1047 typedef bool result_type;
1048
1049 bool interrupt;
1050
1051 inline static_mask_handler()
1052 : interrupt(false)
1053 {}
1054
1055 inline explicit static_mask_handler(StaticMask const& )
1056 : interrupt(false)
1057 {}
1058
1059 result_type result() const
1060 {
1061 return (!Interrupt || !interrupt)
1062 && static_check_matrix<StaticMask>::apply(base_type::matrix());
1063 }
1064
1065 template <field F1, field F2, char D>
1066 inline bool may_update() const
1067 {
1068 return static_may_update<StaticMask, D, F1, F2>::
1069 apply(base_type::matrix());
1070 }
1071
1072 template <field F1, field F2, char V>
1073 inline void update()
1074 {
1075 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1076 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1077 static const int version = interrupt_c ? 0
1078 : should_handle ? 1
1079 : 2;
1080
1081 update_dispatch<F1, F2, V>(integral_constant<int, version>());
1082 }
1083
1084 template
1085 <
1086 field F1, field F2, char V,
1087 std::enable_if_t<static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
1088 >
1089 inline void set()
1090 {
1091 interrupt = true;
1092 }
1093
1094 template
1095 <
1096 field F1, field F2, char V,
1097 std::enable_if_t<! static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
1098 >
1099 inline void set()
1100 {
1101 base_type::template set<F1, F2, V>();
1102 }
1103
1104 template <field F1, field F2>
1105 inline char get() const
1106 {
1107 return base_type::template get<F1, F2>();
1108 }
1109
1110 private:
1111
1112 template <field F1, field F2, char V>
1113 inline void update_dispatch(integral_constant<int, 0>)
1114 {
1115 interrupt = true;
1116 }
1117
1118 template <field F1, field F2, char V>
1119 inline void update_dispatch(integral_constant<int, 1>)
1120 {
1121 base_type::template update<F1, F2, V>();
1122 }
1123
1124 template <field F1, field F2, char V>
1125 inline void update_dispatch(integral_constant<int, 2>)
1126 {}
1127 };
1128
1129
1130
1131
1132
1133 template <field F1, field F2, char D, typename Result>
1134 inline void update(Result & res)
1135 {
1136 res.template update<F1, F2, D>();
1137 }
1138
1139 template
1140 <
1141 field F1, field F2, char D, bool Transpose, typename Result,
1142 std::enable_if_t<! Transpose, int> = 0
1143 >
1144 inline void update(Result & res)
1145 {
1146 res.template update<F1, F2, D>();
1147 }
1148
1149 template
1150 <
1151 field F1, field F2, char D, bool Transpose, typename Result,
1152 std::enable_if_t<Transpose, int> = 0
1153 >
1154 inline void update(Result & res)
1155 {
1156 res.template update<F2, F1, D>();
1157 }
1158
1159
1160
1161 template <field F1, field F2, char D, typename Result>
1162 inline bool may_update(Result const& res)
1163 {
1164 return res.template may_update<F1, F2, D>();
1165 }
1166
1167 template
1168 <
1169 field F1, field F2, char D, bool Transpose, typename Result,
1170 std::enable_if_t<! Transpose, int> = 0
1171 >
1172 inline bool may_update(Result const& res)
1173 {
1174 return res.template may_update<F1, F2, D>();
1175 }
1176
1177 template
1178 <
1179 field F1, field F2, char D, bool Transpose, typename Result,
1180 std::enable_if_t<Transpose, int> = 0
1181 >
1182 inline bool may_update(Result const& res)
1183 {
1184 return res.template may_update<F2, F1, D>();
1185 }
1186
1187
1188
1189 template <typename Geometry>
1190 struct result_dimension
1191 {
1192 static const std::size_t dim = geometry::dimension<Geometry>::value;
1193 BOOST_STATIC_ASSERT(dim >= 0);
1194 static const char value = (dim <= 9) ? ('0' + dim) : 'T';
1195 };
1196
1197 }}
1198 #endif
1199
1200 }}
1201
1202 #endif