Printing Armstrong numbers from 1 to 500. (C Programming)
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
user@host:/tmp/armstrong$ gcc -msse4.1 -o a a.c
a.c: In function main:
a.c:20:14: error: incompatible type for argument 1 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:20:14: error: incompatible type for argument 2 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:21:14: error: incompatible type for argument 1 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:21:14: error: incompatible type for argument 2 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
user@host:/tmp/armstrong$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
AMD FX-8320
I looped over it 1000x from within C (not rerunning the program), not printing the results (I did print the results once and they were all correct) and got:
Code:
real 0m0.005s
user 0m0.001s
sys 0m0.001s
10000x:
Code:
real 0m0.005s
user 0m0.001s
sys 0m0.002s
100000x:
Code:
real 0m0.005s
user 0m0.001s
sys 0m0.001s
1000000x:
Code:
real 0m0.004s
user 0m0.001s
sys 0m0.001s
So basically the documentation is true, SSE commands are basically NOOPs.
This the 1,000,000 time code:
Code:
#include <stdio.h>
#include <smmintrin.h> // SSE 4.1
__m128i vcube(const __m128i v)
{
return _mm_mullo_epi32(v, _mm_mullo_epi32(v, v));
}
int main(int argc, const char * argv[]) {
for (unsigned int y = 0; y < 1000000; y++) {
for (unsigned int i = 1; i <= 500; i++) {
unsigned int firstDigit = i / 100;
unsigned int secondDigit = (i - firstDigit * 100) / 10;
unsigned int thirdDigit = (i - firstDigit * 100 - secondDigit * 10);
__m128i v = _mm_setr_epi32(0, firstDigit, secondDigit, thirdDigit);
__m128i v3 = vcube(v);
v3 = _mm_hadd_ps(v3,v3);
v3 = _mm_hadd_ps(v3,v3);
/* if (_mm_extract_epi32(v3, 0) == i)
printf ("%d is an Armstrong number\n", i);
*/
}
}
return 0;
}
user@host:/tmp/armstrong$ gcc -msse4.1 -o a a.c
a.c: In function main:
a.c:20:14: error: incompatible type for argument 1 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:20:14: error: incompatible type for argument 2 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:21:14: error: incompatible type for argument 1 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
a.c:21:14: error: incompatible type for argument 2 of _mm_hadd_ps
v3 = _mm_hadd_ps(v3,v3);
^
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/tmmintrin.h:31:0,
from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/smmintrin.h:32,
from a.c:2:
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/pmmintrin.h:56:1: note: expected __m128 but argument is of type __m128i
_mm_hadd_ps (__m128 __X, __m128 __Y)
^
user@host:/tmp/armstrong$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
AMD FX-8320
I don't really know... the one thing that sticks out is you have AMD and I know Intel's implementation is slightly different. Like I said this was my first attempt at SSE instructions so maybe someone else can help. But it certainly compiles file on my Mac:
I ran into some compilation problems in Solaris too. I was able to fix them and this printed out the correct answers... hopefully it'll work on your compiler:
Code:
#include <stdio.h>
#include <smmintrin.h> // SSE 4.1
__m128i vcube(const __m128i v)
{
return _mm_mullo_epi32(v, _mm_mullo_epi32(v, v));
}
int main(int argc, const char * argv[]) {
for (unsigned int i = 1; i <= 500; i++) {
unsigned int firstDigit = i / 100;
unsigned int secondDigit = (i - firstDigit * 100) / 10;
unsigned int thirdDigit = (i - firstDigit * 100 - secondDigit * 10);
__m128i v = _mm_setr_epi32(0, firstDigit, secondDigit, thirdDigit);
__m128 v3 = (__m128) vcube(v);
v3 = _mm_hadd_ps(v3, v3);
v3 = _mm_hadd_ps(v3, v3);
if (_mm_extract_epi32((__m128i) v3, 0) == i)
printf ("%d is an Armstrong number\n", i);
}
return 0;
}
normal sse4.1
compiled 0.85 14.91
gcc -O3 0.31 9.00
if I did not miss anything.
So you're saying it's a lot SLOWER on your machine? Hmm... can anyone else confirm that? I get much faster rates.
What type of processor do you have? Maybe it's emulating these instructions in software, not executing them directly in hardware. My computer shows them to be much faster...
I don't mean to make this a d**k measuring contest, but it's definitely interesting why you seemingly got so different speed measurements.
Yes, it looks like. I have no idea why. I have AMD FX-8320, it supports SSE4.1.
I have just tried to debug this and it looks like it used the real SSE, there was no emulation. But again, probably I missed something.
Yes, it looks like. I have no idea why. I have AMD FX-8320, it supports SSE4.1.
I have just tried to debug this and it looks like it used the real SSE, there was no emulation. But again, probably I missed something.
OK, well I have the Intel Core i7 2.3 GHz that came with the MacBook Pro (Retina, 15-inch, Late 2013). Maybe someone who knows more about this can shed some light on it.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.