Annotation of embedaddon/php/ext/bcmath/libbcmath/src/sqrt.c, revision 1.1.1.1
1.1 misho 1: /* sqrt.c: bcmath library file. */
2: /*
3: Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
4: Copyright (C) 2000 Philip A. Nelson
5:
6: This library is free software; you can redistribute it and/or
7: modify it under the terms of the GNU Lesser General Public
8: License as published by the Free Software Foundation; either
9: version 2 of the License, or (at your option) any later version.
10:
11: This library is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: Lesser General Public License for more details. (COPYING.LIB)
15:
16: You should have received a copy of the GNU Lesser General Public
17: License along with this library; if not, write to:
18:
19: The Free Software Foundation, Inc.
20: 59 Temple Place, Suite 330
21: Boston, MA 02111-1307 USA.
22:
23: You may contact the author by:
24: e-mail: philnelson@acm.org
25: us-mail: Philip A. Nelson
26: Computer Science Department, 9062
27: Western Washington University
28: Bellingham, WA 98226-9062
29:
30: *************************************************************************/
31:
32: #include <config.h>
33: #include <stdio.h>
34: #include <assert.h>
35: #include <stdlib.h>
36: #include <ctype.h>
37: #include <stdarg.h>
38: #include "bcmath.h"
39: #include "private.h"
40:
41: /* Take the square root NUM and return it in NUM with SCALE digits
42: after the decimal place. */
43:
44: int
45: bc_sqrt (bc_num *num, int scale TSRMLS_DC)
46: {
47: int rscale, cmp_res, done;
48: int cscale;
49: bc_num guess, guess1, point5, diff;
50:
51: /* Initial checks. */
52: cmp_res = bc_compare (*num, BCG(_zero_));
53: if (cmp_res < 0)
54: return 0; /* error */
55: else
56: {
57: if (cmp_res == 0)
58: {
59: bc_free_num (num);
60: *num = bc_copy_num (BCG(_zero_));
61: return 1;
62: }
63: }
64: cmp_res = bc_compare (*num, BCG(_one_));
65: if (cmp_res == 0)
66: {
67: bc_free_num (num);
68: *num = bc_copy_num (BCG(_one_));
69: return 1;
70: }
71:
72: /* Initialize the variables. */
73: rscale = MAX (scale, (*num)->n_scale);
74: bc_init_num(&guess TSRMLS_CC);
75: bc_init_num(&guess1 TSRMLS_CC);
76: bc_init_num(&diff TSRMLS_CC);
77: point5 = bc_new_num (1,1);
78: point5->n_value[1] = 5;
79:
80:
81: /* Calculate the initial guess. */
82: if (cmp_res < 0)
83: {
84: /* The number is between 0 and 1. Guess should start at 1. */
85: guess = bc_copy_num (BCG(_one_));
86: cscale = (*num)->n_scale;
87: }
88: else
89: {
90: /* The number is greater than 1. Guess should start at 10^(exp/2). */
91: bc_int2num (&guess,10);
92:
93: bc_int2num (&guess1,(*num)->n_len);
94: bc_multiply (guess1, point5, &guess1, 0 TSRMLS_CC);
95: guess1->n_scale = 0;
96: bc_raise (guess, guess1, &guess, 0 TSRMLS_CC);
97: bc_free_num (&guess1);
98: cscale = 3;
99: }
100:
101: /* Find the square root using Newton's algorithm. */
102: done = FALSE;
103: while (!done)
104: {
105: bc_free_num (&guess1);
106: guess1 = bc_copy_num (guess);
107: bc_divide (*num, guess, &guess, cscale TSRMLS_CC);
108: bc_add (guess, guess1, &guess, 0);
109: bc_multiply (guess, point5, &guess, cscale TSRMLS_CC);
110: bc_sub (guess, guess1, &diff, cscale+1);
111: if (bc_is_near_zero (diff, cscale))
112: {
113: if (cscale < rscale+1)
114: cscale = MIN (cscale*3, rscale+1);
115: else
116: done = TRUE;
117: }
118: }
119:
120: /* Assign the number and clean up. */
121: bc_free_num (num);
122: bc_divide (guess,BCG(_one_),num,rscale TSRMLS_CC);
123: bc_free_num (&guess);
124: bc_free_num (&guess1);
125: bc_free_num (&point5);
126: bc_free_num (&diff);
127: return 1;
128: }
129:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>