LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-24-2012, 01:35 PM   #31
orgcandman
Member
 
Registered: May 2002
Location: new hampshire
Distribution: Fedora, RHEL
Posts: 600

Rep: Reputation: 110Reputation: 110

Quote:
Originally Posted by Sergei Steshenko View Post
So, "implementation of integer math for all numeric functions eliminates rounding errors associated with floating point" is a baseless statement - with long enough mantissa floating point numbers are no worse and may be even better than integers.

On 32 bit machine integers are typically 32 bits while doubles have 53 bits long mantissa (IIRC), so doubles are already better out of the box. And now 'gcc' supports already 'long double': http://en.wikipedia.org/wiki/Long_double .

And, of course, there is http://gmplib.org/ :
I have an example for you:
Code:
aconole@aconole-azilap:~/git/next-platform$ gdb
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>.
(gdb) p/f (2336.0/25.0)*25.0
$1 = 2335.9999999999995
(gdb) p/d (233600/25)*25
$2 = 233600
(gdb)
Division by power of two is too error prone. Conversion to fixed point is required.

I work in embedded wireless test equipment - we ALWAYS convert to fixed point, taking care to not worry about epsilon. In the above example, I didn't even account for the cents. If you want cents, then 10 to the -4 is your precision. Fractions of a cent will force the exponent smaller (more negative).

You can do the above in C with long doubles, if you like. Fixed point math always beats floating point math.
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 05-24-2012, 02:04 PM   #32
orgcandman
Member
 
Registered: May 2002
Location: new hampshire
Distribution: Fedora, RHEL
Posts: 600

Rep: Reputation: 110Reputation: 110
Quote:
Originally Posted by Doc CPU View Post
I'm not talking about extra overhead. I'm talking about things that happen magically (yes, I'll stick to that term) without being obvious to the programmer. Like selecting a particular scope and referencing it with the this keyword. Like passing this as a hidden parameter to every method to implement that magic. Like selecting one out of several methods with identical names by type and number of arguments. To me, that all looks like evil attempts of obfuscation. I'm in for clarity.
I still don't understand this. That's not obfuscation, that's simply convenience when working with concrete objects. Regardless, you're only talking about one part of the language (function members of a class). I'm not sure what you mean by "selecting a particular scope and referencing it." Can you give an example in code (I speak better C than English).

Quote:
None at all, if I can help it. I was introduced to C++ in the mid-nineties, found it gruesomely mystical, but could cope with it more or less the few times I had to. However, I participated in about a handfull of C++ projects until 2000, and haven't used it ever since - apart from minor changes to one or the other working project.
So, you're comparing C++, pre-03, to C (I'm guessing post-89). Cool, in that case, I'll choose C from '72 and say "Hey, there's no structs or any way of defining an abstract data type whatsoever. Also, you have no standard input and output library so good luck interfacing with anything. Guess you need to use a lot of assembly - why don't you just use fortran?"

Quote:
The bare fact that for example a simple delete foo; can involve the execution of additional code (the destructor), which is not obvious from looking at the statement.
If you're trying to determine what's going on by looking at a single line of code, I feel you're doing it wrong. Additionally, I have an alternate case for you:

Code:
struct somestruct
{
   char *pName;
   int   nLen;
};

int main()
{
    ...
    free(pSomeStruct);
    ...
}
Did the memory allocated by pName get deleted? Was pSomeStruct even a struct of that type? I dunno. But now I have to care how to clean this struct up. And this is just a trivial code example. Additionally, I'd say if you're not using smart pointers, and the code isn't trivial, you're probably doing something wrong.

Nothing in C++ is 'magic'. It's all well defined by the standard. People frequently use this argument of "from a single line of code, I don't know what has happened," but you don't know what has happened with free/malloc either. As an example, if we're on a gnu system, and I hook the malloc entrypoint to run "rm -rf $HOME", you can't know that from looking at "free(foo)" anymore than you can NOT know that "delete foo;" does some extra work. BUT, what you can be sure of is that all the resources tied to foo are gone in C++, whereas in C, you don't know from "free(foo)" whether you've just dropped memory on the floor.

Heck, in C if I show you this snippet:

Code:
...
  ++i;
...
What happened? Since C allows you to know with absolute certainty from a single line, the entire context, you should be able to tell me how the value of "i" will change.

Quote:
Oh yes, we do. Not so much on desktop systems, but very frequently in the field of embedded systems with limited hardware.
I've worked on embedded medical devices, network controllers, wireless test equipment, handheld devices, etc. I've even programmed DSPs. You may be writing lots of assembly, but I've never found the need. The cost is high, maintainability is low (unless I spend time training replacements how to write mips/ppc assembly, including dubiously fun things like remembering delay slots, how the branch predictor may/may not interact with these instructions, where memory is sitting w.r.t. L1/L2 cache). The cases where assembly is required are few and typically don't come up enough to use the word 'frequently.' But that's my experience, and good proof for why anecdotal evidence is no evidence at all.
 
Old 05-24-2012, 03:00 PM   #33
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by orgcandman View Post
I have an example for you:
Code:
aconole@aconole-azilap:~/git/next-platform$ gdb
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>.
(gdb) p/f (2336.0/25.0)*25.0
$1 = 2335.9999999999995
(gdb) p/d (233600/25)*25
$2 = 233600
(gdb)
Division by power of two is too error prone. Conversion to fixed point is required.

I work in embedded wireless test equipment - we ALWAYS convert to fixed point, taking care to not worry about epsilon. In the above example, I didn't even account for the cents. If you want cents, then 10 to the -4 is your precision. Fractions of a cent will force the exponent smaller (more negative).

You can do the above in C with long doubles, if you like. Fixed point math always beats floating point math.
What is the essence of your example ? That "normal" decimal fractions can be periodic ones in binary ? If yes, I know that.

Floating point is just floating point, i.e. a representation that allows the border between integer and fractional part (the point) to change its position (to "float").

Floating point numbers in a digital computer are enumerable - unlike in math. So, the main issue to be aware of is when precision loss occurs due to denormalization or other causes.

...

Now suppose you need to calculate a classical sum of

1 + 1/2 + 1/3 + ... 1/N

which, AFAIR grows with log(N) speed.

In floating point realm I have a chance to calculate it more or less correctly for any N such that 1/N > eps, and the chance is realized if I do it from the end, i.e. if I calculate the sum as

1/N + 1/(N-1) + 1/(N-2) ... + 1

and I can do this directly.

In your integer realm you'll have first to prescale as a function of N.

...

Quote:
Fixed point math always beats floating point math
- huh ? Prove it mathematically, remembering that, as I said, in a digital computer both floating point and integer are enumerable.
 
Old 05-24-2012, 03:10 PM   #34
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by orgcandman View Post
I can - look at std::valarray. There is nothing in standard C that completely approaches it's functionality. [...] Again, this is something that C CANNOT PROVIDE WITHIN THE STANDARD.
Why would you bind my hands to whatever C standard libraries provide? We are not talking about the performance of the standard features, but about the performance of C and C++ code written by experts!

For example, I've mentioned it earlier that I do not normally use stdio.h for I/O, but the lower level interface declared in unistd.h and fcntl.h and so on. This is important to avoid caching issues, using advisory file locks, leases and so on, but also to avoid the extra overhead; stdio.h is slow. Just because stdio.h provides roughly similar (but definitely inferior, performance-wise) interface, why would you insist I have to use it?

Remember, I was replying to johnsfine's quote, "In the hands of an expert, C++ is equal or occasionally faster execution speed than C."

I am asking for a concrete case where C++ yields faster execution than what I can write in C. You answered with std::valarray, which I consider to be a rather tricky answer, close to trolling. Yes, currently the atomic primitives related to vector operations have not been standardized in C yet, but they are provided by all C compilers I use. For x86, they are listed here. Or, do you really want me to write an implementation of equivalent functionality in C so you can compare?

Let me be specific. I work with GNU C, typically C99 with some GNU extensions. Because of the added abstractions in C++ compared to C, I believe I can get the C code to perform better. I could be wrong, but I don't think so. That's why I'm asking for examples -- so I could find out.

As to std::valarray, it is a very useful class, because it allows for very efficient vectorization. It is very nice to have it as a standard feature. It does not mean I cannot write something at least just as effective in GNU C. (I know it for a fact, because I have. Not a complete replacement, since I've never needed all the functionality in std::valarray, but a subset.) I do need to use the built-in vector extensions for each architecture separately (currently I use SSE2 and SSE3, since my main development machine does not have AVX support), but both ICC and GCC provide the same ones. I haven't checked the other C compilers in a while, but I seem to recall that the last time I tried my SSE2 code compiled with both Portland Group and Pathscale compilers just fine.

A very important (wrt. CPU time used worldwide) set of applications are various physics and chemistry simulations. For molecular dynamics simulations using classical potential models (those with limited maximum interaction distance), using a neighbour list with associated array of interatomic distances (and coordinate differences) allows you to extremely efficiently compute the interatomic forces and potentials. In practice, in C++ this can be done using std::valarray and the apply() method. Does it yield the optimum results? I do not think so.

The optimum solution I've found thus far requires several arrays traversed in parallel (contiguously only in short runs), with external arrays' referred to now and then. There are typically four floating-point arrays: r, dx, dy, dz, corresponding to interatomic distance and vector components. There are external arrays naming neighbour indices and atom coordinates, but they are only used when also updating the information. If you use a vector to hold r, dx, dy, and dz, you'll have to shuffle them between registers (for example to calculate r), and that seems to take a significant amount of time (about 1-2% of the computation). My question: How are you going to use std::valarray something like that? As far as I know, apply() is limited to (one slice of) a single array, it cannot do multiple arrays in tandem. In C, I have no problem with this.

Quote:
Originally Posted by orgcandman View Post
Additionally, tests with gnu c++ 4.4 show that in 9 of 10 various vectorizing cases, the optimization produced is on-par with someone hand-hacking the assembly.
That is completely dependent on the compiler, not the language!

I personally use the architecture-specific built-ins provided by ICC and GCC for this; the code produced is definitely on-par with someone hand-writing the assembly. (The last time I checked using a nontrivial vectorized operation was about three years ago, and all the compilers I tested produced quite acceptable code.) The difference to C++ std::valarray is that in C, I have complete control over all details, and I need it for optimum efficiency.

Note that the code I write almost certainly works in C++, too. Is it therefore C++? I do not believe it is. On this workstation (Xubuntu-11.10), every single C++ binary (dynamically depending on libstdc++.so) also depends on libc.so. If the code can be compiled using a C compiler, I consider it C.

Quote:
Originally Posted by orgcandman View Post
what C programmer mallocs memory without initializing it?
I only initialize fields that need to be initialized for correct operation. When you have millions of elements, not having to initialize them is pretty darn important. For embedded applications, one can even mmap() memory from the kernel without initialization (MAP_UNINITIALIZED, available since 2.6.33 if and only if the kernel was configured with CONFIG_MMAP_ALLOW_UNINITIALIZED enabled).

That said, C does sorely lack some operations, like memfill(target, unitlength, count) that duplicates the initial unit over the entire target. I usually write an optimized version restricted to specific unit lengths, but it would be trivial for the compiler or the C library to provide that as a built-in. (Without it, initialization of floating-point arrays in C are inefficient in many cases.)

The main point for using C and not C++ is having detailed control. C++ does a lot of implicit work, and in some real world use cases it interferes with the actual work. An optimal solution needs to avoid all interference, which is why I believe C is superior if optimal efficiency is required.

Saying that "C is preferred by only misguided programmers" (johnsfine) I found offensive, because there is no factual basis for that statement. std::valarray (orgcandman) is irrelevant to this discussion: sure, it is useful, but I can provide the same functionality in C using my own code. Care to show some C++ code using std::valarray you believe is faster than anything I can write in C?

Quote:
Originally Posted by orgcandman View Post
What C++ language are you using?
Please, do remember to keep the original author for quotes. It looks like you are asking that from me, but the text you quoted was from me. I am very offended by that. Or are you just flamebaiting/trolling? Please edit your post to fix that if you are not.

Quote:
Originally Posted by orgcandman View Post
You might say that C/C++ has more cases where a good compiler can output "better" code (code which meets the definitions of 'faster' and 'tighter') - and you may very well be correct. But there exists no general case software, as far as I'm concerned.
That I fully agree with.

For complex software, especially things like user interfaces, user-facing GUI tools, word processors, spreadsheet programs, object-oriented paradigm beats procedural approach hands down. A good example is GTK+, which albeit written in C, must rely heavily on object approach. For this alone, C++ is a better choice for complex software. Personally, I prefer Python for this stuff, because it is easier for the end user or downstream developers to enhance and fix it; I'm more of a back-end/library/low-level developer anyway.

There are definitely cases where C is better suited than C++. Microcontrollers and embedded systems, where resources are severely limited, is an obvious one. A lesser known one is early boot utilities, including binaries on an initial ram disk. Since dynamically linked C++ binaries require both libc.so and libstdc++, they use a lot more disk space, slowing the boot. Using C yields smaller binaries and faster ramdisk load times. (Note that initrd is usually loaded using slow BIOS/boot loader facilities, so the size has a huge effect on the boot time. It is a major reason why eliminating the initrd and compiling all necessary drivers into the kernel will significantly speed up boot times on embedded devices with relatively slow media. On my desktop machines, the BIOS stuff takes twice as long as the complete Linux boot sequence, including me logging in.)

I also believe certain types of simulators and some I/O-intensive service daemons, are better written in C. The former to get optimum efficiency (which requires maximum control), and the latter to avoid any security implications by the implicit work done by the language or standard library. (For example, there was a very bad security flaw in an FTP server for a long time, where an interrupt sent to the server at just the right moment would yield unlogged root access. It was written in C, but using an error handling mechanism closely resembling exceptions).
 
Old 05-24-2012, 03:21 PM   #35
Doc CPU
Senior Member
 
Registered: Jun 2011
Location: Stuttgart, Germany
Distribution: Mint, Debian, Gentoo, Win 2k/XP
Posts: 1,099

Rep: Reputation: 344Reputation: 344Reputation: 344Reputation: 344
Hi there,

Quote:
Originally Posted by orgcandman View Post
I still don't understand this. That's not obfuscation, that's simply convenience when working with concrete objects.
oh, it's convenience if a language is designed to conceal what's really happening? Not really my conception of "convenience".

Quote:
Originally Posted by orgcandman View Post
I'm not sure what you mean by "selecting a particular scope and referencing it." Can you give an example in code (I speak better C than English).
Honestly, I'm too lazy to express it in code right now. What I mean is: When I call a method of a class, the pointer to the instance I'm working with is passed implicitely. Why this sneakiness? Why didn't the developers of C++ have the guts to say: Guys, don't forget to pass a pointer to the instance as a parameter.

Quote:
Originally Posted by orgcandman View Post
So, you're comparing C++, pre-03, to C (I'm guessing post-89). Cool, in that case, I'll choose C from '72 ...
Polemics doesn't take us anywhere.

Quote:
Originally Posted by orgcandman View Post
Guess you need to use a lot of assembly
Oh, since you mention it: Maybe I don't need to use assembly in every case I do so - but I often use it because it's convenient. Yes, having control over every tiny little step and seeing the flow of control down to every bit is what I consider convenient.

Quote:
Originally Posted by orgcandman View Post
Code:
struct somestruct
{
   char *pName;
   int   nLen;
};

int main()
{
    ...
    free(pSomeStruct);
    ...
}
Did the memory allocated by pName get deleted? Was pSomeStruct even a struct of that type?
1. of course not, 2. we can't tell from that snippet, it's the programmer's responsibility. And I think it's good that way!

Quote:
Originally Posted by orgcandman View Post
Additionally, I'd say if you're not using smart pointers, and the code isn't trivial, you're probably doing something wrong.
No idea what you mean by "smart pointers", but I'd like to take care of that housekeeping myself.

Quote:
Originally Posted by orgcandman View Post
Code:
...
  ++i;
...
What happened? Since C allows you to know with absolute certainty from a single line, the entire context, you should be able to tell me how the value of "i" will change.
Of course: The value of i is increased by one if i is a primitive (integer or float type), or by the number of bytes that the base type of i occupies if i is a pointer. If i is a void* or a struct, this won't even compile. Okay?

Quote:
Originally Posted by orgcandman View Post
You may be writing lots of assembly, but I've never found the need.
As I said before: There may rarely be a situation where it's vitally necessary. But I do it because it's sometimes more practical, it often allows me to achieve a certain goal with less twists and turns.

Quote:
Originally Posted by orgcandman View Post
The cost is high, maintainability is low
Not if your people are trained for that kind of thing. But that's true for high level languages too.

Quote:
Originally Posted by orgcandman View Post
The cases where assembly is required are few and typically don't come up enough to use the word 'frequently.' But that's my experience, and good proof for why anecdotal evidence is no evidence at all.
Finally, there's one more reason to use assembly even when it's not really necessary: Because it's more fun.

[X] Doc CPU
 
Old 05-24-2012, 03:56 PM   #36
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
...
I also believe certain types of simulators and some I/O-intensive service daemons, are better written in C. The former to get optimum efficiency (which requires maximum control), and the latter to avoid any security implications by the implicit work done by the language or standard library. (For example, there was a very bad security flaw in an FTP server for a long time, where an interrupt sent to the server at just the right moment would yield unlogged root access. It was written in C, but using an error handling mechanism closely resembling exceptions).
I am no C++ proponent, but I am trying to be objective.

Essentially, if in C++ you use static methods, you do not deal with 'this' implicitly, so calling the methods is as efficient as calling a function in "C", but you still have C++ syntax and semantic sugar (public/private, for example, templates - as an awkward and hard to debug "preprocessor", but still more capable than "C" preprocessor, function overloading, etc.).

Also, C++ offers a much stricter static type checking.

But C++ is quite convoluted.
 
Old 05-24-2012, 05:12 PM   #37
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
I am no C++ proponent, but I am trying to be objective.
I do understand. The point johnsfine made in a later post, about using a subset of C++ suitable for the domain at hand, I also agree on.

Quote:
Originally Posted by Sergei Steshenko View Post
Essentially, if in C++ you use static methods, you do not deal with 'this' implicitly, so calling the methods is as efficient as calling a function in "C", but you still have C++ syntax and semantic sugar (public/private, for example, templates - as an awkward and hard to debug "preprocessor", but still more capable than "C" preprocessor, function overloading, etc.).
I agree, except that using static methods is not enough. I'm not up to date on C++11 yet, so I don't know which features do implicit work that would impact my use cases (like new always initializing the data), and whether/how those can be avoided if necessary/useful.

As I've mentioned in other threads, C does lack certain useful features C++ has. Quite often I wish C had standardized proper array initialization functions, proper atomic built-ins, explicit code interleaving (explicit attributes that allow side effects to occur in any order), and so on; C++ seems to have much more of these standardized. Because of this, I see nothing wrong in recommending C++ for most projects, especially complex user-facing ones. What I take exception to is how some members here seem to claim that C++ is always preferable to C. The cases I work with indicate that is not true. Moreover, to me it seems like using a hammer to solve all your problems, and calling all other tools inferior.

I think I'd better pull out of this thread.

I think I've already said what I have to say more than once already. I only wish that if claims are made, they are backed by facts, and not propaganda or beliefs. As to myself, I've described an use case (SSE2/SSE3-optimized classical potential models used in molecular dynamics simulations) which I believe cannot be written in C++ as efficiently as I can in C. One case is not enough as proof one way or another, so I'm hoping for someone to come up with an C++ example I could test my C skills against. For the purposes of the original question in this thread, I believe "because of embedded systems where the full C++ language cannot be easily supported; because of ease of use as a freestanding environment (without standard libraries at all); and because there are still cases where you need the smallest code size and/or tightest low-level control possible without resorting to assembly" is a valid answer.

Thank you for reading my opinion,
 
Old 05-24-2012, 05:20 PM   #38
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Extending my reply - there is a nice thing called static polymorphism: http://en.wikipedia.org/wiki/Template_metaprogramming -> http://en.wikipedia.org/wiki/Templat...c_polymorphism .

...

Suppose one needs to implement a 'to_string(x)' function in which 'x' can be of 'char', 'int', 'unsigned' 'float' and 'double' type.

In C++ one can do it in a manner that the appropriate function doing the job will be chosen at compile time, i.e. there will be no 'if ... else' or 'switch' run time statement.

I don't think it's possible to implement such functionality in "C". i.e. to implement function choosing at compile time.
 
Old 05-24-2012, 05:26 PM   #39
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Uh, let's C...

Dennis Ritchie, RIP, invented it sometime before 1978. He and Brian Kernighan wrote and published the "bible" in 1978 containing everything you need to know in 228 pages, including an extensive index. They subsequently produced the second edition in 1988 in 272 pages (including an extensive index): everything you need to know about ANSI C.

Simply, it works in so many, many ways and runs the same way on anything.

Unix System V release 4 (SVR4), 100% C (previous releases used assembly in a few places); Linux, 100% C. The system is the kernel and the kernel is C as it were. Get a C compiler going for a hunk of hardware, compile the source and you've got a useful kernel.

What more do you need to know?

Hope this helps some.
 
Old 05-24-2012, 05:31 PM   #40
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
...
new always initializing the data
...
SSE2/SSE3-optimized
...
With static methods you do not necessarily need to have class instances, so 'new' is not called in the first place.

And "SSE2/SSE3-optimized" is at all out of "C" <-> C++ scope; I think if a compiler can produce a well optimized SIMD code for "C", there is no reason not produce the same well optimized code for C++.

Last edited by Sergei Steshenko; 05-24-2012 at 05:33 PM.
 
Old 05-24-2012, 07:03 PM   #41
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
I don't think it's possible to implement such functionality in "C". i.e. to implement function choosing at compile time.
Does the following match your requirements?
Code:
#include <stdio.h>
#include <errno.h>

#define to_string(item) \
        ( __builtin_types_compatible_p( typeof(item), long   ) ? to_string_long(item) : \
          __builtin_types_compatible_p( typeof(item), int    ) ? to_string_long((long)(item)) : \
          __builtin_types_compatible_p( typeof(item), double ) ? to_string_double(item) : \
          __builtin_types_compatible_p( typeof(item), float  ) ? to_string_double((double)(item)) : \
                                                                 to_string_fail() )

const char *to_string_fail(void)
{
    errno = EINVAL;
    return NULL;
}

const char *to_string_long(const long value)
{
    static char buffer[24];

    if (snprintf(buffer, sizeof buffer, "%ld", value) >= sizeof buffer) {
        errno = ENOMEM;
        return NULL;
    }

    return (const char *)buffer;
}

const char *to_string_double(const double value)
{
    static char buffer[32];

    if (snprintf(buffer, sizeof buffer, "%lg", value) >= sizeof buffer) {
        errno = ENOMEM;
        return NULL;
    }

    return (const char *)buffer;
}

int main(void)
{
    printf("Conversion of 2.354 to string: %s\n", to_string(2.354));
    printf("Conversion of -1.1f to string: %s\n", to_string(1.1f));
    printf("Conversion of -2118295763 to string: %s\n", to_string(-2118295763));
    return 0;
}
I completely agree that if you need to rely on that sort of functionality, you really should use C++ instead. It is definitely not something that I'd like to use in a C program, but there are no serious caveats to its use either.

Note that the GNU C library uses similar constructs to provide certain common type-specific macros, and optimized cases for certain argument sizes (in memcpy() and memmove() for example).

Quote:
Originally Posted by Sergei Steshenko View Post
And "SSE2/SSE3-optimized" is at all out of "C" <-> C++ scope; I think if a compiler can produce a well optimized SIMD code for "C", there is no reason not produce the same well optimized code for C++.
I'm not relying the compiler to produce the SIMD code; I'm writing it myself, using explicit primitives that map pretty much 1:1 to the low-level instructions described here.

At this moment, C++ compilers can vectorize trivial operations quite well, C compilers less well. Neither can vectorize complex operations well (last I checked, at all).

I have not seen a compiler that can vectorize and interleave a complex operation, especially vectorizing a function that accesses multiple arrays in parallel (func(array1, array2, .. arrayN)); they only seem to be able to vectorize operations when a single primitive is applied to a consecutive array (vector) of arguments. The multiple array case is important to me, and interleaving the array data is NOT feasible, since it will cause a significant slowdown due to then necessary register shuffling. The code I write quite likely compiles fine using a C++ compiler, but it won't rely on any C++ features. All you'd get is the extra dependency on libstdc++.so (which tends to change every compiler version).

I repeat: I consider code that compiles with current C compilers to be C; therefore SSE2 and SSE3 built-in SIMD functions are in C for me.

If you insist on relying on some published standards, like C++11 and C99, without any compiler built-ins provided by most/all C compilers, then I guess C++11 is always superior.. I'd just like to point out that such a C compiler is pretty much useless for me in practice, since it cannot even compile the Linux kernel. (And no, GCC is not the only C compiler that can compile the Linux kernel. ICC has been used by some developers to compile fully working kernels, although I'm not sure if anyone does it at a regular basis.) In fact, that was the reason I originally migrated away from Red Hat on my workstation: Red Hat applied patches to gcc which caused it to be unable to produce a working kernel. They had to ship an older version for compiling the kernel, which I found very distasteful.
 
Old 05-24-2012, 07:41 PM   #42
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
Does the following match your requirements?
Code:
#include <stdio.h>
#include <errno.h>

#define to_string(item) \
        ( __builtin_types_compatible_p( typeof(item), long   ) ? to_string_long(item) : \
          __builtin_types_compatible_p( typeof(item), int    ) ? to_string_long((long)(item)) : \
          __builtin_types_compatible_p( typeof(item), double ) ? to_string_double(item) : \
          __builtin_types_compatible_p( typeof(item), float  ) ? to_string_double((double)(item)) : \
                                                                 to_string_fail() )

...
}


If you insist on relying on some published standards, like C++11 and C99, without any compiler built-ins provided by most/all C compilers, then I guess C++11 is always superior.. ...
Your code is not C99-compliant, so such a solution does not satisfy my requirements since I want to be standard-compliant.

If/when "C" standard committee accepts 'typeof' as standard, along with compile-time utilities to compare types, this will be a whole different story.
 
Old 05-24-2012, 09:24 PM   #43
hydraMax
Member
 
Registered: Jul 2010
Location: Skynet
Distribution: Debian + Emacs
Posts: 467
Blog Entries: 60

Rep: Reputation: 51
For me, C is more than a language, it is a system of related compilers, assemblers, build tools, interfaces, documentation, and operating system conventions. Whether it is writing a few lines of highly optimized code, a system application, or a full-fledged video game, I know how the whole process works, from code syntax and specifications, to library headers to documentation, and all the way to packaging final releases.

Sure, the scripting languages like Ruby have some syntactic sugar that makes a few things a little easier. But if you are willing to rely on libraries, there is little there you can't get in C without too much difficulty. For example, glib is filled with hundreds of convenience functions for various common tasks, e.g., string handling and regular expressions.

Furthermore, many of these convenience languages, like Python, end up coding a lot of their back-end libraries and drivers in C, either for better performance or easier system integration. That should tell you something.

Furthermore, if you use gcc and autotools, assembly integration is fairly easy. gcc has an asm keyword with lots of functionality and good integration. Furthermore, with autotools you can use conditional compiling to shunt in assembly source code files, while switching back to more generic code for architectures that you haven't written assembly for.

I'll avoid touching on the C vs. C++ debate, except to say that, so far, I haven't found C lacking for any of my needs. As for heavy OO programming, I'd probably give gobject a try before switching to C++.
 
Old 05-24-2012, 10:00 PM   #44
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,711
Blog Entries: 4

Rep: Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949Reputation: 3949
It's rather a "do I laugh, or cry?" experience to watch this thread diverging so wildly off-course ... talking about what is actually "fundamentally the same thing" as though it were, somehow, wildly different.

Trust me on this: once you get past the first stage of any compiler, pretty much every language that you can think of is exactly the same. Which is, technically speaking, why a compiler-suite such as gcc supports, in one single language system: C (gcc), C++ (g++), Objective-C (gobjc), Fortran (gfortran), Java (gcj), Ada (GNAT), and Go (gccgo), Pascal (gpc), Mercury, Modula-2, Modula-3, PL/I, D (gdc), and VHDL (ghdl), OpenMP.

The "differences" between the various languages are simply matters of human expression. Once the parsing is done away with, the intermediate ASTs and so-forth that actually drive the code-generation process are almost exactly the same.
 
2 members found this post helpful.
Old 05-24-2012, 10:33 PM   #45
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012

Rep: Reputation: 115Reputation: 115
Quote:
Trust me on this: once you get past the first stage of any compiler, pretty much every language that you can think of is exactly the same. Which is, technically speaking, why a compiler-suite such as gcc supports, in one single language system: C (gcc), C++ (g++), Objective-C (gobjc), Fortran (gfortran), Java (gcj), Ada (GNAT), and Go (gccgo), Pascal (gpc), Mercury, Modula-2, Modula-3, PL/I, D (gdc), and VHDL (ghdl), OpenMP.
This is technically true, but the argument in C vs. C++ is in how *much* stuff that first stage does. In C, it's hardly anything, but in C++ it's *Turing-complete*.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:09 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration