Blur Optimization. [Part 4]
[xy_vsfilter.git] / test / unit_test / test_xy_filter.h
blobb0bc1c6d5849521a02f907c42795480cec0bd464
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);
17 template<typename T>
18 std::ostream& GetBufString(std::ostream& os, T* buf, int len)
20 for (int i=0;i<len;i++)
22 os<<buf[i]<<" ";
24 return os;
27 // Usable AlmostEqual function
29 bool AlmostEqual2sComplement(float A, float B, int maxUlps)
32 // Make sure maxUlps is non-negative and small enough that the
34 // default NAN won't compare as equal to anything.
36 assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
38 int aInt = *(int*)&A;
40 // Make aInt lexicographically ordered as a twos-complement int
42 if (aInt < 0)
44 aInt = 0x80000000 - aInt;
46 // Make bInt lexicographically ordered as a twos-complement int
48 int bInt = *(int*)&B;
50 if (bInt < 0)
51 bInt = 0x80000000 - bInt;
53 int intDiff = abs(aInt - bInt);
55 if (intDiff <= maxUlps)
56 return true;
58 return false;
62 class XyFilterTestData
64 public:
65 static const int MAX_FILTER_LENGTH = 256;
66 static const int MAX_DATA_BUFF_SIZE = 512*512;
67 static const int MAX_BUFF_SIZE = MAX_DATA_BUFF_SIZE + 2*MAX_FILTER_LENGTH;
69 float *buff_base;
71 float *filter_f;
73 float *data;
74 int w, h, pitch;
75 int filter_width;
76 int ex_filter_width;
78 XyFilterTestData():buff_base(NULL),filter_f(NULL),data(NULL)
80 buff_base = (float*)xy_malloc(MAX_BUFF_SIZE*sizeof(float));
81 data = buff_base + MAX_FILTER_LENGTH;
82 filter_f = data + MAX_DATA_BUFF_SIZE;
84 ~XyFilterTestData()
86 xy_free(buff_base);buff_base=NULL;
89 const XyFilterTestData& copy (const XyFilterTestData& rhs)
91 w = rhs.w;
92 h = rhs.h;
93 pitch = rhs.pitch;
94 filter_width = rhs.filter_width;
95 ex_filter_width = rhs.ex_filter_width;
97 memcpy(buff_base, rhs.buff_base, MAX_BUFF_SIZE*sizeof(float));
98 return *this;
100 bool operator== (const XyFilterTestData& rhs) const
102 for (int i=0;i<MAX_BUFF_SIZE;i++)
104 if (!AlmostEqual2sComplement(buff_base[i], rhs.buff_base[i],8))
106 std::cerr<<"Not almost equal at: "<<i+buff_base-data
107 <<" lhs:"<<buff_base[i]
108 <<" rhs:"<<rhs.buff_base[i]
109 <<std::endl;
110 return false;
113 return true;
116 void FillRandData(int w, int h, int filter_width)
118 this->w = w;
119 this->h = h;
120 this->filter_width = filter_width;
121 this->ex_filter_width = ((filter_width+3)&~3);
122 this->pitch = ((w+ex_filter_width+3)&~3)*sizeof(float);
124 ASSERT(this->pitch*this->h <= MAX_DATA_BUFF_SIZE);
126 for (int i=0;i<h;i++)
128 float *data2 = (float*)((PUINT8)data + i*pitch);
129 for (int j=0;j<w+filter_width;j++)
131 data2[j] = rand()&0xFF;
134 float sum = 0;
135 for (int i=0;i<filter_width;i++)
137 filter_f[i] = abs((rand()&0xFFFFF)+0xFFFFF);
138 sum += filter_f[i];
140 for (int i=0;i<filter_width;i++)
142 filter_f[i] /= sum;
144 for (int i=filter_width;i<ex_filter_width;i++)
146 filter_f[i] = 0;
149 private:
150 XyFilterTestData(const XyFilterTestData&);
151 const XyFilterTestData& operator= (const XyFilterTestData& rhs);
154 std::ostream& operator<<( std::ostream& os, const XyFilterTestData& data )
156 os<<"filter:"<<std::endl;
157 GetBufString<const float>(os, data.filter_f, data.filter_width)<<" | ";
158 GetBufString<const float>(os, data.filter_f+data.filter_width, data.ex_filter_width - data.filter_width)<<std::endl;
159 os<<"data:"<<std::endl;
160 GetBufString<const float>(os, data.data-data.ex_filter_width, data.ex_filter_width)<<" | ";
161 GetBufString<const float>(os, data.data, data.w-data.ex_filter_width)<<" | ";
162 GetBufString<const float>(os, data.data+data.w-data.ex_filter_width, data.ex_filter_width)<<std::endl;
164 return os;
167 class XyFilterTest : public ::testing::Test
169 public:
170 XyFilterTestData data0, data1, data2;
171 protected:
172 virtual void SetUp()
177 #define LOG_VAR(x) " "#x" "<<x<<" "
179 TEST_F(XyFilterTest, c_vs_sse)
181 int LOOP_NUM = 10;
182 for(int WIDTH=4;WIDTH<256;WIDTH+=4)
183 for (int FILTER_WIDTH=3;FILTER_WIDTH<32;FILTER_WIDTH++)
185 for(int i=0;i<LOOP_NUM;i++)
187 data0.FillRandData(WIDTH, 1, FILTER_WIDTH);
188 data1.copy(data0);
189 data2.copy(data0);
190 xy_filter_one_line_c(data1.data, data1.w, data1.filter_f, data1.ex_filter_width);
191 xy_filter_one_line_sse(data2.data, data2.w, data2.filter_f, data2.ex_filter_width);
192 ASSERT_EQ(true, data2.operator==(data1))
193 <<LOG_VAR(i)<<LOG_VAR(WIDTH)<<LOG_VAR(FILTER_WIDTH)<<std::endl
194 <<"data0:"<<data0
195 <<"data1:"<<data1
196 <<"data2:"<<data2;
202 #endif // __TEST_XY_FILTER_0B6AC4E9_AA51_4EF9_B255_90792DC07DB9_H__