Annotation of embedaddon/php/ext/bcmath/libbcmath/src/raise.c, revision 1.1.1.1
1.1 misho 1: /* raise.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:
42: /* Raise NUM1 to the NUM2 power. The result is placed in RESULT.
43: Maximum exponent is LONG_MAX. If a NUM2 is not an integer,
44: only the integer part is used. */
45:
46: void
47: bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale TSRMLS_DC)
48: {
49: bc_num temp, power;
50: long exponent;
51: int rscale;
52: int pwrscale;
53: int calcscale;
54: char neg;
55:
56: /* Check the exponent for scale digits and convert to a long. */
57: if (num2->n_scale != 0)
58: bc_rt_warn ("non-zero scale in exponent");
59: exponent = bc_num2long (num2);
60: if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
61: bc_rt_error ("exponent too large in raise");
62:
63: /* Special case if exponent is a zero. */
64: if (exponent == 0)
65: {
66: bc_free_num (result);
67: *result = bc_copy_num (BCG(_one_));
68: return;
69: }
70:
71: /* Other initializations. */
72: if (exponent < 0)
73: {
74: neg = TRUE;
75: exponent = -exponent;
76: rscale = scale;
77: }
78: else
79: {
80: neg = FALSE;
81: rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));
82: }
83:
84: /* Set initial value of temp. */
85: power = bc_copy_num (num1);
86: pwrscale = num1->n_scale;
87: while ((exponent & 1) == 0)
88: {
89: pwrscale = 2*pwrscale;
90: bc_multiply (power, power, &power, pwrscale TSRMLS_CC);
91: exponent = exponent >> 1;
92: }
93: temp = bc_copy_num (power);
94: calcscale = pwrscale;
95: exponent = exponent >> 1;
96:
97: /* Do the calculation. */
98: while (exponent > 0)
99: {
100: pwrscale = 2*pwrscale;
101: bc_multiply (power, power, &power, pwrscale TSRMLS_CC);
102: if ((exponent & 1) == 1) {
103: calcscale = pwrscale + calcscale;
104: bc_multiply (temp, power, &temp, calcscale TSRMLS_CC);
105: }
106: exponent = exponent >> 1;
107: }
108:
109: /* Assign the value. */
110: if (neg)
111: {
112: bc_divide (BCG(_one_), temp, result, rscale TSRMLS_CC);
113: bc_free_num (&temp);
114: }
115: else
116: {
117: bc_free_num (result);
118: *result = temp;
119: if ((*result)->n_scale > rscale)
120: (*result)->n_scale = rscale;
121: }
122: bc_free_num (&power);
123: }
124:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>