Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

tree_skeletons.tpp

Go to the documentation of this file.
00001 /***
00002  * Copyright (c) 2005, SkeTo Project
00003  * All rights reserved.
00004  */
00013 #ifdef __TREE_SKELETONS_H__
00014 #ifndef __TREE_SKELETONS_TPP__
00015 #define __TREE_SKELETONS_TPP__
00016 
00017 #include <iostream>
00018 #include <fstream>
00019 #include <cstdlib>
00020 #include <assert.h>
00021 
00022 #include <mpi.h>
00023 
00024 enum {
00025   TAG_REDUCE,
00026   TAG_UACC,
00027   TAG_DACC,
00028   TAG_DISTRIBUTE,
00029   TAG_DISTRIBUTE2,
00030   TAG_GATHER,
00031   TAG_SHIFTP,
00032   TAG_SHIFTL,
00033   TAG_SHIFTR,
00034 };
00035 
00036 /* public, static */
00037 template< typename K1, typename K2 >
00038 inline dist_tree< typename K1::result_type > *
00039 tree_skeletons::map( const K1 &k1,
00040              const K2 &k2,
00041              dist_tree< typename K1::argument_type > *t )
00042 {
00043   return map_adapter<
00044     typename K1::result_type,
00045     typename K1::argument_type,
00046     K1, K2 >( k1, k2, t );
00047 }
00048 
00049 /* private, static */
00050 template< typename C, typename A, typename K1, typename K2 >
00051 inline dist_tree< C >*
00052 tree_skeletons::map_adapter( const K1 &k1,
00053                  const K2 &k2,
00054                  dist_tree< A > *t )
00055 {
00056   dist_tree< C >* ret_tree = new dist_tree< C >( t );
00057   if ( !t->local_root ) return ret_tree;
00058 
00059   ret_tree->local_root = map_rec< C, A, K1, K2 >( k1, k2, t->local_root );
00060   return ret_tree;
00061 }
00062 
00063 /* private, static */
00064 template< typename C, typename A, typename K1, typename K2 >
00065 node< C >*
00066 tree_skeletons::map_rec( const K1 &k1,
00067              const K2 &k2,
00068              node< A >* root )
00069 {
00070   node< C >* ret;
00071   if ( !root->isLeaf( ) ) {
00072     // Normal internal node
00073     ret = new node< C >( k2( root->value ), node< C >::NORMAL );
00074     ret->left  = map_rec< C, A, K1, K2 >( k1, k2, root->left );
00075     ret->left->parent = ret;
00076     
00077     ret->right = map_rec< C, A, K1, K2 >( k1, k2, root->right );
00078     ret->right->parent = ret;
00079 
00080   } else if ( root->nodetype == node< A >::NORMAL ) {
00081     // Normal leaf
00082     ret = new node< C >( k1( root->value ), node< C >::NORMAL );
00083 
00084   } else {
00085     // Cut Node
00086     ret = new node< C >( k2( root->value ), node< C >::CUTNODE );
00087   }
00088   return ret;
00089 }
00090 
00091 /* public, static */
00092 template< typename K1, typename K2 >
00093 inline dist_tree< typename K1::result_type > *
00094 tree_skeletons::zipwith( const K1 &k1, 
00095              const K2 &k2,
00096              const dist_tree< typename K1::first_argument_type >* at, 
00097              const dist_tree< typename K1::second_argument_type >* bt )
00098 {
00099   return zipwith_adapter<
00100     typename K1::result_type,
00101     typename K1::first_argument_type, 
00102     typename K1::second_argument_type,
00103     K1, K2 >( k1, k2, at, bt );
00104 }
00105 
00106 /* private, static */
00107 template< typename E, typename A, typename C, typename K1, typename K2 >
00108 dist_tree< E >*
00109 tree_skeletons::zipwith_adapter( const K1 &k1, 
00110              const K2 &k2,
00111              const dist_tree< A >* at, 
00112              const dist_tree< C >* bt )
00113 {
00114   dist_tree< E >* ret_tree = new dist_tree< E >( at );
00115   if ( !at->local_root ) return ret_tree;
00116 
00117   ret_tree->local_root
00118     = zipwith_rec< E, A, C, K1, K2 >( k1, k2, at->local_root, bt->local_root );
00119   return ret_tree;
00120 }
00121 
00122 /* private, static */
00123 template< typename E, typename A, typename C, typename K1, typename K2 >
00124 node< E >*
00125 tree_skeletons::zipwith_rec( const K1 &k1, 
00126                  const K2 &k2,
00127                  const node< A >* root_a,
00128                  const node< C >* root_b )
00129 {
00130   node< E >* ret_node;
00131   if ( !root_a->isLeaf( ) ) {
00132     // Normal internal node
00133     ret_node = new node< E >( k2( root_a->value, root_b->value ),
00134                   node< E >::NORMAL );
00135     ret_node->left
00136       = zipwith_rec< E, A, C, K1, K2 >( k1, k2, root_a->left,  root_b->left );
00137     ret_node->left->parent = ret_node;
00138     ret_node->right
00139       = zipwith_rec< E, A, C, K1, K2 >( k1, k2, root_a->right, root_b->right );
00140     ret_node->right->parent = ret_node;
00141     
00142   } else if ( root_a->nodetype == node< A >::NORMAL ) {
00143     // Normal leaf
00144     ret_node = new node< E >( k1( root_a->value, root_b->value ),
00145                   node< E >::NORMAL );
00146   } else {
00147     // Cut Node
00148     ret_node = new node< E >( k2( root_a->value, root_b->value ),
00149                   node< E >::CUTNODE );
00150   }
00151   return ret_node;
00152 }
00153 
00154 /* public, static */
00155 template< typename K1, typename K2,
00156       typename PSI, typename PHIL, typename PHIR, typename GG >
00157 inline typename K1::result_type
00158 tree_skeletons::reduce( const K1 &k1, 
00159             const K2 &k2, 
00160             const PSI &psi,
00161             const PHIL &phiL,
00162             const PHIR &phiR,
00163             const GG &G,
00164             const dist_tree< typename K1::argument_type >* t )
00165 {
00166   return reduce_adapter<
00167     typename K1::result_type,
00168     typename PSI::result_type,
00169     typename K1::argument_type,
00170     K1, K2, PSI, PHIL, PHIR, GG >( k1, k2, psi, phiL, phiR, G, t );
00171 }
00172 
00173 /* private, static */
00174 template< typename C, typename D, typename A, typename K1, typename K2,
00175       typename PSI, typename PHIL, typename PHIR, typename GG >
00176 C
00177 tree_skeletons::reduce_adapter( const K1 &k1, 
00178                 const K2 &k2, 
00179                 const PSI &psi,
00180                 const PHIL &phiL,
00181                 const PHIR &phiR,
00182                 const GG &G,
00183                 const dist_tree< A >* t )
00184 {
00185   //  if ( !t->local_root ) { C dummy; return dummy; }
00186   if ( !t->local_root ) { return static_cast< C >( false ); }
00187 
00188   // local_reduce
00189   reduce_result_t< C, D > local_result
00190     = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00191     ( k1, k2, psi, phiL, phiR, t->local_root );
00192 
00193   // global_reduce
00194   return reduce_global< C, D, A, GG >( G, local_result, t );
00195 }
00196 
00197 /* private, static */
00198 template< typename C, typename D, typename A, typename K1, typename K2,
00199       typename PSI, typename PHIL, typename PHIR >
00200 tree_skeletons::reduce_result_t< C, D >
00201 tree_skeletons::reduce_local_rec( const K1 &k1,
00202                   const K2 &k2,
00203                   const PSI &psi,
00204                   const PHIL &phiL,
00205                   const PHIR &phiR, 
00206                   const node< A >* root )
00207 {
00208   reduce_result_t< C, D > ret;
00209   if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00210     // Normal Leaf
00211     ret.resulttype = reduce_result_t< C, D >::TYPEC;
00212     ret.valC = k1( root->value );
00213   } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
00214     // CutNode
00215     ret.resulttype = reduce_result_t< C, D >::TYPED;
00216     ret.valD = psi( root->value );
00217   } else {
00218     // Normal Internal Node
00219     reduce_result_t< C, D > retl
00220       = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00221       ( k1, k2, psi, phiL, phiR, root->left );
00222     reduce_result_t< C, D > retr
00223       = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00224       ( k1, k2, psi, phiL, phiR, root->right );
00225 
00226     if ( retl.resulttype == reduce_result_t< C, D >::TYPEC &&
00227      retr.resulttype == reduce_result_t< C, D >::TYPEC ) {
00228       // Simple Reduction
00229       ret.resulttype = reduce_result_t< C, D >::TYPEC;
00230       ret.valC = k2( root->value, retl.valC, retr.valC );
00231 
00232     } else if ( retl.resulttype == reduce_result_t< C, D >::TYPED &&
00233         retr.resulttype == reduce_result_t< C, D >::TYPEC ) {
00234       // ContractR
00235       ret.resulttype = reduce_result_t< C, D >::TYPED;
00236       ret.valD = phiR( psi( root->value ), retr.valC, retl.valD );
00237 
00238     } else if ( retl.resulttype == reduce_result_t< C, D >::TYPEC &&
00239         retr.resulttype == reduce_result_t< C, D >::TYPED ) {
00240       // ContractL
00241       ret.resulttype = reduce_result_t< C, D >::TYPED;
00242       ret.valD = phiL( psi( root->value ), retl.valC, retr.valD );
00243 
00244     } else {
00245       // Something wrong occur
00246       assert( false );
00247     }
00248   }
00249   return ret;
00250 }
00251 
00252 /* private, static */
00253 template< typename C, typename D, typename A, typename GG >
00254 C
00255 tree_skeletons::reduce_global( const GG &G,
00256                    const tree_skeletons::reduce_result_t< C, D > &local_result,
00257                    const dist_tree< A > *t )
00258 {
00259   C result;
00260 
00261   if ( t->global_node->isLeaf( ) ) {
00262     result = local_result.valC;
00263   } else {
00264     C resultl, resultr;
00265 
00266     MPI_Request req1, req2;
00267     MPI_Irecv( &resultl, sizeof( C ), MPI_BYTE,
00268            t->proc_leftchild, TAG_REDUCE, MPI_COMM_WORLD, &req1 );
00269     MPI_Irecv( &resultr, sizeof( C ), MPI_BYTE,
00270            t->proc_rightchild, TAG_REDUCE, MPI_COMM_WORLD, &req2 );
00271     MPI_Wait( &req1, MPI_STATUS_IGNORE );
00272     MPI_Wait( &req2, MPI_STATUS_IGNORE );
00273 
00274     result = G( local_result.valD, resultl, resultr );
00275   }
00276 
00277   if ( skeleton::rank != 0 ) {
00278     MPI_Request req;
00279     MPI_Isend( &result, sizeof( C ), MPI_BYTE,
00280            t->proc_parent, TAG_REDUCE, MPI_COMM_WORLD, &req );
00281     MPI_Wait( &req, MPI_STATUS_IGNORE );
00282   }
00283 
00284   return result;
00285 }
00286 
00287 /* public, static */
00288 template< typename K1, typename K2,
00289       typename PSI, typename PHIL, typename PHIR, typename GG >
00290 inline dist_tree< typename K1::result_type > *
00291 tree_skeletons::uAcc( const K1 &k1,
00292               const K2 &k2,
00293               const PSI &psi,
00294               const PHIL &phiL,
00295               const PHIR &phiR,
00296               const GG &G,
00297               const dist_tree< typename K1::argument_type > *t )
00298 {
00299   return uAcc_adapter<
00300     typename K1::result_type,
00301     typename PSI::result_type,
00302     typename K1::argument_type,
00303     K1, K2, PSI, PHIL, PHIR, GG >( k1, k2, psi, phiL, phiR, G, t );
00304 }
00305 
00306 /* private, static */
00307 template< typename C, typename D, typename A, typename K1, typename K2,
00308         typename PSI, typename PHIL, typename PHIR, typename GG >
00309 dist_tree< C >*
00310 tree_skeletons::uAcc_adapter( const K1 &k1,
00311                   const K2 &k2,
00312                   const PSI &psi,
00313                   const PHIL &phiL,
00314                   const PHIR &phiR,
00315                   const GG &G,
00316                   const dist_tree< A > *t )
00317 {
00318   dist_tree< C >* ret_tree = new dist_tree< C >( t );
00319   if ( !t->local_root ) return ret_tree;
00320   
00321   // local reduce
00322   tree_skeletons::reduce_result_t< C, D > local_result
00323     = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00324     ( k1, k2, psi, phiL, phiR, t->local_root );
00325   
00326   // global uAcc
00327   C vall, valr;
00328   uAcc_global_uAcc< C, D, A, GG >( G, local_result, &vall, &valr, t );
00329 
00330   // local uAcc
00331   ret_tree->local_root
00332     = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00333     ( k1, k2, vall, valr, t->local_root );
00334 
00335   return ret_tree;
00336 }
00337 
00338 /* private, static */
00339 template< typename C, typename D, typename A, typename GG >
00340 void
00341 tree_skeletons::uAcc_global_uAcc( const GG &G, 
00342                   const tree_skeletons::reduce_result_t< C, D > &local_result,
00343                   C *vall,
00344                   C *valr,
00345                   const dist_tree< A > *t )
00346 {
00347   C result;
00348   
00349   if ( t->global_node->isLeaf( ) ) {
00350     result = local_result.valC;
00351   } else {
00352 
00353     MPI_Request req1, req2;
00354     MPI_Irecv( vall, sizeof( C ), MPI_BYTE,
00355            t->proc_leftchild, TAG_UACC, MPI_COMM_WORLD, &req1 );
00356     MPI_Irecv( valr, sizeof( C ), MPI_BYTE,
00357            t->proc_rightchild, TAG_UACC, MPI_COMM_WORLD, &req2 );
00358     MPI_Wait( &req1, MPI_STATUS_IGNORE );
00359     MPI_Wait( &req2, MPI_STATUS_IGNORE );
00360 
00361     result = G( local_result.valD, *vall, *valr );
00362   }
00363   
00364   if ( skeleton::rank != 0 ) {
00365     MPI_Request req;
00366     MPI_Isend( &result, sizeof( C ), MPI_BYTE,
00367            t->proc_parent, TAG_UACC, MPI_COMM_WORLD, &req );
00368     MPI_Wait( &req, MPI_STATUS_IGNORE );
00369   }
00370 }
00371 
00372 /* private, static */
00373 template< typename C, typename D, typename A, typename K1, typename K2 >
00374 node< C >*
00375 tree_skeletons::uAcc_local_uAcc_rec( const K1 &k1,
00376                      const K2 &k2, 
00377                      const C& left_result,
00378                      const C& right_result,
00379                      const node< A > *root )
00380 {
00381   node< C > *ret_node;
00382 
00383   if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00384     // Normal Leaf
00385     ret_node = new node< C >( k1( root->value ), node< C >::NORMAL );
00386   } else if ( root->nodetype == node< A >::CUTNODE ) {
00387     // CutNode
00388     ret_node = new node< C >( k2( root->value, left_result, right_result ),
00389                   node< C >::CUTNODE );
00390   } else {
00391     // Normal Internal Node
00392     node< C >* left_node
00393       = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00394       ( k1, k2, left_result, right_result, root->left );
00395     node< C >* right_node
00396       = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00397       ( k1, k2, left_result, right_result, root->right );
00398 
00399     ret_node
00400       = new node< C >( k2( root->value, left_node->value, right_node->value ),
00401                node< C >::NORMAL );
00402     ret_node->left  = left_node;  ret_node->left->parent  = ret_node;
00403     ret_node->right = right_node; ret_node->right->parent = ret_node;
00404   }
00405 
00406   return ret_node;
00407 }
00408 
00409 /* public, static */
00410 template< typename OPLUS, typename GL, typename GR >
00411 inline dist_tree< typename OPLUS::result_type > *
00412 tree_skeletons::dAcc( const OPLUS &oplus,
00413               const typename OPLUS::result_type &e_oplus,
00414               const GL &gl,
00415               const GR &gr,
00416               const typename OPLUS::result_type &c,
00417               const dist_tree< typename GL::argument_type >* t )
00418 {
00419   return dAcc_adapter<
00420     typename OPLUS::result_type,
00421     typename GL::argument_type,
00422     OPLUS, GL, GR >( oplus, e_oplus, gl, gr, c, t );
00423 }
00424 
00425 /* private, static */
00426 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00427 dist_tree< C >*
00428 tree_skeletons::dAcc_adapter( const OPLUS &oplus,
00429                   const C &e_oplus,
00430                   const GL &gl,
00431                   const GR &gr,
00432                   const C &c,
00433                   const dist_tree< A >* t )
00434 {
00435   dist_tree< C >* ret_tree = new dist_tree< C >( t );
00436   if ( !t->local_root ) return ret_tree;
00437   
00438   // local dAcc on path
00439   C c_to_left = e_oplus, c_to_right = e_oplus;
00440   dAcc_local_path_rec< C, A, OPLUS, GL, GR >
00441     ( oplus, gl, gr, t->local_root, &c_to_left, &c_to_right );
00442   
00443   // global dAcc
00444   C c_from_parent
00445     = dAcc_global_dAcc< C, A, OPLUS >( oplus, c, c_to_left, c_to_right, t );
00446   
00447   // local dAcc
00448   ret_tree->local_root
00449     = dAcc_local_dAcc_rec< C, A, OPLUS, GL, GR >
00450     ( oplus, gl, gr, c_from_parent, t->local_root );
00451 
00452   return ret_tree;
00453 }
00454 
00455 /* private, static */
00456 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00457 bool
00458 tree_skeletons::dAcc_local_path_rec( const OPLUS &oplus,
00459                      const GL &gl,
00460                      const GR &gr,
00461                      const node< A >* root,
00462                      C *c_to_left,
00463                      C *c_to_right )
00464 {
00465   if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00466     // Normal Leaf
00467     return false;
00468   } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
00469     // CutNode
00470     *c_to_left  = gl( root->value );
00471     *c_to_right = gr( root->value );
00472     return true;
00473   } else {
00474     // Normal Internal Node
00475     if ( dAcc_local_path_rec( oplus, gl, gr, root->left,
00476                   c_to_left, c_to_right ) ) {
00477       *c_to_left  = oplus( gl( root->value ), *c_to_left  );
00478       *c_to_right = oplus( gl( root->value ), *c_to_right );
00479       return true;
00480     }
00481     if ( dAcc_local_path_rec( oplus, gl, gr, root->right,
00482                   c_to_left, c_to_right ) ) {
00483       *c_to_left  = oplus( gr( root->value ), *c_to_left  );
00484       *c_to_right = oplus( gr( root->value ), *c_to_right );
00485       return true;
00486     }
00487     return false;
00488   }
00489 }
00490 
00491 /* private, static */
00492 template< typename C, typename A, typename OPLUS >
00493 C
00494 tree_skeletons::dAcc_global_dAcc( const OPLUS &oplus,
00495                   const C &c,
00496                   const C &c_to_left,
00497                   const C &c_to_right,
00498                   const dist_tree< A >* t )
00499 {
00500   C c_from_parent;
00501   if ( skeleton::rank == 0 ) {
00502     c_from_parent = c;
00503   } else {
00504     MPI_Request req;
00505     MPI_Irecv( &c_from_parent, sizeof( C ), MPI_BYTE,
00506            t->proc_parent, TAG_DACC, MPI_COMM_WORLD, &req );
00507     MPI_Wait( &req, MPI_STATUS_IGNORE );
00508   }
00509 
00510   if ( t->global_node->isLeaf( ) ) {
00511   } else {
00512     C sent_c_to_left  = oplus( c_from_parent, c_to_left );
00513     C sent_c_to_right = oplus( c_from_parent, c_to_right );
00514 
00515     MPI_Request req1, req2;
00516     MPI_Isend( &sent_c_to_left, sizeof( C ), MPI_BYTE,
00517            t->proc_leftchild, TAG_DACC, MPI_COMM_WORLD, &req1 );
00518     MPI_Isend( &sent_c_to_right, sizeof( C ), MPI_BYTE,
00519            t->proc_rightchild, TAG_DACC, MPI_COMM_WORLD, &req2 );
00520     MPI_Wait( &req1, MPI_STATUS_IGNORE );
00521     MPI_Wait( &req2, MPI_STATUS_IGNORE );
00522 
00523   }    
00524 
00525   return c_from_parent;
00526 }
00527 
00528 /* private, static */
00529 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00530 node< C >*
00531 tree_skeletons::dAcc_local_dAcc_rec( const OPLUS &oplus,
00532                      const GL &gl,
00533                      const GR &gr, 
00534                      const C &c,
00535                      const node< A >* root )
00536 {
00537   node< C >* ret_node
00538     = new node< C >( c, ( root->nodetype == node< A >::NORMAL ) ? node< C >::NORMAL : node< C >::CUTNODE );
00539 
00540   if ( !root->isLeaf( ) ) {
00541     ret_node->left = dAcc_local_dAcc_rec( oplus, gl, gr,
00542                       oplus( c, gl( root->value ) ),
00543                       root->left );
00544     ret_node->left->parent = ret_node;
00545     ret_node->right = dAcc_local_dAcc_rec( oplus, gl, gr,
00546                       oplus( c, gr( root->value ) ),
00547                       root->right );
00548     ret_node->right->parent = ret_node;
00549   }
00550 
00551   return ret_node;
00552 }
00553 
00554 /* public, static */
00555 template< typename A >
00556 dist_tree< A >*
00557 tree_skeletons::distribute2( const node< A >* s_tree )
00558 {
00559   dist_tree< A >* d_tree = new dist_tree< A >( );
00560 
00561   if ( skeleton::rank == 0 ) {
00562     // master process
00563     // assert( tree_util::check_perfect_binary_tree( s_tree ) );
00564 
00565     node< tree_skeletons::size_and_critical< A > >* global_root;
00566     int np;
00567     int size;
00568     
00569     if ( !compute_size_and_get_global_tree( s_tree, skeleton::procs, &global_root, &np, &size ) ) {
00570       std::exit( 1 );
00571     }
00572 
00573     // (1) number of blocks
00574     MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00575 
00576     // (2) global_trees
00577     int *localsizes = new int[ np ];
00578     const node< A >** subroots = new const node< A >*[ np ];
00579     const node< A >** subcrits = new const node< A >*[ np ];
00580     {
00581       int *flags = new int[ np ];
00582       serialize_global_structure( s_tree, global_root, size, 
00583                   flags, localsizes, subroots, subcrits );
00584 
00585       MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00586       MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00587 
00588       d_tree->read_from_file_create_global_tree( flags, localsizes );
00589 
00590       delete [] flags;
00591     }
00592 
00593     // obtain maximum local-size to allocate memory once.
00594     int max_size = 0;
00595     for ( int p = 0; p < np; p++ ) {
00596       if ( max_size < localsizes[ p ] ) max_size = localsizes[ p ];
00597     }
00598 
00599     int *flags = new int[ max_size ];
00600     A *values = new A[ max_size ];
00601     
00602     // (3-1) subtrees ( other process but root )
00603     for ( int p = 1; p < np; p++ ) {
00604       get_local_tree( subroots[ p ], subcrits[ p ], flags, values );
00605 
00606       MPI_Request req1, req2;
00607       MPI_Isend( flags, localsizes[ p ], MPI_INT,
00608          p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00609       MPI_Isend( values, localsizes[ p ] * sizeof( A ), MPI_BYTE,
00610          p, TAG_DISTRIBUTE2, MPI_COMM_WORLD, &req2 );
00611       MPI_Wait( &req1, MPI_STATUS_IGNORE );
00612       MPI_Wait( &req2, MPI_STATUS_IGNORE );
00613     }
00614 
00615     // (3-2) subtrees ( root process )
00616     {
00617       get_local_tree( subroots[ 0 ], subcrits[ 0 ], flags, values );
00618       d_tree->read_from_file_create_subtree( flags, values );
00619     }
00620 
00621     delete [] values;
00622     delete [] flags;
00623   }
00624   else {
00625     // slave process
00626     // (1) number of blocks
00627     int np;
00628     MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00629 
00630     // (2) global trees
00631     {
00632       int *localsizes = new int[ np ];
00633       int *flags = new int[ np ];
00634 
00635       MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00636       MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00637 
00638       d_tree->read_from_file_create_global_tree( flags, localsizes );
00639 
00640       delete[] flags;
00641       delete[] localsizes;
00642     }
00643 
00644     // (3-2) subtrees
00645     if ( skeleton::rank < np ) {
00646       const int localsize = d_tree->global_node->value;
00647       int *flags = new int[ localsize ];
00648       A *values = new A[ localsize ];
00649 
00650       MPI_Request req1, req2;
00651       MPI_Irecv( flags, localsize, MPI_INT,
00652          0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00653       MPI_Irecv( values, localsize * sizeof( A ), MPI_BYTE,
00654          0, TAG_DISTRIBUTE2, MPI_COMM_WORLD, &req2 );
00655       MPI_Wait( &req1, MPI_STATUS_IGNORE );
00656       MPI_Wait( &req2, MPI_STATUS_IGNORE );
00657 
00658       d_tree->read_from_file_create_subtree( flags, values );
00659 
00660       delete[] values;
00661       delete[] flags;
00662     }
00663   }
00664 
00665   return d_tree;
00666 }
00667 
00668 template< typename A >
00669 int temp_get_size_rec( const node< A >* tree )
00670 {
00671   if ( tree == NULL ) return 0;
00672 
00673   int size_left, size_right;
00674   size_left  = temp_get_size_rec( tree->left );
00675   size_right = temp_get_size_rec( tree->right );
00676 
00677   return 1 + size_left + size_right;
00678 }
00679 
00680 template< typename A >
00681 bool
00682 tree_skeletons::compute_size_and_get_global_tree( const node< A >* tree,
00683                           int nprocs,
00684                           node< size_and_critical< A > >** global_root,
00685                           int *np,
00686                           int *size )
00687 {
00688   // get size;
00689   *size = tree_util::get_size_rec( tree );
00690   int m = 2 * *size / ( nprocs / 2 + 1 );
00691 
00692   // ( critical_subroot, size ) = get_global_tree_rec( tree, m );
00693   node< size_and_critical< A > >* global_tree;
00694   int s;
00695   get_global_tree_rec( &global_tree, &s, tree, m );
00696 
00697   *np = temp_get_size_rec( global_tree ) * 2 + 1;
00698   assert( *np <= nprocs );
00699 
00700   *global_root = global_tree;
00701 
00702   return true;
00703 }
00704 
00705 template< typename A >
00706 void
00707 tree_skeletons::get_global_tree_rec( node< size_and_critical< A > >** global_tree,
00708                      int *size_root,
00709                      const node< A >* tree,
00710                      int m )
00711 {
00712   if ( tree->isLeaf( ) ) {
00713     *global_tree = NULL;
00714     *size_root = 1;
00715     return;
00716   } 
00717 
00718   int size, size_left, size_right;
00719   node< size_and_critical< A > > *global_root, *global_left, *global_right;
00720 
00721   get_global_tree_rec( &global_left,  &size_left,  tree->left,  m );
00722   get_global_tree_rec( &global_right, &size_right, tree->right, m );
00723 
00724   size = 1 + size_left + size_right;
00725   if ( ( tree_util::ceil_divided_by_m( size, m )
00726      > tree_util::ceil_divided_by_m( size_left, m ) ) &&
00727        ( tree_util::ceil_divided_by_m( size, m )
00728      > tree_util::ceil_divided_by_m( size_right, m ) ) ) {
00729     global_root = new node< size_and_critical< A > >( );
00730     global_root->value.critical_node = tree;
00731     global_root->value.left_size  = size_left;
00732     global_root->value.right_size = size_right;
00733     
00734     global_root->left  = global_left;
00735     global_root->right = global_right;
00736     if ( global_root->left  ) global_root->left ->parent = global_root;
00737     if ( global_root->right ) global_root->right->parent = global_root;
00738 
00739     *global_tree = global_root;
00740     *size_root = size;
00741   } else {
00742     if ( global_left ) {
00743       *global_tree = global_left;
00744     } else {
00745       *global_tree = global_right;
00746     }
00747     *size_root = size;
00748 
00749   }
00750 }
00751 
00752 template< typename A >
00753 void
00754 tree_skeletons::serialize_global_structure( const node< A >* tree,
00755                         const node< size_and_critical< A > >* global_root,
00756                         int size,
00757                         int *flags,
00758                         int *localsizes,
00759                         const node< A >** subroots,
00760                         const node< A >** subcrits )
00761 {
00762   int index = 0;
00763   serialize_global_structure_rec( tree, global_root, size,
00764                   flags, localsizes, subroots, subcrits,
00765                   &index );
00766 }
00767 
00768 template< typename A >
00769 void
00770 tree_skeletons::serialize_global_structure_rec( const node< A >* tree,
00771                         const node< size_and_critical< A > >* global_root,
00772                         int size,
00773                         int *flags,
00774                         int *localsizes,
00775                         const node< A >** subroots,
00776                         const node< A >** subcrits,
00777                         int *index )
00778 {
00779   int cur_index = (*index)++;
00780   flags[ cur_index ] = ( global_root ? node< size_and_critical< A > >::SER_NODE :
00781              node< size_and_critical< A > >::SER_LEAF );
00782   localsizes[ cur_index ] = ( global_root ?
00783                   size - global_root->value.left_size - global_root->value.right_size :
00784                   size );
00785   subroots[ cur_index ] = tree;
00786   subcrits[ cur_index ] = ( global_root ? global_root->value.critical_node : NULL );
00787 
00788   if ( global_root ) {
00789     serialize_global_structure_rec( global_root->value.critical_node->left,
00790                     global_root->left,
00791                     global_root->value.left_size,
00792                     flags,
00793                     localsizes,
00794                     subroots,
00795                     subcrits,
00796                     index );
00797     serialize_global_structure_rec( global_root->value.critical_node->right,
00798                     global_root->right,
00799                     global_root->value.right_size,
00800                     flags,
00801                     localsizes,
00802                     subroots,
00803                     subcrits,
00804                     index );
00805   }     
00806 }
00807 
00808 template< typename A >
00809 void
00810 tree_skeletons::get_local_tree( const node< A >* root,
00811                 const node< A >* crit_node,
00812                 int *flags,
00813                 A *values )
00814 {
00815   int index = 0;
00816   get_local_tree_rec( root, crit_node, flags, values, &index );
00817 }
00818 
00819 template< typename A >
00820 void
00821 tree_skeletons::get_local_tree_rec( const node< A >* root,
00822                     const node< A >* crit_node,
00823                     int *flags,
00824                     A *values,
00825                     int *index )
00826 {
00827   int cur_index = (*index)++;
00828 
00829   values[ cur_index ] = root->value;
00830 
00831   if ( root == crit_node ) {
00832     flags[ cur_index ] = node< A >::SER_CUTNODE;
00833   } else if ( root->isLeaf( ) ) {
00834     flags[ cur_index ] = node< A >::SER_LEAF;
00835   } else {
00836     flags[ cur_index ] = node< A >::SER_NODE;
00837 
00838     get_local_tree_rec( root->left,  crit_node, flags, values, index );
00839     get_local_tree_rec( root->right, crit_node, flags, values, index );
00840   }
00841 }
00842 
00843 /* public, static */
00844 template< typename A >
00845 dist_tree< A >*
00846 tree_skeletons::distribute( const node< A >* s_tree )
00847 {
00848   dist_tree< A >* d_tree = new dist_tree< A >( );
00849 
00850   if ( skeleton::rank == 0 ) {
00851     // master process
00852     assert( tree_util::check_perfect_binary_tree( s_tree ) );
00853 
00854     node< tree_util::IntermediateVal< A > > *size_crit_tree;
00855     int np;
00856     
00857     if ( !tree_util::compute_size_and_mark_critical( s_tree, skeleton::procs, &size_crit_tree, &np ) ) {
00858       std::exit( 1 );
00859     }
00860 
00861     // (1) number of blocks
00862     MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00863 
00864     // (2) global trees
00865     int *localsizes = new int[ np ];
00866     node< tree_util::IntermediateVal< A > > **subroots
00867       = new node< tree_util::IntermediateVal< A > >*[ np ];
00868     {
00869       int *flags = new int[ np ];
00870       tree_util::get_global_tree( size_crit_tree, flags, localsizes, subroots );
00871 
00872       MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00873       MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00874 
00875       d_tree->read_from_file_create_global_tree( flags, localsizes );
00876       delete [] flags;
00877     }
00878 
00879     // (3-1) subtrees ( root process )
00880     {
00881       int *flags = new int[ localsizes[ 0 ] ];
00882       A *values = new A[ localsizes[ 0 ] ];
00883 
00884       tree_util::get_local_tree( subroots[ 0 ], flags, values );
00885       d_tree->read_from_file_create_subtree( flags, values );
00886 
00887       delete[] values;
00888       delete[] flags;
00889     }
00890     
00891     // (3-2) subtrees ( other process )
00892     for ( int p = 1; p < np; p++ ) {
00893       int *flags = new int[ localsizes[ p ] ];
00894       A *values = new A[ localsizes[ p ] ];
00895 
00896       tree_util::get_local_tree( subroots[ p ], flags, values );
00897       MPI_Request req1, req2;
00898       MPI_Isend( flags, localsizes[ p ], MPI_INT,
00899          p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00900       MPI_Isend( values, localsizes[ p ] * sizeof( A ), MPI_BYTE,
00901          p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req2 );
00902       MPI_Wait( &req1, MPI_STATUS_IGNORE );
00903       MPI_Wait( &req2, MPI_STATUS_IGNORE );
00904 
00905       delete[] values;
00906       delete[] flags;
00907     }
00908     delete [] subroots;
00909     delete [] localsizes;
00910 
00911     tree_util::free_all_tree( size_crit_tree );
00912 
00913   } else {
00914     // slave process
00915 
00916     // (1) number of blocks
00917     int np;
00918     MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00919 
00920     // (2) global trees
00921     {
00922       int *localsizes = new int[ np ];
00923       int *flags = new int[ np ];
00924 
00925       MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00926       MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00927 
00928       d_tree->read_from_file_create_global_tree( flags, localsizes );
00929 
00930       delete[] flags;
00931       delete[] localsizes;
00932     }
00933 
00934     // (3-2) subtrees
00935     if ( skeleton::rank < np ) {
00936       const int localsize = d_tree->global_node->value;
00937       int *flags = new int[ localsize ];
00938       A *values = new A[ localsize ];
00939 
00940       MPI_Request req1, req2;
00941       MPI_Irecv( flags, localsize, MPI_INT,
00942          0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00943       MPI_Irecv( values, localsize * sizeof( A ), MPI_BYTE,
00944          0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req2 );
00945       MPI_Wait( &req1, MPI_STATUS_IGNORE );
00946       MPI_Wait( &req2, MPI_STATUS_IGNORE );
00947 
00948       d_tree->read_from_file_create_subtree( flags, values );
00949 
00950       delete[] values;
00951       delete[] flags;
00952     }
00953   }
00954 
00955   return d_tree;
00956 }
00957 
00958 /* public, static */
00959 template< typename A >
00960 node< A >*
00961 tree_skeletons::gather( const dist_tree< A >* d_tree )
00962 {
00963   if ( skeleton::rank == 0 ) {
00964     node< A >* s_tree = gather_copy_tree( d_tree->local_root );
00965     
00966     int proc = 1;
00967     gather_rec( s_tree, d_tree->global_root, &proc );
00968     
00969     return s_tree;
00970   } else {
00971     if ( d_tree->global_node ) {
00972       int *flags  = new int[ d_tree->global_node->value ];
00973       A   *values = new A[ d_tree->global_node->value ];
00974       int *p_flags = flags;
00975       A   *p_values = values;
00976       
00977       tree_util::serialize_subtree( d_tree->local_root, &p_flags, &p_values );
00978       
00979       MPI_Request req1, req2;
00980       MPI_Isend( flags, d_tree->global_node->value, MPI_INT,
00981          0, TAG_GATHER, MPI_COMM_WORLD, &req1 );
00982       MPI_Isend( values, d_tree->global_node->value*sizeof( A ), MPI_BYTE,
00983          0, TAG_GATHER, MPI_COMM_WORLD, &req2 );
00984       MPI_Wait( &req1, MPI_STATUS_IGNORE );
00985       MPI_Wait( &req2, MPI_STATUS_IGNORE );
00986 
00987       delete [] values;
00988       delete [] flags;
00989     }
00990     return NULL;
00991   }
00992 }
00993 
00994 /* private, static */
00995 template< typename A >
00996 void
00997 tree_skeletons::gather_rec( node< A >* root,
00998                 const node< int >* global_root,
00999                 int *proc )
01000 {
01001   node< A >* cutnode = gather_find_cutnode( root );
01002   if ( cutnode ) {
01003     {
01004       // left sub tree
01005       int curproc = (*proc)++;
01006       int size = global_root->left->value;
01007       int *flags = new int[ size ];
01008       A *values = new A[ size ];
01009 
01010       MPI_Request req1, req2;
01011       MPI_Irecv( flags, size, MPI_INT,
01012          curproc, TAG_GATHER, MPI_COMM_WORLD, &req1 );
01013       MPI_Irecv( values, size * sizeof( A ), MPI_BYTE,
01014          curproc, TAG_GATHER, MPI_COMM_WORLD, &req2 );
01015       MPI_Wait( &req1, MPI_STATUS_IGNORE );
01016       MPI_Wait( &req2, MPI_STATUS_IGNORE );
01017       
01018       cutnode->left = gather_create_subtree( flags, values );
01019       cutnode->left->parent = cutnode;
01020 
01021       delete [] flags;
01022       delete [] values;
01023 
01024       gather_rec( cutnode->left, global_root->left, proc );
01025     }
01026     {
01027       // right sub tree
01028       int curproc = (*proc)++;
01029       int size = global_root->right->value;
01030       int *flags = new int[ size ];
01031       A *values = new A[ size ];
01032 
01033       MPI_Request req1, req2;
01034       MPI_Irecv( flags, size, MPI_INT,
01035          curproc, TAG_GATHER, MPI_COMM_WORLD, &req1 );
01036       MPI_Irecv( values, size * sizeof( A ), MPI_BYTE,
01037          curproc, TAG_GATHER, MPI_COMM_WORLD, &req2 );
01038       MPI_Wait( &req1, MPI_STATUS_IGNORE );
01039       MPI_Wait( &req2, MPI_STATUS_IGNORE );
01040 
01041       cutnode->right = gather_create_subtree( flags, values );
01042       cutnode->right->parent = cutnode;
01043 
01044       delete [] flags;
01045       delete [] values;
01046 
01047       gather_rec( cutnode->right, global_root->right, proc );
01048     }
01049   }
01050 }
01051 
01052 /* private, static */
01053 template< typename A >
01054 node< A >*
01055 tree_skeletons::gather_find_cutnode( node< A >* root )
01056 {
01057   if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
01058     return NULL;
01059   } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
01060     return root;
01061   } else {
01062     node< A > *left, *right;
01063     left = gather_find_cutnode( root->left );
01064     if ( left ) return left;
01065     right = gather_find_cutnode( root->right );
01066     if ( right ) return right;
01067     return NULL;
01068   }
01069 }
01070 
01071 /* private, static */
01072 template< typename A >
01073 node< A >*
01074 tree_skeletons::gather_create_subtree( const int* flags,
01075                        const A* values )
01076 {
01077   const int *pflags = flags;
01078   const A *pvalues = values;
01079   return dist_tree< A >::read_from_file_create_subtree_rec( &pflags, &pvalues );
01080 }
01081 
01082 /* private, static */
01083 template< typename A >
01084 node< A >*
01085 tree_skeletons::gather_copy_tree( const node< A >* root )
01086 {
01087   node< A >* ret_node = new node< A >( root->value, root->nodetype );
01088 
01089   if ( root->isLeaf( ) ) {
01090   } else {
01091     ret_node->left = gather_copy_tree( root->left );
01092     ret_node->left->parent = ret_node;
01093     ret_node->right = gather_copy_tree( root->right );
01094     ret_node->right->parent = ret_node;
01095   }
01096 
01097   return ret_node;
01098 }
01099 
01100 /* public, static */
01101 template< typename A >
01102 dist_tree< A >*
01103 tree_skeletons::shiftp( const A& rootval,
01104             const dist_tree< A >* tree )
01105 {
01106   dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01107   if ( !tree->local_root ) return ret_tree;
01108 
01109   A cut_node_val;
01110   ret_tree->local_root = shiftp_rec( tree->local_root, rootval, &cut_node_val );
01111 
01112   // send cut_node_val to child process.
01113   if ( !tree->global_node->isLeaf( ) ) {
01114     MPI_Request req1, req2;
01115     MPI_Isend( &cut_node_val, sizeof( A ), MPI_BYTE,
01116            tree->proc_leftchild, TAG_SHIFTP, MPI_COMM_WORLD, &req1 );
01117     MPI_Isend( &cut_node_val, sizeof( A ), MPI_BYTE,
01118            tree->proc_rightchild, TAG_SHIFTP, MPI_COMM_WORLD, &req2 );
01119     MPI_Wait( &req1, MPI_STATUS_IGNORE );
01120     MPI_Wait( &req2, MPI_STATUS_IGNORE );
01121   }
01122 
01123   // receive root_val from parent process
01124   A real_rootval;
01125   if ( skeleton::rank == 0 ) {
01126     real_rootval = rootval;
01127   } else {
01128     MPI_Request req;
01129     MPI_Irecv( &real_rootval, sizeof( A ), MPI_BYTE,
01130            tree->proc_parent, TAG_SHIFTP, MPI_COMM_WORLD, &req );
01131     MPI_Wait( &req, MPI_STATUS_IGNORE );
01132   }
01133   ret_tree->local_root->value = real_rootval;
01134   return ret_tree;
01135 }
01136 
01137 /* private, static */
01138 template< typename A >
01139 node< A > *
01140 tree_skeletons::shiftp_rec( const node< A >* root,
01141                 const A& root_val, 
01142                 A *cut_node_val )
01143 {
01144   node< A > *ret_node = new node< A >( root_val, root->nodetype );
01145   if ( !root->isLeaf( ) ) {
01146     ret_node->left  = shiftp_rec( root->left,  root->value, cut_node_val );
01147     ret_node->right = shiftp_rec( root->right, root->value, cut_node_val );
01148   }
01149   if ( root->nodetype == node< A >::CUTNODE ) {
01150     *cut_node_val = root->value;
01151   }
01152   return ret_node;
01153 }
01154 
01155 /* public, static */
01156 template< typename A >
01157 dist_tree< A >*
01158 tree_skeletons::shiftl( const A& leafval,
01159             const dist_tree< A >* tree )
01160 {
01161   dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01162   if ( !tree->local_root ) return ret_tree;
01163 
01164   // send value of the root node to parent process,
01165   // if the block is a left block of the parent process.
01166   if ( tree->global_node->parent &&
01167        tree->global_node->parent->left == tree->global_node ) {
01168     MPI_Request req;
01169     MPI_Isend( &(tree->local_root->value), sizeof( A ), MPI_BYTE,
01170            tree->proc_parent, TAG_SHIFTL, MPI_COMM_WORLD, &req );
01171     MPI_Wait( &req, MPI_STATUS_IGNORE );
01172   }
01173 
01174   // receive value of the cutnode from left-child process. 
01175   A left_child_root_val;
01176   if ( !tree->global_node->isLeaf( ) ) {
01177     MPI_Request req;
01178     MPI_Irecv( &left_child_root_val, sizeof( A ), MPI_BYTE,
01179            tree->proc_leftchild, TAG_SHIFTL, MPI_COMM_WORLD, &req );
01180     MPI_Wait( &req, MPI_STATUS_IGNORE );
01181   }
01182 
01183   ret_tree->local_root = shiftl_rec( tree->local_root,
01184                      leafval,
01185                      left_child_root_val );
01186   return ret_tree;
01187 }
01188 
01189 /* private, static */
01190 template< typename A >
01191 node< A >*
01192 tree_skeletons::shiftl_rec( const node< A > *root,
01193                 const A& leafval,
01194                 const A& left_child_root_val )
01195 {
01196   node< A > *ret_node;
01197   if ( !root->isLeaf( ) ) {
01198     // internal node
01199     ret_node = new node< A >( root->left->value, node< A >::NORMAL );
01200     ret_node->left  = shiftl_rec( root->left,  leafval, left_child_root_val );
01201     ret_node->right = shiftl_rec( root->right, leafval, left_child_root_val );
01202   } else if ( root->nodetype == node< A >::NORMAL ) {
01203     // normal leaf
01204     ret_node = new node< A >( leafval, node< A >::NORMAL );
01205   } else {
01206     // cutnode
01207     ret_node = new node< A >( left_child_root_val, node< A >::CUTNODE );
01208   }
01209   return ret_node;
01210 }
01211 
01212 /* public, static */
01213 template< typename A >
01214 dist_tree< A >*
01215 tree_skeletons::shiftr( const A& leafval,
01216             const dist_tree< A >* tree )
01217 {
01218   dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01219   if ( !tree->local_root ) return ret_tree;
01220 
01221   // send value of the root node to parent process,
01222   // if the block is a right block of the parent process.
01223   if ( tree->global_node->parent &&
01224        tree->global_node->parent->right == tree->global_node ) {
01225     MPI_Request req;
01226     MPI_Isend( &(tree->local_root->value), sizeof( A ), MPI_BYTE,
01227            tree->proc_parent, TAG_SHIFTR, MPI_COMM_WORLD, &req );
01228     MPI_Wait( &req, MPI_STATUS_IGNORE );
01229   }
01230 
01231   // receive value of the cutnode from right-child process. 
01232   A right_child_root_val;
01233   if ( !tree->global_node->isLeaf( ) ) {
01234     MPI_Request req;
01235     MPI_Irecv( &right_child_root_val, sizeof( A ), MPI_BYTE,
01236            tree->proc_rightchild, TAG_SHIFTR, MPI_COMM_WORLD, &req );
01237     MPI_Wait( &req, MPI_STATUS_IGNORE );
01238   }
01239 
01240   ret_tree->local_root = shiftr_rec( tree->local_root,
01241                      leafval,
01242                      right_child_root_val );
01243   return ret_tree;
01244 }
01245 
01246 /* private, static */
01247 template< typename A >
01248 node< A >*
01249 tree_skeletons::shiftr_rec( const node< A > *root,
01250                 const A& leafval,
01251                 const A& right_child_root_val )
01252 {
01253   node< A > *ret_node;
01254   if ( !root->isLeaf( ) ) {
01255     // internal node
01256     ret_node = new node< A >( root->right->value, node< A >::NORMAL );
01257     ret_node->left  = shiftr_rec( root->left,  leafval, right_child_root_val );
01258     ret_node->right = shiftr_rec( root->right, leafval, right_child_root_val );
01259   } else if ( root->nodetype == node< A >::NORMAL ) {
01260     // normal leaf
01261     ret_node = new node< A >( leafval, node< A >::NORMAL );
01262   } else {
01263     // cutnode
01264     ret_node = new node< A >( right_child_root_val, node< A >::CUTNODE );
01265   }
01266   return ret_node;
01267 }
01268 
01269 
01270 #endif /* __TREE_SKELETONS_TPP__ */
01271 #endif /* __TREE_SKELETONS_H__ */

Generated on Wed Jan 18 22:19:29 2006 for SkeTo -- Skeleton Library in Tokyo by  doxygen 1.4.4