diff --git a/compiler/dcalc/interpreter.ml b/compiler/dcalc/interpreter.ml index 2e11cb52..3ce69442 100644 --- a/compiler/dcalc/interpreter.ml +++ b/compiler/dcalc/interpreter.ml @@ -256,7 +256,7 @@ and evaluate_operator : | Mult_mon_rat, [LMoney x; LRat y] -> LMoney (o_mult_mon_rat x y) | Mult_dur_int, [LDuration x; LInt y] -> LDuration (o_mult_dur_int x y) - | Div_int_int, [LInt x; LInt y] -> LInt (protect o_div_int_int x y) + | Div_int_int, [LInt x; LInt y] -> LRat (protect o_div_int_int x y) | Div_rat_rat, [LRat x; LRat y] -> LRat (protect o_div_rat_rat x y) | Div_mon_mon, [LMoney x; LMoney y] -> LRat (protect o_div_mon_mon x y) diff --git a/compiler/shared_ast/operator.ml b/compiler/shared_ast/operator.ml index ff7566b2..0acb4c48 100644 --- a/compiler/shared_ast/operator.ml +++ b/compiler/shared_ast/operator.ml @@ -435,7 +435,7 @@ let resolved_type (op, pos) = | Mult_rat_rat -> TRat @- TRat @-> TRat | Mult_mon_rat -> TMoney @- TRat @-> TMoney | Mult_dur_int -> TDuration @- TInt @-> TDuration - | Div_int_int -> TInt @- TInt @-> TInt + | Div_int_int -> TInt @- TInt @-> TRat | Div_rat_rat -> TRat @- TRat @-> TRat | Div_mon_mon -> TMoney @- TMoney @-> TRat | Div_mon_rat -> TMoney @- TRat @-> TMoney diff --git a/examples/tutorial_en/tutorial_en.catala_en b/examples/tutorial_en/tutorial_en.catala_en index 3296985e..52bf0e2c 100644 --- a/examples/tutorial_en/tutorial_en.catala_en +++ b/examples/tutorial_en/tutorial_en.catala_en @@ -177,12 +177,11 @@ subtraction "-", multiplication "*" and division (slash). However, in the Catala code, you should be aware that these operators can behave differently depending on the quantities considered: indeed, money for example is -rounded at the cent ; integers are rounded down on division. The Catala compiler -is able to automatically select the appropriate operation: here it can detect -that money is being multiplied by a decimal (percentage) which is a known -operation that yields an amount of money, rounded at the cent. Some other -operations are not allowed, like multiplying two amounts of money together, or -adding two dates. +rounded at the cent. The Catala compiler is able to automatically select the +appropriate operation: here it can detect that money is being multiplied by a +decimal which is a known operation that yields an amount of money, rounded at +the cent. Some other operations are not allowed, like multiplying two amounts of +money together, or adding two dates. Coming back to article 1, one question remains unknown: what is the value of the fixed percentage? Often, precise values are defined elsewhere in the @@ -742,9 +741,9 @@ declaration scope IntegerValues: internal value2 content integer scope IntegerValues: - definition value1 under condition 12 - (5 * 3) < 65 consequence equals 45 / 9 + definition value1 under condition 12 - (5 * 3) < 65 consequence equals 45 * 9 # The / operators corresponds to an integer division that truncates towards 0. - definition value2 equals value1 * value1 * 65 / 100 + definition value2 equals value1 * value1 * 65 * 100 ``` ### Decimals @@ -761,8 +760,9 @@ declaration scope DecimalValues: scope DecimalValues: definition value1 under condition 12.655465446655426 - 0.45265426541654 < 12.3554654652 consequence - equals (integer_to_decimal of 45) / (integer_to_decimal of 9) - # The / operators corresponds to an exact division. + equals 45 / 9 + # The / operator corresponds to an exact division. The division of integers + # yields a decimal. definition value2 equals value1 * value1 * 65% # Percentages are decimal numbers (0.65 here) ``` diff --git a/examples/tutoriel_fr/tutoriel_fr.catala_fr b/examples/tutoriel_fr/tutoriel_fr.catala_fr index a7a71714..e0f1821e 100644 --- a/examples/tutoriel_fr/tutoriel_fr.catala_fr +++ b/examples/tutoriel_fr/tutoriel_fr.catala_fr @@ -147,12 +147,12 @@ et division (barre oblique). Toutefois, dans le code Catala, ces opérateurs peuvent avoir un sens légèrement différent suivant unités concernées. En effet, l'argent par exemple est arrondi -au centime ; les entiers sont tronqués lors de leur division. Le compilateur -Catala sélectionne automatiquement l'opération appropriée: ici, de l'argent est -multiplié par un pourcentage (soit un nombre décimal), ce qui est une opération -connue dont le résultat est une quantité d'argent, arrondie au centime. D'autres -opérations sont rejetées, comme la multiplication de deux quantités d'argent -entre elles, ou bien l'addition de deux dates. +au centime. Le compilateur Catala sélectionne automatiquement l'opération +appropriée: ici, de l'argent est multiplié par un pourcentage (soit un nombre +décimal), ce qui est une opération connue dont le résultat est une quantité +d'argent, arrondie au centime. D'autres opérations sont rejetées, comme la +multiplication de deux quantités d'argent entre elles, ou l'addition de deux +dates. Revenons à l'article 1, dont une question reste sans réponse: quelle est la valeur de la pourcentage fixe? Souvent, des valeurs précises sont définis diff --git a/runtimes/ocaml/runtime.ml b/runtimes/ocaml/runtime.ml index 47ffc8b1..2c635c7a 100644 --- a/runtimes/ocaml/runtime.ml +++ b/runtimes/ocaml/runtime.ml @@ -639,7 +639,11 @@ module Oper = struct else Z.(res * of_int sign_int) let o_mult_dur_int d m = Dates_calc.Dates.mul_period d (Z.to_int m) - let o_div_int_int i1 i2 = Z.div i1 i2 (* raises Division_by_zero *) + + let o_div_int_int i1 i2 = + (* It's not on the ocamldoc, but Q.div likely already raises this ? *) + if Z.zero = i2 then raise Division_by_zero + else Q.div (Q.of_bigint i1) (Q.of_bigint i2) let o_div_rat_rat i1 i2 = if Q.zero = i2 then raise Division_by_zero else Q.div i1 i2 diff --git a/runtimes/ocaml/runtime.mli b/runtimes/ocaml/runtime.mli index aba59ba6..6d133081 100644 --- a/runtimes/ocaml/runtime.mli +++ b/runtimes/ocaml/runtime.mli @@ -326,7 +326,7 @@ module Oper : sig val o_mult_rat_rat : decimal -> decimal -> decimal val o_mult_mon_rat : money -> decimal -> money val o_mult_dur_int : duration -> integer -> duration - val o_div_int_int : integer -> integer -> integer + val o_div_int_int : integer -> integer -> decimal val o_div_rat_rat : decimal -> decimal -> decimal val o_div_mon_mon : money -> money -> decimal val o_div_mon_rat : money -> decimal -> money diff --git a/runtimes/python/catala/src/catala/runtime.py b/runtimes/python/catala/src/catala/runtime.py index 8ad76117..6bcfa705 100644 --- a/runtimes/python/catala/src/catala/runtime.py +++ b/runtimes/python/catala/src/catala/runtime.py @@ -39,8 +39,8 @@ class Integer: def __mul__(self, other: 'Integer') -> 'Integer': return Integer(self.value * other.value) - def __truediv__(self, other: 'Integer') -> 'Integer': - return Integer(self.value // other.value) + def __truediv__(self, other: 'Integer') -> 'Decimal': + return Decimal (self.value) / Decimal (other.value) def __neg__(self: 'Integer') -> 'Integer': return Integer(- self.value) diff --git a/tests/test_arithmetic/bad/division_by_zero.catala_en b/tests/test_arithmetic/bad/division_by_zero.catala_en index 743bb144..3e95f05e 100644 --- a/tests/test_arithmetic/bad/division_by_zero.catala_en +++ b/tests/test_arithmetic/bad/division_by_zero.catala_en @@ -4,7 +4,7 @@ ```catala declaration scope Int: - context i content integer + context i content decimal scope Int: definition i equals 1 / 0 diff --git a/tests/test_arithmetic/good/priorities.catala_en b/tests/test_arithmetic/good/priorities.catala_en index 9643c815..0062942c 100644 --- a/tests/test_arithmetic/good/priorities.catala_en +++ b/tests/test_arithmetic/good/priorities.catala_en @@ -3,13 +3,13 @@ declaration scope A: output w content integer output x content integer output y content integer - output z content integer + output z content decimal scope A: definition w equals 4 - 2 - 2 definition x equals 4 - (2 - 2) definition y equals 4 - 2 - -2 - definition z equals 200 / 2 * 4 - 50 / - (5 - 20 / 2) + definition z equals 200 / 2 * 4. - 50. / - (5. - 20 / 2) ``` ```catala-test-inline @@ -18,5 +18,5 @@ $ catala Interpret -s A [RESULT] w = 0 [RESULT] x = 4 [RESULT] y = 4 -[RESULT] z = 390 +[RESULT] z = 390. ``` diff --git a/tests/test_proof/bad/no_vars-conflict.catala_en b/tests/test_proof/bad/no_vars-conflict.catala_en index 3db441b1..6dc334c1 100644 --- a/tests/test_proof/bad/no_vars-conflict.catala_en +++ b/tests/test_proof/bad/no_vars-conflict.catala_en @@ -8,7 +8,7 @@ declaration scope A: context y content integer scope A: - definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54)) + definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54.)) consequence equals 0 definition y under condition x <= 0 consequence equals -1 diff --git a/tests/test_proof/bad/no_vars-empty.catala_en b/tests/test_proof/bad/no_vars-empty.catala_en index 3b3bfdcb..421728a1 100644 --- a/tests/test_proof/bad/no_vars-empty.catala_en +++ b/tests/test_proof/bad/no_vars-empty.catala_en @@ -7,7 +7,7 @@ declaration scope A: context y content integer scope A: - definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54)) + definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54.)) consequence equals 1 definition y under condition x <= 0 consequence equals -1 diff --git a/tests/test_proof/good/no_vars.catala_en b/tests/test_proof/good/no_vars.catala_en index 29a532b2..a2c65e4d 100644 --- a/tests/test_proof/good/no_vars.catala_en +++ b/tests/test_proof/good/no_vars.catala_en @@ -5,7 +5,7 @@ declaration scope A: context x content integer scope A: - definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54)) + definition x under condition (6*7 = 42) and (false or (true and 1458 / 27 = 54.)) consequence equals 0 ``` ```catala-test-inline diff --git a/tests/test_typing/bad/err3.catala_en b/tests/test_typing/bad/err3.catala_en index 39f0239e..04cdd814 100644 --- a/tests/test_typing/bad/err3.catala_en +++ b/tests/test_typing/bad/err3.catala_en @@ -7,7 +7,7 @@ scope S: Structure { -- i: 4 -- e: y }; Structure { -- i: 5 -- e: Dat content |1970-01-01| } ] - definition a equals number of (z ++ z) / 2 + definition a equals number of (z ++ z) * 2 ``` ```catala-test-inline @@ -19,14 +19,14 @@ $ catala Typecheck Error coming from typechecking the following expression: ┌─⯈ tests/test_typing/bad/err3.catala_en:10.41-42: └──┐ -10 │ definition a equals number of (z ++ z) / 2 +10 │ definition a equals number of (z ++ z) * 2 │ ‾ Type integer coming from expression: ┌─⯈ tests/test_typing/bad/err3.catala_en:10.41-42: └──┐ -10 │ definition a equals number of (z ++ z) / 2 +10 │ definition a equals number of (z ++ z) * 2 │ ‾ @@ -50,14 +50,14 @@ $ catala ocaml Error coming from typechecking the following expression: ┌─⯈ tests/test_typing/bad/err3.catala_en:10.41-42: └──┐ -10 │ definition a equals number of (z ++ z) / 2 +10 │ definition a equals number of (z ++ z) * 2 │ ‾ Type integer coming from expression: ┌─⯈ tests/test_typing/bad/err3.catala_en:10.41-42: └──┐ -10 │ definition a equals number of (z ++ z) / 2 +10 │ definition a equals number of (z ++ z) * 2 │ ‾ diff --git a/tests/test_typing/good/overload.catala_en b/tests/test_typing/good/overload.catala_en index 6e13693a..6c423bc8 100644 --- a/tests/test_typing/good/overload.catala_en +++ b/tests/test_typing/good/overload.catala_en @@ -29,8 +29,8 @@ scope S: definition t1 equals |2022-01-09| definition t2 equals |2022-01-10| - definition o_i equals -i1 + i2 - i1 * i2 / (i1 + i2) - definition o_x equals -x1 + x2 - x1 * x2 / (x1 + x2) + definition o_i equals -i1 + i2 - i1 * i2 * (i1 + i2) + definition o_x equals -x1 + x2 - x1 * x2 / (x1 + x2) * (i1 / i2) definition o_m equals -m1 + m2 - m1 * x2 / (x1 * m1 / m2) + m1 / x2 definition o_d equals -d1 + d2 - d1 * i2 definition o_t equals d1 + t1 + d1 + (t2 - t1) @@ -42,8 +42,8 @@ scope S: i1 >= i2 or x1 >= x2 or m1 >= m2 or d1 >= d2 or t1 >= t2 ) - assertion o_i = -i1 +! i2 -! i1 *! i2 /! (i1 +! i2) - assertion o_x = -.x1 +. x2 -. x1 *. x2 /. (x1 +. x2) + assertion o_i = -i1 +! i2 -! i1 *! i2 *! (i1 +! i2) + assertion o_x = -.x1 +. x2 -. x1 *. x2 /. (x1 +. x2) *. (i1 /! i2) assertion o_m = -$m1 +$ m2 -$ m1 *$ x2 / (m1 *$ x1 /$ m2) +$ m1 / x2 assertion o_d = -^d1 +^ d2 -^ d1 *^ i2 assertion o_t = t1 +@ d1 +@ (t2 -@ t1) +@ d1 @@ -61,8 +61,8 @@ $ catala Interpret -s S [RESULT] Computation successful! Results: [RESULT] o_b = true [RESULT] o_d = [0 years, 0 months, -13 days] -[RESULT] o_i = 1 +[RESULT] o_i = -5 [RESULT] o_m = $-5.75 [RESULT] o_t = 2022-01-24 -[RESULT] o_x = -0.71428571428571428571… +[RESULT] o_x = 0.14285714285714285714… ```