Build Fix -- compatibility issue with newer autoconf
[sxemacs] / src / ent / ent.h
1 /*
2   ent.h -- Numeric types for SXEmacs
3   Copyright (C) 2004 Jerry James
4   Copyright (C) 2004, 2005, 2006, 2007 Sebastian Freundt
5
6   XEmacs Author:  Jerry James
7   Author: Sebastian Freundt
8   Backport:  Sebastian Freundt
9
10 This file is part of SXEmacs
11
12 SXEmacs is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 SXEmacs is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
24
25
26 #ifndef INCLUDED_ent_h_
27 #define INCLUDED_ent_h_
28
29 /* The following types are always defined in the same manner,
30    we have some inclusions of the categories (worlds) they live in.
31    These inclusions, unlike in XEmacs, are mathematically inspired,
32    so here we go:
33
34    Categories (types):
35    ===========
36    int       = whatever fits in the Lisp_Object type, ordinary C int
37    bigz      = mpz rational integers
38    integer   = int + bigz
39    bigq      = mpq rational numbers
40
41    ffelm     = finite field element
42
43    padic     = p-adic number
44
45    float     = ordinary C double or long double
46    bigf      = mpf big floats (= gmp reals)
47    bigr      = mpfr reals
48
49    bigc      = mpc complex number
50    pseudoc   = mpfr + mpfr*i implementation of complex numbers
51
52    gaussian  = gaussian number (mpz + mpz*i implementation)
53
54    quatern   = quaternion number (which library does that?) - NOT YET
55
56    octon     = octonion number (which library does that? lidia?) - NOT YET
57
58    Category unions:
59    ================
60    rational        = integer + bigq
61    real            = float + bigf + bigr
62                      (and everything else simulating real numbers)
63    comparable      = rational + real
64                      (and everything else that has a total order)
65    complex         = bigc + gaussian
66    algebraic       = rational + ffelm + padic + gaussian
67    archimedean     = rational + real + complex
68                      (and everything else with an archimedean valuation)
69    non-archimidean = padic + ffelm
70
71    number    = archimedean + non-archimedean + quatern + octon
72
73
74    The top-level configure script should define the symbols
75    HAVE_MPZ, HAVE_MPQ, HAVE_MPF, HAVE_MPFR and HAVE_MPC to indicate which
76    it provides.
77    If some type is not defined by the library, this is what happens:
78
79    - (provide 'bignum) and (provide 'bigz) if HAVE_MPZ
80    - (provide 'ratio) and (provide 'bigq) if HAVE_MPQ
81    - (provide 'bigfloat) and (provide 'bigf) if HAVE_MPF
82    - (provide 'bigfr) if HAVE_MPFR
83    - (provide 'bigc) if HAVE_MPC
84    - (provide 'ecm) if HAVE_ECM
85 */
86
87 #if 0
88 /* definitely the wrong way to go */
89 #if defined(LINUX) && !(defined (__GLIBC__) && (__GLIBC__ >= 2))
90 /* These are redefined (correctly, but differently) in values.h.  */
91 #undef INTBITS
92 #undef LONGBITS
93 #undef SHORTBITS
94 #endif
95 #endif  /* 0 */
96
97 #if defined HAVE_MATH_H
98 # include <math.h>
99 #endif  /* HAVE_MATH_H */
100 #if defined HAVE_LIMITS_H
101 # include <limits.h>
102 #endif  /* HAVE_LIMITS_H */
103 #if defined HAVE_VALUES_H
104 # include <values.h>
105 #endif  /* HAVE_VALUES_H */
106
107 #include "ent/ent-optable.h"
108 #include "ent/ent-nullary-op.h"
109 #include "ent/ent-unary-op.h"
110 #include "ent/ent-binary-op.h"
111 #include "ent/ent-unary-rel.h"
112 #include "ent/ent-binary-rel.h"
113 #include "ent/ent-lift.h"
114
115 /* ordinary (small) integers */
116 #include "ent/ent-int.h"
117 /* ordinary floats */
118 #ifdef HAVE_FPFLOAT
119 # include "ent/ent-float.h"
120 #endif  /* HAVE_FPFLOAT */
121
122 #include "ent/ent-indef.h"
123
124 /* Load the library definitions */
125 #if defined HAVE_GMP && defined WITH_GMP
126 # include "ent/ent-gmp.h"
127 #elif defined HAVE_BSDMP && defined WITH_MP
128 # include "ent/ent-mp.h"
129 #endif
130 #if defined HAVE_MPFR && defined WITH_MPFR
131 # include "ent/ent-mpfr.h"
132 #endif
133 #if defined HAVE_MPC && defined WITH_MPC
134 # include "ent/ent-mpc.h"
135 #elif defined HAVE_PSEUC && defined WITH_PSEUC
136 # include "ent/ent-pseumpc.h"
137 #endif
138 #if defined HAVE_ECM && defined WITH_ECM
139 # include "ent/ent-ecm.h"
140 #endif
141
142 /* now maybe include those pseudo implementations */
143 #if defined HAVE_PSEUG && defined WITH_PSEUG
144 # include "ent/ent-gaussian.h"
145 #endif
146 #if defined HAVE_QUATERN && defined WITH_QUATERN
147 # include "ent/ent-quatern.h"
148 #endif
149
150 \f
151 /* debugging stuff */
152 #ifdef ALL_DEBUG_FLAGS
153 #undef ENT_DEBUG_FLAG
154 #define ENT_DEBUG_FLAG
155 #endif
156
157 #define __ENT_DEBUG__(args...)          fprintf(stderr, "ENT " args)
158 #ifndef ENT_DEBUG_FLAG
159 #define ENT_DEBUG(args...)
160 #else
161 #define ENT_DEBUG(args...)              __ENT_DEBUG__(args)
162 #endif
163 #define ENT_DEBUG_OP(args...)           ENT_DEBUG("[operation]: " args)
164 #define ENT_CRITICAL(args...)           __ENT_DEBUG__("CRITICAL: " args)
165
166 \f
167 /******************************** Errors ************************************/
168 extern Lisp_Object Qoperation_error, Qrelation_error, Qvaluation_error;
169
170 \f
171 /************************* Big Rational Integers ****************************/
172 extern Lisp_Object Qbigzp;
173 EXFUN(Fbigzp, 1);
174
175 #if !defined HAVE_MPZ || !(defined WITH_GMP || defined WITH_MP)
176 #define BIGZP(x)                (0 && x)
177 #define CHECK_BIGZ(x)           dead_wrong_type_argument(Qbigzp, x)
178 #define CONCHECK_BIGZ(x)        dead_wrong_type_argument(Qbigzp, x)
179 typedef void bigz;
180 #endif  /* !HAVE_MPZ */
181
182 \f
183 /********************************* Integers *********************************/
184 extern Lisp_Object Qintegerp;
185
186 EXFUN(Fintegerp, 1);
187 EXFUN(Fevenp, 1);
188 EXFUN(Foddp, 1);
189
190 #define INTEGERP(x) (INTP(x) || BIGZP(x))
191 #define CHECK_INTEGER(x)                                        \
192         do {                                                    \
193                 if (!INTEGERP(x))                               \
194                         dead_wrong_type_argument(Qintegerp, x); \
195         } while (0)
196 #define CONCHECK_INTEGER(x)                                     \
197         do {                                                    \
198                 if (!INTEGERP (x))                              \
199                         x = wrong_type_argument (Qintegerp, x); \
200         }  while (0)
201
202 \f
203 /************************** Rational Integer Fractions **********************/
204 extern Lisp_Object Qbigqp;
205 EXFUN(Fbigqp, 1);
206
207 #if !defined HAVE_MPQ || !defined WITH_GMP
208 #define BIGQP(x)                (0 && x)
209 #define CHECK_BIGQ(x)           dead_wrong_type_argument(Qbigqp, x)
210 #define CONCHECK_BIGQ(x)        dead_wrong_type_argument(Qbigqp, x)
211 typedef void bigq;
212 #endif /* !HAVE_MPQ */
213
214 \f
215 /********************************* Rationals ********************************/
216 extern Lisp_Object Qrationalp;
217
218 #define RATIONALP(x) (INTEGERP(x) || BIGQP(x))
219 #define CHECK_RATIONAL(x) do {                  \
220  if (!RATIONALP (x))                            \
221    dead_wrong_type_argument (Qrationalp, x);    \
222  } while (0)
223 #define CONCHECK_RATIONAL(x) do {               \
224  if (!RATIONALP (x))                            \
225    x = wrong_type_argument (Qrationalp, x);     \
226 }  while (0)
227
228 EXFUN(Frationalp, 1);
229 EXFUN(Fnumerator, 1);
230 EXFUN(Fdenominator, 1);
231
232 \f
233 /******************************** Bigfs ************************************/
234 #if !defined HAVE_MPF || !defined WITH_GMP
235 #define BIGFP(x)                (0 && x)
236 #define CHECK_BIGF(x)           dead_wrong_type_argument(Qbigfp, x)
237 #define CONCHECK_BIGF(x)        dead_wrong_type_argument(Qbigfp, x)
238 typedef void bigf;
239 #endif /* !HAVE_MPF */
240
241 extern Lisp_Object Qbigfp;
242 EXFUN(Fbigfp, 1);
243
244 \f
245 /******************************** Bigfrs ***********************************/
246 extern Lisp_Object Qbigfrp;
247 EXFUN(Fbigfrp, 1);
248
249 #if !defined HAVE_MPFR || !defined WITH_MPFR
250 #define BIGFRP(x)               (0 && x)
251 #define CHECK_BIGFR(x)          dead_wrong_type_argument(Qbigfrp, x)
252 #define CONCHECK_BIGFR(x)       dead_wrong_type_argument(Qbigfrp, x)
253 typedef void bigfr;
254 #endif  /* !HAVE_MPFR */
255
256 \f
257 /******************************* Floats *************************************/
258 extern Lisp_Object Qfloatp;
259 EXFUN(Ffloatp, 1);
260
261 #if !defined(HAVE_FPFLOAT)
262 #define FLOATP(x)               (0 && x)
263 #define CHECK_FLOAT(x)          dead_wrong_type_argument(Qfloatp, x)
264 #define CONCHECK_FLOAT(x)       dead_wrong_type_argument(Qfloatp, x)
265 typedef void fpfloat;
266 #endif  /* !HAVE_FPFLOAT */
267
268 #define INT_OR_FLOATP(x)        (INTP(x) || FLOATP(x))
269 #define CHECK_INT_OR_FLOAT(x)                                   \
270         do {                                                    \
271                 if (!INT_OR_FLOATP (x))                         \
272                         dead_wrong_type_argument(Qnumberp, x);  \
273         } while (0)
274
275 #define CONCHECK_INT_OR_FLOAT(x)                                \
276         do {                                                    \
277                 if (!INT_OR_FLOATP (x))                         \
278                         x = wrong_type_argument(Qnumberp, x);   \
279         } while (0)
280
281 \f
282 /*********************************** Reals **********************************/
283 extern Lisp_Object Qrealp;
284
285 #ifdef HAVE_FPFLOAT
286 #define REALP(x) (FLOATP(x) || BIGFP(x) || BIGFRP(x))
287 #else
288 #define REALP(x) (BIGFP(x) || BIGFRP(x))
289 #endif
290 #define CHECK_REAL(x)                                           \
291         do {                                                    \
292                 if (!REALP(x))                                  \
293                         dead_wrong_type_argument(Qrealp, x);    \
294         } while (0)
295 #define CONCHECK_REAL(x)                                        \
296         do {                                                    \
297                 if (!REALP(x))                                  \
298                         x = wrong_type_argument(Qrealp, x);     \
299         }  while (0)
300
301 extern Lisp_Object Vread_real_as;
302 extern Fixnum max_real_precision;
303 extern Fixnum default_real_precision;
304
305 \f
306 /****************************** Comparables *********************************/
307 extern Lisp_Object Qcomparablep;
308
309 #define COMPARABLEP(x) (RATIONALP(x) || REALP(x) || COMPARABLE_INDEF_P(x))
310 #define CHECK_COMPARABLE(x) do {                        \
311  if (!COMPARABLEP(x))                           \
312    dead_wrong_type_argument(Qcomparablep, x);   \
313  } while (0)
314 #define CONCHECK_COMPARABLE(x) do {             \
315  if (!COMPARABLEP(x))                           \
316    x = wrong_type_argument(Qcomparablep, x);    \
317 }  while (0)
318
319 \f
320 /********************************* Biggs ************************************/
321 extern Lisp_Object Qbiggp;
322 EXFUN(Fbiggp, 1);
323
324 #if !defined HAVE_PSEUG || !defined WITH_PSEUG
325 #define BIGGP(x)                (0 && x)
326 #define CHECK_BIGG(x)           dead_wrong_type_argument(Qbiggp, x)
327 #define CONCHECK_BIGG(x)        dead_wrong_type_argument(Qbiggp, x)
328 typedef void bigg;
329 #endif /* HAVE_PSEUG */
330
331 \f
332 /***************************** Bigcs ****************************************/
333 extern Lisp_Object Qbigcp;
334 EXFUN(Fbigcp, 1);
335
336 #if !(defined HAVE_MPC && defined WITH_MPC ||           \
337       defined HAVE_PSEUC && defined WITH_PSEUC)
338 #define BIGCP(x)                (0 && x)
339 #define CHECK_BIGC(x)           dead_wrong_type_argument(Qbigcp, x)
340 #define CONCHECK_BIGC(x)        dead_wrong_type_argument(Qbigcp, x)
341 typedef void bigc;
342 #endif
343
344 \f
345 /******************************* Complex Nums *******************************/
346 extern Lisp_Object Qcomplexp;
347
348 #define COMPLEXP(x) (BIGCP(x) || BIGGP(x) || INFINITE_POINT_P(x))
349 #define CHECK_COMPLEX(x) do {                   \
350  if (!COMPLEXP (x))                             \
351    dead_wrong_type_argument(Qcomplexp, x);      \
352  } while (0)
353 #define CONCHECK_COMPLEX(x) do {                \
354  if (!COMPLEXP (x))                             \
355    x = wrong_type_argument(Qcomplexp, x);       \
356 }  while (0)
357
358 EXFUN(Freal_part, 1);
359 EXFUN(Fimaginary_part, 1);
360
361 \f
362 /********************************* Quaterns *********************************/
363 extern Lisp_Object Qquaternp;
364 EXFUN(Fquaternp, 1);
365
366 #if !defined HAVE_QUATERN || !defined WITH_QUATERN
367 #define QUATERNP(x)             (0 && x)
368 #define CHECK_QUATERN(x)        dead_wrong_type_argument(Qquaternp, x)
369 #define CONCHECK_QUATERN(x)     dead_wrong_type_argument(Qquaternp, x)
370 typedef void quatern;
371 #endif /* HAVE_QUATERN */
372
373 \f
374 /******************************* Archimedeans *******************************/
375 extern Lisp_Object Qarchimedeanp;
376
377 #define ARCHIMEDEANP(x)                                                 \
378   (RATIONALP(x) || REALP(x) || COMPARABLE_INDEF_P(x) ||                 \
379    COMPLEXP(x) || QUATERNP(x))
380 #define CHECK_ARCHIMEDEAN(x) do {                                       \
381  if (!ARCHIMEDEANP (x))                                                 \
382    dead_wrong_type_argument (Qarchimedeanp, x);                         \
383  } while (0)
384 #define CONCHECK_ARCHIMEDEAN(x) do {                                    \
385  if (!ARCHIMEDEANP (x))                                                 \
386    x = wrong_type_argument (Qarchimedeanp, x);                          \
387 }  while (0)
388
389 \f
390 /***************************** Non-Archimedeans ******************************/
391 extern Lisp_Object Qnonarchimedeanp;
392
393 #define NONARCHIMEDEANP(x) (x != x)  /* RESC_ELMP(x) || PADICP(x) */
394 #define CHECK_NONARCHIMEDEAN(x)                                         \
395         do {                                                            \
396                 if (!NONARCHIMEDEANP (x))                               \
397                         dead_wrong_type_argument (Qnonarchimedeanp, x); \
398         } while (0)
399 #define CONCHECK_NONARCHIMEDEAN(x)                                      \
400         do {                                                            \
401                 if (!NONARCHIMEDEANP (x))                               \
402                         x = wrong_type_argument (Qnonarchimedeanp, x);  \
403         }  while (0)
404
405 \f
406 /****************************** Indefinities ********************************/
407 extern Lisp_Object Qindefinitep;
408 extern Lisp_Object Qinfinityp;
409 EXFUN(Findefinitep, 1);
410 EXFUN(Finfinityp, 1);
411
412 \f
413 /********************************* Numbers **********************************/
414 extern Lisp_Object Qnumberp;
415
416 #define NUMBERP(x) (ARCHIMEDEANP(x) || NONARCHIMEDEANP(x))
417 #define CHECK_NUMBER(x) do {                    \
418   if (!NUMBERP (x))                             \
419     dead_wrong_type_argument (Qnumberp, x);     \
420 } while (0)
421 #define CONCHECK_NUMBER(x) do {                 \
422   if (!NUMBERP (x))                             \
423     x = wrong_type_argument (Qnumberp, x);      \
424 } while (0)
425
426 EXFUN(Fcanonicalize_number, 1);
427 EXFUN(Fcoerce_number, 3);
428
429 extern unsigned long ent_normalise_precision(unsigned long);
430 extern unsigned long internal_get_precision(Lisp_Object);
431
432 /* parser hook for resclass objects */
433 extern int(*ase_resc_rng_pred_f)(const char *cp);
434 extern Lisp_Object(*ase_resc_rng_f)(char *cp);
435 extern int(*ase_resc_elm_pred_f)(const char *cp);
436 extern Lisp_Object(*ase_resc_elm_f)(char *cp);
437 /* parser hook for perms */
438 extern Lisp_Object(*ase_permutation_f)(Lisp_Object);
439
440 \f
441 /**************************** Auxiliary Categories **************************/
442 EXFUN(Fzerop, 1);
443 EXFUN(Fonep, 1);
444 EXFUN(Fzero, 1);
445 EXFUN(Fone, 1);
446
447 \f
448 /**************************** Categorical Function Table ********************/
449
450 /* tentative stuff */
451 extern dllist_t ase_empty_sets;
452
453 /* these tables hold functions according to their input signature and are
454    grouped by their operation
455 */
456
457 extern void syms_of_ent(void);
458 extern void vars_of_ent(void);
459 extern void init_ent(void);
460
461 \f
462 /* asm helpers (taken from ASE, KANT, linux kernel and libc) */
463 /* the following is stolen from the linux kernel */
464 /**
465  * find first bit set
466  * \param x the word to search
467  *
468  * This is defined the same way as
469  * the libc and compiler builtin ffs routines, therefore
470  * differs in spirit from the above ffz() (man ffs).
471  *
472  * \example ffs(32) => 5
473  */
474 extern_inline long unsigned int
475 __ase_ffsl(long unsigned int x) __attribute__((always_inline));
476 extern_inline unsigned int
477 __ase_ffs(unsigned int x) __attribute__((always_inline));
478
479 /**
480  * find last bit set
481  * \param x the word to search
482  *
483  * This is defined the same way as ffs().
484  */
485 extern_inline long unsigned int
486 __ase_flsl(long unsigned int x) __attribute__((always_inline));
487 #if 0
488 /* as long as it is undefined ... */
489 extern_inline unsigned int
490 __ase_fls(unsigned int x) __attribute__((always_inline));
491 #endif
492
493 #if defined __x86_64__
494 extern_inline long unsigned int
495 __ase_ffsl(long unsigned int x)
496 {
497         __asm__ volatile(
498                 "bsfq %[in], %[out]\n\t"
499                 : [out] "=r" (x) : [in] "rm" (x));
500         return x;
501 }
502 #elif defined __i386__
503 extern_inline long unsigned int
504 __ase_ffsl(long unsigned int x)
505 {
506         __asm__ volatile(
507                 "bsfl %[in], %[out]\n\t"
508                 : [out] "=r" (x) : [in] "rm" (x));
509         return x;
510 }
511
512 #elif defined __ppc__
513
514 extern_inline long unsigned int
515 __ase_ffsl(long unsigned int x)
516 {
517         long unsigned int cnt;
518
519         __asm__ volatile(
520                 "cntlzw %[out], %[in]\n"
521                 : [out] "=r" (cnt)
522                 : [in] "r" (x & -x));
523         return 32 - cnt;
524 }
525
526 #elif defined __powerpc64__
527
528 extern_inline long unsigned int
529 __ase_ffsl(long unsigned int x)
530 {
531         long unsigned int cnt;
532
533         __asm__ volatile(
534                 "cntlzw %[out], %[in]\n"
535                 : [out] "=r" (cnt)
536                 : [in] "r" (x & -x));
537         return 64 - cnt;
538 }
539
540 #elif defined HAVE_FFSL
541 extern_inline long unsigned int
542 __ase_ffsl(long unsigned int x)
543 {
544         return ffsl(x);
545 }
546
547 #elif SIZEOF_LONG == 4 || SIZEOF_LONG == 8
548 /* that's glibc's idea of ffs */
549 extern_inline long unsigned int
550 __ase_ffs_(long unsigned int i)
551 {
552         const unsigned char table[] = {
553                 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
554                 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
555                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
556                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
557                 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
558                 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
559                 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
560                 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
561         };
562         long unsigned int a;
563         long unsigned int x = i & -i;
564
565         a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ?  16 : 24);
566
567         return table[x >> a] + a;
568 }
569
570 # if SIZEOF_LONG == 4
571 #  define __ase_ffsl    __ase_ffs_
572 # else  /* SIZEOF_LONG == 8 */
573 extern_inline long unsigned int
574 __ase_ffsl(long unsigned int i)
575 {
576         long unsigned int x = i & -i;
577
578         if (x <= 0xffffffff)
579                 return __ase_ffs_(i);
580         else
581                 return 32 + __ase_ffs_(i >> 32);
582 }
583 # endif
584 #else   /* SIZEOF_LONG != 4,8 */
585 # error "Don't know how to compute the first bit set."
586 #endif  /* __x86_64__ || __i386__ */
587
588 #if defined(__x86_64__) || defined(__i386__)
589 extern_inline unsigned int
590 __ase_ffs(unsigned int x)
591 {
592         __asm__ volatile(
593                 "bsfl %[in], %[out]\n\t"
594                 : [out] "=r" (x) : [in] "rm" (x));
595         return x;
596 }
597 #else
598 extern_inline unsigned int
599 __ase_ffs(unsigned int x)
600 {
601         return __ase_ffsl(x);
602 }
603 #endif
604
605 #if defined __x86_64__
606 extern_inline long unsigned int
607 __ase_flsl(long unsigned int x)
608 {
609         __asm__ volatile(
610                 "bsrq %[in], %[out]\n\t"
611                 : [out] "=r" (x) : [in] "rm" (x));
612         return x;
613 }
614 #elif defined __i386__
615 extern_inline long unsigned int
616 __ase_flsl(long unsigned int x)
617 {
618         __asm__ volatile(
619                 "bsrl %[in], %[out]\n\t"
620                 : [out] "=r" (x) : [in] "rm" (x));
621         return x;
622 }
623
624 #elif defined __ppc__
625 extern_inline long unsigned int
626 __ase_flsl(long unsigned int x)
627 {
628         long unsigned int cnt;
629
630         __asm__ volatile(
631                 "cntlzw %[out], %[in]"
632                 : [out] "=r" (cnt)
633                 : [in] "r" (x)
634                 );
635         return 64 - cnt;
636 }
637
638 #elif defined __powerpc64__
639 extern_inline long unsigned int
640 __ase_flsl(long unsigned int x)
641 {
642         long unsigned int cnt;
643
644         __asm__ volatile(
645                 "cntlzd %[out], %[in]"
646                 : [out] "=r" (cnt)
647                 : [in] "r" (x)
648                 );
649         return 64 - x;
650 }
651
652 #elif defined HAVE_FLSL
653 extern_inline long unsigned int
654 __ase_flsl(long unsigned int x)
655 {
656         return flsl(x);
657 }
658
659 #elif SIZEOF_LONG == 8
660
661 /* stolen from glibc-2.7/sysdeps/posix/getaddrinfo.c
662  * what a nice file to put _THAT_ :O */
663 extern_inline long unsigned int
664 __ase_flsl(long unsigned int a)
665 {
666         long unsigned int n = 0;
667         for (long unsigned int mask = 1 << 63; n < 64; mask >>= 1, ++n) {
668                 if ((a & mask) != 0) {
669                         break;
670                 }
671         }
672         return n;
673 }
674
675 #elif SIZEOF_LONG == 4
676
677 /* stolen from glibc-2.7/sysdeps/posix/getaddrinfo.c
678  * what a nice file to put _THAT_ :O */
679 extern_inline long unsigned int
680 __ase_flsl(long unsigned int a)
681 {
682         long unsigned int n = 0;
683         for (long unsigned int mask = 1 << 31; n < 32; mask >>= 1, ++n) {
684                 if ((a & mask) != 0) {
685                         break;
686                 }
687         }
688         return n;
689 }
690
691 #else   /* SIZEOF_LONG != 4,8 */
692 # error "Don't know how to compute the last bit set."
693 #endif  /* __x86_64__ || __i386__ */
694
695 #endif /* INCLUDED_ent_h_ */