fix shared_array::convertTo()

This commit is contained in:
Michael Davidsaver
2023-02-11 12:25:44 -08:00
parent 274133bcfc
commit e93909cf7e
2 changed files with 145 additions and 35 deletions
+35 -34
View File
@@ -263,13 +263,14 @@ void convertArr(ArrayType dtype, void *dbase,
case ArrayType::Bool: convertCast<int8_t, bool>(sbase, dbase, count); return;
case ArrayType::Int8:
case ArrayType::UInt8: memcpy(dbase, sbase, count*sizeof(int8_t)); return;
// cast sint -> *int always sign extends
case ArrayType::Int16:
case ArrayType::UInt16: convertCast<int8_t, int16_t>(sbase, dbase, count); return;
case ArrayType::Int32:
case ArrayType::UInt32: convertCast<int8_t, int32_t>(sbase, dbase, count); return;
case ArrayType::Int64:
case ArrayType::UInt64: convertCast<int8_t, int64_t>(sbase, dbase, count); return;
// cast sint -> sint extends sign
case ArrayType::Int16: convertCast<int8_t, int16_t>(sbase, dbase, count); return;
// cast sint -> uint does not extend sign
case ArrayType::UInt16: convertCast<int8_t, uint16_t>(sbase, dbase, count); return;
case ArrayType::Int32: convertCast<int8_t, int32_t>(sbase, dbase, count); return;
case ArrayType::UInt32: convertCast<int8_t, uint32_t>(sbase, dbase, count); return;
case ArrayType::Int64: convertCast<int8_t, int64_t>(sbase, dbase, count); return;
case ArrayType::UInt64: convertCast<int8_t, uint64_t>(sbase, dbase, count); return;
case ArrayType::Float32:convertCast<int8_t, float>(sbase, dbase, count); return;
case ArrayType::Float64:convertCast<int8_t, double>(sbase, dbase, count); return;
case ArrayType::String: convertToStr<int8_t>(sbase, dbase, count); return;
@@ -281,13 +282,13 @@ void convertArr(ArrayType dtype, void *dbase,
switch(dtype) {
case ArrayType::Bool: convertCast<int16_t, bool>(sbase, dbase, count); return;
case ArrayType::Int8:
case ArrayType::UInt8: convertCast<int16_t, int8_t>(sbase, dbase, count); return;
case ArrayType::UInt8: convertCast<uint16_t, uint8_t>(sbase, dbase, count); return;
case ArrayType::Int16:
case ArrayType::UInt16: memcpy(dbase, sbase, count*sizeof(int16_t)); return;
case ArrayType::Int32:
case ArrayType::UInt32: convertCast<int16_t, int32_t>(sbase, dbase, count); return;
case ArrayType::Int64:
case ArrayType::UInt64: convertCast<int16_t, int64_t>(sbase, dbase, count); return;
case ArrayType::Int32: convertCast<int16_t, int32_t>(sbase, dbase, count); return;
case ArrayType::UInt32: convertCast<int16_t, uint32_t>(sbase, dbase, count); return;
case ArrayType::Int64: convertCast<int16_t, int64_t>(sbase, dbase, count); return;
case ArrayType::UInt64: convertCast<int16_t, uint64_t>(sbase, dbase, count); return;
case ArrayType::Float32:convertCast<int16_t, float>(sbase, dbase, count); return;
case ArrayType::Float64:convertCast<int16_t, double>(sbase, dbase, count); return;
case ArrayType::String: convertToStr<int16_t>(sbase, dbase, count); return;
@@ -299,13 +300,13 @@ void convertArr(ArrayType dtype, void *dbase,
switch(dtype) {
case ArrayType::Bool: convertCast<int32_t, bool>(sbase, dbase, count); return;
case ArrayType::Int8:
case ArrayType::UInt8: convertCast<int32_t, int8_t>(sbase, dbase, count); return;
case ArrayType::UInt8: convertCast<uint32_t, uint8_t>(sbase, dbase, count); return;
case ArrayType::Int16:
case ArrayType::UInt16: convertCast<int32_t, int16_t>(sbase, dbase, count); return;
case ArrayType::UInt16: convertCast<uint32_t, uint16_t>(sbase, dbase, count); return;
case ArrayType::Int32:
case ArrayType::UInt32: memcpy(dbase, sbase, count*sizeof(int32_t)); return;
case ArrayType::Int64:
case ArrayType::UInt64: convertCast<int32_t, int64_t>(sbase, dbase, count); return;
case ArrayType::Int64: convertCast<int32_t, int64_t>(sbase, dbase, count); return;
case ArrayType::UInt64: convertCast<int32_t, uint64_t>(sbase, dbase, count); return;
case ArrayType::Float32:convertCast<int32_t, float>(sbase, dbase, count); return;
case ArrayType::Float64:convertCast<int32_t, double>(sbase, dbase, count); return;
case ArrayType::String: convertToStr<int32_t>(sbase, dbase, count); return;
@@ -407,14 +408,14 @@ void convertArr(ArrayType dtype, void *dbase,
case ArrayType::Float32:
switch(dtype) {
case ArrayType::Bool: convertCast<float, bool>(sbase, dbase, count); return;
case ArrayType::Int8:
case ArrayType::UInt8: convertCast<float, int8_t>(sbase, dbase, count); return;
case ArrayType::Int16:
case ArrayType::UInt16: convertCast<float, int16_t>(sbase, dbase, count); return;
case ArrayType::Int32:
case ArrayType::UInt32: convertCast<float, int32_t>(sbase, dbase, count); return;
case ArrayType::Int64:
case ArrayType::UInt64: convertCast<float, int64_t>(sbase, dbase, count); return;
case ArrayType::Int8: convertCast<float, int8_t>(sbase, dbase, count); return;
case ArrayType::UInt8: convertCast<float, uint8_t>(sbase, dbase, count); return;
case ArrayType::Int16: convertCast<float, int16_t>(sbase, dbase, count); return;
case ArrayType::UInt16: convertCast<float, uint16_t>(sbase, dbase, count); return;
case ArrayType::Int32: convertCast<float, int32_t>(sbase, dbase, count); return;
case ArrayType::UInt32: convertCast<float, uint32_t>(sbase, dbase, count); return;
case ArrayType::Int64: convertCast<float, int64_t>(sbase, dbase, count); return;
case ArrayType::UInt64: convertCast<float, uint64_t>(sbase, dbase, count); return;
case ArrayType::Float32:memcpy(dbase, sbase, count*sizeof(float)); return;
case ArrayType::Float64:convertCast<float, double>(sbase, dbase, count); return;
case ArrayType::String: convertToStr<float>(sbase, dbase, count); return;
@@ -425,16 +426,16 @@ void convertArr(ArrayType dtype, void *dbase,
case ArrayType::Float64:
switch(dtype) {
case ArrayType::Bool: convertCast<double, bool>(sbase, dbase, count); return;
case ArrayType::Int8:
case ArrayType::UInt8: convertCast<double, int8_t>(sbase, dbase, count); return;
case ArrayType::Int16:
case ArrayType::UInt16: convertCast<double, int16_t>(sbase, dbase, count); return;
case ArrayType::Int32:
case ArrayType::UInt32: convertCast<double, int32_t>(sbase, dbase, count); return;
case ArrayType::Int64:
case ArrayType::UInt64: convertCast<double, int64_t>(sbase, dbase, count); return;
case ArrayType::Float32:memcpy(dbase, sbase, count*sizeof(double)); return;
case ArrayType::Float64:convertCast<double, double>(sbase, dbase, count); return;
case ArrayType::Int8: convertCast<double, int8_t>(sbase, dbase, count); return;
case ArrayType::UInt8: convertCast<double, uint8_t>(sbase, dbase, count); return;
case ArrayType::Int16: convertCast<double, int16_t>(sbase, dbase, count); return;
case ArrayType::UInt16: convertCast<double, uint16_t>(sbase, dbase, count); return;
case ArrayType::Int32: convertCast<double, int32_t>(sbase, dbase, count); return;
case ArrayType::UInt32: convertCast<double, uint32_t>(sbase, dbase, count); return;
case ArrayType::Int64: convertCast<double, int64_t>(sbase, dbase, count); return;
case ArrayType::UInt64: convertCast<double, uint64_t>(sbase, dbase, count); return;
case ArrayType::Float32:convertCast<double, float>(sbase, dbase, count); return;
case ArrayType::Float64:memcpy(dbase, sbase, count*sizeof(double)); return;
case ArrayType::String: convertToStr<double>(sbase, dbase, count); return;
case ArrayType::Value:
case ArrayType::Null: break; // no convert
+110 -1
View File
@@ -7,6 +7,7 @@
#include <typeinfo>
#include <vector>
#include <string>
#include <limits>
#include <pvxs/sharedArray.h>
#include <pvxs/data.h>
@@ -324,12 +325,120 @@ void testElemAlloc()
testEq(varr.original_type(), ArrayType::UInt32);
}
// round trip conversion when TO can exactly represent all possible values of FROM
template<typename FROM, typename TO>
void testConvertExact()
{
shared_array<const FROM> inp({
FROM(0),
FROM(1),
FROM(-1),
std::numeric_limits<FROM>::min(),
std::numeric_limits<FROM>::max(),
});
shared_array<const TO> expect({
(TO)FROM(0),
(TO)FROM(1),
(TO)FROM(-1),
(TO)std::numeric_limits<FROM>::min(),
(TO)std::numeric_limits<FROM>::max(),
});
auto conv(inp.template convertTo<const TO>());
testShow()<<"Input "<<inp;
testArrEq(conv, expect)<<" "<<__func__<<"("<<typeid(FROM).name()<<" -> "<<typeid(TO).name()<<")";
testArrEq(expect.template convertTo<const FROM>(), inp)<<" "<<__func__<<"("<<typeid(FROM).name()<<" <- "<<typeid(TO).name()<<")";
}
// conversion based on truncation of unsigned integer
template<typename FROM, typename TO>
void testConvertTrunc()
{
shared_array<const FROM> inp({
FROM(0),
FROM(1),
FROM(-1),
std::numeric_limits<FROM>::min(),
std::numeric_limits<FROM>::max(),
});
shared_array<const TO> expect({
(TO)FROM(0),
(TO)FROM(1),
(TO)FROM(-1),
std::numeric_limits<TO>::min(),
std::numeric_limits<TO>::max(),
});
auto conv(inp.template convertTo<const TO>());
testShow()<<"Input "<<inp;
testArrEq(conv, expect)<<" "<<__func__<<"("<<typeid(FROM).name()<<" -> "<<typeid(TO).name()<<")";
}
void testConvert()
{
testDiag("%s", __func__);
static_assert (detail::CaptureCode<uint32_t>::code!=detail::CaptureCode<uint16_t>::code, "");
testDiag("reversible conversions");
testConvertExact<uint8_t, uint8_t>();
testConvertExact<uint8_t, int16_t>();
testConvertExact<uint8_t, uint16_t>();
testConvertExact<uint8_t, int32_t>();
testConvertExact<uint8_t, uint32_t>();
testConvertExact<uint8_t, int64_t>();
testConvertExact<uint8_t, uint64_t>();
testConvertExact<uint8_t, float>();
testConvertExact<uint8_t, double>();
testConvertExact<int8_t, int8_t>();
testConvertExact<int8_t, int16_t>();
testConvertExact<int8_t, uint16_t>();
testConvertExact<int8_t, int32_t>();
testConvertExact<int8_t, uint32_t>();
testConvertExact<int8_t, int64_t>();
testConvertExact<int8_t, uint64_t>();
testConvertExact<int8_t, float>();
testConvertExact<int8_t, double>();
testConvertExact<uint16_t, uint16_t>();
testConvertExact<uint16_t, int32_t>();
testConvertExact<uint16_t, uint32_t>();
testConvertExact<uint16_t, int64_t>();
testConvertExact<uint16_t, uint64_t>();
testConvertExact<uint16_t, float>();
testConvertExact<uint16_t, double>();
testConvertExact<int16_t, int16_t>();
testConvertExact<int16_t, int32_t>();
testConvertExact<int16_t, uint32_t>();
testConvertExact<int16_t, int64_t>();
testConvertExact<int16_t, uint64_t>();
testConvertExact<int16_t, float>();
testConvertExact<int16_t, double>();
testConvertExact<uint32_t, uint32_t>();
testConvertExact<uint32_t, int64_t>();
testConvertExact<uint32_t, uint64_t>();
testConvertExact<uint32_t, double>();
testConvertExact<int32_t, int32_t>();
testConvertExact<int32_t, int64_t>();
testConvertExact<int32_t, uint64_t>();
testConvertExact<int32_t, double>();
testConvertExact<uint64_t, uint64_t>();
testConvertExact<int64_t, int64_t>();
testConvertExact<float, double>();
testDiag("integer truncation");
testConvertTrunc<uint16_t, uint8_t>();
testConvertTrunc<uint32_t, uint8_t>();
testConvertTrunc<uint64_t, uint8_t>();
testConvertTrunc<uint32_t, uint16_t>();
testConvertTrunc<uint64_t, uint16_t>();
testConvertTrunc<uint64_t, uint32_t>();
testArrEq(shared_array<uint32_t>({1u, 2u, 0xffffffffu}).convertTo<uint32_t>(),
shared_array<uint32_t>({1u, 2u, 0xffffffffu}));
@@ -356,7 +465,7 @@ void testConvert()
MAIN(testshared)
{
testPlan(155);
testPlan(247);
testSetup();
testEmpty<void>();
testEmpty<const void>();