|
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_TOp_set_sub_vector.h" 00045 #include "RTOp_obj_null_vtbl.h" 00046 00047 #include <stdlib.h> 00048 00049 /* Operator object data virtual function table */ 00050 00051 struct RTOp_TOp_set_sub_vector_state_t { /* operator object instance data */ 00052 struct RTOp_SparseSubVector sub_vec; /* The sub vector to set! */ 00053 int owns_mem; /* if true then memory is sub_vec must be deleted! */ 00054 }; 00055 00056 static int get_op_type_num_entries( 00057 const struct RTOp_obj_type_vtbl_t* vtbl 00058 ,const void* obj_data 00059 ,int* num_values 00060 ,int* num_indexes 00061 ,int* num_chars 00062 ) 00063 { 00064 const struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00065 #ifdef RTOp_DEBUG 00066 assert( num_values ); 00067 assert( num_indexes ); 00068 assert( num_chars ); 00069 assert( obj_data ); 00070 #endif 00071 state = (const struct RTOp_TOp_set_sub_vector_state_t*)obj_data; 00072 *num_values = state->sub_vec.sub_nz; /* values[] */ 00073 *num_indexes = 00074 8 /* global_offset, sub_dim, sub_nz, values_stride, indices_stride, local_offset, is_sorted, owns_mem */ 00075 + (state->sub_vec.indices ? state->sub_vec.sub_nz : 0 ); /* indices[] */ 00076 *num_chars = 0; 00077 return 0; 00078 } 00079 00080 static int op_create( 00081 const struct RTOp_obj_type_vtbl_t* vtbl, const void* instance_data 00082 , RTOp_ReductTarget* obj ) 00083 { 00084 struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00085 *obj = malloc(sizeof(struct RTOp_TOp_set_sub_vector_state_t)); 00086 state = (struct RTOp_TOp_set_sub_vector_state_t*)*obj; 00087 RTOp_sparse_sub_vector_null( &state->sub_vec ); 00088 state->owns_mem = 0; 00089 return 0; 00090 } 00091 00092 static int op_free( 00093 const struct RTOp_obj_type_vtbl_t* vtbl, const void* dummy 00094 , void ** obj_data ) 00095 { 00096 struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00097 #ifdef RTOp_DEBUG 00098 assert( *obj_data ); 00099 #endif 00100 state = (struct RTOp_TOp_set_sub_vector_state_t*)*obj_data; 00101 if( state->owns_mem ) { 00102 free( (void*)state->sub_vec.values ); 00103 free( (void*)state->sub_vec.indices ); 00104 } 00105 free( *obj_data ); 00106 *obj_data = NULL; 00107 return 0; 00108 } 00109 00110 static int extract_op_state( 00111 const struct RTOp_obj_type_vtbl_t* vtbl 00112 ,const void * dummy 00113 ,void * obj_data 00114 ,int num_values 00115 ,RTOp_value_type value_data[] 00116 ,int num_indexes 00117 ,RTOp_index_type index_data[] 00118 ,int num_chars 00119 ,RTOp_char_type char_data[] 00120 ) 00121 { 00122 const struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00123 register RTOp_index_type k, j; 00124 #ifdef RTOp_DEBUG 00125 assert( obj_data ); 00126 #endif 00127 state = (const struct RTOp_TOp_set_sub_vector_state_t*)obj_data; 00128 #ifdef RTOp_DEBUG 00129 assert( num_values == state->sub_vec.sub_nz ); 00130 assert( num_indexes == 8 + (state->sub_vec.indices ? state->sub_vec.sub_nz : 0 ) ); 00131 assert( num_chars == 0 ); 00132 assert( value_data ); 00133 assert( index_data ); 00134 #endif 00135 for( k = 0; k < state->sub_vec.sub_nz; ++k ) 00136 value_data[k] = state->sub_vec.values[k]; 00137 index_data[k=0] = state->sub_vec.global_offset; 00138 index_data[++k] = state->sub_vec.sub_dim; 00139 index_data[++k] = state->sub_vec.sub_nz; 00140 index_data[++k] = state->sub_vec.values_stride; 00141 index_data[++k] = state->sub_vec.indices_stride; 00142 index_data[++k] = state->sub_vec.local_offset; 00143 index_data[++k] = state->sub_vec.is_sorted; 00144 index_data[++k] = state->owns_mem; 00145 if( state->sub_vec.indices ) { 00146 for( j = 0; j < state->sub_vec.sub_nz; ++j ) 00147 index_data[++k] = state->sub_vec.indices[j]; 00148 } 00149 return 0; 00150 } 00151 00152 static int load_op_state( 00153 const struct RTOp_obj_type_vtbl_t* vtbl 00154 ,const void * dummy 00155 ,int num_values 00156 ,const RTOp_value_type value_data[] 00157 ,int num_indexes 00158 ,const RTOp_index_type index_data[] 00159 ,int num_chars 00160 ,const RTOp_char_type char_data[] 00161 ,void ** obj_data 00162 ) 00163 { 00164 struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00165 register RTOp_index_type k, j; 00166 RTOp_value_type *values = NULL; 00167 /* Allocate the operator object's state data if it has not been already */ 00168 if( *obj_data == NULL ) { 00169 *obj_data = (void*)malloc(sizeof(struct RTOp_TOp_set_sub_vector_state_t)); 00170 state = (struct RTOp_TOp_set_sub_vector_state_t*)*obj_data; 00171 RTOp_sparse_sub_vector_null( &state->sub_vec ); 00172 state->owns_mem = 0; 00173 } 00174 /* Get the operator object's state data */ 00175 #ifdef RTOp_DEBUG 00176 assert( *obj_data ); 00177 #endif 00178 state = (struct RTOp_TOp_set_sub_vector_state_t*)*obj_data; 00179 #ifdef RTOp_DEBUG 00180 if( num_indexes > 8 ) assert( num_values == num_indexes - 8 ); 00181 #endif 00182 /* Reallocate storage if we have to */ 00183 if( num_values != state->sub_vec.sub_nz || !state->owns_mem ) { 00184 /* Delete current storage if owned */ 00185 if( state->owns_mem ) { 00186 free( (RTOp_value_type*)state->sub_vec.values ); 00187 free( (RTOp_index_type*)state->sub_vec.indices ); 00188 } 00189 /* We need to reallocate storage for values[] and perhaps */ 00190 state->sub_vec.values = (RTOp_value_type*)malloc(num_values*sizeof(RTOp_value_type)); 00191 if( num_indexes > 8 ) 00192 state->sub_vec.indices = (RTOp_index_type*)malloc(num_values*sizeof(RTOp_index_type)); 00193 state->owns_mem = 1; 00194 } 00195 /* Set the internal state! */ 00196 #ifdef RTOp_DEBUG 00197 assert( num_chars == 0 ); 00198 assert( value_data ); 00199 assert( index_data ); 00200 #endif 00201 for( values = (RTOp_value_type*)state->sub_vec.values, k = 0; k < num_values; ++k ) 00202 *values++ = value_data[k]; 00203 state->sub_vec.global_offset = index_data[k=0]; 00204 state->sub_vec.sub_dim = index_data[++k]; 00205 state->sub_vec.sub_nz = index_data[++k]; 00206 state->sub_vec.values_stride = index_data[++k]; 00207 state->sub_vec.indices_stride = index_data[++k]; 00208 state->sub_vec.local_offset = index_data[++k]; 00209 state->sub_vec.is_sorted = index_data[++k]; 00210 state->owns_mem = index_data[++k]; 00211 if( num_indexes > 8 ) { 00212 for( j = 0; j < num_values; ++j ) 00213 ((RTOp_index_type*)state->sub_vec.indices)[j] = index_data[++k]; 00214 } 00215 return 0; 00216 } 00217 00218 static struct RTOp_obj_type_vtbl_t instance_obj_vtbl = 00219 { 00220 get_op_type_num_entries 00221 ,op_create 00222 ,NULL 00223 ,op_free 00224 ,extract_op_state 00225 ,load_op_state 00226 }; 00227 00228 /* Implementation functions */ 00229 00230 static int RTOp_TOp_set_sub_vector_apply_op( 00231 const struct RTOp_RTOp_vtbl_t* vtbl, const void* obj_data 00232 , const int num_vecs, const struct RTOp_SubVector vecs[] 00233 , const int num_targ_vecs, const struct RTOp_MutableSubVector targ_vecs[] 00234 , RTOp_ReductTarget targ_obj ) 00235 { 00236 const struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00237 RTOp_index_type v_global_offset; 00238 RTOp_index_type v_sub_dim; 00239 RTOp_index_type v_sub_nz; 00240 const RTOp_value_type *v_val; 00241 ptrdiff_t v_val_s; 00242 const RTOp_index_type *v_ind; 00243 ptrdiff_t v_ind_s; 00244 ptrdiff_t v_l_off; 00245 int v_sorted; 00246 RTOp_index_type z_global_offset; 00247 RTOp_index_type z_sub_dim; 00248 RTOp_value_type *z_val; 00249 ptrdiff_t z_val_s; 00250 register RTOp_index_type k, i; 00251 RTOp_index_type num_overlap; 00252 00253 /* */ 00254 /* Validate the input */ 00255 /* */ 00256 if( num_vecs != 0 ) 00257 return RTOp_ERR_INVALID_NUM_VECS; 00258 if( num_targ_vecs != 1 ) 00259 return RTOp_ERR_INVALID_NUM_TARG_VECS; 00260 assert(targ_vecs); 00261 assert(targ_obj == RTOp_REDUCT_OBJ_NULL); 00262 00263 /* */ 00264 /* Get pointers to data */ 00265 /* */ 00266 00267 /* Get the sub-vector we are reading from */ 00268 assert(obj_data); 00269 state = (const struct RTOp_TOp_set_sub_vector_state_t*)obj_data; 00270 00271 /* v (the vector to read from) */ 00272 v_global_offset = state->sub_vec.global_offset; 00273 v_sub_dim = state->sub_vec.sub_dim; 00274 v_sub_nz = state->sub_vec.sub_nz; 00275 v_val = state->sub_vec.values; 00276 v_val_s = state->sub_vec.values_stride; 00277 v_ind = state->sub_vec.indices; 00278 v_ind_s = state->sub_vec.indices_stride; 00279 v_l_off = state->sub_vec.local_offset; 00280 v_sorted = state->sub_vec.is_sorted; 00281 00282 /* z (the vector to set) */ 00283 z_global_offset = targ_vecs[0].global_offset; 00284 z_sub_dim = targ_vecs[0].sub_dim; 00285 z_val = targ_vecs[0].values; 00286 z_val_s = targ_vecs[0].values_stride; 00287 00288 /* */ 00289 /* Set part of the sub-vector for this chunk. */ 00290 /* */ 00291 00292 if( v_global_offset + v_sub_dim < z_global_offset + 1 00293 || z_global_offset + z_sub_dim < v_global_offset + 1 ) 00294 return 0; /* The sub-vector that we are setting does not overlap with this vector chunk! */ 00295 00296 if( v_sub_nz == 0 ) 00297 return 0; /* The sparse sub-vector we are reading from is empty? */ 00298 00299 /* Get the number of elements that overlap */ 00300 if( v_global_offset <= z_global_offset ) { 00301 if( v_global_offset + v_sub_dim >= z_global_offset + z_sub_dim ) 00302 num_overlap = z_sub_dim; 00303 else 00304 num_overlap = (v_global_offset + v_sub_dim) - z_global_offset; 00305 } 00306 else { 00307 if( z_global_offset + z_sub_dim >= v_global_offset + v_sub_dim ) 00308 num_overlap = v_sub_dim; 00309 else 00310 num_overlap = (z_global_offset + z_sub_dim) - v_global_offset; 00311 } 00312 00313 /* Set the part of the sub-vector that overlaps */ 00314 if( v_ind != NULL ) { 00315 /* Sparse elements */ 00316 /* Set the overlapping elements to zero first. */ 00317 if( v_global_offset >= z_global_offset ) 00318 z_val += (v_global_offset - z_global_offset) * z_val_s; 00319 for( k = 0; k < num_overlap; ++k, z_val += z_val_s ) 00320 *z_val = 0.0; 00321 /* Now set the sparse entries */ 00322 z_val = targ_vecs[0].values; 00323 for( k = 0; k < v_sub_nz; ++k, v_val += v_val_s, v_ind += v_ind_s ) { 00324 i = v_global_offset + v_l_off + (*v_ind); 00325 if( z_global_offset < i && i <= z_global_offset + z_sub_dim ) 00326 z_val[ z_val_s * (i - z_global_offset - 1) ] = *v_val; 00327 } 00328 /* ToDo: Implement a faster version for v sorted and eliminate the */ 00329 /* if statement in the loop. */ 00330 } 00331 else { 00332 /* Dense elemements */ 00333 if( v_global_offset <= z_global_offset ) 00334 v_val += (z_global_offset - v_global_offset) * v_val_s; 00335 else 00336 z_val += (v_global_offset - z_global_offset) * z_val_s; 00337 for( k = 0; k < num_overlap; ++k, v_val += v_val_s, z_val += z_val_s ) 00338 *z_val = *v_val; 00339 } 00340 00341 return 0; /* success? */ 00342 } 00343 00344 /* Public interface */ 00345 00346 const struct RTOp_RTOp_vtbl_t RTOp_TOp_set_sub_vector_vtbl = 00347 { 00348 &instance_obj_vtbl 00349 ,&RTOp_obj_null_vtbl /* use null type for reduction target object */ 00350 ,"RTOp_TOp_set_sub_vector" 00351 ,NULL /* use default from reduct_vtbl */ 00352 ,RTOp_TOp_set_sub_vector_apply_op 00353 ,NULL /* reduce_reduct_obj */ 00354 ,NULL /* get_reduct_op */ 00355 }; 00356 00357 int RTOp_TOp_set_sub_vector_construct( 00358 const struct RTOp_SparseSubVector* sub_vec, struct RTOp_RTOp* op ) 00359 { 00360 #ifdef RTOp_DEBUG 00361 assert(sub_vec); 00362 assert(op); 00363 #endif 00364 op->vtbl = &RTOp_TOp_set_sub_vector_vtbl; 00365 op->vtbl->obj_data_vtbl->obj_create(NULL,NULL,&op->obj_data); 00366 return RTOp_TOp_set_sub_vector_set_sub_vec(sub_vec,op); 00367 } 00368 00369 int RTOp_TOp_set_sub_vector_set_sub_vec( 00370 const struct RTOp_SparseSubVector* sub_vec, struct RTOp_RTOp* op ) 00371 { 00372 struct RTOp_TOp_set_sub_vector_state_t *state = NULL; 00373 #ifdef RTOp_DEBUG 00374 assert( op->obj_data ); 00375 #endif 00376 state = (struct RTOp_TOp_set_sub_vector_state_t*)op->obj_data; 00377 if( state->owns_mem ) { 00378 free( (void*)state->sub_vec.values ); 00379 free( (void*)state->sub_vec.indices ); 00380 } 00381 state->sub_vec = *sub_vec; /* We do not own the arrays values[] and indices[] */ 00382 state->owns_mem = 0; 00383 return 0; 00384 } 00385 00386 int RTOp_TOp_set_sub_vector_destroy( struct RTOp_RTOp* op ) 00387 { 00388 op_free(NULL,NULL,&op->obj_data); 00389 op->vtbl = NULL; 00390 return 0; 00391 }
1.7.6.1