… | |
… | |
29 | |
29 | |
30 | #ifndef ECB_H |
30 | #ifndef ECB_H |
31 | #define ECB_H |
31 | #define ECB_H |
32 | |
32 | |
33 | /* 16 bits major, 16 bits minor */ |
33 | /* 16 bits major, 16 bits minor */ |
34 | #define ECB_VERSION 0x00010001 |
34 | #define ECB_VERSION 0x00010002 |
35 | |
35 | |
36 | #ifdef _WIN32 |
36 | #ifdef _WIN32 |
37 | typedef signed char int8_t; |
37 | typedef signed char int8_t; |
38 | typedef unsigned char uint8_t; |
38 | typedef unsigned char uint8_t; |
39 | typedef signed short int16_t; |
39 | typedef signed short int16_t; |
… | |
… | |
148 | |
148 | |
149 | #ifndef ECB_MEMORY_FENCE |
149 | #ifndef ECB_MEMORY_FENCE |
150 | #if ECB_GCC_VERSION(4,7) |
150 | #if ECB_GCC_VERSION(4,7) |
151 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
151 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
152 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
152 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
|
|
153 | |
|
|
154 | /* The __has_feature syntax from clang is so misdesigned that we cannot use it |
|
|
155 | * without risking compile time errors with other compilers. We *could* |
|
|
156 | * define our own ecb_clang_has_feature, but I just can't be bothered to work |
|
|
157 | * around * this shit time and again. |
153 | /*#elif defined __clang && __has_feature (cxx_atomic)*/ |
158 | * #elif defined __clang && __has_feature (cxx_atomic) |
154 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
159 | * // see comment below (stdatomic.h) about the C11 memory model. |
155 | /*#define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)*/ |
160 | * #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
|
|
161 | */ |
|
|
162 | |
156 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
163 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
157 | #define ECB_MEMORY_FENCE __sync_synchronize () |
164 | #define ECB_MEMORY_FENCE __sync_synchronize () |
158 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
165 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
159 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
166 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
160 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
167 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
… | |
… | |
554 | || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64 |
561 | || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64 |
555 | #define ECB_STDFP 1 |
562 | #define ECB_STDFP 1 |
556 | #include <string.h> /* for memcpy */ |
563 | #include <string.h> /* for memcpy */ |
557 | #else |
564 | #else |
558 | #define ECB_STDFP 0 |
565 | #define ECB_STDFP 0 |
|
|
566 | #include <math.h> /* for frexp*, ldexp* */ |
559 | #endif |
567 | #endif |
560 | |
568 | |
561 | #ifndef ECB_NO_LIBM |
569 | #ifndef ECB_NO_LIBM |
562 | |
570 | |
563 | /* convert a float to ieee single/binary32 */ |
571 | /* convert a float to ieee single/binary32 */ |
… | |
… | |
569 | |
577 | |
570 | #if ECB_STDFP |
578 | #if ECB_STDFP |
571 | memcpy (&r, &x, 4); |
579 | memcpy (&r, &x, 4); |
572 | #else |
580 | #else |
573 | /* slow emulation, works for anything but -0 */ |
581 | /* slow emulation, works for anything but -0 */ |
574 | ECB_EXTERN_C float frexpf (float v, int *e); |
|
|
575 | uint32_t m; |
582 | uint32_t m; |
576 | int e; |
583 | int e; |
577 | |
584 | |
578 | if (x == 0e0f ) return 0; |
585 | if (x == 0e0f ) return 0x00000000U; |
579 | if (x > +3.40282346638528860e+38f) return 0x7f800000U; |
586 | if (x > +3.40282346638528860e+38f) return 0x7f800000U; |
580 | if (x < -3.40282346638528860e+38f) return 0xff800000U; |
587 | if (x < -3.40282346638528860e+38f) return 0xff800000U; |
581 | if (x != x ) return 0x7fbfffffU; |
588 | if (x != x ) return 0x7fbfffffU; |
582 | |
589 | |
583 | m = frexpf (x, &e) * 0x1000000U; |
590 | m = frexpf (x, &e) * 0x1000000U; |
… | |
… | |
585 | r = m & 0x80000000U; |
592 | r = m & 0x80000000U; |
586 | |
593 | |
587 | if (r) |
594 | if (r) |
588 | m = -m; |
595 | m = -m; |
589 | |
596 | |
590 | if (e < -125) |
597 | if (e <= -126) |
591 | { |
598 | { |
592 | m &= 0xffffffU; |
599 | m &= 0xffffffU; |
593 | m >>= (-125 - e); |
600 | m >>= (-125 - e); |
594 | e = -126; |
601 | e = -126; |
595 | } |
602 | } |
… | |
… | |
610 | |
617 | |
611 | #if ECB_STDFP |
618 | #if ECB_STDFP |
612 | memcpy (&r, &x, 4); |
619 | memcpy (&r, &x, 4); |
613 | #else |
620 | #else |
614 | /* emulation, only works for normals and subnormals and +0 */ |
621 | /* emulation, only works for normals and subnormals and +0 */ |
615 | ECB_EXTERN_C float ldexpf (float x, int e); |
|
|
616 | |
|
|
617 | int neg = x >> 31; |
622 | int neg = x >> 31; |
618 | int e = (x >> 23) & 0xffU; |
623 | int e = (x >> 23) & 0xffU; |
619 | |
624 | |
620 | x &= 0x7fffffU; |
625 | x &= 0x7fffffU; |
621 | |
626 | |
… | |
… | |
623 | x |= 0x800000U; |
628 | x |= 0x800000U; |
624 | else |
629 | else |
625 | e = 1; |
630 | e = 1; |
626 | |
631 | |
627 | /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */ |
632 | /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */ |
628 | r = ldexpf (x * (1.f / 0x1000000U), e - 126); |
633 | r = ldexpf (x * (0.5f / 0x800000U), e - 126); |
629 | |
634 | |
630 | r = neg ? -r : r; |
635 | r = neg ? -r : r; |
631 | #endif |
636 | #endif |
632 | |
637 | |
633 | return r; |
638 | return r; |
… | |
… | |
642 | |
647 | |
643 | #if ECB_STDFP |
648 | #if ECB_STDFP |
644 | memcpy (&r, &x, 8); |
649 | memcpy (&r, &x, 8); |
645 | #else |
650 | #else |
646 | /* slow emulation, works for anything but -0 */ |
651 | /* slow emulation, works for anything but -0 */ |
647 | ECB_EXTERN_C double frexp (double v, int *e); |
|
|
648 | uint64_t m; |
652 | uint64_t m; |
649 | int e; |
653 | int e; |
650 | |
654 | |
651 | if (x == 0e0 ) return 0; |
655 | if (x == 0e0 ) return 0x0000000000000000U; |
652 | if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U; |
656 | if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U; |
653 | if (x < -1.79769313486231470e+308) return 0xfff0000000000000U; |
657 | if (x < -1.79769313486231470e+308) return 0xfff0000000000000U; |
654 | if (x != x ) return 0X7ff7ffffffffffffU; |
658 | if (x != x ) return 0X7ff7ffffffffffffU; |
655 | |
659 | |
656 | m = frexp (x, &e) * 0x20000000000000U; |
660 | m = frexp (x, &e) * 0x20000000000000U; |
… | |
… | |
658 | r = m & 0x8000000000000000;; |
662 | r = m & 0x8000000000000000;; |
659 | |
663 | |
660 | if (r) |
664 | if (r) |
661 | m = -m; |
665 | m = -m; |
662 | |
666 | |
663 | if (e < -1021) |
667 | if (e <= -1022) |
664 | { |
668 | { |
665 | m &= 0x1fffffffffffffU; |
669 | m &= 0x1fffffffffffffU; |
666 | m >>= (-1021 - e); |
670 | m >>= (-1021 - e); |
667 | e = -1022; |
671 | e = -1022; |
668 | } |
672 | } |
… | |
… | |
683 | |
687 | |
684 | #if ECB_STDFP |
688 | #if ECB_STDFP |
685 | memcpy (&r, &x, 8); |
689 | memcpy (&r, &x, 8); |
686 | #else |
690 | #else |
687 | /* emulation, only works for normals and subnormals and +0 */ |
691 | /* emulation, only works for normals and subnormals and +0 */ |
688 | ECB_EXTERN_C double ldexp (double x, int e); |
|
|
689 | |
|
|
690 | int neg = x >> 63; |
692 | int neg = x >> 63; |
691 | int e = (x >> 52) & 0x7ffU; |
693 | int e = (x >> 52) & 0x7ffU; |
692 | |
694 | |
693 | x &= 0xfffffffffffffU; |
695 | x &= 0xfffffffffffffU; |
694 | |
696 | |
… | |
… | |
696 | x |= 0x10000000000000U; |
698 | x |= 0x10000000000000U; |
697 | else |
699 | else |
698 | e = 1; |
700 | e = 1; |
699 | |
701 | |
700 | /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */ |
702 | /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */ |
701 | r = ldexp (x * (1. / 0x20000000000000U), e - 1022); |
703 | r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022); |
702 | |
704 | |
703 | r = neg ? -r : r; |
705 | r = neg ? -r : r; |
704 | #endif |
706 | #endif |
705 | |
707 | |
706 | return r; |
708 | return r; |