1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkThreadedIteratorRangePartitioner_hxx
19 #define itkThreadedIteratorRangePartitioner_hxx
20 
21 #include "itkNumericTraits.h"
22 #include "itkThreadedIteratorRangePartitioner.h"
23 #include "itkMath.h"
24 
25 #include <iterator>
26 
27 namespace itk
28 {
29 
30 template< typename TIterator >
31 ThreadIdType
32 ThreadedIteratorRangePartitioner< TIterator >
PartitionDomain(const ThreadIdType threadId,const ThreadIdType requestedTotal,const DomainType & completeDomain,DomainType & subDomain) const33 ::PartitionDomain( const ThreadIdType threadId,
34                    const ThreadIdType requestedTotal,
35                    const DomainType& completeDomain,
36                    DomainType& subDomain ) const
37 {
38   // overallIndexRange is expected to be inclusive
39 
40   // determine the actual number of pieces that will be generated
41   ThreadIdType count = std::distance( completeDomain.Begin(), completeDomain.End() );
42 
43   auto valuesPerThread = Math::Ceil<ThreadIdType>( static_cast< double >( count ) / static_cast< double >( requestedTotal ));
44   ThreadIdType maxThreadIdUsed =
45     Math::Ceil<ThreadIdType>( static_cast< double >( count ) / static_cast< double >( valuesPerThread )) - 1;
46 
47   if ( threadId > maxThreadIdUsed )
48     {
49     // return before advancing Begin iterator, to prevent advancing
50     // past end
51     return maxThreadIdUsed + 1;
52     }
53 
54   const ThreadIdType startIndexCount = threadId * valuesPerThread;
55   subDomain.m_Begin = completeDomain.Begin();
56   std::advance( subDomain.m_Begin, startIndexCount );
57 
58   if (threadId < maxThreadIdUsed)
59     {
60     subDomain.m_End = subDomain.m_Begin;
61     std::advance( subDomain.m_End, valuesPerThread );
62     }
63   if (threadId == maxThreadIdUsed)
64     {
65     // last thread needs to process the "rest" of the range
66     subDomain.m_End = completeDomain.End();
67     }
68 
69   return maxThreadIdUsed + 1;
70 }
71 
72 } // end namespace itk
73 
74 #endif
75