Removed the CNPY dependency
The test data is directly in the file now...
This commit is contained in:
parent
6790df3709
commit
963e927b39
4 changed files with 353 additions and 771 deletions
|
|
@ -26,13 +26,8 @@ set(SFIZZ_TEST_SOURCES
|
|||
RegionTriggersT.cpp
|
||||
)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
add_library(cnpy cnpy/cnpy.cpp)
|
||||
target_link_libraries(cnpy PUBLIC ZLIB::ZLIB)
|
||||
target_include_directories(cnpy PUBLIC cnpy)
|
||||
|
||||
add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES})
|
||||
target_link_libraries(sfizz_tests PRIVATE sfizz::sfizz cnpy)
|
||||
target_link_libraries(sfizz_tests PRIVATE sfizz::sfizz)
|
||||
sfizz_enable_lto_if_needed(sfizz_tests)
|
||||
# target_link_libraries(sfizz_tests PRIVATE absl::strings absl::str_format absl::flat_hash_map cnpy absl::span absl::algorithm)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,21 +23,23 @@
|
|||
|
||||
#include "sfizz/OnePoleFilter.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include "cnpy.h"
|
||||
#include "ghc/fs_std.hpp"
|
||||
// #include "cnpy.h"
|
||||
// #include "ghc/fs_std.hpp"
|
||||
#include <absl/types/span.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
using namespace Catch::literals;
|
||||
|
||||
template <class Type>
|
||||
inline bool approxEqual(const std::vector<Type>& lhs, const std::vector<Type>& rhs)
|
||||
template <class Type, size_t N>
|
||||
inline bool approxEqual(const std::array<Type, N> &lhs, const std::array<Type, N> &rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < rhs.size(); ++i)
|
||||
if (lhs[i] != Approx(rhs[i]).epsilon(1e-3)) {
|
||||
if (lhs[i] != Approx(rhs[i]).epsilon(1e-3))
|
||||
{
|
||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
||||
return false;
|
||||
}
|
||||
|
|
@ -45,168 +47,362 @@ inline bool approxEqual(const std::vector<Type>& lhs, const std::vector<Type>& r
|
|||
return true;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
void testLowpass(const fs::path& inputNumpyFile, const fs::path& outputNumpyFile, Type gain)
|
||||
template <class Type, size_t N>
|
||||
void testFilter(const std::array<Type, N>& input, const std::array<Type, N>& expectedLow, const std::array<Type, N>& expectedHigh, Type gain)
|
||||
{
|
||||
const auto input = cnpy::npy_load(inputNumpyFile.string());
|
||||
REQUIRE(input.word_size == 8);
|
||||
const auto inputSpan = absl::MakeSpan(input.data<double>(), input.shape[0]);
|
||||
std::array<Type, N> output { static_cast<Type>(0.0) };
|
||||
auto outputSpan = absl::MakeSpan(output);
|
||||
|
||||
const auto output = cnpy::npy_load(outputNumpyFile.string());
|
||||
REQUIRE(output.word_size == 8);
|
||||
const auto outputSpan = absl::MakeSpan(output.data<double>(), output.shape[0]);
|
||||
auto size = std::min(outputSpan.size(), inputSpan.size());
|
||||
REQUIRE(size > 0);
|
||||
|
||||
std::vector<Type> inputData;
|
||||
std::vector<Type> expectedData;
|
||||
inputData.reserve(size);
|
||||
expectedData.reserve(size);
|
||||
for (auto& data : inputSpan)
|
||||
inputData.push_back(static_cast<Type>(data));
|
||||
for (auto& data : outputSpan)
|
||||
expectedData.push_back(static_cast<Type>(data));
|
||||
std::array<Type, N> gains;
|
||||
std::fill(gains.begin(), gains.end(), gain);
|
||||
|
||||
sfz::OnePoleFilter<Type> filter { gain };
|
||||
std::vector<Type> outputData(size);
|
||||
filter.processLowpass(inputData, absl::MakeSpan(outputData));
|
||||
REQUIRE(approxEqual(outputData, expectedData));
|
||||
filter.processLowpass(input, outputSpan);
|
||||
REQUIRE(approxEqual(output, expectedLow));
|
||||
|
||||
filter.reset();
|
||||
std::fill(outputData.begin(), outputData.end(), 0.0f);
|
||||
std::vector<Type> gains(size);
|
||||
std::fill(gains.begin(), gains.end(), gain);
|
||||
filter.processLowpassVariableGain(inputData, absl::MakeSpan(outputData), gains);
|
||||
REQUIRE(approxEqual(outputData, expectedData));
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
void testHighpass(const fs::path& inputNumpyFile, const fs::path& outputNumpyFile, Type gain)
|
||||
{
|
||||
const auto input = cnpy::npy_load(inputNumpyFile.string());
|
||||
REQUIRE(input.word_size == 8);
|
||||
const auto inputSpan = absl::MakeSpan(input.data<double>(), input.shape[0]);
|
||||
|
||||
const auto output = cnpy::npy_load(outputNumpyFile.string());
|
||||
REQUIRE(output.word_size == 8);
|
||||
const auto outputSpan = absl::MakeSpan(output.data<double>(), output.shape[0]);
|
||||
auto size = std::min(outputSpan.size(), inputSpan.size());
|
||||
REQUIRE(size > 0);
|
||||
|
||||
std::vector<Type> inputData;
|
||||
std::vector<Type> expectedData;
|
||||
inputData.reserve(size);
|
||||
expectedData.reserve(size);
|
||||
for (auto& data : inputSpan)
|
||||
inputData.push_back(static_cast<Type>(data));
|
||||
for (auto& data : outputSpan)
|
||||
expectedData.push_back(static_cast<Type>(data));
|
||||
|
||||
sfz::OnePoleFilter<Type> filter { gain };
|
||||
std::vector<Type> outputData(size);
|
||||
filter.processHighpass(inputData, absl::MakeSpan(outputData));
|
||||
REQUIRE(approxEqual(outputData, expectedData));
|
||||
filter.processLowpassVariableGain(input, outputSpan, gains);
|
||||
REQUIRE(approxEqual(output, expectedLow));
|
||||
|
||||
filter.reset();
|
||||
std::fill(outputData.begin(), outputData.end(), 0.0f);
|
||||
std::vector<Type> gains(size);
|
||||
std::fill(gains.begin(), gains.end(), gain);
|
||||
filter.processHighpassVariableGain(inputData, absl::MakeSpan(outputData), gains);
|
||||
REQUIRE(approxEqual(outputData, expectedData));
|
||||
filter.processHighpass(input, outputSpan);
|
||||
REQUIRE(approxEqual(output, expectedHigh));
|
||||
|
||||
filter.reset();
|
||||
filter.processHighpassVariableGain(input, outputSpan, gains);
|
||||
REQUIRE(approxEqual(output, expectedHigh));
|
||||
}
|
||||
|
||||
TEST_CASE("[OnePoleFilter] Lowpass Float")
|
||||
{
|
||||
testLowpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
||||
0.1f);
|
||||
testLowpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
||||
0.3f);
|
||||
testLowpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
||||
0.5f);
|
||||
testLowpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
||||
0.7f);
|
||||
testLowpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
||||
0.9f);
|
||||
}
|
||||
constexpr std::array<float, 64> floatInput01 = {
|
||||
0.7224561488760388f, 0.7385973866948313f, -0.7270493193023231f, -0.10016187172526334f,
|
||||
-0.21705352538152722f, 0.2043840469350767f, -0.9596683661285715f, 0.8180755983644133f,
|
||||
-0.5353916316790325f, -0.3824795777486836f, -0.5199451873852872f, 1.224527476430308f,
|
||||
-1.5955302866080707f, -0.98620318862471f, 0.21447545419407035f, 1.9078154714253879f,
|
||||
-1.18546464770056f, 0.1160266352187059f, -0.14909079569914221f, 0.8926491360964995f,
|
||||
-0.25664421027272116f, -2.88400550880041f, 0.8120130589050852f, -1.2802705105092436f,
|
||||
1.1786547670902738f, 0.564152384756787f, 0.6572670188585557f, -1.2583862043651877f,
|
||||
0.06968219078056098f, -1.8460954875508593f, 0.31619623348534576f, -1.118168076837949f,
|
||||
-0.23268233682843759f, -0.05426088793091379f, -2.369490498577162f, 0.8741655425846802f,
|
||||
0.9695153245133031f, -0.9676818537948265f, 0.3584177148506203f, 0.4488503636037592f,
|
||||
-0.3389304100181121f, 1.2027174865060049f, 0.03546769154829243f, 0.09928053501681143f,
|
||||
-0.7585793622743948f, -0.5387748222254498f, -0.2199304726734363f, 0.63404938853515f,
|
||||
1.1666758495956464f, -0.04382336233428379f, 0.43819763320865857f, 0.1740610608056625f,
|
||||
0.30473671729007396f, -0.4065881153810866f, -0.9784770671900811f, -0.17674381857142665f,
|
||||
0.3493213284003123f, -1.2540491577273034f, 1.2597719140599792f, 0.4198847510851298f,
|
||||
0.9612865621570132f, -1.5614809857797225f, -0.31416474166626646f, -1.4741449502960542f };
|
||||
|
||||
TEST_CASE("[OnePoleFilter] Lowpass Double")
|
||||
{
|
||||
testLowpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
||||
0.1f);
|
||||
testLowpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
||||
0.3f);
|
||||
testLowpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
||||
0.5f);
|
||||
testLowpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
||||
0.7f);
|
||||
testLowpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
||||
0.9f);
|
||||
}
|
||||
constexpr std::array<float, 64> floatOutputLow01 = {
|
||||
0.06567783171600353f, 0.18655945645590016f, 0.15368937959051f, 0.05054483866245487f,
|
||||
0.012517104623209388f, 0.00908949665113036f, -0.06122534993939287f, -0.06296553792897218f,
|
||||
-0.025818715879578978f, -0.10456724112217516f, -0.16759363047577702f, -0.07306912593063386f,
|
||||
-0.0935113585048607f, -0.3112123365251388f, -0.32478534210517174f, -0.07279792302973517f,
|
||||
0.0061063196779283235f, -0.09222555776186356f, -0.07846310730338257f, 0.0033991249697194748f,
|
||||
0.060599731868295786f, -0.23593201202349717f, -0.38139823255516353f, -0.3546219586000573f,
|
||||
-0.2993830337108623f, -0.08651274105006361f, 0.040254975833160934f, -0.02171130936438033f,
|
||||
-0.1258277998058227f, -0.2644421359111548f, -0.3554434979332642f, -0.3637239386138164f,
|
||||
-0.42039689647188494f, -0.370046844818756f, -0.5231066354433527f, -0.5639349704529687f,
|
||||
-0.2937939879071577f, -0.24021022004054027f, -0.2519232835735517f, -0.13273104306432598f,
|
||||
-0.09860540309029879f, -0.0021510501204360377f, 0.11080233881548844f, 0.10290629780949997f,
|
||||
0.024259804820719655f, -0.09809235828303345f, -0.14923059267692612f, -0.08445058347551104f,
|
||||
0.09460636244101792f, 0.17948270447550216f, 0.18270169192308128f, 0.20514308375655024f,
|
||||
0.21137141199133533f, 0.16368102816645502f, 0.008005824629720673f, -0.0984698603721838f,
|
||||
-0.06487738486552441f, -0.13532948119242824f, -0.11020387039992532f, 0.06252925741325283f,
|
||||
0.1767213299964926f, 0.0900270496677931f, -0.09685475276689556f, -0.24181840607858007f };
|
||||
|
||||
TEST_CASE("[OnePoleFilter] Highpass Float")
|
||||
{
|
||||
testHighpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
||||
0.1f);
|
||||
testHighpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
||||
0.3f);
|
||||
testHighpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
||||
0.5f);
|
||||
testHighpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
||||
0.7f);
|
||||
testHighpass<float>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
||||
0.9f);
|
||||
}
|
||||
constexpr std::array<float, 64> floatOutputHigh01 = {
|
||||
0.6567783171600353f, 0.5520379302389311f, -0.8807386988928331f, -0.1507067103877182f,
|
||||
-0.2295706300047366f, 0.19529455028394632f, -0.8984430161891787f, 0.8810411362933855f,
|
||||
-0.5095729157994535f, -0.2779123366265084f, -0.35235155690951014f, 1.297596602360942f,
|
||||
-1.50201892810321f, -0.6749908520995712f, 0.5392607962992421f, 1.980613394455123f,
|
||||
-1.1915709673784882f, 0.20825219298056946f, -0.07062768839575964f, 0.88925001112678f,
|
||||
-0.3172439421410169f, -2.6480734967769126f, 1.1934112914602488f, -0.9256485519091863f,
|
||||
1.4780378008011361f, 0.6506651258068505f, 0.6170120430253947f, -1.2366748950008073f,
|
||||
0.1955099905863837f, -1.5816533516397044f, 0.67163973141861f, -0.7544441382241325f,
|
||||
0.18771455964344735f, 0.3157859568878422f, -1.8463838631338094f, 1.4381005130376487f,
|
||||
1.2633093124204609f, -0.7274716337542863f, 0.610340998424172f, 0.5815814066680851f,
|
||||
-0.24032500692781328f, 1.204868536626441f, -0.07533464726719602f, -0.0036257627926885444f,
|
||||
-0.7828391670951145f, -0.4406824639424164f, -0.07069987999651017f, 0.7184999720106611f,
|
||||
1.0720694871546286f, -0.22330606680978596f, 0.2554959412855773f, -0.031082022950887744f,
|
||||
0.09336530529873863f, -0.5702691435475415f, -0.9864828918198018f, -0.07827395819924285f,
|
||||
0.41419871326583674f, -1.1187196765348753f, 1.3699757844599045f, 0.35735549367187697f,
|
||||
0.7845652321605207f, -1.6515080354475156f, -0.2173099888993709f, -1.2323265442174742f };
|
||||
|
||||
TEST_CASE("[OnePoleFilter] Highpass Double")
|
||||
constexpr std::array<float, 64> floatInput05 = {
|
||||
-0.8247415510202276f, -1.0299159073255513f, 0.7689727513393745f, -0.023063681797826918f,
|
||||
-0.1893245087721241f, -1.615552722124904f, -1.251848891438835f, 0.5338780197836666f,
|
||||
-0.3244188100039259f, 2.598277589396897f, -0.12170602745517456f, -2.7269013649087737f,
|
||||
-1.1332228949082876f, 0.5657123485919064f, 1.7914098463628945f, 0.7841799713943826f,
|
||||
0.22029184793596254f, 0.19814576077109303f, -0.0507307457285169f, 1.190488685111505f,
|
||||
-0.6761916505498549f, -1.083729826174603f, 0.405468008682514f, -1.2478635255587003f,
|
||||
-0.25157954751030825f, -0.9671361521687468f, -0.6434412998426552f, -0.9664977307097671f,
|
||||
-0.9150555987123582f, 1.697917162123366f, -1.3216510109214192f, -1.3943141278602609f,
|
||||
-0.7314910022591513f, -0.8889827595848262f, 1.3514782911515115f, 2.297097472618343f,
|
||||
-0.8897506799878153f, -0.706235549786705f, -0.25391776134956306f, -1.739982172732943f,
|
||||
-0.23465780260154823f, -0.0475767318206883f, -0.441164577073652f, -0.5072245472018251f,
|
||||
-1.1057148994224053f, 0.40324702616815694f, 0.815435779107782f, 0.25403283232711865f,
|
||||
-0.6137810912250902f, -0.7039958189789415f, -1.33840097232278f, 0.4786946763969468f,
|
||||
-0.46464793721558995f, -1.7121509287301122f, 0.7887828546774234f, -0.902172963851904f,
|
||||
-0.2591368523894675f, -0.9510361177022718f, 0.5739217219088085f, -0.25730420306720403f,
|
||||
0.41740839680521646f, -2.0979181310103074f, 1.1494564006889283f, 0.5059893282486726f };
|
||||
|
||||
constexpr std::array<float, 64> floatOutputLow05 = {
|
||||
-0.27491385034007587f, -0.7098571028952849f, -0.32360008629382064f, 0.14076966108257558f,
|
||||
-0.023872843162458468f, -0.6095833580198289f, -1.1589949905278558f, -0.6256552873943414f,
|
||||
-0.1387320258715336f, 0.7117089178404791f, 1.0627601599274006f, -0.5952824108121825f,
|
||||
-1.4851355568764144f, -0.6842153677309318f, 0.557635609074623f, 1.0444084756106333f,
|
||||
0.6829600983136596f, 0.3671325690069051f, 0.1715158613498271f, 0.43709126691093836f,
|
||||
0.3171294338241961f, -0.48093068096675384f, -0.3863974994862809f, -0.4095976721208223f,
|
||||
-0.6363469150632769f, -0.6183542049141106f, -0.7429772189751709f, -0.7843054165091977f,
|
||||
-0.8886195819771077f, -0.03525267285536671f, 0.11367115944885997f, -0.8674313264442733f,
|
||||
-0.9977454855212284f, -0.8727397491217354f, -0.13674807251835008f, 1.170609230417168f,
|
||||
0.8593186743492318f, -0.24555585180842954f, -0.4019030543148992f, -0.7986009961324684f,
|
||||
-0.9244136571556533f, -0.40221606385929665f, -0.29698579091787897f, -0.4151249717311187f,
|
||||
-0.6760214727851164f, -0.4594964486797883f, 0.2530621188653835f, 0.44084357676676134f,
|
||||
0.02703177262292994f, -0.4302483791937005f, -0.8242150568318073f, -0.5613071175858801f,
|
||||
-0.18242012613484115f, -0.7864063306935144f, -0.5699248015820677f, -0.22777163691884944f,
|
||||
-0.46302715105340697f, -0.5577333737150487f, -0.311615923169504f, 0.001667198557366828f,
|
||||
0.05392379743179307f, -0.5421953122577658f, -0.49688568085971485f, 0.3861866826926287f };
|
||||
|
||||
constexpr std::array<float, 64> floatOutputHigh05 = {
|
||||
-0.5498277006801517f, -0.32005880443026635f, 1.0925728376331951f, -0.1638333428804025f,
|
||||
-0.16545166560966562f, -1.005969364105075f, -0.09285390091097923f, 1.159533307178008f,
|
||||
-0.1856867841323923f, 1.886568671556418f, -1.1844661873825753f, -2.131618954096591f,
|
||||
0.35191266196812676f, 1.2499277163228384f, 1.2337742372882716f, -0.26022850421625077f,
|
||||
-0.462668250377697f, -0.16898680823581208f, -0.222246607078344f, 0.7533974182005667f,
|
||||
-0.993321084374051f, -0.602799145207849f, 0.7918655081687949f, -0.838265853437878f,
|
||||
0.38476736755296864f, -0.3487819472546362f, 0.0995359191325157f, -0.18219231420056936f,
|
||||
-0.026436016735250534f, 1.7331698349787326f, -1.4353221703702792f, -0.5268828014159875f,
|
||||
0.2662544832620771f, -0.016243010463090846f, 1.4882263636698616f, 1.126488242201175f,
|
||||
-1.7490693543370472f, -0.46067969797827546f, 0.14798529296533613f, -0.9413811766004746f,
|
||||
0.689755854554105f, 0.35463933203860837f, -0.144178786155773f, -0.09209957547070641f,
|
||||
-0.42969342663728893f, 0.8627434748479452f, 0.5623736602423985f, -0.18681074443964268f,
|
||||
-0.6408128638480202f, -0.27374743978524096f, -0.5141859154909728f, 1.040001793982827f,
|
||||
-0.2822278110807488f, -0.9257445980365978f, 1.358707656259491f, -0.6744013269330547f,
|
||||
0.20389029866393948f, -0.3933027439872231f, 0.8855376450783126f, -0.2589714016245709f,
|
||||
0.36348459937342337f, -1.5557228187525416f, 1.6463420815486431f, 0.11980264555604392f };
|
||||
|
||||
constexpr std::array<float, 64> floatInput09 = {
|
||||
-0.9629663717342508f, 1.054078826032172f, -1.0644939081323097f, -0.05328934531304567f,
|
||||
-0.04857086206002074f, 1.612607856597715f, 1.0513263960877668f, -1.4323863476593215f,
|
||||
2.2461810968138463f, -0.6561891523704232f, 0.022772627664592485f, 0.07616465991959669f,
|
||||
0.8305193318990887f, -0.4888237081549593f, 0.8564039983858606f, 1.4871994957279644f,
|
||||
0.22673465240234947f, 1.658079098180724f, -1.7453062858413877f, -0.11612580324446467f,
|
||||
-0.20232260689840872f, -1.1476998404072543f, -0.6202811352543974f, 1.545975326252028f,
|
||||
1.0442436933320733f, -1.0968040236666232f, 0.7595527972844077f, 1.2073698123442007f,
|
||||
-0.8873573213734941f, -0.17122644896880435f, -1.7574830431070918f, 0.19907680046299245f,
|
||||
1.27872961557419f, -0.7422656051046687f, -0.6846620117838057f, -0.13384854423135875f,
|
||||
0.9007202159691193f, 1.1254806648626967f, -0.04344693397840567f, 0.7948730146831712f,
|
||||
1.1781603468141004f, 0.1875496039927383f, 1.692965002836772f, -0.04201566153548597f,
|
||||
1.1210100661199038f, -0.7501096833348359f, 0.020210228191464837f, 1.9979804313376157f,
|
||||
0.7517403248613556f, 1.1194691465807607f, -1.1160170942539855f, -1.0010374555669668f,
|
||||
2.1609909686692763f, -0.07213993925443297f, -0.5083174992310037f, -0.7489925703250175f,
|
||||
0.5119124853257149f, -0.33950253799120345f, -0.26764774112191847f, 0.10271208568438035f,
|
||||
-0.09893862035889031f, -0.4154625911342657f, 0.11272544601558693f, -0.6895075000870634f };
|
||||
|
||||
constexpr std::array<float, 64> floatOutputLow09 = {
|
||||
-0.45614196555832937f, 0.01915105911173487f, -0.003925509462605503f, -0.5296828837089897f,
|
||||
-0.0761276184245572f, 0.7368529122323524f, 1.3006453256000892f, -0.1120470651865213f,
|
||||
0.37958450932653687f, 0.7731322110167023f, -0.25934823743872504f, 0.033215123727314666f,
|
||||
0.4312300552681833f, 0.1845521404718603f, 0.18383025013420895f, 1.1198032472188755f,
|
||||
0.8708005568627211f, 0.9386381216900201f, 0.008083864881265557f, -0.8813055229942847f,
|
||||
-0.19722848496211295f, -0.6498647637217411f, -0.8716680812987687f, 0.39260945461473207f,
|
||||
1.2476095068879813f, 0.040766659677738515f, -0.1576049672506421f, 0.9234051852319387f,
|
||||
0.20018513705096297f, -0.49089835768577506f, -0.9394359887562548f, -0.7876364301343762f,
|
||||
0.6585590165368562f, 0.2887755321453973f, -0.6607143694658354f, -0.4224899670317008f,
|
||||
0.34101868834779714f, 0.9777277166228496f, 0.5640016470832352f, 0.38562296702242765f,
|
||||
0.9548906958156775f, 0.6971726448988013f, 0.9274633740191786f, 0.8308424971437238f,
|
||||
0.5548311651791308f, 0.204891295276039f, -0.3349580947902264f, 0.9383556758406053f,
|
||||
1.3518864464016498f, 0.9575142994410892f, 0.0520306721253716f, -1.0000768566454319f,
|
||||
0.496816040067124f, 1.015603963410564f, -0.22150068331359823f, -0.6072258583851468f,
|
||||
-0.14426034859888792f, 0.07407521986377441f, -0.2836988048502276f, -0.09305893177831953f,
|
||||
-0.003110407570995219f, -0.24382743742154736f, -0.15623482860471877f, -0.28143543764463197f };
|
||||
|
||||
constexpr std::array<float, 64> floatOutputHigh09 = {
|
||||
-0.5068244061759215f, 1.034927766920437f, -1.0605683986697043f, 0.47639353839594406f,
|
||||
0.027556756364536465f, 0.8757549443653627f, -0.24931892951232237f, -1.3203392824728002f,
|
||||
1.8665965874873094f, -1.4293213633871256f, 0.2821208651033175f, 0.04294953619228202f,
|
||||
0.39928927663090535f, -0.6733758486268195f, 0.6725737482516516f, 0.3673962485090889f,
|
||||
-0.6440659044603716f, 0.7194409764907039f, -1.7533901507226533f, 0.76517971974982f,
|
||||
-0.00509412193629577f, -0.4978350766855132f, 0.2513869460443713f, 1.1533658716372959f,
|
||||
-0.203365813555908f, -1.1375706833443617f, 0.9171577645350498f, 0.283964627112262f,
|
||||
-1.087542458424457f, 0.3196719087169707f, -0.818047054350837f, 0.9867132305973687f,
|
||||
0.6201705990373338f, -1.031041137250066f, -0.023947642317970308f, 0.288641422800342f,
|
||||
0.5597015276213222f, 0.14775294823984708f, -0.6074485810616409f, 0.4092500476607435f,
|
||||
0.22326965099842289f, -0.5096230409060629f, 0.7655016288175934f, -0.8728581586792098f,
|
||||
0.5661789009407731f, -0.9550009786108749f, 0.35516832298169126f, 1.0596247554970104f,
|
||||
-0.6001461215402942f, 0.16195484713967145f, -1.1680477663793571f, -0.0009605989215348831f,
|
||||
1.6641749286021523f, -1.087743902664997f, -0.28681681591740543f, -0.14176671193987078f,
|
||||
0.6561728339246028f, -0.41357775785497786f, 0.016051063728309112f, 0.19577101746269987f,
|
||||
-0.09582821278789509f, -0.17163515371271834f, 0.2689602746203057f, -0.40807206244243144f };
|
||||
|
||||
constexpr std::array<double, 64> doubleInput01 = {
|
||||
0.7224561488760388, 0.7385973866948313, -0.7270493193023231, -0.10016187172526334,
|
||||
-0.21705352538152722, 0.2043840469350767, -0.9596683661285715, 0.8180755983644133,
|
||||
-0.5353916316790325, -0.3824795777486836, -0.5199451873852872, 1.224527476430308,
|
||||
-1.5955302866080707, -0.98620318862471, 0.21447545419407035, 1.9078154714253879,
|
||||
-1.18546464770056, 0.1160266352187059, -0.14909079569914221, 0.8926491360964995,
|
||||
-0.25664421027272116, -2.88400550880041, 0.8120130589050852, -1.2802705105092436,
|
||||
1.1786547670902738, 0.564152384756787, 0.6572670188585557, -1.2583862043651877,
|
||||
0.06968219078056098, -1.8460954875508593, 0.31619623348534576, -1.118168076837949,
|
||||
-0.23268233682843759, -0.05426088793091379, -2.369490498577162, 0.8741655425846802,
|
||||
0.9695153245133031, -0.9676818537948265, 0.3584177148506203, 0.4488503636037592,
|
||||
-0.3389304100181121, 1.2027174865060049, 0.03546769154829243, 0.09928053501681143,
|
||||
-0.7585793622743948, -0.5387748222254498, -0.2199304726734363, 0.63404938853515,
|
||||
1.1666758495956464, -0.04382336233428379, 0.43819763320865857, 0.1740610608056625,
|
||||
0.30473671729007396, -0.4065881153810866, -0.9784770671900811, -0.17674381857142665,
|
||||
0.3493213284003123, -1.2540491577273034, 1.2597719140599792, 0.4198847510851298,
|
||||
0.9612865621570132, -1.5614809857797225, -0.31416474166626646, -1.4741449502960542 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputLow01 = {
|
||||
0.06567783171600353, 0.18655945645590016, 0.15368937959051, 0.05054483866245487,
|
||||
0.012517104623209388, 0.00908949665113036, -0.06122534993939287, -0.06296553792897218,
|
||||
-0.025818715879578978, -0.10456724112217516, -0.16759363047577702, -0.07306912593063386,
|
||||
-0.0935113585048607, -0.3112123365251388, -0.32478534210517174, -0.07279792302973517,
|
||||
0.0061063196779283235, -0.09222555776186356, -0.07846310730338257, 0.0033991249697194748,
|
||||
0.060599731868295786, -0.23593201202349717, -0.38139823255516353, -0.3546219586000573,
|
||||
-0.2993830337108623, -0.08651274105006361, 0.040254975833160934, -0.02171130936438033,
|
||||
-0.1258277998058227, -0.2644421359111548, -0.3554434979332642, -0.3637239386138164,
|
||||
-0.42039689647188494, -0.370046844818756, -0.5231066354433527, -0.5639349704529687,
|
||||
-0.2937939879071577, -0.24021022004054027, -0.2519232835735517, -0.13273104306432598,
|
||||
-0.09860540309029879, -0.0021510501204360377, 0.11080233881548844, 0.10290629780949997,
|
||||
0.024259804820719655, -0.09809235828303345, -0.14923059267692612, -0.08445058347551104,
|
||||
0.09460636244101792, 0.17948270447550216, 0.18270169192308128, 0.20514308375655024,
|
||||
0.21137141199133533, 0.16368102816645502, 0.008005824629720673, -0.0984698603721838,
|
||||
-0.06487738486552441, -0.13532948119242824, -0.11020387039992532, 0.06252925741325283,
|
||||
0.1767213299964926, 0.0900270496677931, -0.09685475276689556, -0.24181840607858007 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputHigh01 = {
|
||||
0.6567783171600353, 0.5520379302389311, -0.8807386988928331, -0.1507067103877182,
|
||||
-0.2295706300047366, 0.19529455028394632, -0.8984430161891787, 0.8810411362933855,
|
||||
-0.5095729157994535, -0.2779123366265084, -0.35235155690951014, 1.297596602360942,
|
||||
-1.50201892810321, -0.6749908520995712, 0.5392607962992421, 1.980613394455123,
|
||||
-1.1915709673784882, 0.20825219298056946, -0.07062768839575964, 0.88925001112678,
|
||||
-0.3172439421410169, -2.6480734967769126, 1.1934112914602488, -0.9256485519091863,
|
||||
1.4780378008011361, 0.6506651258068505, 0.6170120430253947, -1.2366748950008073,
|
||||
0.1955099905863837, -1.5816533516397044, 0.67163973141861, -0.7544441382241325,
|
||||
0.18771455964344735, 0.3157859568878422, -1.8463838631338094, 1.4381005130376487,
|
||||
1.2633093124204609, -0.7274716337542863, 0.610340998424172, 0.5815814066680851,
|
||||
-0.24032500692781328, 1.204868536626441, -0.07533464726719602, -0.0036257627926885444,
|
||||
-0.7828391670951145, -0.4406824639424164, -0.07069987999651017, 0.7184999720106611,
|
||||
1.0720694871546286, -0.22330606680978596, 0.2554959412855773, -0.031082022950887744,
|
||||
0.09336530529873863, -0.5702691435475415, -0.9864828918198018, -0.07827395819924285,
|
||||
0.41419871326583674, -1.1187196765348753, 1.3699757844599045, 0.35735549367187697,
|
||||
0.7845652321605207, -1.6515080354475156, -0.2173099888993709, -1.2323265442174742 };
|
||||
|
||||
constexpr std::array<double, 64> doubleInput05 = {
|
||||
-0.8247415510202276, -1.0299159073255513, 0.7689727513393745, -0.023063681797826918,
|
||||
-0.1893245087721241, -1.615552722124904, -1.251848891438835, 0.5338780197836666,
|
||||
-0.3244188100039259, 2.598277589396897, -0.12170602745517456, -2.7269013649087737,
|
||||
-1.1332228949082876, 0.5657123485919064, 1.7914098463628945, 0.7841799713943826,
|
||||
0.22029184793596254, 0.19814576077109303, -0.0507307457285169, 1.190488685111505,
|
||||
-0.6761916505498549, -1.083729826174603, 0.405468008682514, -1.2478635255587003,
|
||||
-0.25157954751030825, -0.9671361521687468, -0.6434412998426552, -0.9664977307097671,
|
||||
-0.9150555987123582, 1.697917162123366, -1.3216510109214192, -1.3943141278602609,
|
||||
-0.7314910022591513, -0.8889827595848262, 1.3514782911515115, 2.297097472618343,
|
||||
-0.8897506799878153, -0.706235549786705, -0.25391776134956306, -1.739982172732943,
|
||||
-0.23465780260154823, -0.0475767318206883, -0.441164577073652, -0.5072245472018251,
|
||||
-1.1057148994224053, 0.40324702616815694, 0.815435779107782, 0.25403283232711865,
|
||||
-0.6137810912250902, -0.7039958189789415, -1.33840097232278, 0.4786946763969468,
|
||||
-0.46464793721558995, -1.7121509287301122, 0.7887828546774234, -0.902172963851904,
|
||||
-0.2591368523894675, -0.9510361177022718, 0.5739217219088085, -0.25730420306720403,
|
||||
0.41740839680521646, -2.0979181310103074, 1.1494564006889283, 0.5059893282486726 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputLow05 = {
|
||||
-0.27491385034007587, -0.7098571028952849, -0.32360008629382064, 0.14076966108257558,
|
||||
-0.023872843162458468, -0.6095833580198289, -1.1589949905278558, -0.6256552873943414,
|
||||
-0.1387320258715336, 0.7117089178404791, 1.0627601599274006, -0.5952824108121825,
|
||||
-1.4851355568764144, -0.6842153677309318, 0.557635609074623, 1.0444084756106333,
|
||||
0.6829600983136596, 0.3671325690069051, 0.1715158613498271, 0.43709126691093836,
|
||||
0.3171294338241961, -0.48093068096675384, -0.3863974994862809, -0.4095976721208223,
|
||||
-0.6363469150632769, -0.6183542049141106, -0.7429772189751709, -0.7843054165091977,
|
||||
-0.8886195819771077, -0.03525267285536671, 0.11367115944885997, -0.8674313264442733,
|
||||
-0.9977454855212284, -0.8727397491217354, -0.13674807251835008, 1.170609230417168,
|
||||
0.8593186743492318, -0.24555585180842954, -0.4019030543148992, -0.7986009961324684,
|
||||
-0.9244136571556533, -0.40221606385929665, -0.29698579091787897, -0.4151249717311187,
|
||||
-0.6760214727851164, -0.4594964486797883, 0.2530621188653835, 0.44084357676676134,
|
||||
0.02703177262292994, -0.4302483791937005, -0.8242150568318073, -0.5613071175858801,
|
||||
-0.18242012613484115, -0.7864063306935144, -0.5699248015820677, -0.22777163691884944,
|
||||
-0.46302715105340697, -0.5577333737150487, -0.311615923169504, 0.001667198557366828,
|
||||
0.05392379743179307, -0.5421953122577658, -0.49688568085971485, 0.3861866826926287 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputHigh05 = {
|
||||
-0.5498277006801517, -0.32005880443026635, 1.0925728376331951, -0.1638333428804025,
|
||||
-0.16545166560966562, -1.005969364105075, -0.09285390091097923, 1.159533307178008,
|
||||
-0.1856867841323923, 1.886568671556418, -1.1844661873825753, -2.131618954096591,
|
||||
0.35191266196812676, 1.2499277163228384, 1.2337742372882716, -0.26022850421625077,
|
||||
-0.462668250377697, -0.16898680823581208, -0.222246607078344, 0.7533974182005667,
|
||||
-0.993321084374051, -0.602799145207849, 0.7918655081687949, -0.838265853437878,
|
||||
0.38476736755296864, -0.3487819472546362, 0.0995359191325157, -0.18219231420056936,
|
||||
-0.026436016735250534, 1.7331698349787326, -1.4353221703702792, -0.5268828014159875,
|
||||
0.2662544832620771, -0.016243010463090846, 1.4882263636698616, 1.126488242201175,
|
||||
-1.7490693543370472, -0.46067969797827546, 0.14798529296533613, -0.9413811766004746,
|
||||
0.689755854554105, 0.35463933203860837, -0.144178786155773, -0.09209957547070641,
|
||||
-0.42969342663728893, 0.8627434748479452, 0.5623736602423985, -0.18681074443964268,
|
||||
-0.6408128638480202, -0.27374743978524096, -0.5141859154909728, 1.040001793982827,
|
||||
-0.2822278110807488, -0.9257445980365978, 1.358707656259491, -0.6744013269330547,
|
||||
0.20389029866393948, -0.3933027439872231, 0.8855376450783126, -0.2589714016245709,
|
||||
0.36348459937342337, -1.5557228187525416, 1.6463420815486431, 0.11980264555604392 };
|
||||
|
||||
constexpr std::array<double, 64> doubleInput09 = {
|
||||
-0.9629663717342508, 1.054078826032172, -1.0644939081323097, -0.05328934531304567,
|
||||
-0.04857086206002074, 1.612607856597715, 1.0513263960877668, -1.4323863476593215,
|
||||
2.2461810968138463, -0.6561891523704232, 0.022772627664592485, 0.07616465991959669,
|
||||
0.8305193318990887, -0.4888237081549593, 0.8564039983858606, 1.4871994957279644,
|
||||
0.22673465240234947, 1.658079098180724, -1.7453062858413877, -0.11612580324446467,
|
||||
-0.20232260689840872, -1.1476998404072543, -0.6202811352543974, 1.545975326252028,
|
||||
1.0442436933320733, -1.0968040236666232, 0.7595527972844077, 1.2073698123442007,
|
||||
-0.8873573213734941, -0.17122644896880435, -1.7574830431070918, 0.19907680046299245,
|
||||
1.27872961557419, -0.7422656051046687, -0.6846620117838057, -0.13384854423135875,
|
||||
0.9007202159691193, 1.1254806648626967, -0.04344693397840567, 0.7948730146831712,
|
||||
1.1781603468141004, 0.1875496039927383, 1.692965002836772, -0.04201566153548597,
|
||||
1.1210100661199038, -0.7501096833348359, 0.020210228191464837, 1.9979804313376157,
|
||||
0.7517403248613556, 1.1194691465807607, -1.1160170942539855, -1.0010374555669668,
|
||||
2.1609909686692763, -0.07213993925443297, -0.5083174992310037, -0.7489925703250175,
|
||||
0.5119124853257149, -0.33950253799120345, -0.26764774112191847, 0.10271208568438035,
|
||||
-0.09893862035889031, -0.4154625911342657, 0.11272544601558693, -0.6895075000870634 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputLow09 = {
|
||||
-0.45614196555832937, 0.01915105911173487, -0.003925509462605503, -0.5296828837089897,
|
||||
-0.0761276184245572, 0.7368529122323524, 1.3006453256000892, -0.1120470651865213,
|
||||
0.37958450932653687, 0.7731322110167023, -0.25934823743872504, 0.033215123727314666,
|
||||
0.4312300552681833, 0.1845521404718603, 0.18383025013420895, 1.1198032472188755,
|
||||
0.8708005568627211, 0.9386381216900201, 0.008083864881265557, -0.8813055229942847,
|
||||
-0.19722848496211295, -0.6498647637217411, -0.8716680812987687, 0.39260945461473207,
|
||||
1.2476095068879813, 0.040766659677738515, -0.1576049672506421, 0.9234051852319387,
|
||||
0.20018513705096297, -0.49089835768577506, -0.9394359887562548, -0.7876364301343762,
|
||||
0.6585590165368562, 0.2887755321453973, -0.6607143694658354, -0.4224899670317008,
|
||||
0.34101868834779714, 0.9777277166228496, 0.5640016470832352, 0.38562296702242765,
|
||||
0.9548906958156775, 0.6971726448988013, 0.9274633740191786, 0.8308424971437238,
|
||||
0.5548311651791308, 0.204891295276039, -0.3349580947902264, 0.9383556758406053,
|
||||
1.3518864464016498, 0.9575142994410892, 0.0520306721253716, -1.0000768566454319,
|
||||
0.496816040067124, 1.015603963410564, -0.22150068331359823, -0.6072258583851468,
|
||||
-0.14426034859888792, 0.07407521986377441, -0.2836988048502276, -0.09305893177831953,
|
||||
-0.003110407570995219, -0.24382743742154736, -0.15623482860471877, -0.28143543764463197 };
|
||||
|
||||
constexpr std::array<double, 64> doubleOutputHigh09 = {
|
||||
-0.5068244061759215, 1.034927766920437, -1.0605683986697043, 0.47639353839594406,
|
||||
0.027556756364536465, 0.8757549443653627, -0.24931892951232237, -1.3203392824728002,
|
||||
1.8665965874873094, -1.4293213633871256, 0.2821208651033175, 0.04294953619228202,
|
||||
0.39928927663090535, -0.6733758486268195, 0.6725737482516516, 0.3673962485090889,
|
||||
-0.6440659044603716, 0.7194409764907039, -1.7533901507226533, 0.76517971974982,
|
||||
-0.00509412193629577, -0.4978350766855132, 0.2513869460443713, 1.1533658716372959,
|
||||
-0.203365813555908, -1.1375706833443617, 0.9171577645350498, 0.283964627112262,
|
||||
-1.087542458424457, 0.3196719087169707, -0.818047054350837, 0.9867132305973687,
|
||||
0.6201705990373338, -1.031041137250066, -0.023947642317970308, 0.288641422800342,
|
||||
0.5597015276213222, 0.14775294823984708, -0.6074485810616409, 0.4092500476607435,
|
||||
0.22326965099842289, -0.5096230409060629, 0.7655016288175934, -0.8728581586792098,
|
||||
0.5661789009407731, -0.9550009786108749, 0.35516832298169126, 1.0596247554970104,
|
||||
-0.6001461215402942, 0.16195484713967145, -1.1680477663793571, -0.0009605989215348831,
|
||||
1.6641749286021523, -1.087743902664997, -0.28681681591740543, -0.14176671193987078,
|
||||
0.6561728339246028, -0.41357775785497786, 0.016051063728309112, 0.19577101746269987,
|
||||
-0.09582821278789509, -0.17163515371271834, 0.2689602746203057, -0.40807206244243144 };
|
||||
|
||||
TEST_CASE("[OnePoleFilter] Tests")
|
||||
{
|
||||
testHighpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
||||
0.1f);
|
||||
testHighpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
||||
0.3f);
|
||||
testHighpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
||||
0.5f);
|
||||
testHighpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
||||
0.7f);
|
||||
testHighpass<double>(
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||
fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
||||
0.9f);
|
||||
}
|
||||
testFilter(floatInput01, floatOutputLow01, floatOutputHigh01, 0.1f);
|
||||
testFilter(floatInput05, floatOutputLow05, floatOutputHigh05, 0.5f);
|
||||
testFilter(floatInput09, floatOutputLow09, floatOutputHigh09, 0.9f);
|
||||
testFilter(doubleInput01, doubleOutputLow01, doubleOutputHigh01, 0.1);
|
||||
testFilter(doubleInput05, doubleOutputLow05, doubleOutputHigh05, 0.5);
|
||||
testFilter(doubleInput09, doubleOutputLow09, doubleOutputHigh09, 0.9);
|
||||
}
|
||||
|
|
@ -1,340 +0,0 @@
|
|||
//Copyright (C) 2011 Carl Rogers
|
||||
//Released under MIT License
|
||||
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
#include"cnpy.h"
|
||||
#include<complex>
|
||||
#include<cstdlib>
|
||||
#include<algorithm>
|
||||
#include<cstring>
|
||||
#include<iomanip>
|
||||
#include<stdint.h>
|
||||
#include<stdexcept>
|
||||
#include <regex>
|
||||
|
||||
char cnpy::BigEndianTest() {
|
||||
int x = 1;
|
||||
return (((char *)&x)[0]) ? '<' : '>';
|
||||
}
|
||||
|
||||
char cnpy::map_type(const std::type_info& t)
|
||||
{
|
||||
if(t == typeid(float) ) return 'f';
|
||||
if(t == typeid(double) ) return 'f';
|
||||
if(t == typeid(long double) ) return 'f';
|
||||
|
||||
if(t == typeid(int) ) return 'i';
|
||||
if(t == typeid(char) ) return 'i';
|
||||
if(t == typeid(short) ) return 'i';
|
||||
if(t == typeid(long) ) return 'i';
|
||||
if(t == typeid(long long) ) return 'i';
|
||||
|
||||
if(t == typeid(unsigned char) ) return 'u';
|
||||
if(t == typeid(unsigned short) ) return 'u';
|
||||
if(t == typeid(unsigned long) ) return 'u';
|
||||
if(t == typeid(unsigned long long) ) return 'u';
|
||||
if(t == typeid(unsigned int) ) return 'u';
|
||||
|
||||
if(t == typeid(bool) ) return 'b';
|
||||
|
||||
if(t == typeid(std::complex<float>) ) return 'c';
|
||||
if(t == typeid(std::complex<double>) ) return 'c';
|
||||
if(t == typeid(std::complex<long double>) ) return 'c';
|
||||
|
||||
else return '?';
|
||||
}
|
||||
|
||||
template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const std::string rhs) {
|
||||
lhs.insert(lhs.end(),rhs.begin(),rhs.end());
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const char* rhs) {
|
||||
//write in little endian
|
||||
size_t len = strlen(rhs);
|
||||
lhs.reserve(len);
|
||||
for(size_t byte = 0; byte < len; byte++) {
|
||||
lhs.push_back(rhs[byte]);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
void cnpy::parse_npy_header(unsigned char* buffer,size_t& word_size, std::vector<size_t>& shape, bool& fortran_order) {
|
||||
//std::string magic_string(buffer,6);
|
||||
uint8_t major_version = *reinterpret_cast<uint8_t*>(buffer+6);
|
||||
uint8_t minor_version = *reinterpret_cast<uint8_t*>(buffer+7);
|
||||
uint16_t header_len = *reinterpret_cast<uint16_t*>(buffer+8);
|
||||
std::string header(reinterpret_cast<char*>(buffer+9),header_len);
|
||||
|
||||
size_t loc1, loc2;
|
||||
|
||||
//fortran order
|
||||
loc1 = header.find("fortran_order")+16;
|
||||
fortran_order = (header.substr(loc1,4) == "True" ? true : false);
|
||||
|
||||
//shape
|
||||
loc1 = header.find("(");
|
||||
loc2 = header.find(")");
|
||||
|
||||
std::regex num_regex("[0-9][0-9]*");
|
||||
std::smatch sm;
|
||||
shape.clear();
|
||||
|
||||
std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
|
||||
while(std::regex_search(str_shape, sm, num_regex)) {
|
||||
shape.push_back(std::stoi(sm[0].str()));
|
||||
str_shape = sm.suffix().str();
|
||||
}
|
||||
|
||||
//endian, word size, data type
|
||||
//byte order code | stands for not applicable.
|
||||
//not sure when this applies except for byte array
|
||||
loc1 = header.find("descr")+9;
|
||||
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
assert(littleEndian);
|
||||
|
||||
//char type = header[loc1+1];
|
||||
//assert(type == map_type(T));
|
||||
|
||||
std::string str_ws = header.substr(loc1+2);
|
||||
loc2 = str_ws.find("'");
|
||||
word_size = atoi(str_ws.substr(0,loc2).c_str());
|
||||
}
|
||||
|
||||
void cnpy::parse_npy_header(FILE* fp, size_t& word_size, std::vector<size_t>& shape, bool& fortran_order) {
|
||||
char buffer[256];
|
||||
size_t res = fread(buffer,sizeof(char),11,fp);
|
||||
if(res != 11)
|
||||
throw std::runtime_error("parse_npy_header: failed fread");
|
||||
std::string header = fgets(buffer,256,fp);
|
||||
assert(header[header.size()-1] == '\n');
|
||||
|
||||
size_t loc1, loc2;
|
||||
|
||||
//fortran order
|
||||
loc1 = header.find("fortran_order");
|
||||
if (loc1 == std::string::npos)
|
||||
throw std::runtime_error("parse_npy_header: failed to find header keyword: 'fortran_order'");
|
||||
loc1 += 16;
|
||||
fortran_order = (header.substr(loc1,4) == "True" ? true : false);
|
||||
|
||||
//shape
|
||||
loc1 = header.find("(");
|
||||
loc2 = header.find(")");
|
||||
if (loc1 == std::string::npos || loc2 == std::string::npos)
|
||||
throw std::runtime_error("parse_npy_header: failed to find header keyword: '(' or ')'");
|
||||
|
||||
std::regex num_regex("[0-9][0-9]*");
|
||||
std::smatch sm;
|
||||
shape.clear();
|
||||
|
||||
std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
|
||||
while(std::regex_search(str_shape, sm, num_regex)) {
|
||||
shape.push_back(std::stoi(sm[0].str()));
|
||||
str_shape = sm.suffix().str();
|
||||
}
|
||||
|
||||
//endian, word size, data type
|
||||
//byte order code | stands for not applicable.
|
||||
//not sure when this applies except for byte array
|
||||
loc1 = header.find("descr");
|
||||
if (loc1 == std::string::npos)
|
||||
throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'");
|
||||
loc1 += 9;
|
||||
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
assert(littleEndian);
|
||||
|
||||
//char type = header[loc1+1];
|
||||
//assert(type == map_type(T));
|
||||
|
||||
std::string str_ws = header.substr(loc1+2);
|
||||
loc2 = str_ws.find("'");
|
||||
word_size = atoi(str_ws.substr(0,loc2).c_str());
|
||||
}
|
||||
|
||||
void cnpy::parse_zip_footer(FILE* fp, uint16_t& nrecs, size_t& global_header_size, size_t& global_header_offset)
|
||||
{
|
||||
std::vector<char> footer(22);
|
||||
fseek(fp,-22,SEEK_END);
|
||||
size_t res = fread(&footer[0],sizeof(char),22,fp);
|
||||
if(res != 22)
|
||||
throw std::runtime_error("parse_zip_footer: failed fread");
|
||||
|
||||
uint16_t disk_no, disk_start, nrecs_on_disk, comment_len;
|
||||
disk_no = *(uint16_t*) &footer[4];
|
||||
disk_start = *(uint16_t*) &footer[6];
|
||||
nrecs_on_disk = *(uint16_t*) &footer[8];
|
||||
nrecs = *(uint16_t*) &footer[10];
|
||||
global_header_size = *(uint32_t*) &footer[12];
|
||||
global_header_offset = *(uint32_t*) &footer[16];
|
||||
comment_len = *(uint16_t*) &footer[20];
|
||||
|
||||
assert(disk_no == 0);
|
||||
assert(disk_start == 0);
|
||||
assert(nrecs_on_disk == nrecs);
|
||||
assert(comment_len == 0);
|
||||
}
|
||||
|
||||
cnpy::NpyArray load_the_npy_file(FILE* fp) {
|
||||
std::vector<size_t> shape;
|
||||
size_t word_size;
|
||||
bool fortran_order;
|
||||
cnpy::parse_npy_header(fp,word_size,shape,fortran_order);
|
||||
|
||||
cnpy::NpyArray arr(shape, word_size, fortran_order);
|
||||
size_t nread = fread(arr.data<char>(),1,arr.num_bytes(),fp);
|
||||
if(nread != arr.num_bytes())
|
||||
throw std::runtime_error("load_the_npy_file: failed fread");
|
||||
return arr;
|
||||
}
|
||||
|
||||
cnpy::NpyArray load_the_npz_array(FILE* fp, uint32_t compr_bytes, uint32_t uncompr_bytes) {
|
||||
|
||||
std::vector<unsigned char> buffer_compr(compr_bytes);
|
||||
std::vector<unsigned char> buffer_uncompr(uncompr_bytes);
|
||||
size_t nread = fread(&buffer_compr[0],1,compr_bytes,fp);
|
||||
if(nread != compr_bytes)
|
||||
throw std::runtime_error("load_the_npy_file: failed fread");
|
||||
|
||||
int err;
|
||||
z_stream d_stream;
|
||||
|
||||
d_stream.zalloc = Z_NULL;
|
||||
d_stream.zfree = Z_NULL;
|
||||
d_stream.opaque = Z_NULL;
|
||||
d_stream.avail_in = 0;
|
||||
d_stream.next_in = Z_NULL;
|
||||
err = inflateInit2(&d_stream, -MAX_WBITS);
|
||||
|
||||
d_stream.avail_in = compr_bytes;
|
||||
d_stream.next_in = &buffer_compr[0];
|
||||
d_stream.avail_out = uncompr_bytes;
|
||||
d_stream.next_out = &buffer_uncompr[0];
|
||||
|
||||
err = inflate(&d_stream, Z_FINISH);
|
||||
err = inflateEnd(&d_stream);
|
||||
|
||||
std::vector<size_t> shape;
|
||||
size_t word_size;
|
||||
bool fortran_order;
|
||||
cnpy::parse_npy_header(&buffer_uncompr[0],word_size,shape,fortran_order);
|
||||
|
||||
cnpy::NpyArray array(shape, word_size, fortran_order);
|
||||
|
||||
size_t offset = uncompr_bytes - array.num_bytes();
|
||||
memcpy(array.data<unsigned char>(),&buffer_uncompr[0]+offset,array.num_bytes());
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
cnpy::npz_t cnpy::npz_load(std::string fname) {
|
||||
FILE* fp = fopen(fname.c_str(),"rb");
|
||||
|
||||
if(!fp) {
|
||||
throw std::runtime_error("npz_load: Error! Unable to open file "+fname+"!");
|
||||
}
|
||||
|
||||
cnpy::npz_t arrays;
|
||||
|
||||
while(1) {
|
||||
std::vector<char> local_header(30);
|
||||
size_t headerres = fread(&local_header[0],sizeof(char),30,fp);
|
||||
if(headerres != 30)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//if we've reached the global header, stop reading
|
||||
if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
|
||||
|
||||
//read in the variable name
|
||||
uint16_t name_len = *(uint16_t*) &local_header[26];
|
||||
std::string varname(name_len,' ');
|
||||
size_t vname_res = fread(&varname[0],sizeof(char),name_len,fp);
|
||||
if(vname_res != name_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//erase the lagging .npy
|
||||
varname.erase(varname.end()-4,varname.end());
|
||||
|
||||
//read in the extra field
|
||||
uint16_t extra_field_len = *(uint16_t*) &local_header[28];
|
||||
if(extra_field_len > 0) {
|
||||
std::vector<char> buff(extra_field_len);
|
||||
size_t efield_res = fread(&buff[0],sizeof(char),extra_field_len,fp);
|
||||
if(efield_res != extra_field_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
}
|
||||
|
||||
uint16_t compr_method = *reinterpret_cast<uint16_t*>(&local_header[0]+8);
|
||||
uint32_t compr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+18);
|
||||
uint32_t uncompr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+22);
|
||||
|
||||
if(compr_method == 0) {arrays[varname] = load_the_npy_file(fp);}
|
||||
else {arrays[varname] = load_the_npz_array(fp,compr_bytes,uncompr_bytes);}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return arrays;
|
||||
}
|
||||
|
||||
cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
|
||||
FILE* fp = fopen(fname.c_str(),"rb");
|
||||
|
||||
if(!fp) throw std::runtime_error("npz_load: Unable to open file "+fname);
|
||||
|
||||
while(1) {
|
||||
std::vector<char> local_header(30);
|
||||
size_t header_res = fread(&local_header[0],sizeof(char),30,fp);
|
||||
if(header_res != 30)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//if we've reached the global header, stop reading
|
||||
if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
|
||||
|
||||
//read in the variable name
|
||||
uint16_t name_len = *(uint16_t*) &local_header[26];
|
||||
std::string vname(name_len,' ');
|
||||
size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp);
|
||||
if(vname_res != name_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy
|
||||
|
||||
//read in the extra field
|
||||
uint16_t extra_field_len = *(uint16_t*) &local_header[28];
|
||||
fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field
|
||||
|
||||
uint16_t compr_method = *reinterpret_cast<uint16_t*>(&local_header[0]+8);
|
||||
uint32_t compr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+18);
|
||||
uint32_t uncompr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+22);
|
||||
|
||||
if(vname == varname) {
|
||||
NpyArray array = (compr_method == 0) ? load_the_npy_file(fp) : load_the_npz_array(fp,compr_bytes,uncompr_bytes);
|
||||
fclose(fp);
|
||||
return array;
|
||||
}
|
||||
else {
|
||||
//skip past the data
|
||||
uint32_t size = *(uint32_t*) &local_header[22];
|
||||
fseek(fp,size,SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
//if we get here, we haven't found the variable in the file
|
||||
throw std::runtime_error("npz_load: Variable name "+varname+" not found in "+fname);
|
||||
}
|
||||
|
||||
cnpy::NpyArray cnpy::npy_load(std::string fname) {
|
||||
|
||||
FILE* fp = fopen(fname.c_str(), "rb");
|
||||
|
||||
if(!fp) throw std::runtime_error("npy_load: Unable to open file "+fname);
|
||||
|
||||
NpyArray arr = load_the_npy_file(fp);
|
||||
|
||||
fclose(fp);
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
//Copyright (C) 2011 Carl Rogers
|
||||
//Released under MIT License
|
||||
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
#ifndef LIBCNPY_H_
|
||||
#define LIBCNPY_H_
|
||||
|
||||
#include<string>
|
||||
#include<stdexcept>
|
||||
#include<sstream>
|
||||
#include<vector>
|
||||
#include<cstdio>
|
||||
#include<typeinfo>
|
||||
#include<iostream>
|
||||
#include<cassert>
|
||||
#include<zlib.h>
|
||||
#include<map>
|
||||
#include<memory>
|
||||
#include<stdint.h>
|
||||
#include<numeric>
|
||||
|
||||
namespace cnpy {
|
||||
|
||||
struct NpyArray {
|
||||
NpyArray(const std::vector<size_t>& _shape, size_t _word_size, bool _fortran_order) :
|
||||
shape(_shape), word_size(_word_size), fortran_order(_fortran_order)
|
||||
{
|
||||
num_vals = 1;
|
||||
for(size_t i = 0;i < shape.size();i++) num_vals *= shape[i];
|
||||
data_holder = std::shared_ptr<std::vector<char>>(
|
||||
new std::vector<char>(num_vals * word_size));
|
||||
}
|
||||
|
||||
NpyArray() : shape(0), word_size(0), fortran_order(0), num_vals(0) { }
|
||||
|
||||
template<typename T>
|
||||
T* data() {
|
||||
return reinterpret_cast<T*>(&(*data_holder)[0]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* data() const {
|
||||
return reinterpret_cast<T*>(&(*data_holder)[0]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> as_vec() const {
|
||||
const T* p = data<T>();
|
||||
return std::vector<T>(p, p+num_vals);
|
||||
}
|
||||
|
||||
size_t num_bytes() const {
|
||||
return data_holder->size();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<char>> data_holder;
|
||||
std::vector<size_t> shape;
|
||||
size_t word_size;
|
||||
bool fortran_order;
|
||||
size_t num_vals;
|
||||
};
|
||||
|
||||
using npz_t = std::map<std::string, NpyArray>;
|
||||
|
||||
char BigEndianTest();
|
||||
char map_type(const std::type_info& t);
|
||||
template<typename T> std::vector<char> create_npy_header(const std::vector<size_t>& shape);
|
||||
void parse_npy_header(FILE* fp,size_t& word_size, std::vector<size_t>& shape, bool& fortran_order);
|
||||
void parse_npy_header(unsigned char* buffer,size_t& word_size, std::vector<size_t>& shape, bool& fortran_order);
|
||||
void parse_zip_footer(FILE* fp, uint16_t& nrecs, size_t& global_header_size, size_t& global_header_offset);
|
||||
npz_t npz_load(std::string fname);
|
||||
NpyArray npz_load(std::string fname, std::string varname);
|
||||
NpyArray npy_load(std::string fname);
|
||||
|
||||
template<typename T> std::vector<char>& operator+=(std::vector<char>& lhs, const T rhs) {
|
||||
//write in little endian
|
||||
for(size_t byte = 0; byte < sizeof(T); byte++) {
|
||||
char val = *((char*)&rhs+byte);
|
||||
lhs.push_back(val);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const std::string rhs);
|
||||
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const char* rhs);
|
||||
|
||||
|
||||
template<typename T> void npy_save(std::string fname, const T* data, const std::vector<size_t> shape, std::string mode = "w") {
|
||||
FILE* fp = NULL;
|
||||
std::vector<size_t> true_data_shape; //if appending, the shape of existing + new data
|
||||
|
||||
if(mode == "a") fp = fopen(fname.c_str(),"r+b");
|
||||
|
||||
if(fp) {
|
||||
//file exists. we need to append to it. read the header, modify the array size
|
||||
size_t word_size;
|
||||
bool fortran_order;
|
||||
parse_npy_header(fp,word_size,true_data_shape,fortran_order);
|
||||
assert(!fortran_order);
|
||||
|
||||
if(word_size != sizeof(T)) {
|
||||
std::cout<<"libnpy error: "<<fname<<" has word size "<<word_size<<" but npy_save appending data sized "<<sizeof(T)<<"\n";
|
||||
assert( word_size == sizeof(T) );
|
||||
}
|
||||
if(true_data_shape.size() != shape.size()) {
|
||||
std::cout<<"libnpy error: npy_save attempting to append misdimensioned data to "<<fname<<"\n";
|
||||
assert(true_data_shape.size() != shape.size());
|
||||
}
|
||||
|
||||
for(size_t i = 1; i < shape.size(); i++) {
|
||||
if(shape[i] != true_data_shape[i]) {
|
||||
std::cout<<"libnpy error: npy_save attempting to append misshaped data to "<<fname<<"\n";
|
||||
assert(shape[i] == true_data_shape[i]);
|
||||
}
|
||||
}
|
||||
true_data_shape[0] += shape[0];
|
||||
}
|
||||
else {
|
||||
fp = fopen(fname.c_str(),"wb");
|
||||
true_data_shape = shape;
|
||||
}
|
||||
|
||||
std::vector<char> header = create_npy_header<T>(true_data_shape);
|
||||
size_t nels = std::accumulate(shape.begin(),shape.end(),1,std::multiplies<size_t>());
|
||||
|
||||
fseek(fp,0,SEEK_SET);
|
||||
fwrite(&header[0],sizeof(char),header.size(),fp);
|
||||
fseek(fp,0,SEEK_END);
|
||||
fwrite(data,sizeof(T),nels,fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
template<typename T> void npz_save(std::string zipname, std::string fname, const T* data, const std::vector<size_t>& shape, std::string mode = "w")
|
||||
{
|
||||
//first, append a .npy to the fname
|
||||
fname += ".npy";
|
||||
|
||||
//now, on with the show
|
||||
FILE* fp = NULL;
|
||||
uint16_t nrecs = 0;
|
||||
size_t global_header_offset = 0;
|
||||
std::vector<char> global_header;
|
||||
|
||||
if(mode == "a") fp = fopen(zipname.c_str(),"r+b");
|
||||
|
||||
if(fp) {
|
||||
//zip file exists. we need to add a new npy file to it.
|
||||
//first read the footer. this gives us the offset and size of the global header
|
||||
//then read and store the global header.
|
||||
//below, we will write the the new data at the start of the global header then append the global header and footer below it
|
||||
size_t global_header_size;
|
||||
parse_zip_footer(fp,nrecs,global_header_size,global_header_offset);
|
||||
fseek(fp,global_header_offset,SEEK_SET);
|
||||
global_header.resize(global_header_size);
|
||||
size_t res = fread(&global_header[0],sizeof(char),global_header_size,fp);
|
||||
if(res != global_header_size){
|
||||
throw std::runtime_error("npz_save: header read error while adding to existing zip");
|
||||
}
|
||||
fseek(fp,global_header_offset,SEEK_SET);
|
||||
}
|
||||
else {
|
||||
fp = fopen(zipname.c_str(),"wb");
|
||||
}
|
||||
|
||||
std::vector<char> npy_header = create_npy_header<T>(shape);
|
||||
|
||||
size_t nels = std::accumulate(shape.begin(),shape.end(),1,std::multiplies<size_t>());
|
||||
size_t nbytes = nels*sizeof(T) + npy_header.size();
|
||||
|
||||
//get the CRC of the data to be added
|
||||
uint32_t crc = crc32(0L,(uint8_t*)&npy_header[0],npy_header.size());
|
||||
crc = crc32(crc,(uint8_t*)data,nels*sizeof(T));
|
||||
|
||||
//build the local header
|
||||
std::vector<char> local_header;
|
||||
local_header += "PK"; //first part of sig
|
||||
local_header += (uint16_t) 0x0403; //second part of sig
|
||||
local_header += (uint16_t) 20; //min version to extract
|
||||
local_header += (uint16_t) 0; //general purpose bit flag
|
||||
local_header += (uint16_t) 0; //compression method
|
||||
local_header += (uint16_t) 0; //file last mod time
|
||||
local_header += (uint16_t) 0; //file last mod date
|
||||
local_header += (uint32_t) crc; //crc
|
||||
local_header += (uint32_t) nbytes; //compressed size
|
||||
local_header += (uint32_t) nbytes; //uncompressed size
|
||||
local_header += (uint16_t) fname.size(); //fname length
|
||||
local_header += (uint16_t) 0; //extra field length
|
||||
local_header += fname;
|
||||
|
||||
//build global header
|
||||
global_header += "PK"; //first part of sig
|
||||
global_header += (uint16_t) 0x0201; //second part of sig
|
||||
global_header += (uint16_t) 20; //version made by
|
||||
global_header.insert(global_header.end(),local_header.begin()+4,local_header.begin()+30);
|
||||
global_header += (uint16_t) 0; //file comment length
|
||||
global_header += (uint16_t) 0; //disk number where file starts
|
||||
global_header += (uint16_t) 0; //internal file attributes
|
||||
global_header += (uint32_t) 0; //external file attributes
|
||||
global_header += (uint32_t) global_header_offset; //relative offset of local file header, since it begins where the global header used to begin
|
||||
global_header += fname;
|
||||
|
||||
//build footer
|
||||
std::vector<char> footer;
|
||||
footer += "PK"; //first part of sig
|
||||
footer += (uint16_t) 0x0605; //second part of sig
|
||||
footer += (uint16_t) 0; //number of this disk
|
||||
footer += (uint16_t) 0; //disk where footer starts
|
||||
footer += (uint16_t) (nrecs+1); //number of records on this disk
|
||||
footer += (uint16_t) (nrecs+1); //total number of records
|
||||
footer += (uint32_t) global_header.size(); //nbytes of global headers
|
||||
footer += (uint32_t) (global_header_offset + nbytes + local_header.size()); //offset of start of global headers, since global header now starts after newly written array
|
||||
footer += (uint16_t) 0; //zip file comment length
|
||||
|
||||
//write everything
|
||||
fwrite(&local_header[0],sizeof(char),local_header.size(),fp);
|
||||
fwrite(&npy_header[0],sizeof(char),npy_header.size(),fp);
|
||||
fwrite(data,sizeof(T),nels,fp);
|
||||
fwrite(&global_header[0],sizeof(char),global_header.size(),fp);
|
||||
fwrite(&footer[0],sizeof(char),footer.size(),fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
template<typename T> void npy_save(std::string fname, const std::vector<T> data, std::string mode = "w") {
|
||||
std::vector<size_t> shape;
|
||||
shape.push_back(data.size());
|
||||
npy_save(fname, &data[0], shape, mode);
|
||||
}
|
||||
|
||||
template<typename T> void npz_save(std::string zipname, std::string fname, const std::vector<T> data, std::string mode = "w") {
|
||||
std::vector<size_t> shape;
|
||||
shape.push_back(data.size());
|
||||
npz_save(zipname, fname, &data[0], shape, mode);
|
||||
}
|
||||
|
||||
template<typename T> std::vector<char> create_npy_header(const std::vector<size_t>& shape) {
|
||||
|
||||
std::vector<char> dict;
|
||||
dict += "{'descr': '";
|
||||
dict += BigEndianTest();
|
||||
dict += map_type(typeid(T));
|
||||
dict += std::to_string(sizeof(T));
|
||||
dict += "', 'fortran_order': False, 'shape': (";
|
||||
dict += std::to_string(shape[0]);
|
||||
for(size_t i = 1;i < shape.size();i++) {
|
||||
dict += ", ";
|
||||
dict += std::to_string(shape[i]);
|
||||
}
|
||||
if(shape.size() == 1) dict += ",";
|
||||
dict += "), }";
|
||||
//pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to end with \n
|
||||
int remainder = 16 - (10 + dict.size()) % 16;
|
||||
dict.insert(dict.end(),remainder,' ');
|
||||
dict.back() = '\n';
|
||||
|
||||
std::vector<char> header;
|
||||
header += (char) 0x93;
|
||||
header += "NUMPY";
|
||||
header += (char) 0x01; //major version of numpy format
|
||||
header += (char) 0x00; //minor version of numpy format
|
||||
header += (uint16_t) dict.size();
|
||||
header.insert(header.end(),dict.begin(),dict.end());
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue