46# pragma fenv_access(on)
153 const double *param_values,
154 int param_values_len,
163#define FAIL_IF(condition) \
165 return EXPR_PYLIKE_FATAL_ERROR; \
178 feclearexcept(FE_ALL_EXCEPT);
180 for (pc = 0; pc >= 0 && pc < expr->
ops_count; pc++) {
181 switch (ops[pc].opcode) {
185 stack[sp++] = ops[pc].
arg.
dval;
189 stack[sp++] = param_values[ops[pc].
arg.
ival];
193 stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]);
197 stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]);
202 stack[sp - 3] = ops[pc].arg.func3(stack[sp - 3], stack[sp - 2], stack[sp - 1]);
206 FAIL_IF(sp < ops[pc].arg.ival);
207 for (
int j = 1; j < ops[pc].arg.ival; j++, sp--) {
212 FAIL_IF(sp < ops[pc].arg.ival);
213 for (
int j = 1; j < ops[pc].arg.ival; j++, sp--) {
220 pc += ops[pc].jmp_offset;
225 pc += ops[pc].jmp_offset;
232 pc += ops[pc].jmp_offset;
243 if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) {
245 pc += ops[pc].jmp_offset;
249 stack[sp - 2] = stack[sp - 1];
263 *r_result = stack[0];
266 int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID);
307 return arg *
M_PI / 180.0;
312 return arg * 180.0 /
M_PI;
322 return a * (1.0 -
x) +
b * x;
327 CLAMP(arg, 0.0, 1.0);
331static double op_clamp3(
double arg,
double minv,
double maxv)
333 CLAMP(arg, minv, maxv);
339 double t = (x - a) / (
b - a);
341 return t * t * (3.0 - 2.0 * t);
346 return a ? 0.0 : 1.0;
351 return a ==
b ? 1.0 : 0.0;
356 return a !=
b ? 1.0 : 0.0;
361 return a <
b ? 1.0 : 0.0;
366 return a <=
b ? 1.0 : 0.0;
371 return a >
b ? 1.0 : 0.0;
376 return a >=
b ? 1.0 : 0.0;
385 {
"pi",
M_PI}, {
"True", 1.0}, {
"False", 0.0}, {
NULL, 0.0}};
396# pragma function(ceil)
397# pragma function(floor)
436#define MAKE_CHAR2(a, b) (((a) << 8) | (b))
438#define CHECK_ERROR(condition) \
439 if (!(condition)) { \
446#define TOKEN_ID MAKE_CHAR2('I', 'D')
447#define TOKEN_NUMBER MAKE_CHAR2('0', '0')
448#define TOKEN_GE MAKE_CHAR2('>', '=')
449#define TOKEN_LE MAKE_CHAR2('<', '=')
450#define TOKEN_NE MAKE_CHAR2('!', '=')
451#define TOKEN_EQ MAKE_CHAR2('=', '=')
452#define TOKEN_AND MAKE_CHAR2('A', 'N')
453#define TOKEN_OR MAKE_CHAR2('O', 'R')
454#define TOKEN_NOT MAKE_CHAR2('N', 'O')
455#define TOKEN_IF MAKE_CHAR2('I', 'F')
456#define TOKEN_ELSE MAKE_CHAR2('E', 'L')
513 state->stack_ptr += stack_delta;
519 memset(op, 0,
sizeof(
ExprOp));
558 int jmp_gap =
state->ops_count -
state->last_jmp;
560 feclearexcept(FE_ALL_EXCEPT);
566 if (jmp_gap >= 1 && prev_ops[-1].opcode ==
OPCODE_CONST) {
571 volatile double result = func(prev_ops[-1].arg.
dval);
573 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
583 if (jmp_gap >= 2 && prev_ops[-2].opcode ==
OPCODE_CONST &&
590 volatile double result = func(prev_ops[-2].arg.
dval, prev_ops[-1].
arg.
dval);
592 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
604 if (jmp_gap >= 3 && prev_ops[-3].opcode ==
OPCODE_CONST &&
611 volatile double result = func(
614 if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
616 state->ops_count -= 2;
617 state->stack_ptr -= 2;
636 while (isspace(*
state->cur)) {
641 if (*
state->cur == 0) {
647 if (isdigit(*
state->cur) || (
state->cur[0] ==
'.' && isdigit(
state->cur[1]))) {
648 char *end, *out =
state->tokenbuf;
649 bool is_float =
false;
651 while (isdigit(*
state->cur)) {
652 *out++ = *
state->cur++;
655 if (*
state->cur ==
'.') {
657 *out++ = *
state->cur++;
659 while (isdigit(*
state->cur)) {
660 *out++ = *
state->cur++;
666 *out++ = *
state->cur++;
669 *out++ = *
state->cur++;
674 while (isdigit(*
state->cur)) {
675 *out++ = *
state->cur++;
682 if (!is_float &&
state->tokenbuf[0] ==
'0') {
683 for (
char *p =
state->tokenbuf + 1; *p; p++) {
691 state->tokenval = strtod(
state->tokenbuf, &end);
710 char *out =
state->tokenbuf;
713 *out++ = *
state->cur++;
755 switch (
state->token) {
778 switch (
state->token) {
798 for (i =
state->param_names_len - 1; i >= 0; i--) {
863 switch (
state->token) {
885 switch (
state->token) {
1001 int prev_last_jmp =
state->last_jmp;
1002 int start =
state->last_jmp =
state->ops_count;
1009 int size =
state->ops_count - start;
1010 int bytes = size *
sizeof(
ExprOp);
1013 memcpy(body,
state->ops + start, bytes);
1044 else if (
state->last_jmp == start) {
1045 state->last_jmp = prev_last_jmp;
1058 const char **param_names,
1059 int param_names_len)
1067 state.param_names_len = param_names_len;
1068 state.param_names = param_names;
1083 expr =
MEM_mallocN(bytesize,
"ExprPyLike_Parsed");
#define BLI_array_alloca(arr, realsize)
#define BLI_assert_msg(a, msg)
@ EXPR_PYLIKE_FATAL_ERROR
@ EXPR_PYLIKE_DIV_BY_ZERO
struct ExprPyLike_Parsed ExprPyLike_Parsed
MINLINE int power_of_2_max_i(int n)
typedef double(DMatrix)[4][4]
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
void jump(const btVector3 &v=btVector3(0, 0, 0))
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
static double op_negate(double arg)
static bool parse_next_token(ExprParseState *state)
static double op_clamp3(double arg, double minv, double maxv)
struct KeywordTokenDef KeywordTokenDef
static int parse_add_jump(ExprParseState *state, eOpCode code)
double(* TernaryOpFunc)(double, double, double)
static double op_lt(double a, double b)
static int parse_function_args(ExprParseState *state)
static BinaryOpFunc parse_get_cmp_func(short token)
static bool parse_mul(ExprParseState *state)
static double op_smoothstep(double a, double b, double x)
static double op_mul(double a, double b)
static BuiltinOpDef builtin_ops[]
static bool parse_and(ExprParseState *state)
void BLI_expr_pylike_free(ExprPyLike_Parsed *expr)
static bool parse_expr(ExprParseState *state)
static const char * token_characters
eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr, const double *param_values, int param_values_len, double *r_result)
static bool parse_add(ExprParseState *state)
static double op_gt(double a, double b)
#define FAIL_IF(condition)
struct ExprParseState ExprParseState
struct BuiltinOpDef BuiltinOpDef
static double op_ne(double a, double b)
#define CHECK_ERROR(condition)
static BuiltinConstDef builtin_consts[]
static double op_div(double a, double b)
static double op_eq(double a, double b)
static void parse_set_jump(ExprParseState *state, int jump)
bool BLI_expr_pylike_is_constant(const ExprPyLike_Parsed *expr)
static double op_lerp(double a, double b, double x)
static ExprOp * parse_add_op(ExprParseState *state, eOpCode code, int stack_delta)
static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void *funcptr)
static bool parse_unary(ExprParseState *state)
static bool parse_not(ExprParseState *state)
static double op_le(double a, double b)
static const char * token_eq_characters
double(* BinaryOpFunc)(double, double)
double(* UnaryOpFunc)(double)
static double op_ge(double a, double b)
static double op_add(double a, double b)
static double op_not(double a)
bool BLI_expr_pylike_is_using_param(const ExprPyLike_Parsed *expr, int index)
bool BLI_expr_pylike_is_valid(const ExprPyLike_Parsed *expr)
struct BuiltinConstDef BuiltinConstDef
static double op_sub(double a, double b)
ExprPyLike_Parsed * BLI_expr_pylike_parse(const char *expression, const char **param_names, int param_names_len)
static double op_degrees(double arg)
static double op_log2(double a, double b)
static bool parse_cmp_chain(ExprParseState *state, BinaryOpFunc cur_func)
static KeywordTokenDef keyword_list[]
static double op_clamp(double arg)
static ExprOp * parse_alloc_ops(ExprParseState *state, int count)
static double op_radians(double arg)
static bool parse_cmp(ExprParseState *state)
static bool parse_or(ExprParseState *state)
static int opcode_arg_count(eOpCode code)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 exp(float3 v)
ccl_device_inline float3 ceil(const float3 a)
ccl_device_inline float3 cos(float3 v)
ccl_device_inline float3 log(float3 v)
const char ** param_names