Blur Optimization. [Part 7]
[xy_vsfilter.git] / test / unit_test / test_xy_filter.h
blobcdb77bee65a30facdd4933209f2e9133ee6504dd
1 #ifndef __TEST_XY_FILTER_0B6AC4E9_AA51_4EF9_B255_90792DC07DB9_H__
2 #define __TEST_XY_FILTER_0B6AC4E9_AA51_4EF9_B255_90792DC07DB9_H__
4 #include <gtest/gtest.h>
5 #include <wtypes.h>
6 #include <math.h>
7 #include <xmmintrin.h>
8 #include "xy_malloc.h"
10 void xy_filter_one_line_c(float *dst, int width, const float *filter, int filter_width);
11 void xy_filter_sse(float *dst, int width, int height, int stride, const float *filter, int filter_width);
12 void xy_filter_one_line_sse(float *dst, int width, const float *filter, int filter_width)
14 xy_filter_sse(dst, width, 1, ((width*4)+15)&~15, filter, filter_width);
16 void xy_filter_one_line_sse_v6(float *dst, int width, const float *filter, int filter_width);
18 template<typename T>
19 std::ostream& GetBufString(std::ostream& os, T* buf, int len)
21 for (int i=0;i<len;i++)
23 os<<buf[i]<<" ";
25 return os;
28 // Usable AlmostEqual function
30 bool AlmostEqual2sComplement(float A, float B, int maxUlps)
33 // Make sure maxUlps is non-negative and small enough that the
35 // default NAN won't compare as equal to anything.
37 assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
39 int aInt = *(int*)&A;
41 // Make aInt lexicographically ordered as a twos-complement int
43 if (aInt < 0)
45 aInt = 0x80000000 - aInt;
47 // Make bInt lexicographically ordered as a twos-complement int
49 int bInt = *(int*)&B;
51 if (bInt < 0)
52 bInt = 0x80000000 - bInt;
54 int intDiff = abs(aInt - bInt);
56 if (intDiff <= maxUlps)
57 return true;
59 return false;
63 class XyFilterTestData
65 public:
66 static const int MAX_FILTER_LENGTH = 256;
67 static const int MAX_DATA_BUFF_SIZE = 512*512;
68 static const int MAX_BUFF_SIZE = MAX_DATA_BUFF_SIZE + 2*MAX_FILTER_LENGTH;
70 float *buff_base;
72 float *filter_f;
74 float *data;
75 int w, h, pitch;
76 int filter_width;
77 int ex_filter_width;
79 XyFilterTestData():buff_base(NULL),filter_f(NULL),data(NULL)
81 buff_base = (float*)xy_malloc(MAX_BUFF_SIZE*sizeof(float));
82 data = buff_base + MAX_FILTER_LENGTH;
83 filter_f = data + MAX_DATA_BUFF_SIZE;
85 ~XyFilterTestData()
87 xy_free(buff_base);buff_base=NULL;
90 const XyFilterTestData& copy (const XyFilterTestData& rhs)
92 w = rhs.w;
93 h = rhs.h;
94 pitch = rhs.pitch;
95 filter_width = rhs.filter_width;
96 ex_filter_width = rhs.ex_filter_width;
98 memcpy(buff_base, rhs.buff_base, MAX_BUFF_SIZE*sizeof(float));
99 return *this;
101 bool operator== (const XyFilterTestData& rhs) const
103 for (int i=0;i<MAX_BUFF_SIZE;i++)
105 if (!AlmostEqual2sComplement(buff_base[i], rhs.buff_base[i],8))
107 std::cerr<<"Not almost equal at: "<<i+buff_base-data
108 <<" lhs:"<<buff_base[i]
109 <<" rhs:"<<rhs.buff_base[i]
110 <<std::endl;
111 return false;
114 return true;
117 void FillRandData(int w, int h, int filter_width)
119 this->w = w;
120 this->h = h;
121 this->filter_width = filter_width;
122 this->ex_filter_width = ((filter_width+3)&~3);
123 this->pitch = ((w+ex_filter_width+3)&~3)*sizeof(float);
125 ASSERT(this->pitch*this->h <= MAX_DATA_BUFF_SIZE);
127 for (int i=0;i<h;i++)
129 float *data2 = (float*)((PUINT8)data + i*pitch);
130 for (int j=0;j<w+filter_width;j++)
132 data2[j] = rand()&0xFF;
135 float sum = 0;
136 for (int i=0;i<filter_width/2+1;i++)
138 filter_f[i] = abs((rand()&0xFFFFF)+0xFFFFF);
139 sum += filter_f[i];
141 for (int i=filter_width/2+1;i<filter_width;i++)
143 filter_f[i] = filter_f[filter_width-i-1];
144 sum += filter_f[i];
146 for (int i=0;i<filter_width;i++)
148 filter_f[i] /= sum;
150 for (int i=filter_width;i<ex_filter_width;i++)
152 filter_f[i] = 0;
155 private:
156 XyFilterTestData(const XyFilterTestData&);
157 const XyFilterTestData& operator= (const XyFilterTestData& rhs);
160 std::ostream& operator<<( std::ostream& os, const XyFilterTestData& data )
162 os<<"filter:"<<std::endl;
163 GetBufString<const float>(os, data.filter_f, data.filter_width)<<" | ";
164 GetBufString<const float>(os, data.filter_f+data.filter_width, data.ex_filter_width - data.filter_width)<<std::endl;
165 os<<"data:"<<std::endl;
166 GetBufString<const float>(os, data.data-data.ex_filter_width, data.ex_filter_width)<<" | ";
167 GetBufString<const float>(os, data.data, data.w-data.ex_filter_width)<<" | ";
168 GetBufString<const float>(os, data.data+data.w-data.ex_filter_width, data.ex_filter_width)<<std::endl;
170 return os;
173 class XyFilterTest : public ::testing::Test
175 public:
176 XyFilterTestData data0, data1, data2;
177 protected:
178 virtual void SetUp()
183 #define LOG_VAR(x) " "#x" "<<x<<" "
185 TEST_F(XyFilterTest, c_vs_sse)
187 int LOOP_NUM = 10;
188 for(int WIDTH=4;WIDTH<256;WIDTH+=4)
189 for (int FILTER_WIDTH=3;FILTER_WIDTH<32;FILTER_WIDTH++)
191 for(int i=0;i<LOOP_NUM;i++)
193 data0.FillRandData(WIDTH, 1, FILTER_WIDTH);
194 data1.copy(data0);
195 data2.copy(data0);
196 xy_filter_one_line_c(data1.data, data1.w, data1.filter_f, data1.ex_filter_width);
197 xy_filter_one_line_sse_v6(data2.data, data2.w, data2.filter_f, data2.ex_filter_width);
198 ASSERT_EQ(true, data2.operator==(data1))
199 <<LOG_VAR(i)<<LOG_VAR(WIDTH)<<LOG_VAR(FILTER_WIDTH)<<std::endl
200 <<"data0:"<<data0
201 <<"data1:"<<data1
202 <<"data2:"<<data2;
208 TEST_F(XyFilterTest, sse_vs_sse_v6)
210 int LOOP_NUM = 10;
211 for(int WIDTH=4;WIDTH<256;WIDTH+=4)
212 for (int FILTER_WIDTH=3;FILTER_WIDTH<32;FILTER_WIDTH++)
214 for(int i=0;i<LOOP_NUM;i++)
216 data0.FillRandData(WIDTH, 1, FILTER_WIDTH);
217 data1.copy(data0);
218 data2.copy(data0);
219 xy_filter_one_line_sse(data1.data, data1.w, data1.filter_f, data1.ex_filter_width);
220 xy_filter_one_line_sse_v6(data2.data, data2.w, data2.filter_f, data2.ex_filter_width);
221 ASSERT_EQ(true, data2.operator==(data1))
222 <<LOG_VAR(i)<<LOG_VAR(WIDTH)<<LOG_VAR(FILTER_WIDTH)<<std::endl
223 <<"data0:"<<data0
224 <<"data1:"<<data1
225 <<"data2:"<<data2;
230 #endif // __TEST_XY_FILTER_0B6AC4E9_AA51_4EF9_B255_90792DC07DB9_H__