#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
/* #define DEBUG */
#if defined(DEBUG)
#include "xmalloc.h"
#else
#define xmalloc(x, y) malloc(x)
#define xfree(x, y) free(x)
#define xrealloc(x, y, z) realloc(x, y)
#define xmallocdump()
#endif
/* for xmalloc.c */
#define IDRGB 1001
#define IDPALETTE 1002
#define IDBMP 1003
/*---------------------------------------------------------------------------*/
#define NBYTE 1
#define NWORD 2
#define NDWORD 4
typedef struct {
unsigned long bfType1;
unsigned long bfType2;
unsigned long bfSize;
unsigned long bfReserved1;
unsigned long bfReserved2;
unsigned long bfOffBits;
} BitmapFileHeader;
typedef struct {
unsigned long biSize;
long biWidth;
long biHeight;
unsigned long biPlanes;
unsigned long biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} BitmapInfoHeader;
void LittleEndianWrite(unsigned long *data, int size, FILE *fp) {
unsigned char lsb;
unsigned long msb;
if (size == 0)
return;
lsb = (unsigned char)(*data & 0xff);
msb = *data >> 8;
LittleEndianWrite(&msb, size - 1, fp);
}
long iabs(long n) {
return (n > 0) ? n : -n;
}
void task_write_header(FILE *fp, BitmapFileHeader *bh) {
assert(sizeof(unsigned long) >= 4); LittleEndianWrite(&(bh->bfType1), NBYTE, fp);
LittleEndianWrite(&(bh->bfType2), NBYTE, fp);
LittleEndianWrite(&(bh->bfSize), NDWORD, fp);
LittleEndianWrite(&(bh->bfReserved1), NWORD, fp);
LittleEndianWrite(&(bh->bfReserved2), NWORD, fp);
LittleEndianWrite(&(bh->bfOffBits), NDWORD, fp);
#if 0
printf("write:bfType1: %c\n", (char)bh
->bfType1
); printf("write:bfType2: %c\n", (char)bh
->bfType2
); printf("write:bfSize: %lu\n", bh
->bfSize
); printf("write:bfReserved1: %lu\n", bh
->bfReserved1
); printf("write:bfReserved2: %lu\n", bh
->bfReserved2
); printf("write:bfOffBits: %lu\n", bh
->bfOffBits
); #endif
}
void task_write_info(FILE *fp, BitmapInfoHeader *bi) {
assert(sizeof(unsigned short) == 2); assert(sizeof(unsigned long) == 4); LittleEndianWrite(&(bi->biSize), NDWORD, fp);
LittleEndianWrite((unsigned long *)&(bi->biWidth), NDWORD, fp);
LittleEndianWrite((unsigned long *)&(bi->biHeight), NDWORD, fp);
LittleEndianWrite(&(bi->biPlanes), NWORD, fp);
LittleEndianWrite(&(bi->biBitCount), NWORD, fp);
LittleEndianWrite(&(bi->biCompression), NDWORD, fp);
LittleEndianWrite(&(bi->biSizeImage), NDWORD, fp);
LittleEndianWrite((unsigned long *)&(bi->biXPixPerMeter), NDWORD, fp);
LittleEndianWrite((unsigned long *)&(bi->biYPixPerMeter), NDWORD, fp);
LittleEndianWrite(&(bi->biClrUsed), NDWORD, fp);
LittleEndianWrite(&(bi->biClrImportant), NDWORD, fp);
#if 0
printf("write:biSize: %lu\n", bi
->biSize
); printf("write:biWidth: %ld\n", bi
->biWidth
); printf("write:biHeight: %ld\n", bi
->biHeight
); printf("write:biPlanes: %lu\n", bi
->biPlanes
); printf("write:biBitcount: %lu\n", bi
->biBitCount
); printf("write:biCompression: %lu\n", bi
->biCompression
); printf("write:biSizeImage: %lu\n", bi
->biSizeImage
); printf("write:biXPixPerMeter %ld\n", bi
->biXPixPerMeter
); printf("write:biYPixPerMeter %ld\n", bi
->biYPixPerMeter
); printf("write:biClrUsed: %lu\n", bi
->biClrUsed
); printf("write:biClrImporant: %lu\n", bi
->biClrImportant
); #endif
}
void task_write24(FILE *fp,
BitmapFileHeader *bh, BitmapInfoHeader *bi,
unsigned char *dataR,
unsigned char *dataG,
unsigned char *dataB) {
int x, y;
int c;
unsigned char dummy = '\0';
task_write_header(fp, bh);
task_write_info(fp, bi);
for (y = 0; y < iabs(bi->biHeight); y++) {
c = 0;
for (x = 0; x < iabs(bi->biWidth); x++) {
fwrite(&dataB
[y
* iabs
(bi
->biWidth
) + x
], 1, 1, fp
); fwrite(&dataG
[y
* iabs
(bi
->biWidth
) + x
], 1, 1, fp
); fwrite(&dataR
[y
* iabs
(bi
->biWidth
) + x
], 1, 1, fp
); c += 3;
}
while (c % 4 != 0) {
c++;
}
}
}
/*---------------------------------------------------------------------------*/
struct BMP24 {
BitmapFileHeader bh;
BitmapInfoHeader bi;
unsigned char *dataR;
unsigned char *dataG;
unsigned char *dataB;
unsigned char *dataPalette;
};
void BMP24_write(FILE *fp, struct BMP24 *bmp) {
task_write24(fp, &bmp->bh, &bmp->bi,
bmp->dataR, bmp->dataG, bmp->dataB);
}
void _BMP24_allocation(struct BMP24 **w_bmp, long width, long height) {
int n;
*w_bmp = xmalloc(sizeof(struct BMP24), IDBMP);
if (*w_bmp == NULL) {
return;
}
n = width * 3;
if (n % 4 > 0)
n += 4 - (n % 4);
(*w_bmp)->bi.biSizeImage = n * height;
(*w_bmp)->bi.biSize = 40;
(*w_bmp)->bh.bfSize = (*w_bmp)->bi.biSizeImage + (*w_bmp)->bi.biSize + 14;
(*w_bmp)->bh.bfType1 = 'B';
(*w_bmp)->bh.bfType2 = 'M';
(*w_bmp)->bh.bfReserved1 = 0;
(*w_bmp)->bh.bfReserved2 = 0;
(*w_bmp)->bh.bfOffBits = 54;
(*w_bmp)->bi.biPlanes = 1;
(*w_bmp)->bi.biBitCount = 24;
(*w_bmp)->bi.biCompression = 0;
(*w_bmp)->bi.biHeight = height;
(*w_bmp)->bi.biWidth = width;
(*w_bmp)->bi.biClrUsed = 0;
(*w_bmp)->bi.biClrImportant = 0;
(*w_bmp)->bi.biXPixPerMeter = 30;
(*w_bmp)->bi.biYPixPerMeter = 30;
(*w_bmp)->dataR = (*w_bmp)->dataG = (*w_bmp)->dataB = NULL;
(*w_bmp)->dataPalette = NULL;
for (;;) {
if (((*w_bmp)->dataR = xmalloc(width * height, IDRGB)) == 0)
break;
if (((*w_bmp)->dataG = xmalloc(width * height, IDRGB)) == 0)
break;
if (((*w_bmp)->dataB = xmalloc(width * height, IDRGB)) == 0)
break;
/* OK finished */
return;
}
/* exception */
xfree((*w_bmp)->dataR, IDRGB);
xfree((*w_bmp)->dataG, IDRGB);
xfree((*w_bmp)->dataB, IDRGB);
xfree(*w_bmp, IDBMP);
*w_bmp = 0;
return;
}
void BMP24_release(struct BMP24 *bmp) {
if (bmp->dataR) xfree(bmp->dataR, IDRGB);
if (bmp->dataG) xfree(bmp->dataG, IDRGB);
if (bmp->dataB) xfree(bmp->dataB, IDRGB);
if (bmp->dataPalette) xfree(bmp->dataPalette, IDPALETTE);
}
/*---------------------------------------------------------------------------*/
#define EPSILON 0.0000005
double dzdx(double x, double y, double (*z)(double, double)) { return (z(x + EPSILON, y) - z(x, y)) / EPSILON; }
double dzdy(double x, double y, double (*z)(double, double)) { return (z(x, y + EPSILON) - z(x, y)) / EPSILON; }
struct flist {
double (*f)(double, double);
double (*g)(double, double);
};
int newton(double x, double y, double *rx, double *ry, struct flist flist) {
int rc;
double h1, h2;
double a, b, c, d, D;
rc = 0;
while (1) {
a = dzdx(x, y, flist.f);
b = dzdy(x, y, flist.f);
c = dzdx(x, y, flist.g);
d = dzdy(x, y, flist.g);
D = a * d - b * c;
rc = -1;
break;
}
h1 = - (d * flist.f(x, y) - b * flist.g(x, y)) / D;
h2 = - ((-c) * flist.f(x, y) + a * flist.g(x, y)) / D;
x = x + h1;
y = y + h2;
if (fabs(h1
) < EPSILON
&& abs(h2
) < EPSILON
) break;
}
if (rc == 0) {
*rx = x;
*ry = y;
} else {
*rx = *ry = 0.0;
}
return rc;
}
/*---------------------------------------------------------------------------*/
struct convlist {
double x;
double y;
unsigned char colorR;
unsigned char colorG;
unsigned char colorB;
};
#define ALPHA (1.0)
void task(FILE *fp, double x_ll, double x_ul, double y_ll, double y_ul, int k,
struct flist flist, struct convlist clist[], int args) {
double x, y;
double res_x, res_y;
int i, j, idx, r;
unsigned char cr, cg, cb;
struct BMP24 *bmp;
bmp = 0;
_BMP24_allocation(&bmp, k, k);
for (i = 0; i < k; i++) {
x = (x_ul - x_ll) * i / (double)k + x_ll;
for (j = 0; j < k; j++) {
y = (y_ul - y_ll) * j / (double)k + y_ll;
cr = cg = cb = 0; idx = -1;
if ((r = newton(x, y, &res_x, &res_y, flist)) == 0) {
for (idx = 0; idx < args; idx++) {
if ((fabs(res_x
- clist
[idx
].
x) < ALPHA
* EPSILON
) && (fabs(res_y
- clist
[idx
].
y) < ALPHA
* EPSILON
)) { cr = clist[idx].colorR; cg = clist[idx].colorG; cb = clist[idx].colorB;
break;
}
}
if (idx == args)
cr = cg = cb = 255;
}
printf("(%f, %f)->(%f, %f) ", x
, y
, res_x
, res_y
); printf(" : <%d>(%d, %d, %d)\n", idx
, cr
, cg
, cb
); bmp->dataR[j * k + i] = cr;
bmp->dataG[j * k + i] = cg;
bmp->dataB[j * k + i] = cb;
}
}
BMP24_write(fp, bmp);
BMP24_release(bmp);
xfree(bmp, IDBMP);
}
/*----------------------------------------------------------------*/
#define X_LL (-0.5)
#define Y_LL (-0.5)
#define X_UL 0.5
#define Y_UL 0.5
#define K 1000
double f1(double x, double y) { return x * x + y * y - 8.0; }
double g1(double x, double y) { return x + y; }
double f2(double x, double y) { return x * x * x - 3.0 * x * y * y - 8.0; }
double g2(double x, double y) { return x * x * x - 3.0 * x * x * y; }
#define FILENAME1 "g1.bmp"
#define FILENAME2 "g2.bmp"
int main() {
FILE *fp;
int n;
struct flist flist;
struct convlist clist[3];
#if 1
if ((fp
= fopen(FILENAME1
, "wb")) != 0) { n = 2;
flist.f = f1; flist.g = g1;
clist[0].x = -2.0; clist[0].y = +2.0; clist[0].colorR = 255; clist[0].colorG = clist[0].colorB = 0;
clist[1].x = +2.0; clist[1].y = -2.0; clist[1].colorR = 0; clist[1].colorG = 255; clist[1].colorB = 0;
task(fp, X_LL, X_UL, Y_LL, Y_UL, K, flist, clist, n);
}
#endif
if ((fp
= fopen(FILENAME2
, "wb")) != 0) { n = 1;
flist.f = f2; flist.g = g2;
clist[0].x = 2.289428; clist[0].y = +0.763143; clist[0].colorR = 0; clist[0].colorG = 0; clist[0].colorB = 255;
task(fp, X_LL, X_UL, Y_LL, Y_UL, K, flist, clist, n);
}
return 0;
}
/* end */
#if 0
参考文献
http://s...content-available-to-author-only...c.jp/suuchi-pdf/2007-04-11.pdf
#endif
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPGFzc2VydC5oPgoKLyogI2RlZmluZSBERUJVRyAqLwojaWYgZGVmaW5lZChERUJVRykKI2luY2x1ZGUgInhtYWxsb2MuaCIKI2Vsc2UKI2RlZmluZSB4bWFsbG9jKHgsIHkpIG1hbGxvYyh4KQojZGVmaW5lIHhmcmVlKHgsIHkpIGZyZWUoeCkKI2RlZmluZSB4cmVhbGxvYyh4LCB5LCB6KSByZWFsbG9jKHgsIHkpCiNkZWZpbmUgeG1hbGxvY2R1bXAoKQojZW5kaWYKLyogZm9yIHhtYWxsb2MuYyAqLwojZGVmaW5lIElEUkdCICAgICAxMDAxCiNkZWZpbmUgSURQQUxFVFRFIDEwMDIKI2RlZmluZSBJREJNUCAgICAgMTAwMwoKLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwojZGVmaW5lIE5CWVRFICAxCiNkZWZpbmUgTldPUkQgIDIKI2RlZmluZSBORFdPUkQgNAoKdHlwZWRlZiBzdHJ1Y3QgewogIHVuc2lnbmVkIGxvbmcgYmZUeXBlMTsKICB1bnNpZ25lZCBsb25nIGJmVHlwZTI7CiAgdW5zaWduZWQgbG9uZyBiZlNpemU7CiAgdW5zaWduZWQgbG9uZyBiZlJlc2VydmVkMTsKICB1bnNpZ25lZCBsb25nIGJmUmVzZXJ2ZWQyOwogIHVuc2lnbmVkIGxvbmcgYmZPZmZCaXRzOwp9IEJpdG1hcEZpbGVIZWFkZXI7Cgp0eXBlZGVmIHN0cnVjdCB7CiAgdW5zaWduZWQgbG9uZyBiaVNpemU7CiAgbG9uZyBiaVdpZHRoOwogIGxvbmcgYmlIZWlnaHQ7CiAgdW5zaWduZWQgbG9uZyBiaVBsYW5lczsKICB1bnNpZ25lZCBsb25nIGJpQml0Q291bnQ7CiAgdW5zaWduZWQgbG9uZyBiaUNvbXByZXNzaW9uOwogIHVuc2lnbmVkIGxvbmcgYmlTaXplSW1hZ2U7CiAgbG9uZyBiaVhQaXhQZXJNZXRlcjsKICBsb25nIGJpWVBpeFBlck1ldGVyOwogIHVuc2lnbmVkIGxvbmcgYmlDbHJVc2VkOwogIHVuc2lnbmVkIGxvbmcgYmlDbHJJbXBvcnRhbnQ7Cn0gQml0bWFwSW5mb0hlYWRlcjsKCnZvaWQgTGl0dGxlRW5kaWFuV3JpdGUodW5zaWduZWQgbG9uZyAqZGF0YSwgaW50IHNpemUsIEZJTEUgKmZwKSB7CiAgdW5zaWduZWQgY2hhciBsc2I7CiAgdW5zaWduZWQgbG9uZyBtc2I7CiAgaWYgKHNpemUgPT0gMCkKICAgIHJldHVybjsKICBsc2IgPSAodW5zaWduZWQgY2hhcikoKmRhdGEgJiAweGZmKTsKICBmd3JpdGUoJmxzYiwgMSwgMSwgZnApOwogIG1zYiA9ICpkYXRhID4+IDg7CiAgTGl0dGxlRW5kaWFuV3JpdGUoJm1zYiwgc2l6ZSAtIDEsIGZwKTsKfQoKbG9uZyBpYWJzKGxvbmcgbikgewogIHJldHVybiAobiA+IDApID8gbiA6IC1uOwp9Cgp2b2lkIHRhc2tfd3JpdGVfaGVhZGVyKEZJTEUgKmZwLCBCaXRtYXBGaWxlSGVhZGVyICpiaCkgewogIGFzc2VydChzaXplb2YodW5zaWduZWQgbG9uZykgPj0gNCk7CiAgYXNzZXJ0KHNpemVvZihsb25nKSA+PSA0KTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJoLT5iZlR5cGUxKSwgTkJZVEUsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJoLT5iZlR5cGUyKSwgTkJZVEUsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJoLT5iZlNpemUpLCBORFdPUkQsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJoLT5iZlJlc2VydmVkMSksIE5XT1JELCBmcCk7CiAgTGl0dGxlRW5kaWFuV3JpdGUoJihiaC0+YmZSZXNlcnZlZDIpLCBOV09SRCwgZnApOwogIExpdHRsZUVuZGlhbldyaXRlKCYoYmgtPmJmT2ZmQml0cyksIE5EV09SRCwgZnApOwojaWYgMAogIHByaW50Zigid3JpdGU6YmZUeXBlMTogJWNcbiIsIChjaGFyKWJoLT5iZlR5cGUxKTsKICBwcmludGYoIndyaXRlOmJmVHlwZTI6ICVjXG4iLCAoY2hhciliaC0+YmZUeXBlMik7CiAgcHJpbnRmKCJ3cml0ZTpiZlNpemU6ICVsdVxuIiwgYmgtPmJmU2l6ZSk7CiAgcHJpbnRmKCJ3cml0ZTpiZlJlc2VydmVkMTogJWx1XG4iLCBiaC0+YmZSZXNlcnZlZDEpOwogIHByaW50Zigid3JpdGU6YmZSZXNlcnZlZDI6ICVsdVxuIiwgYmgtPmJmUmVzZXJ2ZWQyKTsKICBwcmludGYoIndyaXRlOmJmT2ZmQml0czogJWx1XG4iLCBiaC0+YmZPZmZCaXRzKTsKI2VuZGlmCn0KCnZvaWQgdGFza193cml0ZV9pbmZvKEZJTEUgKmZwLCBCaXRtYXBJbmZvSGVhZGVyICpiaSkgewogIGFzc2VydChzaXplb2YodW5zaWduZWQgc2hvcnQpID09IDIpOwogIGFzc2VydChzaXplb2YodW5zaWduZWQgbG9uZykgPT0gNCk7CiAgYXNzZXJ0KHNpemVvZihsb25nKSA9PSA0KTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJpLT5iaVNpemUpLCBORFdPUkQsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgodW5zaWduZWQgbG9uZyAqKSYoYmktPmJpV2lkdGgpLCBORFdPUkQsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgodW5zaWduZWQgbG9uZyAqKSYoYmktPmJpSGVpZ2h0KSwgTkRXT1JELCBmcCk7CiAgTGl0dGxlRW5kaWFuV3JpdGUoJihiaS0+YmlQbGFuZXMpLCBOV09SRCwgZnApOwogIExpdHRsZUVuZGlhbldyaXRlKCYoYmktPmJpQml0Q291bnQpLCBOV09SRCwgZnApOwogIExpdHRsZUVuZGlhbldyaXRlKCYoYmktPmJpQ29tcHJlc3Npb24pLCBORFdPUkQsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgmKGJpLT5iaVNpemVJbWFnZSksIE5EV09SRCwgZnApOwogIExpdHRsZUVuZGlhbldyaXRlKCh1bnNpZ25lZCBsb25nICopJihiaS0+YmlYUGl4UGVyTWV0ZXIpLCBORFdPUkQsIGZwKTsKICBMaXR0bGVFbmRpYW5Xcml0ZSgodW5zaWduZWQgbG9uZyAqKSYoYmktPmJpWVBpeFBlck1ldGVyKSwgTkRXT1JELCBmcCk7CiAgTGl0dGxlRW5kaWFuV3JpdGUoJihiaS0+YmlDbHJVc2VkKSwgTkRXT1JELCBmcCk7CiAgTGl0dGxlRW5kaWFuV3JpdGUoJihiaS0+YmlDbHJJbXBvcnRhbnQpLCBORFdPUkQsIGZwKTsKI2lmIDAKICBwcmludGYoIndyaXRlOmJpU2l6ZTogJWx1XG4iLCBiaS0+YmlTaXplKTsKICBwcmludGYoIndyaXRlOmJpV2lkdGg6ICVsZFxuIiwgYmktPmJpV2lkdGgpOwogIHByaW50Zigid3JpdGU6YmlIZWlnaHQ6ICVsZFxuIiwgYmktPmJpSGVpZ2h0KTsKICBwcmludGYoIndyaXRlOmJpUGxhbmVzOiAlbHVcbiIsIGJpLT5iaVBsYW5lcyk7CiAgcHJpbnRmKCJ3cml0ZTpiaUJpdGNvdW50OiAlbHVcbiIsIGJpLT5iaUJpdENvdW50KTsKICBwcmludGYoIndyaXRlOmJpQ29tcHJlc3Npb246ICVsdVxuIiwgYmktPmJpQ29tcHJlc3Npb24pOwogIHByaW50Zigid3JpdGU6YmlTaXplSW1hZ2U6ICVsdVxuIiwgYmktPmJpU2l6ZUltYWdlKTsKICBwcmludGYoIndyaXRlOmJpWFBpeFBlck1ldGVyICVsZFxuIiwgYmktPmJpWFBpeFBlck1ldGVyKTsKICBwcmludGYoIndyaXRlOmJpWVBpeFBlck1ldGVyICVsZFxuIiwgYmktPmJpWVBpeFBlck1ldGVyKTsKICBwcmludGYoIndyaXRlOmJpQ2xyVXNlZDogJWx1XG4iLCBiaS0+YmlDbHJVc2VkKTsKICBwcmludGYoIndyaXRlOmJpQ2xySW1wb3JhbnQ6ICVsdVxuIiwgYmktPmJpQ2xySW1wb3J0YW50KTsKI2VuZGlmCn0KCnZvaWQgdGFza193cml0ZTI0KEZJTEUgKmZwLAogICAgICAgICAgICAgICAgICBCaXRtYXBGaWxlSGVhZGVyICpiaCwgQml0bWFwSW5mb0hlYWRlciAqYmksCiAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGNoYXIgKmRhdGFSLAogICAgICAgICAgICAgICAgICB1bnNpZ25lZCBjaGFyICpkYXRhRywKICAgICAgICAgICAgICAgICAgdW5zaWduZWQgY2hhciAqZGF0YUIpIHsKICBpbnQgeCwgeTsKICBpbnQgYzsKICB1bnNpZ25lZCBjaGFyIGR1bW15ID0gJ1wwJzsKICB0YXNrX3dyaXRlX2hlYWRlcihmcCwgYmgpOwogIHRhc2tfd3JpdGVfaW5mbyhmcCwgYmkpOwogIGZvciAoeSA9IDA7IHkgPCBpYWJzKGJpLT5iaUhlaWdodCk7IHkrKykgewogICAgYyA9IDA7CiAgICBmb3IgKHggPSAwOyB4IDwgaWFicyhiaS0+YmlXaWR0aCk7IHgrKykgewogICAgICBmd3JpdGUoJmRhdGFCW3kgKiBpYWJzKGJpLT5iaVdpZHRoKSArIHhdLCAxLCAxLCBmcCk7CiAgICAgIGZ3cml0ZSgmZGF0YUdbeSAqIGlhYnMoYmktPmJpV2lkdGgpICsgeF0sIDEsIDEsIGZwKTsKICAgICAgZndyaXRlKCZkYXRhUlt5ICogaWFicyhiaS0+YmlXaWR0aCkgKyB4XSwgMSwgMSwgZnApOwogICAgICBjICs9IDM7CiAgICB9CiAgICB3aGlsZSAoYyAlIDQgIT0gMCkgewogICAgICBmd3JpdGUoJmR1bW15LCAxLCAxLCBmcCk7CiAgICAgIGMrKzsKICAgIH0KICB9Cn0KLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwpzdHJ1Y3QgQk1QMjQgewogIEJpdG1hcEZpbGVIZWFkZXIgYmg7CiAgQml0bWFwSW5mb0hlYWRlciBiaTsKICB1bnNpZ25lZCBjaGFyICpkYXRhUjsKICB1bnNpZ25lZCBjaGFyICpkYXRhRzsKICB1bnNpZ25lZCBjaGFyICpkYXRhQjsKICB1bnNpZ25lZCBjaGFyICpkYXRhUGFsZXR0ZTsKfTsKCnZvaWQgQk1QMjRfd3JpdGUoRklMRSAqZnAsIHN0cnVjdCBCTVAyNCAqYm1wKSB7CiAgdGFza193cml0ZTI0KGZwLCAmYm1wLT5iaCwgJmJtcC0+YmksCiAgICAgICAgICAgICAgIGJtcC0+ZGF0YVIsIGJtcC0+ZGF0YUcsIGJtcC0+ZGF0YUIpOwp9Cgp2b2lkIF9CTVAyNF9hbGxvY2F0aW9uKHN0cnVjdCBCTVAyNCAqKndfYm1wLCBsb25nIHdpZHRoLCBsb25nIGhlaWdodCkgewogIGludCBuOwogICp3X2JtcCA9IHhtYWxsb2Moc2l6ZW9mKHN0cnVjdCBCTVAyNCksIElEQk1QKTsKICBpZiAoKndfYm1wID09IE5VTEwpIHsKICAgIGZwcmludGYoc3RkZXJyLCAiZXJyb3IoYm1wMjQpXG4iKTsKICAgIHJldHVybjsKICB9CiAgbiA9IHdpZHRoICogMzsKICBpZiAobiAlIDQgPiAwKQogICAgbiArPSA0IC0gKG4gJSA0KTsKICAoKndfYm1wKS0+YmkuYmlTaXplSW1hZ2UgPSBuICogaGVpZ2h0OwogICgqd19ibXApLT5iaS5iaVNpemUgPSA0MDsKICAoKndfYm1wKS0+YmguYmZTaXplID0gKCp3X2JtcCktPmJpLmJpU2l6ZUltYWdlICsgKCp3X2JtcCktPmJpLmJpU2l6ZSArIDE0OwoKICAoKndfYm1wKS0+YmguYmZUeXBlMSA9ICdCJzsKICAoKndfYm1wKS0+YmguYmZUeXBlMiA9ICdNJzsKICAoKndfYm1wKS0+YmguYmZSZXNlcnZlZDEgPSAwOwogICgqd19ibXApLT5iaC5iZlJlc2VydmVkMiA9IDA7CiAgKCp3X2JtcCktPmJoLmJmT2ZmQml0cyA9IDU0OwoKICAoKndfYm1wKS0+YmkuYmlQbGFuZXMgPSAxOwogICgqd19ibXApLT5iaS5iaUJpdENvdW50ID0gMjQ7CiAgKCp3X2JtcCktPmJpLmJpQ29tcHJlc3Npb24gPSAwOwogICgqd19ibXApLT5iaS5iaUhlaWdodCA9IGhlaWdodDsKICAoKndfYm1wKS0+YmkuYmlXaWR0aCA9IHdpZHRoOyAgCiAgKCp3X2JtcCktPmJpLmJpQ2xyVXNlZCA9IDA7CiAgKCp3X2JtcCktPmJpLmJpQ2xySW1wb3J0YW50ID0gMDsKICAoKndfYm1wKS0+YmkuYmlYUGl4UGVyTWV0ZXIgPSAzMDsKICAoKndfYm1wKS0+YmkuYmlZUGl4UGVyTWV0ZXIgPSAzMDsKICAoKndfYm1wKS0+ZGF0YVIgPSAoKndfYm1wKS0+ZGF0YUcgPSAoKndfYm1wKS0+ZGF0YUIgPSBOVUxMOwogICgqd19ibXApLT5kYXRhUGFsZXR0ZSA9IE5VTEw7CiAgZm9yICg7OykgewogICAgaWYgKCgoKndfYm1wKS0+ZGF0YVIgPSB4bWFsbG9jKHdpZHRoICogaGVpZ2h0LCBJRFJHQikpID09IDApCiAgICAgIGJyZWFrOwogICAgaWYgKCgoKndfYm1wKS0+ZGF0YUcgPSB4bWFsbG9jKHdpZHRoICogaGVpZ2h0LCBJRFJHQikpID09IDApCiAgICAgIGJyZWFrOwogICAgaWYgKCgoKndfYm1wKS0+ZGF0YUIgPSB4bWFsbG9jKHdpZHRoICogaGVpZ2h0LCBJRFJHQikpID09IDApCiAgICAgIGJyZWFrOwogICAgLyogT0sgZmluaXNoZWQgKi8KICAgIHJldHVybjsKICB9CiAgLyogZXhjZXB0aW9uICovCiAgeGZyZWUoKCp3X2JtcCktPmRhdGFSLCBJRFJHQik7CiAgeGZyZWUoKCp3X2JtcCktPmRhdGFHLCBJRFJHQik7ICAKICB4ZnJlZSgoKndfYm1wKS0+ZGF0YUIsIElEUkdCKTsKICB4ZnJlZSgqd19ibXAsIElEQk1QKTsKICAqd19ibXAgPSAwOwogIHJldHVybjsKfQoKdm9pZCBCTVAyNF9yZWxlYXNlKHN0cnVjdCBCTVAyNCAqYm1wKSB7CiAgaWYgKGJtcC0+ZGF0YVIpIHhmcmVlKGJtcC0+ZGF0YVIsIElEUkdCKTsKICBpZiAoYm1wLT5kYXRhRykgeGZyZWUoYm1wLT5kYXRhRywgSURSR0IpOwogIGlmIChibXAtPmRhdGFCKSB4ZnJlZShibXAtPmRhdGFCLCBJRFJHQik7CiAgaWYgKGJtcC0+ZGF0YVBhbGV0dGUpIHhmcmVlKGJtcC0+ZGF0YVBhbGV0dGUsIElEUEFMRVRURSk7Cn0KCi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KI2RlZmluZSBFUFNJTE9OIDAuMDAwMDAwNQpkb3VibGUgZHpkeChkb3VibGUgeCwgZG91YmxlIHksIGRvdWJsZSAoKnopKGRvdWJsZSwgZG91YmxlKSkgeyByZXR1cm4gKHooeCArIEVQU0lMT04sIHkpIC0geih4LCB5KSkgLyBFUFNJTE9OOyB9CmRvdWJsZSBkemR5KGRvdWJsZSB4LCBkb3VibGUgeSwgZG91YmxlICgqeikoZG91YmxlLCBkb3VibGUpKSB7IHJldHVybiAoeih4LCB5ICsgRVBTSUxPTikgLSB6KHgsIHkpKSAvIEVQU0lMT047IH0KCnN0cnVjdCBmbGlzdCB7CiAgZG91YmxlICgqZikoZG91YmxlLCBkb3VibGUpOwogIGRvdWJsZSAoKmcpKGRvdWJsZSwgZG91YmxlKTsKfTsKCmludCBuZXd0b24oZG91YmxlIHgsIGRvdWJsZSB5LCBkb3VibGUgKnJ4LCBkb3VibGUgKnJ5LCBzdHJ1Y3QgZmxpc3QgZmxpc3QpIHsKICBpbnQgcmM7CiAgZG91YmxlIGgxLCBoMjsKICBkb3VibGUgYSwgYiwgYywgZCwgRDsKCiAgcmMgPSAwOwogIHdoaWxlICgxKSB7CiAgICBhID0gZHpkeCh4LCB5LCBmbGlzdC5mKTsKICAgIGIgPSBkemR5KHgsIHksIGZsaXN0LmYpOwogICAgYyA9IGR6ZHgoeCwgeSwgZmxpc3QuZyk7CiAgICBkID0gZHpkeSh4LCB5LCBmbGlzdC5nKTsKICAgIEQgPSBhICogZCAtIGIgKiBjOwogIAogICAgaWYgKGZhYnMoRCkgPCAgRVBTSUxPTikgewogICAgICByYyA9IC0xOwogICAgICBicmVhazsKICAgIH0KCiAgICBoMSA9IC0gKGQgKiBmbGlzdC5mKHgsIHkpIC0gYiAqIGZsaXN0LmcoeCwgeSkpIC8gRDsKICAgIGgyID0gLSAoKC1jKSAqIGZsaXN0LmYoeCwgeSkgKyBhICogZmxpc3QuZyh4LCB5KSkgLyBEOwoKICAgIHggPSB4ICsgaDE7CiAgICB5ID0geSArIGgyOwoKICAgIGlmIChmYWJzKGgxKSA8IEVQU0lMT04gJiYgYWJzKGgyKSA8IEVQU0lMT04pCiAgICAgIGJyZWFrOwogIH0KICBpZiAocmMgPT0gMCkgewogICAgKnJ4ID0geDsKICAgICpyeSA9IHk7CiAgfSBlbHNlIHsKICAgICpyeCA9ICpyeSA9IDAuMDsKICB9CgogIHJldHVybiByYzsKfQoKLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwpzdHJ1Y3QgY29udmxpc3QgewogIGRvdWJsZSB4OwogIGRvdWJsZSB5OwogIHVuc2lnbmVkIGNoYXIgY29sb3JSOwogIHVuc2lnbmVkIGNoYXIgY29sb3JHOwogIHVuc2lnbmVkIGNoYXIgY29sb3JCOwp9OwoKI2RlZmluZSBBTFBIQSAoMS4wKQp2b2lkIHRhc2soRklMRSAqZnAsIGRvdWJsZSB4X2xsLCBkb3VibGUgeF91bCwgZG91YmxlIHlfbGwsIGRvdWJsZSB5X3VsLCBpbnQgaywKICAgICAgICAgIHN0cnVjdCBmbGlzdCBmbGlzdCwgc3RydWN0IGNvbnZsaXN0IGNsaXN0W10sIGludCBhcmdzKSB7CiAgZG91YmxlIHgsIHk7CiAgZG91YmxlIHJlc194LCByZXNfeTsKICBpbnQgaSwgaiwgaWR4LCByOwogIHVuc2lnbmVkIGNoYXIgY3IsIGNnLCBjYjsKCiAgc3RydWN0IEJNUDI0ICpibXA7CiAgYm1wID0gMDsKICBfQk1QMjRfYWxsb2NhdGlvbigmYm1wLCBrLCBrKTsKCiAgZm9yIChpID0gMDsgaSA8IGs7IGkrKykgewogICAgeCA9ICh4X3VsIC0geF9sbCkgKiBpIC8gKGRvdWJsZSlrICsgeF9sbDsKICAgIGZvciAoaiA9IDA7IGogPCBrOyBqKyspIHsKICAgICAgeSA9ICh5X3VsIC0geV9sbCkgKiBqIC8gKGRvdWJsZSlrICsgeV9sbDsKCiAgICAgIGNyID0gY2cgPSBjYiA9IDA7IGlkeCA9IC0xOwogICAgICBpZiAoKHIgPSBuZXd0b24oeCwgeSwgJnJlc194LCAmcmVzX3ksIGZsaXN0KSkgPT0gMCkgewogICAgICAgIGZvciAoaWR4ID0gMDsgaWR4IDwgYXJnczsgaWR4KyspIHsKICAgICAgICAgIGlmICgoZmFicyhyZXNfeCAtIGNsaXN0W2lkeF0ueCkgPCBBTFBIQSAqIEVQU0lMT04pICYmIChmYWJzKHJlc195IC0gY2xpc3RbaWR4XS55KSA8IEFMUEhBICogRVBTSUxPTikpIHsKICAgICAgICAgICAgY3IgPSBjbGlzdFtpZHhdLmNvbG9yUjsgY2cgPSBjbGlzdFtpZHhdLmNvbG9yRzsgY2IgPSBjbGlzdFtpZHhdLmNvbG9yQjsgCiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaWR4ID09IGFyZ3MpCiAgICAgICAgICBjciA9IGNnID0gY2IgPSAyNTU7CiAgICAgIH0KICAgICAgcHJpbnRmKCIoJWYsICVmKS0+KCVmLCAlZikgIiwgeCwgeSwgcmVzX3gsIHJlc195KTsgcHJpbnRmKCIgOiA8JWQ+KCVkLCAlZCwgJWQpXG4iLCBpZHgsIGNyLCBjZywgY2IpOwogICAgICBibXAtPmRhdGFSW2ogKiBrICsgaV0gPSBjcjsKICAgICAgYm1wLT5kYXRhR1tqICogayArIGldID0gY2c7CiAgICAgIGJtcC0+ZGF0YUJbaiAqIGsgKyBpXSA9IGNiOyAgICAgIAogICAgfQogIH0KICBCTVAyNF93cml0ZShmcCwgYm1wKTsKICBCTVAyNF9yZWxlYXNlKGJtcCk7CiAgeGZyZWUoYm1wLCBJREJNUCk7Cn0KCi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCiNkZWZpbmUgWF9MTCAoLTAuNSkKI2RlZmluZSBZX0xMICgtMC41KQojZGVmaW5lIFhfVUwgMC41CiNkZWZpbmUgWV9VTCAwLjUKI2RlZmluZSBLICAgIDEwMDAKCmRvdWJsZSBmMShkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIHggKiB4ICsgeSAqIHkgLSA4LjA7IH0KZG91YmxlIGcxKGRvdWJsZSB4LCBkb3VibGUgeSkgeyByZXR1cm4geCArIHk7IH0KZG91YmxlIGYyKGRvdWJsZSB4LCBkb3VibGUgeSkgeyByZXR1cm4geCAqIHggKiB4IC0gMy4wICogeCAqIHkgKiB5ICAtIDguMDsgfQpkb3VibGUgZzIoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiB4ICogeCAqIHggLSAzLjAgKiB4ICogeCAqIHk7IH0KCiNkZWZpbmUgRklMRU5BTUUxICJnMS5ibXAiCiNkZWZpbmUgRklMRU5BTUUyICJnMi5ibXAiCmludCBtYWluKCkgewogIEZJTEUgKmZwOwogIGludCBuOwogIHN0cnVjdCBmbGlzdCBmbGlzdDsKICBzdHJ1Y3QgY29udmxpc3QgY2xpc3RbM107CiNpZiAxCiAgaWYgKChmcCA9IGZvcGVuKEZJTEVOQU1FMSwgIndiIikpICE9IDApIHsKICAgIG4gPSAyOwogICAgZmxpc3QuZiA9IGYxOyBmbGlzdC5nID0gZzE7CiAgICBjbGlzdFswXS54ID0gLTIuMDsgY2xpc3RbMF0ueSA9ICsyLjA7IGNsaXN0WzBdLmNvbG9yUiA9IDI1NTsgY2xpc3RbMF0uY29sb3JHID0gY2xpc3RbMF0uY29sb3JCID0gMDsKICAgIGNsaXN0WzFdLnggPSArMi4wOyBjbGlzdFsxXS55ID0gLTIuMDsgY2xpc3RbMV0uY29sb3JSID0gMDsgY2xpc3RbMV0uY29sb3JHID0gMjU1OyBjbGlzdFsxXS5jb2xvckIgPSAwOwogICAgdGFzayhmcCwgWF9MTCwgWF9VTCwgWV9MTCwgWV9VTCwgSywgZmxpc3QsIGNsaXN0LCBuKTsKICAgIGZjbG9zZShmcCk7CiAgfQojZW5kaWYKICBpZiAoKGZwID0gZm9wZW4oRklMRU5BTUUyLCAid2IiKSkgIT0gMCkgewogICAgbiA9IDE7CiAgICBmbGlzdC5mID0gZjI7IGZsaXN0LmcgPSBnMjsKICAgIGNsaXN0WzBdLnggPSAyLjI4OTQyODsgY2xpc3RbMF0ueSA9ICswLjc2MzE0MzsgY2xpc3RbMF0uY29sb3JSID0gMDsgICBjbGlzdFswXS5jb2xvckcgPSAwOyAgIGNsaXN0WzBdLmNvbG9yQiA9IDI1NTsKICAgIHRhc2soZnAsIFhfTEwsIFhfVUwsIFlfTEwsIFlfVUwsIEssIGZsaXN0LCBjbGlzdCwgbik7CiAgICBmY2xvc2UoZnApOwogIH0KCiAgcmV0dXJuIDA7Cn0KCi8qIGVuZCAqLwojaWYgMArlj4LogIPmlofnjK4KaHR0cDovL3MuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmMuanAvc3V1Y2hpLXBkZi8yMDA3LTA0LTExLnBkZgojZW5kaWYK