// (Refer to file stability.cpp or stability-exact.cpp for more information.) #ifndef MINIBALL_STABILITY #define MINIBALL_STABILITY #include #include #include #include #include #include #include // A functor to convert doubles to some other type T: template struct fromDouble { typedef T Result; const T operator()(const double x) { return static_cast(x); } }; // A class to build an iterator from a functor and an iterator. // Assumes that Functor::Result is the return type of // Functor::operator(). template class FunctorIterator { private: Iterator it; Functor f; public: typedef typename Functor::Result Result; FunctorIterator(Iterator it) : it(it) {} FunctorIterator(Iterator it,const Functor& f) : it(it), f(f) {} const Result operator*() { return f(*it); } FunctorIterator& operator++() { ++it; return *this; } FunctorIterator operator++(int) { FunctorIterator old(*this); ++(*this); return old; } bool operator!=(const FunctorIterator& i) { return it != i.it; } }; // We start with the definition of a sphere class parametrized by // the number type and the dimension: template class Ball { private: // representation: Number c[d]; Number r; public: // construction: // Construct a ball with radius r and center coordinates // from the range [first,first+d). template Ball(InputIterator first,const Number& r) : r(r) { assert(r >= 0); std::copy(first,first+d,c); } public: // access: // Returns the radius. const Number& radius() const { return r; } // Returns an iterator to the first coordinate of the center. const Number *center() const { return c; } // Returns the i-th coordinate for 0<=i defined above: template struct BallTraits { // constants: static const int D = d; // types: typedef Ball Sphere; typedef NumberType FT; typedef CGAL::Default_algorithm Algorithm; typedef Sqrt Use_square_roots; typedef FunctorIterator< const StorageNumberType *, fromDouble > Cartesian_const_iterator; // routines: inline static Cartesian_const_iterator center_cartesian_begin(const Sphere& b) { return Cartesian_const_iterator(b.center()); } inline static FT radius(const Sphere& b) { return static_cast(b.radius()); } }; // A portable random number generator class: class Uniform { private: int lastNo; public: Uniform() : lastNo(230575L) {} double next() { const int a = 16807L, m = 2147483647L, q = 127773L, r = 2836L; int gamma = a * (lastNo % q) - r * (lastNo / q); if (gamma > 0) lastNo = gamma; else lastNo = gamma + m; return static_cast(lastNo)/m; } }; enum Perturbation { None=0, Tiny=1, Small=2, Medium=3, Large=4 }; // The following routine reads a set of balls in R^d from a certain // file, embeds them into R^D and perturbs their coordinates by a // certain amount of pseudo-random noise. Finally, each ball is // duplicated copies times. The resulting set of balls is returned in // the variable balls. template void readConfiguration(const std::string& name, // name of the configuration Perturbation perturb, // amount of perturbation double magnitude, // magnitude of perturbation int copies, // number of copies std::vector< Ball >& balls) { // clear set and open data file: balls.clear(); std::ifstream data(name.c_str()); // determine amount of permutation: Uniform rng; const double amounts[5] = { 0, 1e-50, 1e-30, 1e-10, 1e-3 }; double amount = magnitude * amounts[static_cast(perturb)]; // read number of input balls: int n; data >> n; for (int i=0; i> c[j]; data >> r; // insert duplicates: for (int k=0; k(ce,r)); } } } // Converts a string to some type T. template T strTo(const std::string& str) { std::stringstream strm(str); T t; strm >> t; return t; } // Converts a value to a string. template std::string toStr(const T& t) { std::stringstream strm; strm << t; return strm.str(); } struct RunFlag {}; struct BuildFlag {}; template void atomicTest(const int,const std::string&,Perturbation, const std::vector< Ball >& S,RunFlag); template void atomicTest(const int,const std::string&,Perturbation, const std::vector< Ball >& S,BuildFlag); // (See routine basicTest() below.) int from = 0, to = 1000, curr = -1; template void basicTest(const std::string& name,double magnitude, Perturbation perturb,int copies) { // decide whether to do the test or not: ++curr; if (curr < from || curr > to) return; // construct the set of balls: std::vector< Ball > S; readConfiguration(name,perturb,magnitude,copies,S); // perform test: std::cout << std::endl << " Perturbation: "; switch (perturb) { case None: std::cout << "none" << std::endl; break; case Tiny: std::cout << "10^-50" << std::endl; break; case Small: std::cout << "10^-30" << std::endl; break; case Medium: std::cout << "10^-10" << std::endl; break; case Large: std::cout << "10^-3" << std::endl; break; } atomicTest(curr,name,perturb,S,Flag()); } template void test(const std::string& f,double magnitude) { using std::cout; using std::endl; cout << f << endl; cout << " Set (d): "; basicTest(f,magnitude,None,1); basicTest(f,magnitude,Tiny,1); basicTest(f,magnitude,Small,1); basicTest(f,magnitude,Medium,1); basicTest(f,magnitude,Large,1); cout << endl; cout << " Multiset (d): "; basicTest(f,magnitude,None,10); basicTest(f,magnitude,Tiny,10); basicTest(f,magnitude,Small,10); basicTest(f,magnitude,Medium,10); basicTest(f,magnitude,Large,10); cout << endl; cout << " Set (D): "; basicTest(f,magnitude,None,1); basicTest(f,magnitude,Tiny,1); basicTest(f,magnitude,Small,1); basicTest(f,magnitude,Medium,1); basicTest(f,magnitude,Large,1); cout << endl; cout << " Multiset (D): "; basicTest(f,magnitude,None,10); basicTest(f,magnitude,Tiny,10); basicTest(f,magnitude,Small,10); basicTest(f,magnitude,Medium,10); basicTest(f,magnitude,Large,10); cout << endl; cout << endl; } template void mainTest() { test<2,Flag>("data/cocircular_points_small_radius_2.data",1e8); test<2,Flag>("data/cocircular_points_large_radius_2.data",1e9); test<3,Flag>("data/almost_cospherical_points_3.data",1); test<10,Flag>("data/almost_cospherical_points_10.data",1); test<3,Flag>("data/longitude_latitude_model_3.data",1); test<3,Flag>("data/random_points_3.data",1); test<5,Flag>("data/random_points_5.data",1); test<10,Flag>("data/random_points_10.data",1); test<10,Flag>("data/simplex_10.data",1); test<15,Flag>("data/simplex_15.data",1); test<10,Flag>("data/cube_10.data",1); test<12,Flag>("data/cube_12.data",1); test<2,Flag>("data/balls_on_boundary_2.data",1); test<3,Flag>("data/balls_on_boundary_3.data",1); } #endif // MINIBALL_STABILITY