File mut_wptt_f_moves.c
File List > mut-wptt_f_moves > src > mut_wptt_f_moves.c
Go to the documentation of this file
/******************************************************************************/
/************************** Includes ******************************************/
/******************************************************************************/
#include "mut_wptt_f_moves.h"
#include "mutator_defs.h"
#include "notation_wptt.h"
#include "stdbool.h"
#include "stdio.h"
#include "stdlib.h"
#include "tang_defs.h"
/******************************************************************************/
/************************** Defines *******************************************/
/******************************************************************************/
#define MUT_WPTT_F_MOVES_STACK_SIZE (UTIL_TANG_DEFS_MAX_CROSSINGNUM)
/******************************************************************************/
/************************** Typedefs ******************************************/
/******************************************************************************/
typedef bool (*should_reverse_funptr_t)(size_t depth);
/******************************************************************************/
/************************** Private Function Declarations *********************/
/******************************************************************************/
STATIC_INLINE note_wptt_V4_label_e mut_wptt_f_moves_V4_mult(note_wptt_V4_label_e x,
note_wptt_V4_label_e y);
STATIC_INLINE_UINT8 mut_wptt_f_moves_F1();
STATIC_INLINE_UINT8 mut_wptt_f_moves_F2();
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3();
STATIC_INLINE_UINT8 mut_wptt_f_moves_walk(note_wptt_node_t *vertex,
should_reverse_funptr_t reverse_checker);
STATIC_INLINE bool mut_wptt_f_moves_revall(size_t depth);
STATIC_INLINE bool mut_wptt_f_moves_revodd(size_t depth);
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3_wrap(size_t target_idx);
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3_nowrap();
/******************************************************************************/
/************************** Local Variables ***********************************/
/******************************************************************************/
static uint8_t was_executed = 0;
static mut_wptt_f_moves_config_t *localcfg = NULL;
/******************************************************************************/
/************************** Public Function Definitions ***********************/
/******************************************************************************/
/*
* Documentation in header
*/
uint8_t mut_wptt_f_moves_config(mut_wptt_f_moves_config_t *config_arg)
{
uint8_t ret_val = MUT_DEFS_CONFIG_FAIL;
was_executed = false;
localcfg = NULL;
/*Ensure the cfg is not empty.*/
if (NULL == config_arg)
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_IS_NULL);
} /*Ensure the vertex is not empty.*/
else if (NULL == config_arg->vertex)
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_VERTEX);
}/*Ensure a move is configured.*/
else if (MUT_F_MOVE_UNINIT == config_arg->move)
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_MOVE);
}/*When F_1 is configured ensure the label is configured.*/
else if ((MUT_F_MOVE_F1 == config_arg->move) &&
((NULL == config_arg->V4_label) ||
(NOTE_WPTT_V4_LABEL_UNINIT == *(config_arg->V4_label))))
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_F1);
}/*When F_2 is configured ensure the label and eqclass are configured.*/
else if ((MUT_F_MOVE_F2 == config_arg->move) &&
((NULL == config_arg->V4_label) ||
(NOTE_WPTT_V4_LABEL_UNINIT == *(config_arg->V4_label) ||
(MUT_F_MOVES_EQCLASS_UNINIT == config_arg->eqclass))))
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_F2);
}/*When F_3 is configured ensure the direction is configured.*/
else if ((MUT_F_MOVE_F3 == config_arg->move) &&
(MUT_F_MOVES_DIR_UNINIT == config_arg->direction))
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_CONFIG_FAIL,
MUT_WPTT_F_MOVES_CONFIG_F3);
}
else
{
/* Set the config. */
localcfg = config_arg;
ret_val = MUT_DEFS_CONFIG_SUCCESS;
}
return ret_val;
}
/*
* Documentation in header
*/
uint8_t mut_wptt_f_moves_mutate()
{
uint8_t ret_val = MUT_DEFS_MUTATE_FAIL;
/*Ensure the local config is not empty.*/
if (localcfg == NULL)
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_CFG_ERROR);
} /*Ensure not previously executed.*/
else if (was_executed != false)
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_ALREADY_COMPUTED);
}
else
{
ret_val = MUT_DEFS_MUTATE_SUCCESS;
was_executed = true;
switch (localcfg->move)
{
case MUT_F_MOVE_F1: {
ret_val |= mut_wptt_f_moves_F1();
break;
}
case MUT_F_MOVE_F2: {
ret_val |= mut_wptt_f_moves_F2();
break;
}
case MUT_F_MOVE_F3: {
ret_val |= mut_wptt_f_moves_F3();
break;
}
default: {
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_CFG);
}
}
}
return ret_val;
}
/******************************************************************************/
/************************** Private Function Declarations *********************/
/******************************************************************************/
STATIC_INLINE_UINT8 mut_wptt_f_moves_F1()
{
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
*(localcfg->V4_label) = mut_wptt_f_moves_V4_mult(*(localcfg->V4_label),
NOTE_WPTT_V4_LABEL_Z);
ret_val = mut_wptt_f_moves_walk(localcfg->vertex, &mut_wptt_f_moves_revall);
if (NOTE_WPTT_V4_LABEL_UNINIT == *(localcfg->V4_label))
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_LABEL_ERROR);
}
return ret_val;
}
STATIC_INLINE_UINT8 mut_wptt_f_moves_F2()
{
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
switch (localcfg->eqclass)
{
case MUT_F_MOVES_EQCLASS_SELF: {
*(localcfg->V4_label) = mut_wptt_f_moves_V4_mult(*(localcfg->V4_label),
NOTE_WPTT_V4_LABEL_Y);
ret_val |= mut_wptt_f_moves_walk(localcfg->vertex, &mut_wptt_f_moves_revodd);
break;
};
case MUT_F_MOVES_EQCLASS_CHILD: {
size_t i;
*(localcfg->V4_label) = mut_wptt_f_moves_V4_mult(*(localcfg->V4_label),
NOTE_WPTT_V4_LABEL_X);
for (i = 0; i < localcfg->vertex->number_of_children; i++)
{
ret_val |= mut_wptt_f_moves_walk(localcfg->vertex->children[i],
&mut_wptt_f_moves_revodd);
}
break;
};
default: {
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_EQCLASS);
}
}
if (NOTE_WPTT_V4_LABEL_UNINIT == *(localcfg->V4_label))
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_LABEL_ERROR);
}
return ret_val;
}
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3()
{
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
const size_t idx = localcfg->weight_idx;
const size_t number_of_children = localcfg->vertex->number_of_children;
if (idx <= number_of_children)
{
if ((0 == idx) &&
(((MUT_F_MOVES_DIR_BK == localcfg->direction) &&
(NOTE_WPTT_ORDER_FORWARD == localcfg->vertex->order)) ||
((MUT_F_MOVES_DIR_FWD == localcfg->direction) &&
(NOTE_WPTT_ORDER_REVERSE == localcfg->vertex->order))))
{
ret_val |= mut_wptt_f_moves_F3_wrap(number_of_children);
}
else if ((number_of_children == idx) &&
(((MUT_F_MOVES_DIR_BK == localcfg->direction) &&
(NOTE_WPTT_ORDER_REVERSE == localcfg->vertex->order)) ||
((MUT_F_MOVES_DIR_FWD == localcfg->direction) &&
(NOTE_WPTT_ORDER_FORWARD == localcfg->vertex->order))))
{
ret_val |= mut_wptt_f_moves_F3_wrap(0);
}
else
{
ret_val |= mut_wptt_f_moves_F3_nowrap();
}
}
else
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_F3_ERROR);
}
return ret_val;
}
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3_nowrap()
{
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
const size_t idx = localcfg->weight_idx;
size_t target_idx = idx;
int8_t weight = localcfg->vertex->weights[idx];
if (MUT_F_MOVES_DIR_BK == localcfg->direction)
{
if (NOTE_WPTT_ORDER_FORWARD == localcfg->vertex->order)
{
target_idx--;
}
else
{
target_idx++;
}
}
else if (MUT_F_MOVES_DIR_FWD == localcfg->direction)
{
if (NOTE_WPTT_ORDER_FORWARD == localcfg->vertex->order)
{
target_idx++;
}
else
{
target_idx--;
}
}
else
{
ret_val |= MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_F3_ERROR);
}
localcfg->vertex->weights[target_idx] += weight;
localcfg->vertex->weights[idx] = 0;
if (1 == abs(weight) % 2)
{
ret_val |= mut_wptt_f_moves_walk(localcfg->vertex->children[target_idx],
&mut_wptt_f_moves_revodd);
}
return ret_val;
}
STATIC_INLINE_UINT8 mut_wptt_f_moves_F3_wrap(size_t target_idx)
{
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
const size_t idx = localcfg->weight_idx;
const size_t number_of_children = localcfg->vertex->number_of_children;
int8_t weight = localcfg->vertex->weights[idx];
localcfg->vertex->weights[target_idx] += weight;
localcfg->vertex->weights[idx] = 0;
if (1 == abs(weight) % 2)
{
size_t i;
for (i = 0; i < number_of_children; i++)
{
ret_val |= mut_wptt_f_moves_walk(localcfg->vertex->children[i],
&mut_wptt_f_moves_revodd);
}
}
return ret_val;
}
STATIC_INLINE_UINT8 mut_wptt_f_moves_walk(note_wptt_node_t *vertex,
should_reverse_funptr_t reverse_checker)
{
/* We are going to use count instead of index. This helps with intuiting the state of the stack.
* The count starts at 1 since the root is going to be added to the stack before the main loop.
*/
uint8_t ret_val = MUT_DEFS_MUTATE_SUCCESS;
size_t stack_count = 1;
note_wptt_node_t *stack[MUT_WPTT_F_MOVES_STACK_SIZE] = { NULL };
size_t childidx_stack[MUT_WPTT_F_MOVES_STACK_SIZE] = { 0 };
stack[stack_count - 1] = vertex;
while ((MUT_DEFS_MUTATE_SUCCESS == ret_val) &&
(stack_count != 0))
{
note_wptt_node_t *active_vertex = stack[stack_count - 1];
/* Active vertex is a leaf vertex*/
if (true == reverse_checker(stack_count - 1))
{
if (NOTE_WPTT_ORDER_FORWARD == active_vertex->order)
{
active_vertex->order = NOTE_WPTT_ORDER_REVERSE;
}
else if (NOTE_WPTT_ORDER_REVERSE == active_vertex->order)
{
active_vertex->order = NOTE_WPTT_ORDER_FORWARD;
}
else
{
ret_val = MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_WALK_ERROR);
}
}
if (active_vertex->number_of_children <= childidx_stack[stack_count - 1])
{
/*Pop stack*/
stack_count--;
}
else
{
size_t child_idx = childidx_stack[stack_count - 1];
/*Push child to stack*/
childidx_stack[stack_count - 1]++;
if ((NULL != active_vertex->children[child_idx]) &&
(stack_count < MUT_WPTT_F_MOVES_STACK_SIZE))
{
stack_count++;
stack[stack_count - 1] = active_vertex->children[child_idx];
childidx_stack[stack_count - 1] = 0;
}
else
{
ret_val = MUT_STATUS_BLDR(MUT_DEFS_MUTATE_FAIL,
MUT_WPTT_F_MOVES_MUTATE_MOVE_WALK_ERROR);
}
}
}
return ret_val;
}
STATIC_INLINE bool mut_wptt_f_moves_revall(size_t depth)
{
return true;
}
STATIC_INLINE bool mut_wptt_f_moves_revodd(size_t depth)
{
if (0 == depth % 2)
{
return true;
}
return false;
}
STATIC_INLINE note_wptt_V4_label_e mut_wptt_f_moves_V4_mult(note_wptt_V4_label_e x,
note_wptt_V4_label_e y)
{
if (x == y)
{
return NOTE_WPTT_V4_LABEL_I;
}
if (NOTE_WPTT_V4_LABEL_I == x)
{
return y;
}
if (NOTE_WPTT_V4_LABEL_I == y)
{
return x;
}
switch (x)
{
case NOTE_WPTT_V4_LABEL_X: {
switch (y)
{
case NOTE_WPTT_V4_LABEL_Y: { return NOTE_WPTT_V4_LABEL_Z; }
case NOTE_WPTT_V4_LABEL_Z: { return NOTE_WPTT_V4_LABEL_Y; }
default: { return NOTE_WPTT_V4_LABEL_UNINIT; }
}
}
case NOTE_WPTT_V4_LABEL_Y: {
switch (y)
{
case NOTE_WPTT_V4_LABEL_X: { return NOTE_WPTT_V4_LABEL_Z; }
case NOTE_WPTT_V4_LABEL_Z: { return NOTE_WPTT_V4_LABEL_X; }
default: { return NOTE_WPTT_V4_LABEL_UNINIT; }
}
}
case NOTE_WPTT_V4_LABEL_Z: {
switch (y)
{
case NOTE_WPTT_V4_LABEL_X: { return NOTE_WPTT_V4_LABEL_Y; }
case NOTE_WPTT_V4_LABEL_Y: { return NOTE_WPTT_V4_LABEL_X; }
default: { return NOTE_WPTT_V4_LABEL_UNINIT; }
}
}
default: { return NOTE_WPTT_V4_LABEL_UNINIT; }
}
return NOTE_WPTT_V4_LABEL_UNINIT;
}