diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c14eb2f..f1273c74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 8) -set(pip_REVISION 0) +set(pip_MINOR 15) +set(pip_REVISION 1) set(pip_SUFFIX ) set(pip_COMPANY SHS) set(pip_DOMAIN org.SHS) @@ -121,11 +121,6 @@ macro(pip_find_lib NAME) endif() endmacro() -if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) - set(STATIC_LIB ON) -endif() - - # Version list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_version.h") @@ -433,6 +428,9 @@ if (NOT CROSSTOOLS) # Test program if(PIP_UTILS) + #add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp") + #target_link_libraries(pip_plugin pip) + add_executable(pip_test "main.cpp") target_link_libraries(pip_test pip pip_cloud) if (LUA_FOUND) @@ -441,24 +439,9 @@ if (NOT CROSSTOOLS) endif() else() - - set(PIP_MSG_crypt "yes") - set(PIP_MSG_compress "yes") - set(PIP_MODULES pip) - add_definitions(-DPIP_CRYPT) - add_library(pip_crypt ${pip_LIB_TYPE} ${CPP_LIB_CRYPT}) - target_link_libraries(pip_crypt pip) - list(APPEND PIP_MODULES pip_crypt) - set(IO_UTILS_LIBS pip) - add_library(pip_io_utils ${pip_LIB_TYPE} ${CPP_LIB_IO_UTILS}) - list(APPEND IO_UTILS_LIBS pip_crypt) - target_link_libraries(pip_io_utils ${IO_UTILS_LIBS}) - list(APPEND PIP_MODULES pip_io_utils) - add_definitions(-DPIP_COMPRESS) - add_library(pip_compress ${pip_LIB_TYPE} ${CPP_LIB_COMPRESS}) - target_link_libraries(pip_compress pip) - list(APPEND PIP_MODULES pip_compress) - + pip_module(crypt "" "PIP crypt support" "" "") + pip_module(compress "" "PIP compression support" "" "") + pip_module(io_utils "pip_crypt" "PIP I/O support" "" " (+crypt)") endif() endif() diff --git a/cmake/FindPIP.cmake b/cmake/FindPIP.cmake index 17cc3f3a..72f4e88c 100644 --- a/cmake/FindPIP.cmake +++ b/cmake/FindPIP.cmake @@ -21,8 +21,13 @@ cmake_policy(SET CMP0011 NEW) # don`t affect includer policies include(SHSTKMacros) shstk_set_find_dirs(pip) +if(PIP_DIR) + list(APPEND pip_LIBDIR "${PIP_DIR}/lib") + list(APPEND pip_INCDIR "${PIP_DIR}/include/pip") + list(APPEND pip_BINDIR "${PIP_DIR}/bin") +endif() -set(__libs "usb;crypt;console;fftw;compress;io_utils;cloud;lua") +set(__libs "usb;crypt;console;fftw;compress;io_utils;opencl;cloud;lua") if (BUILDING_pip) #set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua") diff --git a/cmake/PIPMacros.cmake b/cmake/PIPMacros.cmake index acd97207..32b6822b 100644 --- a/cmake/PIPMacros.cmake +++ b/cmake/PIPMacros.cmake @@ -1,11 +1,11 @@ #[[ - pip_code_model( file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ] [ABSOLUTE]) + pip_code_model( file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ]) Generate code model files for source files file0 [file1 ...] Options you can see by exec "pip_cmg -h" - If not ABSOLUTE source files will be prepended by CMAKE_CURRENT_SOURCE_DIR + Relative files pathes read from CMAKE_CURRENT_SOURCE_DIR You should add ${} to your target @@ -53,15 +53,13 @@ macro(pip_code_model RESULT) set(CCM_OUT ${CMAKE_CURRENT_BINARY_DIR}/ccm_${PROJECT_NAME}.cpp) set(${RESULT} ${${RESULT}} ${CCM_OUT}) set(CCM_FILES) - if (ABS) - foreach(csrc ${CCM_SRC}) + foreach(csrc ${CCM_SRC}) + if (IS_ABSOLUTE "${csrc}") list(APPEND CCM_FILES "${csrc}") - endforeach() - else() - foreach(csrc ${CCM_SRC}) + else() list(APPEND CCM_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${csrc}") - endforeach() - endif() + endif() + endforeach() #message(STATUS "CCM = ${RESULT}") if(NOT DEFINED PIP_DLL_DIR) set(PIP_DLL_DIR ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/doc/examples/pichunkstream.cpp b/doc/examples/pichunkstream.cpp index ec2048eb..dc6003ce 100644 --- a/doc/examples/pichunkstream.cpp +++ b/doc/examples/pichunkstream.cpp @@ -47,3 +47,21 @@ while (!cs2.atEnd()) { } piCout << i << str << f << s.i << s.f << s.s; //! [read] + +//! [write_new] +PIByteArray & operator <<(PIByteArray & s, const S & value) { + PIChunkStream cs; + cs.add(1, value.i).add(2, value.f).add(3, value.s); + s << cs.data(); + return s; +} +//! [write_new] +//! [read_new] +PIByteArray & operator >>(PIByteArray & s, S & value) { + PIChunkStream cs; + if (!cs.extract(s)) return s; + cs.readAll(); + cs.get(1, value.i).get(2, value.f).get(3, value.s); + return b; +} +//! [read_new] diff --git a/esp-pip/CMakeLists.txt b/esp-pip/CMakeLists.txt new file mode 100644 index 00000000..00e1f1fb --- /dev/null +++ b/esp-pip/CMakeLists.txt @@ -0,0 +1,49 @@ +set(COMPONENT_SRCS "main.cpp") +set(COMPONENT_ADD_INCLUDEDIRS "../libs/main") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/cloud") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/code") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/compress") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/console") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/containers") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/core") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/crypt") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/geo") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/io_devices") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/io_utils") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/math") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/resources") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/system") +list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/thread") +set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spi_flash libsodium) +register_component() +set(PIP_FREERTOS ON) +set(LIB OFF) +set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES}) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/platform_include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/libsodium/libsodium/src/libsodium/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/libsodium/port_include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/heap/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/esp_rom/include/esp32) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/driver/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/spi_flash/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/spiffs/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/soc/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/soc/esp32/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/freertos/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/lwip/lwip/src/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/lwip/port/esp32/include) +list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/vfs/include) +include_directories(${INCLUDE_DIRS}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip) +#message("IDF_COMPILE_DEFINITIONS = ${IDF_COMPILE_DEFINITIONS}") +#message("IDF_INCLUDE_DIRECTORIES = ${IDF_INCLUDE_DIRECTORIES}") +add_compile_options(${IDF_COMPILE_OPTIONS}) +add_compile_options(${IDF_CXX_COMPILE_OPTIONS}) +add_definitions(-DESP_PLATFORM) +add_definitions(-DGCC_NOT_5_2_0=0) +add_definitions(-DHAVE_CONFIG_H) +add_subdirectory(.. pip) +find_package(PIP REQUIRED) +target_link_libraries(${COMPONENT_TARGET} PIP::Crypt PIP::IOUtils PIP::Compress) +target_compile_definitions(${COMPONENT_TARGET} PRIVATE ESP_PLATFORM PIP_FREERTOS) diff --git a/esp32_component/esp-idf/components/pip/main.cpp b/esp-pip/main.cpp similarity index 100% rename from esp32_component/esp-idf/components/pip/main.cpp rename to esp-pip/main.cpp diff --git a/esp32_component/esp-idf/miniz.patch b/esp-pip/miniz.patch similarity index 100% rename from esp32_component/esp-idf/miniz.patch rename to esp-pip/miniz.patch diff --git a/esp32_component/esp-idf/components/pip/CMakeLists.txt b/esp32_component/esp-idf/components/pip/CMakeLists.txt deleted file mode 100644 index 751927f8..00000000 --- a/esp32_component/esp-idf/components/pip/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -set(COMPONENT_SRCS "main.cpp") -set(COMPONENT_ADD_INCLUDEDIRS "pip/lib/main") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/auxiliary") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/code") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/console") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/containers") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/core") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/crypt") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/geo") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_devices") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_utils") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/math") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/opencl") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/resources") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/system") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/thread") -list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/introspection") -set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs) -register_component() -set(PIP_FREERTOS ON) -set(LIB OFF) -set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES}) -list(APPEND INCLUDE_DIRS "../newlib/platform_include") -list(APPEND INCLUDE_DIRS "../newlib/include") -list(APPEND INCLUDE_DIRS "../libsodium/libsodium/src/libsodium/include") -list(APPEND INCLUDE_DIRS "../libsodium/port_include") -list(APPEND INCLUDE_DIRS "../heap/include") -list(APPEND INCLUDE_DIRS "../esp_rom/include/esp32") -list(APPEND INCLUDE_DIRS "../driver/include") -list(APPEND INCLUDE_DIRS "../spi_flash/include") -list(APPEND INCLUDE_DIRS "../spiffs/include") -list(APPEND INCLUDE_DIRS "../soc/include") -list(APPEND INCLUDE_DIRS "../soc/esp32/include") -list(APPEND INCLUDE_DIRS "../freertos/include") -list(APPEND INCLUDE_DIRS "../lwip/lwip/src/include") -list(APPEND INCLUDE_DIRS "../lwip/port/esp32/include") -list(APPEND INCLUDE_DIRS "../vfs/include") -include_directories(${INCLUDE_DIRS}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip) -#message("IDF_COMPILE_DEFINITIONS = ${IDF_COMPILE_DEFINITIONS}") -#message("IDF_INCLUDE_DIRECTORIES = ${IDF_INCLUDE_DIRECTORIES}") -add_compile_options(${IDF_COMPILE_OPTIONS}) -add_compile_options(${IDF_CXX_COMPILE_OPTIONS}) -add_definitions(-DESP_PLATFORM) -add_definitions(-DGCC_NOT_5_2_0=0) -add_definitions(-DHAVE_CONFIG_H) -add_subdirectory(pip) - -target_link_libraries(${COMPONENT_TARGET} pip pip_crypt pip_io_utils pip_compress) diff --git a/libs/compress/picompress.cpp b/libs/compress/picompress.cpp index 16c0dcaa..b9d73a51 100644 --- a/libs/compress/picompress.cpp +++ b/libs/compress/picompress.cpp @@ -20,7 +20,7 @@ #include "picompress.h" #ifdef PIP_COMPRESS # ifdef FREERTOS -# include "rom/miniz.h" +# include "esp32/rom/miniz.h" # define compress2 mz_compress2 # define Z_OK MZ_OK # define uncompress mz_uncompress diff --git a/libs/crypt/picrypt.cpp b/libs/crypt/picrypt.cpp index 742e6147..a129db7b 100644 --- a/libs/crypt/picrypt.cpp +++ b/libs/crypt/picrypt.cpp @@ -409,6 +409,8 @@ bool PICrypt::init() { if (inited) return true; //piCout << "[PICrypt]" << "init ..."; inited = sodium_init(); + if (!inited) + inited = sodium_init(); //piCout << "[PICrypt]" << "init" << inited; return inited; #else diff --git a/libs/main/code/picodeinfo.h b/libs/main/code/picodeinfo.h index 97506149..c95d58b0 100644 --- a/libs/main/code/picodeinfo.h +++ b/libs/main/code/picodeinfo.h @@ -174,6 +174,13 @@ inline const char * getMemberType(const char * class_name, const char * member_n PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name); + +template::value, int>::type = 0> +void serialize(PIByteArray & ret, const T & v) {ret << v;} + +template::value, int>::type = 0> +void serialize(PIByteArray & ret, const T & v) {} + } class PIP_EXPORT __PICodeInfoInitializer__ { diff --git a/libs/main/console/pikbdlistener.h b/libs/main/console/pikbdlistener.h index c1bf9906..185d21a3 100644 --- a/libs/main/console/pikbdlistener.h +++ b/libs/main/console/pikbdlistener.h @@ -252,5 +252,8 @@ inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) { inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;} +REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent) +REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent) +REGISTER_PIVARIANTSIMPLE(PIKbdListener::WheelEvent) #endif // PIKBDLISTENER_H diff --git a/libs/main/console/piscreentypes.h b/libs/main/console/piscreentypes.h index 05335ed1..0409cd0d 100644 --- a/libs/main/console/piscreentypes.h +++ b/libs/main/console/piscreentypes.h @@ -25,6 +25,7 @@ #include "pip_console_export.h" #include "pivariant.h" +#include "pivariantsimple.h" class PIScreenTile; @@ -140,8 +141,11 @@ namespace PIScreenTypes { inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;} - inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;} + +REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent) #endif // PISCREENTYPES_H diff --git a/libs/main/containers/picontainers.h b/libs/main/containers/picontainers.h index 1d989b65..708d7e7b 100644 --- a/libs/main/containers/picontainers.h +++ b/libs/main/containers/picontainers.h @@ -28,15 +28,6 @@ #include "picout.h" #include "piintrospection_containers.h" -#ifdef PIP_DEBUG -# ifdef NDEBUG -# undef NDEBUG -# endif -# include -#endif -#ifndef assert -# define assert(x) -#endif #ifdef MAC_OS # include #else diff --git a/libs/main/containers/pideque.h b/libs/main/containers/pideque.h index dd62b501..82d00b45 100644 --- a/libs/main/containers/pideque.h +++ b/libs/main/containers/pideque.h @@ -209,7 +209,22 @@ public: inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);} inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);} - inline PIDeque & clear() {resize(0); return *this;} + template::value + , int>::type = 0> + inline PIDeque & clear() { + resize(0); + return *this; + } + template::value + , int>::type = 0> + inline PIDeque & clear() { + PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size) + pid_size = 0; + return *this; + } + inline PIDeque & fill(const T & f = T()) { deleteT(pid_data + pid_start, pid_size); PIINTROSPECTION_CONTAINER_USED(T, pid_size) @@ -218,10 +233,20 @@ public: return *this; } inline PIDeque & assign(const T & f = T()) {return fill(f);} + template::value + , int>::type = 0> inline PIDeque & assign(size_t new_size, const T & f) { resize(new_size); return fill(f); } + template::value + , int>::type = 0> + inline PIDeque & assign(size_t new_size, const T & f) { + _resizeRaw(new_size); + return fill(f); + } inline PIDeque & resize(size_t new_size, const T & f = T()) { if (new_size < pid_size) { @@ -236,9 +261,18 @@ public: } return *this; } + + template::value + , int>::type = 0> inline PIDeque & _resizeRaw(size_t new_size) { - piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIDEQUE_SIMPLE_TYPE__ macro!"; - assert(0); + if (new_size > pid_size) { + PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size)); + } + if (new_size < pid_size) { + PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size)); + } + alloc(new_size, true); return *this; } @@ -437,11 +471,24 @@ private: ++t; return (1 << t); } + template::value + , int>::type = 0> inline void newT(T * dst, const T * src, size_t s) { PIINTROSPECTION_CONTAINER_USED(T, s) for (size_t i = 0; i < s; ++i) elementNew(dst + i, src[i]); } + template::value + , int>::type = 0> + inline void newT(T * dst, const T * src, size_t s) { + PIINTROSPECTION_CONTAINER_USED(T, s) + memcpy((void*)(dst), (const void*)(src), s * sizeof(T)); + } + template::value + , int>::type = 0> inline void deleteT(T * d, size_t sz) { PIINTROSPECTION_CONTAINER_UNUSED(T, sz) if ((uchar*)d != 0) { @@ -449,9 +496,36 @@ private: elementDelete(d[i]); } } + template::value + , int>::type = 0> + inline void deleteT(T * d, size_t sz) { + PIINTROSPECTION_CONTAINER_UNUSED(T, sz) + } + template::value + , int>::type = 0> inline void elementNew(T * to, const T & from) {new(to)T(from);} + template::value + , int>::type = 0> inline void elementNew(T * to, T && from) {new(to)T(std::move(from));} + template::value + , int>::type = 0> + inline void elementNew(T1 * to, const T & from) {(*to) = from;} + template::value + , int>::type = 0> + inline void elementNew(T * to, T && from) {(*to) = std::move(from);} + template::value + , int>::type = 0> inline void elementDelete(T & from) {from.~T();} + template::value + , int>::type = 0> + inline void elementDelete(T & from) {} inline void dealloc() { if ((uchar*)pid_data != 0) free((uchar*)pid_data); pid_data = 0; @@ -520,41 +594,6 @@ private: ssize_t pid_start; }; -#define __PIDEQUE_SIMPLE_TYPE__(T) \ - template<> inline void PIDeque::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \ - template<> inline void PIDeque::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ - template<> inline void PIDeque::elementNew(T * to, const T & from) {(*to) = from;} \ - template<> inline void PIDeque::elementNew(T * to, T && from) {(*to) = std::move(from);} \ - template<> inline void PIDeque::elementDelete(T &) {;} \ - template<> inline PIDeque & PIDeque::_resizeRaw(size_t new_size) { \ - if (new_size > pid_size) { \ - PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size)); \ - } \ - if (new_size < pid_size) { \ - PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size)); \ - } \ - alloc(new_size, true); \ - return *this; \ - } \ - template<> inline PIDeque & PIDeque::clear() {PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size); pid_size = 0; return *this;} \ - template<> inline PIDeque & PIDeque::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);} - - -__PIDEQUE_SIMPLE_TYPE__(bool) -__PIDEQUE_SIMPLE_TYPE__(char) -__PIDEQUE_SIMPLE_TYPE__(uchar) -__PIDEQUE_SIMPLE_TYPE__(short) -__PIDEQUE_SIMPLE_TYPE__(ushort) -__PIDEQUE_SIMPLE_TYPE__(int) -__PIDEQUE_SIMPLE_TYPE__(uint) -__PIDEQUE_SIMPLE_TYPE__(long) -__PIDEQUE_SIMPLE_TYPE__(ulong) -__PIDEQUE_SIMPLE_TYPE__(llong) -__PIDEQUE_SIMPLE_TYPE__(ullong) -__PIDEQUE_SIMPLE_TYPE__(float) -__PIDEQUE_SIMPLE_TYPE__(double) -__PIDEQUE_SIMPLE_TYPE__(ldouble) - #ifdef PIP_STD_IOSTREAM template diff --git a/libs/main/containers/pimap.h b/libs/main/containers/pimap.h index 38339dd7..ab4c6007 100644 --- a/libs/main/containers/pimap.h +++ b/libs/main/containers/pimap.h @@ -28,9 +28,6 @@ #include "pivector.h" #include "pideque.h" #include "pipair.h" -# define __PICONTAINERS_SIMPLE_TYPE__(T) \ -__PIDEQUE_SIMPLE_TYPE__(T)\ -__PIVECTOR_SIMPLE_TYPE__(T) template diff --git a/libs/main/containers/pivector.h b/libs/main/containers/pivector.h index 73f4d572..e7a3bd48 100644 --- a/libs/main/containers/pivector.h +++ b/libs/main/containers/pivector.h @@ -210,7 +210,22 @@ public: inline T * data(size_t index = 0) {return &(piv_data[index]);} inline const T * data(size_t index = 0) const {return &(piv_data[index]);} - inline PIVector & clear() {resize(0); return *this;} + template::value + , int>::type = 0> + inline PIVector & clear() { + resize(0); + return *this; + } + template::value + , int>::type = 0> + inline PIVector & clear() { + PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size) + piv_size = 0; + return *this; + } + inline PIVector & fill(const T & f = T()) { deleteT(piv_data, piv_size); PIINTROSPECTION_CONTAINER_USED(T, piv_size) @@ -219,10 +234,20 @@ public: return *this; } inline PIVector & assign(const T & f = T()) {return fill(f);} + template::value + , int>::type = 0> inline PIVector & assign(size_t new_size, const T & f) { resize(new_size); return fill(f); } + template::value + , int>::type = 0> + inline PIVector & assign(size_t new_size, const T & f) { + _resizeRaw(new_size); + return fill(f); + } inline PIVector & resize(size_t new_size, const T & f = T()) { if (new_size < piv_size) { @@ -239,9 +264,17 @@ public: } return *this; } + template::value + , int>::type = 0> inline PIVector & _resizeRaw(size_t new_size) { - piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!"; - assert(0); + if (new_size > piv_size) { + PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size)); + } + if (new_size < piv_size) { + PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size)); + } + alloc(new_size); return *this; } inline void _copyRaw(T * dst, const T * src, size_t size) { @@ -425,11 +458,24 @@ private: while (s_ >> t) ++t; return (1 << t); } + template::value + , int>::type = 0> inline void newT(T * dst, const T * src, size_t s) { PIINTROSPECTION_CONTAINER_USED(T, s) for (size_t i = 0; i < s; ++i) elementNew(dst + i, src[i]); } + template::value + , int>::type = 0> + inline void newT(T * dst, const T * src, size_t s) { + PIINTROSPECTION_CONTAINER_USED(T, s) + memcpy((void*)(dst), (const void*)(src), s * sizeof(T)); + } + template::value + , int>::type = 0> inline void deleteT(T * d, size_t sz) { PIINTROSPECTION_CONTAINER_UNUSED(T, sz) if ((uchar*)d != 0) { @@ -437,9 +483,36 @@ private: elementDelete(d[i]); } } + template::value + , int>::type = 0> + inline void deleteT(T * d, size_t sz) { + PIINTROSPECTION_CONTAINER_UNUSED(T, sz) + } + template::value + , int>::type = 0> inline void elementNew(T * to, const T & from) {new(to)T(from);} + template::value + , int>::type = 0> inline void elementNew(T * to, T && from) {new(to)T(std::move(from));} + template::value + , int>::type = 0> + inline void elementNew(T1 * to, const T & from) {(*to) = from;} + template::value + , int>::type = 0> + inline void elementNew(T * to, T && from) {(*to) = std::move(from);} + template::value + , int>::type = 0> inline void elementDelete(T & from) {from.~T();} + template::value + , int>::type = 0> + inline void elementDelete(T & from) {} inline void dealloc() { if ((uchar*)piv_data != 0) free((uchar*)piv_data); piv_data = 0; @@ -464,41 +537,6 @@ private: }; -#define __PIVECTOR_SIMPLE_TYPE__(T) \ - template<> inline void PIVector::newT(T * dst, const T * src, size_t s) {PIINTROSPECTION_CONTAINER_USED(T, s); memcpy((void*)(dst), (const void*)(src), s * sizeof(T));} \ - template<> inline void PIVector::deleteT(T *, size_t sz) {PIINTROSPECTION_CONTAINER_UNUSED(T, sz);} \ - template<> inline void PIVector::elementNew(T * to, const T & from) {(*to) = from;} \ - template<> inline void PIVector::elementNew(T * to, T && from) {(*to) = std::move(from);} \ - template<> inline void PIVector::elementDelete(T &) {;} \ - template<> inline PIVector & PIVector::_resizeRaw(size_t new_size) { \ - if (new_size > piv_size) { \ - PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size)); \ - } \ - if (new_size < piv_size) { \ - PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size)); \ - } \ - alloc(new_size); \ - return *this; \ - } \ - template<> inline PIVector & PIVector::clear() {PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size); piv_size = 0; return *this;} \ - template<> inline PIVector & PIVector::assign(size_t new_size, const T & f) {_resizeRaw(new_size); return fill(f);} - - -__PIVECTOR_SIMPLE_TYPE__(bool) -__PIVECTOR_SIMPLE_TYPE__(char) -__PIVECTOR_SIMPLE_TYPE__(uchar) -__PIVECTOR_SIMPLE_TYPE__(short) -__PIVECTOR_SIMPLE_TYPE__(ushort) -__PIVECTOR_SIMPLE_TYPE__(int) -__PIVECTOR_SIMPLE_TYPE__(uint) -__PIVECTOR_SIMPLE_TYPE__(long) -__PIVECTOR_SIMPLE_TYPE__(ulong) -__PIVECTOR_SIMPLE_TYPE__(llong) -__PIVECTOR_SIMPLE_TYPE__(ullong) -__PIVECTOR_SIMPLE_TYPE__(float) -__PIVECTOR_SIMPLE_TYPE__(double) -__PIVECTOR_SIMPLE_TYPE__(ldouble) - #ifdef PIP_STD_IOSTREAM template diff --git a/libs/main/containers/pivector2d.h b/libs/main/containers/pivector2d.h index f573439f..b55adbe5 100644 --- a/libs/main/containers/pivector2d.h +++ b/libs/main/containers/pivector2d.h @@ -160,6 +160,7 @@ public: inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];} inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];} + inline const T & at(size_t row, size_t col) const {return mat[row * cols_ + col];} inline Row operator[](size_t index) {return Row(this, index);} inline RowConst operator[](size_t index) const {return RowConst(this, index);} inline T * data(size_t index = 0) {return mat.data(index);} @@ -218,7 +219,7 @@ public: int cs = (cols - cols_); if (cs < 0) { for (size_t r=0; r & t) const { + if (cols_ != t.cols_ || rows_ != t.rows_) + return false; + return mat == t.mat; + } + inline bool operator !=(const PIVector2D & t) const {return !(*this == t);} + PIVector > toVectors() const { PIVector > ret; ret.reserve(rows_); @@ -251,9 +259,13 @@ public: piSwap(cols_, other.cols_); } + template::value + , int>::type = 0> inline PIVector2D & _resizeRaw(size_t r, size_t c) { - piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!"; - assert(0); + rows_ = r; + cols_ = c; + mat._resizeRaw(r*c); return *this; } @@ -287,22 +299,5 @@ inline PICout operator <<(PICout s, const PIVector2D & v) { return s; } -#define __PIVECTOR2D_SIMPLE_TYPE__(T) \ - template<> inline PIVector2D & PIVector2D::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;} - -__PIVECTOR2D_SIMPLE_TYPE__(bool) -__PIVECTOR2D_SIMPLE_TYPE__(char) -__PIVECTOR2D_SIMPLE_TYPE__(uchar) -__PIVECTOR2D_SIMPLE_TYPE__(short) -__PIVECTOR2D_SIMPLE_TYPE__(ushort) -__PIVECTOR2D_SIMPLE_TYPE__(int) -__PIVECTOR2D_SIMPLE_TYPE__(uint) -__PIVECTOR2D_SIMPLE_TYPE__(long) -__PIVECTOR2D_SIMPLE_TYPE__(ulong) -__PIVECTOR2D_SIMPLE_TYPE__(llong) -__PIVECTOR2D_SIMPLE_TYPE__(ullong) -__PIVECTOR2D_SIMPLE_TYPE__(float) -__PIVECTOR2D_SIMPLE_TYPE__(double) -__PIVECTOR2D_SIMPLE_TYPE__(ldouble) #endif // PIVECTOR2D_H diff --git a/libs/main/core/pibase.h b/libs/main/core/pibase.h index 73c79213..593a0dfa 100644 --- a/libs/main/core/pibase.h +++ b/libs/main/core/pibase.h @@ -155,6 +155,16 @@ extern char ** environ; #endif +#ifdef NDEBUG +# undef NDEBUG +#endif +#include +#ifndef assert +# define assert(x) +# define assertm(exp, msg) +#else +# define assertm(exp, msg) assert(((void)msg, exp)) +#endif #ifdef CC_GCC # undef DEPRECATED @@ -348,7 +358,7 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) { * * Example: * \snippet piincludes.cpp round */ -template inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} +template inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} /*! \brief Templated function return floor of float falue * \details Floor is the largest integer that is not greater than value \n @@ -358,7 +368,7 @@ template inline int piRound(const T & v) {return int(v >= T(0.) ? v * * Example: * \snippet piincludes.cpp floor */ -template inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} +template inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} /*! \brief Templated function return ceil of float falue * \details Ceil is the smallest integer that is not less than value \n @@ -368,7 +378,7 @@ template inline int piFloor(const T & v) {return v < T(0) ? int(v) - * * Example: * \snippet piincludes.cpp ceil */ -template inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} +template inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} /*! \brief Templated function return absolute of numeric falue * \details Absolute is the positive or equal 0 value \n @@ -382,7 +392,7 @@ template inline int piCeil(const T & v) {return v < T(0) ? int(v) : * * Example: * \snippet piincludes.cpp abs */ -template inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} +template inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);} /*! \brief Templated function return minimum of two values * \details There are some macros: @@ -395,7 +405,7 @@ template inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} * * Example: * \snippet piincludes.cpp min2 */ -template inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} +template inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} /*! \brief Templated function return minimum of tree values * \details There are some macros: @@ -408,7 +418,7 @@ template inline T piMin(const T & f, const T & s) {return ((f > s) ? * * Example: * \snippet piincludes.cpp min3 */ -template inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} +template inline constexpr T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} /*! \brief Templated function return maximum of two values * \details There are some macros: @@ -421,7 +431,7 @@ template inline T piMin(const T & f, const T & s, const T & t) {retu * * Example: * \snippet piincludes.cpp max2 */ -template inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} +template inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} /*! \brief Templated function return maximum of tree values * \details There are some macros: @@ -434,7 +444,7 @@ template inline T piMax(const T & f, const T & s) {return ((f < s) ? * * Example: * \snippet piincludes.cpp max3 */ -template inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} +template inline constexpr T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} /*! \brief Templated function return clamped value * \details Clamped is the not greater than "max" and not lesser than "min" value \n @@ -448,7 +458,7 @@ template inline T piMax(const T & f, const T & s, const T & t) {retu * * Example: * \snippet piincludes.cpp clamp */ -template inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} +template inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} /// Function inverse byte order in memory block inline void piLetobe(void * data, int size) { diff --git a/libs/main/core/pibytearray.cpp b/libs/main/core/pibytearray.cpp index f939ef0a..3c4a01a9 100644 --- a/libs/main/core/pibytearray.cpp +++ b/libs/main/core/pibytearray.cpp @@ -401,3 +401,14 @@ PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) { } return s; } + + +PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) { + s << int(v.size_s()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()); + memcpy(s.data(os), v.data(), v.size()); + } + return s; +} diff --git a/libs/main/core/pibytearray.h b/libs/main/core/pibytearray.h index d3d532b4..687a4d76 100644 --- a/libs/main/core/pibytearray.h +++ b/libs/main/core/pibytearray.h @@ -28,23 +28,6 @@ #include "pimap.h" #include "pivector2d.h" -__PICONTAINERS_SIMPLE_TYPE__(PIChar) - -#define __PIBYTEARRAY_SIMPLE_TYPE__(T) \ -template<> \ -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \ -template<> \ -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \ -template<> \ -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \ -template<> \ -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \ -template<> \ -inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {s << int(v.rows()) << int(v.cols()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \ -template<> \ -inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {assert(s.size_s() >= 8); int r, c; s >> r >> c; v._resizeRaw(r, c); int sz = r*c; if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} - - class PIString; class PIByteArray; @@ -136,9 +119,48 @@ public: static PIByteArray fromHex(PIString str); static PIByteArray fromBase64(const PIByteArray & base64); static PIByteArray fromBase64(const PIString & base64); + + + class StreamRef { + public: + StreamRef(PIByteArray & s): ba(s) {} + operator PIByteArray&() {return ba;} + private: + PIByteArray & ba; + }; + }; -inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();} +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) { + if (v0.size() == v1.size()) { + for (uint i = 0; i < v0.size(); ++i) + if (v0[i] != v1[i]) + return v0[i] < v1[i]; + return false; + } + return v0.size() < v1.size(); +} + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator ==(PIByteArray & f, PIByteArray & s) { + if (f.size_s() != s.size_s()) + return false; + for (int i = 0; i < f.size_s(); ++i) + if (f[i] != s[i]) + return false; + return true; +} + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator !=(PIByteArray & f, PIByteArray & s) { + if (f.size_s() != s.size_s()) + return true; + for (int i = 0; i < f.size_s(); ++i) + if (f[i] != s[i]) + return true; + return false; +} #ifdef PIP_STD_IOSTREAM //! \relatesalso PIByteArray \brief Output to std::ostream operator @@ -148,114 +170,308 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba); //! \relatesalso PIByteArray \brief Output to PICout operator PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba); -#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v)); + + + +// store operators for basic types //! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, bool v) {s.push_back(v); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;} + //! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, char v) {s.push_back(v); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;} + //! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ldouble & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -template inline PIByteArray & operator <<(PIByteArray & s, const PIFlags & v) {PBA_OPERATOR_TO return s;} +inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;} + +//! \relatesalso PIByteArray \brief Store operator for any trivial copyable type +template::value, int>::type = 0> +inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) { + int os = s.size_s(); + s.enlarge(sizeof(v)); + memcpy(s.data(os), &v, sizeof(v)); + return s; +} + //! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;} +PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v); + //! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) { + int os = s.size_s(); + if (v.s > 0) { + s.enlarge(v.s); + memcpy(s.data(os), v.d, v.s); + } + return s; +} -#undef PBA_OPERATOR_TO -#define PBA_OPERATOR_FROM memcpy((void*)(&v), s.data(), sizeof(v)); s.remove(0, sizeof(v)); +//! \relatesalso PIByteArray \brief Store operator for PIVector of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ldouble & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -template inline PIByteArray & operator >>(PIByteArray & s, PIFlags & v) {PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy((void*)(v.d), s.data(), v.s); s.remove(0, v.s); return s;} - -#undef PBA_OPERATOR_FROM - -template inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v); -//! \relatesalso PIByteArray \brief Store operator -template inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v); -//! \relatesalso PIByteArray \brief Store operator -template inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v); - //! \relatesalso PIByteArray \brief Store operator -template inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v); -//! Write operator to \c PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << v.ch; return s;} - -//! \relatesalso PIByteArray \brief Restore operator -template inline PIByteArray & operator >>(PIByteArray & s, PIPair & v); -//! \relatesalso PIByteArray \brief Restore operator -template inline PIByteArray & operator >>(PIByteArray & s, PIVector & v); -//! \relatesalso PIByteArray \brief Restore operator -template inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v); - //! \relatesalso PIByteArray \brief Restore operator -template inline PIByteArray & operator >>(PIByteArray & s, PIMap & v); -//! Read operator from \c PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {s >> v.ch; return s;} +//! \relatesalso PIByteArray \brief Store operator for PIDeque of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} +//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()); + int os = s.size_s(); + if (v.size_s() > 0) { + s.enlarge(v.size_s()*sizeof(T)); + memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); + return s; +} //! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;} + +//! \relatesalso PIPair \brief Store operator template inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} + + + + +// restore operators for basic types + + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} + +//! \relatesalso PIByteArray \brief Restore operator for any trivial copyable type +template::value, int>::type = 0> +inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) { + assert(s.size() >= sizeof(v)); + memcpy((void*)(&v), s.data(), sizeof(v)); + s.remove(0, sizeof(v)); + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); + +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { + assert(s.size_s() >= v.s); + if (v.s > 0) { + memcpy((void*)(v.d), s.data(), v.s); + s.remove(0, v.s); + } + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v._resizeRaw(sz); + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v._resizeRaw(sz); + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any trivial copyable type +template::value, int>::type = 0, + typename std::enable_if< std::is_same() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + assert(s.size_s() >= 8); + int r, c; s >> r >> c; + v._resizeRaw(r, c); + int sz = r*c; + if (sz > 0) { + memcpy(v.data(), s.data(), sz*sizeof(T)); + s.remove(0, sz*sizeof(T)); + } + return s; +} +template::value, int>::type = 0, + typename std::enable_if() << std::declval()), PIByteArray::StreamRef>::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + assert(s.size_s() >= 8); + int r,c; + PIVector tmp; + s >> r >> c >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;} + +//! \relatesalso PIPair \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} + + + + +// store operators for complex types + + +//! \relatesalso PIByteArray \brief Store operator for PIVector of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIDeque of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) { + s << int(v.size_s()); + for (uint i = 0; i < v.size(); ++i) s << v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Store operator for PIVector2D of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) { + s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); + return s; +} + + + + +// restore operators for complex types + + +//! \relatesalso PIByteArray \brief Restore operator for PIVector of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIDeque of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) { + assert(s.size_s() >= 4); + int sz; s >> sz; + v.resize(sz); + for (int i = 0; i < sz; ++i) s >> v[i]; + return s; +} + +//! \relatesalso PIByteArray \brief Restore operator for PIVector2D of any compound type +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) { + assert(s.size_s() >= 8); + int r,c; + PIVector tmp; + s >> r >> c >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} + + + + +// other types + + template inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) { s << int(v.pim_index.size_s()); @@ -264,18 +480,8 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIMap & v) { s << v.pim_content; return s; } -template -inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D & v) {s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;} -template -inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} -template -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} -template -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} template inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) { assert(s.size_s() >= 4); @@ -292,36 +498,20 @@ inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) { } return s; } -template -inline PIByteArray & operator >>(PIByteArray & s, PIVector2D & v) {assert(s.size_s() >= 8); int r,c; PIVector tmp; s >> r >> c >> tmp; v = PIVector2D(r, c, tmp); return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const T & ) {piCout << "[PIByteArray] Warning: using undeclared operator < -inline PIByteArray & operator >>(PIByteArray & s, T & ) {piCout << "[PIByteArray] Warning: using undeclared operator >>!"; return s;} +template::value, int>::type = 0> +inline PIByteArray & operator <<(PIByteArray & s, const T & ) { + static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator << for complex type!"); + return s; +} -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;} -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;} - -__PIBYTEARRAY_SIMPLE_TYPE__(bool) -__PIBYTEARRAY_SIMPLE_TYPE__(char) -__PIBYTEARRAY_SIMPLE_TYPE__(short) -__PIBYTEARRAY_SIMPLE_TYPE__(ushort) -__PIBYTEARRAY_SIMPLE_TYPE__(int) -__PIBYTEARRAY_SIMPLE_TYPE__(uint) -__PIBYTEARRAY_SIMPLE_TYPE__(long) -__PIBYTEARRAY_SIMPLE_TYPE__(ulong) -__PIBYTEARRAY_SIMPLE_TYPE__(llong) -__PIBYTEARRAY_SIMPLE_TYPE__(ullong) -__PIBYTEARRAY_SIMPLE_TYPE__(float) -__PIBYTEARRAY_SIMPLE_TYPE__(double) -__PIBYTEARRAY_SIMPLE_TYPE__(ldouble) -__PIBYTEARRAY_SIMPLE_TYPE__(PIChar) - +template::value, int>::type = 0> +inline PIByteArray & operator >>(PIByteArray & s, T & ) { + static_assert(std::is_trivially_copyable::value, "[PIByteArray] Error: using undeclared operator >> for complex type!"); + return s; +} template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();} template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);} diff --git a/libs/main/core/pichar.h b/libs/main/core/pichar.h index 5b18db41..a2b5dad2 100644 --- a/libs/main/core/pichar.h +++ b/libs/main/core/pichar.h @@ -32,9 +32,7 @@ extern PIP_EXPORT char * __utf8name__; class PIP_EXPORT PIChar { friend class PIString; - friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v); - friend PIByteArray & operator >>(PIByteArray & s, PIChar & v); - friend PICout operator <<(PICout s, const PIChar & v); + friend PICout PIP_EXPORT operator <<(PICout s, const PIChar & v); public: //! Contructs ascii symbol PIChar(const char c) {ch = c; ch &= 0xFF;} @@ -135,7 +133,7 @@ private: }; //! Output operator to \a PICout -PICout operator <<(PICout s, const PIChar & v); +PICout PIP_EXPORT operator <<(PICout s, const PIChar & v); //! Compare operator inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);} diff --git a/libs/main/core/pichunkstream.cpp b/libs/main/core/pichunkstream.cpp index c80455d3..b5525aa3 100644 --- a/libs/main/core/pichunkstream.cpp +++ b/libs/main/core/pichunkstream.cpp @@ -41,13 +41,22 @@ * but you should definitely know type of this value. You can read from byte array * while \a atEnd() if false. * - * \section PIChunkStream_ex0 Example - * Prepare your structs to work with %PIChunkStream + * \section PIChunkStream_sec2 Examples + * + * Using simple operator and cascade serialization: + * + * Prepare your structs to work with %PIChunkStream: * \snippet pichunkstream.cpp struct - * Writing to %PIChunkStream + * Old-style writing to %PIChunkStream: * \snippet pichunkstream.cpp write - * Reading from %PIChunkStream + * Fastest reading from %PIChunkStream: * \snippet pichunkstream.cpp read + * + * And next code show how to serialize your struct with %PIChunkStream: + * \snippet pichunkstream.cpp write_new + * + * ... and deserialize: + * \snippet pichunkstream.cpp read_new */ @@ -115,7 +124,18 @@ void PIChunkStream::readAll() { PIChunkStream::~PIChunkStream() { +} + +bool PIChunkStream::extract(PIByteArray & data, bool read_all) { + if (data.size_s() < 4) return false; + data >> tmp_data; + if (tmp_data.size_s() < 4) return false; + data_ = &tmp_data; + _init(); + if (read_all) + readAll(); + return true; } diff --git a/libs/main/core/pichunkstream.h b/libs/main/core/pichunkstream.h index 89dad97d..256c620d 100644 --- a/libs/main/core/pichunkstream.h +++ b/libs/main/core/pichunkstream.h @@ -67,6 +67,11 @@ public: //! Add data to this chunk strean with ID "id" and value "data" template PIChunkStream & add(int id, const T & data) {*this << ChunkConst(id, data); return *this;} + //! Extract %PIByteArray from "data" and set it current stream. + //! If "read_all" then call \a readAll() after extract. + //! Returns if has data to read. + bool extract(PIByteArray & data, bool read_all = false); + void setSource(const PIByteArray & data); void setSource(PIByteArray * data); diff --git a/libs/main/core/piflags.h b/libs/main/core/piflags.h index d7584dd5..6d824826 100644 --- a/libs/main/core/piflags.h +++ b/libs/main/core/piflags.h @@ -38,8 +38,6 @@ public: PIFlags(): flags(0) {;} //! Constructor with flags = Enum "e" PIFlags(Enum e): flags(e) {;} - //! Constructor with flags = PIFlags "f" - PIFlags(const PIFlags & f): flags(f.flags) {;} //! Constructor with flags = int "i" PIFlags(const int i): flags(i) {;} //! Set flags "f" to value "on" @@ -49,8 +47,6 @@ public: //! Set flag "i" to value "on" PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;} //! copy operator - void operator =(const PIFlags & f) {flags = f.flags;} - //! copy operator void operator =(const Enum & e) {flags = e;} //! copy operator void operator =(const int & i) {flags = i;} diff --git a/libs/main/core/piincludes.cpp b/libs/main/core/piincludes.cpp index 6b480a21..aa583426 100644 --- a/libs/main/core/piincludes.cpp +++ b/libs/main/core/piincludes.cpp @@ -79,6 +79,22 @@ PIString PIPVersion() { return ret; } + +void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) { + qsort(base, num, size, compar); +} + + +void randomize() { + srand(PISystemTime::current(true).nanoseconds); +} + + +int randomi() { + return rand(); +} + + /*! \class PICout * \brief Class for formatted output similar std::cout * @@ -131,6 +147,9 @@ PIString PIPVersion() { * * packets extractor (\a PIPacketExtractor) * * binary log (\a PIBinaryLog) * * complex I/O point (\a PIConnection) + * * Run-time libraries + * * abstract (\a PILibrary) + * * plugin (\a PIPluginLoader) * * connection quality diagnotic (\a PIDiagnostics) * * command-line arguments parser (\a PICLI) * * math evaluator (\a PIEvaluator) @@ -247,19 +266,3 @@ int main(int argc, char * argv[]) { /*! \page using_advanced Advanced using * Sorry, creativity crysis xD */ - - -void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) { - qsort(base, num, size, compar); -} - - -void randomize() { - srand(PISystemTime::current(true).nanoseconds); -} - - -int randomi() { - return rand(); -} - diff --git a/libs/main/core/piincludes.h b/libs/main/core/piincludes.h index ba158476..f09366e9 100644 --- a/libs/main/core/piincludes.h +++ b/libs/main/core/piincludes.h @@ -28,6 +28,7 @@ #endif #include + class PIMutex; class PIMutexLocker; class PIObject; diff --git a/libs/main/core/piinit.cpp b/libs/main/core/piinit.cpp index 90eacfa1..38e64be8 100644 --- a/libs/main/core/piinit.cpp +++ b/libs/main/core/piinit.cpp @@ -282,7 +282,7 @@ PIInit::PIInit() { PIInit::~PIInit() { - if (file_charset) delete file_charset; + if (file_charset) delete[] file_charset; file_charset = 0; PIResourcesStorage::instance()->clear(); #ifdef WINDOWS diff --git a/libs/main/core/piobject.cpp b/libs/main/core/piobject.cpp index fa04cd78..06fe88d9 100644 --- a/libs/main/core/piobject.cpp +++ b/libs/main/core/piobject.cpp @@ -105,7 +105,7 @@ PIMap PIObject::properties() const { -bool PIObject::execute(const PIString & method, const PIVector & vl) { +bool PIObject::execute(const PIString & method, const PIVector & vl) { if (method.isEmpty()) return false; if (!isPIObject()) { piCout << "Error: \"execute(" << method << ")\":" << (void*)this << "is not PIObject!"; @@ -121,7 +121,7 @@ bool PIObject::execute(const PIString & method, const PIVector & vl) } -bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector & vl) { +bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector & vl) { if (!isPIObject()) { piCout << "Error: \"executeQueued(" << method << ")\": this(" << (void*)this << ") is not PIObject!"; return false; @@ -535,14 +535,14 @@ PIMutex & PIObject::mutexObjects() { } -void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector & vl) { +void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector & vl) { args = piMini(args, vl.size_s()); switch (args) { case 0: ((void(*)(void *))slot)(obj); break; - case 1: ((void(*)(void * , const PIVariant & ))slot)(obj, vl[0]); break; - case 2: ((void(*)(void * , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1]); break; - case 3: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2]); break; - case 4: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break; + case 1: ((void(*)(void * , const PIVariantSimple & ))slot)(obj, vl[0]); break; + case 2: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1]); break; + case 3: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2]); break; + case 4: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break; default: break; } } diff --git a/libs/main/core/piobject.h b/libs/main/core/piobject.h index abfb5436..939ebb0e 100644 --- a/libs/main/core/piobject.h +++ b/libs/main/core/piobject.h @@ -1,7 +1,7 @@ /*! \file piobject.h * \brief Base object * - * This file declare PIObject class and associated macros + * This file declare PIObject class */ /* PIP - Platform Independent Primitives @@ -27,6 +27,7 @@ #include "piinit.h" #include "pivariant.h" +#include "pivariantsimple.h" #include "pimutex.h" #include "piset.h" #include "piqueue.h" @@ -101,33 +102,33 @@ public: void setThreadSafe(bool yes) {thread_safe_ = yes;} bool isThreadSafe() const {return thread_safe_;} - bool execute(const PIString & method, const PIVector & vl); - bool execute(const PIString & method) {return execute(method, PIVector());} - bool execute(const PIString & method, const PIVariant & v0) {return execute(method, PIVector() << v0);} - bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(method, PIVector() << v0 << v1);} - bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(method, PIVector() << v0 << v1 << v2);} - bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(method, PIVector() << v0 << v1 << v2 << v3);} + bool execute(const PIString & method, const PIVector & vl); + bool execute(const PIString & method) {return execute(method, PIVector());} + bool execute(const PIString & method, const PIVariantSimple & v0) {return execute(method, PIVector() << v0);} + bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(method, PIVector() << v0 << v1);} + bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(method, PIVector() << v0 << v1 << v2);} + bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(method, PIVector() << v0 << v1 << v2 << v3);} - bool executeQueued(PIObject * performer, const PIString & method, const PIVector & vl); - bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector());} - bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(performer, method, PIVector() << v0);} - bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(performer, method, PIVector() << v0 << v1);} - bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(performer, method, PIVector() << v0 << v1 << v2);} - bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(performer, method, PIVector() << v0 << v1 << v2 << v3);} + bool executeQueued(PIObject * performer, const PIString & method, const PIVector & vl); + bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector());} + bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(performer, method, PIVector() << v0);} + bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(performer, method, PIVector() << v0 << v1);} + bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(performer, method, PIVector() << v0 << v1 << v2);} + bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(performer, method, PIVector() << v0 << v1 << v2 << v3);} - static bool execute(PIObject * o, const PIString & method, const PIVector & vl) {return o->execute(method, vl);} - static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector());} - static bool execute(PIObject * o, const PIString & method, const PIVariant & v0) {return execute(o, method, PIVector() << v0);} - static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(o, method, PIVector() << v0 << v1);} - static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(o, method, PIVector() << v0 << v1 << v2);} - static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(o, method, PIVector() << v0 << v1 << v2 << v3);} + static bool execute(PIObject * o, const PIString & method, const PIVector & vl) {return o->execute(method, vl);} + static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector());} + static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {return execute(o, method, PIVector() << v0);} + static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(o, method, PIVector() << v0 << v1);} + static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(o, method, PIVector() << v0 << v1 << v2);} + static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(o, method, PIVector() << v0 << v1 << v2 << v3);} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector & vl) {return o->executeQueued(performer, method, vl);} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector());} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(o, performer, method, PIVector() << v0);} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(o, performer, method, PIVector() << v0 << v1);} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(o, performer, method, PIVector() << v0 << v1 << v2);} - static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(o, performer, method, PIVector() << v0 << v1 << v2 << v3);} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector & vl) {return o->executeQueued(performer, method, vl);} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector());} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(o, performer, method, PIVector() << v0);} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(o, performer, method, PIVector() << v0 << v1);} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(o, performer, method, PIVector() << v0 << v1 << v2);} + static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(o, performer, method, PIVector() << v0 << v1 << v2 << v3);} void dump(const PIString & line_prefix = PIString()) const; @@ -201,8 +202,8 @@ public: (*((std::function*)i.functor))(v0); } else { if (i.performer) { - PIVector vl; - if (i.args_count > 0) vl << PIVariant::fromValue(v0); + PIVector vl; + if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0); i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl)); } else { bool ts = sender->thread_safe_; @@ -232,9 +233,9 @@ public: (*((std::function*)i.functor))(v0, v1); } else { if (i.performer) { - PIVector vl; - if (i.args_count > 0) vl << PIVariant::fromValue(v0); - if (i.args_count > 1) vl << PIVariant::fromValue(v1); + PIVector vl; + if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0); + if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1); i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl)); } else { bool ts = sender->thread_safe_; @@ -267,10 +268,10 @@ public: (*((std::function*)i.functor))(v0, v1, v2); } else { if (i.performer) { - PIVector vl; - if (i.args_count > 0) vl << PIVariant::fromValue(v0); - if (i.args_count > 1) vl << PIVariant::fromValue(v1); - if (i.args_count > 2) vl << PIVariant::fromValue(v2); + PIVector vl; + if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0); + if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1); + if (i.args_count > 2) vl << PIVariantSimple::fromValue(v2); i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl)); } else { bool ts = sender->thread_safe_; @@ -304,11 +305,11 @@ public: (*((std::function*)i.functor))(v0, v1, v2, v3); } else { if (i.performer) { - PIVector vl; - if (i.args_count > 0) vl << PIVariant::fromValue(v0); - if (i.args_count > 1) vl << PIVariant::fromValue(v1); - if (i.args_count > 2) vl << PIVariant::fromValue(v2); - if (i.args_count > 3) vl << PIVariant::fromValue(v3); + PIVector vl; + if (i.args_count > 0) vl << PIVariantSimple::fromValue(v0); + if (i.args_count > 1) vl << PIVariantSimple::fromValue(v1); + if (i.args_count > 2) vl << PIVariantSimple::fromValue(v2); + if (i.args_count > 3) vl << PIVariantSimple::fromValue(v3); i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl)); } else { bool ts = sender->thread_safe_; @@ -452,7 +453,7 @@ private: }; struct __QueuedEvent { - __QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector & v = PIVector()) { + __QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector & v = PIVector()) { slot = sl; dest = d; dest_o = d_o; @@ -463,7 +464,7 @@ private: void * dest; PIObject * dest_o; PIObject * src; - PIVector values; + PIVector values; }; class Deleter { @@ -496,7 +497,7 @@ private: static PIVector & objects(); static PIMutex & mutexObjects(); - static void callAddrV(void * slot, void * obj, int args, const PIVector & vl); + static void callAddrV(void * slot, void * obj, int args, const PIVector & vl); PIVector<__Connection> connections; diff --git a/libs/main/core/piobject_macros.h b/libs/main/core/piobject_macros.h index c4c5da43..1f0d27a5 100644 --- a/libs/main/core/piobject_macros.h +++ b/libs/main/core/piobject_macros.h @@ -1,7 +1,7 @@ -/*! \file piobject.h +/*! \file piobject_macros.h * \brief Base object * - * This file declare PIObject class and associated macros + * This file declare macros for PIObject */ /* PIP - Platform Independent Primitives @@ -25,8 +25,6 @@ #ifndef PIOBJECT_MACROS_H #define PIOBJECT_MACROS_H -//#include "piobject_macros.h" - #ifdef DOXYGEN @@ -269,7 +267,7 @@ PIMutexLocker ml(__meta_mutex()); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \ - void * fpV = (void*)(ret(*)(void*, const PIVariant &))__stat_eh_v_##name##__; \ + void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \ if (eh.eh_set[fp]) return; \ eh.eh_set << fp; \ __MetaFunc & f(eh.eh_func[fp]); \ @@ -287,7 +285,7 @@ PIMutexLocker ml(__meta_mutex()); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \ - void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \ + void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ if (eh.eh_set[fp]) return; \ eh.eh_set << fp; \ __MetaFunc & f(eh.eh_func[fp]); \ @@ -305,7 +303,7 @@ PIMutexLocker ml(__meta_mutex()); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \ - void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \ + void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ if (eh.eh_set[fp]) return; \ eh.eh_set << fp; \ __MetaFunc & f(eh.eh_func[fp]); \ @@ -323,7 +321,7 @@ PIMutexLocker ml(__meta_mutex()); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \ - void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \ + void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ if (eh.eh_set[fp]) return; \ eh.eh_set << fp; \ __MetaFunc & f(eh.eh_func[fp]); \ @@ -345,7 +343,7 @@ #define EVENT_HANDLER1(ret, name, a0, n0) \ EH_INIT1(ret, name, a0, n0) \ static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) { \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \ __PTYPE(a0) tv0 = __VVALUE(a0, v0); \ return ((__PIObject__*)__o__)->name(tv0);} \ ret name(a0 n0) @@ -353,7 +351,7 @@ #define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \ EH_INIT2(ret, name, a0, n0, a1, n1) \ static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) { \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \ __PTYPE(a0) tv0 = __VVALUE(a0, v0); \ __PTYPE(a1) tv1 = __VVALUE(a1, v1); \ return ((__PIObject__*)__o__)->name(tv0, tv1);} \ @@ -362,7 +360,7 @@ #define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \ EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) { \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \ __PTYPE(a0) tv0 = __VVALUE(a0, v0); \ __PTYPE(a1) tv1 = __VVALUE(a1, v1); \ __PTYPE(a2) tv2 = __VVALUE(a2, v2); \ @@ -372,7 +370,7 @@ #define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) { \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \ __PTYPE(a0) tv0 = __VVALUE(a0, v0); \ __PTYPE(a1) tv1 = __VVALUE(a1, v1); \ __PTYPE(a2) tv2 = __VVALUE(a2, v2); \ @@ -385,43 +383,63 @@ #define EVENT_VHANDLER0(ret, name) \ EH_INIT0(ret, name) \ - static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \ + static ret __stat_eh_##name##__(void * __o__) { \ + return ((__PIObject__*)__o__)->name();} \ virtual ret name() #define EVENT_VHANDLER1(ret, name, a0, n0) \ EH_INIT1(ret, name, a0, n0) \ - static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \ + static ret __stat_eh_##name##__(void * __o__, a0 n0) { \ + return ((__PIObject__*)__o__)->name(n0);} \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \ + return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \ virtual ret name(a0 n0) #define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \ EH_INIT2(ret, name, a0, n0, a1, n1) \ - static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) { \ + return ((__PIObject__*)__o__)->name(n0, n1);} \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \ + return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \ virtual ret name(a0 n0, a1 n1) #define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \ EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ - static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \ + return ((__PIObject__*)__o__)->name(n0, n1, n2);} \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \ + return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \ virtual ret name(a0 n0, a1 n1, a2 n2) #define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ - static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \ - static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \ + return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \ + static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \ + return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \ virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3) #define EVENT_VHANDLER EVENT_VHANDLER0 -#define EVENT0(name) EVENT_HANDLER0(void, name) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);} -#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);} -#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);} -#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);} -#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);} +#define EVENT0(name) EVENT_HANDLER0(void, name) { \ + static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);} + +#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) { \ + static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);} + +#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) { \ + static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);} + +#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) { \ + static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);} + +#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) { \ + static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);} + #define EVENT EVENT0 + #define RAISE_EVENT0(src, event) (src)->event(); #define RAISE_EVENT1(src, event, v0) (src)->event(v0); #define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1); @@ -429,35 +447,81 @@ #define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3); #define RAISE_EVENT RAISE_EVENT0 -#define CONNECTU(src, event, dest, handler) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION); -#define CONNECTU_QUEUED(src, event, dest, handler, performer) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer); -#define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION); -#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION); -#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION); -#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION); -#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION); -#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION); +#define CONNECTU(src, event, dest, handler) \ + PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION); + +#define CONNECTU_QUEUED(src, event, dest, handler, performer) \ + PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer); + +#define CONNECTL(src, event, functor) \ + PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION); + + +#define CONNECT0(ret, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), \ + (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION); + +#define CONNECT1(ret, a0, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), \ + (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION); + +#define CONNECT2(ret, a0, a1, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), \ + (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION); + +#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \ + (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION); + +#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \ + (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION); + #define CONNECT CONNECT0 -#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION); -#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION); -#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION); -#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION); -#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION); + +#define WEAK_CONNECT0(ret, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION); + +#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION); + +#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION); + +#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION); + +#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \ + PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION); + #define WEAK_CONNECT WEAK_CONNECT0 -#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__)); + +#define DISCONNECT0(ret, src, event, dest, handler) \ + PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__)); + +#define DISCONNECT1(ret, a0, src, event, dest, handler) \ + PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__)); + +#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) \ + PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__)); + +#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) \ + PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__)); + +#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \ + PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__)); + #define DISCONNECT DISCONNECT0 + #define HANDLER(handler) __stat_eh_##handler##__ #define __PIOBJECT_SIGNATURE__ 0xabcdbadc + #endif diff --git a/libs/main/core/pipropertystorage.cpp b/libs/main/core/pipropertystorage.cpp index 679d374b..246ba6c9 100644 --- a/libs/main/core/pipropertystorage.cpp +++ b/libs/main/core/pipropertystorage.cpp @@ -28,41 +28,54 @@ bool PIPropertyStorage::isPropertyExists(const PIString & _name) const { } -void PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) { +bool PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) { for (uint i = 0; i < props.size(); ++i) if (props[i].name == p.name) { props[i] = p; - return; + return false; } props << p; + return true; } -void PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) { +bool PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) { for (uint i = 0; i < props.size(); ++i) if (props[i].name == p.name) { props[i] = std::move(p); - return; + return false; } props << std::move(p); + return true; } -void PIPropertyStorage::removeProperty(const PIString & _name) { - for (uint i = 0; i < props.size(); ++i) +bool PIPropertyStorage::addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment, int _flags) { + return addProperty(Property(_name, _comment, _def_value, _flags)); +} + + +bool PIPropertyStorage::removeProperty(const PIString & _name) { + for (uint i = 0; i < props.size(); ++i) { if (props[i].name == _name) { props.remove(i); - return; + return true; } + } + return false; } -void PIPropertyStorage::removePropertiesByFlag(int flag) { - for (int i = 0; i < props.size_s(); ++i) +int PIPropertyStorage::removePropertiesByFlag(int flag) { + int ret = 0; + for (int i = 0; i < props.size_s(); ++i) { if ((props[i].flags & flag) == flag) { props.remove(i); --i; + ret++; } + } + return ret; } @@ -99,30 +112,36 @@ PIVariant PIPropertyStorage::propertyValueByName(const PIString & name) const { } -void PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) { - for (uint i = 0; i < props.size(); ++i) +bool PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) { + for (uint i = 0; i < props.size(); ++i) { if (props[i].name == name) { props[i].value = value; - return; + return true; } + } + return false; } -void PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) { - for (uint i = 0; i < props.size(); ++i) +bool PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) { + for (uint i = 0; i < props.size(); ++i) { if (props[i].name == name) { props[i].comment = comment; - return; + return true; } + } + return false; } -void PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) { - for (uint i = 0; i < props.size(); ++i) +bool PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) { + for (uint i = 0; i < props.size(); ++i) { if (props[i].name == name) { props[i].flags = flags; - return; + return true; } + } + return false; } diff --git a/libs/main/core/pipropertystorage.h b/libs/main/core/pipropertystorage.h index c338b968..31f01cd3 100644 --- a/libs/main/core/pipropertystorage.h +++ b/libs/main/core/pipropertystorage.h @@ -110,24 +110,49 @@ public: PIVector & properties() {return props;} const PIVector & properties() const {return props;} const PIPropertyStorage & propertyStorage() const {return *this;} + + /** + * @brief Check if property with \a name exists + * @return "true" if property exists + */ bool isPropertyExists(const PIString & _name) const; + + /** + * @brief Remove all properties + */ void clearProperties() {props.clear();} /** * @brief Add property if name isn't present in storage, otherwrise update existing property with same name. - * + * @return "true" if new property added, else if update existing property return "false" * @param p to copy in storage */ - void addProperty(const Property & p); - void addProperty(Property && p); + bool addProperty(const Property & p); + bool addProperty(Property && p); /** * @brief First of all construct Property with method params. After then add property if name isn't present * in storage, otherwrise update existing property with same name. + * @return "true" if new property added, else if update existing property return "false" + */ + bool addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0); + + /** + * @brief Remove property with \a name + * @return "true" if property exists and removed + */ + bool removeProperty(const PIString & _name); + + /** + * @brief Remove properties wich has \a flag set + * @return removed properties count + */ + int removePropertiesByFlag(int flag); + + /** + * @brief Merge other \a properties_ into this + * @param flag_ignore - properties wich has this flag set will be ignored in merge */ - void addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0) {addProperty(Property(_name, _comment, _def_value, _flags));} - void removeProperty(const PIString & _name); - void removePropertiesByFlag(int flag); void updateProperties(const PIVector & properties_, int flag_ignore = 0); /** @@ -151,24 +176,27 @@ public: * * @param name of property to set value * @param value to set + * @return "true" if property exists and updated */ - void setPropertyValue(const PIString & name, const PIVariant & value); + bool setPropertyValue(const PIString & name, const PIVariant & value); /** * @brief Set comment of property with specific name if name is present in storage. * * @param name of property to set comment * @param comment to set + * @return "true" if property exists and updated */ - void setPropertyComment(const PIString & name, const PIString & comment); + bool setPropertyComment(const PIString & name, const PIString & comment); - /** - * @brief Set flags of property with specific name if name is present in storage. - * - * @param name of property to set flags - * @param flags to set - */ - void setPropertyFlags(const PIString & name, int flags); + /** + * @brief Set flags of property with specific name if name is present in storage. + * + * @param name of property to set flags + * @param flags to set + * @return "true" if property exists and updated + */ + bool setPropertyFlags(const PIString & name, int flags); PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;} PIPropertyStorage & operator <<(const PIVector & p) {props << p; return *this;} diff --git a/libs/main/core/pistring.cpp b/libs/main/core/pistring.cpp index c5e5c3e5..578d949a 100644 --- a/libs/main/core/pistring.cpp +++ b/libs/main/core/pistring.cpp @@ -333,11 +333,14 @@ PIString PIString::fromAscii(const char * s) { ret.push_back(PIChar(s[l])); ++l; } - /*while (s[l] != '\0') ++l; + return ret; +} + + +PIString PIString::fromAscii(const char * s, int len) { PIString ret; - ret.resize(l); - for (int i = 0; i < l; ++i) - ret[i] = s[i];*/ + for (int l = 0; l < len; ++l) + ret.push_back(PIChar(s[l])); return ret; } diff --git a/libs/main/core/pistring.h b/libs/main/core/pistring.h index 75e06b46..455ad87d 100644 --- a/libs/main/core/pistring.h +++ b/libs/main/core/pistring.h @@ -722,6 +722,9 @@ public: //! \brief Return string constructed from ASCII static PIString fromAscii(const char * s); + //! \brief Return string constructed from "len" chars ASCII + static PIString fromAscii(const char * s, int len); + //! \brief Return string constructed from "c" codepage static PIString fromCodepage(const char * s, const char * c); diff --git a/libs/main/core/pistring_std.h b/libs/main/core/pistring_std.h index 8d1d05e1..909c5348 100644 --- a/libs/main/core/pistring_std.h +++ b/libs/main/core/pistring_std.h @@ -1,5 +1,5 @@ -/*! \file pistring.h - * \brief String +/*! \file pistring_std.h + * \brief STD for PIString * * This file declare std operators and string conversions */ @@ -23,11 +23,12 @@ */ #ifndef PISTRING_STD_H #define PISTRING_STD_H + + #include #ifdef QNX typedef std::basic_string wstring; #endif - #include "pistringlist.h" @@ -97,4 +98,5 @@ inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) { return s; } + #endif // PISTRING_STD_H diff --git a/libs/main/core/pitime.cpp b/libs/main/core/pitime.cpp index 5e3fdb8c..220289e9 100644 --- a/libs/main/core/pitime.cpp +++ b/libs/main/core/pitime.cpp @@ -212,6 +212,13 @@ PIDateTime PIDateTime::current() { } +void PISystemTime::toTimespec(void * ts) { +#ifndef WINDOWS + ((timespec*)ts)->tv_sec = seconds; + ((timespec*)ts)->tv_nsec = nanoseconds; +#endif +} + PISystemTime PISystemTime::abs() const { if (seconds < 0) return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds)); @@ -255,12 +262,12 @@ PISystemTime PISystemTime::current(bool precise_but_not_system) { timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); t_cur.tv_sec = tv.tv_sec; t_cur.tv_nsec = tv.tv_usec * 1000; # else timespec t_cur; - clock_gettime(0, &t_cur); + clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur); # endif # endif return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec); diff --git a/libs/main/core/pitime.h b/libs/main/core/pitime.h index e0a00c0b..9c9a959d 100644 --- a/libs/main/core/pitime.h +++ b/libs/main/core/pitime.h @@ -60,8 +60,6 @@ public: //! Contructs system time with s = "s" and ns = "ns" PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();} - //! Contructs system time from another - PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;} //! Returns stored system time value in seconds double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;} @@ -93,6 +91,8 @@ public: //! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever. void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0) + //! On Unix system assign current value to timespec struct + void toTimespec(void *ts); //! Returns copy of this system time with absolutely values of s and ns PISystemTime abs() const; @@ -170,13 +170,6 @@ private: //! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;} -//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;} - -//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;} - - struct PIP_EXPORT PITime { @@ -197,8 +190,6 @@ PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1); inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);} inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);} inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);} -inline PIByteArray & operator <<(PIByteArray & s, const PITime & v) {s << v.hours << v.minutes << v.seconds << v.milliseconds; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PITime & v) {s >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;} //! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout PIP_EXPORT PICout operator <<(PICout s, const PITime & v); @@ -221,8 +212,6 @@ PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1); inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);} inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);} inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);} -inline PIByteArray & operator <<(PIByteArray & s, const PIDate & v) {s << v.year << v.month << v.day; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PIDate & v) {s >> v.year >> v.month >> v.day; return s;} //! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout PIP_EXPORT PICout operator <<(PICout s, const PIDate & v); diff --git a/libs/main/core/pivariant.h b/libs/main/core/pivariant.h index bea37f17..77313cf4 100644 --- a/libs/main/core/pivariant.h +++ b/libs/main/core/pivariant.h @@ -661,6 +661,7 @@ template<> inline PIVariantTypes::Color PIVariant::value() const {return toColor template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();} template<> inline PIPointd PIVariant::value() const {return toPoint();} template<> inline PIRectd PIVariant::value() const {return toRect();} +template<> inline PIVariant PIVariant::value() const {return *this;} template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);} @@ -691,6 +692,7 @@ template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIV template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivBool;} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivChar;} @@ -752,7 +754,6 @@ REGISTER_VARIANT(PIRectd) REGISTER_VARIANT(PIMathVectord) REGISTER_VARIANT(PIMathMatrixd) - inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) { s << v._content << int(v._type); if (v._type == PIVariant::pivCustom) { diff --git a/libs/main/core/pivariantsimple.h b/libs/main/core/pivariantsimple.h new file mode 100644 index 00000000..0336dc9b --- /dev/null +++ b/libs/main/core/pivariantsimple.h @@ -0,0 +1,148 @@ +/*! \file pivariantsimple.h + * \brief Variant simple type + * + * This file declares PIVariantSimple +*/ +/* + PIP - Platform Independent Primitives + Variant simple type + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PIVARIANTSIMPLE_H +#define PIVARIANTSIMPLE_H + +#include "pistring.h" +#include +#ifdef PIP_FREERTOS +#include "pivariant.h" +#endif + + +class __VariantFunctionsBase__ { +public: + virtual __VariantFunctionsBase__ * instance() {return 0;} + virtual PIString typeName() const {return PIString();} + virtual uint hash() const {return 0;} + virtual void newT(void *& ptr, const void * value) {;} + virtual void newNullT(void *& ptr) {;} + virtual void assignT(void *& ptr, const void * value) {;} + virtual void deleteT(void *& ptr) {;} +}; + + +template +class __VariantFunctions__: public __VariantFunctionsBase__ { +public: + __VariantFunctionsBase__ * instance() final {static __VariantFunctions__ ret; return &ret;} +#ifdef PIP_FREERTOS + PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;} +#else + PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;} +#endif + uint hash() const final {static uint ret = typeName().hash(); return ret;} + void newT(void *& ptr, const void * value) final {ptr = (void*)(new T(*(const T*)value));} + void newNullT(void *& ptr) final {ptr = (void*)(new T());} + void assignT(void *& ptr, const void * value) final {*(T*)ptr = *(const T*)value;} + void deleteT(void *& ptr) final {delete (T*)(ptr);} +}; + + +class PIVariantSimple { +public: + PIVariantSimple() {ptr = 0; f = 0;} + PIVariantSimple(const PIVariantSimple & v) { + ptr = 0; + f = v.f; + if (f && v.ptr) + f->newT(ptr, v.ptr); + } + ~PIVariantSimple() {destroy();} + + PIVariantSimple & operator=(const PIVariantSimple & v) { + destroy(); + f = v.f; + if (f && v.ptr) + f->newT(ptr, v.ptr); + return *this; + } + + template + void setValue(const T & v) { + if (f) { + if (isMyType()) { + f->assignT(ptr, (const void *)&v); + return; + } + } + destroy(); + f = __VariantFunctions__().instance(); + f->newT(ptr, (const void *)&v); + } + + template + T value() const { + if (!f) return T(); + if (!isMyType()) + return T(); + return *(T*)(ptr); + } + + template + static PIVariantSimple fromValue(const T & v) { + PIVariantSimple ret; + ret.setValue(v); + return ret; + } + +private: + template + bool isMyType() const { + if (!f) return false; + uint mh = f->hash(), th = __VariantFunctions__().instance()->hash(); + if (mh == 0 || th == 0) return false; + return mh == th; + } + + void destroy() { + if (ptr && f) + f->deleteT(ptr); + ptr = 0; + f = 0; + } + + void * ptr; + __VariantFunctionsBase__ * f; + +}; + + +#define REGISTER_PIVARIANTSIMPLE(Type) \ + template<> \ + class __VariantFunctions__: public __VariantFunctionsBase__ { \ + public: \ + __VariantFunctionsBase__ * instance() final {static __VariantFunctions__ ret; return &ret;} \ + PIString typeName() const final {static PIString ret(#Type); return ret;} \ + uint hash() const final {static uint ret = typeName().hash(); return ret;} \ + void newT(void *& ptr, const void * value) final {ptr = (void*)(new Type(*(const Type *)value));} \ + void newNullT(void *& ptr) final {ptr = (void*)(new Type());} \ + void assignT(void *& ptr, const void * value) final {*(Type *)ptr = *(const Type *)value;} \ + void deleteT(void *& ptr) final {delete (Type *)(ptr);} \ + }; + +REGISTER_PIVARIANTSIMPLE(std::function) + +#endif // PIVARIANTSIMPLE_H diff --git a/libs/main/geo/pigeoposition.cpp b/libs/main/geo/pigeoposition.cpp index eac7e3a6..c7974546 100644 --- a/libs/main/geo/pigeoposition.cpp +++ b/libs/main/geo/pigeoposition.cpp @@ -203,10 +203,7 @@ double PIGeoPosition::height() const { PIGeoPosition &PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell) { - if(lat > 90 || lat < -90) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in setGeodetic:" << lat; - assert(lat <= 90 && lat >= -90); - } + assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeodetic"); (*this)[0] = lat; (*this)[1] = lon; if((*this)[1] < 0) (*this)[1] += 360 * (1 + (unsigned long)((*this)[1]/360)); @@ -219,14 +216,8 @@ PIGeoPosition &PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIE PIGeoPosition &PIGeoPosition::setGeocentric(double lat, double lon, double rad) { - if(lat > 90 || lat < -90) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in setGeocentric:" << lat; - assert(lat <= 90 && lat >= -90); - } - if(rad < 0) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in setGeocentric:" << rad; - assert(rad >= 0); - } + assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeocentric"); + assertm(rad >= 0, "Achtung! Invalid radius in setGeocentric"); (*this)[0] = lat; (*this)[1] = lon; (*this)[2] = rad; @@ -238,14 +229,8 @@ PIGeoPosition &PIGeoPosition::setGeocentric(double lat, double lon, double rad) PIGeoPosition &PIGeoPosition::setSpherical(double theta, double phi, double rad) { - if(theta < 0 || theta > 180) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid theta in setSpherical:" << theta; - assert(theta <= 180 && theta >= 0); - } - if(rad < 0) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in setSpherical:" << rad; - assert(rad >= 0); - } + assertm(theta <= 180 && theta >= 0, "Achtung! Invalid theta in setSpherical"); + assertm(rad >= 0, "Achtung! Invalid radius in setSpherical"); (*this)[0] = theta; (*this)[1] = phi; (*this)[2] = rad; @@ -439,24 +424,15 @@ bool PIGeoPosition::operator==(const PIGeoPosition &right) const { void PIGeoPosition::initialize(PIMathVectorT3d v, PIGeoPosition::CoordinateSystem sys, PIEllipsoidModel ell) { double a(v[0]), b(v[1]), c(v[2]); if(sys == Geodetic || sys==Geocentric) { - if(a > 90 || a < -90) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid latitude in constructor:" << a; - assert(a <= 90 && a >= -90); - } + assertm(a <= 90 && a >= -90, "Achtung! Invalid latitude in constructor"); if(b < 0) b += 360*(1+(unsigned long)(b/360)); else if(b >= 360) b -= 360*(unsigned long)(b/360); } if(sys==Geocentric || sys==Spherical) { - if(c < 0) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid radius in constructor:" << c; - assert(c >= 0); - } + assertm(c >= 0, "Achtung! Invalid radius in constructor"); } if(sys==Spherical) { - if(a < 0 || a > 180) { - piCout << "[PIGeoPosition]" << "Achtung! Invalid theta in constructor:" << a; - assert(a >= 0 && a <= 180); - } + assertm(a >= 0 && a <= 180, "Achtung! Invalid theta in constructor"); if(b < 0) b += 360*(1+(unsigned long)(b/360)); else if(b >= 360) b -= 360*(unsigned long)(b/360); } @@ -493,10 +469,7 @@ double PIGeoPosition::elevationGeodetic(const PIGeoPosition &p) const { r.transformTo(Cartesian); s.transformTo(Cartesian); PIMathVectorT3d z = s - r; - if (z.length() <= 1e-4) { // if the positions are within .1 millimeter - piCout << "[PIGeoPosition]" << "Positions are within .1 millimeter" << z; - assert(z.length() > 1e-4); - } + assertm(z.length() > 1e-4, "Positions are within .1 millimeter"); PIMathVectorT3d kv; // Compute k vector in local North-East-Up (NEU) system kv[0] = cos(lat) * cos(lng); kv[1] = cos(lat) * sin(lng); @@ -517,10 +490,7 @@ double PIGeoPosition::azimuth(const PIGeoPosition &p) const { xyz = xy + r[2] * r[2]; xy = sqrt(xy); xyz = sqrt(xyz); - if (xy <= 1e-14 || xyz <=1e-14) { - piCout << "[PIGeoPosition]" << "Divide by Zero Error"; - assert(xy > 1e-14 && xyz > 1e-14); - } + assertm(xy > 1e-14 && xyz > 1e-14, "Divide by Zero Error"); cosl = r[0] / xy; sinl = r[1] / xy; sint = r[2] / xyz; @@ -535,10 +505,7 @@ double PIGeoPosition::azimuth(const PIGeoPosition &p) const { p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3) ; p2 = (xe1 * z1) + (xe2 * z2) ; test = piAbsd(p1) + piAbsd(p2); - if (test < 1.0e-16) { - piCout << "[PIGeoPosition]" << "azAngle(), failed p1+p2 test" << test; - assert(test >= 1.0e-16); - } + assertm(test >= 1.0e-16, "azAngle(), failed p1+p2 test"); alpha = 90 - atan2(p1, p2) * rad2deg; if (alpha < 0) return alpha + 360; else return alpha; @@ -553,10 +520,7 @@ double PIGeoPosition::azimuthGeodetic(const PIGeoPosition &p) const { s.transformTo(Cartesian); PIMathVectorT3d z; z = s - r; - if (z.length() <= 1e-4) { // if the positions are within .1 millimeter - piCout << "[PIGeoPosition]" << "Positions are within 0.1 millimeter" << z.length(); - assert(z.length() > 1e-4); - } + assertm(z.length() > 1e-4, "Positions are within 0.1 millimeter"); PIMathVectorT3d iv; // Compute i vector in local North-East-Up (NEU) system iv[0] = -sin(lat) * cos(lng); iv[1] = -sin(lat) * sin(lng); diff --git a/libs/main/io_devices/piethernet.h b/libs/main/io_devices/piethernet.h index bb9f988e..266134a0 100644 --- a/libs/main/io_devices/piethernet.h +++ b/libs/main/io_devices/piethernet.h @@ -65,8 +65,6 @@ public: //! \brief IPv4 network address, IP and port class PIP_EXPORT Address { friend class PIEthernet; - friend inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v); - friend inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v); public: //! Contructs %Address with binary representation of IP and port @@ -519,7 +517,5 @@ inline PICout operator <<(PICout s, const PIEthernet::Address & v) {s.space(); s inline bool operator ==(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() == v1.ip() && v0.port() == v1.port());} inline bool operator !=(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() != v1.ip() || v0.port() != v1.port());} -inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v) {s << v.ip_ << v.port_; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v) {s >> v.ip_ >> v.port_; return s;} #endif // PIETHERNET_H diff --git a/libs/main/io_devices/pifile.cpp b/libs/main/io_devices/pifile.cpp index 8f598b05..c8754a08 100644 --- a/libs/main/io_devices/pifile.cpp +++ b/libs/main/io_devices/pifile.cpp @@ -124,10 +124,12 @@ PIString PIFile::FileInfo::extension() const { PIString PIFile::FileInfo::dir() const { if (path.isEmpty()) return PIString(); - PIString ret = path.mid(0, path.findLast(PIDir::separator)); - if (ret.isEmpty()) ret = PIDir::separator; - if (!PIDir(ret).isExists()) return (PIStringAscii(".") + PIDir::separator); - return ret; + int ind = path.findLast(PIDir::separator); + PIString ret; + if (ind >= 0) + ret = path.mid(0, ind); + if (ret.isEmpty()) ret = "."; + return ret + PIDir::separator; } diff --git a/libs/main/io_devices/pifile.h b/libs/main/io_devices/pifile.h index 56b1df6f..a84cd63d 100644 --- a/libs/main/io_devices/pifile.h +++ b/libs/main/io_devices/pifile.h @@ -36,7 +36,7 @@ public: explicit PIFile(); struct PIP_EXPORT FileInfo { - FileInfo() {size = 0; id_group = id_user = 0;} + FileInfo(const PIString & path_ = PIString()) {path = path_; size = 0; id_group = id_user = 0;} enum Flag { File = 0x01, diff --git a/libs/main/io_devices/piserial.cpp b/libs/main/io_devices/piserial.cpp index 07fdded6..203d8e2a 100644 --- a/libs/main/io_devices/piserial.cpp +++ b/libs/main/io_devices/piserial.cpp @@ -709,7 +709,16 @@ int PISerial::readDevice(void * read_to, int max_size) { return PRIVATE->readed; #else if (!canRead()) return -1; - return ::read(fd, read_to, max_size); + int ret = ::read(fd, read_to, max_size); + if (ret < 0) { + int err = errno; + if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) { + PIThread::stop(false); + close(); + return 0; + } + } + return ret; #endif } diff --git a/libs/main/math/pievaluator.cpp b/libs/main/math/pievaluator.cpp index 06e3fbf2..ebd42eed 100644 --- a/libs/main/math/pievaluator.cpp +++ b/libs/main/math/pievaluator.cpp @@ -330,8 +330,10 @@ void PIEvaluator::makeOutput(PIString & string) { void PIEvaluator::findUnknownVariables() { PIString cvar; unknownVars.clear(); + usedVars.clear(); for (int i = 0; i < currentString.length(); i++) { - if (elements[i].var_num == -666) cvar += currentString[i]; + if (elements[i].var_num >= 0) usedVars << content.variable(elements[i].var_num).name; + else if (elements[i].var_num == -666) cvar += currentString[i]; else { if (cvar.length() == 0) continue; unknownVars << cvar; @@ -340,6 +342,10 @@ void PIEvaluator::findUnknownVariables() { } if (cvar.length() > 0) unknownVars << cvar; unknownVars.removeDuplicates(); + usedVars.removeDuplicates(); + usedVars.removeOne("i"); + usedVars.removeOne("pi"); + usedVars.removeOne("e"); } @@ -1196,7 +1202,7 @@ complexd PIEvaluator::evaluate() { PIByteArray PIEvaluator::save() const { PIByteArray ret; - ret << content << currentVariables << unknownVars << instructions << currentString << lastError << out << correct; + ret << content << currentVariables << unknownVars << instructions << currentString << lastError << out << correct << usedVars; return ret; } @@ -1204,5 +1210,6 @@ PIByteArray PIEvaluator::save() const { void PIEvaluator::load(PIByteArray ba) { if (ba.size() <= 4) return; ba >> content >> currentVariables >> unknownVars >> instructions >> currentString >> lastError >> out >> correct; + if (ba.size() >= 4) ba >> usedVars; variables = currentVariables; } diff --git a/libs/main/math/pievaluator.h b/libs/main/math/pievaluator.h index 94ff6250..5433fb57 100644 --- a/libs/main/math/pievaluator.h +++ b/libs/main/math/pievaluator.h @@ -176,6 +176,9 @@ public: //! Returns all unknown variables founded in last expression passed to \a check() function const PIStringList & unknownVariables() const {return unknownVars;} + //! Returns all used variables founded in last expression passed to \a check() function + const PIStringList & usedVariables() const {return usedVars;} + //! Returns processed last expression passed to \a check() function const PIString & expression() const {return currentString;} @@ -220,7 +223,7 @@ private: PIDeque elements; PIVector currentVariables, variables, tmpvars, * kvars; PIVector instructions; - PIStringList unknownVars; + PIStringList unknownVars, usedVars; PIString currentString, lastError; complexd out; bool correct; diff --git a/libs/main/math/pifft.cpp b/libs/main/math/pifft.cpp index 7fbb6ca7..6a0ea413 100644 --- a/libs/main/math/pifft.cpp +++ b/libs/main/math/pifft.cpp @@ -177,17 +177,13 @@ void PIFFT_double::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) { curplan.plan.resize(planarraysize); int ftbase_ftbasecffttask = 0; ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr); - if (stackptr != 0) { - return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); - } + assert(stackptr==0); curplan.stackbuf.resize(piMax(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1)); curplan.tmpbuf.resize(piMax(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1)); curplan.precomputed.resize(piMax(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1)); stackptr = 0; ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr); - if (stackptr != 0) { - return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); - } + assert(stackptr==0); } @@ -1117,17 +1113,13 @@ void PIFFT_float::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) { curplan.plan.resize(planarraysize); int ftbase_ftbasecffttask = 0; ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr); - if (stackptr != 0) { - return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); - } + assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan"); curplan.stackbuf.resize(piMax(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1)); curplan.tmpbuf.resize(piMax(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1)); curplan.precomputed.resize(piMax(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1)); stackptr = 0; ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr); - if (stackptr != 0) { - return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); - } + assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan"); } diff --git a/libs/main/math/pigeometry.h b/libs/main/math/pigeometry.h index ad2df750..65bf39d1 100644 --- a/libs/main/math/pigeometry.h +++ b/libs/main/math/pigeometry.h @@ -59,12 +59,6 @@ public: template PICout operator <<(PICout & s, const PIPoint & v) {s.setControl(0, true); s << "Point{" << v.x << ", " << v.y << "}"; s.restoreControl(); return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const PIPoint & v) {s << v.x << v.y; return s;} - -template -inline PIByteArray & operator >>(PIByteArray & s, PIPoint & v) {s >> v.x >> v.y; return s;} - typedef PIPoint PIPointi; typedef PIPoint PIPointu; @@ -145,12 +139,6 @@ public: template PICout operator <<(PICout & s, const PIRect & v) {s.setControl(0, true); s << "Rect{" << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << "}"; s.restoreControl(); return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const PIRect & v) {s << v.x0 << v.x1 << v.y0 << v.y1; return s;} - -template -inline PIByteArray & operator >>(PIByteArray & s, PIRect & v) {s >> v.x0 >> v.x1 >> v.y0 >> v.y1; return s;} - typedef PIRect PIRecti; typedef PIRect PIRectu; diff --git a/libs/main/math/pimathbase.h b/libs/main/math/pimathbase.h index 0841ac4c..ee845dd8 100644 --- a/libs/main/math/pimathbase.h +++ b/libs/main/math/pimathbase.h @@ -95,12 +95,10 @@ const double deg2rad = M_PI_180; const double rad2deg = M_180_PI; -inline int sign(const float & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} -inline int sign(const double & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} +inline int sign(const float & x) {return (x < 0.f) ? -1 : (x > 0.f ? 1 : 0);} +inline int sign(const double & x) {return (x < 0. ) ? -1 : (x > 0. ? 1 : 0);} +inline int sign(const ldouble & x) {return (x < 0.L) ? -1 : (x > 0.L ? 1 : 0);} inline int pow2(const int p) {return 1 << p;} -inline int sqr(const int v) {return v * v;} -inline float sqr(const float & v) {return v * v;} -inline double sqr(const double & v) {return v * v;} inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;} PIP_EXPORT double piJ0(const double & v); @@ -109,22 +107,27 @@ PIP_EXPORT double piJn(int n, const double & v); PIP_EXPORT double piY0(const double & v); PIP_EXPORT double piY1(const double & v); PIP_EXPORT double piYn(int n, const double & v); -inline double toDb(double val) {return 10. * log10(val);} -inline double fromDb(double val) {return pow(10., val / 10.);} -inline double toRad(double deg) {return deg * M_PI_180;} -inline double toDeg(double rad) {return rad * M_180_PI;} + +inline constexpr float toRad(float deg) {return deg * M_PI_180;} +inline constexpr double toRad(double deg) {return deg * M_PI_180;} +inline constexpr ldouble toRad(ldouble deg) {return deg * M_PI_180;} +inline constexpr float toDeg(float rad) {return rad * M_180_PI;} +inline constexpr double toDeg(double rad) {return rad * M_180_PI;} +inline constexpr ldouble toDeg(ldouble rad) {return rad * M_180_PI;} +template inline constexpr T sqr(const T & v) {return v * v;} +template inline constexpr T toDb (T val) {return T(10.) * std::log10(val);} +template inline constexpr T fromDb(T val) {return std::pow(T(10.), val / T(10.));} // [-1 ; 1] PIP_EXPORT double randomd(); // [-1 ; 1] normal PIP_EXPORT double randomn(double dv = 0., double sv = 1.); - -inline PIVector abs(const PIVector & v) { - PIVector result; +template inline PIVector piAbs(const PIVector & v) { + PIVector result; result.resize(v.size()); for (uint i = 0; i < v.size(); i++) - result[i] = fabs(v[i]); + result[i] = piAbs(v[i]); return result; } diff --git a/libs/main/math/pimathcomplex.h b/libs/main/math/pimathcomplex.h index 2bcc7fea..369513a4 100644 --- a/libs/main/math/pimathcomplex.h +++ b/libs/main/math/pimathcomplex.h @@ -47,22 +47,6 @@ const complexld complexld_i(0., 1.); const complexld complexld_0(0.); const complexld complexld_1(1.); -__PICONTAINERS_SIMPLE_TYPE__(complexi) -__PICONTAINERS_SIMPLE_TYPE__(complexs) -__PICONTAINERS_SIMPLE_TYPE__(complexf) -__PICONTAINERS_SIMPLE_TYPE__(complexd) -__PICONTAINERS_SIMPLE_TYPE__(complexld) -__PIVECTOR2D_SIMPLE_TYPE__(complexi) -__PIVECTOR2D_SIMPLE_TYPE__(complexs) -__PIVECTOR2D_SIMPLE_TYPE__(complexf) -__PIVECTOR2D_SIMPLE_TYPE__(complexd) -__PIVECTOR2D_SIMPLE_TYPE__(complexld) -__PIBYTEARRAY_SIMPLE_TYPE__(complexi) -__PIBYTEARRAY_SIMPLE_TYPE__(complexs) -__PIBYTEARRAY_SIMPLE_TYPE__(complexf) -__PIBYTEARRAY_SIMPLE_TYPE__(complexd) -__PIBYTEARRAY_SIMPLE_TYPE__(complexld) - inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x.imag()));} inline complexd round(const complexd & c) {return complexd(piRound(c.real()), piRound(c.imag()));} @@ -85,20 +69,6 @@ inline complexd log10(const complexd & c) {return log(c) / M_LN10;} template inline PICout operator <<(PICout s, const complex & v) {s.space(); s.setControl(0, true); s << "(" << v.real() << "; " << v.imag() << ")"; s.restoreControl(); return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, complexf v) {float t; t = v.real(); s << t; t = v.imag(); s << t; return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, complexd v) {double t; t = v.real(); s << t; t = v.imag(); s << t; return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, complexld v) {ldouble t; t = v.real(); s << t; t = v.imag(); s << t; return s;} - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, complexf & v) {float t0, t1; s >> t0; s >> t1; v = complexf(t0, t1); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, complexd & v) {double t0, t1; s >> t0; s >> t1; v = complexd(t0, t1); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, complexld & v) {ldouble t0, t1; s >> t0; s >> t1; v = complexld(t0, t1); return s;} - inline PIVector abs(const PIVector & v) { PIVector result; @@ -117,4 +87,33 @@ inline PIVector2D abs(const PIVector2D & v) { return result; } + +/** +* @brief floating point number specific comparison between value passed as parameter and zero +* +* @param v floating point parameter for comparison +* @return true if v in locality of zero, otherwise false +*/ +template::value, int>::type = 0> +inline bool PIMathFloatNullCompare(const T v) { + static_assert(std::is_floating_point::value, "Type must be floating point"); + return (piAbs(v) < T(1E-200)); +} + +/** +* @brief floating point number specific comparison between parameter value and zero. +* +* @param v complex with floating point real and imag parts +* @return true if absolute of v in locality of zero, otherwise false +*/ +template::value && + std::is_floating_point::value + , int>::type = 0> +inline bool PIMathFloatNullCompare(const T v) { + static_assert(std::is_floating_point::value, "Type must be floating point"); + static_assert(std::is_floating_point::value, "Type must be floating point"); + return (abs(v) < float(1E-200)); +} + #endif // PIMATHCOMPLEX_H diff --git a/libs/main/math/pimathmatrix.h b/libs/main/math/pimathmatrix.h index 897fe6ae..f1fedb55 100644 --- a/libs/main/math/pimathmatrix.h +++ b/libs/main/math/pimathmatrix.h @@ -28,49 +28,12 @@ #include "pimathvector.h" #include "pimathcomplex.h" -/** -* @brief Inline funtion of compare with zero different types -* -* @param v is input parameter of type T -* @return true if zero, false if not zero -*/ -template -inline bool _PIMathMatrixNullCompare(const T v) { - static_assert(std::is_floating_point::value, "Type must be floating point"); - return (piAbs(v) < T(1E-200)); -} - -/** -* @brief Inline funtion of compare with zero colmplexf type -* -* @param v is input parameter of type colmplexf -* @return true if zero, false if not zero -*/ -template<> -inline bool _PIMathMatrixNullCompare(const complexf v) { - return (abs(v) < float(1E-200)); -} - -/** -* @brief Inline funtion of compare with zero complexd type -* -* @param v is input parameter of type colmplexd -* @return true if zero, false if not zero -*/ -template<> -inline bool _PIMathMatrixNullCompare(const complexd v) { - return (abs(v) < double(1E-200)); -} - /// Matrix templated -#define PIMM_FOR(r, c) for (uint c = 0; c < Cols; ++c) { for (uint r = 0; r < Rows; ++r) { -#define PIMM_FOR_WB(r, c) for (uint c = 0; c < Cols; ++c) for (uint r = 0; r < Rows; ++r) // without brakes -#define PIMM_FOR_I(r, c) for (uint r = 0; r < Rows; ++r) { for (uint c = 0; c < Cols; ++c) { -#define PIMM_FOR_I_WB(r, c) for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c) // without brakes -#define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v) -#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v) +#define PIMM_FOR for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c) +#define PIMM_FOR_C for (uint i = 0; i < Cols; ++i) +#define PIMM_FOR_R for (uint i = 0; i < Rows; ++i) #pragma pack(push, 1) @@ -90,22 +53,26 @@ class PIP_EXPORT PIMathMatrixT { static_assert(Cols > 0, "Column count must be > 0"); public: /** - * @brief Constructor that calls the private resize method - * - * @return identitied matrix of type PIMathMatrixT + * @brief Constructs PIMathMatrixT that is filled by \a new_value */ - PIMathMatrixT() { resize(Rows, Cols); } + PIMathMatrixT(const Type &new_value = Type()) {PIMM_FOR m[r][c] = new_value;} /** - * @brief Constructor that calls the private resize method - * - * @param val is the PIVector with which the matrix is ​​filled - * @return identitied matrix of type PIMathMatrixT + * @brief Contructs PIMathMatrixT from PIVector */ PIMathMatrixT(const PIVector &val) { - resize(Rows, Cols); + assert(Rows*Cols == val.size()); int i = 0; - PIMM_FOR_I_WB(r, c) m[r][c] = val[i++]; + PIMM_FOR m[r][c] = val[i++]; + } + + /** + * @brief Contructs PIMathMatrixT from C++11 initializer list + */ + PIMathMatrixT(std::initializer_list init_list) { + assert(Rows*Cols == init_list.size()); + int i = 0; + PIMM_FOR m[r][c] = init_list.begin()[i++]; } /** @@ -115,98 +82,23 @@ public: */ static _CMatrix identity() { _CMatrix tm = _CMatrix(); - PIMM_FOR_WB(r, c) tm.m[r][c] = (c == r ? Type(1) : Type(0)); + PIMM_FOR tm.m[r][c] = (c == r ? Type(1) : Type(0)); return tm; } - /** - * @brief Creates a matrix that is filled with elements - * - * @param v is a parameter the type and value of which is selected and later filled into the matrix - * @return filled matrix of type PIMathMatrixT - */ - static _CMatrix filled(const Type &v) { - _CMatrix tm; - PIMM_FOR_WB(r, c) tm.m[r][c] = v; - return tm; - } - - /** - * @brief Rotation the matrix by an "angle". Works only with 2x2 matrix, - * else return default construction of PIMathMatrixT - * - * @param angle is the angle of rotation of the matrix - * @return rotated matrix - */ - static _CMatrix rotation(double angle) { return _CMatrix(); } - - /** - * @brief Rotation of the matrix by an "angle" along the X axis. Works only with 3x3 matrix, - * else return default construction of PIMathMatrixT - * - * @param angle is the angle of rotation of the matrix along the X axis - * @return rotated matrix - */ - static _CMatrix rotationX(double angle) { return _CMatrix(); } - - /** - * @brief Rotation of the matrix by an "angle" along the Y axis. Works only with 3x3 matrix, - * else return default construction of PIMathMatrixT - * - * @param angle is the angle of rotation of the matrix along the Y axis - * @return rotated matrix - */ - static _CMatrix rotationY(double angle) { return _CMatrix(); } - - /** - * @brief Rotation of the matrix by an "angle" along the Z axis. Works only with 3x3 matrix, - * else return default construction of PIMathMatrixT - * - * @param angle is the angle of rotation of the matrix along the Z axis - * @return rotated matrix - */ - static _CMatrix rotationZ(double angle) { return _CMatrix(); } - - /** - * @brief Scaling the matrix along the X axis by the value "factor". Works only with 3x3 and 2x2 matrix, - * else return default construction of PIMathMatrixT - * - * @param factor is the value of scaling by X axis - * @return rotated matrix - */ - static _CMatrix scaleX(double factor) { return _CMatrix(); } - - /** - * @brief Scaling the matrix along the Y axis by the value "factor". Works only with 3x3 and 2x2 matrix, - * else return default construction of PIMathMatrixT - * - * @param factor is the value of scaling by Y axis - * @return rotated matrix - */ - static _CMatrix scaleY(double factor) { return _CMatrix(); } - - /** - * @brief Scaling the matrix along the Z axis by the value "factor". Works only with 3x3 matrix, - * else return default construction of PIMathMatrixT - * - * @param factor is the value of scaling by Z axis - * @return rotated matrix - */ - static _CMatrix scaleZ(double factor) { return _CMatrix(); } - /** * @brief Method which returns number of columns in matrix * * @return type uint shows number of columns */ - uint cols() const { return Cols; } + constexpr uint cols() const {return Cols;} /** * @brief Method which returns number of rows in matrix * * @return type uint shows number of rows */ - uint rows() const { return Rows; } + constexpr uint rows() const {return Rows;} /** * @brief Method which returns the selected column in PIMathVectorT format. @@ -217,7 +109,7 @@ public: */ _CMCol col(uint index) { _CMCol tv; - PIMM_FOR_R(i) tv[i] = m[i][index]; + PIMM_FOR_R tv[i] = m[i][index]; return tv; } @@ -230,7 +122,7 @@ public: */ _CMRow row(uint index) { _CMRow tv; - PIMM_FOR_C(i) tv[i] = m[index][i]; + PIMM_FOR_C tv[i] = m[index][i]; return tv; } @@ -243,7 +135,7 @@ public: * @return matrix type _CMatrix */ _CMatrix &setCol(uint index, const _CMCol &v) { - PIMM_FOR_R(i) m[i][index] = v[i]; + PIMM_FOR_R m[i][index] = v[i]; return *this; } @@ -256,7 +148,7 @@ public: * @return matrix type _CMatrix */ _CMatrix &setRow(uint index, const _CMRow &v) { - PIMM_FOR_C(i) m[index][i] = v[i]; + PIMM_FOR_C m[index][i] = v[i]; return *this; } @@ -268,13 +160,8 @@ public: * @param r1 is the number of the second selected row * @return matrix type _CMatrix */ - _CMatrix &swapRows(uint r0, uint r1) { - Type t; - PIMM_FOR_C(i) { - t = m[r0][i]; - m[r0][i] = m[r1][i]; - m[r1][i] = t; - } + _CMatrix &swapRows(uint rf, uint rs) { + PIMM_FOR_C piSwap(m[rf][i], m[rs][i]); return *this; } @@ -286,13 +173,8 @@ public: * @param c1 is the number of the second selected column * @return matrix type _CMatrix */ - _CMatrix &swapCols(uint c0, uint c1) { - Type t; - PIMM_FOR_R(i) { - t = m[i][c0]; - m[i][c0] = m[i][c1]; - m[i][c1] = t; - } + _CMatrix &swapCols(uint cf, uint cs) { + PIMM_FOR_R piSwap(m[i][cf], m[i][cs]); return *this; } @@ -303,7 +185,7 @@ public: * @return filled matrix type _CMatrix */ _CMatrix &fill(const Type &v) { - PIMM_FOR_WB(r, c) m[r][c] = v; + PIMM_FOR m[r][c] = v; return *this; } @@ -312,7 +194,7 @@ public: * * @return true if matrix is square, else false */ - bool isSquare() const { return cols() == rows(); } + constexpr bool isSquare() const { return Rows == Cols; } /** * @brief Method which checks if main diagonal of matrix consists of ones and another elements are zeros @@ -320,7 +202,7 @@ public: * @return true if matrix is identitied, else false */ bool isIdentity() const { - PIMM_FOR_WB(r, c) if ((c == r) ? m[r][c] != Type(1) : m[r][c] != Type(0)) return false; + PIMM_FOR if ((c == r) ? m[r][c] != Type(1) : m[r][c] != Type(0)) return false; return true; } @@ -330,34 +212,45 @@ public: * @return true if matrix is null, else false */ bool isNull() const { - PIMM_FOR_WB(r, c) if (m[r][c] != Type(0)) return false; + PIMM_FOR if (m[r][c] != Type(0)) return false; return true; } - /** - * @brief Full access to elements reference by row "row" and col "col". - * If you enter an index out of the border of the matrix there will be "undefined behavior" - * - * @param row is a parameter that shows the row number of the matrix of the selected element - * @param col is a parameter that shows the column number of the matrix of the selected element - * @return reference to element of matrix by row "row" and col "col" - */ - Type &at(uint row, uint col) { return m[row][col]; } /** - * @brief Full access to element by row "row" and col "col". + * @brief Read-only access to element by \a row and \a col. * If you enter an index out of the border of the matrix there will be "undefined behavior" * - * @param row is a parameter that shows the row number of the matrix of the selected element - * @param col is a parameter that shows the column number of the matrix of the selected element - * @return element of matrix by row "row" and col "col" + * @param row of matrix + * @param col of matrix + * @return copy of element of matrix */ Type at(uint row, uint col) const { return m[row][col]; } + /** + * @brief Full access to element by \a row and \a col. + * If you enter an index out of the border of the matrix there will be "undefined behavior" + * + * @param row of matrix + * @param col of matrix + * @return element of matrix + */ + inline Type & element(uint row, uint col) {return m[row][col];} + + /** + * @brief Read-only access to element by \a row and \a col. + * If you enter an index out of the border of the matrix there will be "undefined behavior" + * + * @param row of matrix + * @param col of matrix + * @return element of matrix + */ + inline const Type & element(uint row, uint col) const {return m[row][col];} + /** * @brief Full access to the matrix row pointer. If you enter an index out of the border of the matrix there will be "undefined behavior" * - * @param row is a row of necessary matrix + * @param row of matrix * @return matrix row pointer */ Type *operator[](uint row) { return m[row]; } @@ -365,37 +258,26 @@ public: /** * @brief Read-only access to the matrix row pointer. If you enter an index out of the border of the matrix there will be "undefined behavior" * - * @param row is a row of necessary matrix + * @param row of matrix * @return matrix row pointer */ - const Type *operator[](uint row) const { return m[row]; } + const Type *operator[](uint row) const {return m[row];} /** - * @brief Matrix assignment to matrix "sm" + * @brief Matrix compare * - * @param sm matrix for the assigment - * @return matrix equal with sm - */ - _CMatrix &operator=(const _CMatrix &sm) { - memcpy(m, sm.m, sizeof(Type) * Cols * Rows); - return *this; - } - - /** - * @brief Compare with matrix "sm" - * - * @param sm matrix for the compare + * @param sm matrix for compare * @return if matrices are equal true, else false */ bool operator==(const _CMatrix &sm) const { - PIMM_FOR_WB(r, c) if (m[r][c] != sm.m[r][c]) return false; + PIMM_FOR if (m[r][c] != sm.m[r][c]) return false; return true; } /** - * @brief Compare with matrix "sm" + * @brief Matrix negative compare * - * @param sm matrix for the compare + * @param sm matrix for compare * @return if matrices are not equal true, else false */ bool operator!=(const _CMatrix &sm) const { return !(*this == sm); } @@ -405,28 +287,33 @@ public: * * @param sm matrix for the addition assigment */ - void operator+=(const _CMatrix &sm) { PIMM_FOR_WB(r, c) m[r][c] += sm.m[r][c]; } + void operator+=(const _CMatrix &sm) {PIMM_FOR m[r][c] += sm.m[r][c];} /** * @brief Subtraction assignment with matrix "sm" * * @param sm matrix for the subtraction assigment */ - void operator-=(const _CMatrix &sm) { PIMM_FOR_WB(r, c) m[r][c] -= sm.m[r][c]; } + void operator-=(const _CMatrix &sm) {PIMM_FOR m[r][c] -= sm.m[r][c];} /** * @brief Multiplication assignment with value "v" * * @param v value for the multiplication assigment */ - void operator*=(const Type &v) { PIMM_FOR_WB(r, c) m[r][c] *= v; } + void operator*=(const Type &v) { + PIMM_FOR m[r][c] *= v; + } /** * @brief Division assignment with value "v" * * @param v value for the division assigment */ - void operator/=(const Type &v) { PIMM_FOR_WB(r, c) m[r][c] /= v; } + void operator/=(const Type &v) { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + PIMM_FOR m[r][c] /= v; + } /** * @brief Matrix substraction @@ -435,7 +322,7 @@ public: */ _CMatrix operator-() const { _CMatrix tm; - PIMM_FOR_WB(r, c) tm.m[r][c] = -m[r][c]; + PIMM_FOR tm.m[r][c] = -m[r][c]; return tm; } @@ -447,7 +334,7 @@ public: */ _CMatrix operator+(const _CMatrix &sm) const { _CMatrix tm = _CMatrix(*this); - PIMM_FOR_WB(r, c) tm.m[r][c] += sm.m[r][c]; + PIMM_FOR tm.m[r][c] += sm.m[r][c]; return tm; } @@ -459,7 +346,7 @@ public: */ _CMatrix operator-(const _CMatrix &sm) const { _CMatrix tm = _CMatrix(*this); - PIMM_FOR_WB(r, c) tm.m[r][c] -= sm.m[r][c]; + PIMM_FOR tm.m[r][c] -= sm.m[r][c]; return tm; } @@ -471,7 +358,7 @@ public: */ _CMatrix operator*(const Type &v) const { _CMatrix tm = _CMatrix(*this); - PIMM_FOR_WB(r, c) tm.m[r][c] *= v; + PIMM_FOR tm.m[r][c] *= v; return tm; } @@ -482,8 +369,9 @@ public: * @return the result of matrix division */ _CMatrix operator/(const Type &v) const { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); _CMatrix tm = _CMatrix(*this); - PIMM_FOR_WB(r, c) tm.m[r][c] /= v; + PIMM_FOR tm.m[r][c] /= v; return tm; } @@ -501,10 +389,21 @@ public: if (ok) *ok = k; if (!k) return ret; ret = Type(1); - for (uint c = 0; c < Cols; ++c) - for (uint r = 0; r < Rows; ++r) - if (r == c) - ret *= m[r][c]; + PIMM_FOR if (r == c) ret *= m[r][c]; + return ret; + } + + /** + * @brief Trace of the matrix is calculated. Works only with square matrix, nonzero matrices and invertible matrix + * + * @return matrix trace + */ + Type trace() const { + static_assert(Rows == Cols, "Works only with square matrix"); + Type ret = Type(0); + for (uint i = 0; i < Cols; ++i) { + ret += m[i][i]; + } return ret; } @@ -515,10 +414,7 @@ public: * @return copy of transformed upper triangular matrix */ _CMatrix &toUpperTriangular(bool *ok = 0) { - if (Cols != Rows) { - if (ok != 0) *ok = false; - return *this; - } + static_assert(Rows == Cols, "Works only with square matrix"); _CMatrix smat(*this); bool ndet; uint crow; @@ -540,7 +436,7 @@ public: for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i]; } if (i < Cols - 1) { - if (fabs(smat.m[i + 1][i + 1]) < Type(1E-200)) { + if (piAbs(smat.m[i + 1][i + 1]) < Type(1E-200)) { if (ok != 0) *ok = false; return *this; } @@ -558,7 +454,7 @@ public: * @return copy of inverted matrix */ _CMatrix &invert(bool *ok = 0) { - static_assert(Cols == Rows, "Only square matrix invertable"); + static_assert(Rows == Cols, "Works only with square matrix"); _CMatrix mtmp = _CMatrix::identity(), smat(*this); bool ndet; uint crow; @@ -584,7 +480,7 @@ public: for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i]; } if (i < Cols - 1) { - if (fabs(smat.m[i + 1][i + 1]) < Type(1E-200)) { + if (piAbs(smat.m[i + 1][i + 1]) < Type(1E-200)) { if (ok != 0) *ok = false; return *this; } @@ -624,111 +520,43 @@ public: */ _CMatrixI transposed() const { _CMatrixI tm; - PIMM_FOR_WB(r, c) tm[c][r] = m[r][c]; + PIMM_FOR tm[c][r] = m[r][c]; return tm; } -private: - void resize(uint rows_, uint cols_, const Type &new_value = Type()) { - r_ = rows_; - c_ = cols_; - PIMM_FOR_WB(r, c) m[r][c] = new_value; + _CMatrix rotate(Type angle) { + static_assert(Rows == 2 && Cols == 2, "Works only with 2x2 matrix"); + Type c = std::cos(angle); + Type s = std::sin(angle); + PIMathMatrixT<2u, 2u> tm; + tm[0][0] = tm[1][1] = c; + tm[0][1] = -s; + tm[1][0] = s; + *this = *this * tm; + return *this; } - int c_, r_; +private: Type m[Rows][Cols]; - }; #pragma pack(pop) -template<> -inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) { - double c = cos(angle), s = sin(angle); - PIMathMatrixT<2u, 2u> tm; - tm[0][0] = tm[1][1] = c; - tm[0][1] = -s; - tm[1][0] = s; - return tm; -} - -template<> -inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleX(double factor) { - PIMathMatrixT<2u, 2u> tm; - tm[0][0] = factor; - tm[1][1] = 1.; - return tm; -} - -template<> -inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleY(double factor) { - PIMathMatrixT<2u, 2u> tm; - tm[0][0] = 1.; - tm[1][1] = factor; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationX(double angle) { - double c = cos(angle), s = sin(angle); - PIMathMatrixT<3u, 3u> tm; - tm[0][0] = 1.; - tm[1][1] = tm[2][2] = c; - tm[2][1] = s; - tm[1][2] = -s; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationY(double angle) { - double c = cos(angle), s = sin(angle); - PIMathMatrixT<3u, 3u> tm; - tm[1][1] = 1.; - tm[0][0] = tm[2][2] = c; - tm[2][0] = -s; - tm[0][2] = s; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationZ(double angle) { - double c = cos(angle), s = sin(angle); - PIMathMatrixT<3u, 3u> tm; - tm[2][2] = 1.; - tm[0][0] = tm[1][1] = c; - tm[1][0] = s; - tm[0][1] = -s; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleX(double factor) { - PIMathMatrixT<3u, 3u> tm; - tm[1][1] = tm[2][2] = 1.; - tm[0][0] = factor; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleY(double factor) { - PIMathMatrixT<3u, 3u> tm; - tm[0][0] = tm[2][2] = 1.; - tm[1][1] = factor; - return tm; -} - -template<> -inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleZ(double factor) { - PIMathMatrixT<3u, 3u> tm; - tm[0][0] = tm[1][1] = 1.; - tm[2][2] = factor; - return tm; -} - #ifdef PIP_STD_IOSTREAM template -inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT & m) {s << "{"; PIMM_FOR_I(r, c) s << m[r][c]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << std::endl << " ";} s << "}"; return s;} +inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT & m) { + s << "{"; + for (uint r = 0; r < Rows; ++r) { + for (uint c = 0; c < Cols; ++c) { + s << m[r][c]; + if (c < Cols - 1 || r < Rows - 1) s << ", "; + } + if (r < Rows - 1) s << std::endl << " "; + } + s << "}"; + return s; +} #endif /** @@ -741,9 +569,13 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT inline PICout operator<<(PICout s, const PIMathMatrixT &m) { s << "{"; - PIMM_FOR_I(r, c) s << m[r][c]; - if (c < Cols - 1 || r < Rows - 1) s << ", "; } - if (r < Rows - 1) s << PICoutManipulators::NewLine << " "; } + for (uint r = 0; r < Rows; ++r) { + for (uint c = 0; c < Cols; ++c) { + s << m[r][c]; + if (c < Cols - 1 || r < Rows - 1) s << ", "; + } + if (r < Rows - 1) s << PICoutManipulators::NewLine << " "; + } s << "}"; return s; } @@ -838,9 +670,6 @@ template class PIMathMatrix; #undef PIMM_FOR -#undef PIMM_FOR_WB -#undef PIMM_FOR_I -#undef PIMM_FOR_I_WB #undef PIMM_FOR_C #undef PIMM_FOR_R @@ -850,11 +679,10 @@ class PIMathMatrix; /// Matrix -#define PIMM_FOR(c, r) for (uint c = 0; c < _V2D::cols_; ++c) for (uint r = 0; r < _V2D::rows_; ++r) -#define PIMM_FOR_I(c, r) for (uint r = 0; r < _V2D::rows_; ++r) for (uint c = 0; c < _V2D::cols_; ++c) -#define PIMM_FOR_A(v) for (uint v = 0; v < _V2D::mat.size(); ++v) -#define PIMM_FOR_C(v) for (uint v = 0; v < _V2D::cols_; ++v) -#define PIMM_FOR_R(v) for (uint v = 0; v < _V2D::rows_; ++v) +#define PIMM_FOR for (uint r = 0; r < _V2D::rows_; ++r) for (uint c = 0; c < _V2D::cols_; ++c) +#define PIMM_FOR_A for (uint i = 0; i < _V2D::mat.size(); ++i) +#define PIMM_FOR_C for (uint i = 0; i < _V2D::cols_; ++i) +#define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i) //! \brief A class that works with matrix operations, the input data of which is the data type of the matrix //! @tparam There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /) @@ -863,7 +691,6 @@ template class PIP_EXPORT PIMathMatrix : public PIVector2D { typedef PIVector2D _V2D; typedef PIMathMatrix _CMatrix; - typedef PIMathVector _CMCol; public: /** * @brief Constructor of class PIMathMatrix, which creates a matrix @@ -884,7 +711,7 @@ public: PIMathMatrix(const uint cols, const uint rows, const PIVector &val) { _V2D::resize(rows, cols); int i = 0; - PIMM_FOR_I(c, r) _V2D::element(r, c) = val[i++]; + PIMM_FOR _V2D::element(r, c) = val[i++]; } /** @@ -895,7 +722,11 @@ public: PIMathMatrix(const PIVector > &val) { if (!val.isEmpty()) { _V2D::resize(val.size(), val[0].size()); - PIMM_FOR_I(c, r) _V2D::element(r, c) = val[r][c]; + for (uint r = 0; r < _V2D::rows_; ++r) { + assert(val[r].size() == _V2D::cols_); + for (uint c = 0; c < _V2D::cols_; ++c) + _V2D::element(r, c) = val[r][c]; + } } } @@ -907,7 +738,7 @@ public: PIMathMatrix(const PIVector2D &val) { if (!val.isEmpty()) { _V2D::resize(val.rows(), val.cols()); - PIMM_FOR_I(c, r) _V2D::element(r, c) = val.element(r, c); + PIMM_FOR _V2D::element(r, c) = val.element(r, c); } } @@ -916,7 +747,7 @@ public: * * @param cols is number of matrix column uint type * @param rows is number of matrix row uint type - * @return identity matrix of type PIMathMatrix + * @return identity matrix(cols,rows) */ static _CMatrix identity(const uint cols, const uint rows) { _CMatrix tm(cols, rows); @@ -930,7 +761,7 @@ public: * @param val is the vector type PIMathVector * @return row matrix of every element that is equal to every element of the vector */ - static _CMatrix matrixRow(const PIMathVector &val) { return _CMatrix(val.size(), 1, val.toVector()); } + static _CMatrix matrixRow(const PIMathVector &val) {return _CMatrix(val.size(), 1, val.toVector());} /** * @brief Creates a column matrix of every element that is equal to every element of the vector @@ -938,18 +769,19 @@ public: * @param val is the vector type PIMathVector * @return column matrix of every element that is equal to every element of the vector */ - static _CMatrix matrixCol(const PIMathVector &val) { return _CMatrix(1, val.size(), val.toVector()); } + static _CMatrix matrixCol(const PIMathVector &val) {return _CMatrix(1, val.size(), val.toVector());} /** * @brief Set the selected column in matrix. If there are more elements of the vector than elements in the column of the matrix - * or index larger than the number of columns otherwise there will be "undefined behavior" + * or index larger than the number of columns otherwise there will be "undefined behavior" * * @param index is the number of the selected column * @param v is a vector of the type _CMCol that needs to fill the column * @return matrix type _CMatrix */ - _CMatrix &setCol(uint index, const _CMCol &v) { - PIMM_FOR_R(i) _V2D::element(i, index) = v[i]; + _CMatrix &setCol(uint index, const PIMathVector &v) { + assert(_V2D::rows() == v.size()); + PIMM_FOR_R _V2D::element(i, index) = v[i]; return *this; } @@ -960,8 +792,9 @@ public: * @param v is a vector of the type _CMCol that needs to fill the row * @return matrix type _CMatrix */ - _CMatrix &setRow(uint index, const _CMCol &v) { - PIMM_FOR_C(i) _V2D::element(index, i) = v[i]; + _CMatrix &setRow(uint index, const PIMathVector &v) { + assert(_V2D::cols() == v.size()); + PIMM_FOR_C _V2D::element(index, i) = v[i]; return *this; } @@ -974,7 +807,7 @@ public: * @return matrix type _CMatrix */ _CMatrix &swapCols(uint r0, uint r1) { - PIMM_FOR_C(i) { piSwap(_V2D::element(i, r0), _V2D::element(i, r1)); } + PIMM_FOR_C piSwap(_V2D::element(i, r0), _V2D::element(i, r1)); return *this; } @@ -987,7 +820,7 @@ public: * @return matrix type _CMatrix */ _CMatrix &swapRows(uint c0, uint c1) { - PIMM_FOR_R(i) { piSwap(_V2D::element(c0, i), _V2D::element(c1, i)); } + PIMM_FOR_R piSwap(_V2D::element(c0, i), _V2D::element(c1, i)); return *this; } @@ -998,7 +831,7 @@ public: * @return filled matrix type _CMatrix */ _CMatrix &fill(const Type &v) { - PIMM_FOR_A(i) _V2D::mat[i] = v; + PIMM_FOR_A _V2D::mat[i] = v; return *this; } @@ -1015,7 +848,7 @@ public: * @return true if matrix is identity, else false */ bool isIdentity() const { - PIMM_FOR(c, r) if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0))return false; + PIMM_FOR if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0))return false; return true; } @@ -1025,7 +858,7 @@ public: * @return true if matrix elements equal to zero, else false */ bool isNull() const { - PIMM_FOR_A(i) if (_V2D::mat[i] != Type(0)) return false; + PIMM_FOR_A if (_V2D::mat[i] != Type(0)) return false; return true; } @@ -1036,63 +869,46 @@ public: */ bool isValid() const { return !PIVector2D::isEmpty(); } - /** - * @brief Matrix assignment to matrix "v" - * - * @param v matrix for the assigment - * @return matrix equal with v - */ - _CMatrix &operator=(const PIVector > &v) { - *this = _CMatrix(v); - return *this; - } - - /** - * @brief Compare with matrix "sm" - * - * @param sm matrix for the compare - * @return if matrices are equal true, else false - */ - bool operator==(const _CMatrix &sm) const { - PIMM_FOR_A(i) if (_V2D::mat[i] != sm.mat[i]) return false; - return true; - } - - /** - * @brief Compare with matrix "sm" - * - * @param sm matrix for the compare - * @return if matrices are not equal true, else false - */ - bool operator!=(const _CMatrix &sm) const { return !(*this == sm); } - /** * @brief Addition assignment with matrix "sm" * * @param sm matrix for the addition assigment */ - void operator+=(const _CMatrix &sm) { PIMM_FOR_A(i) _V2D::mat[i] += sm.mat[i]; } + void operator+=(const _CMatrix &sm) { + assert(_V2D::rows() == sm.rows()); + assert(_V2D::cols() == sm.cols()); + PIMM_FOR_A _V2D::mat[i] += sm.mat[i]; + } /** * @brief Subtraction assignment with matrix "sm" * * @param sm matrix for the subtraction assigment */ - void operator-=(const _CMatrix &sm) { PIMM_FOR_A(i) _V2D::mat[i] -= sm.mat[i]; } + void operator-=(const _CMatrix &sm) { + assert(_V2D::rows() == sm.rows()); + assert(_V2D::cols() == sm.cols()); + PIMM_FOR_A _V2D::mat[i] -= sm.mat[i]; + } /** * @brief Multiplication assignment with value "v" * * @param v value for the multiplication assigment */ - void operator*=(const Type &v) { PIMM_FOR_A(i) _V2D::mat[i] *= v; } + void operator*=(const Type &v) { + PIMM_FOR_A _V2D::mat[i] *= v; + } /** * @brief Division assignment with value "v" * * @param v value for the division assigment */ - void operator/=(const Type &v) { PIMM_FOR_A(i) _V2D::mat[i] /= v; } + void operator/=(const Type &v) { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + PIMM_FOR_A _V2D::mat[i] /= v; + } /** * @brief Matrix substraction @@ -1101,7 +917,7 @@ public: */ _CMatrix operator-() const { _CMatrix tm(*this); - PIMM_FOR_A(i) tm.mat[i] = -_V2D::mat[i]; + PIMM_FOR_A tm.mat[i] = -_V2D::mat[i]; return tm; } @@ -1113,7 +929,9 @@ public: */ _CMatrix operator+(const _CMatrix &sm) const { _CMatrix tm(*this); - PIMM_FOR_A(i) tm.mat[i] += sm.mat[i]; + assert(tm.rows() == sm.rows()); + assert(tm.cols() == sm.cols()); + PIMM_FOR_A tm.mat[i] += sm.mat[i]; return tm; } @@ -1125,7 +943,9 @@ public: */ _CMatrix operator-(const _CMatrix &sm) const { _CMatrix tm(*this); - PIMM_FOR_A(i) tm.mat[i] -= sm.mat[i]; + assert(tm.rows() == sm.rows()); + assert(tm.cols() == sm.cols()); + PIMM_FOR_A tm.mat[i] -= sm.mat[i]; return tm; } @@ -1137,7 +957,7 @@ public: */ _CMatrix operator*(const Type &v) const { _CMatrix tm(*this); - PIMM_FOR_A(i) tm.mat[i] *= v; + PIMM_FOR_A tm.mat[i] *= v; return tm; } @@ -1148,8 +968,9 @@ public: * @return the result of matrix division */ _CMatrix operator/(const Type &v) const { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); _CMatrix tm(*this); - PIMM_FOR_A(i) tm.mat[i] /= v; + PIMM_FOR_A tm.mat[i] /= v; return tm; } @@ -1162,8 +983,8 @@ public: Type determinant(bool *ok = 0) const { _CMatrix m(*this); bool k; - Type ret = Type(0); m.toUpperTriangular(&k); + Type ret = Type(0); if (ok) *ok = k; if (!k) return ret; ret = Type(1); @@ -1177,19 +998,14 @@ public: /** * @brief Trace of the matrix is calculated. Works only with square matrix, nonzero matrices and invertible matrix * - * @param ok is a parameter with which we can find out if the method worked correctly * @return matrix trace */ - Type trace(bool *ok = 0) const { + Type trace() const { + assert(isSquare()); Type ret = Type(0); - if (!isSquare()) { - if (ok != 0) *ok = false; - return ret; - } for (uint i = 0; i < _V2D::cols_; ++i) { ret += _V2D::element(i, i); } - if (ok != 0) *ok = true; return ret; } @@ -1200,10 +1016,7 @@ public: * @return copy of transformed upper triangular matrix */ _CMatrix &toUpperTriangular(bool *ok = 0) { - if (!isSquare()) { - if (ok != 0) *ok = false; - return *this; - } + assert(isSquare()); _CMatrix smat(*this); bool ndet; uint crow; @@ -1225,7 +1038,7 @@ public: for (uint k = i; k < _V2D::cols_; ++k) smat.element(k, j) -= mul * smat.element(k, i); } if (i < _V2D::cols_ - 1) { - if (_PIMathMatrixNullCompare(smat.element(i + 1, i + 1))) { + if (PIMathFloatNullCompare(smat.element(i + 1, i + 1))) { if (ok != 0) *ok = false; return *this; } @@ -1243,11 +1056,8 @@ public: * @param sv is a vector multiplier * @return copy of inverted matrix */ - _CMatrix &invert(bool *ok = 0, _CMCol *sv = 0) { - if (!isSquare()) { - if (ok != 0) *ok = false; - return *this; - } + _CMatrix &invert(bool *ok = 0, PIMathVector *sv = 0) { + assert(isSquare()); _CMatrix mtmp = _CMatrix::identity(_V2D::cols_, _V2D::rows_), smat(*this); bool ndet; uint crow; @@ -1266,7 +1076,7 @@ public: ++crow; smat.swapRows(i, crow); mtmp.swapRows(i, crow); - if (sv != 0) sv->swap(i, crow); + if (sv != 0) sv->swapElements(i, crow); } for (uint j = i + 1; j < _V2D::rows_; ++j) { mul = smat.element(i, j) / smat.element(i, i); @@ -1275,7 +1085,7 @@ public: if (sv != 0) (*sv)[j] -= mul * (*sv)[i]; } if (i < _V2D::cols_ - 1) { - if (_PIMathMatrixNullCompare(smat.element(i + 1, i + 1))) { + if (PIMathFloatNullCompare(smat.element(i + 1, i + 1))) { if (ok != 0) *ok = false; return *this; } @@ -1317,7 +1127,7 @@ public: */ _CMatrix transposed() const { _CMatrix tm(_V2D::rows_, _V2D::cols_); - PIMM_FOR(c, r) tm.element(c, r) = _V2D::element(r, c); + PIMM_FOR tm.element(c, r) = _V2D::element(r, c); return tm; } }; @@ -1386,14 +1196,13 @@ inline PIByteArray &operator>>(PIByteArray &s, PIMathMatrix &v) { template inline PIMathMatrix operator*(const PIMathMatrix &fm, const PIMathMatrix &sm) { - uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols(); - PIMathMatrix tm(cols1, rows0); - if (fm.cols() != sm.rows()) return tm; + assert(fm.cols() == sm.rows()); + PIMathMatrix tm(sm.cols(), fm.rows()); Type t; - for (uint j = 0; j < rows0; ++j) { - for (uint i = 0; i < cols1; ++i) { + for (uint j = 0; j < fm.rows(); ++j) { + for (uint i = 0; i < sm.cols(); ++i) { t = Type(0); - for (uint k = 0; k < cr; ++k) + for (uint k = 0; k < fm.cols(); ++k) t += fm.element(j, k) * sm.element(k, i); tm.element(j, i) = t; } @@ -1411,13 +1220,12 @@ inline PIMathMatrix operator*(const PIMathMatrix &fm, template inline PIMathVector operator*(const PIMathMatrix &fm, const PIMathVector &sv) { - uint c = fm.cols(), r = fm.rows(); - PIMathVector tv(r); - if (c != sv.size()) return tv; + assert(fm.cols() == sv.size()); + PIMathVector tv(fm.rows()); Type t; - for (uint j = 0; j < r; ++j) { + for (uint j = 0; j < fm.rows(); ++j) { t = Type(0); - for (uint i = 0; i < c; ++i) + for (uint i = 0; i < fm.cols(); ++i) t += fm.element(j, i) * sv[i]; tv[j] = t; } @@ -1434,12 +1242,12 @@ inline PIMathVector operator*(const PIMathMatrix &fm, template inline PIMathVector operator*(const PIMathVector &sv, const PIMathMatrix &fm) { - uint c = fm.cols(), r = fm.rows(); - PIMathVector tv(c); + PIMathVector tv(fm.cols()); + assert(fm.rows() == sv.size()); Type t; - for (uint j = 0; j < c; ++j) { + for (uint j = 0; j < fm.cols(); ++j) { t = Type(0); - for (uint i = 0; i < r; ++i) + for (uint i = 0; i < fm.rows(); ++i) t += fm.element(i, j) * sv[i]; tv[j] = t; } @@ -1477,7 +1285,6 @@ PIMathMatrix > hermitian(const PIMathMatrix > &m) { } #undef PIMM_FOR -#undef PIMM_FOR_I #undef PIMM_FOR_A #undef PIMM_FOR_C #undef PIMM_FOR_R diff --git a/libs/main/math/pimathvector.h b/libs/main/math/pimathvector.h index 7c4a9b41..a98cef49 100644 --- a/libs/main/math/pimathvector.h +++ b/libs/main/math/pimathvector.h @@ -28,85 +28,202 @@ template class PIMathMatrixT; +#define PIMATHVECTOR_ZERO_CMP Type(1E-100) + /// Vector templated -#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v) +#define PIMV_FOR for (uint i = 0; i < Size; ++i) template class PIP_EXPORT PIMathVectorT { typedef PIMathVectorT _CVector; static_assert(std::is_arithmetic::value, "Type must be arithmetic"); - static_assert(Size > 0, "Size count must be > 0"); + static_assert(Size > 0, "Size must be > 0"); public: - PIMathVectorT() {resize();} - PIMathVectorT(const PIVector & val) {resize(); PIMV_FOR(i, 0) c[i] = val[i];} - PIMathVectorT(const _CVector & st, const _CVector & fn) {resize(); set(st, fn);} + PIMathVectorT(const Type & v = Type()) {PIMV_FOR c[i] = v;} + PIMathVectorT(const PIVector & val) { + assert(Size == val.size()); + PIMV_FOR c[i] = val[i]; + } + PIMathVectorT(std::initializer_list init_list) { + assert(Size == init_list.size()); + PIMV_FOR c[i] = init_list.begin()[i]; + } + static _CVector fromTwoPoints(const _CVector & st, const _CVector & fn) { + _CVector tv; + PIMV_FOR tv[i] = fn[i] - st[i]; + return tv; + } - uint size() const {return Size;} - _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - _CVector & set(const _CVector & st, const _CVector & fn) {PIMV_FOR(i, 0) c[i] = fn[i] - st[i]; return *this;} - _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} - _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} - Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} - Type length() const {return sqrt(lengthSqr());} - Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} - Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} - Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} - Type angleRad(const _CVector & v) const {return acos(angleCos(v));} - Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} - Type angleElevation(const _CVector & v) const {_CVector z = v - *this; double c = z.angleCos(*this); return 90.0 - acos(c) * rad2deg;} - _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} - _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} + constexpr uint size() const {return Size;} + _CVector & fill(const Type & v) {PIMV_FOR c[i] = v; return *this;} + _CVector & move(const Type & v) {PIMV_FOR c[i] += v; return *this;} + _CVector & move(const _CVector & v) {PIMV_FOR c[i] += v[i]; return *this;} + _CVector & swapElements(uint f, uint s) { + piSwap(c[f], c[s]); + return *this; + } + Type lengthSqr() const { + Type tv(0); + PIMV_FOR tv += c[i] * c[i]; + return tv; + } + Type length() const {return std::sqrt(lengthSqr());} + Type manhattanLength() const { + Type tv(0); + PIMV_FOR tv += piAbs(c[i]); + return tv; + } + Type angleCos(const _CVector & v) const { + Type tv = v.length() * length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + return dot(v) / tv; + } + Type angleSin(const _CVector & v) const { + Type tv = angleCos(v); + return std::sqrt(Type(1) - tv * tv); + } + Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));} + Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));} + Type angleElevation(const _CVector & v) const {return 90.0 - angleDeg(v - *this);} + _CVector projection(const _CVector & v) { + Type tv = v.length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + return v * (dot(v) / tv); + } + _CVector & normalize() { + Type tv = length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + if (tv == Type(1)) return *this; + PIMV_FOR c[i] /= tv; + return *this; + } _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} - _CVector cross(const _CVector & v) {return (*this) * v;} - Type dot(const _CVector & v) const {return (*this) ^ v;} - bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} + bool isNull() const {PIMV_FOR if (c[i] != Type(0)) return false; return true;} bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} - Type & at(uint index) {return c[index];} - Type at(uint index) const {return c[index];} Type & operator [](uint index) {return c[index];} - Type operator [](uint index) const {return c[index];} - _CVector & operator =(const _CVector & v) {memcpy(c, v.c, sizeof(Type) * Size); return *this;} - _CVector & operator =(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} + const Type & operator [](uint index) const {return c[index];} + Type at(uint index) const {return c[index];} + + _CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;} + + bool operator ==(const _CVector & v) const {PIMV_FOR if (c[i] != v[i]) return false; return true;} bool operator !=(const _CVector & v) const {return !(*this == c);} - void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} - void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} - void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} - void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} - void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} - void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} - _CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} - _CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} - _CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} - _CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} - _CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} - _CVector operator /(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v[i]; return tv;} - _CVector operator *(const _CVector & v) const {if (Size != 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} - _CVector operator &(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v[i]; return tv;} - Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} - + + void operator +=(const _CVector & v) {PIMV_FOR c[i] += v[i];} + void operator -=(const _CVector & v) {PIMV_FOR c[i] -= v[i];} + void operator *=(const Type & v) {PIMV_FOR c[i] *= v;} + void operator /=(const Type & v) { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + PIMV_FOR c[i] /= v; + } + _CVector operator -() const { + _CVector tv; + PIMV_FOR tv[i] = -c[i]; + return tv; + } + _CVector operator +(const _CVector & v) const { + _CVector tv(*this); + PIMV_FOR tv[i] += v[i]; + return tv; + } + _CVector operator -(const _CVector & v) const { + _CVector tv(*this); + PIMV_FOR tv[i] -= v[i]; + return tv; + } + _CVector operator *(const Type & v) const { + _CVector tv(*this); + PIMV_FOR tv[i] *= v; + return tv; + } + _CVector operator /(const Type & v) const { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + _CVector tv = _CVector(*this); + PIMV_FOR tv[i] /= v; + return tv; + } + + _CVector cross(const _CVector & v) const { + static_assert(Size == 3, "cross product avalible only for 3D vectors"); + _CVector tv; + tv[0] = c[1]*v[2] - v[1]*c[2]; + tv[1] = v[0]*c[2] - c[0]*v[2]; + tv[2] = c[0]*v[1] - v[0]*c[1]; + return tv; + } + Type dot(const _CVector & v) const { + Type tv(0); + PIMV_FOR tv += c[i] * v[i]; + return tv; + } + _CVector mul(const _CVector & v) const { + _CVector tv(*this); + PIMV_FOR tv[i] *= v[i]; + return tv; + } + _CVector mul(const Type & v) const { + return (*this) * v; + } + _CVector div(const _CVector & v) const { + _CVector tv(*this); + PIMV_FOR { + assert(piAbs(v[i]) > PIMATHVECTOR_ZERO_CMP); + tv[i] /= v[i]; + } + return tv; + } + _CVector div(const Type & v) const { + return (*this) / v; + } + PIMathMatrixT<1, Size, Type> transposed() const { PIMathMatrixT<1, Size, Type> ret; - PIMV_FOR(i, 0) ret[0][i] = c[i]; + PIMV_FOR ret[0][i] = c[i]; return ret; } Type distToLine(const _CVector & lp0, const _CVector & lp1) { - _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); - Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length(); - return f;} + _CVector a(lp0, lp1); + Type tv = a.length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + _CVector b(lp0, *this); + return piAbs(a[0]*b[1] - a[1]*b[0]) / tv; + } template /// vector {Size, Type} to vector {Size1, Type1} - PIMathVectorT turnTo() const {PIMathVectorT tv; uint sz = piMin(Size, Size1); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} + PIMathVectorT turnTo() const { + PIMathVectorT tv; + uint sz = piMin(Size, Size1); + for (uint i = 0; i < sz; ++i) tv[i] = c[i]; + return tv; + } - static _CVector filled(const Type & v) {_CVector vv; PIMV_FOR(i, 0) vv[i] = v; return vv;} + static _CVector cross(const _CVector & v1, const _CVector & v2) { + return v1.cross(v2); + } + static _CVector dot(const _CVector & v1, const _CVector & v2) { + return v1.dot(v2); + } + static _CVector mul(const _CVector & v1, const _CVector & v2) { + return v1.mul(v2); + } + static _CVector mul(const Type & v1, const _CVector & v2) { + return v2 * v1; + } + static _CVector mul(const _CVector & v1, const Type & v2) { + return v1 * v2; + } + static _CVector div(const _CVector & v1, const _CVector & v2) { + return v1.div(v2); + } + static _CVector div(const _CVector & v1, const Type & v2) { + return v1 / v2; + } private: - void resize(const Type & new_value = Type()) {for (uint i = 0; i < Size; ++i) c[i] = new_value;} - Type c[Size]; }; @@ -117,25 +234,8 @@ inline PIMathVectorT operator *(const Type & x, const PIMathVectorT< } template -inline PICout operator <<(PICout s, const PIMathVectorT & v) {s << "{"; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << "}"; return s;} -template -inline bool operator ||(const PIMathVectorT & f, const PIMathVectorT & s) {return (f * s).isNull();} -template -inline PIMathVectorT sqrt(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqrt(v[i]);} return ret;} -template -inline PIMathVectorT sqr(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;} +inline PICout operator <<(PICout s, const PIMathVectorT & v) {s << "{"; PIMV_FOR {s << v[i]; if (i < Size - 1) s << ", ";} s << "}"; return s;} -template -inline PIByteArray & operator <<(PIByteArray & s, const PIMathVectorT & v) {for (uint i = 0; i < Size; ++i) s << v[i]; return s;} -template -inline PIByteArray & operator >>(PIByteArray & s, PIMathVectorT & v) {for (uint i = 0; i < Size; ++i) s >> v[i]; return s;} - -template -inline PIMathVectorT<2u, T> createVectorT2(T x, T y) {return PIMathVectorT<2u, T>(PIVector() << x << y);} -template -inline PIMathVectorT<3u, T> createVectorT3(T x, T y, T z) {return PIMathVectorT<3u, T>(PIVector() << x << y << z);} -template -inline PIMathVectorT<4u, T> createVectorT4(T x, T y, T z, T w) {return PIMathVectorT<4u, T>(PIVector() << x << y << z << w);} typedef PIMathVectorT<2u, int> PIMathVectorT2i; typedef PIMathVectorT<3u, int> PIMathVectorT3i; @@ -143,21 +243,13 @@ typedef PIMathVectorT<4u, int> PIMathVectorT4i; typedef PIMathVectorT<2u, double> PIMathVectorT2d; typedef PIMathVectorT<3u, double> PIMathVectorT3d; typedef PIMathVectorT<4u, double> PIMathVectorT4d; -#define createVectorT2i createVectorT2 -#define createVectorT3i createVectorT3 -#define createVectorT4i createVectorT4 -#define createVectorT2f createVectorT2 -#define createVectorT3f createVectorT3 -#define createVectorT4f createVectorT4 -#define createVectorT2d createVectorT2 -#define createVectorT3d createVectorT3 -#define createVectorT4d createVectorT4 + #undef PIMV_FOR /// Vector -#define PIMV_FOR(v, s) for (uint v = s; v < c.size(); ++v) +#define PIMV_FOR for (uint i = 0; i < c.size(); ++i) template class PIP_EXPORT PIMathVector { @@ -165,73 +257,228 @@ class PIP_EXPORT PIMathVector { template friend PIByteArray & operator <<(PIByteArray & s, const PIMathVector & v); template friend PIByteArray & operator >>(PIByteArray & s, PIMathVector & v); public: - PIMathVector(const uint size = 0) {c.resize(size);} - PIMathVector(const PIVector & val) {c.resize(val.size()); PIMV_FOR(i, 0) c[i] = val[i];} - PIMathVector(const _CVector & st, const _CVector & fn) {c.resize(st.size()); PIMV_FOR(i, 0) c[i] = fn[i] - st[i];} + PIMathVector(const uint size = 0, const Type & new_value = Type()) {c.resize(size, new_value);} + PIMathVector(const PIVector & val) {c = val;} + PIMathVector(std::initializer_list init_list) {c = PIVector(init_list);} - uint size() const {return c.size();} - _CVector & resize(uint size, const Type & new_value = Type()) {c.resize(size, new_value); return *this;} - _CVector resized(uint size, const Type & new_value = Type()) {_CVector tv = _CVector(*this); tv.resize(size, new_value); return tv;} - _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} - _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} - _CVector & swap(uint fe, uint se) {piSwap(c[fe], c[se]); return *this;} - Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} - Type length() const {return sqrt(lengthSqr());} - Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} - Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} - Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} - Type angleRad(const _CVector & v) const {return acos(angleCos(v));} - Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} - _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} - _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} - _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} - bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} - bool isValid() const {return !c.isEmpty();} + template + PIMathVector(const PIMathVectorT & val) {c.resize(Size); PIMV_FOR c[i] = val[i];} - bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} - - Type & at(uint index) {return c[index];} - Type at(uint index) const {return c[index];} - Type & operator [](uint index) {return c[index];} - Type operator [](uint index) const {return c[index];} - _CVector & operator =(const _CVector & v) {c = v.c; return *this;} - _CVector & operator =(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} - bool operator !=(const _CVector & v) const {return !(*this == c);} - void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} - void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} - void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} - void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} - void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} - void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} - _CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} - _CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} - _CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} - _CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} - _CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} - _CVector operator *(const _CVector & v) const {if (c.size() < 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} - _CVector operator &(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v[i]; return tv;} - Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} - - Type distToLine(const _CVector & lp0, const _CVector & lp1) { - _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); - Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length(); - return f; + static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) { + assert(st.size() == fn.size()); + _CVector v(st.size()); + for (uint i = 0; i < v.size(); ++i) v.c[i] = fn[i] - st[i]; + } + + uint size() const {return c.size();} + _CVector & resize(uint size, const Type & new_value = Type()) { + c.resize(size, new_value); + return *this; + } + _CVector resized(uint size, const Type & new_value = Type()) { + _CVector tv = _CVector(*this); + tv.resize(size, new_value); + return tv; + } + _CVector & fill(const Type & v) { + c.fill(v); + return *this; + } + _CVector & move(const Type & v) { + PIMV_FOR c[i] += v; + return *this; + } + _CVector & move(const _CVector & v) { + assert(c.size() == v.size()); + PIMV_FOR c[i] += v[i]; + return *this; + } + _CVector & swapElements(uint f, uint s) { + piSwap(c[f], c[s]); + return *this; + } + Type lengthSqr() const { + Type tv(0); + PIMV_FOR tv += c[i] * c[i]; + return tv; + } + Type length() const {return std::sqrt(lengthSqr());} + Type manhattanLength() const { + Type tv(0); + PIMV_FOR tv += piAbs(c[i]); + return tv; + } + Type angleCos(const _CVector & v) const { + assert(c.size() == v.size()); + Type tv = v.length() * length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + return dot(v) / tv; + } + Type angleSin(const _CVector & v) const { + assert(c.size() == v.size()); + Type tv = angleCos(v); + return std::sqrt(Type(1) - tv * tv); + } + Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));} + Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));} + _CVector projection(const _CVector & v) { + assert(c.size() == v.size()); + Type tv = v.length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + return v * (dot(v) / tv); + } + _CVector & normalize() { + Type tv = length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + if (tv == Type(1)) return *this; + PIMV_FOR c[i] /= tv; + return *this; + } + _CVector normalized() { + _CVector tv(*this); + tv.normalize(); + return tv; + } + bool isNull() const { + PIMV_FOR if (c[i] != Type(0)) return false; + return true; + } + bool isValid() const {return !c.isEmpty();} + bool isOrtho(const _CVector & v) const {return dot(v) == Type(0);} + + Type & operator [](uint index) {return c[index];} + const Type & operator [](uint index) const {return c[index];} + Type at(uint index) const {return c[index];} + + _CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;} + + bool operator ==(const _CVector & v) const {return c == v.c;} + bool operator !=(const _CVector & v) const {return c != v.c;} + + void operator +=(const _CVector & v) { + assert(c.size() == v.size()); + PIMV_FOR c[i] += v[i]; + } + void operator -=(const _CVector & v) { + assert(c.size() == v.size()); + PIMV_FOR c[i] -= v[i]; + } + void operator *=(const Type & v) {PIMV_FOR c[i] *= v;} + void operator /=(const Type & v) { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + PIMV_FOR c[i] /= v; + } + _CVector operator -() const { + _CVector tv(c.size()); + PIMV_FOR tv[i] = -c[i]; + return tv; + } + _CVector operator +(const _CVector & v) const { + assert(c.size() == v.size()); + _CVector tv(*this); + PIMV_FOR tv[i] += v[i]; + return tv; + } + _CVector operator -(const _CVector & v) const { + assert(c.size() == v.size()); + _CVector tv(*this); + PIMV_FOR tv[i] -= v[i]; + return tv; + } + _CVector operator *(const Type & v) const { + _CVector tv(*this); + PIMV_FOR tv[i] *= v; + return tv; + } + _CVector operator /(const Type & v) const { + assert(piAbs(v) > PIMATHVECTOR_ZERO_CMP); + _CVector tv(*this); + PIMV_FOR tv[i] /= v; + return tv; + } + _CVector cross(const _CVector & v) const { + assert(c.size() == 3); + assert(v.size() == 3); + _CVector tv(3); + tv[0] = c[1]*v[2] - v[1]*c[2]; + tv[1] = c[2]*v[0] - v[2]*c[0]; + tv[2] = c[0]*v[1] - v[0]*c[1]; + return tv; + } + Type dot(const _CVector & v) const { + assert(c.size() == v.size()); + Type tv(0); + PIMV_FOR tv += c[i] * v[i]; + return tv; + } + _CVector mul(const _CVector & v) const { + assert(c.size() == v.size()); + _CVector tv(*this); + PIMV_FOR tv[i] *= v[i]; + return tv; + } + _CVector mul(const Type & v) const { + return (*this) * v; + } + _CVector div(const _CVector & v) const { + assert(c.size() == v.size()); + _CVector tv(*this); + PIMV_FOR { + assert(piAbs(v[i]) > PIMATHVECTOR_ZERO_CMP); + tv[i] /= v[i]; + } + return tv; + } + _CVector div(const Type & v) const { + return (*this) / v; + } + + Type distToLine(const _CVector & lp0, const _CVector & lp1) { + assert(c.size() == lp0.size()); + assert(c.size() == lp1.size()); + _CVector a = _CVector::fromTwoPoints(lp0, lp1); + Type tv = a.length(); + assert(piAbs(tv) > PIMATHVECTOR_ZERO_CMP); + _CVector b = _CVector::fromTwoPoints(lp0, *this); + return piAbs(a[0]*b[1] - a[1]*b[0]) / tv; } - template - PIMathVector turnTo(uint size) const {PIMathVector tv; uint sz = piMin(c.size(), size); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} PIVector toVector() const {return c;} inline Type * data() {return c.data();} inline const Type * data() const {return c.data();} + + static _CVector cross(const _CVector & v1, const _CVector & v2) { + return v1.cross(v2); + } + static _CVector dot(const _CVector & v1, const _CVector & v2) { + return v1.dot(v2); + } + static _CVector mul(const _CVector & v1, const _CVector & v2) { + return v1.mul(v2); + } + static _CVector mul(const Type & v1, const _CVector & v2) { + return v2 * v1; + } + static _CVector mul(const _CVector & v1, const Type & v2) { + return v1 * v2; + } + static _CVector div(const _CVector & v1, const _CVector & v2) { + return v1.div(v2); + } + static _CVector div(const _CVector & v1, const Type & v2) { + return v1 / v2; + } private: PIVector c; - }; +template +inline PIMathVector operator *(const Type & x, const PIMathVector & v) { + return v * x; +} + #undef PIMV_FOR #ifdef PIP_STD_IOSTREAM diff --git a/libs/main/math/piquaternion.cpp b/libs/main/math/piquaternion.cpp index 5ea23fe9..d71c5389 100644 --- a/libs/main/math/piquaternion.cpp +++ b/libs/main/math/piquaternion.cpp @@ -40,7 +40,7 @@ PIMathVectorT3d PIQuaternion::eyler() const { angle_z = atan2(-rmat[0][1] / c, rmat[0][0] / c); } if (angle_z < 0) angle_z = 2*M_PI + angle_z; - return createVectorT3d(angle_x,angle_y,angle_z); + return PIMathVectorT3d({angle_x,angle_y,angle_z}); } @@ -96,16 +96,6 @@ void PIQuaternion::normalize() { } -PIMathMatrixT44d PIQuaternion::makeMatrix() const { - PIMathMatrixT44d ret; - ret[0][0] = q[0]; ret[0][1] = -q[1]; ret[0][2] = -q[2]; ret[0][3] = -q[3]; - ret[1][0] = q[1]; ret[1][1] = q[0]; ret[1][2] = -q[3]; ret[1][3] = q[2]; - ret[2][0] = q[2]; ret[2][1] = q[3]; ret[2][2] = q[0]; ret[2][3] = -q[1]; - ret[3][0] = q[3]; ret[3][1] = -q[2]; ret[3][2] = q[1]; ret[3][3] = q[0]; - return ret; -} - - PIQuaternion PIQuaternion::fromEyler(double ax, double ay, double az) { PIQuaternion q_heading; PIQuaternion q_pinch; @@ -153,7 +143,7 @@ PIQuaternion PIQuaternion::fromAngles(double ax, double ay, double az) { } PIQuaternion PIQuaternion::fromAngles2(double ax, double ay, double az) { - double om = createVectorT3d(ax,ay,az).length(); + double om = PIMathVectorT3d({ax,ay,az}).length(); if (om == 0.) return PIQuaternion(PIMathVectorT3d(), 1.); PIQuaternion res; res.q[0] = cos(om/2); @@ -199,8 +189,8 @@ PIQuaternion PIQuaternion::fromRotationMatrix(const PIMathMatrixT33d & m) { PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1) { PIMathVectorT3d v0(q0.vector()), v1(q1.vector()); - double r0 = q0.q[0] * q1.q[0] - (v0^v1); - PIMathVectorT3d qv = v1*q0.q[0] + v0*q1.q[0] + v0*v1; + double r0 = q0.q[0] * q1.q[0] - v0.dot(v1); + PIMathVectorT3d qv = v1*q0.q[0] + v0*q1.q[0] + v0.cross(v1); PIQuaternion ret; ret.q[0] = r0; ret.q[1] = qv[0]; diff --git a/libs/main/math/piquaternion.h b/libs/main/math/piquaternion.h index e9b79e92..4cfb6f1f 100644 --- a/libs/main/math/piquaternion.h +++ b/libs/main/math/piquaternion.h @@ -39,7 +39,7 @@ public: double & scalar() {return q[0];} double scalar() const {return q[0];} - PIMathVectorT3d vector() const {return createVectorT3(q[1], q[2], q[3]);} + PIMathVectorT3d vector() const {return PIMathVectorT3d({q[1], q[2], q[3]});} PIMathVectorT3d eyler() const; PIMathMatrixT33d rotationMatrix() const; @@ -52,9 +52,6 @@ public: protected: double q[4]; - PIMathMatrixT44d makeMatrix() const; - - }; PIP_EXPORT PIQuaternion operator *(const double & a, const PIQuaternion & q); diff --git a/libs/main/opencl/piopencl.h b/libs/main/opencl/piopencl.h index 51be9a6a..5c531054 100644 --- a/libs/main/opencl/piopencl.h +++ b/libs/main/opencl/piopencl.h @@ -31,11 +31,13 @@ public: struct Device; struct Platform; class Context; + class Buffer; class Program; class Kernel; typedef PIVector DeviceList; + enum AddressQualifier { AddressGlobal, AddressLocal, @@ -50,6 +52,12 @@ public: AccessNone, }; + enum Direction { + Input = 0x01, + Output = 0x02, + InputOutput = Input | Output, + }; + enum TypeQualifier { TypeConst, TypeRestrict, @@ -70,10 +78,12 @@ public: Double, }; + struct PIP_OPENCL_EXPORT KernelArg { KernelArg(); AddressQualifier address_qualifier; AccessQualifier access_qualifier; + Direction direction; TypeQualifier type_qualifier; PIString arg_name; PIString type_name; @@ -86,6 +96,7 @@ public: void init(void * _k, uint index); }; + struct PIP_OPENCL_EXPORT Device { Device() {id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0;} bool isValid() const {return id != 0;} @@ -101,6 +112,7 @@ public: ullong max_memory_size; }; + struct PIP_OPENCL_EXPORT Platform { Platform() {id = 0;} bool isValid() const {return id != 0;} @@ -114,28 +126,86 @@ public: PIVector devices; }; + class PIP_OPENCL_EXPORT Context { + friend class Buffer; friend class Program; + friend class Kernel; public: ~Context(); static Context * create(const DeviceList & dl); static Context * create(const Device & d) {return create(DeviceList() << d);} + static Context * create(const PIString & part_name); Program * createProgram(const PIString & source, PIString * error = 0); + template Buffer * createBuffer(PIOpenCL::Direction dir, PIVector & container) { + T def = T(); + return createBuffer(dir, &container, Buffer::cVector , PIByteArray(&def, sizeof(T)), container.size()); + } + template Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque & container) { + T def = T(); + return createBuffer(dir, &container, Buffer::cDeque , PIByteArray(&def, sizeof(T)), container.size()); + } + template Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D & container) { + T def = T(); + return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size()); + } + template Buffer * createBuffer(PIOpenCL::Direction dir, uint elements) { + T def = T(); + Buffer * ret = createBuffer(dir, 0, Buffer::cNone, PIByteArray(&def, sizeof(T)), elements); + if (ret) + ret->clear(); + return ret; + } private: Context(); void zero(); void deletePrograms(); + void deleteBuffers(); + Buffer * createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements); PIVector programs_; + PIVector buffers_; PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; + + class PIP_OPENCL_EXPORT Buffer { + friend class Context; + friend class Kernel; + public: + ~Buffer(); + bool resize(uint new_elements); + void clear(); + void copyToContainer(); + void copyFromContainer(); + private: + enum Container { + cNone, + cVector, + cDeque, + cVector2D, + }; + Buffer(); + void zero(); + bool init(); + void * containerData(); + Context * context_; + Direction dir; + Container type; + void * container; + PIByteArray def; + uint elements; + PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) + }; + + class PIP_OPENCL_EXPORT Program { friend class Context; friend class Kernel; + friend class Buffer; public: ~Program(); const PIString & sourceCode() const {return source_;} - const Kernel * kernel(int index = 0) const {return kernels_[index];} + Kernel * kernel(int index = 0) const {return kernels_[index];} const PIVector & kernels() const {return kernels_;} private: Program(); @@ -147,28 +217,38 @@ public: PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; + class PIP_OPENCL_EXPORT Kernel { friend class Program; + friend class Buffer; public: + bool execute(); + void setExecuteRange(int size) {setExecuteRanges(PIVector() << size);} + void setExecuteRanges(const PIVector & ranges); const PIString & name() const {return name_;} const PIVector & args() const {return args_;} - template bool setArgValue(int index, const T & value) {return setArgValueV(index, PIVariant::fromValue(value));} + template bool setArgValue(int index, const T & value) {return setArgValueS(index, PIVariant::fromValue(value));} template bool setArgValue(const PIString & arg, const T & value) {return setArgValue(argIndex(arg), value);} + bool setArgValue(const PIString & arg, const PIVariant & value) {return setArgValueS(argIndex(arg), value);} + bool bindArgValue(int index, Buffer * buffer); + bool bindArgValue(const PIString & arg, Buffer * buffer) {return bindArgValue(argIndex(arg), buffer);} private: Kernel(); ~Kernel(); void zero(); bool init(); - bool setArgValueV(int index, const PIVariant & value); + bool setArgValueS(int index, const PIVariant & value); int argIndex(const PIString & an) const; KernelArg argByName(const PIString & an) const; Context * context_; Program * program_; PIString name_; PIVector args_; + PIVector dims; PRIVATE_DECLARATION(PIP_OPENCL_EXPORT) }; + static void init(); static const PIVector & platforms(); static const PIVector devices(); @@ -189,7 +269,7 @@ private: }; -PICout operator <<(PICout s, const PIOpenCL::KernelArg & v); +PIP_OPENCL_EXPORT PICout operator <<(PICout s, const PIOpenCL::KernelArg & v); #endif // PIOPENCL_H diff --git a/libs/main/system/pilibrary.h b/libs/main/system/pilibrary.h index 581fa5d1..17b61dc3 100644 --- a/libs/main/system/pilibrary.h +++ b/libs/main/system/pilibrary.h @@ -1,3 +1,6 @@ +/*! \file pilibrary.h +* \brief Dynamic library +*/ /* PIP - Platform Independent Primitives Dynamic library diff --git a/libs/main/system/piplugin.cpp b/libs/main/system/piplugin.cpp new file mode 100644 index 00000000..ed91f87d --- /dev/null +++ b/libs/main/system/piplugin.cpp @@ -0,0 +1,398 @@ +/* + PIP - Platform Independent Primitives + Plugin helpers + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PIP_FREERTOS + +#include "piplugin.h" +#include "pifile.h" +#include "piincludes_p.h" + +/*! \class PIPluginLoader + * \brief Plugin loader + * + * \section PIPluginLoader_sec0 Synopsis + * This class provides several macro to define plugin and %PIPluginLoader - class + * to load and check plugin. + * + * \section PIPluginLoader_sec1 Plugin side + * Plugin is a shared library that can be loaded in run-time. + * This is only PIP_PLUGIN macro necessary to define plugin. + * If you want to set and check some version, use macro + * \a PIP_PLUGIN_SET_USER_VERSION(version). Also you can + * define a function to merge static sections between application + * and plugin with macro \a PIP_PLUGIN_STATIC_SECTION_MERGE. Before + * merge, you should set pointers to that sections with macro + * \a PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr). + * + * \section PIPluginLoader_sec2 Application side + * Application should use class \a PIPluginLoader to load + * plugin. Main function is \a load(PIString name). + * "name" is base name of library, %PIPluginLoader + * try to use sevaral names, , lib and + * "dll", "so" and "dylib" extensions, depends on system. + * For example: + * \code + * PIPluginLoader l; + * l.load("foo"); + * \endcode + * On Windows, try to open "foo", "libfoo", "foo.dll" and + * "libfoo.dll". + * If you using user version check, you should set it + * with macro \a PIP_PLUGIN_SET_USER_VERSION(version). + * When plugin is successfully loaded and checked, + * you can load your custom symbols with function + * \a resolve(name), similar to PILibrary. + * \note You should use PIP_PLUGIN_EXPORT and "export "C"" + * with functions you want to use with \a resolve(name)! + * + * \section PIPluginLoader_sec3 Static sections + * Macro \a PIP_PLUGIN_STATIC_SECTION_MERGE defines function + * with arguments (int type, void * from, void * to), so you + * can leave this macro as declaration or define its body next: + * \code + * PIP_PLUGIN_STATIC_SECTION_MERGE() { + * switch (type) { + * ... + * } + * } + * \endcode + * \note If you using singletones, remember that cpp-defined + * singletones in shared libraries are single for whole application, + * including plugins! But if you use h-defined singletones or + * static linking, there are many objects in application and you + * should merge their content with this macro. + * + * Anyway, if this is macro \a PIP_PLUGIN_STATIC_SECTION_MERGE, it + * called once while loading plugin with "from" - plugin side + * and "to" - application side, and second (optionally) on method + * \a mergeStatic() with "from" - application side and "to" - plugin side. + * First direction allow you to copy all defined static content from plugin + * to application, and second - after loading all plugins (for example) + * to copy static content from application (and all plugins) to plugin. + * + * \section PIPluginLoader_sec4 Examples + * Simple plugin: + * \code + * #include + * + * PIP_PLUGIN + * + * extern "C" { + * PIP_PLUGIN_EXPORT void myFunc() { + * piCout << "Hello plugin!"; + * } + * } + * \endcode + * + * Application: + * \code + * #include + * int main() { + * PIPluginLoader pl; + * pl.load("your_lib"); + * if (pl.isLoaded()) { + * typedef void(*MyFunc)(); + * MyFunc f = (MyFunc)pl.resolve("myFunc"); + * if (f) f(); + * } + * return 0; + * } + * \endcode + * + * Complex plugin: + * \code + * #include + * + * PIStringList global_list; + * + * PIP_PLUGIN + * PIP_PLUGIN_SET_USER_VERSION("1.0.0") + * PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list) + * + * STATIC_INITIALIZER_BEGIN + * global_list << "plugin_init"; + * STATIC_INITIALIZER_END + * + * PIP_PLUGIN_STATIC_SECTION_MERGE { + * PIStringList * sfrom = (PIStringList*)from, * sto = (PIStringList*)to; + * *sto << *sfrom; + * sto->removeDuplicates(); + * } + * \endcode + * + * Application: + * \code + * #include + * + * PIStringList global_list; + * + * PIP_PLUGIN_SET_USER_VERSION("1.0.0"); + * PIP_PLUGIN_ADD_STATIC_SECTION(1, &global_list); + * + * int main() { + * global_list << "app"; + * PIPluginLoader pl; + * pl.load("your_lib"); + * pl.mergeStatic(); + * piCout << "list =" << global_list; + * return 0; + * } + * \endcode + * + */ + +#define STR_WF(s) #s +#define STR(s) STR_WF(s) + + +PIPluginInfo::PIPluginInfo() { +} + + +void PIPluginInfo::setUserVersion(const PIString & v) { + user_version = v; +} + + +void PIPluginInfo::setStaticSection(int type, void * ptr) { + static_sections[type] = ptr; +} + + +PIString PIPluginInfo::userVersion() const { + return user_version; +} + + +PIMap PIPluginInfo::staticSections() const { + return static_sections; +} + + + + + +PIPluginInfoStorage::PIPluginInfoStorage() { + enterPlugin(0); +} + + +PIPluginInfo * PIPluginInfoStorage::currentInfo() { + return info[current]; +} + + +PIPluginInfo * PIPluginInfoStorage::pluginInfo(void * p) { + return info.value(p, nullptr); +} + + +PIPluginInfo * PIPluginInfoStorage::applicationInfo() { + return info[0]; +} + + +PIPluginInfo * PIPluginInfoStorage::enterPlugin(void * p) { + current = p; + PIPluginInfo *& i(info[p]); + if (!i) i = new PIPluginInfo(); + return i; +} + + +void PIPluginInfoStorage::unloadPlugin(void * p) { + if (current == p) current = 0; + PIPluginInfo *& i(info[p]); + if (i) delete i; + info.remove(p); +} + + +PIPluginInfoStorage * PIPluginInfoStorage::instance() { + static PIPluginInfoStorage ret; + return &ret; +} + + + + +PIPluginLoader::PIPluginLoader(const PIString & name) { + func_loader_version = nullptr; + func_static_merge = nullptr; + error = Unknown; + loaded = false; + messages = true; + if (!name.isEmpty()) + load(name); +} + + +PIPluginLoader::~PIPluginLoader() { + unload(); +} + + +bool PIPluginLoader::load(const PIString & name) { + unload(); + PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo(); + PIPluginInfo * pi = PIPluginInfoStorage::instance()->enterPlugin(this); + if (!lib.load(findLibrary(name))) { + unload(); + error = LibraryLoadError; + error_str = "Load plugin \"" + lib.path() + "\" error: can`t load lib: " + lib.lastError(); + if (messages) piCout << error_str; + return false; + } + //piCout << "loading" << lib.path() << "..."; + func_loader_version = (FunctionLoaderVersion)lib.resolve(STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__)); + if (!func_loader_version) { + unload(); + error = MissingSymbols; + error_str = "Load plugin \"" + lib.path() + "\" error: can`t find " + STR(__PIP_PLUGIN_LOADER_VERSION_FUNC__); + if (messages) piCout << error_str; + return false; + } + if (__PIP_PLUGIN_LOADER_VERSION__ != func_loader_version()) { + unload(); + error = InvalidLoaderVersion; + error_str = "Load plugin \"" + lib.path() + "\" error: invalid loader version: application = " + PIString::fromNumber(func_loader_version()) + + ", plugin = " + PIString::fromNumber(__PIP_PLUGIN_LOADER_VERSION__); + if (messages) piCout << error_str; + return false; + } + if (ai->userVersion().size_s() > 1) { + PIString pversion = pi->userVersion(), lversion = ai->userVersion(); + if (pversion != lversion) { + unload(); + error = InvalidUserVersion; + error_str = "Load plugin \"" + lib.path() + "\" error: invalid user version: application = " + lversion + ", plugin = " + pversion; + if (messages) piCout << error_str; + return false; + } + } + func_static_merge = (FunctionStaticMerge)lib.resolve(STR(__PIP_PLUGIN_STATIC_MERGE_FUNC__)); + if (func_static_merge) { + auto pss = pi->staticSections(), lss = ai->staticSections(); + //piCout << lss.keys() << pss.keys(); + auto it = lss.makeIterator(); + while (it.next()) { + if (!pss.contains(it.key())) + continue; + void * from = pss.value(it.key()), * to = it.value(); + if (from != to) + func_static_merge(it.key(), from, to); + } + } + loaded = true; + error = NoError; + return true; +} + + +void PIPluginLoader::unload() { + lib.unload(); + loaded = false; + error_str.clear(); + error = Unknown; + PIPluginInfoStorage::instance()->unloadPlugin(this); +} + + +bool PIPluginLoader::isLoaded() const { + return loaded; +} + + +PIPluginLoader::Error PIPluginLoader::lastError() const { + return error; +} + + +PIString PIPluginLoader::lastErrorText() const { + return error_str; +} + + +void PIPluginLoader::setMessages(bool yes) { + messages = yes; +} + + +bool PIPluginLoader::isMessages() const { + return messages; +} + + +PIString PIPluginLoader::libPath() { + return lib.path(); +} + + +void * PIPluginLoader::resolve(const char * name) { + if (!loaded) return nullptr; + return lib.resolve(name); +} + + +void PIPluginLoader::mergeStatic() { + if (!loaded || !func_static_merge) return; + PIPluginInfo * ai = PIPluginInfoStorage::instance()->applicationInfo(); + PIPluginInfo * pi = PIPluginInfoStorage::instance()->pluginInfo(this); + auto pss = pi->staticSections(), lss = ai->staticSections(); + auto it = lss.makeIterator(); + while (it.next()) { + if (!pss.contains(it.key())) + continue; + void * from = it.value(), * to = pss.value(it.key()); + if (from != to) + func_static_merge(it.key(), from, to); + } +} + + +PIString PIPluginLoader::findLibrary(const PIString & path) { + static const PIStringList prefixes({"", "lib"}); + static const PIStringList suffixes({"", libExtension()}); + PIFile::FileInfo fi(path); + PIString dir = fi.dir(), name = fi.name(); + piForeachC (PIString & p, prefixes) { + piForeachC (PIString & s, suffixes) { + PIString fn = dir + p + name + s; + if (PIFile::isExists(fn)) + return fn; + } + } + return PIString(); +} + + +PIString PIPluginLoader::libExtension() { + return +#ifdef WINDOWS + ".dll" +#elif defined(MAC_OS) + ".dylib" +#else + ".so" +#endif + ; +} + + +#endif // PIP_FREERTOS diff --git a/libs/main/system/piplugin.h b/libs/main/system/piplugin.h new file mode 100644 index 00000000..9e75c534 --- /dev/null +++ b/libs/main/system/piplugin.h @@ -0,0 +1,214 @@ +/*! \file piplugin.h +* \brief Plugin helpers +*/ +/* + PIP - Platform Independent Primitives + Plugin helpers + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PIPLUGIN_H +#define PIPLUGIN_H + +#ifndef PIP_FREERTOS + +#include "pilibrary.h" +#include "pistringlist.h" + +#ifdef DOXYGEN + + +//! Declare plugin export functions, should be used before other PIP_PLUGIN_* macros +//! \relatedalso PIPluginLoader +#define PIP_PLUGIN + +//! Set user version to check it while loading +//! \relatedalso PIPluginLoader +#define PIP_PLUGIN_SET_USER_VERSION(version) + +//! Add pointer to future merge with plugin. Type is integer +//! \relatedalso PIPluginLoader +#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) + +//! Declare function to merge static sections. This is functions +//! with 3 arguments: (int type, void * from, void * to). +//! This function invoked first while loading plugin with +//! "from" - plugin scope, "to" - application scope, and second +//! (optionally) on \a PIPluginLoader::mergeStatic() method with +//! "from" - application scope, "to" - plugin scope. So with macro +//! you can merge application and plugin static data. +//! \relatedalso PIPluginLoader +#define PIP_PLUGIN_STATIC_SECTION_MERGE + +//! Mark method to export +//! \relatedalso PIPluginLoader +#define PIP_PLUGIN_EXPORT + + +#else + + +#ifdef WINDOWS +# define PIP_PLUGIN_EXPORT __declspec(dllexport) +#else +# define PIP_PLUGIN_EXPORT +#endif + +#define __PIP_PLUGIN_LOADER_VERSION_FUNC__ pip_loader_version +#define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static +#define __PIP_PLUGIN_LOADER_VERSION__ 2 + +#define PIP_PLUGIN_SET_USER_VERSION(v) \ + STATIC_INITIALIZER_BEGIN \ + PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \ + if (pi) pi->setUserVersion(v); \ + STATIC_INITIALIZER_END + +#define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \ + STATIC_INITIALIZER_BEGIN \ + PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \ + if (pi) pi->setStaticSection(type, ptr); \ + STATIC_INITIALIZER_END + +#define PIP_PLUGIN \ + extern "C" { \ + PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() {return __PIP_PLUGIN_LOADER_VERSION__;} \ + } + +#define PIP_PLUGIN_STATIC_SECTION_MERGE \ + extern "C" { \ + PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \ + } \ + void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to) + + +#endif + + + +class PIP_EXPORT PIPluginInfo { +public: + PIPluginInfo(); + + void setUserVersion(const PIString & v); + void setStaticSection(int type, void * ptr); + PIString userVersion() const; + PIMap staticSections() const; + +private: + PIString user_version; + PIMap static_sections; + +}; + + + +class PIP_EXPORT PIPluginInfoStorage { +public: + PIPluginInfoStorage(); + + PIPluginInfo * currentInfo(); + PIPluginInfo * pluginInfo(void * p); + PIPluginInfo * applicationInfo(); + PIPluginInfo * enterPlugin(void * p); + void unloadPlugin(void * p); + + static PIPluginInfoStorage * instance(); + +private: + NO_COPY_CLASS(PIPluginInfoStorage) + + void * current; + PIMap info; + +}; + + + + +class PIP_EXPORT PIPluginLoader { +public: + typedef int(*FunctionLoaderVersion)(); + typedef void(*FunctionStaticMerge)(int, void *, void *); + + //! Possible load plugin error + enum Error { + Unknown /** No \a load call yet */ , + NoError /** No error */ , + LibraryLoadError /** System can`t load library */ , + MissingSymbols /** Can`t find necessary symbols */ , + InvalidLoaderVersion /** Integer version mismatch */ , + InvalidUserVersion /** User version mismatch */ , + }; + + //! Contruscts loader with filename "name" + PIPluginLoader(const PIString & name = PIString()); + + //! Destructor + ~PIPluginLoader(); + + + //! Load plugin with base filename "name". Loader try prefix "lib" + //! and suffix ".dll", ".so" or ".dylib", depends on platform + bool load(const PIString & name); + + //! Unload plugin and free library + void unload(); + + //! Returns if plugin is successfully loaded + bool isLoaded() const; + + //! Returns error of last \a load() call + Error lastError() const; + + //! Returns error message of last \a load() call + PIString lastErrorText() const; + + //! Set if %PIPluginLoader should print load messages, \b true by default + void setMessages(bool yes); + + //! Returns if %PIPluginLoader should print load messages, \b true by default + bool isMessages() const; + + //! Returns loaded plugin library path + PIString libPath(); + + //! Resolve symbol "name" from plugin library + void * resolve(const char * name); + + //! Invoke plugin PIP_PLUGIN_STATIC_SECTION_MERGE function + //! on every common type, with "from" - application scope, + //! "to" - plugin scope + void mergeStatic(); + +private: + NO_COPY_CLASS(PIPluginLoader) + + PIString findLibrary(const PIString & path); + static PIString libExtension(); + + PILibrary lib; + FunctionLoaderVersion func_loader_version; + FunctionStaticMerge func_static_merge; + PIString error_str; + Error error; + bool loaded, messages; + +}; + + +#endif // PIP_FREERTOS +#endif // PIPLUGIN_H diff --git a/libs/main/thread/piconditionvar.cpp b/libs/main/thread/piconditionvar.cpp index 9ad6538b..7eb476d9 100644 --- a/libs/main/thread/piconditionvar.cpp +++ b/libs/main/thread/piconditionvar.cpp @@ -35,7 +35,6 @@ PRIVATE_DEFINITION_START(PIConditionVariable) CONDITION_VARIABLE nativeHandle; #else pthread_cond_t nativeHandle; - PIMutex * currentLock; #endif bool isDestroying; PRIVATE_DEFINITION_END(PIConditionVariable) @@ -46,9 +45,14 @@ PIConditionVariable::PIConditionVariable() { InitializeConditionVariable(&PRIVATE->nativeHandle); #else PRIVATE->isDestroying = false; - PRIVATE->currentLock = nullptr; + + pthread_condattr_t condattr; + pthread_condattr_init(&condattr); +# ifndef MAC_OS + pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); +# endif memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); - pthread_cond_init(&PRIVATE->nativeHandle, NULL); + pthread_cond_init(&PRIVATE->nativeHandle, &condattr); #endif } @@ -90,8 +94,11 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { #ifdef WINDOWS isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; #else - timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs % 1000 * 1000000}; - isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; + timespec expire_ts; + PISystemTime st = PISystemTime::current(true); + st.addMilliseconds(timeoutMs); + st.toTimespec(&expire_ts); + isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0; #endif if (PRIVATE->isDestroying) return false; return isNotTimeout; @@ -100,7 +107,14 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function &condition) { bool isCondition; +#ifdef WINDOWS PITimeMeasurer measurer; +#else + timespec expire_ts; + PISystemTime st = PISystemTime::current(true); + st.addMilliseconds(timeoutMs); + st.toTimespec(&expire_ts); +#endif while (true) { isCondition = condition(); if (isCondition) break; @@ -110,9 +124,7 @@ bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::functio (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()) == 0; #else - int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); - timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr % 1000 * 1000000}; - bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) != 0; + bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; #endif if (isTimeout) return false; if (PRIVATE->isDestroying) return false; diff --git a/libs/main/thread/pimutex.cpp b/libs/main/thread/pimutex.cpp index 2c0a97b2..be259ed3 100644 --- a/libs/main/thread/pimutex.cpp +++ b/libs/main/thread/pimutex.cpp @@ -1,6 +1,6 @@ /* PIP - Platform Independent Primitives - Mutex + PIMutex, PIMutexLocker Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify @@ -105,7 +105,7 @@ void PIMutex::init() { pthread_mutexattr_t attr; memset(&attr, 0, sizeof(attr)); pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); memset(&(PRIVATE->mutex), 0, sizeof(PRIVATE->mutex)); pthread_mutex_init(&(PRIVATE->mutex), &attr); pthread_mutexattr_destroy(&attr); diff --git a/libs/main/thread/pimutex.h b/libs/main/thread/pimutex.h index a551625d..9165c725 100644 --- a/libs/main/thread/pimutex.h +++ b/libs/main/thread/pimutex.h @@ -1,9 +1,9 @@ /*! \file pimutex.h - * \brief PIMutexLocker + * \brief PIMutex, PIMutexLocker */ /* PIP - Platform Independent Primitives - PIMutexLocker + PIMutex, PIMutexLocker Ivan Pelipenko peri4ko@yandex.ru, Stephan Fomenko, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify diff --git a/libs/main/thread/pispinlock.cpp b/libs/main/thread/pispinlock.cpp new file mode 100644 index 00000000..3262f39b --- /dev/null +++ b/libs/main/thread/pispinlock.cpp @@ -0,0 +1,30 @@ +/* + PIP - Platform Independent Primitives + PISpinlock + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/** \class PISpinlock + * \brief Spinlock + * \details + * \section PISpinlock_sec0 Synopsis + * %PISpinlock provides synchronization blocks between several threads. + * PISpinlock functionality similar to PIMutex, but working on atomic + * type and \a lock() method wait with 100% CPU load. + * \note + * Use this type instead of PIMutex when less waiting time is more + * important than CPU load! + * */ diff --git a/libs/main/thread/pispinlock.h b/libs/main/thread/pispinlock.h new file mode 100644 index 00000000..6de315c4 --- /dev/null +++ b/libs/main/thread/pispinlock.h @@ -0,0 +1,75 @@ +/*! \file pispinlock.h + * \brief PISpinlock +*/ +/* + PIP - Platform Independent Primitives + PISpinlock + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PISPINLOCK_H +#define PISPINLOCK_H + +#include "piinit.h" +#include + + +class PIP_EXPORT PISpinlock +{ +public: + NO_COPY_CLASS(PISpinlock) + + //! Constructs unlocked spinlock + explicit PISpinlock() {flag.clear();} + + //! Destroy spinlock + ~PISpinlock() {} + + + //! \brief Lock spinlock + //! \details If spinlock is unlocked it set to locked state and returns immediate. + //! If spinlock is already locked function blocks until spinlock will be unlocked + void lock() {while (flag.test_and_set(std::memory_order_acquire));} + + //! \brief Unlock spinlock + //! \details In any case this function returns immediate + void unlock() {flag.clear(std::memory_order_release);} + +private: + std::atomic_flag flag; + +}; + + +//! \brief PISpinlockLocker +//! \details +//! When a PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true. +//! When control leaves the scope in which the PISpinlockLocker object was created, +//! the PISpinlockLocker is destructed and the spinlock is released, if "condition" true. +//! If "condition" false this class do nothing. +//! The PISpinlockLocker class is non-copyable. +class PIP_EXPORT PISpinlockLocker +{ +public: + NO_COPY_CLASS(PISpinlockLocker) + PISpinlockLocker(PISpinlock & s, bool condition = true): spinlock(s), cond(condition) {if (cond) spinlock.lock();} + ~PISpinlockLocker() {if (cond) spinlock.unlock();} +private: + PISpinlock & spinlock; + bool cond; +}; + +#endif // PISPINLOCK_H diff --git a/libs/main/thread/pithreadmodule.h b/libs/main/thread/pithreadmodule.h index 5973dfe4..cb1128e1 100644 --- a/libs/main/thread/pithreadmodule.h +++ b/libs/main/thread/pithreadmodule.h @@ -21,6 +21,7 @@ #define PITHREADMODULE_H #include "pimutex.h" +#include "pispinlock.h" #include "pithread.h" #include "pitimer.h" #include "pipipelinethread.h" diff --git a/libs/opencl/piopencl.cpp b/libs/opencl/piopencl.cpp index 8f7313c5..40ea7e19 100644 --- a/libs/opencl/piopencl.cpp +++ b/libs/opencl/piopencl.cpp @@ -15,6 +15,11 @@ PRIVATE_DEFINITION_START(PIOpenCL::Context) PRIVATE_DEFINITION_END(PIOpenCL::Context) +PRIVATE_DEFINITION_START(PIOpenCL::Buffer) + cl_mem buffer; +PRIVATE_DEFINITION_END(PIOpenCL::Buffer) + + PRIVATE_DEFINITION_START(PIOpenCL::Program) cl_program program; PRIVATE_DEFINITION_END(PIOpenCL::Program) @@ -141,6 +146,7 @@ PIOpenCL::Context::Context() { PIOpenCL::Context::~Context() { piCout << "destroy context" << this; deletePrograms(); + deleteBuffers(); if (PRIVATE->queue) clReleaseCommandQueue(PRIVATE->queue); if (PRIVATE->context) @@ -151,6 +157,7 @@ PIOpenCL::Context::~Context() { void PIOpenCL::Context::zero() { programs_.clear(); + buffers_.clear(); PRIVATE->context = 0; PRIVATE->queue = 0; PRIVATE->devices.clear(); @@ -158,7 +165,7 @@ void PIOpenCL::Context::zero() { void PIOpenCL::Context::deletePrograms() { - piCout << "context: delete" << programs_.size() << "progs"; + piCout << "context: delete" << programs_.size() << "programs"; PIVector ptdl = programs_; programs_.clear(); piForeach (Program * p, ptdl) { @@ -167,6 +174,16 @@ void PIOpenCL::Context::deletePrograms() { } +void PIOpenCL::Context::deleteBuffers() { + piCout << "context: delete" << buffers_.size() << "buffers"; + PIVector btdl = buffers_; + buffers_.clear(); + piForeach (Buffer * b, btdl) { + if (b) delete b; + } +} + + PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) { if (dl.isEmpty()) return 0; Context * rc = 0; @@ -195,6 +212,17 @@ PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) { } +PIOpenCL::Context * PIOpenCL::Context::create(const PIString & part_name) { + PIString pn = part_name.toLowerCase(); + PIVector dl = PIOpenCL::devices(); + piForeachC (Device & d, dl) { + if (d.displayText().toLowerCase().contains(pn)) + return create(d); + } + return 0; +} + + PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, PIString * error) { if (error) error->clear(); if (source.isEmpty()) { @@ -264,6 +292,105 @@ PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, PI } +PIOpenCL::Buffer * PIOpenCL::Context::createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements) { + Buffer * ret = new Buffer(); + ret->context_ = this; + ret->dir = dir; + ret->type = (Buffer::Container)type; + ret->container = container; + ret->def = def; + ret->elements = elements; + if (!ret->init()) { + delete ret; + return 0; + } + buffers_ << ret; + return ret; +} + + + + +PIOpenCL::Buffer::Buffer() { + zero(); +} + + +PIOpenCL::Buffer::~Buffer() { + if (context_) + context_->buffers_.removeAll(this); + if (PRIVATE->buffer) + clReleaseMemObject(PRIVATE->buffer); + zero(); +} + + +void PIOpenCL::Buffer::zero() { + type = cNone; + container = 0; + elements = 0; + PRIVATE->buffer = 0; +} + + +bool PIOpenCL::Buffer::init() { + cl_int ret = 0; + cl_mem_flags f = container ? CL_MEM_COPY_HOST_PTR : 0; + switch (dir) { + case Input : f |= CL_MEM_READ_ONLY ; break; + case Output : f |= CL_MEM_WRITE_ONLY; break; + case InputOutput: f |= CL_MEM_READ_WRITE; break; + default: break; + } + PRIVATE->buffer = clCreateBuffer(context_->PRIVATEWB->context, f, elements * def.size(), container ? containerData() : 0, &ret); + if (ret != 0) { + piCout << "[PIOpenCL::Buffer]" << "clCreateBuffer error" << ret; + return false; + } + return true; +} + + +void * PIOpenCL::Buffer::containerData() { + if (type == cNone || !container) return 0; + switch (type) { + case cVector : return ((PIVector *)container)->data(); + case cDeque : return ((PIDeque *)container)->data(); + case cVector2D: return ((PIVector2D*)container)->data(); + default: break; + } + return 0; +} + + +void PIOpenCL::Buffer::clear() { + if (!PRIVATE->buffer) return; + if (def.isEmpty() || elements == 0) return; + cl_int ret = clEnqueueFillBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, def.data(), def.size_s(), 0, elements * def.size(), 0, 0, 0); + if (ret != 0) { + piCout << "[PIOpenCL::Buffer]" << "clEnqueueFillBuffer error" << ret; + } +} + + +void PIOpenCL::Buffer::copyToContainer() { + if (!PRIVATE->buffer || !container) return; + cl_int ret = clEnqueueReadBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), containerData(), 0, 0, 0); + if (ret != 0) { + piCout << "[PIOpenCL::Buffer]" << "clEnqueueReadBuffer error" << ret; + } +} + + +void PIOpenCL::Buffer::copyFromContainer() { + if (!PRIVATE->buffer || !container) return; + cl_int ret = clEnqueueWriteBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), containerData(), 0, 0, 0); + if (ret != 0) { + piCout << "[PIOpenCL::Buffer]" << "clEnqueueWriteBuffer error" << ret; + } +} + + PIOpenCL::Program::Program() { @@ -310,6 +437,25 @@ bool PIOpenCL::Program::initKernels(PIVector kerns) { +bool PIOpenCL::Kernel::execute() { + if (dims.isEmpty()) { + piCout << "[PIOpenCL::Kernel]" << "Error: empty range"; + return false; + } + cl_int ret = clEnqueueNDRangeKernel(context_->PRIVATEWB->queue, PRIVATE->kernel, dims.size(), 0, dims.data(), 0, 0, 0, 0); + if (ret != 0) { + piCout << "[PIOpenCL::Kernel]" << "clEnqueueNDRangeKernel error" << ret; + return false; + } + return true; +} + + +void PIOpenCL::Kernel::setExecuteRanges(const PIVector & ranges) { + dims = ranges.toType(); +} + + PIOpenCL::Kernel::Kernel() { zero(); //piCout << "new Kernel" << this; @@ -349,17 +495,56 @@ bool PIOpenCL::Kernel::init() { ka.init(PRIVATE->kernel, i); args_ << ka; } - piCout << "kname" << kname << na; + //piCout << "kname" << kname << na; return true; } -bool PIOpenCL::Kernel::setArgValueV(int index, const PIVariant & value) { +template +void setArgV(cl_kernel k, int index, T v) { + //piCout << "setArgV" << k << index <= args_.size_s()) { piCout << "[PIOpenCL::Kernel]" << "setArgValue invalid index" << index; return false; } + KernelArg & ka(args_[index]); + if (ka.dims > 0) { + piCout << "[PIOpenCL::Kernel]" << "setArgValue set scalar to \"" << ka.type_name << ka.arg_name << "\""; + return false; + } + switch (ka.arg_type) { + case Char : setArgV(PRIVATE->kernel, index, (cl_char)(value.toInt())); break; + case UChar : setArgV(PRIVATE->kernel, index, (cl_uchar)(value.toInt())); break; + case Short : setArgV(PRIVATE->kernel, index, (cl_short)(value.toInt())); break; + case UShort: setArgV(PRIVATE->kernel, index, (cl_ushort)(value.toInt())); break; + case Int : setArgV(PRIVATE->kernel, index, (cl_int)(value.toInt())); break; + case UInt : setArgV(PRIVATE->kernel, index, (cl_uint)(value.toInt())); break; + case Long : setArgV(PRIVATE->kernel, index, (cl_long)(value.toLLong())); break; + case ULong : setArgV(PRIVATE->kernel, index, (cl_ulong)(value.toLLong())); break; + case Float : setArgV(PRIVATE->kernel, index, (cl_float)(value.toFloat())); break; + case Double: setArgV(PRIVATE->kernel, index, (cl_double)(value.toDouble())); break; + default: break; + } + return true; +} + +bool PIOpenCL::Kernel::bindArgValue(int index, Buffer * buffer) { + if (!buffer) return false; + if (index < 0 || index >= args_.size_s()) { + piCout << "[PIOpenCL::Kernel]" << "bindArgValue invalid index" << index; + return false; + } + KernelArg & ka(args_[index]); + if (ka.dims <= 0) { + piCout << "[PIOpenCL::Kernel]" << "bindArgValue set buffer to \"" << ka.type_name << ka.arg_name << "\""; + return false; + } + clSetKernelArg(PRIVATE->kernel, index, sizeof(buffer->PRIVATEWB->buffer), &(buffer->PRIVATEWB->buffer)); return true; } @@ -441,14 +626,26 @@ void PIOpenCL::KernelArg::init(void * _k, uint index) { case CL_KERNEL_ARG_TYPE_VOLATILE: type_qualifier = TypeVolatile; break; case CL_KERNEL_ARG_TYPE_NONE : type_qualifier = TypeNone; break; } - base_type_name = type_name; is_pointer = false; - if (type_name.endsWith("*")) { - is_pointer = true; - base_type_name.cutRight(1); + base_type_name = type_name; + base_type_name.removeAll("__global"); + dims = piMaxi(0, base_type_name.entries('*') + base_type_name.entries('[')); + base_type_name.removeAll('*'); + while (base_type_name.contains('[')) { + int i = base_type_name.find('['); + base_type_name.remove(i, base_type_name.find(']') - i + 1); } - dims = piMaxi(1, base_type_name.right(1).toInt()); - if (dims > 1) base_type_name.cutRight(1); + if (base_type_name == "char" ) arg_type = Char ; + if (base_type_name == "uchar" ) arg_type = UChar ; + if (base_type_name == "short") arg_type = Short; + if (base_type_name == "ushort") arg_type = UShort; + if (base_type_name == "int" ) arg_type = Int ; + if (base_type_name == "uint" ) arg_type = UInt ; + if (base_type_name == "long" ) arg_type = Long ; + if (base_type_name == "ulong" ) arg_type = ULong ; + if (base_type_name == "float" ) arg_type = Float ; + if (base_type_name == "double") arg_type = Double; + //piCout << type_name << base_type_name; } diff --git a/main.cpp b/main.cpp index 1165af51..0f49cc37 100644 --- a/main.cpp +++ b/main.cpp @@ -1,79 +1,53 @@ #include "pip.h" +#include "pivariantsimple.h" +#pragma pack(push, 1) +struct MM { + int x; + int x2; + double y; + char c[16]; + int e2; + int e; + //PIPointd h; +}; +#pragma pack(pop) -#define REGISTER_CNT (__COUNTER__) -#define REGISTER_V_STREAM_INTERNAL(T, C) \ - class _VariantRegistrator_##C##__ { \ - public: \ - _VariantRegistrator_##C##__() { \ - __VariantFunctionsBase__ * f = __VariantFunctions__().instance(); \ - __VariantFunctionsBase__::registered()[f->hash()] = f; \ - } \ - }; \ - _VariantRegistrator_##C##__ __registrator_##C##__; +int Acnt = 0; - -#define REGISTER_V_STREAM_INTERNAL_W(T, C) REGISTER_V_STREAM_INTERNAL(T, C) -#define REGISTER_V_STREAM(T) REGISTER_V_STREAM_INTERNAL_W(T, __COUNTER__) - - - - -class Send: public PIObject { - PIOBJECT(Send) +class A { public: - Send() {piCout << "Send";} - ~Send() {piCout << "~Send";} - EVENT1(ev, PIObject * , o); + A() {moved = false; i = "constructor"; piCout << "A()"; ++Acnt;} + A(const PIString & s): i(s) {moved = false; piCout << "A(String)"; ++Acnt;} + A(const A & a): i(a.i) {moved = false; piCout << "copy A(&)"; ++Acnt;} + A(A && a): i(std::move(a.i)) {moved = false; a.moved = true; piCout << "copy A(&&)"; ++Acnt;} + ~A() {piCout << "~A()" << moved; --Acnt;} + void swap(A & a) {piCout << "swap A()"; piSwap(i, a.i);} + A & operator =(const A & a) {i = a.i; piCout << "= A&"; return *this;} + A & operator =(A && a) {piSwap(i, a.i); a.moved = true; piCout << "= A&&)"; return *this;} + bool operator ==(const A & a) {return true;} + PIString i; + bool moved; + MM m; + static void F(int) {} }; +inline PIByteArray & operator <<(PIByteArray & ba, const A & v) {ba << v.i << v.m; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, A & v) {ba >> v.i >> v.m; return ba;} -class Recv: public PIObject { - PIOBJECT(Recv) -public: - Recv() {piCout << "Recv";} - ~Recv() {piCout << "~Recv";} - EVENT_HANDLER1(void, eh, PIObject * , o) { - piCout << "eh ..." << o; - o->deleteLater(); - piMSleep(1000); - piCout << "eh ok"; - } -}; +inline PIByteArray & operator <<(PIByteArray & ba, const MM & v) {piCout << "<<"; ba << v.x << v.y << v.c; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, MM & v) {piCout << ">>"; ba >> v.x >> v.y >> v.c; return ba;} -Send * s = new Send(); -Recv * r = new Recv(); - -#include "piconditionvar.h" int main() { - - CONNECTU(s, ev, r, eh); - s->ev(r); - r->deleteLater(); - s->deleteLater(); - piMSleep(1500); - //s->deleteLater(); - //delete o; - //eth.dump(); - //versionCompare("",""); - //PICloudServer s("127.0.0.1:10101"); - //s.startThreadedRead(); - piMSleep(10); - - /*PIMutex m; - PIConditionVariable var; - - PIThread::runOnce([&](){ - piCout << "wait ..."; - m.lock(); - var.wait(m); - m.unlock(); - piCout << "wait done"; - }); - - piMSleep(100); - var.notifyAll();*/ - + PIMathVectorT3d v3({1,2,3}); + PIMathVectord v(v3); + PIMathVectord v2({3,2,1}); + piCout << v; + piCout << v2; + PIMathMatrixT22d m = PIMathMatrixT22d::identity(); + piCout << m; + m.rotate(toRad(90.)); + piCout << m; return 0; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68c51388..49d5005d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,20 +1,26 @@ include(DownloadGTest) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/suppr.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) + macro(pip_test NAME LIBS) file(GLOB _CPPS "${NAME}/*.cpp") file(GLOB _HDRS "${NAME}/*.h") set(_target pip_${NAME}_test) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PIP_ROOT_BINARY_DIR}") add_executable(${_target} ${_CPPS} ${_HDRS}) + if (NOT WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(${_target} PRIVATE -fsanitize=address,undefined) + target_link_options(${_target} PRIVATE -fsanitize=address,undefined) + target_link_libraries(${_target} asan) + endif() target_link_libraries(${_target} pip ${LIBS} gtest_main gmock_main) add_test(NAME ${_target} COMMAND tests) - add_custom_target(${_target}_perform ALL COMMAND ${_target}) + add_custom_target(${_target}_perform ALL + COMMAND ${CMAKE_COMMAND} -E env "LSAN_OPTIONS=suppressions=suppr.txt" $) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY) list(APPEND PIP_TESTS_LIST "${NAME}") set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE) endmacro() -# Concurrent tests pip_test(concurrent "") pip_test(math "") -pip_test(core "") diff --git a/tests/concurrent/BlockingDequeueUnitTest.cpp b/tests/concurrent/BlockingDequeueUnitTest.cpp index 993326dd..8c9c8818 100644 --- a/tests/concurrent/BlockingDequeueUnitTest.cpp +++ b/tests/concurrent/BlockingDequeueUnitTest.cpp @@ -14,9 +14,7 @@ public: void wait(PIMutex& lk, const std::function& condition) override { isWaitCalled = true; - lk.lock(); isTrueCondition = condition(); - lk.unlock(); } bool waitFor(PIMutex& lk, int timeoutMs) override { @@ -27,10 +25,8 @@ public: bool waitFor(PIMutex& lk, int timeoutMs, const std::function& condition) override { isWaitForCalled = true; - lk.lock(); isTrueCondition = condition(); timeout = timeoutMs; - lk.unlock(); return isTrueCondition; } }; diff --git a/tests/concurrent/testutil.h b/tests/concurrent/testutil.h index 7c3c15c7..2966862f 100644 --- a/tests/concurrent/testutil.h +++ b/tests/concurrent/testutil.h @@ -8,7 +8,7 @@ * Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests * write "Start thread timeout reach!" message. You can reduce it if you want increase test performance. */ -const int WAIT_THREAD_TIME_MS = 40; +const int WAIT_THREAD_TIME_MS = 400; const int THREAD_COUNT = 5; diff --git a/tests/math/testpimathmatrix.cpp b/tests/math/testpimathmatrix.cpp index fb7109fb..94f3076b 100644 --- a/tests/math/testpimathmatrix.cpp +++ b/tests/math/testpimathmatrix.cpp @@ -2,554 +2,542 @@ #include "pimathmatrix.h" bool cmpSquareMatrixWithValue(PIMathMatrix matrix, double val, int num) { - bool b = true; - for(int i = 0; i < num; i++) { - for(int j = 0; j < num; j++) { - if(matrix.element(i, j) != val) { - b = false; - } - } - } - return b; + bool b = true; + for(int i = 0; i < num; i++) { + for(int j = 0; j < num; j++) { + if(matrix.element(i, j) != val) { + b = false; + } + } + } + return b; } TEST(PIMathMatrix_Test, identity) { - auto matrix = PIMathMatrix::identity(3, 3); - for(int i = 0; i < 3; i++) { - for(int j = 0; j < 3; j++) { - if(i != j) { - if(matrix[i][j] != 0.0){ - ASSERT_TRUE(false); - } - } - else { - if(matrix[i][i] != 1.0){ - ASSERT_TRUE(false); - } - } - } - } - ASSERT_TRUE(true); + auto matrix = PIMathMatrix::identity(3, 3); + for(int i = 0; i < 3; i++) { + for(int j = 0; j < 3; j++) { + if(i != j) { + if(matrix[i][j] != 0.0){ + ASSERT_TRUE(false); + } + } + else { + if(matrix[i][i] != 1.0){ + ASSERT_TRUE(false); + } + } + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, element) { - auto matrix = PIMathMatrix::identity(3, 3); - for(int i = 0; i < 3; i++){ - for(int j = 0; j < 3; j++){ - if(i != j){ - if(matrix[i][j] != 0.0){ - ASSERT_TRUE(false); - } - } - else { - if(matrix.element(i,i) != 1.0) { - ASSERT_TRUE(false); - } - } - } - } - ASSERT_TRUE(true); + auto matrix = PIMathMatrix::identity(3, 3); + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(i != j){ + if(matrix[i][j] != 0.0){ + ASSERT_TRUE(false); + } + } + else { + if(matrix.element(i,i) != 1.0) { + ASSERT_TRUE(false); + } + } + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, matrixRow) { - PIMathVector vector; - vector.resize(3, 3.0); - auto matrix = PIMathMatrix::matrixRow(vector); - for(uint i = 0; i < vector.size(); i++) { - if(matrix[0][i] != 3.0) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathVector vector; + vector.resize(3, 3.0); + auto matrix = PIMathMatrix::matrixRow(vector); + for(uint i = 0; i < vector.size(); i++) { + if(matrix[0][i] != 3.0) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, matrixCol) { - PIMathVector vector; - vector.resize(3, 3.0); - auto matrix = PIMathMatrix::matrixCol(vector); - for(uint i = 0; i < vector.size(); i++) { - if(matrix[i][0] != 3.0) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathVector vector; + vector.resize(3, 3.0); + auto matrix = PIMathMatrix::matrixCol(vector); + for(uint i = 0; i < vector.size(); i++) { + if(matrix[i][0] != 3.0) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, setCol) { - PIMathVector vector; - vector.resize(3, 3.0); - auto matrix = PIMathMatrix::matrixCol(vector); - vector.fill(10.0); - matrix.setCol(0, vector); - for(uint i = 0; i < vector.size(); i++) { - if(matrix[i][0] != 10.0) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathVector vector; + vector.resize(3, 3.0); + auto matrix = PIMathMatrix::matrixCol(vector); + vector.fill(10.0); + matrix.setCol(0, vector); + for(uint i = 0; i < vector.size(); i++) { + if(matrix[i][0] != 10.0) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, setRow) { - PIMathVector vector; - vector.resize(3, 3.0); - auto matrix = PIMathMatrix::matrixRow(vector); - vector.fill(10.0); - matrix.setRow(0, vector); - for(uint i = 0; i < vector.size(); i++) { - if(matrix[0][i] != 10.0) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathVector vector; + vector.resize(3, 3.0); + auto matrix = PIMathMatrix::matrixRow(vector); + vector.fill(10.0); + matrix.setRow(0, vector); + for(uint i = 0; i < vector.size(); i++) { + if(matrix[0][i] != 10.0) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, swapCols) { - PIMathMatrix origMatr; - PIMathMatrix matrix1; - PIMathVector vector; - uint i1 = 0; uint i2 = 1; - double a1[3], a2[3], a3[3]; - double b1[3], b2[3], b3[3]; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix1 = origMatr.identity(3, 3); - matrix1.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix1.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix1.setCol(2, vector); - for(int i = 0; i < 3; i++) { - a1[i] = matrix1.element(i, 0); - a2[i] = matrix1.element(i, 1); - a3[i] = matrix1.element(i, 2); - } - matrix1.swapCols(i1, i2); - for(int i = 0; i < 3; i++) { - b1[i] = matrix1.element(i, 0); - b2[i] = matrix1.element(i, 1); - b3[i] = matrix1.element(i, 2); - } - ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0)); + PIMathMatrix origMatr; + PIMathMatrix matrix1; + PIMathVector vector; + uint i1 = 0; uint i2 = 1; + double a1[3], a2[3], a3[3]; + double b1[3], b2[3], b3[3]; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix1 = origMatr.identity(3, 3); + matrix1.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix1.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix1.setCol(2, vector); + for(int i = 0; i < 3; i++) { + a1[i] = matrix1.element(i, 0); + a2[i] = matrix1.element(i, 1); + a3[i] = matrix1.element(i, 2); + } + matrix1.swapCols(i1, i2); + for(int i = 0; i < 3; i++) { + b1[i] = matrix1.element(i, 0); + b2[i] = matrix1.element(i, 1); + b3[i] = matrix1.element(i, 2); + } + ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0)); } TEST(PIMathMatrix_Test, swapRows) { - PIMathMatrix origMatr; - PIMathMatrix matrix1; - PIMathVector vector; - uint i1 = 0; uint i2 = 1; - double a1[3], a2[3], a3[3]; - double b1[3], b2[3], b3[3]; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix1 = origMatr.identity(3, 3); - matrix1.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix1.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix1.setCol(2, vector); - for(int i = 0; i < 3; i++) { - a1[i] = matrix1.element(0, i); - a2[i] = matrix1.element(1, i); - a3[i] = matrix1.element(2, i); - } - matrix1.swapRows(i1, i2); - for(int i = 0; i < 3; i++) { - b1[i] = matrix1.element(0, i); - b2[i] = matrix1.element(1, i); - b3[i] = matrix1.element(2, i); - } - ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0)); + PIMathMatrix origMatr; + PIMathMatrix matrix1; + PIMathVector vector; + uint i1 = 0; uint i2 = 1; + double a1[3], a2[3], a3[3]; + double b1[3], b2[3], b3[3]; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix1 = origMatr.identity(3, 3); + matrix1.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix1.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix1.setCol(2, vector); + for(int i = 0; i < 3; i++) { + a1[i] = matrix1.element(0, i); + a2[i] = matrix1.element(1, i); + a3[i] = matrix1.element(2, i); + } + matrix1.swapRows(i1, i2); + for(int i = 0; i < 3; i++) { + b1[i] = matrix1.element(0, i); + b2[i] = matrix1.element(1, i); + b3[i] = matrix1.element(2, i); + } + ASSERT_TRUE((memcmp(a1, b2, sizeof(b1)) == 0) && (memcmp(a2, b1, sizeof(b1)) == 0) && (memcmp(a3, b3, sizeof(b1)) == 0)); } TEST(PIMathMatrix_Test, fill) { - PIMathMatrix matrix(3, 3, 5.0); - matrix.fill(7.0); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 7.0, 3)); + PIMathMatrix matrix(3, 3, 5.0); + matrix.fill(7.0); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 7.0, 3)); } TEST(PIMathMatrix_Test, isSquareTrue) { - PIMathMatrix matrix(3, 3, 1.0); - ASSERT_TRUE(matrix.isSquare()); + PIMathMatrix matrix(3, 3, 1.0); + ASSERT_TRUE(matrix.isSquare()); } TEST(PIMathMatrix_Test, isSquareFalse) { - PIMathMatrix matrix(2, 4, 1.0); - ASSERT_FALSE(matrix.isSquare()); + PIMathMatrix matrix(2, 4, 1.0); + ASSERT_FALSE(matrix.isSquare()); } TEST(PIMathMatrix_Test, isIdentityTrue) { - auto matrix = PIMathMatrix::identity(3, 3); - ASSERT_TRUE(matrix.isIdentity()); + auto matrix = PIMathMatrix::identity(3, 3); + ASSERT_TRUE(matrix.isIdentity()); } TEST(PIMathMatrix_Test, isIdentityFalse) { - PIMathMatrix matrix(3, 3, 5.0); - ASSERT_FALSE(matrix.isIdentity()); + PIMathMatrix matrix(3, 3, 5.0); + ASSERT_FALSE(matrix.isIdentity()); } TEST(PIMathMatrix_Test, isNullTrue) { - PIMathMatrix matrix(3, 3, 0.0); - ASSERT_TRUE(matrix.isNull()); + PIMathMatrix matrix(3, 3, 0.0); + ASSERT_TRUE(matrix.isNull()); } TEST(PIMathMatrix_Test, isNullFalse) { - PIMathMatrix matrix(3, 3, 5.0); - ASSERT_FALSE(matrix.isNull()); + PIMathMatrix matrix(3, 3, 5.0); + ASSERT_FALSE(matrix.isNull()); } TEST(PIMathMatrix_Test, isValidTrue) { - PIMathMatrix matrix(3, 3, 1.62); - ASSERT_TRUE(matrix.isValid()); + PIMathMatrix matrix(3, 3, 1.62); + ASSERT_TRUE(matrix.isValid()); } TEST(PIMathMatrix_Test, isValidFalse) { - PIMathMatrix matrix; - ASSERT_FALSE(matrix.isValid()); + PIMathMatrix matrix; + ASSERT_FALSE(matrix.isValid()); } TEST(PIMathMatrix_Test, operator_Assignment) { - PIMathMatrix matrix1(3, 3, 5.72); - PIMathMatrix matrix2(3, 3, 7.12); - matrix1 = matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.12, 3)); + PIMathMatrix matrix1(3, 3, 5.72); + PIMathMatrix matrix2(3, 3, 7.12); + matrix1 = matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.12, 3)); } TEST(PIMathMatrix_Test, operator_EqualTrue) { - PIMathMatrix matrix1(2, 2, 2.0); - PIMathMatrix matrix2(2, 2, 2.0); - matrix1.element(0, 0) = 5.1; - matrix1.element(0, 1) = 1.21; - matrix1.element(1, 1) = 0.671; - matrix1.element(1, 0) = 2.623; - matrix2.element(0, 0) = 5.1; - matrix2.element(0, 1) = 1.21; - matrix2.element(1, 1) = 0.671; - matrix2.element(1, 0) = 2.623; - ASSERT_TRUE(matrix1 == matrix2); + PIMathMatrix matrix1(2, 2, 2.0); + PIMathMatrix matrix2(2, 2, 2.0); + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 0.671; + matrix2.element(1, 0) = 2.623; + ASSERT_TRUE(matrix1 == matrix2); } TEST(PIMathMatrix_Test, operator_EqualFalse) { - PIMathMatrix matrix1(2, 2, 2.0); - PIMathMatrix matrix2(2, 2, 2.0); - matrix1.element(0, 0) = 5.1; - matrix1.element(0, 1) = 1.21; - matrix1.element(1, 1) = 0.671; - matrix1.element(1, 0) = 2.623; - matrix2.element(0, 0) = 5.1; - matrix2.element(0, 1) = 1.21; - matrix2.element(1, 1) = 665.671; - matrix2.element(1, 0) = 2.623; - ASSERT_FALSE(matrix1 == matrix2); + PIMathMatrix matrix1(2, 2, 2.0); + PIMathMatrix matrix2(2, 2, 2.0); + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 665.671; + matrix2.element(1, 0) = 2.623; + ASSERT_FALSE(matrix1 == matrix2); } TEST(PIMathMatrix_Test, operator_Not_EqualTrue) { - PIMathMatrix matrix1(2, 2, 2.0); - PIMathMatrix matrix2(2, 2, 2.0); - matrix1.element(0, 0) = 5.1; - matrix1.element(0, 1) = 1.21; - matrix1.element(1, 1) = 0.671; - matrix1.element(1, 0) = 2.623; - matrix2.element(0, 0) = 5.1; - matrix2.element(0, 1) = 1.21; - matrix2.element(1, 1) = 665.671; - matrix2.element(1, 0) = 2.623; - ASSERT_TRUE(matrix1 != matrix2); + PIMathMatrix matrix1(2, 2, 2.0); + PIMathMatrix matrix2(2, 2, 2.0); + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 665.671; + matrix2.element(1, 0) = 2.623; + ASSERT_TRUE(matrix1 != matrix2); } TEST(PIMathMatrix_Test, operator_Not_EqualFalse) { - PIMathMatrix matrix1(2, 2, 2.0); - PIMathMatrix matrix2(2, 2, 2.0); - matrix1.element(0, 0) = 5.1; - matrix1.element(0, 1) = 1.21; - matrix1.element(1, 1) = 0.671; - matrix1.element(1, 0) = 2.623; - matrix2.element(0, 0) = 5.1; - matrix2.element(0, 1) = 1.21; - matrix2.element(1, 1) = 0.671; - matrix2.element(1, 0) = 2.623; - ASSERT_FALSE(matrix1 != matrix2); + PIMathMatrix matrix1(2, 2, 2.0); + PIMathMatrix matrix2(2, 2, 2.0); + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 0.671; + matrix2.element(1, 0) = 2.623; + ASSERT_FALSE(matrix1 != matrix2); } TEST(PIMathMatrix_Test, operator_Addition_Aassignment) { - PIMathMatrix matrix1(3, 3, 6.72); - PIMathMatrix matrix2(3, 3, 1.0); - matrix1 += matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + PIMathMatrix matrix2(3, 3, 1.0); + matrix1 += matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, 3)); } TEST(PIMathMatrix_Test, operator_Subtraction_Assignment) { - PIMathMatrix matrix1(3, 3, 1.0); - PIMathMatrix matrix2(3, 3, 6.72); - matrix1 -= matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, 3)); + PIMathMatrix matrix1(3, 3, 1.0); + PIMathMatrix matrix2(3, 3, 6.72); + matrix1 -= matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, 3)); } TEST(PIMathMatrix_Test, operator_Multiplication_Assignment) { - PIMathMatrix matrix1(3, 3, 6.72); - matrix1 *= 2.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + matrix1 *= 2.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, 3)); } TEST(PIMathMatrix_Test, operator_Division_Assignment) { - PIMathMatrix matrix1(3, 3, 6.72); - matrix1 /= 2.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + matrix1 /= 2.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, 3)); } TEST(PIMathMatrix_Test, operator_Addition) { - PIMathMatrix matrix1(3, 3, 6.72); - PIMathMatrix matrix2(3, 3, 8.28); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + PIMathMatrix matrix2(3, 3, 8.28); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, 3)); } TEST(PIMathMatrix_Test, operator_Subtraction) { - PIMathMatrix matrix1(3, 3, 6.0); - PIMathMatrix matrix2(3, 3, 5.0); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, 3)); + PIMathMatrix matrix1(3, 3, 6.0); + PIMathMatrix matrix2(3, 3, 5.0); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, 3)); } TEST(PIMathMatrix_Test, operator_Multiplication) { - PIMathMatrix matrix1(3, 3, 6.72); - PIMathMatrix matrix2(3, 3, 5.0); - matrix2 = matrix1*4.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 26.88, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + PIMathMatrix matrix2(3, 3, 5.0); + matrix2 = matrix1*4.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 26.88, 3)); } TEST(PIMathMatrix_Test, operator_Division) { - PIMathMatrix matrix1(3, 3, 6.72); - PIMathMatrix matrix2(3, 3, 5.0); - matrix2 = matrix1/4.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 1.68, 3)); + PIMathMatrix matrix1(3, 3, 6.72); + PIMathMatrix matrix2(3, 3, 5.0); + matrix2 = matrix1/4.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix2, 1.68, 3)); } TEST(PIMathMatrix_Test, determinantIfSquare) { - double d; - double i = 59.0; - PIMathMatrix matrix(3, 3, 0.0); - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix.setCol(2, vector); - d = matrix.determinant(); - ASSERT_DOUBLE_EQ(d, i); -} - -TEST(PIMathMatrix_Test, determinantIfNotSquare) { - PIMathMatrix matrix(3, 5, 1.0); - matrix.element(1,1) = 5.0; - ASSERT_FALSE(matrix.determinant()); + double d; + double i = 59.0; + PIMathMatrix matrix(3, 3, 0.0); + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix.setCol(2, vector); + d = matrix.determinant(); + ASSERT_DOUBLE_EQ(d, i); } TEST(PIMathMatrix_Test, trace) { - PIMathMatrix matrix(3, 3, 0.0); - double t; - double i = 9.0; - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix.setCol(2, vector); - t = matrix.trace(); - ASSERT_DOUBLE_EQ(t, i); -} - -TEST(PIMathMatrix_Test, traceIfNotSquare) { - PIMathMatrix matrix(3, 5, 1.0); - matrix.element(1,1) = 5.0; - ASSERT_FALSE(matrix.trace()); + PIMathMatrix matrix(3, 3, 0.0); + double t; + double i = 9.0; + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix.setCol(2, vector); + t = matrix.trace(); + ASSERT_DOUBLE_EQ(t, i); } TEST(PIMathMatrix_Test, toUpperTriangular) { - PIMathMatrix matrix(3, 3, 0.0); - double d1, d2 = 1; - int i; - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix.setCol(2, vector); - d1 = matrix.determinant(); - matrix.toUpperTriangular(); - for(i = 0; i < 3; i++) - { - d2 = d2 * matrix.element(i, i); - } - ASSERT_DOUBLE_EQ(d1, d2); + PIMathMatrix matrix(3, 3, 0.0); + double d1, d2 = 1; + int i; + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix.setCol(2, vector); + d1 = matrix.determinant(); + matrix.toUpperTriangular(); + for(i = 0; i < 3; i++) + { + d2 = d2 * matrix.element(i, i); + } + ASSERT_DOUBLE_EQ(d1, d2); } TEST(PIMathMatrix_Test, invert) { - double d1, d2; - PIMathMatrix matrix1(3, 3, 0.0); - PIMathMatrix matrix2(3, 3, 0.0); - PIMathMatrix matrix3(3, 3, 0.0); - PIMathMatrix matrix4(3, 3, 0.0); - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix1.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix1.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix1.setCol(2, vector); - d1 = matrix1.determinant(); - matrix2 = matrix1; - matrix2.invert(); - d2 = matrix2.determinant(); - matrix4.invert(); - ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); + double d1, d2; + PIMathMatrix matrix1(3, 3, 0.0); + PIMathMatrix matrix2(3, 3, 0.0); + PIMathMatrix matrix3(3, 3, 0.0); + PIMathMatrix matrix4(3, 3, 0.0); + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix1.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix1.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix1.setCol(2, vector); + d1 = matrix1.determinant(); + matrix2 = matrix1; + matrix2.invert(); + d2 = matrix2.determinant(); + matrix4.invert(); + ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); } TEST(PIMathMatrix_Test, inverted) { - double d1, d2; - PIMathMatrix matrix1(3, 3, 0.0); - PIMathMatrix matrix2(3, 3, 0.0); - PIMathMatrix matrix3(3, 3, 0.0); - PIMathMatrix matrix4(3, 3, 0.0); - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix1.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix1.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix1.setCol(2, vector); - d1 = matrix1.determinant(); - matrix2 = matrix1; - matrix1 = matrix2.invert(); - d2 = matrix1.determinant(); - matrix3 = matrix4.invert(); - ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); + double d1, d2; + PIMathMatrix matrix1(3, 3, 0.0); + PIMathMatrix matrix2(3, 3, 0.0); + PIMathMatrix matrix3(3, 3, 0.0); + PIMathMatrix matrix4(3, 3, 0.0); + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix1.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix1.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix1.setCol(2, vector); + d1 = matrix1.determinant(); + matrix2 = matrix1; + matrix1 = matrix2.invert(); + d2 = matrix1.determinant(); + matrix3 = matrix4.invert(); + ASSERT_TRUE((matrix3 == matrix4) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); } TEST(PIMathMatrix_Test, transposed) { - PIMathMatrix origMatr; - double d1, d2; - PIMathMatrix matrix1; - PIMathMatrix matrix2; - PIMathMatrix matrix3; - PIMathVector vector; - vector.resize(3, 3.0); - vector.at(0) = 3.0; - vector.at(1) = 6.0; - vector.at(2) = 8.0; - matrix1 = origMatr.identity(3, 3); - matrix1.setCol(0, vector); - vector.at(0) = 2.0; - vector.at(1) = 1.0; - vector.at(2) = 4.0; - matrix1.setCol(1, vector); - vector.at(0) = 6.0; - vector.at(1) = 2.0; - vector.at(2) = 5.0; - matrix1.setCol(2, vector); - d1 = matrix1.determinant(); - matrix2 = matrix1.transposed(); - d2 = matrix2.determinant(); - matrix3 = matrix2.transposed(); - ASSERT_TRUE((d1 == d2) && (matrix1 == matrix3)); + PIMathMatrix origMatr; + double d1, d2; + PIMathMatrix matrix1; + PIMathMatrix matrix2; + PIMathMatrix matrix3; + PIMathVector vector; + vector.resize(3, 3.0); + vector[0] = 3.0; + vector[1] = 6.0; + vector[2] = 8.0; + matrix1 = origMatr.identity(3, 3); + matrix1.setCol(0, vector); + vector[0] = 2.0; + vector[1] = 1.0; + vector[2] = 4.0; + matrix1.setCol(1, vector); + vector[0] = 6.0; + vector[1] = 2.0; + vector[2] = 5.0; + matrix1.setCol(2, vector); + d1 = matrix1.determinant(); + matrix2 = matrix1.transposed(); + d2 = matrix2.determinant(); + matrix3 = matrix2.transposed(); + ASSERT_TRUE((d1 == d2) && (matrix1 == matrix3)); } TEST(PIMathMatrix_Test, matrixMultiplication) { - PIMathMatrix matrix1(2, 2, 1.5); - PIMathMatrix matrix2(2, 2, 2.5); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 7.5, 2)); + PIMathMatrix matrix1(2, 2, 1.5); + PIMathMatrix matrix2(2, 2, 2.5); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 7.5, 2)); } TEST(PIMathMatrix_Test, matrixAndVectorMultiplication) { - PIMathMatrix matrix1(2, 2, 1.5); - PIMathVector vector; - vector.resize(2, 2.5); - for(uint i = 0; i < 2; i++) { - if((matrix1 * vector)[i] != 7.5) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrix matrix1(2, 2, 1.5); + PIMathVector vector; + vector.resize(2, 2.5); + for(uint i = 0; i < 2; i++) { + if((matrix1 * vector)[i] != 7.5) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, vectorAndMatrixMultiplication) { - PIMathMatrix matrix1(2, 2, 1.5); - PIMathVector vector; - vector.resize(2, 2.5); - for(uint i = 0; i < 2; i++) { - if((vector * matrix1)[i] != 7.5) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrix matrix1(2, 2, 1.5); + PIMathVector vector; + vector.resize(2, 2.5); + for(uint i = 0; i < 2; i++) { + if((vector * matrix1)[i] != 7.5) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrix_Test, valAndMatrixMultiplication) { - PIMathMatrix matrix1(3, 3, 1.5); - ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3)); + PIMathMatrix matrix1(3, 3, 1.5); + ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3)); } TEST(PIMathMatrix_Test, hermitian) { - complex val; - complex res; - val.imag(1.0); - val.real(1.0); - PIMathMatrix> matrix(3, 3, val); - res.imag(-1.0); - res.real(1.0); - auto matr = hermitian(matrix); - for(uint i = 0; i < 3; i++) { - for(uint j = 0; j < 3; j++) { - if(matr.element(i, j) != res) { - ASSERT_TRUE(false); - } - } - } - ASSERT_TRUE(true); + complex val; + complex res; + val.imag(1.0); + val.real(1.0); + PIMathMatrix> matrix(3, 3, val); + res.imag(-1.0); + res.real(1.0); + auto matr = hermitian(matrix); + for(uint i = 0; i < 3; i++) { + for(uint j = 0; j < 3; j++) { + if(matr.element(i, j) != res) { + ASSERT_TRUE(false); + } + } + } + ASSERT_TRUE(true); } diff --git a/tests/math/testpimathmatrixt.cpp b/tests/math/testpimathmatrixt.cpp index df96a01c..5f3a20bf 100644 --- a/tests/math/testpimathmatrixt.cpp +++ b/tests/math/testpimathmatrixt.cpp @@ -5,558 +5,485 @@ const uint rows = 3; const uint cols = 3; bool cmpSquareMatrixWithValue(PIMathMatrixT matrix, double val, int num) { - bool b = true; - for(int i = 0; i < num; i++) { - for(int j = 0; j < num; j++) { - if(matrix.at(i, j) != val) { - b = false; - } - } - } - return b; + bool b = true; + for(int i = 0; i < num; i++) { + for(int j = 0; j < num; j++) { + if(matrix.at(i, j) != val) { + b = false; + } + } + } + return b; } TEST(PIMathMatrixT_Test, identity) { - auto matrix = PIMathMatrixT::identity(); - for(int i = 0; i < 3; i++){ - for(int j = 0; j < 3; j++){ - if(i != j){ - if(matrix[i][j] != 0.0){ - ASSERT_TRUE(false); - } - } - else { - if(matrix[i][i] != 1.0){ - ASSERT_TRUE(false); - } - } - } - } - ASSERT_TRUE(true); + auto matrix = PIMathMatrixT::identity(); + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(i != j){ + if(matrix[i][j] != 0.0){ + ASSERT_TRUE(false); + } + } + else { + if(matrix[i][i] != 1.0){ + ASSERT_TRUE(false); + } + } + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, at) { - auto matrix1 = PIMathMatrixT::identity(); - for(uint i = 0; i < rows; i++) { - if(matrix1.at(i,i) != 1.0) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + auto matrix1 = PIMathMatrixT::identity(); + for(uint i = 0; i < rows; i++) { + if(matrix1.at(i,i) != 1.0) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, filled) { - auto matr = PIMathMatrixT::filled(1.0); - ASSERT_TRUE(cmpSquareMatrixWithValue(matr, 1.0, rows)); + auto matr = PIMathMatrixT(1.0); + ASSERT_TRUE(cmpSquareMatrixWithValue(matr, 1.0, rows)); } TEST(PIMathMatrixT_Test, cols) { - PIMathMatrixT matr; - ASSERT_EQ(cols,matr.cols()); + PIMathMatrixT matr; + ASSERT_EQ(cols,matr.cols()); } TEST(PIMathMatrixT_Test, rows) { - PIMathMatrixT matr; - ASSERT_EQ(rows,matr.rows()); + PIMathMatrixT matr; + ASSERT_EQ(rows,matr.rows()); } TEST(PIMathMatrixT_Test, col) { - PIMathMatrixT matr; - PIMathVectorT vect; - uint g = 2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - vect = matr.col(g); - for(uint i = 0; i < matr.cols(); i++) { - if(matr.at(i, g) != vect.at(i)) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrixT matr; + PIMathVectorT vect; + uint g = 2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + vect = matr.col(g); + for(uint i = 0; i < matr.cols(); i++) { + if(matr.element(i, g) != vect[i]) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, row) { - PIMathMatrixT matr; - PIMathVectorT vect; - uint g = 2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - vect = matr.row(g); - for(uint i = 0; i < matr.rows(); i++) { - if(matr.at(g, i) != vect.at(i)) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrixT matr; + PIMathVectorT vect; + uint g = 2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + vect = matr.row(g); + for(uint i = 0; i < matr.rows(); i++) { + if(matr.element(g, i) != vect[i]) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, setCol) { - PIMathMatrixT matr; - PIMathVectorT vect; - vect.at(0) = 1.0; - vect.at(1) = 3.0; - vect.at(2) = 5.0; - uint g = 1; - matr.setCol(g, vect); - for(uint i = 0; i < vect.size(); i++) { - if(matr.at(i, g) != vect.at(i)) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrixT matr; + PIMathVectorT vect; + vect[0] = 1.0; + vect[1] = 3.0; + vect[2] = 5.0; + uint g = 1; + matr.setCol(g, vect); + for(uint i = 0; i < vect.size(); i++) { + if(matr.element(i, g) != vect[i]) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, setRow) { - PIMathMatrixT matr; - PIMathVectorT vect; - vect.at(0) = 1.0; - vect.at(1) = 3.0; - vect.at(2) = 5.0; - uint g = 1; - matr.setRow(g, vect); - for(uint i = 0; i < vect.size(); i++) { - if(matr.at(g,i) != vect.at(i)) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + PIMathMatrixT matr; + PIMathVectorT vect; + vect[0] = 1.0; + vect[1] = 3.0; + vect[2] = 5.0; + uint g = 1; + matr.setRow(g, vect); + for(uint i = 0; i < vect.size(); i++) { + if(matr.element(g,i) != vect[i]) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, swapCols) { - PIMathMatrixT matr; - int g1 = 1, g2 = 2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - const PIMathVectorT before_Vect1 = matr.col(g1); - const PIMathVectorT before_Vect2 = matr.col(g2); - matr.swapCols(g1, g2); - const PIMathVectorT after_Vect1 = matr.col(g1); - const PIMathVectorT after_Vect2 = matr.col(g2); - if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) { - ASSERT_TRUE(true); - } - else { - ASSERT_TRUE(false); - } + PIMathMatrixT matr; + int g1 = 1, g2 = 2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + const PIMathVectorT before_Vect1 = matr.col(g1); + const PIMathVectorT before_Vect2 = matr.col(g2); + matr.swapCols(g1, g2); + const PIMathVectorT after_Vect1 = matr.col(g1); + const PIMathVectorT after_Vect2 = matr.col(g2); + if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) { + ASSERT_TRUE(true); + } + else { + ASSERT_TRUE(false); + } } TEST(PIMathMatrixT_Test, swapRows) { - PIMathMatrixT matr; - int g1 = 1, g2 = 2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - const PIMathVectorT before_Vect1 = matr.row(g1); - const PIMathVectorT before_Vect2 = matr.row(g2); - matr.swapRows(g1, g2); - const PIMathVectorT after_Vect1 = matr.row(g1); - const PIMathVectorT after_Vect2 = matr.row(g2); - if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) { - ASSERT_TRUE(true); - } - else { - ASSERT_TRUE(false); - } + PIMathMatrixT matr; + int g1 = 1, g2 = 2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + const PIMathVectorT before_Vect1 = matr.row(g1); + const PIMathVectorT before_Vect2 = matr.row(g2); + matr.swapRows(g1, g2); + const PIMathVectorT after_Vect1 = matr.row(g1); + const PIMathVectorT after_Vect2 = matr.row(g2); + if((before_Vect1 == after_Vect2) && (before_Vect2 == after_Vect1)) { + ASSERT_TRUE(true); + } + else { + ASSERT_TRUE(false); + } } TEST(PIMathMatrixT_Test, fill) { - PIMathMatrixT matr; - PIMathMatrixT matrix1; - double g = 1.0; - matr.fill(g); - for(uint i = 0; i < cols; i++) { - for(uint j = 0; j < rows; j++) { - matrix1.at(j,i) = g; - } - } - ASSERT_TRUE(matr == matrix1); + PIMathMatrixT matr; + PIMathMatrixT matrix1; + double g = 1.0; + matr.fill(g); + for(uint i = 0; i < cols; i++) { + for(uint j = 0; j < rows; j++) { + matrix1.element(j,i) = g; + } + } + ASSERT_TRUE(matr == matrix1); } TEST(PIMathMatrixT_Test, isSquareTrue) { - PIMathMatrixT matrix1; - ASSERT_TRUE(matrix1.isSquare()); + PIMathMatrixT matrix1; + ASSERT_TRUE(matrix1.isSquare()); } TEST(PIMathMatrixT_Test, isSquareFalse) { - const uint new_Cols = 4; - PIMathMatrixT matrix2; - ASSERT_FALSE(matrix2.isSquare()); + const uint new_Cols = 4; + PIMathMatrixT matrix2; + ASSERT_FALSE(matrix2.isSquare()); } TEST(PIMathMatrixT_Test, isIdentityTrue) { - auto matrix1 = PIMathMatrixT::identity(); - ASSERT_TRUE(matrix1.isIdentity()); + auto matrix1 = PIMathMatrixT::identity(); + ASSERT_TRUE(matrix1.isIdentity()); } TEST(PIMathMatrixT_Test, isIdentityFalse) { - auto matrix1 = PIMathMatrixT::filled(2.5); - ASSERT_FALSE(matrix1.isIdentity()); + auto matrix1 = PIMathMatrixT(2.5); + ASSERT_FALSE(matrix1.isIdentity()); } TEST(PIMathMatrixT_Test, isNullTrue) { - PIMathMatrixT matrix1; - ASSERT_TRUE(matrix1.isNull()); + PIMathMatrixT matrix1; + ASSERT_TRUE(matrix1.isNull()); } TEST(PIMathMatrixT_Test, isNullFalse) { - auto matrix1 = PIMathMatrixT::identity(); - ASSERT_FALSE(matrix1.isNull()); + auto matrix1 = PIMathMatrixT::identity(); + ASSERT_FALSE(matrix1.isNull()); } TEST(PIMathMatrixT_Test, operator_Assignment) { - PIMathMatrixT matrix1; - auto matrix2 = PIMathMatrixT::filled(6.72); - matrix1 = matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 6.72, rows)); + PIMathMatrixT matrix1; + auto matrix2 = PIMathMatrixT(6.72); + matrix1 = matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 6.72, rows)); } TEST(PIMathMatrixT_Test, operator_EqualTrue) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - matrix1.at(0, 0) = 5.1; - matrix1.at(0, 1) = 1.21; - matrix1.at(1, 1) = 0.671; - matrix1.at(1, 0) = 2.623; - matrix2.at(0, 0) = 5.1; - matrix2.at(0, 1) = 1.21; - matrix2.at(1, 1) = 0.671; - matrix2.at(1, 0) = 2.623; - ASSERT_TRUE(matrix1 == matrix2); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 0.671; + matrix2.element(1, 0) = 2.623; + ASSERT_TRUE(matrix1 == matrix2); } TEST(PIMathMatrixT_Test, operator_EqualFalse) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - matrix1.at(0, 0) = 5.1; - matrix1.at(0, 1) = 1.21; - matrix1.at(1, 1) = 0.671; - matrix1.at(1, 0) = 2.623; - matrix2.at(0, 0) = 5.1; - matrix2.at(0, 1) = 1.21; - matrix2.at(1, 1) = 665.671; - matrix2.at(1, 0) = 2.623; - ASSERT_FALSE(matrix1 == matrix2); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 665.671; + matrix2.element(1, 0) = 2.623; + ASSERT_FALSE(matrix1 == matrix2); } TEST(PIMathMatrixT_Test, operator_Not_EqualTrue) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - matrix1.at(0, 0) = 5.1; - matrix1.at(0, 1) = 1.21; - matrix1.at(1, 1) = 0.671; - matrix1.at(1, 0) = 2.623; - matrix2.at(0, 0) = 5.1; - matrix2.at(0, 1) = 1.21; - matrix2.at(1, 1) = 665.671; - matrix2.at(1, 0) = 2.623; - ASSERT_TRUE(matrix1 != matrix2); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 665.671; + matrix2.element(1, 0) = 2.623; + ASSERT_TRUE(matrix1 != matrix2); } TEST(PIMathMatrixT_Test, operator_Not_EqualFalse) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - matrix1.at(0, 0) = 5.1; - matrix1.at(0, 1) = 1.21; - matrix1.at(1, 1) = 0.671; - matrix1.at(1, 0) = 2.623; - matrix2.at(0, 0) = 5.1; - matrix2.at(0, 1) = 1.21; - matrix2.at(1, 1) = 0.671; - matrix2.at(1, 0) = 2.623; - ASSERT_FALSE(matrix1 != matrix2); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + matrix1.element(0, 0) = 5.1; + matrix1.element(0, 1) = 1.21; + matrix1.element(1, 1) = 0.671; + matrix1.element(1, 0) = 2.623; + matrix2.element(0, 0) = 5.1; + matrix2.element(0, 1) = 1.21; + matrix2.element(1, 1) = 0.671; + matrix2.element(1, 0) = 2.623; + ASSERT_FALSE(matrix1 != matrix2); } TEST(PIMathMatrixT_Test, operator_Addition_Assignment) { - auto matrix1 = PIMathMatrixT::filled(6.72) ; - auto matrix2 = PIMathMatrixT::filled(1.0) ; - matrix1 += matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, rows)); + auto matrix1 = PIMathMatrixT(6.72) ; + auto matrix2 = PIMathMatrixT(1.0) ; + matrix1 += matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 7.72, rows)); } TEST(PIMathMatrixT_Test, operator_Subtraction_Assignment) { - auto matrix1 = PIMathMatrixT::filled(1.0); - auto matrix2 = PIMathMatrixT::filled(6.72); - matrix1 -= matrix2; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, rows)); + auto matrix1 = PIMathMatrixT(1.0); + auto matrix2 = PIMathMatrixT(6.72); + matrix1 -= matrix2; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, -5.72, rows)); } TEST(PIMathMatrixT_Test, operator_Multiplication_Assignment) { - auto matrix1 = PIMathMatrixT::filled(6.72); - matrix1 *= 2.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, rows)); + auto matrix1 = PIMathMatrixT(6.72); + matrix1 *= 2.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 13.44, rows)); } TEST(PIMathMatrixT_Test, operator_Division_Assignment) { - auto matrix1 = PIMathMatrixT::filled(6.72); - matrix1 /= 2.0; - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, rows)); + auto matrix1 = PIMathMatrixT(6.72); + matrix1 /= 2.0; + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1, 3.36, rows)); } TEST(PIMathMatrixT_Test, operator_Addition) { - auto matrix1 = PIMathMatrixT::filled(6.72); - auto matrix2 = PIMathMatrixT::filled(8.28); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, rows)); + auto matrix1 = PIMathMatrixT(6.72); + auto matrix2 = PIMathMatrixT(8.28); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 + matrix2, 15.0, rows)); } TEST(PIMathMatrixT_Test, operator_Subtraction) { - auto matrix1 = PIMathMatrixT::filled(6.0); - auto matrix2 = PIMathMatrixT::filled(5.0); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, rows)); + auto matrix1 = PIMathMatrixT(6.0); + auto matrix2 = PIMathMatrixT(5.0); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 - matrix2, 1.0, rows)); } TEST(PIMathMatrixT_Test, operator_Multiplication) { - auto matrix1 = PIMathMatrixT::filled(6.72); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * 4.0, 26.88, rows)); + auto matrix1 = PIMathMatrixT(6.72); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * 4.0, 26.88, rows)); } TEST(PIMathMatrixT_Test, operator_Division) { - auto matrix1 = PIMathMatrixT::filled(6.72); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 / 4.0, 1.68, rows)); + auto matrix1 = PIMathMatrixT(6.72); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 / 4.0, 1.68, rows)); } TEST(PIMathMatrixT_Test, determinantIfSquare) { - double d; - double i = 59.0; - PIMathMatrixT matr; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - d = matr.determinant(); - ASSERT_DOUBLE_EQ(i, d); -} - -TEST(PIMathMatrixT_Test, determinantIfNotSquare) { - PIMathMatrixT matr; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - ASSERT_FALSE(matr.determinant()); + double d; + double i = 59.0; + PIMathMatrixT matr; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + d = matr.determinant(); + ASSERT_DOUBLE_EQ(i, d); } TEST(PIMathMatrixT_Test, invert) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - PIMathMatrixT matrix3; - PIMathMatrixT matr; - double d1, d2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - matrix2 = matr; - matr.invert(); - d1 = matr.determinant(); - d2 = matrix2.determinant(); - matrix3 = matrix1; - matrix1.invert(); - ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2)); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + PIMathMatrixT matrix3; + PIMathMatrixT matr; + double d1, d2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + matrix2 = matr; + matr.invert(); + d1 = matr.determinant(); + d2 = matrix2.determinant(); + matrix3 = matrix1; + matrix1.invert(); + ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2)); } TEST(PIMathMatrixT_Test, inverted) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - PIMathMatrixT matrix3; - PIMathMatrixT matr; - double d1, d2; - matrix1 = matr.identity(); - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - matrix2 = matr.inverted(); - d1 = matr.determinant(); - d2 = matrix2.determinant(); - matrix3 = matrix1.inverted(); - ASSERT_TRUE((matrix1 == matrix3) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + PIMathMatrixT matrix3; + PIMathMatrixT matr; + double d1, d2; + matrix1 = matr.identity(); + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + matrix2 = matr.inverted(); + d1 = matr.determinant(); + d2 = matrix2.determinant(); + matrix3 = matrix1.inverted(); + ASSERT_TRUE((matrix1 == matrix3) && (round((1/d1)*10000)/10000 == round(d2*10000)/10000)); } TEST(PIMathMatrixT_Test, toUpperTriangular) { - PIMathMatrixT matrix; - double d1, d2 = 1; - PIMathMatrixT matr; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - matrix = matr.toUpperTriangular(); - d1 = matrix.determinant(); - for(uint i = 0; i < cols; i++) - { - d2 = d2*matrix.at(i,i); - } - ASSERT_DOUBLE_EQ(d1, d2); + PIMathMatrixT matrix; + double d1, d2 = 1; + PIMathMatrixT matr; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + matrix = matr.toUpperTriangular(); + d1 = matrix.determinant(); + for(uint i = 0; i < cols; i++) + { + d2 = d2*matrix.at(i,i); + } + ASSERT_DOUBLE_EQ(d1, d2); } TEST(PIMathMatrixT_Test, transposed) { - PIMathMatrixT matrix1; - PIMathMatrixT matrix2; - PIMathMatrixT matr; - double d1, d2; - matr.at(0,0) = 3; - matr.at(0,1) = 6; - matr.at(0,2) = 8; - matr.at(1,0) = 2; - matr.at(1,1) = 1; - matr.at(1,2) = 4; - matr.at(2,0) = 6; - matr.at(2,1) = 2; - matr.at(2,2) = 5; - d1 = matr.determinant(); - matrix1 = matr.transposed(); - d2 = matrix1.determinant(); - matrix2 = matrix1.transposed(); - ASSERT_TRUE((d1 == d2) && (matr == matrix2)); -} - -TEST(PIMathMatrixT_Test, scaleX_two) { - double factor = 5.64; - PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::scaleX(factor); - ASSERT_TRUE((1.0 == matrix.at(1u,1u)) && (factor == matrix.at(0u,0u))); -} - -TEST(PIMathMatrixT_Test, scaleY_two) { - double factor = 5.64; - PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::scaleY(factor); - ASSERT_TRUE((factor == matrix.at(1u,1u)) && (1.0 == matrix.at(0u,0u))); + PIMathMatrixT matrix1; + PIMathMatrixT matrix2; + PIMathMatrixT matr; + double d1, d2; + matr.element(0,0) = 3; + matr.element(0,1) = 6; + matr.element(0,2) = 8; + matr.element(1,0) = 2; + matr.element(1,1) = 1; + matr.element(1,2) = 4; + matr.element(2,0) = 6; + matr.element(2,1) = 2; + matr.element(2,2) = 5; + d1 = matr.determinant(); + matrix1 = matr.transposed(); + d2 = matrix1.determinant(); + matrix2 = matrix1.transposed(); + ASSERT_TRUE((d1 == d2) && (matr == matrix2)); } TEST(PIMathMatrixT_Test, rotation_2x2) { - double angle = 1.0; - PIMathMatrixT<2u, 2u, double> matrix = PIMathMatrixT<2u, 2u, double>::rotation(angle); - double c = cos(angle); - double s = sin(angle); - ASSERT_TRUE((c == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (-s == matrix.at(0u,1u)) && (s == matrix.at(1u,0u))); -} - -TEST(PIMathMatrixT_Test, rotation_3x3) { - double angle = 1.0; - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotation(angle); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix, 0.0, rows)); -} - -TEST(PIMathMatrixT_Test, rotationX) { - double angle = 1.0; - double c = cos(angle); - double s = sin(angle); - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationX(angle); - ASSERT_TRUE((1.0 == matrix.at(0u,0u)) && (c == matrix.at(1u,1u)) && (c == matrix.at(2u,2u)) && (s == matrix.at(2u,1u)) && (-s == matrix.at(1u,2u))); -} - -TEST(PIMathMatrixT_Test, rotationY) { - double angle = 1.0; - double c = cos(angle); - double s = sin(angle); - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationY(angle); - ASSERT_TRUE((1.0 == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (c == matrix.at(2u,2u)) && (s == matrix.at(0u,2u)) && (-s == matrix.at(2u,0u))); -} - -TEST(PIMathMatrixT_Test, rotationZ) { - double angle = 1.0; - double c = cos(angle); - double s = sin(angle); - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::rotationZ(angle); - ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (c == matrix.at(0u,0u)) && (c == matrix.at(1u,1u)) && (s == matrix.at(1u,0u)) && (-s == matrix.at(0u,1u))); -} - -TEST(PIMathMatrixT_Test, scaleX_three) { - double factor = 23.65; - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleX(factor); - ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (factor == matrix.at(0u,0u)) && (1.0 == matrix.at(1u,1u))); -} - -TEST(PIMathMatrixT_Test, scaleY_three) { - double factor = 23.65; - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleY(factor); - ASSERT_TRUE((1.0 == matrix.at(2u,2u)) && (1.0 == matrix.at(0u,0u)) && (factor == matrix.at(1u,1u))); -} - -TEST(PIMathMatrixT_Test, scaleZ_three) { - double factor = 23.65; - PIMathMatrixT<3u, 3u, double> matrix = PIMathMatrixT<3u, 3u, double>::scaleZ(factor); - ASSERT_TRUE((factor == matrix.at(2u,2u)) && (1.0 == matrix.at(0u,0u)) && (1.0 == matrix.at(1u,1u))); + double angle = 1.0; + auto matrix = PIMathMatrixT<2u, 2u, double>::identity(); + matrix.rotate(angle); + double c = cos(angle); + double s = sin(angle); + ASSERT_TRUE((c == matrix.at(1u,1u)) && (c == matrix.at(0u,0u)) && (-s == matrix.at(0u,1u)) && (s == matrix.at(1u,0u))); } TEST(PIMathMatrixT_Test, matrixMultiplication) { - auto matrix1 = PIMathMatrixT::filled(1.5); - auto matrix2 = PIMathMatrixT::filled(2.5); - ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 11.25, 3)); + auto matrix1 = PIMathMatrixT(1.5); + auto matrix2 = PIMathMatrixT(2.5); + ASSERT_TRUE(cmpSquareMatrixWithValue(matrix1 * matrix2, 11.25, 3)); } TEST(PIMathMatrixT_Test, matrixAndVectorMultiplication) { - auto matrix1 = PIMathMatrixT::filled(1.5); - auto vector = PIMathVectorT::filled(2.5); - for(uint i = 0; i < 2; i++) { - if((matrix1 * vector)[i] != 11.25) { - ASSERT_TRUE(false); - } - } - ASSERT_TRUE(true); + auto matrix1 = PIMathMatrixT(1.5); + auto vector = PIMathVectorT(2.5); + for(uint i = 0; i < 2; i++) { + if((matrix1 * vector)[i] != 11.25) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); } TEST(PIMathMatrixT_Test, vectorAndMatrixMultiplication) { - auto matrix1 = PIMathMatrixT::filled(1.5); - auto vector = PIMathVectorT::filled(2.5); - for(uint i = 0; i < 2; i++) { - if((vector * matrix1)[i] != 11.25) { - ASSERT_TRUE(false); - } - } + auto matrix1 = PIMathMatrixT(1.5); + auto vector = PIMathVectorT(2.5); + for(uint i = 0; i < 2; i++) { + if((vector * matrix1)[i] != 11.25) { + ASSERT_TRUE(false); + } + } } TEST(PIMathMatrixT_Test, valAndMatrixMultiplication) { - auto matrix1 = PIMathMatrixT::filled(1.5); - ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3)); + auto matrix1 = PIMathMatrixT(1.5); + ASSERT_TRUE(cmpSquareMatrixWithValue(25.0*matrix1, 37.5, 3)); } diff --git a/tests/math/testpivector2d.cpp b/tests/math/testpivector2d.cpp new file mode 100644 index 00000000..ae66b01c --- /dev/null +++ b/tests/math/testpivector2d.cpp @@ -0,0 +1,84 @@ +#include "gtest/gtest.h" +#include "pivector2d.h" + +int ROWS_COUNT_INIT = 31; +int ROWS_COUNT_INCREASE = 41; +int ROWS_COUNT_REDUCE = 22; + +int COLS_COUNT_INIT = 34; +int COLS_COUNT_INCREASE = 44; +int COLS_COUNT_REDUCE = 13; + +void assert_fill_with(PIVector2D vec, int rows, int cols) { + for(int r = 0; r < rows; r++) { + for(int c = 0; c < cols; c++) { + ASSERT_EQ(vec.element(r, c), r * COLS_COUNT_INIT + c); + } + } +} + +class Vector2D : public ::testing::Test { +protected: + PIVector2D vec = PIVector2D(ROWS_COUNT_INIT, COLS_COUNT_INIT); + + void SetUp() override { + for (int r = 0; r < ROWS_COUNT_INIT; ++r) { + for (int c = 0; c < COLS_COUNT_INIT; ++c) { + vec.element(r, c) = r * COLS_COUNT_INIT + c; + } + } + } + + void resize_reduce_is_data_stay_consistent(int newRowsCount, int newColsCount) { + vec.resize(newRowsCount, newColsCount, 0); + assert_fill_with(vec, newRowsCount, newColsCount); + } + + void resize_increase_is_data_stay_consistent(int newRowsCount, int newColsCount) { + vec.resize(newRowsCount, newColsCount, 0); + assert_fill_with(vec, ROWS_COUNT_INIT, COLS_COUNT_INIT); + + for (int r = 0; r < newRowsCount; ++r) { + for (int c = 0; c < newColsCount; ++c) { + if (r < ROWS_COUNT_INIT || c < COLS_COUNT_INIT) continue; + ASSERT_EQ(vec.element(r, c), 0); + } + } + } +}; + +TEST_F(Vector2D, resize_is_increase_col_count) { + vec.resize(ROWS_COUNT_INIT, COLS_COUNT_INCREASE, 0); + ASSERT_EQ(vec.cols(), COLS_COUNT_INCREASE); +} + +TEST_F(Vector2D, resize_is_reduce_col_count) { + vec.resize(ROWS_COUNT_INIT, COLS_COUNT_REDUCE, 0); + ASSERT_EQ(vec.cols(), COLS_COUNT_REDUCE); +} + +TEST_F(Vector2D, resize_is_increase_rows_count) { + vec.resize(ROWS_COUNT_INCREASE, COLS_COUNT_INIT, 0); + ASSERT_EQ(vec.rows(), ROWS_COUNT_INCREASE); +} + +TEST_F(Vector2D, resize_is_reduce_rows_count) { + vec.resize(ROWS_COUNT_REDUCE, COLS_COUNT_INIT, 0); + ASSERT_EQ(vec.rows(), ROWS_COUNT_REDUCE); +} + +TEST_F(Vector2D, resize_increase_both_is_data_stay_consistent) { + resize_increase_is_data_stay_consistent(ROWS_COUNT_INCREASE, COLS_COUNT_INCREASE); +} + +TEST_F(Vector2D, resize_reduce_cols_is_data_stay_consistent) { + resize_reduce_is_data_stay_consistent(ROWS_COUNT_INIT, COLS_COUNT_REDUCE); +} + +TEST_F(Vector2D, resize_reduce_rows_is_data_stay_consistent) { + resize_reduce_is_data_stay_consistent(ROWS_COUNT_REDUCE, COLS_COUNT_INIT); +} + +TEST_F(Vector2D, resize_reduce_both_is_data_stay_consistent) { + resize_reduce_is_data_stay_consistent(ROWS_COUNT_REDUCE, COLS_COUNT_REDUCE); +} diff --git a/tests/suppr.txt b/tests/suppr.txt new file mode 100644 index 00000000..ccdc4da6 --- /dev/null +++ b/tests/suppr.txt @@ -0,0 +1,2 @@ +leak:ConditionVariable::SetUp +leak:ConditionLock_ \ No newline at end of file diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index b207d679..8742ef26 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -325,7 +325,7 @@ void makeGetterValue(PIFile & f, const PICodeParser::Entity * e) { piForeachC (PICodeParser::Member & m, e->members) { if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue; - f << "\tif (strcmp(name, \"" << m.name << "\") == 0) {ret << o->" << m.name << "; return ret;}\n"; + f << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n"; } f << "\treturn ret;\n}\n"; } diff --git a/utils/deploy_tool/main.cpp b/utils/deploy_tool/main.cpp index dbee6b7d..98dccabb 100644 --- a/utils/deploy_tool/main.cpp +++ b/utils/deploy_tool/main.cpp @@ -67,7 +67,7 @@ void usage() { "[-p ] [-s ] [--ignore ] [-S ] " "[-l ] [-D ] [--dpkg-workdir ] [-L | -W | -M ] " "[--name-tool ] [-d ] [-q ] [-a ] [-S ] " - "[-P ] [--qt-plugins ] -o [ ...]\"" << NewLine; + "[-P ] [--qt-plugins ] [--qt-modules ] -o [ ...]\"" << NewLine; piCout << Green << Bold << "Details:"; piCout << Bold << "Debug control"; piCout << "-h, --help " << Green << "- display this message and exit"; @@ -92,10 +92,11 @@ void usage() { piCout << "-S " << Green << "- set Qt styles (e.g. \"oxygen,breeze\"), default \"*\""; piCout << "-P " << Green << "- set Qt platforms (e.g. \"win,mini\"), default by host system"; piCout << "--qt-plugins " << Green << "- set Qt plugins description"; + piCout << "--qt-modules " << Green << "- additional Qt modules, may be separated by \"" DELIM "\" (e.g. \"Sql" DELIM "Xml\")"; piCout << ""; piCout << Bold << "Output control"; piCout << "-o " << Green << "- path for libraries copy to"; - piCout << "-p " << Green << "- path for Qt plugins, default \"/plugins\""; + piCout << "-p " << Green << "- path for Qt plugins, default \"\""; piCout << "--dependencies " << Green << "- search dependencies by , print them and copy missing libraries"; piCout << "--prefix " << Green << "- print before dependencies"; piCout << ""; @@ -127,9 +128,10 @@ QtDep qt_deps[] = { int depth = 8; -bool fake = false, is_ldd = true, is_deps = false, need_qt = false; +bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true; PIString ldd, readelf, objdump, otool, dpkg, nametool, strip, out_dir, qt_dir, out_plugins_dir, dpkg_workdir; -PIStringList styles, lib_dirs, add_libs, platforms, sqldrivers, input_files, plugin_libs; +PIString qt_pref, qt_suff; +PIStringList styles, lib_dirs, add_libs, platforms, sqldrivers, input_files, plugin_libs, qt_add_libs; PISet all_libs, miss_libs, all_deps, frameworks, framework_libs, miss_frameworks, qt_plugins, ignore_libs; PIMap qt_filters; @@ -181,17 +183,22 @@ PIString execute(const PIString & cmd) { void checkQtLib(PIString lib) { - if (lib.startsWith("lib")) lib.cutLeft(3); - if (lib.startsWith("qt5")) lib.cutLeft(3); - if (lib.startsWith("qt")) lib.cutLeft(2); - if (lib.find(".")) lib = lib.left(lib.find(".")); - //piCout << "checkQt" << lib; + PIString pref, suff; + if (lib.startsWith("lib")) {pref += "lib"; lib.cutLeft(3);} + if (lib.startsWith("qt5")) {pref += "Qt5"; lib.cutLeft(3);} + if (lib.startsWith("qt" )) {pref += "Qt" ; lib.cutLeft(2);} + if (lib.find('.') >= 0) {suff = lib.right(lib.size_s() - lib.find('.')); lib = lib.left(lib.find('.'));} for (int i = 0; ; ++i) { if (qt_deps[i].lib.isEmpty()) break; if (qt_deps[i].lib == lib) { qt_plugins << qt_deps[i].plugins; //piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins; need_qt = true; + if (make_qt_format) { + make_qt_format = false; + qt_pref = pref; + qt_suff = suff; + } break; } } @@ -484,6 +491,7 @@ int main(int argc, char * argv[]) { cli.addArgument("Styles", true); cli.addArgument("Platforms", true); cli.addArgument("qt-plugins", PIChar('\0'), true); + cli.addArgument("qt-modules", PIChar('\0'), true); cli.addArgument("ldd", true); cli.addArgument("Lreadelf", true); cli.addArgument("Wobjdump", true); @@ -590,6 +598,9 @@ int main(int argc, char * argv[]) { qt_filters["platforms"] = platforms; qt_filters["styles" ] = styles ; + qt_add_libs = cli.argumentValue("qt-modules").split(DELIM); + need_qt = !qt_add_libs.isEmpty(); + auto it = qt_filters.makeIterator(); while (it.next()) it.valueRef().forEachInplace([](PIString i)->PIString{ @@ -616,8 +627,15 @@ int main(int argc, char * argv[]) { } }); //piCout << files; - if (depth > 0) + if (depth > 0) { input_files.forEach([&](const PIString & f){procLdd(f);}); + qt_add_libs.forEach([&](const PIString & f){ + PIString l = findLib(qt_pref + f + qt_suff); + if (l.isEmpty()) return; + procLdd(l, true); + checkQtLib(f.toLowerCase()); + }); + } piForeach (PIString & s, add_libs) { if (s.isEmpty()) continue; PIString alib = findLib(s);