1 /*
2 Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7 
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer. Redistributions in binary form must reproduce
10 the above copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the distribution.
12 
13 Neither the name of the Johns Hopkins University nor the names of its contributors
14 may be used to endorse or promote products derived from this software without specific
15 prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGE.
27 */
28 
29 #ifndef BSPLINE_DATA_INCLUDED
30 #define BSPLINE_DATA_INCLUDED
31 
32 #define NEW_BSPLINE_CODE 1
33 
34 #include "BinaryNode.h"
35 #include "PPolynomial.h"
36 #include "Array.h"
37 
38 // This class represents a function that is a linear combination of B-spline elements,
39 // with the coeff member indicating how much of each element is present.
40 // [WARNING] The ordering of B-spline elements is in the opposite order from that returned by Polynomial::BSplineComponent
41 template< int Degree >
42 struct BSplineElementCoefficients
43 {
44 	int coeffs[Degree+1];
BSplineElementCoefficientsBSplineElementCoefficients45 	BSplineElementCoefficients( void ){ memset( coeffs , 0 , sizeof( int ) * ( Degree+1 ) ); }
46 	int& operator[]( int idx ){ return coeffs[idx]; }
47 	const int& operator[]( int idx ) const { return coeffs[idx]; }
48 };
49 
50 // This class represents a function on the the interval, partitioned into "res" blocks.
51 // On each block, the function is a degree-Degree polynomial, represented by the coefficients
52 // in the associated BSplineElementCoefficients.
53 // [NOTE] This representation of a function is agnostic to the type of boundary conditions (though the constructor is not).
54 template< int Degree >
55 struct BSplineElements : public std::vector< BSplineElementCoefficients< Degree > >
56 {
57 	static const bool _Primal = (Degree&1)==1;
58 	static const int _Off = (Degree+1)/2;
59 	static int _ReflectLeft ( int offset , int res );
60 	static int _ReflectRight( int offset , int res );
61 	static int _RotateLeft  ( int offset , int res );
62 	static int _RotateRight ( int offset , int res );
63 	template< bool Left > void _addPeriodic( int offset , bool negate );
64 public:
65 	// Coefficients are ordered as "/" "-" "\"
66 	// [WARNING] This is the opposite of the order in Polynomial::BSplineComponent
67 	int denominator;
68 
BSplineElementsBSplineElements69 	BSplineElements( void ) { denominator = 1; }
70 	BSplineElements( int res , int offset , bool dirichlet );
71 
72 	void upSample( BSplineElements& high ) const;
73 	void differentiate( BSplineElements< Degree-1 >& d ) const;
74 
75 	void print( FILE* fp=stdout ) const
76 	{
77 		for( int i=0 ; i<std::vector< BSplineElementCoefficients< Degree > >::size() ; i++ )
78 		{
79 			printf( "%d]" , i );
80 			for( int j=0 ; j<=Degree ; j++ ) printf( " %d" , (*this)[i][j] );
81 			printf( " (%d)\n" , denominator );
82 		}
83 	}
84 };
85 #define BSPLINE_SET_BOUNDS( name , s , e ) \
86 	static const int name ## Start = (s); \
87 	static const int name ## End   = (e); \
88 	static const int name ## Size  = (e)-(s)+1
89 
90 // Assumes that x is non-negative
91 #define _FLOOR_OF_HALF( x ) (   (x)    >>1 )
92 #define  _CEIL_OF_HALF( x ) ( ( (x)+1 )>>1 )
93 // Done with the assumption
94 #define FLOOR_OF_HALF( x ) ( (x)<0 ? -  _CEIL_OF_HALF( -(x) ) : _FLOOR_OF_HALF( x ) )
95 #define  CEIL_OF_HALF( x ) ( (x)<0 ? - _FLOOR_OF_HALF( -(x) ) :  _CEIL_OF_HALF( x ) )
96 #define SMALLEST_INTEGER_LARGER_THAN_HALF( x ) (  CEIL_OF_HALF( (x)+1 ) )
97 #define LARGEST_INTEGER_SMALLER_THAN_HALF( x ) ( FLOOR_OF_HALF( (x)-1 ) )
98 #define SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( x ) (  CEIL_OF_HALF( x ) )
99 #define LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( x ) ( FLOOR_OF_HALF( x ) )
100 
101 template< int Degree >
102 class BSplineEvaluationData
103 {
104 public:
105 	BSplineEvaluationData( void );
106 	static double Value( int depth , int off , double s , bool dirichlet , bool derivative );
107 
Dimension(int depth)108 	static int Dimension( int depth ){ return ( 1<<depth ) + ( Degree&1 ); }
109 	// An index is interiorly supported if its support is in the range [0,1<<depth)
InteriorSupportedSpan(int depth,int & begin,int & end)110 	inline static void InteriorSupportedSpan( int depth , int& begin , int& end ){ begin = -SupportStart , end = (1<<depth)-SupportEnd; }
111 
112 	// If the degree is even, we use a dual basis and functions are centered at the center of the interval
113 	// It the degree is odd, we use a primal basis and functions are centered at the left end of the interval
114 	// The function at index I is supported in:
115 	//	Support( I ) = [ I - (Degree+1-Inset)/2 , I + (Degree+1+Inset)/2 ]
116 	// [NOTE] The value of ( Degree + 1 +/- Inset ) is always even
117 	static const int Inset = (Degree&1) ? 0 : 1;
118 	BSPLINE_SET_BOUNDS(      Support , -( (Degree+1)/2 ) , Degree/2           );
119 	BSPLINE_SET_BOUNDS( ChildSupport ,    2*SupportStart , 2*(SupportEnd+1)-1 );
120 	BSPLINE_SET_BOUNDS(       Corner ,    SupportStart+1 , SupportEnd         );
121 	BSPLINE_SET_BOUNDS(  ChildCorner ,  2*SupportStart+1 , 2*SupportEnd + 1   );
122 
123 	// Setting I=0, we are looking for the smallest/largest integers J such that:
124 	//		Support( 0 ) CONTAINS Support( J )
125 	// <=>	[-(Degree+1-Inset) , (Degree+1+Inset) ] CONTAINS [ J-(Degree+1-Inset)/2 , J+(Degree+1+Inset)/2 ]
126 	// Which is the same as the smallest/largest integers J such that:
127 	//		J - (Degree+1-Inset)/2 >= -(Degree+1-Inset)	| J + (Degree+1+Inset)/2 <= (Degree+1+Inset)
128 	// <=>	J >= -(Degree+1-Inset)/2					| J <= (Degree+1+Inset)/2
129 	BSPLINE_SET_BOUNDS( UpSample , - ( Degree + 1 - Inset ) / 2 , ( Degree + 1 + Inset ) /2 );
130 
131 	// Setting I=0/1, we are looking for the smallest/largest integers J such that:
132 	//		Support( J ) CONTAINS Support( 0/1 )
133 	// <=>	[ 2*J - (Degree+1-Inset) , 2*J + (Degree+1+Inset) ] CONTAINS [ 0/1 - (Degree+1-Inset)/2 , 0/1 + (Degree+1+Inset)/2 ]
134 	// Which is the same as the smallest/largest integers J such that:
135 	//		2*J + (Degree+1+Inset) >= 0/1 + (Degree+1+Inset)/2	| 2*J - (Degree+1-Inset) <= 0/1 - (Degree+1-Inset)/2
136 	// <=>	2*J >= 0/1 - (Degree+1+Inset)/2						| 2*J <= 0/1 + (Degree+1-Inset)/2
137 	BSPLINE_SET_BOUNDS( DownSample0 , SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( 0 - ( Degree + 1 + Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( 0 + ( Degree + 1 - Inset ) / 2 ) );
138 	BSPLINE_SET_BOUNDS( DownSample1 , SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF( 1 - ( Degree + 1 + Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF( 1 + ( Degree + 1 - Inset ) / 2 ) );
139 	static const int DownSampleStart[] , DownSampleEnd[] , DownSampleSize[];
140 
141 	// Note that this struct stores the components in left-to-right order
142 	struct BSplineComponents
143 	{
144 	protected:
145 		Polynomial< Degree > _polys[Degree+1];
146 	public:
BSplineComponentsBSplineComponents147 		BSplineComponents( void ){ ; }
148 		BSplineComponents( int depth , int offset , bool dirichlet );
149 		const Polynomial< Degree >& operator[] ( int idx ) const { return _polys[idx]; }
printnlBSplineComponents150 		void printnl( void ) const { for( int d=0 ; d<=Degree ; d++ ) printf( "[%d] " , d ) , _polys[d].printnl(); }
151 	};
152 	struct BSplineUpSamplingCoefficients
153 	{
154 	protected:
155 		int _coefficients[ UpSampleSize ];
156 	public:
BSplineUpSamplingCoefficientsBSplineUpSamplingCoefficients157 		BSplineUpSamplingCoefficients( void ){ ; }
158 		BSplineUpSamplingCoefficients( int depth , int offset , bool dirichlet );
159 		double operator[] ( int idx ){ return (double)_coefficients[idx] / (1<<Degree); }
160 	};
161 
162 	struct CenterEvaluator
163 	{
164 		static const int Start = -SupportStart , Stop = SupportEnd , Size = Start + Stop + 1;
165 
IndexCenterEvaluator166 		static const int Index( int depth , int offset  )
167 		{
168 			int dim = BSplineEvaluationData< Degree >::Dimension( depth );
169 			if     ( offset<Start )     return offset;
170 			else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop );
171 			else                        return Start;
172 		}
173 		struct Evaluator
174 		{
175 		protected:
176 			friend BSplineEvaluationData;
177 			int _depth;
178 			double _ccValues[2][Size][SupportSize];
179 		public:
180 			double value( int fIdx , int cIdx , bool d ) const;
depthCenterEvaluator::Evaluator181 			int depth( void ) const { return _depth; }
182 		};
183 		struct ChildEvaluator
184 		{
185 		protected:
186 			friend BSplineEvaluationData;
187 			int _parentDepth;
188 			double _pcValues[2][Size][ChildSupportSize];
189 		public:
190 			double value( int fIdx , int cIdx , bool d ) const;
parentDepthCenterEvaluator::ChildEvaluator191 			int parentDepth( void ) const { return _parentDepth; }
childDepthCenterEvaluator::ChildEvaluator192 			int childDepth( void ) const { return _parentDepth+1; }
193 		};
194 	};
195 	static void SetCenterEvaluator( typename CenterEvaluator::Evaluator& evaluator , int depth , bool dirichlet );
196 	static void SetChildCenterEvaluator( typename CenterEvaluator::ChildEvaluator& evaluator , int parentDepth , bool dirichlet );
197 
198 	struct CornerEvaluator
199 	{
200 		static const int Start = -SupportStart , Stop = SupportEnd , Size = Start + Stop + 1;
201 
IndexCornerEvaluator202 		static const int Index( int depth , int offset  )
203 		{
204 			int dim = BSplineEvaluationData< Degree >::Dimension( depth );
205 			if     ( offset<Start )     return offset;
206 			else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop );
207 			else                        return Start;
208 		}
209 		struct Evaluator
210 		{
211 		protected:
212 			friend BSplineEvaluationData;
213 			int _depth;
214 			double _ccValues[2][Size][CornerSize];
215 		public:
216 			double value( int fIdx , int cIdx , bool d ) const;
depthCornerEvaluator::Evaluator217 			int depth( void ) const { return _depth; }
218 		};
219 		struct ChildEvaluator
220 		{
221 		protected:
222 			friend BSplineEvaluationData;
223 			int _parentDepth;
224 			double _pcValues[2][Size][ChildCornerSize];
225 		public:
226 			double value( int fIdx , int cIdx , bool d ) const;
parentDepthCornerEvaluator::ChildEvaluator227 			int parentDepth( void ) const { return _parentDepth; }
childDepthCornerEvaluator::ChildEvaluator228 			int childDepth( void ) const { return _parentDepth+1; }
229 		};
230 	};
231 	static void SetCornerEvaluator( typename CornerEvaluator::Evaluator& evaluator , int depth , bool dirichlet );
232 	static void SetChildCornerEvaluator( typename CornerEvaluator::ChildEvaluator& evaluator , int parentDepth , bool dirichlet );
233 
234 	struct Evaluator
235 	{
236 		typename CenterEvaluator::Evaluator centerEvaluator;
237 		typename CornerEvaluator::Evaluator cornerEvaluator;
centerValueEvaluator238 		double centerValue( int fIdx , int cIdx , bool d ) const { return centerEvaluator.value( fIdx , cIdx , d ); }
cornerValueEvaluator239 		double cornerValue( int fIdx , int cIdx , bool d ) const { return cornerEvaluator.value( fIdx , cIdx , d ); }
240 	};
SetEvaluator(Evaluator & evaluator,int depth,bool dirichlet)241 	static void SetEvaluator( Evaluator& evaluator , int depth , bool dirichlet ){ SetCenterEvaluator( evaluator.centerEvaluator , depth , dirichlet ) , SetCornerEvaluator( evaluator.cornerEvaluator , depth , dirichlet ); }
242 	struct ChildEvaluator
243 	{
244 		typename CenterEvaluator::ChildEvaluator centerEvaluator;
245 		typename CornerEvaluator::ChildEvaluator cornerEvaluator;
centerValueChildEvaluator246 		double centerValue( int fIdx , int cIdx , bool d ) const { return centerEvaluator.value( fIdx , cIdx , d ); }
cornerValueChildEvaluator247 		double cornerValue( int fIdx , int cIdx , bool d ) const { return cornerEvaluator.value( fIdx , cIdx , d ); }
248 	};
SetChildEvaluator(ChildEvaluator & evaluator,int depth,bool dirichlet)249 	static void SetChildEvaluator( ChildEvaluator& evaluator , int depth , bool dirichlet ){ SetChildCenterEvaluator( evaluator.centerEvaluator , depth , dirichlet ) , SetChildCornerEvaluator( evaluator.cornerEvaluator , depth , dirichlet ); }
250 
251 	struct UpSampleEvaluator
252 	{
253 		static const int Start = - SupportStart , Stop = SupportEnd , Size = Start + Stop + 1;
IndexUpSampleEvaluator254 		static const int Index( int depth , int offset  )
255 		{
256 			int dim = BSplineEvaluationData< Degree >::Dimension( depth );
257 			if     ( offset<Start )     return offset;
258 			else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop );
259 			else                        return Start;
260 		}
261 	protected:
262 		friend BSplineEvaluationData;
263 		int _lowDepth;
264 		double _pcValues[Size][UpSampleSize];
265 	public:
266 		double value( int pIdx , int cIdx ) const;
lowDepthUpSampleEvaluator267 		int lowDepth( void ) const { return _lowDepth; }
268 	};
269 	static void SetUpSampleEvaluator( UpSampleEvaluator& evaluator , int lowDepth , bool dirichlet );
270 };
271 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleStart[] = { DownSample0Start , DownSample1Start };
272 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleEnd  [] = { DownSample0End   , DownSample1End   };
273 template< int Degree > const int BSplineEvaluationData< Degree >::DownSampleSize [] = { DownSample0Size  , DownSample1Size  };
274 
275 template< int Degree1 , int Degree2 >
276 class BSplineIntegrationData
277 {
278 public:
279 	static double Dot( int depth1 , int off1 , bool dirichlet1 , bool d1 , int depth2 , int off2 , bool dirichlet2 , bool d2 );
280 	// An index is interiorly overlapped if the support of its overlapping neighbors is in the range [0,1<<depth)
InteriorOverlappedSpan(int depth,int & begin,int & end)281 	inline static void InteriorOverlappedSpan( int depth , int& begin , int& end ){ begin = -OverlapStart-BSplineEvaluationData< Degree2 >::SupportStart , end = (1<<depth)-OverlapEnd-BSplineEvaluationData< Degree2 >::SupportEnd; }
282 
283 	typedef BSplineEvaluationData< Degree1 > EData1;
284 	typedef BSplineEvaluationData< Degree2 > EData2;
285 	BSPLINE_SET_BOUNDS(             Overlap , EData1::     SupportStart - EData2::SupportEnd , EData1::     SupportEnd - EData2::SupportStart );
286 	BSPLINE_SET_BOUNDS(        ChildOverlap , EData1::ChildSupportStart - EData2::SupportEnd , EData1::ChildSupportEnd - EData2::SupportStart );
287 	BSPLINE_SET_BOUNDS(      OverlapSupport ,      OverlapStart + EData2::SupportStart ,      OverlapEnd + EData2::SupportEnd );
288 	BSPLINE_SET_BOUNDS( ChildOverlapSupport , ChildOverlapStart + EData2::SupportStart , ChildOverlapEnd + EData2::SupportEnd );
289 
290 	// Setting I=0/1, we are looking for the smallest/largest integers J such that:
291 	//		Support( 2*J ) * 2 INTERSECTION Support( 0/1 ) NON-EMPTY
292 	// <=>	[ 2*J - (Degree2+1-Inset2) , 2*J + (Degree2+1+Inset2) ] INTERSECTION [ 0/1 - (Degree1+1-Inset1)/2 , 0/1 + (Degree1+1+Inset1)/2 ] NON-EMPTY
293 	// Which is the same as the smallest/largest integers J such that:
294 	//		0/1 - (Degree1+1-Inset1)/2 < 2*J + (Degree2+1+Inset2)			| 0/1 + (Degree1+1+Inset1)/2 > 2*J - (Degree2+1-Inset2)
295 	// <=>	2*J > 0/1 - ( 2*Degree2 + Degree1 + 3 + 2*Inset2 - Inset1 ) / 2	| 2*J < 0/1 + ( 2*Degree2 + Degree1 + 3 - 2*Inset2 + Inset1 ) / 2
296 	BSPLINE_SET_BOUNDS( ParentOverlap0 , SMALLEST_INTEGER_LARGER_THAN_HALF( 0 - ( 2*Degree2 + Degree1 + 3 + 2*EData2::Inset - EData1::Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_HALF( 0 + ( 2*Degree2 + Degree1 + 3 - 2*EData2::Inset + EData1::Inset ) / 2 ) );
297 	BSPLINE_SET_BOUNDS( ParentOverlap1 , SMALLEST_INTEGER_LARGER_THAN_HALF( 1 - ( 2*Degree2 + Degree1 + 3 + 2*EData2::Inset - EData1::Inset ) / 2 ) , LARGEST_INTEGER_SMALLER_THAN_HALF( 1 + ( 2*Degree2 + Degree1 + 3 - 2*EData2::Inset + EData1::Inset ) / 2 ) );
298 	static const int ParentOverlapStart[] , ParentOverlapEnd[] , ParentOverlapSize[];
299 
300 	struct FunctionIntegrator
301 	{
302 		static const int Start = - OverlapSupportStart , Stop = OverlapSupportEnd , Size = Start + Stop + 1;
IndexFunctionIntegrator303 		static const int Index( int depth , int offset  )
304 		{
305 			int dim = BSplineEvaluationData< Degree2 >::Dimension( depth );
306 			if     ( offset<Start )     return offset;
307 			else if( offset>=dim-Stop ) return Start + 1 + offset - ( dim-Stop );
308 			else                        return Start;
309 		}
310 		struct Integrator
311 		{
312 		protected:
313 			friend BSplineIntegrationData;
314 			int _depth;
315 			double _ccIntegrals[2][2][Size][OverlapSize];
316 		public:
317 			double dot( int fIdx1 , int fidx2 , bool d1 , bool d2 ) const;
depthFunctionIntegrator::Integrator318 			int depth( void ) const { return _depth; }
319 		};
320 		struct ChildIntegrator
321 		{
322 		protected:
323 			friend BSplineIntegrationData;
324 			int _parentDepth;
325 			double _pcIntegrals[2][2][Size][ChildOverlapSize];
326 		public:
327 			double dot( int fIdx1 , int fidx2 , bool d1 , bool d2 ) const;
parentDepthFunctionIntegrator::ChildIntegrator328 			int parentDepth( void ) const { return _parentDepth; }
childDepthFunctionIntegrator::ChildIntegrator329 			int childDepth( void ) const { return _parentDepth+1; }
330 		};
331 	};
332 	static void SetIntegrator( typename FunctionIntegrator::Integrator& integrator , int depth , bool dirichlet1 , bool dirichlet2 );
333 	static void SetChildIntegrator( typename FunctionIntegrator::ChildIntegrator& integrator , int parentDepth , bool dirichlet1 , bool dirichlet2 );
334 };
335 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapStart[] = { ParentOverlap0Start , ParentOverlap1Start };
336 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapEnd  [] = { ParentOverlap0End   , ParentOverlap1End   };
337 template< int Degree1 , int Degree2 > const int BSplineIntegrationData< Degree1 , Degree2 >::ParentOverlapSize [] = { ParentOverlap0Size  , ParentOverlap1Size  };
338 #undef BSPLINE_SET_BOUNDS
339 #undef _FLOOR_OF_HALF
340 #undef  _CEIL_OF_HALF
341 #undef FLOOR_OF_HALF
342 #undef  CEIL_OF_HALF
343 #undef SMALLEST_INTEGER_LARGER_THAN_HALF
344 #undef LARGEST_INTEGER_SMALLER_THAN_HALF
345 #undef SMALLEST_INTEGER_LARGER_THAN_OR_EQUAL_TO_HALF
346 #undef LARGEST_INTEGER_SMALLER_THAN_OR_EQUAL_TO_HALF
347 
348 template< int Degree >
349 class BSplineData
350 {
351 	bool _dirichlet;
352 public:
353 
Centers(int depth)354 	inline static int Centers  ( int depth ){ return (1<<depth); }
Corners(int depth)355 	inline static int Corners  ( int depth ){ return (1<<depth) + 1; }
Dimension(int depth)356 	inline static int Dimension( int depth ){ return (1<<depth) + (Degree&1); }
FunctionIndex(int depth,int offset)357 	inline static int FunctionIndex( int depth , int offset ){ return (Degree&1) ? BinaryNode::CornerIndex( depth , offset ) : BinaryNode::CenterIndex( depth , offset ); }
FactorFunctionIndex(int idx,int & depth,int & offset)358 	inline static void FactorFunctionIndex( int idx , int& depth , int& offset ){ return (Degree&1) ? BinaryNode::CornerDepthAndOffset( idx , depth , offset ) : BinaryNode::CenterDepthAndOffset( idx , depth , offset ); }
TotalFunctionCount(int depth)359 	inline static int TotalFunctionCount( int depth ){ return (Degree&1) ? BinaryNode::CumulativeCornerCount( depth ) : BinaryNode::CumulativeCenterCount( depth ); }
TotalSampleCount(int depth)360 	inline static int TotalSampleCount( int depth ){ return BinaryNode::CenterCount( depth ) + BinaryNode::CornerCount( depth ); }
FunctionSpan(int depth,int & fStart,int & fEnd)361 	inline static void FunctionSpan( int depth , int& fStart , int& fEnd ){ fStart = (depth>0) ? TotalFunctionCount(depth-1) : 0 , fEnd = TotalFunctionCount(depth); }
SampleSpan(int depth,int & sStart,int & sEnd)362 	inline static void SampleSpan( int depth , int& sStart , int& sEnd ){ sStart = (depth>0) ? TotalSampleCount(depth-1) : 0 , sEnd = TotalSampleCount(depth); }
363 
364 	inline static int RemapOffset( int depth , int idx , bool& reflect );
365 
366 	int depth;
367 	size_t functionCount , sampleCount;
368 	Pointer( typename BSplineEvaluationData< Degree >::BSplineComponents ) baseBSplines;
369 
370 	BSplineData( void );
371 
372 	void set( int maxDepth , bool dirichlet=false );
373 };
374 
375 template< int Degree1 , int Degree2 > void SetBSplineElementIntegrals( double integrals[Degree1+1][Degree2+1] );
376 
377 
378 #include "BSplineData.inl"
379 #endif // BSPLINE_DATA_INCLUDED