|
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 // This library is free software; you can redistribute it and/or modify 00012 // it under the terms of the GNU Lesser General Public License as 00013 // published by the Free Software Foundation; either version 2.1 of the 00014 // License, or (at your option) any later version. 00015 // 00016 // This library is distributed in the hope that it will be useful, but 00017 // WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 // Lesser General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Lesser General Public 00022 // License along with this library; if not, write to the Free Software 00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00024 // USA 00025 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00026 // 00027 // *********************************************************************** 00028 // @HEADER 00029 */ 00030 00031 #include "RTOp_ROp_get_sub_vector.h" 00032 #include "RTOp_obj_free_free.h" 00033 00034 #include <stdlib.h> 00035 00036 #define MY_MIN(a,b) a < b ? a : b 00037 00038 /* Operator object data virtual function table */ 00039 00040 struct RTOp_ROp_get_sub_vector_rng_t { /* operator object instance data */ 00041 RTOp_index_type l; 00042 RTOp_index_type u; 00043 }; 00044 00045 static int get_op_type_num_entries( 00046 const struct RTOp_obj_type_vtbl_t* vtbl 00047 ,const void* obj_data 00048 ,int* num_values 00049 ,int* num_indexes 00050 ,int* num_chars 00051 ) 00052 { 00053 assert( num_values ); 00054 assert( num_indexes ); 00055 assert( num_chars ); 00056 *num_values = 0; 00057 *num_indexes = 2; /* l, u */ 00058 *num_chars = 0; 00059 return 0; 00060 } 00061 00062 static int obj_create( 00063 const struct RTOp_obj_type_vtbl_t* vtbl, const void* instance_data 00064 , RTOp_ReductTarget* obj ) 00065 { 00066 *obj = malloc(sizeof(struct RTOp_ROp_get_sub_vector_rng_t)); 00067 return 0; 00068 } 00069 00070 static int extract_op_state( 00071 const struct RTOp_obj_type_vtbl_t* vtbl 00072 ,const void * dummy 00073 ,void * obj_data 00074 ,int num_values 00075 ,RTOp_value_type value_data[] 00076 ,int num_indexes 00077 ,RTOp_index_type index_data[] 00078 ,int num_chars 00079 ,RTOp_char_type char_data[] 00080 ) 00081 { 00082 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00083 assert(obj_data); 00084 assert( num_values == 0 ); 00085 assert( num_indexes == 2 ); 00086 assert( num_chars == 0 ); 00087 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00088 index_data[0] = rng->l; 00089 index_data[1] = rng->u; 00090 return 0; 00091 } 00092 00093 static int load_op_state( 00094 const struct RTOp_obj_type_vtbl_t* vtbl 00095 ,const void * dummy 00096 ,int num_values 00097 ,const RTOp_value_type value_data[] 00098 ,int num_indexes 00099 ,const RTOp_index_type index_data[] 00100 ,int num_chars 00101 ,const RTOp_char_type char_data[] 00102 ,void ** obj_data 00103 ) 00104 { 00105 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00106 assert(obj_data); 00107 assert( num_values == 0 ); 00108 assert( num_indexes == 2 ); 00109 assert( num_chars == 0 ); 00110 if(*obj_data == NULL) 00111 *obj_data = malloc(sizeof(struct RTOp_ROp_get_sub_vector_rng_t)); 00112 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)*obj_data; 00113 rng->l = index_data[0]; 00114 rng->u = index_data[1]; 00115 return 0; 00116 } 00117 00118 static struct RTOp_obj_type_vtbl_t instance_obj_vtbl = 00119 { 00120 get_op_type_num_entries 00121 ,obj_create 00122 ,NULL 00123 ,RTOp_obj_free_free 00124 ,extract_op_state 00125 ,load_op_state 00126 }; 00127 00128 /* Reduction object virtual function table */ 00129 00130 static int get_targ_type_num_entries( 00131 const struct RTOp_obj_type_vtbl_t* vtbl 00132 ,const void* obj_data 00133 ,int* num_values 00134 ,int* num_indexes 00135 ,int* num_chars 00136 ) 00137 { 00138 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00139 assert(obj_data); 00140 assert( num_values ); 00141 assert( num_indexes ); 00142 assert( num_chars ); 00143 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00144 *num_values = rng->u - rng->l + 1; /* dense storage for elements of sub-vector to get */ 00145 *num_indexes = 2; /* l and u */ 00146 *num_chars = 0; 00147 return 0; 00148 } 00149 00150 static int targ_obj_create( 00151 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00152 , RTOp_ReductTarget* targ_obj ) 00153 { 00154 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00155 const int mem_size = sizeof(struct RTOp_SubVector); 00156 struct RTOp_SubVector *sub_vec_targ = NULL; 00157 RTOp_index_type sub_dim = 0; 00158 /* Get the range of the sub-vector */ 00159 assert(obj_data); 00160 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00161 sub_dim = rng->u - rng->l + 1; 00162 /* Allocate the sub-vector target object */ 00163 *targ_obj = malloc(mem_size); 00164 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00165 /* Setup storage for the target sub-vector */ 00166 RTOp_sub_vector( 00167 rng->l - 1 /* global_offset */ 00168 ,sub_dim /* sub_dim */ 00169 ,(const RTOp_value_type*)malloc(sub_dim*sizeof(RTOp_value_type)) /* values[] */ 00170 ,1 /* value_stride */ 00171 ,sub_vec_targ ); 00172 /* Initialize the sub-vector to zero */ 00173 vtbl->obj_reinit( vtbl, obj_data, *targ_obj ); 00174 return 0; 00175 } 00176 00177 static int targ_obj_reinit( 00178 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00179 , RTOp_ReductTarget targ_obj ) 00180 { 00181 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00182 struct RTOp_SubVector *sub_vec_targ = NULL; 00183 RTOp_index_type sub_dim = 0; 00184 RTOp_value_type *values = NULL; 00185 register RTOp_index_type k; 00186 assert(obj_data); 00187 /* Get the range of the sub-vector */ 00188 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00189 sub_dim = rng->u - rng->l + 1; 00190 /* Get the target sub-vector */ 00191 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00192 assert( sub_dim == sub_vec_targ->sub_dim ); 00193 assert( sub_vec_targ->values ); 00194 /* Initialize the values to zero */ 00195 values = (RTOp_value_type*)sub_vec_targ->values; 00196 for( k = 0; k < sub_dim; ++k ) 00197 *values++ = 0.0; 00198 return 0; 00199 } 00200 00201 static int targ_obj_free( 00202 const struct RTOp_obj_type_vtbl_t* vtbl, const void* obj_data 00203 , RTOp_ReductTarget* targ_obj ) 00204 { 00205 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00206 struct RTOp_SubVector *sub_vec_targ = NULL; 00207 RTOp_index_type sub_dim = 0; 00208 assert(obj_data); 00209 /* Get the range of the sub-vector */ 00210 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00211 sub_dim = rng->u - rng->l + 1; 00212 /* Get the target sub-vector */ 00213 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00214 assert( sub_dim == sub_vec_targ->sub_dim ); 00215 assert( sub_vec_targ->values ); 00216 /* Deallocate the vectors and the object */ 00217 if( (void*)sub_vec_targ->values ) 00218 free( (void*)sub_vec_targ->values ); 00219 free( (void*)sub_vec_targ ); 00220 *targ_obj = RTOp_REDUCT_OBJ_NULL; 00221 return 0; 00222 } 00223 00224 static int targ_extract_state( 00225 const struct RTOp_obj_type_vtbl_t* vtbl 00226 ,const void * obj_data 00227 ,void * targ_obj 00228 ,int num_values 00229 ,RTOp_value_type value_data[] 00230 ,int num_indexes 00231 ,RTOp_index_type index_data[] 00232 ,int num_chars 00233 ,RTOp_char_type char_data[] 00234 ) 00235 { 00236 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00237 struct RTOp_SubVector *sub_vec_targ = NULL; 00238 RTOp_index_type sub_dim = 0; 00239 register RTOp_index_type k; 00240 assert(obj_data); 00241 /* Get the range of the sub-vector */ 00242 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00243 sub_dim = rng->u - rng->l + 1; 00244 /* Get the target sub-vector */ 00245 assert( targ_obj ); 00246 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00247 assert( sub_dim == sub_vec_targ->sub_dim ); 00248 assert( sub_vec_targ->values ); 00249 /* Extract the state */ 00250 assert( num_values == sub_dim ); 00251 assert( num_indexes == 2 ); 00252 assert( num_chars == 0 ); 00253 for( k = 0; k < sub_dim; ++k ) 00254 value_data[k] = sub_vec_targ->values[k]; 00255 index_data[0] = rng->l; 00256 index_data[1] = rng->u; 00257 return 0; 00258 } 00259 00260 static int targ_load_state( 00261 const struct RTOp_obj_type_vtbl_t* vtbl 00262 ,const void* obj_data 00263 ,int num_values 00264 ,const RTOp_value_type value_data[] 00265 ,int num_indexes 00266 ,const RTOp_index_type index_data[] 00267 ,int num_chars 00268 ,const RTOp_char_type char_data[] 00269 ,void ** targ_obj 00270 ) 00271 { 00272 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00273 struct RTOp_SubVector *sub_vec_targ = NULL; 00274 RTOp_index_type sub_dim = 0; 00275 RTOp_value_type *values = NULL; 00276 register RTOp_index_type k; 00277 assert(obj_data); 00278 /* Get the range of the sub-vector */ 00279 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00280 sub_dim = rng->u - rng->l + 1; 00281 /* Get the target sub-vector */ 00282 assert( *targ_obj ); 00283 sub_vec_targ = (struct RTOp_SubVector*)*targ_obj; 00284 assert( sub_dim == sub_vec_targ->sub_dim ); 00285 assert( sub_vec_targ->values ); 00286 /* Load the state */ 00287 assert( num_values == sub_dim ); 00288 assert( num_indexes == 2 ); 00289 assert( num_chars == 0 ); 00290 assert( index_data[0] == sub_vec_targ->global_offset + 1 ); 00291 assert( index_data[1] == sub_vec_targ->global_offset + sub_vec_targ->sub_dim ); 00292 values = (RTOp_value_type*)sub_vec_targ->values; 00293 for( k = 0; k < sub_dim; ++k ) 00294 *values++ = value_data[k]; 00295 RTOp_sub_vector( 00296 rng->l - 1 /* global_offset */ 00297 ,sub_dim /* sub_dim */ 00298 ,sub_vec_targ->values /* values[] */ 00299 ,1 /* value_stide */ 00300 ,sub_vec_targ ); 00301 return 0; 00302 } 00303 00304 static struct RTOp_obj_type_vtbl_t targ_obj_vtbl = 00305 { 00306 get_targ_type_num_entries 00307 ,targ_obj_create 00308 ,targ_obj_reinit 00309 ,targ_obj_free 00310 ,targ_extract_state 00311 ,targ_load_state 00312 }; 00313 00314 /* Implementation functions */ 00315 00316 static int RTOp_ROp_get_sub_vector_apply_op( 00317 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data 00318 , const int num_vecs, const struct RTOp_SubVector vecs[] 00319 , const int num_targ_vecs, const struct RTOp_MutableSubVector targ_vecs[] 00320 , RTOp_ReductTarget targ_obj ) 00321 { 00322 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00323 struct RTOp_SubVector *sub_vec_targ = NULL; 00324 RTOp_index_type global_offset; 00325 RTOp_index_type sub_dim; 00326 const RTOp_value_type *v0_val; 00327 ptrdiff_t v0_val_s; 00328 RTOp_index_type i, i_l, i_u; 00329 00330 /* */ 00331 /* Validate the input */ 00332 /* */ 00333 if( num_vecs != 1 ) 00334 return RTOp_ERR_INVALID_NUM_VECS; 00335 if( num_targ_vecs != 0 ) 00336 return RTOp_ERR_INVALID_NUM_TARG_VECS; 00337 assert(targ_obj); 00338 assert(vecs); 00339 00340 /* */ 00341 /* Get pointers to data */ 00342 /* */ 00343 00344 /* Get the range of the sub-vector that we are trying to extract */ 00345 assert(obj_data); 00346 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00347 00348 /* Get the sub-vector target object */ 00349 assert( targ_obj ); 00350 sub_vec_targ = (struct RTOp_SubVector*)targ_obj; 00351 assert( sub_vec_targ->global_offset + 1 == rng->l ); 00352 assert( sub_vec_targ->global_offset + sub_vec_targ->sub_dim == rng->u ); 00353 00354 /* v0 */ 00355 global_offset = vecs[0].global_offset; 00356 sub_dim = vecs[0].sub_dim; 00357 v0_val = vecs[0].values; 00358 v0_val_s = vecs[0].values_stride; 00359 00360 /* */ 00361 /* Extract part of the sub-vector for this chunk. */ 00362 /* */ 00363 /* We only want the elements from rng->l to rng->u */ 00364 /* and this vector chunk only has elements from global_offset */ 00365 /* to global_offset + sub_dim. */ 00366 /* */ 00367 00368 if( rng->u < global_offset + 1 || global_offset + sub_dim < rng->l ) 00369 return 0; /* None of the sub-vector that we are looking for is not in this vector chunk! */ 00370 00371 i_l = ( rng->l <= ( global_offset + 1 ) ? 1 : rng->l - global_offset ); 00372 i_u = ( rng->u >= ( global_offset + sub_dim ) ? sub_dim : rng->u - global_offset ); 00373 00374 for( i = i_l; i <= i_u; ++i ) 00375 ((RTOp_value_type*)sub_vec_targ->values)[i-1+(global_offset-(rng->l-1))] = v0_val[(i-1)*v0_val_s]; 00376 00377 return 0; /* success? */ 00378 00379 } 00380 00381 static int reduce_reduct_objs( 00382 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data /* Can be NULL! */ 00383 , RTOp_ReductTarget in_reduct_obj, RTOp_ReductTarget inout_reduct_obj ) 00384 { 00385 const struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00386 struct RTOp_SubVector 00387 *in_sub_vec_targ = NULL, 00388 *inout_sub_vec_targ = NULL; 00389 RTOp_index_type sub_dim = 0; 00390 RTOp_value_type *inout_values = NULL; 00391 register RTOp_index_type k; 00392 /* Get the range of the sub-vector */ 00393 assert(obj_data); 00394 rng = (const struct RTOp_ROp_get_sub_vector_rng_t*)obj_data; 00395 sub_dim = rng->u - rng->l + 1; 00396 /* Get the in target sub-vector */ 00397 assert( in_reduct_obj ); 00398 in_sub_vec_targ = (struct RTOp_SubVector*)in_reduct_obj; 00399 assert( sub_dim == in_sub_vec_targ->sub_dim ); 00400 assert( in_sub_vec_targ->values ); 00401 /* Get the inout target sub-vector */ 00402 assert( inout_reduct_obj ); 00403 inout_sub_vec_targ = (struct RTOp_SubVector*)inout_reduct_obj; 00404 assert( sub_dim == inout_sub_vec_targ->sub_dim ); 00405 assert( inout_sub_vec_targ->values ); 00406 /* Perform the reduction */ 00407 inout_values = (RTOp_value_type*)inout_sub_vec_targ->values; 00408 for( k = 0; k < sub_dim; ++k ) 00409 *inout_values++ += in_sub_vec_targ->values[k]; 00410 return 0; 00411 } 00412 00413 static void CALL_API external_reduct_op( void* in_targ_array, void* inout_targ_array 00414 , int* len, RTOp_Datatype* datatype ) 00415 { 00416 int num_values_off, num_indexes_off, num_chars_off 00417 , values_off, l_off, u_off; 00418 int num_values, num_indexes, num_chars; 00419 const RTOp_value_type *in_values = NULL; 00420 RTOp_value_type *inout_values = NULL; 00421 register RTOp_index_type k; 00422 /* Get the offsets for the number of elements of each data type */ 00423 num_values_off = 0; 00424 num_indexes_off = num_values_off + sizeof(RTOp_value_type); 00425 num_chars_off = num_indexes_off + sizeof(RTOp_value_type); 00426 /* Get the number of elements of each data type */ 00427 num_values = *(RTOp_value_type*)((char*)in_targ_array + num_values_off); 00428 num_indexes = *(RTOp_value_type*)((char*)in_targ_array + num_indexes_off); 00429 num_chars = *(RTOp_value_type*)((char*)in_targ_array + num_chars_off); 00430 #ifdef RTOp_DEBUG 00431 assert( num_values > 0 ); 00432 assert( num_indexes == 2 ); 00433 assert( num_chars == 0 ); 00434 assert( num_values == *(RTOp_value_type*)((char*)inout_targ_array + num_values_off) ); 00435 assert( num_indexes == *(RTOp_value_type*)((char*)inout_targ_array + num_indexes_off) ); 00436 assert( num_chars == *(RTOp_value_type*)((char*)inout_targ_array + num_chars_off) ); 00437 #endif 00438 /* Get the offsets for the sub-vector values and range l and u */ 00439 values_off = num_chars_off + sizeof(RTOp_value_type); 00440 l_off = values_off + num_values * sizeof(RTOp_value_type); 00441 u_off = l_off + sizeof(RTOp_index_type); 00442 #ifdef RTOp_DEBUG 00443 assert( *(RTOp_index_type*)((char*)in_targ_array + l_off) 00444 == *(RTOp_index_type*)((char*)inout_targ_array + l_off) ); 00445 assert( *(RTOp_index_type*)((char*)in_targ_array + u_off) 00446 == *(RTOp_index_type*)((char*)inout_targ_array + u_off) ); 00447 #endif 00448 /* Perform the reduction! (just add the elements together) */ 00449 in_values = (const RTOp_value_type*)((char*)in_targ_array + values_off); 00450 inout_values = (RTOp_value_type*)((char*)inout_targ_array + values_off); 00451 for( k = 0; k < num_values; ++k ) 00452 *inout_values++ += *in_values++; 00453 } 00454 00455 static int get_reduct_op( 00456 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data 00457 , RTOp_reduct_op_func_ptr_t* reduct_op_func_ptr ) 00458 { 00459 *reduct_op_func_ptr = external_reduct_op; 00460 return 0; 00461 } 00462 00463 /* Public interface */ 00464 00465 const struct RTOp_RTOp_vtbl_t RTOp_ROp_get_sub_vector_vtbl = 00466 { 00467 &instance_obj_vtbl 00468 ,&targ_obj_vtbl 00469 ,"RTOp_ROp_get_sub_vector" 00470 ,NULL 00471 ,RTOp_ROp_get_sub_vector_apply_op 00472 ,reduce_reduct_objs 00473 ,get_reduct_op 00474 }; 00475 00476 int RTOp_ROp_get_sub_vector_construct( 00477 RTOp_index_type l, RTOp_index_type u, struct RTOp_RTOp* op ) 00478 { 00479 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00480 op->vtbl = &RTOp_ROp_get_sub_vector_vtbl; 00481 op->vtbl->obj_data_vtbl->obj_create(NULL,NULL,&op->obj_data); 00482 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)op->obj_data; 00483 rng->l = l; 00484 rng->u = u; 00485 return 0; 00486 } 00487 00488 int RTOp_ROp_get_sub_vector_set_range( 00489 RTOp_index_type l, RTOp_index_type u, struct RTOp_RTOp* op ) 00490 { 00491 struct RTOp_ROp_get_sub_vector_rng_t *rng = NULL; 00492 assert( op->vtbl ); 00493 assert( op->obj_data ); 00494 rng = (struct RTOp_ROp_get_sub_vector_rng_t*)op->obj_data; 00495 rng->l = l; 00496 rng->u = u; 00497 return 0; 00498 } 00499 00500 int RTOp_ROp_get_sub_vector_destroy( struct RTOp_RTOp* op ) 00501 { 00502 #ifdef TEUCHOS_DEBUG 00503 assert( op->vtbl ); 00504 assert( op->obj_data ); 00505 #endif 00506 op->vtbl->obj_data_vtbl->obj_free(NULL,NULL,&op->obj_data); 00507 op->vtbl = NULL; 00508 return 0; 00509 } 00510 00511 struct RTOp_SubVector RTOp_ROp_get_sub_vector_val( 00512 RTOp_ReductTarget targ_obj 00513 ) 00514 { 00515 return *((struct RTOp_SubVector*)targ_obj); 00516 }
1.7.4