ViennaCL - The Vienna Computing Library  1.5.0
viennacl/linalg/bisect.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_BISECT_HPP_
00002 #define VIENNACL_LINALG_BISECT_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2013, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00027 #include <vector>
00028 #include <cmath>
00029 #include <limits>
00030 #include <cstddef>
00031 #include "viennacl/meta/result_of.hpp"
00032 
00033 namespace viennacl
00034 {
00035   namespace linalg
00036   {
00037 
00038     namespace detail
00039     {
00043       template <typename T, typename OtherVectorType>
00044       void copy_vec_to_vec(viennacl::vector<T> const & src, OtherVectorType & dest)
00045       {
00046         viennacl::copy(src, dest);
00047       }
00048 
00049       template <typename OtherVectorType, typename T>
00050       void copy_vec_to_vec(OtherVectorType const & src, viennacl::vector<T> & dest)
00051       {
00052         viennacl::copy(src, dest);
00053       }
00054 
00055       template <typename VectorType1, typename VectorType2>
00056       void copy_vec_to_vec(VectorType1 const & src, VectorType2 & dest)
00057       {
00058         for (vcl_size_t i=0; i<src.size(); ++i)
00059           dest[i] = src[i];
00060       }
00061     }
00062 
00070     template< typename VectorT >
00071     std::vector<
00072             typename viennacl::result_of::cpu_value_type<typename VectorT::value_type>::type
00073             >
00074     bisect(VectorT const & alphas, VectorT const & betas)
00075     {
00076       typedef typename viennacl::result_of::value_type<VectorT>::type           ScalarType;
00077       typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type    CPU_ScalarType;
00078 
00079       vcl_size_t size = betas.size();
00080       std::vector<CPU_ScalarType>  x_temp(size);
00081 
00082 
00083       std::vector<CPU_ScalarType> beta_bisect;
00084       std::vector<CPU_ScalarType> wu;
00085 
00086       double rel_error = std::numeric_limits<CPU_ScalarType>::epsilon();
00087       beta_bisect.push_back(0);
00088 
00089       for(vcl_size_t i = 1; i < size; i++){
00090               beta_bisect.push_back(betas[i] * betas[i]);
00091       }
00092 
00093       double xmin = alphas[size - 1] - std::fabs(betas[size - 1]);
00094       double xmax = alphas[size - 1] + std::fabs(betas[size - 1]);
00095 
00096       for(vcl_size_t i = 0; i < size - 1; i++)
00097       {
00098         double h = std::fabs(betas[i]) + std::fabs(betas[i + 1]);
00099         if (alphas[i] + h > xmax)
00100           xmax = alphas[i] + h;
00101         if (alphas[i] - h < xmin)
00102           xmin = alphas[i] - h;
00103       }
00104 
00105 
00106       double eps1 = 1e-6;
00107       /*double eps2 = (xmin + xmax > 0) ? (rel_error * xmax) : (-rel_error * xmin);
00108       if(eps1 <= 0)
00109         eps1 = eps2;
00110       else
00111         eps2 = 0.5 * eps1 + 7.0 * eps2; */
00112 
00113       double x0 = xmax;
00114 
00115       for(vcl_size_t i = 0; i < size; i++)
00116       {
00117         x_temp[i] = xmax;
00118         wu.push_back(xmin);
00119       }
00120 
00121       for(long k = static_cast<long>(size) - 1; k >= 0; --k)
00122       {
00123         double xu = xmin;
00124         for(long i = k; i >= 0; --i)
00125         {
00126           if(xu < wu[k-i])
00127           {
00128             xu = wu[i];
00129             break;
00130           }
00131         }
00132 
00133         if(x0 > x_temp[k])
00134           x0 = x_temp[k];
00135 
00136         double x1 = (xu + x0) / 2.0;
00137         while (x0 - xu > 2.0 * rel_error * (std::fabs(xu) + std::fabs(x0)) + eps1)
00138         {
00139           vcl_size_t a = 0;
00140           double q = 1;
00141           for(vcl_size_t i = 0; i < size; i++)
00142           {
00143             if(q != 0)
00144               q = alphas[i] - x1 - beta_bisect[i] / q;
00145             else
00146               q = alphas[i] - x1 - std::fabs(betas[i] / rel_error);
00147 
00148             if(q < 0)
00149               a++;
00150           }
00151 
00152           if (a <= static_cast<vcl_size_t>(k))
00153           {
00154             xu = x1;
00155             if(a < 1)
00156               wu[0] = x1;
00157             else
00158             {
00159               wu[a] = x1;
00160               if(x_temp[a - 1] > x1)
00161                   x_temp[a - 1] = x1;
00162             }
00163           }
00164           else
00165             x0 = x1;
00166 
00167           x1 = (xu + x0) / 2.0;
00168         }
00169         x_temp[k] = x1;
00170       }
00171       return x_temp;
00172     }
00173 
00174   } // end namespace linalg
00175 } // end namespace viennacl
00176 #endif