/*
* surf - visualizing algebraic curves and algebraic surfaces
* Copyright (C) 1996-1997 Friedrich-Alexander-Universitaet
* Erlangen-Nuernberg
* 1997-2000 Johannes Gutenberg-Universitaet Mainz
* Authors: Stephan Endrass, Hans Huelf, Ruediger Oertel,
* Kai Schneider, Ralf Schmitt, Johannes Beigel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
//-----------------------------------------------------------------------------
//---------------------------- Sturmchain.cc ----------------------------------
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <math.h>
#include "def.h"
#include "simple.h"
#include "UniVariatePolynom.h"
#include "Sturmchain.h"
//-----------------------------------------------------------------------------
//------------------ Sturmchain constructor -----------------------------------
//-----------------------------------------------------------------------------
Sturmchain::Sturmchain( const Polyx &Pol )
: Chain(new Polyx[Pol.GetNumber()+1]) // generate sturmchain
{
int i = 0;
Chain[0] = Pol;
Chain[1] = Pol.Derive();
for( i = 2;
Chain[i-1].ShorterThan(Chain[i-2]) && !Chain[i-1].IsConstant();
i++ )
{
Chain[i] = Chain[i-2] % Chain[i-1];
Chain[i].NegateCoeffs();
}
if( Chain[i-1].IsEmpty() ) i--;
Length = i;
}
Sturmchain::~Sturmchain() // cleanup
{
delete [] Chain;
}
// ----------------------------------------------------------------------------
// ------------ return number of signchanges of sturmchain in a ---------------
// ------------ f(a) is given to save computation -----------------------------
// ----------------------------------------------------------------------------
int Sturmchain::SignChange( double x, double Val ) const
{
int result = 0;
for( int i = 1; i < Length; i++ )
{
double ValN = Chain[i].Horner( x );
if(ValN == 0.0) {
continue;
}
if(Val*ValN < 0.0) {
result ++;
}
Val = ValN;
}
return result;
}
// ----------------------------------------------------------------------------
// ------ divides intervall until there is only one root inside ---------------
// ------ is first called from class polyx with last arg maxiterations --------
// ------ and then counts down to zero ----------------------------------------
// ----------------------------------------------------------------------------
int Sturmchain::DivideIntervalMulti( double x1, double fx1, int sx1,
double x2, double fx2, int sx2,
double *Root, int &NumberOfRoots,
int Iterations )
{
int Total = sx1 - sx2; // difference of signchanges between a and b
// is the number of zeroes between a and b
if( Total > 1 )
{
if( --Iterations == 0 )
return FALSE;
double m = ( x1 + x2 ) / 2.0;
double fm = Chain[0].Horner( m );
int sm = SignChange( m, fm );
// check range m...b (upper first to get roots descending)
int Flag = DivideIntervalMulti( m, fm ,sm, x2, fx2, sx2,
Root, NumberOfRoots, Iterations );
// check range a...m
Flag += DivideIntervalMulti( x1, fx1, sx1, m, fm, sm,
Root, NumberOfRoots, Iterations );
return Flag; // >0 if root in one of both ranges
}
if( Total == 1 )
return Chain[0].RootFunction( x2, x1, fx2, fx1, Root, NumberOfRoots );
// root function calls the selected algorithm via function pointer
return FALSE;
}
// ----------------------------------------------------------------------------
// ------- same but get only largest root -------------------------------------
// ----------------------------------------------------------------------------
int Sturmchain::DivideIntervalSingle( double x1, double fx1, int sx1,
double x2, double fx2, int sx2,
double *Root, int &NumberOfRoots,
int Iterations )
{
int Total = sx1 - sx2;
if( Total > 1 )
{
if( --Iterations == 0 )
return FALSE;
double m = ( x1 + x2 ) / 2.0;
double fm = Chain[0].Horner( m );
int sm = SignChange( m, fm );
int Flag = 0;
// if not in m...b
if( !( Flag = DivideIntervalSingle( m, fm ,sm, x2, fx2, sx2,
Root, NumberOfRoots, Iterations ) ) )
// search a...m
Flag = DivideIntervalSingle( x1, fx1, sx1, m, fm, sm, Root,
NumberOfRoots, Iterations );
return Flag;
}
if( Total == 1 )
return Chain[0].RootFunction( x2, x1, fx2, fx1, Root, NumberOfRoots );
return FALSE;
}
// ----------------------------------------------------------------------------
// ------------ end of file Sturmchain.cc -------------------------------------
// ----------------------------------------------------------------------------
syntax highlighted by Code2HTML, v. 0.9.1