Mercurial > hg > octave-nkf
comparison src/xpow.cc @ 9123:f39b98237d5c
use more robust and less aggressive scalar .^ range optimization
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 16 Apr 2009 07:02:31 +0200 |
parents | 10bed8fbec99 |
children | ab80681c44d9 |
comparison
equal
deleted
inserted
replaced
9122:8ca06fd9c6ef | 9123:f39b98237d5c |
---|---|
690 } | 690 } |
691 | 691 |
692 return result; | 692 return result; |
693 } | 693 } |
694 | 694 |
695 static inline bool | |
696 same_sign (double a, double b) | |
697 { | |
698 return (a >= 0 && b >= 0) || (a <= 0 && b <= 0); | |
699 } | |
700 | |
695 octave_value | 701 octave_value |
696 elem_xpow (double a, const Range& r) | 702 elem_xpow (double a, const Range& r) |
697 { | 703 { |
698 octave_value retval; | 704 octave_value retval; |
699 | 705 |
700 if (r.nelem () <= 0) | 706 // Only optimize powers with ranges that are integer and monotonic in |
701 retval = Matrix (); | 707 // magnitude. |
702 else if (a < 0.0 && ! r.all_elements_are_ints ()) | 708 if (r.nelem () > 1 && r.all_elements_are_ints () |
703 { | 709 && same_sign (r.base (), r.limit ())) |
704 ComplexMatrix mat (1, r.nelem ()); | 710 { |
705 Complex atmp (a); | 711 octave_idx_type n = r.nelem (); |
706 Complex *pmat = mat.fortran_vec (); | 712 Matrix result (1, n); |
707 | 713 if (same_sign (r.base (), r.inc ())) |
708 pmat[0] = std::pow (atmp, r.base ()); | 714 { |
709 Complex mul = std::pow (atmp, r.inc ()); | 715 double base = std::pow (a, r.base ()); |
710 for (octave_idx_type i = 1; i < r.nelem (); i++) | 716 double inc = std::pow (a, r.inc ()); |
711 pmat[i] = pmat[i-1] * mul; | 717 result(0) = base; |
712 | 718 for (octave_idx_type i = 1; i < n; i++) |
713 retval = mat; | 719 result(i) = (base *= inc); |
714 } | 720 } |
715 else | 721 else |
716 { | 722 { |
717 Matrix mat (1, r.nelem ()); | 723 // Don't use Range::limit () here. |
718 double *pmat = mat.fortran_vec (); | 724 double limit = std::pow (a, r.base () + (n-1) * r.inc ()); |
719 | 725 double inc = std::pow (a, -r.inc ()); |
720 double base = std::pow (a, r.base ()); | 726 result(n-1) = limit; |
721 pmat[0] = base; | 727 for (octave_idx_type i = n-2; i >= 0; i--) |
722 double mul = std::pow (a, r.inc ()); | 728 result(i) = (limit *= inc); |
723 for (octave_idx_type i = 1; i < r.nelem (); i++) | 729 } |
724 pmat[i] = (base *= mul); | 730 |
725 | 731 retval = result; |
726 retval = mat; | 732 } |
727 } | 733 else |
734 retval = elem_xpow (a, r.matrix_value ()); | |
728 | 735 |
729 return retval; | 736 return retval; |
730 } | 737 } |
731 | 738 |
732 // -*- 3 -*- | 739 // -*- 3 -*- |
929 octave_value | 936 octave_value |
930 elem_xpow (const Complex& a, const Range& r) | 937 elem_xpow (const Complex& a, const Range& r) |
931 { | 938 { |
932 octave_value retval; | 939 octave_value retval; |
933 | 940 |
934 if (r.nelem () <= 0) | 941 // Only optimize powers with ranges that are integer and monotonic in |
935 retval = Matrix (); | 942 // magnitude. |
936 else | 943 if (r.nelem () > 1 && r.all_elements_are_ints () |
937 { | 944 && same_sign (r.base (), r.limit ())) |
938 ComplexMatrix mat (1, r.nelem ()); | 945 { |
939 Complex *pmat = mat.fortran_vec (); | 946 octave_idx_type n = r.nelem (); |
940 | 947 ComplexMatrix result (1, n); |
941 pmat[0] = std::pow (a, r.base ()); | 948 |
942 Complex mul = std::pow (a, r.inc ()); | 949 if (same_sign (r.base (), r.inc ())) |
943 for (octave_idx_type i = 1; i < r.nelem (); i++) | 950 { |
944 pmat[i] = pmat[i-1] * mul; | 951 Complex base = std::pow (a, r.base ()); |
945 | 952 Complex inc = std::pow (a, r.inc ()); |
946 retval = mat; | 953 result(0) = base; |
947 } | 954 for (octave_idx_type i = 1; i < n; i++) |
955 result(i) = (base *= inc); | |
956 } | |
957 else | |
958 { | |
959 // Don't use Range::limit () here. | |
960 Complex limit = std::pow (a, r.base () + (n-1) * r.inc ()); | |
961 Complex inc = std::pow (a, -r.inc ()); | |
962 result(n-1) = limit; | |
963 for (octave_idx_type i = n-2; i >= 0; i--) | |
964 result(i) = (limit *= inc); | |
965 } | |
966 | |
967 retval = result; | |
968 } | |
969 else | |
970 retval = elem_xpow (a, r.matrix_value ()); | |
971 | |
948 | 972 |
949 return retval; | 973 return retval; |
950 } | 974 } |
951 | 975 |
952 // -*- 9 -*- | 976 // -*- 9 -*- |