Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #140290 > unrolled thread
| Started by | "Chris M. Thomasson" <ahh_f_it@crap.nothing> |
|---|---|
| First post | 2019-01-25 14:24 -0800 |
| Last post | 2019-02-11 13:44 -0800 |
| Articles | 20 on this page of 41 — 10 participants |
Back to article view | Back to comp.lang.c
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 →
| From | "Chris M. Thomasson" <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-01-25 14:24 -0800 |
| Subject | Simple 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]
| From | "Chris M. Thomasson " <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-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]
| From | Eli the Bearded <*@eli.users.panix.com> |
|---|---|
| Date | 2019-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]
| From | "Chris M. Thomasson" <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | "Chris M. Thomasson " <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2019-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | "Chris M. Thomasson" <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | "Chris M. Thomasson" <ahh_f_it@crap.nothing> |
|---|---|
| Date | 2019-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> |
|---|---|
| Date | 2019-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