array_promotions.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00018 #ifndef array_promotions_h
00019 #define array_promotions_h
00020 
00021 #include <cml/core/cml_meta.h>
00022 #include <cml/et/scalar_promotions.h>
00023 
00024 namespace cml {
00025 namespace et {
00026 
00027 #define VAL_MAX(_a_,_b_)        ( ((_a_)>(_b_))?(_a_):(_b_) )
00028 
00029 namespace detail {
00030 
00031 /* This is specialized for 1D and 2D promotions: */
00032 template<class A1, class A2, typename DTag1, typename DTag2,
00033     typename PromotedSizeTag> struct promote;
00034 
00035 /* Promote 1D fixed-size arrays to a 1D fixed-size array: */
00036 template<class A1, class A2>
00037 struct promote<A1,A2,oned_tag,oned_tag,fixed_size_tag>
00038 {
00039     typedef typename A1::value_type left_scalar;
00040     typedef typename A2::value_type right_scalar;
00041 
00042     /* First, promote the scalar type: */
00043     typedef typename ScalarPromote<
00044         left_scalar,right_scalar>::type promoted_scalar;
00045 
00046     /* Next, deduce the array size: */
00047     enum { Size = VAL_MAX((size_t)A1::array_size, (size_t)A2::array_size) };
00048 
00049     /* Finally, generate the promoted array type: */
00050     typedef fixed_1D<promoted_scalar,Size> type;
00051 };
00052 
00053 /* Promote 1D dynamic arrays to a 1D dynamic array: */
00054 template<class A1, class A2>
00055 struct promote<A1,A2,oned_tag,oned_tag,dynamic_size_tag>
00056 {
00057     typedef typename A1::value_type left_scalar;
00058     typedef typename A2::value_type right_scalar;
00059 
00060     /* First, promote the scalar type: */
00061     typedef typename ScalarPromote<
00062         left_scalar,right_scalar>::type promoted_scalar;
00063 
00064     /* Next, rebind to get the proper allocator: */
00065     typedef typename CML_DEFAULT_ARRAY_ALLOC
00066         ::rebind<promoted_scalar>::other allocator;
00067 
00068     /* Finally, generate the promoted array type: */
00069     typedef dynamic_1D<promoted_scalar,allocator> type;
00070 };
00071 
00072 /* Promote fixed 2D+1D array expressions to a fixed 1D array: */
00073 template<class A1, class A2>
00074 struct promote<A1,A2,twod_tag,oned_tag,fixed_size_tag>
00075 {
00076     typedef typename A1::value_type left_scalar;
00077     typedef typename A2::value_type right_scalar;
00078 
00079     /* First, promote the scalar type: */
00080     typedef typename ScalarPromote<
00081         left_scalar,right_scalar>::type promoted_scalar;
00082 
00083     /* Next, deduce the array size: */
00084     enum { Size = (size_t)A1::array_rows };
00085 
00086     /* Finally, generate the promoted array type: */
00087     typedef fixed_1D<promoted_scalar,Size> type;
00088 };
00089 
00090 /* Promote fixed 1D+2D array expressions to a fixed 1D array: */
00091 template<class A1, class A2>
00092 struct promote<A1,A2,oned_tag,twod_tag,fixed_size_tag>
00093 {
00094     typedef typename A1::value_type left_scalar;
00095     typedef typename A2::value_type right_scalar;
00096 
00097     /* First, promote the scalar type: */
00098     typedef typename ScalarPromote<
00099         left_scalar,right_scalar>::type promoted_scalar;
00100 
00101     /* Next, deduce the array size: */
00102     enum { Size = (size_t)A2::array_cols };
00103 
00104     /* Finally, generate the promoted array type: */
00105     typedef fixed_1D<promoted_scalar,Size> type;
00106 };
00107 
00108 /* Promote dynamic 2D+1D array expression to a 1D dynamic array: */
00109 template<class A1, class A2>
00110 struct promote<A1,A2,twod_tag,oned_tag,dynamic_size_tag>
00111 {
00112     typedef typename A1::value_type left_scalar;
00113     typedef typename A2::value_type right_scalar;
00114 
00115     /* First, promote the scalar type: */
00116     typedef typename ScalarPromote<
00117         left_scalar,right_scalar>::type promoted_scalar;
00118 
00119     /* Next, rebind to get the proper allocator: */
00120     typedef typename CML_DEFAULT_ARRAY_ALLOC
00121         ::rebind<promoted_scalar>::other allocator;
00122 
00123     /* Finally, generate the promoted array type: */
00124     typedef dynamic_1D<promoted_scalar,allocator> type;
00125 };
00126 
00127 /* Promote dynamic 1D+2D array expression to a 1D dynamic array: */
00128 template<class A1, class A2>
00129 struct promote<A1,A2,oned_tag,twod_tag,dynamic_size_tag>
00130 {
00131     typedef typename A1::value_type left_scalar;
00132     typedef typename A2::value_type right_scalar;
00133 
00134     /* First, promote the scalar type: */
00135     typedef typename ScalarPromote<
00136         left_scalar,right_scalar>::type promoted_scalar;
00137 
00138     /* Next, rebind to get the proper allocator: */
00139     typedef typename CML_DEFAULT_ARRAY_ALLOC
00140         ::rebind<promoted_scalar>::other allocator;
00141 
00142     /* Finally, generate the promoted array type: */
00143     typedef dynamic_1D<promoted_scalar,allocator> type;
00144 };
00145 
00146 
00147 /* This is a helper to deduce the result of a promoted 2D array: */
00148 template<typename LeftL, typename RightL> struct deduce_layout {
00149 #if defined(CML_ALWAYS_PROMOTE_TO_DEFAULT_LAYOUT)
00150     typedef CML_DEFAULT_ARRAY_LAYOUT promoted_layout;
00151 #else
00152     typedef typename select_if<
00153         same_type<LeftL,RightL>::is_true, LeftL,
00154         CML_DEFAULT_ARRAY_LAYOUT>::result promoted_layout;
00155 #endif
00156 };
00157 
00158 /* Promote 2D fixed-size arrays to a 2D fixed-size array.  The resulting
00159  * matrix has the same number of rows as A1, and the same number of
00160  * columns as A2.
00161  */
00162 template<class A1, class A2>
00163 struct promote<A1,A2,twod_tag,twod_tag,fixed_size_tag>
00164 {
00165     typedef typename A1::value_type left_scalar;
00166     typedef typename A2::value_type right_scalar;
00167 
00168     /* First, promote the scalar type: */
00169     typedef typename ScalarPromote<
00170         left_scalar,right_scalar>::type promoted_scalar;
00171 
00172     /* Next, deduce the array size: */
00173     enum {
00174         Rows = (size_t)A1::array_rows,
00175         Cols = (size_t)A2::array_cols
00176     };
00177 
00178     /* Then deduce the array layout: */
00179     typedef typename A1::layout left_layout;
00180     typedef typename A2::layout right_layout;
00181     typedef typename deduce_layout<left_layout,right_layout>
00182         ::promoted_layout promoted_layout;
00183 
00184     /* Finally, generate the promoted array type: */
00185     typedef fixed_2D<promoted_scalar,Rows,Cols,promoted_layout> type;
00186 };
00187 
00188 /* Promote 2D dynamic arrays to a 2D dynamic array: */
00189 template<class A1, class A2>
00190 struct promote<A1,A2,twod_tag,twod_tag,dynamic_size_tag>
00191 {
00192     typedef typename A1::value_type left_scalar;
00193     typedef typename A2::value_type right_scalar;
00194 
00195     /* First, promote the scalar type: */
00196     typedef typename ScalarPromote<
00197         left_scalar,right_scalar>::type promoted_scalar;
00198 
00199     /* Next, rebind to get the proper allocator: */
00200     typedef typename CML_DEFAULT_ARRAY_ALLOC
00201         ::rebind<promoted_scalar>::other allocator;
00202 
00203     /* Then deduce the array layout: */
00204     typedef typename A1::layout left_layout;
00205     typedef typename A2::layout right_layout;
00206     typedef typename deduce_layout<left_layout,right_layout>
00207         ::promoted_layout promoted_layout;
00208 
00209     /* Finally, generate the promoted array type: */
00210     typedef dynamic_2D<promoted_scalar,promoted_layout,allocator> type;
00211 };
00212 
00213 } // namespace detail
00214 
00224 template<class A1, class A2>
00225 struct ArrayPromote
00226 {
00227     /* Shorthand: */
00228     //typedef typename A1::value_type left_scalar;
00229     //typedef typename A2::value_type right_scalar;
00230     typedef typename A1::dimension_tag left_dtag;
00231     typedef typename A2::dimension_tag right_dtag;
00232 
00233     /* Deduce the proper type based upon the characteristics of AT1 and
00234      * AT2.  This is the table of type conversions:
00235      *
00236      *         AT1               AT2              Result
00237      *   memory   size     memory   size      memory   size
00238      *
00239      *   fixed    fixed    fixed    fixed     fixed    fixed
00240      *   fixed    fixed    dynamic  dynamic   dynamic  dynamic
00241      *   fixed    fixed    external fixed     fixed    fixed
00242      *   fixed    fixed    external dynamic   dynamic  dynamic
00243      *
00244      *   dynamic  dynamic  fixed    fixed     dynamic  dynamic
00245      *   dynamic  dynamic  dynamic  dynamic   dynamic  dynamic
00246      *   dynamic  dynamic  external fixed     dynamic  dynamic
00247      *   dynamic  dynamic  external dynamic   dynamic  dynamic
00248      *
00249      *   external fixed    external fixed     fixed    fixed
00250      *   external fixed    fixed    fixed     fixed    fixed
00251      *   external fixed    dynamic  dynamic   dynamic  dynamic
00252      *   external fixed    external dynamic   dynamic  dynamic
00253      *
00254      *   external dynamic  external fixed     dynamic  dynamic
00255      *   external dynamic  fixed    fixed     dynamic  dynamic
00256      *   external dynamic  dynamic  dynamic   dynamic  dynamic
00257      *   external dynamic  external dynamic   dynamic  dynamic
00258      *
00259      * Note that if one argument is a dynamically-sized array, the result
00260      * must be a dynamically allocated and sized array.  Likewise, if both
00261      * arguments have fixed size, the result can be a fixed-sized array.
00262      */
00263 
00264     /* Check if both arguments are fixed-size arrays.  If so, the promoted
00265      * array will be a fixed array, and if not, it will be a dynamic array:
00266      */
00267     typedef typename select_if<
00268         (same_type<typename A1::size_tag, fixed_size_tag>::is_true
00269          && same_type<typename A2::size_tag, fixed_size_tag>::is_true),
00270         fixed_size_tag,         /* True */
00271         dynamic_size_tag        /* False */
00272     >::result promoted_size_tag;
00273 
00274     /* Deduce the promoted type: */
00275     typedef typename detail::promote<
00276         A1, A2, left_dtag, right_dtag, promoted_size_tag>::type type;
00277 };
00278 
00279 /* Cleanup internal macros: */
00280 #undef VAL_MAX
00281 
00282 } // namespace et
00283 } // namespace cml
00284 
00285 #endif
00286 
00287 // -------------------------------------------------------------------------
00288 // vim:ft=cpp

Generated on Sat Jul 18 19:35:20 2009 for CML 1.0 by  doxygen 1.5.9