|
RTOpPack: Extra C/C++ Code for Vector Reduction/Transformation Operators
Version of the Day
|
00001 /* 00002 // @HEADER 00003 // *********************************************************************** 00004 // 00005 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization 00006 // Copyright (2003) Sandia Corporation 00007 // 00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00009 // license for use of this work by or on behalf of the U.S. Government. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00039 // 00040 // *********************************************************************** 00041 // @HEADER 00042 */ 00043 00044 #include "RTOp_ROp_get_sub_vector.h" 00045 #include "RTOp_obj_free_free.h" 00046 00047 #include <stdlib.h> 00048 00049 #define MY_MIN(a,b) a < b ? a : b 00050 00051 /* Operator object data virtual function table */ 00052 00053 struct RTOp_ROp_get_sub_vector_rng_t { /* operator object instance data */ 00054 RTOp_index_type l; 00055 RTOp_index_type u; 00056 }; 00057 00058 static int get_op_type_num_entries( 00059 const struct RTOp_obj_type_vtbl_t* vtbl 00060 ,const void* obj_data 00061 ,int* num_values 00062 ,int* num_indexes 00063 ,int* num_chars 00064 ) 00065 { 00066 assert( num_values ); 00067 assert( num_indexes ); 00068 assert( num_chars ); 00069 *num_values = 0; 00070 *num_indexes = 2; /* l, u */ 00071 *num_chars = 0; 00072 return 0; 00073 } 00074 00075 static int obj_create( 00076 const struct RTOp_obj_type_vtbl_t* vtbl, const void* instance_data 00077 , RTOp_ReductTarget* obj ) 00078 { 00079 *obj = malloc(sizeof(struct RTOp_ROp_get_sub_vector_rng_t)); 00080 return 0; 00081 } 00082 00083 static int extract_op_state( 00084 const struct RTOp_obj_type_vtbl_t* vtbl 00085 ,const void * dummy 00086 ,void * obj_data 00087 ,int num_values 00088 ,RTOp_value_type value_data[] 00089 ,int num_indexes 00090 ,RTOp_index_type index_data[] 00091 ,int num_chars 00092 ,RTOp_char_type char_data[] 00093 ) 00094 { 00095 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00096 assert(obj_data); 00097 assert( num_values == 0 ); 00098 assert( num_indexes == 2 ); 00099 assert( num_chars == 0 ); 00100 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00101 index_data[0] = rng->l; 00102 index_data[1] = rng->u; 00103 return 0; 00104 } 00105 00106 static int load_op_state( 00107 const struct RTOp_obj_type_vtbl_t* vtbl 00108 ,const void * dummy 00109 ,int num_values 00110 ,const RTOp_value_type value_data[] 00111 ,int num_indexes 00112 ,const RTOp_index_type index_data[] 00113 ,int num_chars 00114 ,const RTOp_char_type char_data[] 00115 ,void ** obj_data 00116 ) 00117 { 00118 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00119 assert(obj_data); 00120 assert( num_values == 0 ); 00121 assert( num_indexes == 2 ); 00122 assert( num_chars == 0 ); 00123 if(*obj_data == NULL) 00124 *obj_data = malloc(sizeof(struct RTOp_ROp_get_sub_vector_rng_t)); 00125 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)*obj_data; 00126 rng->l = index_data[0]; 00127 rng->u = index_data[1]; 00128 return 0; 00129 } 00130 00131 static struct RTOp_obj_type_vtbl_t instance_obj_vtbl = 00132 { 00133 get_op_type_num_entries 00134 ,obj_create 00135 ,NULL 00136 ,RTOp_obj_free_free 00137 ,extract_op_state 00138 ,load_op_state 00139 }; 00140 00141 /* Reduction object virtual function table */ 00142 00143 static int get_targ_type_num_entries( 00144 const struct RTOp_obj_type_vtbl_t* vtbl 00145 ,const void* obj_data 00146 ,int* num_values 00147 ,int* num_indexes 00148 ,int* num_chars 00149 ) 00150 { 00151 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00152 assert(obj_data); 00153 assert( num_values ); 00154 assert( num_indexes ); 00155 assert( num_chars ); 00156 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00157 *num_values = rng->u - rng->l + 1; /* dense storage for elements of sub-vector to get */ 00158 *num_indexes = 2; /* l and u */ 00159 *num_chars = 0; 00160 return 0; 00161 } 00162 00163 static int targ_obj_create( 00164 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00165 , RTOp_ReductTarget* targ_obj ) 00166 { 00167 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00168 const int mem_size = sizeof(struct RTOp_SubVector); 00169 struct RTOp_SubVector *sub_vec_targ = NULL; 00170 RTOp_index_type sub_dim = 0; 00171 /* Get the range of the sub-vector */ 00172 assert(obj_data); 00173 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00174 sub_dim = rng->u - rng->l + 1; 00175 /* Allocate the sub-vector target object */ 00176 *targ_obj = malloc(mem_size); 00177 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00178 /* Setup storage for the target sub-vector */ 00179 RTOp_sub_vector( 00180 rng->l - 1 /* global_offset */ 00181 ,sub_dim /* sub_dim */ 00182 ,(const RTOp_value_type*)malloc(sub_dim*sizeof(RTOp_value_type)) /* values[] */ 00183 ,1 /* value_stride */ 00184 ,sub_vec_targ ); 00185 /* Initialize the sub-vector to zero */ 00186 vtbl->obj_reinit( vtbl, obj_data, *targ_obj ); 00187 return 0; 00188 } 00189 00190 static int targ_obj_reinit( 00191 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00192 , RTOp_ReductTarget targ_obj ) 00193 { 00194 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00195 struct RTOp_SubVector *sub_vec_targ = NULL; 00196 RTOp_index_type sub_dim = 0; 00197 RTOp_value_type *values = NULL; 00198 register RTOp_index_type k; 00199 assert(obj_data); 00200 /* Get the range of the sub-vector */ 00201 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00202 sub_dim = rng->u - rng->l + 1; 00203 /* Get the target sub-vector */ 00204 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00205 assert( sub_dim == sub_vec_targ->sub_dim ); 00206 assert( sub_vec_targ->values ); 00207 /* Initialize the values to zero */ 00208 values = (RTOp_value_type*)sub_vec_targ->values; 00209 for( k = 0; k < sub_dim; ++k ) 00210 *values++ = 0.0; 00211 return 0; 00212 } 00213 00214 static int targ_obj_free( 00215 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00216 , RTOp_ReductTarget* targ_obj ) 00217 { 00218 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00219 struct RTOp_SubVector *sub_vec_targ = NULL; 00220 RTOp_index_type sub_dim = 0; 00221 assert(obj_data); 00222 /* Get the range of the sub-vector */ 00223 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00224 sub_dim = rng->u - rng->l + 1; 00225 /* Get the target sub-vector */ 00226 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00227 assert( sub_dim == sub_vec_targ->sub_dim ); 00228 assert( sub_vec_targ->values ); 00229 /* Deallocate the vectors and the object */ 00230 if( (void*)sub_vec_targ->values ) 00231 free( (void*)sub_vec_targ->values ); 00232 free( (void*)sub_vec_targ ); 00233 *targ_obj = RTOp_REDUCT_OBJ_NULL; 00234 return 0; 00235 } 00236 00237 static int targ_extract_state( 00238 const struct RTOp_obj_type_vtbl_t* vtbl 00239 ,const void * obj_data 00240 ,void * targ_obj 00241 ,int num_values 00242 ,RTOp_value_type value_data[] 00243 ,int num_indexes 00244 ,RTOp_index_type index_data[] 00245 ,int num_chars 00246 ,RTOp_char_type char_data[] 00247 ) 00248 { 00249 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00250 struct RTOp_SubVector *sub_vec_targ = NULL; 00251 RTOp_index_type sub_dim = 0; 00252 register RTOp_index_type k; 00253 assert(obj_data); 00254 /* Get the range of the sub-vector */ 00255 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00256 sub_dim = rng->u - rng->l + 1; 00257 /* Get the target sub-vector */ 00258 assert( targ_obj ); 00259 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00260 assert( sub_dim == sub_vec_targ->sub_dim ); 00261 assert( sub_vec_targ->values ); 00262 /* Extract the state */ 00263 assert( num_values == sub_dim ); 00264 assert( num_indexes == 2 ); 00265 assert( num_chars == 0 ); 00266 for( k = 0; k < sub_dim; ++k ) 00267 value_data[k] = sub_vec_targ->values[k]; 00268 index_data[0] = rng->l; 00269 index_data[1] = rng->u; 00270 return 0; 00271 } 00272 00273 static int targ_load_state( 00274 const struct RTOp_obj_type_vtbl_t* vtbl 00275 ,const void* obj_data 00276 ,int num_values 00277 ,const RTOp_value_type value_data[] 00278 ,int num_indexes 00279 ,const RTOp_index_type index_data[] 00280 ,int num_chars 00281 ,const RTOp_char_type char_data[] 00282 ,void ** targ_obj 00283 ) 00284 { 00285 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00286 struct RTOp_SubVector *sub_vec_targ = NULL; 00287 RTOp_index_type sub_dim = 0; 00288 RTOp_value_type *values = NULL; 00289 register RTOp_index_type k; 00290 assert(obj_data); 00291 /* Get the range of the sub-vector */ 00292 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00293 sub_dim = rng->u - rng->l + 1; 00294 /* Get the target sub-vector */ 00295 assert( *targ_obj ); 00296 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00297 assert( sub_dim == sub_vec_targ->sub_dim ); 00298 assert( sub_vec_targ->values ); 00299 /* Load the state */ 00300 assert( num_values == sub_dim ); 00301 assert( num_indexes == 2 ); 00302 assert( num_chars == 0 ); 00303 assert( index_data[0] == sub_vec_targ->global_offset + 1 ); 00304 assert( index_data[1] == sub_vec_targ->global_offset + sub_vec_targ->sub_dim ); 00305 values = (RTOp_value_type*)sub_vec_targ->values; 00306 for( k = 0; k < sub_dim; ++k ) 00307 *values++ = value_data[k]; 00308 RTOp_sub_vector( 00309 rng->l - 1 /* global_offset */ 00310 ,sub_dim /* sub_dim */ 00311 ,sub_vec_targ->values /* values[] */ 00312 ,1 /* value_stide */ 00313 ,sub_vec_targ ); 00314 return 0; 00315 } 00316 00317 static struct RTOp_obj_type_vtbl_t targ_obj_vtbl = 00318 { 00319 get_targ_type_num_entries 00320 ,targ_obj_create 00321 ,targ_obj_reinit 00322 ,targ_obj_free 00323 ,targ_extract_state 00324 ,targ_load_state 00325 }; 00326 00327 /* Implementation functions */ 00328 00329 static int RTOp_ROp_get_sub_vector_apply_op( 00330 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data 00331 , const int num_vecs, const struct RTOp_SubVector vecs[] 00332 , const int num_targ_vecs, const struct RTOp_MutableSubVector targ_vecs[] 00333 , RTOp_ReductTarget targ_obj ) 00334 { 00335 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00336 struct RTOp_SubVector *sub_vec_targ = NULL; 00337 RTOp_index_type global_offset; 00338 RTOp_index_type sub_dim; 00339 const RTOp_value_type *v0_val; 00340 ptrdiff_t v0_val_s; 00341 RTOp_index_type i, i_l, i_u; 00342 00343 /* */ 00344 /* Validate the input */ 00345 /* */ 00346 if( num_vecs != 1 ) 00347 return RTOp_ERR_INVALID_NUM_VECS; 00348 if( num_targ_vecs != 0 ) 00349 return RTOp_ERR_INVALID_NUM_TARG_VECS; 00350 assert(targ_obj); 00351 assert(vecs); 00352 00353 /* */ 00354 /* Get pointers to data */ 00355 /* */ 00356 00357 /* Get the range of the sub-vector that we are trying to extract */ 00358 assert(obj_data); 00359 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00360 00361 /* Get the sub-vector target object */ 00362 assert( targ_obj ); 00363 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00364 assert( sub_vec_targ->global_offset + 1 == rng->l ); 00365 assert( sub_vec_targ->global_offset + sub_vec_targ->sub_dim == rng->u ); 00366 00367 /* v0 */ 00368 global_offset = vecs[0].global_offset; 00369 sub_dim = vecs[0].sub_dim; 00370 v0_val = vecs[0].values; 00371 v0_val_s = vecs[0].values_stride; 00372 00373 /* */ 00374 /* Extract part of the sub-vector for this chunk. */ 00375 /* */ 00376 /* We only want the elements from rng->l to rng->u */ 00377 /* and this vector chunk only has elements from global_offset */ 00378 /* to global_offset + sub_dim. */ 00379 /* */ 00380 00381 if( rng->u < global_offset + 1 || global_offset + sub_dim < rng->l ) 00382 return 0; /* None of the sub-vector that we are looking for is not in this vector chunk! */ 00383 00384 i_l = ( rng->l <= ( global_offset + 1 ) ? 1 : rng->l - global_offset ); 00385 i_u = ( rng->u >= ( global_offset + sub_dim ) ? sub_dim : rng->u - global_offset ); 00386 00387 for( i = i_l; i <= i_u; ++i ) 00388 ((RTOp_value_type*)sub_vec_targ->values)[i-1+(global_offset-(rng->l-1))] = v0_val[(i-1)*v0_val_s]; 00389 00390 return 0; /* success? */ 00391 00392 } 00393 00394 static int reduce_reduct_objs( 00395 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data /* Can be NULL! */ 00396 , RTOp_ReductTarget in_reduct_obj, RTOp_ReductTarget inout_reduct_obj ) 00397 { 00398 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00399 struct RTOp_SubVector 00400 *in_sub_vec_targ = NULL, 00401 *inout_sub_vec_targ = NULL; 00402 RTOp_index_type sub_dim = 0; 00403 RTOp_value_type *inout_values = NULL; 00404 register RTOp_index_type k; 00405 /* Get the range of the sub-vector */ 00406 assert(obj_data); 00407 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00408 sub_dim = rng->u - rng->l + 1; 00409 /* Get the in target sub-vector */ 00410 assert( in_reduct_obj ); 00411 in_sub_vec_targ = (struct RTOp_SubVector*)in_reduct_obj; 00412 assert( sub_dim == in_sub_vec_targ->sub_dim ); 00413 assert( in_sub_vec_targ->values ); 00414 /* Get the inout target sub-vector */ 00415 assert( inout_reduct_obj ); 00416 inout_sub_vec_targ = (struct RTOp_SubVector*)inout_reduct_obj; 00417 assert( sub_dim == inout_sub_vec_targ->sub_dim ); 00418 assert( inout_sub_vec_targ->values ); 00419 /* Perform the reduction */ 00420 inout_values = (RTOp_value_type*)inout_sub_vec_targ->values; 00421 for( k = 0; k < sub_dim; ++k ) 00422 *inout_values++ += in_sub_vec_targ->values[k]; 00423 return 0; 00424 } 00425 00426 static void CALL_API external_reduct_op( void* in_targ_array, void* inout_targ_array 00427 , int* len, RTOp_Datatype* datatype ) 00428 { 00429 int num_values_off, num_indexes_off, num_chars_off 00430 , values_off, l_off, u_off; 00431 int num_values, num_indexes, num_chars; 00432 const RTOp_value_type *in_values = NULL; 00433 RTOp_value_type *inout_values = NULL; 00434 register RTOp_index_type k; 00435 /* Get the offsets for the number of elements of each data type */ 00436 num_values_off = 0; 00437 num_indexes_off = num_values_off + sizeof(RTOp_value_type); 00438 num_chars_off = num_indexes_off + sizeof(RTOp_value_type); 00439 /* Get the number of elements of each data type */ 00440 num_values = *(RTOp_value_type*)((char*)in_targ_array + num_values_off); 00441 num_indexes = *(RTOp_value_type*)((char*)in_targ_array + num_indexes_off); 00442 num_chars = *(RTOp_value_type*)((char*)in_targ_array + num_chars_off); 00443 #ifdef RTOp_DEBUG 00444 assert( num_values > 0 ); 00445 assert( num_indexes == 2 ); 00446 assert( num_chars == 0 ); 00447 assert( num_values == *(RTOp_value_type*)((char*)inout_targ_array + num_values_off) ); 00448 assert( num_indexes == *(RTOp_value_type*)((char*)inout_targ_array + num_indexes_off) ); 00449 assert( num_chars == *(RTOp_value_type*)((char*)inout_targ_array + num_chars_off) ); 00450 #endif 00451 /* Get the offsets for the sub-vector values and range l and u */ 00452 values_off = num_chars_off + sizeof(RTOp_value_type); 00453 l_off = values_off + num_values * sizeof(RTOp_value_type); 00454 u_off = l_off + sizeof(RTOp_index_type); 00455 #ifdef RTOp_DEBUG 00456 assert( *(RTOp_index_type*)((char*)in_targ_array + l_off) 00457 == *(RTOp_index_type*)((char*)inout_targ_array + l_off) ); 00458 assert( *(RTOp_index_type*)((char*)in_targ_array + u_off) 00459 == *(RTOp_index_type*)((char*)inout_targ_array + u_off) ); 00460 #endif 00461 /* Perform the reduction! (just add the elements together) */ 00462 in_values = (const RTOp_value_type*)((char*)in_targ_array + values_off); 00463 inout_values = (RTOp_value_type*)((char*)inout_targ_array + values_off); 00464 for( k = 0; k < num_values; ++k ) 00465 *inout_values++ += *in_values++; 00466 } 00467 00468 static int get_reduct_op( 00469 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data 00470 , RTOp_reduct_op_func_ptr_t* reduct_op_func_ptr ) 00471 { 00472 *reduct_op_func_ptr = external_reduct_op; 00473 return 0; 00474 } 00475 00476 /* Public interface */ 00477 00478 const struct RTOp_RTOp_vtbl_t RTOp_ROp_get_sub_vector_vtbl = 00479 { 00480 &instance_obj_vtbl 00481 ,&targ_obj_vtbl 00482 ,"RTOp_ROp_get_sub_vector" 00483 ,NULL 00484 ,RTOp_ROp_get_sub_vector_apply_op 00485 ,reduce_reduct_objs 00486 ,get_reduct_op 00487 }; 00488 00489 int RTOp_ROp_get_sub_vector_construct( 00490 RTOp_index_type l, RTOp_index_type u, struct RTOp_RTOp* op ) 00491 { 00492 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00493 op->vtbl = &RTOp_ROp_get_sub_vector_vtbl; 00494 op->vtbl->obj_data_vtbl->obj_create(NULL,NULL,&op->obj_data); 00495 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)op->obj_data; 00496 rng->l = l; 00497 rng->u = u; 00498 return 0; 00499 } 00500 00501 int RTOp_ROp_get_sub_vector_set_range( 00502 RTOp_index_type l, RTOp_index_type u, struct RTOp_RTOp* op ) 00503 { 00504 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00505 assert( op->vtbl ); 00506 assert( op->obj_data ); 00507 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)op->obj_data; 00508 rng->l = l; 00509 rng->u = u; 00510 return 0; 00511 } 00512 00513 int RTOp_ROp_get_sub_vector_destroy( struct RTOp_RTOp* op ) 00514 { 00515 #ifdef TEUCHOS_DEBUG 00516 assert( op->vtbl ); 00517 assert( op->obj_data ); 00518 #endif 00519 op->vtbl->obj_data_vtbl->obj_free(NULL,NULL,&op->obj_data); 00520 op->vtbl = NULL; 00521 return 0; 00522 } 00523 00524 struct RTOp_SubVector RTOp_ROp_get_sub_vector_val( 00525 RTOp_ReductTarget targ_obj 00526 ) 00527 { 00528 return *((struct RTOp_SubVector*)targ_obj); 00529 }
1.7.6.1