I'm learning C by translating some of the things I have done in Python to C. I have tried to look online as much as I can before coming here but it seems really difficult to find answers to what I'm looking for.
What follows is my (so-far) translation of the Miller-Rabin test for a number's primality.
#include <stdio.h>
#include <math.h>
_Bool prime(long long n);
int main() {
int i = 6;
for (i; i < 9; i++) {
if (prime(i)) {
printf("%i\n", prime(i));
}
}
}
_Bool prime(long long n) {
int s = 0;
int r = 0;
int a_index = 0;
// printf("the value of a_index when initialised is: %d\n", a_index);
// printf("the value of s when initialised is: %d\n", s);
int *a_list;
_Bool is_prime = 1;
_Bool composite_part_a = 1;
_Bool composite_part_b = 1;
long long d = n - 1;
while (d % 2 == 0) {
s++;
d = d / 2;
}
if (4759123141 <= n && n < 2152302898747) {
// malloc
a_list[0] = 2;
a_list[1] = 3;
a_list[2] = 5;
a_list[3] = 7;
a_list[4] = 11;
}
else if (9080191 <= n && n < 4759123141) {
// malloc
a_list[0] = 2;
a_list[1] = 7;
a_list[2] = 61;
}
else if (1373653 <= n && n < 9080191) {
// malloc
a_list[0] = 31;
a_list[1] = 73;
}
else if (4 <= n && n < 1373653) {
a_list = (int *) malloc(sizeof(int) * 2);
a_list[0] = 2;
a_list[1] = 3;
printf("the value of a_list[0] upon its first assignment is: %d\n", a_list[0]);
// printf("the first element of a_list is: %d\n", a_list[0]);
// printf("the second element of a_list is: %d\n", a_list[1]);
}
else if (n == 3 | n == 2) {
return 1;
}
else if (n % 2 == 0 | n == 1) {
return 0;
}
printf("the value of a_list[0] over here is: %d\n", a_list[0]);
// printf("%d\n", a_list[1]);
for (a_index; a_index < sizeof(a_list) / sizeof(int); a_index++) {
printf("test");
if ((long long)pow(a_index[a_list], d) % n != 1) {
composite_part_a = 1;
}
else {
composite_part_a = 0;
}
// printf("the value of r is: %d\n", r);
// printf("the value of s is: %d\n", s);
for (r; r < s; r++) {
printf("%lld\n", (int)pow(a_list[a_index], exp2(r) * d) % n);
if ((long long)pow(a_index[a_list], exp2(r) * d) % n != -1) {
composite_part_b = 1;
}
else {
composite_part_b = 0;
break;
}
}
if (composite_part_a && composite_part_b) {
return 0;
}
}
return is_prime;
}
The trouble with learning C is there isn't much good literature for pure beginners, outside of what I hear about K&R but that's in the mail and I can't get my hands on it right now. The program returns these errors:
3.c: In function ‘prime’:
3.c:52:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
/tmp/ccGQnk9T.o: In function `prime':
3.c:(.text+0x272): undefined reference to `pow'
3.c:(.text+0x2b9): undefined reference to `exp2'
3.c:(.text+0x2db): undefined reference to `pow'
3.c:(.text+0x30b): undefined reference to `exp2'
3.c:(.text+0x32d): undefined reference to `pow'
collect2: ld returned 1 exit status
First off, haven't I included to introduce pow and else? I know it's not proper to ask two questions and my main question is about pow and exp2, but if you do have a suggestion about the malloc as well feel free to include it.
You need to link with the math library as well, it's not included by default.
Something like the following command:
$ gcc 3.c -lm
Notice the -lm argument... It tells the linker to add a library (the -l part) and the name of the library (the m part).
Math functions are part of libm. Link them when you compile with -lm.
3.c:52:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
Is caused by a missing include, malloc() is defined in stdlib.h so need to include that.
3.c:(.text+0x272): undefined reference to `pow' (and the rest)
Is caused by a missing link to libm. Most (if not all) methods in math.h are not in standard libc that always gets linked but in libm instead.
How to link differs between compiler, but for gcc (and many other unix compilers):
gcc 3.c -o 3 -lm
Where "-lm" tells gcc to link libm.
You need to include <stdlib.h> for malloc and free.
For the math stuff to work you have to link it,
gcc 3.c -lm
Where -l is the library flag and m is tell it to use the math library
Also you need to move the definition of prime to above main, things need to be declared in order.
Since you are just starting here are some other helpful flags for the compiler
-g this will give better debugging when using valgrind or gdb.
-o lets you define the compiled file name eg: gcc 3.c -o 3 will create ./3 instead of ./a.out
Related
To vectorize the following mathematical expression (linear recursion):
f(i)=f(i-1)/c+g(i), i starts at 1, f(0), c are constant numbers and given.
I can get better speed by using list-comprehension, that is:
def function():
txt= [0,2,0,2,0,2,0,2,2,2,0,2,2,2,0,2,0,2,2,2,0,2,0,2,0,2,0,2,2,2,0,2,0,2,0,2,0,2,2,2]
indices_0=[]
vl=0
sb_l=10
CONST=512
[vl := vl+pow(txt[i],(i+1)) for i in range(sb_l)]
if (vl==1876):
indices_0=[0]
p=[i for i in range(1,len(txt)-sb_l+1) if (vl := (vl-txt[i-1])/2+ txt[i+sb_l-1]*CONST)==1876]
print(indices_0+p)
function()
I am looking for a vectorized/faster than vectorization (if possible!) implementation of the above code in python/c.
Note:
1.
A linear recursive function is a function that only makes a single call to itself each time the function runs (as opposed to one that would call itself multiple times during its execution). The factorial function is a good example of linear recursion.
2.
Note that all variables array are given for demonstration purpose, the main part for vectorization is :
[vl := vl+pow(txt[i],(i+1)) for i in range(sb_l)]
if (vl==1876):
indices_0=[0]
p=[i for i in range(1,len(txt)-sb_l+1)
if (vl := (vl-txt[i-1])/2+ txt[i+sb_l-1]*CONST)==1876]
Here, f(i-1)= (vl-txt[i-1]), c=2, g(i)= txt[i+sb_l-1]*CONST.
POSTSCRIPT: I am currently doing it in python, would it be much faster if it is implemented in C language's vectorization?
Here is an example of equivalent C program doing the same thing but faster:
#include <stdio.h>
#include <stdlib.h>
// See: https://stackoverflow.com/questions/29787310/does-pow-work-for-int-data-type-in-c
int64_t int_pow(int64_t base, int exp)
{
int64_t result = 1;
while (exp)
{
// Branchless optimization: result *= base * (exp % 2);
if(exp % 2)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
void function()
{
// Both txt values and sb_l not be too big or it will cause silent overflows (ie. wrong results)
const int64_t txt[] = {0,2,0,2,0,2,0,2,2,2,0,2,2,2,0,2,0,2,2,2,0,2,0,2,0,2,0,2,2,2,0,2,0,2,0,2,0,2,2,2};
const size_t txtSize = sizeof(txt) / sizeof(txt[0]);
const int sb_l = 10;
const int64_t CONST = 512;
int64_t vl = 0;
int64_t* results = (int64_t*)malloc(txtSize * sizeof(int64_t));
size_t cur = 0;
// Optimization so not to compute pow(0,i+1) which is 0
for (int i = 0; i < sb_l; ++i)
if(txt[i] != 0)
vl += int_pow(txt[i], i+1);
if (vl == 1876)
{
results[cur] = 0;
cur++;
}
for (int i = 1; i < txtSize-sb_l+1; ++i)
{
vl = (vl - txt[i-1]) / 2 + txt[i+sb_l-1] * CONST;
if(vl == 1876)
results[cur++] = i;
}
// Printing
printf("[");
for (int i = 0; i < cur; ++i)
{
if(i > 0)
printf(", ");
printf("%ld", results[i]);
}
printf("]\n");
fflush(stdout);
free(results);
}
int main(int argc, char* argv[])
{
function();
return 0;
}
Be careful with overflows. You can put assertions if you are unsure about that in specific places (note they make the code slower when enabled though). Please do not forget to compile the program with optimizations (eg. -O3 with GCC and Clang and /O2 with MSVC).
I have this program. When I run in on gcc using gcc egyptionFractions.c -o egypt -Wall -std=c11, it works great! However, I am trying to run it using llvm on a server and I continually get this error:
* Error in `/home/codewarrior/solution': malloc(): memory corruption (fast): 0x0000000000fb8620 *
The program uses malloc and realloc several times, but I can't find the issue. I think maybe a null string end may run off the memory, but when I increase the allocation size, my answers go off track...
The function is given two numbers, like "3" and "4". It decomposes the fraction in a greedy mannor like "1/2 + 1/4". You can see the sample input and output at the bottom.
I really appreciate your help. Again, it runs perfectly on gcc. :) And I don't have an llvm compiler.. I looked through some of the other threads concerning similar issues and haven't found an acceptable solution.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char* decompose(char* nrStr, char* drStr) {
long long num = atof(nrStr);
long long den = atof(drStr);
double val = 1.0 * num / den;
int curr_den = 2, curr_pos = 0;
char * ans = malloc(1);
ans[0] = 0;
char denStr[50] = {0};
if (val > 1)
{
sprintf(denStr, "%lld,", num/den);
num -= (int)val * den;
ans = realloc(ans, curr_pos += strlen(denStr) );
strcat(ans, denStr);
}
printf("strlen: %d\n", (int)strlen(denStr));
while (num > 0)
{
if (1.0*num/den >= 1.0/curr_den)
{
num *= curr_den;
if (num >= den)
{
num -= den;
sprintf(denStr, "1/%d,", curr_den);
ans = realloc(ans, curr_pos += strlen(denStr) );
printf("strlen: %d\n", (int)strlen(denStr));
strcat(ans, denStr);
}
den *= curr_den;
}
curr_den++;
}
ans[curr_pos-1] = '\0';
return ans;
}
void dotest(char* u, char* v, char* expr) {
char* sact = decompose(u, v);
if(strcmp(sact, expr) != 0)
printf("Error. Expected %s but got %s\n", expr, sact);
printf("%s\n%s\n\n", sact, expr);
free(sact); sact = NULL;
}
int main () {
dotest("3", "4", "1/2,1/4");
dotest("12","4", "3");
dotest("4","5", "1/2,1/4,1/20");
dotest("66","100", "1/2,1/7,1/59,1/5163,1/53307975");
dotest("22","23", "1/2,1/3,1/9,1/83,1/34362");
//dotest("99","101", "1/2,1/3,1/7,1/250,1/132563");
return 0;
}
The solution is... after I decoupled these two statements, then add 1 to allocation..
curr_pos += strlen(denStr);
ans = realloc(ans, curr_pos+1 );
I was doing this:
ans = realloc(ans, curr_pos += strlen(denStr)+1 );
Which broke things! I post on here and then the answer comes too quick. Sorry if I wasted anyone's time!
I've been working through SICP and tried my hand at creating a LISP interprater. I keep getting the following warnings:
$ make littleLisp
cc littleLisp.c -o littleLisp
littleLisp.c:309:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
1 warning generated.
$ make littleLisp
make: `littleLisp' is up to date.
$ ./littleLisp
warning: this program uses gets(), which is unsafe.
5.000000
I'm not quite sure what this is referring to as my main method is returning 0. Is my "in.lisp" file not being called properly?
Here is the code:
https://gist.github.com/rahul1346/8596118b834ecf41b1d9
Any ideas?
Also, what are your thoughts on the interperater itself?
Here is the fxn ending on 309:
long interpret_list(long scope, long first, long last) {
parent[first] = scope;
// printf("interpret_list %d %d %d\n", scope, first, last);
long i, j, brace;
if (last>=first && in_special(first)) {
// puts("OK");
special(scope, first, last);
} else {
child_count[scope] = 0;
i = j = first; brace = 0;
while ( i <= last) {
if (!strcmp(seg[i], "(")) brace++;
if (!strcmp(seg[i], ")")) brace--;
if (brace == 0) {
interpret(scope, j, i);
child[scope][child_count[scope]++] = j;
j = i + 1;
}
i++;
}
if (brace) {
// puts("Format error!!");
exit(2);
}
if (is_function(seg[first])) {
apply_function(seg[first], scope);
} else {
return scope;
}
}
}
There are two ways your function can fall off the end without returning:
When last>=first && in_special(first) is true.
When is_function(seg[first]) is true.
I wrote a program that receive from user a series of numbers (<=20) while the last '0' means end of series (not included in series storing).
2 arrays (x,y) size 20 (0-19 + 1 for the '0') must be zeros, and m means number of organs in Y array.
The user must enter numbers ascending (it is ok 4ex. 1,2,2,3,7,8,...,0) and end with a '0' of course, if not, appropriate error message will appear, and program will shut off.
We can be sure the user will keep the <=20 numbers of input.
Y array will be (if everything went ok with X array) a sorted array of X but without duplicates.
'm' will be number of organs in Y exclude '0' of course.
Function SIFT must only organize the Y array for being printed from main().
Example:
If user will store in X: 1,1,2,3,5,5,5,6
On screen will be: m = 5 Y = 1,2,3,5,6
My tryout:
#include <stdio.h>
#include <string.h>
void SIFT(int x_arr[ ], int y_arr[]);
int main ()
{
int x[20] = {0} , y[20] = {0};
int m=0,temp=0,curr=0,i=0,j=0;
printf("Please enter your numbers now:\n\n");
/*enter numbers one by one. if x[i+1] value < x[i] value, err msg.
when user want to end the series he must enter '0' which means end of string (it wont included in x[]) */
while ( ( temp = getchar() ) != '0' )
{
if (temp >= curr)
{
x[i] = temp;
curr = temp;
i++;
}
else
{
printf("The numbers are not at the right order !\n\nProgram will now terminate...\n\n");
}
}
SIFT(x,y);
for (i=0 ; y[i]=='0' ; i++) /*strlen(y) without ('0')'s includes*/
m++;
/*Prints m , y's organs*/
printf("\n\nm = %d",m);
printf("Y = ");
while (y[j]!='0')
{
printf ("%d ,",y[j]);
j++;
}
void SIFT(int x_arr[ ], int y_arr[])
{
int i=0,j=0;
while (x_arr[i] != '0')
{
if (x_arr[i] == x_arr[i+1]) /*if current val. equals next val. -> jump dbl at x_arr*/
{
y_arr[j] = x_arr[i];
i+=2;
j++;
}
else
{
y_arr[j]=x_arr[i];
i++;
j++;
}
}
}
return 0;
}
The error I'm getting from the gcc is:
gcc -g -ansi -pedantic -Wall 2.c -o 2
2.c: In function ‘main’:
2.c:43: warning: ISO C forbids nested functions
2.c:43: warning: ISO C90 forbids mixed declarations and code
/tmp/ccyZNfkF.o: In function `main':
/home/student/Desktop/2/2.c:29: undefined reference to `SIFT'
collect2: ld returned 1 exit status
make: *** [2] Error 1
And another question:
I would like to convert this code to the MIPS Assembly code, is there a short and fast way to do so ?
Thanks all you guys !!
You didn't close main function before declaration of SIFT, so SIFT is declared inside of main which is forbidden.
Fix it by returning from main before the definition of SIFT():
...
return 0;
}
void SIFT(int x_arr[ ], int y_arr[])
{
int i=0,j=0;
...
I'm writing my first program in C for a class; I've managed to even out most of the syntax errors, but I'm getting a strange error when gcc tries to link the object files together. It prints exactly like below:
gcc -o proj04.support.o proj04.driver.o
Undefined first referenced
symbol in file
convert proj04.driver.o
I've looked around for a few answers, but none really make sense to me. I'll post the files I'm using to make the program below, and if you've got the answer I would really appreciate the help. It seems to be a pretty basic error, so it's probably something silly I didn't do.
Makefile (posting this first because I suspect the issue is here)
# Comments
# Comments
proj04: proj04.support.o proj04.driver.o
gcc -o proj04.support.o proj04.driver.o
proj04.support.o: proj04.support.c
gcc -Wall -c proj04.support.c
proj04.driver.o: proj04.driver.c
gcc -Wall -c proj04.driver.c
Header file (provided by the professor, unchangeable, one line long):
int convert( int, unsigned, char[], int )
Implementation file
#include <stdio.h>
#include "/user/cse320/Projects/project04.support.h"
#include <string.h>
void formatdisplay( char[], int );
int convert( int I, unsigned base, char result[], int display )
{
int quotient, dividend, remainder;
const int divisor = base;
int count = 0;
char ending[] = " base ";
dividend = I;
remainder = 0;
quotient = 1;
while (quotient != 0)
{
if (count <= strlen(result))
{
quotient = (dividend / divisor);
remainder = (dividend % divisor);
//convert to ascii char
result[count] = remainder;
count++;
}
}
formatdisplay ( result, display );
strrev(result);
if ( I >= 0 ) { result[0] = '+'; }
if ( I < 0 ) { result[0] = '-'; }
printf( "%s" , strcat (result, ending));
}
void formatdisplay ( char str[], int disp )
{
if ( disp < 0 )
{
unsigned i = 0;
for ( i; i < strlen(str)-1; i++)
{
if ( str[i] = '\0') { str[i] = '0'; }
}
}
if ( disp >= 0 )
{
unsigned i = 0;
for ( i; i < strlen(str)-1; i++)
{
if ( str[i] = '\0') { str[i] = ' '; }
}
}
}
Driver file (not really implemented yet)
#include <stdio.h>
#include "/user/cse320/Projects/project04.support.h"
int main () {
char Result1[32];
int T = convert(10, 2, Result1, 1);
}
Yes, the problem is probably in the Makefile:
proj04: proj04.support.o proj04.driver.o
gcc -o proj04.support.o proj04.driver.o
The -o option to gcc takes an argument, the output filename. So this is asking gcc to link the file proj04.driver.o, producing an output file of proj04.support.o.
gcc -o proj04 proj04.support.o proj04.driver.o should work better.
I had the almost the same problem.
Undefined first referenced symbol in file isThreeOfAKind /var/tmp//ccIQWbaj.o
My problem was that I had missed on a letter in one of my functions, so the declaration and the function misaligned. Ex:
void isThreeOfAKind (void);
void isThreeOfAkind {}
Missed the uppercase K, and wrote lowercase k instead.
After I changed the k to a uppercase K it compiled fine.
I dont know if it helps, but it could be something as easy as that.
I am no expert but as Andreas Joensson (who, judging by function name is writing the exact same program I am) says above this problem seems to occur when there's some mismatch between declaration and use of a function.
Your function convert is declared as returning an int but I find no return value. That might be the problem.