Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
quantize.cpp
Go to the documentation of this file.
1/*
2 @author herumi
3
4 JPEG quantize sample
5 This program generates a quantization routine by using fast division algorithm in run-time.
6
7 time(sec)
8 quality 1(low) 10 50 100(high)
9 VC2005 8.0 8.0 8.0 8.0
10 Xbyak 1.6 0.8 0.5 0.5
11
12
13; generated code at q = 100
14 push esi
15 push edi
16 mov edi,dword ptr [esp+0Ch]
17 mov esi,dword ptr [esp+10h]
18 mov eax,dword ptr [esi]
19 shr eax,4
20 mov dword ptr [edi],eax
21 mov eax,dword ptr [esi+4]
22 mov edx,0BA2E8BA3h
23 mul eax,edx
24 shr edx,3
25 ...
26
27; generated code at q = 100
28 push esi
29 push edi
30 mov edi,dword ptr [esp+0Ch]
31 mov esi,dword ptr [esp+10h]
32 mov eax,dword ptr [esi]
33 mov dword ptr [edi],eax
34 mov eax,dword ptr [esi+4]
35 mov dword ptr [edi+4],eax
36 mov eax,dword ptr [esi+8]
37 mov dword ptr [edi+8],eax
38 mov eax,dword ptr [esi+0Ch]
39 ...
40
41*/
42#include <stdio.h>
43#include <stdlib.h>
44#include <time.h>
45#define XBYAK_NO_OP_NAMES
46#include "xbyak/xbyak.h"
47#ifdef _MSC_VER
48 #pragma warning(disable : 4996) // scanf
49#endif
50
53
54const int N = 64;
55
57 static int ilog2(int x)
58 {
59 int shift = 0;
60 while ((1 << shift) <= x) shift++;
61 return shift - 1;
62 }
63public:
64 /*
65 input : esi
66 output : eax = [esi+offset] / dividend
67 destroy : edx
68 */
69 void udiv(uint32 dividend, int offset)
70 {
71 mov(eax, ptr[esi + offset]);
72
73 /* dividend = odd x 2^exponent */
74 int exponent = 0, odd = dividend;
75 while ((odd & 1) == 0) {
76 odd >>= 1; exponent++;
77 }
78
79 if (odd == 1) { // trivial case
80 if (exponent) {
81 shr(eax, exponent);
82 }
83 return;
84 }
85
86 uint64 mLow, mHigh;
87 int len = ilog2(odd) + 1;
88 {
89 uint64 roundUp = uint64(1) << (32 + len);
90 uint64 k = roundUp / (0xFFFFFFFFL - (0xFFFFFFFFL % odd));
91 mLow = roundUp / odd;
92 mHigh = (roundUp + k) / odd;
93 }
94
95 while (((mLow >> 1) < (mHigh >> 1)) && (len > 0)) {
96 mLow >>= 1; mHigh >>= 1; len--;
97 }
98
99 uint64 m; int a;
100 if ((mHigh >> 32) == 0) {
101 m = mHigh; a = 0;
102 } else {
103 len = ilog2(odd);
104 uint64 roundDown = uint64(1) << (32 + len);
105 mLow = roundDown / odd;
106 int r = (int)(roundDown % odd);
107 m = (r <= (odd >> 1)) ? mLow : mLow + 1;
108 a = 1;
109 }
110 while ((m & 1) == 0) {
111 m >>= 1; len--;
112 }
113 len += exponent;
114
115 mov(edx, int(m));
116 mul(edx);
117 if (a) {
118 add(eax, int(m));
119 adc(edx, 0);
120 }
121 if (len) {
122 shr(edx, len);
123 }
124 mov(eax, edx);
125 }
126 /*
127 quantize(uint32 dest[64], const uint32 src[64]);
128 */
129 Quantize(const uint32 qTbl[64])
130 {
131 push(esi);
132 push(edi);
133 const int P_ = 4 * 2;
134 mov(edi, ptr [esp+P_+4]); // dest
135 mov(esi, ptr [esp+P_+8]); // src
136 for (int i = 0; i < N; i++) {
137 udiv(qTbl[i], i * 4);
138 mov(ptr[edi+i*4], eax);
139 }
140 pop(edi);
141 pop(esi);
142 ret();
143 }
144};
145
146void quantize(uint32 dest[64], const uint32 src[64], const uint32 qTbl[64])
147{
148 for (int i = 0; i < N; i++) {
149 dest[i] = src[i] / qTbl[i];
150 }
151}
152
153#ifdef XBYAK64
154int main()
155{
156 puts("not implemented for 64bit");
157 return 1;
158}
159#else
160int main(int argc, char *argv[])
161{
162 int q;
163 if (argc > 1) {
164 q = atoi(argv[1]);
165 } else {
166 printf("input quantize=");
167 if (scanf("%d", &q) != 1) {
168 fprintf(stderr, "bad number\n");
169 return 1;
170 }
171 }
172 printf("q=%d\n", q);
173 uint32 qTbl[] = {
174 16, 11, 10, 16, 24, 40, 51, 61,
175 12, 12, 14, 19, 26, 58, 60, 55,
176 14, 13, 16, 24, 40, 57, 69, 56,
177 14, 17, 22, 29, 51, 87, 80, 62,
178 18, 22, 37, 56, 68, 109, 103, 77,
179 24, 35, 55, 64, 81, 104, 113, 92,
180 49, 64, 78, 87, 103, 121, 120, 101,
181 72, 92, 95, 98, 112, 100, 103, 99
182 };
183
184 for (int i = 0; i < N; i++) {
185 qTbl[i] /= q;
186 if (qTbl[i] == 0) qTbl[i] = 1;
187 }
188
189 try {
190 uint32 src[N];
191 uint32 dest[N];
192 uint32 dest2[N];
193 for (int i = 0; i < N; i++) {
194 src[i] = rand() % 2048;
195 }
196
197 Quantize jit(qTbl);
198//printf("jit size=%d, ptr=%p\n", jit.getSize(), jit.getCode());
199 void (*quantize2)(uint32*, const uint32*, const uint32 *) = jit.getCode<void (*)(uint32*, const uint32*, const uint32 *)>();
200
201 quantize(dest, src, qTbl);
202 quantize2(dest2, src, qTbl);
203 for (int i = 0; i < N; i++) {
204 if (dest[i] != dest2[i]) {
205 printf("err[%d] %d %d\n", i, dest[i], dest2[i]);
206 }
207 }
208
209 const int count = 10000000;
210 int begin;
211
212 begin = clock();
213 for (int i = 0; i < count; i++) {
214 quantize(dest, src, qTbl);
215 }
216 printf("time=%.1fsec\n", (clock() - begin) / double(CLOCKS_PER_SEC));
217
218 begin = clock();
219 for (int i = 0; i < count; i++) {
220 quantize2(dest, src, qTbl);
221 }
222 printf("time=%.1fsec\n", (clock() - begin) / double(CLOCKS_PER_SEC));
223 } catch (std::exception& e) {
224 printf("ERR:%s\n", e.what());
225 } catch (...) {
226 printf("unknown error\n");
227 }
228}
229#endif
const mie::Vuint & r
Definition bn.cpp:28
Quantize(const uint32 qTbl[64])
Definition quantize.cpp:129
void udiv(uint32 dividend, int offset)
Definition quantize.cpp:69
const uint8 * getCode() const
Definition xbyak.h:905
void shr(const Operand &op, const Reg8 &_cl)
Definition xbyak.h:730
const Reg32 esp
Definition xbyak.h:2087
const Reg32 eax
Definition xbyak.h:2087
void add(const Operand &op, uint32 imm)
Definition xbyak.h:6
const Reg32 edi
Definition xbyak.h:2087
void adc(const Operand &op, uint32 imm)
Definition xbyak.h:3
const Reg32 edx
Definition xbyak.h:2087
void mov(const Operand &reg1, const Operand &reg2)
Definition xbyak.h:2210
void pop(const Operand &op)
Definition xbyak.h:2190
void mul(const Operand &op)
Definition xbyak.h:497
const Reg32 esi
Definition xbyak.h:2087
void push(const Operand &op)
Definition xbyak.h:2189
const AddressFrame ptr
Definition xbyak.h:2090
int * count
char ** argv
uint64_t uint64
Definition xbyak.h:117
unsigned int uint32
Definition xbyak.h:120
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
Xbyak::uint64 uint64
Definition quantize.cpp:51
void quantize(uint32 dest[64], const uint32 src[64], const uint32 qTbl[64])
Definition quantize.cpp:146
const int N
Definition quantize.cpp:54
Xbyak::uint32 uint32
Definition quantize.cpp:52
Xbyak ; JIT assembler for x86(IA32)/x64 by C++.
CK_RV ret
size_t len