Unverified Commit 9852aaef authored by bpickrel's avatar bpickrel Committed by GitHub
Browse files

Clang format ver10 (#1106)

Update the base version of clang-format from 5.0 to 10.0
parent af0148ce
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# are installed, and if so, uses the installed version to format # are installed, and if so, uses the installed version to format
# the staged changes. # the staged changes.
base=clang-format-5.0 base=clang-format-10
format="" format=""
yapf_base=yapf yapf_base=yapf
yapf_format="" yapf_format=""
......
...@@ -133,7 +133,7 @@ jobs: ...@@ -133,7 +133,7 @@ jobs:
-o -iname '*.cpp.in' \ -o -iname '*.cpp.in' \
-o -iname '*.cl' \ -o -iname '*.cl' \
| grep -v 'build/' \ | grep -v 'build/' \
| xargs -n 1 -P 1 -I{} -t sh -c 'clang-format-5.0 -style=file {} | diff - {}' | xargs -n 1 -P 1 -I{} -t sh -c 'clang-format-10 -style=file {} | diff - {}'
find . -iname '*.py' \ find . -iname '*.py' \
| grep -v 'build/' \ | grep -v 'build/' \
| xargs -n 1 -P 1 -I{} -t sh -c 'yapf {} | diff - {}' | xargs -n 1 -P 1 -I{} -t sh -c 'yapf {} | diff - {}'
......
...@@ -12,7 +12,7 @@ RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/4.5 ...@@ -12,7 +12,7 @@ RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/4.5
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \
apt-utils \ apt-utils \
build-essential \ build-essential \
clang-format-5.0 \ clang-format-10 \
cmake \ cmake \
curl \ curl \
doxygen \ doxygen \
......
...@@ -205,7 +205,7 @@ Depending on your setup `sudo` may be required for the pip install. ...@@ -205,7 +205,7 @@ Depending on your setup `sudo` may be required for the pip install.
All the code is formatted using clang-format. To format a file, use: All the code is formatted using clang-format. To format a file, use:
``` ```
clang-format-5.0 -style=file -i <path-to-source-file> clang-format-10 -style=file -i <path-to-source-file>
``` ```
Also, githooks can be installed to format the code per-commit: Also, githooks can be installed to format the code per-commit:
......
...@@ -12,7 +12,7 @@ RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/4.5 ...@@ -12,7 +12,7 @@ RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/4.5
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \
apt-utils \ apt-utils \
build-essential \ build-essential \
clang-format-5.0 \ clang-format-10 \
cmake \ cmake \
curl \ curl \
doxygen \ doxygen \
......
...@@ -25,7 +25,8 @@ extern "C" { ...@@ -25,7 +25,8 @@ extern "C" {
#endif #endif
// return code, more to be added later // return code, more to be added later
typedef enum { typedef enum
{
migraphx_status_success = 0, migraphx_status_success = 0,
migraphx_status_bad_param = 1, migraphx_status_bad_param = 1,
migraphx_status_unknown_target = 3, migraphx_status_unknown_target = 3,
...@@ -35,7 +36,8 @@ typedef enum { ...@@ -35,7 +36,8 @@ typedef enum {
#define MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES(x, t) migraphx_shape_##x, #define MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES(x, t) migraphx_shape_##x,
/// An enum to represent the different data type inputs /// An enum to represent the different data type inputs
typedef enum { typedef enum
{
migraphx_shape_tuple_type, migraphx_shape_tuple_type,
MIGRAPHX_SHAPE_VISIT_TYPES(MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES) MIGRAPHX_SHAPE_VISIT_TYPES(MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES)
} migraphx_shape_datatype_t; } migraphx_shape_datatype_t;
......
...@@ -101,17 +101,17 @@ template <class M> ...@@ -101,17 +101,17 @@ template <class M>
auto bind_match(M m, std::string name) auto bind_match(M m, std::string name)
{ {
return make_function_matcher( return make_function_matcher(
[ =, name = std::move(name) ](matcher_context & ctx, instruction_ref ins) [=, name = std::move(name)](matcher_context& ctx,
->optional<instruction_ref> { instruction_ref ins) -> optional<instruction_ref> {
auto result = m.match(ctx, ins); auto result = m.match(ctx, ins);
if(result) if(result)
{ {
if(not ctx.has_instruction(ins)) if(not ctx.has_instruction(ins))
return nullopt; return nullopt;
ctx.instructions[name] = ins; ctx.instructions[name] = ins;
} }
return result; return result;
}); });
} }
/// Convert a matcher to a bindable matcher /// Convert a matcher to a bindable matcher
...@@ -536,7 +536,7 @@ auto skip_output(Ms... ms) ...@@ -536,7 +536,7 @@ auto skip_output(Ms... ms)
inline auto name(std::string s) inline auto name(std::string s)
{ {
return make_basic_pred_matcher( return make_basic_pred_matcher(
[ =, s = std::move(s) ](instruction_ref ins) { return ins->name() == s; }); [=, s = std::move(s)](instruction_ref ins) { return ins->name() == s; });
} }
inline auto name_contains(const std::string& name) inline auto name_contains(const std::string& name)
...@@ -547,7 +547,7 @@ inline auto name_contains(const std::string& name) ...@@ -547,7 +547,7 @@ inline auto name_contains(const std::string& name)
inline auto name(std::unordered_set<std::string> names) inline auto name(std::unordered_set<std::string> names)
{ {
return make_basic_pred_matcher([ =, names = std::move(names) ](instruction_ref ins) { return make_basic_pred_matcher([=, names = std::move(names)](instruction_ref ins) {
return names.count(ins->name()) > 0; return names.count(ins->name()) > 0;
}); });
} }
......
...@@ -97,7 +97,6 @@ struct deconvolution ...@@ -97,7 +97,6 @@ struct deconvolution
shape win_shape{output_shape.type(), win_size}; shape win_shape{output_shape.type(), win_size};
par_dfor(in_n, wei_c)([&](int o, int k) { par_dfor(in_n, wei_c)([&](int o, int k) {
shape_for_each(win_shape, [&](auto idx_win) { shape_for_each(win_shape, [&](auto idx_win) {
const int w = idx_win[0]; const int w = idx_win[0];
...@@ -140,9 +139,7 @@ struct deconvolution ...@@ -140,9 +139,7 @@ struct deconvolution
weights(idx_wei.begin(), idx_wei.end()); weights(idx_wei.begin(), idx_wei.end());
} }
}); });
}); });
}); });
return result; return result;
} }
......
...@@ -181,14 +181,15 @@ struct nonmaxsuppression ...@@ -181,14 +181,15 @@ struct nonmaxsuppression
make_function_output_iterator([&](const auto& x) { sorted_boxes.push(x); }); make_function_output_iterator([&](const auto& x) { sorted_boxes.push(x); });
int64_t box_idx = 0; int64_t box_idx = 0;
transform_if(scores.begin() + score_offset, transform_if(
scores.begin() + score_offset + box_num, scores.begin() + score_offset,
insert_to_sorted_boxes, scores.begin() + score_offset + box_num,
[&](auto sc) { insert_to_sorted_boxes,
box_idx++; [&](auto sc) {
return sc >= score_threshold; box_idx++;
}, return sc >= score_threshold;
[&](auto sc) { return std::make_pair(sc, box_idx - 1); }); },
[&](auto sc) { return std::make_pair(sc, box_idx - 1); });
selected_boxes_inside_class.clear(); selected_boxes_inside_class.clear();
// Get the next box with top score, filter by iou_threshold // Get the next box with top score, filter by iou_threshold
......
...@@ -253,7 +253,6 @@ struct roialign ...@@ -253,7 +253,6 @@ struct roialign
max_pool{}); max_pool{});
output(n, c, ph, pw) = output_val; output(n, c, ph, pw) = output_val;
}); });
}); });
}); });
......
...@@ -64,7 +64,6 @@ struct unary : op_name<Derived> ...@@ -64,7 +64,6 @@ struct unary : op_name<Derived>
input.end(), input.end(),
output.begin(), output.begin(),
static_cast<const Derived&>(*this).apply()); static_cast<const Derived&>(*this).apply());
}); });
}); });
return result; return result;
......
...@@ -41,7 +41,6 @@ auto par_dfor(Ts... xs) ...@@ -41,7 +41,6 @@ auto par_dfor(Ts... xs)
{ {
dfor(xs...)(f); dfor(xs...)(f);
} }
}; };
} }
......
...@@ -35,7 +35,7 @@ struct shape ...@@ -35,7 +35,7 @@ struct shape
m(int64_type, int64_t) \ m(int64_type, int64_t) \
m(uint32_type, uint32_t) \ m(uint32_type, uint32_t) \
m(uint64_type, uint64_t) m(uint64_type, uint64_t)
// clang-format on // clang-format on
#define MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES(x, t) x, #define MIGRAPHX_SHAPE_GENERATE_ENUM_TYPES(x, t) x,
enum type_t enum type_t
...@@ -188,8 +188,7 @@ struct shape ...@@ -188,8 +188,7 @@ struct shape
{ {
switch(t) switch(t)
{ {
case tuple_type: case tuple_type: {
{
tv(); tv();
return; return;
} }
......
...@@ -131,16 +131,17 @@ inline std::string interpolate_string(const std::string& input, ...@@ -131,16 +131,17 @@ inline std::string interpolate_string(const std::string& input,
std::string start = "${", std::string start = "${",
std::string end = "}") std::string end = "}")
{ {
return interpolate_string(input, return interpolate_string(
[&](auto start_it, auto last_it) { input,
auto key = trim({start_it, last_it}); [&](auto start_it, auto last_it) {
auto it = vars.find(key); auto key = trim({start_it, last_it});
if(it == vars.end()) auto it = vars.find(key);
throw std::runtime_error("Unknown key: " + key); if(it == vars.end())
return it->second; throw std::runtime_error("Unknown key: " + key);
}, return it->second;
std::move(start), },
std::move(end)); std::move(start),
std::move(end));
} }
template <class Iterator> template <class Iterator>
......
...@@ -315,8 +315,7 @@ struct value ...@@ -315,8 +315,7 @@ struct value
{ {
switch(this->get_type()) switch(this->get_type())
{ {
case null_type: case null_type: {
{
std::nullptr_t null{}; std::nullptr_t null{};
if(this->key.empty()) if(this->key.empty())
v(null); v(null);
...@@ -325,8 +324,7 @@ struct value ...@@ -325,8 +324,7 @@ struct value
return; return;
} }
#define MIGRAPHX_VALUE_GENERATE_CASE(vt, cpp_type) \ #define MIGRAPHX_VALUE_GENERATE_CASE(vt, cpp_type) \
case vt##_type: \ case vt##_type: { \
{ \
if(this->key.empty()) \ if(this->key.empty()) \
v(this->get_##vt()); \ v(this->get_##vt()); \
else \ else \
...@@ -346,15 +344,13 @@ struct value ...@@ -346,15 +344,13 @@ struct value
{ {
switch(this->get_type()) switch(this->get_type())
{ {
case null_type: case null_type: {
{
std::nullptr_t null{}; std::nullptr_t null{};
v(null); v(null);
return; return;
} }
#define MIGRAPHX_VALUE_GENERATE_CASE_VALUE(vt, cpp_type) \ #define MIGRAPHX_VALUE_GENERATE_CASE_VALUE(vt, cpp_type) \
case vt##_type: \ case vt##_type: { \
{ \
v(this->get_##vt()); \ v(this->get_##vt()); \
return; \ return; \
} }
......
...@@ -14,44 +14,36 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) ...@@ -14,44 +14,36 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
{ {
switch(o.type) switch(o.type)
{ {
case msgpack::type::NIL: case msgpack::type::NIL: {
{
v = nullptr; v = nullptr;
break; break;
} }
case msgpack::type::BOOLEAN: case msgpack::type::BOOLEAN: {
{
v = o.as<bool>(); v = o.as<bool>();
break; break;
} }
case msgpack::type::POSITIVE_INTEGER: case msgpack::type::POSITIVE_INTEGER: {
{
v = o.as<std::uint64_t>(); v = o.as<std::uint64_t>();
break; break;
} }
case msgpack::type::NEGATIVE_INTEGER: case msgpack::type::NEGATIVE_INTEGER: {
{
v = o.as<std::int64_t>(); v = o.as<std::int64_t>();
break; break;
} }
case msgpack::type::FLOAT32: case msgpack::type::FLOAT32:
case msgpack::type::FLOAT64: case msgpack::type::FLOAT64: {
{
v = o.as<double>(); v = o.as<double>();
break; break;
} }
case msgpack::type::STR: case msgpack::type::STR: {
{
v = o.as<std::string>(); v = o.as<std::string>();
break; break;
} }
case msgpack::type::BIN: case msgpack::type::BIN: {
{
v = migraphx::value::binary{o.via.bin.ptr, o.via.bin.size}; v = migraphx::value::binary{o.via.bin.ptr, o.via.bin.size};
break; break;
} }
case msgpack::type::ARRAY: case msgpack::type::ARRAY: {
{
migraphx::value r = migraphx::value::array{}; migraphx::value r = migraphx::value::array{};
std::for_each( std::for_each(
o.via.array.ptr, o.via.array.ptr,
...@@ -60,8 +52,7 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) ...@@ -60,8 +52,7 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
v = r; v = r;
break; break;
} }
case msgpack::type::MAP: case msgpack::type::MAP: {
{
migraphx::value r = migraphx::value::object{}; migraphx::value r = migraphx::value::object{};
std::for_each(o.via.map.ptr, std::for_each(o.via.map.ptr,
o.via.map.ptr + o.via.map.size, o.via.map.ptr + o.via.map.size,
...@@ -71,7 +62,8 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) ...@@ -71,7 +62,8 @@ MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
v = r; v = r;
break; break;
} }
case msgpack::type::EXT: { MIGRAPHX_THROW("msgpack EXT type not supported."); case msgpack::type::EXT: {
MIGRAPHX_THROW("msgpack EXT type not supported.");
} }
} }
return o; return o;
......
...@@ -382,8 +382,7 @@ literal onnx_parser::parse_tensor(const onnx::TensorProto& t) const ...@@ -382,8 +382,7 @@ literal onnx_parser::parse_tensor(const onnx::TensorProto& t) const
case onnx::TensorProto::INT64: return create_literal(shape::int64_type, dims, t.int64_data()); case onnx::TensorProto::INT64: return create_literal(shape::int64_type, dims, t.int64_data());
case onnx::TensorProto::UINT64: case onnx::TensorProto::UINT64:
return create_literal(shape::uint64_type, dims, t.uint64_data()); return create_literal(shape::uint64_type, dims, t.uint64_data());
case onnx::TensorProto::FLOAT16: case onnx::TensorProto::FLOAT16: {
{
std::vector<uint16_t> data_uint16(t.int32_data().begin(), t.int32_data().end()); std::vector<uint16_t> data_uint16(t.int32_data().begin(), t.int32_data().end());
std::vector<half> data_half; std::vector<half> data_half;
std::transform(data_uint16.begin(), std::transform(data_uint16.begin(),
...@@ -453,7 +452,8 @@ shape::type_t get_type(int dtype) ...@@ -453,7 +452,8 @@ shape::type_t get_type(int dtype)
case 11: return shape::double_type; case 11: return shape::double_type;
case 12: return shape::uint32_type; case 12: return shape::uint32_type;
case 13: return shape::uint64_type; case 13: return shape::uint64_type;
default: { MIGRAPHX_THROW("Prototensor data type " + std::to_string(dtype) + " not supported"); default: {
MIGRAPHX_THROW("Prototensor data type " + std::to_string(dtype) + " not supported");
} }
} }
} }
......
...@@ -809,11 +809,12 @@ void generic_get_unused_modules(Map& m, const std::vector<T*>& mods, OutputItera ...@@ -809,11 +809,12 @@ void generic_get_unused_modules(Map& m, const std::vector<T*>& mods, OutputItera
std::transform(mods.begin(), mods.end(), std::inserter(used, used.end()), [](auto&& mod) { std::transform(mods.begin(), mods.end(), std::inserter(used, used.end()), [](auto&& mod) {
return mod->name(); return mod->name();
}); });
transform_if(m.begin(), transform_if(
m.end(), m.begin(),
out, m.end(),
[&](auto&& pp) { return not contains(used, pp.first); }, out,
[](auto&& pp) { return &pp.second; }); [&](auto&& pp) { return not contains(used, pp.first); },
[](auto&& pp) { return &pp.second; });
} }
std::vector<const module*> program::get_modules() const std::vector<const module*> program::get_modules() const
......
...@@ -303,86 +303,90 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m) ...@@ -303,86 +303,90 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m)
.def("name", &migraphx::operation::name); .def("name", &migraphx::operation::name);
m.def("parse_tf", m.def(
[](const std::string& filename, "parse_tf",
bool is_nhwc, [](const std::string& filename,
unsigned int batch_size, bool is_nhwc,
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims, unsigned int batch_size,
std::vector<std::string> output_names) { std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
return migraphx::parse_tf( std::vector<std::string> output_names) {
filename, return migraphx::parse_tf(
migraphx::tf_options{is_nhwc, batch_size, map_input_dims, output_names}); filename, migraphx::tf_options{is_nhwc, batch_size, map_input_dims, output_names});
}, },
"Parse tf protobuf (default format is nhwc)", "Parse tf protobuf (default format is nhwc)",
py::arg("filename"), py::arg("filename"),
py::arg("is_nhwc") = true, py::arg("is_nhwc") = true,
py::arg("batch_size") = 1, py::arg("batch_size") = 1,
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(), py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("output_names") = std::vector<std::string>()); py::arg("output_names") = std::vector<std::string>());
m.def("parse_onnx", m.def(
[](const std::string& filename, "parse_onnx",
unsigned int default_dim_value, [](const std::string& filename,
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims, unsigned int default_dim_value,
bool skip_unknown_operators, std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
bool print_program_on_error, bool skip_unknown_operators,
int64_t max_loop_iterations) { bool print_program_on_error,
migraphx::onnx_options options; int64_t max_loop_iterations) {
options.default_dim_value = default_dim_value; migraphx::onnx_options options;
options.map_input_dims = map_input_dims; options.default_dim_value = default_dim_value;
options.skip_unknown_operators = skip_unknown_operators; options.map_input_dims = map_input_dims;
options.print_program_on_error = print_program_on_error; options.skip_unknown_operators = skip_unknown_operators;
options.max_loop_iterations = max_loop_iterations; options.print_program_on_error = print_program_on_error;
return migraphx::parse_onnx(filename, options); options.max_loop_iterations = max_loop_iterations;
}, return migraphx::parse_onnx(filename, options);
"Parse onnx file", },
py::arg("filename"), "Parse onnx file",
py::arg("default_dim_value") = 1, py::arg("filename"),
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(), py::arg("default_dim_value") = 1,
py::arg("skip_unknown_operators") = false, py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("print_program_on_error") = false, py::arg("skip_unknown_operators") = false,
py::arg("max_loop_iterations") = 10); py::arg("print_program_on_error") = false,
py::arg("max_loop_iterations") = 10);
m.def("parse_onnx_buffer",
[](const std::string& onnx_buffer, m.def(
unsigned int default_dim_value, "parse_onnx_buffer",
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims, [](const std::string& onnx_buffer,
bool skip_unknown_operators, unsigned int default_dim_value,
bool print_program_on_error) { std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
migraphx::onnx_options options; bool skip_unknown_operators,
options.default_dim_value = default_dim_value; bool print_program_on_error) {
options.map_input_dims = map_input_dims; migraphx::onnx_options options;
options.skip_unknown_operators = skip_unknown_operators; options.default_dim_value = default_dim_value;
options.print_program_on_error = print_program_on_error; options.map_input_dims = map_input_dims;
return migraphx::parse_onnx_buffer(onnx_buffer, options); options.skip_unknown_operators = skip_unknown_operators;
}, options.print_program_on_error = print_program_on_error;
"Parse onnx file", return migraphx::parse_onnx_buffer(onnx_buffer, options);
py::arg("filename"), },
py::arg("default_dim_value") = 1, "Parse onnx file",
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(), py::arg("filename"),
py::arg("skip_unknown_operators") = false, py::arg("default_dim_value") = 1,
py::arg("print_program_on_error") = false); py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("skip_unknown_operators") = false,
m.def("load", py::arg("print_program_on_error") = false);
[](const std::string& name, const std::string& format) {
migraphx::file_options options; m.def(
options.format = format; "load",
return migraphx::load(name, options); [](const std::string& name, const std::string& format) {
}, migraphx::file_options options;
"Load MIGraphX program", options.format = format;
py::arg("filename"), return migraphx::load(name, options);
py::arg("format") = "msgpack"); },
"Load MIGraphX program",
m.def("save", py::arg("filename"),
[](const migraphx::program& p, const std::string& name, const std::string& format) { py::arg("format") = "msgpack");
migraphx::file_options options;
options.format = format; m.def(
return migraphx::save(p, name, options); "save",
}, [](const migraphx::program& p, const std::string& name, const std::string& format) {
"Save MIGraphX program", migraphx::file_options options;
py::arg("p"), options.format = format;
py::arg("filename"), return migraphx::save(p, name, options);
py::arg("format") = "msgpack"); },
"Save MIGraphX program",
py::arg("p"),
py::arg("filename"),
py::arg("format") = "msgpack");
m.def("get_target", &migraphx::make_target); m.def("get_target", &migraphx::make_target);
m.def("generate_argument", &migraphx::generate_argument, py::arg("s"), py::arg("seed") = 0); m.def("generate_argument", &migraphx::generate_argument, py::arg("s"), py::arg("seed") = 0);
......
...@@ -39,9 +39,7 @@ bool reduce_dim(std::vector<shape>& shapes, std::size_t n) ...@@ -39,9 +39,7 @@ bool reduce_dim(std::vector<shape>& shapes, std::size_t n)
std::size_t reduce_dim_all(std::vector<shape>& shapes, std::size_t n) std::size_t reduce_dim_all(std::vector<shape>& shapes, std::size_t n)
{ {
while(reduce_dim(shapes, n) and n < shapes.size()) while(reduce_dim(shapes, n) and n < shapes.size()) {}
{
}
return n + 1; return n + 1;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment