Friday, April 14, 2017

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

ram@zedat.fu-berlin.de (Stefan Ram): Apr 14 08:38PM

Some other languages (like Pascal or COBOL) provide types
for ranges and enumerations, and I wonder to which extend
one can create such types in C++.
 
For example,
 
struct example { range<2'000'000'000,2'000'000'010> i; };
 
. The implementation should emit an error message (a
compile-time error message if possible) when one tries to
 
instance.i = 0;
 
, and, if possible,
 
sizeof instance.i
 
should be just 1, because one byte is enough to store
one out of 10 values.
ram@zedat.fu-berlin.de (Stefan Ram): Apr 14 10:09PM

Newsgroups: comp.lang.c,comp.lang.c++
 
> 55
> > (loop for i from 1 below 10 sum i)
> 45
 
C++ (after appropriate definitions):
 
int main()
{
auto sum { 0 };
 
for( auto const i : from{ 1, below( 3 )} )sum += i;
::std::cout << sum << '\n'; }
 
. And, BTW, the variable declaration and the whole
loop are being compiled here into just
 
movl $3, %edx
 
, that is, all the looping is done at compile time!
 
However, my current, simplistic, definitions are not
prepared for other increments than »+1«. (See full
C++ code at the end of this post.)
 
JavaScript is closer to Lisp, so you can get the value
of the sum /as the value of the loop/ in JavaScript,
just as in Common Lisp.
 
function * from_below( from, top )
{ let i = from; while ( i < top )yield i++; }
 
console.log
( eval( "sum = 0; for( let i of from_below( 1, 3 ))sum += i;" ));
 
(prints »3«).
 
Full C++ source code:
 
#include <initializer_list>
#include <iostream>
#include <ostream>
 
struct intref
{ int i = 0;
constexpr explicit intref( int const i ): i{ i } {}
constexpr int operator * () const { return i; }
constexpr intref & operator ++ () { ++i; return *this; }
constexpr bool operator != ( intref const other ) const
{ return this->i != other.i; }};
 
struct from
{ intref const first;
intref const top;
constexpr from( int const first, int const top ):
first{ first }, top{ top } {}
constexpr intref const begin() const { return first; }
constexpr intref const end() const { return top; }};
 
constexpr int below( int const i )
{ return i; }
 
constexpr int including( int const i )
{ return i + 1; }
 
int main()
{ auto sum { 0 };
for( auto const i : from{ 1, below( 3 )} )sum += i;
::std::cout << sum << '\n'; }
 
. I am not an experienced writer of C++ classes, so
I appreciate all comments on my C++ source code with a
Followup-To header for the newsgroup comp.lang.c++.
 
My most frequent error when summing up, is forgetting to
initialize the sum variable. Using »auto« above means that
I can't forget this!
 
Of course, one could define the abstractions so as to
force the user to use one of »below« or »including«.
 
Newsgroups: comp.lang.c,comp.lang.c++
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 14 11:57PM +0200

On 14-Apr-17 10:38 PM, Stefan Ram wrote:
 
> sizeof instance.i
 
> should be just 1, because one byte is enough to store
> one out of 10 values.
 
The problem is just all the boilerplate code to support arithmetic and
comparisons.
 
Boost has a little macro-based (I think it was) thing to generate that code.
 
 
Cheers!,
 
- Alf
Ralf Goertz <me@myprovider.invalid>: Apr 14 10:04AM +0200

Am Thu, 13 Apr 2017 10:28:02 -0700
 
> Nice. Well, I think that std::polar has the best chance of using
> sincos(). Need to check the implementation.
 
It doesn't use it here :-(
 
template<typename _Tp>
inline complex<_Tp>
polar(const _Tp& __rho, const _Tp& __theta)
{
__glibcxx_assert( __rho >= 0 );
return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta));
}
 
> g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/6/lto-wrapper
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada,go --enable-offload-targets=hsa --enable-checking=release --with-gxx-include-dir=/usr/include/c++/6 --enable-ssp --disable-libssp --disable-libvtv --disable-libcc1 --enable-plugin --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --enable-linker-build-id --enable-linux-futex --enable-gnu-indirect-function --program-suffix=-6 --without-system-libunwind --enable-multilib --with-arch-32=x86-64 --with-tune=generic --build=x86_64-suse-linux --host=x86_64-suse-linux
Thread model: posix
gcc version 6.3.1 20170202 [gcc-6-branch revision 245119] (SUSE Linux)
Ralf Goertz <me@myprovider.invalid>: Apr 14 11:42AM +0200

Am Wed, 12 Apr 2017 14:57:52 +0200
> single call on platforms that allow that. This makes use of the power
> of numerical algorithms to calculate both values simultaneously in
> significantly less time than the two separate calls.
 
Do you know where I can read more about that efficient algorithm. Sine
being odd and cos even means that their Taylor serieses don't share
any common powers of x. So I am a bit puzzled how that is accomplished.
 
> be used on 32-bit x86
> - on x86_64 it requires more work, but still the core numerical
> algorithm (e.g. a Newton expansion) can be easily adapted to this.
 
Hm, I just experimented a bit. Calculating 10 Million sines and cosine
separately takes as long as doing it in one go using sincos on my linux x86_64
architecture. Is it because the glibc sincos function is bogus here?
Christian Gollwitzer <auriocus@gmx.de>: Apr 14 02:26PM +0200

Am 14.04.17 um 11:42 schrieb Ralf Goertz:
 
> Do you know where I can read more about that efficient algorithm. Sine
> being odd and cos even means that their Taylor serieses don't share
> any common powers of x. So I am a bit puzzled how that is accomplished.
 
There are ways to do it together, e.g. if an algorithm is involved which
is based upon rotation like CORDIC. Here is another paper:
https://arxiv.org/abs/cs/0406049
 
 
 
> Hm, I just experimented a bit. Calculating 10 Million sines and cosine
> separately takes as long as doing it in one go using sincos on my linux x86_64
> architecture. Is it because the glibc sincos function is bogus here?
 
1) sincos only exists in (deprecated) 8087 math, so the instruction is
no longer used for SSE math
 
2) Have you run the sin and cos in spearate loops or in two consecutive
lines? gcc may have optimized it to a single call to _sincos - check the
disassembly to be sure
 
Christian
Ralf Goertz <me@myprovider.invalid>: Apr 14 03:39PM +0200

Am Fri, 14 Apr 2017 14:26:07 +0200
 
> There are ways to do it together, e.g. if an algorithm is involved
> which is based upon rotation like CORDIC. Here is another paper:
> https://arxiv.org/abs/cs/0406049
 
Thanks, I'll have a look.

 
> 2) Have you run the sin and cos in spearate loops or in two
> consecutive lines? gcc may have optimized it to a single call to
> _sincos - check the disassembly to be sure
 
 
diff'ing the two assembler files I get:
 
< movl $_ZZ7mypolarIdESt7complexIT_ERKS1_S4_E1c, %esi
< movl $_ZZ7mypolarIdESt7complexIT_ERKS1_S4_E1s, %edi
1084c1082,1091
< call sincos
---
> call cos
> movq %xmm0, %rax
> movq %rax, _ZZ7mypolarIdESt7complexIT_ERKS1_S4_E1c(%rip)
 
So I guess g++ is not that clever. The function (mypolar) I used was
defined according to the std::polar function I posted elsewhere in this
thread:
 
template<typename T> inline complex<T> mypolar(const T& rho, const T& theta) {
static T s,c;
sincos(theta,&s,&c);
//s=sin(theta);
//c=cos(theta);
return complex<T>(rho*c,rho*s);
}
 
The 10 million runs of the loop take about 350 ms. The loop does nothing
but replacing the appropriate element of a vector<complex<double>> (vc)
with the result of the mypolar call:
 
for (auto &i:vc) {
i=mypolar(1.0,i.real());
}
 
I had placed [0, M_2_PI)-uniformly distributed angles into the real
components of the elements of vc beforehand.
bitrex <bitrex@de.lete.earthlink.net>: Apr 14 04:05PM -0400

On 04/11/2017 02:23 AM, Alf P. Steinbach wrote:
> I've been thinking about this also in my younger days.
 
> Cheers!,
 
> - Alf (baffled, again :) )
 
e^(i*x) = cos(x) + i*sin(x).
 
HTH ;)
bitrex <bitrex@de.lete.earthlink.net>: Apr 14 04:16PM -0400

On 04/14/2017 04:05 PM, bitrex wrote:
 
>> - Alf (baffled, again :) )
 
> e^(i*x) = cos(x) + i*sin(x).
 
> HTH ;)
 
The proof is, roughly speaking, given certain assumptions two functions
that are the homogeneous solution to the same linear ordinary
differential equation and have the same Taylor series coefficients over
some domain must be the same function.
 
Here the domain is actually the entire set of complex numbers, z, of
which the real numbers are a subset.
"Chris M. Thomasson" <invalid@invalid.invalid>: Apr 14 10:45AM -0700

On 4/12/2017 9:51 PM, Chris M. Thomasson wrote:
 
> "n-ary roots from complex numbers..."
> https://groups.google.com/d/topic/comp.lang.c++/05XwgswUnDg/discussion
 
> to actually store data.
[...]
> Btw, I am wondering if you can run it and perhaps post some of the
> output? It would be interesting to compare the results I get on to other
> systems.
[...]
 
> __________________________________________
[...]
> __________________________________________
 
Fwiw, here are the outputs of the ct_store function I am getting from
two different compilers, MSVC and GCC:
 
 
MSVC 2015
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.8460152306934853e-15
________________________________________
 
 
GCC version 5.1.0 (tdm64-1)
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.8460152306934853e-15
________________________________________
 
 
If you run this and get different numbers, I would be interested in
looking at them. For instance, when this is executed online at:
 
http://cpp.sh I get:
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.1392213260039921e-15
________________________________________
 
The store_avg_err is different!
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: