CC := cc
-CFLAGS := -Wall -Wextra -Werror -Wpedantic -std=c99
+CFLAGS := -std=c99 -Wall -Wextra -Werror -Wpedantic
AR := ar
RM := rm -f
SRCarr := ft_vec_init.c \
ft_vec_reserve.c \
+ ft_vec_enlarge.c \
ft_vec_insert.c \
ft_vec_append.c \
+ ft_vec_forget.c \
ft_vec_erase.c \
ft_vec_access.c \
ft_vec_free.c \
+ \
+ ft_mat_init.c \
+ ft_mat_append.c \
+ ft_mat_insert_col.c \
+ ft_mat_insert_row.c \
+ ft_mat_free.c \
SOURCES := $(foreach dir, $(SRCDIR), $(addprefix $(dir)/, $($(dir:ft_%=SRC%))))
OBJECTS := $(SOURCES:.c=.o)
all : $(NAME)
+debug : CFLAGS += -g
+debug : $(NAME)
+
$(NAME) : $(OBJECTS)
$(AR) rcs $@ $^
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_mat_append.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/12 10:25:34 by ljiriste #+# #+# */
+/* Updated: 2023/12/12 10:28:46 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+
+t_arr_stat ft_mat_append_row(t_mat *mat, const t_vec *vec)
+{
+ return (ft_mat_insert_row(mat, vec, mat->rows));
+}
+
+t_arr_stat ft_mat_append_col(t_mat *mat, const t_vec *vec)
+{
+ return (ft_mat_insert_col(mat, vec, mat->cols));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_mat_free.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/11 19:06:07 by ljiriste #+# #+# */
+/* Updated: 2023/12/11 19:08:21 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+
+void ft_mat_free(t_mat *mat, void (*free_el)(void *))
+{
+ ft_vec_free(&(mat->vec), free_el);
+ mat->cols = 0;
+ mat->rows = 0;
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_mat_init.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/11 19:03:27 by ljiriste #+# #+# */
+/* Updated: 2023/12/11 19:05:45 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+
+t_arr_stat ft_mat_init(t_mat *mat, size_t el_size)
+{
+ mat->rows = 0;
+ mat->cols = 0;
+ return (ft_vec_init(&(mat->vec), el_size));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_mat_insert_col.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/12 08:57:22 by ljiriste #+# #+# */
+/* Updated: 2024/01/12 17:24:31 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+#include "ft_mem.h"
+
+/* Failure is too complicated to deal with in this approach
+void revert_partial_col_insert(t_mat *mat, size_t col, size_t failed_row)
+{
+ while (failed_row > 0)
+ {
+ ft_vec_forget(&(mat->vec), (failed_row - 1) * mat->cols + col);
+ --failed_row;
+ }
+ return ;
+}
+
+// Number of bytes moved is O(n^2) but it is doable in O(n) (not that hard)
+ft_mat_insert_col(t_mat *mat, const t_vec *vec, size_t index)
+{
+ size_t i;
+ t_arr_stat res;
+
+ if (!mat || !input_row || mat->rows != vec->size)
+ return (invalid_input);
+ ++mat->cols;
+ i = 0;
+ while (i < mat->rows)
+ {
+ res = ft_vec_insert(&(mat->vec), (char *)vec->vec + i * vec->el_size,
+ i * mat->cols + index)
+ if (res)
+ {
+ revert_partial_col_insert(mat, index, i);
+ --mat->cols;
+ return (res);
+ }
+ ++i;
+ }
+ return (success);
+}
+*/
+
+// Creates space for the inserted column inside the mat->vec
+void reorganize(t_mat *mat, size_t move_index, size_t change)
+{
+ size_t i;
+
+ i = mat->rows - 1;
+ if (move_index < mat->cols)
+ {
+ ft_memmove((char *)mat->vec.vec
+ + ((mat->rows - 1) * mat->cols + move_index) * mat->vec.el_size,
+ (char *)mat->vec.vec + ((mat->rows - 1)
+ * (mat->cols + change) + move_index) * mat->vec.el_size,
+ (mat->cols - move_index) * mat->vec.el_size);
+ }
+ --i;
+ while (i + 1 > 0)
+ {
+ ft_memmove((char *)mat->vec.vec
+ + (i * mat->cols + move_index) * mat->vec.el_size,
+ (char *)mat->vec.vec
+ + (i * (mat->cols + change) + move_index) * mat->vec.el_size,
+ mat->cols * mat->vec.el_size);
+ --i;
+ }
+ mat->cols += change;
+ return ;
+}
+
+static void copy(t_mat *mat, const t_vec *vec, size_t index)
+{
+ size_t i;
+
+ i = 0;
+ while (i < mat->rows)
+ {
+ ft_memmove((char *)vec->vec + i * vec->el_size,
+ (char *)mat->vec.vec + (i * mat->cols + index)
+ * mat->vec.el_size, vec->el_size);
+ ++i;
+ }
+ return ;
+}
+
+t_arr_stat ft_mat_insert_col(t_mat *mat, const t_vec *vec, size_t index)
+{
+ size_t cols_change;
+ size_t move_index;
+ t_arr_stat res;
+
+ cols_change = 1;
+ move_index = index;
+ if (index > mat->cols)
+ {
+ cols_change = index - mat->cols + 1;
+ move_index = mat->cols;
+ }
+ while ((mat->cols + cols_change) * mat->rows < mat->vec.capacity)
+ {
+ res = ft_vec_enlarge(&(mat->vec));
+ if (res != success)
+ return (res);
+ }
+ reorganize(mat, move_index, cols_change);
+ if (res != success)
+ return (res);
+ copy(mat, vec, index);
+ return (res);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_mat_insert_row.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/11 19:20:00 by ljiriste #+# #+# */
+/* Updated: 2024/01/12 17:08:04 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+
+t_arr_stat ft_mat_insert_row(t_mat *mat, const t_vec *vec, size_t index)
+{
+ size_t res;
+
+ if (!mat || !vec || mat->cols != vec->size)
+ return (invalid_input);
+ res = ft_vec_insert_range(&(mat->vec), vec->vec,
+ mat->cols, index * mat->cols);
+ if (res != success)
+ return (res);
+ ++mat->rows;
+ return (success);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_vec_enlarge.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/12 17:03:50 by ljiriste #+# #+# */
+/* Updated: 2024/01/12 17:06:04 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+#include <stdint.h>
+
+t_arr_stat ft_vec_enlarge(t_vec *vec)
+{
+ if (vec->capacity == SIZE_MAX)
+ return (alloc_fail);
+ if (vec->capacity > SIZE_MAX / 2)
+ {
+ if (ft_vec_reserve(vec, SIZE_MAX))
+ return (alloc_fail);
+ }
+ else if (vec->capacity == 0)
+ {
+ if (ft_vec_reserve(vec, V_DEFAULT_CAPACITY))
+ return (alloc_fail);
+ }
+ else
+ {
+ if (ft_vec_reserve(vec, vec->capacity * 2))
+ return (alloc_fail);
+ }
+ return (success);
+}
/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/09 17:10:39 by ljiriste #+# #+# */
-/* Updated: 2023/12/11 19:59:50 by ljiriste ### ########.fr */
+/* Updated: 2024/01/11 10:53:17 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
#include "ft_arr.h"
-#include "libft.h"
t_arr_stat ft_vec_erase(t_vec *vec, size_t index, void (*free_el)(void *))
{
t_arr_stat ft_vec_erase_range(t_vec *vec, size_t count, size_t index,
void (*free_el)(void *))
{
- void *p;
+ char *p;
- if (!vec || index + count > vec->size || index > SIZE_MAX - count)
- return (invalid_input);
- vec->size -= count;
- ft_memmove((char *)vec->vec + index,
- (char *)vec->vec + vec->el_size * (index + count),
- vec->el_size * (vec->size - index));
if (free_el)
{
- p = (char *)vec->vec + vec->size * vec->el_size;
- while ((char *)p < (char *)vec->vec
- + (vec->size + count) * vec->el_size)
+ p = (char *)vec->vec + index * vec->el_size;
+ while (p < (char *)vec->vec
+ + (index + count) * vec->el_size)
{
free_el(p);
- p = (char *)p + vec->el_size;
+ p += vec->el_size;
}
}
+ ft_vec_forget_range(vec, count, index);
return (success);
}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* ft_vec_forget.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/12/12 10:11:45 by ljiriste #+# #+# */
+/* Updated: 2023/12/23 12:46:49 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ft_arr.h"
+#include "libft.h"
+
+t_arr_stat ft_vec_forget(t_vec *vec, size_t index)
+{
+ return (ft_vec_forget_range(vec, 1, index));
+}
+
+t_arr_stat ft_vec_forget_range(t_vec *vec, size_t count, size_t index)
+{
+ if (!vec || index + count > vec->size || index > SIZE_MAX - count)
+ return (invalid_input);
+ vec->size -= count;
+ ft_memmove((char *)vec->vec + index,
+ (char *)vec->vec + vec->el_size * (index + count),
+ vec->el_size * (vec->size - index));
+ return (success);
+}
/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/09 16:50:57 by ljiriste #+# #+# */
-/* Updated: 2023/12/11 19:53:35 by ljiriste ### ########.fr */
+/* Updated: 2024/01/12 17:03:45 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
#include "ft_arr.h"
#include "libft.h"
-static t_arr_stat ft_vec_enlarge(t_vec *vec)
-{
- if (vec->capacity == SIZE_MAX)
- return (alloc_fail);
- if (vec->capacity > SIZE_MAX / 2)
- {
- if (ft_vec_reserve(vec, SIZE_MAX))
- return (alloc_fail);
- }
- else if (vec->capacity == 0)
- {
- if (ft_vec_reserve(vec, V_DEFAULT_CAPACITY))
- return (alloc_fail);
- }
- else
- {
- if (ft_vec_reserve(vec, vec->capacity * 2))
- return (alloc_fail);
- }
- return (success);
-}
-
t_arr_stat ft_vec_insert(t_vec *vec, void const *element, size_t index)
{
return (ft_vec_insert_range(vec, element, 1, index));
ft_memmove((char *)vec->vec + vec->el_size * (index + count),
(char *)vec->vec + vec->el_size * index,
vec->el_size * (vec->size - index));
- ft_memcpy((char *)vec->vec + vec->el_size * index, element,
+ ft_memmove((char *)vec->vec + vec->el_size * index, element,
vec->el_size * count);
if (index > vec->size)
vec->size = index;
- ++vec->size;
+ vec->size += count;
return (success);
}
/* By: ljiriste <ljiriste@student.42prague.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/09 13:58:15 by ljiriste #+# #+# */
-/* Updated: 2023/12/11 20:04:34 by ljiriste ### ########.fr */
+/* Updated: 2024/01/12 19:13:06 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
alloc_fail,
invalid_size,
invalid_input,
+ non_specific_failure,
} t_arr_stat;
-// It should be possible to remove el_size with the use of macros
+// It should be possible to remove el_size with the use of macros?
typedef struct s_vec
{
size_t capacity;
void *vec;
} t_vec;
-t_arr_stat ft_vec_init(t_vec *vec, size_t el_size);
-void ft_vec_free(t_vec *vec, void (*free_el)(void *));
+typedef struct s_mat
+{
+ size_t rows;
+ size_t cols;
+ t_vec vec;
+} t_mat;
+
t_arr_stat ft_vec_reserve(t_vec *vec, size_t capacity);
+t_arr_stat ft_vec_enlarge(t_vec *vec);
t_arr_stat ft_vec_insert(t_vec *vec, const void *element, size_t index);
t_arr_stat ft_vec_append(t_vec *vec, const void *element);
+t_arr_stat ft_vec_forget(t_vec *vec, size_t index);
+t_arr_stat ft_vec_erase(t_vec *vec, size_t index, void (*free_el)(void *));
+
t_arr_stat ft_vec_insert_range(t_vec *vec, const void *element,
size_t count, size_t index);
t_arr_stat ft_vec_append_range(t_vec *vec, const void *element, size_t count);
-t_arr_stat ft_vec_erase(t_vec *vec, size_t index, void (*free_el)(void *));
+t_arr_stat ft_vec_forget_range(t_vec *vec, size_t index, size_t count);
t_arr_stat ft_vec_erase_range(t_vec *vec, size_t count, size_t index,
void (*free_el)(void *));
+
+t_arr_stat ft_vec_init(t_vec *vec, size_t el_size);
+void ft_vec_free(t_vec *vec, void (*free_el)(void *));
void *ft_vec_access(t_vec *vec, size_t index);
+/* It is probably better to use (type *)vec->vec + index for pointer
+ * or ((type *)vec->vec)[index] for value
+ * insted of (type *)ft_vec_access(vec, index)
+ * because it is smaller, more readable. But it does not range-check!
+ * Also implement access function that casts to desired type
+ * eg. int *int_access(t_vec *vec, size_t ind){return ((int *)vec->vec + ind);}
+ */
+
+t_arr_stat ft_mat_init(t_mat *mat, size_t el_size);
+void ft_mat_free(t_mat *mat, void (*free_el)(void *));
+t_arr_stat ft_mat_resize(t_mat *mat, size_t rows, size_t cols);
+t_arr_stat ft_mat_insert_row(t_mat *mat, const t_vec *vec, size_t index);
+t_arr_stat ft_mat_insert_col(t_mat *mat, const t_vec *vec, size_t index);
+t_arr_stat ft_mat_append_row(t_mat *mat, const t_vec *vec);
+t_arr_stat ft_mat_append_col(t_mat *mat, const t_vec *vec);
+t_arr_stat ft_mat_erase_rows(t_mat *mat, size_t count,
+ size_t index, void (*free_el)(void *));
+t_arr_stat ft_mat_erase_cols(t_mat *mat, size_t count,
+ size_t index, void (*free_el)(void *));
+void *ft_mat_access(t_mat *mat, size_t row, size_t col);
+
#endif