File: zimmermann.c

package info (click to toggle)
numerix 0.22-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 4,380 kB
  • ctags: 4,165
  • sloc: asm: 26,210; ansic: 12,168; ml: 4,912; sh: 3,899; pascal: 414; makefile: 179
file content (121 lines) | stat: -rw-r--r-- 4,182 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// file kernel/n/c/zimmermann.c: Zimmermann square root
/*-----------------------------------------------------------------------+
 |  Copyright 2005-2006, Michel Quercia (michel.quercia@prepas.org)      |
 |                                                                       |
 |  This file is part of Numerix. Numerix is free software; you can      |
 |  redistribute it and/or modify it under the terms of the GNU Lesser   |
 |  General Public License as published by the Free Software Foundation; |
 |  either version 2.1 of the License, or (at your option) any later     |
 |  version.                                                             |
 |                                                                       |
 |  The Numerix Library is distributed in the hope that it will be       |
 |  useful, but WITHOUT ANY WARRANTY; without even the implied warranty  |
 |  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  |
 |  Lesser General Public License for more details.                      |
 |                                                                       |
 |  You should have received a copy of the GNU Lesser General Public     |
 |  License along with the GNU MP Library; see the file COPYING. If not, |
 |  write to the Free Software Foundation, Inc., 59 Temple Place -       |
 |  Suite 330, Boston, MA 02111-1307, USA.                               |
 +-----------------------------------------------------------------------+
 |                                                                       |
 |                         Racine carre de Zimmermann                   |
 |                                                                       |
 +-----------------------------------------------------------------------*/

                            /* +-----------------+
                               |  Racine carre  |
                               +-----------------+ */

/*
  entre :
  a = naturel de longueur la
  b = naturel de longueur la/2

  contraintes :
  la > 0, la pair, BASE/16 <= a[la-1] < BASE/4
  a,b non confondus

  sortie :
  b <- 2*floor(sqrt(a))
  a <- a - b^2/4
*/

#ifndef assembly_sn_zimsqrt
#ifdef debug_zimsqrt
void xn(zimsqrt_buggy)
#else
void xn(zimsqrt)
#endif
(chiffre *a, long la, chiffre *b) {
  long p,q;
  chiffre *x;

  /* petite racine -> sqrt_n2 */
  if (la <= zimsqrt_lim) {xn(sqrt_n2)(a,la,b); return;}

  /* cas rcursif : divise a en 2 et calcule la racine du haut */
  p = la/4; q = la/2-p;
  xn(zimsqrt)(a+2*p,2*q,b+p);

  /* divise le reste par 2b[p..p+q-1] */
  if (xn(cmp)(a+2*p,q,b+p,q)) xn(burnidiv)(a+p,p,b+p,q,b);
  else {
    xn(fill)(b,p);
    xn(clear)(a+2*p,q);
    xn(inc)(a+p,p+q,b+p,q);
  }

  /* retranche le carr du quotient et dcale le quotient */
  x = xn(alloc_tmp)(2*p);
  xn(toomsqr)(b,p,x);
  xn(dec)(a,p+q+1,x,2*p);
  xn(free_tmp)(x);
  if (xn(shift_up)(b,p,b,1)) b[p]++;

  /* si < 0, corrige */
  while(a[p+q]) {
    xn(dec1)(b,p+1);
    xn(inc)(a,p+q+1,b,p+q);
    b[0]--;
  }
}
#endif /* assembly_sn_zimsqrt */

                              /* +------------+
                                 |  Contrle  |
                                 +------------+ */

#ifdef debug_zimsqrt
void xn(zimsqrt_buggy)(chiffre *a, long la, chiffre *b);
void xn(zimsqrt)(chiffre *a, long la, chiffre *b) {
  long lb = la/2;
  chiffre *x,*y, r;

  /* vrifie que la est pair > 0 et BASE/16 <= a[la-1] < BASE/4 */
  if ((la%2) || (la < 2))
      xn(internal_error)("error, zimsqrt is called with la odd or la < 2",0);

  r = a[la-1] >> (HW-4);
  if ((r == 0) || (r > 3))
      xn(internal_error)("error, zimsqrt is called without BASE/16 <= msb(la) < BASE/4",1,a,la);

  /* calcule la racine carre douteuse */
  x = xn(alloc_tmp)(2*la); y = x + la;
  xn(move)(a,la,x);
  xn(zimsqrt_buggy)(a,la,b);

  /* vrifie que a_entre = a_sortie + (b/2)^2 et a_sortie <= b */
  xn(toomsqr)(b,lb,y);
  r = xn(shift_down)(y,la,y,2);
  if (r == 0) r = xn(inc)(y,la,a,lb);
  if (r == 0) r = xn(cmp)(x,la,y,la);
  if (r == 0) r = (xn(cmp)(a,lb,b,lb) > 0);

  if (r) xn(internal_error)("error in zimsqrt", 3,x,la,b,lb,a,lb);

  xn(free_tmp)(x);

}
#endif /* debug_zimsqrt */