Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/circle-resizer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
add_subdirectory(src)
add_subdirectory(app)
add_subdirectory(tests)
60 changes: 60 additions & 0 deletions compiler/circle-resizer/include/Dim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __CIRCLE_RESIZER_DIM_H__
#define __CIRCLE_RESIZER_DIM_H__

#include <stdint.h>

namespace circle_resizer
{
/**
* The representation of a single dimension. Note that a dimension can be dynamic.
*/
class Dim
{
public:
/**
* @brief Initialize a single dimension. Note that '-1' means a dynamic dimension.
*
* Exceptions:
* - std::runtime_error if provided dim value is less than -1.
*/
explicit Dim(int32_t dim);

public:
/**
* @brief Return true if the dimension is dynamic. Otherwise, return false.
*/
bool is_dynamic() const;

/**
* @brief Return value of dimension in int32_t representation.
*/
int32_t value() const;

/**
* @brief Return true of the current dimension and the provided rhs are equal.
*/
bool operator==(const Dim &rhs) const;

private:
// Note that in the future, we might need to support dimension with lower and upper bounds
int32_t _dim_value;
};
} // namespace circle_resizer

#endif // __CIRCLE_RESIZER_DIM_H__
51 changes: 51 additions & 0 deletions compiler/circle-resizer/include/Shape.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __CIRCLE_RESIZER_SHAPE_H__
#define __CIRCLE_RESIZER_SHAPE_H__

#include "Dim.h"

#include <ostream>
#include <vector>

namespace circle_resizer
{
/**
* The representation of a single shape.
*/
class Shape
{
public:
Shape(const std::initializer_list<Dim> &dims);
Shape(const std::vector<Dim> &shape_vec);
static Shape scalar();

public:
size_t rank() const;
Dim operator[](const size_t &axis) const;
bool is_scalar() const;
bool is_dynamic() const;
bool operator==(const Shape &rhs) const;
friend std::ostream &operator<<(std::ostream &os, const Shape &shape);

private:
std::vector<Dim> _dims;
};

} // namespace circle_resizer

#endif // __CIRCLE_RESIZER_SHAPE_H__
40 changes: 40 additions & 0 deletions compiler/circle-resizer/include/ShapeParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __CIRCLE_RESIZER_SHAPE_PARSER_H__
#define __CIRCLE_RESIZER_SHAPE_PARSER_H__

#include "Shape.h"

#include <string>
#include <vector>
Comment thread
jinevening marked this conversation as resolved.

namespace circle_resizer
{
/**
Comment thread
jinevening marked this conversation as resolved.
* @brief Parse shapes from string representation to Shapes object.
*
* The single shape is represented by comma-separated integers inside squared brackets.
* If there is more than one shape, they are separated by commas.
* An example for single shape: [1,2,3], an example for many shapes: [1,2,3],[4,5].
*
* Exceptions:
* std::invalid_argument is the parsing failed.
*/
std::vector<Shape> parse_shapes(const std::string &shapes);
Comment thread
jinevening marked this conversation as resolved.
} // namespace circle_resizer

#endif // __CIRCLE_RESIZER_SHAPE_PARSER_H__
9 changes: 9 additions & 0 deletions compiler/circle-resizer/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
list(APPEND CIRCLE_RESIZER_CORE_SOURCES Dim.cpp)
list(APPEND CIRCLE_RESIZER_CORE_SOURCES Shape.cpp)
list(APPEND CIRCLE_RESIZER_CORE_SOURCES ShapeParser.cpp)

add_library(circle_resizer_core STATIC "${CIRCLE_RESIZER_CORE_SOURCES}")

target_include_directories(circle_resizer_core PUBLIC ../include)

install(TARGETS circle_resizer_core DESTINATION lib)
35 changes: 35 additions & 0 deletions compiler/circle-resizer/src/Dim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Dim.h"

#include <stdexcept>

using namespace circle_resizer;

Dim::Dim(int32_t dim) : _dim_value{dim}
{
if (dim < -1)
{
throw std::runtime_error("Invalid value of dimension: " + dim);
}
}

bool Dim::is_dynamic() const { return _dim_value == -1; }

int32_t Dim::value() const { return _dim_value; }

bool Dim::operator==(const Dim &rhs) const { return value() == rhs.value(); }
75 changes: 75 additions & 0 deletions compiler/circle-resizer/src/Shape.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Shape.h"

#include <algorithm>

using namespace circle_resizer;

Shape::Shape(const std::initializer_list<Dim> &dims) : _dims{dims} {}

Shape::Shape(const std::vector<Dim> &shape_vec) : _dims{shape_vec} {}

Shape Shape::scalar() { return Shape{std::initializer_list<Dim>{}}; }

size_t Shape::rank() const { return _dims.size(); }

Dim Shape::operator[](const size_t &axis) const { return _dims[axis]; }

bool Shape::is_scalar() const { return _dims.empty(); }

bool Shape::is_dynamic() const
{
if (is_scalar())
{
return false;
}
return std::any_of(std::begin(_dims), std::end(_dims),
[](const Dim &dim) { return dim.is_dynamic(); });
}

bool Shape::operator==(const Shape &rhs) const
{
if (rank() != rhs.rank())
{
return false;
}
for (size_t axis = 0; axis < rank(); ++axis)
{
if (_dims[axis].value() != rhs[axis].value())
{
return false;
}
}
return true;
}

std::ostream &circle_resizer::operator<<(std::ostream &os, const Shape &shape)
{
if (shape.is_scalar())
{
os << "[]";
return os;
}
os << "[";
for (int i = 0; i < shape.rank() - 1; ++i)
{
os << shape[i].value() << ", ";
}
os << shape[shape.rank() - 1].value() << "]";
return os;
}
90 changes: 90 additions & 0 deletions compiler/circle-resizer/src/ShapeParser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "ShapeParser.h"
#include <Dim.h>

#include <algorithm>
#include <stdexcept>
#include <sstream>

using namespace circle_resizer;

namespace
{
bool is_blank(const std::string &s)
Comment thread
jinevening marked this conversation as resolved.
{
return !s.empty() && std::find_if(s.begin(), s.end(),
[](unsigned char c) { return !std::isblank(c); }) == s.end();
}

Shape parse_single_shape(const std::string &shape)
{
if (shape.empty() || is_blank(shape))
{
return Shape::scalar();
}

std::vector<Dim> result_dims;
std::stringstream shape_stream(shape);
std::string token;
try
{
while (std::getline(shape_stream, token, ','))
{
result_dims.push_back(Dim{std::stoi(token)});
}
}
catch (...)
{
throw std::invalid_argument("Error during shape processing: " + shape);
}
if (result_dims.empty())
{
throw std::invalid_argument("No shapes found in input string: " + shape);
}
return Shape{result_dims};
}
} // namespace
Comment thread
jinevening marked this conversation as resolved.

std::vector<Shape> circle_resizer::parse_shapes(const std::string &shapes)
{
std::vector<Shape> result_shapes;
auto shapes_tmp = shapes;
std::string token;
size_t begin_pos = 0, end_pos = 0;
while ((begin_pos = shapes_tmp.find_first_of("[")) != std::string::npos &&
(end_pos = shapes_tmp.find_first_of("]")) != std::string::npos)
{
const size_t token_size = end_pos - begin_pos - 1;
Comment thread
jinevening marked this conversation as resolved.
token = shapes_tmp.substr(begin_pos + 1, token_size);
result_shapes.push_back(parse_single_shape(token));
shapes_tmp.erase(0, end_pos + 1);
}

if (result_shapes.empty())
{
throw std::invalid_argument("No shapes found in the input string: " + shapes);
}

// the rest of the input not handled by loop above cannot be processed properly
if (shapes_tmp.size() > 0 && !is_blank(shapes_tmp))
{
throw std::invalid_argument("The part of input shapes: " + shapes_tmp + " cannot be processed");
}

return result_shapes;
}
9 changes: 9 additions & 0 deletions compiler/circle-resizer/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)

list(APPEND CIRCLE_RESIZER_TEST_SOURCES ShapeParser.test.cpp)

nnas_find_package(GTest REQUIRED)
GTest_AddTest(circle_resizer_unit_test ${CIRCLE_RESIZER_TEST_SOURCES})
target_link_libraries(circle_resizer_unit_test circle_resizer_core)
Loading