Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/libtommath/bn_mp_sqrt.c @ 25

Last change on this file since 25 was 25, checked in by landauf, 16 years ago

added tcl to libs

File size: 2.7 KB
Line 
1#include <tommath.h>
2
3#ifdef BN_MP_SQRT_C
4/* LibTomMath, multiple-precision integer library -- Tom St Denis
5 *
6 * LibTomMath is a library that provides multiple-precision
7 * integer arithmetic as well as number theoretic functionality.
8 *
9 * The library was designed directly after the MPI library by
10 * Michael Fromberger but has been written from scratch with
11 * additional optimizations in place.
12 *
13 * The library is free for all purposes without any express
14 * guarantee it works.
15 *
16 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
17 */
18
19#ifndef NO_FLOATING_POINT
20#include <math.h>
21#endif
22
23/* this function is less generic than mp_n_root, simpler and faster */
24int mp_sqrt(mp_int *arg, mp_int *ret) 
25{
26  int res;
27  mp_int t1,t2;
28  int i, j, k;
29#ifndef NO_FLOATING_POINT
30  double d;
31  mp_digit dig;
32#endif
33
34  /* must be positive */
35  if (arg->sign == MP_NEG) {
36    return MP_VAL;
37  }
38
39  /* easy out */
40  if (mp_iszero(arg) == MP_YES) {
41    mp_zero(ret);
42    return MP_OKAY;
43  }
44 
45  i = (arg->used / 2) - 1;
46  j = 2 * i;
47  if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) {
48      return res;
49  }
50 
51  if ((res = mp_init(&t2)) != MP_OKAY) {
52    goto E2;
53  }
54
55  for (k = 0; k < i; ++k) {
56      t1.dp[k] = (mp_digit) 0;
57  }
58     
59#ifndef NO_FLOATING_POINT
60
61  /* Estimate the square root using the hardware floating point unit. */
62
63  d = 0.0;
64  for (k = arg->used-1; k >= j; --k) {
65      d = ldexp(d, DIGIT_BIT) + (double) (arg->dp[k]);
66  }
67  d = sqrt(d);
68  dig = (mp_digit) ldexp(d, -DIGIT_BIT);
69  if (dig) {
70      t1.used = i+2;
71      d -= ldexp((double) dig, DIGIT_BIT);
72      if (d != 0.0) {
73          t1.dp[i+1] = dig;
74          t1.dp[i] = ((mp_digit) d) - 1;
75      } else {
76          t1.dp[i+1] = dig-1;
77          t1.dp[i] = MP_DIGIT_MAX;
78      }
79  } else {
80      t1.used = i+1;
81      t1.dp[i] = ((mp_digit) d) - 1;
82  }
83
84#else
85
86  /* Estimate the square root as having 1 in the most significant place. */
87
88  t1.used = i + 2;
89  t1.dp[i+1] = (mp_digit) 1;
90  t1.dp[i] = (mp_digit) 0;
91
92#endif
93
94  /* t1 > 0  */ 
95  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
96    goto E1;
97  }
98  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
99    goto E1;
100  }
101  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
102    goto E1;
103  }
104  /* And now t1 > sqrt(arg) */
105  do { 
106    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
107      goto E1;
108    }
109    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
110      goto E1;
111    }
112    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
113      goto E1;
114    }
115    /* t1 >= sqrt(arg) >= t2 at this point */
116  } while (mp_cmp_mag(&t1,&t2) == MP_GT);
117
118  mp_exch(&t1,ret);
119
120E1: mp_clear(&t2);
121E2: mp_clear(&t1);
122  return res;
123}
124
125#endif
126
127/* $Source: /cvsroot/tcl/libtommath/bn_mp_sqrt.c,v $ */
128/* Based on Tom's 1.3 */
129/* $Revision: 1.5 $ */
130/* $Date: 2006/12/01 05:48:23 $ */
Note: See TracBrowser for help on using the repository browser.