1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 09:48:45 -05:00
sdrangel/plugins/channelrx/demoddatv/ldpctool/simd.h

1210 lines
29 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////////
/*
Single instruction, multiple data
Copyright 2018 Ahmet Inan <inan@aicodix.de>
*/
#ifndef SIMD_HH
#define SIMD_HH
#include <cstdint>
#include <cstdlib>
#include <cmath>
namespace ldpctool {
template <typename TYPE, int WIDTH>
union SIMD;
template <int WIDTH>
union SIMD<float, WIDTH>
{
static const int SIZE = WIDTH;
typedef float value_type;
typedef uint32_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<double, WIDTH>
{
static const int SIZE = WIDTH;
typedef double value_type;
typedef uint64_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<int8_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef int8_t value_type;
typedef uint8_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<int16_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef int16_t value_type;
typedef uint16_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<int32_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef int32_t value_type;
typedef uint32_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<int64_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef int64_t value_type;
typedef uint64_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<uint8_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef uint8_t value_type;
typedef uint8_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<uint16_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef uint16_t value_type;
typedef uint16_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<uint32_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef uint32_t value_type;
typedef uint32_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <int WIDTH>
union SIMD<uint64_t, WIDTH>
{
static const int SIZE = WIDTH;
typedef uint64_t value_type;
typedef uint64_t uint_type;
value_type v[SIZE];
uint_type u[SIZE];
};
template <typename TYPE>
static inline TYPE vdup(typename TYPE::value_type a)
{
TYPE tmp;
for (int i = 0; i < TYPE::SIZE; ++i)
tmp.v[i] = a;
return tmp;
}
template <typename TYPE>
static inline TYPE vzero()
{
TYPE tmp;
for (int i = 0; i < TYPE::SIZE; ++i)
tmp.u[i] ^= tmp.u[i];
return tmp;
}
template <typename DST, typename SRC>
static inline DST vreinterpret(SRC a)
{
static_assert(SRC::SIZE == DST::SIZE, "source and destination width must be same");
static_assert(sizeof(typename SRC::value_type) == sizeof(typename DST::value_type), "source and destination value type sizes must be same");
DST tmp;
for (int i = 0; i < DST::SIZE; ++i)
tmp.u[i] = a.u[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vmask(SIMD<float, WIDTH> a)
{
return vreinterpret<SIMD<uint32_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vmask(SIMD<double, WIDTH> a)
{
return vreinterpret<SIMD<uint64_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vmask(SIMD<int8_t, WIDTH> a)
{
return vreinterpret<SIMD<uint8_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vmask(SIMD<int16_t, WIDTH> a)
{
return vreinterpret<SIMD<uint16_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vmask(SIMD<int32_t, WIDTH> a)
{
return vreinterpret<SIMD<uint32_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vmask(SIMD<int64_t, WIDTH> a)
{
return vreinterpret<SIMD<uint64_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vunsigned(SIMD<int8_t, WIDTH> a)
{
return vreinterpret<SIMD<uint8_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vunsigned(SIMD<int16_t, WIDTH> a)
{
return vreinterpret<SIMD<uint16_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vunsigned(SIMD<int32_t, WIDTH> a)
{
return vreinterpret<SIMD<uint32_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vunsigned(SIMD<int64_t, WIDTH> a)
{
return vreinterpret<SIMD<uint64_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vsigned(SIMD<uint8_t, WIDTH> a)
{
return vreinterpret<SIMD<int8_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vsigned(SIMD<uint16_t, WIDTH> a)
{
return vreinterpret<SIMD<int16_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vsigned(SIMD<uint32_t, WIDTH> a)
{
return vreinterpret<SIMD<int32_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vsigned(SIMD<uint64_t, WIDTH> a)
{
return vreinterpret<SIMD<int64_t, WIDTH>>(a);
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vneg(SIMD<float, WIDTH> a)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vneg(SIMD<double, WIDTH> a)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vneg(SIMD<int8_t, WIDTH> a)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vneg(SIMD<int16_t, WIDTH> a)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vneg(SIMD<int32_t, WIDTH> a)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vneg(SIMD<int64_t, WIDTH> a)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -a.v[i];
return tmp;
}
template <typename TYPE, int WIDTH>
static inline SIMD<TYPE, WIDTH> vabs(SIMD<TYPE, WIDTH> a)
{
SIMD<TYPE, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::abs(a.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vqabs(SIMD<int8_t, WIDTH> a)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::abs(std::max<int8_t>(a.v[i], -INT8_MAX));
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vqabs(SIMD<int16_t, WIDTH> a)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::abs(std::max<int16_t>(a.v[i], -INT16_MAX));
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vqabs(SIMD<int32_t, WIDTH> a)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::abs(std::max<int32_t>(a.v[i], -INT32_MAX));
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vqabs(SIMD<int64_t, WIDTH> a)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::abs(std::max<int64_t>(a.v[i], -INT64_MAX));
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vnot(SIMD<uint8_t, WIDTH> a)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ~a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vnot(SIMD<uint16_t, WIDTH> a)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ~a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vnot(SIMD<uint32_t, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ~a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vnot(SIMD<uint64_t, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ~a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vorr(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] | b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vorr(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] | b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vorr(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] | b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vorr(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] | b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vand(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vand(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vand(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vand(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> veor(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] ^ b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> veor(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] ^ b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> veor(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] ^ b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> veor(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] ^ b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vbic(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & ~b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vbic(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & ~b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vbic(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & ~b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vbic(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] & ~b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vbsl(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b, SIMD<uint8_t, WIDTH> c)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = (a.v[i] & b.v[i]) | (~a.v[i] & c.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vbsl(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b, SIMD<uint16_t, WIDTH> c)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = (a.v[i] & b.v[i]) | (~a.v[i] & c.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vbsl(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b, SIMD<uint32_t, WIDTH> c)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = (a.v[i] & b.v[i]) | (~a.v[i] & c.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vbsl(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b, SIMD<uint64_t, WIDTH> c)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = (a.v[i] & b.v[i]) | (~a.v[i] & c.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcgtz(SIMD<float, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0.f);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcgtz(SIMD<double, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0.);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vcgtz(SIMD<int8_t, WIDTH> a)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vcgtz(SIMD<int16_t, WIDTH> a)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcgtz(SIMD<int32_t, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcgtz(SIMD<int64_t, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vceqz(SIMD<float, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == 0.f);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vceqz(SIMD<double, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == 0.);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vceqz(SIMD<int8_t, WIDTH> a)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -!a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vceqz(SIMD<int16_t, WIDTH> a)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -!a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vceqz(SIMD<int32_t, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -!a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vceqz(SIMD<int64_t, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -!a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcltz(SIMD<float, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0.f);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcltz(SIMD<double, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0.);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vcltz(SIMD<int8_t, WIDTH> a)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vcltz(SIMD<int16_t, WIDTH> a)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcltz(SIMD<int32_t, WIDTH> a)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcltz(SIMD<int64_t, WIDTH> a)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] < 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcgt(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcgt(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vcgt(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vcgt(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcgt(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcgt(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vcgt(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vcgt(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vcgt(SIMD<uint32_t, WIDTH> a, SIMD<uint32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vcgt(SIMD<uint64_t, WIDTH> a, SIMD<uint64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] > b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vceq(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vceq(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vceq(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vceq(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint32_t, WIDTH> vceq(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<uint32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint64_t, WIDTH> vceq(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<uint64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = -(a.v[i] == b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vmin(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vmin(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vmin(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vmin(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vmin(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vmin(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vmax(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vmax(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vmax(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vmax(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vmax(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vmax(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max(a.v[i], b.v[i]);
return tmp;
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vadd(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vadd(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vadd(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vadd(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vadd(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vadd(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] + b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vqadd(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min<int16_t>(std::max<int16_t>(int16_t(a.v[i]) + int16_t(b.v[i]), INT8_MIN), INT8_MAX);
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vqadd(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min<int32_t>(std::max<int32_t>(int32_t(a.v[i]) + int32_t(b.v[i]), INT16_MIN), INT16_MAX);
return tmp;
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vsub(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vsub(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vsub(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vsub(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vsub(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vsub(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = a.v[i] - b.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vqsub(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min<int16_t>(std::max<int16_t>(int16_t(a.v[i]) - int16_t(b.v[i]), INT8_MIN), INT8_MAX);
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vqsub(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::min<int32_t>(std::max<int32_t>(int32_t(a.v[i]) - int32_t(b.v[i]), INT16_MIN), INT16_MAX);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint8_t, WIDTH> vqsub(SIMD<uint8_t, WIDTH> a, SIMD<uint8_t, WIDTH> b)
{
SIMD<uint8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max<int16_t>(int16_t(a.v[i]) - int16_t(b.v[i]), 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<uint16_t, WIDTH> vqsub(SIMD<uint16_t, WIDTH> a, SIMD<uint16_t, WIDTH> b)
{
SIMD<uint16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = std::max<int32_t>(int32_t(a.v[i]) - int32_t(b.v[i]), 0);
return tmp;
}
template <int WIDTH>
static inline SIMD<float, WIDTH> vsign(SIMD<float, WIDTH> a, SIMD<float, WIDTH> b)
{
SIMD<float, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0.f) - (b.v[i] < 0.f)) * a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<double, WIDTH> vsign(SIMD<double, WIDTH> a, SIMD<double, WIDTH> b)
{
SIMD<double, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0.) - (b.v[i] < 0.)) * a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int8_t, WIDTH> vsign(SIMD<int8_t, WIDTH> a, SIMD<int8_t, WIDTH> b)
{
SIMD<int8_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0) - (b.v[i] < 0)) * a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int16_t, WIDTH> vsign(SIMD<int16_t, WIDTH> a, SIMD<int16_t, WIDTH> b)
{
SIMD<int16_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0) - (b.v[i] < 0)) * a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int32_t, WIDTH> vsign(SIMD<int32_t, WIDTH> a, SIMD<int32_t, WIDTH> b)
{
SIMD<int32_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0) - (b.v[i] < 0)) * a.v[i];
return tmp;
}
template <int WIDTH>
static inline SIMD<int64_t, WIDTH> vsign(SIMD<int64_t, WIDTH> a, SIMD<int64_t, WIDTH> b)
{
SIMD<int64_t, WIDTH> tmp;
for (int i = 0; i < WIDTH; ++i)
tmp.v[i] = ((b.v[i] > 0) - (b.v[i] < 0)) * a.v[i];
return tmp;
}
#if 0
#ifdef __AVX2__
#include "avx2.h"
#else
#ifdef __SSE4_1__
#include "sse4_1.h"
#endif
#endif
#ifdef __ARM_NEON__
#include "neon.h"
#endif
#endif
} // namespace ldpctool
#endif