46 template<
typename ScalarType>
 
   51       return (s1 - s2) / 
std::max(std::fabs(s1), std::fabs(s2));
 
   55 template<
typename ScalarType, 
typename VCLVectorType>
 
   58    std::vector<ScalarType> v2_cpu(v2.size());
 
   63    for (
unsigned int i=0;i<v1.size(); ++i)
 
   65      if ( 
std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) > 0 )
 
   67        ScalarType tmp = std::fabs(v2_cpu[i] - v1[i]) / 
std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) );
 
   76 template<
typename ScalarType, 
typename VCLMatrixType>
 
   77 ScalarType diff(std::vector<std::vector<ScalarType> > 
const & mat1, VCLMatrixType 
const & mat2)
 
   79    std::vector<std::vector<ScalarType> > mat2_cpu(mat2.size1(), std::vector<ScalarType>(mat2.size2()));
 
   85     for (std::size_t i = 0; i < mat2_cpu.size(); ++i)
 
   87       for (std::size_t j = 0; j < mat2_cpu[i].size(); ++j)
 
   89          act = std::fabs(mat2_cpu[i][j] - mat1[i][j]) / 
std::max( std::fabs(mat2_cpu[i][j]), std::fabs(mat1[i][j]) );
 
  101 template<
typename NumericT, 
typename Epsilon,
 
  102           typename STLMatrixType, 
typename STLVectorType,
 
  103           typename VCLMatrixType, 
typename VCLVectorType1, 
typename VCLVectorType2>
 
  105                     STLMatrixType & std_m1, STLVectorType & std_v1, STLVectorType & std_v2, STLMatrixType & std_m2,
 
  106                     VCLMatrixType & vcl_m1, VCLVectorType1 & vcl_v1, VCLVectorType2 & vcl_v2, VCLMatrixType & vcl_m2)
 
  108    int retval = EXIT_SUCCESS;
 
  111    std_v1 = std::vector<NumericT>(std_v1.size(), 
NumericT(0.1234));
 
  112    std_v2 = std::vector<NumericT>(std_v2.size(), 
NumericT(0.4321));
 
  118    std::cout << 
"Rank 1 update" << std::endl;
 
  120    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  121      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  122        std_m1[i][j] += std_v1[i] * std_v2[j];
 
  124    if ( std::fabs(
diff(std_m1, vcl_m1)) > epsilon )
 
  126       std::cout << 
"# Error at operation: rank 1 update" << std::endl;
 
  127       std::cout << 
"  diff: " << std::fabs(
diff(std_m1, vcl_m1)) << std::endl;
 
  134    std::cout << 
"Scaled rank 1 update - CPU Scalar" << std::endl;
 
  135    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  136      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  137        std_m1[i][j] += 
NumericT(4.2) * std_v1[i] * std_v2[j];
 
  140    if ( std::fabs(
diff(std_m1, vcl_m1)) > epsilon )
 
  142       std::cout << 
"# Error at operation: scaled rank 1 update - CPU Scalar" << std::endl;
 
  143       std::cout << 
"  diff: " << std::fabs(
diff(std_m1, vcl_m1)) << std::endl;
 
  148    std::cout << 
"Scaled rank 1 update - GPU Scalar" << std::endl;
 
  149    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  150      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  151        std_m1[i][j] += 
NumericT(4.2) * std_v1[i] * std_v2[j];
 
  154    if ( std::fabs(
diff(std_m1, vcl_m1)) > epsilon )
 
  156       std::cout << 
"# Error at operation: scaled rank 1 update - GPU Scalar" << std::endl;
 
  157       std::cout << 
"  diff: " << std::fabs(
diff(std_m1, vcl_m1)) << std::endl;
 
  165    std::cout << 
"Matrix-Vector product" << std::endl;
 
  166    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  169      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  170        std_v1[i] += std_m1[i][j] * std_v2[j];
 
  174    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  176       std::cout << 
"# Error at operation: matrix-vector product" << std::endl;
 
  177       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  178       retval = EXIT_FAILURE;
 
  181    std::cout << 
"Matrix-Vector product with scaled add" << std::endl;
 
  187    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  190      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  191        tmp += std_m1[i][j] * std_v2[j];
 
  192      std_v1[i] = alpha * tmp + beta * std_v1[i];
 
  196    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  198       std::cout << 
"# Error at operation: matrix-vector product with scaled additions" << std::endl;
 
  199       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  200       retval = EXIT_FAILURE;
 
  203    std::cout << 
"Matrix-Vector product with matrix expression" << std::endl;
 
  204    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  207      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  208        std_v1[i] += (std_m1[i][j] + std_m1[i][j]) * std_v2[j];
 
  212    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  214       std::cout << 
"# Error at operation: matrix-vector product" << std::endl;
 
  215       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  216       retval = EXIT_FAILURE;
 
  219    std::cout << 
"Matrix-Vector product with vector expression" << std::endl;
 
  220    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  223      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  224        std_v1[i] += std_m1[i][j] * 
NumericT(3) * std_v2[j];
 
  228    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  230       std::cout << 
"# Error at operation: matrix-vector product" << std::endl;
 
  231       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  232       retval = EXIT_FAILURE;
 
  235    std::cout << 
"Matrix-Vector product with matrix and vector expression" << std::endl;
 
  236    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  239      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  240        std_v1[i] += (std_m1[i][j] + std_m1[i][j]) * (std_v2[j] + std_v2[j]);
 
  244    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  246       std::cout << 
"# Error at operation: matrix-vector product" << std::endl;
 
  247       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  248       retval = EXIT_FAILURE;
 
  255    std::cout << 
"Transposed Matrix-Vector product" << std::endl;
 
  256    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  259      for (std::size_t j=0; j<std_m1.size(); ++j)
 
  260        std_v2[i] += alpha * std_m1[j][i] * std_v1[j];
 
  264    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  266       std::cout << 
"# Error at operation: transposed matrix-vector product" << std::endl;
 
  267       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  268       retval = EXIT_FAILURE;
 
  271    std::cout << 
"Transposed Matrix-Vector product with scaled add" << std::endl;
 
  272    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  275      for (std::size_t j=0; j<std_m1.size(); ++j)
 
  276        tmp += std_m1[j][i] * std_v1[j];
 
  277      std_v2[i] = alpha * tmp + beta * std_v2[i];
 
  281    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  283       std::cout << 
"# Error at operation: transposed matrix-vector product with scaled additions" << std::endl;
 
  284       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  285       retval = EXIT_FAILURE;
 
  289    std::cout << 
"Row sum with matrix" << std::endl;
 
  290    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  293      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  294        std_v1[i] += std_m1[i][j];
 
  298    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  300       std::cout << 
"# Error at operation: row sum" << std::endl;
 
  301       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  302       retval = EXIT_FAILURE;
 
  306    std::cout << 
"Row sum with matrix expression" << std::endl;
 
  307    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  310      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  311        std_v1[i] += std_m1[i][j] + std_m1[i][j];
 
  315    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  317       std::cout << 
"# Error at operation: row sum (with expression)" << std::endl;
 
  318       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  319       retval = EXIT_FAILURE;
 
  323    std::cout << 
"Column sum with matrix" << std::endl;
 
  324    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  327      for (std::size_t j=0; j<std_m1.size(); ++j)
 
  328        std_v2[i] += std_m1[j][i];
 
  332    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  334       std::cout << 
"# Error at operation: column sum" << std::endl;
 
  335       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  336       retval = EXIT_FAILURE;
 
  340    std::cout << 
"Column sum with matrix expression" << std::endl;
 
  341    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  344      for (std::size_t j=0; j<std_m1.size(); ++j)
 
  345        std_v2[i] += std_m1[j][i] + std_m1[j][i];
 
  349    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  351       std::cout << 
"# Error at operation: column sum (with expression)" << std::endl;
 
  352       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  353       retval = EXIT_FAILURE;
 
  361    std::cout << 
"Row extraction from matrix" << std::endl;
 
  362    for (std::size_t j=0; j<std_m1[7].size(); ++j)
 
  363      std_v2[j] = std_m1[7][j];
 
  364    vcl_v2   = 
row(vcl_m1, std::size_t(7));
 
  366    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  368       std::cout << 
"# Error at operation: diagonal extraction from matrix" << std::endl;
 
  369       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  370       retval = EXIT_FAILURE;
 
  373    std::cout << 
"Column extraction from matrix" << std::endl;
 
  374    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  375      std_v1[i] = std_m1[i][7];
 
  376    vcl_v1   = 
column(vcl_m1, std::size_t(7));
 
  378    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  380       std::cout << 
"# Error at operation: diagonal extraction from matrix" << std::endl;
 
  381       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  382       retval = EXIT_FAILURE;
 
  390    STLMatrixType A = std_m2;
 
  392    std::cout << 
"Diagonal extraction from matrix" << std::endl;
 
  393    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  394      std_v2[i] = std_m1[i + 3][i];
 
  395    vcl_v2   = 
diag(vcl_m1, static_cast<int>(-3));
 
  397    if ( std::fabs(
diff(std_v2, vcl_v2)) > epsilon )
 
  399       std::cout << 
"# Error at operation: diagonal extraction from matrix" << std::endl;
 
  400       std::cout << 
"  diff: " << std::fabs(
diff(std_v2, vcl_v2)) << std::endl;
 
  401       retval = EXIT_FAILURE;
 
  404    std::cout << 
"Matrix diagonal assignment from vector" << std::endl;
 
  405    A = std::vector<std::vector<NumericT> >(A.size(), std::vector<NumericT>(A[0].size()));
 
  406    for (std::size_t i=0; i<std_m1[0].size(); ++i)
 
  407      A[i + (A.size() - std_m1[i].size())][i] = std_v2[i];
 
  408    vcl_m2 = 
diag(vcl_v2, static_cast<int>(std_m1[0].
size()) - static_cast<int>(A.size()));
 
  410    if ( std::fabs(
diff(A, vcl_m2)) > epsilon )
 
  412       std::cout << 
"# Error at operation: Matrix assignment from diagonal" << std::endl;
 
  413       std::cout << 
"  diff: " << std::fabs(
diff(A, vcl_m2)) << std::endl;
 
  414       retval = EXIT_FAILURE;
 
  421 template<
typename NumericT>
 
  422 void inplace_solve_upper(std::vector<std::vector<NumericT> > 
const & A, std::vector<NumericT> & b, 
bool unit_diagonal)
 
  424   for (std::size_t i2=0; i2<A.size(); ++i2)
 
  426     std::size_t i = A.size() - i2 - 1;
 
  427     for (std::size_t j = i+1; j < A.size(); ++j)
 
  428       b[i] -= A[i][j] * b[j];
 
  429     b[i] = unit_diagonal ? b[i] : b[i] / A[i][i];
 
  433 template<
typename NumericT>
 
  439 template<
typename NumericT>
 
  446 template<
typename NumericT>
 
  447 void inplace_solve_lower(std::vector<std::vector<NumericT> > 
const & A, std::vector<NumericT> & b, 
bool unit_diagonal)
 
  449   for (std::size_t i=0; i<A.size(); ++i)
 
  451     for (std::size_t j = 0; j < i; ++j)
 
  452       b[i] -= A[i][j] * b[j];
 
  453     b[i] = unit_diagonal ? b[i] : b[i] / A[i][i];
 
  457 template<
typename NumericT>
 
  463 template<
typename NumericT>
 
  470 template<
typename NumericT, 
typename TagT>
 
  471 std::vector<NumericT> 
solve(std::vector<std::vector<NumericT> > 
const & A, std::vector<NumericT> 
const & b, TagT)
 
  473   std::vector<NumericT> ret(b);
 
  478 template<
typename NumericT, 
typename Epsilon,
 
  479           typename STLMatrixType, 
typename STLVectorType,
 
  480           typename VCLMatrixType, 
typename VCLVectorType1>
 
  482                STLMatrixType & std_m1, STLVectorType & std_v1,
 
  483                VCLMatrixType & vcl_m1, VCLVectorType1 & vcl_v1)
 
  485    int retval = EXIT_SUCCESS;
 
  495    std::cout << 
"Upper triangular solver" << std::endl;
 
  498    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  500       std::cout << 
"# Error at operation: upper triangular solver" << std::endl;
 
  501       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  502       retval = EXIT_FAILURE;
 
  506    std::cout << 
"Upper unit triangular solver" << std::endl;
 
  510    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  512       std::cout << 
"# Error at operation: unit upper triangular solver" << std::endl;
 
  513       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  514       retval = EXIT_FAILURE;
 
  518    std::cout << 
"Lower triangular solver" << std::endl;
 
  522    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  524       std::cout << 
"# Error at operation: lower triangular solver" << std::endl;
 
  525       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  526       retval = EXIT_FAILURE;
 
  530    std::cout << 
"Lower unit triangular solver" << std::endl;
 
  534    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  536       std::cout << 
"# Error at operation: unit lower triangular solver" << std::endl;
 
  537       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  538       retval = EXIT_FAILURE;
 
  544    STLMatrixType std_m1_trans(std_m1[0].
size(), std::vector<NumericT>(std_m1.size()));
 
  545    for (std::size_t i=0; i<std_m1.size(); ++i)
 
  546      for (std::size_t j=0; j<std_m1[i].size(); ++j)
 
  547        std_m1_trans[j][i] = std_m1[i][j];
 
  551    std::cout << 
"Transposed upper triangular solver" << std::endl;
 
  555    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  557       std::cout << 
"# Error at operation: upper triangular solver" << std::endl;
 
  558       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  559       retval = EXIT_FAILURE;
 
  563    std::cout << 
"Transposed unit upper triangular solver" << std::endl;
 
  567    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  569       std::cout << 
"# Error at operation: unit upper triangular solver" << std::endl;
 
  570       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  571       retval = EXIT_FAILURE;
 
  575    std::cout << 
"Transposed lower triangular solver" << std::endl;
 
  579    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  581       std::cout << 
"# Error at operation: lower triangular solver" << std::endl;
 
  582       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  583       retval = EXIT_FAILURE;
 
  587    std::cout << 
"Transposed unit lower triangular solver" << std::endl;
 
  591    if ( std::fabs(
diff(std_v1, vcl_v1)) > epsilon )
 
  593       std::cout << 
"# Error at operation: unit lower triangular solver" << std::endl;
 
  594       std::cout << 
"  diff: " << std::fabs(
diff(std_v1, vcl_v1)) << std::endl;
 
  595       retval = EXIT_FAILURE;
 
  605 template< 
typename NumericT, 
typename F, 
typename Epsilon >
 
  606 int test(Epsilon 
const& epsilon)
 
  608    int retval = EXIT_SUCCESS;
 
  612    std::size_t num_rows = 141; 
 
  613    std::size_t num_cols = 103;
 
  616    std::vector<NumericT> std_v1(num_rows);
 
  617    for (std::size_t i = 0; i < std_v1.size(); ++i)
 
  618      std_v1[i] = randomNumber();
 
  619    std::vector<NumericT> std_v2 = std::vector<NumericT>(num_cols, 
NumericT(3.1415));
 
  622    std::vector<std::vector<NumericT> > std_m1(std_v1.size(), std::vector<NumericT>(std_v2.size()));
 
  624    for (std::size_t i = 0; i < std_m1.size(); ++i)
 
  625       for (std::size_t j = 0; j < std_m1[i].size(); ++j)
 
  626         std_m1[i][j] = static_cast<NumericT>(0.1) * randomNumber();
 
  629    std::vector<std::vector<NumericT> > std_m2(std_v1.size(), std::vector<NumericT>(std_v1.size()));
 
  631    for (std::size_t i = 0; i < std_m2.size(); ++i)
 
  633       for (std::size_t j = 0; j < std_m2[i].size(); ++j)
 
  634          std_m2[i][j] = static_cast<NumericT>(-0.1) * randomNumber();
 
  635       std_m2[i][i] = 
static_cast<NumericT>(2) + randomNumber();
 
  705    std::cout << 
"------------ Testing rank-1-updates and matrix-vector products ------------------" << std::endl;
 
  707    std::cout << 
"* m = full, v1 = full, v2 = full" << std::endl;
 
  708    retval = test_prod_rank1<NumericT>(epsilon,
 
  709                                       std_m1, std_v1, std_v2, std_m2,
 
  710                                       vcl_m1_native, vcl_v1_native, vcl_v2_native, vcl_m2_native);
 
  711    if (retval == EXIT_FAILURE)
 
  713      std::cout << 
" --- FAILED! ---" << std::endl;
 
  717      std::cout << 
" --- PASSED ---" << std::endl;
 
  720    std::cout << 
"* m = full, v1 = full, v2 = range" << std::endl;
 
  721    retval = test_prod_rank1<NumericT>(epsilon,
 
  722                                       std_m1, std_v1, std_v2, std_m2,
 
  723                                       vcl_m1_native, vcl_v1_native, vcl_v2_range, vcl_m2_native);
 
  724    if (retval == EXIT_FAILURE)
 
  726      std::cout << 
" --- FAILED! ---" << std::endl;
 
  730      std::cout << 
" --- PASSED ---" << std::endl;
 
  733    std::cout << 
"* m = full, v1 = full, v2 = slice" << std::endl;
 
  734    retval = test_prod_rank1<NumericT>(epsilon,
 
  735                                       std_m1, std_v1, std_v2, std_m2,
 
  736                                       vcl_m1_native, vcl_v1_native, vcl_v2_slice, vcl_m2_native);
 
  737    if (retval == EXIT_FAILURE)
 
  739      std::cout << 
" --- FAILED! ---" << std::endl;
 
  743      std::cout << 
" --- PASSED ---" << std::endl;
 
  749    std::cout << 
"* m = full, v1 = range, v2 = full" << std::endl;
 
  750    retval = test_prod_rank1<NumericT>(epsilon,
 
  751                                       std_m1, std_v1, std_v2, std_m2,
 
  752                                       vcl_m1_native, vcl_v1_range, vcl_v2_native, vcl_m2_native);
 
  753    if (retval == EXIT_FAILURE)
 
  755      std::cout << 
" --- FAILED! ---" << std::endl;
 
  759      std::cout << 
" --- PASSED ---" << std::endl;
 
  762    std::cout << 
"* m = full, v1 = range, v2 = range" << std::endl;
 
  763    retval = test_prod_rank1<NumericT>(epsilon,
 
  764                                       std_m1, std_v1, std_v2, std_m2,
 
  765                                       vcl_m1_native, vcl_v1_range, vcl_v2_range, vcl_m2_native);
 
  766    if (retval == EXIT_FAILURE)
 
  768      std::cout << 
" --- FAILED! ---" << std::endl;
 
  772      std::cout << 
" --- PASSED ---" << std::endl;
 
  775    std::cout << 
"* m = full, v1 = range, v2 = slice" << std::endl;
 
  776    retval = test_prod_rank1<NumericT>(epsilon,
 
  777                                       std_m1, std_v1, std_v2, std_m2,
 
  778                                       vcl_m1_native, vcl_v1_range, vcl_v2_slice, vcl_m2_native);
 
  779    if (retval == EXIT_FAILURE)
 
  781      std::cout << 
" --- FAILED! ---" << std::endl;
 
  785      std::cout << 
" --- PASSED ---" << std::endl;
 
  791    std::cout << 
"* m = full, v1 = slice, v2 = full" << std::endl;
 
  792    retval = test_prod_rank1<NumericT>(epsilon,
 
  793                                       std_m1, std_v1, std_v2, std_m2,
 
  794                                       vcl_m1_native, vcl_v1_slice, vcl_v2_native, vcl_m2_native);
 
  795    if (retval == EXIT_FAILURE)
 
  797      std::cout << 
" --- FAILED! ---" << std::endl;
 
  801      std::cout << 
" --- PASSED ---" << std::endl;
 
  804    std::cout << 
"* m = full, v1 = slice, v2 = range" << std::endl;
 
  805    retval = test_prod_rank1<NumericT>(epsilon,
 
  806                                       std_m1, std_v1, std_v2, std_m2,
 
  807                                       vcl_m1_native, vcl_v1_slice, vcl_v2_range, vcl_m2_native);
 
  808    if (retval == EXIT_FAILURE)
 
  810      std::cout << 
" --- FAILED! ---" << std::endl;
 
  814      std::cout << 
" --- PASSED ---" << std::endl;
 
  817    std::cout << 
"* m = full, v1 = slice, v2 = slice" << std::endl;
 
  818    retval = test_prod_rank1<NumericT>(epsilon,
 
  819                                       std_m1, std_v1, std_v2, std_m2,
 
  820                                       vcl_m1_native, vcl_v1_slice, vcl_v2_slice, vcl_m2_native);
 
  821    if (retval == EXIT_FAILURE)
 
  823      std::cout << 
" --- FAILED! ---" << std::endl;
 
  827      std::cout << 
" --- PASSED ---" << std::endl;
 
  832    std::cout << 
"* m = range, v1 = full, v2 = full" << std::endl;
 
  833    retval = test_prod_rank1<NumericT>(epsilon,
 
  834                                       std_m1, std_v1, std_v2, std_m2,
 
  835                                       vcl_m1_range, vcl_v1_native, vcl_v2_native, vcl_m2_range);
 
  836    if (retval == EXIT_FAILURE)
 
  838      std::cout << 
" --- FAILED! ---" << std::endl;
 
  842      std::cout << 
" --- PASSED ---" << std::endl;
 
  845    std::cout << 
"* m = range, v1 = full, v2 = range" << std::endl;
 
  846    retval = test_prod_rank1<NumericT>(epsilon,
 
  847                                       std_m1, std_v1, std_v2, std_m2,
 
  848                                       vcl_m1_range, vcl_v1_native, vcl_v2_range, vcl_m2_range);
 
  849    if (retval == EXIT_FAILURE)
 
  851      std::cout << 
" --- FAILED! ---" << std::endl;
 
  855      std::cout << 
" --- PASSED ---" << std::endl;
 
  858    std::cout << 
"* m = range, v1 = full, v2 = slice" << std::endl;
 
  859    retval = test_prod_rank1<NumericT>(epsilon,
 
  860                                       std_m1, std_v1, std_v2, std_m2,
 
  861                                       vcl_m1_range, vcl_v1_native, vcl_v2_slice, vcl_m2_range);
 
  862    if (retval == EXIT_FAILURE)
 
  864      std::cout << 
" --- FAILED! ---" << std::endl;
 
  868      std::cout << 
" --- PASSED ---" << std::endl;
 
  874    std::cout << 
"* m = range, v1 = range, v2 = full" << std::endl;
 
  875    retval = test_prod_rank1<NumericT>(epsilon,
 
  876                                       std_m1, std_v1, std_v2, std_m2,
 
  877                                       vcl_m1_range, vcl_v1_range, vcl_v2_native, vcl_m2_range);
 
  878    if (retval == EXIT_FAILURE)
 
  880      std::cout << 
" --- FAILED! ---" << std::endl;
 
  884      std::cout << 
" --- PASSED ---" << std::endl;
 
  887    std::cout << 
"* m = range, v1 = range, v2 = range" << std::endl;
 
  888    retval = test_prod_rank1<NumericT>(epsilon,
 
  889                                       std_m1, std_v1, std_v2, std_m2,
 
  890                                       vcl_m1_range, vcl_v1_range, vcl_v2_range, vcl_m2_range);
 
  891    if (retval == EXIT_FAILURE)
 
  893      std::cout << 
" --- FAILED! ---" << std::endl;
 
  897      std::cout << 
" --- PASSED ---" << std::endl;
 
  900    std::cout << 
"* m = range, v1 = range, v2 = slice" << std::endl;
 
  901    retval = test_prod_rank1<NumericT>(epsilon,
 
  902                                       std_m1, std_v1, std_v2, std_m2,
 
  903                                       vcl_m1_range, vcl_v1_range, vcl_v2_slice, vcl_m2_range);
 
  904    if (retval == EXIT_FAILURE)
 
  906      std::cout << 
" --- FAILED! ---" << std::endl;
 
  910      std::cout << 
" --- PASSED ---" << std::endl;
 
  916    std::cout << 
"* m = range, v1 = slice, v2 = full" << std::endl;
 
  917    retval = test_prod_rank1<NumericT>(epsilon,
 
  918                                       std_m1, std_v1, std_v2, std_m2,
 
  919                                       vcl_m1_range, vcl_v1_slice, vcl_v2_native, vcl_m2_range);
 
  920    if (retval == EXIT_FAILURE)
 
  922      std::cout << 
" --- FAILED! ---" << std::endl;
 
  926      std::cout << 
" --- PASSED ---" << std::endl;
 
  929    std::cout << 
"* m = range, v1 = slice, v2 = range" << std::endl;
 
  930    retval = test_prod_rank1<NumericT>(epsilon,
 
  931                                       std_m1, std_v1, std_v2, std_m2,
 
  932                                       vcl_m1_range, vcl_v1_slice, vcl_v2_range, vcl_m2_range);
 
  933    if (retval == EXIT_FAILURE)
 
  935      std::cout << 
" --- FAILED! ---" << std::endl;
 
  939      std::cout << 
" --- PASSED ---" << std::endl;
 
  942    std::cout << 
"* m = range, v1 = slice, v2 = slice" << std::endl;
 
  943    retval = test_prod_rank1<NumericT>(epsilon,
 
  944                                       std_m1, std_v1, std_v2, std_m2,
 
  945                                       vcl_m1_range, vcl_v1_slice, vcl_v2_slice, vcl_m2_range);
 
  946    if (retval == EXIT_FAILURE)
 
  948      std::cout << 
" --- FAILED! ---" << std::endl;
 
  952      std::cout << 
" --- PASSED ---" << std::endl;
 
  957    std::cout << 
"* m = slice, v1 = full, v2 = full" << std::endl;
 
  958    retval = test_prod_rank1<NumericT>(epsilon,
 
  959                                       std_m1, std_v1, std_v2, std_m2,
 
  960                                       vcl_m1_slice, vcl_v1_native, vcl_v2_native, vcl_m2_slice);
 
  961    if (retval == EXIT_FAILURE)
 
  963      std::cout << 
" --- FAILED! ---" << std::endl;
 
  967      std::cout << 
" --- PASSED ---" << std::endl;
 
  970    std::cout << 
"* m = slice, v1 = full, v2 = range" << std::endl;
 
  971    retval = test_prod_rank1<NumericT>(epsilon,
 
  972                                       std_m1, std_v1, std_v2, std_m2,
 
  973                                       vcl_m1_slice, vcl_v1_native, vcl_v2_range, vcl_m2_slice);
 
  974    if (retval == EXIT_FAILURE)
 
  976      std::cout << 
" --- FAILED! ---" << std::endl;
 
  980      std::cout << 
" --- PASSED ---" << std::endl;
 
  983    std::cout << 
"* m = slice, v1 = full, v2 = slice" << std::endl;
 
  984    retval = test_prod_rank1<NumericT>(epsilon,
 
  985                                       std_m1, std_v1, std_v2, std_m2,
 
  986                                       vcl_m1_slice, vcl_v1_native, vcl_v2_slice, vcl_m2_slice);
 
  987    if (retval == EXIT_FAILURE)
 
  989      std::cout << 
" --- FAILED! ---" << std::endl;
 
  993      std::cout << 
" --- PASSED ---" << std::endl;
 
  999    std::cout << 
"* m = slice, v1 = range, v2 = full" << std::endl;
 
 1000    retval = test_prod_rank1<NumericT>(epsilon,
 
 1001                                       std_m1, std_v1, std_v2, std_m2,
 
 1002                                       vcl_m1_slice, vcl_v1_range, vcl_v2_native, vcl_m2_slice);
 
 1003    if (retval == EXIT_FAILURE)
 
 1005      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1009      std::cout << 
" --- PASSED ---" << std::endl;
 
 1012    std::cout << 
"* m = slice, v1 = range, v2 = range" << std::endl;
 
 1013    retval = test_prod_rank1<NumericT>(epsilon,
 
 1014                                       std_m1, std_v1, std_v2, std_m2,
 
 1015                                       vcl_m1_slice, vcl_v1_range, vcl_v2_range, vcl_m2_slice);
 
 1016    if (retval == EXIT_FAILURE)
 
 1018      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1022      std::cout << 
" --- PASSED ---" << std::endl;
 
 1025    std::cout << 
"* m = slice, v1 = range, v2 = slice" << std::endl;
 
 1026    retval = test_prod_rank1<NumericT>(epsilon,
 
 1027                                       std_m1, std_v1, std_v2, std_m2,
 
 1028                                       vcl_m1_slice, vcl_v1_range, vcl_v2_slice, vcl_m2_slice);
 
 1029    if (retval == EXIT_FAILURE)
 
 1031      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1035      std::cout << 
" --- PASSED ---" << std::endl;
 
 1041    std::cout << 
"* m = slice, v1 = slice, v2 = full" << std::endl;
 
 1042    retval = test_prod_rank1<NumericT>(epsilon,
 
 1043                                       std_m1, std_v1, std_v2, std_m2,
 
 1044                                       vcl_m1_slice, vcl_v1_slice, vcl_v2_native, vcl_m2_slice);
 
 1045    if (retval == EXIT_FAILURE)
 
 1047      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1051      std::cout << 
" --- PASSED ---" << std::endl;
 
 1054    std::cout << 
"* m = slice, v1 = slice, v2 = range" << std::endl;
 
 1055    retval = test_prod_rank1<NumericT>(epsilon,
 
 1056                                       std_m1, std_v1, std_v2, std_m2,
 
 1057                                       vcl_m1_slice, vcl_v1_slice, vcl_v2_range, vcl_m2_slice);
 
 1058    if (retval == EXIT_FAILURE)
 
 1060      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1064      std::cout << 
" --- PASSED ---" << std::endl;
 
 1067    std::cout << 
"* m = slice, v1 = slice, v2 = slice" << std::endl;
 
 1068    retval = test_prod_rank1<NumericT>(epsilon,
 
 1069                                       std_m1, std_v1, std_v2, std_m2,
 
 1070                                       vcl_m1_slice, vcl_v1_slice, vcl_v2_slice, vcl_m2_slice);
 
 1071    if (retval == EXIT_FAILURE)
 
 1073      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1077      std::cout << 
" --- PASSED ---" << std::endl;
 
 1085    std::cout << 
"------------ Testing triangular solves ------------------" << std::endl;
 
 1087    std::cout << 
"* m = full, v1 = full" << std::endl;
 
 1088    retval = test_solve<NumericT>(epsilon,
 
 1090                                  vcl_m2_native, vcl_v1_native);
 
 1091    if (retval == EXIT_FAILURE)
 
 1093      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1097      std::cout << 
" --- PASSED ---" << std::endl;
 
 1099    std::cout << 
"* m = full, v1 = range" << std::endl;
 
 1100    retval = test_solve<NumericT>(epsilon,
 
 1102                                  vcl_m2_native, vcl_v1_range);
 
 1103    if (retval == EXIT_FAILURE)
 
 1105      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1109      std::cout << 
" --- PASSED ---" << std::endl;
 
 1111    std::cout << 
"* m = full, v1 = slice" << std::endl;
 
 1112    retval = test_solve<NumericT>(epsilon,
 
 1114                                  vcl_m2_native, vcl_v1_slice);
 
 1115    if (retval == EXIT_FAILURE)
 
 1117      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1121      std::cout << 
" --- PASSED ---" << std::endl;
 
 1126    std::cout << 
"* m = range, v1 = full" << std::endl;
 
 1127    retval = test_solve<NumericT>(epsilon,
 
 1129                                  vcl_m2_range, vcl_v1_native);
 
 1130    if (retval == EXIT_FAILURE)
 
 1132      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1136      std::cout << 
" --- PASSED ---" << std::endl;
 
 1138    std::cout << 
"* m = range, v1 = range" << std::endl;
 
 1139    retval = test_solve<NumericT>(epsilon,
 
 1141                                  vcl_m2_range, vcl_v1_range);
 
 1142    if (retval == EXIT_FAILURE)
 
 1144      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1148      std::cout << 
" --- PASSED ---" << std::endl;
 
 1150    std::cout << 
"* m = range, v1 = slice" << std::endl;
 
 1151    retval = test_solve<NumericT>(epsilon,
 
 1153                                  vcl_m2_range, vcl_v1_slice);
 
 1154    if (retval == EXIT_FAILURE)
 
 1156      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1160      std::cout << 
" --- PASSED ---" << std::endl;
 
 1164    std::cout << 
"* m = slice, v1 = full" << std::endl;
 
 1165    retval = test_solve<NumericT>(epsilon,
 
 1167                                  vcl_m2_slice, vcl_v1_native);
 
 1168    if (retval == EXIT_FAILURE)
 
 1170      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1174      std::cout << 
" --- PASSED ---" << std::endl;
 
 1176    std::cout << 
"* m = slice, v1 = range" << std::endl;
 
 1177    retval = test_solve<NumericT>(epsilon,
 
 1179                                  vcl_m2_slice, vcl_v1_range);
 
 1180    if (retval == EXIT_FAILURE)
 
 1182      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1186      std::cout << 
" --- PASSED ---" << std::endl;
 
 1188    std::cout << 
"* m = slice, v1 = slice" << std::endl;
 
 1189    retval = test_solve<NumericT>(epsilon,
 
 1191                                  vcl_m2_slice, vcl_v1_slice);
 
 1192    if (retval == EXIT_FAILURE)
 
 1194      std::cout << 
" --- FAILED! ---" << std::endl;
 
 1198      std::cout << 
" --- PASSED ---" << std::endl;
 
 1209    std::cout << 
"Full solver" << std::endl;
 
 1210    unsigned int lu_dim = 100;
 
 1211    std::vector<std::vector<NumericT> > square_matrix(lu_dim, std::vector<NumericT>(lu_dim));
 
 1212    std::vector<NumericT> lu_rhs(lu_dim);
 
 1213    std::vector<NumericT> lu_result(lu_dim);
 
 1217    for (std::size_t i=0; i<lu_dim; ++i)
 
 1218      for (std::size_t j=0; j<lu_dim; ++j)
 
 1219        square_matrix[i][j] = -static_cast<NumericT>(0.5) * randomNumber();
 
 1222    for (std::size_t j=0; j<lu_dim; ++j)
 
 1224      square_matrix[j][j] = 
static_cast<NumericT>(20.0) + randomNumber();
 
 1225      lu_result[j] = 
NumericT(0.1) + randomNumber();
 
 1228    for (std::size_t i=0; i<lu_dim; ++i)
 
 1229      for (std::size_t j=0; j<lu_dim; ++j)
 
 1230        lu_rhs[i] += square_matrix[i][j] * lu_result[j];
 
 1239    if ( std::fabs(
diff(lu_result, vcl_lu_rhs)) > epsilon )
 
 1241       std::cout << 
"# Error at operation: dense solver" << std::endl;
 
 1242       std::cout << 
"  diff: " << std::fabs(
diff(lu_rhs, vcl_lu_rhs)) << std::endl;
 
 1243       retval = EXIT_FAILURE;
 
 1255    std::cout << std::endl;
 
 1256    std::cout << 
"----------------------------------------------" << std::endl;
 
 1257    std::cout << 
"----------------------------------------------" << std::endl;
 
 1258    std::cout << 
"## Test :: Matrix" << std::endl;
 
 1259    std::cout << 
"----------------------------------------------" << std::endl;
 
 1260    std::cout << 
"----------------------------------------------" << std::endl;
 
 1261    std::cout << std::endl;
 
 1263    int retval = EXIT_SUCCESS;
 
 1281    std::cout << std::endl;
 
 1282    std::cout << 
"----------------------------------------------" << std::endl;
 
 1283    std::cout << std::endl;
 
 1286       NumericT epsilon = 
NumericT(1.0E-3);
 
 1287       std::cout << 
"# Testing setup:" << std::endl;
 
 1288       std::cout << 
"  eps:     " << epsilon << std::endl;
 
 1289       std::cout << 
"  numeric: float" << std::endl;
 
 1290       std::cout << 
"  layout: column-major" << std::endl;
 
 1291       retval = test<NumericT, viennacl::column_major>(epsilon);
 
 1292       if ( retval == EXIT_SUCCESS )
 
 1293          std::cout << 
"# Test passed" << std::endl;
 
 1297    std::cout << std::endl;
 
 1298    std::cout << 
"----------------------------------------------" << std::endl;
 
 1299    std::cout << std::endl;
 
 1302 #ifdef VIENNACL_WITH_OPENCL 
 1308          NumericT epsilon = 1.0E-11;
 
 1309          std::cout << 
"# Testing setup:" << std::endl;
 
 1310          std::cout << 
"  eps:     " << epsilon << std::endl;
 
 1311          std::cout << 
"  numeric: double" << std::endl;
 
 1312          std::cout << 
"  layout: row-major" << std::endl;
 
 1313          retval = test<NumericT, viennacl::row_major>(epsilon);
 
 1314             if ( retval == EXIT_SUCCESS )
 
 1315                std::cout << 
"# Test passed" << std::endl;
 
 1319       std::cout << std::endl;
 
 1320       std::cout << 
"----------------------------------------------" << std::endl;
 
 1321       std::cout << std::endl;
 
 1324          NumericT epsilon = 1.0E-11;
 
 1325          std::cout << 
"# Testing setup:" << std::endl;
 
 1326          std::cout << 
"  eps:     " << epsilon << std::endl;
 
 1327          std::cout << 
"  numeric: double" << std::endl;
 
 1328          std::cout << 
"  layout: column-major" << std::endl;
 
 1329          retval = test<NumericT, viennacl::column_major>(epsilon);
 
 1330             if ( retval == EXIT_SUCCESS )
 
 1331                std::cout << 
"# Test passed" << std::endl;
 
 1335       std::cout << std::endl;
 
 1336       std::cout << 
"----------------------------------------------" << std::endl;
 
 1337       std::cout << std::endl;
 
 1340    std::cout << std::endl;
 
 1341    std::cout << 
"------- Test completed --------" << std::endl;
 
 1342    std::cout << std::endl;
 
This class represents a single scalar value on the GPU and behaves mostly like a built-in scalar type...
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
Class for representing strided submatrices of a bigger matrix A. 
std::vector< std::vector< NumericT > > trans(std::vector< std::vector< NumericT > > const &A)
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Implementation of the dense matrix class. 
viennacl::vector_expression< const viennacl::matrix_base< NumericT >, const viennacl::matrix_base< NumericT >, viennacl::op_row_sum > row_sum(viennacl::matrix_base< NumericT > const &A)
User interface function for computing the sum of all elements of each row of a matrix. 
void lu_substitute(matrix< NumericT, F1, AlignmentV1 > const &A, matrix< NumericT, F2, AlignmentV2 > &B)
LU substitution for the system LU = rhs. 
A tag class representing a lower triangular matrix. 
void inplace_solve_upper(std::vector< std::vector< NumericT > > const &A, std::vector< NumericT > &b, bool unit_diagonal)
void finish()
Synchronizes the execution. finish() will only return after all compute kernels (CUDA, OpenCL) have completed. 
viennacl::scalar< int > s2
viennacl::scalar< float > s1
T max(const T &lhs, const T &rhs)
Maximum. 
viennacl::ocl::device const & current_device()
Convenience function for returning the active device in the current context. 
VectorT solve(MatrixT const &matrix, VectorT const &rhs, bicgstab_tag const &tag, PreconditionerT const &precond)
viennacl::vector< float > v1
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
void inplace_solve(std::vector< std::vector< NumericT > > const &A, std::vector< NumericT > &b, viennacl::linalg::upper_tag)
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.) 
Class for representing non-strided subvectors of a bigger vector x. 
A tag class representing an upper triangular matrix. 
int test_solve(Epsilon const &epsilon, STLMatrixType &std_m1, STLVectorType &std_v1, VCLMatrixType &vcl_m1, VCLVectorType1 &vcl_v1)
Class for representing strided subvectors of a bigger vector x. 
bool double_support() const 
ViennaCL convenience function: Returns true if the device supports double precision. 
vector_expression< const matrix_base< NumericT >, const int, op_matrix_diag > diag(const matrix_base< NumericT > &A, int k=0)
Implementations of LU factorization for row-major and column-major dense matrices. 
Implementations of dense direct solvers are found here. 
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_row > row(const matrix_base< NumericT, F > &A, unsigned int i)
viennacl::matrix_expression< const vector_base< NumericT >, const vector_base< NumericT >, op_prod > outer_prod(const vector_base< NumericT > &vec1, const vector_base< NumericT > &vec2)
Returns a proxy class for the operation mat += vec1 * vec2^T, i.e. a rank 1 update. 
Stub routines for the summation of elements in a vector, or all elements in either a row or column of...
viennacl::vector< int > v2
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
T norm_inf(std::vector< T, A > const &v1)
void copy(std::vector< NumericT > &cpu_vec, circulant_matrix< NumericT, AlignmentV > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
A small collection of sequential random number generators. 
A range class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded. 
A tag class representing a lower triangular matrix with unit diagonal. 
int test_prod_rank1(Epsilon const &epsilon, STLMatrixType &std_m1, STLVectorType &std_v1, STLVectorType &std_v2, STLMatrixType &std_m2, VCLMatrixType &vcl_m1, VCLVectorType1 &vcl_v1, VCLVectorType2 &vcl_v2, VCLMatrixType &vcl_m2)
ScalarType diff(ScalarType &s1, viennacl::scalar< ScalarType > &s2)
void inplace_solve_lower(std::vector< std::vector< NumericT > > const &A, std::vector< NumericT > &b, bool unit_diagonal)
Class for representing non-strided submatrices of a bigger matrix A. 
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_column > column(const matrix_base< NumericT, F > &A, unsigned int j)
A slice class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded. 
viennacl::vector_expression< const viennacl::matrix_base< NumericT >, const viennacl::matrix_base< NumericT >, viennacl::op_col_sum > column_sum(viennacl::matrix_base< NumericT > const &A)
User interface function for computing the sum of all elements of each column of a matrix...
Implementation of the ViennaCL scalar class. 
int test(Epsilon const &epsilon)
void lu_factorize(matrix< NumericT, viennacl::row_major > &A)
LU factorization of a row-major dense matrix. 
A tag class representing an upper triangular matrix with unit diagonal. 
std::vector< NumericT > solve(std::vector< std::vector< NumericT > > const &A, std::vector< NumericT > const &b, TagT)