module Fraction exposing ( Erreur , Fraction , Resultat , add , den , div , estEntier , exp , frac , inv , mul , neg , num , opp , raw , sub , teX ) import Arithmetic exposing (gcd) type alias Fraction = { num : Int, den : Int } type alias Resultat = Result Erreur Fraction type alias Erreur = String frac : Int -> Int -> Resultat frac a b = let min = 1 - 2 ^ 31 max = 2 ^ 31 - 1 in case b of 0 -> Err "Division par zéro." _ -> if a > max || b > max || a < min || b < min then Err "Certains calculs font intervenir des valeurs trop grandes pour être prises en charge." else Ok <| simplifier <| Fraction a b simplifier : Fraction -> Fraction simplifier a = let pgcd = gcd a.num a.den sgnDuDen = if a.den < 0 then -1 else 1 in { a | num = sgnDuDen * (a.num // pgcd) , den = sgnDuDen * (a.den // pgcd) } num a = a.num den a = a.den estEntier a = a.den == 1 opp : (Fraction -> Fraction -> Resultat) -> Resultat -> Resultat -> Resultat opp operation resultat1 resultat2 = case ( resultat1, resultat2 ) of ( Ok fraction1, Ok fraction2 ) -> operation fraction1 fraction2 ( Err erreur, _ ) -> Err erreur ( _, Err erreur ) -> Err erreur add : Fraction -> Fraction -> Resultat add a b = let pgcd = gcd a.den b.den aDenBis = a.den // pgcd bDenBis = b.den // pgcd in frac (a.num * bDenBis + b.num * aDenBis) (a.den * bDenBis) neg : Fraction -> Fraction neg a = Fraction -a.num a.den sub : Fraction -> Fraction -> Resultat sub a b = add a (neg b) mul : Fraction -> Fraction -> Resultat mul a b = let pgcd = gcd a.num b.den pgcdBis = gcd b.num a.den aNum = a.num // pgcd aDen = a.den // pgcdBis bNum = b.num // pgcdBis bDen = b.den // pgcd in frac (aNum * bNum) (aDen * bDen) inv : Fraction -> Resultat inv a = case a.num of 0 -> Err "Division par zéro" _ -> Ok <| Fraction a.den a.num div : Fraction -> Fraction -> Resultat div a b = Result.andThen (mul a) <| inv b exp : Fraction -> Fraction -> Resultat exp a b = let sgnDeA = if a.num < 0 then -1 else 1 sgnDeB = if b.num < 0 then -1 else 1 in if b.den == 1 && b.num < 0 then frac ((sgnDeA * a.den) ^ (sgnDeB * b.num)) ((sgnDeA * a.num) ^ (sgnDeB * b.num)) else if b.den == 1 then frac (a.num ^ b.num) (a.den ^ b.num) else Err "Extraction de racine impossible" teX a = case a.den of 1 -> String.fromInt a.num _ -> if a.num < 0 then "-\\frac{" ++ String.fromInt -a.num ++ "}{" ++ String.fromInt a.den ++ "}" else "\\frac{" ++ String.fromInt a.num ++ "}{" ++ String.fromInt a.den ++ "}" raw a = "(" ++ String.fromInt a.num ++ "/" ++ String.fromInt a.den ++ ")"