Actually hook powernow.4 into the build.
[dragonfly.git] / contrib / mpfr / sum.c
blob228c14565b29fc24de25383798b02645e489a482
1 /* Sum -- efficiently sum a list of floating-point numbers
3 Copyright 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
26 /* I would really like to use "mpfr_srcptr const []" but the norm is buggy:
27 it doesn't automaticaly cast a "mpfr_ptr []" to "mpfr_srcptr const []"
28 if necessary. So the choice are:
29 mpfr_s ** : ok
30 mpfr_s *const* : ok
31 mpfr_s **const : ok
32 mpfr_s *const*const : ok
33 const mpfr_s *const* : no
34 const mpfr_s **const : no
35 const mpfr_s *const*const: no
36 VL: this is not a bug, but a feature. See the reason here:
37 http://c-faq.com/ansi/constmismatch.html
39 static void heap_sort (mpfr_srcptr *const, unsigned long, mpfr_srcptr *);
40 static void count_sort (mpfr_srcptr *const, unsigned long, mpfr_srcptr *,
41 mp_exp_t, mpfr_uexp_t);
43 /* Either sort the tab in perm and returns 0
44 Or returns 1 for +INF, -1 for -INF and 2 for NAN */
45 int
46 mpfr_sum_sort (mpfr_srcptr *const tab, unsigned long n, mpfr_srcptr *perm)
48 mp_exp_t min, max;
49 mpfr_uexp_t exp_num;
50 unsigned long i;
51 int sign_inf;
53 sign_inf = 0;
54 min = MPFR_EMIN_MAX;
55 max = MPFR_EMAX_MIN;
56 for (i = 0; i < n; i++)
58 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (tab[i])))
60 if (MPFR_IS_NAN (tab[i]))
61 return 2; /* Return NAN code */
62 else if (MPFR_IS_INF (tab[i]))
64 if (sign_inf == 0) /* No previous INF */
65 sign_inf = MPFR_SIGN (tab[i]);
66 else if (sign_inf != MPFR_SIGN (tab[i]))
67 return 2; /* Return NAN */
70 else
72 if (MPFR_GET_EXP (tab[i]) < min)
73 min = MPFR_GET_EXP(tab[i]);
74 if (MPFR_GET_EXP (tab[i]) > max)
75 max = MPFR_GET_EXP(tab[i]);
78 if (MPFR_UNLIKELY (sign_inf != 0))
79 return sign_inf;
81 exp_num = max - min + 1;
82 /* FIXME : better test */
83 if (exp_num > n * MPFR_INT_CEIL_LOG2 (n))
84 heap_sort (tab, n, perm);
85 else
86 count_sort (tab, n, perm, min, exp_num);
87 return 0;
90 #define GET_EXP1(x) (MPFR_IS_ZERO (x) ? min : MPFR_GET_EXP (x))
91 /* Performs a count sort of the entries */
92 static void
93 count_sort (mpfr_srcptr *const tab, unsigned long n,
94 mpfr_srcptr *perm, mp_exp_t min, mpfr_uexp_t exp_num)
96 unsigned long *account;
97 unsigned long target_rank, i;
98 MPFR_TMP_DECL(marker);
100 /* Reserve a place for potential 0 (with EXP min-1)
101 If there is no zero, we only lose one unused entry */
102 min--;
103 exp_num++;
105 /* Performs a counting sort of the entries */
106 MPFR_TMP_MARK (marker);
107 account = (unsigned long *) MPFR_TMP_ALLOC (exp_num * sizeof * account);
108 for (i = 0; i < exp_num; i++)
109 account[i] = 0;
110 for (i = 0; i < n; i++)
111 account[GET_EXP1 (tab[i]) - min]++;
112 for (i = exp_num - 1; i >= 1; i--)
113 account[i - 1] += account[i];
114 for (i = 0; i < n; i++)
116 target_rank = --account[GET_EXP1 (tab[i]) - min];
117 perm[target_rank] = tab[i];
119 MPFR_TMP_FREE (marker);
123 #define GET_EXP2(x) (MPFR_IS_ZERO (x) ? MPFR_EMIN_MIN : MPFR_GET_EXP (x))
125 /* Performs a heap sort of the entries */
126 static void
127 heap_sort (mpfr_srcptr *const tab, unsigned long n, mpfr_srcptr *perm)
129 unsigned long dernier_traite;
130 unsigned long i, pere;
131 mpfr_srcptr tmp;
132 unsigned long fils_gauche, fils_droit, fils_indigne;
133 /* Reminder of a heap structure :
134 node(i) has for left son node(2i +1) and right son node(2i)
135 and father(node(i)) = node((i - 1) / 2)
138 /* initialize the permutation to identity */
139 for (i = 0; i < n; i++)
140 perm[i] = tab[i];
142 /* insertion phase */
143 for (dernier_traite = 1; dernier_traite < n; dernier_traite++)
145 i = dernier_traite;
146 while (i > 0)
148 pere = (i - 1) / 2;
149 if (GET_EXP2 (perm[pere]) > GET_EXP2 (perm[i]))
151 tmp = perm[pere];
152 perm[pere] = perm[i];
153 perm[i] = tmp;
154 i = pere;
156 else
157 break;
161 /* extraction phase */
162 for (dernier_traite = n - 1; dernier_traite > 0; dernier_traite--)
164 tmp = perm[0];
165 perm[0] = perm[dernier_traite];
166 perm[dernier_traite] = tmp;
168 i = 0;
169 while (1)
171 fils_gauche = 2 * i + 1;
172 fils_droit = fils_gauche + 1;
173 if (fils_gauche < dernier_traite)
175 if (fils_droit < dernier_traite)
177 if (GET_EXP2(perm[fils_droit]) < GET_EXP2(perm[fils_gauche]))
178 fils_indigne = fils_droit;
179 else
180 fils_indigne = fils_gauche;
182 if (GET_EXP2 (perm[i]) > GET_EXP2 (perm[fils_indigne]))
184 tmp = perm[i];
185 perm[i] = perm[fils_indigne];
186 perm[fils_indigne] = tmp;
187 i = fils_indigne;
189 else
190 break;
192 else /* on a un fils gauche, pas de fils droit */
194 if (GET_EXP2 (perm[i]) > GET_EXP2 (perm[fils_gauche]))
196 tmp = perm[i];
197 perm[i] = perm[fils_gauche];
198 perm[fils_gauche] = tmp;
200 break;
203 else /* on n'a pas de fils */
204 break;
210 /* Sum a list of float with order given by permutation perm,
211 * intermediate size set to F.
212 * Internal use function.
214 static int
215 sum_once (mpfr_ptr ret, mpfr_srcptr *const tab, unsigned long n, mp_prec_t F)
217 mpfr_t sum;
218 unsigned long i;
219 int error_trap;
221 MPFR_ASSERTD (n >= 2);
223 mpfr_init2 (sum, F);
224 error_trap = mpfr_set (sum, tab[0], GMP_RNDN);
225 for (i = 1; i < n - 1; i++)
227 MPFR_ASSERTD (!MPFR_IS_NAN (sum) && !MPFR_IS_INF (sum));
228 error_trap |= mpfr_add (sum, sum, tab[i], GMP_RNDN);
230 error_trap |= mpfr_add (ret, sum, tab[n - 1], GMP_RNDN);
231 mpfr_clear (sum);
232 return error_trap;
235 /* Sum a list of floating-point numbers.
236 * FIXME : add reference to Demmel-Hida's paper.
240 mpfr_sum (mpfr_ptr ret, mpfr_ptr *const tab_p, unsigned long n, mp_rnd_t rnd)
242 mpfr_t cur_sum;
243 mp_prec_t prec;
244 mpfr_srcptr *perm, *const tab = (mpfr_srcptr *) tab_p;
245 int k, error_trap;
246 MPFR_ZIV_DECL (loop);
247 MPFR_SAVE_EXPO_DECL (expo);
248 MPFR_TMP_DECL (marker);
250 if (MPFR_UNLIKELY (n <= 1))
252 if (n < 1)
254 MPFR_SET_ZERO (ret);
255 MPFR_SET_POS (ret);
256 return 0;
258 else
259 return mpfr_set (ret, tab[0], rnd);
262 /* Sort and treat special cases */
263 MPFR_TMP_MARK (marker);
264 perm = (mpfr_srcptr *) MPFR_TMP_ALLOC (n * sizeof *perm);
265 error_trap = mpfr_sum_sort (tab, n, perm);
266 /* Check if there was a NAN or a INF */
267 if (MPFR_UNLIKELY (error_trap != 0))
269 MPFR_TMP_FREE (marker);
270 if (error_trap == 2)
272 MPFR_SET_NAN (ret);
273 MPFR_RET_NAN;
275 MPFR_SET_INF (ret);
276 MPFR_SET_SIGN (ret, error_trap);
277 MPFR_RET (0);
280 /* Initial precision */
281 prec = MAX (MPFR_PREC (tab[0]), MPFR_PREC (ret));
282 k = MPFR_INT_CEIL_LOG2 (n) + 1;
283 prec += k + 2;
284 mpfr_init2 (cur_sum, prec);
286 /* Ziv Loop */
287 MPFR_SAVE_EXPO_MARK (expo);
288 MPFR_ZIV_INIT (loop, prec);
289 for (;;)
291 error_trap = sum_once (cur_sum, perm, n, prec + k);
292 if (MPFR_LIKELY (error_trap == 0 ||
293 (!MPFR_IS_ZERO (cur_sum) &&
294 mpfr_can_round (cur_sum,
295 MPFR_GET_EXP (cur_sum) - prec + 2,
296 GMP_RNDN, rnd, MPFR_PREC (ret)))))
297 break;
298 MPFR_ZIV_NEXT (loop, prec);
299 mpfr_set_prec (cur_sum, prec);
301 MPFR_ZIV_FREE (loop);
302 MPFR_TMP_FREE (marker);
304 error_trap |= mpfr_set (ret, cur_sum, rnd);
305 mpfr_clear (cur_sum);
307 MPFR_SAVE_EXPO_FREE (expo);
308 error_trap |= mpfr_check_range (ret, 0, rnd);
309 return error_trap; /* It doesn't return the ternary value */
312 /* __END__ */