Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #140290 > unrolled thread

Simple 2d C99 fractal plotter...

Started by"Chris M. Thomasson" <ahh_f_it@crap.nothing>
First post2019-01-25 14:24 -0800
Last post2019-02-11 13:44 -0800
Articles 20 on this page of 41 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  Simple 2d C99 fractal plotter... "Chris M. Thomasson" <ahh_f_it@crap.nothing> - 2019-01-25 14:24 -0800
    Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson " <ahh_f_it@crap.nothing> - 2019-01-25 15:11 -0800
    Re: Simple 2d C99 fractal plotter... Eli the Bearded <*@eli.users.panix.com> - 2019-01-25 23:50 +0000
      Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <ahh_f_it@crap.nothing> - 2019-01-25 16:33 -0800
      Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 00:45 +0000
        Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson " <ahh_f_it@crap.nothing> - 2019-01-25 16:55 -0800
          Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 00:59 +0000
        Re: Simple 2d C99 fractal plotter... Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-01-26 20:29 +0000
          Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 21:37 +0000
            Re: Simple 2d C99 fractal plotter... Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-01-27 12:11 +0000
              Re: Simple 2d C99 fractal plotter... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-01-27 13:40 +0000
    Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 00:57 +0000
      Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <ahh_f_it@crap.nothing> - 2019-01-27 15:37 -0800
    Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 12:35 +0000
      Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-01-27 13:20 +0100
        Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-27 14:13 +0000
          Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-01-27 16:36 +0100
            Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <ahh_f_it@crap.nothing> - 2019-01-27 14:28 -0800
              Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-27 23:53 +0000
            Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-01-29 13:11 -0800
              Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-29 22:23 +0000
                Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-02-04 15:30 -0800
                  Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-02-05 01:26 +0000
                    Re: Simple 2d C99 fractal plotter... Ian Collins <ian-news@hotmail.com> - 2019-02-05 16:14 +1300
                    Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-02-05 11:38 +0100
                      Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-02-05 11:14 +0000
                        Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-02-05 14:35 +0100
                          Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-02-05 15:06 +0000
                            Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-02-05 17:02 +0100
                              Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-02-05 19:07 +0000
                                Re: Simple 2d C99 fractal plotter... Ian Collins <ian-news@hotmail.com> - 2019-02-06 08:12 +1300
                                Re: Simple 2d C99 fractal plotter... Keith Thompson <kst-u@mib.org> - 2019-02-05 12:49 -0800
                                Re: Simple 2d C99 fractal plotter... David Brown <david.brown@hesbynett.no> - 2019-02-05 22:39 +0100
          Re: Simple 2d C99 fractal plotter... Keith Thompson <kst-u@mib.org> - 2019-01-27 13:09 -0800
    Re: Simple 2d C99 fractal plotter... Bart <bc@freeuk.com> - 2019-01-26 18:53 +0000
      Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <ahh_f_it@crap.nothing> - 2019-01-26 18:21 -0800
    Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-01-28 22:20 -0800
      Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-01-28 22:55 -0800
        Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-01-28 23:03 -0800
      Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-02-06 22:37 -0800
        Re: Simple 2d C99 fractal plotter... "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-02-11 13:44 -0800

Page 1 of 3  [1] 2 3  Next page →


#140290 — Simple 2d C99 fractal plotter...

From"Chris M. Thomasson" <ahh_f_it@crap.nothing>
Date2019-01-25 14:24 -0800
SubjectSimple 2d C99 fractal plotter...
Message-ID<q2g2bo$deg$1@dont-email.me>
Just wondering, when you get some free time, if you can perhaps run the 
my experimental plotter code that generates a PPM called "ct_plane.ppm". 
And if you can see a fractal in the resulting rendering. Here is my C99 
code:

https://pastebin.com/raw/322XAnsT
(raw text, pure C99: no ads!)

It should just compile with GCC, and run like a charm. It has proper 
aspect ratios so one can use any dimensions they want.

Can you notice anything wrong with the code below:

Btw, Hugh is one of my fractal friends... :^)
___________________________
/*
     A Simple 2d Plane For Hugh, with proper aspect ratios!
     By: Chris M. Thomasson
*_____________________________________________________________*/


#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>
#include <stdbool.h>


#define CT_WIDTH 1920
#define CT_HEIGHT 1080
#define CT_N 5000000


struct ct_canvas
{
     unsigned long width;
     unsigned long height;
     unsigned char* buf;
};

bool
ct_canvas_create(
     struct ct_canvas* const self,
     unsigned long width,
     unsigned long height
){
     size_t size = width * height;

     self->buf = calloc(1, size);

     if (self->buf)
     {
         self->width = width;
         self->height = height;

         return true;
     }

     return false;
}

void
ct_canvas_destroy(
     struct ct_canvas const* const self
){
     free(self->buf);
}

bool
ct_canvas_save_ppm(
     struct ct_canvas const* const self,
     char const* fname
){
     FILE* fout = fopen(fname, "w");

     if (fout)
     {
         char const ppm_head[] =
             "P3\n"
             "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";

         fprintf(fout, "%s\n%lu %lu\n%u\n",
                 ppm_head,
                 self->width, self->height,
                 255U);

         size_t size = self->width * self->height;

         for (size_t i = 0; i < size; ++i)
         {
             unsigned int c = self->buf[i];
             fprintf(fout, "%u %u %u  ", c, 0U, 0U);
         }

         if (! fclose(fout))
         {
             return true;
         }
     }

     return false;
}




struct ct_axes
{
     double xmin;
     double xmax;
     double ymin;
     double ymax;
};

struct ct_axes
ct_axes_from_point(
     double complex z,
     double radius
){
     struct ct_axes axes = {
         creal(z) - radius, creal(z) + radius,
         cimag(z) - radius, cimag(z) + radius
     };

     return axes;
}


struct ct_plane
{
     struct ct_axes axes;
     double xstep;
     double ystep;
};


void
ct_plane_init(
     struct ct_plane* const self,
     struct ct_axes const* axes,
     unsigned long width,
     unsigned long height
){
     self->axes = *axes;

     double awidth = self->axes.xmax - self->axes.xmin;
     double aheight = self->axes.ymax - self->axes.ymin;

     assert(width > 0 && height > 0 && awidth > 0.0);

     double daspect = fabs((double)height / width);
     double waspect = fabs(aheight / awidth);

     if (daspect > waspect)
     {
         double excess = aheight * (daspect / waspect - 1.0);
         self->axes.ymax += excess / 2.0;
         self->axes.ymin -= excess / 2.0;
     }

     else if (daspect < waspect)
     {
         double excess = awidth * (waspect / daspect - 1.0);
         self->axes.xmax += excess / 2.0;
         self->axes.xmin -= excess / 2.0;
     }

     self->xstep = (self->axes.xmax - self->axes.xmin) / width;
     self->ystep = (self->axes.ymax - self->axes.ymin) / height;
}



struct ct_plot
{
     struct ct_plane plane;
     struct ct_canvas* canvas;
};


void
ct_plot_init(
     struct ct_plot* const self,
     struct ct_axes const* axes,
     struct ct_canvas* canvas
){
     ct_plane_init(&self->plane, axes, canvas->width - 1, canvas->height 
- 1);
     self->canvas = canvas;
}


bool
ct_plot_point(
     struct ct_plot* const self,
     double complex z,
     unsigned char color
){
     long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
     long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;

     if (x > -1 && x < (long)self->canvas->width &&
         y > -1 && y < (long)self->canvas->height)
     {
         // Now, we can convert to index.
         size_t i = x + y * self->canvas->width;

         assert(i < self->canvas->height * self->canvas->width);

         self->canvas->buf[i] = color;
         return true;
     }

     return false;
}



// Compute the fractal
void
ct_ifs(
     struct ct_plot* const plot,
     unsigned long n
){
     // 2 sets
     double complex jp[] = {
         .5 + 0 * I,
         -5.5 + I*.0
     };

     double complex z = 0+0*I;
     double complex c = 0+0*I;

     for (unsigned long i = 0; i < n; ++i)
     {
         double rn0 = rand() / (RAND_MAX - .0);
         double rn1 = rand() / (RAND_MAX - .0);

         if (rn0 > .5)
         {
             c = jp[0];
         }

         else
         {
             c = jp[1];
         }


         double complex d = z - c;
         double complex root = csqrt(d);

         z = root;

         if (rn1 > .5)
         {
             z = -root;
         }

          ct_plot_point(plot, z, 255);
          ct_plot_point(plot, root, 255);

         if (! (i % 256))
         {
             printf("rendering: %lu of %lu\r", i + 1, n);
         }
     }

     printf("rendering: %lu of %lu\n", n, n);
}





// slow, so what for now... ;^)
void ct_circle(
     struct ct_plot* const plot,
     double complex c,
     double radius,
     unsigned int n
){
     double abase = 6.2831853071 / n;

     for (unsigned int i = 0; i < n; ++i)
     {
         double angle = abase * i;

         double complex z =
             (creal(c) + cos(angle) * radius) +
             (cimag(c) + sin(angle) * radius) * I;

         ct_plot_point(plot, z, 255);
     }
}


int main(void)
{
     struct ct_canvas canvas;

     if (ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT))
     {
         double complex plane_origin = 0+0*I;
         double plane_radius = 2.0;

         struct ct_axes axes = ct_axes_from_point(plane_origin, 
plane_radius);

         struct ct_plot plot;
         ct_plot_init(&plot, &axes, &canvas);


         ct_ifs(&plot, CT_N);

         // Our unit circle
         ct_circle(&plot, 0+0*I, 1.0, 2048);
         ct_circle(&plot, 2+0*I, 2.0, 2048);
         ct_circle(&plot, -2+0*I, 2.0, 2048);
         ct_circle(&plot, 0+2*I, 2.0, 2048);
         ct_circle(&plot, 0-2*I, 2.0, 2048);

         ct_canvas_save_ppm(&canvas, "ct_plane.ppm");

         ct_canvas_destroy(&canvas);

         return EXIT_SUCCESS;
     }

     return EXIT_FAILURE;
}
___________________________

[toc] | [next] | [standalone]


#140293

From"Chris M. Thomasson " <ahh_f_it@crap.nothing>
Date2019-01-25 15:11 -0800
Message-ID<q2g529$upl$1@dont-email.me>
In reply to#140290
On 1/25/2019 2:24 PM, Chris M. Thomasson wrote:
> Just wondering, when you get some free time, if you can perhaps run the 
> my experimental plotter code that generates a PPM called "ct_plane.ppm". 
> And if you can see a fractal in the resulting rendering. Here is my C99 
> code:
> 
> https://pastebin.com/raw/322XAnsT
> (raw text, pure C99: no ads!)
> 
> It should just compile with GCC, and run like a charm. It has proper 
> aspect ratios so one can use any dimensions they want.
[...]

It should create a PPM called ct_plane.ppm that look just like this 
rendering:

https://plus.google.com/101799841244447089430/posts/PQ6jekiPpqo

[toc] | [prev] | [next] | [standalone]


#140294

FromEli the Bearded <*@eli.users.panix.com>
Date2019-01-25 23:50 +0000
Message-ID<eli$1901251850@qaz.wtf>
In reply to#140290
In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
> Just wondering, when you get some free time, if you can perhaps run the 
> my experimental plotter code that generates a PPM called "ct_plane.ppm". 
> And if you can see a fractal in the resulting rendering. Here is my C99 
> code:
> 
> https://pastebin.com/raw/322XAnsT
> (raw text, pure C99: no ads!)
> 
> It should just compile with GCC, and run like a charm. It has proper 
> aspect ratios so one can use any dimensions they want.
> 
> Can you notice anything wrong with the code below:
...
>      if (fout)
>      {
>          char const ppm_head[] =
>              "P3\n"
>              "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";
> 
>          fprintf(fout, "%s\n%lu %lu\n%u\n",
>                  ppm_head,
>                  self->width, self->height,
>                  255U);
> 
>          size_t size = self->width * self->height;
> 
>          for (size_t i = 0; i < size; ++i)
>          {
>              unsigned int c = self->buf[i];
>              fprintf(fout, "%u %u %u  ", c, 0U, 0U);
>          }

If you are going to have monochrome output (all red channel here), why
not just use the PGM format ("P2")? And since you are using just 0..255,
you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
create a much smaller file.

$ pnmtopnm ct_plane.ppm > noplain.ppm
$ ls -l ct_plane.ppm noplain.ppm
-rw-rw-r--. 1 user group 14584534 Jan 25 15:08 ct_plane.ppm
-rw-rw-r--. 1 user group  6220817 Jan 25 15:16 noplain.ppm
$ ppmtorgb3 ct_plane.ppm
$ ls -l ct_plane.red
-rw-rw-r--. 1 user group  2073617 Jan 25 15:19 ct_plane.red
$ file noplain.ppm ct_plane.red             
noplain.ppm:  Netpbm PPM "rawbits" image data, size = 1920 x 1080
ct_plane.red: Netpbm PGM "rawbits" image data, size = 1920 x 1080
$ diff fractal.c.orig fractal.c
56c56
< ct_canvas_save_ppm(
---
> ct_canvas_save_pgm(
64,65c64,65
<         char const ppm_head[] =
<             "P3\n"
---
>         char const pgm_head[] =
>             "P5\n"
69c69
<                 ppm_head,
---
>                 pgm_head,
78c78
<             fprintf(fout, "%u %u %u  ", c, 0U, 0U);
---
>             putc(c, fout);
307c307
<         ct_canvas_save_ppm(&canvas, "ct_plane.ppm");
---
>         ct_canvas_save_pgm(&canvas, "ct_plane.pgm");


Elijah
------
the fractal output may even be suited for 2-color pbm output

[toc] | [prev] | [next] | [standalone]


#140295

From"Chris M. Thomasson" <ahh_f_it@crap.nothing>
Date2019-01-25 16:33 -0800
Message-ID<q2g9td$mrn$2@dont-email.me>
In reply to#140294
On 1/25/2019 3:50 PM, Eli the Bearded wrote:
> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>> Just wondering, when you get some free time, if you can perhaps run the
>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>> And if you can see a fractal in the resulting rendering. Here is my C99
>> code:
>>
>> https://pastebin.com/raw/322XAnsT
>> (raw text, pure C99: no ads!)
>>
>> It should just compile with GCC, and run like a charm. It has proper
>> aspect ratios so one can use any dimensions they want.
>>
>> Can you notice anything wrong with the code below:
> ...
>>       if (fout)
>>       {
>>           char const ppm_head[] =
>>               "P3\n"
>>               "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";
[...]

> the fractal output may even be suited for 2-color pbm output
> 

You are correct. However, I have further plans for this simple code that 
can support at least RGB. A simple struct comprising each element in the 
buffer for the ct_canvas:

struct ct_rgb
{
     unsigned char r;
     unsigned char g;
     unsigned char b;
};

or even:

struct ct_rgba
{
     unsigned char r;
     unsigned char g;
     unsigned char b;
     unsigned char a;
};

That would be a decent start.

[toc] | [prev] | [next] | [standalone]


#140296

FromBart <bc@freeuk.com>
Date2019-01-26 00:45 +0000
Message-ID<n4O2E.233248$ZE1.59408@fx24.am4>
In reply to#140294
On 25/01/2019 23:50, Eli the Bearded wrote:
> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>> Just wondering, when you get some free time, if you can perhaps run the
>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>> And if you can see a fractal in the resulting rendering. Here is my C99
>> code:
>>
>> https://pastebin.com/raw/322XAnsT
>> (raw text, pure C99: no ads!)
>>
>> It should just compile with GCC, and run like a charm. It has proper
>> aspect ratios so one can use any dimensions they want.
>>
>> Can you notice anything wrong with the code below:
> ...
>>       if (fout)
>>       {
>>           char const ppm_head[] =
>>               "P3\n"
>>               "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";
>>
>>           fprintf(fout, "%s\n%lu %lu\n%u\n",
>>                   ppm_head,
>>                   self->width, self->height,
>>                   255U);
>>
>>           size_t size = self->width * self->height;
>>
>>           for (size_t i = 0; i < size; ++i)
>>           {
>>               unsigned int c = self->buf[i];
>>               fprintf(fout, "%u %u %u  ", c, 0U, 0U);
>>           }
> 
> If you are going to have monochrome output (all red channel here), why
> not just use the PGM format ("P2")? And since you are using just 0..255,
> you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
> create a much smaller file.

Yes, I had some problems reading the file. My image viewer had to be 
extended to support P3 format.

But also, while P3 is a text format, all the data is on one long 14 
million character line, so that I wasn't able to use line-oriented 
reads, and makes manipulating it in some text editors difficult.

A P5 format (8-bit/binary) would have taken only 2MB instead of 14MB.

[toc] | [prev] | [next] | [standalone]


#140297

From"Chris M. Thomasson " <ahh_f_it@crap.nothing>
Date2019-01-25 16:55 -0800
Message-ID<q2gb6p$s4u$1@dont-email.me>
In reply to#140296
On 1/25/2019 4:45 PM, Bart wrote:
> On 25/01/2019 23:50, Eli the Bearded wrote:
>> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>>> Just wondering, when you get some free time, if you can perhaps run the
>>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>>> And if you can see a fractal in the resulting rendering. Here is my C99
>>> code:
>>>
>>> https://pastebin.com/raw/322XAnsT
>>> (raw text, pure C99: no ads!)
>>>
>>> It should just compile with GCC, and run like a charm. It has proper
>>> aspect ratios so one can use any dimensions they want.
>>>
>>> Can you notice anything wrong with the code below:
>> ...
>>>       if (fout)
>>>       {
>>>           char const ppm_head[] =
>>>               "P3\n"
>>>               "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 
>>> (pre-alpha)";
>>>
>>>           fprintf(fout, "%s\n%lu %lu\n%u\n",
>>>                   ppm_head,
>>>                   self->width, self->height,
>>>                   255U);
>>>
>>>           size_t size = self->width * self->height;
>>>
>>>           for (size_t i = 0; i < size; ++i)
>>>           {
>>>               unsigned int c = self->buf[i];
>>>               fprintf(fout, "%u %u %u  ", c, 0U, 0U);
>>>           }
>>
>> If you are going to have monochrome output (all red channel here), why
>> not just use the PGM format ("P2")? And since you are using just 0..255,
>> you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
>> create a much smaller file.
> 
> Yes, I had some problems reading the file. My image viewer had to be 
> extended to support P3 format.

I am viewing it in the GIMP 2.8.16. Loads right up. What are you using? 
Can you view the PPM at all?

> 
> But also, while P3 is a text format, all the data is on one long 14 
> million character line, so that I wasn't able to use line-oriented 
> reads, and makes manipulating it in some text editors difficult.
> 
> A P5 format (8-bit/binary) would have taken only 2MB instead of 14MB.
> 

[toc] | [prev] | [next] | [standalone]


#140299

FromBart <bc@freeuk.com>
Date2019-01-26 00:59 +0000
Message-ID<zhO2E.141754$RE1.72501@fx32.am4>
In reply to#140297
On 26/01/2019 00:55, Chris M. Thomasson  wrote:
> On 1/25/2019 4:45 PM, Bart wrote:

>> Yes, I had some problems reading the file. My image viewer had to be 
>> extended to support P3 format.
> 
> I am viewing it in the GIMP 2.8.16. Loads right up. What are you using? 
> Can you view the PPM at all?

Yes I can view it now after I added P3 support. But see my other post 
where I tried P6.

[toc] | [prev] | [next] | [standalone]


#140304

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-01-26 20:29 +0000
Message-ID<slrnq4pgop.4jo.grahn+nntp@frailea.sa.invalid>
In reply to#140296
On Sat, 2019-01-26, Bart wrote:
> On 25/01/2019 23:50, Eli the Bearded wrote:
>> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>>> Just wondering, when you get some free time, if you can perhaps run the
>>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>>> And if you can see a fractal in the resulting rendering. Here is my C99
>>> code:
...

>> If you are going to have monochrome output (all red channel here), why
>> not just use the PGM format ("P2")? And since you are using just 0..255,
>> you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
>> create a much smaller file.
>
> Yes, I had some problems reading the file. My image viewer had to be 
> extended to support P3 format.
>
> But also, while P3 is a text format, all the data is on one long 14 
> million character line, so that I wasn't able to use line-oriented 
> reads, and makes manipulating it in some text editors difficult.
>
> A P5 format (8-bit/binary) would have taken only 2MB instead of 14MB.

Please remember that all those formats are intended as only
intermediates, to be used in Unix pipelines and so on.  In situations
where disk space matters, they should have been converted to PNG or
similar.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#140311

FromBart <bc@freeuk.com>
Date2019-01-26 21:37 +0000
Message-ID<Iq43E.297349$VH1.216347@fx40.am4>
In reply to#140304
On 26/01/2019 20:29, Jorgen Grahn wrote:
> On Sat, 2019-01-26, Bart wrote:
>> On 25/01/2019 23:50, Eli the Bearded wrote:
>>> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>>>> Just wondering, when you get some free time, if you can perhaps run the
>>>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>>>> And if you can see a fractal in the resulting rendering. Here is my C99
>>>> code:
> ...
> 
>>> If you are going to have monochrome output (all red channel here), why
>>> not just use the PGM format ("P2")? And since you are using just 0..255,
>>> you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
>>> create a much smaller file.
>>
>> Yes, I had some problems reading the file. My image viewer had to be
>> extended to support P3 format.
>>
>> But also, while P3 is a text format, all the data is on one long 14
>> million character line, so that I wasn't able to use line-oriented
>> reads, and makes manipulating it in some text editors difficult.
>>
>> A P5 format (8-bit/binary) would have taken only 2MB instead of 14MB.
> 
> Please remember that all those formats are intended as only
> intermediates, to be used in Unix pipelines and so on.  In situations
> where disk space matters, they should have been converted to PNG or
> similar.

Disk space isn't so important. But it can make it slower.

For example, my ppm readers are written in interpreted code. For 
1920x1080 RGB, a P6 binary format be read a row at a time, 5760 bytes.

A P3 text format requires reading 5760 separate values per line. And 
because it might not be line-oriented, I had to resort to reading a 
character at a time and forming each number.

Reading this size of file in binary is instant; text took 4-5 seconds.

[toc] | [prev] | [next] | [standalone]


#140320

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-01-27 12:11 +0000
Message-ID<slrnq4r7vn.4jo.grahn+nntp@frailea.sa.invalid>
In reply to#140311
On Sat, 2019-01-26, Bart wrote:
> On 26/01/2019 20:29, Jorgen Grahn wrote:
>> On Sat, 2019-01-26, Bart wrote:
>>> On 25/01/2019 23:50, Eli the Bearded wrote:
>>>> In comp.lang.c, Chris M. Thomasson <ahh_f_it@crap.nothing> wrote:
>>>>> Just wondering, when you get some free time, if you can perhaps run the
>>>>> my experimental plotter code that generates a PPM called "ct_plane.ppm".
>>>>> And if you can see a fractal in the resulting rendering. Here is my C99
>>>>> code:
>> ...
>> 
>>>> If you are going to have monochrome output (all red channel here), why
>>>> not just use the PGM format ("P2")? And since you are using just 0..255,
>>>> you can very easily use a raw format ("P5" for pgm / "P6" for ppm) and
>>>> create a much smaller file.
>>>
>>> Yes, I had some problems reading the file. My image viewer had to be
>>> extended to support P3 format.
>>>
>>> But also, while P3 is a text format, all the data is on one long 14
>>> million character line, so that I wasn't able to use line-oriented
>>> reads, and makes manipulating it in some text editors difficult.
>>>
>>> A P5 format (8-bit/binary) would have taken only 2MB instead of 14MB.
>> 
>> Please remember that all those formats are intended as only
>> intermediates, to be used in Unix pipelines and so on.  In situations
>> where disk space matters, they should have been converted to PNG or
>> similar.
>
> Disk space isn't so important. But it can make it slower.
>
> For example, my ppm readers are written in interpreted code. For 
> 1920x1080 RGB, a P6 binary format be read a row at a time, 5760 bytes.
>
> A P3 text format requires reading 5760 separate values per line. And 
> because it might not be line-oriented, I had to resort to reading a 
> character at a time and forming each number.

A third option is to read a few kilobytes at a time, form the numbers,
and keep a remainder buffer for the case where you cut a number in
half with your read.

(Or you can use libpnm, but I suspect you want to do it yourself.)

> Reading this size of file in binary is instant; text took 4-5 seconds.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#140323

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-01-27 13:40 +0000
Message-ID<875zuaw75b.fsf@bsb.me.uk>
In reply to#140320
Jorgen Grahn <grahn+nntp@snipabacken.se> writes:

> On Sat, 2019-01-26, Bart wrote:
<snip>
>> A P3 text format requires reading 5760 separate values per line. And 
>> because it might not be line-oriented, I had to resort to reading a 
>> character at a time and forming each number.
>
> A third option is to read a few kilobytes at a time, form the numbers,
> and keep a remainder buffer for the case where you cut a number in
> half with your read.

Or you can use fscanf if you just want to get a solution quickly.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#140298

FromBart <bc@freeuk.com>
Date2019-01-26 00:57 +0000
Message-ID<agO2E.141753$RE1.49405@fx32.am4>
In reply to#140290
On 25/01/2019 22:24, Chris M. Thomasson wrote:
> Just wondering, when you get some free time, if you can perhaps run the 
> my experimental plotter code that generates a PPM called "ct_plane.ppm". 
> And if you can see a fractal in the resulting rendering. Here is my C99 
> code:
> 
> https://pastebin.com/raw/322XAnsT
> (raw text, pure C99: no ads!)
> 
> It should just compile with GCC, and run like a charm. It has proper 
> aspect ratios so one can use any dimensions they want.
> 
> Can you notice anything wrong with the code below:

>      FILE* fout = fopen(fname, "w");
> 
>      if (fout)
>      {
>          char const ppm_head[] =
>              "P3\n"
>              "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 
> (pre-alpha)";
> 
>          fprintf(fout, "%s\n%lu %lu\n%u\n",
>                  ppm_head,
>                  self->width, self->height,
>                  255U);
> 
>          size_t size = self->width * self->height;
> 
>          for (size_t i = 0; i < size; ++i)
>          {
>              unsigned int c = self->buf[i];
>              fprintf(fout, "%u %u %u  ", c, 0U, 0U);

Further to the posts about the format, I changed the above lines to:

     FILE* fout = fopen(fname, "wb");

     if (fout)
     {
         char const ppm_head[] =
             "P6\n"
             "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";

         fprintf(fout, "%s\n%lu %lu\n%u\n",
                 ppm_head,
                 self->width, self->height,
                 255U);

         size_t size = self->width * self->height;

         for (size_t i = 0; i < size; ++i)
         {
             unsigned int c = self->buf[i];
             fprintf(fout, "%c%c%c", 255-c,255-c,255-c);
         }

This give a P6 24/binary format (as you said you were going to use RGB). 
I've also written all planes not just R, and took the liberty of 
reversing the bytes to get black on white (my preference).

Note the "wb" for the file mode. (These P4/P5/P6 formats are peculiar in 
that they mix text and binary data. With "wb", new lines are /not/ 
written as cr/lf under Windows, but as lf only. I don't know how much 
that's likely to screw up some ppm viewers.)

I wasn't sure if %c to write binary bytes would work, but it seems to.

Loading of this format is considerably faster with my viewer.

(To generate binary greyscale, use P5 and write only one %c byte per 
pixel. The file extension should also be pgm, although my viewer is not 
fussy as it will check the "P" code.)











>          }
> 
>          if (! fclose(fout))
>          {
>              return true;
>          }
>      }
> 
>      return false;
> }
> 
> 
> 
> 
> struct ct_axes
> {
>      double xmin;
>      double xmax;
>      double ymin;
>      double ymax;
> };
> 
> struct ct_axes
> ct_axes_from_point(
>      double complex z,
>      double radius
> ){
>      struct ct_axes axes = {
>          creal(z) - radius, creal(z) + radius,
>          cimag(z) - radius, cimag(z) + radius
>      };
> 
>      return axes;
> }
> 
> 
> struct ct_plane
> {
>      struct ct_axes axes;
>      double xstep;
>      double ystep;
> };
> 
> 
> void
> ct_plane_init(
>      struct ct_plane* const self,
>      struct ct_axes const* axes,
>      unsigned long width,
>      unsigned long height
> ){
>      self->axes = *axes;
> 
>      double awidth = self->axes.xmax - self->axes.xmin;
>      double aheight = self->axes.ymax - self->axes.ymin;
> 
>      assert(width > 0 && height > 0 && awidth > 0.0);
> 
>      double daspect = fabs((double)height / width);
>      double waspect = fabs(aheight / awidth);
> 
>      if (daspect > waspect)
>      {
>          double excess = aheight * (daspect / waspect - 1.0);
>          self->axes.ymax += excess / 2.0;
>          self->axes.ymin -= excess / 2.0;
>      }
> 
>      else if (daspect < waspect)
>      {
>          double excess = awidth * (waspect / daspect - 1.0);
>          self->axes.xmax += excess / 2.0;
>          self->axes.xmin -= excess / 2.0;
>      }
> 
>      self->xstep = (self->axes.xmax - self->axes.xmin) / width;
>      self->ystep = (self->axes.ymax - self->axes.ymin) / height;
> }
> 
> 
> 
> struct ct_plot
> {
>      struct ct_plane plane;
>      struct ct_canvas* canvas;
> };
> 
> 
> void
> ct_plot_init(
>      struct ct_plot* const self,
>      struct ct_axes const* axes,
>      struct ct_canvas* canvas
> ){
>      ct_plane_init(&self->plane, axes, canvas->width - 1, canvas->height 
> - 1);
>      self->canvas = canvas;
> }
> 
> 
> bool
> ct_plot_point(
>      struct ct_plot* const self,
>      double complex z,
>      unsigned char color
> ){
>      long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
>      long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;
> 
>      if (x > -1 && x < (long)self->canvas->width &&
>          y > -1 && y < (long)self->canvas->height)
>      {
>          // Now, we can convert to index.
>          size_t i = x + y * self->canvas->width;
> 
>          assert(i < self->canvas->height * self->canvas->width);
> 
>          self->canvas->buf[i] = color;
>          return true;
>      }
> 
>      return false;
> }
> 
> 
> 
> // Compute the fractal
> void
> ct_ifs(
>      struct ct_plot* const plot,
>      unsigned long n
> ){
>      // 2 sets
>      double complex jp[] = {
>          .5 + 0 * I,
>          -5.5 + I*.0
>      };
> 
>      double complex z = 0+0*I;
>      double complex c = 0+0*I;
> 
>      for (unsigned long i = 0; i < n; ++i)
>      {
>          double rn0 = rand() / (RAND_MAX - .0);
>          double rn1 = rand() / (RAND_MAX - .0);
> 
>          if (rn0 > .5)
>          {
>              c = jp[0];
>          }
> 
>          else
>          {
>              c = jp[1];
>          }
> 
> 
>          double complex d = z - c;
>          double complex root = csqrt(d);
> 
>          z = root;
> 
>          if (rn1 > .5)
>          {
>              z = -root;
>          }
> 
>           ct_plot_point(plot, z, 255);
>           ct_plot_point(plot, root, 255);
> 
>          if (! (i % 256))
>          {
>              printf("rendering: %lu of %lu\r", i + 1, n);
>          }
>      }
> 
>      printf("rendering: %lu of %lu\n", n, n);
> }
> 
> 
> 
> 
> 
> // slow, so what for now... ;^)
> void ct_circle(
>      struct ct_plot* const plot,
>      double complex c,
>      double radius,
>      unsigned int n
> ){
>      double abase = 6.2831853071 / n;
> 
>      for (unsigned int i = 0; i < n; ++i)
>      {
>          double angle = abase * i;
> 
>          double complex z =
>              (creal(c) + cos(angle) * radius) +
>              (cimag(c) + sin(angle) * radius) * I;
> 
>          ct_plot_point(plot, z, 255);
>      }
> }
> 
> 
> int main(void)
> {
>      struct ct_canvas canvas;
> 
>      if (ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT))
>      {
>          double complex plane_origin = 0+0*I;
>          double plane_radius = 2.0;
> 
>          struct ct_axes axes = ct_axes_from_point(plane_origin, 
> plane_radius);
> 
>          struct ct_plot plot;
>          ct_plot_init(&plot, &axes, &canvas);
> 
> 
>          ct_ifs(&plot, CT_N);
> 
>          // Our unit circle
>          ct_circle(&plot, 0+0*I, 1.0, 2048);
>          ct_circle(&plot, 2+0*I, 2.0, 2048);
>          ct_circle(&plot, -2+0*I, 2.0, 2048);
>          ct_circle(&plot, 0+2*I, 2.0, 2048);
>          ct_circle(&plot, 0-2*I, 2.0, 2048);
> 
>          ct_canvas_save_ppm(&canvas, "ct_plane.ppm");
> 
>          ct_canvas_destroy(&canvas);
> 
>          return EXIT_SUCCESS;
>      }
> 
>      return EXIT_FAILURE;
> }
> ___________________________

[toc] | [prev] | [next] | [standalone]


#140332

From"Chris M. Thomasson" <ahh_f_it@crap.nothing>
Date2019-01-27 15:37 -0800
Message-ID<q2lfcd$fe0$3@dont-email.me>
In reply to#140298
On 1/25/2019 4:57 PM, Bart wrote:
> On 25/01/2019 22:24, Chris M. Thomasson wrote:
>> Just wondering, when you get some free time, if you can perhaps run 
>> the my experimental plotter code that generates a PPM called 
>> "ct_plane.ppm". And if you can see a fractal in the resulting 
>> rendering. Here is my C99 code:
>>
>> https://pastebin.com/raw/322XAnsT
>> (raw text, pure C99: no ads!)
>>
>> It should just compile with GCC, and run like a charm. It has proper 
>> aspect ratios so one can use any dimensions they want.
>>
>> Can you notice anything wrong with the code below:
> 
>>      FILE* fout = fopen(fname, "w");
>>
>>      if (fout)
>>      {
>>          char const ppm_head[] =
>>              "P3\n"
>>              "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 
>> (pre-alpha)";
>>
>>          fprintf(fout, "%s\n%lu %lu\n%u\n",
>>                  ppm_head,
>>                  self->width, self->height,
>>                  255U);
>>
>>          size_t size = self->width * self->height;
>>
>>          for (size_t i = 0; i < size; ++i)
>>          {
>>              unsigned int c = self->buf[i];
>>              fprintf(fout, "%u %u %u  ", c, 0U, 0U);
> 
> Further to the posts about the format, I changed the above lines to:
> 
>      FILE* fout = fopen(fname, "wb");
> 
>      if (fout)
>      {
>          char const ppm_head[] =
>              "P6\n"
>              "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 
> (pre-alpha)";
> 
>          fprintf(fout, "%s\n%lu %lu\n%u\n",
>                  ppm_head,
>                  self->width, self->height,
>                  255U);
> 
>          size_t size = self->width * self->height;
> 
>          for (size_t i = 0; i < size; ++i)
>          {
>              unsigned int c = self->buf[i];
>              fprintf(fout, "%c%c%c", 255-c,255-c,255-c);
>          }
> 
> This give a P6 24/binary format (as you said you were going to use RGB). 
> I've also written all planes not just R, and took the liberty of 
> reversing the bytes to get black on white (my preference).
> 
> Note the "wb" for the file mode. (These P4/P5/P6 formats are peculiar in 
> that they mix text and binary data. With "wb", new lines are /not/ 
> written as cr/lf under Windows, but as lf only. I don't know how much 
> that's likely to screw up some ppm viewers.)
> 
> I wasn't sure if %c to write binary bytes would work, but it seems to.
> 
> Loading of this format is considerably faster with my viewer.
> 
> (To generate binary greyscale, use P5 and write only one %c byte per 
> pixel. The file extension should also be pgm, although my viewer is not 
> fussy as it will check the "P" code.)
[...]

Your conversion to P6 24/binary works great. The black on white is nice 
as well. I really need to put in some log-density coloring.

Thanks Bart.

[toc] | [prev] | [next] | [standalone]


#140302

FromBart <bc@freeuk.com>
Date2019-01-26 12:35 +0000
Message-ID<iuY2E.451909$Fi6.364335@fx12.am4>
In reply to#140290
On 25/01/2019 22:24, Chris M. Thomasson wrote:
> Just wondering, when you get some free time, if you can perhaps run the 
> my experimental plotter code that generates a PPM called "ct_plane.ppm". 
> And if you can see a fractal in the resulting rendering. Here is my C99 
> code:
> 
> https://pastebin.com/raw/322XAnsT
> (raw text, pure C99: no ads!)
> 
> It should just compile with GCC, and run like a charm. It has proper 
> aspect ratios so one can use any dimensions they want.
> 
> Can you notice anything wrong with the code below:

Nothing really wrong, but it gives problems on several other compilers:

bcc: no complex.h, no tgmath.h, and lack of complex support (including 
in the C library msvcrt.dll even if I added it in the compiler)

tcc: no tgmath.h or complex.h

dmc: no tgmath.h (and doesn't support dynamic struct init)

msvc: no tgmath.h (and loads of errors when you just comment it out. 
What is tgmath.h for anyway?)

clang: error: passing '_Complex float' to parameter of incompatible
  type '_Fcomplex' (aka 'struct _C_float_complex')
     __tg_acos(float _Complex __x) {return cacosf(__x);} etc
                                                  ^~~
lccwin: compiler failures


I modified it to so that it doesn't use complex.h nor tgmath.h:

   https://pastebin.com/raw/tJFxYsb0

Now it runs on all those compilers, except lccwin which appears to have 
bugs (it fails on -64, builds on -32, but that doesn't terminate).

Interestingly, all programs seem to have the same runtime: optimisation 
makes little difference (all take around 6-7 seconds on my machine, of 
which generating the .ppm file is a tiny part).


-- 
bart

[toc] | [prev] | [next] | [standalone]


#140321

FromDavid Brown <david.brown@hesbynett.no>
Date2019-01-27 13:20 +0100
Message-ID<q2k7n0$gak$1@dont-email.me>
In reply to#140302
On 26/01/2019 13:35, Bart wrote:
> On 25/01/2019 22:24, Chris M. Thomasson wrote:
>> Just wondering, when you get some free time, if you can perhaps run 
>> the my experimental plotter code that generates a PPM called 
>> "ct_plane.ppm". And if you can see a fractal in the resulting 
>> rendering. Here is my C99 code:
>>
>> https://pastebin.com/raw/322XAnsT
>> (raw text, pure C99: no ads!)
>>
>> It should just compile with GCC, and run like a charm. It has proper 
>> aspect ratios so one can use any dimensions they want.
>>
>> Can you notice anything wrong with the code below:
> 
> Nothing really wrong, but it gives problems on several other compilers:
> 
> bcc: no complex.h, no tgmath.h, and lack of complex support (including 
> in the C library msvcrt.dll even if I added it in the compiler)
> 
> tcc: no tgmath.h or complex.h
> 
> dmc: no tgmath.h (and doesn't support dynamic struct init)
> 
> msvc: no tgmath.h (and loads of errors when you just comment it out. 
> What is tgmath.h for anyway?)
> 


Chris said it was a C99 program.  A C implementation that does not have 
tgmath.h, complex.h, and the required libraries is not a C99 
implementation.  So it is entirely reasonable that his program does not 
work on systems that don't support C99 - the standard is only 20 years 
old, and not every tool has caught up yet.

> clang: error: passing '_Complex float' to parameter of incompatible
>   type '_Fcomplex' (aka 'struct _C_float_complex')
>      __tg_acos(float _Complex __x) {return cacosf(__x);} etc
>                                                   ^~~

I wonder if that is something specific to clang on Windows using MS's 
headers?  (This is purely speculation, not based on any experience of 
the tool on Windows.)

> lccwin: compiler failures
> 
> 
> I modified it to so that it doesn't use complex.h nor tgmath.h:
> 
>    https://pastebin.com/raw/tJFxYsb0
> 

Neither complex numbers nor the generic maths functions are that hard to 
duplicate in old C90.  They are just more convenient in C99.

> Now it runs on all those compilers, except lccwin which appears to have 
> bugs (it fails on -64, builds on -32, but that doesn't terminate).
> 
> Interestingly, all programs seem to have the same runtime: optimisation 
> makes little difference (all take around 6-7 seconds on my machine, of 
> which generating the .ppm file is a tiny part).
> 

Depending on the cpu you are running on, that is not too surprising for 
a program that works with a lot of floating point calculations, 
especially things like square roots and division.  These usually take a 
fair amount of clock cycles - and the cpu will do plenty of other 
"simple" things while waiting.  Thus optimisation of other parts - 
function calls, loops, data movement, etc., will have little effect 
here.  Modern x86 cpus are very good at running sub-optimal code.  It is 
an interesting point to consider.

Still, in my testing with gcc 5.4 (64-bit Linux), unoptimised code took 
0.68s, while with reasonable fast options "-O3 -ffast-math 
-march=native" it takes 0.44 seconds.

Since that is an order of magnitude faster than your system, and my PC 
is not usually /that/ much faster than yours, it could well be the 
effect of scheduling, pipelining, and out-of-order execution on the 
particular cpu.

[toc] | [prev] | [next] | [standalone]


#140326

FromBart <bc@freeuk.com>
Date2019-01-27 14:13 +0000
Message-ID<TZi3E.87684$nC1.54261@fx04.am4>
In reply to#140321
On 27/01/2019 12:20, David Brown wrote:
> On 26/01/2019 13:35, Bart wrote:

>> msvc: no tgmath.h (and loads of errors when you just comment it out. 
>> What is tgmath.h for anyway?)
>>
> 
> 
> Chris said it was a C99 program.

Most of those compilers, except for bcc, are reasonably full c99 
compilers. Yet tgmath.h, which varies from 130 to 1400 lines where it 
exists, seems to be missing from dmc, tcc and msvc.

   A C implementation that does not have
> tgmath.h, complex.h, and the required libraries is not a C99 
> implementation.  So it is entirely reasonable that his program does not 
> work on systems that don't support C99 - the standard is only 20 years 
> old, and not every tool has caught up yet.

No, it's just support for tgmath.h that is not so universal. Actually 
I'm still not sure what it does.

>> clang: error: passing '_Complex float' to parameter of incompatible
>>   type '_Fcomplex' (aka 'struct _C_float_complex')
>>      __tg_acos(float _Complex __x) {return cacosf(__x);} etc
>>                                                   ^~~
> 
> I wonder if that is something specific to clang on Windows using MS's 
> headers?  (This is purely speculation, not based on any experience of 
> the tool on Windows.)

This is an odd one: clang seems to rely on msvc somehow, but msvc 
doesn't have tgmath,h, yet clang has.

>> Interestingly, all programs seem to have the same runtime: 
>> optimisation makes little difference (all take around 6-7 seconds on 
>> my machine, of which generating the .ppm file is a tiny part).
>>
> 
> Depending on the cpu you are running on, that is not too surprising for 
> a program that works with a lot of floating point calculations, 
> especially things like square roots and division.
...
> Still, in my testing with gcc 5.4 (64-bit Linux), unoptimised code took 
> 0.68s, while with reasonable fast options "-O3 -ffast-math 
> -march=native" it takes 0.44 seconds.

> Since that is an order of magnitude faster than your system, and my PC 
> is not usually /that/ much faster than yours, it could well be the 
> effect of scheduling, pipelining, and out-of-order execution on the 
> particular cpu.

Actually there is something I overlooked completely, which is the printf 
that is called on every point. It overwrites the same line so you don't 
appreciate how many lines are displayed.

Without that, then it was much faster (certainly on Windows). Fast 
enough that generating the .ppm was was significant.

So without the ppm, and without printf, timings varied from 0.75 seconds 
to 1.2 seconds, with gcc-O3 fastest.

Using your additional options, gcc took 0.5 seconds. Just over twice as 
fast as my unoptimised bcc (1.1) or gcc-O0 (1.15); this is where the 
floating point overheads limit the difference.

[toc] | [prev] | [next] | [standalone]


#140328

FromDavid Brown <david.brown@hesbynett.no>
Date2019-01-27 16:36 +0100
Message-ID<q2kj67$nkj$1@dont-email.me>
In reply to#140326
On 27/01/2019 15:13, Bart wrote:
> On 27/01/2019 12:20, David Brown wrote:
>> On 26/01/2019 13:35, Bart wrote:
> 
>>> msvc: no tgmath.h (and loads of errors when you just comment it out. 
>>> What is tgmath.h for anyway?)
>>>
>>
>>
>> Chris said it was a C99 program.
> 
> Most of those compilers, except for bcc, are reasonably full c99 
> compilers. Yet tgmath.h, which varies from 130 to 1400 lines where it 
> exists, seems to be missing from dmc, tcc and msvc.
> 

As you know, a "C implementation" consists of a C compiler, headers, a 
standard library, and whatever other bits and pieces are needed to turn 
C code into an executable (assembler, linker, etc.).  A compiler that 
can handle C99 syntax is only part of the system - if you don't have the 
C99 headers, you don't have a C99 implementation.  That seems to be the 
case for these C implementations - at least with the installation on 
your system (maybe other tcc or dmc installations have C99 headers and 
libraries).

>    A C implementation that does not have
>> tgmath.h, complex.h, and the required libraries is not a C99 
>> implementation.  So it is entirely reasonable that his program does 
>> not work on systems that don't support C99 - the standard is only 20 
>> years old, and not every tool has caught up yet.
> 
> No, it's just support for tgmath.h that is not so universal. Actually 
> I'm still not sure what it does.
> 

At the risk of stating the blindingly obvious, "tgmath.h" is a header of 
type-generic maths macros.  It is documented in the C99 (and C11, and 
C17) standards.  And if you don't like reading the standards documents 
(which is not unreasonable - they are not always easy to read), this 
site is a good reference for C and C++:

<https://en.cppreference.com/w/c/numeric/tgmath>

I can't tell you how universal support for tgmath.h is.  For my modest C 
needs on big systems, my gcc installations support it fine.  For my 
embedded programming, I usually write my own maths functions anyway and 
thus have little need of <tgmath.h> or even <math.h>


>>> clang: error: passing '_Complex float' to parameter of incompatible
>>>   type '_Fcomplex' (aka 'struct _C_float_complex')
>>>      __tg_acos(float _Complex __x) {return cacosf(__x);} etc
>>>                                                   ^~~
>>
>> I wonder if that is something specific to clang on Windows using MS's 
>> headers?  (This is purely speculation, not based on any experience of 
>> the tool on Windows.)
> 
> This is an odd one: clang seems to rely on msvc somehow, but msvc 
> doesn't have tgmath,h, yet clang has.
> 

MSVC has famously bad C99 support.  clang has perfectly good C99 
support.  But this sort of thing lies partly between the compiler and 
the library (the two main parts of the C implementation).  <tgmath.h> 
cannot be written in standard C (until C11) - it requires 
compiler-specific features.  So it is one of the headers that is likely 
to come with the compiler rather than the library.  On the other hand, 
the /implementations/ of the functions used will be part of the C 
run-time library.  MSVC uses highly inefficient DLL's for this, and 
their DLL's don't have good C99 support.  So it does not surprise me 
that the hack they have made with fitting clang onto MSVC results in the 
<tgmath.h> header being fine while missing the functions in the library. 
  (The same applies if you are using MingW rather than MSVC - that's why 
I recommended MingW-64.)  I'd imagine that with enough effort, you could 
find options or libraries to handle this, or you could install clang 
along with fuller libraries.

>>> Interestingly, all programs seem to have the same runtime: 
>>> optimisation makes little difference (all take around 6-7 seconds on 
>>> my machine, of which generating the .ppm file is a tiny part).
>>>
>>
>> Depending on the cpu you are running on, that is not too surprising 
>> for a program that works with a lot of floating point calculations, 
>> especially things like square roots and division.
> ...
>> Still, in my testing with gcc 5.4 (64-bit Linux), unoptimised code 
>> took 0.68s, while with reasonable fast options "-O3 -ffast-math 
>> -march=native" it takes 0.44 seconds.
> 
>> Since that is an order of magnitude faster than your system, and my PC 
>> is not usually /that/ much faster than yours, it could well be the 
>> effect of scheduling, pipelining, and out-of-order execution on the 
>> particular cpu.
> 
> Actually there is something I overlooked completely, which is the printf 
> that is called on every point. It overwrites the same line so you don't 
> appreciate how many lines are displayed.
> 

You are right - I never noticed that (I didn't look much at the program 
itself).  Yes, this will dominate.

> Without that, then it was much faster (certainly on Windows). Fast 
> enough that generating the .ppm was was significant.
> 
> So without the ppm, and without printf, timings varied from 0.75 seconds 
> to 1.2 seconds, with gcc-O3 fastest.
> 
> Using your additional options, gcc took 0.5 seconds. Just over twice as 
> fast as my unoptimised bcc (1.1) or gcc-O0 (1.15); this is where the 
> floating point overheads limit the difference.
> 

Interesting.


[toc] | [prev] | [next] | [standalone]


#140331

From"Chris M. Thomasson" <ahh_f_it@crap.nothing>
Date2019-01-27 14:28 -0800
Message-ID<q2lbaj$o2m$3@dont-email.me>
In reply to#140328
On 1/27/2019 7:36 AM, David Brown wrote:
> On 27/01/2019 15:13, Bart wrote:
>> On 27/01/2019 12:20, David Brown wrote:
>>> On 26/01/2019 13:35, Bart wrote:
>>
>>>> msvc: no tgmath.h (and loads of errors when you just comment it out. 
>>>> What is tgmath.h for anyway?)
>>>>
>>>
>>>
>>> Chris said it was a C99 program.
>>
>> Most of those compilers, except for bcc, are reasonably full c99 
>> compilers. Yet tgmath.h, which varies from 130 to 1400 lines where it 
>> exists, seems to be missing from dmc, tcc and msvc.
>>
> 
> As you know, a "C implementation" consists of a C compiler, headers, a 
> standard library, and whatever other bits and pieces are needed to turn 
> C code into an executable (assembler, linker, etc.).  A compiler that 
> can handle C99 syntax is only part of the system - if you don't have the 
> C99 headers, you don't have a C99 implementation.  That seems to be the 
> case for these C implementations - at least with the installation on 
> your system (maybe other tcc or dmc installations have C99 headers and 
> libraries).
> 
>>    A C implementation that does not have
>>> tgmath.h, complex.h, and the required libraries is not a C99 
>>> implementation.  So it is entirely reasonable that his program does 
>>> not work on systems that don't support C99 - the standard is only 20 
>>> years old, and not every tool has caught up yet.
>>
>> No, it's just support for tgmath.h that is not so universal. Actually 
>> I'm still not sure what it does.
>>
> 
> At the risk of stating the blindingly obvious, "tgmath.h" is a header of 
> type-generic maths macros.  It is documented in the C99 (and C11, and 
> C17) standards.  And if you don't like reading the standards documents 
> (which is not unreasonable - they are not always easy to read), this 
> site is a good reference for C and C++:
> 
> <https://en.cppreference.com/w/c/numeric/tgmath>
> 
> I can't tell you how universal support for tgmath.h is.  For my modest C 
> needs on big systems, my gcc installations support it fine.  For my 
> embedded programming, I usually write my own maths functions anyway and 
> thus have little need of <tgmath.h> or even <math.h>
> 
> 
>>>> clang: error: passing '_Complex float' to parameter of incompatible
>>>>   type '_Fcomplex' (aka 'struct _C_float_complex')
>>>>      __tg_acos(float _Complex __x) {return cacosf(__x);} etc
>>>>                                                   ^~~
>>>
>>> I wonder if that is something specific to clang on Windows using MS's 
>>> headers?  (This is purely speculation, not based on any experience of 
>>> the tool on Windows.)
>>
>> This is an odd one: clang seems to rely on msvc somehow, but msvc 
>> doesn't have tgmath,h, yet clang has.
>>
> 
> MSVC has famously bad C99 support.  clang has perfectly good C99 
> support.  But this sort of thing lies partly between the compiler and 
> the library (the two main parts of the C implementation).  <tgmath.h> 
> cannot be written in standard C (until C11) - it requires 
> compiler-specific features.  So it is one of the headers that is likely 
> to come with the compiler rather than the library.  On the other hand, 
> the /implementations/ of the functions used will be part of the C 
> run-time library.  MSVC uses highly inefficient DLL's for this, and 
> their DLL's don't have good C99 support.  So it does not surprise me 
> that the hack they have made with fitting clang onto MSVC results in the 
> <tgmath.h> header being fine while missing the functions in the library. 
>   (The same applies if you are using MingW rather than MSVC - that's why 
> I recommended MingW-64.)  I'd imagine that with enough effort, you could 
> find options or libraries to handle this, or you could install clang 
> along with fuller libraries.
> 
>>>> Interestingly, all programs seem to have the same runtime: 
>>>> optimisation makes little difference (all take around 6-7 seconds on 
>>>> my machine, of which generating the .ppm file is a tiny part).
>>>>
>>>
>>> Depending on the cpu you are running on, that is not too surprising 
>>> for a program that works with a lot of floating point calculations, 
>>> especially things like square roots and division.
>> ...
>>> Still, in my testing with gcc 5.4 (64-bit Linux), unoptimised code 
>>> took 0.68s, while with reasonable fast options "-O3 -ffast-math 
>>> -march=native" it takes 0.44 seconds.
>>
>>> Since that is an order of magnitude faster than your system, and my 
>>> PC is not usually /that/ much faster than yours, it could well be the 
>>> effect of scheduling, pipelining, and out-of-order execution on the 
>>> particular cpu.
>>
>> Actually there is something I overlooked completely, which is the 
>> printf that is called on every point. It overwrites the same line so 
>> you don't appreciate how many lines are displayed.
>>
> 
> You are right - I never noticed that (I didn't look much at the program 
> itself).  Yes, this will dominate.

Well, "almost" every point in the grand scheme of things. In the ct_ifs 
function the output is within the damn fractal computation loop.

         if (! (i % 256))
         {
             printf("rendering: %lu of %lu\r", i + 1, n);
         }

That mod is not pretty as well...

_________________
// Compute the fractal
void
ct_ifs(
     struct ct_plot* const plot,
     unsigned long n
){
     // 2 sets
     double complex jp[] = {
         .5 + 0 * I,
         -5.5 + I*.0
     };

     double complex z = 0+0*I;
     double complex c = 0+0*I;

     for (unsigned long i = 0; i < n; ++i)
     {
         double rn0 = rand() / (RAND_MAX - .0);
         double rn1 = rand() / (RAND_MAX - .0);

         if (rn0 > .5)
         {
             c = jp[0];
         }

         else
         {
             c = jp[1];
         }


         double complex d = z - c;
         double complex root = csqrt(d);

         z = root;

         if (rn1 > .5)
         {
             z = -root;
         }

          ct_plot_point(plot, z, 255);
          ct_plot_point(plot, root, 255);


   //****** Output in 256 chunks.
         if (! (i % 256))
         {
             printf("rendering: %lu of %lu\r", i + 1, n);
         }
     }

     printf("rendering: %lu of %lu\n", n, n);
}
_________________

Removing this "pointless, in a sense... progress" output will greatly 
increase the speed of the fractal calculations. I just left it in there 
so I could see the damn progress. I should use a fflush(stdout) after 
each call to printf to make it even more inefficient. ;^)


Sorry about that.

> 
>> Without that, then it was much faster (certainly on Windows). Fast 
>> enough that generating the .ppm was was significant.
>>
>> So without the ppm, and without printf, timings varied from 0.75 
>> seconds to 1.2 seconds, with gcc-O3 fastest.
>>
>> Using your additional options, gcc took 0.5 seconds. Just over twice 
>> as fast as my unoptimised bcc (1.1) or gcc-O0 (1.15); this is where 
>> the floating point overheads limit the difference.
>>
> 
> Interesting.
> 
> 
> 

[toc] | [prev] | [next] | [standalone]


#140334

FromBart <bc@freeuk.com>
Date2019-01-27 23:53 +0000
Message-ID<Tvr3E.98534$AD1.55847@fx05.am4>
In reply to#140331
On 27/01/2019 22:28, Chris M. Thomasson wrote:
> On 1/27/2019 7:36 AM, David Brown wrote:
>> On 27/01/2019 15:13, Bart wrote:

>>> Actually there is something I overlooked completely, which is the 
>>> printf that is called on every point.

>          if (! (i % 256))
>          {
>              printf("rendering: %lu of %lu\r", i + 1, n);
>          }
>      }

> }
> _________________
> 
> Removing this "pointless, in a sense... progress" output will greatly 
> increase the speed of the fractal calculations. I just left it in there 
> so I could see the damn progress. I should use a fflush(stdout) after 
> each call to printf to make it even more inefficient. ;^)

Yeah, it's not really every point, but every 256th. Although that still 
makes it dominate the run-time.

I tried a printf literally on every point, and it took 12 minutes, 
compared with 1-2 seconds without any printing.

[toc] | [prev] | [next] | [standalone]


#140387

From"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>
Date2019-01-29 13:11 -0800
Message-ID<q2qfht$ddk$2@gioia.aioe.org>
In reply to#140328
On 1/27/2019 7:36 AM, David Brown wrote:
> On 27/01/2019 15:13, Bart wrote:
>> On 27/01/2019 12:20, David Brown wrote:
>>> On 26/01/2019 13:35, Bart wrote:
>>
>>>> msvc: no tgmath.h (and loads of errors when you just comment it out. 
>>>> What is tgmath.h for anyway?)
>>>>
>>>
>>>
>>> Chris said it was a C99 program.

[...]

I thank Bart for removing the dependency of tgmath.h and complex.h. 
However, C99 is just to convenient. I am sticking with it for several 
reasons, one of which is I like the way it can handle complex numbers so 
naturally. 1+0*I is just so easy, right in the language itself.

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web