mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 01:50:30 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Boost example/findroot_demo.cpp
 | |
|  * find zero points of some function by dichotomy
 | |
|  *
 | |
|  * Copyright 2000 Jens Maurer
 | |
|  * Copyright 2002-2003 Guillaume Melquiond
 | |
|  *
 | |
|  * Distributed under the Boost Software License, Version 1.0.
 | |
|  * (See accompanying file LICENSE_1_0.txt or
 | |
|  * copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
|  *
 | |
|  * The idea and the 2D function are based on RVInterval,
 | |
|  * which contains the following copyright notice:
 | |
| 
 | |
|         This file is copyrighted 1996 by Ronald Van Iwaarden.
 | |
| 
 | |
|         Permission is hereby granted, without written agreement and
 | |
|         without license or royalty fees, to use, copy, modify, and
 | |
|         distribute this software and its documentation for any
 | |
|         purpose, subject to the following conditions:
 | |
|         
 | |
|         The above license notice and this permission notice shall
 | |
|         appear in all copies or substantial portions of this software.
 | |
|         
 | |
|         The name "RVInterval" cannot be used for any modified form of
 | |
|         this software that does not originate from the authors.
 | |
|         Nevertheless, the name "RVInterval" may and should be used to
 | |
|         designate the optimization software implemented and described
 | |
|         in this package, even if embedded in any other system, as long
 | |
|         as any portion of this code remains.
 | |
|         
 | |
|         The authors specifically disclaim any warranties, including,
 | |
|         but not limited to, the implied warranties of merchantability
 | |
|         and fitness for a particular purpose.  The software provided
 | |
|         hereunder is on an "as is" basis, and the authors have no
 | |
|         obligation to provide maintenance, support, updates,
 | |
|         enhancements, or modifications.  In no event shall the authors
 | |
|         be liable to any party for direct, indirect, special,
 | |
|         incidental, or consequential damages arising out of the use of
 | |
|         this software and its documentation.      
 | |
| */
 | |
| 
 | |
| #include <boost/numeric/interval.hpp>    // must be first for <limits> workaround
 | |
| #include <list>
 | |
| #include <deque>
 | |
| #include <vector>
 | |
| #include <fstream>
 | |
| #include <iostream>
 | |
| 
 | |
| 
 | |
| template<class T>
 | |
| struct test_func2d
 | |
| {
 | |
|   T operator()(T x, T y) const
 | |
|   {
 | |
|     return sin(x)*cos(y) - exp(x*y)/45.0 * (pow(x+y, 2)+100.0) - 
 | |
|       cos(sin(y))*y/4.0;
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <class T>
 | |
| struct test_func1d
 | |
| {
 | |
|   T operator()(T x) const
 | |
|   {
 | |
|     return sin(x)/(x*x+1.0);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template<class T>
 | |
| struct test_func1d_2
 | |
| {
 | |
|   T operator()(T x) const
 | |
|   {
 | |
|     using std::sqrt;
 | |
|     return sqrt(x*x-1.0);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template<class Function, class I>
 | |
| void find_zeros(std::ostream & os, Function f, I searchrange)
 | |
| {
 | |
|   std::list<I> l, done;
 | |
|   l.push_back(searchrange);
 | |
|   while(!l.empty()) {
 | |
|     I range = l.front();
 | |
|     l.pop_front();
 | |
|     I val = f(range);
 | |
|     if (zero_in(val)) {
 | |
|       if(width(range) < 1e-6) {
 | |
|         os << range << '\n';
 | |
|         continue;
 | |
|       }
 | |
|       // there's still a solution hidden somewhere
 | |
|       std::pair<I,I> p = bisect(range);
 | |
|       l.push_back(p.first);
 | |
|       l.push_back(p.second);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| template<class T>
 | |
| std::ostream &operator<<(std::ostream &os, const std::pair<T, T> &x) {
 | |
|   os << "(" << x.first << ", " << x.second << ")";
 | |
|   return os;
 | |
| }
 | |
| 
 | |
| template<class T, class Policies>
 | |
| std::ostream &operator<<(std::ostream &os,
 | |
|                          const boost::numeric::interval<T, Policies> &x) {
 | |
|   os << "[" << x.lower() << ", " << x.upper() << "]";
 | |
|   return os;
 | |
| }
 | |
| 
 | |
| static const double epsilon = 5e-3;
 | |
| 
 | |
| template<class Function, class I>
 | |
| void find_zeros(std::ostream & os, Function f, I rx, I ry)
 | |
| {
 | |
|   typedef std::pair<I, I> rectangle;
 | |
|   typedef std::deque<rectangle> container;
 | |
|   container l, done;
 | |
|   // l.reserve(50);
 | |
|   l.push_back(std::make_pair(rx, ry));
 | |
|   for(int i = 1; !l.empty(); ++i) {
 | |
|     rectangle rect = l.front();
 | |
|     l.pop_front();
 | |
|     I val = f(rect.first, rect.second);
 | |
|     if (zero_in(val)) {
 | |
|       if(width(rect.first) < epsilon && width(rect.second) < epsilon) {
 | |
|         os << median(rect.first) << " " << median(rect.second) << " "
 | |
|            << lower(rect.first) << " " << upper(rect.first) << " "
 | |
|            << lower(rect.second) << " " << upper(rect.second) 
 | |
|            << '\n';
 | |
|       } else {
 | |
|         if(width(rect.first) > width(rect.second)) {
 | |
|           std::pair<I,I> p = bisect(rect.first);
 | |
|           l.push_back(std::make_pair(p.first, rect.second));
 | |
|           l.push_back(std::make_pair(p.second, rect.second));
 | |
|         } else {
 | |
|           std::pair<I,I> p = bisect(rect.second);
 | |
|           l.push_back(std::make_pair(rect.first, p.first));
 | |
|           l.push_back(std::make_pair(rect.first, p.second));
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if(i % 10000 == 0)
 | |
|       std::cerr << "\rIteration " << i << ", l.size() = " << l.size();
 | |
|   }
 | |
|   std::cerr << '\n';
 | |
| }
 | |
| 
 | |
| int main()
 | |
| {
 | |
|   using namespace boost;
 | |
|   using namespace numeric;
 | |
|   using namespace interval_lib;
 | |
| 
 | |
|   typedef interval<double,
 | |
|                    policies<save_state<rounded_transc_opp<double> >,
 | |
|                             checking_base<double> > > I;
 | |
| 
 | |
|   std::cout << "Zero points of sin(x)/(x*x+1)\n";
 | |
|   find_zeros(std::cout, test_func1d<I>(), I(-11, 10));
 | |
|   std::cout << "Zero points of sqrt(x*x-1)\n";
 | |
|   find_zeros(std::cout, test_func1d_2<I>(), I(-5, 6));
 | |
|   std::cout << "Zero points of Van Iwaarden's 2D function\n";
 | |
|   std::ofstream f("func2d.data");
 | |
|   find_zeros(f, test_func2d<I>(), I(-20, 20), I(-20, 20));
 | |
|   std::cout << "Use gnuplot, command 'plot \"func2d.data\" with dots'   to plot\n";
 | |
| }
 |