Annotation of embedaddon/php/ext/bcmath/libbcmath/src/sqrt.c, revision 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>