ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libecb/ecb.h
(Generate patch)

Comparing libecb/ecb.h (file contents):
Revision 1.102 by root, Thu Jun 28 17:23:58 2012 UTC vs.
Revision 1.108 by root, Fri Jun 29 01:39:51 2012 UTC

534 } 534 }
535#else 535#else
536 #define ecb_array_length(name) (sizeof (name) / sizeof (name [0])) 536 #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
537#endif 537#endif
538 538
539#if __STDC_IEC_559__ 539/*******************************************************************************/
540 // we assume this is defined for most C and many C++ compilers 540/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
541 ecb_inline ecb_bool ecb_float_ieee (void) ecb_const;
542 ecb_inline ecb_bool ecb_float_ieee (void) { return 1; }
543 ecb_inline ecb_bool ecb_double_ieee (void) ecb_const;
544 ecb_inline ecb_bool ecb_double_ieee (void) { return 1; }
545#elif ECB_CPP
546 #include <limits>
547 ecb_inline ecb_bool ecb_float_ieee (void) ecb_const;
548 ecb_inline ecb_bool ecb_float_ieee (void) { return std::numeric_limits<float >::is_iec559; }
549 ecb_inline ecb_bool ecb_double_ieee (void) ecb_const;
550 ecb_inline ecb_bool ecb_double_ieee (void) { return std::numeric_limits<double>::is_iec559; }
551#else
552 ecb_inline ecb_bool ecb_float_ieee (void) ecb_const;
553 ecb_inline ecb_bool ecb_float_ieee (void) { return 0; }
554 ecb_inline ecb_bool ecb_double_ieee (void) ecb_const;
555 ecb_inline ecb_bool ecb_double_ieee (void) { return 0; }
556#endif
557 541
542/* basically, everything uses "ieee pure-endian" floating point numbers */
543/* the only noteworthy exception is ancient armle, which uses order 43218765 */
544#if 0 \
545 || __i386 || __i386__ \
546 || __amd64 || __amd64__ || __x86_64 || __x86_64__ \
547 || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
548 || defined __arm__ && defined __ARM_EABI__ \
549 || defined __s390__ || defined __s390x__ \
550 || defined __mips__ \
551 || defined __alpha__ \
552 || defined __hppa__ \
553 || defined __ia64__ \
554 || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64
555 #define ECB_STDFP 1
556 #include <string.h> /* for memcpy */
557#else
558 #define ECB_STDFP 0
559#endif
560
561#ifndef ECB_NO_LIBM
562
558// convert a float to ieee single/binary32 563 /* convert a float to ieee single/binary32 */
559ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const; 564 ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const;
560ecb_function_ uint32_t 565 ecb_function_ uint32_t
561ecb_float_to_binary32 (float x) 566 ecb_float_to_binary32 (float x)
562{ 567 {
568 uint32_t r;
569
570 #if ECB_STDFP
571 memcpy (&r, &x, 4);
572 #else
563 /* slow emulation, works for anything but nan's and -0 */ 573 /* slow emulation, works for anything but -0 */
564 ECB_EXTERN_C float frexpf (float v, int *e); 574 ECB_EXTERN_C float frexpf (float v, int *e);
565 uint32_t r, m; 575 uint32_t m;
566 int e; 576 int e;
567 577
568 if (x == 0e0f ) return 0; 578 if (x == 0e0f ) return 0x00000000U;
569 if (x > +3.40282346638528860e+38f) return 0x7f800000U; 579 if (x > +3.40282346638528860e+38f) return 0x7f800000U;
570 if (x < -3.40282346638528860e+38f) return 0xff800000U; 580 if (x < -3.40282346638528860e+38f) return 0xff800000U;
581 if (x != x ) return 0x7fbfffffU;
571 582
572 m = frexpf (x, &e) * 0x1000000U; 583 m = frexpf (x, &e) * 0x1000000U;
573 584
574 r = m & 0x80000000U; 585 r = m & 0x80000000U;
575 586
576 if (r) 587 if (r)
577 m = -m; 588 m = -m;
578 589
579 if (e < -125) 590 if (e <= -126)
580 { 591 {
581 m &= 0xffffffU; 592 m &= 0xffffffU;
582 m >>= (-125 - e); 593 m >>= (-125 - e);
583 e = -126; 594 e = -126;
584 } 595 }
585 596
586 r |= (e + 126) << 23; 597 r |= (e + 126) << 23;
587 r |= m & 0x7fffffU; 598 r |= m & 0x7fffffU;
599 #endif
588 600
589 return r; 601 return r;
590} 602 }
591 603
592// converts a ieee single/binary32 to a float 604 /* converts an ieee single/binary32 to a float */
593ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const; 605 ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const;
594ecb_function_ float 606 ecb_function_ float
595ecb_binary32_to_float (uint32_t x) 607 ecb_binary32_to_float (uint32_t x)
596{ 608 {
609 float r;
610
611 #if ECB_STDFP
612 memcpy (&r, &x, 4);
613 #else
597 /* emulation, only works for normals and subnormals and +0 */ 614 /* emulation, only works for normals and subnormals and +0 */
598 ECB_EXTERN_C float ldexpf (float x, int e); 615 ECB_EXTERN_C float ldexpf (float x, int e);
599 616
600 int neg = x >> 31; 617 int neg = x >> 31;
601 int e = (x >> 23) & 0xffU; 618 int e = (x >> 23) & 0xffU;
602 float r;
603 619
604 x &= 0x7fffffU; 620 x &= 0x7fffffU;
605 621
606 if (e) 622 if (e)
607 x |= 0x800000U; 623 x |= 0x800000U;
624 else
625 e = 1;
608 626
609 /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */ 627 /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
610 r = ldexpf (x * (1.f / 0x1000000U), e - 126); 628 r = ldexpf (x * (0.5f / 0x800000U), e - 126);
611 629
612 return neg ? -r : r; 630 r = neg ? -r : r;
613} 631 #endif
614 632
633 return r;
634 }
635
636 /* convert a double to ieee double/binary64 */
615ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const; 637 ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const;
616ecb_function_ uint64_t 638 ecb_function_ uint64_t
617ecb_double_to_binary64 (double x) 639 ecb_double_to_binary64 (double x)
618{ 640 {
619} 641 uint64_t r;
620 642
643 #if ECB_STDFP
644 memcpy (&r, &x, 8);
645 #else
646 /* slow emulation, works for anything but -0 */
647 ECB_EXTERN_C double frexp (double v, int *e);
648 uint64_t m;
649 int e;
650
651 if (x == 0e0 ) return 0x0000000000000000U;
652 if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
653 if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
654 if (x != x ) return 0X7ff7ffffffffffffU;
655
656 m = frexp (x, &e) * 0x20000000000000U;
657
658 r = m & 0x8000000000000000;;
659
660 if (r)
661 m = -m;
662
663 if (e <= -1022)
664 {
665 m &= 0x1fffffffffffffU;
666 m >>= (-1021 - e);
667 e = -1022;
668 }
669
670 r |= ((uint64_t)(e + 1022)) << 52;
671 r |= m & 0xfffffffffffffU;
621#endif 672 #endif
622 673
674 return r;
675 }
676
677 /* converts an ieee double/binary64 to a double */
678 ecb_function_ double ecb_binary64_to_double (uint64_t x) ecb_const;
679 ecb_function_ double
680 ecb_binary64_to_double (uint64_t x)
681 {
682 double r;
683
684 #if ECB_STDFP
685 memcpy (&r, &x, 8);
686 #else
687 /* 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;
691 int e = (x >> 52) & 0x7ffU;
692
693 x &= 0xfffffffffffffU;
694
695 if (e)
696 x |= 0x10000000000000U;
697 else
698 e = 1;
699
700 /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
701 r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
702
703 r = neg ? -r : r;
704 #endif
705
706 return r;
707 }
708
709#endif
710
711#endif
712

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines