Skip to content

Commit 478d0be

Browse files
committed
Implement MISRA compliant merge sort
- MISRA compliant merge sort
1 parent c4f004b commit 478d0be

File tree

6 files changed

+220
-0
lines changed

6 files changed

+220
-0
lines changed

Inc/sort/merge_sort.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2025 IMProject Development Team. All rights reserved.
4+
* Authors: Juraj Ciberlin <[email protected]>
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in
14+
* the documentation and/or other materials provided with the
15+
* distribution.
16+
* 3. Neither the name IMProject nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
* POSSIBILITY OF SUCH DAMAGE.
32+
*
33+
****************************************************************************/
34+
35+
#ifndef UTILITY_MERGE_SORT_H_
36+
#define UTILITY_MERGE_SORT_H_
37+
38+
#include "typedefs.h"
39+
40+
#define MAX_HALVES_SIZE (64)
41+
42+
/**
43+
* @brief Sort elements using merge sort algorithm. Merge sort algorithm works on a principle that it
44+
* divides the list/array into two halves. Sort each one. Merge them back together. Repeat the whole
45+
* process until the entire array is sorted. This algorithm does not use recursion since it is not MISRA
46+
* compliant.
47+
* Time complexity: O(N log N)
48+
*
49+
* @param[in/out] *buffer Pointer to the buffer that contains elements that will be sorted.
50+
* @param[in] number_of_elements Number of elements in the buffer.
51+
* @param[in] element_size Size of the element, in bytes.
52+
* @param[in] *compareFun Pointer to compare function. Compare function has two parameters (pointer to
53+
* first element and pointer to second element). As a result, it returns boolean,
54+
* true if first element is greater than second element, otherwise false.
55+
*/
56+
void MergeSort_sort(byte_t* buffer, int32_t number_of_elements, int32_t element_size,
57+
bool (*compareFun)(void* first, void* second));
58+
59+
#endif /* UTILITY_MERGE_SORT_H_ */

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ IMUTILITY_FILES=\
111111
Src/sort/bubble_sort.c \
112112
Src/sort/heap_sort.c \
113113
Src/sort/insertion_sort.c \
114+
Src/sort/merge_sort.c \
114115
Src/sort/selection_sort.c \
115116
Src/json.c \
116117
Src/map.c \
@@ -136,6 +137,7 @@ SRC_FILES+=$(IMUTILITY_FILES) \
136137
Tests/test_insertion_sort.c \
137138
Tests/test_json.c \
138139
Tests/test_map.c \
140+
Tests/test_merge_sort.c \
139141
Tests/test_priority_queue.c \
140142
Tests/test_queue.c \
141143
Tests/test_scheduler.c \

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ Join us on the Discord channel https://discord.gg/R6nZxZqDH3
161161
- BubbleSort_sort
162162
- HeapSort_sort
163163
- InsertionSort_sort
164+
- MergeSort_sort
164165
- SelectionSort_sort
165166

166167
### Utils

Src/sort/merge_sort.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2025 IMProject Development Team. All rights reserved.
4+
* Authors: Juraj Ciberlin <[email protected]>
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in
14+
* the documentation and/or other materials provided with the
15+
* distribution.
16+
* 3. Neither the name IMProject nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
* POSSIBILITY OF SUCH DAMAGE.
32+
*
33+
****************************************************************************/
34+
35+
#include "merge_sort.h"
36+
37+
#include <string.h>
38+
39+
void
40+
MergeHalves(byte_t* buffer, int32_t element_size, int32_t left, int32_t mid, int32_t right,
41+
bool (*compareFun)(void* first, void* second)) {
42+
byte_t* elements = buffer;
43+
byte_t left_half[MAX_HALVES_SIZE];
44+
byte_t right_half[MAX_HALVES_SIZE];
45+
int32_t i;
46+
int32_t j;
47+
int32_t k;
48+
int32_t number_of_elements_1 = mid - left + 1;
49+
int32_t number_of_elements_2 = right - mid;
50+
51+
for (i = 0; i < number_of_elements_1; ++i) {
52+
memcpy(&left_half[i * element_size], &elements[(left + i) * element_size], (size_t)element_size);
53+
}
54+
55+
for (j = 0; j < number_of_elements_2; ++j) {
56+
memcpy(&right_half[j * element_size], &elements[(mid + 1 + j) * element_size], (size_t)element_size);
57+
}
58+
59+
i = 0;
60+
j = 0;
61+
k = left;
62+
63+
while ((i < number_of_elements_1) && (j < number_of_elements_2)) {
64+
bool compare = compareFun(&right_half[j * element_size], &left_half[i * element_size]);
65+
if (compare) {
66+
memcpy(&elements[k * element_size], &left_half[i * element_size], (size_t)element_size);
67+
++i;
68+
} else {
69+
memcpy(&elements[k * element_size], &right_half[j * element_size], (size_t)element_size);
70+
++j;
71+
}
72+
++k;
73+
}
74+
75+
while (i < number_of_elements_1) {
76+
memcpy(&elements[k * element_size], &left_half[i * element_size], (size_t)element_size);
77+
++i;
78+
++k;
79+
}
80+
81+
while (j < number_of_elements_2) {
82+
memcpy(&elements[k * element_size], &right_half[j * element_size], (size_t)element_size);
83+
++j;
84+
++k;
85+
}
86+
}
87+
88+
void
89+
MergeSort_sort(byte_t* buffer, int32_t number_of_elements, int32_t element_size,
90+
bool (*compareFun)(void* first, void* second)) {
91+
byte_t* elements = buffer;
92+
for (int32_t current_size = 1; current_size <= number_of_elements - 1; current_size *= 2) {
93+
for (int32_t left = 0; left < number_of_elements - 1; left += (2 * current_size)) {
94+
int32_t compare_first_1 = left + current_size - 1;
95+
int32_t compare_second = number_of_elements - 1;
96+
int32_t mid = (compare_first_1 < compare_second) ? compare_first_1 : compare_second;
97+
98+
int32_t compare_first_2 = left + (2 * current_size) - 1;
99+
int32_t right = (compare_first_2 < compare_second) ? compare_first_2 : compare_second;
100+
101+
MergeHalves(elements, element_size, left, mid, right, compareFun);
102+
}
103+
}
104+
}

Tests/test_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RunAllTests(void) {
1515
RUN_TEST_GROUP(InsertionSort);
1616
RUN_TEST_GROUP(Json);
1717
RUN_TEST_GROUP(Map);
18+
RUN_TEST_GROUP(MergeSort);
1819
RUN_TEST_GROUP(PriorityQueue);
1920
RUN_TEST_GROUP(Queue);
2021
RUN_TEST_GROUP(Scheduler);

Tests/test_merge_sort.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "merge_sort.h"
2+
3+
#include "unity.h"
4+
#include "unity_fixture.h"
5+
6+
#include "helper/sort_functions.h"
7+
8+
TEST_GROUP(MergeSort);
9+
10+
TEST_SETUP(MergeSort) {
11+
}
12+
13+
TEST_TEAR_DOWN(MergeSort) {
14+
}
15+
16+
TEST_GROUP_RUNNER(MergeSort) {
17+
RUN_TEST_CASE(MergeSort, MergeSort_int32);
18+
RUN_TEST_CASE(MergeSort, MergeSort_float64);
19+
RUN_TEST_CASE(MergeSort, MergeSort_uint64);
20+
}
21+
22+
TEST(MergeSort, MergeSort_int32) {
23+
int32_t unsorted_array[] = {5, 2, 3, 1000000, 9, 10, 11, 8, 9, 100};
24+
const int32_t sorted_array[] = {2, 3, 5, 8, 9, 9, 10, 11, 100, 1000000};
25+
MergeSort_sort((byte_t*)unsorted_array, sizeof(unsorted_array) / sizeof(unsorted_array[0]), sizeof(unsorted_array[0]),
26+
CompareInt32);
27+
28+
for (uint32_t i = 0U; i < (sizeof(unsorted_array) / sizeof(unsorted_array[0])); ++i) {
29+
TEST_ASSERT_EQUAL_INT32(sorted_array[i], unsorted_array[i]);
30+
}
31+
}
32+
33+
TEST(MergeSort, MergeSort_float64) {
34+
float64_t unsorted_array[] = {5.8, 2.2, 3.1, 1.1, 9.1, 10.3, 11.2, 8.4, 9.2, 100.9};
35+
const float64_t sorted_array[] = {1.1, 2.2, 3.1, 5.8, 8.4, 9.1, 9.2, 10.3, 11.2, 100.9};
36+
MergeSort_sort((byte_t*)unsorted_array, sizeof(unsorted_array) / sizeof(unsorted_array[0]), sizeof(unsorted_array[0]),
37+
CompareFloat64);
38+
39+
for (uint32_t i = 0U; i < (sizeof(unsorted_array) / sizeof(unsorted_array[0])); ++i) {
40+
TEST_ASSERT_EQUAL_DOUBLE(sorted_array[i], unsorted_array[i]);
41+
}
42+
}
43+
44+
TEST(MergeSort, MergeSort_uint64) {
45+
uint64_t unsorted_array[] = {1111111U, 55555555U, 44444U, 10000000000000U, 212121U, 1111U, 1U, 2U, 5U, 3U};
46+
const uint64_t sorted_array[] = {1U, 2U, 3U, 5U, 1111U, 44444U, 212121U, 1111111U, 55555555U, 10000000000000U};
47+
MergeSort_sort((byte_t*)unsorted_array, sizeof(unsorted_array) / sizeof(unsorted_array[0]), sizeof(unsorted_array[0]),
48+
CompareUint64);
49+
50+
for (uint32_t i = 0U; i < (sizeof(unsorted_array) / sizeof(unsorted_array[0])); ++i) {
51+
TEST_ASSERT_EQUAL_UINT64(sorted_array[i], unsorted_array[i]);
52+
}
53+
}

0 commit comments

Comments
 (0)