generic_salembier_float2.cc

00001 // Copyright (C) 2006  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
00016 // Boston, Boston, MA 02110-1301, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #include <cstdlib>
00029 #include <functional>
00030 
00031 #include <ntg/int.hh>
00032 #include <oln/basics2d.hh>
00033 #include <oln/utils/timer.hh>
00034 
00035 #include <oln/lrde/ufmt/generic_salembier.hh>
00036 #include <oln/lrde/efigi/io.hh>
00037 
00038 
00039 void usage(char* argv[])
00040 {
00041   std::cerr << "generic max-tree computation with salembier's flooding"
00042             << " (float version, with a different comparison function)."
00043             << std::endl
00044             << "usage: " << argv[0] << " input.pfm c" << std::endl;
00045   exit(1);
00046 }
00047 
00048 // A comparison functor on floats, inspired from
00049 // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
00050 class almost_greater : public std::binary_function<float, float, bool>
00051 {
00052 public:
00053   almost_greater(float max_relative_error = 0.0000001f,
00054                  float max_absolute_error = 3 * FLT_MIN) :
00055     max_relative_error_ (max_relative_error),
00056     max_absolute_error_ (max_absolute_error)
00057   {
00058   }
00059 
00060   bool
00061   operator() (float a, float b)
00062   {
00063     // Return false if A and B are close numbers, to ensure that the
00064     // equivalence of the ``strict'' weak ordering
00065     // (http://www.sgi.com/tech/stl/StrictWeakOrdering.html) is
00066     // preserved (i.e. to let STL containers using this function
00067     // consider A and B as equal when their difference is small).
00068     if (almost_equal_relative_or_absolute(a, b))
00069       return false;
00070     return a > b;
00071   }
00072 
00073 private:
00074   bool almost_equal_relative_or_absolute(float A, float B)
00075   {
00076     if (fabs(A - B) < max_absolute_error_)
00077       return true;
00078     float relative_error;
00079     if (fabs(B) > fabs(A))
00080       relative_error = fabs((A - B) / B);
00081     else
00082       relative_error = fabs((A - B) / A);
00083     if (relative_error <= max_relative_error_)
00084       return true;
00085     return false;
00086   }
00087 
00088 private:
00089   float max_relative_error_;
00090   float max_absolute_error_;
00091 };
00092 
00093 
00094 int main(int argc, char* argv[])
00095 {
00096   if (argc != 3)
00097     usage(argv);
00098 
00099   using namespace oln;
00100   typedef image2d<float> image_t;
00101 
00102   image_t input = efigi::load_pfm(argv[1]);
00103   assert (input.has_impl());
00104 
00105   int c = atoi(argv[2]);
00106   if (not (c == 2 or c == 4 or c == 8))
00107     usage(argv);
00108 
00109   neighborhood2d nbh;
00110   if (c == 2)
00111     nbh.add(dpoint2d(0, 1));
00112   else
00113     nbh = c == 4 ? neighb_c4() : neighb_c8();
00114 
00115   typedef lrde::ufmt::generic_salembier<image_t, almost_greater> algorithm_t;
00116 
00117   algorithm_t run(input, nbh);
00118   utils::timer t;
00119   t.start();
00120   run.go();
00121   t.stop();
00122   std::cout << "n level roots = " << run.n_level_roots() << std::endl
00123             << "elapsed time  = " << t.last_time() << std::endl;
00124 }

Generated on Tue Feb 20 20:19:43 2007 for Olena by  doxygen 1.5.1