MOOCHO (Single Doxygen Collection) Version of the Day
RTOp_TOp_set_sub_vector.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines