Révision 176

pobysoPythonSage/src/sageSLZ/sageSLZ.sage (revision 176)
112 112
    if numberAsRR == 0:
113 113
        return RR(-infinity)
114 114
    else:
115
        return floor(numberAsRR.abs().log2())
115
        realField           = numberAsRR.parent()
116
        numberLog2          = numberAsRR.abs().log2()
117
        floorNumberLog2     = floor(numberLog2)
118
        ## Do not get caught by rounding of log2() both ways.
119
        ## When numberLog2 is an integer, compare numberAsRR
120
        #  with 2^numberLog2.
121
        if floorNumberLog2 == numberLog2:
122
            if numberAsRR.abs() < realField(2^floorNumberLog2):
123
                return floorNumberLog2 - 1
124
            else:
125
                return floorNumberLog2
126
        else:
127
            return floorNumberLog2
116 128
# End slz_compute_binade
117 129

  
118 130
#
......
480 492
    if lowerBoundSa > upperBoundSa:
481 493
        return None
482 494
    RRR = lowerBoundSa.parent()
483
    intervalShrinkConstFactorSa = RRR('0.8')
495
    intervalShrinkConstFactorSa = RRR('0.9')
484 496
    absoluteErrorTypeSo = pobyso_absolute_so_so()
485 497
    currentRangeSo = pobyso_bounds_to_range_sa_so(lowerBoundSa, upperBoundSa)
486 498
    currentUpperBoundSa = upperBoundSa
......
498 510
        sollya_lib_clear_obj(polySo)
499 511
        sollya_lib_clear_obj(intervalCenterSo)
500 512
        sollya_lib_clear_obj(maxErrorSo)
501
        shrinkFactorSa = RRR('5')/(maxErrorSa/approxPrecSa).log2().abs()
502
        #shrinkFactorSa = 1.5/(maxErrorSa/approxPrecSa)
513
        # Very empirical schrinking factor.
514
        shrinkFactorSa = 1 /  (maxErrorSa/approxPrecSa).log2().abs()
515
        print "Shrink factor:", shrinkFactorSa, intervalShrinkConstFactorSa
503 516
        #errorRatioSa = approxPrecSa/maxErrorSa
504 517
        #print "Error ratio: ", errorRatioSa
505 518
        if shrinkFactorSa > intervalShrinkConstFactorSa:
......
540 553
        #print "Sollya prec:",
541 554
        #pobyso_autoprint(sollya_lib_get_prec(None))
542 555
    sollya_lib_clear_obj(absoluteErrorTypeSo)
543
    return((polySo, currentRangeSo, intervalCenterSo, maxErrorSo))
556
    return (polySo, currentRangeSo, intervalCenterSo, maxErrorSo)
544 557
# End slz_compute_polynomial_and_interval
545 558

  
546 559
def slz_compute_reduced_polynomial(matrixRow,
......
795 808
    degreeSo = pobyso_constant_from_int_sa_so(degreeSa)
796 809
    scaledBoundsSo = pobyso_bounds_to_range_sa_so(scaledLowerBoundSa, 
797 810
                                                  scaledUpperBoundSa)
798
    # Compute the first Taylor expansion.
799
    print "Computing first Taylor expansion..."
800
    (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
801
        slz_compute_polynomial_and_interval(functionSo, degreeSo,
802
                                        scaledLowerBoundSa, scaledUpperBoundSa,
803
                                        approxPrecSa, internalSollyaPrecSa)
804
    print "...done."
805
    if polySo is None:
806
        print "slz_get_intervals_and_polynomials: Aborting and returning None!"
807
        if precChangedSa:
808
            pobyso_set_prec_so_so(currentSollyaPrecSo)
809
            sollya_lib_clear_obj(currentSollyaPrecSo)
810
        sollya_lib_clear_obj(functionSo)
811
        sollya_lib_clear_obj(degreeSo)
812
        sollya_lib_clear_obj(scaledBoundsSo)
813
        return None
811

  
814 812
    realIntervalField = RealIntervalField(max(lowerBoundSa.parent().precision(),
815 813
                                              upperBoundSa.parent().precision()))
816
    boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
817
    errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
818
    print "First approximation error:", errorSa.n(digits=10)
819
    # If the error and interval are OK a the first try, just return.
820
    if boundsSa.endpoints()[1] >= scaledUpperBoundSa:
821
        # Change variable stuff in Sollya x -> x0-x.
822
        changeVarExpressionSo = sollya_lib_build_function_sub( \
823
                              sollya_lib_build_function_free_variable(), \
814
    currentScaledLowerBoundSa = scaledLowerBoundSa
815
    currentScaledUpperBoundSa = scaledUpperBoundSa
816
    while True:
817
        ## Compute the first Taylor expansion.
818
        print "Computing a Taylor expansion..."
819
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
820
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
821
                                        currentScaledLowerBoundSa, 
822
                                        currentScaledUpperBoundSa,
823
                                        approxPrecSa, internalSollyaPrecSa)
824
        print "...done."
825
        ## If slz_compute_polynomial_and_interval fails, it returns None.
826
        #  This value goes to the first variable: polySo. Other variables are
827
        #  not assigned and should not be tested.
828
        if polySo is None:
829
            print "slz_get_intervals_and_polynomials: Aborting and returning None!"
830
            if precChangedSa:
831
                pobyso_set_prec_so_so(currentSollyaPrecSo)
832
                sollya_lib_clear_obj(currentSollyaPrecSo)
833
            sollya_lib_clear_obj(functionSo)
834
            sollya_lib_clear_obj(degreeSo)
835
            sollya_lib_clear_obj(scaledBoundsSo)
836
            return None
837
        ## Add to the result array.
838
        ### Change variable stuff in Sollya x -> x0-x.
839
        changeVarExpressionSo = \
840
            sollya_lib_build_function_sub( \
841
                              sollya_lib_build_function_free_variable(), 
824 842
                              sollya_lib_copy_obj(intervalCenterSo))
825
        polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo) 
843
        polyVarChangedSo = \
844
                    sollya_lib_evaluate(polySo, changeVarExpressionSo)
845
        #### Get rid of the variable change Sollya stuff. 
826 846
        sollya_lib_clear_obj(changeVarExpressionSo)
827
        resultArray.append((polySo, polyVarChangedSo, boundsSo, \
847
        resultArray.append((polySo, polyVarChangedSo, boundsSo,
828 848
                            intervalCenterSo, maxErrorSo))
829
        if internalSollyaPrecSa != currentSollyaPrecSa:
830
            pobyso_set_prec_sa_so(currentSollyaPrecSa)
831
        sollya_lib_clear_obj(currentSollyaPrecSo)
832
        sollya_lib_clear_obj(functionSo)
833
        sollya_lib_clear_obj(degreeSo)
834
        sollya_lib_clear_obj(scaledBoundsSo)
835
        #print "Approximation error:", errorSa
836
        return resultArray
837
    # The returned interval upper bound does not reach the requested upper
838
    # upper bound: compute the next upper bound.
839
    # The following ratio is always >= 1
840
    currentErrorRatio = approxPrecSa / errorSa
841
    # Starting point for the next upper bound.
842
    currentScaledUpperBoundSa = boundsSa.endpoints()[1]
843
    boundsWidthSa = boundsSa.endpoints()[1] - boundsSa.endpoints()[0]
844
    # Compute the increment. 
845
    if currentErrorRatio > RR('1000'): # ]1.5, infinity[
846
        currentScaledUpperBoundSa += \
847
                        currentErrorRatio * boundsWidthSa * 2
848
    else:  # [1, 1.5]
849
        currentScaledUpperBoundSa += \
850
                        (RR('1.0') + currentErrorRatio.log() / 500) * boundsWidthSa
851
    # Take into account the original interval upper bound.                     
852
    if currentScaledUpperBoundSa > scaledUpperBoundSa:
853
        currentScaledUpperBoundSa = scaledUpperBoundSa
854
    # Compute the other expansions.
855
    while boundsSa.endpoints()[1] < scaledUpperBoundSa:
856
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
857
        (polySo, boundsSo, intervalCenterSo, maxErrorSo) = \
858
            slz_compute_polynomial_and_interval(functionSo, degreeSo,
859
                                            currentScaledLowerBoundSa, 
860
                                            currentScaledUpperBoundSa, 
861
                                            approxPrecSa, 
862
                                            internalSollyaPrecSa)
849
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
863 850
        errorSa = pobyso_get_constant_as_rn_with_rf_so_sa(maxErrorSo)
864
        if  errorSa < approxPrecSa:
865
            # Change variable stuff
851
        print "Computed approximation error:", errorSa.n(digits=10)
852
        # If the error and interval are OK a the first try, just return.
853
        if (boundsSa.endpoints()[1] >= scaledUpperBoundSa) and \
854
            (errorSa <= approxPrecSa):
855
            if precChangedSa:
856
                pobyso_set_prec_sa_so(currentSollyaPrecSa)
857
            sollya_lib_clear_obj(currentSollyaPrecSo)
858
            sollya_lib_clear_obj(functionSo)
859
            sollya_lib_clear_obj(degreeSo)
860
            sollya_lib_clear_obj(scaledBoundsSo)
866 861
            #print "Approximation error:", errorSa
867
            changeVarExpressionSo = sollya_lib_build_function_sub(
868
                                    sollya_lib_build_function_free_variable(), 
869
                                    sollya_lib_copy_obj(intervalCenterSo))
870
            polyVarChangedSo = sollya_lib_evaluate(polySo, changeVarExpressionSo) 
871
            sollya_lib_clear_obj(changeVarExpressionSo)
872
            resultArray.append((polySo, polyVarChangedSo, boundsSo, \
873
                                intervalCenterSo, maxErrorSo))
874
        boundsSa = pobyso_range_to_interval_so_sa(boundsSo, realIntervalField)
875
        # Compute the next upper bound.
876
        # The following ratio is always >= 1
862
            return resultArray
863
        ## The returned interval upper bound does not reach the requested upper
864
        #  upper bound: compute the next upper bound.
865
        ## The following ratio is always >= 1. If errorSa, we may want to
866
        #  enlarge the interval
877 867
        currentErrorRatio = approxPrecSa / errorSa
878
        # Starting point for the next upper bound.
879
        currentScaledUpperBoundSa = boundsSa.endpoints()[1]
868
        ## --|--------------------------------------------------------------|--
869
        #  --|--------------------|--------------------------------------------
870
        #  --|----------------------------|------------------------------------
871
        ## Starting point for the next upper bound.
880 872
        boundsWidthSa = boundsSa.endpoints()[1] - boundsSa.endpoints()[0]
881 873
        # Compute the increment. 
882
        if currentErrorRatio > RR('1000'): # ]1.5, infinity[
883
            currentScaledUpperBoundSa += \
884
                            currentErrorRatio * boundsWidthSa * 2
885
        else:  # [1, 1.5]
886
            currentScaledUpperBoundSa += \
887
                     (RR('1.0') + currentErrorRatio.log()/500) * boundsWidthSa
888
        #print "currentErrorRatio:", currentErrorRatio
889
        #print "currentScaledUpperBoundSa", currentScaledUpperBoundSa
890
        # Test for insufficient precision.
891
        if currentScaledUpperBoundSa == scaledLowerBoundSa:
874
        newBoundsWidthSa = \
875
                        ((currentErrorRatio.log() / 10) + 1) * boundsWidthSa
876
        currentScaledLowerBoundSa = boundsSa.endpoints()[1]
877
        currentScaledUpperBoundSa = boundsSa.endpoints()[1] + newBoundsWidthSa
878
        # Take into account the original interval upper bound.                     
879
        if currentScaledUpperBoundSa > scaledUpperBoundSa:
880
            currentScaledUpperBoundSa = scaledUpperBoundSa
881
        if currentScaledUpperBoundSa == currentScaledLowerBoundSa:
892 882
            print "Can't shrink the interval anymore!"
893 883
            print "You should consider increasing the Sollya internal precision"
894 884
            print "or the polynomial degree."
895 885
            print "Giving up!"
896
            if internalSollyaPrecSa != currentSollyaPrecSa:
886
            if precChangedSa:
897 887
                pobyso_set_prec_sa_so(currentSollyaPrecSa)
898 888
            sollya_lib_clear_obj(currentSollyaPrecSo)
899 889
            sollya_lib_clear_obj(functionSo)
900 890
            sollya_lib_clear_obj(degreeSo)
901 891
            sollya_lib_clear_obj(scaledBoundsSo)
902 892
            return None
903
        if currentScaledUpperBoundSa > scaledUpperBoundSa:
904
            currentScaledUpperBoundSa = scaledUpperBoundSa
905
    if internalSollyaPrecSa > currentSollyaPrecSa:
906
        pobyso_set_prec_so_so(currentSollyaPrecSo)
907
    sollya_lib_clear_obj(currentSollyaPrecSo)
908
    sollya_lib_clear_obj(functionSo)
909
    sollya_lib_clear_obj(degreeSo)
910
    sollya_lib_clear_obj(scaledBoundsSo)
911
    return(resultArray)
893
        # Compute the other expansions.
894
        # Test for insufficient precision.
912 895
# End slz_get_intervals_and_polynomials
913 896

  
914

  
915 897
def slz_interval_scaling_expression(boundsInterval, expVar):
916 898
    """
917 899
    Compute the scaling expression to map an interval that spans at most

Formats disponibles : Unified diff