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