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