Changeset 3520 for libpipi


Ignore:
Timestamp:
May 25, 2009, 2:16:44 AM (11 years ago)
Author:
Sam Hocevar
Message:

Tremendously improve img2twit.cpp: only compute the new error around the
updated pixel, compute bit allocation at runtime, weight operations in
order to try usual "winners" more often, increase RGB allocation size.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libpipi/trunk/examples/img2twit.cpp

    r3518 r3520  
    1212#include <pipi.h>
    1313
    14 #define TOTAL_POINTS 138
     14/*
     15 * User-definable settings.
     16 */
     17
     18/* The maximum message length */
     19#define MAX_MSG_LEN 140
     20
     21/* The number of characters at disposal */
     22//#define NUM_CHARACTERS 0x7fffffff // The sky's the limit
     23//#define NUM_CHARACTERS 1111998 // Full valid Unicode set
     24//#define NUM_CHARACTERS 100507 // Full graphic Unicode
     25#define NUM_CHARACTERS 32768 // Chinese characters
     26//#define NUM_CHARACTERS 127 // ASCII
     27
     28/* The maximum image size we want to support */
     29#define MAX_W 4000
     30#define MAX_H 4000
     31
     32/* How does the algorithm work: one point per cell, or two */
    1533#define POINTS_PER_CELL 2
    1634
    17 #define RANGE_X 16
    18 #define RANGE_Y 16
    19 #define RANGE_R 5
    20 #define RANGE_G 5
    21 #define RANGE_B 5
    22 #define RANGE_S 1
     35/* The range value for point parameters: X Y, red/green/blue, "strength"
     36 * Tested values (on Mona Lisa) are:
     37 *  16 16 5 5 5 2 -> 0.06511725914
     38 *  16 16 6 7 6 1 -> 0.05731491348 *
     39 *  16 16 7 6 6 1 -> 0.06450513783
     40 *  14 14 7 7 6 1 -> 0.0637207893
     41 *  19 19 6 6 5 1 -> 0.06801999094 */
     42static unsigned int RANGE_X = 16;
     43static unsigned int RANGE_Y = 16;
     44static unsigned int RANGE_R = 6;
     45static unsigned int RANGE_G = 6;
     46static unsigned int RANGE_B = 6;
     47static unsigned int RANGE_S = 1;
     48
     49/*
     50 * These values are computed at runtime
     51 */
     52
     53static float TOTAL_BITS;
     54static float HEADER_BITS;
     55static float DATA_BITS;
     56static float POINT_BITS;
     57
     58static unsigned int TOTAL_CELLS;
    2359
    2460#define RANGE_SY (RANGE_S*RANGE_Y)
     
    3369
    3470/* Global aspect ratio */
    35 static int dw, dh;
     71static unsigned int dw, dh;
    3672
    3773/* Global point encoding */
     
    4985}
    5086
    51 static inline int float2int(float val, int range)
     87static inline int range2int(float val, int range)
    5288{
    5389    int ret = (int)(val * ((float)range - 0.0001));
    54     return ret < 0 ? 0 : ret > range - 1? range - 1 : ret;
    55 }
    56 
    57 static inline float int2float(int val, int range)
     90    return ret < 0 ? 0 : ret > range - 1 ? range - 1 : ret;
     91}
     92
     93static inline float int2midrange(int val, int range)
    5894{
    5995    return (float)(1 + 2 * val) / (float)(2 * range);
    6096}
    6197
    62 static inline uint32_t set_point(int index, float x, float y, float r,
    63                                  float g, float b, float s)
     98static inline float int2fullrange(int val, int range)
     99{
     100    return range > 1 ? (float)val / (float)(range - 1) : 0.0;
     101}
     102
     103static inline void set_point(int index, float x, float y, float r,
     104                             float g, float b, float s)
    64105{
    65106    int dx = (index / POINTS_PER_CELL) % dw;
     
    69110    float fy = (y - dy * RANGE_Y) / RANGE_Y;
    70111
    71     int is = float2int(s, RANGE_S);
    72 
    73     int ix = float2int(fx, RANGE_X);
    74     int iy = float2int(fy, RANGE_Y);
    75 
    76     int ir = float2int(r, RANGE_R);
    77     int ig = float2int(g, RANGE_G);
    78     int ib = float2int(b, RANGE_B);
     112    int is = range2int(s, RANGE_S);
     113
     114    int ix = range2int(fx, RANGE_X);
     115    int iy = range2int(fy, RANGE_Y);
     116
     117    int ir = range2int(r, RANGE_R);
     118    int ig = range2int(g, RANGE_G);
     119    int ib = range2int(b, RANGE_B);
    79120
    80121    points[index] = is + RANGE_S * (iy + RANGE_Y * (ix + RANGE_X *
     
    90131    unsigned int dy = (index / POINTS_PER_CELL) / dw;
    91132
    92     float fs = int2float(pt % RANGE_S, RANGE_S); pt /= RANGE_S;
    93 
    94     *s = fs < 0.5 ? 0.0 : 1.0;
    95 
    96     float fy = int2float(pt % RANGE_Y, RANGE_Y); pt /= RANGE_Y;
    97     float fx = int2float(pt % RANGE_X, RANGE_X); pt /= RANGE_X;
     133    *s = int2fullrange(pt % RANGE_S, RANGE_S); pt /= RANGE_S;
     134
     135    float fy = int2midrange(pt % RANGE_Y, RANGE_Y); pt /= RANGE_Y;
     136    float fx = int2midrange(pt % RANGE_X, RANGE_X); pt /= RANGE_X;
    98137
    99138    *x = (fx + dx) * RANGE_X;
    100139    *y = (fy + dy) * RANGE_Y;
    101140
    102     *b = int2float(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
    103     *g = int2float(pt % RANGE_G, RANGE_G); pt /= RANGE_G;
    104     *r = int2float(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
     141    *b = int2midrange(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
     142    *g = int2midrange(pt % RANGE_G, RANGE_G); pt /= RANGE_G;
     143    *r = int2midrange(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
    105144}
    106145
     
    115154{
    116155    set_point(npoints, x, y, r, g, b, s);
    117     get_point(npoints, &x, &y, &r, &g, &b, &s);
    118156    npoints++;
    119157}
    120158
    121 #define MAX_OPS 15
     159static void add_random_point()
     160{
     161    points[npoints] = det_rand(RANGE_SYXRGB);
     162    npoints++;
     163}
     164
     165#define NB_OPS 20
     166
     167static uint8_t rand_op(void)
     168{
     169    uint8_t x = det_rand(NB_OPS);
     170
     171    /* Randomly ignore statistically less efficient ops */
     172    if(x == 0)
     173        return rand_op();
     174    if(x == 1 && (RANGE_S == 1 || det_rand(2)))
     175        return rand_op();
     176    if(x <= 5 && det_rand(2))
     177        return rand_op();
     178    //if((x < 10 || x > 15) && !det_rand(4)) /* Favour colour changes */
     179    //    return rand_op();
     180
     181    return x;
     182}
    122183
    123184static uint32_t apply_op(uint8_t op, uint32_t val)
     
    128189    {
    129190    case 0: /* Flip strength value */
     191    case 1:
     192        /* Statistics show that this helps often, but does not reduce
     193         * the error significantly. */
    130194        return val ^ 1;
    131     case 1: /* Move up; if impossible, down */
     195    case 2: /* Move up; if impossible, down */
    132196        rem = val % RANGE_S;
    133197        ext = (val / RANGE_S) % RANGE_Y;
    134198        ext = ext > 0 ? ext - 1 : ext + 1;
    135199        return (val / RANGE_SY * RANGE_Y + ext) * RANGE_S + rem;
    136     case 2: /* Move down; if impossible, up */
     200    case 3: /* Move down; if impossible, up */
    137201        rem = val % RANGE_S;
    138202        ext = (val / RANGE_S) % RANGE_Y;
    139203        ext = ext < RANGE_Y - 1 ? ext + 1 : ext - 1;
    140204        return (val / RANGE_SY * RANGE_Y + ext) * RANGE_S + rem;
    141     case 3: /* Move left; if impossible, right */
     205    case 4: /* Move left; if impossible, right */
    142206        rem = val % RANGE_SY;
    143207        ext = (val / RANGE_SY) % RANGE_X;
    144208        ext = ext > 0 ? ext - 1 : ext + 1;
    145209        return (val / RANGE_SYX * RANGE_X + ext) * RANGE_SY + rem;
    146     case 4: /* Move left; if impossible, right */
     210    case 5: /* Move left; if impossible, right */
    147211        rem = val % RANGE_SY;
    148212        ext = (val / RANGE_SY) % RANGE_X;
    149213        ext = ext < RANGE_X - 1 ? ext + 1 : ext - 1;
    150214        return (val / RANGE_SYX * RANGE_X + ext) * RANGE_SY + rem;
    151     case 5: /* Corner 1 */
    152         return apply_op(1, apply_op(3, val));
    153     case 6: /* Corner 2 */
    154         return apply_op(1, apply_op(4, val));
    155     case 7: /* Corner 3 */
     215    case 6: /* Corner 1 */
    156216        return apply_op(2, apply_op(4, val));
    157     case 8: /* Corner 4 */
    158         return apply_op(2, apply_op(3, val));
    159     case 9: /* R-- (or R++) */
     217    case 7: /* Corner 2 */
     218        return apply_op(2, apply_op(5, val));
     219    case 8: /* Corner 3 */
     220        return apply_op(3, apply_op(5, val));
     221    case 9: /* Corner 4 */
     222        return apply_op(3, apply_op(4, val));
     223    case 16: /* Double up */
     224        return apply_op(2, apply_op(2, val));
     225    case 17: /* Double down */
     226        return apply_op(3, apply_op(3, val));
     227    case 18: /* Double left */
     228        return apply_op(4, apply_op(4, val));
     229    case 19: /* Double right */
     230        return apply_op(5, apply_op(5, val));
     231    case 10: /* R-- (or R++) */
    160232        rem = val % RANGE_SYX;
    161233        ext = (val / RANGE_SYX) % RANGE_R;
    162234        ext = ext > 0 ? ext - 1 : ext + 1;
    163235        return (val / RANGE_SYXR * RANGE_R + ext) * RANGE_SYX + rem;
    164     case 10: /* R++ (or R--) */
     236    case 11: /* R++ (or R--) */
    165237        rem = val % RANGE_SYX;
    166238        ext = (val / RANGE_SYX) % RANGE_R;
    167239        ext = ext < RANGE_R - 1 ? ext + 1 : ext - 1;
    168240        return (val / RANGE_SYXR * RANGE_R + ext) * RANGE_SYX + rem;
    169     case 11: /* G-- (or G++) */
     241    case 12: /* G-- (or G++) */
    170242        rem = val % RANGE_SYXR;
    171243        ext = (val / RANGE_SYXR) % RANGE_G;
    172244        ext = ext > 0 ? ext - 1 : ext + 1;
    173245        return (val / RANGE_SYXRG * RANGE_G + ext) * RANGE_SYXR + rem;
    174     case 12: /* G++ (or G--) */
     246    case 13: /* G++ (or G--) */
    175247        rem = val % RANGE_SYXR;
    176248        ext = (val / RANGE_SYXR) % RANGE_G;
    177249        ext = ext < RANGE_G - 1 ? ext + 1 : ext - 1;
    178250        return (val / RANGE_SYXRG * RANGE_G + ext) * RANGE_SYXR + rem;
    179     case 13: /* B-- (or B++) */
     251    case 14: /* B-- (or B++) */
    180252        rem = val % RANGE_SYXRG;
    181253        ext = (val / RANGE_SYXRG) % RANGE_B;
    182254        ext = ext > 0 ? ext - 1 : ext + 1;
    183255        return ext * RANGE_SYXRG + rem;
    184     case 14: /* B++ (or B--) */
     256    case 15: /* B++ (or B--) */
    185257        rem = val % RANGE_SYXRG;
    186258        ext = (val / RANGE_SYXRG) % RANGE_B;
     
    212284static void render(pipi_image_t *dst, int rx, int ry, int rw, int rh)
    213285{
    214     uint8_t lookup[TOTAL_POINTS / POINTS_PER_CELL * RANGE_X * RANGE_Y];
     286    uint8_t lookup[TOTAL_CELLS * RANGE_X * RANGE_Y];
    215287    pipi_pixels_t *p = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
    216288    float *data = (float *)p->pixels;
    217     float fx, fy, fr, fg, fb, fs;
    218289    int i, x, y;
    219290
     
    222293    for(i = 0; i < npoints; i++)
    223294    {
     295        float fx, fy, fr, fg, fb, fs;
    224296        get_point(i, &fx, &fy, &fr, &fg, &fb, &fs);
    225297        lookup[(int)fx + dw * RANGE_X * (int)fy] = i; /* Keep link to point */
     
    237309        for(x = rx; x < rx + rw; x++)
    238310        {
    239             int i1 = 0, i2 = 0, i3 = 0;
    240             float d1 = 1000000, d2 = 0, d3 = 0;
    241 
    242311            K::Point_2 m(x, y);
    243312            Point_coordinate_vector coords;
     
    253322            for(it = coords.begin(); it != coords.end(); ++it)
    254323            {
    255                 float fx = (*it).first.x();
    256                 float fy = (*it).first.y();
     324                float fx, fy, fr, fg, fb, fs;
     325
     326                fx = (*it).first.x();
     327                fy = (*it).first.y();
    257328
    258329                if(fx < 0 || fy < 0 || fx > p->w - 1 || fy > p->h - 1)
     
    263334                get_point(index, &fx, &fy, &fr, &fg, &fb, &fs);
    264335
    265                 float k = (*it).second;
    266                 if(fs > 0.5) k = pow(k, 1.2);
    267                 else k = pow(k, 0.8);
    268                 //float k = (*it).second * (1.0f + fs);
     336                //float k = pow((*it).second * (1.0 + fs), 1.2);
     337                float k = (*it).second * (1.00f + fs);
     338                //float k = (*it).second * (0.60f + fs);
     339                //float k = pow((*it).second, (1.0f + fs));
    269340
    270341                r += k * fr;
     
    288359    pipi_pixels_t *p = pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
    289360    float *data = (float *)p->pixels;
    290     int i;
    291 
    292     for(int dy = 0; dy < dh; dy++)
    293         for(int dx = 0; dx < dw; dx++)
     361
     362    for(unsigned int dy = 0; dy < dh; dy++)
     363        for(unsigned int dx = 0; dx < dw; dx++)
    294364        {
    295365            float min = 1.1f, max = -0.1f;
     
    298368            int npixels = 0;
    299369
    300             for(int iy = RANGE_Y * dy; iy < RANGE_Y * (dy + 1); iy++)
    301                 for(int ix = RANGE_X * dx; ix < RANGE_X * (dx + 1); ix++)
     370            for(unsigned int iy = RANGE_Y * dy; iy < RANGE_Y * (dy + 1); iy++)
     371                for(unsigned int ix = RANGE_X * dx; ix < RANGE_X * (dx + 1); ix++)
    302372                {
    303373                    float lum = 0.0f;
     
    331401            if(total < min + (max - min) / 4)
    332402                wmin = 1.0, wmax = 0.0;
    333             else if(total < min + (max - min) / 4 * 2)
    334                 wmin = 0.0, wmax = 0.0;
    335403            else if(total < min + (max - min) / 4 * 3)
    336404                wmin = 0.0, wmax = 0.0;
     
    338406                wmin = 0.0, wmax = 1.0;
    339407
    340 //wmin = wmax = 1.0;
    341 //if(total < min + (max - min) /3 )
    342 //if((dx + dy) & 1)
    343 {
     408#if 0
     409add_random_point();
     410add_random_point();
     411#else
     412#if POINTS_PER_CELL == 1
     413            if(total < min + (max - min) / 2)
     414            {
     415#endif
    344416            add_point(xmin, ymin,
    345417                      data[4 * (xmin + ymin * p->w) + 0],
     
    347419                      data[4 * (xmin + ymin * p->w) + 2],
    348420                      wmin);
    349 }
    350 //else
    351 {
     421#if POINTS_PER_CELL == 1
     422            }
     423            else
     424            {
     425#endif
    352426            add_point(xmax, ymax,
    353427                      data[4 * (xmax + ymax * p->w) + 0],
     
    355429                      data[4 * (xmax + ymax * p->w) + 2],
    356430                      wmax);
    357 }
     431#if POINTS_PER_CELL == 1
     432            }
     433#endif
     434#endif
    358435        }
    359436}
     
    361438int main(int argc, char *argv[])
    362439{
    363     int opstats[2 * MAX_OPS];
     440    int opstats[2 * NB_OPS];
    364441    pipi_image_t *src, *tmp, *dst;
    365442    double error = 1.0;
    366443    int width, height, ret = 0;
     444
     445    /* Compute bit allocation */
     446    fprintf(stderr, "Available characters: %i\n", NUM_CHARACTERS);
     447    fprintf(stderr, "Maximum message size: %i\n", MAX_MSG_LEN);
     448    TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2);
     449    fprintf(stderr, "Available bits: %f\n", TOTAL_BITS);
     450    fprintf(stderr, "Maximum image resolution: %ix%i\n", MAX_W, MAX_H);
     451    HEADER_BITS = logf(MAX_W * MAX_H) / logf(2);
     452    fprintf(stderr, "Header bits: %f\n", HEADER_BITS);
     453    DATA_BITS = TOTAL_BITS - HEADER_BITS;
     454    fprintf(stderr, "Bits available for data: %f\n", DATA_BITS);
     455#if POINTS_PER_CELL == 1
     456    POINT_BITS = logf(RANGE_SYXRGB) / logf(2);
     457#else
     458    float coord_bits = logf((RANGE_Y * RANGE_X) * (RANGE_Y * RANGE_X + 1) / 2);
     459    float other_bits = logf(RANGE_R * RANGE_G * RANGE_B * RANGE_S);
     460    POINT_BITS = (coord_bits + 2 * other_bits) / logf(2);
     461#endif
     462    fprintf(stderr, "Cell bits: %f\n", POINT_BITS);
     463    TOTAL_CELLS = (int)(DATA_BITS / POINT_BITS);
     464    fprintf(stderr, "Available cells: %i\n", TOTAL_CELLS);
     465    fprintf(stderr, "Wasted bits: %f\n", DATA_BITS - POINT_BITS * TOTAL_CELLS);
    367466
    368467    /* Load image */
     
    373472
    374473    /* Compute best w/h ratio */
    375     dw = 1;
    376     for(int i = 1; i <= TOTAL_POINTS / POINTS_PER_CELL; i++)
     474    dw = 1; dh = TOTAL_CELLS;
     475    for(unsigned int i = 1; i <= TOTAL_CELLS; i++)
    377476    {
     477        int j = TOTAL_CELLS / i;
     478
    378479        float r = (float)width / (float)height;
    379         float ir = (float)i / (float)(TOTAL_POINTS / POINTS_PER_CELL / i);
    380         float dwr = (float)dw / (float)(TOTAL_POINTS / POINTS_PER_CELL / dw);
     480        float ir = (float)i / (float)j;
     481        float dwr = (float)dw / (float)dh;
    381482
    382483        if(fabs(logf(r / ir)) < fabs(logf(r / dwr)))
     484        {
    383485            dw = i;
     486            dh = TOTAL_CELLS / dw;
     487        }
    384488    }
    385     dh = TOTAL_POINTS / POINTS_PER_CELL / dw;
    386     fprintf(stderr, "Chosen image ratio: %i:%i\n", dw, dh);
     489    while((dh + 1) * dw <= TOTAL_CELLS) dh++;
     490    while(dw * (dh + 1) <= TOTAL_CELLS) dw++;
     491    fprintf(stderr, "Chosen image ratio: %i:%i (wasting %i point cells)\n",
     492            dw, dh, TOTAL_CELLS - dw * dh);
     493    fprintf(stderr, "Total wasted bits: %f\n",
     494            DATA_BITS - POINT_BITS * dw * dh);
    387495
    388496    /* Resize and filter image to better state */
    389497    tmp = pipi_resize(src, dw * RANGE_X, dh * RANGE_Y);
    390498    pipi_free(src);
    391     src = pipi_median_ext(tmp, 2, 2);
     499    src = pipi_median_ext(tmp, 1, 1);
     500    pipi_free(tmp);
    392501
    393502    /* Analyse image */
     
    402511
    403512    memset(opstats, 0, sizeof(opstats));
    404     for(int iter = 0, failures = 0; /*failures < 200 &&*/ iter < 3000; iter++)
     513    for(int iter = 0, stuck = 0, failures = 0, success = 0;
     514        /*stuck < 5 && */iter < 10000;
     515        iter++)
    405516    {
    406         uint32_t oldval;
     517        if(failures > 500)
     518        {
     519            stuck++;
     520            failures = 0;
     521        }
     522
    407523        pipi_image_t *scrap = pipi_copy(tmp);
    408524
    409525        /* Choose a point at random */
    410526        int pt = det_rand(npoints);
    411         oldval = points[pt];
    412 
    413         /* Apply a random operation and measure its effect */
    414         uint8_t op = det_rand(MAX_OPS);
    415         points[pt] = apply_op(op, oldval);
    416         render(scrap, 0, 0, dw * RANGE_X, dh * RANGE_Y);
    417 
    418         opstats[op * 2]++;
    419 
    420         double newerr = pipi_measure_rmsd(src, scrap);
    421         if(newerr < error)
     527        uint32_t oldval = points[pt];
     528
     529        /* Compute the affected image zone */
     530        float fx, fy, fr, fg, fb, fs;
     531        get_point(pt, &fx, &fy, &fr, &fg, &fb, &fs);
     532        int zonex = (int)fx / RANGE_X - 1;
     533        int zoney = (int)fy / RANGE_Y - 1;
     534        int zonew = 3;
     535        int zoneh = 3;
     536        if(zonex < 0) { zonex = 0; zonew--; }
     537        if(zoney < 0) { zoney = 0; zoneh--; }
     538        if(zonex + zonew >= (int)dw) { zonew--; }
     539        if(zoney + zoneh >= (int)dh) { zoneh--; }
     540
     541        /* Choose random operations and measure their effect */
     542        uint8_t op1 = rand_op();
     543        //uint8_t op2 = rand_op();
     544
     545        uint32_t candidates[3];
     546        double besterr = error + 1.0;
     547        int bestop = -1;
     548        candidates[0] = apply_op(op1, oldval);
     549        //candidates[1] = apply_op(op2, oldval);
     550        //candidates[2] = apply_op(op1, apply_op(op2, oldval));
     551
     552        for(int i = 0; i < 1; i++)
     553        //for(int i = 0; i < 3; i++)
    422554        {
     555            if(oldval == candidates[i])
     556                continue;
     557
     558            points[pt] = candidates[i];
     559
     560            render(scrap, zonex * RANGE_X, zoney * RANGE_Y,
     561                   zonew * RANGE_X, zoneh * RANGE_Y);
     562
     563            double newerr = pipi_measure_rmsd(src, scrap);
     564            if(newerr < besterr)
     565            {
     566                besterr = newerr;
     567                bestop = i;
     568            }
     569        }
     570
     571        opstats[op1 * 2]++;
     572        //opstats[op2 * 2]++;
     573
     574        if(besterr < error)
     575        {
     576            points[pt] = candidates[bestop];
     577            /* Redraw image if the last check wasn't the best one */
     578            if(bestop != 2)
     579                render(scrap, zonex * RANGE_X, zoney * RANGE_Y,
     580                       zonew * RANGE_X, zoneh * RANGE_Y);
     581
    423582            pipi_free(tmp);
    424583            tmp = scrap;
    425             error = newerr;
    426             fprintf(stderr, "%06i %2.010g after op%i(%i)\n",
    427                     iter, error, op, pt);
    428             opstats[op * 2 + 1]++;
     584            //fprintf(stderr, "%08i %2.010g %2.010g after op%i(%i)\n",
     585            //        iter, besterr - error, error, op1, pt);
     586            fprintf(stderr, "%08i -.%08i %2.010g after op%i(%i)\n", iter,
     587                    (int)((error - besterr) * 100000000), error, op1, pt);
     588            error = besterr;
     589            opstats[op1 * 2 + 1]++;
     590            //opstats[op2 * 2 + 1]++;
    429591            failures = 0;
     592            success++;
     593
     594            /* Save image! */
     595            //char buf[128];
     596            //sprintf(buf, "twit%08i.bmp", success);
     597            //if((success % 10) == 0)
     598            //    pipi_save(tmp, buf);
    430599        }
    431600        else
     
    437606    }
    438607
    439     fprintf(stderr,   "operation: ");
    440     for(int i = 0; i < MAX_OPS; i++)
    441         fprintf(stderr, "%3i ", i);
    442     fprintf(stderr, "\nattempts:  ");
    443     for(int i = 0; i < MAX_OPS; i++)
    444         fprintf(stderr, "%3i ", opstats[i * 2]);
    445     fprintf(stderr, "\nsuccesses: ");
    446     for(int i = 0; i < MAX_OPS; i++)
    447         fprintf(stderr, "%3i ", opstats[i * 2 + 1]);
    448     fprintf(stderr, "\n");
     608    for(int j = 0; j < 2; j++)
     609    {
     610        fprintf(stderr,   "operation: ");
     611        for(int i = NB_OPS / 2 * j; i < NB_OPS / 2 * (j + 1); i++)
     612            fprintf(stderr, "%4i ", i);
     613        fprintf(stderr, "\nattempts:  ");
     614        for(int i = NB_OPS / 2 * j; i < NB_OPS / 2 * (j + 1); i++)
     615            fprintf(stderr, "%4i ", opstats[i * 2]);
     616        fprintf(stderr, "\nsuccesses: ");
     617        for(int i = NB_OPS / 2 * j; i < NB_OPS / 2 * (j + 1); i++)
     618            fprintf(stderr, "%4i ", opstats[i * 2 + 1]);
     619        fprintf(stderr, "\n");
     620    }
    449621
    450622    fprintf(stderr, "Distance: %2.10g\n", error);
Note: See TracChangeset for help on using the changeset viewer.