From de5bdc8ef6587ed203c43951adb10fd9eb076f24 Mon Sep 17 00:00:00 2001 From: Thorsten Liebig Date: Wed, 19 May 2010 11:41:35 +0200 Subject: [PATCH] introducing compressed sse operator & engine use --engine=sse-compressed option to enable --- FDTD/engine_sse_compressed.cpp | 144 ++++++++++++++++++ FDTD/engine_sse_compressed.h | 38 +++++ FDTD/operator_sse.cpp | 4 + FDTD/operator_sse_compressed.cpp | 247 +++++++++++++++++++++++++++++++ FDTD/operator_sse_compressed.h | 66 +++++++++ matlab/examples/PlaneWave.m | 14 +- openEMS.pro | 8 +- openems.cpp | 11 ++ openems.h | 2 +- tools/array_ops.cpp | 15 ++ tools/array_ops.h | 2 + 11 files changed, 542 insertions(+), 9 deletions(-) create mode 100644 FDTD/engine_sse_compressed.cpp create mode 100644 FDTD/engine_sse_compressed.h create mode 100644 FDTD/operator_sse_compressed.cpp create mode 100644 FDTD/operator_sse_compressed.h diff --git a/FDTD/engine_sse_compressed.cpp b/FDTD/engine_sse_compressed.cpp new file mode 100644 index 0000000..d0b08c6 --- /dev/null +++ b/FDTD/engine_sse_compressed.cpp @@ -0,0 +1,144 @@ +/* +* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de) +* +* 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, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include "engine_sse_compressed.h" + + +Engine_SSE_Compressed* Engine_SSE_Compressed::New(const Operator_SSE_Compressed* op) +{ + Engine_SSE_Compressed* e = new Engine_SSE_Compressed(op); + e->Init(); + return e; +} + +Engine_SSE_Compressed::Engine_SSE_Compressed(const Operator_SSE_Compressed* op) : Engine_sse(op) +{ + Op = op; +} + +Engine_SSE_Compressed::~Engine_SSE_Compressed() +{ +} + +void Engine_SSE_Compressed::UpdateVoltages(unsigned int startX, unsigned int numX) +{ + unsigned int pos[3]; + bool shift[2]; + f4vector temp; + + pos[0] = startX; + unsigned int index=0; + for (unsigned int posX=0;posXm_Op_index[pos[0]][pos[1]][pos[2]]; + // x-polarization + f4_volt[0][pos[0]][pos[1]][pos[2]].v *= Op->f4_vv_Compressed[0][index].v; + f4_volt[0][pos[0]][pos[1]][pos[2]].v += Op->f4_vi_Compressed[0][index].v * ( f4_curr[2][pos[0]][pos[1]][pos[2]].v - f4_curr[2][pos[0]][pos[1]-shift[1]][pos[2]].v - f4_curr[1][pos[0]][pos[1]][pos[2]].v + f4_curr[1][pos[0]][pos[1]][pos[2]-1].v ); + + // y-polarization + f4_volt[1][pos[0]][pos[1]][pos[2]].v *= Op->f4_vv_Compressed[1][index].v; + f4_volt[1][pos[0]][pos[1]][pos[2]].v += Op->f4_vi_Compressed[1][index].v * ( f4_curr[0][pos[0]][pos[1]][pos[2]].v - f4_curr[0][pos[0]][pos[1]][pos[2]-1].v - f4_curr[2][pos[0]][pos[1]][pos[2]].v + f4_curr[2][pos[0]-shift[0]][pos[1]][pos[2]].v); + + // z-polarization + f4_volt[2][pos[0]][pos[1]][pos[2]].v *= Op->f4_vv_Compressed[2][index].v; + f4_volt[2][pos[0]][pos[1]][pos[2]].v += Op->f4_vi_Compressed[2][index].v * ( f4_curr[1][pos[0]][pos[1]][pos[2]].v - f4_curr[1][pos[0]-shift[0]][pos[1]][pos[2]].v - f4_curr[0][pos[0]][pos[1]][pos[2]].v + f4_curr[0][pos[0]][pos[1]-shift[1]][pos[2]].v); + } + + // for pos[2] = 0 + // x-polarization + index = Op->m_Op_index[pos[0]][pos[1]][0]; + temp.f[0] = 0; + temp.f[1] = f4_curr[1][pos[0]][pos[1]][numVectors-1].f[0]; + temp.f[2] = f4_curr[1][pos[0]][pos[1]][numVectors-1].f[1]; + temp.f[3] = f4_curr[1][pos[0]][pos[1]][numVectors-1].f[2]; + f4_volt[0][pos[0]][pos[1]][0].v *= Op->f4_vv_Compressed[0][index].v; + f4_volt[0][pos[0]][pos[1]][0].v += Op->f4_vi_Compressed[0][index].v * ( f4_curr[2][pos[0]][pos[1]][0].v - f4_curr[2][pos[0]][pos[1]-shift[1]][0].v - f4_curr[1][pos[0]][pos[1]][0].v + temp.v ); + + // y-polarization + temp.f[0] = 0; + temp.f[1] = f4_curr[0][pos[0]][pos[1]][numVectors-1].f[0]; + temp.f[2] = f4_curr[0][pos[0]][pos[1]][numVectors-1].f[1]; + temp.f[3] = f4_curr[0][pos[0]][pos[1]][numVectors-1].f[2]; + f4_volt[1][pos[0]][pos[1]][0].v *= Op->f4_vv_Compressed[1][index].v; + f4_volt[1][pos[0]][pos[1]][0].v += Op->f4_vi_Compressed[1][index].v * ( f4_curr[0][pos[0]][pos[1]][0].v - temp.v - f4_curr[2][pos[0]][pos[1]][0].v + f4_curr[2][pos[0]-shift[0]][pos[1]][0].v); + + // z-polarization + f4_volt[2][pos[0]][pos[1]][0].v *= Op->f4_vv_Compressed[2][index].v; + f4_volt[2][pos[0]][pos[1]][0].v += Op->f4_vi_Compressed[2][index].v * ( f4_curr[1][pos[0]][pos[1]][0].v - f4_curr[1][pos[0]-shift[0]][pos[1]][0].v - f4_curr[0][pos[0]][pos[1]][0].v + f4_curr[0][pos[0]][pos[1]-shift[1]][0].v); + } + ++pos[0]; + } +} + +void Engine_SSE_Compressed::UpdateCurrents(unsigned int startX, unsigned int numX) +{ + unsigned int pos[5]; + f4vector temp; + + pos[0] = startX; + unsigned int index; + for (unsigned int posX=0;posXm_Op_index[pos[0]][pos[1]][pos[2]]; + // x-pol + f4_curr[0][pos[0]][pos[1]][pos[2]].v *= Op->f4_ii_Compressed[0][index].v; + f4_curr[0][pos[0]][pos[1]][pos[2]].v += Op->f4_iv_Compressed[0][index].v * ( f4_volt[2][pos[0]][pos[1]][pos[2]].v - f4_volt[2][pos[0]][pos[1]+1][pos[2]].v - f4_volt[1][pos[0]][pos[1]][pos[2]].v + f4_volt[1][pos[0]][pos[1]][pos[2]+1].v); + + // y-pol + f4_curr[1][pos[0]][pos[1]][pos[2]].v *= Op->f4_ii_Compressed[1][index].v; + f4_curr[1][pos[0]][pos[1]][pos[2]].v += Op->f4_iv_Compressed[1][index].v * ( f4_volt[0][pos[0]][pos[1]][pos[2]].v - f4_volt[0][pos[0]][pos[1]][pos[2]+1].v - f4_volt[2][pos[0]][pos[1]][pos[2]].v + f4_volt[2][pos[0]+1][pos[1]][pos[2]].v); + + // z-pol + f4_curr[2][pos[0]][pos[1]][pos[2]].v *= Op->f4_ii_Compressed[2][index].v; + f4_curr[2][pos[0]][pos[1]][pos[2]].v += Op->f4_iv_Compressed[2][index].v * ( f4_volt[1][pos[0]][pos[1]][pos[2]].v - f4_volt[1][pos[0]+1][pos[1]][pos[2]].v - f4_volt[0][pos[0]][pos[1]][pos[2]].v + f4_volt[0][pos[0]][pos[1]+1][pos[2]].v); + } + + index = Op->m_Op_index[pos[0]][pos[1]][numVectors-1]; + // for pos[2] = numVectors-1 + // x-pol + temp.f[0] = f4_volt[1][pos[0]][pos[1]][0].f[1]; + temp.f[1] = f4_volt[1][pos[0]][pos[1]][0].f[2]; + temp.f[2] = f4_volt[1][pos[0]][pos[1]][0].f[3]; + temp.f[3] = 0; + f4_curr[0][pos[0]][pos[1]][numVectors-1].v *= Op->f4_ii_Compressed[0][index].v; + f4_curr[0][pos[0]][pos[1]][numVectors-1].v += Op->f4_iv_Compressed[0][index].v * ( f4_volt[2][pos[0]][pos[1]][numVectors-1].v - f4_volt[2][pos[0]][pos[1]+1][numVectors-1].v - f4_volt[1][pos[0]][pos[1]][numVectors-1].v + temp.v); + + // y-pol + temp.f[0] = f4_volt[0][pos[0]][pos[1]][0].f[1]; + temp.f[1] = f4_volt[0][pos[0]][pos[1]][0].f[2]; + temp.f[2] = f4_volt[0][pos[0]][pos[1]][0].f[3]; + temp.f[3] = 0; + f4_curr[1][pos[0]][pos[1]][numVectors-1].v *= Op->f4_ii_Compressed[1][index].v; + f4_curr[1][pos[0]][pos[1]][numVectors-1].v += Op->f4_iv_Compressed[1][index].v * ( f4_volt[0][pos[0]][pos[1]][numVectors-1].v - temp.v - f4_volt[2][pos[0]][pos[1]][numVectors-1].v + f4_volt[2][pos[0]+1][pos[1]][numVectors-1].v); + + // z-pol + f4_curr[2][pos[0]][pos[1]][numVectors-1].v *= Op->f4_ii_Compressed[2][index].v; + f4_curr[2][pos[0]][pos[1]][numVectors-1].v += Op->f4_iv_Compressed[2][index].v * ( f4_volt[1][pos[0]][pos[1]][numVectors-1].v - f4_volt[1][pos[0]+1][pos[1]][numVectors-1].v - f4_volt[0][pos[0]][pos[1]][numVectors-1].v + f4_volt[0][pos[0]][pos[1]+1][numVectors-1].v); + } + ++pos[0]; + } +} diff --git a/FDTD/engine_sse_compressed.h b/FDTD/engine_sse_compressed.h new file mode 100644 index 0000000..ab86cc8 --- /dev/null +++ b/FDTD/engine_sse_compressed.h @@ -0,0 +1,38 @@ +/* +* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de) +* +* 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, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef ENGINE_SSE_COMPRESSED_H +#define ENGINE_SSE_COMPRESSED_H + +#include "engine_sse.h" +#include "operator_sse_compressed.h" + +class Engine_SSE_Compressed : public Engine_sse +{ +public: + static Engine_SSE_Compressed* New(const Operator_SSE_Compressed* op); + virtual ~Engine_SSE_Compressed(); + +protected: + Engine_SSE_Compressed(const Operator_SSE_Compressed* op); + const Operator_SSE_Compressed* Op; + + virtual void UpdateVoltages(unsigned int startX, unsigned int numX); + virtual void UpdateCurrents(unsigned int startX, unsigned int numX); +}; + +#endif // ENGINE_SSE_COMPRESSED_H diff --git a/FDTD/operator_sse.cpp b/FDTD/operator_sse.cpp index ecf65ff..0903f9c 100644 --- a/FDTD/operator_sse.cpp +++ b/FDTD/operator_sse.cpp @@ -28,6 +28,10 @@ Operator_sse* Operator_sse::New() Operator_sse::Operator_sse() : Operator() { + f4_vv = 0; + f4_vi = 0; + f4_iv = 0; + f4_ii = 0; } Operator_sse::~Operator_sse() diff --git a/FDTD/operator_sse_compressed.cpp b/FDTD/operator_sse_compressed.cpp new file mode 100644 index 0000000..fb60756 --- /dev/null +++ b/FDTD/operator_sse_compressed.cpp @@ -0,0 +1,247 @@ +/* +* Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de) +* +* 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, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include "operator_sse_compressed.h" +#include "engine_sse_compressed.h" +#include "engine_sse.h" +#include "tools/array_ops.h" + +#include + +Operator_SSE_Compressed* Operator_SSE_Compressed::New() +{ + Operator_SSE_Compressed* op = new Operator_SSE_Compressed(); + op->Init(); + return op; +} + +Operator_SSE_Compressed::Operator_SSE_Compressed() : Operator_sse() +{ + m_Op_index = NULL; + m_Use_Compression = false; + m_Max_Compression = false; + + m_Compression_Threshold = 0.8; + + for (int n=0;n<3;++n) + { + f4_vv_Compressed[n]=NULL; + f4_vi_Compressed[n]=NULL; + f4_ii_Compressed[n]=NULL; + f4_iv_Compressed[n]=NULL; + } + + m_max_fifo = 1000; +} + +Operator_SSE_Compressed::~Operator_SSE_Compressed() +{ + Reset(); +} + +Engine* Operator_SSE_Compressed::CreateEngine() const +{ + if (m_Use_Compression==false) + { + //!create a default sse-engine + Engine_sse* eng = Engine_sse::New(this); + return eng; + } + Engine_SSE_Compressed* eng = Engine_SSE_Compressed::New(this); + return eng; +} + +int Operator_SSE_Compressed::CalcECOperator() +{ + Operator_sse::CalcECOperator(); + m_Use_Compression = CompressOperator(); + + return 0; +} + +void Operator_SSE_Compressed::Init() +{ + Operator_sse::Init(); + m_Op_index = NULL; + for (int n=0;n<3;++n) + { + f4_vv_Compressed[n]=NULL; + f4_vi_Compressed[n]=NULL; + f4_ii_Compressed[n]=NULL; + f4_iv_Compressed[n]=NULL; + } +} + +void Operator_SSE_Compressed::Reset() +{ + Operator_sse::Reset(); + + if (m_Op_index) + { + unsigned int pos[3]; + for (pos[0]=0;pos[0] fifo; + vector index_list[3]; + + bool found; + unsigned int pos[3]; + unsigned int index_pos[3]; + list::iterator it; + for (pos[0]=0;pos[0]m_max_fifo) + { + fifo.pop_back(); + m_Max_Compression = false; + } + } + } + } + + m_Op_Count = index_list[0].size(); + if ( ((double)m_Op_Count/(double)GetNumberCells()) > m_Compression_Threshold) + { + cerr << "Operator_SSE_Compressed::CompressOperator: Warning: Compression unsuccessful, ratio is " << (double)m_Op_Count/(double)GetNumberCells() << "! Fallback to conventional sse-engine..." << endl; + return false; + } +// cerr << "total found: " << index_list[0].size() << endl; + + for (int n=0;n<3;++n) + { + f4_vv_Compressed[n] = Create1DArray_v4sf(m_Op_Count); + f4_vi_Compressed[n] = Create1DArray_v4sf(m_Op_Count); + f4_ii_Compressed[n] = Create1DArray_v4sf(m_Op_Count); + f4_iv_Compressed[n] = Create1DArray_v4sf(m_Op_Count); + + for (unsigned int m=0;m. +*/ + +#ifndef OPERATOR_SSE_COMPRESSED_H +#define OPERATOR_SSE_COMPRESSED_H + +#include "operator_sse.h" + +class Operator_SSE_Compressed : public Operator_sse +{ +public: + //! Create a new operator + static Operator_SSE_Compressed* New(); + virtual ~Operator_SSE_Compressed(); + + virtual Engine* CreateEngine() const; + + virtual int CalcECOperator(); + + void SetCompressionThreshold(double val) {m_Compression_Threshold = val;} + void SetCacheSize(unsigned int size) {m_max_fifo = size;} + bool CompressOperator(); + +protected: + Operator_SSE_Compressed(); + + bool m_Use_Compression; + bool m_Max_Compression; //reached maximal compression? + unsigned int m_Op_Count; + + //! Compression ratio threshold. If this ratio is exceeded, compression will be disabled. \sa SetCompressionThreshold + double m_Compression_Threshold; //default is 0.8 + + virtual void Init(); + virtual void Reset(); + virtual void InitOperator(); + + //! Compression cache size, default is 1000 \sa SetCacheSize + unsigned int m_max_fifo; + + bool CompareOperators(unsigned int pos1[3], unsigned int pos2[3]); + + // engine needs access +public: + unsigned int*** m_Op_index; + f4vector* f4_vv_Compressed[3]; //calc new voltage from old voltage + f4vector* f4_vi_Compressed[3]; //calc new voltage from old current + f4vector* f4_iv_Compressed[3]; //calc new current from old current + f4vector* f4_ii_Compressed[3]; //calc new current from old voltage +}; + +#endif // OPERATOR_SSE_Compressed_H diff --git a/matlab/examples/PlaneWave.m b/matlab/examples/PlaneWave.m index 817a194..b83c88c 100644 --- a/matlab/examples/PlaneWave.m +++ b/matlab/examples/PlaneWave.m @@ -3,20 +3,22 @@ clear clc %% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -abs_length = 250; -length = 4000; +length = 10000; width = 1000; height = 1000; -mesh_res = 25; +mesh_res = 20; +abs_length = mesh_res*10; EPS0 = 8.85418781762e-12; MUE0 = 1.256637062e-6; %% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% openEMS_opts = ''; -% openEMS_opts = [openEMS_opts ' --disable-dumps']; +openEMS_opts = [openEMS_opts ' --disable-dumps']; % openEMS_opts = [openEMS_opts ' --debug-material']; -% openEMS_opts = [openEMS_opts ' --engine=multithreaded']; +openEMS_opts = [openEMS_opts ' --engine=multithreaded']; +% openEMS_opts = [openEMS_opts ' --engine=sse']; +openEMS_opts = [openEMS_opts ' --engine=sse-compressed']; Sim_Path = 'tmp'; Sim_CSX = 'plane_wave.xml'; @@ -24,7 +26,7 @@ Sim_CSX = 'plane_wave.xml'; mkdir(Sim_Path); %% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FDTD = InitFDTD(5e5,1e-5,'OverSampling',10); +FDTD = InitFDTD(5000,1e-5,'OverSampling',10); FDTD = SetGaussExcite(FDTD,0.5e9,0.5e9); BC = [1 1 0 0 0 0]; FDTD = SetBoundaryCond(FDTD,BC); diff --git a/openEMS.pro b/openEMS.pro index ffd6601..dbd7481 100644 --- a/openEMS.pro +++ b/openEMS.pro @@ -52,7 +52,9 @@ SOURCES += main.cpp \ FDTD/operator_ext_mur_abc.cpp \ FDTD/excitation.cpp \ FDTD/operator_ext_cylinder.cpp \ - FDTD/engine_ext_cylinder.cpp + FDTD/engine_ext_cylinder.cpp \ + FDTD/operator_sse_compressed.cpp \ + FDTD/engine_sse_compressed.cpp HEADERS += tools/ErrorMsg.h \ tools/AdrOp.h \ tools/constants.h \ @@ -75,7 +77,9 @@ HEADERS += tools/ErrorMsg.h \ FDTD/operator_ext_mur_abc.h \ FDTD/excitation.h \ FDTD/operator_ext_cylinder.h \ - FDTD/engine_ext_cylinder.h + FDTD/engine_ext_cylinder.h \ + FDTD/operator_sse_compressed.h \ + FDTD/engine_sse_compressed.h QMAKE_CXXFLAGS_RELEASE = -O3 \ -g \ -march=native diff --git a/openems.cpp b/openems.cpp index 34423ea..ef4e147 100644 --- a/openems.cpp +++ b/openems.cpp @@ -22,6 +22,7 @@ #include "FDTD/operator_cylinder.h" #include "FDTD/engine_multithread.h" #include "FDTD/engine_sse.h" +#include "FDTD/operator_sse_compressed.h" #include "FDTD/operator_ext_mur_abc.h" #include "FDTD/processvoltage.h" #include "FDTD/processcurrent.h" @@ -121,6 +122,12 @@ bool openEMS::parseCommandLineArgument( const char *argv ) m_engine = EngineType_SSE; return true; } + else if (strcmp(argv,"--engine=sse-compressed")==0) + { + cout << "openEMS - enabled compressed sse engine" << endl; + m_engine = EngineType_SSE_Compressed; + return true; + } return false; } @@ -211,6 +218,10 @@ int openEMS::SetupFDTD(const char* file) { FDTD_Op = Operator_sse::New(); } + else if (m_engine == EngineType_SSE_Compressed) + { + FDTD_Op = Operator_SSE_Compressed::New(); + } else { FDTD_Op = Operator::New(); diff --git a/openems.h b/openems.h index c22950b..2b38c88 100644 --- a/openems.h +++ b/openems.h @@ -60,7 +60,7 @@ protected: Engine* FDTD_Eng; ProcessingArray* PA; - enum EngineType {EngineType_Standard, EngineType_SSE}; + enum EngineType {EngineType_Standard, EngineType_SSE, EngineType_SSE_Compressed}; EngineType m_engine; unsigned int m_engine_numThreads; }; diff --git a/tools/array_ops.cpp b/tools/array_ops.cpp index eb0cfa2..2150090 100644 --- a/tools/array_ops.cpp +++ b/tools/array_ops.cpp @@ -132,6 +132,11 @@ void Dump_N_3DArray2File(ostream &file, FDTD_FLOAT**** array, unsigned int* numL } +void Delete1DArray_v4sf(f4vector* array) +{ + if (array==NULL) return; + FREE( array ); +} void Delete3DArray_v4sf(f4vector*** array, const unsigned int* numLines) @@ -163,6 +168,16 @@ void Delete_N_3DArray_v4sf(f4vector**** array, const unsigned int* numLines) //delete[] array; } +f4vector* Create1DArray_v4sf(const unsigned int numLines) +{ + f4vector* array=NULL; + if (MEMALIGN( (void**)&array, 16, sizeof(typeof(f4vector))*numLines )) { + cerr << "cannot allocate aligned memory" << endl; + exit(3); + } + return array; +} + //! \brief this function allocates a 3D array, which is aligned to 16 byte f4vector*** Create3DArray_v4sf(const unsigned int* numLines) { diff --git a/tools/array_ops.h b/tools/array_ops.h index 661bd2f..c96cd6b 100644 --- a/tools/array_ops.h +++ b/tools/array_ops.h @@ -47,8 +47,10 @@ void Delete_N_3DArray(FDTD_FLOAT**** array, const unsigned int* numLines); void Dump_N_3DArray2File(ostream &file, FDTD_FLOAT**** array, const unsigned int* numLines); +void Delete1DArray_v4sf(f4vector* array); void Delete3DArray_v4sf(f4vector*** array, const unsigned int* numLines); void Delete_N_3DArray_v4sf(f4vector**** array, const unsigned int* numLines); +f4vector* Create1DArray_v4sf(const unsigned int numLines); f4vector*** Create3DArray_v4sf(const unsigned int* numLines); f4vector**** Create_N_3DArray_v4sf(const unsigned int* numLines);