/* * * Copyright (C) 2024 Brett Terpstra * * This program 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 * (at your option) any later version. * * This program 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 this program. If not, see . */ #ifndef GP_IMAGE_TEST_FUNCTIONS_H #define GP_IMAGE_TEST_FUNCTIONS_H // FUNC_DEFINE(NAME, REQUIRED_ARGS, FUNC, ALLOWED_FUNCS) // FUNC_ALLOW_ANY #include #include #include "blt/std/hashmap.h" #include "blt/std/logging.h" #include "blt/std/types.h" #include #include #include template using allowed_funcs = std::vector; template using allowed_funcs_set = HASHSET; template using func_list = std::vector>; template using func_set = std::vector>; template inline constexpr func_set convert(const func_list& func) { func_set set_list; for (const auto& v : func) { allowed_funcs_set set; for (const auto& f : v) set.insert(f); set_list.push_back(set); } return set_list; } using data_t = std::array; class empty { }; // #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ALLOWED...) #define FUNC_ALLOW_ANY #define FUNC_ALLOW_NONE #define FUNC_ALLOW_BOOL #define FUNC_ALLOW_COORD #define FUNC_ALLOW_SCALAR #define FUNC_ALLOW_SCALAR_COORD #define FUNC_ALLOW_TERMINALS /* * Define Functions */ #define ARGS image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data void f_x(ARGS); void f_y(ARGS); void f_random(ARGS); void f_noise(ARGS); void f_cnoise(ARGS); void f_scalar(ARGS); void f_color(ARGS); void f_log(ARGS); void f_sqrt(ARGS); void f_sin(ARGS); void f_cos(ARGS); void f_atan(ARGS); void f_add(ARGS); void f_sub(ARGS); void f_mul(ARGS); void f_div(ARGS); void f_or(ARGS); void f_and(ARGS); void f_xor(ARGS); void f_if(ARGS); /* * Define function enums / lists */ // NAME MIN MAX FUNC ALLOWED FUNC LIST #define FUNC_FUNCTIONS \ FUNC_DEFINE(X, 0, 0, f_x, FUNC_ALLOW_NONE) \ FUNC_DEFINE(Y, 0, 0, f_y, FUNC_ALLOW_NONE) \ FUNC_DEFINE(RANDOM, 0, 0, f_random, FUNC_ALLOW_NONE) \ FUNC_DEFINE(NOISE, 0, 2, f_noise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \ FUNC_DEFINE(CNOISE, 0, 6, f_cnoise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \ FUNC_DEFINE(SCALAR, 0, 0, f_scalar, FUNC_ALLOW_NONE) \ FUNC_DEFINE(COLOR, 0, 0, f_color, FUNC_ALLOW_NONE) \ FUNC_DEFINE(LOG, 1, 1, f_log, FUNC_ALLOW_ANY) \ FUNC_DEFINE(SQRT, 1, 1, f_sqrt, FUNC_ALLOW_ANY) \ FUNC_DEFINE(SIN, 1, 1, f_sin, FUNC_ALLOW_ANY) \ FUNC_DEFINE(COS, 1, 1, f_cos, FUNC_ALLOW_ANY) \ FUNC_DEFINE(ATAN, 1, 1, f_atan, FUNC_ALLOW_ANY) \ FUNC_DEFINE(ADD, 2, 2, f_add, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(SUB, 2, 2, f_sub, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(MUL, 2, 2, f_mul, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(DIV, 2, 2, f_div, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(OR, 2, 2, f_or, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(AND, 2, 2, f_and, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(XOR, 2, 2, f_xor, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ FUNC_DEFINE(IF, 3, 3, f_if, FUNC_ALLOW_BOOL, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ #undef FUNC_ALLOW_ANY #undef FUNC_ALLOW_NONE #undef FUNC_ALLOW_BOOL #undef FUNC_ALLOW_COORD #undef FUNC_ALLOW_SCALAR #undef FUNC_ALLOW_SCALAR_COORD #undef FUNC_ALLOW_TERMINALS /* * Construct enum */ #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) NAME, enum class function_t : blt::i32 { FUNC_FUNCTIONS m_END }; #undef FUNC_DEFINE static inline blt::i32 to_underlying(function_t f) { return static_cast(f); } static inline constexpr blt::i32 OPERATOR_COUNT = static_cast(function_t::m_END); #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) MAX_ARGS, static inline constexpr blt::i32 MAX_ARGS = std::max({FUNC_FUNCTIONS}); #undef FUNC_DEFINE /* * Define function lists */ #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) function_t::NAME, #define DEF_FUNC_LIST(NAME, ...) \ static inline const allowed_funcs_set NAME##_SET{__VA_ARGS__}; \ static inline const allowed_funcs NAME{__VA_ARGS__}; DEF_FUNC_LIST(FUNC_ALLOW_ANY, FUNC_FUNCTIONS); DEF_FUNC_LIST(FUNC_ALLOW_NONE,); DEF_FUNC_LIST(FUNC_ALLOW_BOOL, function_t::OR, function_t::AND, function_t::XOR); DEF_FUNC_LIST(FUNC_ALLOW_COORD, function_t::X, function_t::Y); DEF_FUNC_LIST(FUNC_ALLOW_SCALAR, function_t::SCALAR); DEF_FUNC_LIST(FUNC_ALLOW_SCALAR_COORD, function_t::SCALAR, function_t::X, function_t::Y); DEF_FUNC_LIST(FUNC_ALLOW_TERMINALS, function_t::SCALAR, function_t::X, function_t::Y, function_t::COLOR, function_t::RANDOM); #undef FUNC_DEFINE /* * Create mappings */ #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) MIN_ARGS, [[maybe_unused]] static inline std::array function_arg_min_map = { FUNC_FUNCTIONS }; #undef FUNC_DEFINE #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) MAX_ARGS, [[maybe_unused]] static inline std::array function_arg_max_map = { FUNC_FUNCTIONS }; #undef FUNC_DEFINE #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) func_list{__VA_ARGS__}, [[maybe_unused]] static inline std::array, OPERATOR_COUNT> function_arg_allowed_map = { FUNC_FUNCTIONS }; #undef FUNC_DEFINE #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) convert(func_list{__VA_ARGS__}), [[maybe_unused]] static inline std::array, OPERATOR_COUNT> function_arg_allowed_set_map = { FUNC_FUNCTIONS }; #undef FUNC_DEFINE #define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) #NAME, [[maybe_unused]] static inline std::array function_name_map = { FUNC_FUNCTIONS }; #undef FUNC_DEFINE /* * Helper functions */ inline static allowed_funcs intersection(const allowed_funcs& vec, const allowed_funcs_set& has) { allowed_funcs set; for (auto v : vec) if (has.contains(v)) set.push_back(v); return set; } inline static allowed_funcs intersection_comp(const allowed_funcs& vec, const allowed_funcs_set& has) { allowed_funcs set; for (auto v : vec) if (!has.contains(v)) set.push_back(v); return set; } // distribution from normality (DFN) float eval_DNF_SW(const image& img); float eval_DNF_KS(const image& img); //template //bool isNan(F f) //{ // return f == std::numeric_limits::quiet_NaN() || f == std::numeric_limits::signaling_NaN(); //} template bool isInf(F f) { return f == std::numeric_limits::infinity() || f == -std::numeric_limits::infinity(); } #endif //GP_IMAGE_TEST_FUNCTIONS_H