X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmoof%2Fcml%2Fet%2Farray_promotions.h;fp=src%2Fmoof%2Fcml%2Fet%2Farray_promotions.h;h=418211dfa5d0a6b6603f9d3b09f38b3631cd8308;hb=831f04d4bc19a390415ac0bbac4331c7a65509bc;hp=0000000000000000000000000000000000000000;hpb=299af4f2047e767e5d79501c26444473bda64c64;p=chaz%2Fyoink diff --git a/src/moof/cml/et/array_promotions.h b/src/moof/cml/et/array_promotions.h new file mode 100644 index 0000000..418211d --- /dev/null +++ b/src/moof/cml/et/array_promotions.h @@ -0,0 +1,288 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + * + * Defines promotions between array types. + * + * @todo Can/should an expression with a fixed-size argument promote to a + * fixed array instead of a dynamic array? + */ + +#ifndef array_promotions_h +#define array_promotions_h + +#include +#include + +namespace cml { +namespace et { + +#define VAL_MAX(_a_,_b_) ( ((_a_)>(_b_))?(_a_):(_b_) ) + +namespace detail { + +/* This is specialized for 1D and 2D promotions: */ +template struct promote; + +/* Promote 1D fixed-size arrays to a 1D fixed-size array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, deduce the array size: */ + enum { Size = VAL_MAX((size_t)A1::array_size, (size_t)A2::array_size) }; + + /* Finally, generate the promoted array type: */ + typedef fixed_1D type; +}; + +/* Promote 1D dynamic arrays to a 1D dynamic array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, rebind to get the proper allocator: */ + typedef typename CML_DEFAULT_ARRAY_ALLOC + ::rebind::other allocator; + + /* Finally, generate the promoted array type: */ + typedef dynamic_1D type; +}; + +/* Promote fixed 2D+1D array expressions to a fixed 1D array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, deduce the array size: */ + enum { Size = (size_t)A1::array_rows }; + + /* Finally, generate the promoted array type: */ + typedef fixed_1D type; +}; + +/* Promote fixed 1D+2D array expressions to a fixed 1D array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, deduce the array size: */ + enum { Size = (size_t)A2::array_cols }; + + /* Finally, generate the promoted array type: */ + typedef fixed_1D type; +}; + +/* Promote dynamic 2D+1D array expression to a 1D dynamic array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, rebind to get the proper allocator: */ + typedef typename CML_DEFAULT_ARRAY_ALLOC + ::rebind::other allocator; + + /* Finally, generate the promoted array type: */ + typedef dynamic_1D type; +}; + +/* Promote dynamic 1D+2D array expression to a 1D dynamic array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, rebind to get the proper allocator: */ + typedef typename CML_DEFAULT_ARRAY_ALLOC + ::rebind::other allocator; + + /* Finally, generate the promoted array type: */ + typedef dynamic_1D type; +}; + + +/* This is a helper to deduce the result of a promoted 2D array: */ +template struct deduce_layout { +#if defined(CML_ALWAYS_PROMOTE_TO_DEFAULT_LAYOUT) + typedef CML_DEFAULT_ARRAY_LAYOUT promoted_layout; +#else + typedef typename select_if< + same_type::is_true, LeftL, + CML_DEFAULT_ARRAY_LAYOUT>::result promoted_layout; +#endif +}; + +/* Promote 2D fixed-size arrays to a 2D fixed-size array. The resulting + * matrix has the same number of rows as A1, and the same number of + * columns as A2. + */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, deduce the array size: */ + enum { + Rows = (size_t)A1::array_rows, + Cols = (size_t)A2::array_cols + }; + + /* Then deduce the array layout: */ + typedef typename A1::layout left_layout; + typedef typename A2::layout right_layout; + typedef typename deduce_layout + ::promoted_layout promoted_layout; + + /* Finally, generate the promoted array type: */ + typedef fixed_2D type; +}; + +/* Promote 2D dynamic arrays to a 2D dynamic array: */ +template +struct promote +{ + typedef typename A1::value_type left_scalar; + typedef typename A2::value_type right_scalar; + + /* First, promote the scalar type: */ + typedef typename ScalarPromote< + left_scalar,right_scalar>::type promoted_scalar; + + /* Next, rebind to get the proper allocator: */ + typedef typename CML_DEFAULT_ARRAY_ALLOC + ::rebind::other allocator; + + /* Then deduce the array layout: */ + typedef typename A1::layout left_layout; + typedef typename A2::layout right_layout; + typedef typename deduce_layout + ::promoted_layout promoted_layout; + + /* Finally, generate the promoted array type: */ + typedef dynamic_2D type; +}; + +} // namespace detail + +/** Class to promote array types. + * + * Both arguments must be array types. + * + * @sa fixed_1D + * @sa fixed_2D + * @sa dynamic_1D + * @sa dynamic_2D + */ +template +struct ArrayPromote +{ + /* Shorthand: */ + //typedef typename A1::value_type left_scalar; + //typedef typename A2::value_type right_scalar; + typedef typename A1::dimension_tag left_dtag; + typedef typename A2::dimension_tag right_dtag; + + /* Deduce the proper type based upon the characteristics of AT1 and + * AT2. This is the table of type conversions: + * + * AT1 AT2 Result + * memory size memory size memory size + * + * fixed fixed fixed fixed fixed fixed + * fixed fixed dynamic dynamic dynamic dynamic + * fixed fixed external fixed fixed fixed + * fixed fixed external dynamic dynamic dynamic + * + * dynamic dynamic fixed fixed dynamic dynamic + * dynamic dynamic dynamic dynamic dynamic dynamic + * dynamic dynamic external fixed dynamic dynamic + * dynamic dynamic external dynamic dynamic dynamic + * + * external fixed external fixed fixed fixed + * external fixed fixed fixed fixed fixed + * external fixed dynamic dynamic dynamic dynamic + * external fixed external dynamic dynamic dynamic + * + * external dynamic external fixed dynamic dynamic + * external dynamic fixed fixed dynamic dynamic + * external dynamic dynamic dynamic dynamic dynamic + * external dynamic external dynamic dynamic dynamic + * + * Note that if one argument is a dynamically-sized array, the result + * must be a dynamically allocated and sized array. Likewise, if both + * arguments have fixed size, the result can be a fixed-sized array. + */ + + /* Check if both arguments are fixed-size arrays. If so, the promoted + * array will be a fixed array, and if not, it will be a dynamic array: + */ + typedef typename select_if< + (same_type::is_true + && same_type::is_true), + fixed_size_tag, /* True */ + dynamic_size_tag /* False */ + >::result promoted_size_tag; + + /* Deduce the promoted type: */ + typedef typename detail::promote< + A1, A2, left_dtag, right_dtag, promoted_size_tag>::type type; +}; + +/* Cleanup internal macros: */ +#undef VAL_MAX + +} // namespace et +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp