Google Answers Logo
View Question
 
Q: Debug of this program ( No Answer,   2 Comments )
Question  
Subject: Debug of this program
Category: Computers > Algorithms
Asked by: july2003-ga
List Price: $10.00
Posted: 22 Jun 2003 19:53 PDT
Expires: 22 Jul 2003 19:53 PDT
Question ID: 220556
The following code is to find a root for the polynomial, but it seems
to have the limitation on the order sicne the code as the follows
enountered a run time crash. Would you kind to let me know the bug of
this program and how to solve it.
	
/*const FLOAT	*a,		 	 Coefficients 
	FLOAT			*u,			 Real component of each root 
	FLOAT			*v,			 Imaginary component of each root 
	FLOAT			*conv,		 Convergence constant associated with each root 
	register long	n,			 Degree of polynomial (order-1) 
	long			maxiter,	 Maximum number of iterations 
	long			fig			 The number of decimal figures to be computed 
	*/
//#include <fp.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>

#ifdef DOUBLE_PRECISION
//# define FLOAT double
# define PARAMFLOAT double_t
#else	/* DOUBLE_PRECISION */
# define FLOAT float
# define PARAMFLOAT float_t
#endif	/* DOUBLE_PRECISION */


void FindPolynomialRoots( const float *a,float *u,float
*v,float*conv,register long	n,long	maxiter,long fig);

#define MAXN 16

int main (){
	float *Coeff;
	float *Real;
	float *Imaginary;
	float *Convergence;
	register long Degree;
	long Max_iter;
	long decifig;
	int i;
	int seg_number=25;//max 18
	float s0Val=0.001;
	float wireLeni=0.08636;
	
	
	Coeff=malloc(sizeof(float)*seg_number);
	Real=malloc(sizeof(float)*(seg_number));
	Imaginary=malloc(sizeof(float)*(seg_number));
	Convergence=malloc(sizeof(double)*(seg_number));
	Degree=seg_number-1;
	Max_iter=1000;
	decifig=12;
	for(i=0;i<(seg_number-1);i++){
		Real[i]=Imaginary[i]=Convergence[i]=0;
	}
	for (i=0; i<seg_number; i++){
		Coeff[i]=s0Val;
		printf("Coeff[%d] is %f\n",i,Coeff[i]);
	}
	Coeff[0]=Coeff[0]-wireLeni;
	printf("Coeff[0] is %f\n",Coeff[0]);
	FindPolynomialRoots(Coeff,Real,Imaginary,Convergence,Degree,Max_iter,decifig);
	for(i=0;i<(seg_number-1);i++){
		printf("Real %d is %f",i,Real[i]);
		printf("Imag %d is %f",i,Imaginary[i]);
		printf("\n");
	}
	
	
	return 0;

}

void FindPolynomialRoots( const float *a,float *u,float
*v,float	*conv,register long	n,long	maxiter,long fig){
	int i;
	register int j;
	FLOAT h[MAXN + 3], b[MAXN + 3], c[MAXN + 3], d[MAXN + 3], e[MAXN +
3];
	/* [-2 : n] */
	FLOAT K, ps, qs, pt, qt, s, rev, r;
	int t;
	FLOAT p, q;

	/* Zero elements with negative indices */
	b[2 + -1] = b[2 + -2] =
	c[2 + -1] = c[2 + -2] =
	d[2 + -1] = d[2 + -2] =
	e[2 + -1] = e[2 + -2] =
	h[2 + -1] = h[2 + -2] = 0.0;

	/* Copy polynomial coefficients to working storage */
	for (j = n; j >= 0; j--)
		h[2 + j] = *a++;						/* Note reversal of coefficients */

	t = 1;
	K = pow(10.0, (double)(fig));				/* Relative accuracy */

	for (; h[2 + n] == 0.0; n--) {				/* Look for zero high-order coeff.
*/
		*u++ = 0.0;
		*v++ = 0.0;
		*conv++ = K;
	}

INIT:
	if (n == 0)
		return;

	ps = qs = pt = qt = s = 0.0;
	rev = 1.0;
	K = pow(10.0, (double)(fig));

	if (n == 1) {
		r = -h[2 + 1] / h[2 + 0];
		goto LINEAR;
	}

	for (j = n; j >= 0; j--)					/* Find geometric mean of coeff's */
		if (h[2 + j] != 0.0)
			s += log(fabs(h[2 + j]));
	s = exp(s / (n + 1));

	for (j = n; j >= 0; j--)					/* Normalize coeff's by mean */
		h[2 + j] /= s;

	if (fabs(h[2 + 1] / h[2 + 0]) < fabs(h[2 + n - 1] / h[2 + n])) {
REVERSE:
		t = -t;
		for (j = (n - 1) / 2; j >= 0; j--) {
			s = h[2 + j];
			h[2 + j] = h[2 + n - j];
			h[2 + n - j] = s;
		}
	}
	if (qs != 0.0) {
		p = ps;
		q = qs;
	} else {
		if (h[2 + n - 2] == 0.0) {
			q = 1.0;
			p = -2.0;
		} else {
			q = h[2 + n] / h[2 + n - 2];
			p = (h[2 + n - 1] - q * h[2 + n - 3]) / h[2 + n - 2];
		}
		if (n == 2)
			goto QADRTIC;
		r = 0.0;
	}
ITERATE:
	for (i = maxiter; i > 0; i--) {

		for (j = 0; j <= n; j++) {				/* BAIRSTOW */
			b[2 + j] = h[2 + j] - p * b[2 + j - 1] - q * b[2 + j - 2];
			c[2 + j] = b[2 + j] - p * c[2 + j - 1] - q * c[2 + j - 2];
		}
		if ((h[2 + n - 1] != 0.0) && (b[2 + n - 1] != 0.0)) {
			if (fabs(h[2 + n - 1] / b[2 + n - 1]) >= K) {
				b[2 + n] = h[2 + n] - q * b[2 + n - 2];
			}
			if (b[2 + n] == 0.0)
				goto QADRTIC;
			if (K < fabs(h[2 + n] / b[2 + n]))
				goto QADRTIC;
		}

		for (j = 0; j <= n; j++) {				/* NEWTON */
			d[2 + j] = h[2 + j] + r * d[2 + j - 1];/* Calculate polynomial at r
*/
			e[2 + j] = d[2 + j] + r * e[2 + j - 1];/* Calculate derivative at r
*/
		}
		if (d[2 + n] == 0.0)
			goto LINEAR;
		if (K < fabs(h[2 + n] / d[2 + n]))
			goto LINEAR;

		c[2 + n - 1] = -p * c[2 + n - 2] - q * c[2 + n - 3];
		s = c[2 + n - 2] * c[2 + n - 2] - c[2 + n - 1] * c[2 + n - 3];
		if (s == 0.0) {
			p -= 2.0;
			q *= (q + 1.0);
		} else {
			p += (b[2 + n - 1] * c[2 + n - 2] - b[2 + n] * c[2 + n - 3]) / s;
			q += (-b[2 + n - 1] * c[2 + n - 1] + b[2 + n] * c[2 + n - 2]) / s;
		}
		if (e[2 + n - 1] == 0.0)
			r -= 1.0;							/* Minimum step */
		else
			r -= d[2 + n] / e[2 + n - 1];		/* Newton's iteration */
	}
	ps = pt;
	qs = qt;
	pt = p;
	qt = q;
	if (rev < 0.0)
		K /= 10.0;
	rev = -rev;
	goto REVERSE;

LINEAR:
	if (t < 0)
		r = 1.0 / r;
	n--;
	*u++ = r;
	*v++ = 0.0;
	*conv++ = K;

	for (j = n; j >= 0; j--) {					/* Polynomial deflation by lin-nomial
*/
		if ((d[2 + j] != 0.0) && (fabs(h[2 + j] / d[2 + j]) < K))
			h[2 + j] = d[2 + j];
		else
			h[2 + j] = 0.0;
	}

	if (n == 0)
		return;
	goto ITERATE;

QADRTIC:
	if (t < 0) {
		p /= q;
		q = 1.0 / q;
	}
	n -= 2;

	if (0.0 < (q - (p * p / 4.0))) {			/* Two complex roots */
		*(u + 1) = *u = -p / 2.0;
		u += 2;
		s = sqrt(q - (p * p / 4.0));
		*v++ = s;
		*v++ = -s;
	} else {									/* Two real roots */
		s = sqrt(((p * p / 4.0)) - q);
		if (p < 0.0)
			*u++ = -p / 2.0 + s;
		else
			*u++ = -p / 2.0 - s;
		*u++ = q / u[-1];
		*v++ = 0.0;
		*v++ = 0.0;
	}
	*conv++ = K;
	*conv++ = K;

	for (j = n; j >= 0; j--) {					/* Polynomial deflation by quadratic
*/
		if ((b[2 + j] != 0.0) && (fabs(h[2 + j] / b[2 + j]) < K))
			h[2 + j] = b[2 + j];
		else
			h[2 + j] = 0.0;
	}
	goto INIT;
}


#undef MAXN

Request for Question Clarification by mathtalk-ga on 22 Jun 2003 20:43 PDT
Hi, july2003-ga:

I have compiled your program under Microsoft's Visual Studio .Net
2003.

The compiler emits fourteen warnings, about conversions (on '='
assignment) from double to float and the attendant possibility of loss
of precision.  However the program compiles and links successfully.

When I run the program, there is no "run time crash" that occurs (at
least within the first ten minutes or so).  However the program
appears to be in an infinite loop.

Would you like me to post my analysis of the infinite loop as an
answer?  I will tell you in advance that it is connected with the
compiler warnings noted above.

regards, mathtalk-ga

Clarification of Question by july2003-ga on 22 Jun 2003 21:46 PDT
Hi mathtalk-ga 

Thanks for helping.
Would you able to fix it and let me know where did you fix (Like
highlighting it) since I am not familiar with this alogrithm and this
program is not originally developed by me.
Below is some infomation the author has provided in his code.
Thanks

/*******************************************************************************
 * FindPolynomialRoots
 *
 * The Bairstow and Newton correction formulae are used for a
simultaneous
 * linear and quadratic iterated synthetic division.  The coefficients
of
 * a polynomial of degree n are given as a[i] (i=0,i,..., n) where
a[0] is
 * the constant term.  The coefficients are scaled by dividing them by
 * their geometric mean.  The Bairstow or Newton iteration method will
 * nearly always converge to the number of figures carried, fig,
either to
 * root values or to their reciprocals.  If the simultaneous Newton
and
 * Bairstow iteration fails to converge on root values or their
 * reciprocals in maxiter iterations, the convergence requirement will
be
 * successively reduced by one decimal figure.  This program
anticipates
 * and protects against loss of significance in the quadratic
synthetic
 * division.  (Refer to "On Programming the Numerical Solution of
 * Polynomial Equations," by K. W. Ellenberger, Commun. ACM 3 (Dec.
1960),
 * 644-647.)  The real and imaginary part of each root is stated as
u[i]
 * and v[i], respectively, together with the corresponding constant,
 * conv[i], used in the convergence test.  This program has been used
 * successfully for over a year on the Bendix G15-D (Intercard System)
and
 * has recently been coded for the IBM 709 (Fortran system).
 */

Request for Question Clarification by mathtalk-ga on 22 Jun 2003 22:18 PDT
Well, as I delicately tried to hint, the central problem is not a line
wrong here or there, but the fundamental choice of precision.

As you seem to be compiling the program, the coefficients and roots
are simply floats (single precision), yet you seem to require 12
figures of "relative precision" in the answers.  The root finding
procedure is unable to converge.

So before I can "make the program work" I have to know whether you
meant to use single precision (and back off the number of significant
figures) or you meant to use double precision (and see how much
precision can be obtained).

regards, mathtalk-ga

Clarification of Question by july2003-ga on 24 Jun 2003 08:11 PDT
Hi:

Is float single precision and doulbe double precision?
To get the root like 1.2345 (precision up to the fourth digit beyond
the decimal point) will be fine.
BTW, what's the difference between the single precision and double
precision?
How doest the choice affect the result?
Thanks

Request for Question Clarification by mathtalk-ga on 24 Jun 2003 11:09 PDT
Yes.  In C "float" means the single precision floating point numeric
datatype, and "double" means the double precision floating point
numeric datatype.

The usual "Pentium" Intel microprocessors and most others found in
PC's implement those datatypes according to an IEEE floating point
standard:

[IEEE Standard 754 Floating-Point]
http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html

The single precision "float" takes up 32 bits (4 bytes), some of which
is used to hold the floating point exponent and sign, with 23 bits
left to store the mantissa (fractional part of a number after
normalizing for powers of two).  The double precision "double" takes
up 64 bits (8 bytes), and despite allowing more space for the
exponent, there is still 52 bits for a mantissa or fractional part. 
The (relative) precision of these numeric datatypes depends on the
length of the mantissa, so "double" actually is more than twice as
precise as a "float" in that sense (52 bits being more than twice 23
bits).

In my opinion the "float" datatype is useless for your computational
purposes.  The savings of "space" for the handful of variables can
hardly have any real merit, nor is there economy of time in performing
computations with the less precise "float" over "double".  The
floating point arithmetic is almost certain to be done with a "math
coprocessor" instruction that takes away essentially all of the
performance penalty of working with doubles.  [Graphics processing is
done with a lot of single precision computations performed in
parallel.]

Note that while you state the purpose of the code as "to find a root
for the polynomial," the comments in the code itself indicate that it
tries to find "roots" (plural).  In particular the section of code
which will attempt to perform "deflation" will not produce accurate
roots after an "inaccurate" one is removed from the polynomial by
(synthetic) division.

If you want code that approximates to limited accuracy to a single
root of a polynomial, then I would not use the approach outlined in
this code.  A simple bisection method would be more than adequate for
approximating a real root of a real polynomial to (say) five digits. 
Complex roots of real polynomials are a bit trickier, which is where
Bairstow's method comes into play.

If your goal is rather to make the FindPolynomialRoots subroutine
work, so that it locates all polynomial roots as reliably as possible,
then perhaps some work on this program makes sense.  After working
with the code to this point I feel the $10 list price you have
initially offered is not sufficient for the time it will take to do
the debugging needed to get the code working in reliable fashion.

Although another researcher may take an interest in working it at the
offered price, you may want to review the Google Answer pricing
guidelines here:

http://answers.google.com/answers/pricing.html   
  
Multi-part questions are normally priced at $50 and above, and I'm
inclined to think of debugging a program of this complexity as a
multi-part question.

regards, mathtalk-ga

Clarification of Question by july2003-ga on 24 Jun 2003 14:55 PDT
Hi:

I am confused..
If my purpose is to let the program work for the case I set
(int seg_number=25;float s0Val=0.001;float wireLeni=0.08636;)
and let the result could be obtained as :
  -1.2876          
  -1.2103 + 0.2749i
  -1.2103 - 0.2749i
  -1.0618 + 0.5757i
  -1.0618 - 0.5757i
  -0.8566 + 0.8420i
  -0.8566 - 0.8420i
  -0.6013 + 1.0565i
  -0.6013 - 1.0565i
  -0.3267 + 1.2089i
  -0.3267 - 1.2089i
  -0.0571 + 1.2448i
  -0.0571 - 1.2448i
   0.2499 + 1.1776i
   0.2499 - 1.1776i
   0.5488 + 1.0478i
   0.5488 - 1.0478i
   0.8064 + 0.8573i
   0.8064 - 0.8573i
   1.0000 + 0.6181i
   1.0000 - 0.6181i
   1.1045 + 0.3407i
   1.1045 - 0.3407i
   1.0960  

Which one (single precision or double precision) will be work for it?
Will this program need to be modified a lot?
Thanks

Request for Question Clarification by mathtalk-ga on 24 Jun 2003 23:50 PDT
In order to find as many roots as you have here, it only makes sense
to store the coefficients in double precision.

If you want to round the roots to four decimal places at the end of
the computation, then that's simply a matter of output formatting. 
The internal computations should be done as accurately as possible.

Apparently what was once a reliably working program on an entirely
different platform (mainframe?), possibily written in a different
language, has been "ported" to the code you now have.

If so it seems likely that that code can be made to work without "a
lot" of modification.  However debugging the code is presumably a
matter of a few hours work, not a few minutes.

Given the effort involved to understand what the code is doing and
how, it would only make sense to add substantial comments at this
point about its algorithmic aspects, for the sake of future
maintenance.

best wishes, mathtalk-ga
Answer  
There is no answer at this time.

Comments  
Subject: Re: Debug of this program
From: mathtalk-ga on 22 Jun 2003 22:29 PDT
 
My guess is that the <fp.h> header file, which is not a standard
include and which you apparently decided to comment out, was intended
to distinguish between using double precision and using single (float)
precision.  Based on the presence of a macro DOUBLE_PRECISION, the
datatype FLOAT would be mapped either to double or (else) to float.

Since the macro is not defined, the latter path is taken in
compilation.  Single precision provides not quite 7 decimal figures of
precision in the Intel PC architecture.  Possibly in the (mainframe?)
architecture for which this program was originally developed, the
sample input of 12 digits of precision might have been attainable with
floats.  The C standard really only requires that double mean at least
as precise as float, if memory serves.

regards, mathtalk-ga
Subject: Re: Debug of this program
From: mathtalk-ga on 22 Jun 2003 22:36 PDT
 
Oops, single precision provides 7.2 something digits of precision in
the Intel architecture... I forgot the "implied" leading 1 bit (plus
23 bits of mantissa).

-- mathtalk-ga

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy