@@ -832,6 +832,142 @@ cdef _as_float(numerator, denominator):
832
832
return numerator / denominator
833
833
834
834
835
+ # Rational arithmetic algorithms: Knuth, TAOCP, Volume 2, 4.5.1.
836
+ #
837
+ # Assume input fractions a and b are normalized.
838
+ #
839
+ # 1) Consider addition/subtraction.
840
+ #
841
+ # Let g = gcd(da, db). Then
842
+ #
843
+ # na nb na*db ± nb*da
844
+ # a ± b == -- ± -- == ------------- ==
845
+ # da db da*db
846
+ #
847
+ # na*(db//g) ± nb*(da//g) t
848
+ # == ----------------------- == -
849
+ # (da*db)//g d
850
+ #
851
+ # Now, if g > 1, we're working with smaller integers.
852
+ #
853
+ # Note, that t, (da//g) and (db//g) are pairwise coprime.
854
+ #
855
+ # Indeed, (da//g) and (db//g) share no common factors (they were
856
+ # removed) and da is coprime with na (since input fractions are
857
+ # normalized), hence (da//g) and na are coprime. By symmetry,
858
+ # (db//g) and nb are coprime too. Then,
859
+ #
860
+ # gcd(t, da//g) == gcd(na*(db//g), da//g) == 1
861
+ # gcd(t, db//g) == gcd(nb*(da//g), db//g) == 1
862
+ #
863
+ # Above allows us optimize reduction of the result to lowest
864
+ # terms. Indeed,
865
+ #
866
+ # g2 = gcd(t, d) == gcd(t, (da//g)*(db//g)*g) == gcd(t, g)
867
+ #
868
+ # t//g2 t//g2
869
+ # a ± b == ----------------------- == ----------------
870
+ # (da//g)*(db//g)*(g//g2) (da//g)*(db//g2)
871
+ #
872
+ # is a normalized fraction. This is useful because the unnormalized
873
+ # denominator d could be much larger than g.
874
+ #
875
+ # We should special-case g == 1 (and g2 == 1), since 60.8% of
876
+ # randomly-chosen integers are coprime:
877
+ # https://en.wikipedia.org/wiki/Coprime_integers#Probability_of_coprimality
878
+ # Note, that g2 == 1 always for fractions, obtained from floats: here
879
+ # g is a power of 2 and the unnormalized numerator t is an odd integer.
880
+ #
881
+ # 2) Consider multiplication
882
+ #
883
+ # Let g1 = gcd(na, db) and g2 = gcd(nb, da), then
884
+ #
885
+ # na*nb na*nb (na//g1)*(nb//g2)
886
+ # a*b == ----- == ----- == -----------------
887
+ # da*db db*da (db//g1)*(da//g2)
888
+ #
889
+ # Note, that after divisions we're multiplying smaller integers.
890
+ #
891
+ # Also, the resulting fraction is normalized, because each of
892
+ # two factors in the numerator is coprime to each of the two factors
893
+ # in the denominator.
894
+ #
895
+ # Indeed, pick (na//g1). It's coprime with (da//g2), because input
896
+ # fractions are normalized. It's also coprime with (db//g1), because
897
+ # common factors are removed by g1 == gcd(na, db).
898
+ #
899
+ # As for addition/subtraction, we should special-case g1 == 1
900
+ # and g2 == 1 for same reason. That happens also for multiplying
901
+ # rationals, obtained from floats.
902
+
903
+ cdef _add(na, da, nb, db):
904
+ """ a + b"""
905
+ # return Fraction(na * db + nb * da, da * db)
906
+ g = _gcd(da, db)
907
+ if g == 1 :
908
+ return Fraction(na * db + da * nb, da * db, _normalize = False )
909
+ s = da // g
910
+ t = na * (db // g) + nb * s
911
+ g2 = _gcd(t, g)
912
+ if g2 == 1 :
913
+ return Fraction(t, s * db, _normalize = False )
914
+ return Fraction(t // g2, s * (db // g2), _normalize = False )
915
+
916
+ cdef _sub(na, da, nb, db):
917
+ """ a - b"""
918
+ # return Fraction(na * db - nb * da, da * db)
919
+ g = _gcd(da, db)
920
+ if g == 1 :
921
+ return Fraction(na * db - da * nb, da * db, _normalize = False )
922
+ s = da // g
923
+ t = na * (db // g) - nb * s
924
+ g2 = _gcd(t, g)
925
+ if g2 == 1 :
926
+ return Fraction(t, s * db, _normalize = False )
927
+ return Fraction(t // g2, s * (db // g2), _normalize = False )
928
+
929
+ cdef _mul(na, da, nb, db):
930
+ """ a * b"""
931
+ # return Fraction(na * nb, da * db)
932
+ g1 = _gcd(na, db)
933
+ if g1 > 1 :
934
+ na //= g1
935
+ db //= g1
936
+ g2 = _gcd(nb, da)
937
+ if g2 > 1 :
938
+ nb //= g2
939
+ da //= g2
940
+ return Fraction(na * nb, db * da, _normalize = False )
941
+
942
+ cdef _div(na, da, nb, db):
943
+ """ a / b"""
944
+ # return Fraction(na * db, da * nb)
945
+ # Same as _mul(), with inversed b.
946
+ g1 = _gcd(na, nb)
947
+ if g1 > 1 :
948
+ na //= g1
949
+ nb //= g1
950
+ g2 = _gcd(db, da)
951
+ if g2 > 1 :
952
+ da //= g2
953
+ db //= g2
954
+ n, d = na * db, nb * da
955
+ if d < 0 :
956
+ n, d = - n, - d
957
+ return Fraction(n, d, _normalize = False )
958
+
959
+ cdef _floordiv(an, ad, bn, bd):
960
+ """ a // b -> int"""
961
+ return (an * bd) // (bn * ad)
962
+
963
+ cdef _divmod(an, ad, bn, bd):
964
+ div, n_mod = divmod (an * bd, ad * bn)
965
+ return div, Fraction(n_mod, ad * bd)
966
+
967
+ cdef _mod(an, ad, bn, bd):
968
+ return Fraction((an * bd) % (bn * ad), ad * bd)
969
+
970
+
835
971
"""
836
972
In general, we want to implement the arithmetic operations so
837
973
that mixed-mode operations either call an implementation whose
@@ -906,35 +1042,6 @@ uses similar boilerplate code:
906
1042
will get a TypeError.
907
1043
"""
908
1044
909
-
910
- cdef _add(an, ad, bn, bd):
911
- """ a + b"""
912
- return Fraction(an * bd + bn * ad, ad * bd)
913
-
914
- cdef _sub(an, ad, bn, bd):
915
- """ a - b"""
916
- return Fraction(an * bd - bn * ad, ad * bd)
917
-
918
- cdef _mul(an, ad, bn, bd):
919
- """ a * b"""
920
- return Fraction(an * bn, ad * bd)
921
-
922
- cdef _div(an, ad, bn, bd):
923
- """ a / b"""
924
- return Fraction(an * bd, ad * bn)
925
-
926
- cdef _floordiv(an, ad, bn, bd):
927
- """ a // b -> int"""
928
- return (an * bd) // (bn * ad)
929
-
930
- cdef _divmod(an, ad, bn, bd):
931
- div, n_mod = divmod (an * bd, ad * bn)
932
- return div, Fraction(n_mod, ad * bd)
933
-
934
- cdef _mod(an, ad, bn, bd):
935
- return Fraction((an * bd) % (bn * ad), ad * bd)
936
-
937
-
938
1045
cdef:
939
1046
_math_op_add = operator.add
940
1047
_math_op_sub = operator.sub
0 commit comments