From e6e96e1a941b3e71a5f4209c3b4c4aab013cf05c Mon Sep 17 00:00:00 2001 From: Sean Talts Date: Mon, 18 Jan 2021 11:59:29 -0500 Subject: [PATCH 1/7] Update to use the new array[] syntax for signatures. --- test/sig_utils.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/sig_utils.py b/test/sig_utils.py index 74d6ccde3a3..f2f8a5474d7 100644 --- a/test/sig_utils.py +++ b/test/sig_utils.py @@ -12,15 +12,15 @@ arg_types = { "int": "int", - "int[]": "std::vector", - "int[,]": "std::vector>", + "array[] int": "std::vector", + "array[,] int": "std::vector>", "real": "SCALAR", - "real[]": "std::vector", - "real[,]": "std::vector>", + "array[] real": "std::vector", + "array[,] real": "std::vector>", "vector": "Eigen::Matrix", - "vector[]": "std::vector>", + "array[] vector": "std::vector>", "row_vector": "Eigen::Matrix", - "row_vector[]": "std::vector>", + "array[] row_vector": "std::vector>", "matrix": "Eigen::Matrix", "rng": "std::minstd_rand", "ostream_ptr": "std::ostream*", @@ -249,10 +249,13 @@ def parse_signature(signature): :param signature: stanc3 function signature :return: return type, fucntion name and list of function argument types """ - return_type, rest = signature.split(" ", 1) - function_name, rest = rest.split("(", 1) - args = re.findall(r"(?:[(][^()]+[)][^,()]+)|(?:[^,()]+(?:,*[]])?)", rest) - args = [i.strip() for i in args if i.strip()] + signature = signature[:-1] # Remove the close paren at the end. + rt_name, args = signature.split("(", ) # There's only one open paren and it occurs on the function name. + # The last word is the function name, the rest is the return type. + rt_name = rt_name.split() + return_type = " ".join(rt_name[:-1]) + function_name = rt_name[-1] + args = args.split(", ") return return_type, function_name, args From eadec615e7b251f5c17b1d9beca2c5b3ae5c749d Mon Sep 17 00:00:00 2001 From: Sean Talts Date: Mon, 18 Jan 2021 13:27:02 -0500 Subject: [PATCH 2/7] Change to use => notation --- test/sig_utils.py | 101 ++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/test/sig_utils.py b/test/sig_utils.py index f2f8a5474d7..b4ff2b7599b 100644 --- a/test/sig_utils.py +++ b/test/sig_utils.py @@ -149,51 +149,51 @@ def get_cpp_type(stan_type): ] internal_signatures = [ - "vector unit_vector_constrain(vector)", - "vector unit_vector_constrain(vector, real)", - "vector unit_vector_free(vector)", - "vector positive_ordered_constrain(vector)", - "vector positive_ordered_constrain(vector, real)", - "vector positive_ordered_free(vector)", - "vector ordered_constrain(vector)", - "vector ordered_constrain(vector, real)", - "vector ordered_free(vector)", - "vector simplex_constrain(vector)", - "vector simplex_constrain(vector, real)", - "vector simplex_free(vector)", - "int is_cholesky_factor(matrix)", - "int is_cholesky_factor_corr(matrix)", - "int is_column_index(matrix, int)", - "int is_column_index(vector, int)", - "int is_corr_matrix(matrix)", - "int is_cholesky_factor(matrix)", - "int is_lower_triangular(matrix)", - "int is_mat_finite(matrix)", - "int is_mat_finite(vector)", - "int is_matching_dims(matrix, matrix)", - "int is_matching_dims(vector, matrix)", - "int is_matching_dims(matrix, vector)", - "int is_matching_dims(row_vector, matrix)", - "int is_matching_dims(matrix, row_vector)", - "int is_matching_dims(matrix, matrix)", - "int is_matching_dims(row_vector, row_vector)", - "int is_matching_dims(vector, row_vector)", - "int is_matching_dims(row_vector, vector)", - "int is_matching_dims(vector, vector)", - "int is_pos_definite(matrix)", - "int is_square(matrix)", - "int is_square(vector)", - "int is_square(row_vector)", - "int is_symmetric(matrix)", - "int is_unit_vector(vector)", + "unit_vector_constrain(vector) => vector", + "unit_vector_constrain(vector, real) => vector", + "unit_vector_free(vector) => vector", + "positive_ordered_constrain(vector) => vector", + "positive_ordered_constrain(vector, real) => vector", + "positive_ordered_free(vector) => vector", + "ordered_constrain(vector) => vector", + "ordered_constrain(vector, real) => vector", + "ordered_free(vector) => vector", + "simplex_constrain(vector) => vector", + "simplex_constrain(vector, real) => vector", + "simplex_free(vector) => vector", + "is_cholesky_factor(matrix) => int", + "is_cholesky_factor_corr(matrix) => int", + "is_column_index(matrix, int) => int", + "is_column_index(vector, int) => int", + "is_corr_matrix(matrix) => int", + "is_cholesky_factor(matrix) => int", + "is_lower_triangular(matrix) => int", + "is_mat_finite(matrix) => int", + "is_mat_finite(vector) => int", + "is_matching_dims(matrix, matrix) => int", + "is_matching_dims(vector, matrix) => int", + "is_matching_dims(matrix, vector) => int", + "is_matching_dims(row_vector, matrix) => int", + "is_matching_dims(matrix, row_vector) => int", + "is_matching_dims(matrix, matrix) => int", + "is_matching_dims(row_vector, row_vector) => int", + "is_matching_dims(vector, row_vector) => int", + "is_matching_dims(row_vector, vector) => int", + "is_matching_dims(vector, vector) => int", + "is_pos_definite(matrix) => int", + "is_square(matrix) => int", + "is_square(vector) => int", + "is_square(row_vector) => int", + "is_symmetric(matrix) => int", + "is_unit_vector(vector) => int", # variadic functions: these are tested with one vector for variadic args - "real[,] ode_adams((real, vector, ostream_ptr, vector) => vector, vector, real, real[], ostream_ptr, vector)", - "real[,] ode_adams_tol((real, vector, ostream_ptr, vector) => vector, vector, real, real[], real, real, real, ostream_ptr, vector)", - "real[,] ode_bdf((real, vector, ostream_ptr, vector) => vector, vector, real, real[], ostream_ptr, vector)", - "real[,] ode_bdf_tol((real, vector, ostream_ptr, vector) => vector, vector, real, real[], real, real, real, ostream_ptr, vector)", - "real[,] ode_rk45((real, vector, ostream_ptr, vector) => vector, vector, real, real[], ostream_ptr, vector)", - "real[,] ode_rk45_tol((real, vector, ostream_ptr, vector) => vector, vector, real, real[], real, real, real, ostream_ptr, vector)", - "real reduce_sum(real[], int, vector)", + "ode_adams((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, ostream_ptr, vector) => array[,] real", + "ode_adams_tol((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, real, real, real, ostream_ptr, vector) => array[,] real", + "ode_bdf((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, ostream_ptr, vector) => array[,] real", + "ode_bdf_tol((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, real, real, real, ostream_ptr, vector) => array[,] real", + "ode_rk45((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, ostream_ptr, vector) => array[,] real", + "ode_rk45_tol((real, vector, ostream_ptr, vector) => vector, vector, real, array[] real, real, real, real, ostream_ptr, vector) => array[,] real", + "reduce_sum(array[] real, int, vector) => real", ] @@ -249,13 +249,10 @@ def parse_signature(signature): :param signature: stanc3 function signature :return: return type, fucntion name and list of function argument types """ - signature = signature[:-1] # Remove the close paren at the end. - rt_name, args = signature.split("(", ) # There's only one open paren and it occurs on the function name. - # The last word is the function name, the rest is the return type. - rt_name = rt_name.split() - return_type = " ".join(rt_name[:-1]) - function_name = rt_name[-1] - args = args.split(", ") + rest, return_type = signature.rsplit(" => ", 1) + function_name, rest = rest.split("(", 1) + args = re.findall(r"(?:[(][^()]+[)][^,()]+)|(?:[^,()]+(?:,*[]])?)", rest) + args = [i.strip() for i in args if i.strip()] return return_type, function_name, args @@ -286,6 +283,6 @@ def reference_vector_argument(arg): :param arg: argument :return: reference argument """ - if arg in ("real[]", "row_vector"): + if arg in ("array[] real", "row_vector"): return "vector" return arg From 1e80264a3ffc52d88e0cc4dd723590cadb4c0433 Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 27 Jan 2021 12:23:12 +0100 Subject: [PATCH 3/7] fixed expression tests and benchmarks --- benchmarks/benchmark.py | 6 +++--- test/sig_utils.py | 33 ++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/benchmarks/benchmark.py b/benchmarks/benchmark.py index 18bdf8cc84e..15fca0109c3 100755 --- a/benchmarks/benchmark.py +++ b/benchmarks/benchmark.py @@ -403,10 +403,10 @@ def benchmark( n, (arg_overload, cpp_arg_template, stan_arg), ) in enumerate(zip(arg_overloads, cpp_arg_templates, stan_args)): - if stan_arg.endswith("]"): - stan_arg2, vec = stan_arg.split("[") + n_vec, inner_type = parse_array(stan_arg) + if n_vec: benchmark_name += ( - "_" + arg_overload + "_" + stan_arg2 + str(len(vec)) + "_" + arg_overload + "_" + inner_type + str(n_vec) ) else: benchmark_name += "_" + arg_overload + "_" + stan_arg diff --git a/test/sig_utils.py b/test/sig_utils.py index b4ff2b7599b..7b907c003ca 100644 --- a/test/sig_utils.py +++ b/test/sig_utils.py @@ -28,12 +28,26 @@ scalar_stan_types = ("int", "real", "rng", "ostream_ptr") +def parse_array(stan_arg): + """ + parses stan array type + :param stan_arg: stan type, possibly an array + :return: number of nested arrays, inner type + """ + if stan_arg.startswith("array["): + print(stan_arg) + commas, inner_type = stan_arg.lstrip("array[").split("]") + return len(commas)+1, inner_type + return 0, stan_arg + def get_cpp_type(stan_type): - n_vec = 0 - if stan_type.endswith("]"): - stan_type, vec = stan_type.split("[") - n_vec = len(vec) - res = arg_types[stan_type] + """ + Determines cpp type that implements given stan type. + :param stan_type: stan type + :return: cpp type + """ + n_vec, inner_type = parse_array(stan_type) + res = arg_types[inner_type] for i in range(n_vec): res = "std::vector<{}>".format(res) return res @@ -208,7 +222,7 @@ def parse_signature_file(sig_file): for signature in sig_file: signature = part_sig + signature part_sig = "" - if not signature.endswith(")\n"): + if signature.endswith(",\n"): part_sig = signature continue res.append(signature) @@ -251,9 +265,10 @@ def parse_signature(signature): """ rest, return_type = signature.rsplit(" => ", 1) function_name, rest = rest.split("(", 1) - args = re.findall(r"(?:[(][^()]+[)][^,()]+)|(?:[^,()]+(?:,*[]])?)", rest) - args = [i.strip() for i in args if i.strip()] - return return_type, function_name, args + args = re.findall(r"(?:[(][^()]+[)][^,()]+)|(?:[^,()]+(?:,*[]][^,()]+)?)", rest) + # regex parts: ^^^^^^functor^^^^^^ ^^^^any other arg^^^^^^^ + args = [i.lstrip("data").strip() if "data" in i else i.strip() for i in args if i.strip()] + return return_type.strip(), function_name, args def handle_function_list(functions_input): From 6b5b36780d8dd97777d8cc18b3bdc56965fb054a Mon Sep 17 00:00:00 2001 From: Rok Cesnovar Date: Mon, 1 Feb 2021 09:06:05 +0100 Subject: [PATCH 4/7] add a static cast --- test/expressions/expression_test_helpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/expressions/expression_test_helpers.hpp b/test/expressions/expression_test_helpers.hpp index b46d37098ce..b3a2c74f995 100644 --- a/test/expressions/expression_test_helpers.hpp +++ b/test/expressions/expression_test_helpers.hpp @@ -187,7 +187,7 @@ struct test_functor { auto operator()(T... args) const { using Ret_scal = return_type_t; return stan::test::make_arg>( - math::sum(std::vector{sum_if_number(args)...})); + math::sum(std::vector{static_cast(sum_if_number(args)...}))); } }; From e3447d13cb72effa5e2201edb55d3901daa7b0a0 Mon Sep 17 00:00:00 2001 From: Rok Cesnovar Date: Mon, 1 Feb 2021 09:28:22 +0100 Subject: [PATCH 5/7] fix parenthesis --- test/expressions/expression_test_helpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/expressions/expression_test_helpers.hpp b/test/expressions/expression_test_helpers.hpp index b3a2c74f995..327d78881c6 100644 --- a/test/expressions/expression_test_helpers.hpp +++ b/test/expressions/expression_test_helpers.hpp @@ -187,7 +187,7 @@ struct test_functor { auto operator()(T... args) const { using Ret_scal = return_type_t; return stan::test::make_arg>( - math::sum(std::vector{static_cast(sum_if_number(args)...}))); + math::sum(std::vector{static_cast(sum_if_number(args))...})); } }; From 40e0eb6850687dac02273e25f2b0c4df0ed3aa6f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 1 Feb 2021 08:28:59 +0000 Subject: [PATCH 6/7] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- test/expressions/expression_test_helpers.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/expressions/expression_test_helpers.hpp b/test/expressions/expression_test_helpers.hpp index 327d78881c6..93284aebb57 100644 --- a/test/expressions/expression_test_helpers.hpp +++ b/test/expressions/expression_test_helpers.hpp @@ -187,7 +187,8 @@ struct test_functor { auto operator()(T... args) const { using Ret_scal = return_type_t; return stan::test::make_arg>( - math::sum(std::vector{static_cast(sum_if_number(args))...})); + math::sum(std::vector{ + static_cast(sum_if_number(args))...})); } }; From 8a84b9566f4bf50daa01aa6a0f37bb02fdfb493f Mon Sep 17 00:00:00 2001 From: tadej Date: Mon, 1 Feb 2021 09:59:08 +0100 Subject: [PATCH 7/7] fixed tests for expression testing framework --- test/expressions/test_expression_testing_framework.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/expressions/test_expression_testing_framework.py b/test/expressions/test_expression_testing_framework.py index 5b3da1cf085..487ee8b9bfa 100644 --- a/test/expressions/test_expression_testing_framework.py +++ b/test/expressions/test_expression_testing_framework.py @@ -24,25 +24,25 @@ def assertStdoutContains(self, content, stdout, stderr): self.assertTrue(content in stdout, msg = error_template.format(content, stdout, stderr)) def testExpressionNotAcceptedFailure(self): - return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--make-only", "--only-functions", "matrix bad_no_expressions(matrix)")) + return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--make-only", "--only-functions", "bad_no_expressions(matrix) => real")) self.assertNotEqual(return_code, 0) def testMultipleEvaluationsFailure(self): - return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "matrix bad_multiple_evaluations(matrix)")) + return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "bad_multiple_evaluations(matrix) => matrix")) self.assertNotEqual(return_code, 0) self.assertStdoutContains("[ FAILED ] ExpressionTestPrim.bad_multiple_evaluations0", stdout, stderr) self.assertStdoutContains("[ FAILED ] ExpressionTestRev.bad_multiple_evaluations0", stdout, stderr) self.assertStdoutContains("[ FAILED ] ExpressionTestFwd.bad_multiple_evaluations0", stdout, stderr) def testWrongResultFailure(self): - return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "real bad_wrong_value(matrix)")) + return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "bad_wrong_value(matrix) => real")) self.assertNotEqual(return_code, 0) self.assertStdoutContains("[ FAILED ] ExpressionTestPrim.bad_wrong_value0", stdout, stderr) self.assertStdoutContains("[ FAILED ] ExpressionTestRev.bad_wrong_value0", stdout, stderr) self.assertStdoutContains("[ FAILED ] ExpressionTestFwd.bad_wrong_value0", stdout, stderr) def testWrongDerivativeFailure(self): - return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "real bad_wrong_derivatives(vector)")) + return_code, stdout, stderr = self.runCommand((sys.executable, "./runTests.py", "./test/expressions", "-e1", "--only-functions", "bad_wrong_derivatives(vector) => real")) self.assertNotEqual(return_code, 0) self.assertStdoutContains("[ OK ] ExpressionTestPrim.bad_wrong_derivatives0", stdout, stderr) self.assertStdoutContains("[ FAILED ] ExpressionTestRev.bad_wrong_derivatives0", stdout, stderr)