Continuing implementation of rpn_if, adding default if functions implementation

This commit is contained in:
Yann Weber 2020-03-29 12:39:54 +02:00
commit eeac401bb3
6 changed files with 467 additions and 185 deletions

View file

@ -21,7 +21,7 @@ PYTHON_LDFLAGS=-shared -fPIC `$(PYTHON_CONFIG) --libs` `$(PYTHON_CONFIG) --ldfl
all: .deps pyrpn.so
pyrpn.so: python_pyrpn.o python_rpnexpr.o rpn_lib.o rpn_jit.o rpn_parse.o rpn_mutation.o rpn_if.o
pyrpn.so: python_pyrpn.o python_rpnexpr.o rpn_lib.o rpn_jit.o rpn_parse.o rpn_mutation.o rpn_if.o rpn_if_default.o
$(LD) $(LDFLAGS) $(PYTHON_LDFLAGS) -o $@ $^
python_pyrpn.o: python_pyrpn.c python_rpnexpr.h python_rpnexpr.o rpn_jit.o
@ -42,6 +42,9 @@ rpn_mutation.o: rpn_mutation.c rpn_mutation.h rpn_parse.o
rpn_if.o: rpn_if.c rpn_if.h rpn_jit.o
$(CC) $(CFLAGS) -c $<
rpn_if_default.o: rpn_if_default.c rpn_if_default.h rpn_if.o
$(CC) $(CFLAGS) -c $<
rpn_lib.o: rpn_lib.asm rpn_lib.h
$(NASM) $(NASMCFLAGS) -o $@ $<

View file

@ -92,6 +92,7 @@ PyObject* rpnexpr_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds);
* @ingroup python_type
*/
int rpnexpr_init(PyObject *self, PyObject *args, PyObject *kwds);
/**@brief RPNExpr __del__ method
* @param self RPNExpr instance
* @ingroup python_type

150
rpn_if.c
View file

@ -18,66 +18,86 @@
*/
#include "rpn_if.h"
rpn_if_t* rpn_if_new(size_t mem_sz, rpn_if_transfo_t *if2rpn,
rpn_if_transfo_t *rpn2if, rpn_expr_t *rpn)
rpn_if_t* rpn_if_new(const rpn_if_param_t *params, rpn_expr_t *rpn)
{
rpn_if_t *res;
if(mem_sz != 0)
{
if((if2rpn->mem_sz != 0 && if2rpn->mem_sz != mem_sz) ||
(rpn2if->mem_sz != 0 && rpn2if->mem_sz != mem_sz))
{
errno = EINVAL;
return NULL;
}
}
else
{
if(if2rpn->mem_sz == 0 && rpn2if->mem_sz == 0)
{
errno = EINVAL;
return NULL;
}
if(if2rpn->mem_sz != rpn2if->mem_sz && if2rpn->mem_sz != 0 &&
rpn2if->mem_sz != 0)
{
errno = EINVAL;
return NULL;
}
mem_sz = if2rpn->mem_sz != 0?if2rpn->mem_sz:rpn2if->mem_sz;
}
if(if2rpn->data_sz != rpn2if->data_sz || if2rpn->data_sz == 0)
{
errno = EINVAL;
return NULL;
}
res = _rpn_if_new(mem_sz, if2rpn->argc, rpn2if->argc, rpn2if->data_sz);
int err;
res = malloc(sizeof(rpn_if_t));
if(!res)
{
return NULL;
goto error;
}
res->if2rpn = if2rpn->if2rpn;
res->rpn2if = rpn2if->rpn2if;
res->rpn = rpn;
memcpy(&res->params, params, sizeof(rpn_if_param_t));
res->mem = mmap(NULL, params->mem_sz, PROT_READ|PROT_WRITE, MAP_ANON,
-1, 0);
if(res->mem == (void*)-1)
{
goto mmap_err;
}
res->rpn_res = malloc(sizeof(rpn_value_t) *
(params->rpn_sz + params->rpn_argc));
if(!res->rpn_res)
{
goto rpn_malloc_err;
}
res->rpn_args = &(res->rpn_res[params->rpn_sz]);
res->rpn = malloc(sizeof(rpn_expr_t) * params->rpn_sz);
if(!res->rpn)
{
goto rpn_expr_err;
}
return res;
rpn_expr_err:
err = errno;
free(res->rpn_res);
rpn_malloc_err:
err = errno;
munmap(res->mem, params->mem_sz);
mmap_err:
err = errno;
free(res);
error:
err = errno;
errno = err;
return NULL;
}
void rpn_if_free(rpn_if_t* rif)
{
size_t i;
for(i=0; i<rif->rpn_sz; i++)
for(i=0; i<rif->params.rpn_sz; i++)
{
rpn_expr_close(&(rif->rpn[i]));
}
free(rif->rpn);
free(rif->rpn_res);
munmap(rif->mem, rif->mem_sz);
munmap(rif->mem, rif->params.mem_sz);
free(rif);
}
size_t rpn_if_step(rpn_if_t *rif, size_t pos)
{
size_t i;
size_t newpos;
rif->params.arg_f(rif, pos, rif->rpn_args);
for(i=0; i<rif->params.rpn_sz; i++)
{
rif->rpn_res[i] = rpn_expr_eval(&(rif->rpn[i]), rif->rpn_args);
}
rif->params.res_f(rif, &newpos, rif->rpn_res);
return newpos;
}
int rpn_if_rpn_upd(rpn_if_t *rif, rpn_tokenized_t *rpns)
{
return rpn_if_rpn_upd_rng(rif, rpns, rif->rpn_sz, 0);
return rpn_if_rpn_upd_rng(rif, rpns, rif->params.rpn_sz, 0);
}
int rpn_if_rpn_upd_rng(rpn_if_t *rif, rpn_tokenized_t *rpns, size_t sz,
@ -91,55 +111,3 @@ int rpn_if_rpn_upd_rng(rpn_if_t *rif, rpn_tokenized_t *rpns, size_t sz,
return 0;
}
rpn_if_t* _rpn_if_new(size_t mem_sz, size_t rpn_argc, size_t rpn_count, size_t
value_sz)
{
rpn_if_t *res;
int err;
res = malloc(sizeof(rpn_if_t));
if(!res)
{
goto error;
}
res->rpn_sz = rpn_count;
res->rpn_argc = rpn_argc;
res->mem_sz = mem_sz;
res->value_sz = value_sz;
res->mem = mmap(NULL, mem_sz, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if(res->mem == (void*)-1)
{
goto mmap_err;
}
res->rpn_res = malloc(sizeof(unsigned long) * (rpn_count +rpn_argc));
if(!res->rpn_res)
{
goto rpn_malloc_err;
}
res->rpn_args = &(res->rpn_res[res->rpn_sz]);
res->rpn = malloc(sizeof(rpn_expr_t) * res->rpn_sz);
if(!res->rpn)
{
goto rpn_expr_err;
}
return res;
rpn_expr_err:
err = errno;
free(res->rpn_res);
rpn_malloc_err:
err = errno;
munmap(res->mem, mem_sz);
mmap_err:
err = errno;
free(res);
error:
err = errno;
errno = err;
return NULL;
}

136
rpn_if.h
View file

@ -34,120 +34,69 @@
* For more details about IF see dedicated page : @ref doc_ifs_if
*/
typedef void* rpn_if_arg_t;
typedef unsigned long rpn_arg_t;
/**@brief Shortcut for struct @ref rpn_if_s */
typedef struct rpn_if_s rpn_if_t;
typedef struct rpn_if_res_s rpn_if_res_t;
typedef struct rpn_if_state_s rpn_if_state_t;
typedef struct rpn_if_transfo_s rpn_if_transfo_t;
typedef enum rpn_if_transfo_type_e rpn_if_transfo_type_t;
/**@brief IF state to RPN arguments transformation */
typedef void (*if2rpn_f)(rpn_if_t *rif, rpn_if_state_t, rpn_arg_t*);
/**@brief RPN arguments to IF state transformation */
typedef rpn_if_res_t (*rpn2if_f)(rpn_if_t *rif, rpn_arg_t, rpn_if_state_t);
/**@brief Shortcut for struct @ref rpn_if_param_s */
typedef struct rpn_if_param_s rpn_if_param_t;
/**@brief IF state
*
* Will always be something like :
* - memory adress/offset/index
* - value
*/
struct rpn_if_state_s
/**@brief Stores IF parameters and transformations function pointers */
struct rpn_if_param_s
{
/**@brief Data address */
size_t i;
/**@brief Data value(s) */
void *val;
};
/**@brief Indicate function type for @ref rpn_if_transfo_s */
enum rpn_if_transfo_type_e
{
/**@brief No transformation
*
* Default behavior is to copy data in args directly assuming
* argc * sizeof(unsigned long) = data_sz */
RPN_f_null,
/**@brief Transform RPN result into data */
RPN_f_rpn2if,
/**@brief Transform data into RPN result */
RPN_f_if2rpn
};
/**@brief Represent an IF transformation function
*
* Can transform data into arguments or arguments into data, depending
* on function type.
*/
struct rpn_if_transfo_s
{
/**@brief Function pointer type
* @note optionnal, for type checking
*/
rpn_if_transfo_type_t type;
/**@brief Data size (a @ref rpn_if_s::mem item ) in bytes */
size_t data_sz;
/**@brief Memory size in byte */
/**@brief Memory map size in items */
size_t mem_sz;
/**@brief RPN arg/result size
*
* - if type is RPN_if2rpn argc is the rpn expression argc
* - if type is RPN_rpn2if argc is the rpn expression count (results
* count)
*/
size_t argc;
union {
/**@brief IF state to RPN arguments transformation */
if2rpn_f if2rpn;
/**@brief RPN arguments to IF state transformation */
rpn2if_f rpn2if;
};
/**@brief Size of a memory item */
size_t value_sz;
/**@brief RPN expression count */
size_t rpn_sz;
/**@brief Number of arguments expected by RPN expressions */
size_t rpn_argc;
/**@brief Position to RPN argument transformation */
int (*arg_f)(rpn_if_t *rif, size_t pos, rpn_value_t *args);
/**@brief RPN results to data and position transformation
* @note set memory maps with converted data */
int (*res_f)(rpn_if_t *rif, size_t *pos,
rpn_value_t *data);
void *data;
};
/**@brief Generic Iterated function implementation */
struct rpn_if_s
{
/**@brief Memory map in wich data are fetch & stored */
void *mem;
/**@brief Memory map size in bytes */
size_t mem_sz;
/**@brief Size of a memory item */
size_t value_sz;
/**@brief IF last position + value buffer */
rpn_if_state_t state;
/**@brief RPN expression(s) result(s) buffer */
unsigned long *rpn_res;
/**@brief Arguments given to RPN expression(s) buffer */
rpn_arg_t *rpn_args;
/**@brief Number of arguments expected by RPN expressions */
size_t rpn_argc;
/**@brief IF parameters */
rpn_if_param_t params;
/**@brief RPN expression(s) pointer(s) */
rpn_expr_t *rpn;
/**@brief RPN expression count */
size_t rpn_sz;
/**@brief IF state to RPN arguments transformation */
if2rpn_f if2rpn;
/**@brief RPN arguments to IF state transformation */
rpn2if_f rpn2if;
/**@brief RPN expression(s) result(s) buffer */
rpn_value_t *rpn_res;
/**@brief Arguments given to RPN expression(s) buffer */
rpn_value_t *rpn_args;
/**@brief Memory map in wich data are fetch & stored */
rpn_value_t *mem;
};
#define rpn_if_getitem(rif, pos) (rif->mem + (rif->params.value_sz * pos))
/**@brief Alloc a new @ref rpn_if_s from two transformation functions
* @param if2rpn informations about data to rpn args transformation
* @param rpn2if informations about rpn args to data transformation
* @param rpn list of RPN expresions ( must be of rpn2if->argc size !!!)
* @param params IF parameters
* @param rpn list of RPN expresions of params->rpn_sz size
* @return A pointer on an allocated @ref rpn_if_s
*/
rpn_if_t* rpn_if_new(size_t mem_sz, rpn_if_transfo_t *if2rpn,
rpn_if_transfo_t *rpn2if, rpn_expr_t *rpn);
rpn_if_t* rpn_if_new(const rpn_if_param_t *params, rpn_expr_t *rpn);
/**@brief Deallocate an @ref rpn_ifs_s and close associated @ref rpn_expr_s
/**@brief Deallocate an @ref rpn_ifs_s and its ressources and close associated
* @ref rpn_expr_s
* @param rif The IF to deallocate
*/
void rpn_if_free(rpn_if_t *rif);
/**@brief Run an IF
* @param rif Pointer on IF
* @param pos Input position
* @return new position
*/
size_t rpn_if_step(rpn_if_t *rif, size_t pos);
/**@brief Update all RPN expressions
* @param rif The concerned IF
@ -156,6 +105,7 @@ void rpn_if_free(rpn_if_t *rif);
* @note Shortcut for @ref rpn_if_rpn_upd_rng(rif, rpns, rif->rpn_sz, 0);
*/
int rpn_if_rpn_upd(rpn_if_t *rif, rpn_tokenized_t *rpns);
/**@brief Update a range of RPN expressions
* @param rif The concerned IF
* @param rpn A list of tokenized expressions

233
rpn_if_default.c Normal file
View file

@ -0,0 +1,233 @@
#include "rpn_if_default.h"
int rpn_if_argf_default(rpn_if_t *rif, size_t pos, rpn_value_t *args)
{
size_t cur_arg, i, rgb_imax;
rpn_if_default_data_t *data;
rpn_value_t *values;
data = (rpn_if_default_data_t*)rif->params.data;
switch(data->pos_flag)
{
case RPN_IF_POSITION_LINEAR:
rpn_if_argf_linear(rif, pos, args);
cur_arg = 1;
break;
case RPN_IF_POSITION_XY:
rpn_if_argf_xy(rif, pos, args);
cur_arg = 2;
break;
case RPN_IF_POSITION_XDIM:
rpn_if_argf_xdim(rif, pos, args);
cur_arg = *(data->size_lim);
break;
}
if(cur_arg >= rif->params.rpn_argc)
{
/* Too many arguments for given rif !! */
return -1;
}
rgb_imax = 4; /* rgba */
values = rpn_if_getitem(rif, pos);
switch(data->res_flag)
{
case RPN_IF_RES_BOOL:
args[cur_arg] = values[0]?1:0;
break;
case RPN_IF_RES_CONST:
case RPN_IF_RES_COUNT:
args[cur_arg] = *values;
break;
case RPN_IF_RES_RGB:
rgb_imax = 3;
case RPN_IF_RES_CONST_RGBA:
case RPN_IF_RES_RGBA:
for(i=0; i<rgb_imax; i++)
{
args[cur_arg+i] = values[i];
}
break;
case RPN_IF_RES_XFUN:
for(i=0; i < rif->params.rpn_sz - cur_arg; i++)
{
args[cur_arg+i] = values[i];
}
break;
default:
return -1;
}
return -1;
}
int rpn_if_resf_default(rpn_if_t *rif, size_t *pos, rpn_value_t *data);
int rpn_if_argf_linear(rpn_if_t *rif, size_t pos, rpn_value_t *args)
{
rpn_if_default_data_t *data;
data = (rpn_if_default_data_t*)rif->params.data;
if(data->size_lim && pos >= *data->size_lim)
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
pos %= *(data->size_lim);
}
args[0] = pos;
return 0;
}
int rpn_if_resf_linear(rpn_if_t *rif, size_t *pos, rpn_value_t *_data)
{
rpn_if_default_data_t *data;
size_t res;
data = (rpn_if_default_data_t*)rif->params.data;
res = rif->rpn_res[0];
if(data->size_lim && res >= *data->size_lim)
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
res %= *(data->size_lim);
}
*pos = res;
return 0;
}
int rpn_if_argf_xy(rpn_if_t *rif, size_t pos, rpn_value_t *args)
{
rpn_if_default_data_t *data;
data = (rpn_if_default_data_t*)rif->params.data;
if(!data->size_lim)
{
return -1;
}
args[0] = pos % data->size_lim[0];
args[1] = pos / data->size_lim[0];
if(args[1] > data->size_lim[1])
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
args[1] %= data->size_lim[1];
}
return 0;
}
int rpn_if_resf_xy(rpn_if_t *rif, size_t *pos, rpn_value_t *_data)
{
rpn_if_default_data_t *data;
size_t xy[2];
data = (rpn_if_default_data_t*)rif->params.data;
xy[0] = rif->rpn_res[0];
xy[1] = rif->rpn_res[1];
if(!data->size_lim)
{
return -1;
}
if(xy[0] >= data->size_lim[0] || xy[1] >= data->size_lim[1])
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
xy[0] %= data->size_lim[0];
xy[1] %= data->size_lim[1];
}
*pos = xy[0]+(xy[1]*data->size_lim[0]);
return 0;
}
int rpn_if_argf_xdim(rpn_if_t *rif, size_t pos, rpn_value_t *args)
{
rpn_if_default_data_t *data;
size_t i, curdim_sz, curpos;
data = (rpn_if_default_data_t*)rif->params.data;
if(!data->size_lim)
{
return -1;
}
if(*(data->size_lim) < 1)
{
return -1;
}
/**@todo check if *(data->size_lim) overflow rif->params->rpn_argc */
curdim_sz = 1;
curpos = pos;
for(i=0; i<*(data->size_lim)-1; i++)
{
curdim_sz *= data->size_lim[i+1];
args[i] = curpos % curdim_sz;
curpos /= curdim_sz;
}
args[i] = curpos;
if(args[i] >= curdim_sz)
{
if(data->pos_flag && RPN_IF_POSITION_OF_ERR)
{
return -1;
}
args[i] %= curdim_sz;
}
return 0;
}
int rpn_if_resf_xdim(rpn_if_t *rif, size_t *pos, rpn_value_t *_data)
{
rpn_if_default_data_t *data;
size_t i, res, cur, curlim, prevlim;
data = (rpn_if_default_data_t*)rif->params.data;
res = 0;
if(!data->size_lim)
{
return -1;
}
if(*(data->size_lim) < 1)
{
return -1;
}
/**@todo check if *(data->size_lim) overflow rif->params->rpn_argc */
res = rif->rpn_res[0];
if(res >= data->size_lim[1])
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
res %= data->size_lim[1];
}
for(i=1; i < *(data->size_lim); i++)
{
cur = rif->rpn_res[i];
prevlim = data->size_lim[i];
curlim = data->size_lim[i+1];
if(cur >= curlim)
{
if(data->pos_flag & RPN_IF_POSITION_OF_ERR)
{
return -1;
}
cur %= curlim;
}
res += cur * prevlim;
}
*pos = res;
return 0;
}

127
rpn_if_default.h Normal file
View file

@ -0,0 +1,127 @@
/*
* Copyright (C) 2020 Weber Yann
*
* This file is part of pyrpn.
*
* pyrpn is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* pyrpn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __rpn_if_default__h__
#define __rpn_if_default__h__
/**@file rpn_if_default.h Defines default IF
* @brief Default IF definitions
*/
/**@defgroup ifs_if_default Default functions
* @brief Simple iterated functions functions
*/
#include "config.h"
#include "rpn_if.h"
#define RPN_IF_POSITION_LINEAR 0 // One expr for position
#define RPN_IF_POSITION_XY 1 // two expr for poisition
#define RPN_IF_POSITION_XDIM 2 // X expr for position
#define RPN_IF_POSITION_OF_LOOP 0 // Loop on position overflow
#define RPN_IF_POSITION_OF_ERR 16 // Trigger error on position overflow
#define RPN_IF_RES_BOOL 0 // Set to one when position occurs
#define RPN_IF_RES_CONST 1 // Set to a constant value
#define RPN_IF_RES_CONST_RGBA 2 // Set to a constant RGB using alpha channel
#define RPN_IF_RES_COUNT 3 // Count number of time position occurs
#define RPN_IF_RES_XFUN 4 // Set to result of rpn_expr
#define RPN_IF_RES_RGB 5 // Set result to RGB color from rpn_expr
#define RPN_IF_RES_RGBA 6 // Set result to RGB using alpha channel from rpn_expr
typedef struct rpn_if_default_data_s rpn_if_default_data_t;
/**@brief Stores default IF data
*
* Stores flags and size limit
*/
struct rpn_if_default_data_s
{
short pos_flag;
short res_flag;
/**@brief Stores size limits given pos_flag
*
* @note If NULL no limit
* - For @ref RPN_IF_POSITION_LINEAR size_lim is a single size_t
* - For @ref RPN_IF_POSITION_XY size_lim is two size_t (height and width)
* - For @ref RPN_IF_POSITION_XDIM *size_lim is the size of size_lim
*/
size_t *size_lim;
/**@brief Store constant values to set mem giver res_flag
* - For @ref RPN_IF_CONST_RGBA const_val points on a single value
* - For @ref RPN_IF_RES_CONST_RGBA const_val points on 4 values
*/
rpn_value_t *const_val;
};
int rpn_if_argf_default(rpn_if_t *rif, size_t pos, rpn_value_t *args);
int rpn_if_resf_default(rpn_if_t *rif, size_t *pos, rpn_value_t *data);
/**@brief Set the first expression argument from position
* @params rif Expressions
* @params pos Memory map offset
* @params args pointer on expressions arguments
* @note Other arguments are set using the generic @ref rpn_if_argf_default
* function
*/
int rpn_if_argf_linear(rpn_if_t *rif, size_t pos, rpn_value_t *args);
/**@brief Transform 1st expression result to position
* @params rif Expressions
* @params pos Pointer on resulting position in memory map
* @params data Pointer on resulting data
* @note Data from position fecth is done by generic @ref rpn_if_resf_default
* function
*/
int rpn_if_resf_linear(rpn_if_t *rif, size_t *pos, rpn_value_t *data);
/**@brief Set the 1st & 2nd argument from position
* @params rif Expressions
* @params pos Memory map offset
* @params args pointer on expression arguments
* @note Other arguments are set using the generic @ref rpn_if_argf_default
* function
*/
int rpn_if_argf_xy(rpn_if_t *rif, size_t pos, rpn_value_t *args);
/**@brief Transform 1st and 2nd result into a memory map's offset
* @params rif Expressions
* @param pos Memory map offset pointer
* @params data Pointer on resulting data
* @note Data from position fetch is done by generic @ref rpn_if_resf_default
* function
*/
int rpn_if_resf_xy(rpn_if_t *rif, size_t *pos, rpn_value_t *data);
/**@brief Set X first arguments from position
* @params rif Expressions
* @params pos Memory map offset
* @params args Pointer on expression arguments
* @note Other arguments are set using the generic @ref rpn_if_argf_default
* function
*/
int rpn_if_argf_xdim(rpn_if_t *rif, size_t pos, rpn_value_t *args);
/**@brief Transform X arguments into a memory map's offset
* @params rif Expressions
* @param pos Memory map offset pointer
* @param data Pointer on resulting data
* @note Data from position fetch is done by generic @ref rpn_if_resf_default
* function
*/
int rpn_if_resf_xdim(rpn_if_t *rif, size_t *pos, rpn_value_t *data);
#endif