├── .gitignore ├── Encoder-Decoder-System ├── Encoder-Decoder-System.sln ├── Encoder-Decoder-System │ ├── Block.cpp │ ├── Block.h │ ├── Encoder-Decoder-System.cpp │ ├── Encoder-Decoder-System.vcxproj │ ├── Encoder-Decoder-System.vcxproj.filters │ ├── Encoder.cpp │ ├── Encoder.h │ ├── Error_Injection.h │ ├── Field.cpp │ ├── Field.h │ ├── Field_Element.cpp │ ├── Field_Element.h │ ├── File_Decoder.cpp │ ├── File_Decoder.h │ ├── File_Encoder.cpp │ ├── File_Encoder.h │ ├── Fileio.cpp │ ├── Fileio.h │ ├── Generator_polynomial.h │ ├── Logger.cpp │ ├── Logger.h │ ├── Mixing.cpp │ ├── Mixing.h │ ├── Polynomial.cpp │ ├── Polynomial.h │ ├── audio.opus │ ├── binary_image_corrected.bmp │ ├── binary_image_corrupted.bmp │ ├── binary_image_data.bin │ ├── binary_image_encoded.bmp │ ├── decoder.cpp │ ├── decoder.h │ ├── input.dat │ ├── logfile_2024-09-12_16_48_06.txt │ ├── logfile_2024-09-15_13_53_22.txt │ ├── output.rsdec │ ├── output.rsenc │ ├── picture.bmp │ ├── picture_too_big.bmp │ ├── report.h │ └── setup_utilities.h └── Sample-Test1 │ ├── E2E_Tests.cpp │ ├── Sample-Test1.vcxproj │ ├── Test_Utility.cpp │ ├── Test_Utility.h │ ├── Unit_Test.cpp │ ├── Unit_Tests.cpp │ ├── binary_image_data.bin │ ├── empty_input.dat │ ├── input.dat │ ├── packages.config │ ├── pch.cpp │ ├── pch.h │ └── test_logfile.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34728.123 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Encoder-Decoder-System", "Encoder-Decoder-System\Encoder-Decoder-System.vcxproj", "{6102594D-81FF-43B3-A93B-1DF35C90A239}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Encoder-Decoder-Tests", "Sample-Test1\Sample-Test1.vcxproj", "{EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {6102594D-81FF-43B3-A93B-1DF35C90A239} = {6102594D-81FF-43B3-A93B-1DF35C90A239} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|x64 = Release|x64 18 | Release|x86 = Release|x86 19 | Test|x64 = Test|x64 20 | Test|x86 = Test|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Debug|x64.ActiveCfg = Debug|x64 24 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Debug|x64.Build.0 = Debug|x64 25 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Debug|x86.ActiveCfg = Debug|Win32 26 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Debug|x86.Build.0 = Debug|Win32 27 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Release|x64.ActiveCfg = Release|x64 28 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Release|x64.Build.0 = Release|x64 29 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Release|x86.ActiveCfg = Release|Win32 30 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Release|x86.Build.0 = Release|Win32 31 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Test|x64.ActiveCfg = Test|x64 32 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Test|x64.Build.0 = Test|x64 33 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Test|x86.ActiveCfg = Test|Win32 34 | {6102594D-81FF-43B3-A93B-1DF35C90A239}.Test|x86.Build.0 = Test|Win32 35 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Debug|x64.ActiveCfg = Debug|x64 36 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Debug|x64.Build.0 = Debug|x64 37 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Debug|x86.ActiveCfg = Debug|Win32 38 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Debug|x86.Build.0 = Debug|Win32 39 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Release|x64.ActiveCfg = Release|x64 40 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Release|x64.Build.0 = Release|x64 41 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Release|x86.ActiveCfg = Release|Win32 42 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Release|x86.Build.0 = Release|Win32 43 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Test|x64.ActiveCfg = Test|x64 44 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Test|x64.Build.0 = Test|x64 45 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Test|x86.ActiveCfg = Test|Win32 46 | {EA94A37C-CCDB-412D-A1AA-CD16A9E0D57F}.Test|x86.Build.0 = Test|Win32 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | GlobalSection(ExtensibilityGlobals) = postSolution 52 | SolutionGuid = {D24AE478-60B5-4F6E-B1BB-C31C1D8E6FE8} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Block.cpp: -------------------------------------------------------------------------------- 1 | #include "Block.h" 2 | 3 | namespace wd_codec { 4 | namespace reed_solomon { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Field.h" 4 | 5 | 6 | namespace wd_codec { 7 | namespace reed_solomon 8 | { 9 | template 10 | class Block 11 | { 12 | public: 13 | // Typedefs 14 | typedef galois::field_symbol symbol_type; 15 | typedef Block block_t; 16 | 17 | // Default constructor 18 | Block() 19 | : errors_detected(0), 20 | errors_corrected(0), 21 | zero_numerators(0), 22 | unrecoverable(false) 23 | { 24 | } 25 | 26 | // Constructor with data and fec strings 27 | Block(const std::string& _data, const std::string& _fec)//todo::is nesscary? 28 | : errors_detected(0), 29 | errors_corrected(0), 30 | zero_numerators(0), 31 | unrecoverable(false) 32 | { 33 | //// Ensure _data and _fec sizes are correct before processing 34 | //if (_data.size() != data_length || _fec.size() != fec_length) {//todo:is nesscary 35 | // throw std::invalid_argument("Invalid data or fec length."); 36 | //} 37 | 38 | // Copy data into the array 39 | for (std::size_t i = 0; i < data_length; ++i) 40 | { 41 | data[i] = static_cast(_data[i]); 42 | } 43 | 44 | for (std::size_t i = 0; i < fec_length; ++i) 45 | { 46 | data[i + data_length] = static_cast(_fec[i]); 47 | } 48 | } 49 | 50 | galois::field_symbol& fec(int index) { 51 | return data[index + data_length]; 52 | } 53 | 54 | // Placing operators: 55 | galois::field_symbol& operator[](const std::size_t index) { 56 | return data[index]; 57 | } 58 | 59 | const galois::field_symbol& operator[](const std::size_t index) const { 60 | return data[index]; 61 | } 62 | 63 | galois::field_symbol& operator()(const std::size_t index) { 64 | return data[index]; 65 | } 66 | // Member variables 67 | std::size_t errors_detected; 68 | std::size_t errors_corrected; 69 | 70 | std::size_t zero_numerators; 71 | bool unrecoverable; 72 | galois::field_symbol data[code_length]; 73 | }; 74 | template 75 | inline void copy(const T src_data[], 76 | const std::size_t& src_length, 77 | Block& dest_block) 78 | { 79 | for (std::size_t index = 0; index < src_length; ++index) 80 | { 81 | dest_block.data[index] = static_cast::symbol_type>(src_data[index]); 82 | } 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Encoder-Decoder-System.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Encoder-Decoder-System.cpp : This file contains the 'main' function. Program execution begins and ends there. 3 | #include "setup_utilities.h" 4 | int main() 5 | {//todo : insted of if encode return 1 just call encode function 6 | //FLSE OR TRUE FOR THE DECIDE OF THE DEVELOPER 7 | wd_codec::setup(); 8 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 9 | const wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 10 | 11 | wd_codec::file_encoder_t file_encoder(encoder); 12 | wd_codec::file_decoder_t file_decoder(decoder); 13 | 14 | std::cout << "Enter 1 for primitive input-\n 2 for file input\n 3 for image file\n 4 for audio file\n"; 15 | int choice; 16 | std::cin >> choice; 17 | wd_codec::Logger::increaseCoverage(); 18 | if (choice == 1) { 19 | //TODO: handle string input; 20 | std::string message = "Tamar Ayala and Efrat developed the best encoder deocder system\n, they worked hard, but at the end it was worth it"; 21 | message.resize(wd_codec::code_length, 0x00); 22 | if (!encoder.encode(wd_codec::block, message)) 23 | { 24 | 25 | return 1; 26 | } 27 | else { 28 | wd_codec::Logger::increaseCoverage(); 29 | std::cout << "\nEncode word: ["; 30 | for (std::size_t i = 0; i < wd_codec::code_length; ++i) 31 | { 32 | std::cout << static_cast(wd_codec::block[i]); 33 | } 34 | std::cout << "]\n"; 35 | } 36 | if (!decoder.decode(wd_codec::block)) { 37 | wd_codec::Logger::increaseCoverage(); 38 | 39 | return 1; 40 | } 41 | else { 42 | std::cout << "\Decode word: ["; 43 | for (std::size_t i = 0; i < wd_codec::data_length; ++i) 44 | { 45 | std::cout << static_cast(wd_codec::block[i]); 46 | } 47 | std::cout << "]\n"; 48 | } 49 | 50 | 51 | } 52 | else if (choice == 2) { //TODO: handle the files names will be input from the client 53 | const std::string input_file_name = "input.dat"; 54 | const std::string rsencoded_output_file_name = "output.rsenc"; 55 | const std::string rsdecoded_file_name = "output.rsdec"; 56 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * wd_codec::stack_size - 3); 57 | // Call the encode function 58 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 59 | return 1; 60 | } 61 | wd_codec::Logger::increaseCoverage(); 62 | wd_codec::error_injection::inject_random_errors(rsencoded_output_file_name); 63 | wd_codec::Logger::increaseCoverage(); 64 | if (!file_decoder.decode(rsencoded_output_file_name, rsdecoded_file_name)) { 65 | wd_codec::Logger::log(wd_codec::INFO, "File Decoder: Decoder failed " ); 66 | wd_codec::close(); 67 | return 1; 68 | } 69 | else { 70 | std::cout << "Decoding succeed." << std::endl; 71 | } 72 | std::cout << "num blocks " << file_decoder.getCurrentBlockIndex(); 73 | } 74 | else if (choice == 3) 75 | { 76 | //TODO: handle the files names will be input from the client 77 | const std::string input_file_name = "picture.bmp"; 78 | const std::string rsencoded_output_file_name = "output.rsenc"; 79 | const std::string rsdecoded_file_name = "output.rsdec"; 80 | // Call the encode function 81 | const std::string binaryFilePath = "binary_image_data.bin"; 82 | wd_codec::fileio::convert_image_to_binary(input_file_name, binaryFilePath); 83 | wd_codec::error_injection::inject_random_errors_for_image(binaryFilePath, "binary_image_corrupted.bmp"); 84 | if (!file_encoder.encode_image(input_file_name, rsencoded_output_file_name)) { 85 | std::cout << "Encoding failed." << std::endl; 86 | wd_codec::close(); 87 | return 1; 88 | } 89 | wd_codec::Logger::increaseCoverage(); 90 | wd_codec::error_injection::inject_random_errors_for_image(rsencoded_output_file_name, "binary_image_encoded.bmp"); 91 | wd_codec::Logger::increaseCoverage(); 92 | if (!file_decoder.decode_image(rsencoded_output_file_name, rsdecoded_file_name)) { 93 | std::cout << "Decoding failed." << std::endl; 94 | wd_codec::close(); 95 | return 1; 96 | } 97 | else { 98 | std::cout << "Decoding succeed." << std::endl; 99 | } 100 | std::cout << "num blocks " << file_decoder.get_current_block_index_(); 101 | wd_codec::Logger::increaseCoverage(); 102 | 103 | 104 | } 105 | 106 | else if (choice == 4) 107 | { 108 | //TODO: handle the files names will be input from the client 109 | const std::string input_file_name = "audio.opus"; 110 | const std::string rsencoded_output_file_name = "output.rsenc"; 111 | const std::string rsdecoded_file_name = "output.rsdec"; 112 | // Call the encode function 113 | const std::string binaryFilePath = "binary_audio_data.bin"; 114 | wd_codec::fileio::converAudioToBinary(input_file_name, binaryFilePath); 115 | wd_codec::error_injection::inject_random_errors_for_audio(binaryFilePath, "binary_audio_corrupted.opus"); 116 | if (!file_encoder.encode_audio(input_file_name, rsencoded_output_file_name)) { 117 | std::cout << "Encoding failed." << std::endl; 118 | wd_codec::close(); 119 | return 1; 120 | } 121 | wd_codec::Logger::increaseCoverage(); 122 | wd_codec::error_injection::inject_random_errors_for_audio(rsencoded_output_file_name, "binary_audio_encoded.opus"); 123 | wd_codec::Logger::increaseCoverage(); 124 | if (!file_decoder.decode_audio(rsencoded_output_file_name, rsdecoded_file_name)) { 125 | std::cout << "Decoding failed." << std::endl; 126 | wd_codec::close(); 127 | return 1; 128 | } 129 | else { 130 | std::cout << "Decoding succeed." << std::endl; 131 | } 132 | std::cout << "num blocks " << file_decoder.get_current_block_index_(); 133 | wd_codec::Logger::increaseCoverage(); 134 | } 135 | else { 136 | wd_codec::Logger::log(wd_codec::ERROR, "your choice is invalid!"); 137 | 138 | } 139 | wd_codec::close(); 140 | } 141 | 142 | 143 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Encoder-Decoder-System.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Testing 22 | Win32 23 | 24 | 25 | Testing 26 | x64 27 | 28 | 29 | Test_Mode 30 | Win32 31 | 32 | 33 | Test_Mode 34 | x64 35 | 36 | 37 | Test 38 | Win32 39 | 40 | 41 | Test 42 | x64 43 | 44 | 45 | 46 | 17.0 47 | Win32Proj 48 | {6102594d-81ff-43b3-a93b-1df35c90a239} 49 | EncoderDecoderSystem 50 | 10.0 51 | 52 | 53 | 54 | Application 55 | true 56 | v143 57 | Unicode 58 | 59 | 60 | Application 61 | true 62 | v143 63 | Unicode 64 | 65 | 66 | Application 67 | false 68 | v143 69 | true 70 | Unicode 71 | 72 | 73 | Application 74 | false 75 | v143 76 | true 77 | Unicode 78 | 79 | 80 | Application 81 | true 82 | v143 83 | Unicode 84 | 85 | 86 | Application 87 | true 88 | v143 89 | Unicode 90 | 91 | 92 | Application 93 | false 94 | v143 95 | true 96 | Unicode 97 | 98 | 99 | Application 100 | false 101 | v143 102 | true 103 | Unicode 104 | 105 | 106 | v143 107 | 108 | 109 | v143 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | Level3 144 | true 145 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | true 147 | 148 | 149 | Console 150 | true 151 | 152 | 153 | 154 | 155 | Level3 156 | true 157 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 158 | true 159 | 160 | 161 | Console 162 | true 163 | 164 | 165 | 166 | 167 | Level3 168 | true 169 | true 170 | true 171 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 172 | true 173 | 174 | 175 | Console 176 | true 177 | true 178 | true 179 | 180 | 181 | 182 | 183 | Level3 184 | true 185 | true 186 | true 187 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 188 | true 189 | 190 | 191 | Console 192 | true 193 | true 194 | true 195 | 196 | 197 | 198 | 199 | Level3 200 | true 201 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 202 | true 203 | 204 | 205 | Console 206 | true 207 | 208 | 209 | 210 | 211 | Level3 212 | true 213 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 214 | true 215 | 216 | 217 | Console 218 | true 219 | 220 | 221 | 222 | 223 | Level3 224 | true 225 | true 226 | true 227 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 228 | true 229 | ProgramDatabase 230 | 231 | 232 | Console 233 | true 234 | true 235 | true 236 | 237 | 238 | 239 | 240 | Level3 241 | true 242 | true 243 | true 244 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 245 | true 246 | ProgramDatabase 247 | 248 | 249 | Console 250 | true 251 | true 252 | true 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Encoder-Decoder-System.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | 97 | 98 | Header Files 99 | 100 | 101 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Encoder.cpp: -------------------------------------------------------------------------------- 1 | #include "Encoder.h" 2 | namespace wd_codec { 3 | namespace reed_solomon { 4 | 5 | } 6 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Encoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Field.h" 7 | #include "Polynomial.h" 8 | #include "Field_Element.h" 9 | #include "Block.h" 10 | #include "Logger.h" 11 | namespace wd_codec 12 | { 13 | 14 | namespace reed_solomon 15 | { 16 | template 17 | class Encoder 18 | { 19 | public: 20 | typedef Block block_type; 21 | 22 | Encoder(const galois::Field& gfield, const galois::Polynomial& generator) 23 | : encoder_valid(code_length == gfield.size()), 24 | field_(gfield), 25 | generator_(generator) 26 | { 27 | wd_codec::Logger::increaseCoverage(); 28 | 29 | #ifdef _DEBUG 30 | Logger::log(wd_codec::INFO, "Decoder: generate encoder."); 31 | #endif // DEBUG 32 | } 33 | 34 | ~Encoder() 35 | {} 36 | 37 | //Encoding the message. 38 | bool encode(block_type& rsblock) const { 39 | #ifdef _DEBUG 40 | wd_codec::Logger::log(wd_codec::INFO, "Encode: Encoding..."); 41 | #endif // DEBUG 42 | //Computing data = p(x)*x^n-k, 43 | //where p(x) in rsblock. 44 | galois::Polynomial data(field_, code_length); 45 | place_data_in_codeword(rsblock, data); 46 | //remainder = r(x) = p(x)*x^n-k % g(x). 47 | const galois::Polynomial remainder = data % generator_; 48 | const galois::field_symbol mask = field_.mask(); 49 | ////fec_length = n-k, to make sure the remainder is valid. 50 | if (remainder.deg() == (fec_length - 1)) 51 | { 52 | //make rsblock = (reversed) s(x) = p(x)*x^n-k - r(x) 53 | for (std::size_t i = 0; i < fec_length; ++i) 54 | { 55 | //rsblock.fec(i) = rsblock[k+i] 56 | rsblock.fec(i) = remainder[fec_length - 1 - i].poly() & mask; 57 | } 58 | } 59 | else 60 | { 61 | /* 62 | Note: Encoder should never branch here. 63 | Possible issues to look for: 64 | 1. Generator polynomial degree is not equivelent to fec length 65 | 2. Field and code length are not consistent. 66 | 67 | */ 68 | 69 | wd_codec::Logger::log(wd_codec::ERROR, "Encode: Encode failed!"); 70 | return false; 71 | } 72 | #ifdef _DEBUG 73 | wd_codec::Logger::log(wd_codec::INFO, "Encode: Encode succeeded"); 74 | #endif // DEBUG 75 | return true; 76 | } 77 | 78 | bool encode(block_type& rsblock, const std::string& data) const { 79 | const galois::field_symbol mask = field_.mask(); 80 | //iterate the data polynomial and add it to the rsblock data. 81 | for (std::size_t i = 0; i < data_length; i++) { 82 | rsblock[i] = data[i] & mask; 83 | } 84 | return encode(rsblock); 85 | } 86 | 87 | private: 88 | const bool encoder_valid; 89 | const galois::Field& field_; 90 | const galois::Polynomial generator_; 91 | 92 | //Compute the P(x)*x^(n-k) for making place to the redundancy. 93 | inline void place_data_in_codeword(const block_type& rsblock, galois::Polynomial& data) const { 94 | #ifdef _DEBUG 95 | wd_codec::Logger::log(wd_codec::INFO, "Encode: place data in codeword"); 96 | #endif // DEBUG 97 | for (std::size_t i = code_length - 1; i >= fec_length; i--) { 98 | data[i] = rsblock[code_length - 1 - i]; 99 | } 100 | } 101 | 102 | }; 103 | } 104 | } 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Error_Injection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fileio.h" 3 | #include "Block.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include // For rand() 11 | #include // For time() 12 | 13 | namespace wd_codec { 14 | namespace error_injection { 15 | 16 | // Function that inject random errors for primitive input types 17 | /* template 18 | inline void inject_random_errors(Block& rsblock) { 19 | for (int i = 0; i < data_length; i += 20) { 20 | rsblock[i] = rsblock[i]; 21 | } 22 | }*/ 23 | 24 | // Function that inject a lot of random errors for files input 25 | template 26 | inline void inject_random_errors(const std::string& file_name, int errors_number = 0, std::size_t start = 0) { 27 | wd_codec::Logger::log(wd_codec::INFO, "Error Injection: inject random errors."); 28 | if (!wd_codec::fileio::file_exists(file_name)) 29 | { 30 | wd_codec::Logger::log(wd_codec::ERROR,"Error Injection: file does not exist!"); 31 | return; 32 | } 33 | 34 | std::ifstream file(file_name.c_str(), std::ios::in | std::ios::binary); 35 | if (!file) 36 | { 37 | wd_codec::Logger::log(wd_codec::ERROR,"Error Injection: Unable to open file for reading!"); 38 | return; 39 | } 40 | 41 | // Get the file size 42 | std::streamsize file_size = wd_codec::fileio::file_size(file_name); 43 | 44 | std::vector buffer(data_length); 45 | 46 | // Initialize random number generator: 47 | std::random_device rd; // Seed generator 48 | std::mt19937 gen(rd()); // Random number engine 49 | std::uniform_int_distribution<> byte_dis(0, data_length - 1); // Uniform distribution [0, data_length] 50 | 51 | // Process the file in chunks 52 | int i = 0; 53 | for (std::streamoff offset = start; offset < file_size; offset += code_length) 54 | { 55 | std::streamsize current_chunk_size = (data_length < file_size - offset) ? data_length : (file_size - offset); 56 | file.seekg(offset); 57 | file.read(buffer.data(), current_chunk_size); 58 | 59 | // Inject random errors 60 | std::set error_indices; 61 | int counter_errors = 0; 62 | /* if (i % 10 == 0) { 63 | errors_number = 20; 64 | } 65 | else 66 | errors_number = 0; 67 | i++;*/ 68 | while (counter_errors < fec_length / 2 + errors_number) 69 | { 70 | std::size_t random_index = byte_dis(gen); 71 | // Valid condition 72 | if (random_index < current_chunk_size) 73 | { 74 | error_indices.insert(random_index); 75 | counter_errors++; 76 | } 77 | } 78 | 79 | for (std::size_t index : error_indices) 80 | { 81 | buffer[index] = char(buffer[index] + 2); // Corrupt the byte 82 | } 83 | 84 | // Write the corrupted chunk back to the file 85 | std::ofstream file_out(file_name.c_str(), std::ios::in | std::ios::out | std::ios::binary); 86 | if (!file_out) 87 | { 88 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection: Unable to open file for writing!"); 89 | return; 90 | } 91 | 92 | file_out.seekp(offset); 93 | file_out.write(buffer.data(), current_chunk_size); 94 | file_out.close(); 95 | } 96 | 97 | file.close(); 98 | } 99 | 100 | // Function that inject little bit random errors 101 | inline void inject_random_errors(const std::string& binaryFilename) { 102 | // Open the binary file for reading 103 | wd_codec::Logger::log(wd_codec::INFO, "Error Injection: inject random errors."); 104 | std::ifstream binaryFile(binaryFilename, std::ios::binary); 105 | if (!binaryFile) { 106 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection::binary file: Error opening binary file for reading."); 107 | return; 108 | } 109 | 110 | // Read the binary file into a buffer 111 | std::vector buffer((std::istreambuf_iterator(binaryFile)), std::istreambuf_iterator()); 112 | binaryFile.close(); 113 | 114 | // Seed the random number generator 115 | std::srand(std::time(nullptr)); 116 | 117 | // Number of errors to inject 118 | const size_t numErrors = 10; // Adjust the number of errors as needed 119 | 120 | // Inject random errors 121 | for (size_t i = 0; i < numErrors; ++i) { 122 | size_t index = std::rand() % buffer.size(); // Random index in the buffer 123 | buffer[index] = static_cast(std::rand() % 256); // Random byte value 124 | } 125 | 126 | // Open the binary file for writing 127 | std::ofstream outFile(binaryFilename, std::ios::binary); 128 | if (!outFile) { 129 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection::binary file: Error opening binary file for writing."); 130 | return; 131 | } 132 | 133 | // Write the corrupted buffer back to the binary file 134 | outFile.write(buffer.data(), buffer.size()); 135 | outFile.close(); 136 | } 137 | 138 | template 139 | inline void inject_random_errors_for_image(const std::string& file_name, const std::string& imageFilePath) { 140 | inject_random_errors(file_name, 0, code_length); 141 | wd_codec::fileio::convert_binary_to_image(file_name, imageFilePath); 142 | } 143 | 144 | template 145 | inline void inject_random_errors_for_audio(const std::string& file_name, const std::string& audioFilePath) { 146 | inject_random_errors(file_name); 147 | wd_codec::fileio::convert_binary_to_audio(file_name, audioFilePath); 148 | } 149 | 150 | inline void corrupt_file_with_burst_errors(const std::string& file_name, 151 | const long& start_position, 152 | const long& burst_length) 153 | { 154 | wd_codec::Logger::log(wd_codec::INFO, "Error Injection: corrupt file with burst errors"); 155 | if (!wd_codec::fileio::file_exists(file_name)) 156 | { 157 | 158 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection file: file does not exist!"); 159 | return; 160 | } 161 | 162 | if (static_cast(start_position + burst_length) >= wd_codec::fileio::file_size(file_name)) 163 | { 164 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection file: Burst error out of bounds!"); 165 | return; 166 | } 167 | 168 | std::vector data(burst_length); 169 | 170 | std::ifstream ifile(file_name.c_str(), std::ios::in | std::ios::binary); 171 | 172 | if (!ifile) 173 | { 174 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection file: Cannot open file for reading!"); 175 | return; 176 | } 177 | 178 | ifile.seekg(start_position, std::ios_base::beg); 179 | ifile.read(&data[0], burst_length); 180 | ifile.close(); 181 | 182 | for (long i = 0; i < burst_length; ++i) 183 | { 184 | data[i] = ~data[i]; 185 | } 186 | 187 | std::ofstream ofile(file_name.c_str(), std::ios::in | std::ios::out | std::ios::binary); 188 | 189 | if (!ofile) 190 | { 191 | wd_codec::Logger::log(wd_codec::ERROR, "Error Injection::file: Cannot open file for writing!"); 192 | 193 | return; 194 | } 195 | 196 | ofile.seekp(start_position, std::ios_base::beg); 197 | ofile.write(&data[0], burst_length); 198 | ofile.close(); 199 | } 200 | 201 | } 202 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Field.cpp: -------------------------------------------------------------------------------- 1 | #include "Field.h" 2 | #include "Logger.h" 3 | 4 | 5 | 6 | 7 | namespace wd_codec { 8 | namespace galois { 9 | 10 | const field_symbol GFERROR = -1; 11 | 12 | Field::Field(const unsigned int pwr, const std::size_t primpoly_deg, const unsigned int* primitive_poly) 13 | :power_(pwr), 14 | prim_poly_deg_(primpoly_deg), 15 | //to reach last number in gf(a^power) 16 | field_size_((1 << power_) - 1) 17 | { 18 | wd_codec::Logger::log(wd_codec::INFO, "generating field."); 19 | alpha_to_ = new field_symbol[field_size_ + 1]; 20 | index_of_ = new field_symbol[field_size_ + 1]; 21 | 22 | //TODO: check why mult with 3 is not enouph 23 | static const std::size_t buffer_size = ((4 * (field_size_ + 1) * (field_size_ + 1)) + ((field_size_ + 1) * 2)) * sizeof(field_symbol); 24 | 25 | buffer_ = new char[buffer_size]; 26 | std::size_t offset = 0; 27 | offset = create_2d_array(buffer_, (field_size_ + 1), (field_size_ + 1), offset, &mul_table_); 28 | offset = create_2d_array(buffer_, (field_size_ + 1), (field_size_ + 1), offset, &div_table_); 29 | offset = create_2d_array(buffer_, (field_size_ + 1), (field_size_ + 1), offset, &exp_table_); 30 | offset = create_array(buffer_, (field_size_ + 1) * 2, offset, &mul_inverse_); 31 | 32 | prim_poly_ = new unsigned int[prim_poly_deg_ + 1]; 33 | for (unsigned int i = 0; i < prim_poly_deg_ + 1; i++) 34 | { 35 | prim_poly_[i] = primitive_poly[i]; 36 | } 37 | prim_poly_hash_ = 0xAAAAAAAA; 38 | //Create a unique hash value for a given primitive polynomial to provide optimization for comparing two fields. prim_poly_hash_ = 0xAAAAAAAA; //10101010101010b good for hashing 39 | for (std::size_t i = 0; i < (prim_poly_deg_ + 1); i++) 40 | { 41 | prim_poly_hash_ += ((i & 1) == 0) ? ((prim_poly_hash_ << 7) ^ primitive_poly[i] * (prim_poly_hash_ >> 3)) : 42 | (~((prim_poly_hash_ << 11) + (primitive_poly[i] ^ (prim_poly_hash_ >> 5)))); 43 | } 44 | 45 | generate_field(prim_poly_); 46 | 47 | } 48 | 49 | Field::~Field() { 50 | //TODO: check about the: #if !defined(NO_GFLUT) 51 | if (!alpha_to_) { delete[] alpha_to_; alpha_to_ = 0; } 52 | if (!index_of_) { delete[] index_of_; index_of_ = 0; } 53 | if (!mul_inverse_) { delete[] mul_inverse_; mul_inverse_ = 0; } 54 | if (!prim_poly_) { delete[] prim_poly_; prim_poly_ = 0; } 55 | if (!mul_table_) { delete[] mul_table_; mul_table_ = 0; } 56 | if (!div_table_) { delete[] div_table_; div_table_ = 0; } 57 | if (!exp_table_) { delete[] exp_table_; exp_table_ = 0; } 58 | if (!buffer_) { delete[] buffer_; buffer_ = 0; } 59 | } 60 | 61 | bool Field::operator==(const Field& field) const { 62 | return this->power_ == field.power_ && this->prim_poly_hash_ == field.prim_poly_hash_; 63 | } 64 | 65 | bool Field::operator!=(const Field& field) const { 66 | return !operator==(field); 67 | } 68 | 69 | std::ostream& operator << (std::ostream& os, const Field& field) { 70 | for (int i = 0; i < field.field_size_; i++) { 71 | os << i << ": " << "alpha[i]= " << field.alpha_to_[i] << " index[i]= " << field.index_of_[i] << "\n"; 72 | } 73 | return os; 74 | } 75 | 76 | field_symbol Field::gen_mul(const field_symbol& a, const field_symbol& b) const 77 | { 78 | if ((a == 0) || (b == 0)) // if either operand is zero, the result is zero. 79 | return 0; 80 | else 81 | // log(a) + log(b), normalize, and look up the corresponding field element. 82 | return alpha_to_[normalize(index_of_[a] + index_of_[b])]; 83 | } 84 | 85 | field_symbol Field::gen_div(const field_symbol& a, const field_symbol& b) const 86 | { 87 | if ((a == 0) || (b == 0)) {// if the numerator or denominator is zero, the result is zero or error(which represnt in the table as zero) 88 | return 0; 89 | } 90 | else 91 | { 92 | // log(a) - log(b) + (field_size_ - 1) (to ensure non-negative), 93 | // normalize, and look up the corresponding field element. 94 | return alpha_to_[normalize(index_of_[a] - index_of_[b] + (field_size_ - 1))]; 95 | } 96 | } 97 | 98 | field_symbol Field::gen_exp(const field_symbol& a, const std::size_t& n) const 99 | { 100 | if (a != 0) 101 | { // if exponent is zero, return 1 (a^0 = 1) 102 | return ((n == 0) // log(a)*n 103 | ? 1 : alpha_to_[normalize(index_of_[a] * static_cast(n))]); 104 | } 105 | else // if a is zero 106 | { 107 | return 0; // 0^x = 0 for any x 108 | } 109 | } 110 | 111 | // computes the multiplicative inverse of a field element 'val' 112 | field_symbol Field::gen_inverse(const field_symbol& val) const 113 | { 114 | // e = log(val) 115 | // we want to find b so: 116 | // (a^e)*(a^b) = 1 : = a^(e+b) = 1 117 | // e + b = 0 = field_size_(because the field is cyclic) 118 | //b = field_size_ - log(val) 119 | return alpha_to_[normalize(field_size_ - index_of_[val])]; 120 | } 121 | 122 | void Field::generate_field(const unsigned int* prim_poly) 123 | { 124 | field_symbol mask = 1; 125 | 126 | alpha_to_[power_] = 0; 127 | 128 | for (field_symbol i = 0; i < static_cast(power_); ++i) 129 | { 130 | //a is the primitive element 131 | //alpha_to_[i] = a^i 132 | alpha_to_[i] = mask; 133 | //index_of_[a^i] = i (index_of_[a^i] = log(a^i) 134 | index_of_[alpha_to_[i]] = i; 135 | // checks if the current coefficient in the primitive polynomial is 1 (non-zero). 136 | if (prim_poly[i] != 0) 137 | { 138 | alpha_to_[power_] ^= mask; 139 | } 140 | //a^(i+1) 141 | mask <<= 1; 142 | } 143 | 144 | index_of_[alpha_to_[power_]] = power_; 145 | 146 | mask >>= 1; 147 | 148 | for (field_symbol i = power_ + 1; i < static_cast(field_size_); ++i) 149 | { 150 | if (alpha_to_[i - 1] >= mask)//alpha_to_[i - 1]<<1 will be out of the field range so it needs to be "normalizes" 151 | alpha_to_[i] = alpha_to_[power_] ^ ((alpha_to_[i - 1] ^ mask) << 1); 152 | else 153 | alpha_to_[i] = alpha_to_[i - 1] << 1; 154 | //index_of_[alpha_to_[i]] = i = log(alpha_to_[i]) 155 | index_of_[alpha_to_[i]] = i; 156 | } 157 | //log of nothig is zero! 158 | index_of_[0] = GFERROR; 159 | //becouse the field is cyclic 160 | alpha_to_[field_size_] = 1; 161 | 162 | #if !defined(NO_GFLUT) 163 | 164 | for (field_symbol i = 0; i < static_cast(field_size_ + 1); ++i) 165 | { 166 | for (field_symbol j = 0; j < static_cast(field_size_ + 1); ++j) 167 | { 168 | mul_table_[i][j] = gen_mul(i, j); 169 | div_table_[i][j] = gen_div(i, j); 170 | exp_table_[i][j] = gen_exp(i, j); 171 | } 172 | } 173 | 174 | //TODO: check about the linear exp table 175 | for (field_symbol i = 0; i < static_cast(field_size_ + 1); ++i) 176 | { 177 | mul_inverse_[i] = gen_inverse(i); 178 | mul_inverse_[i + (field_size_ + 1)] = mul_inverse_[i]; 179 | } 180 | 181 | #endif 182 | } 183 | 184 | std::size_t Field::create_array(char buffer[], const std::size_t& length, const std::size_t offset, field_symbol** array) 185 | { 186 | const std::size_t row_size = length * sizeof(field_symbol); 187 | (*array) = new(buffer + offset)field_symbol[length]; 188 | return row_size + offset; 189 | } 190 | 191 | std::size_t Field::create_2d_array(char buffer[], std::size_t row_cnt, std::size_t col_cnt, const std::size_t offset, field_symbol*** array) 192 | { 193 | const std::size_t row_size = col_cnt * sizeof(field_symbol); 194 | char* buffer__offset = buffer + offset; 195 | (*array) = new field_symbol * [row_cnt]; 196 | for (std::size_t i = 0; i < row_cnt; ++i) 197 | { 198 | (*array)[i] = new(buffer__offset + (i * row_size))field_symbol[col_cnt]; 199 | } 200 | return (row_cnt * row_size) + offset; 201 | } 202 | } 203 | } 204 | 205 | 206 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Field.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wd_codec { 8 | 9 | namespace galois { 10 | 11 | typedef int field_symbol; 12 | 13 | class Field 14 | { 15 | public: 16 | Field(const unsigned int pwr, const std::size_t primpoly_deg, const unsigned int* primitive_poly); 17 | Field(); 18 | ~Field(); 19 | // convert a field element to its corresponding exponent in terms of a primitive element 20 | inline field_symbol index(const field_symbol value) const { 21 | return index_of_[value]; 22 | } 23 | 24 | //returns the field element corresponding to a given exponent using a precomputed antilog table. 25 | inline field_symbol alpha(const field_symbol value) const { 26 | return alpha_to_[value]; 27 | } 28 | 29 | //get size of the Galois Field. 30 | inline unsigned int size() const { 31 | return field_size_; 32 | } 33 | 34 | //returns the power m used to define the field size 2^m 35 | inline unsigned int pwr() const { 36 | return power_; 37 | } 38 | 39 | //returns a mask value used for bitwise operations 40 | inline unsigned int mask() const { 41 | return field_size_; 42 | } 43 | 44 | //addition in a Galois Field 45 | inline field_symbol add(const field_symbol& a, const field_symbol& b) const { 46 | return (a ^ b); 47 | } 48 | 49 | //subtraction of two field elements 50 | inline field_symbol sub(const field_symbol& a, const field_symbol& b) const { 51 | return (a ^ b); 52 | } 53 | 54 | //A function that normalizes the values that deviate from the field value range. 55 | inline field_symbol normalize(field_symbol x) const { 56 | while (x < 0) { 57 | x += static_cast(field_size_); 58 | } 59 | while (x > static_cast(field_size_)) { 60 | x -= static_cast(field_size_); 61 | //optimization of the typical normalization(using mod) to addition of div and mod 62 | x = (x >> power_) + (x & field_size_); 63 | } 64 | return x; 65 | } 66 | 67 | inline field_symbol mul(const field_symbol& a, const field_symbol& b) const 68 | { 69 | #if !defined(NO_GFLUT) 70 | return mul_table_[a][b]; 71 | #else 72 | if ((a == 0) || (b == 0)) 73 | return 0; 74 | else 75 | return alpha_to_[normalize(index_of_[a] + index_of_[b])]; 76 | #endif 77 | } 78 | 79 | inline field_symbol div(const field_symbol& a, const field_symbol& b) const 80 | { 81 | if ((a == 0) || (b == 0)) 82 | return 0; 83 | else 84 | return alpha_to_[normalize(index_of_[a] - index_of_[b] + field_size_)]; 85 | } 86 | 87 | inline field_symbol exp(const field_symbol& a, int n) const 88 | { 89 | #if !defined(NO_GFLUT) 90 | if (n >= 0) 91 | return exp_table_[a][n & field_size_]; 92 | else 93 | { 94 | while (n < 0) n += field_size_; 95 | 96 | return (n ? exp_table_[a][n] : 1); 97 | } 98 | #else 99 | if (a != 0) 100 | { 101 | if (n < 0) 102 | { 103 | while (n < 0) n += field_size_; 104 | return (n ? alpha_to_[normalize(index_of_[a] * n)] : 1); 105 | } 106 | else if (n) 107 | return alpha_to_[normalize(index_of_[a] * static_cast(n))]; 108 | else 109 | return 1; 110 | } 111 | else 112 | return 0; 113 | #endif 114 | } 115 | 116 | inline field_symbol inverse(const field_symbol& val) const { 117 | return mul_inverse_[val]; 118 | } 119 | 120 | //accesses the coefficients of the primitive polynomial at a specified index.prim_poly_term(0) returns 1 (coefficient of x^0) 121 | inline unsigned int prim_poly_term(const unsigned int index) const { 122 | return prim_poly_[index]; 123 | } 124 | friend std::ostream& operator << (std::ostream& os, const Field& gf); 125 | bool operator==(const Field& field) const; 126 | bool operator!=(const Field& field) const; 127 | 128 | private: 129 | //finite field parameters: 130 | unsigned int power_; 131 | std::size_t prim_poly_deg_; 132 | unsigned int field_size_; 133 | unsigned int prim_poly_hash_; 134 | unsigned int* prim_poly_; 135 | //lookup tables: 136 | field_symbol* alpha_to_; //mapping exponents to field elements 137 | field_symbol* index_of_; //mapping field elements to exponents 138 | field_symbol* mul_inverse_; 139 | field_symbol** mul_table_; 140 | field_symbol** div_table_; 141 | field_symbol** exp_table_; //exp_table_[i][j] = alpha^(j*i) 142 | field_symbol** linear_exp_table_;//for complex operations that involve linear combinations of field elements 143 | char* buffer_; 144 | 145 | 146 | void generate_field(const unsigned int* prim_poly_); 147 | field_symbol gen_mul(const field_symbol& a, const field_symbol& b) const; 148 | field_symbol gen_div(const field_symbol& a, const field_symbol& b) const; 149 | field_symbol gen_exp(const field_symbol& a, const std::size_t& n) const; 150 | field_symbol gen_inverse(const field_symbol& val) const; 151 | 152 | std::size_t create_array(char buffer_[], 153 | const std::size_t& length, 154 | const std::size_t offset, 155 | field_symbol** array); 156 | 157 | std::size_t create_2d_array(char buffer_[], 158 | std::size_t row_cnt, std::size_t col_cnt, 159 | const std::size_t offset, 160 | field_symbol*** array); 161 | 162 | 163 | }; 164 | //define basic primitive polynomials 165 | //start from 4 becuase the min possible m for gf(2^m) is 2 166 | /* 1x^0 + 1x^1 + 0x^2 + 1x^3 */ 167 | const unsigned int primitive_polynomial00[] = { 1, 1, 0, 1 }; 168 | const unsigned int primitive_polynomial_size00 = 4; 169 | 170 | /* 1x^0 + 1x^1 + 0x^2 + 0x^3 + 1x^4*/ 171 | const unsigned int primitive_polynomial01[] = { 1, 1, 0, 0, 1 }; 172 | const unsigned int primitive_polynomial_size01 = 5; 173 | 174 | /* 1x^0 + 0x^1 + 1x^2 + 0x^3 + 0x^4 + 1x^5 */ 175 | const unsigned int primitive_polynomial02[] = { 1, 0, 1, 0, 0, 1 }; 176 | const unsigned int primitive_polynomial_size02 = 6; 177 | 178 | /* 1x^0 + 1x^1 + 0x^2 + 0x^3 + 0x^4 + 0x^5 + 1x^6 */ 179 | const unsigned int primitive_polynomial03[] = { 1, 1, 0, 0, 0, 0, 1 }; 180 | const unsigned int primitive_polynomial_size03 = 7; 181 | 182 | /* 1x^0 + 0x^1 + 0x^2 + 1x^3 + 0x^4 + 0x^5 + 0x^6 + 1x^7 */ 183 | const unsigned int primitive_polynomial04[] = { 1, 0, 0, 1, 0, 0, 0, 1 }; 184 | const unsigned int primitive_polynomial_size04 = 8; 185 | 186 | /* 1x^0 + 0x^1 + 1x^2 + 1x^3 + 1x^4 + 0x^5 + 0x^6 + 0x^7 + 1x^8 */ 187 | const unsigned int primitive_polynomial05[] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 }; 188 | const unsigned int primitive_polynomial_size05 = 9; 189 | 190 | /* 1x^0 + 1x^1 + 1x^2 + 0x^3 + 0x^4 + 0x^5 + 0x^6 + 1x^7 + 1x^8 */ 191 | const unsigned int primitive_polynomial06[] = { 1, 1, 1, 0, 0, 0, 0, 1, 1 }; 192 | const unsigned int primitive_polynomial_size06 = 9; 193 | 194 | /* 1x^0 + 0x^1 + 0x^2 + 0x^3 + 1x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 1x^9 */ 195 | const unsigned int primitive_polynomial07[] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; 196 | const unsigned int primitive_polynomial_size07 = 10; 197 | 198 | /* 1x^0 + 0x^1 + 0x^2 + 1x^3 + 0x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 1x^10 */ 199 | const unsigned int primitive_polynomial08[] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; 200 | const unsigned int primitive_polynomial_size08 = 11; 201 | 202 | /* 1x^0 + 0x^1 + 1x^2 + 0x^3 + 0x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 1x^11 */ 203 | const unsigned int primitive_polynomial09[] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 204 | const unsigned int primitive_polynomial_size09 = 12; 205 | 206 | /* 1x^0 + 1x^1 + 0x^2 + 0x^3 + 1x^4 + 0x^5 + 1x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 0x^11 + 1x^12 */ 207 | const unsigned int primitive_polynomial10[] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 }; 208 | const unsigned int primitive_polynomial_size10 = 13; 209 | 210 | /* 1x^0 + 1x^1 + 0x^2 + 1x^3 + 1x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 0x^11 + 0x^12 + 1x^13 */ 211 | const unsigned int primitive_polynomial11[] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 212 | const unsigned int primitive_polynomial_size11 = 14; 213 | 214 | /* 1x^0 + 1x^1 + 0x^2 + 0x^3 + 0x^4 + 0x^5 + 1x^6 + 0x^7 + 0x^8 + 0x^9 + 1x^10 + 0x^11 + 0x^12 + 0x^13 + 1x^14 */ 215 | const unsigned int primitive_polynomial12[] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }; 216 | const unsigned int primitive_polynomial_size12 = 15; 217 | 218 | /* 1x^0 + 1x^1 + 0x^2 + 0x^3 + 0x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 0x^11 + 0x^12 + 0x^13 + 0x^14 + 1x^15 */ 219 | const unsigned int primitive_polynomial13[] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 220 | const unsigned int primitive_polynomial_size13 = 16; 221 | 222 | /* 1x^0 + 1x^1 + 0x^2 + 1x^3 + 0x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 0x^11 + 1x^12 + 0x^13 + 0x^14 + 0x^15 + 1x^16 */ 223 | const unsigned int primitive_polynomial14[] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 }; 224 | const unsigned int primitive_polynomial_size14 = 17; 225 | 226 | } 227 | } 228 | 229 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Field_Element.cpp: -------------------------------------------------------------------------------- 1 | #include "Field_Element.h" 2 | #include 3 | 4 | 5 | namespace wd_codec { 6 | 7 | namespace galois { 8 | 9 | 10 | //check if the two Field_Element equals 11 | bool Field_Element::operator == (const Field_Element& gfe) const 12 | { 13 | return ((field_ == gfe.field_) && (poly_value_ == gfe.poly_value_)); 14 | } 15 | //check if value equals to the poly_value_ of an Field_Element 16 | bool Field_Element::operator == (const field_symbol& v) const 17 | { 18 | return (poly_value_ == v); 19 | } 20 | //check if the two Field_Element are different 21 | bool Field_Element::operator != (const Field_Element& gfe) const 22 | { 23 | return ((field_ != gfe.field_) || (poly_value_ != gfe.poly_value_)); 24 | } 25 | //check if value is different to the poly_value_ of an Field_Element 26 | bool Field_Element::operator != (const field_symbol& v) const { 27 | return (poly_value_ != v); 28 | } 29 | //check if this is smaller then gfe by comparing there poly_value_ 30 | bool Field_Element::operator < (const Field_Element& gfe) 31 | { 32 | return (poly_value_ < gfe.poly_value_); 33 | } 34 | //check if this poly_value_ is smaller then v 35 | bool Field_Element::operator < (const field_symbol& v) 36 | { 37 | return (poly_value_ < v); 38 | } 39 | //check if this is bigger then gfe by comparing there poly_value_ 40 | bool Field_Element::operator > (const Field_Element& gfe) 41 | { 42 | return (poly_value_ > gfe.poly_value_); 43 | } 44 | //check if this poly_value_ is bigger then v 45 | bool Field_Element::operator > (const field_symbol& v) 46 | { 47 | return (poly_value_ > v); 48 | } 49 | //function that returns the index of the Field_Element 50 | field_symbol Field_Element::index() const 51 | { 52 | //log(poly_value_) 53 | return field_.index(poly_value_); 54 | } 55 | //function that returns the poly_value_ (coefficient) of this Field_Element 56 | field_symbol Field_Element::poly() const 57 | { 58 | return poly_value_; 59 | } 60 | 61 | //function that returns a reference to the poly_value_ (coefficient) of this Field_Element 62 | field_symbol& Field_Element::poly() 63 | { 64 | return poly_value_; 65 | } 66 | 67 | //function that returns a refernce to the field of ths Field_Element 68 | const Field& Field_Element::galois_field() const 69 | { 70 | return field_; 71 | } 72 | 73 | //Compound Assignment Operators: 74 | Field_Element& Field_Element::operator= (const Field_Element& gfe) { 75 | if ((this != &gfe) && (&this->field_ == &gfe.field_)) { 76 | this->poly_value_ = gfe.poly_value_; 77 | } 78 | return *this; 79 | } 80 | 81 | 82 | Field_Element& Field_Element::operator= (const field_symbol& value) { 83 | poly_value_ = value & field_.size(); 84 | return *this; 85 | } 86 | 87 | 88 | Field_Element& Field_Element::operator += (const Field_Element& gfe) { 89 | this->poly_value_ = this->field_.add(poly_value_, gfe.poly_value_); 90 | return *this; 91 | } 92 | 93 | Field_Element& Field_Element::operator += (const field_symbol& value) { 94 | this->poly_value_ = this->field_.add(poly_value_, value); 95 | return *this; 96 | } 97 | 98 | Field_Element& Field_Element::operator -= (const Field_Element& gfe) { 99 | this->poly_value_ = this->field_.sub(poly_value_, gfe.poly_value_); 100 | return *this; 101 | } 102 | 103 | Field_Element& Field_Element::operator -= (const field_symbol& value) { 104 | this->poly_value_ = this->field_.sub(poly_value_, value); 105 | return *this; 106 | } 107 | 108 | Field_Element& Field_Element::operator *= (const Field_Element& gfe) { 109 | this->poly_value_ = this->field_.mul(poly_value_, gfe.poly_value_); 110 | return *this; 111 | } 112 | 113 | Field_Element& Field_Element::operator *= (const field_symbol& value) { 114 | this->poly_value_ = this->field_.mul(poly_value_, value); 115 | return *this; 116 | } 117 | 118 | Field_Element& Field_Element::operator /= (const Field_Element& gfe) { 119 | this->poly_value_ = this->field_.div(poly_value_, gfe.poly_value_); 120 | return *this; 121 | } 122 | 123 | 124 | Field_Element& Field_Element::operator /= (const field_symbol& value) { 125 | this->poly_value_ = this->field_.div(poly_value_, value); 126 | return *this; 127 | } 128 | 129 | Field_Element& Field_Element::operator ^= (const int& n) { 130 | this->poly_value_ = field_.exp(poly_value_, n); 131 | return *this; 132 | } 133 | 134 | std::ostream& operator << (std::ostream& os, const Field_Element& gfe) { 135 | return os << gfe.poly_value_; 136 | } 137 | 138 | field_symbol Field_Element::inverse() const { 139 | return field_.inverse(poly_value_); 140 | } 141 | 142 | void Field_Element::normalize() { 143 | //assign the modulo to keep in range of field size 144 | poly_value_ &= field_.size(); 145 | } 146 | 147 | 148 | 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Field_Element.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Field.h" 4 | 5 | namespace wd_codec { 6 | namespace galois { 7 | 8 | class Field_Element 9 | { 10 | public: 11 | 12 | 13 | Field_Element(const Field& field, const field_symbol& value):field_(const_cast(field)),poly_value_(value){}//ctor 14 | Field_Element(const Field& gfield):field_(gfield),poly_value_(-1){}//ctor 15 | Field_Element(const Field_Element& element) :field_(const_cast(element.field_)), poly_value_(element.poly_value_) {};//copy ctor 16 | ~Field_Element() {};//dtor 17 | 18 | Field_Element& operator = (const Field_Element& gfe); 19 | Field_Element& operator = (const field_symbol& v); 20 | Field_Element& operator += (const Field_Element& gfe); 21 | Field_Element& operator += (const field_symbol& v); 22 | Field_Element& operator -= (const Field_Element& gfe); 23 | Field_Element& operator -= (const field_symbol& v); 24 | Field_Element& operator *= (const Field_Element& gfe); 25 | Field_Element& operator *= (const field_symbol& v); 26 | Field_Element& operator /= (const Field_Element& gfe); 27 | Field_Element& operator /= (const field_symbol& v); 28 | Field_Element& operator ^= (const int& n); 29 | bool operator == (const Field_Element& gfe) const; 30 | bool operator == (const field_symbol& v) const; 31 | bool operator != (const Field_Element& gfe) const; 32 | bool operator != (const field_symbol& v) const; 33 | bool operator < (const Field_Element& gfe); 34 | bool operator < (const field_symbol& v); 35 | bool operator > (const Field_Element& gfe); 36 | bool operator > (const field_symbol& v); 37 | field_symbol index() const; 38 | field_symbol poly() const; 39 | field_symbol& poly(); 40 | const Field& galois_field() const; 41 | field_symbol inverse() const; 42 | void normalize(); 43 | friend std::ostream& operator << (std::ostream& os, const Field_Element& gfe); 44 | 45 | private: 46 | const Field& field_; 47 | //the value of the coefficient 48 | field_symbol poly_value_; 49 | 50 | }; 51 | 52 | inline Field_Element operator + (const Field_Element& a, const Field_Element& b) { 53 | Field_Element result = a; 54 | result += b; 55 | return result; 56 | } 57 | inline Field_Element operator - (const Field_Element& a, const Field_Element& b) { 58 | Field_Element result = a; 59 | result -= b; 60 | return result; 61 | } 62 | inline Field_Element operator * (const Field_Element& a, const Field_Element& b) { 63 | Field_Element result = a; 64 | result *= b; 65 | return result; 66 | } 67 | inline Field_Element operator * (const Field_Element& a, const field_symbol& b) { 68 | Field_Element result = a; 69 | result *= b; 70 | return result; 71 | } 72 | inline Field_Element operator * (const field_symbol& a, const Field_Element& b) { 73 | Field_Element result = b; 74 | result *= a; 75 | return result; 76 | } 77 | 78 | inline Field_Element operator / (const Field_Element& a, const Field_Element& b) 79 | { 80 | Field_Element result = a; 81 | result /= b; 82 | return result; 83 | } 84 | 85 | inline Field_Element operator ^ (const Field_Element& a, const int& b) { 86 | Field_Element result = a; 87 | result ^= b; 88 | return result; 89 | } 90 | 91 | 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/File_Decoder.cpp: -------------------------------------------------------------------------------- 1 | #include "File_Decoder.h" 2 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/File_Decoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Block.h" 5 | #include "Decoder.h" 6 | #include "Fileio.h" 7 | 8 | namespace wd_codec { 9 | namespace reed_solomon { 10 | 11 | template 12 | class File_Decoder 13 | { 14 | public: 15 | std::size_t getCurrentBlockIndex() const { 16 | return current_block_index_; 17 | } 18 | typedef Decoder decoder_type; 19 | typedef typename decoder_type::block_type block_type; 20 | 21 | bool decode_image(const std::string& input_file_name, 22 | const std::string& output_file_name) { 23 | bool result = decode(input_file_name, output_file_name); 24 | const std::string imageFilePath = "binary_image_corrected.bmp"; 25 | if (wd_codec::fileio::convert_binary_to_image(output_file_name, imageFilePath)) { 26 | #ifdef DEBUG 27 | wd_codec::Logger::log(wd_codec::INFO, "Binary to image conversion complete!"); 28 | #endif // DEBUG 29 | } 30 | else { 31 | wd_codec::Logger::log(wd_codec::ERROR, "Binary to image conversion failed!"); 32 | } 33 | return result; 34 | } 35 | 36 | bool decode_audio(const std::string& input_file_name, 37 | const std::string& output_file_name) { 38 | bool result = decode(input_file_name, output_file_name); 39 | const std::string imageFilePath = "binary_audio_corrected.opus"; 40 | wd_codec::fileio::convert_binary_to_audio(output_file_name, imageFilePath); 41 | return result; 42 | } 43 | 44 | File_Decoder(const decoder_type& decoder) : decoder(decoder), current_block_index_(0) {}; 45 | 46 | bool decode(const std::string& input_file_name, 47 | const std::string& output_file_name) 48 | { 49 | 50 | std::size_t remaining_bytes = wd_codec::fileio::file_size(input_file_name); 51 | 52 | if (remaining_bytes == 0) 53 | { 54 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Decoder: input file has ZERO size."); 55 | return false; 56 | } 57 | 58 | std::ifstream in_stream(input_file_name.c_str(), std::ios::binary); 59 | if (!in_stream) 60 | { 61 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Decoder: input file could not be opened."); 62 | return false; 63 | } 64 | 65 | std::ofstream out_stream(output_file_name.c_str(), std::ios::binary); 66 | if (!out_stream) 67 | { 68 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Decoder: output file could not be created."); 69 | return false; 70 | } 71 | 72 | current_block_index_ = 0; 73 | wd_codec::Logger::log(wd_codec::INFO, "File Decoder: decodeing file "); 74 | std::string message; 75 | while (remaining_bytes >= code_length) 76 | { 77 | message = "Decoding block number "+ std::to_string(current_block_index_); 78 | wd_codec::Logger::log(INFO, message); 79 | 80 | if (!process_complete_block(in_stream, out_stream)) { 81 | wd_codec::errors_block_locations += " "; 82 | wd_codec::errors_block_locations += std::to_string(current_block_index_); 83 | wd_codec::errors_block_locations += ","; 84 | wd_codec::num_uncorrected_blocks ++; 85 | failed_decode = false; 86 | } 87 | remaining_bytes -= code_length; 88 | current_block_index_++; 89 | } 90 | 91 | if (remaining_bytes > 0) 92 | { 93 | if (!process_partial_block(in_stream, out_stream, remaining_bytes)) 94 | failed_decode = false; 95 | } 96 | if(!wd_codec::errors_block_locations.empty()) 97 | wd_codec::errors_block_locations.pop_back(); 98 | in_stream.close(); 99 | out_stream.close(); 100 | #ifdef DEBUG 101 | wd_codec::Logger::log(wd_codec::INFO, "File Decoder: Decoder succeeded" ); 102 | #endif // DEBUG 103 | // wd_codec::Logger::logErrorsNumber(); 104 | wd_codec::num_blocks = current_block_index_; 105 | return failed_decode; 106 | } 107 | bool get_is_residue_handled() { 108 | return is_residue_handled; 109 | } 110 | 111 | std::size_t get_current_block_index_() { 112 | return current_block_index_; 113 | } 114 | 115 | private: 116 | 117 | inline bool process_complete_block( 118 | std::ifstream& in_stream, 119 | std::ofstream& out_stream) 120 | { 121 | in_stream.read(&buffer_[0], static_cast(code_length)); 122 | copy(buffer_, code_length, block_); 123 | bool decoder_succeed = true; 124 | if (!decoder.decode(block_)) 125 | { 126 | wd_codec::Logger::log(wd_codec::ERROR, "File Decoder::process_complete_block(): Error during decoding of block " + std::to_string(current_block_index_) ); 127 | wd_codec::global_errors_detected += block_.errors_detected; 128 | decoder_succeed = false; 129 | } 130 | else { 131 | wd_codec::global_errors_detected += block_.errors_detected; 132 | wd_codec::global_errors_corrected += block_.errors_corrected; 133 | } 134 | 135 | for (std::size_t i = 0; i < data_length; ++i) 136 | { 137 | buffer_[i] = static_cast(block_[i]); 138 | } 139 | out_stream.write(&buffer_[0], static_cast(data_length)); 140 | return decoder_succeed; 141 | } 142 | 143 | inline bool process_partial_block( 144 | std::ifstream& in_stream, 145 | std::ofstream& out_stream, 146 | const std::size_t& read_amount) 147 | { 148 | if (read_amount <= fec_length) 149 | { 150 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Decoder::process_partial_block(): Error during decoding of block" /*<< current_block_index_ << "!"*/); 151 | return false; 152 | } 153 | bool decoder_succeed = true; 154 | in_stream.read(&buffer_[0], static_cast(read_amount)); 155 | 156 | for (std::size_t i = 0; i < (read_amount - fec_length); ++i) 157 | { 158 | block_.data[i] = static_cast(buffer_[i]); 159 | } 160 | 161 | if ((read_amount - fec_length) < data_length) 162 | { 163 | for (std::size_t i = (read_amount - fec_length); i < data_length; ++i) 164 | { 165 | block_.data[i] = 0; 166 | } 167 | is_residue_handled = true; 168 | } 169 | 170 | for (std::size_t i = 0; i < fec_length; ++i) 171 | { 172 | block_.fec(i) = static_cast(buffer_[(read_amount - fec_length) + i]); 173 | } 174 | 175 | if (!decoder.decode(block_)) 176 | { 177 | wd_codec::Logger::log(wd_codec::ERROR, "File Decoder::process_partial_block(): Error during decoding of block" /*<< current_block_index_<<"!"*/); 178 | wd_codec::global_errors_detected += block_.errors_detected; 179 | decoder_succeed = false; 180 | } 181 | else{ 182 | wd_codec::global_errors_detected += block_.errors_detected; 183 | wd_codec::global_errors_corrected += block_.errors_corrected;} 184 | for (std::size_t i = 0; i < (read_amount - fec_length); ++i) 185 | { 186 | buffer_[i] = static_cast(block_.data[i]); 187 | } 188 | 189 | out_stream.write(&buffer_[0], static_cast(read_amount - fec_length)); 190 | return decoder_succeed; 191 | } 192 | 193 | const decoder_type& decoder; 194 | block_type block_; 195 | int current_block_index_; 196 | char buffer_[code_length]; 197 | bool is_residue_handled = false; 198 | bool failed_decode = true; 199 | }; 200 | 201 | } 202 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/File_Encoder.cpp: -------------------------------------------------------------------------------- 1 | #include "File_Encoder.h" 2 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/File_Encoder.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Field.h" 8 | #include "Polynomial.h" 9 | #include "Encoder.h" 10 | #include "Logger.h" 11 | #include "Fileio.h" 12 | #include "Block.h" 13 | 14 | 15 | namespace wd_codec { 16 | 17 | namespace reed_solomon { 18 | template 19 | class File_Encoder 20 | { 21 | 22 | public: 23 | typedef Encoder encoder_type; 24 | typedef typename encoder_type::block_type block_type; 25 | 26 | File_Encoder(const encoder_type& encoder) :encoder(encoder), blocks_number(0){ 27 | static_assert(data_length > 0, "data_length must be greater than 0"); 28 | if (data_length <= 0) { 29 | wd_codec::Logger::log(wd_codec::CRITICAL, "Encoder FAILED: data_length is non-positive"); 30 | throw std::invalid_argument("data_length must be greater than 0"); 31 | } 32 | }; 33 | 34 | bool encode_image(const std::string& input_file_name, 35 | const std::string& output_file_name) { 36 | const std::string binaryFilePath = "binary_image_data.bin"; 37 | fileio::convert_image_to_binary(input_file_name, binaryFilePath); 38 | return encode(binaryFilePath, output_file_name); 39 | } 40 | 41 | bool encode_audio(const std::string& input_file_name, 42 | const std::string& output_file_name) { 43 | const std::string binaryFilePath = "binary_audio_data.bin"; 44 | fileio::converAudioToBinary(input_file_name, binaryFilePath); 45 | return encode(binaryFilePath, output_file_name); 46 | } 47 | 48 | bool encode(const std::string& input_file_name, 49 | const std::string& output_file_name) 50 | { 51 | wd_codec::Logger::log(wd_codec::INFO, "INFO: encoding"); 52 | 53 | std::size_t remaining_bytes = wd_codec::fileio::file_size(input_file_name); 54 | if (remaining_bytes == 0) 55 | { 56 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Encoder: input file has ZERO size."); 57 | return false; 58 | } 59 | //open input file to read 60 | std::ifstream in_stream(input_file_name.c_str(), std::ios::binary); 61 | if (!in_stream) 62 | { 63 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Encoder: input file could not be opened."); 64 | return false; 65 | } 66 | //open output file to write 67 | std::ofstream out_stream(output_file_name.c_str(), std::ios::binary); 68 | if (!out_stream) 69 | { 70 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Encoder: output file could not be created."); 71 | return false; 72 | } 73 | 74 | std::memset(data_buffer_, 0, sizeof(data_buffer_)); 75 | std::memset(fec_buffer_, 0, sizeof(fec_buffer_)); 76 | 77 | if (remaining_bytes >= data_length) { 78 | #ifdef _DEBUG 79 | wd_codec::Logger::log(wd_codec::INFO, "INFO: dividing the file to blocks with size k"); 80 | #endif // DEBUG 81 | } 82 | //divide the file to blocks size k 83 | while (remaining_bytes >= data_length) 84 | { 85 | //encode each block 86 | process_block(in_stream, out_stream, data_length); 87 | inc_blocks_number(); 88 | remaining_bytes -= data_length; 89 | } 90 | //last block 91 | if (remaining_bytes > 0) 92 | { 93 | process_block(in_stream, out_stream, remaining_bytes); 94 | 95 | } 96 | #ifdef _DEBUG 97 | wd_codec::Logger::log(wd_codec::INFO, "File Encoder: Encode process successed"); 98 | #endif // DEBUG 99 | 100 | in_stream.close(); 101 | out_stream.close(); 102 | 103 | return true; 104 | } 105 | 106 | std::size_t get_blocks_number() { 107 | return blocks_number; 108 | } 109 | 110 | void set_blocks_number(std::size_t number) { 111 | blocks_number = number; 112 | } 113 | 114 | void inc_blocks_number() { 115 | blocks_number++; 116 | } 117 | bool get_is_residue_handled() { 118 | return is_residue_handled; 119 | } 120 | private: 121 | 122 | bool process_block(std::ifstream& in_stream, 123 | std::ofstream& out_stream, 124 | const std::size_t& read_amount) { 125 | in_stream.read(&data_buffer_[0], static_cast(read_amount)); 126 | //copy k bytes from the buffer to current block 127 | for (std::size_t i = 0; i < read_amount; ++i) 128 | { 129 | block_.data[i] = (data_buffer_[i] & 0xFF); 130 | } 131 | 132 | // padding zeros if needed 133 | if (read_amount < data_length) 134 | { 135 | for (std::size_t i = read_amount; i < data_length; ++i) 136 | { 137 | block_.data[i] = 0x00; 138 | } 139 | is_residue_handled = true; 140 | } 141 | 142 | if (!encoder.encode(block_)) 143 | { 144 | wd_codec::Logger::log(wd_codec::CRITICAL, "File Encoder: Error during encoding block."); 145 | return false; 146 | } 147 | //print each block 148 | /* std::cout << "\nEncode word: ["; 149 | for (std::size_t i = 0; i < code_length; ++i) 150 | { 151 | if (i == data_length) 152 | std::cout << " ++ "; 153 | std::cout << static_cast(block_[i]); 154 | } 155 | std::cout << "]\n";*/ 156 | 157 | 158 | for (std::size_t i = 0; i < fec_length; ++i) 159 | { 160 | fec_buffer_[i] = static_cast(block_.fec(i) & 0xFF); 161 | } 162 | 163 | out_stream.write(&data_buffer_[0], static_cast(read_amount)); 164 | out_stream.write(&fec_buffer_[0], fec_length); 165 | 166 | return true; 167 | } 168 | 169 | const encoder_type& encoder; 170 | block_type block_; 171 | std::size_t blocks_number; 172 | char data_buffer_[data_length]; 173 | 174 | char fec_buffer_[fec_length]; 175 | bool is_residue_handled = false; 176 | 177 | }; 178 | } 179 | 180 | } 181 | 182 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Fileio.cpp: -------------------------------------------------------------------------------- 1 | #include "Fileio.h" 2 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Fileio.h: -------------------------------------------------------------------------------- 1 | //for fileio- file_size function 2 | #pragma once 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Logger.h" 9 | #define IMG_TYPE ".BMP" 10 | #define IMG_TYPE_SIZE 4 11 | // Fileio.cpp 12 | 13 | namespace wd_codec { 14 | namespace fileio { 15 | 16 | inline std::size_t file_size(const std::string& file_name) { 17 | std::ifstream file(file_name, std::ios::binary | std::ios::ate); 18 | if (!file) return 0; 19 | return static_cast(file.tellg()); 20 | } 21 | 22 | inline bool file_exists(const std::string& file_name)//errors handle in call 23 | { 24 | std::ifstream file(file_name.c_str(), std::ios::binary); 25 | return ((!file) ? false : true); 26 | } 27 | 28 | inline void write_file(const std::string& file_name, const std::string& buffer) { 29 | std::ofstream file(file_name, std::ios::binary); 30 | if (!file) { 31 | wd_codec::Logger::log(wd_codec::CRITICAL, "Fileio: open file failed!"); 32 | return; 33 | } 34 | 35 | file.write(buffer.data(), static_cast(buffer.size())); 36 | } 37 | 38 | inline void write_file(const std::string& file_name, const char* buffer, std::size_t buffer_size) { 39 | std::ofstream file(file_name, std::ios::binary); 40 | if (!file) { 41 | wd_codec::Logger::log(wd_codec::CRITICAL, "Fileio: open file failed!"); 42 | return; 43 | } 44 | file.write(buffer, static_cast(buffer_size)); 45 | } 46 | 47 | inline void create_file(const std::string& file_name, const std::size_t file_size) 48 | { 49 | std::string buffer = std::string(file_size, 0x00); 50 | 51 | for (std::size_t i = 0; i < buffer.size() - 1; i += 2) 52 | { 53 | //buffer[i] = static_cast(i & 0xFF);//example 1 54 | //example 2 55 | buffer[i] = 'o'; 56 | buffer[i + 1] = 'z'; 57 | } 58 | 59 | wd_codec::fileio::write_file(file_name, buffer); 60 | } 61 | 62 | inline void converAudioToBinary(const std::string& audioFilename, const std::string& binaryFilename) { 63 | // Open the Opus file 64 | wd_codec::Logger::log(wd_codec::INFO, "convet audio to binary"); 65 | std::ifstream audioFile(audioFilename, std::ios::binary); 66 | if (!audioFile) { 67 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening Opus file."); 68 | return; 69 | } 70 | 71 | // Read the Opus file into a buffer 72 | std::vector buffer((std::istreambuf_iterator(audioFile)), std::istreambuf_iterator()); 73 | 74 | // Close the Opus file 75 | audioFile.close(); 76 | 77 | // Open the binary file 78 | std::ofstream binaryFile(binaryFilename, std::ios::binary); 79 | if (!binaryFile) { 80 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening binary file."); 81 | return; 82 | } 83 | 84 | // Write the buffer to the binary file 85 | binaryFile.write(buffer.data(), buffer.size()); 86 | 87 | // Close the binary file 88 | binaryFile.close(); 89 | } 90 | inline void convert_binary_to_audio(const std::string& binaryFilename, const std::string& audioFilename) { 91 | // Open the binary file 92 | wd_codec::Logger::log(wd_codec::INFO, "convet binary to audio "); 93 | 94 | std::ifstream binaryFile(binaryFilename, std::ios::binary); 95 | if (!binaryFile) { 96 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening binary file."); 97 | return; 98 | } 99 | 100 | // Read the binary file into a buffer 101 | std::vector buffer((std::istreambuf_iterator(binaryFile)), std::istreambuf_iterator()); 102 | 103 | // Close the binary file 104 | binaryFile.close(); 105 | 106 | // Open the Opus file 107 | std::ofstream audioFile(audioFilename, std::ios::binary); 108 | if (!audioFile) { 109 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening Opus file."); 110 | return; 111 | } 112 | 113 | // Write the buffer to the Opus file 114 | audioFile.write(buffer.data(), buffer.size()); 115 | 116 | // Close the Opus file 117 | audioFile.close(); 118 | } 119 | 120 | inline bool convert_image_to_binary(const std::string& imageFilePath, const std::string& binaryFilePath) 121 | { 122 | wd_codec::Logger::log(wd_codec::INFO, "convert image to binary "); 123 | 124 | std::ifstream image(imageFilePath, std::ios::in | std::ios::binary); 125 | if (!image) 126 | { 127 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening image file: "); 128 | return false; 129 | } 130 | 131 | std::ofstream binary(binaryFilePath, std::ios::out | std::ios::binary); 132 | if (!binary) 133 | { 134 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening binary output file: "); 135 | return false; 136 | } 137 | 138 | std::vector buffer((std::istreambuf_iterator(image)), std::istreambuf_iterator()); 139 | binary.write(buffer.data(), buffer.size()); 140 | 141 | image.close(); 142 | binary.close(); 143 | 144 | return true; 145 | } 146 | 147 | template 148 | inline bool convert_binary_to_image(const std::string& binaryFilePath, const std::string& imageFilePath) 149 | { 150 | wd_codec::Logger::log(wd_codec::INFO, "convert binary to image "); 151 | 152 | std::ifstream binary(binaryFilePath, std::ios::in | std::ios::binary); 153 | if (!binary) 154 | { 155 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening binary file: "); 156 | std::cerr << binaryFilePath << std::endl; 157 | return false; 158 | } 159 | 160 | std::ofstream image(imageFilePath, std::ios::out | std::ios::binary); 161 | if (!image) 162 | { 163 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening image output file: "); 164 | return false; 165 | } 166 | 167 | std::vector buffer((std::istreambuf_iterator(binary)), std::istreambuf_iterator()); 168 | image.write(buffer.data(), buffer.size()); 169 | 170 | binary.close(); 171 | image.close(); 172 | 173 | return true; 174 | } 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Generator_polynomial.h: -------------------------------------------------------------------------------- 1 | #include "Field.h" 2 | #include "Field_Element.h" 3 | #include "Polynomial.h" 4 | #include "Logger.h" 5 | //#include "Polynomial.cpp" 6 | namespace wd_codec { 7 | inline bool create_root_generator_polynomial(const galois::Field& field, 8 | const std::size_t initial_index, 9 | const std::size_t num_elements, 10 | galois::Polynomial& generator_polynomial) 11 | { 12 | wd_codec::Logger::increaseCoverage(); 13 | wd_codec::Logger::log(wd_codec::INFO, "Generating Polynomial...", generator_polynomial); 14 | if ( 15 | (initial_index >= field.size()) || 16 | ((initial_index + num_elements) > field.size()) 17 | ) 18 | { 19 | wd_codec::Logger::log(wd_codec::ERROR, "Generator Polynomial - creation faild!"); 20 | return false; 21 | } 22 | galois::Polynomial X = galois::generate_X(field);//polynomial X 23 | galois::Field_Element alpha(field, 2);//basic for all the root 24 | generator_polynomial = galois::Field_Element(field, 1); 25 | 26 | for (std::size_t i = initial_index; i < (initial_index + num_elements); i++) { 27 | //alpha^i is the root 28 | generator_polynomial *= (X + (alpha ^ static_cast(i))); 29 | } 30 | #ifdef _DEBUG 31 | wd_codec::Logger::log(wd_codec::INFO, "Generator Polynomial - creation succeeded!,\n G(x)= ", generator_polynomial); 32 | #endif // DEBUG 33 | 34 | return true; 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.h" 2 | namespace wd_codec { 3 | std::ofstream Logger::logFile; // Definition 4 | //std::chrono::time_point Logger::start_time; 5 | long long wd_codec::Logger::duration = 0; 6 | int wd_codec::Logger::coverage ; 7 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Logger.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "report.h" 5 | #include "Polynomial.h" 6 | 7 | #define POSTFIX ".txt" 8 | #define NUM_STAGES 7 9 | namespace wd_codec { 10 | 11 | // Enum to represent log levels 12 | enum LogLevel { DEBUG, INFO, WARNING, ERROR, CRITICAL }; 13 | static bool test_mode_empty_file = false; 14 | static std::chrono::time_point start_time; 15 | static std::chrono::time_point duration; 16 | 17 | class Logger { 18 | public: 19 | 20 | // Initializes the logger, opens the log file in append mode 21 | static void init() { 22 | char timestamp[20]; 23 | start_timer(); 24 | create_timestamp(timestamp); 25 | coverage = 0; 26 | // Convert C-style timestamp to std::string for concatenation 27 | std::string filename = std::string("logfile_") + timestamp + POSTFIX; 28 | 29 | // Replace spaces and colons in the filename to avoid file system issues 30 | for (char& c : filename) { 31 | if (c == ' ' || c == ':') { 32 | c = '_'; // Replace spaces and colons with underscores 33 | } 34 | } 35 | 36 | if (!logFile.is_open()) { 37 | // Open the log file in append mode 38 | logFile.open(filename, std::ios::out | std::ios::trunc); 39 | if (!logFile.is_open()) { 40 | wd_codec::Logger::log(wd_codec::ERROR, "Error opening log file."); 41 | } 42 | } 43 | } 44 | 45 | // Call this function at the beginning of the program to start the timer 46 | static void start_timer() { 47 | start_time = std::chrono::high_resolution_clock::now(); 48 | } 49 | 50 | // Call this function at the end of the program to log the elapsed time and other metrics 51 | static void log_report_metrics_summary(long long& duration) { 52 | auto end_time = std::chrono::high_resolution_clock::now(); 53 | duration = std::chrono::duration_cast(end_time - start_time).count(); 54 | std::ostringstream elapsed_time_message; 55 | wd_codec::Logger::log("-REPORT- "); 56 | elapsed_time_message << "* Elapsed time: " << duration << " milliseconds"; 57 | wd_codec::Logger::log_errors_number(); 58 | wd_codec::Logger::log("* Coverage system: " + std::to_string((coverage * 100) / NUM_STAGES) + "% done."); 59 | wd_codec::Logger::log(elapsed_time_message.str()); 60 | } 61 | 62 | // Function that log the report of the errors after the process 63 | static void log_errors_number() { 64 | // Create log entry 65 | std::ostringstream logEntry; 66 | std::size_t num_corrected_blocks = num_blocks - num_uncorrected_blocks; 67 | logEntry << "* Number of error that detected: " << wd_codec::global_errors_detected 68 | << "\n" 69 | << "* Number of error that corected: " << wd_codec::global_errors_corrected 70 | << "\n" 71 | << "* Number of blocks: " << num_blocks 72 | << "\n" 73 | << "* Number of corrected blocks: " << num_corrected_blocks 74 | << "\n" 75 | << "* Number of uncorrected blocks: " << num_uncorrected_blocks 76 | << "\n" 77 | << " The uncorrected blocks are:" << errors_block_locations 78 | << "\n" 79 | << "* Success rate: " << (((double)(num_corrected_blocks) / num_blocks) * 100) 80 | << "%" 81 | << std::endl; 82 | 83 | 84 | // Output to console 85 | std::cout << logEntry.str(); 86 | 87 | // Output to log file 88 | if (logFile.is_open()) { 89 | logFile << logEntry.str(); 90 | logFile.flush(); // Ensure immediate write to file 91 | } 92 | 93 | } 94 | 95 | // Overloading of log function: 96 | static void log(LogLevel level, const std::string& message, galois::Polynomial& poly) { 97 | std::string newMessage = message + poly.convert_to_string(); 98 | wd_codec::Logger::log(wd_codec::INFO, newMessage); 99 | 100 | } 101 | 102 | static void log(LogLevel level, const std::string& message) 103 | { 104 | char timestamp[20]; 105 | create_timestamp(timestamp); 106 | 107 | // Create log entry 108 | std::ostringstream logEntry; 109 | logEntry << "[" << timestamp << "] " 110 | << levelToString(level) << ": " << message 111 | << std::endl; 112 | //TODO: switch for run tests 113 | //#ifdef _DEBUG||_RELEASE 114 | //std::cout << logEntry.str(); 115 | //#endif 116 | // Output to log file 117 | if (logFile.is_open()) { 118 | logFile << logEntry.str(); 119 | logFile.flush(); // Ensure immediate write to file 120 | } 121 | } 122 | static void log(const std::string& message) 123 | { 124 | // Create log entry 125 | std::ostringstream logEntry; 126 | logEntry << message 127 | << std::endl; 128 | // Output to console 129 | std::cout << logEntry.str(); 130 | // Output to log file 131 | if (logFile.is_open()) { 132 | logFile << logEntry.str(); 133 | logFile.flush(); // Ensure immediate write to file 134 | } 135 | } 136 | 137 | // Closes the log file 138 | static void close() { 139 | char timestamp[20]; 140 | create_timestamp(timestamp); 141 | log_report_metrics_summary(duration); 142 | log_update_total_metrics_report_for_all_runnings(duration, timestamp); 143 | if (logFile.is_open()) { 144 | logFile.close(); 145 | } 146 | } 147 | static void increaseCoverage() { 148 | if (coverage < NUM_STAGES) { 149 | coverage++; 150 | } 151 | } 152 | private: 153 | static std::ofstream logFile; // File stream for the log file 154 | static int coverage; 155 | static long long duration; 156 | // Converts log level to a string for output 157 | static std::string levelToString(LogLevel level) 158 | { 159 | switch (level) { 160 | case DEBUG: 161 | return "DEBUG"; 162 | case INFO: 163 | return "INFO"; 164 | case WARNING: 165 | return "WARNING"; 166 | case ERROR: 167 | return "ERROR"; 168 | case CRITICAL: 169 | return "CRITICAL"; 170 | default: 171 | return "UNKNOWN"; 172 | } 173 | } 174 | }; 175 | 176 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Mixing.cpp: -------------------------------------------------------------------------------- 1 | #include "Mixing.h" 2 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Mixing.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include // For std::size_t 3 | #include "Field.h" 4 | template 5 | void mix_columns(const std::string& input_file, const std::string& output_file, std::size_t num_blocks) { 6 | std::ifstream in_stream(input_file, std::ios::binary); 7 | std::ofstream out_stream(output_file, std::ios::binary); 8 | 9 | if (!in_stream || !out_stream) { 10 | throw std::runtime_error("Error opening files."); 11 | } 12 | 13 | std::vector column_data(num_blocks); // Buffer for one column of data 14 | 15 | // Process columns 16 | for (std::size_t col = 0; col < code_length; ++col) { 17 | // Read the column data for all blocks 18 | for (std::size_t block_idx = 0; block_idx < num_blocks; ++block_idx) { 19 | in_stream.read(reinterpret_cast(&column_data[block_idx]), sizeof(wd_codec::galois::field_symbol)); 20 | if (!in_stream) { 21 | throw std::runtime_error("Error reading from input file."); 22 | } 23 | } 24 | 25 | // Write the column data to output file (after mixing logic, if any) 26 | for (std::size_t block_idx = 0; block_idx < num_blocks; ++block_idx) { 27 | out_stream.write(reinterpret_cast(&column_data[block_idx]), sizeof(wd_codec::galois::field_symbol)); 28 | if (!out_stream) { 29 | throw std::runtime_error("Error writing to output file."); 30 | } 31 | } 32 | } 33 | 34 | in_stream.close(); 35 | out_stream.close(); 36 | } 37 | 38 | 39 | template 40 | void unmix_columns(const std::string& input_file, const std::string& output_file, std::size_t num_blocks) { 41 | std::ifstream in_stream(input_file, std::ios::binary); 42 | std::ofstream out_stream(output_file, std::ios::binary); 43 | 44 | if (!in_stream || !out_stream) { 45 | throw std::runtime_error("Error opening files."); 46 | } 47 | 48 | std::vector column_data(num_blocks); // Buffer for one column of data 49 | 50 | // Process columns 51 | for (std::size_t col = 0; col < code_length; ++col) { 52 | // Read the column data for all blocks 53 | for (std::size_t block_idx = 0; block_idx < num_blocks; ++block_idx) { 54 | in_stream.read(reinterpret_cast(&column_data[block_idx]), sizeof(wd_codec::galois::field_symbol)); 55 | if (!in_stream) { 56 | throw std::runtime_error("Error reading from input file."); 57 | } 58 | } 59 | 60 | // Write the column data to output file (after unmixing logic, if any) 61 | for (std::size_t block_idx = 0; block_idx < num_blocks; ++block_idx) { 62 | out_stream.write(reinterpret_cast(&column_data[block_idx]), sizeof(wd_codec::galois::field_symbol)); 63 | if (!out_stream) { 64 | throw std::runtime_error("Error writing to output file."); 65 | } 66 | } 67 | } 68 | 69 | in_stream.close(); 70 | out_stream.close(); 71 | } 72 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Polynomial.cpp: -------------------------------------------------------------------------------- 1 | #include "Polynomial.h" 2 | #include "Logger.h" 3 | 4 | namespace wd_codec 5 | { 6 | 7 | namespace galois 8 | { 9 | 10 | // ctor & copy ctor 11 | Polynomial::Polynomial(const Field& gfield) 12 | : field_(const_cast(gfield)) 13 | { 14 | poly_.clear(); 15 | poly_.reserve(256);//set the capacity to 256 16 | } 17 | 18 | Polynomial::Polynomial(const Field& gfield, const unsigned int& degree) 19 | : field_(const_cast(gfield)) 20 | { 21 | poly_.reserve(256);//set the capacity to 256 22 | //resize the poly_ to degree+1 size, and peds the poly_ with Field_Element(field_, 0) 23 | poly_.resize(degree + 1, Field_Element(field_, 0)); 24 | } 25 | 26 | Polynomial::Polynomial(const Field& gfield, const unsigned int& degree, const Field_Element element[]) 27 | : field_(const_cast(gfield)) 28 | { 29 | poly_.reserve(256); 30 | 31 | if (element != NULL) 32 | { 33 | /* 34 | It is assumed that element is an array of field elements 35 | with size/element count of degree + 1. 36 | */ 37 | for (unsigned int i = 0; i <= degree; ++i) 38 | { 39 | poly_.push_back(element[i]); 40 | } 41 | } 42 | else 43 | poly_.resize(degree + 1, Field_Element(field_, 0)); 44 | } 45 | 46 | Polynomial::Polynomial(const Polynomial& polynomial) 47 | : field_(const_cast(polynomial.field_)), 48 | poly_(polynomial.poly_) 49 | {} 50 | 51 | Polynomial::Polynomial(const Field_Element& element) 52 | : field_(const_cast(element.galois_field())) 53 | { 54 | poly_.resize(1, element); 55 | } 56 | 57 | // Placing operators: 58 | Field_Element& Polynomial::operator[] (const std::size_t& term) { 59 | assert(term < poly_.size()); 60 | return poly_[term]; 61 | } 62 | 63 | const Field_Element& Polynomial::operator[](const std::size_t& term) const { 64 | assert(term < poly_.size()); 65 | return poly_[term]; 66 | } 67 | 68 | //function that return the placeing of value as X in the polynomial 69 | const Field_Element Polynomial::operator () (const Field_Element& value) const 70 | { 71 | //Note : not like schifras imlementation 72 | return (*this)(value.poly()); 73 | } 74 | 75 | //function that return the placeing of value as X in the polynomial 76 | Field_Element Polynomial::operator() (field_symbol value) 77 | { 78 | if (!poly_.empty()) 79 | { 80 | int i = 0; 81 | field_symbol total_sum = 0; 82 | //loop that go throught the poly_ vector 83 | for (const_poly_iter it = poly_.begin(); it != poly_.end(); ++it, ++i) 84 | { 85 | //total_sum =+ (value ^ i)* coeffitient[i] 86 | total_sum ^= field_.mul(field_.exp(value, i), (*it).poly()); 87 | } 88 | //total_sum = poly_[0] + poly_[1]*value + poly_[2]*value^2 + ... + poly_[i]*value^i 89 | return Field_Element(field_, total_sum); 90 | } 91 | return Field_Element(field_, 0); 92 | } 93 | 94 | //function that return the placeing of value as X in the polynomial 95 | Field_Element Polynomial::operator()(const Field_Element& value) { 96 | //Note : shorter than origin 97 | return (*this)(value.poly()); 98 | } 99 | 100 | //function that return the placeing of value as X in the polynomial 101 | const Field_Element Polynomial::operator()(field_symbol value) const { 102 | if (!poly_.empty()) 103 | { 104 | int i = 0; 105 | field_symbol total_sum = 0; 106 | //loop that go throught the poly_ vector 107 | for (const_poly_iter it = poly_.begin(); it != poly_.end(); ++it, ++i) 108 | { 109 | //total_sum =+ (value ^ i)* coeffitient[i] 110 | total_sum ^= field_.mul(field_.exp(value, i), (*it).poly()); 111 | } 112 | //total_sum = poly_[0] + poly_[1]*value + poly_[2]*value^2 + ... + poly_[i]*value^i 113 | return Field_Element(field_, total_sum); 114 | } 115 | return Field_Element(field_, 0); 116 | } 117 | 118 | // Capture assign operators: 119 | 120 | Polynomial& Polynomial::operator = (const Polynomial& polynomial) { 121 | if ((this != &polynomial) && (&field_ == &(polynomial.field_))) 122 | { 123 | poly_ = polynomial.poly_; 124 | } 125 | return (*this); 126 | } 127 | 128 | Polynomial& Polynomial::operator = (const Field_Element& element) { 129 | if (&field_ == &(element.galois_field())) 130 | { 131 | poly_.resize(1, element); 132 | } 133 | return *this; 134 | } 135 | 136 | Polynomial& Polynomial::operator += (const Polynomial& element) { 137 | const_poly_iter it1 = element.poly_.begin(); 138 | for (poly_iter it0 = poly_.begin(); it0 != poly_.end() && it1 != element.poly_.end(); ++it0, ++it1) { 139 | (*it0) += (*it1); 140 | } 141 | while (it1 != element.poly_.end()) { 142 | poly_.push_back(*it1); 143 | ++it1; 144 | } 145 | simplify(*this); 146 | 147 | return (*this); 148 | } 149 | 150 | Polynomial& Polynomial::operator += (const Field_Element& element) { 151 | poly_[0] += element; 152 | return *this; 153 | } 154 | 155 | Polynomial& Polynomial ::operator -= (const Polynomial& element) { 156 | return (*this += element); 157 | } 158 | 159 | Polynomial& Polynomial::operator -= (const Field_Element& element) { 160 | poly_[0] -= element; 161 | return *this; 162 | } 163 | 164 | Polynomial& Polynomial::operator ^= (const unsigned int& n) 165 | { 166 | Polynomial result = *this; 167 | 168 | for (std::size_t i = 0; i < n; ++i) 169 | { 170 | 171 | result *= *this; 172 | } 173 | 174 | *this = result; 175 | 176 | return *this; 177 | } 178 | 179 | 180 | Polynomial& Polynomial::operator %= (const Polynomial& divisor) { 181 | if ( 182 | (field_ == divisor.field_) && 183 | (deg() >= divisor.deg()) && 184 | (divisor.deg() >= 0) 185 | ) 186 | { 187 | Polynomial remainder(field_, divisor.deg() - 1); 188 | Polynomial quotient(field_, deg() - divisor.deg() + 1); 189 | long_division(divisor, remainder, quotient); 190 | /*std::cout << "\divisor\n: " << divisor; 191 | std::cout << "\nremainder: " << remainder; 192 | std::cout << "\nquotient\n: " << quotient;*/ 193 | poly_ = remainder.poly_; 194 | } 195 | 196 | return *this; 197 | } 198 | 199 | Polynomial& Polynomial::operator %= (const unsigned int& power) 200 | { 201 | if (poly_.size() >= power) 202 | { 203 | poly_.resize(power, Field_Element(field_, 0)); 204 | simplify(*this); 205 | 206 | } 207 | 208 | return *this; 209 | } 210 | 211 | // Function that multiply two polynomials 212 | Polynomial& Polynomial::operator *= (const Polynomial& polynomial) 213 | { 214 | if (&field_ == &(polynomial.field_)) 215 | { 216 | Polynomial product(field_, deg() + polynomial.deg() + 1); 217 | 218 | poly_iter result_it = product.poly_.begin(); 219 | 220 | for (poly_iter it0 = poly_.begin(); it0 != poly_.end(); ++it0) 221 | { 222 | poly_iter current_result_it = result_it; 223 | 224 | for (const_poly_iter it1 = polynomial.poly_.begin(); it1 != polynomial.poly_.end(); ++it1) 225 | { 226 | 227 | (*current_result_it) += (*it0) * (*it1); 228 | ++current_result_it; 229 | } 230 | 231 | ++result_it; 232 | } 233 | 234 | simplify(product); 235 | poly_ = product.poly_; 236 | } 237 | 238 | return *this; 239 | } 240 | 241 | 242 | 243 | // Function that multiply polynomial by a scalar 244 | Polynomial& Polynomial::operator *= (const Field_Element& element) { 245 | if (&field_ == &(element.galois_field())) { 246 | for (poly_iter it = this->poly_.begin(); it != this->poly_.end(); it++) { 247 | *(it) *= element; 248 | } 249 | } 250 | return *this; 251 | } 252 | 253 | Polynomial& Polynomial::operator /= (const Polynomial& divisor) { 254 | if ( 255 | (field_ == divisor.field_) && 256 | (deg() >= divisor.deg()) && 257 | (divisor.deg() >= 0) 258 | ) 259 | { 260 | Polynomial quotient(field_, deg() - divisor.deg() + 1); 261 | Polynomial remainder(field_, divisor.deg() - 1); 262 | long_division(divisor, remainder, quotient); 263 | poly_ = quotient.poly_; 264 | } 265 | 266 | return *this; 267 | } 268 | 269 | // Function that divide polynomial by a scalar 270 | Polynomial& Polynomial::operator/= (const Field_Element& element) { 271 | if (&field_ == &(element.galois_field())) { 272 | for (poly_iter it = this->poly_.begin(); it != this->poly_.end(); it++) { 273 | *(it) /= element; 274 | } 275 | } 276 | return *this; 277 | } 278 | 279 | 280 | Polynomial& Polynomial::operator <<= (const unsigned int& n) { 281 | //to shift right the polynomial n places, nX0 in begin 282 | size_t init_size = poly_.size(); 283 | if (init_size > 0) { 284 | poly_.resize(init_size + n, Field_Element(field_, 0)); 285 | for (size_t i = init_size - 1; static_cast(i) >= 0; --i)//move 286 | { 287 | poly_[i + n] = poly_[i]; 288 | } 289 | for (unsigned int i = 0; i < n; ++i)//fill 0 290 | { 291 | poly_[i] = 0; 292 | } 293 | } 294 | return *this; 295 | } 296 | 297 | Polynomial& Polynomial::operator >>= (const unsigned int& n) { 298 | // to shift left the polynomial n places, make it smaller size-n 299 | if (n <= poly_.size()) 300 | { 301 | for (unsigned int i = 0; i <= deg() - n; ++i) 302 | { 303 | poly_[i] = poly_[i + n]; 304 | } 305 | 306 | poly_.resize(poly_.size() - n, Field_Element(field_, 0)); 307 | } 308 | else if (static_cast(n) >= (deg() + 1)) 309 | { 310 | poly_.resize(0, Field_Element(field_, 0)); 311 | } 312 | 313 | return *this; 314 | } 315 | 316 | //compare operators: 317 | 318 | //function that check if two polynomials are equal 319 | bool Polynomial::operator==(const Polynomial& polynomial) const { 320 | if (field_ == polynomial.field_) 321 | { 322 | if (poly_.size() != polynomial.poly_.size()) 323 | return false; 324 | const_poly_iter it0 = poly_.begin(); 325 | const_poly_iter it1 = polynomial.poly_.begin(); 326 | while (it0 != poly_.end() && (*it0) == (*it1)) { 327 | it0++; 328 | it1++; 329 | } 330 | return (it0 == poly_.end()); 331 | } 332 | else 333 | return false; 334 | } 335 | 336 | bool Polynomial::operator!=(const Polynomial& polynomial) const { 337 | return !((*this) == polynomial); 338 | } 339 | 340 | //return polynomial that represent X 341 | Polynomial generate_X(const Field& gfield) {//create base polynomail 342 | const Field_Element xgfe[2] = { 343 | Field_Element(gfield, 0), 344 | Field_Element(gfield, 1) 345 | }; 346 | //X_ = 0*x^0 + 1*X^1 = x 347 | Polynomial X_(gfield, 1, xgfe);//todo fix this creation 348 | return X_; 349 | } 350 | 351 | 352 | // Function that deletes unnecessary trailing zeros. 353 | void Polynomial::simplify(Polynomial& polynomial) const { 354 | std::size_t poly_size = polynomial.poly_.size(); 355 | // If the last coefficient is not zero, the polynomial is in its simplified representation. 356 | if ((poly_size > 0) && (polynomial.poly_.back() == 0)) { 357 | 358 | poly_iter it = polynomial.poly_.end(); 359 | poly_iter begin = polynomial.poly_.begin(); 360 | int counter = 0; 361 | 362 | // Iterate and count all trailing zeros, as long as there are any. 363 | while ((begin != it) && (*(--it) == 0)) { 364 | counter++; 365 | } 366 | 367 | // Delete the trailing zeros. 368 | polynomial.poly_.resize(poly_size - counter, Field_Element(field_, 0)); 369 | } 370 | } 371 | 372 | // Function that check whether a plynomial is monic or not. 373 | bool Polynomial::monic() const { 374 | return poly_[poly_.size() - 1] == static_cast(1); 375 | } 376 | 377 | // Function that claculate the derivative of polynomials 378 | Polynomial Polynomial::derivative() const { 379 | /* In finite fields, the derivative of a polynomial is computed using modulo arithmetic. 380 | we multiply each coefficient by its exponent modulo the field's characteristic. 381 | In GF(2), this means each coefficient is multiplied by 0 or 1: 382 | f(x) = x ^ n 383 | f'(x) = (n%2) * x ^ (n-1) where n is 0/1*/ 384 | 385 | if (field_.size() > 1) { 386 | Polynomial deriv(field_, deg()); 387 | const std::size_t upper_bound = poly_.size() - 1; 388 | //i+=2 becuase poly_[i + 1] * 0 = 0. 389 | //poly_[i + 1] * 1 = poly_[i + 1]; 390 | for (std::size_t i = 0; i < upper_bound; i += 2) 391 | { 392 | deriv.poly_[i] = poly_[i + 1]; 393 | } 394 | 395 | simplify(deriv); 396 | return deriv; 397 | 398 | } 399 | 400 | return Polynomial(field_, 0); 401 | } 402 | 403 | // Function that implements polynomial division using the long division algorithm 404 | void Polynomial::long_division(const Polynomial& divisor, Polynomial& remainder, Polynomial& quotient) 405 | { 406 | if ( 407 | (field_ == divisor.field_) && 408 | (deg() >= divisor.deg()) && 409 | (divisor.deg() >= 0) 410 | ) 411 | { 412 | 413 | // Long division algorithm: 414 | for (int i = static_cast(deg()); i >= 0; i--) 415 | { 416 | // if the current degree matches or is within the range of the quotient polynomial 417 | if (i <= static_cast(quotient.deg())) 418 | { 419 | //q = p / d 420 | // calculate the coefficient for the current term in the quotient polynomial 421 | quotient[i] = remainder[remainder.deg()] / divisor[divisor.deg()]; 422 | 423 | // update the remainder by subtracting the product of the quotient term and divisor 424 | for (int j = static_cast(remainder.deg()); j > 0; --j) 425 | { 426 | // r = p - q * d 427 | remainder[j] = remainder[j - 1] + (quotient[i] * divisor[j]); 428 | } 429 | 430 | // adjust the lowest degree term of the remainder 431 | remainder[0] = poly_[i] + (quotient[i] * divisor[0]); 432 | } 433 | else 434 | { 435 | // shift the remainder polynomial down to align with the next term in the dividend 436 | for (int j = static_cast(remainder.deg()); j > 0; --j) 437 | { 438 | remainder[j] = remainder[j - 1]; 439 | } 440 | 441 | // set the leading term of the remainder to the current term of the dividend polynomial 442 | remainder[0] = poly_[i]; 443 | } 444 | } 445 | simplify(quotient); 446 | simplify(remainder); 447 | } 448 | } 449 | 450 | 451 | 452 | std::ostream& operator << (std::ostream& os, const Polynomial& polynomial) 453 | { 454 | if (polynomial.deg() >= 0) 455 | { 456 | 457 | for (unsigned int i = 0; i < polynomial.poly_.size(); ++i) 458 | { 459 | os << polynomial.poly_[i].poly() 460 | << " " 461 | << "x^" 462 | << i 463 | << ((static_cast(i) != (polynomial.deg())) ? " + " : ""); 464 | } 465 | } 466 | 467 | return os; 468 | } 469 | 470 | 471 | } 472 | } 473 | 474 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/Polynomial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Field_Element.h" 7 | 8 | 9 | namespace wd_codec 10 | { 11 | namespace galois 12 | { 13 | 14 | class Polynomial 15 | { 16 | 17 | public: 18 | Polynomial(const Field& gfield); 19 | Polynomial(const Field& gfield, const unsigned int& degree); 20 | Polynomial(const Field& gfield, const unsigned int& degree, const Field_Element element[]); 21 | Polynomial(const Polynomial& polynomial); 22 | Polynomial(const Field_Element& gfe); 23 | ~Polynomial() {} 24 | 25 | bool valid() const { 26 | return poly_.size() > 0; 27 | } 28 | 29 | inline int deg() const { 30 | return static_cast(poly_.size()) - 1; 31 | } 32 | 33 | const Field& galois_field() const { 34 | return field_; 35 | } 36 | 37 | 38 | void set_degree(const unsigned int& x) { 39 | poly_.resize(x - 1,Field_Element(field_,0)); 40 | } 41 | 42 | void simplify() { 43 | simplify(*this); 44 | } 45 | 46 | std::string convert_to_string() { 47 | std::string polyStr; 48 | if (deg() >= 0) { 49 | for (unsigned int i = 0; i < poly_.size(); ++i) { 50 | polyStr += std::to_string(poly_[i].poly()) // Convert the coefficient to a string 51 | + " x^" 52 | + std::to_string(i) // Convert the exponent to a string 53 | + ((static_cast(i) != deg()) ? " + " : ""); 54 | } 55 | } 56 | return polyStr; 57 | } 58 | 59 | 60 | Polynomial& operator = (const Polynomial& polynomial); 61 | Polynomial& operator = (const Field_Element& element); 62 | Polynomial& operator += (const Polynomial& element); 63 | Polynomial& operator += (const Field_Element& element); 64 | Polynomial& operator -= (const Polynomial& element); 65 | Polynomial& operator -= (const Field_Element& element); 66 | Polynomial& operator *= (const Polynomial& polynomial); 67 | Polynomial& operator *= (const Field_Element& element); 68 | Polynomial& operator /= (const Polynomial& divisor); 69 | Polynomial& operator /= (const Field_Element& element); 70 | Polynomial& operator %= (const Polynomial& divisor); 71 | Polynomial& operator %= (const unsigned int& power); 72 | Polynomial& operator ^= (const unsigned int& n); 73 | Polynomial& operator <<= (const unsigned int& n); 74 | Polynomial& operator >>= (const unsigned int& n); 75 | 76 | Field_Element& operator[] (const std::size_t& term); 77 | Field_Element operator() (const Field_Element& value); 78 | Field_Element operator() (field_symbol value); 79 | 80 | const Field_Element& operator[](const std::size_t& term) const; 81 | const Field_Element operator()(const Field_Element& value) const; 82 | const Field_Element operator()(field_symbol value) const; 83 | 84 | bool operator==(const Polynomial& polynomial) const; 85 | bool operator!=(const Polynomial& polynomial) const; 86 | 87 | bool monic() const; 88 | 89 | Polynomial derivative() const; 90 | 91 | void long_division(const Polynomial& divisor, Polynomial& remainder, Polynomial& quotient); 92 | 93 | friend std::ostream& operator << (std::ostream& os, const Polynomial& polynomial); 94 | 95 | private: 96 | 97 | typedef std::vector::iterator poly_iter; 98 | typedef std::vector::const_iterator const_poly_iter; 99 | 100 | void simplify(Polynomial& polynomial) const; 101 | 102 | Field& field_; 103 | std::vector poly_; 104 | 105 | }; 106 | 107 | ////non member functions: 108 | 109 | inline Polynomial operator + (const Polynomial& a, const Polynomial& b) { 110 | Polynomial result = a; 111 | result += b; 112 | return result; 113 | } 114 | inline Polynomial operator + (const Polynomial& a, const Field_Element& b) { 115 | Polynomial result = a; 116 | result += b; 117 | return result; 118 | } 119 | inline Polynomial operator + (const Field_Element& a, const Polynomial& b) { 120 | Polynomial result = b; 121 | result += a; 122 | return result; 123 | } 124 | inline Polynomial operator + (const Polynomial& a, const field_symbol& b) { 125 | return a + Field_Element(a.galois_field(), b); 126 | } 127 | inline Polynomial operator + (const field_symbol& a, const Polynomial& b) { 128 | return b + Field_Element(b.galois_field(), a); 129 | } 130 | inline Polynomial operator - (const Polynomial& a, const Polynomial& b) { 131 | Polynomial result = a; 132 | result -= b; 133 | return result; 134 | } 135 | inline Polynomial operator - (const Polynomial& a, const Field_Element& b) { 136 | Polynomial result = a; 137 | result -= b; 138 | return result; 139 | } 140 | inline Polynomial operator - (const Field_Element& a, const Polynomial& b) { 141 | Polynomial result = b; 142 | result -= a; 143 | return result; 144 | } 145 | inline Polynomial operator - (const Polynomial& a, const field_symbol& b) { 146 | return a - Field_Element(a.galois_field(), b); 147 | } 148 | inline Polynomial operator - (const field_symbol& a, const Polynomial& b) { 149 | return b - Field_Element(b.galois_field(), a); 150 | } 151 | inline Polynomial operator * (const Polynomial& a, const Polynomial& b) { 152 | Polynomial result = a; 153 | result *= b; 154 | return result; 155 | } 156 | inline Polynomial operator * (const Field_Element& a, const Polynomial& b) { 157 | Polynomial result = a; 158 | result *= b; 159 | return result; 160 | } 161 | inline Polynomial operator * (const Polynomial& a, const Field_Element& b) { 162 | Polynomial result = a; 163 | result *= b; 164 | return result; 165 | } 166 | 167 | inline Polynomial operator / (const Polynomial& a, const Polynomial& b) { 168 | Polynomial result = a; 169 | result /= b; 170 | return result; 171 | } 172 | 173 | inline Polynomial operator / (const Polynomial& a, const Field_Element& b) { 174 | Polynomial result = a; 175 | result /= b; 176 | return result; 177 | } 178 | 179 | inline Polynomial operator % (const Polynomial& a, const Polynomial& b) { 180 | Polynomial result = a; 181 | result %= b; 182 | return result; 183 | } 184 | 185 | inline Polynomial operator % (const Polynomial& a, const unsigned int& power) { 186 | Polynomial result = a; 187 | result %= power; 188 | return result; 189 | } 190 | 191 | inline Polynomial operator <<(const Polynomial& a, const unsigned int& n) { 192 | Polynomial result = a; 193 | result <<= n; 194 | return result; 195 | } 196 | 197 | inline Polynomial operator >>(const Polynomial& a, const unsigned int& n) { 198 | Polynomial result = a; 199 | result >>= n; 200 | return result; 201 | } 202 | 203 | inline Polynomial operator ^ (const Polynomial& a, const int& n) { 204 | Polynomial result = a; 205 | result ^= n; 206 | return result; 207 | } 208 | 209 | inline Polynomial gcd(const Polynomial& a, const Polynomial& b) 210 | {//calculates the greatest common divisor of two polynomials , ensuring both polynomials same Galois Field. 211 | if (&a.galois_field() == &b.galois_field()) 212 | { 213 | if ((!a.valid()) && (!b.valid()))//not same 214 | { 215 | Polynomial error_polynomial(a.galois_field()); 216 | return error_polynomial; 217 | } 218 | 219 | if (!a.valid()) return b; 220 | if (!b.valid()) return a; 221 | 222 | Polynomial x = a % b; 223 | Polynomial y = b; 224 | Polynomial z = x; 225 | 226 | while ((z = (y % x)).valid()) 227 | { 228 | y = x; 229 | x = z; 230 | } 231 | return x; 232 | } 233 | else 234 | { 235 | Polynomial error_polynomial(a.galois_field()); 236 | return error_polynomial; 237 | } 238 | } 239 | Polynomial generate_X(const Field& gfield); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/audio.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/audio.opus -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/binary_image_corrected.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/binary_image_corrected.bmp -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/binary_image_corrupted.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/binary_image_corrupted.bmp -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/binary_image_data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/binary_image_data.bin -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/binary_image_encoded.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/binary_image_encoded.bmp -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/decoder.cpp: -------------------------------------------------------------------------------- 1 | #include "decoder.h" 2 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/decoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Field.h" 7 | #include "Polynomial.h" 8 | #include "Logger.h" 9 | #include "Block.h" 10 | 11 | namespace wd_codec { 12 | 13 | namespace reed_solomon { 14 | template // n-data+redundancy ,redundancy length, k-data length 15 | 16 | class Decoder 17 | { 18 | 19 | public: 20 | typedef Block block_type; //n,k 21 | Decoder(const galois::Field& field, const unsigned int& gen_initial_index = 0): 22 | decoder_valid_(field.size() == code_length), 23 | field_(field), 24 | gen_initial_index_(gen_initial_index), 25 | X_(wd_codec::galois::generate_X(field_)) 26 | { 27 | wd_codec::Logger::increaseCoverage(); 28 | 29 | #ifdef _DEBUG 30 | Logger::log(wd_codec::INFO, "Decoder: generate decoder."); 31 | #endif // DEBUG 32 | if (decoder_valid_) { 33 | create_lookup_tables(); 34 | } 35 | else { 36 | 37 | wd_codec::Logger::log(wd_codec::CRITICAL, "Decode: Decoder not valid!"); 38 | } 39 | } 40 | 41 | //Function that try to detect and correct the errors 42 | bool decode(block_type& rsblock) const { 43 | Logger::log(wd_codec::INFO, "Decoder: decoding..."); 44 | //TODO: handle the erasure_list 45 | if (!decoder_valid_) { 46 | rsblock.errors_detected = 0; 47 | rsblock.errors_corrected = 0; 48 | rsblock.zero_numerators = 0; 49 | rsblock.unrecoverable = true; 50 | wd_codec::Logger::log(wd_codec::ERROR, "Decode: Decoder not valid!"); 51 | return false; 52 | } 53 | 54 | galois::Polynomial received(field_, code_length - 1); 55 | 56 | load_message(received, rsblock); 57 | galois::Polynomial syndrome(field_); 58 | 59 | //if the syndrom is zero - no error detected!! 60 | if (compute_syndrome(received, syndrome) == 0) { 61 | 62 | rsblock.errors_detected = 0; 63 | rsblock.errors_corrected = 0; 64 | rsblock.zero_numerators = 0; 65 | rsblock.unrecoverable = false; 66 | #ifdef _DEBUG 67 | Logger::log(wd_codec::INFO, "Decoder - decode succeed"); 68 | #endif // DEBUG 69 | out_in_syndrom = true; 70 | return true; 71 | } 72 | 73 | //lamda is the error locator polynomial 74 | galois::Polynomial lambda(galois::Field_Element(field_, 1)); 75 | //using the berlekamp_massey_algorithm to compute the error locator polynomial (lamda) 76 | berlekamp_massey_algorithm(lambda, syndrome); 77 | 78 | std::vector error_locations; 79 | //using the chien sreach to compute the error locations using the lamda polynomial 80 | chien_sreach(lambda, error_locations); 81 | 82 | if (0 == error_locations.size()) 83 | { 84 | /* 85 | Syndrome is non-zero yet and no error locations have 86 | been obtained, conclusion: 87 | It is possible that there are MORE errrors in the 88 | message than can be detected and corrected for this 89 | particular code. 90 | */ 91 | 92 | rsblock.errors_detected = 0; 93 | rsblock.errors_corrected = 0; 94 | rsblock.zero_numerators = 0; 95 | rsblock.unrecoverable = true; 96 | //rsblock.error = block_type::e_decoder_error1; 97 | wd_codec::Logger::log(wd_codec::ERROR, "Decode: Decode failed!"); 98 | return false; 99 | } 100 | else 101 | rsblock.errors_detected = error_locations.size(); 102 | if (lambda.deg() != static_cast(rsblock.errors_detected)) { 103 | rsblock.errors_corrected = 0; 104 | return false; 105 | } 106 | 107 | //correct the errors 108 | return forney_algorithm(error_locations, lambda, syndrome, rsblock); 109 | 110 | } 111 | 112 | //Function that compute the result of placing all the generate roots in the recieved poly. 113 | int compute_syndrome(const galois::Polynomial& received,galois::Polynomial& syndrome) const 114 | { 115 | #ifdef _DEBUG 116 | Logger::log(wd_codec::INFO, "Decoder: compute syndrome."); 117 | #endif // DEBUG 118 | 119 | int error_flag = 0; 120 | syndrome = galois::Polynomial(field_, fec_length - 1); 121 | for (std::size_t i = 0; i < fec_length; i++) 122 | { 123 | //syndrome[i] equal to the result of place root_i (syndrome_exponent_table_[i]) in the received data. 124 | syndrome[i] = received(syndrome_exponent_table_[i]); 125 | error_flag |= syndrome[i].poly(); 126 | } 127 | return error_flag; 128 | } 129 | 130 | // Function that Compute the magnitudes of the errors and the correct the data 131 | bool forney_algorithm(const std::vector& error_locations, const galois::Polynomial& lambda, 132 | const galois::Polynomial& syndrome, block_type& rsblock) const 133 | { 134 | #ifdef _DEBUG 135 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 136 | Logger::log(wd_codec::INFO, "Decoder - forney algorithm."); 137 | #endif // DEBUG 138 | 139 | 140 | /* the forney algorthim is a formula that find the correct data base on the lambda, syndrom and error_locations*/ 141 | galois::Polynomial omega = (lambda * syndrome) % fec_length; 142 | galois::Polynomial lambda_derivative = lambda.derivative(); 143 | #ifdef _DEBUG 144 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 145 | std::cout << "omega: " << omega<<"\n"; 146 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 147 | std::cout << "lambda_derivative: " << lambda_derivative << " \n"; 148 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" ; 149 | #endif // DEBUG 150 | rsblock.errors_corrected = 0; 151 | rsblock.zero_numerators = 0; 152 | // pass over all the error_locations in E(x). 153 | 154 | wd_codec::Logger::log(wd_codec::INFO, "Decode: correction errors"); 155 | 156 | for (const unsigned int error_location : error_locations) { 157 | // compute the polynomial expression alpha at the error location (alpha^E[i]) 158 | const galois::field_symbol alpha_inverse = field_.alpha(error_location); 159 | const galois::field_symbol numerator = (omega(alpha_inverse) * root_exponent_table_[error_location]).poly(); 160 | const galois::field_symbol denominator = lambda_derivative(alpha_inverse).poly(); 161 | if (numerator != 0) { 162 | if (denominator != 0) { 163 | #ifdef _DEBUG 164 | 165 | 166 | std::cout << "befor: " << char(rsblock[error_location - 1]) << " "; 167 | #endif // DEBUG 168 | 169 | rsblock[error_location - 1] ^= field_.div(numerator, denominator); 170 | #ifdef _DEBUG 171 | std::cout << "after: " << char(rsblock[error_location - 1]) << "\n"; 172 | #endif // DEBUG 173 | 174 | rsblock.errors_corrected++; 175 | } 176 | else { 177 | //if the denominator equal to 0, cannot evaluate 178 | wd_codec::Logger::log(wd_codec::ERROR, "Decode: correction errors failed!"); 179 | return false; 180 | } 181 | 182 | } 183 | else { 184 | rsblock.zero_numerators++; 185 | } 186 | } 187 | if (lambda.deg() == static_cast(rsblock.errors_detected)) 188 | return true; 189 | else 190 | { 191 | wd_codec::Logger::log(wd_codec::ERROR, "Decode: correction errors failed!"); 192 | return false; 193 | } 194 | } 195 | void create_lookup_tables() 196 | { 197 | //root Exponent : used in chien search , forney algo' to find error positionsby evaluating the error locator polynomial 198 | #ifdef _DEBUG 199 | wd_codec::Logger::log(wd_codec::INFO, "Decoder: create lookup tables "); 200 | #endif // DEBUG 201 | root_exponent_table_.reserve(field_.size() + 1); 202 | for (int i = 0; i < static_cast(field_.size() + 1); ++i) 203 | { 204 | root_exponent_table_.push_back(field_.exp(field_.alpha(code_length - i), (1 - gen_initial_index_))); 205 | } 206 | //Syndrome Exponent : used to compute syndromes for error detection. 207 | syndrome_exponent_table_.reserve(fec_length); 208 | for (int i = 0; i < static_cast(fec_length); ++i) 209 | { 210 | syndrome_exponent_table_.push_back(field_.alpha(gen_initial_index_ + i)); 211 | } 212 | //TODO:ERASSURE BUILT TABLE 213 | } 214 | 215 | void chien_sreach(const galois::Polynomial& lambda, std::vector& error_locations) const { 216 | // Locate the exact positions of the errors 217 | #ifdef _DEBUG 218 | wd_codec::Logger::log(wd_codec::INFO, "Decoder - cheain sreach"); 219 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 220 | #endif // DEBUG 221 | error_locations.reserve(fec_length << 1); 222 | error_locations.resize(0); 223 | const std::size_t lambda_degree = lambda.deg(); 224 | for (int i = 1; i <= static_cast(code_length); ++i) { 225 | if (0 == lambda(field_.alpha(i)).poly()) { 226 | error_locations.push_back(i); 227 | if (lambda_degree == error_locations.size()) { 228 | break; 229 | } 230 | } 231 | } 232 | } 233 | 234 | void compute_discrepancy(galois::Field_Element& discrepancy, 235 | const galois::Polynomial& lambda, 236 | const galois::Polynomial& syndrome, 237 | const std::size_t& l, 238 | const std::size_t& round) const 239 | { 240 | //#ifdef _DEBUG 241 | // wd_codec::Logger::log(wd_codec::INFO, "Decoder: compute discrepancy "); 242 | //#endif // DEBUG 243 | /* 244 | Compute the lambda discrepancy at the current round of BMA 245 | */ 246 | const std::size_t upper_bound = std::min(static_cast(l), lambda.deg()); 247 | discrepancy = 0; 248 | for (std::size_t i = 0; i <= upper_bound; ++i) 249 | { // c(j)*s(i-j) 250 | discrepancy += lambda[i] * syndrome[round - i]; 251 | } 252 | } 253 | 254 | void berlekamp_massey_algorithm(galois::Polynomial& lambda, 255 | const galois::Polynomial& syndrome) const 256 | { 257 | #ifdef _DEBUG 258 | Logger::log(wd_codec::INFO, "Decoder: berlekamp massey algo'."); 259 | #endif // DEBUG 260 | //f - last faild 261 | int i = -1; 262 | //|c| - coeffictiont number 263 | std::size_t l = 0; 264 | //d - the c correcting 265 | galois::Field_Element discrepancy(field_, 0); 266 | //b 267 | galois::Polynomial previous_lambda = lambda << 1; 268 | #ifdef _DEBUG 269 | Logger::log(wd_codec::INFO, "Decoder: compute discrepancy n times."); 270 | #endif // DEBUG 271 | for (std::size_t round = 0; round < fec_length; ++round) 272 | { 273 | //checking if the current d is good - discrepancy = 0 274 | compute_discrepancy(discrepancy, lambda, syndrome, l, round); 275 | if (discrepancy != 0) 276 | { 277 | //computing c+d 278 | galois::Polynomial tau = lambda - (discrepancy * previous_lambda); 279 | 280 | if (static_cast(l) < (static_cast(round) - i)) 281 | { 282 | const std::size_t tmp = round - i; 283 | i = static_cast(round - l); 284 | l = tmp; 285 | //d = (old c sequence)/discrepancy count 286 | previous_lambda = lambda / discrepancy; 287 | } 288 | lambda = tau; 289 | 290 | } 291 | 292 | previous_lambda <<= 1; 293 | } 294 | #ifdef _DEBUG 295 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 296 | std::cout << "lambda: " << lambda << std::endl; 297 | std::cout << "-----------------------------------------------------------------------------------------------------------------------" << std::endl; 298 | #endif // DEBUG 299 | 300 | 301 | } 302 | mutable bool out_in_syndrom = false; 303 | 304 | 305 | protected: 306 | void load_message(galois::Polynomial& received, const block_type& rsblock) const 307 | { 308 | #ifdef _DEBUG 309 | 310 | Logger::log(wd_codec::INFO, "Decoder: load message."); 311 | #endif // DEBUG 312 | //Load message data into received polynomial in reverse order. 313 | for (std::size_t i = 0; i < code_length; ++i) 314 | { 315 | received[code_length - 1 - i] = rsblock[i]; 316 | } 317 | } 318 | bool decoder_valid_; //if decoder is properly initialized 319 | const galois::Field& field_; // used in decoding 320 | std::vector root_exponent_table_; // Stores root exponents for error correction 321 | std::vector syndrome_exponent_table_;// Holds syndrome exponents for error detection 322 | const galois::Polynomial X_; // for error correction calculations in the Error locations 323 | const unsigned int gen_initial_index_; //index for generator polynomial 324 | //std::vector gamma_table_; // Contains gamma polynomials for error correction-ERASURES 325 | 326 | 327 | }; 328 | 329 | 330 | } 331 | } 332 | 333 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/output.rsenc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/output.rsenc -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/picture.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/picture.bmp -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/picture_too_big.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Encoder-Decoder-System/picture_too_big.bmp -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/report.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace wd_codec { 10 | static std::size_t global_errors_detected = 0; 11 | static std::size_t global_errors_corrected = 0; 12 | static std::size_t num_uncorrected_blocks = 0; 13 | static std::size_t num_blocks = 0; 14 | static std::string errors_block_locations = " "; 15 | 16 | // Function that update the matrics in summary_log file, with the current matrics 17 | inline static void log_update_total_metrics_report_for_all_runnings(long long duration, const char* timestamp) { 18 | 19 | std::ifstream inputFile("summary_log.txt"); 20 | int totalExecutions = 0; 21 | double totalRuntime = 0; 22 | int totalErrorsCorrected = 0; 23 | int totalErrorsDetected = 0; 24 | double averageRuntime = 0; 25 | double totalSuccessRate = 0; 26 | 27 | // Read the existing log file if it exists 28 | if (inputFile.is_open()) { 29 | std::string line; 30 | while (std::getline(inputFile, line)) { 31 | std::istringstream iss(line); 32 | std::string label; 33 | if (line.find("Total Executions") != std::string::npos) { 34 | iss >> label >> label >> totalExecutions; 35 | } 36 | else if (line.find("Total Runtime") != std::string::npos) { 37 | iss >> label >> label >> label >> totalRuntime; 38 | } 39 | else if (line.find("Total Errors Detected") != std::string::npos) { 40 | iss >> label >> label >> label >> totalErrorsDetected; 41 | } 42 | else if (line.find("Total Errors Corrected") != std::string::npos) { 43 | iss >> label >> label >> label >> totalErrorsCorrected; 44 | } 45 | } 46 | inputFile.close(); 47 | } 48 | 49 | // Update values 50 | totalExecutions++; 51 | totalRuntime += duration; 52 | totalErrorsDetected += global_errors_detected; 53 | totalErrorsCorrected += global_errors_corrected; 54 | totalSuccessRate = (totalErrorsCorrected / (double)totalErrorsDetected) * 100; 55 | averageRuntime = totalRuntime / totalExecutions; 56 | 57 | // Write the updated data back to the file 58 | std::ofstream outputFile("summary_log.txt"); 59 | outputFile << "Total Executions: " << totalExecutions << "\n"; 60 | outputFile << "Total Runtime (milliseconds): " << totalRuntime << "\n"; 61 | outputFile << "Total Errors Detected: " << totalErrorsDetected << "\n"; 62 | outputFile << "Total Errors Corrected: " << totalErrorsCorrected << "\n"; 63 | outputFile << "Total Success rate: " << totalSuccessRate << "%\n"; 64 | outputFile << "Average Runtime (milliseconds): " << averageRuntime << "\n"; 65 | outputFile << "Last Run: " << timestamp << "\n"; 66 | outputFile.close(); 67 | } 68 | 69 | 70 | // Creates a timestamp string in the format "YYYY-MM-DD HH:MM:SS" 71 | inline static void create_timestamp(char* timestamp) { 72 | // Get current timestamp 73 | time_t now = time(0); 74 | tm timeinfo; 75 | 76 | // Use localtime_s or localtime_r based on the platform 77 | #ifdef _WIN32 78 | localtime_s(&timeinfo, &now); 79 | #else 80 | localtime_r(&now, &timeinfo); 81 | #endif 82 | 83 | // Format the timestamp 84 | strftime(timestamp, 20, "%Y-%m-%d %H:%M:%S", &timeinfo); 85 | } 86 | 87 | 88 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Encoder-Decoder-System/setup_utilities.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "Logger.h"; 5 | #include "Field.h"; 6 | #include "Polynomial.h" 7 | #include "Encoder.h"; 8 | #include "Generator_polynomial.h" 9 | #include "Fileio.h" 10 | #include "File_Encoder.h" 11 | #include "Error_Injection.h" 12 | #include "Decoder.h" 13 | #include "File_Decoder.h" 14 | 15 | namespace wd_codec { 16 | 17 | /* Finite Field Parameters */ 18 | const std::size_t field_descriptor = 8; 19 | const std::size_t generator_polynomial_index = 120; 20 | const std::size_t generator_polynomial_root_count = 32; 21 | 22 | /* Reed Solomon Code Parameters */ 23 | const std::size_t code_length = 255; 24 | const std::size_t fec_length = 32; 25 | const std::size_t data_length = code_length - fec_length; 26 | 27 | const std::size_t stack_size = 255; 28 | 29 | /* Instantiate Finite Field and Generator Polynomials */ 30 | 31 | const wd_codec::galois::Field field(field_descriptor, 32 | wd_codec::galois::primitive_polynomial_size06, 33 | wd_codec::galois::primitive_polynomial06); 34 | 35 | static wd_codec::galois::Polynomial generator_polynomial(field); 36 | /* Instantiate RS Block For Codec */ 37 | static wd_codec::reed_solomon::Block block; 38 | 39 | /* Instantiate Encoder and Decoder */ 40 | typedef wd_codec::reed_solomon::Encoder Encoder; 41 | typedef wd_codec::reed_solomon::Decoder Decoder; 42 | 43 | typedef wd_codec::reed_solomon::File_Encoder file_encoder_t; 44 | typedef wd_codec::reed_solomon::File_Decoder file_decoder_t; 45 | 46 | static inline void close() { 47 | wd_codec::Logger::close(); 48 | } 49 | 50 | static inline void setup() { 51 | wd_codec::Logger::increaseCoverage(); 52 | wd_codec::Logger::log(wd_codec::INFO, "init system"); 53 | Logger::init(); 54 | //Generate G(X) 55 | if (!wd_codec::create_root_generator_polynomial(field, 56 | generator_polynomial_index, 57 | generator_polynomial_root_count, 58 | generator_polynomial)) {//todo:deledte if 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/E2E_Tests.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "gtest/gtest.h" 3 | #include 4 | #include "Test_Utility.h" 5 | //#include "pch.h" 6 | //Test case for handling an empty file 7 | TEST(EncoderDecoderTests, HandleEmptyFile) { 8 | wd_codec::test_mode_empty_file = true; 9 | const std::string empty_file_name = "empty_input.dat"; 10 | const std::string rsencoded_output_file_name = "empty_encode_output.txt"; 11 | const std::string rsdecoded_file_name = "empty_decode_output.txt"; 12 | 13 | // Create an empty file 14 | createEmptyFile(empty_file_name); 15 | wd_codec::setup(); 16 | // Attempt to perform encoding and decoding on the empty file 17 | bool encode_success = false; 18 | bool decode_success = false; 19 | 20 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 21 | const wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 22 | 23 | wd_codec::file_encoder_t file_encoder(encoder); 24 | wd_codec::file_decoder_t file_decoder(decoder); 25 | 26 | // Check if the encoded file is empty 27 | std::ifstream encoded_file(rsencoded_output_file_name, std::ios::binary); 28 | encode_success = file_encoder.encode(empty_file_name, rsencoded_output_file_name) && 29 | !(encoded_file.peek() == std::ifstream::traits_type::eof()); 30 | 31 | // Check if the decoded file is empty 32 | std::ifstream decoded_file(rsdecoded_file_name, std::ios::binary); 33 | decode_success = file_decoder.decode(empty_file_name, rsencoded_output_file_name) && 34 | !(decoded_file.peek() == std::ifstream::traits_type::eof()); 35 | 36 | // Check if the encode/decode process correctly handled the empty file 37 | EXPECT_FALSE(encode_success) << "Encoding should fail or handle an empty input file correctly."; 38 | EXPECT_FALSE(decode_success) << "Decoding should handle an empty file appropriately."; 39 | // Close the logger 40 | wd_codec::Logger::close(); 41 | } 42 | 43 | 44 | 45 | // Test full end to end 46 | TEST(EncoderDecoderTests, FullEncodeDecodeCycle) { 47 | wd_codec::setup(); 48 | 49 | const std::string input_file_name = "input.dat"; 50 | const std::string rsencoded_output_file_name = "output_encode.txt"; 51 | const std::string rsdecoded_file_name = "output_decode.txt"; 52 | // Create a valid input file 53 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * wd_codec::stack_size - 3); 54 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 55 | const wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 56 | 57 | // Perform encoding 58 | wd_codec::file_encoder_t file_encoder(encoder); 59 | wd_codec::file_decoder_t file_decoder(decoder); 60 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 61 | std::cout << "Encoding failed." << std::endl; 62 | return; 63 | } 64 | wd_codec::error_injection::inject_random_errors(rsencoded_output_file_name); 65 | if (!file_decoder.decode(rsencoded_output_file_name, rsdecoded_file_name)) { 66 | std::cout << "Decoding failed." << std::endl; 67 | return; 68 | } 69 | // Compare the decoded file with the original input file 70 | EXPECT_TRUE(compare_files(input_file_name, rsdecoded_file_name)) << "Decoded output does not match the original input."; 71 | // Close the logger 72 | wd_codec::Logger::close(); 73 | } 74 | 75 | // Test the encoder with data larger than k 76 | TEST(EncoderDecoderTests, BiggerThanK) { 77 | wd_codec::setup(); 78 | const std::string input_file_name = "input.dat"; 79 | const std::string rsencoded_output_file_name = "output_encode.txt"; 80 | const std::string rsdecoded_file_name = "output_decode.txt"; 81 | // Create a valid input file bigger than k 82 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * wd_codec::stack_size - 3); 83 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 84 | 85 | wd_codec::file_encoder_t file_encoder(encoder); 86 | 87 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 88 | std::cout << "Encoding failed." << std::endl; 89 | return; 90 | } 91 | // Compare the decoded file with the original input file 92 | std::size_t expected_block_count = wd_codec::fileio::file_size(input_file_name) / wd_codec::data_length; 93 | EXPECT_EQ(expected_block_count, file_encoder.get_blocks_number()) << "expected block count is different than the actual blocks number."; 94 | } 95 | 96 | // Test UnCorruptedEncodeDecodeCycle 97 | TEST(EncoderDecoderTests, UnCorruptedEncodeDecodeCycle){ 98 | 99 | wd_codec::setup(); 100 | const std::string input_file_name = "input.dat"; 101 | const std::string rsencoded_output_file_name = "output_encode.txt"; 102 | const std::string rsdecoded_file_name = "output_decode.txt"; 103 | 104 | // Create a valid input file 105 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * wd_codec::stack_size - 3); 106 | wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 107 | wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 108 | 109 | wd_codec::file_encoder_t file_encoder(encoder); 110 | wd_codec::file_decoder_t file_decoder(decoder); 111 | 112 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 113 | std::cout << "Encoding failed." << std::endl; 114 | return; 115 | } 116 | 117 | bool decode_success = file_decoder.decode(rsencoded_output_file_name, rsdecoded_file_name); 118 | 119 | // Check if the decoding was successful 120 | EXPECT_TRUE(decode_success) << "Decoding failed or syndrome is non-zero."; 121 | EXPECT_TRUE(decoder.out_in_syndrom) << "Syndrome check in decode process was not triggered as expected."; 122 | // Close the logger 123 | wd_codec::Logger::close(); 124 | } 125 | 126 | 127 | 128 | // Test too many random errors to be handled - expected false 129 | TEST(EncoderDecoderTests, HandleTooManyErrors) { 130 | wd_codec::setup(); 131 | 132 | const std::string input_file_name = "input.dat"; 133 | const std::string rsencoded_output_file_name = "output_encode.txt"; 134 | const std::string rsdecoded_file_name = "output_decode.txt"; 135 | 136 | // Create a valid input file 137 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * wd_codec::stack_size - 3); 138 | wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 139 | wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 140 | 141 | // Perform encoding 142 | wd_codec::file_encoder_t file_encoder(encoder); 143 | wd_codec::file_decoder_t file_decoder(decoder); 144 | 145 | // Introduce more errors than the code can correct 146 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 147 | std::cout << "Encoding failed." << std::endl; 148 | return; 149 | } 150 | wd_codec::error_injection::inject_random_errors(rsencoded_output_file_name,50); 151 | bool decode_success = file_decoder.decode(rsencoded_output_file_name, rsdecoded_file_name); 152 | 153 | // Compare the decoded file with the original input file 154 | EXPECT_FALSE(decode_success) << "Decoder was expected to fail with too many errors."; 155 | 156 | // Close the logger 157 | wd_codec::Logger::close(); 158 | 159 | } 160 | 161 | // TODO: Test too many burst errors - expected true 162 | 163 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/Sample-Test1.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Testing 22 | Win32 23 | 24 | 25 | Testing 26 | x64 27 | 28 | 29 | Test_Mode 30 | Win32 31 | 32 | 33 | Test_Mode 34 | x64 35 | 36 | 37 | Test 38 | Win32 39 | 40 | 41 | Test 42 | x64 43 | 44 | 45 | 46 | {ea94a37c-ccdb-412d-a1aa-cd16a9e0d57f} 47 | Win32Proj 48 | 10.0.22621.0 49 | Application 50 | v143 51 | Unicode 52 | Encoder-Decoder-Tests 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | false 62 | 63 | 64 | false 65 | 66 | 67 | false 68 | 69 | 70 | false 71 | 72 | 73 | 74 | 75 | Use 76 | pch.h 77 | Disabled 78 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | EnableFastChecks 80 | MultiThreadedDebugDLL 81 | Level3 82 | 83 | 84 | true 85 | Console 86 | 87 | 88 | 89 | 90 | Use 91 | pch.h 92 | Disabled 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | EnableFastChecks 95 | MultiThreadedDebugDLL 96 | Level3 97 | 98 | 99 | true 100 | Console 101 | 102 | 103 | 104 | 105 | NotUsing 106 | pch.h 107 | Disabled 108 | X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | EnableFastChecks 110 | MultiThreadedDebugDLL 111 | Level3 112 | D:\users\user1\Desktop\kamatech\ב\Encoder-Decoder-System\Encoder-Decoder-System;%(AdditionalIncludeDirectories) 113 | 114 | 115 | true 116 | Console 117 | Comctl32.lib;%(AdditionalDependencies) 118 | 119 | 120 | 121 | 122 | NotUsing 123 | pch.h 124 | Disabled 125 | X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | EnableFastChecks 127 | MultiThreadedDebugDLL 128 | Level3 129 | C:\Users\user1\source\repos\Encode-Decode-Project3\Encoder-Decoder-System\Encoder-Decoder-System 130 | 131 | 132 | true 133 | Console 134 | Comctl32.lib;%(AdditionalDependencies) 135 | 136 | 137 | 138 | 139 | Use 140 | pch.h 141 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | MultiThreadedDLL 143 | Level3 144 | ProgramDatabase 145 | 146 | 147 | true 148 | Console 149 | true 150 | true 151 | 152 | 153 | 154 | 155 | Use 156 | pch.h 157 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 158 | MultiThreadedDLL 159 | Level3 160 | ProgramDatabase 161 | 162 | 163 | true 164 | Console 165 | true 166 | true 167 | 168 | 169 | 170 | 171 | NotUsing 172 | pch.h 173 | X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 174 | MultiThreadedDLL 175 | Level3 176 | ProgramDatabase 177 | C:\Users\user1\source\repos\Encode-Decode-Project3\Encoder-Decoder-System\Encoder-Decoder-System;%(AdditionalIncludeDirectories) 178 | 179 | 180 | true 181 | Console 182 | true 183 | true 184 | 185 | 186 | 187 | 188 | NotUsing 189 | pch.h 190 | X64;NDEBUG;_CONSOLE;TEST%(PreprocessorDefinitions) 191 | MultiThreadedDLL 192 | Level3 193 | EditAndContinue 194 | C:\Users\user1\source\repos\Encode-Decode-Project3\Encoder-Decoder-System\Encoder-Decoder-System\x64 195 | 196 | 197 | true 198 | Console 199 | true 200 | true 201 | UseLinkTimeCodeGeneration 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 244 | 245 | 246 | 247 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/Test_Utility.cpp: -------------------------------------------------------------------------------- 1 | // Helper function to create an empty file 2 | void createEmptyFile(const std::string& file_name) { 3 | std::ofstream file(file_name, std::ios::out | std::ios::binary); 4 | // The file is created empty 5 | } 6 | // 7 | //// Setup and teardown functions for logging 8 | void setupTestEnvironment() { 9 | wd_codec::Logger::init(); 10 | } 11 | 12 | void teardownTestEnvironment() { 13 | wd_codec::Logger::close(); 14 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/Test_Utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Encoder-Decoder-System/setup_utilities.h" 3 | 4 | // Helper function to create an empty file 5 | static inline void createEmptyFile(const std::string& file_name) { 6 | std::ofstream file(file_name, std::ios::out | std::ios::binary); 7 | // The file is created empty 8 | } 9 | 10 | // Setup and teardown functions for logging 11 | static inline void setupTestEnvironment() { 12 | wd_codec::Logger::init(); 13 | } 14 | 15 | // Helper function to compare files 16 | static inline bool compare_files(const std::string& file1, const std::string& file2) { 17 | std::ifstream f1(file1, std::ios::binary | std::ios::ate); 18 | std::ifstream f2(file2, std::ios::binary | std::ios::ate); 19 | 20 | if (!f1.good() || !f2.good()) return false; 21 | 22 | auto size1 = f1.tellg(); 23 | auto size2 = f2.tellg(); 24 | 25 | if (size1 != size2) return false; 26 | 27 | f1.seekg(0, std::ios::beg); 28 | f2.seekg(0, std::ios::beg); 29 | 30 | std::vector buffer1(size1); 31 | std::vector buffer2(size2); 32 | 33 | f1.read(buffer1.data(), size1); 34 | f2.read(buffer2.data(), size2); 35 | 36 | return std::equal(buffer1.begin(), buffer1.end(), buffer2.begin()); 37 | } -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/Unit_Test.cpp: -------------------------------------------------------------------------------- 1 | //#include "pch.h" 2 | #pragma once 3 | #include "gtest/gtest.h" 4 | #include "Test_Utility.h" 5 | 6 | #include "../Encoder-Decoder-System/setup_utilities.h" 7 | 8 | 9 | 10 | // Test if file size is Non Divisible By K is handled. 11 | const std::string rsencoded_output_file_name_with_residue = "output_encode.txt"; 12 | TEST(EncoderDecoderTests, NonDivisibleInputByK) { 13 | wd_codec::setup(); 14 | const std::string input_file_name = "input.dat"; 15 | // Create a valid input file bigger than k 16 | wd_codec::fileio::create_file(input_file_name, wd_codec::data_length * (wd_codec::stack_size - 1) + 200); 17 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 18 | 19 | // Perform encoding 20 | wd_codec::file_encoder_t file_encoder(encoder); 21 | 22 | file_encoder.encode(input_file_name, rsencoded_output_file_name_with_residue); 23 | 24 | bool is_residue_handled = file_encoder.get_is_residue_handled(); 25 | EXPECT_TRUE(is_residue_handled) << "Encode does not handle the last smaller than k block."; 26 | 27 | // Close the logger 28 | wd_codec::Logger::close(); 29 | } 30 | 31 | // Test if encoded file size is Non Divisible By n is handled. 32 | TEST(EncoderDecoderTests, NonDivisibleInputByN) { 33 | wd_codec::setup(); 34 | const std::string rsdecoded_file_name = "output_decode.txt"; 35 | const wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 36 | 37 | // Perform encoding 38 | wd_codec::file_decoder_t file_decoder(decoder); 39 | 40 | file_decoder.decode(rsencoded_output_file_name_with_residue, rsdecoded_file_name); 41 | 42 | bool is_residue_handled = file_decoder.get_is_residue_handled(); 43 | EXPECT_TRUE(is_residue_handled) << "Decode does not handle the last smaller than n block."; 44 | 45 | 46 | // Close the logger 47 | wd_codec::Logger::close(); 48 | } 49 | 50 | TEST(EncoderDecoderTests, CreatePolynomial) { 51 | wd_codec::Logger::increaseCoverage(); 52 | wd_codec::Logger::log(wd_codec::INFO, "init system"); 53 | wd_codec::Logger::init(); 54 | bool success = wd_codec::create_root_generator_polynomial(wd_codec::field, wd_codec::generator_polynomial_index, wd_codec::generator_polynomial_root_count, wd_codec::generator_polynomial); 55 | EXPECT_TRUE(success); 56 | } 57 | 58 | 59 | // Test if polynomial multiplicationin base on nGaloisField indeed works. 60 | TEST(EncoderDecoderTests, PolynomialMultiplicationinGaloisField) { 61 | // P(x) = x^2 + x + 1 62 | wd_codec::galois::Field_Element P_elements[] = { 63 | wd_codec::galois::Field_Element(wd_codec::field, 1), 64 | wd_codec::galois::Field_Element(wd_codec::field, 1), 65 | wd_codec::galois::Field_Element(wd_codec::field, 1) 66 | }; 67 | 68 | // Q(x) = 2x + 2 69 | wd_codec::galois::Field_Element Q_elements[] = { 70 | wd_codec::galois::Field_Element(wd_codec::field, 2), 71 | wd_codec::galois::Field_Element(wd_codec::field, 2) 72 | }; 73 | 74 | // R(x) = 2x^3 + 4x^2 + 3x + 2 75 | wd_codec::galois::Field_Element expected_coeffs[] = { 76 | wd_codec::galois::Field_Element(wd_codec::field, 2), 77 | wd_codec::galois::Field_Element(wd_codec::field, 0), 78 | wd_codec::galois::Field_Element(wd_codec::field, 0), 79 | wd_codec::galois::Field_Element(wd_codec::field, 2) 80 | }; 81 | 82 | wd_codec::galois::Polynomial P(wd_codec::field, 2 ,P_elements); 83 | wd_codec::galois::Polynomial Q(wd_codec::field, 1 , Q_elements); 84 | wd_codec::galois::Polynomial expected_result(wd_codec::field, 3, expected_coeffs); 85 | wd_codec::galois::Polynomial result(wd_codec::field); 86 | 87 | result = P * Q; 88 | EXPECT_EQ(result, expected_result); 89 | 90 | P *= Q; 91 | EXPECT_EQ(P, result); 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/Unit_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "setup_utilities.h" 3 | 4 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/binary_image_data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Sample-Test1/binary_image_data.bin -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/empty_input.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WDcodec/Encode-Decode-Project/ed4226e86b391a0ae477556bb7eaae71d6dd94b0/Encoder-Decoder-System/Sample-Test1/empty_input.dat -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/pch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // pch.cpp 3 | // 4 | 5 | #include "pch.h" 6 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/pch.h: -------------------------------------------------------------------------------- 1 | // 2 | // pch.h 3 | // 4 | 5 | #pragma once 6 | 7 | #include "gtest/gtest.h" 8 | -------------------------------------------------------------------------------- /Encoder-Decoder-System/Sample-Test1/test_logfile.txt: -------------------------------------------------------------------------------- 1 | [2024-09-05 10:57:57] INFO: Start generate field. 2 | [2024-09-05 10:57:57] INFO: Decoder - generate decoder. 3 | [2024-09-05 10:57:57] INFO: Decoder - create lookup tables 4 | [2024-09-05 10:57:57] ERROR: file_encoder() - Error: input file has ZERO size.. 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Encoder Decoder System 2 | The wd_codec library is an Encoder-Decoder System for protecting and recovering data using Reed-Solomon error correction. 3 | 4 | ## Installation 5 | 6 | Open the cmd in your local folder to install the code 7 | 8 | ```bash 9 | git clone https://github.com/WDcodec/Encode-Decode-Project.git 10 | ``` 11 | 12 | ## Usage 13 | The parameters of both the Reed-Solomon algorithm and the finite field definition can be manually adjusted in setup_utilities.h, where they are currently set to the CCSDS standard by default. 14 | 15 | so, Each usage must have these declarations: 16 | ```main 17 | #include "setup_utilities.h" 18 | int main() 19 | { 20 | wd_codec::setup(); 21 | 22 | const wd_codec::Encoder encoder(wd_codec::field, wd_codec::generator_polynomial); 23 | const wd_codec::Decoder decoder(wd_codec::field, wd_codec::generator_polynomial_index); 24 | 25 | wd_codec::file_encoder_t file_encoder(encoder); 26 | wd_codec::file_decoder_t file_decoder(decoder); 27 | 28 | ``` 29 | Choosing type of input: 30 | 31 | ### Primitive Input 32 | ``` 33 | std::string message ; 34 | std::cin >> message ; 35 | message.resize(wd_codec::code_length, 0x00); 36 | if (!encoder.encode(wd_codec::block, message)){ 37 | return 1; 38 | } 39 | if (!decoder.decode(wd_codec::block)) { 40 | return 1; 41 | } 42 | ``` 43 | ### File 44 | ``` 45 | const std::string input_file_name = "input.dat";//your file 46 | const std::string rsencoded_output_file_name = "output.rsenc"; 47 | const std::string rsdecoded_file_name = "output.rsdec"; 48 | 49 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 50 | return 1; 51 | } 52 | 53 | //inject random errors 54 | wd_codec::error_injection::inject_random_errors(rsencoded_output_file_name); 55 | 56 | if (!file_decoder.decode(rsencoded_output_file_name, rsdecoded_file_name)) { 57 | wd_codec::Logger::log(wd_codec::INFO, "File Decoder: Decoder failed " ); 58 | wd_codec::close(); 59 | return 1; 60 | } 61 | 62 | //number of blocks 63 | std::cout << "num blocks " << file_decoder.getCurrentBlockIndex(); 64 | 65 | ``` 66 | 67 | ### Photo: BMP Format 68 | [convert photo from other format:](https://convertfree.com/he/converter/audio/opus) 69 | ``` 70 | const std::string input_file_name = "picture.bmp";//your photo path 71 | const std::string rsencoded_output_file_name = "output.rsenc"; 72 | const std::string rsdecoded_file_name = "output.rsdec"; 73 | const std::string binaryFilePath = "binary_image_data.bin"; 74 | 75 | wd_codec::fileio::convert_image_to_binary(input_file_name, binaryFilePath); 76 | 77 | if (!file_encoder.encode_image(input_file_name, rsencoded_output_file_name)) { 78 | std::cout << "Encoding failed." << std::endl; 79 | wd_codec::close(); 80 | return 1; 81 | } 82 | //inject random errors 83 | wd_codec::error_injection::inject_random_errors_for_image(rsencoded_output_file_name, "binary_image_encoded.bmp"); 84 | 85 | if (!file_decoder.decode_image(rsencoded_output_file_name, rsdecoded_file_name)) { 86 | return 1; 87 | } 88 | ``` 89 | ### Audio: OPUS Format 90 | 91 | [convert audio from other format :](https://he.onlineconvert.com/mp4-to-opus) 92 | 93 | ``` 94 | const std::string input_file_name = "audio.opus";//your audio path 95 | const std::string rsencoded_output_file_name = "output.rsenc"; 96 | const std::string rsdecoded_file_name = "output.rsdec"; 97 | const std::string binaryFilePath = "binary_audio_data.bin"; 98 | 99 | wd_codec::fileio::converAudioToBinary(input_file_name, binaryFilePath); 100 | 101 | if (!file_encoder.encode_audio(input_file_name, rsencoded_output_file_name)) { 102 | return 1; 103 | } 104 | //inject random errors 105 | wd_codec::error_injection::inject_random_errors_for_audio(rsencoded_output_file_name, "binary_audio_encoded.opus"); 106 | 107 | if (!file_decoder.decode_audio(rsencoded_output_file_name, rsdecoded_file_name)) { 108 | return 1; 109 | } 110 | ``` 111 | 112 | ### Additional : Mixing solution for Burst Errors: 113 | 114 | ``` 115 | const std::string input_file_name = "input.txt";//your file path 116 | const std::string rsencoded_output_file_name = "output.rsenc"; 117 | const std::string mixing_output_file_name = "mix.rsenc"; 118 | const std::string remixing_output_file_name = "remix.rsenc"; 119 | const std::string rsdecoded_file_name = "output.rsdec"; 120 | // Call the encode function 121 | if (!file_encoder.encode(input_file_name, rsencoded_output_file_name)) { 122 | return 1; 123 | } 124 | // add a mixing layer between encode - decode for burst errors 125 | wd_codec::transpose_mix(rsencoded_output_file_name, mixing_output_file_name, file_encoder.get_blocks_number(), wd_codec::fileio::file_size(rsencoded_output_file_name)); 126 | 127 | long burst_start_position = 1000; // Example start position 128 | long burst_length = 100; // Example burst length 129 | wd_codec::error_injection::corrupt_file_with_burst_errors(mixing_output_file_name, burst_start_position, burst_length); 130 | wd_codec::transpose_remix2(mixing_output_file_name, remixing_output_file_name, file_encoder.get_blocks_number(), wd_codec::fileio::file_size(mixing_output_file_name)); 131 | 132 | if (!file_decoder.decode(remixing_output_file_name, rsdecoded_file_name)) 133 | return 1; 134 | } 135 | ``` 136 | 137 | ### Polynomial Support 138 | Support of Polynomial data structure 139 | 140 | An example of multiplying 2 polynomials: 141 | ``` 142 | include "setup_utilities.h" 143 | // P(x) = x^2 + x + 1 144 | wd_codec::galois::Field_Element P_elements[] = { 145 | wd_codec::galois::Field_Element(wd_codec::field, 1), 146 | wd_codec::galois::Field_Element(wd_codec::field, 1), 147 | wd_codec::galois::Field_Element(wd_codec::field, 1) 148 | }; 149 | 150 | // Q(x) = 2x + 2 151 | wd_codec::galois::Field_Element Q_elements[] = { 152 | wd_codec::galois::Field_Element(wd_codec::field, 2), 153 | wd_codec::galois::Field_Element(wd_codec::field, 2) 154 | }; 155 | 156 | wd_codec::galois::Polynomial P(wd_codec::field, 2, P_elements); 157 | wd_codec::galois::Polynomial Q(wd_codec::field, 1, Q_elements); 158 | 159 | //P(X) = 2 x^3 + 2 160 | P *= Q; 161 | ``` 162 | 163 | ## Test 164 | 165 | Set properties in Test project: 166 | 167 | ![Set properties](https://github.com/user-attachments/assets/9b36fba8-8043-4d92-8a23-c7e918dd3fd8) 168 | 169 | Chose the Test mode for run 170 | 171 | ![mode for run](https://github.com/user-attachments/assets/33138b8a-457e-4017-a7a6-942f97e3913d) 172 | 173 | Unmark the lines in Logger.h: 174 | 175 | ![Unmarked the lines](https://github.com/user-attachments/assets/4d3fe26a-0936-4db0-8f73-aa79227302f5) 176 | 177 | Run 178 | 179 | you should see: 9/9 tests passed 180 | 181 | you can write more tests according to your goals 182 | 183 | ## 184 | #### Run Time: O(n^2) 185 | #### Space comlexity:O(n) 186 | 187 | 188 | #### You are welcome to read our [design document](https://docs.google.com/document/d/15HjDrKq-bXMuxdPeO_hRMhoan5Ts4Vxn/edit?usp=sharing&ouid=103102751553159913006&rtpof=true&sd=true) and see our [presentation](https://docs.google.com/presentation/d/1ogAyA55F_DTyFQMUE5UGRZJBpf7j_wuBfhxTugHZ9KU/edit?usp=sharing) 189 | 190 | ## Contributing 191 | 192 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 193 | 194 | Please make sure to update tests as appropriate. 195 | 196 | We look forward to your feedback to help us improve this project. 197 | 198 | ### Team Members: 199 | 200 | - [Efrat Eisenbach](https://github.com/efratizen) 201 | - [Ayala Elhadad](https://github.com/AyalaElha) 202 | - [Tamar Godinger](https://github.com/tamargodin) 203 | 204 | --------------------------------------------------------------------------------