]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/algorithms/detail/relate/result.hpp
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / relate / result.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
b32b8144 4// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
7c673cae 5
20effc67
TL
6// This file was modified by Oracle on 2013-2020.
7// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
7c673cae
FG
8
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11// Use, modification and distribution is subject to the Boost Software License,
12// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
16#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
17
20effc67 18#include <algorithm>
7c673cae 19#include <cstddef>
92f5a8d4 20#include <cstring>
1e59de90 21#include <string>
20effc67 22#include <type_traits>
7c673cae 23
b32b8144 24#include <boost/throw_exception.hpp>
7c673cae 25#include <boost/tuple/tuple.hpp>
7c673cae
FG
26
27#include <boost/geometry/core/assert.hpp>
28#include <boost/geometry/core/coordinate_dimension.hpp>
29#include <boost/geometry/core/exception.hpp>
20effc67 30#include <boost/geometry/core/static_assert.hpp>
7c673cae 31#include <boost/geometry/util/condition.hpp>
20effc67 32#include <boost/geometry/util/sequence.hpp>
7c673cae
FG
33
34namespace boost { namespace geometry {
35
36#ifndef DOXYGEN_NO_DETAIL
37namespace detail { namespace relate {
38
39enum field { interior = 0, boundary = 1, exterior = 2 };
40
41// TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES
42// THE VALUE ALREADY STORED MUSN'T BE CHECKED
43// update() calls chould be replaced with set() in those cases
44// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
45// so some additional function could be added, e.g. set_dim()
46
47// --------------- MATRIX ----------------
48
49// matrix
50
51template <std::size_t Height, std::size_t Width = Height>
52class matrix
53{
54public:
55 typedef char value_type;
56 typedef std::size_t size_type;
57 typedef const char * const_iterator;
58 typedef const_iterator iterator;
59
60 static const std::size_t static_width = Width;
61 static const std::size_t static_height = Height;
62 static const std::size_t static_size = Width * Height;
63
64 inline matrix()
65 {
66 ::memset(m_array, 'F', static_size);
67 }
68
69 template <field F1, field F2>
70 inline char get() const
71 {
72 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
73 static const std::size_t index = F1 * Width + F2;
74 BOOST_STATIC_ASSERT(index < static_size);
75 return m_array[index];
76 }
77
78 template <field F1, field F2, char V>
79 inline void set()
80 {
81 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
82 static const std::size_t index = F1 * Width + F2;
83 BOOST_STATIC_ASSERT(index < static_size);
84 m_array[index] = V;
85 }
86
87 inline char operator[](std::size_t index) const
88 {
89 BOOST_GEOMETRY_ASSERT(index < static_size);
90 return m_array[index];
91 }
92
93 inline const_iterator begin() const
94 {
95 return m_array;
96 }
97
98 inline const_iterator end() const
99 {
100 return m_array + static_size;
101 }
102
103 inline static std::size_t size()
104 {
105 return static_size;
106 }
107
108 inline const char * data() const
109 {
110 return m_array;
111 }
112
113 inline std::string str() const
114 {
115 return std::string(m_array, static_size);
116 }
117
118private:
119 char m_array[static_size];
120};
121
122// matrix_handler
123
124template <typename Matrix>
125class matrix_handler
126{
127public:
128 typedef Matrix result_type;
129
130 static const bool interrupt = false;
131
132 matrix_handler()
133 {}
134
135 result_type const& result() const
136 {
137 return m_matrix;
138 }
139
140 result_type const& matrix() const
141 {
142 return m_matrix;
143 }
144
145 result_type & matrix()
146 {
147 return m_matrix;
148 }
149
150 template <field F1, field F2, char D>
151 inline bool may_update() const
152 {
153 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
154
155 char const c = m_matrix.template get<F1, F2>();
156 return D > c || c > '9';
157 }
158
159 template <field F1, field F2, char V>
160 inline void set()
161 {
162 static const bool in_bounds = F1 < Matrix::static_height
163 && F2 < Matrix::static_width;
20effc67 164 typedef std::integral_constant<bool, in_bounds> in_bounds_t;
7c673cae
FG
165 set_dispatch<F1, F2, V>(in_bounds_t());
166 }
167
168 template <field F1, field F2, char D>
169 inline void update()
170 {
171 static const bool in_bounds = F1 < Matrix::static_height
172 && F2 < Matrix::static_width;
20effc67 173 typedef std::integral_constant<bool, in_bounds> in_bounds_t;
7c673cae
FG
174 update_dispatch<F1, F2, D>(in_bounds_t());
175 }
176
177private:
178 template <field F1, field F2, char V>
20effc67 179 inline void set_dispatch(std::true_type)
7c673cae
FG
180 {
181 static const std::size_t index = F1 * Matrix::static_width + F2;
182 BOOST_STATIC_ASSERT(index < Matrix::static_size);
183 BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
184 m_matrix.template set<F1, F2, V>();
185 }
186 template <field F1, field F2, char V>
20effc67 187 inline void set_dispatch(std::false_type)
7c673cae
FG
188 {}
189
190 template <field F1, field F2, char D>
20effc67 191 inline void update_dispatch(std::true_type)
7c673cae
FG
192 {
193 static const std::size_t index = F1 * Matrix::static_width + F2;
194 BOOST_STATIC_ASSERT(index < Matrix::static_size);
195 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
196 char const c = m_matrix.template get<F1, F2>();
197 if ( D > c || c > '9')
198 m_matrix.template set<F1, F2, D>();
199 }
200 template <field F1, field F2, char D>
20effc67 201 inline void update_dispatch(std::false_type)
7c673cae
FG
202 {}
203
204 Matrix m_matrix;
205};
206
207// --------------- RUN-TIME MASK ----------------
208
209// run-time mask
210
211template <std::size_t Height, std::size_t Width = Height>
212class mask
213{
214public:
215 static const std::size_t static_width = Width;
216 static const std::size_t static_height = Height;
217 static const std::size_t static_size = Width * Height;
218
219 inline mask(const char * s)
220 {
221 char * it = m_array;
222 char * const last = m_array + static_size;
223 for ( ; it != last && *s != '\0' ; ++it, ++s )
224 {
225 char c = *s;
226 check_char(c);
227 *it = c;
228 }
229 if ( it != last )
230 {
231 ::memset(it, '*', last - it);
232 }
233 }
234
235 inline mask(const char * s, std::size_t count)
236 {
237 if ( count > static_size )
238 {
239 count = static_size;
240 }
241 if ( count > 0 )
242 {
243 std::for_each(s, s + count, check_char);
244 ::memcpy(m_array, s, count);
245 }
246 if ( count < static_size )
247 {
248 ::memset(m_array + count, '*', static_size - count);
249 }
250 }
251
252 template <field F1, field F2>
253 inline char get() const
254 {
255 BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
256 static const std::size_t index = F1 * Width + F2;
257 BOOST_STATIC_ASSERT(index < static_size);
258 return m_array[index];
259 }
260
261private:
262 static inline void check_char(char c)
263 {
264 bool const is_valid = c == '*' || c == 'T' || c == 'F'
265 || ( c >= '0' && c <= '9' );
266 if ( !is_valid )
267 {
b32b8144 268 BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
7c673cae
FG
269 }
270 }
271
272 char m_array[static_size];
273};
274
275// interrupt()
276
277template <typename Mask, bool InterruptEnabled>
278struct interrupt_dispatch
279{
280 template <field F1, field F2, char V>
281 static inline bool apply(Mask const&)
282 {
283 return false;
284 }
285};
286
287template <typename Mask>
288struct interrupt_dispatch<Mask, true>
289{
290 template <field F1, field F2, char V>
291 static inline bool apply(Mask const& mask)
292 {
293 char m = mask.template get<F1, F2>();
294 return check_element<V>(m);
295 }
296
297 template <char V>
298 static inline bool check_element(char m)
299 {
300 if ( BOOST_GEOMETRY_CONDITION(V >= '0' && V <= '9') )
301 {
302 return m == 'F' || ( m < V && m >= '0' && m <= '9' );
303 }
304 else if ( BOOST_GEOMETRY_CONDITION(V == 'T') )
305 {
306 return m == 'F';
307 }
308 return false;
309 }
310};
311
20effc67 312template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
7c673cae
FG
313struct interrupt_dispatch_tuple
314{
315 template <field F1, field F2, char V>
316 static inline bool apply(Masks const& masks)
317 {
20effc67
TL
318 typedef typename std::tuple_element<I, Masks>::type mask_type;
319 mask_type const& mask = std::get<I>(masks);
7c673cae
FG
320 return interrupt_dispatch<mask_type, true>::template apply<F1, F2, V>(mask)
321 && interrupt_dispatch_tuple<Masks, I+1>::template apply<F1, F2, V>(masks);
322 }
323};
324
325template <typename Masks, int N>
326struct interrupt_dispatch_tuple<Masks, N, N>
327{
328 template <field F1, field F2, char V>
329 static inline bool apply(Masks const& )
330 {
331 return true;
332 }
333};
334
20effc67
TL
335template <typename ...Masks>
336struct interrupt_dispatch<std::tuple<Masks...>, true>
7c673cae 337{
20effc67 338 typedef std::tuple<Masks...> mask_type;
7c673cae
FG
339
340 template <field F1, field F2, char V>
341 static inline bool apply(mask_type const& mask)
342 {
343 return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
344 }
345};
346
347template <field F1, field F2, char V, bool InterruptEnabled, typename Mask>
348inline bool interrupt(Mask const& mask)
349{
350 return interrupt_dispatch<Mask, InterruptEnabled>
351 ::template apply<F1, F2, V>(mask);
352}
353
354// may_update()
355
356template <typename Mask>
357struct may_update_dispatch
358{
359 template <field F1, field F2, char D, typename Matrix>
360 static inline bool apply(Mask const& mask, Matrix const& matrix)
361 {
362 BOOST_STATIC_ASSERT('0' <= D && D <= '9');
363
364 char const m = mask.template get<F1, F2>();
365
366 if ( m == 'F' )
367 {
368 return true;
369 }
370 else if ( m == 'T' )
371 {
372 char const c = matrix.template get<F1, F2>();
373 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
374 }
375 else if ( m >= '0' && m <= '9' )
376 {
377 char const c = matrix.template get<F1, F2>();
378 return D > c || c > '9';
379 }
380
381 return false;
382 }
383};
384
20effc67 385template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
7c673cae
FG
386struct may_update_dispatch_tuple
387{
388 template <field F1, field F2, char D, typename Matrix>
389 static inline bool apply(Masks const& masks, Matrix const& matrix)
390 {
20effc67
TL
391 typedef typename std::tuple_element<I, Masks>::type mask_type;
392 mask_type const& mask = std::get<I>(masks);
7c673cae
FG
393 return may_update_dispatch<mask_type>::template apply<F1, F2, D>(mask, matrix)
394 || may_update_dispatch_tuple<Masks, I+1>::template apply<F1, F2, D>(masks, matrix);
395 }
396};
397
398template <typename Masks, int N>
399struct may_update_dispatch_tuple<Masks, N, N>
400{
401 template <field F1, field F2, char D, typename Matrix>
402 static inline bool apply(Masks const& , Matrix const& )
403 {
404 return false;
405 }
406};
407
20effc67
TL
408template <typename ...Masks>
409struct may_update_dispatch<std::tuple<Masks...>>
7c673cae 410{
20effc67 411 typedef std::tuple<Masks...> mask_type;
7c673cae
FG
412
413 template <field F1, field F2, char D, typename Matrix>
414 static inline bool apply(mask_type const& mask, Matrix const& matrix)
415 {
416 return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
417 }
418};
419
420template <field F1, field F2, char D, typename Mask, typename Matrix>
421inline bool may_update(Mask const& mask, Matrix const& matrix)
422{
423 return may_update_dispatch<Mask>
424 ::template apply<F1, F2, D>(mask, matrix);
425}
426
427// check_matrix()
428
429template <typename Mask>
430struct check_dispatch
431{
432 template <typename Matrix>
433 static inline bool apply(Mask const& mask, Matrix const& matrix)
434 {
435 return per_one<interior, interior>(mask, matrix)
436 && per_one<interior, boundary>(mask, matrix)
437 && per_one<interior, exterior>(mask, matrix)
438 && per_one<boundary, interior>(mask, matrix)
439 && per_one<boundary, boundary>(mask, matrix)
440 && per_one<boundary, exterior>(mask, matrix)
441 && per_one<exterior, interior>(mask, matrix)
442 && per_one<exterior, boundary>(mask, matrix)
443 && per_one<exterior, exterior>(mask, matrix);
444 }
445
446 template <field F1, field F2, typename Matrix>
447 static inline bool per_one(Mask const& mask, Matrix const& matrix)
448 {
449 const char mask_el = mask.template get<F1, F2>();
450 const char el = matrix.template get<F1, F2>();
451
452 if ( mask_el == 'F' )
453 {
454 return el == 'F';
455 }
456 else if ( mask_el == 'T' )
457 {
458 return el == 'T' || ( el >= '0' && el <= '9' );
459 }
460 else if ( mask_el >= '0' && mask_el <= '9' )
461 {
462 return el == mask_el;
463 }
464
465 return true;
466 }
467};
468
20effc67 469template <typename Masks, int I = 0, int N = std::tuple_size<Masks>::value>
7c673cae
FG
470struct check_dispatch_tuple
471{
472 template <typename Matrix>
473 static inline bool apply(Masks const& masks, Matrix const& matrix)
474 {
20effc67
TL
475 typedef typename std::tuple_element<I, Masks>::type mask_type;
476 mask_type const& mask = std::get<I>(masks);
7c673cae
FG
477 return check_dispatch<mask_type>::apply(mask, matrix)
478 || check_dispatch_tuple<Masks, I+1>::apply(masks, matrix);
479 }
480};
481
482template <typename Masks, int N>
483struct check_dispatch_tuple<Masks, N, N>
484{
485 template <typename Matrix>
486 static inline bool apply(Masks const&, Matrix const&)
487 {
488 return false;
489 }
490};
491
20effc67
TL
492template <typename ...Masks>
493struct check_dispatch<std::tuple<Masks...>>
7c673cae 494{
20effc67 495 typedef std::tuple<Masks...> mask_type;
7c673cae
FG
496
497 template <typename Matrix>
498 static inline bool apply(mask_type const& mask, Matrix const& matrix)
499 {
500 return check_dispatch_tuple<mask_type>::apply(mask, matrix);
501 }
502};
503
504template <typename Mask, typename Matrix>
505inline bool check_matrix(Mask const& mask, Matrix const& matrix)
506{
507 return check_dispatch<Mask>::apply(mask, matrix);
508}
509
510// matrix_width
511
512template <typename MatrixOrMask>
513struct matrix_width
514{
515 static const std::size_t value = MatrixOrMask::static_width;
516};
517
518template <typename Tuple,
519 int I = 0,
20effc67 520 int N = std::tuple_size<Tuple>::value>
7c673cae
FG
521struct matrix_width_tuple
522{
523 static const std::size_t
20effc67 524 current = matrix_width<typename std::tuple_element<I, Tuple>::type>::value;
7c673cae
FG
525 static const std::size_t
526 next = matrix_width_tuple<Tuple, I+1>::value;
527
528 static const std::size_t
529 value = current > next ? current : next;
530};
531
532template <typename Tuple, int N>
533struct matrix_width_tuple<Tuple, N, N>
534{
535 static const std::size_t value = 0;
536};
537
20effc67
TL
538template <typename ...Masks>
539struct matrix_width<std::tuple<Masks...>>
7c673cae
FG
540{
541 static const std::size_t
20effc67 542 value = matrix_width_tuple<std::tuple<Masks...>>::value;
7c673cae
FG
543};
544
545// mask_handler
546
547template <typename Mask, bool Interrupt>
548class mask_handler
549 : private matrix_handler
550 <
551 relate::matrix<matrix_width<Mask>::value>
552 >
553{
554 typedef matrix_handler
555 <
556 relate::matrix<matrix_width<Mask>::value>
557 > base_t;
558
559public:
560 typedef bool result_type;
561
562 bool interrupt;
563
564 inline explicit mask_handler(Mask const& m)
565 : interrupt(false)
566 , m_mask(m)
567 {}
568
569 result_type result() const
570 {
571 return !interrupt
572 && check_matrix(m_mask, base_t::matrix());
573 }
574
575 template <field F1, field F2, char D>
576 inline bool may_update() const
577 {
578 return detail::relate::may_update<F1, F2, D>(
579 m_mask, base_t::matrix()
580 );
581 }
582
583 template <field F1, field F2, char V>
584 inline void set()
585 {
586 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
587 {
588 interrupt = true;
589 }
590 else
591 {
592 base_t::template set<F1, F2, V>();
593 }
594 }
595
596 template <field F1, field F2, char V>
597 inline void update()
598 {
599 if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
600 {
601 interrupt = true;
602 }
603 else
604 {
605 base_t::template update<F1, F2, V>();
606 }
607 }
608
609private:
610 Mask const& m_mask;
611};
612
92f5a8d4
TL
613// --------------- FALSE MASK ----------------
614
615struct false_mask {};
616
7c673cae
FG
617// --------------- COMPILE-TIME MASK ----------------
618
619// static_check_characters
20effc67
TL
620template <typename Seq>
621struct static_check_characters {};
622
623template <char C, char ...Cs>
624struct static_check_characters<std::integer_sequence<char, C, Cs...>>
625 : static_check_characters<std::integer_sequence<char, Cs...>>
7c673cae 626{
20effc67
TL
627 typedef std::integer_sequence<char, C, Cs...> type;
628 static const bool is_valid = (C >= '0' && C <= '9')
629 || C == 'T' || C == 'F' || C == '*';
630 BOOST_GEOMETRY_STATIC_ASSERT((is_valid),
631 "Invalid static mask character",
632 type);
7c673cae
FG
633};
634
20effc67
TL
635template <char ...Cs>
636struct static_check_characters<std::integral_constant<char, Cs...>>
7c673cae
FG
637{};
638
639// static_mask
640
20effc67 641template <typename Seq, std::size_t Height, std::size_t Width = Height>
7c673cae
FG
642struct static_mask
643{
644 static const std::size_t static_width = Width;
645 static const std::size_t static_height = Height;
646 static const std::size_t static_size = Width * Height;
647
648 BOOST_STATIC_ASSERT(
20effc67 649 std::size_t(util::sequence_size<Seq>::value) == static_size);
7c673cae
FG
650
651 template <detail::relate::field F1, detail::relate::field F2>
652 struct static_get
653 {
654 BOOST_STATIC_ASSERT(std::size_t(F1) < static_height);
655 BOOST_STATIC_ASSERT(std::size_t(F2) < static_width);
656
657 static const char value
20effc67 658 = util::sequence_element<F1 * static_width + F2, Seq>::value;
7c673cae
FG
659 };
660
661private:
662 // check static_mask characters
663 enum { mask_check = sizeof(static_check_characters<Seq>) };
664};
665
666// static_should_handle_element
667
20effc67
TL
668template
669<
670 typename StaticMask, field F1, field F2,
671 bool IsSequence = util::is_sequence<StaticMask>::value
672>
7c673cae
FG
673struct static_should_handle_element_dispatch
674{
675 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
676 static const bool value = mask_el == 'F'
677 || mask_el == 'T'
678 || ( mask_el >= '0' && mask_el <= '9' );
679};
680
20effc67
TL
681template
682<
683 typename Seq, field F1, field F2,
684 std::size_t I = 0,
685 std::size_t N = util::sequence_size<Seq>::value
686>
7c673cae
FG
687struct static_should_handle_element_sequence
688{
20effc67 689 typedef typename util::sequence_element<I, Seq>::type StaticMask;
7c673cae
FG
690
691 static const bool value
692 = static_should_handle_element_dispatch
693 <
20effc67 694 StaticMask, F1, F2
7c673cae
FG
695 >::value
696 || static_should_handle_element_sequence
697 <
20effc67 698 Seq, F1, F2, I + 1
7c673cae
FG
699 >::value;
700};
701
20effc67
TL
702template <typename Seq, field F1, field F2, std::size_t N>
703struct static_should_handle_element_sequence<Seq, F1, F2, N, N>
7c673cae
FG
704{
705 static const bool value = false;
706};
707
708template <typename StaticMask, field F1, field F2>
709struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>
710{
711 static const bool value
712 = static_should_handle_element_sequence
713 <
20effc67 714 StaticMask, F1, F2
7c673cae
FG
715 >::value;
716};
717
718template <typename StaticMask, field F1, field F2>
719struct static_should_handle_element
720{
721 static const bool value
722 = static_should_handle_element_dispatch
723 <
20effc67 724 StaticMask, F1, F2
7c673cae
FG
725 >::value;
726};
727
728// static_interrupt
729
20effc67
TL
730template
731<
732 typename StaticMask, char V, field F1, field F2,
733 bool InterruptEnabled,
734 bool IsSequence = util::is_sequence<StaticMask>::value
735>
7c673cae
FG
736struct static_interrupt_dispatch
737{
738 static const bool value = false;
739};
740
741template <typename StaticMask, char V, field F1, field F2, bool IsSequence>
742struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
743{
744 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
745
746 static const bool value
747 = ( V >= '0' && V <= '9' ) ?
748 ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
749 ( ( V == 'T' ) ? mask_el == 'F' : false );
750};
751
20effc67
TL
752template
753<
754 typename Seq, char V, field F1, field F2,
755 std::size_t I = 0,
756 std::size_t N = util::sequence_size<Seq>::value
757>
7c673cae
FG
758struct static_interrupt_sequence
759{
20effc67 760 typedef typename util::sequence_element<I, Seq>::type StaticMask;
7c673cae
FG
761
762 static const bool value
763 = static_interrupt_dispatch
764 <
20effc67 765 StaticMask, V, F1, F2, true
7c673cae
FG
766 >::value
767 && static_interrupt_sequence
768 <
20effc67 769 Seq, V, F1, F2, I + 1
7c673cae
FG
770 >::value;
771};
772
20effc67
TL
773template <typename Seq, char V, field F1, field F2, std::size_t N>
774struct static_interrupt_sequence<Seq, V, F1, F2, N, N>
7c673cae
FG
775{
776 static const bool value = true;
777};
778
779template <typename StaticMask, char V, field F1, field F2>
780struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, true>
781{
782 static const bool value
783 = static_interrupt_sequence
784 <
20effc67 785 StaticMask, V, F1, F2
7c673cae
FG
786 >::value;
787};
788
789template <typename StaticMask, char V, field F1, field F2, bool EnableInterrupt>
790struct static_interrupt
791{
792 static const bool value
793 = static_interrupt_dispatch
794 <
20effc67 795 StaticMask, V, F1, F2, EnableInterrupt
7c673cae
FG
796 >::value;
797};
798
799// static_may_update
800
20effc67
TL
801template
802<
803 typename StaticMask, char D, field F1, field F2,
804 bool IsSequence = util::is_sequence<StaticMask>::value
805>
7c673cae
FG
806struct static_may_update_dispatch
807{
808 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
809 static const int version
810 = mask_el == 'F' ? 0
811 : mask_el == 'T' ? 1
812 : mask_el >= '0' && mask_el <= '9' ? 2
813 : 3;
814
20effc67
TL
815 // TODO: use std::enable_if_t instead of std::integral_constant
816
7c673cae
FG
817 template <typename Matrix>
818 static inline bool apply(Matrix const& matrix)
819 {
20effc67 820 return apply_dispatch(matrix, std::integral_constant<int, version>());
7c673cae
FG
821 }
822
823 // mask_el == 'F'
824 template <typename Matrix>
20effc67 825 static inline bool apply_dispatch(Matrix const& , std::integral_constant<int, 0>)
7c673cae
FG
826 {
827 return true;
828 }
829 // mask_el == 'T'
830 template <typename Matrix>
20effc67 831 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 1>)
7c673cae
FG
832 {
833 char const c = matrix.template get<F1, F2>();
834 return c == 'F'; // if it's T or between 0 and 9, the result will be the same
835 }
836 // mask_el >= '0' && mask_el <= '9'
837 template <typename Matrix>
20effc67 838 static inline bool apply_dispatch(Matrix const& matrix, std::integral_constant<int, 2>)
7c673cae
FG
839 {
840 char const c = matrix.template get<F1, F2>();
841 return D > c || c > '9';
842 }
843 // else
844 template <typename Matrix>
20effc67 845 static inline bool apply_dispatch(Matrix const&, std::integral_constant<int, 3>)
7c673cae
FG
846 {
847 return false;
848 }
849};
850
20effc67
TL
851template
852<
853 typename Seq, char D, field F1, field F2,
854 std::size_t I = 0,
855 std::size_t N = util::sequence_size<Seq>::value
856>
7c673cae
FG
857struct static_may_update_sequence
858{
20effc67 859 typedef typename util::sequence_element<I, Seq>::type StaticMask;
7c673cae
FG
860
861 template <typename Matrix>
862 static inline bool apply(Matrix const& matrix)
863 {
864 return static_may_update_dispatch
865 <
20effc67 866 StaticMask, D, F1, F2
7c673cae
FG
867 >::apply(matrix)
868 || static_may_update_sequence
869 <
20effc67 870 Seq, D, F1, F2, I + 1
7c673cae
FG
871 >::apply(matrix);
872 }
873};
874
20effc67
TL
875template <typename Seq, char D, field F1, field F2, std::size_t N>
876struct static_may_update_sequence<Seq, D, F1, F2, N, N>
7c673cae
FG
877{
878 template <typename Matrix>
879 static inline bool apply(Matrix const& /*matrix*/)
880 {
881 return false;
882 }
883};
884
885template <typename StaticMask, char D, field F1, field F2>
886struct static_may_update_dispatch<StaticMask, D, F1, F2, true>
887{
888 template <typename Matrix>
889 static inline bool apply(Matrix const& matrix)
890 {
891 return static_may_update_sequence
892 <
20effc67 893 StaticMask, D, F1, F2
7c673cae
FG
894 >::apply(matrix);
895 }
896};
897
898template <typename StaticMask, char D, field F1, field F2>
899struct static_may_update
900{
901 template <typename Matrix>
902 static inline bool apply(Matrix const& matrix)
903 {
904 return static_may_update_dispatch
905 <
20effc67 906 StaticMask, D, F1, F2
7c673cae
FG
907 >::apply(matrix);
908 }
909};
910
911// static_check_matrix
912
20effc67
TL
913template
914<
915 typename StaticMask,
916 bool IsSequence = util::is_sequence<StaticMask>::value
917>
7c673cae
FG
918struct static_check_dispatch
919{
920 template <typename Matrix>
921 static inline bool apply(Matrix const& matrix)
922 {
923 return per_one<interior, interior>::apply(matrix)
924 && per_one<interior, boundary>::apply(matrix)
925 && per_one<interior, exterior>::apply(matrix)
926 && per_one<boundary, interior>::apply(matrix)
927 && per_one<boundary, boundary>::apply(matrix)
928 && per_one<boundary, exterior>::apply(matrix)
929 && per_one<exterior, interior>::apply(matrix)
930 && per_one<exterior, boundary>::apply(matrix)
931 && per_one<exterior, exterior>::apply(matrix);
932 }
933
934 template <field F1, field F2>
935 struct per_one
936 {
937 static const char mask_el = StaticMask::template static_get<F1, F2>::value;
938 static const int version
939 = mask_el == 'F' ? 0
940 : mask_el == 'T' ? 1
941 : mask_el >= '0' && mask_el <= '9' ? 2
942 : 3;
943
20effc67
TL
944 // TODO: use std::enable_if_t instead of std::integral_constant
945
7c673cae
FG
946 template <typename Matrix>
947 static inline bool apply(Matrix const& matrix)
948 {
949 const char el = matrix.template get<F1, F2>();
20effc67 950 return apply_dispatch(el, std::integral_constant<int, version>());
7c673cae
FG
951 }
952
953 // mask_el == 'F'
20effc67 954 static inline bool apply_dispatch(char el, std::integral_constant<int, 0>)
7c673cae
FG
955 {
956 return el == 'F';
957 }
958 // mask_el == 'T'
20effc67 959 static inline bool apply_dispatch(char el, std::integral_constant<int, 1>)
7c673cae
FG
960 {
961 return el == 'T' || ( el >= '0' && el <= '9' );
962 }
963 // mask_el >= '0' && mask_el <= '9'
20effc67 964 static inline bool apply_dispatch(char el, std::integral_constant<int, 2>)
7c673cae
FG
965 {
966 return el == mask_el;
967 }
968 // else
20effc67 969 static inline bool apply_dispatch(char /*el*/, std::integral_constant<int, 3>)
7c673cae
FG
970 {
971 return true;
972 }
973 };
974};
975
20effc67
TL
976template
977<
978 typename Seq,
979 std::size_t I = 0,
980 std::size_t N = util::sequence_size<Seq>::value
981>
7c673cae
FG
982struct static_check_sequence
983{
20effc67 984 typedef typename util::sequence_element<I, Seq>::type StaticMask;
7c673cae
FG
985
986 template <typename Matrix>
987 static inline bool apply(Matrix const& matrix)
988 {
989 return static_check_dispatch
990 <
20effc67 991 StaticMask
7c673cae
FG
992 >::apply(matrix)
993 || static_check_sequence
994 <
20effc67 995 Seq, I + 1
7c673cae
FG
996 >::apply(matrix);
997 }
998};
999
20effc67
TL
1000template <typename Seq, std::size_t N>
1001struct static_check_sequence<Seq, N, N>
7c673cae
FG
1002{
1003 template <typename Matrix>
1004 static inline bool apply(Matrix const& /*matrix*/)
1005 {
1006 return false;
1007 }
1008};
1009
1010template <typename StaticMask>
1011struct static_check_dispatch<StaticMask, true>
1012{
1013 template <typename Matrix>
1014 static inline bool apply(Matrix const& matrix)
1015 {
1016 return static_check_sequence
1017 <
20effc67 1018 StaticMask
7c673cae
FG
1019 >::apply(matrix);
1020 }
1021};
1022
1023template <typename StaticMask>
1024struct static_check_matrix
1025{
1026 template <typename Matrix>
1027 static inline bool apply(Matrix const& matrix)
1028 {
1029 return static_check_dispatch
1030 <
20effc67 1031 StaticMask
7c673cae
FG
1032 >::apply(matrix);
1033 }
1034};
1035
1036// static_mask_handler
1037
1038template <typename StaticMask, bool Interrupt>
1039class static_mask_handler
1040 : private matrix_handler< matrix<3> >
1041{
1042 typedef matrix_handler< relate::matrix<3> > base_type;
1043
1044public:
1045 typedef bool result_type;
1046
1047 bool interrupt;
1048
1049 inline static_mask_handler()
1050 : interrupt(false)
1051 {}
1052
1053 inline explicit static_mask_handler(StaticMask const& /*dummy*/)
1054 : interrupt(false)
1055 {}
1056
1057 result_type result() const
1058 {
1059 return (!Interrupt || !interrupt)
1060 && static_check_matrix<StaticMask>::apply(base_type::matrix());
1061 }
1062
1063 template <field F1, field F2, char D>
1064 inline bool may_update() const
1065 {
1066 return static_may_update<StaticMask, D, F1, F2>::
1067 apply(base_type::matrix());
1068 }
1069
1070 template <field F1, field F2>
1071 static inline bool expects()
1072 {
1073 return static_should_handle_element<StaticMask, F1, F2>::value;
1074 }
1075
1076 template <field F1, field F2, char V>
1077 inline void set()
1078 {
1079 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1080 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1081 static const int version = interrupt_c ? 0
1082 : should_handle ? 1
1083 : 2;
1084
1085 set_dispatch<F1, F2, V>(integral_constant<int, version>());
1086 }
1087
1088 template <field F1, field F2, char V>
1089 inline void update()
1090 {
1091 static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
1092 static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
1093 static const int version = interrupt_c ? 0
1094 : should_handle ? 1
1095 : 2;
1096
1097 update_dispatch<F1, F2, V>(integral_constant<int, version>());
1098 }
1099
1100private:
1101 // Interrupt && interrupt
1102 template <field F1, field F2, char V>
1103 inline void set_dispatch(integral_constant<int, 0>)
1104 {
1105 interrupt = true;
1106 }
1107 // else should_handle
1108 template <field F1, field F2, char V>
1109 inline void set_dispatch(integral_constant<int, 1>)
1110 {
1111 base_type::template set<F1, F2, V>();
1112 }
1113 // else
1114 template <field F1, field F2, char V>
1115 inline void set_dispatch(integral_constant<int, 2>)
1116 {}
1117
1118 // Interrupt && interrupt
1119 template <field F1, field F2, char V>
1120 inline void update_dispatch(integral_constant<int, 0>)
1121 {
1122 interrupt = true;
1123 }
1124 // else should_handle
1125 template <field F1, field F2, char V>
1126 inline void update_dispatch(integral_constant<int, 1>)
1127 {
1128 base_type::template update<F1, F2, V>();
1129 }
1130 // else
1131 template <field F1, field F2, char V>
1132 inline void update_dispatch(integral_constant<int, 2>)
1133 {}
1134};
1135
1136// --------------- UTIL FUNCTIONS ----------------
1137
1138// set
1139
1140template <field F1, field F2, char V, typename Result>
1141inline void set(Result & res)
1142{
1143 res.template set<F1, F2, V>();
1144}
1145
1146template <field F1, field F2, char V, bool Transpose>
1147struct set_dispatch
1148{
1149 template <typename Result>
1150 static inline void apply(Result & res)
1151 {
1152 res.template set<F1, F2, V>();
1153 }
1154};
1155
1156template <field F1, field F2, char V>
1157struct set_dispatch<F1, F2, V, true>
1158{
1159 template <typename Result>
1160 static inline void apply(Result & res)
1161 {
1162 res.template set<F2, F1, V>();
1163 }
1164};
1165
1166template <field F1, field F2, char V, bool Transpose, typename Result>
1167inline void set(Result & res)
1168{
1169 set_dispatch<F1, F2, V, Transpose>::apply(res);
1170}
1171
1172// update
1173
1174template <field F1, field F2, char D, typename Result>
1175inline void update(Result & res)
1176{
1177 res.template update<F1, F2, D>();
1178}
1179
1180template <field F1, field F2, char D, bool Transpose>
1181struct update_result_dispatch
1182{
1183 template <typename Result>
1184 static inline void apply(Result & res)
1185 {
1186 update<F1, F2, D>(res);
1187 }
1188};
1189
1190template <field F1, field F2, char D>
1191struct update_result_dispatch<F1, F2, D, true>
1192{
1193 template <typename Result>
1194 static inline void apply(Result & res)
1195 {
1196 update<F2, F1, D>(res);
1197 }
1198};
1199
1200template <field F1, field F2, char D, bool Transpose, typename Result>
1201inline void update(Result & res)
1202{
1203 update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1204}
1205
1206// may_update
1207
1208template <field F1, field F2, char D, typename Result>
1209inline bool may_update(Result const& res)
1210{
1211 return res.template may_update<F1, F2, D>();
1212}
1213
1214template <field F1, field F2, char D, bool Transpose>
1215struct may_update_result_dispatch
1216{
1217 template <typename Result>
1218 static inline bool apply(Result const& res)
1219 {
1220 return may_update<F1, F2, D>(res);
1221 }
1222};
1223
1224template <field F1, field F2, char D>
1225struct may_update_result_dispatch<F1, F2, D, true>
1226{
1227 template <typename Result>
1228 static inline bool apply(Result const& res)
1229 {
1230 return may_update<F2, F1, D>(res);
1231 }
1232};
1233
1234template <field F1, field F2, char D, bool Transpose, typename Result>
1235inline bool may_update(Result const& res)
1236{
1237 return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
1238}
1239
1240// result_dimension
1241
1242template <typename Geometry>
1243struct result_dimension
1244{
1245 BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);
1246 static const char value
1247 = ( geometry::dimension<Geometry>::value <= 9 ) ?
1248 ( '0' + geometry::dimension<Geometry>::value ) :
1249 'T';
1250};
1251
1252}} // namespace detail::relate
1253#endif // DOXYGEN_NO_DETAIL
1254
1255}} // namespace boost::geometry
1256
1257#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP