Home | History | Annotate | Download | only in b_TensorEm
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    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