Wednesday, July 6, 2022

Digest for comp.lang.c++@googlegroups.com - 16 updates in 4 topics

"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 06 12:32PM -0700

I asked around to some very knowledgeable fractal geniuses, and so far,
nobody has seen it before. To make this more on topic, here is my quick
and dirty code that generates a PPM. It uses the GLM library that can be
found here:
 
https://github.com/g-truc/glm
 
For those that are using vcpkg for MSVC just install it using:
 
.\vcpkg install glm
 
https://vcpkg.io/en/index.html
 
Actually, this tool makes installing packages rather easy... Ahh that is
another topic altogether. Anyway, here is my code. I only compiled it
with MSVC so far in C++14 mode. I have to try some other compilers. Can
you get it to compile and generate a ppm called "ct_p0.ppm" on your end?
Thanks everybody:
_______________________________
#include <iostream>
#include <vector>
#include <cstdio>
 
#include <glm/glm.hpp>
 
 
#define CT_WIDTH 1920
#define CT_HEIGHT 1080
#define CT_PI 3.14159f
#define CT_PI2 (CT_PI * 2)
 
 
// The PPM Canvas
namespace ct
{
namespace ppm
{
struct canvas
{
unsigned long m_width;
unsigned long m_height;
std::vector<glm::ivec3> m_buf;
 
canvas(
unsigned long width,
unsigned long height
): m_width(width),
m_height(height),
m_buf(width * height)
{
std::cout << "(" << this << ")->canvas::canvas(" <<
width << ", " << height << ")\n";
}
 
 
bool
save(
char const* fname
) {
std::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)";
 
std::fprintf(fout, "%s\n%lu %lu\n%u\n",
ppm_head,
m_width, m_height,
255U
);
 
std::size_t size = m_width * m_height;
 
for (std::size_t i = 0; i < size; ++i)
{
glm::ivec3& pixel = m_buf[i];
 
std::fprintf(fout, "%c%c%c", pixel.r, pixel.g,
pixel.b);
}
 
if (! std::fclose(fout))
{
std::cout << "(" << this << ")->canvas::save("
<< fname << ")\n";
return true;
}
}
 
return false;
}
};
}
}
 
 
 
// The Plane
namespace ct
{
namespace plot2d
{
glm::vec4
axes_from_point(
glm::vec2 z,
float radius
) {
return {
z.x - radius, z.x + radius,
z.y - radius, z.y + radius
};
}
 
struct plane
{
glm::vec4 m_axes;
glm::vec4 m_step;
 
plane(
glm::vec4 const& axes,
unsigned long width,
unsigned long height
) : m_axes(axes)
{
float awidth = m_axes.y - m_axes.x;
float aheight = m_axes.w - m_axes.z;
 
float daspect = glm::abs((float)height / width);
float waspect = glm::abs(aheight / awidth);
 
if (daspect > waspect)
{
float excess = aheight * (daspect / waspect - 1.0f);
m_axes.w += excess / 2.0f;
m_axes.z -= excess / 2.0f;
}
 
else if (daspect < waspect)
{
float excess = awidth * (waspect / daspect - 1.0f);
m_axes.y += excess / 2.0f;
m_axes.x -= excess / 2.0f;
}
 
m_step.x = (m_axes.y - m_axes.x) / width;
m_step.y = (m_axes.w - m_axes.z) / height;
}
};
}
}
 
 
// The Plotter
namespace ct
{
namespace plot2d
{
struct plot
{
plane m_plane;
ppm::canvas& m_canvas;
 
plot(
plane const& plane,
ppm::canvas& canvas
) : m_plane(plane),
m_canvas(canvas)
{
 
}
 
bool
plot_pixel(
long x,
long y,
glm::vec3 const& color
) {
if (x > -1 && x < (long)m_canvas.m_width &&
y > -1 && y < (long)m_canvas.m_height)
{
// Now, we can convert to index.
std::size_t i = x + y * m_canvas.m_width;
 
glm::ivec3 rgb_color = { color.x * 255, color.y *
255, color.z * 255 };
 
m_canvas.m_buf[i] = rgb_color;
return true;
}
 
return false;
}
 
bool
plot_point(
glm::vec2 z,
glm::vec3 const& color
) {
long x = (long)((z.x - m_plane.m_axes.x) /
m_plane.m_step.x);
long y = (long)((m_plane.m_axes.w - z.y) /
m_plane.m_step.y);
 
if (x > -1 && x < (long)m_canvas.m_width &&
y > -1 && y < (long)m_canvas.m_height)
{
// Now, we can convert to index.
std::size_t i = x + y * m_canvas.m_width;
 
glm::ivec3 rgb_color = { color.x * 255, color.y *
255, color.z * 255 };
 
m_canvas.m_buf[i] = rgb_color;
 
return true;
}
 
return false;
}
};
}
}
 
 
 
// TTR
namespace ct
{
namespace ttr
{
struct circle
{
glm::vec3 p;
float r;
};
 
#define SQ(a) ((a) * (a))
 
bool
intersect(
circle const& c0,
circle const& c1,
circle& i0,
circle& i1
) {
// load from the two input circles c0 and c1
float A = c0.p.x;
float B = c0.p.y;
float C = c0.r;
 
float O = c1.p.x;
float P = c1.p.y;
float F = c1.r;
 
 
// gather delta's between c0 and c1
float G = A - O;
float H = B - P;
 
 
// evaluate the formulas conditions
if ((SQ(O - A) + SQ(P - B)) == 0 ||
(4 * SQ(O - A) + 4 * SQ(P - B)) == 0 ||
(((-SQ(SQ(C) - SQ(F) + SQ(O - A) + SQ(H))) /
(4 * SQ(O - A) + 4 * SQ(P - B)) +
SQ(C)) / (SQ(O - A) + SQ(P - B))) < 0.f)
{
return false;
}
 
float Q = -2 * SQ(A) + 4 * A * O - 2 * SQ(B) + 4 * B * P -
2 * SQ(O) - 2 * SQ(P);
 
float J = glm::sqrt(((-SQ(SQ(C) - SQ(F) + SQ(G) + SQ(H))) /
(4 * SQ(G) + 4 * SQ(H)) + SQ(C)) / (SQ(G) + SQ(H)));
 
float K = (-G) * (SQ(F) - SQ(C)) / Q + A / 2 + O / 2;
float L = (-H) * (SQ(F) - SQ(C)) / Q + B / 2 + P / 2;
 
float M = K - H * J; // x i0
float R = G * J + L; // y i0
float S = H * J + K; // x i1
float T = L - G * J; // y i1
 
i0.p.x = M;
i0.p.y = R;
i0.p.z = 0;
i0.r = 0;
 
i1.p.x = S;
i1.p.y = T;
i1.p.z = 0;
i1.r = 0;
 
return true;
}
}
}
 
 
 
 
// Test Fractal
namespace ct
{
namespace test_fractal
{
bool
find_tangent(
ct::ttr::circle c0,
ct::ttr::circle c1,
ct::ttr::circle& t0,
ct::ttr::circle& t1,
float radius
) {
// add the radius to the circles
c0.r += radius;
c1.r += radius;
 
// Find the intersections
if (!ct::ttr::intersect(c0, c1, t0, t1)) return false;
 
// Set the radius of the intersections
t0.r = radius;
t1.r = radius;
 
return true;
}
 
 
 
void
recur(
ct::plot2d::plot& scene,
unsigned long ri,
unsigned long rn,
ct::ttr::circle c0,
ct::ttr::circle c1,
float radius,
float scale
) {
if (ri >= rn) return;
 
// Find the tangent circles
ct::ttr::circle t0;
ct::ttr::circle t1;
 
if (! find_tangent(c0, c1, t0, t1, radius))
{
return;
}
 
// Plot points
scene.plot_point(t0.p, { 1, 1, 1 });
scene.plot_point(t1.p, { 1, 1, 1 });
 
float radius_next = radius * scale;
 
recur(scene, ri + 1, rn, c0, t0, radius_next, scale);
recur(scene, ri + 1, rn, c1, t0, radius_next, scale);
recur(scene, ri + 1, rn, c0, t1, radius_next, scale);
recur(scene, ri + 1, rn, c1, t1, radius_next, scale);
}
}
}
 
 
 
 
// Circle Test
void
ct_plot_circle(
ct::plot2d::plot& scene,
glm::vec3 origin,
float origin_radius
) {
unsigned long n = 512;
 
float angle_base = CT_PI2 / n;
 
for (unsigned long i = 0; i < n; ++i)
{
float angle = angle_base * i;
 
glm::vec3 p0_normal = {
glm::cos(angle),
glm::sin(angle),
0
};
 
glm::vec3 p0 = origin + p0_normal * origin_radius;
 
scene.plot_point(p0, { 1, 0, 1 });
}
}
 
 
 
int
main(void)
{
std::cout << "ct_ppm_base\n";
std::cout << "________________________________\n" << std::endl;
 
{
// Setup plotter...
ct::ppm::canvas canvas(CT_WIDTH, CT_HEIGHT);
glm::vec4 axes = ct::plot2d::axes_from_point({ 0, 0 }, 2.f);
ct::plot2d::plane plane(axes, canvas.m_width, canvas.m_height);
ct::plot2d::plot scene(plane, canvas);
 
// Plot test fractal
{
ct::ttr::circle c0 = { { -.5, 0, 0 }, .5 };
ct::ttr::circle c1 = { { .5, 0, 0 }, .5 };
 
ct::test_fractal::recur(scene, 0, 10, c0, c1, .8f, .45f);
}
 
// Plot unit circle
ct_plot_circle(scene, { 0, 0, 0 }, 1.f);
 
scene.m_canvas.save("ct_p0.ppm");
}
 
return 0;
}
_______________________________
 
Take a look at the code and tear it apart. Tell me about any issues.
What am I doing wrong? ;^)
 
Thanks again.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 06 12:40PM -0700

On 7/6/2022 12:32 PM, Chris M. Thomasson wrote:
> nobody has seen it before. To make this more on topic, here is my quick
> and dirty code that generates a PPM. It uses the GLM library that can be
> found here:
[...]
 
> with MSVC so far in C++14 mode. I have to try some other compilers. Can
> you get it to compile and generate a ppm called "ct_p0.ppm" on your end?
> Thanks everybody:
 
One nitpick on my own crude work:
 
>                         glm::ivec3& pixel = m_buf[i];
 
>                         std::fprintf(fout, "%c%c%c", pixel.r, pixel.g,
> pixel.b);
 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
Humm. I should really cast pixel.r/g/b components into 8-bit quantity's
here... Any thoughts?
 
>                         return true;
>                     }
>                 }
[...]
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jul 06 11:26PM +0100


> Can you get it to compile and generate a ppm called "ct_p0.ppm" on
> your end?
 
Compiles and runs on Ubuntu with gcc.
 
--
Ben.
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 06 02:10PM -0500

"Windows 11 Version Detection" by Shao Voon Wong

https://www.codeproject.com/Articles/5336372/Windows-11-Version-Detection
 
Complicated as usual.
 
Lynn
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 05 05:20PM -0700

Hm, perhaps having legacy code should be forced to change especially if new standards plug old problems. We all need jobs, well some of us do and recoding the old stuff, we are talking about job security till death.
 
I do now understand some of the choices made be swift language creators. Except one, why not call a constant a const instead of the let, let just seems so corny (basic) good grief.
 
Too many integer types in c++, just too many for 2023, int , double, 64 bits, let's move on. Plenty of memory, plenty on space in the chips as we get to one nm.
 
Until the 128 bit processors show up.
 
πŸ€”πŸ™‚πŸ˜ŽπŸ˜‡
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 05 07:06PM -0700

Paavo Helde <eesnimi@osa.pri.ee>: Jul 06 09:51AM +0300


>> C++'s built-in integer types: unsigned long, long, unsigned int, int, unsigned short, short,char,unsigned char,signed char,bool C++11's additions: unsigned long long and long long
>> πŸ€”πŸ™‚πŸ˜ŽπŸ˜‡
 
You are forgetting some: wchar_t, char8_t, char16_t, char32_t.
 
Curiously enough, the standard first says that bool and char... types do
not belong under signed integer nor unsigned integer types, but all
these collectively belong into "integral types". Then it goes on and
says this is the same as "integer types".
 
Welcome the the beautiful C++ world of counting angels on a pinhead!
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jul 06 10:42AM +0200

On 6 Jul 2022 08:51, Paavo Helde wrote:
> these collectively belong into "integral types". Then it goes on and
> says this is the same as "integer types".
 
> Welcome the the beautiful C++ world of counting angels on a pinhead!
 
Descartes concluded that you could fit an infinite number of them,
because an angel was pure intellect of zero size. He also thought the
Earth was the center of the universe and that Pascal was wrong about the
existence of vacuum; no no, no matter what your experiments show,
Pascal, nature abhors a vacuum.
 
Not sure if he adopted Aristotle's stance that an arrow could not move
in vacuum because there was no air that it could push away so that it
moved around to behind it for pushing it forward.
 
The greatest philosophers these, and that makes me wonder about the
quality of the less than greatest.
 
But perhaps Descartes and Pascal simply meant different concepts when
they said "vacuum", like an absence of everything versus absence of air.
I don't think they ever stopped and asked the other, what /exactly/ do
you mean when you say "vacuum"? Perhaps they wouldn't have disagreed so
strongly if they both had to adhere to some word list's definition.
 
And perhaps a lot of discussion and argument could have been avoided
with more clear terminology for C++, e.g. "call", of constructors. The
old meme that one cannot "call" constructors is still being passed
around and used as advice to beginners. There is no good defense against
that kind of irrationality that like religion ends up sabotaging minds.
 
- Alf
jak <nospam@please.ty>: Jul 06 11:03AM +0200

Il 06/07/2022 10:42, Alf P. Steinbach ha scritto:
> old meme that one cannot "call" constructors is still being passed
> around and used as advice to beginners. There is no good defense against
> that kind of irrationality that like religion ends up sabotaging minds.
 
 
This is because the manuals are full of ambiguity that allow too much
interpretation. This is the reason why infinite threads begin to discuss
about sex of angels (nothingness).
Juha Nieminen <nospam@thanks.invalid>: Jul 06 09:12AM

> Too many integer types in c++, just too many for 2023, int , double, 64 bits, let???s move on. Plenty of memory, plenty on space in the chips as we get to one nm.
 
Yeah, plenty of memory... until you need to use a billion 8-bit or 16-bit integers
in an array. Then you'll be glad you have the option.
 
If you don't like having so many options for integers, go program in JavaScript.
jak <nospam@please.ty>: Jul 06 11:26AM +0200

Il 06/07/2022 11:12, Juha Nieminen ha scritto:
 
> Yeah, plenty of memory... until you need to use a billion 8-bit or 16-bit integers
> in an array. Then you'll be glad you have the option.
 
> If you don't like having so many options for integers, go program in JavaScript.
 
If the C# produced code executable similar to C++ (not IL), the latter
language would have died dozens of years ago
Bo Persson <bo@bo-persson.se>: Jul 06 02:07PM +0200

On 2022-07-06 at 11:26, jak wrote:
>> JavaScript.
 
> If the C# produced code executable similar to C++ (not IL), the latter
> language would have died dozens of years ago
 
Right, if C++ wasn't any good, we wouldn't use it.
 
Amazing what we can discover here.
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 06 05:27AM -0700

Java terrible idea, the cobol of modern language.
Why invest in new standards for an old language if you are not going to be much more concise.
Or much less concise.
But the idea that there are new features in those other bands of kitchen sink, well, we have to throw that in ours it is not necessary. Are lambdas really a must have? I'm just asking.
What newbies to love c++ , get rid pointers and or change the notation for it, lol. Ok I know you don't about the newbies, but this is how dead language must have started
🧐
jak <nospam@please.ty>: Jul 06 02:28PM +0200

Il 06/07/2022 14:07, Bo Persson ha scritto:
>> language would have died dozens of years ago
 
> Right, if C++ wasn't any good, we wouldn't use it.
 
> Amazing what we can discover here.
 
As a programmer you shouldn't ignore the 'if' when you read the comments
Paul N <gw7rib@aol.com>: Jul 06 08:45AM -0700

> old meme that one cannot "call" constructors is still being passed
> around and used as advice to beginners. There is no good defense against
> that kind of irrationality that like religion ends up sabotaging minds.
 
I thought that "one cannot call constructors" wasn't irrational, it's just out of date now. See https://isocpp.org/wiki/faq/ctors#init-methods in the FAQ.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jul 05 11:50PM -0400

On 7/1/22 16:56, Richard Damon wrote:
...
> actual constant condition could be presumed to eventually end, so if a
> loop has no observable effects, it can be optimized away. This has
> broken many a benchmark when the code under test just gets optimized away.
 
I think the rule you're thinking of is the following:
 
"An iteration statement may be assumed by the implementation to
terminate if its controlling expression is not a constant expression,
171) and none of the following operations are performed in its body,
controlling expression or (in the case of a for statement) its
expression-3: 172)
— input/output operations
— accessing a volatile object
— synchronization or atomic operations."
 
However, that rule is from the C standard (6.8.5p6), and I did not
locate corresponding text in the C++ standard.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: