qrtools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +65 -0
  3. data/README.txt +75 -0
  4. data/Rakefile +49 -0
  5. data/bin/qrdecode +14 -0
  6. data/ext/qrtools/Makefile.in +65 -0
  7. data/ext/qrtools/bitstream.cpp +147 -0
  8. data/ext/qrtools/bitstream.h +48 -0
  9. data/ext/qrtools/codedata.cpp +506 -0
  10. data/ext/qrtools/codedata.h +95 -0
  11. data/ext/qrtools/container.cpp +288 -0
  12. data/ext/qrtools/container.h +175 -0
  13. data/ext/qrtools/decodeqr.h +286 -0
  14. data/ext/qrtools/ecidecoder.cpp +341 -0
  15. data/ext/qrtools/ecidecoder.h +110 -0
  16. data/ext/qrtools/extconf.rb +24 -0
  17. data/ext/qrtools/formatinfo.cpp +195 -0
  18. data/ext/qrtools/formatinfo.h +113 -0
  19. data/ext/qrtools/galois.cpp +593 -0
  20. data/ext/qrtools/galois.h +134 -0
  21. data/ext/qrtools/imagereader.cpp +1099 -0
  22. data/ext/qrtools/imagereader.h +127 -0
  23. data/ext/qrtools/libdecodeqr.cpp +195 -0
  24. data/ext/qrtools/libdecodeqr.dep +80 -0
  25. data/ext/qrtools/libdecodeqr.dsp +160 -0
  26. data/ext/qrtools/libdecodeqr.dsw +29 -0
  27. data/ext/qrtools/libdecodeqr.mak +245 -0
  28. data/ext/qrtools/qrerror.h +40 -0
  29. data/ext/qrtools/qrtools.c +17 -0
  30. data/ext/qrtools/qrtools.h +21 -0
  31. data/ext/qrtools/qrtools_decoder.c +123 -0
  32. data/ext/qrtools/qrtools_decoder.h +10 -0
  33. data/ext/qrtools/qrtools_encoder.c +63 -0
  34. data/ext/qrtools/qrtools_encoder.h +10 -0
  35. data/ext/qrtools/qrtools_header.c +51 -0
  36. data/ext/qrtools/qrtools_header.h +10 -0
  37. data/ext/qrtools/qrtools_image.c +80 -0
  38. data/ext/qrtools/qrtools_image.h +11 -0
  39. data/ext/qrtools/qrtools_qrcode.c +36 -0
  40. data/ext/qrtools/qrtools_qrcode.h +10 -0
  41. data/ext/qrtools/qrtools_ui_camera.c +58 -0
  42. data/ext/qrtools/qrtools_ui_camera.h +10 -0
  43. data/ext/qrtools/qrtools_ui_window.c +40 -0
  44. data/ext/qrtools/qrtools_ui_window.h +10 -0
  45. data/ext/qrtools/qrtypes.h +42 -0
  46. data/ext/qrtools/version.h +42 -0
  47. data/lib/qrtools.rb +11 -0
  48. data/lib/qrtools/decoder.rb +17 -0
  49. data/lib/qrtools/encoder.rb +14 -0
  50. data/lib/qrtools/image.rb +43 -0
  51. data/lib/qrtools/qrcode.rb +54 -0
  52. data/lib/qrtools/ui/camera.rb +28 -0
  53. data/lib/qrtools/ui/window.rb +16 -0
  54. data/lib/qrtools/version.rb +3 -0
  55. data/qrtools.gemspec +38 -0
  56. data/test/assets/01-1.jpg +0 -0
  57. data/test/helper.rb +17 -0
  58. data/test/test_decoder.rb +67 -0
  59. data/test/test_encoder.rb +35 -0
  60. data/test/test_header.rb +14 -0
  61. data/test/test_image.rb +19 -0
  62. data/test/test_qrcode.rb +78 -0
  63. data/test/test_qrdecode.rb +0 -0
  64. data/test/ui/test_camera.rb +43 -0
  65. data/test/ui/test_window.rb +34 -0
  66. metadata +138 -0
@@ -0,0 +1,110 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // ecidecoder.h --a part of libdecodeqr
4
+ //
5
+ // Copyright(C) 2007 NISHI Takao <zophos@koka-in.org>
6
+ // JMA (Japan Medical Association)
7
+ // NaCl (Network Applied Communication Laboratory Ltd.)
8
+ //
9
+ // This is free software with ABSOLUTELY NO WARRANTY.
10
+ // You can redistribute and/or modify it under the terms of LGPL.
11
+ //
12
+ // $Id: ecidecoder.h 36 2007-02-21 23:22:03Z zophos $
13
+ //
14
+ #ifndef __QR_ECI_DECODER__
15
+ #define __QR_ECI_DECODER__
16
+
17
+ #include <stdio.h>
18
+
19
+ #ifdef WIN32
20
+ #include <winsock2.h>
21
+ #define snprintf _snprintf
22
+ #else
23
+ #include <netinet/in.h>
24
+ #endif
25
+
26
+ #include "bitstream.h"
27
+
28
+ namespace Qr{
29
+ namespace ECI{
30
+ class Decoder{
31
+ public:
32
+ int mode;
33
+ int length;
34
+ int byte_length;
35
+ int eci_mode;
36
+
37
+ protected:
38
+ unsigned char *_raw_data;
39
+ int _bit_par_block;
40
+ int _char_par_block;
41
+ int _byte_par_char;
42
+
43
+ int _read_length;
44
+ int _written_length;
45
+ unsigned char *_current_pos;
46
+
47
+ public:
48
+ Decoder();
49
+ ~Decoder();
50
+
51
+ unsigned char *raw_data();
52
+ virtual int decode(int version,BitStream *bitstream);
53
+
54
+ private:
55
+ virtual int _read_header(int version,BitStream *bitstream);
56
+ virtual int _get_charactor_count(int version)=0;
57
+ virtual int _read_data(BitStream *bitstream);
58
+ };
59
+
60
+ class NumericalDecoder :public Decoder{
61
+ private:
62
+ short _read_buf;
63
+ public:
64
+ NumericalDecoder();
65
+ private:
66
+ virtual int _get_charactor_count(int version);
67
+ virtual int _read_data(BitStream *bitstream);
68
+ };
69
+
70
+ class AlphabeticalDecoder :public Decoder{
71
+ private:
72
+ short _read_buf;
73
+ public:
74
+ AlphabeticalDecoder();
75
+ private:
76
+ virtual int _get_charactor_count(int version);
77
+ virtual int _read_data(BitStream *bitstream);
78
+ };
79
+
80
+ class ByteDecoder :public Decoder{
81
+ private:
82
+ char _read_buf;
83
+ public:
84
+ ByteDecoder();
85
+ private:
86
+ virtual int _get_charactor_count(int version);
87
+ virtual int _read_data(BitStream *bitstream);
88
+ };
89
+
90
+ class GenericDecoder :public Decoder{
91
+ public:
92
+ GenericDecoder();
93
+ private:
94
+ virtual int _get_charactor_count(int version);
95
+ virtual int _read_data(BitStream *bitstream);
96
+ };
97
+
98
+ class KanjiDecoder :public Decoder{
99
+ private:
100
+ short _read_buf;
101
+ public:
102
+ KanjiDecoder();
103
+ private:
104
+ virtual int _get_charactor_count(int version);
105
+ virtual int _read_data(BitStream *bitstream);
106
+ };
107
+ };
108
+ }
109
+
110
+ #endif
@@ -0,0 +1,24 @@
1
+ ENV["ARCHFLAGS"] = "-arch #{`uname -p` =~ /powerpc/ ? 'ppc' : 'i386'}"
2
+
3
+ require 'mkmf'
4
+
5
+ LIBDIR = Config::CONFIG['libdir']
6
+ INCLUDEDIR = Config::CONFIG['includedir']
7
+
8
+ HEADER_DIRS = [
9
+ '/opt/local/include/opencv',
10
+ ]
11
+
12
+ LIB_DIRS = [
13
+ LIBDIR,
14
+ '/opt/local/lib',
15
+ ]
16
+
17
+ dir_config('opencv', "/opt/local/include/opencv", "/opt/local/lib")
18
+ dir_config('qrencode', "/opt/local/include", "/opt/local/lib")
19
+ %w{ qrencode cxcore cv highgui }.each do |lib|
20
+ abort "need #{lib}" unless have_library(lib)
21
+ end
22
+ find_header('qrencode.h')
23
+ have_library('stdc++')
24
+ create_makefile('qrtools')
@@ -0,0 +1,195 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // formatinfo.cpp --a part of libdecodeqr
4
+ //
5
+ // Copyright(C) 2007 NISHI Takao <zophos@koka-in.org>
6
+ // JMA (Japan Medical Association)
7
+ // NaCl (Network Applied Communication Laboratory Ltd.)
8
+ //
9
+ // This is free software with ABSOLUTELY NO WARRANTY.
10
+ // You can redistribute and/or modify it under the terms of LGPL.
11
+ //
12
+ // $Id: formatinfo.cpp 36 2007-02-21 23:22:03Z zophos $
13
+ //
14
+ #include "formatinfo.h"
15
+
16
+ namespace Qr{
17
+ unsigned char MaskPatterner000::pixel(int i,int j)
18
+ {
19
+ return((i+j)%2?0:255);
20
+ }
21
+ unsigned char MaskPatterner001::pixel(int i,int j)
22
+ {
23
+ return(i%2?0:255);
24
+ }
25
+ unsigned char MaskPatterner010::pixel(int i,int j)
26
+ {
27
+ return(j%3?0:255);
28
+ }
29
+ unsigned char MaskPatterner011::pixel(int i,int j)
30
+ {
31
+ return((i+j)%3?0:255);
32
+ }
33
+ unsigned char MaskPatterner100::pixel(int i,int j)
34
+ {
35
+ return((i/2+j/3)%2?0:255);
36
+ }
37
+ unsigned char MaskPatterner101::pixel(int i,int j)
38
+ {
39
+ return(((i*j)%2)+((i*j)%3)?0:255);
40
+ }
41
+ unsigned char MaskPatterner110::pixel(int i,int j)
42
+ {
43
+ return((((i*j)%2)+((i*j)%3))%2?0:255);
44
+ }
45
+ unsigned char MaskPatterner111::pixel(int i,int j)
46
+ {
47
+ return((((i*j)%3)+((i*j)%2))%2?0:255);
48
+ }
49
+
50
+ FormatInfo::FormatInfo()
51
+ {
52
+ this->level=0;
53
+ this->mask_pattern=0;
54
+ this->status=0;
55
+
56
+ this->_patterner=NULL;
57
+ }
58
+ FormatInfo::~FormatInfo()
59
+ {
60
+ if(this->_patterner)
61
+ delete this->_patterner;
62
+ }
63
+
64
+ int FormatInfo::set_level(int l)
65
+ {
66
+ this->level=l;
67
+ if(l<0||l>3){
68
+ this->status|=QR_FORMATINFO_INVALID_LEVEL;
69
+ this->level=0;
70
+ }
71
+ return(this->level);
72
+ }
73
+ int FormatInfo::set_mask_pattern(int m)
74
+ {
75
+ if(this->_patterner)
76
+ delete this->_patterner;
77
+
78
+ this->mask_pattern=m;
79
+ switch(this->mask_pattern){
80
+ case 0:
81
+ this->_patterner=new MaskPatterner000();
82
+ break;
83
+ case 1:
84
+ this->_patterner=new MaskPatterner001();
85
+ break;
86
+ case 2:
87
+ this->_patterner=new MaskPatterner010();
88
+ break;
89
+ case 3:
90
+ this->_patterner=new MaskPatterner011();
91
+ break;
92
+ case 4:
93
+ this->_patterner=new MaskPatterner100();
94
+ break;
95
+ case 5:
96
+ this->_patterner=new MaskPatterner101();
97
+ break;
98
+ case 6:
99
+ this->_patterner=new MaskPatterner110();
100
+ break;
101
+ case 7:
102
+ this->_patterner=new MaskPatterner111();
103
+ break;
104
+ }
105
+
106
+ return(this->mask_pattern);
107
+ }
108
+
109
+ int FormatInfo::decode_formatinfo(unsigned short data)
110
+ {
111
+ data^=QR_FORMAT_INFO_XOR_MASK;
112
+
113
+ this->status=0;
114
+ int ret=this->_error_correct(&data);
115
+
116
+ this->set_level(data>>13);
117
+ this->set_mask_pattern((data>>10)&0x7);
118
+
119
+ if(ret<0)
120
+ this->status|=QR_FORMATINFO_UNRECOVERABLE;
121
+
122
+ return(ret);
123
+ }
124
+
125
+ int FormatInfo::_error_correct(unsigned short *src)
126
+ {
127
+ Galois::Field *gf=new Galois::Field(4);
128
+ Galois::BCH *bch=new Galois::BCH(gf,15,3);
129
+ unsigned short mask=0x01;
130
+ int i;
131
+ for(i=0;i<15;i++,mask<<=1){
132
+ if(*src&mask)
133
+ bch->set(i,gf->exp2nomial(0));
134
+ else
135
+ bch->set(i,gf->zero());
136
+ }
137
+ int errors=bch->decode();
138
+ if(errors>0){
139
+ mask=0x01;
140
+ for(i=0;i<errors;i++)
141
+ (*src)^=(mask<<bch->error_pos[i]);
142
+ }
143
+
144
+ delete bch;
145
+ delete gf;
146
+ return(errors);
147
+ }
148
+
149
+ unsigned char FormatInfo::mask_pixel(int i,int j){
150
+ return(this->_patterner->pixel(i,j));
151
+ }
152
+
153
+ FormatInfo *FormatInfo::init_each_pattern_pixel()
154
+ {
155
+ this->_pattern_c=0;
156
+ return(this);
157
+ }
158
+ FormatInfo *FormatInfo::each_pattern_pixel(int *x,int *y)
159
+ {
160
+ if(this->_pattern_c<16){
161
+ *x=format_info_addr[0][this->_pattern_c][0];
162
+ *y=format_info_addr[0][this->_pattern_c][1];
163
+ }
164
+ else if(this->_pattern_c<32){
165
+ *x=format_info_addr[1][this->_pattern_c-16][0];
166
+ *y=format_info_addr[1][this->_pattern_c-16][1];
167
+ }
168
+ else
169
+ return(NULL);
170
+
171
+ this->_pattern_c++;
172
+ return(this);
173
+ }
174
+ FormatInfo *FormatInfo::each_pattern_pixel(int pos,int *x,int *y)
175
+ {
176
+ switch(pos){
177
+ case 0:
178
+ if(this->_pattern_c>14)
179
+ return(NULL);
180
+ break;
181
+ case 1:
182
+ if(this->_pattern_c>15)
183
+ return(NULL);
184
+ break;
185
+ default:
186
+ return(NULL);
187
+ }
188
+
189
+ *x=format_info_addr[pos][this->_pattern_c][0];
190
+ *y=format_info_addr[pos][this->_pattern_c][1];
191
+
192
+ this->_pattern_c++;
193
+ return(this);
194
+ }
195
+ }
@@ -0,0 +1,113 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // formatinfo.h --a part of libdecodeqr
4
+ //
5
+ // Copyright(C) 2007 NISHI Takao <zophos@koka-in.org>
6
+ // JMA (Japan Medical Association)
7
+ // NaCl (Network Applied Communication Laboratory Ltd.)
8
+ //
9
+ // This is free software with ABSOLUTELY NO WARRANTY.
10
+ // You can redistribute and/or modify it under the terms of LGPL.
11
+ //
12
+ // $Id: formatinfo.h 36 2007-02-21 23:22:03Z zophos $
13
+ //
14
+ #ifndef __QR_FORMAT_INFO__
15
+ #define __QR_FORMAT_INFO__
16
+
17
+ #ifndef NULL
18
+ #define NULL 0
19
+ #endif
20
+
21
+ #include "qrerror.h"
22
+ #include "galois.h"
23
+
24
+ #define QR_FORMAT_INFO_GX 0x537 // G(x)=x^10+x^8+x^5+x^4+x^2+x+1
25
+ #define QR_FORMAT_INFO_XOR_MASK 0x5412 //0101010000010010B
26
+ #define QR_FORMAT_INFO_DATA_SIZE 15
27
+
28
+ namespace Qr{
29
+ //
30
+ // format info;
31
+ // matrix of (x,y); minus value means SymbolLength - Value;
32
+ // e.g; symbol size = 21 x 21, values {1,-1} points {1,20} module
33
+ //
34
+ const int format_info_addr[2][16][2]={
35
+ {
36
+ {0,8},{1,8},{2,8},{3,8},{4,8},{5,8},{7,8},
37
+ {8,8},{8,7},{8,5},{8,4},{8,3},{8,2},{8,1},{8,0}
38
+ },
39
+ {
40
+ {8,-8}, // always black
41
+ {8,-1},{8,-2},{8,-3},{8,-4},{8,-5},{8,-6},{8,-7},
42
+ {-8,8},{-7,8},{-6,8},{-5,8},{-4,8},{-3,8},{-2,8},{-1,8}
43
+ }
44
+ };
45
+
46
+ class MaskPatterner{
47
+ public:
48
+ virtual unsigned char pixel(int i,int j)=0;
49
+ };
50
+ class MaskPatterner000:public MaskPatterner{
51
+ public:
52
+ virtual unsigned char pixel(int i,int j);
53
+ };
54
+ class MaskPatterner001:public MaskPatterner{
55
+ public:
56
+ virtual unsigned char pixel(int i,int j);
57
+ };
58
+ class MaskPatterner010:public MaskPatterner{
59
+ public:
60
+ virtual unsigned char pixel(int i,int j);
61
+ };
62
+ class MaskPatterner011:public MaskPatterner{
63
+ public:
64
+ virtual unsigned char pixel(int i,int j);
65
+ };
66
+ class MaskPatterner100:public MaskPatterner{
67
+ public:
68
+ virtual unsigned char pixel(int i,int j);
69
+ };
70
+ class MaskPatterner101:public MaskPatterner{
71
+ public:
72
+ virtual unsigned char pixel(int i,int j);
73
+ };
74
+ class MaskPatterner110:public MaskPatterner{
75
+ public:
76
+ virtual unsigned char pixel(int i,int j);
77
+ };
78
+ class MaskPatterner111:public MaskPatterner{
79
+ public:
80
+ virtual unsigned char pixel(int i,int j);
81
+ };
82
+
83
+ class FormatInfo{
84
+ public:
85
+ int level;
86
+ int mask_pattern;
87
+ short status;
88
+
89
+ private:
90
+ MaskPatterner *_patterner;
91
+
92
+ int _pattern_c;
93
+
94
+ public:
95
+ FormatInfo();
96
+ ~FormatInfo();
97
+
98
+ int set_level(int l);
99
+ int set_mask_pattern(int m);
100
+
101
+ int decode_formatinfo(unsigned short data);
102
+
103
+ unsigned char mask_pixel(int i,int j);
104
+
105
+ FormatInfo *init_each_pattern_pixel();
106
+ FormatInfo *each_pattern_pixel(int *x,int *y);
107
+ FormatInfo *each_pattern_pixel(int pos,int *x,int *y);
108
+
109
+ private:
110
+ int _error_correct(unsigned short *src);
111
+ };
112
+ }
113
+ #endif
@@ -0,0 +1,593 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // galois.cpp --a part of libdecodeqr
4
+ //
5
+ // Copyright(C) 2007 NISHI Takao <zophos@koka-in.org>
6
+ // JMA (Japan Medical Association)
7
+ // NaCl (Network Applied Communication Laboratory Ltd.)
8
+ //
9
+ // This is free software with ABSOLUTELY NO WARRANTY.
10
+ // You can redistribute and/or modify it under the terms of LGPL.
11
+ //
12
+ // $Id: galois.cpp 38 2007-02-23 21:16:42Z zophos $
13
+ //
14
+ #include "galois.h"
15
+
16
+ namespace Galois{
17
+
18
+ /////////////////////////////////////////////////////////////////////
19
+ //
20
+ // galois field GF(2^4); G(x)=x^10+x^8+x^5+x^4+x^2+x+1
21
+ //
22
+
23
+ //
24
+ // generator polynomial
25
+ //
26
+ static const int bch_15_5_generator_polynomial[11]={
27
+ 1,1,1,0,1,1,0,0,1,0,1
28
+ };
29
+
30
+ //
31
+ // exponent -> vector notation convert table
32
+ //
33
+ static const unsigned int gf2_4_exp2vect[16]={
34
+ 1,2,4,8,3,6,12,11,5,10,7,14,15,13,9,0
35
+ };
36
+
37
+ //
38
+ // vector -> exponent notation convert table
39
+ //
40
+ static const unsigned int gf2_4_vect2exp[16]={
41
+ 15,0,1,4,2,8,5,10,3,14,9,7,6,13,11,12
42
+ };
43
+
44
+ /////////////////////////////////////////////////////////////////////
45
+ //
46
+ // galois field GF(2^8); G(x)=X^8+x^4+x^3+x^2+1
47
+ //
48
+
49
+ //
50
+ // generator polynomial
51
+ //
52
+ static const int bch_16_8_generator_polynomial[9]={
53
+ 1,0,1,1,1,0,0,0,1
54
+ };
55
+
56
+ //
57
+ // exponent -> vector notation convert table
58
+ //
59
+ static const unsigned int gf2_8_exp2vect[256]={
60
+ 1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,
61
+ 76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,
62
+ 157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,
63
+ 70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,
64
+ 95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,
65
+ 253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,
66
+ 217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,
67
+ 129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,
68
+ 133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,
69
+ 168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,
70
+ 230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,
71
+ 227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,
72
+ 130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,
73
+ 81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,
74
+ 18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,
75
+ 44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,0
76
+ };
77
+
78
+ //
79
+ // vector -> exponent notation convert table
80
+ //
81
+ static const unsigned int gf2_8_vect2exp[256]={
82
+ 255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,
83
+ 4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,
84
+ 5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,
85
+ 29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,
86
+ 6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,
87
+ 54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,
88
+ 30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,
89
+ 202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,
90
+ 7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,
91
+ 227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,
92
+ 55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,
93
+ 242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,
94
+ 31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,
95
+ 108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,
96
+ 203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,
97
+ 79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175
98
+ };
99
+
100
+ //
101
+ // G(x)=x^12+x^11+x^10+x^9+x^8+x^5+x^2+1
102
+ //
103
+ static const int bch_18_6_generator_polynomial[13]={
104
+ 1,0,1,0,0,1,0,0,1,1,1,1,1
105
+ };
106
+
107
+
108
+ /////////////////////////////////////////////////////////////////////
109
+ //
110
+ //
111
+ //
112
+ Nomial::Nomial(void *gf,unsigned int x)
113
+ {
114
+ this->val=x;
115
+ this->_gf=gf;
116
+ ((Field *)(this->_gf))->pool[x]=this;
117
+ }
118
+
119
+ Nomial *Nomial::instance(void *gf,unsigned int x)
120
+ {
121
+ x=x%(((Field *)gf)->pool_size());
122
+ if(!((Field *)gf)->pool[x])
123
+ new Nomial(gf,x);
124
+
125
+ return(((Field *)gf)->pool[x]);
126
+ }
127
+
128
+ Nomial *Nomial::dup()
129
+ {
130
+ return(Nomial::instance(this->_gf,this->val));
131
+ }
132
+
133
+
134
+ unsigned int Nomial::to_exp()
135
+ {
136
+ return(this->val);
137
+ }
138
+ unsigned int Nomial::to_vect()
139
+ {
140
+ return(((Field *)this->_gf)->exp2vect[this->val]);
141
+ }
142
+
143
+ inline int Nomial::m()
144
+ {
145
+ return(((Field *)(this->_gf))->m);
146
+ }
147
+ inline int Nomial::n()
148
+ {
149
+ return(((Field *)(this->_gf))->n);
150
+ }
151
+ inline unsigned int Nomial::exp2vect(unsigned int x)
152
+ {
153
+ return(((Field *)(this->_gf))->exp2vect[x]);
154
+ }
155
+ inline unsigned int Nomial::vect2exp(unsigned int x)
156
+ {
157
+ return(((Field *)(this->_gf))->vect2exp[x]);
158
+ }
159
+
160
+ bool Nomial::is_zero()
161
+ {
162
+ return(this->to_vect()==0);
163
+ }
164
+ bool Nomial::operator==(Nomial x)
165
+ {
166
+ return(this->val==x.val);
167
+ }
168
+ bool Nomial::operator!=(Nomial x)
169
+ {
170
+ return(this->val!=x.val);
171
+ }
172
+ Nomial Nomial::operator+(Nomial x)
173
+ {
174
+ return(*Nomial::instance(this->_gf,
175
+ this->vect2exp(this->to_vect()^
176
+ x.to_vect())));
177
+ }
178
+ Nomial Nomial::operator-(Nomial x)
179
+ {
180
+ return(*this+x);
181
+ }
182
+ Nomial Nomial::operator*(Nomial x)
183
+ {
184
+ if(this->is_zero()||x.is_zero())
185
+ return(*(((Field *)(this->_gf))->zero()));
186
+ else
187
+ return(*Nomial::instance(this->_gf,(this->val+x.val)%this->n()));
188
+
189
+ }
190
+ Nomial Nomial::operator/(Nomial x)
191
+ {
192
+ if(x.is_zero())
193
+ throw(x);
194
+ else if(this->is_zero())
195
+ return(*(((Field *)(this->_gf))->zero()));
196
+ else
197
+ return(*Nomial::instance(this->_gf,
198
+ (this->val+this->n()-x.val)%this->n()));
199
+ }
200
+
201
+ /////////////////////////////////////////////////////////////////////
202
+ //
203
+ //
204
+ //
205
+ Field::Field(int m)
206
+ {
207
+ this->_need_delete=false;
208
+
209
+ this->m=m;
210
+ int i;
211
+ for(i=0,this->n=1;i<m;i++)
212
+ this->n*=2;
213
+ this->n-=1;
214
+
215
+ switch(this->m){
216
+ case 4:
217
+ this->exp2vect=(unsigned int *)gf2_4_exp2vect;
218
+ this->vect2exp=(unsigned int *)gf2_4_vect2exp;
219
+ break;
220
+ case 8:
221
+ this->exp2vect=(unsigned int *)gf2_8_exp2vect;
222
+ this->vect2exp=(unsigned int *)gf2_8_vect2exp;
223
+ break;
224
+ default:
225
+ throw;
226
+ }
227
+
228
+ this->_pool_size=this->n+1;
229
+ this->pool=new Nomial *[this->_pool_size];
230
+ for(i=0;i<this->_pool_size;i++){
231
+ this->pool[i]=NULL;
232
+ Nomial::instance(this,i);
233
+ }
234
+ }
235
+ Field::~Field()
236
+ {
237
+ delete this->pool;
238
+ if(this->_need_delete){
239
+ delete this->exp2vect;
240
+ delete this->vect2exp;
241
+ }
242
+ }
243
+
244
+ int Field::pool_size()
245
+ {
246
+ return(this->_pool_size);
247
+ }
248
+
249
+ Nomial *Field::exp2nomial(unsigned int x)
250
+ {
251
+ return(this->pool[x%(this->n)]);
252
+ }
253
+ Nomial *Field::vect2nomial(unsigned int x)
254
+ {
255
+ return(this->pool[this->vect2exp[x%(this->n)]]);
256
+ }
257
+ Nomial *Field::zero()
258
+ {
259
+ return(this->pool[this->n]);
260
+ }
261
+
262
+ ////////////////////////////////////////////////////////////////////////
263
+ //
264
+ //
265
+ //
266
+ Polynomial::Polynomial()
267
+ {
268
+ this->cols=0;
269
+ this->rows=0;
270
+
271
+ this->nomial=NULL;
272
+ }
273
+
274
+ Polynomial::Polynomial(int rows)
275
+ {
276
+ this->cols=1;
277
+ this->rows=rows;
278
+
279
+ this->nomial=new Galois::Nomial *[this->rows];
280
+ }
281
+ Polynomial::Polynomial(int cols,int rows)
282
+ {
283
+ this->cols=cols;
284
+ this->rows=rows;
285
+
286
+ this->nomial=new Nomial *[this->cols*this->rows];
287
+ }
288
+ Polynomial::~Polynomial()
289
+ {
290
+ delete this->nomial;
291
+ }
292
+
293
+ Polynomial *Polynomial::dup()
294
+ {
295
+ Polynomial *ret=new Polynomial(this->cols,this->rows);
296
+ memcpy(ret->nomial,this->nomial,
297
+ sizeof(Nomial *)*this->cols*this->rows);
298
+
299
+ return(ret);
300
+ }
301
+ Polynomial *Polynomial::dup(int count)
302
+ {
303
+ return(this->dup(0,0,count,count));
304
+ }
305
+ Polynomial *Polynomial::dup(int start_col,int start_row,int count)
306
+ {
307
+ return(this->dup(start_col,start_row,count,count));
308
+ }
309
+ Polynomial *Polynomial::dup(int start_col,int start_row,
310
+ int col_count,int row_count)
311
+ {
312
+ Polynomial *ret=new Polynomial(col_count,row_count);
313
+
314
+ for(int i=0,c=start_col;i<col_count;i++,c++){
315
+ for(int j=0,r=start_row;j<row_count;j++,r++){
316
+ ret->set(i,j,this->get(c,r));
317
+ }
318
+ }
319
+
320
+ return(ret);
321
+ }
322
+
323
+
324
+ Nomial *Polynomial::set(int row,Nomial *val)
325
+ {
326
+ return(this->set(0,row,val));
327
+ }
328
+ Nomial *Polynomial::set(int col,int row,Nomial *val)
329
+ {
330
+ this->nomial[col*rows+row]=val->dup();
331
+ return(this->nomial[col*rows+row]);
332
+ }
333
+
334
+ Nomial *Polynomial::get(int row)
335
+ {
336
+ return(this->get(0,row));
337
+ }
338
+ Nomial *Polynomial::get(int col,int row)
339
+ {
340
+ return(this->nomial[col*rows+row]->dup());
341
+ }
342
+
343
+
344
+ /////////////////////////////////////////////////////////////////////
345
+ //
346
+ // LU analyze with pivot selection
347
+ //
348
+ Polynomial *Polynomial::lu()
349
+ {
350
+ Polynomial *buf=this->dup();
351
+ Polynomial *ret=buf->_lu(buf);
352
+ if(!ret)
353
+ delete buf;
354
+ return(ret);
355
+ }
356
+ Polynomial *Polynomial::lu(int count)
357
+ {
358
+ Polynomial *buf=this->dup(0,0,count);
359
+ Polynomial *ret=buf->_lu(buf);
360
+ if(!ret)
361
+ delete buf;
362
+ return(ret);
363
+ }
364
+ Polynomial *Polynomial::lu(int start_col,int start_row,int count)
365
+ {
366
+ Polynomial *buf=this->dup(start_col,start_row,count);
367
+ Polynomial *ret=buf->_lu(buf);
368
+ if(!ret)
369
+ delete buf;
370
+ return(ret);
371
+ }
372
+
373
+ Polynomial *Polynomial::_lu(Polynomial *buf)
374
+ {
375
+ int count=buf->cols,i,j;
376
+ if(buf->rows<buf->cols)
377
+ count=buf->rows;
378
+
379
+ for(j=0;j<count;j++){
380
+ Nomial *l;
381
+ //
382
+ // pivot
383
+ //
384
+ for(i=j;i<count;i++){
385
+ l=buf->get(i,j);
386
+ if(!l->is_zero())
387
+ break;
388
+ }
389
+ if(i>=count)
390
+ return(NULL);
391
+ else if(i>j)
392
+ buf->swap_col(j,i);
393
+
394
+ for(i=j+1;i<count;i++){
395
+ Nomial *n=&(*buf->get(i,j)/(*l));
396
+ buf->set(i,j,n);
397
+ for(int k=j+1;k<count;k++){
398
+ Nomial *m=&(*buf->get(i,k)-*buf->get(j,k)**n);
399
+ *buf->set(i,k,m);
400
+ }
401
+ }
402
+ }
403
+ return(buf);
404
+ }
405
+
406
+ /////////////////////////////////////////////////////////////////////
407
+ //
408
+ // Gaussian elimination
409
+ //
410
+ Polynomial *Polynomial::solve()
411
+ {
412
+ Polynomial *lu=this->lu();
413
+ if(lu){
414
+ Polynomial *ret=this->solve(lu);
415
+ delete lu;
416
+ return(ret);
417
+ }
418
+ else{
419
+ return(NULL);
420
+ }
421
+ }
422
+
423
+ Polynomial *Polynomial::solve(Polynomial *lu)
424
+ {
425
+ if(!lu)
426
+ return(NULL);
427
+
428
+ if(lu->rows!=this->cols+1)
429
+ throw((void *)NULL);
430
+
431
+ //
432
+ // check rank
433
+ //
434
+ int rank=0,i,j,k;
435
+ for(j=0;j<lu->cols;j++){
436
+ bool is_zero_cols=true;
437
+ for(k=j;k<lu->cols;k++){
438
+ is_zero_cols&=lu->get(j,k)->is_zero();
439
+ }
440
+ if(!is_zero_cols)
441
+ rank++;
442
+ }
443
+ if(rank<lu->cols)
444
+ return(NULL);
445
+
446
+ Polynomial *ret=new Polynomial(lu->cols);
447
+ for(i=0;i<lu->cols;i++){
448
+ ret->set(i,lu->get(i,lu->cols));
449
+ }
450
+
451
+ for(j=0;j<lu->cols;j++){
452
+ for(i=j+1;i<lu->cols;i++){
453
+ ret->set(i,&(*ret->get(i)-*ret->get(j)**lu->get(i,j)));
454
+ }
455
+ }
456
+ for(j=lu->cols-1;j>=0;j--){
457
+ for(int i=j+1;i<lu->cols;i++){
458
+ ret->set(j,&(*ret->get(j)-
459
+ *lu->get(j,i)**ret->get(i)));
460
+ }
461
+ ret->set(j,&(*ret->get(j)/(*lu->get(j,j))));
462
+ }
463
+ return(ret);
464
+ }
465
+
466
+ void Polynomial::swap_col(int i,int j)
467
+ {
468
+ size_t sz=sizeof(Nomial *)*this->rows;
469
+
470
+ Nomial **tmp=new Nomial *[this->rows];
471
+
472
+ memcpy(tmp,this->nomial+i*this->rows,sz);
473
+ memcpy(this->nomial+i*this->rows,
474
+ this->nomial+j*this->rows,sz);
475
+ memcpy(this->nomial+j*this->rows,tmp,sz);
476
+
477
+ delete tmp;
478
+ }
479
+
480
+
481
+ /////////////////////////////////////////////////////////////////////
482
+ //
483
+ //
484
+ //
485
+ BCH::BCH(Field *gf,int size,int capability)
486
+ {
487
+ this->_gf=gf;
488
+ this->rows=size;
489
+ this->cols=1;
490
+ this->_capability=capability;
491
+ this->error_size=0;
492
+ this->error_pos=NULL;
493
+ this->nomial=new Galois::Nomial *[this->rows];
494
+ this->syndrome_size=0;
495
+ this->syndromes=NULL;
496
+ }
497
+ BCH::~BCH()
498
+ {
499
+ if(this->error_pos)
500
+ delete this->error_pos;
501
+
502
+ if(this->syndromes)
503
+ delete this->syndromes;
504
+ }
505
+
506
+ int BCH::decode(int syndrome_base)
507
+ {
508
+ //
509
+ // error syndromes
510
+ //
511
+ this->syndrome_size=this->_capability*2+syndrome_base;
512
+ this->syndromes=new Galois::Nomial *[this->syndrome_size];
513
+
514
+ int errors=0,i;
515
+ for(i=0;i<this->syndrome_size;i++){
516
+ this->syndromes[i]=this->_error_syndrome(i);
517
+ if(!this->syndromes[i]->is_zero())
518
+ errors++;
519
+ }
520
+ if(!errors)
521
+ return(0);
522
+
523
+ //
524
+ // calculate error position variables
525
+ //
526
+ Galois::Polynomial *err=NULL;
527
+ for(errors=this->_capability;errors>0;errors--){
528
+ Galois::Polynomial *mat=new Galois::Polynomial(errors,
529
+ errors+1);
530
+
531
+ for(int j=0;j<errors;j++){
532
+ for(i=0;i<=errors;i++){
533
+ mat->set(j,i,this->syndromes[i+j+syndrome_base]);
534
+ }
535
+ }
536
+
537
+ err=mat->solve();
538
+ delete mat;
539
+
540
+ if(err)
541
+ break;
542
+ }
543
+ if(!err){
544
+ this->error_size=-1;
545
+ return(-1);
546
+ }
547
+
548
+ if(err){
549
+ //
550
+ // get error position
551
+ //
552
+ this->error_pos=new int[errors];
553
+ memset(this->error_pos,-1,errors);
554
+
555
+ int c,i,j;
556
+ for(j=0,c=0;j<this->rows;j++){
557
+ Galois::Nomial *sigma=err->get(0);
558
+ for(i=1;i<errors;i++){
559
+ sigma=&(*sigma+*err->get(i)*
560
+ *this->_gf->exp2nomial(j*i));
561
+ }
562
+ sigma=&(*sigma+*this->_gf->exp2nomial(j*i));
563
+
564
+ if(sigma->is_zero()){
565
+ if(c<errors){
566
+ this->error_pos[c]=j;
567
+ }
568
+ c++;
569
+ }
570
+ }
571
+ delete err;
572
+ if(c==errors)
573
+ this->error_size=errors;
574
+ else
575
+ this->error_size=-1;
576
+ }
577
+
578
+ return(this->error_size);
579
+ }
580
+
581
+ Galois::Nomial *BCH::_error_syndrome(int d)
582
+ {
583
+ Galois::Nomial *x=this->_gf->zero();
584
+
585
+ for(int i=0;i<this->rows;i++){
586
+ x=&(*x+*this->get(i)*
587
+ *this->_gf->exp2nomial(i*d));
588
+ }
589
+
590
+ return(x->dup());
591
+ }
592
+
593
+ }