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