1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* ---- includes ----------------------------------------------------------- */
18 
19 #include "b_TensorEm/RBFMap2D.h"
20 #include "b_BasicEm/Math.h"
21 #include "b_BasicEm/Memory.h"
22 #include "b_BasicEm/Functions.h"
23 
24 /* ------------------------------------------------------------------------- */
25 
26 /* ========================================================================= */
27 /*                                                                           */
28 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
29 /*                                                                           */
30 /* ========================================================================= */
31 
32 /* ------------------------------------------------------------------------- */
33 
34 /* ========================================================================= */
35 /*                                                                           */
36 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
37 /*                                                                           */
38 /* ========================================================================= */
39 
40 /* ------------------------------------------------------------------------- */
41 
bts_RBFMap2D_init(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA)42 void bts_RBFMap2D_init( struct bbs_Context* cpA,
43 					    struct bts_RBFMap2D* ptrA )
44 {
45 	ptrA->RBFTypeE = bts_RBF_LINEAR;
46 	bts_Cluster2D_init( cpA, &ptrA->srcClusterE );
47 	bts_Cluster2D_init( cpA, &ptrA->rbfCoeffClusterE );
48 	ptrA->altTypeE = bts_ALT_LINEAR;
49 	bts_Flt16Alt2D_init( &ptrA->altE );
50 
51 	ptrA->altOnlyE = FALSE;
52 
53 	bts_Int32Mat_init( cpA, &ptrA->matE );
54 	bts_Int32Mat_init( cpA, &ptrA->tempMatE );
55 	bbs_Int32Arr_init( cpA, &ptrA->inVecE );
56 	bbs_Int32Arr_init( cpA, &ptrA->outVecE );
57 	bbs_Int32Arr_init( cpA, &ptrA->tempVecE );
58 }
59 
60 /* ------------------------------------------------------------------------- */
61 
bts_RBFMap2D_exit(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA)62 void bts_RBFMap2D_exit( struct bbs_Context* cpA,
63 					    struct bts_RBFMap2D* ptrA )
64 {
65 	ptrA->RBFTypeE = bts_RBF_LINEAR;
66 	bts_Cluster2D_exit( cpA, &ptrA->srcClusterE );
67 	bts_Cluster2D_exit( cpA, &ptrA->rbfCoeffClusterE );
68 	ptrA->altTypeE = bts_ALT_LINEAR;
69 	bts_Flt16Alt2D_exit( &ptrA->altE );
70 
71 	ptrA->altOnlyE = FALSE;
72 
73 	bts_Int32Mat_exit( cpA, &ptrA->matE );
74 	bts_Int32Mat_exit( cpA, &ptrA->tempMatE );
75 	bbs_Int32Arr_exit( cpA, &ptrA->inVecE );
76 	bbs_Int32Arr_exit( cpA, &ptrA->outVecE );
77 	bbs_Int32Arr_exit( cpA, &ptrA->tempVecE );
78 }
79 
80 /* ------------------------------------------------------------------------- */
81 
82 /* ========================================================================= */
83 /*                                                                           */
84 /* ---- \ghd{ operators } -------------------------------------------------- */
85 /*                                                                           */
86 /* ========================================================================= */
87 
88 /* ------------------------------------------------------------------------- */
89 
bts_RBFMap2D_copy(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA,const struct bts_RBFMap2D * srcPtrA)90 void bts_RBFMap2D_copy( struct bbs_Context* cpA,
91 					    struct bts_RBFMap2D* ptrA,
92 						const struct bts_RBFMap2D* srcPtrA )
93 {
94 	ptrA->RBFTypeE = srcPtrA->RBFTypeE;
95 	bts_Cluster2D_copy( cpA, &ptrA->srcClusterE, &srcPtrA->srcClusterE );
96 	bts_Cluster2D_copy( cpA, &ptrA->rbfCoeffClusterE, &srcPtrA->rbfCoeffClusterE );
97 	ptrA->altTypeE = srcPtrA->altTypeE;
98 	bts_Flt16Alt2D_copy( &ptrA->altE, &srcPtrA->altE );
99 }
100 
101 /* ------------------------------------------------------------------------- */
102 
bts_RBFMap2D_equal(struct bbs_Context * cpA,const struct bts_RBFMap2D * ptrA,const struct bts_RBFMap2D * srcPtrA)103 flag bts_RBFMap2D_equal( struct bbs_Context* cpA,
104 						 const struct bts_RBFMap2D* ptrA,
105 						 const struct bts_RBFMap2D* srcPtrA )
106 {
107 	if( ptrA->RBFTypeE != srcPtrA->RBFTypeE ) return FALSE;
108 	if( ! bts_Cluster2D_equal( cpA, &ptrA->srcClusterE, &srcPtrA->srcClusterE ) ) return FALSE;
109 	if( ! bts_Cluster2D_equal( cpA, &ptrA->rbfCoeffClusterE, &srcPtrA->rbfCoeffClusterE ) ) return FALSE;
110 	if( ptrA->altTypeE != srcPtrA->altTypeE ) return FALSE;
111 	if( ! bts_Flt16Alt2D_equal( &ptrA->altE, &srcPtrA->altE ) ) return FALSE;
112 	return TRUE;
113 }
114 
115 /* ------------------------------------------------------------------------- */
116 
117 /* ========================================================================= */
118 /*                                                                           */
119 /* ---- \ghd{ query functions } -------------------------------------------- */
120 /*                                                                           */
121 /* ========================================================================= */
122 
123 /* ------------------------------------------------------------------------- */
124 
125 /* ========================================================================= */
126 /*                                                                           */
127 /* ---- \ghd{ modify functions } ------------------------------------------- */
128 /*                                                                           */
129 /* ========================================================================= */
130 
131 /* ------------------------------------------------------------------------- */
132 
bts_RBFMap2D_create(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA,uint32 sizeA,struct bbs_MemSeg * mspA)133 void bts_RBFMap2D_create( struct bbs_Context* cpA,
134 						  struct bts_RBFMap2D* ptrA,
135 						  uint32 sizeA,
136 				          struct bbs_MemSeg* mspA )
137 {
138 	if( bbs_Context_error( cpA ) ) return;
139 	bts_Cluster2D_create( cpA, &ptrA->srcClusterE, sizeA, mspA );
140 	bts_Cluster2D_create( cpA, &ptrA->rbfCoeffClusterE, sizeA, mspA );
141 
142 	bts_Int32Mat_create( cpA, &ptrA->matE, sizeA, mspA );
143 	bts_Int32Mat_create( cpA, &ptrA->tempMatE, sizeA, mspA );
144 	bbs_Int32Arr_create( cpA, &ptrA->inVecE, sizeA, mspA );
145 	bbs_Int32Arr_create( cpA, &ptrA->outVecE, sizeA, mspA );
146 	bbs_Int32Arr_create( cpA, &ptrA->tempVecE, sizeA, mspA );
147 }
148 
149 /* ------------------------------------------------------------------------- */
150 
bts_RBFMap2D_compute(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA,const struct bts_Cluster2D * srcPtrA,const struct bts_Cluster2D * dstPtrA)151 void bts_RBFMap2D_compute( struct bbs_Context* cpA,
152 						   struct bts_RBFMap2D* ptrA,
153 						   const struct bts_Cluster2D* srcPtrA,
154 						   const struct bts_Cluster2D* dstPtrA )
155 {
156 	const uint32 sizeL = srcPtrA->sizeE;
157 	int32 bbp_internalL = 15;
158 	int32 bbp_rbfCoeffL = 12;
159 
160 	int32 internalShiftL = bbp_internalL - srcPtrA->bbpE;
161 	int32 rbfCoeffShiftL;
162 
163 	uint32 iL, jL;
164 
165 	if( dstPtrA->sizeE != srcPtrA->sizeE )
166 	{
167 		bbs_ERROR2( "void bts_RBFMap2D_compute( ... ): size mismatch, src cluster has size %d,"
168 			"but dst cluster has size %d\n", srcPtrA->sizeE, dstPtrA->sizeE );
169 		return;
170 	}
171 
172 	ptrA->altOnlyE = FALSE;
173 
174 	/* if bbp of src cluster should be larger than bbp_internal, use it instead */
175 	if( internalShiftL < 0 )
176 	{
177 		internalShiftL = 0;
178 		bbp_internalL = srcPtrA->bbpE;
179 	}
180 
181 	/* also checks for sizeL > allocated size */
182 	bts_Cluster2D_size( cpA, &ptrA->rbfCoeffClusterE, sizeL );
183 
184 	/* set rbf coefficients to 0 in case they don't get computed */
185 	for( iL =0; iL < sizeL; iL++ )
186 	{
187 		ptrA->rbfCoeffClusterE.vecArrE[ iL ].xE = 0;
188 		ptrA->rbfCoeffClusterE.vecArrE[ iL ].yE = 0;
189 	}
190 
191 	/* 1. Compute rigid transformation: if cluster size == 0 returns identity */
192 	ptrA->altE = bts_Cluster2D_alt( cpA, srcPtrA, dstPtrA, ptrA->altTypeE );
193 
194 	/* if cluster size is less than 3 affine trafo covers whole transformation */
195 	if( sizeL < 3 )
196 	{
197 		bts_Cluster2D_copy( cpA, &ptrA->srcClusterE, srcPtrA );
198 		ptrA->altOnlyE = TRUE;
199 		return;
200 	}
201 
202 	/* 2. Compute RBF trafo */
203 	ptrA->matE.widthE = sizeL;
204 	ptrA->tempMatE.widthE = sizeL;
205 
206 	/* Set up linear matrix to invert */
207 	switch( ptrA->RBFTypeE )
208 	{
209 		case bts_RBF_IDENTITY:
210 		{
211 			return;
212 		}
213 
214 		case bts_RBF_LINEAR:
215 		{
216 			/* ||r|| */
217 			for( iL = 0; iL < sizeL; iL++ )
218 			{
219 				struct bts_Int16Vec2D vec0L = srcPtrA->vecArrE[ iL ];
220 				int32* ptrL = ptrA->matE.arrE.arrPtrE + iL * sizeL;
221 
222 				/* set diagonal elements having null distance */
223 				*( ptrL + iL ) = 0;
224 
225 				for( jL = 0; jL < iL; jL++ )	/* use symmetry */
226 				{
227 					int32 normL = 0;
228 					struct bts_Int16Vec2D vecL = srcPtrA->vecArrE[ jL ];
229 					vecL.xE -= vec0L.xE;
230 					vecL.yE -= vec0L.yE;
231 					normL = bts_Int16Vec2D_norm( &vecL );
232 					*ptrL++ = normL << internalShiftL;
233 				}
234 			}
235 		}
236 		break;
237 
238 		/* Add a new RBF type here */
239 
240 		default:
241 		{
242 			bbs_ERROR1( "void bts_RBFMap2D_compute( ... ): RBFType %d is not handled\n", ptrA->RBFTypeE );
243 			return;
244 		}
245 	}
246 
247 	/* use symmetry: set symmetric elements in matrix */
248 	for( iL = 0; iL < sizeL; iL++ )
249 	{
250 		int32* basePtrL = ptrA->matE.arrE.arrPtrE;
251 		uint32 jL;
252 		for( jL = iL + 1; jL < sizeL; jL++ )
253 		{
254 			*( basePtrL + iL * sizeL + jL ) = *( basePtrL + jL * sizeL + iL );
255 		}
256 	}
257 
258 	/* Precompute alt transformed cluster, srcClusterE will be restored at the end */
259 	bts_Cluster2D_copy( cpA, &ptrA->srcClusterE, srcPtrA );
260 	bts_Cluster2D_transformBbp( cpA, &ptrA->srcClusterE, ptrA->altE, dstPtrA->bbpE );
261 
262 	bbs_Int32Arr_size( cpA, &ptrA->inVecE, sizeL );
263 	bbs_Int32Arr_size( cpA, &ptrA->outVecE, sizeL );
264 	bbs_Int32Arr_size( cpA, &ptrA->tempVecE, sizeL );
265 
266 	{
267 		flag successL;
268 
269 		/* compute right side vector of linear system to be solved, for x */
270 		int32* inPtrL = ptrA->inVecE.arrPtrE;
271 		struct bts_Int16Vec2D* dstVecL = dstPtrA->vecArrE;
272 		struct bts_Int16Vec2D* altVecL = ptrA->srcClusterE.vecArrE;
273 
274 		int32 shiftL = srcPtrA->bbpE - ptrA->srcClusterE.bbpE + internalShiftL;
275 		if( shiftL >= 0 )
276 		{
277 			for( iL = 0; iL < sizeL; iL++ ) inPtrL[ iL ] = ( int32 )( dstVecL[ iL ].xE - altVecL[ iL ].xE ) << shiftL;
278 		}
279 		else
280 		{
281 			for( iL = 0; iL < sizeL; iL++ ) inPtrL[ iL ] = ( ( ( int32 )( dstVecL[ iL ].xE - altVecL[ iL ].xE ) >> ( ( -shiftL ) - 1 ) ) + 1 ) >> 1;
282 		}
283 
284 		/* solve linear system in x */
285 		successL = bts_Int32Mat_solve(  cpA,
286 			                            ptrA->matE.arrE.arrPtrE,
287 										sizeL,
288 										ptrA->inVecE.arrPtrE,
289 										ptrA->outVecE.arrPtrE,
290 										bbp_internalL,
291 										ptrA->tempMatE.arrE.arrPtrE,
292 										ptrA->tempVecE.arrPtrE );
293 
294 		/* no error condition here! system must be failsafe */
295 		if( !successL ) ptrA->altOnlyE = TRUE;
296 
297 		/* store rbf coefficients, x component */
298 		rbfCoeffShiftL = bbp_internalL - bbp_rbfCoeffL;
299 		for( iL = 0; iL < sizeL; iL++ )
300 		{
301 			int32 rbfCoeffL = ptrA->outVecE.arrPtrE[ iL ] >> rbfCoeffShiftL;
302 			if( rbfCoeffL < -32768 || rbfCoeffL > 32767 ) ptrA->altOnlyE = TRUE; /* check for overflow */
303 			ptrA->rbfCoeffClusterE.vecArrE[ iL ].xE = rbfCoeffL;
304 		}
305 
306 
307 		/* compute right side vector of linear system to be solved, for y */
308 		if( shiftL >= 0 )
309 		{
310 			for( iL = 0; iL < sizeL; iL++ ) inPtrL[ iL ] = ( int32 )( dstVecL[ iL ].yE - altVecL[ iL ].yE ) << shiftL;
311 		}
312 		else
313 		{
314 			for( iL = 0; iL < sizeL; iL++ ) inPtrL[ iL ] = ( ( ( int32 )( dstVecL[ iL ].yE - altVecL[ iL ].yE ) >> ( ( -shiftL ) - 1 ) ) + 1 ) >> 1;
315 		}
316 
317 		/* solve linear system in y */
318 		successL = bts_Int32Mat_solve(  cpA,
319 			                            ptrA->matE.arrE.arrPtrE,
320 										sizeL,
321 										ptrA->inVecE.arrPtrE,
322 										ptrA->outVecE.arrPtrE,
323 										bbp_internalL,
324 										ptrA->tempMatE.arrE.arrPtrE,
325 										ptrA->tempVecE.arrPtrE );
326 		if( !successL )
327 		{
328 			/* no error condition here! system must be failsafe */
329 			ptrA->altOnlyE = TRUE;
330 		}
331 
332 		/* store rbf coefficients, y component */
333 		for( iL = 0; iL < sizeL; iL++ )
334 		{
335 			int32 rbfCoeffL = ptrA->outVecE.arrPtrE[ iL ] >> rbfCoeffShiftL;
336 			if( rbfCoeffL < -32768 || rbfCoeffL > 32767 ) ptrA->altOnlyE = TRUE; /* check for overflow */
337 			ptrA->rbfCoeffClusterE.vecArrE[ iL ].yE = rbfCoeffL;
338 		}
339 
340 		/* set bbp of coeff cluster */
341 		ptrA->rbfCoeffClusterE.bbpE = bbp_rbfCoeffL;
342 	}
343 
344 	/** after having used srcClusterE for temporary storage of the alt src cluster,
345 		restore the orig src cluster as needed for the RBF trafo */
346 	bts_Cluster2D_copy( cpA, &ptrA->srcClusterE, srcPtrA );
347 }
348 
349 /* ------------------------------------------------------------------------- */
350 
351 /* ========================================================================= */
352 /*                                                                           */
353 /* ---- \ghd{ I/O } -------------------------------------------------------- */
354 /*                                                                           */
355 /* ========================================================================= */
356 
357 /* ------------------------------------------------------------------------- */
358 
bts_RBFMap2D_memSize(struct bbs_Context * cpA,const struct bts_RBFMap2D * ptrA)359 uint32 bts_RBFMap2D_memSize( struct bbs_Context* cpA,
360 							 const struct bts_RBFMap2D *ptrA )
361 {
362 	return  bbs_SIZEOF16( uint32 )
363 		  + bbs_SIZEOF16( uint32 ) /* version */
364 		  + bbs_SIZEOF16( ptrA->RBFTypeE )
365 		  + bts_Cluster2D_memSize( cpA, &ptrA->srcClusterE )
366 		  + bts_Cluster2D_memSize( cpA, &ptrA->rbfCoeffClusterE )
367 		  + bbs_SIZEOF16( ptrA->altTypeE )
368 		  + bts_Flt16Alt2D_memSize( cpA, &ptrA->altE );
369 }
370 
371 /* ------------------------------------------------------------------------- */
372 
bts_RBFMap2D_memWrite(struct bbs_Context * cpA,const struct bts_RBFMap2D * ptrA,uint16 * memPtrA)373 uint32 bts_RBFMap2D_memWrite( struct bbs_Context* cpA,
374 							  const struct bts_RBFMap2D* ptrA,
375 							  uint16* memPtrA )
376 {
377 	uint32 memSizeL = bts_RBFMap2D_memSize( cpA, ptrA );
378 	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
379 	memPtrA += bbs_memWriteUInt32( bts_IRBFMAP2D_VERSION, memPtrA );
380 	memPtrA += bbs_memWrite32( &ptrA->RBFTypeE, memPtrA );
381 	memPtrA += bts_Cluster2D_memWrite( cpA, &ptrA->srcClusterE, memPtrA );
382 	memPtrA += bts_Cluster2D_memWrite( cpA, &ptrA->rbfCoeffClusterE, memPtrA );
383 	memPtrA += bbs_memWrite32( &ptrA->altTypeE, memPtrA );
384 	memPtrA += bts_Flt16Alt2D_memWrite( cpA, &ptrA->altE, memPtrA );
385 	return memSizeL;
386 }
387 
388 /* ------------------------------------------------------------------------- */
389 
bts_RBFMap2D_memRead(struct bbs_Context * cpA,struct bts_RBFMap2D * ptrA,const uint16 * memPtrA,struct bbs_MemSeg * mspA)390 uint32 bts_RBFMap2D_memRead( struct bbs_Context* cpA,
391 							 struct bts_RBFMap2D* ptrA,
392 							 const uint16* memPtrA,
393 				             struct bbs_MemSeg* mspA )
394 {
395 	uint32 memSizeL, versionL;
396 	if( bbs_Context_error( cpA ) ) return 0;
397 	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
398 	memPtrA += bbs_memReadVersion32( cpA, &versionL, bts_IRBFMAP2D_VERSION, memPtrA );
399 	memPtrA += bbs_memRead32( &ptrA->RBFTypeE, memPtrA );
400 	memPtrA += bts_Cluster2D_memRead( cpA, &ptrA->srcClusterE, memPtrA, mspA );
401 	memPtrA += bts_Cluster2D_memRead( cpA, &ptrA->rbfCoeffClusterE, memPtrA, mspA );
402 	memPtrA += bbs_memRead32( &ptrA->altTypeE, memPtrA );
403 	memPtrA += bts_Flt16Alt2D_memRead( cpA, &ptrA->altE, memPtrA );
404 
405 	bts_Int32Mat_create( cpA, &ptrA->matE, ptrA->srcClusterE.sizeE, mspA );
406 	bts_Int32Mat_create( cpA, &ptrA->tempMatE, ptrA->srcClusterE.sizeE, mspA );
407 
408 	if( memSizeL != bts_RBFMap2D_memSize( cpA, ptrA ) )
409 	{
410 		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bts_RBFMap2D_memRead( ... ): size mismatch\n" );
411 		return 0;
412 	}
413 	return memSizeL;
414 }
415 
416 /* ------------------------------------------------------------------------- */
417 
418 /* ========================================================================= */
419 /*                                                                           */
420 /* ---- \ghd{ exec functions } --------------------------------------------- */
421 /*                                                                           */
422 /* ========================================================================= */
423 
424 /* ------------------------------------------------------------------------- */
425 /**	R, A are rbf and A affine linear transformations
426  *	T( x ) = R( x ) + A( x )
427  */
bts_RBFMap2D_mapVector(struct bbs_Context * cpA,const struct bts_RBFMap2D * ptrA,struct bts_Flt16Vec2D vecA)428 struct bts_Flt16Vec2D bts_RBFMap2D_mapVector( struct bbs_Context* cpA,
429 											  const struct bts_RBFMap2D* ptrA,
430 											  struct bts_Flt16Vec2D vecA )
431 {
432 	const uint32 sizeL = ptrA->srcClusterE.sizeE;
433 	const int32 bbp_internalL = ptrA->rbfCoeffClusterE.bbpE;
434 	uint32 iL;
435 	int32 shL;
436 
437 	int32 outXL;
438 	int32 outYL;
439 	int32 outBbpL;
440 
441 	/* 1. Compute rigid transformation, i.e. A( x ) */
442 	struct bts_Flt16Vec2D altVecL = bts_Flt16Alt2D_mapFlt( &ptrA->altE, &vecA );
443 
444 	/* compute output on 32 bit here to prevent temporary overflows (j.s.) */
445 	outXL   = altVecL.xE;
446 	outYL   = altVecL.yE;
447 	outBbpL = altVecL.bbpE;
448 
449 	/* if bbp was altered, change it back to bbp of vecA ( det A is always close to 1 here ) */
450 	shL = vecA.bbpE - outBbpL;
451 	if( shL > 0 )
452 	{
453 		outXL <<= shL;
454 		outYL <<= shL;
455 	}
456 	else if( shL < 0 )
457 	{
458 		outXL = ( ( outXL >> ( -shL - 1 ) ) + 1 ) >> 1;
459 		outYL = ( ( outYL >> ( -shL - 1 ) ) + 1 ) >> 1;
460 	}
461 	outBbpL = vecA.bbpE;
462 
463 	/* stop here if rbf coefficients could not be computed  */
464 	if( ptrA->altOnlyE )
465 	{
466 		return bts_Flt16Vec2D_create32( outXL, outYL, outBbpL );
467 	}
468 
469 	/* 2. Compute RBF transformation, i.e. R( x ) depending on type */
470 	switch( ptrA->RBFTypeE )
471     {
472 		case bts_RBF_IDENTITY:
473 		break;
474 
475         case bts_RBF_LINEAR:
476         {
477 			int32 xSumL = 0;
478 			int32 ySumL = 0;
479 			int32 internalShiftL = bbp_internalL - ptrA->srcClusterE.bbpE;
480 
481 			/* first adapt vecA to bbp of srcCluster */
482 			int32 xL = vecA.xE;
483 			int32 yL = vecA.yE;
484 			int32 shiftL = ptrA->srcClusterE.bbpE - vecA.bbpE;
485 			if( shiftL > 0 )
486 			{
487 				xL <<= shiftL;
488 				yL <<= shiftL;
489 			}
490 			else if( shiftL < 0 )
491 			{
492 				xL = ( ( xL >> ( -shiftL - 1 ) ) + 1 ) >> 1;
493 				yL = ( ( yL >> ( -shiftL - 1 ) ) + 1 ) >> 1;
494 			}
495 
496 			shiftL = ptrA->srcClusterE.bbpE;
497 
498             for( iL = 0; iL < sizeL; iL++ )
499             {
500 				struct bts_Int16Vec2D vecL = ptrA->srcClusterE.vecArrE[ iL ];
501 				int32 normL = 0;
502 				vecL.xE -= xL;
503 				vecL.yE -= yL;
504 				normL = bts_Int16Vec2D_norm( &vecL );
505 
506 /* printf( "iL = %d, norm = %d\n", iL, normL ); */
507 
508 				xSumL += ( normL * ptrA->rbfCoeffClusterE.vecArrE[ iL ].xE ) >> shiftL;
509 				ySumL += ( normL * ptrA->rbfCoeffClusterE.vecArrE[ iL ].yE ) >> shiftL;
510 
511 /* printf( "iL = %d, xSumL = %d, ySumL = %d\n", iL, xSumL, ySumL ); */
512 
513             }
514 
515 			xSumL >>= internalShiftL;
516 			ySumL >>= internalShiftL;
517 
518 			/* change bbp of result back to bbp of vecA */
519 		/*	shiftL = vecA.bbpE - ptrA->srcClusterE.bbpE - internalShiftL; */
520 			shiftL = vecA.bbpE - ptrA->srcClusterE.bbpE;
521 			if( shiftL > 0 )
522 			{
523 				xSumL <<= shiftL;
524 				ySumL <<= shiftL;
525 			}
526 			else if( shiftL < 0 )
527 			{
528 				xSumL = ( ( xSumL >> ( -shiftL - 1 ) ) + 1 ) >> 1;
529 				ySumL = ( ( ySumL >> ( -shiftL - 1 ) ) + 1 ) >> 1;
530 			}
531 
532 			/* add rbf part to already computed alt part */
533 			outXL += xSumL;
534 			outYL += ySumL;
535         }
536         break;
537 
538 		/* Add a new RBF type here */
539 
540 		default:
541 		{
542 			bbs_ERROR1( "struct bts_Flt16Vec2D bts_RBFMap2D_mapVector( ... ): "
543 				"RBFType %d is not handled\n", ptrA->RBFTypeE );
544 			return bts_Flt16Vec2D_create32( outXL, outYL, outBbpL );
545 		}
546 	}
547 
548 	return bts_Flt16Vec2D_create32( outXL, outYL, outBbpL );
549 }
550 
551 /* ------------------------------------------------------------------------- */
552 
bts_RBFMap2D_mapCluster(struct bbs_Context * cpA,const struct bts_RBFMap2D * ptrA,const struct bts_Cluster2D * srcPtrA,struct bts_Cluster2D * dstPtrA,int32 dstBbpA)553 void bts_RBFMap2D_mapCluster( struct bbs_Context* cpA,
554 							  const struct bts_RBFMap2D* ptrA,
555 							  const struct bts_Cluster2D* srcPtrA,
556 							  struct bts_Cluster2D* dstPtrA,
557 							  int32 dstBbpA )
558 {
559 	if( dstPtrA->sizeE != srcPtrA->sizeE )
560 	{
561 		/* resizing of clusters is allowed as long as allocated size is not exceeded */
562 		bts_Cluster2D_size( cpA, dstPtrA, srcPtrA->sizeE );
563 	}
564 
565 	{
566 		uint32 iL;
567 		int16 bbpL = srcPtrA->bbpE;
568 
569 		dstPtrA->bbpE = dstBbpA;
570 
571 		for( iL = 0; iL < srcPtrA->sizeE; iL++ )
572 		{
573 			struct bts_Int16Vec2D vecL = srcPtrA->vecArrE[ iL ];
574 			struct bts_Flt16Vec2D srcVecL = bts_Flt16Vec2D_create16( vecL.xE, vecL.yE, bbpL );
575 			struct bts_Flt16Vec2D dstVecL = bts_RBFMap2D_mapVector( cpA, ptrA, srcVecL );
576 			dstPtrA->vecArrE[ iL ].xE = bbs_convertS32( dstVecL.xE, dstVecL.bbpE, dstBbpA );
577 			dstPtrA->vecArrE[ iL ].yE = bbs_convertS32( dstVecL.yE, dstVecL.bbpE, dstBbpA );
578 		}
579 	}
580 }
581 
582 /* ------------------------------------------------------------------------- */
583 
584 /* ========================================================================= */
585 
586