Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

The best way to accelerate a Macintoy is at 9.8 meters per second per second.


devel / comp.lang.c / C vis C++ standard deviation function.

SubjectAuthor
* C vis C++ standard deviation function.Malcolm McLean
+* Re: C vis C++ standard deviation function.Bart
|+* Re: C vis C++ standard deviation function.Ben Bacarisse
||+* Re: C vis C++ standard deviation function.Malcolm McLean
|||`* Re: C vis C++ standard deviation function.Ben Bacarisse
||| `* Re: C vis C++ standard deviation function.Malcolm McLean
|||  `* Re: C vis C++ standard deviation function.Ben Bacarisse
|||   `* Re: C vis C++ standard deviation function.Malcolm McLean
|||    `* Re: C vis C++ standard deviation function.Ben Bacarisse
|||     `* Re: C vis C++ standard deviation function.Malcolm McLean
|||      `- Re: C vis C++ standard deviation function.Ben Bacarisse
||`* Re: C vis C++ standard deviation function.Scott Lurndal
|| `* Re: C vis C++ standard deviation function.Ben Bacarisse
||  `* Re: C vis C++ standard deviation function.David Brown
||   +- Re: C vis C++ standard deviation function.Malcolm McLean
||   `* Re: C vis C++ standard deviation function.Ben Bacarisse
||    `* Re: C vis C++ standard deviation function.David Brown
||     `* Re: C vis C++ standard deviation function.Ben Bacarisse
||      `- Re: C vis C++ standard deviation function.Andreas Kempe
|`* Re: C vis C++ standard deviation function.Manu Raju
| +* Re: C vis C++ standard deviation function.Bonita Montero
| |+* Re: C vis C++ standard deviation function.Bart
| ||+- Re: C vis C++ standard deviation function.Bonita Montero
| ||`* Re: C vis C++ standard deviation function.Bonita Montero
| || `* Re: C vis C++ standard deviation function.Bart
| ||  +* Re: C vis C++ standard deviation function.Bonita Montero
| ||  |`* Re: C vis C++ standard deviation function.Bart
| ||  | `- Re: C vis C++ standard deviation function.Bonita Montero
| ||  +* Re: C vis C++ standard deviation function.Ben Bacarisse
| ||  |+* Re: C vis C++ standard deviation function.Bart
| ||  ||`* Re: C vis C++ standard deviation function.Ben Bacarisse
| ||  || `* Re: C vis C++ standard deviation function.Bart
| ||  ||  +- Re: C vis C++ standard deviation function.Ben Bacarisse
| ||  ||  +* Re: C vis C++ standard deviation function.Bonita Montero
| ||  ||  |`* Re: C vis C++ standard deviation function.Bart
| ||  ||  | +- Re: C vis C++ standard deviation function.Bonita Montero
| ||  ||  | `* Re: C vis C++ standard deviation function.Manfred
| ||  ||  |  `* Re: C vis C++ standard deviation function.Bonita Montero
| ||  ||  |   `- Re: C vis C++ standard deviation function.Bart
| ||  ||  `* Re: C vis C++ standard deviation function.Malcolm McLean
| ||  ||   +- Re: C vis C++ standard deviation function.Bonita Montero
| ||  ||   +* Re: C vis C++ standard deviation function.Scott Lurndal
| ||  ||   |+* Re: C vis C++ standard deviation function.Malcolm McLean
| ||  ||   ||`- Re: C vis C++ standard deviation function.Scott Lurndal
| ||  ||   |`- Re: C vis C++ standard deviation function.Manu Raju
| ||  ||   `* Re: C vis C++ standard deviation function.Bart
| ||  ||    `- Re: C vis C++ standard deviation function.Ben Bacarisse
| ||  |`- Re: C vis C++ standard deviation function.Bonita Montero
| ||  `- Re: C vis C++ standard deviation function.Malcolm McLean
| |`* Re: C vis C++ standard deviation function.Manu Raju
| | +- Re: C vis C++ standard deviation function.Bart
| | `- Re: C vis C++ standard deviation function.Bonita Montero
| +- Re: C vis C++ standard deviation function.Bonita Montero
| `* Re: C vis C++ standard deviation function.Bart
|  `* Re: C vis C++ standard deviation function.Bonita Montero
|   `- Re: C vis C++ standard deviation function.Malcolm McLean
+* Re: C vis C++ standard deviation function.Kenny McCormack
|`* Re: C vis C++ standard deviation function.Bonita Montero
| `- Re: C vis C++ standard deviation function.Kenny McCormack
+- Re: C vis C++ standard deviation function.Ben Bacarisse
`* Re: C vis C++ standard deviation function.Bonita Montero
 `- Re: C vis C++ standard deviation function.Bonita Montero

Pages:123
C vis C++ standard deviation function.

<b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20823&group=comp.lang.c#20823

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:622a:188f:b0:2de:8a7:3272 with SMTP id v15-20020a05622a188f00b002de08a73272mr5491235qtc.559.1646565427822;
Sun, 06 Mar 2022 03:17:07 -0800 (PST)
X-Received: by 2002:a05:620a:8c3:b0:67b:1821:efd5 with SMTP id
z3-20020a05620a08c300b0067b1821efd5mr760159qkz.450.1646565427652; Sun, 06 Mar
2022 03:17:07 -0800 (PST)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Sun, 6 Mar 2022 03:17:07 -0800 (PST)
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23a8:400a:5601:885b:85dd:7ba4:6e95;
posting-account=Dz2zqgkAAADlK5MFu78bw3ab-BRFV4Qn
NNTP-Posting-Host: 2a00:23a8:400a:5601:885b:85dd:7ba4:6e95
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Subject: C vis C++ standard deviation function.
From: malcolm....@gmail.com (Malcolm McLean)
Injection-Date: Sun, 06 Mar 2022 11:17:07 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 83
 by: Malcolm McLean - Sun, 6 Mar 2022 11:17 UTC

Following the recent discussion of "reduce", I decided to try my hand at generic programming in C++.

Here's how I would write the standard deviation function in C

double stddev(double *x, int N)
{ int i;
double mean = 0;
double sumvar2 = 0;

for (i =0; i < N; i++)
mean += x[i];
mean /= N;

for (i =0; i < N; i++)
sumvar2 += (x[i] - mean)*(x[i]-mean);

return sqrt(sumvar2/(N-1));
}

Here's my attempt in C++.

#include <iostream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <cmath>

template <class Iterator, typename func_t>
double stddev(Iterator first, Iterator last, func_t todouble)
{ typedef typename std::iterator_traits<Iterator>::value_type T;
double sum = std::transform_reduce(first, last, 0.0,
[](double a, double b){return a + b;}, todouble);
typename std::iterator_traits<Iterator>::difference_type N = std::distance(first, last);
double sume2 = std::transform_reduce(first, last, 0.0,
[](double a, double b){return a + b;},
[sum, N, todouble](T &value){double x = todouble(value);
return (x - sum/N)*(x-sum/N);}
);

return sqrt(sume2/(N-1));
}

A few comments. Whilst C has a reputation for efficiency, in fact
the C implementation will usually be less efficient. That's because
typically data comes in structs. You might want the standard deviation
of the employees' salaries. In C, that means allocating a temporary array,
traversing the employee array and picking out the salaries, calling stddev,
and freeing the temporary. In C++, it's easy to provide an access function.
(You can do this in C, but it makes the signature of the function too
complicated).

C++ is meant to be generic. But the standard deviation of a set of
integers is a real. How are you meant to express that? I'm sure there's
a way, but there didn't seem to be any tidy way of doing it. I resorted
to using a double as the return value. A lot of the complexity expresses
the simple idea that the function operates on the type that the iterators
point to. This is a legacy of the way C++ has grown by accretion.

transform_reduce can be parallelised. So in theory, once we've written
this function, we never need to write it again. When we get whizzy hardware
which is really good at fine-grained parallelisation, we rewrite transform_reduce() to take advantage of it.

In reality, it's hard to think of a case where calculating the standard
deviation would need to be faster than a commodity PC can do it
on a single core. In a real program, the x values have to mean something,
which usually means they are collected from the outside world. Collection
is so expensive and slow that rocessing speed is almost irrelevant.

However, of course, I chose this function because it is easy to implement
with transform_reduce.

I tried to develop this on replit. It failed to compile because the C++
version didn't have transform_reduce. So I tried my commandline g++.
Same story. g++ is mean to be a front end to clang. My IDE did compile
it. However setting up a project is heavyweight, so I cut and pasted
into another project. Finally it compiled. But this sort of messing about
with implementations greatly reduces the utility of code in the real world,
and is why I write a lot of code in a conservative subset of C89 and
the later versions. Then it almost always compiles in a new environment
without problems.

Re: C vis C++ standard deviation function.

<t028t1$53p$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20824&group=comp.lang.c#20824

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 12:19:45 +0000
Organization: A noiseless patient Spider
Lines: 87
Message-ID: <t028t1$53p$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 12:19:45 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="8980970af4ff0eac474a7e725117ab98";
logging-data="5241"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18E7mZkzeZ4TvjwZtzKZaC4+pXqwp24xyk="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.1
Cancel-Lock: sha1:iyIvkudAHsDbwzQliPF0Vm3iPBA=
In-Reply-To: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
 by: Bart - Sun, 6 Mar 2022 12:19 UTC

On 06/03/2022 11:17, Malcolm McLean wrote:
> Following the recent discussion of "reduce", I decided to try my hand at generic programming in C++.
>
> Here's how I would write the standard deviation function in C
>
> double stddev(double *x, int N)
> {
> int i;
> double mean = 0;
> double sumvar2 = 0;
>
> for (i =0; i < N; i++)
> mean += x[i];
> mean /= N;
>
> for (i =0; i < N; i++)
> sumvar2 += (x[i] - mean)*(x[i]-mean);
>
> return sqrt(sumvar2/(N-1));
> }
>
> Here's my attempt in C++.
....
> template <class Iterator, typename func_t>
> double stddev(Iterator first, Iterator last, func_t todouble)
> {
> typedef typename std::iterator_traits<Iterator>::value_type T;
> double sum = std::transform_reduce(first, last, 0.0,
> [](double a, double b){return a + b;}, todouble);
> typename std::iterator_traits<Iterator>::difference_type N = std::distance(first, last);
> double sume2 = std::transform_reduce(first, last, 0.0,
> [](double a, double b){return a + b;},
> [sum, N, todouble](T &value){double x = todouble(value);
> return (x - sum/N)*(x-sum/N);}
> );
>
> return sqrt(sume2/(N-1));
> }
>
> A few comments.

I don't need to read any further. Just look at the difference between
those two examples. I can easily follow the algorithm expressed as C,
but I can'make out anything in the C++. Is there even an algorithm in
that lot? All I can see is the last line that matches C's.

That this is supposed to be generic is no excuse. Generic code should
not need to look much different from non-generic code. With dynamic
typing, it would be exactly the same source code**.

According to the examples posted by David Brown, a generic version of
your the C function, written in C++, ought to look like this:

double stddev(auto *x, int N) {...}

x is a pointer to int, long long int, float or double. But I couldn't
get this to compile. If code needs to look like your C++, then it is a
failure IMO.

--

** I'm in the process of adding dynamic types to my otherwise static
systems language. The following example should be partly working by
tomorrow (when A is a simple List of variants), and fully working in a
week or two (allow any static arrays to be passed).

function stddev(var A)real =
real mean:=0, sumvar2:=0

for x in A do
mean +:= x
od

mean /:= A.len

for x in A do
sumvar2 +:= sqr(x-mean)
od

sqrt(sumvar2/(A.len-1))
end

The only downside is that expressions involving A and x need to use
dynamic type dispatch. But this does provide a generic routine if one is
needed.

Re: C vis C++ standard deviation function.

<t02a7n$19k6p$1@news.xmission.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20825&group=comp.lang.c#20825

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!xmission!nnrp.xmission!.POSTED.shell.xmission.com!not-for-mail
From: gaze...@shell.xmission.com (Kenny McCormack)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 12:42:31 -0000 (UTC)
Organization: The official candy of the new Millennium
Message-ID: <t02a7n$19k6p$1@news.xmission.com>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Injection-Date: Sun, 6 Mar 2022 12:42:31 -0000 (UTC)
Injection-Info: news.xmission.com; posting-host="shell.xmission.com:166.70.8.4";
logging-data="1364185"; mail-complaints-to="abuse@xmission.com"
X-Newsreader: trn 4.0-test77 (Sep 1, 2010)
Originator: gazelle@shell.xmission.com (Kenny McCormack)
 by: Kenny McCormack - Sun, 6 Mar 2022 12:42 UTC

In article <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>,
Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
>Following the recent discussion of "reduce", I decided to try my hand at generic
>programming in C++.

Off topic.

Try comp.lang.c++

--
BigBusiness types (aka, Republicans/Conservatives/Independents/Liberatarians/whatevers)
don't hate big government. They *love* big government as a means for them to get
rich, sucking off the public teat. What they don't like is *democracy* - you know,
like people actually having the right to vote and stuff like that.

Re: C vis C++ standard deviation function.

<8735jvb0wa.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20827&group=comp.lang.c#20827

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 14:39:49 +0000
Organization: A noiseless patient Spider
Lines: 169
Message-ID: <8735jvb0wa.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="16434"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18TMS+j5tLsWvH+MGHnJK0eUEWnQajirmA="
Cancel-Lock: sha1:nLb6Q87t0PUkL8i8EfFHsLY8+7Y=
sha1:eeg2RCzCQwvfjvfxQtg/qYH/mRw=
X-BSB-Auth: 1.fbe0154f4beca14b5694.20220306143949GMT.8735jvb0wa.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 14:39 UTC

Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> Following the recent discussion of "reduce", I decided to try my hand
> at generic programming in C++.
>
> Here's how I would write the standard deviation function in C
>
> double stddev(double *x, int N)
> {
> int i;
> double mean = 0;
> double sumvar2 = 0;
>
> for (i =0; i < N; i++)
> mean += x[i];
> mean /= N;
>
> for (i =0; i < N; i++)
> sumvar2 += (x[i] - mean)*(x[i]-mean);
>
> return sqrt(sumvar2/(N-1));
> }

If I was not worried about extreme data values, I'd write

double stddev(double *x, int N)
{
double sum = 0, sum_sq = 0;
for (int i = 0; i < N; i++) {
sum += x[i];
sum_sq += x[i] * x[i];
}
return sqrt((sum_sq - sum*sum/N) / (N-1));
}

> Here's my attempt in C++.
>
> #include <iostream>
> #include <numeric>
> #include <algorithm>
> #include <vector>
> #include <cmath>
>
> template <class Iterator, typename func_t>
> double stddev(Iterator first, Iterator last, func_t todouble)
> {
> typedef typename std::iterator_traits<Iterator>::value_type T;
> double sum = std::transform_reduce(first, last, 0.0,
> [](double a, double b){return a + b;}, todouble);
> typename std::iterator_traits<Iterator>::difference_type N = std::distance(first, last);
> double sume2 = std::transform_reduce(first, last, 0.0,
> [](double a, double b){return a + b;},
> [sum, N, todouble](T &value){double x = todouble(value);
> return (x - sum/N)*(x-sum/N);}
> );
>
> return sqrt(sume2/(N-1));
> }
>
> A few comments. Whilst C has a reputation for efficiency, in fact
> the C implementation will usually be less efficient. That's because
> typically data comes in structs. You might want the standard deviation
> of the employees' salaries. In C, that means allocating a temporary array,
> traversing the employee array and picking out the salaries, calling stddev,
> and freeing the temporary. In C++, it's easy to provide an access function.
> (You can do this in C, but it makes the signature of the function too
> complicated).
>
> C++ is meant to be generic. But the standard deviation of a set of
> integers is a real. How are you meant to express that? I'm sure there's
> a way, but there didn't seem to be any tidy way of doing it. I resorted
> to using a double as the return value. A lot of the complexity expresses
> the simple idea that the function operates on the type that the iterators
> point to. This is a legacy of the way C++ has grown by accretion.

You don't need to do that. Just tidying up a bit and giving the code
some room to breathe, I get a more readable template:

template <class Iterator, typename func_t>
double stddev(Iterator first, Iterator last, func_t todouble)
{
auto add_func = [](double a, double b){ return a + b; };

double sum = std::transform_reduce(first, last, 0.0, add_func, todouble);
auto N = std::distance(first, last);

double sume2 = std::transform_reduce(
first, last, 0.0, add_func,
[&](auto &value){
double x = todouble(value);
return (x - sum/N) * (x - sum/N);
});

return sqrt(sume2/(N-1));
}

But I don't know why you are worried about the conversion from int to
double:

template <class Iterator>
double stddevY(Iterator first, Iterator last)
{
auto add_func = [](double a, double b){ return a + b; };

double sum = std::accumulate(first, last, 0.0, add_func);
auto N = std::distance(first, last);

double sume2 = std::transform_reduce(
first, last, 0.0, add_func,
[&](double x){ return (x - sum/N) * (x - sum/N); }
);

return sqrt(sume2/(N-1));
}

But surely you could just use accumulate:

template <class Iterator>
double stddev(Iterator first, Iterator last)
{
double sum = std::accumulate(first, last, 0);
double sum_sq = std::accumulate(
first, last, 0, [](double sqs, double x){ return sqs + x*x; });
double N = std::distance(first, last);
return sqrt((sum_sq - sum*sum/N)/(N-1));
}

> transform_reduce can be parallelised.

I assume that accumulate can also be parallelised, but if not you can
just use something that can be like transform_reduce with the identity
function.

> So in theory, once we've written this function, we never need to write
> it again. When we get whizzy hardware which is really good at
> fine-grained parallelisation, we rewrite transform_reduce() to take
> advantage of it.
>
> In reality, it's hard to think of a case where calculating the standard
> deviation would need to be faster than a commodity PC can do it
> on a single core. In a real program, the x values have to mean something,
> which usually means they are collected from the outside world. Collection
> is so expensive and slow that rocessing speed is almost irrelevant.

A long time ago I was asked to write a function that (in effect)
averaged the standard deviations of every subset of a data set (with
some minimum size which I can't remember). It was, as you would expect,
very slow! But your main point stands: parallelisation of stddev would
not have helped much in this case, especially as I just kept adjusting a
running sum and sum of squares rather than calling stddev a lot.

However, my point is that can't say speed of F(X) is almost irrelevant
just because collecting X is expensive.

Also, collecting X is not always expensive. A network monitor that
collects real-time trip times and displays the standard deviation comes
to mind. Also a computer simulation of something might run at many,
many times the speed of the events in the real world and therefore end
up accumulating lots of data very fast.

> However, of course, I chose this function because it is easy to implement
> with transform_reduce.

It's an odd thing to post in comp.lang.c. You are really asking for
expert C++ advice on generics. Take what I say above with a pinch of
salt. It could be very bad C++ advice.

--
Ben.

Re: C vis C++ standard deviation function.

<87mti39l6r.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20828&group=comp.lang.c#20828

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 15:04:28 +0000
Organization: A noiseless patient Spider
Lines: 46
Message-ID: <87mti39l6r.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="28176"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/L6cLi1eAmSCYkgieyAxHgu4IeZTBJrE4="
Cancel-Lock: sha1:R6JjvVePZi01k6EO/9qxZXWrrBU=
sha1:KQw/4uuyPRPYnj96a7Sj2c9uhKo=
X-BSB-Auth: 1.41d3171455d6f199b576.20220306150428GMT.87mti39l6r.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 15:04 UTC

Bart <bc@freeuk.com> writes:

> That this is supposed to be generic is no excuse. Generic code should
> not need to look much different from non-generic code. With dynamic
> typing, it would be exactly the same source code**.
>
> According to the examples posted by David Brown, a generic version of
> your the C function, written in C++, ought to look like this:
>
> double stddev(auto *x, int N) {...}

double stddev(const auto *x, int N)
{
double sum = 0, sum_sq = 0;
for (int i = 0; i < N; i++) {
sum += x[i];
sum_sq += x[i]*x[i];
}
return sqrt((sum_sq - sum*sum/N)/(N-1));
}

But then you then probably loose the automatic parallelisation that the
standard library might give you.

> x is a pointer to int, long long int, float or double. But I couldn't
> get this to compile. If code needs to look like your C++, then it is a
> failure IMO.

The trouble is that the C++ code shown was intended to do more than the
C, and not just in terms of handling generic types. Also, you can't
judge C++ by a single example from one person. For example, I don't
think

double stddev(const auto &first, const auto &last)
{
double sum = std::accumulate(first, last);
double sum_sq = std::accumulate(
first, last, [](double sqs, double x){ return sqs + x*x; });
double N = std::distance(first, last);
return sqrt((sum_sq - sum*sum/N)/(N-1));
}

is particularly unclear.

--
Ben.

Re: C vis C++ standard deviation function.

<8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20829&group=comp.lang.c#20829

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:620a:459e:b0:67a:f44c:a2d9 with SMTP id bp30-20020a05620a459e00b0067af44ca2d9mr3710873qkb.179.1646580572998;
Sun, 06 Mar 2022 07:29:32 -0800 (PST)
X-Received: by 2002:a05:6214:62e:b0:435:6220:6f04 with SMTP id
a14-20020a056214062e00b0043562206f04mr5361062qvx.29.1646580572802; Sun, 06
Mar 2022 07:29:32 -0800 (PST)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Sun, 6 Mar 2022 07:29:32 -0800 (PST)
In-Reply-To: <87mti39l6r.fsf@bsb.me.uk>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23a8:400a:5601:795d:930b:4c0d:ec30;
posting-account=Dz2zqgkAAADlK5MFu78bw3ab-BRFV4Qn
NNTP-Posting-Host: 2a00:23a8:400a:5601:795d:930b:4c0d:ec30
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
Subject: Re: C vis C++ standard deviation function.
From: malcolm....@gmail.com (Malcolm McLean)
Injection-Date: Sun, 06 Mar 2022 15:29:32 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 56
 by: Malcolm McLean - Sun, 6 Mar 2022 15:29 UTC

On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
> Bart <b...@freeuk.com> writes:
>
> > That this is supposed to be generic is no excuse. Generic code should
> > not need to look much different from non-generic code. With dynamic
> > typing, it would be exactly the same source code**.
> >
> > According to the examples posted by David Brown, a generic version of
> > your the C function, written in C++, ought to look like this:
> >
> > double stddev(auto *x, int N) {...}
> double stddev(const auto *x, int N)
> {
> double sum = 0, sum_sq = 0;
> for (int i = 0; i < N; i++) {
> sum += x[i];
> sum_sq += x[i]*x[i];
> }
> return sqrt((sum_sq - sum*sum/N)/(N-1));
> }
> But then you then probably loose the automatic parallelisation that the
> standard library might give you.
> > x is a pointer to int, long long int, float or double. But I couldn't
> > get this to compile. If code needs to look like your C++, then it is a
> > failure IMO.
> The trouble is that the C++ code shown was intended to do more than the
> C, and not just in terms of handling generic types. Also, you can't
> judge C++ by a single example from one person. For example, I don't
> think
>
> double stddev(const auto &first, const auto &last)
> {
> double sum = std::accumulate(first, last);
> double sum_sq = std::accumulate(
> first, last, [](double sqs, double x){ return sqs + x*x; });
> double N = std::distance(first, last);
> return sqrt((sum_sq - sum*sum/N)/(N-1));
> }
>
> is particularly unclear.
>
Yes, but that's not generic. If first and last iterator over employees, the "+'
operator has to be defined to add two employees together. That's unlikely
to make any sort of sense.
In fact we'll want that standard deviation of the salaries. So we can pass
in a trivial little lambda [](Employee &employee){return employee.salary;}
If we've not another variable associated with the employees, like hours
worked, we can get the standard deviation of that just by changing the lambda.

reduce is better than accumulate because accumulate requires left-to
right evaluation of the operands. That's not necessary for a standard deviation,
unless annoyingly, we need every bit of precision (floating point arithmetic
isn't exactly associative, though it's near enough for almost all purposes).

You've used a slightly different formula for the standard deviation., which
is more efficient and creates tighter code.

Re: C vis C++ standard deviation function.

<bt4VJ.43898$7F2.32592@fx12.iad>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20830&group=comp.lang.c#20830

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!peer03.ams1!peer.ams1.xlned.com!news.xlned.com!peer03.ams4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx12.iad.POSTED!not-for-mail
X-newsreader: xrn 9.03-beta-14-64bit
Sender: scott@dragon.sl.home (Scott Lurndal)
From: sco...@slp53.sl.home (Scott Lurndal)
Reply-To: slp53@pacbell.net
Subject: Re: C vis C++ standard deviation function.
Newsgroups: comp.lang.c
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com> <t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
Lines: 28
Message-ID: <bt4VJ.43898$7F2.32592@fx12.iad>
X-Complaints-To: abuse@usenetserver.com
NNTP-Posting-Date: Sun, 06 Mar 2022 15:31:19 UTC
Organization: UsenetServer - www.usenetserver.com
Date: Sun, 06 Mar 2022 15:31:19 GMT
X-Received-Bytes: 1689
 by: Scott Lurndal - Sun, 6 Mar 2022 15:31 UTC

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>Bart <bc@freeuk.com> writes:
>
>> That this is supposed to be generic is no excuse. Generic code should
>> not need to look much different from non-generic code. With dynamic
>> typing, it would be exactly the same source code**.
>>
>> According to the examples posted by David Brown, a generic version of
>> your the C function, written in C++, ought to look like this:
>>
>> double stddev(auto *x, int N) {...}
>
> double stddev(const auto *x, int N)
> {
> double sum = 0, sum_sq = 0;
> for (int i = 0; i < N; i++) {
> sum += x[i];
> sum_sq += x[i]*x[i];
> }
> return sqrt((sum_sq - sum*sum/N)/(N-1));
> }
>
>But then you then probably loose the automatic parallelisation that the
>standard library might give you.

Unless you're using one of the ubiquitous automatically vectorizing
compilers.

Re: C vis C++ standard deviation function.

<87h78b9jpk.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20831&group=comp.lang.c#20831

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 15:36:23 +0000
Organization: A noiseless patient Spider
Lines: 35
Message-ID: <87h78b9jpk.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<bt4VJ.43898$7F2.32592@fx12.iad>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="28176"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+OiHLCToV0sS/Ga10gfaGbqcDRXCVbly8="
Cancel-Lock: sha1:XNZECvr5Tc7BJEdBWK7clefmWNE=
sha1:Xs9HRlrbQasqYq1OT03N98huKsM=
X-BSB-Auth: 1.62f9aab063784efa76a6.20220306153623GMT.87h78b9jpk.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 15:36 UTC

scott@slp53.sl.home (Scott Lurndal) writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>Bart <bc@freeuk.com> writes:
>>
>>> That this is supposed to be generic is no excuse. Generic code should
>>> not need to look much different from non-generic code. With dynamic
>>> typing, it would be exactly the same source code**.
>>>
>>> According to the examples posted by David Brown, a generic version of
>>> your the C function, written in C++, ought to look like this:
>>>
>>> double stddev(auto *x, int N) {...}
>>
>> double stddev(const auto *x, int N)
>> {
>> double sum = 0, sum_sq = 0;
>> for (int i = 0; i < N; i++) {
>> sum += x[i];
>> sum_sq += x[i]*x[i];
>> }
>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> }
>>
>>But then you then probably loose the automatic parallelisation that the
>>standard library might give you.
>
> Unless you're using one of the ubiquitous automatically vectorizing
> compilers.

Do they work well with type-generic code, given that they won't always
know how + and * are defined?

--
Ben.

Re: C vis C++ standard deviation function.

<t02lei$jcq$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20832&group=comp.lang.c#20832

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 16:53:53 +0100
Organization: A noiseless patient Spider
Lines: 47
Message-ID: <t02lei$jcq$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<bt4VJ.43898$7F2.32592@fx12.iad> <87h78b9jpk.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 15:53:54 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="23fbedda00f6040df04193486ad49b41";
logging-data="19866"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19Vx3Qy/TX1w3CdFIA0/M4KoOr8P7+XXjI="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:+a19O6Lc55uqKw2e7HNL5aJbjHc=
In-Reply-To: <87h78b9jpk.fsf@bsb.me.uk>
Content-Language: en-GB
 by: David Brown - Sun, 6 Mar 2022 15:53 UTC

On 06/03/2022 16:36, Ben Bacarisse wrote:
> scott@slp53.sl.home (Scott Lurndal) writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>> Bart <bc@freeuk.com> writes:
>>>
>>>> That this is supposed to be generic is no excuse. Generic code should
>>>> not need to look much different from non-generic code. With dynamic
>>>> typing, it would be exactly the same source code**.
>>>>
>>>> According to the examples posted by David Brown, a generic version of
>>>> your the C function, written in C++, ought to look like this:
>>>>
>>>> double stddev(auto *x, int N) {...}
>>>
>>> double stddev(const auto *x, int N)
>>> {
>>> double sum = 0, sum_sq = 0;
>>> for (int i = 0; i < N; i++) {
>>> sum += x[i];
>>> sum_sq += x[i]*x[i];
>>> }
>>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>>> }
>>>
>>> But then you then probably loose the automatic parallelisation that the
>>> standard library might give you.
>>
>> Unless you're using one of the ubiquitous automatically vectorizing
>> compilers.
>
> Do they work well with type-generic code, given that they won't always
> know how + and * are defined?
>

They know how + and * are defined when compiling the code - it's
compile-time polymorphism. Compilers can do exactly as much with such
templated (or implicitly templated with "auto") code as they can with
explicit types.

But I think there's a bit of mixup here between "parallelisation" and
"vectorisation" - they don't mean the same thing. Compilers can do
automatic vectorisation on code like this, but automatic parallelisation
is rarer. In theory, the C++ algorithm library functions support
parallel execution strategy - in practice they usually don't (i.e., you
can ask for parallel strategies, but you still get sequential ones).

Re: C vis C++ standard deviation function.

<87bkyj9ior.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20833&group=comp.lang.c#20833

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 15:58:28 +0000
Organization: A noiseless patient Spider
Lines: 93
Message-ID: <87bkyj9ior.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="22037"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19qvejrAVPVvvMQoEHvLw5pRrzuWBXgY1M="
Cancel-Lock: sha1:wa79BlY0rhaJwLS9P/QIuLBQkrs=
sha1:hLeppFuHBigDX71XDI2yWTG6A88=
X-BSB-Auth: 1.4ba85c1568b0e756ca87.20220306155828GMT.87bkyj9ior.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 15:58 UTC

Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
>> Bart <b...@freeuk.com> writes:
>>
>> > That this is supposed to be generic is no excuse. Generic code should
>> > not need to look much different from non-generic code. With dynamic
>> > typing, it would be exactly the same source code**.
>> >
>> > According to the examples posted by David Brown, a generic version of
>> > your the C function, written in C++, ought to look like this:
>> >
>> > double stddev(auto *x, int N) {...}
>> double stddev(const auto *x, int N)
>> {
>> double sum = 0, sum_sq = 0;
>> for (int i = 0; i < N; i++) {
>> sum += x[i];
>> sum_sq += x[i]*x[i];
>> }
>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> }
>> But then you then probably loose the automatic parallelisation that the
>> standard library might give you.
>> > x is a pointer to int, long long int, float or double. But I couldn't
>> > get this to compile. If code needs to look like your C++, then it is a
>> > failure IMO.
>> The trouble is that the C++ code shown was intended to do more than the
>> C, and not just in terms of handling generic types. Also, you can't
>> judge C++ by a single example from one person. For example, I don't
>> think
>>
>> double stddev(const auto &first, const auto &last)
>> {
>> double sum = std::accumulate(first, last);
>> double sum_sq = std::accumulate(
>> first, last, [](double sqs, double x){ return sqs + x*x; });
>> double N = std::distance(first, last);
>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> }
>>
>> is particularly unclear.
>>
> Yes, but that's not generic. If first and last iterator over employees, the "+'
> operator has to be defined to add two employees together. That's unlikely
> to make any sort of sense.

I think that's a good thing. Standard deviation is an arithmetic
property.

> In fact we'll want that standard deviation of the salaries. So we can pass
> in a trivial little lambda [](Employee &employee){return
> employee.salary;}

I think you should use the ranges::view types to pass iterators to that
data. Otherwise, every arithmetic operation has to acquire a little
function to do the conversion, and the most common cases need a trivial
function that does no more than the language does by default.

> If we've not another variable associated with the employees, like hours
> worked, we can get the standard deviation of that just by changing the
> lambda.

I think views can handle this just fine without complicating every
arithmetic operation. But this is a classic example of why you should
be posting where experts can reply -- I may be wrong.

> reduce is better than accumulate because accumulate requires left-to
> right evaluation of the operands. That's not necessary for a standard
> deviation, unless annoyingly, we need every bit of precision (floating
> point arithmetic isn't exactly associative, though it's near enough
> for almost all purposes).

Sure. You can just plug in reduce if you don't mid the risk of losing
control over the order:

double stddev(const auto &first, const auto &last)
{
double sum = std::reduce(first, last);
double sum_sq = std::reduce(
first, last, [](double sqs, double x){ return sqs + x*x; });
double N = std::distance(first, last);
return sqrt((sum_sq - sum*sum/N)/(N-1));
}

> You've used a slightly different formula for the standard deviation., which
> is more efficient and creates tighter code.

It comes with a risk, though, because the sum of squares grows much
faster than the sum of variances.

--
Ben.

Re: C vis C++ standard deviation function.

<e994c5e5-e9be-4ea0-a1c6-771ba6a191c1n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20834&group=comp.lang.c#20834

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a37:ac16:0:b0:60a:dac5:1656 with SMTP id e22-20020a37ac16000000b0060adac51656mr4497617qkm.680.1646582471308;
Sun, 06 Mar 2022 08:01:11 -0800 (PST)
X-Received: by 2002:a37:6c45:0:b0:478:a755:8845 with SMTP id
h66-20020a376c45000000b00478a7558845mr4522062qkc.362.1646582471031; Sun, 06
Mar 2022 08:01:11 -0800 (PST)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Sun, 6 Mar 2022 08:01:10 -0800 (PST)
In-Reply-To: <t02lei$jcq$1@dont-email.me>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23a8:400a:5601:795d:930b:4c0d:ec30;
posting-account=Dz2zqgkAAADlK5MFu78bw3ab-BRFV4Qn
NNTP-Posting-Host: 2a00:23a8:400a:5601:795d:930b:4c0d:ec30
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk> <bt4VJ.43898$7F2.32592@fx12.iad>
<87h78b9jpk.fsf@bsb.me.uk> <t02lei$jcq$1@dont-email.me>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <e994c5e5-e9be-4ea0-a1c6-771ba6a191c1n@googlegroups.com>
Subject: Re: C vis C++ standard deviation function.
From: malcolm....@gmail.com (Malcolm McLean)
Injection-Date: Sun, 06 Mar 2022 16:01:11 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 53
 by: Malcolm McLean - Sun, 6 Mar 2022 16:01 UTC

On Sunday, 6 March 2022 at 15:54:29 UTC, David Brown wrote:
> On 06/03/2022 16:36, Ben Bacarisse wrote:
> > sc...@slp53.sl.home (Scott Lurndal) writes:
> >
> >> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
> >>> Bart <b...@freeuk.com> writes:
> >>>
> >>>> That this is supposed to be generic is no excuse. Generic code should
> >>>> not need to look much different from non-generic code. With dynamic
> >>>> typing, it would be exactly the same source code**.
> >>>>
> >>>> According to the examples posted by David Brown, a generic version of
> >>>> your the C function, written in C++, ought to look like this:
> >>>>
> >>>> double stddev(auto *x, int N) {...}
> >>>
> >>> double stddev(const auto *x, int N)
> >>> {
> >>> double sum = 0, sum_sq = 0;
> >>> for (int i = 0; i < N; i++) {
> >>> sum += x[i];
> >>> sum_sq += x[i]*x[i];
> >>> }
> >>> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >>> }
> >>>
> >>> But then you then probably loose the automatic parallelisation that the
> >>> standard library might give you.
> >>
> >> Unless you're using one of the ubiquitous automatically vectorizing
> >> compilers.
> >
> > Do they work well with type-generic code, given that they won't always
> > know how + and * are defined?
> >
> They know how + and * are defined when compiling the code - it's
> compile-time polymorphism. Compilers can do exactly as much with such
> templated (or implicitly templated with "auto") code as they can with
> explicit types.
>
> But I think there's a bit of mixup here between "parallelisation" and
> "vectorisation" - they don't mean the same thing. Compilers can do
> automatic vectorisation on code like this, but automatic parallelisation
> is rarer. In theory, the C++ algorithm library functions support
> parallel execution strategy - in practice they usually don't (i.e., you
> can ask for parallel strategies, but you still get sequential ones).
>
The idea is to future-proof the code. Currently most readily-available
platforms can't do the fine-grained parallelisation you'd need to make
a parallel sddev worthwhile. But that might change.

However you could argue that a simple C for loop might be easier for
a future compiler to paralleise, and thus more future-proof than the C++
transform_reduce.

Re: C vis C++ standard deviation function.

<875yor9fp1.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20835&group=comp.lang.c#20835

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 17:03:06 +0000
Organization: A noiseless patient Spider
Lines: 68
Message-ID: <875yor9fp1.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<bt4VJ.43898$7F2.32592@fx12.iad> <87h78b9jpk.fsf@bsb.me.uk>
<t02lei$jcq$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="23025"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/m2K9Vy9iyDDoKKTfP/gUsVYhY/omQoPs="
Cancel-Lock: sha1:VTl0Wi82UtDObiHTFjiA0swnRWE=
sha1:0eTSM+KADw2XoG/ufqmi26/WYck=
X-BSB-Auth: 1.4eefb7ee77d315c36ca6.20220306170306GMT.875yor9fp1.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 17:03 UTC

David Brown <david.brown@hesbynett.no> writes:

> On 06/03/2022 16:36, Ben Bacarisse wrote:
>> scott@slp53.sl.home (Scott Lurndal) writes:
>>
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>> Bart <bc@freeuk.com> writes:
>>>>
>>>>> That this is supposed to be generic is no excuse. Generic code should
>>>>> not need to look much different from non-generic code. With dynamic
>>>>> typing, it would be exactly the same source code**.
>>>>>
>>>>> According to the examples posted by David Brown, a generic version of
>>>>> your the C function, written in C++, ought to look like this:
>>>>>
>>>>> double stddev(auto *x, int N) {...}
>>>>
>>>> double stddev(const auto *x, int N)
>>>> {
>>>> double sum = 0, sum_sq = 0;
>>>> for (int i = 0; i < N; i++) {
>>>> sum += x[i];
>>>> sum_sq += x[i]*x[i];
>>>> }
>>>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>>>> }
>>>>
>>>> But then you then probably loose the automatic parallelisation that the
>>>> standard library might give you.
>>>
>>> Unless you're using one of the ubiquitous automatically vectorizing
>>> compilers.
>>
>> Do they work well with type-generic code, given that they won't always
>> know how + and * are defined?
>
> They know how + and * are defined when compiling the code - it's
> compile-time polymorphism. Compilers can do exactly as much with such
> templated (or implicitly templated with "auto") code as they can with
> explicit types.

But do they? If you include link-time with compile-time, sure the
compiler knows what * is, but it's usually too late to change what the
loop compiled to. Does the code generator write two forms and the
linker picks one or the other when certain conditions are met?

Or maybe I've missed your point altogether.

> But I think there's a bit of mixup here between "parallelisation" and
> "vectorisation" - they don't mean the same thing. Compilers can do
> automatic vectorisation on code like this, but automatic parallelisation
> is rarer.

I would say that vectorisation is a form of parallelisation -- the
latter being the generic term for whole range of specialist
optimisations. I may well have used one or other of them incorrectly,
but I know they are different!

> In theory, the C++ algorithm library functions support
> parallel execution strategy - in practice they usually don't (i.e., you
> can ask for parallel strategies, but you still get sequential ones).

That's a good point. Explicit loops (that Malcolm was, I think, trying
to avoid) may well be better targets for optimisation than the library
functions he was leaning towards.

--
Ben.

Re: C vis C++ standard deviation function.

<t02t4r$kj4$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20836&group=comp.lang.c#20836

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 19:05:16 +0100
Organization: A noiseless patient Spider
Lines: 26
Message-ID: <t02t4r$kj4$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 18:05:15 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="a844639c26a5899e804f081be1998dde";
logging-data="21092"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1950DgJ0goH/W4QiO/UcZW/cbbW2e0LxSA="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:oafevRCkFxuOxs18GrDgPVOIQGE=
In-Reply-To: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
Content-Language: de-DE
 by: Bonita Montero - Sun, 6 Mar 2022 18:05 UTC

I use this code:

template<typename Iterator>
requires std::is_convertible_v<typename
std::iterator_traits<Iterator>::value_type, double>
double stddev( Iterator begin, Iterator end )
{ using namespace std;
using T = typename iterator_traits<Iterator>::value_type;
ptrdiff_t n;
double mean = 0.0;
if constexpr( random_access_iterator<Iterator> )
n = std::distance( begin, end ),
for_each( begin, end, [&]( T &value ) { mean += (double)value; } );
else
n = 0,
for_each( begin, end, [&]( T &value ) { ++n; mean += (double)value; } );
mean /= n;
double sqSum = 0.0;
for_each( begin, end, [&]( T &value ) { double v = value; sqSum += (v -
mean) * (v - mean); } );
return sqrt( sqSum / n );
}

I don't use reduce because the type inside the array might
be asymmetrical to double.

Re: C vis C++ standard deviation function.

<t02t8a$kj4$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20837&group=comp.lang.c#20837

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 19:07:07 +0100
Organization: A noiseless patient Spider
Lines: 12
Message-ID: <t02t8a$kj4$2@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t02a7n$19k6p$1@news.xmission.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 18:07:06 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="a844639c26a5899e804f081be1998dde";
logging-data="21092"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18yQKbMhzIrNrMHyOfNXVUup88yGUuVdvA="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:/hpJ+S6zWMp5wkjb3Nk8FQ+3oHQ=
In-Reply-To: <t02a7n$19k6p$1@news.xmission.com>
Content-Language: de-DE
 by: Bonita Montero - Sun, 6 Mar 2022 18:07 UTC

Am 06.03.2022 um 13:42 schrieb Kenny McCormack:
> In article <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>,
> Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
>> Following the recent discussion of "reduce", I decided to try my hand at generic
>> programming in C++.
>
> Off topic.
>
> Try comp.lang.c++

Comparison of C against other languages is on-topic here.

Re: C vis C++ standard deviation function.

<t02u1h$s1g$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20838&group=comp.lang.c#20838

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 19:20:33 +0100
Organization: A noiseless patient Spider
Lines: 25
Message-ID: <t02u1h$s1g$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t02t4r$kj4$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 18:20:33 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="a844639c26a5899e804f081be1998dde";
logging-data="28720"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18B103JxOewi+W6XFl1bXSGVpmqFdryDVE="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:uZPZqlcLePJzew8Akj5d0HQMWH0=
In-Reply-To: <t02t4r$kj4$1@dont-email.me>
Content-Language: de-DE
 by: Bonita Montero - Sun, 6 Mar 2022 18:20 UTC

This might be better:

template<typename Iterator>
requires std::is_convertible_v<typename
std::iterator_traits<Iterator>::value_type, double> &&
std::input_iterator<Iterator>
double stddev( Iterator begin, Iterator end )
{ using namespace std;
using T = typename iterator_traits<Iterator>::value_type;
ptrdiff_t n;
double mean = 0.0;
if constexpr( random_access_iterator<Iterator> )
n = std::distance( begin, end ),
for_each( begin, end, [&]( T &value ) { mean += (double)value; } );
else
n = 0,
for_each( begin, end, [&]( T &value ) { ++n; mean += (double)value; } );
mean /= n;
double sqSum = 0.0;
for_each( begin, end, [&]( T &value ) { double diff = (double)value -
mean; sqSum += diff * diff; } );
return sqrt( sqSum / n );
}

Re: C vis C++ standard deviation function.

<ff4b63dd-d429-495b-a353-454fcde29a76n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20839&group=comp.lang.c#20839

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:622a:309:b0:2dd:53e9:ae80 with SMTP id q9-20020a05622a030900b002dd53e9ae80mr6830607qtw.557.1646592509384;
Sun, 06 Mar 2022 10:48:29 -0800 (PST)
X-Received: by 2002:ac8:7fca:0:b0:2de:8f3d:89be with SMTP id
b10-20020ac87fca000000b002de8f3d89bemr6963925qtk.34.1646592509245; Sun, 06
Mar 2022 10:48:29 -0800 (PST)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Sun, 6 Mar 2022 10:48:29 -0800 (PST)
In-Reply-To: <87bkyj9ior.fsf@bsb.me.uk>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23a8:400a:5601:d55b:953b:1c0e:b3ac;
posting-account=Dz2zqgkAAADlK5MFu78bw3ab-BRFV4Qn
NNTP-Posting-Host: 2a00:23a8:400a:5601:d55b:953b:1c0e:b3ac
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk> <8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
<87bkyj9ior.fsf@bsb.me.uk>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <ff4b63dd-d429-495b-a353-454fcde29a76n@googlegroups.com>
Subject: Re: C vis C++ standard deviation function.
From: malcolm....@gmail.com (Malcolm McLean)
Injection-Date: Sun, 06 Mar 2022 18:48:29 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 83
 by: Malcolm McLean - Sun, 6 Mar 2022 18:48 UTC

On Sunday, 6 March 2022 at 15:59:14 UTC, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.ar...@gmail.com> writes:
>
> > On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
> >> Bart <b...@freeuk.com> writes:
> >>
> >> > That this is supposed to be generic is no excuse. Generic code should
> >> > not need to look much different from non-generic code. With dynamic
> >> > typing, it would be exactly the same source code**.
> >> >
> >> > According to the examples posted by David Brown, a generic version of
> >> > your the C function, written in C++, ought to look like this:
> >> >
> >> > double stddev(auto *x, int N) {...}
> >> double stddev(const auto *x, int N)
> >> {
> >> double sum = 0, sum_sq = 0;
> >> for (int i = 0; i < N; i++) {
> >> sum += x[i];
> >> sum_sq += x[i]*x[i];
> >> }
> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >> }
> >> But then you then probably loose the automatic parallelisation that the
> >> standard library might give you.
> >> > x is a pointer to int, long long int, float or double. But I couldn't
> >> > get this to compile. If code needs to look like your C++, then it is a
> >> > failure IMO.
> >> The trouble is that the C++ code shown was intended to do more than the
> >> C, and not just in terms of handling generic types. Also, you can't
> >> judge C++ by a single example from one person. For example, I don't
> >> think
> >>
> >> double stddev(const auto &first, const auto &last)
> >> {
> >> double sum = std::accumulate(first, last);
> >> double sum_sq = std::accumulate(
> >> first, last, [](double sqs, double x){ return sqs + x*x; });
> >> double N = std::distance(first, last);
> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >> }
> >>
> >> is particularly unclear.
> >>
> > Yes, but that's not generic. If first and last iterator over employees, the "+'
> > operator has to be defined to add two employees together. That's unlikely
> > to make any sort of sense.
> I think that's a good thing. Standard deviation is an arithmetic
> property.
> > In fact we'll want that standard deviation of the salaries. So we can pass
> > in a trivial little lambda [](Employee &employee){return
> > employee.salary;}
> I think you should use the ranges::view types to pass iterators to that
> data. Otherwise, every arithmetic operation has to acquire a little
> function to do the conversion, and the most common cases need a trivial
> function that does no more than the language does by default.
> > If we've not another variable associated with the employees, like hours
> > worked, we can get the standard deviation of that just by changing the
> > lambda.
> I think views can handle this just fine without complicating every
> arithmetic operation. But this is a classic example of why you should
> be posting where experts can reply -- I may be wrong.
> > reduce is better than accumulate because accumulate requires left-to
> > right evaluation of the operands. That's not necessary for a standard
> > deviation, unless annoyingly, we need every bit of precision (floating
> > point arithmetic isn't exactly associative, though it's near enough
> > for almost all purposes).
> Sure. You can just plug in reduce if you don't mid the risk of losing
> control over the order:
> double stddev(const auto &first, const auto &last)
> {
> double sum = std::reduce(first, last);
> double sum_sq = std::reduce(
> first, last, [](double sqs, double x){ return sqs + x*x; });
> double N = std::distance(first, last);
> return sqrt((sum_sq - sum*sum/N)/(N-1));
> }
>
This won't work. You want the sum of squares. But if you evaluate left to right,
the first element is not squared. That's easily fixed by passing in an init.
However if you use "reduce" instead of "accumulate" then the problem is
much more serious. Rndom pairs might not have the first operand squared.

You must use reduce_transform.

Re: C vis C++ standard deviation function.

<t03216$snr$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20840&group=comp.lang.c#20840

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 20:28:37 +0100
Organization: A noiseless patient Spider
Lines: 97
Message-ID: <t03216$snr$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<bt4VJ.43898$7F2.32592@fx12.iad> <87h78b9jpk.fsf@bsb.me.uk>
<t02lei$jcq$1@dont-email.me> <875yor9fp1.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 6 Mar 2022 19:28:38 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="23fbedda00f6040df04193486ad49b41";
logging-data="29435"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19AdppWKReDHosJb/uLq/5sUN+rDk6pPlU="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:kM7U8BzhY1ncaZS4sOz33Hsak8M=
In-Reply-To: <875yor9fp1.fsf@bsb.me.uk>
Content-Language: en-GB
 by: David Brown - Sun, 6 Mar 2022 19:28 UTC

On 06/03/2022 18:03, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 06/03/2022 16:36, Ben Bacarisse wrote:
>>> scott@slp53.sl.home (Scott Lurndal) writes:
>>>
>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>> Bart <bc@freeuk.com> writes:
>>>>>
>>>>>> That this is supposed to be generic is no excuse. Generic code should
>>>>>> not need to look much different from non-generic code. With dynamic
>>>>>> typing, it would be exactly the same source code**.
>>>>>>
>>>>>> According to the examples posted by David Brown, a generic version of
>>>>>> your the C function, written in C++, ought to look like this:
>>>>>>
>>>>>> double stddev(auto *x, int N) {...}
>>>>>
>>>>> double stddev(const auto *x, int N)
>>>>> {
>>>>> double sum = 0, sum_sq = 0;
>>>>> for (int i = 0; i < N; i++) {
>>>>> sum += x[i];
>>>>> sum_sq += x[i]*x[i];
>>>>> }
>>>>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>>>>> }
>>>>>
>>>>> But then you then probably loose the automatic parallelisation that the
>>>>> standard library might give you.
>>>>
>>>> Unless you're using one of the ubiquitous automatically vectorizing
>>>> compilers.
>>>
>>> Do they work well with type-generic code, given that they won't always
>>> know how + and * are defined?
>>
>> They know how + and * are defined when compiling the code - it's
>> compile-time polymorphism. Compilers can do exactly as much with such
>> templated (or implicitly templated with "auto") code as they can with
>> explicit types.
>
> But do they? If you include link-time with compile-time, sure the
> compiler knows what * is, but it's usually too late to change what the
> loop compiled to. Does the code generator write two forms and the
> linker picks one or the other when certain conditions are met?
>
> Or maybe I've missed your point altogether.
>

When you use "auto" in a function declaration, it is just like a
template (indeed it /is/ a template, written with a shorter syntax).
Code is not generated for it at all until the compiler knows the type
being used, and the details of it. Of course, if the type is a class
with operators + and *, which are declared at the point of template
instantiation but defined externally, then the compiler won't be able to
do anything special with them. But if the definitions of the operators
are known when the template is instantiated (and that's likely to be the
case for arithmetic types), then the compiler has all the information it
needs at compile time.

>> But I think there's a bit of mixup here between "parallelisation" and
>> "vectorisation" - they don't mean the same thing. Compilers can do
>> automatic vectorisation on code like this, but automatic parallelisation
>> is rarer.
>
> I would say that vectorisation is a form of parallelisation -- the
> latter being the generic term for whole range of specialist
> optimisations. I may well have used one or other of them incorrectly,
> but I know they are different!
>

I would use "vectorisation" to refer to SIMD operations in the same
thread, and "parallelisation" to refer to splitting the calculation into
parts and running them on separate threads on separate cores. There is
an overlap, but I think the distinction is clear.

>> In theory, the C++ algorithm library functions support
>> parallel execution strategy - in practice they usually don't (i.e., you
>> can ask for parallel strategies, but you still get sequential ones).
>
> That's a good point. Explicit loops (that Malcolm was, I think, trying
> to avoid) may well be better targets for optimisation than the library
> functions he was leaning towards.
>

Explicit loops are often easier for optimisation when the loop count is
small - function calls can be better when the loop count is high. (You
get the same thing for memcpy() - a memcpy with a small known count can
be turned into a few move instructions, but a library function can do
things like alignment of cache lines to optimise large movements better.)

In particular, an explicit loop /might/ be vectorised, depending of
flags and the details of the code. A function call might lead to code
that has different vectorised versions for different processors - larger
overhead, but fast operation regardless of flags.

Re: C vis C++ standard deviation function.

<87sfru98c3.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20841&group=comp.lang.c#20841

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 19:42:04 +0000
Organization: A noiseless patient Spider
Lines: 119
Message-ID: <87sfru98c3.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
<87bkyj9ior.fsf@bsb.me.uk>
<ff4b63dd-d429-495b-a353-454fcde29a76n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="4009"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19thGmxfH9TQS5n+o46G4wF+KcIebVY/rA="
Cancel-Lock: sha1:6KGcEAjwVI0NNaPc9yFX2uWVuoQ=
sha1:08HXvQG9XZBoGXaieGoaZsKxXAQ=
X-BSB-Auth: 1.3b6d7e7f168487f9875a.20220306194204GMT.87sfru98c3.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 19:42 UTC

Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> On Sunday, 6 March 2022 at 15:59:14 UTC, Ben Bacarisse wrote:
>> Malcolm McLean <malcolm.ar...@gmail.com> writes:
>>
>> > On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
>> >> Bart <b...@freeuk.com> writes:
>> >>
>> >> > That this is supposed to be generic is no excuse. Generic code should
>> >> > not need to look much different from non-generic code. With dynamic
>> >> > typing, it would be exactly the same source code**.
>> >> >
>> >> > According to the examples posted by David Brown, a generic version of
>> >> > your the C function, written in C++, ought to look like this:
>> >> >
>> >> > double stddev(auto *x, int N) {...}
>> >> double stddev(const auto *x, int N)
>> >> {
>> >> double sum = 0, sum_sq = 0;
>> >> for (int i = 0; i < N; i++) {
>> >> sum += x[i];
>> >> sum_sq += x[i]*x[i];
>> >> }
>> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> >> }
>> >> But then you then probably loose the automatic parallelisation that the
>> >> standard library might give you.
>> >> > x is a pointer to int, long long int, float or double. But I couldn't
>> >> > get this to compile. If code needs to look like your C++, then it is a
>> >> > failure IMO.
>> >> The trouble is that the C++ code shown was intended to do more than the
>> >> C, and not just in terms of handling generic types. Also, you can't
>> >> judge C++ by a single example from one person. For example, I don't
>> >> think
>> >>
>> >> double stddev(const auto &first, const auto &last)
>> >> {
>> >> double sum = std::accumulate(first, last);
>> >> double sum_sq = std::accumulate(
>> >> first, last, [](double sqs, double x){ return sqs + x*x; });
>> >> double N = std::distance(first, last);
>> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> >> }
>> >>
>> >> is particularly unclear.
>> >>
>> > Yes, but that's not generic. If first and last iterator over employees, the "+'
>> > operator has to be defined to add two employees together. That's unlikely
>> > to make any sort of sense.
>> I think that's a good thing. Standard deviation is an arithmetic
>> property.
>> > In fact we'll want that standard deviation of the salaries. So we can pass
>> > in a trivial little lambda [](Employee &employee){return
>> > employee.salary;}
>> I think you should use the ranges::view types to pass iterators to that
>> data. Otherwise, every arithmetic operation has to acquire a little
>> function to do the conversion, and the most common cases need a trivial
>> function that does no more than the language does by default.
>> > If we've not another variable associated with the employees, like hours
>> > worked, we can get the standard deviation of that just by changing the
>> > lambda.
>> I think views can handle this just fine without complicating every
>> arithmetic operation. But this is a classic example of why you should
>> be posting where experts can reply -- I may be wrong.
>> > reduce is better than accumulate because accumulate requires left-to
>> > right evaluation of the operands. That's not necessary for a standard
>> > deviation, unless annoyingly, we need every bit of precision (floating
>> > point arithmetic isn't exactly associative, though it's near enough
>> > for almost all purposes).
>> Sure. You can just plug in reduce if you don't mid the risk of losing
>> control over the order:
>> double stddev(const auto &first, const auto &last)
>> {
>> double sum = std::reduce(first, last);
>> double sum_sq = std::reduce(
>> first, last, [](double sqs, double x){ return sqs + x*x; });
>> double N = std::distance(first, last);
>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> }
>>
> This won't work. You want the sum of squares. But if you evaluate left
> to right, the first element is not squared. That's easily fixed by
> passing in an init.

Thanks. I removed the 0 init from the accumulate version without
thinking. But...

> However if you use "reduce" instead of "accumulate" then the problem is
> much more serious. Rndom pairs might not have the first operand
> squared.

Ah yes. The binary operator must be associative and commutative.

> You must use reduce_transform.

(transform_reduce)

So I read the documentation (as I clearly should have done before!) and,
unless I've messed up again, an even neater solution presents itself:

double stddev(const auto &first, const auto &last)
{
double sum = std::reduce(first, last);
double sum_sq = std::transform_reduce(first, last, first);
double N = std::distance(first, last);
return sqrt((sum_sq - sum*sum/N)/(N-1));
}

because std::transform_reduce(first, last, first) is essentially a
parallel inner product of the sequence with itself. It's possible,
given the prevalence of inner products, that this might be special-cased
and particularly fast on some hardware.

BTW, can you do anything about your Usenet client messing up the
formatting? It's particularly unhelpful with code, but "paragraph
breaks" get lost too.

--
Ben.

Re: C vis C++ standard deviation function.

<8b0fda1c-d550-486e-81d3-b52747a60943n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20842&group=comp.lang.c#20842

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:620a:4510:b0:67b:3f0:897e with SMTP id t16-20020a05620a451000b0067b03f0897emr3824536qkp.278.1646596823568;
Sun, 06 Mar 2022 12:00:23 -0800 (PST)
X-Received: by 2002:a37:2f04:0:b0:663:397d:7051 with SMTP id
v4-20020a372f04000000b00663397d7051mr5070538qkh.333.1646596823321; Sun, 06
Mar 2022 12:00:23 -0800 (PST)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!news.misty.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Sun, 6 Mar 2022 12:00:23 -0800 (PST)
In-Reply-To: <87sfru98c3.fsf@bsb.me.uk>
Injection-Info: google-groups.googlegroups.com; posting-host=2a00:23a8:400a:5601:d55b:953b:1c0e:b3ac;
posting-account=Dz2zqgkAAADlK5MFu78bw3ab-BRFV4Qn
NNTP-Posting-Host: 2a00:23a8:400a:5601:d55b:953b:1c0e:b3ac
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk> <8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
<87bkyj9ior.fsf@bsb.me.uk> <ff4b63dd-d429-495b-a353-454fcde29a76n@googlegroups.com>
<87sfru98c3.fsf@bsb.me.uk>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <8b0fda1c-d550-486e-81d3-b52747a60943n@googlegroups.com>
Subject: Re: C vis C++ standard deviation function.
From: malcolm....@gmail.com (Malcolm McLean)
Injection-Date: Sun, 06 Mar 2022 20:00:23 +0000
Content-Type: text/plain; charset="UTF-8"
Lines: 121
 by: Malcolm McLean - Sun, 6 Mar 2022 20:00 UTC

On Sunday, 6 March 2022 at 19:42:41 UTC, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.ar...@gmail.com> writes:
>
> > On Sunday, 6 March 2022 at 15:59:14 UTC, Ben Bacarisse wrote:
> >> Malcolm McLean <malcolm.ar...@gmail.com> writes:
> >>
> >> > On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
> >> >> Bart <b...@freeuk.com> writes:
> >> >>
> >> >> > That this is supposed to be generic is no excuse. Generic code should
> >> >> > not need to look much different from non-generic code. With dynamic
> >> >> > typing, it would be exactly the same source code**.
> >> >> >
> >> >> > According to the examples posted by David Brown, a generic version of
> >> >> > your the C function, written in C++, ought to look like this:
> >> >> >
> >> >> > double stddev(auto *x, int N) {...}
> >> >> double stddev(const auto *x, int N)
> >> >> {
> >> >> double sum = 0, sum_sq = 0;
> >> >> for (int i = 0; i < N; i++) {
> >> >> sum += x[i];
> >> >> sum_sq += x[i]*x[i];
> >> >> }
> >> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >> >> }
> >> >> But then you then probably loose the automatic parallelisation that the
> >> >> standard library might give you.
> >> >> > x is a pointer to int, long long int, float or double. But I couldn't
> >> >> > get this to compile. If code needs to look like your C++, then it is a
> >> >> > failure IMO.
> >> >> The trouble is that the C++ code shown was intended to do more than the
> >> >> C, and not just in terms of handling generic types. Also, you can't
> >> >> judge C++ by a single example from one person. For example, I don't
> >> >> think
> >> >>
> >> >> double stddev(const auto &first, const auto &last)
> >> >> {
> >> >> double sum = std::accumulate(first, last);
> >> >> double sum_sq = std::accumulate(
> >> >> first, last, [](double sqs, double x){ return sqs + x*x; });
> >> >> double N = std::distance(first, last);
> >> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >> >> }
> >> >>
> >> >> is particularly unclear.
> >> >>
> >> > Yes, but that's not generic. If first and last iterator over employees, the "+'
> >> > operator has to be defined to add two employees together. That's unlikely
> >> > to make any sort of sense.
> >> I think that's a good thing. Standard deviation is an arithmetic
> >> property.
> >> > In fact we'll want that standard deviation of the salaries. So we can pass
> >> > in a trivial little lambda [](Employee &employee){return
> >> > employee.salary;}
> >> I think you should use the ranges::view types to pass iterators to that
> >> data. Otherwise, every arithmetic operation has to acquire a little
> >> function to do the conversion, and the most common cases need a trivial
> >> function that does no more than the language does by default.
> >> > If we've not another variable associated with the employees, like hours
> >> > worked, we can get the standard deviation of that just by changing the
> >> > lambda.
> >> I think views can handle this just fine without complicating every
> >> arithmetic operation. But this is a classic example of why you should
> >> be posting where experts can reply -- I may be wrong.
> >> > reduce is better than accumulate because accumulate requires left-to
> >> > right evaluation of the operands. That's not necessary for a standard
> >> > deviation, unless annoyingly, we need every bit of precision (floating
> >> > point arithmetic isn't exactly associative, though it's near enough
> >> > for almost all purposes).
> >> Sure. You can just plug in reduce if you don't mid the risk of losing
> >> control over the order:
> >> double stddev(const auto &first, const auto &last)
> >> {
> >> double sum = std::reduce(first, last);
> >> double sum_sq = std::reduce(
> >> first, last, [](double sqs, double x){ return sqs + x*x; });
> >> double N = std::distance(first, last);
> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
> >> }
> >>
> > This won't work. You want the sum of squares. But if you evaluate left
> > to right, the first element is not squared. That's easily fixed by
> > passing in an init.
> Thanks. I removed the 0 init from the accumulate version without
> thinking. But...
> > However if you use "reduce" instead of "accumulate" then the problem is
> > much more serious. Rndom pairs might not have the first operand
> > squared.
> Ah yes. The binary operator must be associative and commutative.
>
> > You must use reduce_transform.
>
> (transform_reduce)
>
> So I read the documentation (as I clearly should have done before!) and,
> unless I've messed up again, an even neater solution presents itself:
> double stddev(const auto &first, const auto &last)
> {
> double sum = std::reduce(first, last);
> double sum_sq = std::transform_reduce(first, last, first);
> double N = std::distance(first, last);
> return sqrt((sum_sq - sum*sum/N)/(N-1));
> }
That's a huge readability improvement.
>
> because std::transform_reduce(first, last, first) is essentially a
> parallel inner product of the sequence with itself. It's possible,
> given the prevalence of inner products, that this might be special-cased
> and particularly fast on some hardware.
>
I'm in two minds about this. Whilst it's good to know that inner products
are particularly fast, ina sense special-casing is a cheat. The idea is that
the transorm reduce paradigm can be widely used to construct a wide
varienty of functions. I chose stddev because it lends itself to this
approach.
>
> BTW, can you do anything about your Usenet client messing up the
> formatting? It's particularly unhelpful with code, but "paragraph
> breaks" get lost too.
>
Unfortunately the machine I use is a work machine, and not my property.

Re: C vis C++ standard deviation function.

<t0340u$dqa$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20843&group=comp.lang.c#20843

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: MR...@invalid.invalid (Manu Raju)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 19:30:00 +0000
Organization: Aioe.org NNTP Server
Lines: 63
Message-ID: <t0340u$dqa$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 6 Mar 2022 20:02:38 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="2f3d1f57643a6a879b105b3308138537";
logging-data="14154"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19moBsBJKrAwYeCuQkmq2Q1PW5R/7zuuAY="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:CsFyg/VOB13K38G7be7APdBpsfE=
In-Reply-To: <t028t1$53p$1@dont-email.me>
Content-Language: en-US
 by: Manu Raju - Sun, 6 Mar 2022 19:30 UTC

On 06/03/2022 12:19, Bart wrote:
>
>
> I don't need to read any further. Just look at the difference between
> those two examples. I can easily follow the algorithm expressed as C,
> but I can'make out anything in the C++. Is there even an algorithm in
> that lot? All I can see is the last line that matches C's.

A simple C program without any bells & whistles!!!!

<====================================================================>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

float calculateSD(float data[]);
int main()
{ int i;
srand(time(NULL));
float data[10];

for (i = 0; i < 10; ++i)
{
data[i] = rand() % 99;
}
printf("The 10 numbers are: \n");
for (int i = 0; i < 10; i++)
{
printf("%4.0f", data[i]);
}
printf("\nStandard Deviation = %.6f", calculateSD(data));
return 0;
}

float calculateSD(float data[])
{ float sum = 0.0, mean, SD = 0.0;
int i;
for (i = 0; i < 10; ++i)
{
sum += data[i];
}
mean = sum / 10;
for (i = 0; i < 10; ++i)
{
SD += pow(data[i] - mean, 2);
}
return sqrt(SD / 10);
}

<====================================================================>

Re: C vis C++ standard deviation function.

<t034a2$alm$7@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20844&group=comp.lang.c#20844

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 21:07:31 +0100
Organization: A noiseless patient Spider
Lines: 83
Message-ID: <t034a2$alm$7@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <t0340u$dqa$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 6 Mar 2022 20:07:31 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="a844639c26a5899e804f081be1998dde";
logging-data="10934"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+DdlHNeAiLNWcJjzBBvBm3CodGseFcBsk="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:lVsfMwMWgaGDipDSiQ3Q9bnIcDg=
In-Reply-To: <t0340u$dqa$1@dont-email.me>
Content-Language: de-DE
 by: Bonita Montero - Sun, 6 Mar 2022 20:07 UTC

Am 06.03.2022 um 20:30 schrieb Manu Raju:
> On 06/03/2022 12:19, Bart wrote:
>>
>>
>> I don't need to read any further. Just look at the difference between
>> those two examples. I can easily follow the algorithm expressed as C,
>> but I can'make out anything in the C++. Is there even an algorithm in
>> that lot? All I can see is the last line that matches C's.
>
> A simple C program without any bells & whistles!!!!
>
> <====================================================================>
> #include <math.h>
> #include <stdio.h>
> #include <time.h>
> #include <stdlib.h>
>
> float calculateSD(float data[]);
> int main()
> {
>    int i;
>    srand(time(NULL));    float data[10];
>    for (i = 0; i < 10; ++i)
>    {
>        data[i] = rand() % 99;
>    }
>    printf("The 10 numbers are: \n");
>    for (int i = 0; i < 10; i++)
>    {
>        printf("%4.0f", data[i]);
>    }
>    printf("\nStandard Deviation = %.6f", calculateSD(data));
>    return 0;
> }
>
> float calculateSD(float data[])
> {
>    float sum = 0.0, mean, SD = 0.0;
>    int i;
>    for (i = 0; i < 10; ++i)
>    {
>        sum += data[i];
>    }
>    mean = sum / 10;
>    for (i = 0; i < 10; ++i)
>    {
>        SD += pow(data[i] - mean, 2);
>    }
>    return sqrt(SD / 10);
> }

Works only with float-arrays.

This works with any input-iterable data that is
convertible to double:

template<typename Iterator>
requires std::is_convertible_v<typename
std::iterator_traits<Iterator>::value_type, double> &&
std::input_iterator<Iterator>
double stddev( Iterator begin, Iterator end )
{ using namespace std;
using T = typename iterator_traits<Iterator>::value_type;
ptrdiff_t n;
double mean = 0.0;
if constexpr( random_access_iterator<Iterator> )
n = std::distance( begin, end ),
for_each( begin, end, [&]( T &value ) { mean += (double)value; } );
else
n = 0,
for_each( begin, end, [&]( T &value ) { ++n; mean +=
(double)value; } );
mean /= n;
double sqSum = 0.0;
for_each( begin, end, [&]( T &value ) { double diff = (double)value
- mean; sqSum += diff * diff; } );
return sqrt( sqSum / n );
}

Magnitudes more flexible.

Re: C vis C++ standard deviation function.

<t034gf$hmp$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20845&group=comp.lang.c#20845

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 21:10:55 +0100
Organization: A noiseless patient Spider
Lines: 13
Message-ID: <t034gf$hmp$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <t0340u$dqa$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 6 Mar 2022 20:10:55 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="a844639c26a5899e804f081be1998dde";
logging-data="18137"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19rWsSeJOPuna3O9Aj1M4U+BQvpvX2YDnU="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.2
Cancel-Lock: sha1:Ua/aPEitjY/v33SLHKBvvo9rHSc=
In-Reply-To: <t0340u$dqa$1@dont-email.me>
Content-Language: de-DE
 by: Bonita Montero - Sun, 6 Mar 2022 20:10 UTC

>        SD += pow(data[i] - mean, 2);

#include <cmath>

double f( double d )
{ return pow( d, 2 );
}

MSVC:

movsd xmm1, QWORD PTR __real@4000000000000000
jmp pow

Re: C vis C++ standard deviation function.

<87mti29702.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20846&group=comp.lang.c#20846

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 20:10:53 +0000
Organization: A noiseless patient Spider
Lines: 85
Message-ID: <87mti29702.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<bt4VJ.43898$7F2.32592@fx12.iad> <87h78b9jpk.fsf@bsb.me.uk>
<t02lei$jcq$1@dont-email.me> <875yor9fp1.fsf@bsb.me.uk>
<t03216$snr$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="18921"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19nAo+oLv/HWEuiSqfj6GW/FGYAZvfQxgc="
Cancel-Lock: sha1:KBS/JaA4XVHs7ey4+5N7JiOkkK8=
sha1:6LZZ+wVVatmdQYBmEscuwsmGJ1s=
X-BSB-Auth: 1.fd49f5bd79acf5ce159b.20220306201053GMT.87mti29702.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 20:10 UTC

David Brown <david.brown@hesbynett.no> writes:

> On 06/03/2022 18:03, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 06/03/2022 16:36, Ben Bacarisse wrote:
>>>> scott@slp53.sl.home (Scott Lurndal) writes:
>>>>
>>>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>>>> Bart <bc@freeuk.com> writes:
>>>>>>
>>>>>>> That this is supposed to be generic is no excuse. Generic code should
>>>>>>> not need to look much different from non-generic code. With dynamic
>>>>>>> typing, it would be exactly the same source code**.
>>>>>>>
>>>>>>> According to the examples posted by David Brown, a generic version of
>>>>>>> your the C function, written in C++, ought to look like this:
>>>>>>>
>>>>>>> double stddev(auto *x, int N) {...}
>>>>>>
>>>>>> double stddev(const auto *x, int N)
>>>>>> {
>>>>>> double sum = 0, sum_sq = 0;
>>>>>> for (int i = 0; i < N; i++) {
>>>>>> sum += x[i];
>>>>>> sum_sq += x[i]*x[i];
>>>>>> }
>>>>>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>>>>>> }
>>>>>>
>>>>>> But then you then probably loose the automatic parallelisation that the
>>>>>> standard library might give you.
>>>>>
>>>>> Unless you're using one of the ubiquitous automatically vectorizing
>>>>> compilers.
>>>>
>>>> Do they work well with type-generic code, given that they won't always
>>>> know how + and * are defined?
>>>
>>> They know how + and * are defined when compiling the code - it's
>>> compile-time polymorphism. Compilers can do exactly as much with such
>>> templated (or implicitly templated with "auto") code as they can with
>>> explicit types.
>>
>> But do they? If you include link-time with compile-time, sure the
>> compiler knows what * is, but it's usually too late to change what the
>> loop compiled to. Does the code generator write two forms and the
>> linker picks one or the other when certain conditions are met?
>>
>> Or maybe I've missed your point altogether.
>
> When you use "auto" in a function declaration, it is just like a
> template (indeed it /is/ a template, written with a shorter syntax).
> Code is not generated for it at all until the compiler knows the type
> being used, and the details of it. Of course, if the type is a class
> with operators + and *, which are declared at the point of template
> instantiation but defined externally, then the compiler won't be able to
> do anything special with them.

Your "of course" is exactly my point -- apparently what I was saying is
obvious! Your "[t]hey know how + and * are defined when compiling the
code" is either not always true, or, in the case of whole-program
optimisation, not current enough to be much use.

>>> But I think there's a bit of mixup here between "parallelisation" and
>>> "vectorisation" - they don't mean the same thing. Compilers can do
>>> automatic vectorisation on code like this, but automatic parallelisation
>>> is rarer.
>>
>> I would say that vectorisation is a form of parallelisation -- the
>> latter being the generic term for whole range of specialist
>> optimisations. I may well have used one or other of them incorrectly,
>> but I know they are different!
>
> I would use "vectorisation" to refer to SIMD operations in the same
> thread, and "parallelisation" to refer to splitting the calculation into
> parts and running them on separate threads on separate cores. There is
> an overlap, but I think the distinction is clear.

I would call that concurrency. It's another form of parallelism. My
usage was common (at least in the UK) some time ago, but maybe the kids
use the words differently nowadays and the meaning has drifted.

--
Ben.

Re: C vis C++ standard deviation function.

<87h78a96g9.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20847&group=comp.lang.c#20847

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 06 Mar 2022 20:22:46 +0000
Organization: A noiseless patient Spider
Lines: 137
Message-ID: <87h78a96g9.fsf@bsb.me.uk>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <87mti39l6r.fsf@bsb.me.uk>
<8ca832bf-0bc7-4d63-a937-28ad49a6403dn@googlegroups.com>
<87bkyj9ior.fsf@bsb.me.uk>
<ff4b63dd-d429-495b-a353-454fcde29a76n@googlegroups.com>
<87sfru98c3.fsf@bsb.me.uk>
<8b0fda1c-d550-486e-81d3-b52747a60943n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="30f43e6961ef395679471ce045850a06";
logging-data="18921"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+hwRpezMkNrYyz8sXHvp/6sTeu8O4lQos="
Cancel-Lock: sha1:zqe2Q4SlKapPm+oMVdHHK7R21a4=
sha1:S0w3uHcuxYPv4wZ1c4k+6jD8PgM=
X-BSB-Auth: 1.8fbf6e25975c2deb879c.20220306202246GMT.87h78a96g9.fsf@bsb.me.uk
 by: Ben Bacarisse - Sun, 6 Mar 2022 20:22 UTC

Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> On Sunday, 6 March 2022 at 19:42:41 UTC, Ben Bacarisse wrote:
>> Malcolm McLean <malcolm.ar...@gmail.com> writes:
>>
>> > On Sunday, 6 March 2022 at 15:59:14 UTC, Ben Bacarisse wrote:
>> >> Malcolm McLean <malcolm.ar...@gmail.com> writes:
>> >>
>> >> > On Sunday, 6 March 2022 at 15:05:04 UTC, Ben Bacarisse wrote:
>> >> >> Bart <b...@freeuk.com> writes:
>> >> >>
>> >> >> > That this is supposed to be generic is no excuse. Generic code should
>> >> >> > not need to look much different from non-generic code. With dynamic
>> >> >> > typing, it would be exactly the same source code**.
>> >> >> >
>> >> >> > According to the examples posted by David Brown, a generic version of
>> >> >> > your the C function, written in C++, ought to look like this:
>> >> >> >
>> >> >> > double stddev(auto *x, int N) {...}
>> >> >> double stddev(const auto *x, int N)
>> >> >> {
>> >> >> double sum = 0, sum_sq = 0;
>> >> >> for (int i = 0; i < N; i++) {
>> >> >> sum += x[i];
>> >> >> sum_sq += x[i]*x[i];
>> >> >> }
>> >> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> >> >> }
>> >> >> But then you then probably loose the automatic parallelisation that the
>> >> >> standard library might give you.
>> >> >> > x is a pointer to int, long long int, float or double. But I couldn't
>> >> >> > get this to compile. If code needs to look like your C++, then it is a
>> >> >> > failure IMO.
>> >> >> The trouble is that the C++ code shown was intended to do more than the
>> >> >> C, and not just in terms of handling generic types. Also, you can't
>> >> >> judge C++ by a single example from one person. For example, I don't
>> >> >> think
>> >> >>
>> >> >> double stddev(const auto &first, const auto &last)
>> >> >> {
>> >> >> double sum = std::accumulate(first, last);
>> >> >> double sum_sq = std::accumulate(
>> >> >> first, last, [](double sqs, double x){ return sqs + x*x; });
>> >> >> double N = std::distance(first, last);
>> >> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> >> >> }
>> >> >>
>> >> >> is particularly unclear.
>> >> >>
>> >> > Yes, but that's not generic. If first and last iterator over employees, the "+'
>> >> > operator has to be defined to add two employees together. That's unlikely
>> >> > to make any sort of sense.
>> >> I think that's a good thing. Standard deviation is an arithmetic
>> >> property.
>> >> > In fact we'll want that standard deviation of the salaries. So we can pass
>> >> > in a trivial little lambda [](Employee &employee){return
>> >> > employee.salary;}
>> >> I think you should use the ranges::view types to pass iterators to that
>> >> data. Otherwise, every arithmetic operation has to acquire a little
>> >> function to do the conversion, and the most common cases need a trivial
>> >> function that does no more than the language does by default.
>> >> > If we've not another variable associated with the employees, like hours
>> >> > worked, we can get the standard deviation of that just by changing the
>> >> > lambda.
>> >> I think views can handle this just fine without complicating every
>> >> arithmetic operation. But this is a classic example of why you should
>> >> be posting where experts can reply -- I may be wrong.
>> >> > reduce is better than accumulate because accumulate requires left-to
>> >> > right evaluation of the operands. That's not necessary for a standard
>> >> > deviation, unless annoyingly, we need every bit of precision (floating
>> >> > point arithmetic isn't exactly associative, though it's near enough
>> >> > for almost all purposes).
>> >> Sure. You can just plug in reduce if you don't mid the risk of losing
>> >> control over the order:
>> >> double stddev(const auto &first, const auto &last)
>> >> {
>> >> double sum = std::reduce(first, last);
>> >> double sum_sq = std::reduce(
>> >> first, last, [](double sqs, double x){ return sqs + x*x; });
>> >> double N = std::distance(first, last);
>> >> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> >> }
>> >>
>> > This won't work. You want the sum of squares. But if you evaluate left
>> > to right, the first element is not squared. That's easily fixed by
>> > passing in an init.
>> Thanks. I removed the 0 init from the accumulate version without
>> thinking. But...
>> > However if you use "reduce" instead of "accumulate" then the problem is
>> > much more serious. Rndom pairs might not have the first operand
>> > squared.
>> Ah yes. The binary operator must be associative and commutative.
>>
>> > You must use reduce_transform.
>>
>> (transform_reduce)
>>
>> So I read the documentation (as I clearly should have done before!) and,
>> unless I've messed up again, an even neater solution presents itself:
>> double stddev(const auto &first, const auto &last)
>> {
>> double sum = std::reduce(first, last);
>> double sum_sq = std::transform_reduce(first, last, first);
>> double N = std::distance(first, last);
>> return sqrt((sum_sq - sum*sum/N)/(N-1));
>> }
> That's a huge readability improvement.
>>
>> because std::transform_reduce(first, last, first) is essentially a
>> parallel inner product of the sequence with itself. It's possible,
>> given the prevalence of inner products, that this might be special-cased
>> and particularly fast on some hardware.
>>
> I'm in two minds about this. Whilst it's good to know that inner products
> are particularly fast, ina sense special-casing is a cheat. The idea is that
> the transorm reduce paradigm can be widely used to construct a wide
> varienty of functions. I chose stddev because it lends itself to this
> approach.

I would not write the code that way /because/ it might be special-cased.
I would write it that way because it's, to me, clearer than using the
long form with two functions.

Maybe your objection is that the fact that

std::transform_reduce(first, last, first)

means

std::transform_reduce(first, last, first, std::plus<>(), std::multiplies<>())

is rather less than obvious? Maybe. But once you know what the three
iterator version of reduce is doing, the defaults for the functions
become obvious.

--
Ben.

Re: C vis C++ standard deviation function.

<t038e5$hai$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=20848&group=comp.lang.c#20848

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: C vis C++ standard deviation function.
Date: Sun, 6 Mar 2022 21:17:56 +0000
Organization: A noiseless patient Spider
Lines: 63
Message-ID: <t038e5$hai$1@dont-email.me>
References: <b2017949-b97f-4d1e-87c5-5b6ed79ecd10n@googlegroups.com>
<t028t1$53p$1@dont-email.me> <t0340u$dqa$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 6 Mar 2022 21:17:57 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="8980970af4ff0eac474a7e725117ab98";
logging-data="17746"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+/iK5CcONfHe813VuM75RmNd/mKMTLbjw="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.6.1
Cancel-Lock: sha1:EAI+31UXhLOmNxg+KPa5RmUczH4=
In-Reply-To: <t0340u$dqa$1@dont-email.me>
 by: Bart - Sun, 6 Mar 2022 21:17 UTC

On 06/03/2022 19:30, Manu Raju wrote:
> On 06/03/2022 12:19, Bart wrote:
>>
>>
>> I don't need to read any further. Just look at the difference between
>> those two examples. I can easily follow the algorithm expressed as C,
>> but I can'make out anything in the C++. Is there even an algorithm in
>> that lot? All I can see is the last line that matches C's.
>
> A simple C program without any bells & whistles!!!!
>
> <====================================================================>
> #include <math.h>
> #include <stdio.h>
> #include <time.h>
> #include <stdlib.h>
>
> float calculateSD(float data[]);
> int main()
> {
>    int i;
>    srand(time(NULL));    float data[10];
>    for (i = 0; i < 10; ++i)
>    {
>        data[i] = rand() % 99;
>    }
>    printf("The 10 numbers are: \n");
>    for (int i = 0; i < 10; i++)
>    {
>        printf("%4.0f", data[i]);
>    }
>    printf("\nStandard Deviation = %.6f", calculateSD(data));
>    return 0;
> }
>
> float calculateSD(float data[])
> {
>    float sum = 0.0, mean, SD = 0.0;
>    int i;
>    for (i = 0; i < 10; ++i)
>    {
>        sum += data[i];
>    }
>    mean = sum / 10;
>    for (i = 0; i < 10; ++i)
>    {
>        SD += pow(data[i] - mean, 2);
>    }
>    return sqrt(SD / 10);
> }
>
> <====================================================================>

This is a little /too/ simple. The size of the data should be a
parameter to calculateSD(), otherwise it will only ever work for arrays
of length 10.

> return sqrt(SD / 10);

This should probably divide by 9 (or N-1 when done properly).

Also, it there is only one such routine, making it work on doubles is
better.

Pages:123
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor