#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);
}
/*---------------------------------------------------------------------------*/
struct flist {
double (*f)(double, double);
double (*g)(double, double);
double (*dfdx)(double, double);
double (*dfdy)(double, double);
double (*dgdx)(double, double);
double (*dgdy)(double, double);
};
#define EPSILON 0.0000005
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 = flist.dfdx(x, y);
b = flist.dfdy(x, y);
c = flist.dgdx(x, y);
d = flist.dgdy(x, y);
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
)) { printf("(1):(%d)(%d, %d, %d)\n", idx
, cr
, cg
, cb
); cr = clist[idx].colorR; cg = clist[idx].colorG; cb = clist[idx].colorB;
printf("(2):(%d)(%d, %d, %d)\n", idx
, cr
, cg
, cb
); 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 dfdx1(double x, double y) { return 2.0 * x; }
double dfdy1(double x, double y) { return 2.0 * y; }
double dgdx1(double x, double y) { return 1.0; }
double dgdy1(double x, double y) { return 1.0; }
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; }
double dfdx2(double x, double y) { return 3.0 * x * x - 3.0 * y * y; }
double dfdy2(double x, double y) { return -6.0 * x * y; }
double dgdx2(double x, double y) { return 3.0 * x * x - 6.0 * x * y; }
double dgdy2(double x, double y) { return -3.0 * x * x; }
#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; flist.dfdx = dfdx1; flist.dfdy = dfdy1; flist.dgdx = dgdx1; flist.dgdy = dgdy1;
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 = 3;
flist.f = f2; flist.g = g2; flist.dfdx = dfdx2; flist.dfdy = dfdy2; flist.dgdx = dgdx2; flist.dgdy = dgdy2;
clist[0].x = 2.289428; clist[0].y = +0.763143; clist[0].colorR = 0; clist[0].colorG = 0; clist[0].colorB = 255;
clist[1].x = 2.394859; clist[1].y = -0.798286; clist[1].colorR = 255; clist[1].colorG = 0; clist[1].colorB = 0;
clist[2].x = 2.394859; clist[2].y = +0.798286; clist[2].colorR = 0; clist[2].colorG = 255; clist[2].colorB = 0;
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+ZGF0YVBhbGV0dGUsIElEUEFMRVRURSk7Cn0KCi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8Kc3RydWN0IGZsaXN0IHsKICBkb3VibGUgKCpmKShkb3VibGUsIGRvdWJsZSk7CiAgZG91YmxlICgqZykoZG91YmxlLCBkb3VibGUpOwogIGRvdWJsZSAoKmRmZHgpKGRvdWJsZSwgZG91YmxlKTsKICBkb3VibGUgKCpkZmR5KShkb3VibGUsIGRvdWJsZSk7CiAgZG91YmxlICgqZGdkeCkoZG91YmxlLCBkb3VibGUpOwogIGRvdWJsZSAoKmRnZHkpKGRvdWJsZSwgZG91YmxlKTsKfTsKCiNkZWZpbmUgRVBTSUxPTiAwLjAwMDAwMDUKaW50IG5ld3Rvbihkb3VibGUgeCwgZG91YmxlIHksIGRvdWJsZSAqcngsIGRvdWJsZSAqcnksIHN0cnVjdCBmbGlzdCBmbGlzdCkgewogIGludCByYzsKICBkb3VibGUgaDEsIGgyOwogIGRvdWJsZSBhLCBiLCBjLCBkLCBEOwoKICByYyA9IDA7CiAgd2hpbGUgKDEpIHsKICAgIGEgPSBmbGlzdC5kZmR4KHgsIHkpOwogICAgYiA9IGZsaXN0LmRmZHkoeCwgeSk7CiAgICBjID0gZmxpc3QuZGdkeCh4LCB5KTsKICAgIGQgPSBmbGlzdC5kZ2R5KHgsIHkpOwogICAgRCA9IGEgKiBkIC0gYiAqIGM7CiAgCiAgICBpZiAoZmFicyhEKSA8ICBFUFNJTE9OKSB7CiAgICAgIHJjID0gLTE7CiAgICAgIGJyZWFrOwogICAgfQoKICAgIGgxID0gLSAoZCAqIGZsaXN0LmYoeCwgeSkgLSBiICogZmxpc3QuZyh4LCB5KSkgLyBEOwogICAgaDIgPSAtICgoLWMpICogZmxpc3QuZih4LCB5KSArIGEgKiBmbGlzdC5nKHgsIHkpKSAvIEQ7CgogICAgeCA9IHggKyBoMTsKICAgIHkgPSB5ICsgaDI7CgogICAgaWYgKGZhYnMoaDEpIDwgRVBTSUxPTiAmJiBhYnMoaDIpIDwgRVBTSUxPTikKICAgICAgYnJlYWs7CiAgfQogIGlmIChyYyA9PSAwKSB7CiAgICAqcnggPSB4OwogICAgKnJ5ID0geTsKICB9IGVsc2UgewogICAgKnJ4ID0gKnJ5ID0gMC4wOwogIH0KCiAgcmV0dXJuIHJjOwp9CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCnN0cnVjdCBjb252bGlzdCB7CiAgZG91YmxlIHg7CiAgZG91YmxlIHk7CiAgdW5zaWduZWQgY2hhciBjb2xvclI7CiAgdW5zaWduZWQgY2hhciBjb2xvckc7CiAgdW5zaWduZWQgY2hhciBjb2xvckI7Cn07CgojZGVmaW5lIEFMUEhBICgxLjApCnZvaWQgdGFzayhGSUxFICpmcCwgZG91YmxlIHhfbGwsIGRvdWJsZSB4X3VsLCBkb3VibGUgeV9sbCwgZG91YmxlIHlfdWwsIGludCBrLAogICAgICAgICAgc3RydWN0IGZsaXN0IGZsaXN0LCBzdHJ1Y3QgY29udmxpc3QgY2xpc3RbXSwgaW50IGFyZ3MpIHsKICBkb3VibGUgeCwgeTsKICBkb3VibGUgcmVzX3gsIHJlc195OwogIGludCBpLCBqLCBpZHgsIHI7CiAgdW5zaWduZWQgY2hhciBjciwgY2csIGNiOwoKICBzdHJ1Y3QgQk1QMjQgKmJtcDsKICBibXAgPSAwOwogIF9CTVAyNF9hbGxvY2F0aW9uKCZibXAsIGssIGspOwoKICBmb3IgKGkgPSAwOyBpIDwgazsgaSsrKSB7CiAgICB4ID0gKHhfdWwgLSB4X2xsKSAqIGkgLyAoZG91YmxlKWsgKyB4X2xsOwogICAgZm9yIChqID0gMDsgaiA8IGs7IGorKykgewogICAgICB5ID0gKHlfdWwgLSB5X2xsKSAqIGogLyAoZG91YmxlKWsgKyB5X2xsOwoKICAgICAgY3IgPSBjZyA9IGNiID0gMDsgaWR4ID0gLTE7CiAgICAgIGlmICgociA9IG5ld3Rvbih4LCB5LCAmcmVzX3gsICZyZXNfeSwgZmxpc3QpKSA9PSAwKSB7CiAgICAgICAgZm9yIChpZHggPSAwOyBpZHggPCBhcmdzOyBpZHgrKykgewogICAgICAgICAgaWYgKChmYWJzKHJlc194IC0gY2xpc3RbaWR4XS54KSA8IEFMUEhBICogRVBTSUxPTikgJiYgKGZhYnMocmVzX3kgLSBjbGlzdFtpZHhdLnkpIDwgQUxQSEEgKiBFUFNJTE9OKSkgewogICAgICAgICAgICBwcmludGYoIigxKTooJWQpKCVkLCAlZCwgJWQpXG4iLCBpZHgsIGNyLCBjZywgY2IpOwogICAgICAgICAgICBjciA9IGNsaXN0W2lkeF0uY29sb3JSOyBjZyA9IGNsaXN0W2lkeF0uY29sb3JHOyBjYiA9IGNsaXN0W2lkeF0uY29sb3JCOyAKICAgICAgICAgICAgcHJpbnRmKCIoMik6KCVkKSglZCwgJWQsICVkKVxuIiwgaWR4LCBjciwgY2csIGNiKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChpZHggPT0gYXJncykKICAgICAgICAgIGNyID0gY2cgPSBjYiA9IDI1NTsKICAgICAgfQovKiAgICAgIHByaW50ZigiKCVmLCAlZiktPiglZiwgJWYpICIsIHgsIHksIHJlc194LCByZXNfeSk7IHByaW50ZigiIDogPCVkPiglZCwgJWQsICVkKVxuIiwgaWR4LCBjciwgY2csIGNiKTsgKi8KICAgICAgYm1wLT5kYXRhUltqICogayArIGldID0gY3I7CiAgICAgIGJtcC0+ZGF0YUdbaiAqIGsgKyBpXSA9IGNnOwogICAgICBibXAtPmRhdGFCW2ogKiBrICsgaV0gPSBjYjsgICAgICAKICAgIH0KICB9CiAgQk1QMjRfd3JpdGUoZnAsIGJtcCk7CiAgQk1QMjRfcmVsZWFzZShibXApOwogIHhmcmVlKGJtcCwgSURCTVApOwp9CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwojZGVmaW5lIFhfTEwgKC0wLjUpCiNkZWZpbmUgWV9MTCAoLTAuNSkKI2RlZmluZSBYX1VMIDAuNQojZGVmaW5lIFlfVUwgMC41CiNkZWZpbmUgSyAgICAxMDAwCgpkb3VibGUgZjEoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiB4ICogeCArIHkgKiB5IC0gOC4wOyB9CmRvdWJsZSBnMShkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIHggKyB5OyB9CmRvdWJsZSBkZmR4MShkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIDIuMCAqIHg7IH0KZG91YmxlIGRmZHkxKGRvdWJsZSB4LCBkb3VibGUgeSkgeyByZXR1cm4gMi4wICogeTsgfQpkb3VibGUgZGdkeDEoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiAxLjA7IH0KZG91YmxlIGRnZHkxKGRvdWJsZSB4LCBkb3VibGUgeSkgeyByZXR1cm4gMS4wOyB9Cgpkb3VibGUgZjIoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiB4ICogeCAqIHggLSAzLjAgKiB4ICogeSAqIHkgIC0gOC4wOyB9CmRvdWJsZSBnMihkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIHggKiB4ICogeCAtIDMuMCAqIHggKiB4ICogeTsgfQpkb3VibGUgZGZkeDIoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiAzLjAgKiB4ICogeCAtIDMuMCAqIHkgKiB5OyB9CmRvdWJsZSBkZmR5Mihkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIC02LjAgKiB4ICogeTsgfQpkb3VibGUgZGdkeDIoZG91YmxlIHgsIGRvdWJsZSB5KSB7IHJldHVybiAzLjAgKiB4ICogeCAtIDYuMCAqIHggKiB5OyB9CmRvdWJsZSBkZ2R5Mihkb3VibGUgeCwgZG91YmxlIHkpIHsgcmV0dXJuIC0zLjAgKiB4ICogeDsgfQoKI2RlZmluZSBGSUxFTkFNRTEgImcxLmJtcCIKI2RlZmluZSBGSUxFTkFNRTIgImcyLmJtcCIKaW50IG1haW4oKSB7CiAgRklMRSAqZnA7CiAgaW50IG47CiAgc3RydWN0IGZsaXN0IGZsaXN0OwogIHN0cnVjdCBjb252bGlzdCBjbGlzdFszXTsKI2lmIDEKICBpZiAoKGZwID0gZm9wZW4oRklMRU5BTUUxLCAid2IiKSkgIT0gMCkgewogICAgbiA9IDI7CiAgICBmbGlzdC5mID0gZjE7IGZsaXN0LmcgPSBnMTsgZmxpc3QuZGZkeCA9IGRmZHgxOyBmbGlzdC5kZmR5ID0gZGZkeTE7IGZsaXN0LmRnZHggPSBkZ2R4MTsgZmxpc3QuZGdkeSA9IGRnZHkxOwogICAgY2xpc3RbMF0ueCA9IC0yLjA7IGNsaXN0WzBdLnkgPSArMi4wOyBjbGlzdFswXS5jb2xvclIgPSAyNTU7IGNsaXN0WzBdLmNvbG9yRyA9IGNsaXN0WzBdLmNvbG9yQiA9IDA7CiAgICBjbGlzdFsxXS54ID0gKzIuMDsgY2xpc3RbMV0ueSA9IC0yLjA7IGNsaXN0WzFdLmNvbG9yUiA9IDA7IGNsaXN0WzFdLmNvbG9yRyA9IDI1NTsgY2xpc3RbMV0uY29sb3JCID0gMDsKICAgIHRhc2soZnAsIFhfTEwsIFhfVUwsIFlfTEwsIFlfVUwsIEssIGZsaXN0LCBjbGlzdCwgbik7CiAgICBmY2xvc2UoZnApOwogIH0KI2VuZGlmCiAgaWYgKChmcCA9IGZvcGVuKEZJTEVOQU1FMiwgIndiIikpICE9IDApIHsKICAgIG4gPSAzOwogICAgZmxpc3QuZiA9IGYyOyBmbGlzdC5nID0gZzI7IGZsaXN0LmRmZHggPSBkZmR4MjsgZmxpc3QuZGZkeSA9IGRmZHkyOyBmbGlzdC5kZ2R4ID0gZGdkeDI7IGZsaXN0LmRnZHkgPSBkZ2R5MjsKICAgIGNsaXN0WzBdLnggPSAyLjI4OTQyODsgY2xpc3RbMF0ueSA9ICswLjc2MzE0MzsgY2xpc3RbMF0uY29sb3JSID0gMDsgICBjbGlzdFswXS5jb2xvckcgPSAwOyAgIGNsaXN0WzBdLmNvbG9yQiA9IDI1NTsKICAgIGNsaXN0WzFdLnggPSAyLjM5NDg1OTsgY2xpc3RbMV0ueSA9IC0wLjc5ODI4NjsgY2xpc3RbMV0uY29sb3JSID0gMjU1OyBjbGlzdFsxXS5jb2xvckcgPSAwOyAgIGNsaXN0WzFdLmNvbG9yQiA9IDA7CiAgICBjbGlzdFsyXS54ID0gMi4zOTQ4NTk7IGNsaXN0WzJdLnkgPSArMC43OTgyODY7IGNsaXN0WzJdLmNvbG9yUiA9IDA7ICAgY2xpc3RbMl0uY29sb3JHID0gMjU1OyBjbGlzdFsyXS5jb2xvckIgPSAwOwogICAgdGFzayhmcCwgWF9MTCwgWF9VTCwgWV9MTCwgWV9VTCwgSywgZmxpc3QsIGNsaXN0LCBuKTsKICAgIGZjbG9zZShmcCk7CiAgfQoKCgoKICByZXR1cm4gMDsKfQoKLyogZW5kICovCiNpZiAwCuWPguiAg+aWh+eMrgpodHRwOi8vcy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uYy5qcC9zdXVjaGktcGRmLzIwMDctMDQtMTEucGRmCiNlbmRpZgo=