RTOp_ROp_get_sub_vector.c

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

Generated on Thu Sep 18 12:33:38 2008 for RTOpPack: Extra C/C++ Code for Vector Reduction/Transformation Operators by doxygen 1.3.9.1