RTOpPack: Extra C/C++ Code for Vector Reduction/Transformation Operators Version of the Day
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 #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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends