Révision 165 pobysoPythonSage/src/sageSLZ/sageSLZ.sage
sageSLZ.sage (revision 165) | ||
---|---|---|
89 | 89 |
|
90 | 90 |
# End slz_check_htr_value. |
91 | 91 |
|
92 |
def slz_compute_binade(number): |
|
93 |
"""" |
|
94 |
For a given number, compute the "binade" that is integer m such that |
|
95 |
2^m <= number < 2^(m+1). If number == 0 return None. |
|
96 |
""" |
|
97 |
# Checking the parameter. |
|
98 |
# The exception construction is used to detect if numbre is a RealNumber |
|
99 |
# since not all numbers have |
|
100 |
# the mro() method. sage.rings.real_mpfr.RealNumber do. |
|
101 |
try: |
|
102 |
classTree = [number.__class__] + number.mro() |
|
103 |
# If the number is not a RealNumber (of offspring thereof) try |
|
104 |
# to transform it. |
|
105 |
if not sage.rings.real_mpfr.RealNumber in classTree: |
|
106 |
numberAsRR = RR(number) |
|
107 |
else: |
|
108 |
numberAsRR = number |
|
109 |
except AttributeError: |
|
110 |
return None |
|
111 |
# Zero special case. |
|
112 |
if numberAsRR == 0: |
|
113 |
return RR(-infinity) |
|
114 |
else: |
|
115 |
return floor(numberAsRR.abs().log2()) |
|
116 |
# End slz_compute_binade |
|
117 |
|
|
92 | 118 |
# |
93 | 119 |
def slz_compute_binade_bounds(number, emin, emax=sys.maxint): |
94 | 120 |
""" |
... | ... | |
103 | 129 |
""" |
104 | 130 |
# Check the parameters. |
105 | 131 |
# RealNumbers or RealNumber offspring only. |
106 |
# The execption construction is necessary since not all objects have
|
|
132 |
# The exception construction is necessary since not all objects have
|
|
107 | 133 |
# the mro() method. sage.rings.real_mpfr.RealNumber do. |
108 | 134 |
try: |
109 | 135 |
classTree = [number.__class__] + number.mro() |
... | ... | |
134 | 160 |
return (RF(2^(emax+1)), RF(+infinity) ) |
135 | 161 |
else: |
136 | 162 |
return (RF(-infinity), -RF(2^(emax+1))) |
163 |
# Regular case cont'd. |
|
137 | 164 |
offset = int(l2) |
138 | 165 |
# number.abs() >= 1. |
139 | 166 |
if l2 >= 0: |
... | ... | |
879 | 906 |
""" |
880 | 907 |
Compute the scaling expression to map an interval that spans at most |
881 | 908 |
a single binade to [1, 2) and the inverse expression as well. |
909 |
If the interval spans more than one binade, result is wrong since |
|
910 |
scaling is only based on the lower bound. |
|
882 | 911 |
Not very sure that the transformation makes sense for negative numbers. |
883 | 912 |
""" |
913 |
# The "one of the bounds is 0" special case. Here we consider |
|
914 |
# the interval as the subnormals binade. |
|
915 |
if boundsInterval.endpoints()[0] == 0 or boundsInterval.endpoints()[1] == 0: |
|
916 |
# The upper bound is (or should be) positive. |
|
917 |
if boundsInterval.endpoints()[0] == 0: |
|
918 |
if boundsInterval.endpoints()[1] == 0: |
|
919 |
return None |
|
920 |
binade = slz_compute_binade(boundsInterval.endpoints()[1]) |
|
921 |
l2 = boundsInterval.endpoints()[1].abs().log2() |
|
922 |
# The upper bound is a power of two |
|
923 |
if binade == l2: |
|
924 |
scalingCoeff = 2^(-binade) |
|
925 |
invScalingCoeff = 2^(binade) |
|
926 |
scalingOffset = 1 |
|
927 |
return((scalingCoeff * expVar + scalingOffset),\ |
|
928 |
((expVar - scalingOffset) * invScalingCoeff)) |
|
929 |
else: |
|
930 |
scalingCoeff = 2^(-binade-1) |
|
931 |
invScalingCoeff = 2^(binade+1) |
|
932 |
scalingOffset = 1 |
|
933 |
return((scalingCoeff * expVar + scalingOffset),\ |
|
934 |
((expVar - scalingOffset) * invScalingCoeff)) |
|
935 |
# The lower bound is (or should be) negative. |
|
936 |
if boundsInterval.endpoints()[1] == 0: |
|
937 |
if boundsInterval.endpoints()[0] == 0: |
|
938 |
return None |
|
939 |
binade = slz_compute_binade(boundsInterval.endpoints()[0]) |
|
940 |
l2 = boundsInterval.endpoints()[0].abs().log2() |
|
941 |
# The upper bound is a power of two |
|
942 |
if binade == l2: |
|
943 |
scalingCoeff = -2^(-binade) |
|
944 |
invScalingCoeff = -2^(binade) |
|
945 |
scalingOffset = 1 |
|
946 |
return((scalingCoeff * expVar + scalingOffset),\ |
|
947 |
((expVar - scalingOffset) * invScalingCoeff)) |
|
948 |
else: |
|
949 |
scalingCoeff = -2^(-binade-1) |
|
950 |
invScalingCoeff = -2^(binade+1) |
|
951 |
scalingOffset = 1 |
|
952 |
return((scalingCoeff * expVar + scalingOffset),\ |
|
953 |
((expVar - scalingOffset) * invScalingCoeff)) |
|
954 |
# General case |
|
955 |
lbBinade = slz_compute_binade(boundsInterval.endpoints()[0]) |
|
956 |
ubBinade = slz_compute_binade(boundsInterval.endpoints()[1]) |
|
957 |
# We allow for a single exception in binade spanning is when the |
|
958 |
# "outward bound" is a power of 2 and its binade is that of the |
|
959 |
# "inner bound" + 1. |
|
960 |
if boundsInterval.endpoints()[0] > 0: |
|
961 |
ubL2 = boundsInterval.endpoints()[1].abs().log2() |
|
962 |
if lbBinade != ubBinade: |
|
963 |
print "Different binades." |
|
964 |
if ubL2 != ubBinade: |
|
965 |
print "Not a power of 2." |
|
966 |
return None |
|
967 |
elif abs(ubBinade - lbBinade) > 1: |
|
968 |
print "Too large span:", abs(ubBinade - lbBinade) |
|
969 |
return None |
|
970 |
else: |
|
971 |
lbL2 = boundsInterval.endpoints()[0].abs().log2() |
|
972 |
if lbBinade != ubBinade: |
|
973 |
print "Different binades." |
|
974 |
if lbL2 != lbBinade: |
|
975 |
print "Not a power of 2." |
|
976 |
return None |
|
977 |
elif abs(ubBinade - lbBinade) > 1: |
|
978 |
print "Too large span:", abs(ubBinade - lbBinade) |
|
979 |
return None |
|
980 |
#print "Lower bound binade:", binade |
|
981 |
if boundsInterval.endpoints()[0] > 0: |
|
982 |
return((2^(-lbBinade) * expVar),(2^(lbBinade) * expVar)) |
|
983 |
else: |
|
984 |
return((-(2^(-lbBinade+1)) * expVar),(-(2^(lbBinade-1)) * expVar)) |
|
985 |
""" |
|
986 |
# Code sent to attic. Should be the base for a |
|
987 |
# "slz_interval_translate_expression" rather than scale. |
|
988 |
# Extra control and special cases code added in |
|
989 |
# slz_interval_scaling_expression could (should ?) be added to |
|
990 |
# this new function. |
|
884 | 991 |
# The scaling offset is only used for negative numbers. |
885 | 992 |
# When the absolute value of the lower bound is < 0. |
886 | 993 |
if abs(boundsInterval.endpoints()[0]) < 1: |
... | ... | |
908 | 1015 |
#scalingOffset = 0 |
909 | 1016 |
return((scalingCoeff * expVar + scalingOffset, |
910 | 1017 |
1/scalingCoeff * expVar + 3)) |
1018 |
""" |
|
911 | 1019 |
# End slz_interval_scaling_expression |
912 | 1020 |
|
913 | 1021 |
def slz_interval_and_polynomial_to_sage(polyRangeCenterErrorSo): |
Formats disponibles : Unified diff