Friday, February 24, 2017

Digest for comp.lang.c++@googlegroups.com - 25 updates in 8 topics

scott@slp53.sl.home (Scott Lurndal): Feb 24 01:41PM

>putted, so that means it shouldn't be an input but rather an output. So why=
> it exists inside LAPACKE_ssyev( ... , &w); I don't understand.
 
>Sorry, I'm very new to programming. I appreciate your time.
 
It seems evident that the W parameter is an output parameter. Since the
function will be storing a value indirectly through the pointer,
you don't need to initialize the variable before passing its address
to the function.
thebtc@hotmail.com: Feb 24 09:49AM -0800

Thank you Ben and Scott for your help. It seems that my problems are not over however because now I'm having trouble printing my eigenvalues to a text file. Here is my code:
 
#include <iostream>
#include <fstream>
#include <string>
#include "lapacke.h"
 
using namespace std;
 
int main(){
char jobz = 'N'; // computes eigenvalues only
char uplo = 'U'; // stores the upper triangle of a in an array a
int n = 10; // the order of the matrix a
float a[n][n]= {
{1, 11, 7, 9, 7, 11, 7, 9, 2, 11},
{11, 4, 10, 10, 6, 2, 9, 6, 10, 0},
{7, 10, 3, 5, 4, 4, 4, 4, 6, 10,},
{9, 10, 5, 3, 8, 8, 3, 5, 1, 8,},
{7, 6, 4, 8, 8, 10, 5, 6, 10, 0},
{11, 2, 4, 8, 10, 9, 4, 3, 5, 11},
{7, 9, 4, 3, 5, 4, 3, 10, 7, 2},
{9, 6, 4, 5, 6, 3, 10, 11, 1, 7},
{2, 10, 6, 1, 10, 5, 7, 1, 10, 5},
{11, 0, 10, 8, 0, 11, 2, 7, 5, 1}
}; // the symmetric matrix a for which the eigenvalues will be found
int lda = n; // the leading dimension of the array a
float w[n]; // stores the eigenvalues
}; // end of declarations
 
ofstream fout("eigenvaluesA.txt");
fout << "eigenvalues of matrix A" << endl;
LAPACKE_ssyev(&jobz, &uplo, &n, a, &lda, &w);
fout.close();
 
 
I keep getting the following errors:
'fout' does not name a type. How can it not name a type if I specified the namespace std thing at the beginning? I also get the error
expected constructor, destructor, or type conversion before '(' token
LAPACKE_ssyev(&jobz, &uplo, &n, a, &lda, &w);
However I am following several articles right now with examples that all list Lapacke and its inputs as I did above. so I'm not sure what is wrong with that line either. Any input is much appreciated.
scott@slp53.sl.home (Scott Lurndal): Feb 24 06:19PM

>expected constructor, destructor, or type conversion before '(' token
> LAPACKE_ssyev(&jobz, &uplo, &n, a, &lda, &w);
>However I am following several articles right now with examples that all list Lapacke and its inputs as I did above. so I'm not sure what is wrong with that line either. Any input is much appreciated.
 
put your code _inside_ main, not outside of it.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Feb 24 08:09PM

thebtc@hotmail.com writes:
I'll make a few more remarks...
 
> {2, 10, 6, 1, 10, 5, 7, 1, 10, 5},
> {11, 0, 10, 8, 0, 11, 2, 7, 5, 1}
> }; // the symmetric matrix a for which the eigenvalues will be found
 
C++ does not permit this sort of array. The size of a plain array must
be a compile-time constant and, despite is being obvious to you, n is
not a compile-time constant. Writing
 
float a[10][10]
 
would be fine, as would
 
float a[][] = { { ... }, { ... }, ... { ... } };
 
where the compiler will deduce that the size is 10x10.
 
> fout << "eigenvalues of matrix A" << endl;
> LAPACKE_ssyev(&jobz, &uplo, &n, a, &lda, &w);
> fout.close();
 
This needs to go into main. But then you will find other problems.
Firstly, you are not passing enough arguments to LAPACKE_ssyev and the
ones you are passing are of the wrong type. In general, you won't need
any of those &s. In fact, you don't need many of those variables -- you
can pass 'N' and 'U' directly rather than by putting them into jobz and
uplo.
 
<snip>
--
Ben.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 24 12:41AM +0100

> $var instead of auto? Why don't you like the auto keyword?
 
I don't /dislike/ `auto`. But `auto` has many different meanings, and
that makes it
 
• hard to search for e.g. variable declarations as opposed to constant
or reference declarations,
 
• hard to see at a glance what kind of declaration (such as variable or
constant, as in the array example below) a declaration is,
 
• hard to see what type a declaration is about, and
 
• I believe, difficult to learn to use correctly for a novice.
 
These are problems that are somewhat alleviated by the $ pseudo-keywords.
 
There are also problems, some mentioned below, that are irrelevant for
the use or not of pseudo-keywords, at least as long as they're macros
and not more real keywords supported by compiler extension. I think it's
easier now to do compiler extensions, with clang's support machinery.
But the last time I tried my hand at that, with gcc (for an idea about
exception handling), I found that gcc had a really complex structure
expressed in the apparently lowest possible level K&R C...
 
• • •
 
Regarding the claim of hard to see type, consider
 
auto s = "Blah";
 
Until I learned this as a special case (that didn't take long, but
until) I thought this would deduce `s` as `char const[5]`, which is
non-assignable and with length. But it deduces `s` as `char const*`.
Which is not even a constant, so one can, perhaps inadvertently, do
 
s = "Oh!";
 
Well, then perhaps change the declaration to
 
auto s[] = "Blah"; // ?
 
But contrary to what I think is a natural expectation, one just can't
use `auto` for an array item type: that won't compile.
 
The /technically/ correct way when one desires `s` as an immutable array
with length information retained, as the initializer, is to write
 
auto& s = "Blah";
 
But I wouldn't do that because it just obscures the desired result.
 
With the pseudo-keywords one can, however, write quite naturally
 
$let s = "Blah"; // `s` is const, decayed to pointer
$var s = "Blah"; // `s` is variable, decayed to pointer
$name s = "Blah"; // `s` is `char const[5]`
 
where
 
• $let → auto const, always yielding just a constant /value/;
 
• $var → auto, always yielding a mutable /variable/; and
 
• $name → auto&, always yielding just an /alias/.
 
Still lacking is a way to express
 
decay_t<decltype( *"Blah" )> s[] = "Blah";
 
which yields a mutable array, `char[5]`. A macro for this would get
/too/ ugly not just because it would have to take the initializer as
argument, but because that initializer could easily contain a comma or
two, which would be interpreted as macro argument separators. Well, a
variadic macro would be able to handle that, but it would still be ugly.
 
• • •
 
As an example of a problem that as far as I can see is not generally
solvable with keywords, consider the following code:
 
template< class Some_type >
using ref_ = Some_type&;
 
template< class Stream >
auto int_from( ref_<Stream> stream )
-> int
{
int result;
stream >> result;
if( stream.fail() ) { abort(); }
return result;
}
 
auto input_int( ref_<const wstring> prompt )
-> int
{
wcout << prompt;
return int_from( wcin ); // <--- Deducing the type Stream.
}
 
That works fine.
 
But the second declaration here does not work fine:
 
void foo()
{
auto& yep = wcin;
ref_<auto> nope = wcin; // <--- Uh oh.
 
(void) yep; (void) nope;
}
 
The problem here isn't the reference, which is just one specific use
case, it's the use of `auto` as a template (alias) argument.
 
The good old general template argument type deduction can see right
through that little template alias, as in the `ref_<Stream>`, but `auto`
just doesn't cut it.
 
 
> Why do you prefer obfuscation to idiomatic C++? What you are doing
> try to make C++ code look like code from other inferior languages is
> really egregious.
 
Well, those are emotional reactions.
 
I don't share them. :)
 
Actually I felt happy being able to express how I think about things
(just also slightly annoyed at having to use evil macros etc.).
 
For re the inferior languages, I think that to use C++ in a good way one
must have a clear picture of what /hypothetical language constructs/,
usually very much like constructs from other languages that one has
used, one is trying to implement with one's C++ code.
 
For example, to me, header and implementation files, and the whole thing
with include guards etc., implements modules, like Modula-2 MODULE or
Pascal UNIT or Ada PACKAGE. I haven't really used Ada but I've read some
books about it. And for example, to me, my `i_up_to` for a range-based
loop, implements in an imperfect but practically useful way, Python 2.7
`xrange` or Python 3.x `range`. And correspondingly, e.g. the $let
pseudo keyword in the expressive dialect implements in a very restricted
and awkward, but IMHO still very practically useful, way, a logical
`let` from a functional language or maths.
 
 
Cheers!,
 
- Alf
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 23 07:18PM -0600

> pseudo keyword in the expressive dialect implements in a very restricted
> and awkward, but IMHO still very practically useful, way, a logical
> `let` from a functional language or maths.
 
Apart from yourself who are you trying to convince? Really bad.
 
/Flibble
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 24 03:16AM +0100

On 24.02.2017 02:18, Mr Flibble wrote:
> Apart from yourself who are you trying to convince? Really bad.
 
I replied because you asked. Now you quoted everything just to point out
that you can't remember asking, and you wonder who. That's dumb.
 
Cheers!,
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 24 05:26AM +0100

On 24.02.2017 01:33, Stefan Ram wrote:
> R = ::std::move( x );
> x = ::std::move( r );
> r = ::std::move( a ); }}
 
Oh. :)
 
I confirmed, by writing my own little program for that, that you get a
correct result. Although it is for index 999.999 in the sequence, when
one considers fib(0) = 1, fib(1) = 1, fib(2) = 2, fib(3) = 3 and so on.
 
I'm not sure how your code works, it seems to do strange things, but
here's the expressive C++ dialect code that I cooked up to test it and
show how I would have written that program:
 
 
[code]
#include <p/expressive/using_weakly_all.hpp>
 
#include <algorithm>
#include <iostream>
#include <math.h> // log
#include <vector>
using namespace std;
 
using Big_int = std::vector<int>; // Each item is a decimal digit.
 
$procedure add_to( ref_<Big_int> a, ref_<const Big_int> b )
{
$let size_a = n_items_in( a ); $let size_b = n_items_in( b );
$var carry = 0;
for( $each i $in i_up_to( max( size_a, size_b ) ) )
{
if( i >= size_a ) { a.resize( i + 1 ); }
a[i] += carry + ($when( i < size_b ) $use( b[i] ) $default_to(
0 ));
carry = a[i]/10;
a[i] -= 10*carry;
}
if( carry != 0 ) { a.push_back( carry ); }
}
 
$just
{
$let golden_ratio = 1.6180339887498948482045868343656;
$let n = 100'000;
$let n_digits = static_cast<int>( (n + 10)*log10( golden_ratio ) + 1 );
clog << n_digits << " digits expected.\n";
 
$var a = Big_int{1}; a.reserve( n_digits );
$var b = Big_int{0}; b.reserve( n_digits );
for( $n_times( n ) )
{
$var next = a;
add_to( next, b );
a = move( b ); b = move( next );
}
for( $each digit $in reverse_span_of( b ) ) { cout << digit; }
cout << endl;
}
[/code]
 
I did not take the trouble to split the addition loop into parts where
the processing could be specialized for speed; I just used `-O3`. ;-)
 
This might be the reason that this code is shorter, 43 versus 91 lines,
even though my code looks much more verbose and whitespacey-ish.
 
 
Cheers!,
 
- Alf
 
PS: One problem with the $n_times macro is that g++ produces a very much
undesired warning "-Wno-unused-but-set-variable". I just turn it off but
I would like to suppress it for this situation in the code. I tried with
`_Pragma` expressions in the macro but g++ would have none of that
inside a `for` loop head. The macro is currently defined as
`$e::Dummy_reference_consumer $unique_temp_name $in $e::i_up_to( n )`. I
can't think of a way to do that without a range based loop.
Robert Wessel <robertwessel2@yahoo.com>: Feb 24 01:19AM -0600

On 24 Feb 2017 02:58:43 GMT, ram@zedat.fu-berlin.de (Stefan Ram)
wrote:
 
> 1.4 seconds. And this was only in Firefox, Chrome might
> even be faster. Amazing what they can get out of
> interpreters today!
 
 
The better Javascript processors are JITs these days.
Tim Rentsch <txr@alumni.caltech.edu>: Feb 24 12:08PM -0800


> Which is possibly in the subtraction operator or something, but I'm
> exhausted & hungry; I'll eat and watch a movie, and see tomorrow if
> anyone saw something blindingly obviously wrong?
 
I think some other replies have let you find the bug. I
just wanted to add my vote for using regular C++ rather
than the "expressive" flavor when posting this kind of
stuff. To look at any code more than about 10 or 20
lines I would like to be able to compile it. If the
code is written in "expressive" C++ I can't do that.
Paul <pepstein5@gmail.com>: Feb 24 11:52AM -0800

Please could someone link to (or provide) an example of copy-on-write in C++.
I know what it means, but I'd like to see a simple example. I didn't
really find one that looked convincing on a Google search.
 
I was asked about it in a job interview and got stumped.
Because I did well enough on the other questions, I have now been
invited back for a second interview, and I think they may test
how much I've learned in the meantime.
 
Many thanks,
 
Paul
kushal bhattacharya <bhattacharya.kushal4@gmail.com>: Feb 24 12:31AM -0800

Can anybody help in enabling thread support so that libevent automatically allocates lock for bufferevent from multiple threads
red floyd <dont.bother@its.invalid>: Feb 24 11:18AM -0800

On 2/24/2017 12:31 AM, kushal bhattacharya wrote:
> Can anybody help in enabling thread support so that libevent automatically allocates lock for bufferevent from multiple threads
 
The C++ Standard says nothing about libevent. Try a Unix or
or Linux group.
Steve Keller <keller@no.invalid>: Feb 24 06:52PM +0100

For a simple interpreter I wrote a class
 
class Stmt {
public:
virtual void exec() const = 0;
...
};
 
and several statement classes derived from that. In these classes I
have a number of occurrences of code like the following:
 
class FooStmt : public Stmt {
Stmt *s;
public:
virtual void exec() const {
if (s)
s->exec();
}
};
 
Therefore, I added a wrapper
 
void exec(const Stmt *s) {
if (s)
s->exec();
}
 
However, in order to be able to call exec(const Stmt *) from inside
FooStmt, I either need to
 
a) make this wrapper a static member function of class Stmt
 
b) if the wrapper is outside of class Stmt, I have to call it using
 
::exec(s)
 
instead of only exec(s).
 
c) rename the wrapper to something different than exec.
 
It seems the compiler, when looking for an exec(const Stmt *)
function, first looks for any exec(...) function in FooStmt and if it
finds one (in this case the exec() member function without parameters)
it does not continue to look for a matching exec(const Stmt *) outside
of FooStmt. But why does is behave that way?
 
I don't like any of these solutions because a) makes the wrapper
visible in the header file and b) and c) look cumbersome.
 
Are there other suggestions?
 
Steve
Paavo Helde <myfirstname@osa.pri.ee>: Feb 24 08:53PM +0200

On 24.02.2017 19:52, Steve Keller wrote:
> have a number of occurrences of code like the following:
 
> class FooStmt : public Stmt {
> Stmt *s;
 
I assume you have taken care to consider why you can and need to use a
raw pointer here instead of some standard smart pointer.
 
 
> finds one (in this case the exec() member function without parameters)
> it does not continue to look for a matching exec(const Stmt *) outside
> of FooStmt. But why does is behave that way?
 
It's a general rule in C++ to use the matching identifier from the
closest scope (class scope in this case). Otherwise you could not write
things like
 
#include <complex.h>
 
int foo(int arg) {
return arg + 1; // ambiguity! is this the local parameter
// or the arg() function from <complex.h>?
}
 
 
> I don't like any of these solutions because a) makes the wrapper
> visible in the header file and b) and c) look cumbersome.
 
Basically you want to have a special kind of pointer where dereferencing
null is ignored. In C++ one writes a new class for such things:
 
class ExecPtr {
const Stmt* s;
// ...
public:
void exec() const {
if (s) {
s->exec();
}
}
};
 
class FooStmt : public Stmt {
ExecPtr s;
public:
virtual void exec() const {
s.exec();
}
};
Christiano <christiano@engineer.com>: Feb 24 02:22PM -0300

On 02/23/2017 01:35 AM, Christiano wrote:
> // access d using d.day(), d.month(), and d.year()
> // make new Date to return
> }
 
I was testing some codes here.
 
See this C code:
 
/----------- a1.c -----------------\
#include <stdio.h>
 
struct house {
int a;
int b;
};
 
struct house func()
{
struct house e = {2,3};
return e;
}
 
int main()
{
int num =8;
struct house x = func();
 
printf("%d %d\n", x.a, x.b);
 
return 0;
}
\---------------------------------/
 
Now, see the second version:
 
/------------- a2.c -----------------------\
#include <stdio.h>
 
struct house {
int a;
int b;
};
 
struct house func()
{
return (struct house){2,3};
}
 
int main()
{
int num =8;
struct house x = func();
 
printf("%d %d\n", x.a, x.b);
 
return 0;
}
\--------------------------------------/
 
The "func" function in the first version locally creates a "struct
house" and then copies it to the "struct house" in the main.
 
The "func" function in the second version creates the "struct house" in
the main directly.
 
It is possible to observe this in the generated assembly code using -S
option (gcc/g++).
 
In C++ things are not different.
 
For example:
 
Date new_date_random()
{
Date x = Date{ random_day(), random_month(), random_year() };
return x;
}
 
VERSUS
 
Date new_date_random()
{
return Date{ random_day(), random_month(), random_year() };
}
 
The first version locally creates a "Date" and then copies it to the
"Date" outside. (Assuming here that there was no RVO optimization.)
 
The second version creates the "Date" outside directly.
 
That is, this information indicates that:
 
In situations where we are not receiving references from the object
outside, It is preferable whenever possible to return an unnamed literal
class object.
Paavo Helde <myfirstname@osa.pri.ee>: Feb 24 08:24PM +0200

On 24.02.2017 19:22, Christiano wrote:
 
 
> I was testing some codes here.
 
Are you sure you compiled with optimization flags like -O2 ? This whole
thread is all about optimizations, for testing them you need to switch
them on.
helpseeker <vijaybhaskar@gmail.com>: Feb 24 12:29AM -0800

Hi,
 
I would like to know what is the general guidance/preference for using the override keyword in cpp files. I personally think that it is helpful to have the override keyword in the cpp files too so that it is easy to identify which methods are overridden and which are not. But I know its not needed to have the override keyword in cpp files. Is there a bad side to it though - to have override keyword in cpp file?
 
Thanks
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 24 11:09AM +0100

On 24.02.2017 09:29, helpseeker wrote:
> not. But I know its not needed to have the override keyword in cpp
> files. Is there a bad side to it though - to have override keyword in
> cpp file?
 
Your decision to use `override` should not be influenced by the kind of
file – whether header or implementation file like cpp.
 
The kind of file plays a rôle for the compiler's assumption of what
programming language the code is written in, and it plays a rôle for
your assumption about how the file will be used, e.g. that a header file
will be included and an implementation file used as the main code file
for a translation unit.
 
The by convention different usage means that one adopts some different
conventions in header files versus implementation files, e.g. for
include guards, use of `inline`, definitions of namespace scope
variables. But this does not extend to use of `override` or not. There
is no way that the different usage of different file types is related to
what `override` is about.
 
`override` is a safeguard against believing one overrides a base class'
member function that isn't there or isn't virtual, and it's a safeguard
against maintenance changing the signature of an overridden function,
e.g. by adding a defaulted argument. So, it's effectively a part of the
static type checking, even though it doesn't influence the type.
Essentially it says to the compiler, "this is what I intend, namely an
override, please check that for me", and clearly that has nothing to do
with file types whatsoever.
 
The cost is mainly that the syntax is awkward, with `override` at the
end of the function head. That can present a formatting problem. But
it's IMO a very small problem, and the safety is well worth it.
 
 
Cheers & hth.,
 
- Alf
Paavo Helde <myfirstname@osa.pri.ee>: Feb 24 01:32PM +0200

On 24.02.2017 10:29, helpseeker wrote:
> Hi,
 
> I would like to know what is the general guidance/preference for using the override keyword in cpp files. I personally think that it is helpful to have the override keyword in the cpp files too so that it is easy to identify which methods are overridden and which are not. But I know its not needed to have the override keyword in cpp files. Is there a bad side to it though - to have override keyword in cpp file?
 
What do you mean by 'in cpp file'? If you mean if you should repeat the
override keyword in a member function definition outside of the class
definition, then this is expressly forbidden by the current standard
(C++14):
 
8.4.1/1: "A virt-specifier-seq can be part of a function-definition only
if it is a member-declaration."
 
9.2/8: "A virt-specifier-seq shall appear only in the declaration of a
virtual member function."
ram@zedat.fu-berlin.de (Stefan Ram): Feb 24 12:33AM

>I decided to do a little challenge we used to give to the students in
>Bodø in the mid 1990s: to implement a bignumber class and use it to
>compute the Fibonacci sequence up to a ridiculous length.
 
I did not really try to find the bug in your code, but I
wrote a C++ program to print the 100'000th Fibonacci number.
 
Disclaimer: it's a quick hack: One cannot really change the
»< long, 1'000'000'000L >« below to something else, unless
on also edits the »"000000000"« in »to_string«.
 
Disclaimer: Code was slightly edited between the last test
and the post, hope not to introduce new bugs.
 
#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
 
using namespace ::std::literals;
 
/* a vector that will grow on demand */
template< typename T >
class vector : public ::std::vector< T >
{ public: using ::std::vector< T >::vector;
 
/* delete the following function definition when your estimates for
the number of digits in main are surely large enough (to trade some
security for speed) */
T& operator[]( typename vector::size_type const i )
{ while( i >= this->size() )this->push_back( 0 );
return( *( static_cast< ::std::vector< T >* >( this )))[ i ]; }};
 
/* a big number */
/* base must be less than MAX_DIGIT/2, say less than MAX_DIGIT/2-2,
base must be a power of 10 for the simplistic to_string function
below to be correct. */
template< typename DIGIT, DIGIT base >
class bignum : public vector< DIGIT >
{ public: public: using vector< DIGIT >::vector;
using digit_type = DIGIT;
typename ::bignum<DIGIT,base>::size_type length;
 
/* add h to g giving R,
h must not be shorter than g,
R is the result */
static void sum
( ::bignum<DIGIT,base> & g, ::bignum<DIGIT,base> & h,
::bignum<DIGIT,base> & R )
{ typename ::bignum<DIGIT,base>::size_type p = 0;
bool o = false; /* actually the carry bit */
while( p < g.length )
{ DIGIT const s = o + g[ p ]+ h[ p ];
R[ p++ ]= s -( o = s > base )* base; }
while( p < h.length )
{ DIGIT const s = o + h[ p ];
R[ p++ ]= s -( o = s > base )* base ; }
if( o )
{ DIGIT const s = o;
R[ p++ ]= s -( o = s > base )*base; }
R.length = p; }
 
static ::std::string to_string( ::bignum<DIGIT,base> & n )
{ ::std::string result; result.reserve( 1000 );
for( int i = n.length; i > 0; )
{ --i;
if( i == n.length - 1 )result += ::std::to_string( n[ i ]);
else
{ ::std::string s = ::std::to_string( n[ i ]);
char const * p = "000000000" + s.length();
result += p; result += s; }}
return result; }
 
/* set the argument to the number one */
static void one( ::bignum<DIGIT,base> & x )
{ x[ 0 ]= 1; x.length = 1; }};
 
int main()
{ using number = bignum< long, 1'000'000'000L >;
number x( 30'000 ); number::one( x );
number r( 30'000 ); number::one( r );
number R( 30'000 ); number::one( R );
number a;
for( long i = 2; i <= 100'000; ++i )
{
bool print = i == 100'000; /* edit here to specify which values */
/* you want to be printed. */
if( print )
{ ::std::string result = number::to_string( r );
::std::cout << i << ' ' << result << '\n'; ::std::cout.flush(); }
if( r.length < x.length )number::sum( r, x, R );
else number::sum( x, r, R );
a = ::std::move( R );
R = ::std::move( x );
x = ::std::move( r );
r = ::std::move( a ); }}
ram@zedat.fu-berlin.de (Stefan Ram): Feb 24 12:52AM

>Java/C# have quite same roots but Java/Javascript? Nonsense connection.
 
Using aggressive wording like »Nonsense« will not help
to cover your lack of expertise.
 
»The diktat from upper engineering management was that
the language must "look like Java"«. - Brendan Eich
ram@zedat.fu-berlin.de (Stefan Ram): Feb 24 01:09AM

>>Java/C# have quite same roots but Java/Javascript? Nonsense connection.
>Using aggressive wording like »Nonsense« will not help
>to cover your lack of expertise.
 
Now I made the error that I dislike so much when I read it!
 
An article (determiner) is missing in front of »aggressive
wording«, but actually I intended to write the plural
»aggressive wordings«, and the »s« somehow disappeared.
ram@zedat.fu-berlin.de (Stefan Ram): Feb 24 02:58AM

>I did not really try to find the bug in your code, but I
>wrote a C++ program to print the 100'000th Fibonacci number.
 
I wrote a similar program in JavaScript:
 
Turns out: Here the JavaScript program is not much
slower than the compiled C++ program. The C++ program
takes about 1 second here and the JavaScript program about
1.4 seconds. And this was only in Firefox, Chrome might
even be faster. Amazing what they can get out of
interpreters today!
 
{ const alpha = new Date().getTime();
const fib =
( () =>
{ "use strict";
const e = 14;
const b = eval( "1e" + e );
const f = Array( e ).join( "0" );
let x = new Float64Array( 3e4 ); x[ 0 ] = 1.0; let xl = 1;
let r = new Float64Array( 3e4 ); r[ 0 ] = 1.0; let rl = 1;
let R = new Float64Array( 3e4 ); let Rl = 0;
let j = new Array( 3e4 );
let s = 0;
let a; let al;
let o = 0;
let p = 0;
let g; let G;
let h; let H;
const fibonacci =( n )=>
{ for( let i = 1; i < n - 1; ++i )
{ if( rl < xl ){ g = r; G = rl; h = x; H = xl; }
else { g = x; G = xl; h = r; H = rl; }
p = 0; o = 0;
while(p<G){s=o+g[p]+h[p];R[p++]=(s-(o=+(s>b))*b);}
while(p<H){s=o+h[p];R[p++]=(s-(o=+(s>b))*b);}
if(o!=0){s=o;R[p++]=(s-(o=+(s>b))*b);}
Rl = p;
a = R; al = Rl; R = x; Rl = xl; x = r; xl = rl; r = a; rl = al; }
let i = 0;
for( ; i < al - 1; ++i )j[ i ]=( f +( a[ i ] )).slice( -e );
j[ i ]= a[ i ];
return j.slice( 0, al ); }
return fibonacci( 100000 ).reverse().join( "" ); } )()
const omega = new Date().getTime();
console.log( fib );
console.log( omega - alpha ); }
ram@zedat.fu-berlin.de (Stefan Ram): Feb 24 03:08AM

>Turns out: Here the JavaScript program is not much
>slower than the compiled C++ program. The C++ program
 
When I use »double« for a bignum digit, I can store
14 decimal digits in one bignum digit with C++, and
then the program is about 10 % faster.
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: