// Copyright (C) 2023 RozK // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef RK_ENGINE_CMP_MEMCPY_H #define RK_ENGINE_CMP_MEMCPY_H #include "../types.hpp" template [[RK_FAST]] inline bool _rk_cmp_memcpy_small( _small * __restrict dst, _small const * __restrict src, unsigned count) { _small cmp = 0; do { cmp |= *dst ^ *src; *dst++ = *src++; } while(--count > 0); return (cmp != 0); } template [[RK_FAST, RK_FLATTEN]] inline bool _rk_cmp_memcpy_big( _small * const __restrict _dst, _small const * const __restrict _src, unsigned const _count) { unsigned const ratio = sizeof(_big) / sizeof(_small); unsigned big_count = _count / ratio; unsigned const small_count = _count % ratio; _big * dst = reinterpret_cast<_big *>(_dst); _big const * src = reinterpret_cast<_big const *>(_src); _big cmp = 0; do { cmp |= *dst ^ *src; *dst++ = *src++; } while(--big_count > 0); bool modified = (cmp != 0); if (small_count) { modified |= _rk_cmp_memcpy_small<_small>( reinterpret_cast<_small *>(dst), reinterpret_cast<_small const *>(src), small_count); } return modified; } #ifdef RK_CMP_MEMCPY_UNALIGNED #define _rk_count_and_alignment(_t) (count >= (sizeof(_t) / sizeof(_small))) #else #define _rk_count_and_alignment(_t) ((count >= (sizeof(_t) / sizeof(_small))) && !(alignment % sizeof(_t))) #endif template [[RK_HOT, RK_FAST, RK_FLATTEN]] bool rk_cmp_memcpy( _small * const __restrict _dst, _small const * const __restrict _src, unsigned const count) { #ifndef RK_CMP_MEMCPY_UNALIGNED unsigned const alignment = reinterpret_cast(_dst) | reinterpret_cast(_src); #endif if (sizeof(_small) < sizeof(rk_ullong)) { if (_rk_count_and_alignment(rk_ullong)) { return _rk_cmp_memcpy_big(_dst, _src, count); } } if (sizeof(_small) < sizeof(rk_ulong)) { if (_rk_count_and_alignment(rk_ulong)) { return _rk_cmp_memcpy_big(_dst, _src, count); } } if (sizeof(_small) < sizeof(rk_uint)) { if (_rk_count_and_alignment(rk_uint)) { return _rk_cmp_memcpy_big(_dst, _src, count); } } if (sizeof(_small) < sizeof(rk_ushort)) { if (_rk_count_and_alignment(rk_ushort)) { return _rk_cmp_memcpy_big(_dst, _src, count); } } if (count) { return _rk_cmp_memcpy_small<_small>(_dst, _src, count); } return false; } #undef _rk_count_and_alignment #endif // RK_ENGINE_CMP_MEMCPY_H