bool checkSubArithmeticDSS( const DSL & D,
                            const typename DSL::Point & A, 
                            const typename DSL::Point & B ) 
{
  typedef typename DSL::Fraction Fraction;
  typedef typename DSL::Integer Integer;
  typedef typename DSL::Quotient Quotient;
  typedef typename DSL::Point Point;
  typedef typename DSL::ConstIterator ConstIterator;
  typedef typename DSL::Point2I Point2I;
  typedef typename DSL::Vector2I Vector2I;
  typedef ArithmeticalDSS<ConstIterator, Integer, 4> ADSS;

  ConstIterator it = D.begin( A );
  ConstIterator it_end = D.end( B );
  ADSS dss;
  dss.init( it );
  while ( ( dss.end() != it_end )
          && ( dss.extendForward() ) ) {}
  std::cout << D.a() << " " << D.b() << " " << D.mu() << " "
            << dss.getA() << " " << dss.getB() << " " << dss.getMu() << " "
            << A[0] << " " << A[1] << " " << B[0] << " " << B[1] 
            << std::endl;

  return true;
}
bool checkSubStandardDSLQ0( const DSL & D,
                            const typename DSL::Point & A, 
                            const typename DSL::Point & B ) 
{
  typedef typename DSL::Integer Integer;
  typedef typename DSL::ConstIterator ConstIterator;
  typedef ArithmeticalDSSComputer<ConstIterator, Integer, 4> ADSS;

  DSL S = D.reversedSmartDSS( A, B );
  ConstIterator it = D.begin( A );
  ConstIterator it_end = D.end( B );
  ADSS dss;
  dss.init( it );
  while ( ( dss.end() != it_end )
          && ( dss.extendFront() ) ) {}
  bool ok = S.a() == dss.a() 
    &&  S.b() == dss.b() 
    &&  S.mu() == dss.mu(); 
  if ( ! ok )
    {
      trace.info() << "-------------------------------------------------------"
                   << std::endl;
      trace.info() << "D = " << D // << " U1=" << U1 << " U2=" << U2
                   << " " << D.pattern().rE() << endl;
      trace.info() << "S(" << A << "," << B << ") = "
                   << S << " " << S.pattern() << endl;
      trace.info() << "ArithDSS = " << dss << std::endl;
    }
  // if ( ok )
  //   trace.info() << "========================== OK =========================";
  // else
  //   trace.info() << "eeeeeeeeeeeeeeeeeeeeeeeeee KO eeeeeeeeeeeeeeeeeeeeeeeee";
  // std::cerr << std::endl;
  return ok;
}
bool checkSubArithmeticDSS( const DSL & D,
                            const typename DSL::Point & A, 
                            const typename DSL::Point & B ) 
{
  typedef typename DSL::Integer Integer;
  typedef typename DSL::ConstIterator ConstIterator;
  typedef ArithmeticalDSSComputer<ConstIterator, Integer, 4> ADSS;

  ConstIterator it = D.begin( A );
  ConstIterator it_end = D.end( B );
  ADSS dss;
  dss.init( it );
  while ( ( dss.end() != it_end )
          && ( dss.extendFront() ) ) {}
  std::cout << D.a() << " " << D.b() << " " << D.mu() << " "
            << dss.a() << " " << dss.b() << " " << dss.mu() << " "
            << A[0] << " " << A[1] << " " << B[0] << " " << B[1] 
            << std::endl;

  return true;
}
bool checkSubStandardDSLQ0( const DSL & D,
                            const typename DSL::Point & A, 
                            const typename DSL::Point & B ) 
{
  
  
  DSL S = D.smartDSS( A, B );
  // std::cout << D.a() << " " << D.b() << " " << D.mu() << " "
  //           << S.a() << " " << S.b() << " " << S.mu() << " "
  //           << A[0] << " " << A[1] << " " << B[0] << " " << B[1]
  //           << std::endl;
  return true;
}
bool sameOctantTest(const DSL& dsl1, const DSL& dsl2)
{
  trace.beginBlock ( "Test same octant" );
  trace.info() << dsl1  << " " << dsl2 << std::endl; 
  
  typename DSL::Octant::first_type oc;
  
  return dsl1.sameOctant(dsl2,&oc);

  trace.endBlock();


}
bool checkSubStandardDSLQ0( const DSL & D,
                            const typename DSL::Point & A, 
                            const typename DSL::Point & B ) 
{
  typedef typename DSL::Fraction Fraction;
  typedef typename DSL::Integer Integer;
  typedef typename DSL::Quotient Quotient;
  typedef typename DSL::Point Point;
  typedef typename DSL::ConstIterator ConstIterator;
  typedef typename DSL::Point2I Point2I;
  typedef typename DSL::Vector2I Vector2I;

  DSL S = D.reversedSmartDSS( A, B );
  std::cout << D.a() << " " << D.b() << " " << D.mu() << " "
            << S.a() << " " << S.b() << " " << S.mu() << " "
            << A[0] << " " << A[1] << " " << B[0] << " " << B[1]
            << std::endl;
  return true;
}
bool rangeTest(const DSL& dsl)
{
  ASSERT( dsl.mu() == 0 ); 
  typedef typename DSL::Point Point; 

  unsigned int nbok = 0;
  unsigned int nb = 0;
  
  trace.beginBlock ( "Range/Iterator services..." );
  trace.info() << dsl << std::endl; 

  Point first(0,0); 
  Point last(dsl.b(), dsl.a()); 
  trace.info() << "from " << first << " to " << last << std::endl; 

  if (dsl.isValid())
    nbok++; 
  nb++; 

  trace.info() << "(" << nbok << "/" << nb << ") "
  	       << std::endl;

  {//forward pass  
    typedef typename DSL::ConstIterator I; 
    BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<I> )); 
    BOOST_CONCEPT_ASSERT(( boost_concepts::BidirectionalTraversalConcept<I> ));
    bool res = true; 
    int c = 0; 
    for (I it = dsl.begin(first), itEnd = dsl.end(last); 
	 ( (it != itEnd)&&(res)&&(c<100) ); 
	 ++it, ++c)
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") ";  
	if ( !dsl(*it) )
	  res = false; 
      }
    trace.info() << " : " << c << " points " << std::endl; 
    trace.info() << std::endl; 

    if ( (res)&&(c == (dsl.omega()+1)) ) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;
  }

  {//backward pass
    typedef typename DSL::ConstReverseIterator I; 
    BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<I> )); 
    BOOST_CONCEPT_ASSERT(( boost_concepts::BidirectionalTraversalConcept<I> ));
    bool res = true; 
    int c = 0; 
    for (I it = dsl.rbegin(last), itEnd = dsl.rend(first); 
	 ( (it != itEnd)&&(res)&&(c<100) ); 
	 ++it, ++c)
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") ";  
	if ( !dsl(*it) )
	  res = false; 
      }
    trace.info() << " : " << c << " points " << std::endl; 
    trace.info() << std::endl; 

    if ( (res)&&(c == (dsl.omega()+1)) ) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;
  }

  trace.endBlock();
  
  return nbok == nb;
}
bool testDSLSubsegment(Integer modb)
{
  //typedef long double Number;
  typedef DGtal::DSLSubsegment<Integer,Integer> DSLSubseg;
  //typedef DGtal::DSLSubsegment<Integer,Number> DSLSubsegD;


  typedef ArithDSSIterator<Integer,8> DSSIterator;
  typedef NaiveDSS8<Integer> ArithDSS;

  typedef typename DSLSubseg::Point Point;

  typedef StandardDSLQ0<Fraction> DSL;
  typedef typename DSL::Point PointDSL;

  DGtal::IntegerComputer<Integer> ic;


  // Draw random value for b in [0,modb]
  Integer b( rand() % modb +1);
  
  // Draw random value for a in [0,b]
  Integer a( random() % b +1);
  // Draw a new a while a and b are not coprime (do not divide by
  // the gcd so that b remains in the required interval)
  while(ic.gcd(a,b) !=1)
    a = rand() %b +1;

  // Draw random value for mu in [0,2modb]
  Integer mu = rand() % (2*modb);
  
  Integer l = 200; // max length of the DSSs

  // Draw random values for the subsegment first extremity abscissa
  Integer xf = rand() % modb;
  
  trace.beginBlock("Draw random values for a,b,mu and abscissa of the first point");
  trace.info() << "a b mu xf:" << a << " " << b << " " << mu << " " << xf << std::endl; 
  trace.endBlock();
  trace.info() << std::endl;
  
  int error1 = 0;
  // Consider the subsegment S of the line (a,b,mu), with xf <= x < xf+l
  // Test all the subsegments of S
  
  trace.beginBlock("Compare DSLSubsegment/Farey fan with ArithmeticalDSS algorithm");
  for(unsigned int i = 0; i<l; i++)
    for(unsigned int j = i+1; j<l; j++)
      {
	Integer x1 = xf+i;
	Integer x2 = xf+j;

	Integer y1 = ic.floorDiv(a*x1+mu,b);
	Integer y2 = ic.floorDiv(a*x2+mu,b);
	Point A = Point(x1,y1);
	Point B = Point(x2,y2);
	
	// DSLSubsegment with Farey Fan (O(log(n))
	DSLSubseg DSLsub(a,b,mu,A,B,"farey");
	
	
	// ArithmeticalDSS recognition algorithm (O(n))
	DSSIterator  it(a,b,-mu,A);
	ArithDSS myDSS(*it, *it);
	++it; 
	while ( (*it)[0] <=x2 && myDSS.extendFront(*it))
	  { ++it; }
	
	// If results are different, count an error
	if(DSLsub.getA() != myDSS.a() || DSLsub.getB() != myDSS.b() || DSLsub.getMu() != - myDSS.mu())
	  error1 ++;
      }
  trace.info() << error1 << " errors." << std::endl;
  trace.endBlock();
  trace.info() << std::endl;

  int error2 = 0;
  trace.beginBlock("Compare DSLSubsegment/localCH with DSLSubsegment/FareyFan");
  for(unsigned int i = 0; i<l; i++)
    for(unsigned int j = i+1; j<l; j++)
      {
	Integer x1 = xf+i;
	Integer x2 = xf+j;

	Integer y1 = ic.floorDiv(a*x1+mu,b);
	Integer y2 = ic.floorDiv(a*x2+mu,b);
	Point A = Point(x1,y1);
	Point B = Point(x2,y2);
	
	// DSLSubsegment with local CH (O(log(n))
	DSLSubseg DSLsubCH(a,b,mu,A,B,"localCH");
	
	// DSLSubsegment with Farey Fan (O(log(n))
	DSLSubseg DSLsubF(a,b,mu,A,B,"farey");
	
	
	// If results are different, count an error
	if(DSLsubCH.getA() != DSLsubF.getA() || DSLsubCH.getB() != DSLsubF.getB() || DSLsubCH.getMu() != DSLsubF.getMu())	
	  error2 ++;
	
      }
  trace.info() << error2 << " errors." << std::endl;
  trace.endBlock();
  trace.info() << std::endl;
  
  int error3 = 0;
  trace.beginBlock("Compare DSLSubsegment/FareyFan with ReversedSmartDSS for 4-connected DSL");
  for(unsigned int i = 0; i<l; i++)
    for(unsigned int j = i+1; j<l; j++)
      {
	Integer x1 = xf+i;
	Integer x2 = xf+j;
	
	DSL D( a, b, mu );
	PointDSL AA = D.lowestY( x1 );
	PointDSL BB = D.lowestY( x2 );	
	
	// ReversedSmartDSS algorithm
	DSL S = D.reversedSmartDSS(AA,BB);
	
	// DSLSubsegment algorithm for 4-connected DSL.
	// Application of an horizontal shear transform
	Point A2 = AA;
	A2[0] += A2[1];
	Point B2 = BB;
	B2[0] += B2[1];
		
	// DSLSubsegment algorithm works with the definition 0  <= ab -by + mu <
	// b whereas reversedSmartDSS uses  mu <= ab-by < mu + b 
	// => -mu is introduced in order to compare the results  
	
	DSLSubseg D2(a,a+b,-mu,A2,B2,"farey");
	// The result is (aa,getB()-aa, nu)
	// Compare results of DSLsubseg4 and reversedSmartDSS
	if(!(D2.getA()==S.a() && (D2.getB()-D2.getA())==S.b() && D2.getMu()==-S.mu()))
	  error3 ++;
	
      }
  trace.info() << error3 << " errors." << std::endl;
  trace.endBlock();
  trace.info() << std::endl;
  
  return (error1==0 && error2==0 && error3==0);

}
bool rangeTest(const DSL& dsl)
{
  typedef typename DSL::Point Point; 

  unsigned int nbok = 0;
  unsigned int nb = 0;
  
  trace.beginBlock ( "Range/Iterator services..." );
  trace.info() << dsl << std::endl; 

  Point origin = dsl.getPoint();
  Point first = Point(origin[0]-dsl.b(), origin[1]-dsl.a());
  Point last = Point(first[0]+dsl.b(), first[1]+dsl.a()); 
  trace.info() << "from " << first << " to " << last << std::endl; 

  if (dsl.isValid())
    nbok++; 
  nb++; 

  trace.info() << "(" << nbok << "/" << nb << ") "
  	       << std::endl;

  {//forward pass  
    typedef typename DSL::ConstIterator I; 
    BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<I> )); 
    BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<I> ));
    bool res = true; 
    int c = 0; 
    for (I it = dsl.begin(first), itEnd = dsl.end(last); 
	 ( (it != itEnd)&&(res)&&(c<100) ); 
	 ++it, ++c)
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") ";  
	if ( !dsl(*it) )
	  res = false; 
      }
    trace.info() << " : " << c << " points " << std::endl; 
    trace.info() << std::endl; 

    if ( (res)&&(c == (dsl.omega()+1)) ) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;
  }

  {//backward pass
    typedef typename DSL::ConstReverseIterator I; 
    BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<I> )); 
    BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<I> ));
    bool res = true; 
    int c = 0; 
    for (I it = dsl.rbegin(last), itEnd = dsl.rend(first); 
	 ( (it != itEnd)&&(res)&&(c<100) ); 
	 ++it, ++c)
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") ";  
	if ( !dsl(*it) )
	  res = false; 
      }
    trace.info() << " : " << c << " points " << std::endl; 
    trace.info() << std::endl; 

    if ( (res)&&(c == (dsl.omega()+1)) ) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;
  }

  {//random access services  
    typedef typename DSL::ConstIterator I; 
    BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<I> )); 
    BOOST_CONCEPT_ASSERT(( boost_concepts::RandomAccessTraversalConcept<I> ));
    bool res = true; 
    int c = 0; 
    I itBegin = dsl.begin(first); 
    for (I it = itBegin, itEnd = dsl.end(last); 
	 ( (it != itEnd)&&(res)&&(c<100) ); 
	 ++it, ++c)
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") " << it.remainder() << ", ";  
	I it2 = ( itBegin + c ); 
	if ( (it != it2) || ((it2 - itBegin) != c) )
	  res = false; 
      }
    int n = c; 
    trace.info() << " : " << c << " points " << std::endl; 
    trace.info() << std::endl; 

    if (res) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;

    --n; 
    c = 0; 
    for (I it = (itBegin+n), itEnd = itBegin; 
	 ( (it!=itEnd)&&(res)&&(c < 100) );
	 --it, ++c )
      {
	trace.info() << "(" << it->operator[](0) << "," << it->operator[](1) << ") " << it.remainder() << ", ";  
	I it2 = ( (itBegin+n) - c ); 
	if ( (it != it2) || (((itBegin+n) - it2) != c) )
	  res = false; 
      }

    if (res) 
      nbok++; 
    nb++;

    trace.info() << "(" << nbok << "/" << nb << ") "
		 << std::endl;
  }


  trace.endBlock();
  
  return nbok == nb;
}