How does one link with the SoftFloat library? - c

I am designing hardware to do floating point arithmetic in compliance with the IEEE-754 standard. SoftFloat is a library (written by John Hauser - UC Berkeley) which is a reference model (in C++) of IEEE-754 floating point behavior. It implements functions to do all the floating point computations specified by the standard. I want to use SoftFloat to generate test cases for my hardware implementation. The link for the author's page is http://www.jhauser.us/arithmetic/SoftFloat.html.
I downloaded the zip file from the link on that page (http://www.jhauser.us/arithmetic/SoftFloat-3e.zip), unzipped it, and used to provided Makefile to build it. I am running under bash on Windows10. At the end of the build process, I end up with an archive "softfloat.a".
One of the functions which SoftFloat implements is fused floating-point multiply-add. Per the documentation, this can be invoked by calling the function f32_mulAdd, and a template for it is in the provided header file softfloat.h.
In my main code (sf.cc), I include that header, define arguments to that function using types defined in the same header, and build the code with:
gcc -o sf -I. sf.cc softfloat.a
This gives the following error:
/tmp/ccALxpC8.o: In function `main':
sf.cc:(.text+0x4f): undefined reference to `f32_mulAdd(float32_t, float32_t, float32_t)'
collect2: error: ld returned 1 exit status
f32_mulAdd IS defined in softfloat.h (I checked), and the archive file softfloat.a DOES contain f32_mulAdd.o (checked with ar -t softfloat.a) and f32_mulAdd.c in the SoftFloat source code DOES define the function (as "float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c)") and my call to that function is consistent with the definition, so I don't understand why I get this message. If anyone has used SoftFloat please chime in.
The source code in which I call the SoftFloat function f32_mulAdd is as follows (I want to get this to compile/link cleanly first, then I will add statements to initialize the variables multiplier, multiplicand and addend to specific values):
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
#include "softfloat_types.h"
int float_rounding_mode = 0;
int main()
{
uint8_t rounding_mode;
uint8_t exceptions;
uint32_t multiplier, multiplicand, addend, result;
float32_t f_multiplier, f_multiplicand, f_addend, f_result;
f_multiplier.v = multiplier;
f_multiplicand.v = multiplicand;
f_addend.v = addend;
softfloat_roundingMode = rounding_mode;
softfloat_exceptionFlags = 0;
softfloat_detectTininess = softfloat_tininess_beforeRounding;
f_result = f32_mulAdd(f_multiplier, f_multiplicand, f_addend);
result = f_result.v;
exceptions = softfloat_exceptionFlags & 0x1f;
return 0;
}

The key is to change the header file inclusion to:
extern "C" {
#include "softfloat.h"
}
Also, softfloat.h was the only header file required.

There is no need to use a softfloat library.
The GCC compiler already have a floating point implementation.
For-eg - You can just do a A + B on float types and you should get the result.
You can also control the rounding mode using std::fesetround() and get the exceptions by using.

Related

In c programming language, i keep getting this error [duplicate]

Just a simple program, but I keep getting this compiler error. I'm using MinGW for the compiler.
Here's the header file, point.h:
//type for a Cartesian point
typedef struct {
double x;
double y;
} Point;
Point create(double x, double y);
Point midpoint(Point p, Point q);
And here's point.c:
//This is the implementation of the point type
#include "point.h"
int main() {
return 0;
}
Point create(double x, double y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Point midpoint(Point p, Point q) {
Point mid;
mid.x = (p.x + q.x) / 2;
mid.y = (p.y + q.y) / 2;
return mid;
}
And here's where the compiler issue comes in. I keep getting:
testpoint.c: undefined reference to 'create(double x, double y)'
While it is defined in point.c.
This is a separate file called testpoint.c:
#include "point.h"
#include <assert.h>
#include <stdio.h>
int main() {
double x = 1;
double y = 1;
Point p = create(x, y);
assert(p.x == 1);
return 0;
}
I'm at a loss as to what the issue could be.
How are you doing the compiling and linking? You'll need to specify both files, something like:
gcc testpoint.c point.c
...so that it knows to link the functions from both together. With the code as it's written right now, however, you'll then run into the opposite problem: multiple definitions of main. You'll need/want to eliminate one (undoubtedly the one in point.c).
In a larger program, you typically compile and link separately to avoid re-compiling anything that hasn't changed. You normally specify what needs to be done via a makefile, and use make to do the work. In this case you'd have something like this:
OBJS=testpoint.o point.o
testpoint.exe: $(OBJS)
gcc $(OJBS)
The first is just a macro for the names of the object files. You get it expanded with $(OBJS). The second is a rule to tell make 1) that the executable depends on the object files, and 2) telling it how to create the executable when/if it's out of date compared to an object file.
Most versions of make (including the one in MinGW I'm pretty sure) have a built-in "implicit rule" to tell them how to create an object file from a C source file. It normally looks roughly like this:
.c.o:
$(CC) -c $(CFLAGS) $<
This assumes the name of the C compiler is in a macro named CC (implicitly defined like CC=gcc) and allows you to specify any flags you care about in a macro named CFLAGS (e.g., CFLAGS=-O3 to turn on optimization) and $< is a special macro that expands to the name of the source file.
You typically store this in a file named Makefile, and to build your program, you just type make at the command line. It implicitly looks for a file named Makefile, and runs whatever rules it contains.
The good point of this is that make automatically looks at the timestamps on the files, so it will only re-compile the files that have changed since the last time you compiled them (i.e., files where the ".c" file has a more recent time-stamp than the matching ".o" file).
Also note that 1) there are lots of variations in how to use make when it comes to large projects, and 2) there are also lots of alternatives to make. I've only hit on the bare minimum of high points here.
I had this issue recently. In my case, I had my IDE set to choose which compiler (C or C++) to use on each file according to its extension, and I was trying to call a C function (i.e. from a .c file) from C++ code.
The .h file for the C function wasn't wrapped in this sort of guard:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
I could've added that, but I didn't want to modify it, so I just included it in my C++ file like so:
extern "C" {
#include "legacy_C_header.h"
}
(Hat tip to UncaAlby for his clear explanation of the effect of extern "C".)
I think the problem is that when you're trying to compile testpoint.c, it includes point.h but it doesn't know about point.c. Since point.c has the definition for create, not having point.c will cause the compilation to fail.
I'm not familiar with MinGW, but you need to tell the compiler to look for point.c. For example with gcc you might do this:
gcc point.c testpoint.c
As others have pointed out, you also need to remove one of your main functions, since you can only have one.
Add the "extern" keyword to the function definitions in point.h
I saw here that this question
In c programming language, i keep getting this error
has been answered here so the thread seems closed for answers.
I disagree. It is different code.
The answer should be that we don't know what is in custom header file "functions.h".
Also, we don't know what are
MAPA m;
POSICAO heroi;
Are these functions, constants?
If these were some constants, one should expect #define in front of them, and no semicolon e.g.
#define MAPA m
#define POSICAO heroi
If You intended to prototype the function, since there's is semicolon behing, than You did not insert the parentheses ().
In that case MAPA and POSICAO are some custom-type functions, whose content should be determined in "Functions.h"
Also, there's a possibilty that You wanted to import the functions or variable or constant from some other directory, and in that case You're missing the word
extern MAPA m;
I had a similar problem running a bunch of .c files in a directory all linking to one header file with custom function prototypes.
I ran:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c
Getting these errors:
/usr/bin/ld: /tmp/ccovH4zH.o: in function `_puts': 3-puts.c:(.text+0x2f): undefined reference to `_putchar'
/usr/bin/ld: 3-puts.c:(.text+0x51): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o: in function `main': _putchar.c:(.text+0xe): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x18): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x22): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o:_putchar.c:(.text+0x2c): more undefined references to `_putchar' follow
collect2: error: ld returned 1 exit status
Note: All files were linked to the same header file with all the function declarations.
I manage to compile successfully after adding -c option to the gcc compiler like:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 -c *.c
This run successfully.
Just in case anyone comes across the same.

VS Code shows error in cs50.h header file downloaded from GitHub [duplicate]

Just a simple program, but I keep getting this compiler error. I'm using MinGW for the compiler.
Here's the header file, point.h:
//type for a Cartesian point
typedef struct {
double x;
double y;
} Point;
Point create(double x, double y);
Point midpoint(Point p, Point q);
And here's point.c:
//This is the implementation of the point type
#include "point.h"
int main() {
return 0;
}
Point create(double x, double y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Point midpoint(Point p, Point q) {
Point mid;
mid.x = (p.x + q.x) / 2;
mid.y = (p.y + q.y) / 2;
return mid;
}
And here's where the compiler issue comes in. I keep getting:
testpoint.c: undefined reference to 'create(double x, double y)'
While it is defined in point.c.
This is a separate file called testpoint.c:
#include "point.h"
#include <assert.h>
#include <stdio.h>
int main() {
double x = 1;
double y = 1;
Point p = create(x, y);
assert(p.x == 1);
return 0;
}
I'm at a loss as to what the issue could be.
How are you doing the compiling and linking? You'll need to specify both files, something like:
gcc testpoint.c point.c
...so that it knows to link the functions from both together. With the code as it's written right now, however, you'll then run into the opposite problem: multiple definitions of main. You'll need/want to eliminate one (undoubtedly the one in point.c).
In a larger program, you typically compile and link separately to avoid re-compiling anything that hasn't changed. You normally specify what needs to be done via a makefile, and use make to do the work. In this case you'd have something like this:
OBJS=testpoint.o point.o
testpoint.exe: $(OBJS)
gcc $(OJBS)
The first is just a macro for the names of the object files. You get it expanded with $(OBJS). The second is a rule to tell make 1) that the executable depends on the object files, and 2) telling it how to create the executable when/if it's out of date compared to an object file.
Most versions of make (including the one in MinGW I'm pretty sure) have a built-in "implicit rule" to tell them how to create an object file from a C source file. It normally looks roughly like this:
.c.o:
$(CC) -c $(CFLAGS) $<
This assumes the name of the C compiler is in a macro named CC (implicitly defined like CC=gcc) and allows you to specify any flags you care about in a macro named CFLAGS (e.g., CFLAGS=-O3 to turn on optimization) and $< is a special macro that expands to the name of the source file.
You typically store this in a file named Makefile, and to build your program, you just type make at the command line. It implicitly looks for a file named Makefile, and runs whatever rules it contains.
The good point of this is that make automatically looks at the timestamps on the files, so it will only re-compile the files that have changed since the last time you compiled them (i.e., files where the ".c" file has a more recent time-stamp than the matching ".o" file).
Also note that 1) there are lots of variations in how to use make when it comes to large projects, and 2) there are also lots of alternatives to make. I've only hit on the bare minimum of high points here.
I had this issue recently. In my case, I had my IDE set to choose which compiler (C or C++) to use on each file according to its extension, and I was trying to call a C function (i.e. from a .c file) from C++ code.
The .h file for the C function wasn't wrapped in this sort of guard:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
I could've added that, but I didn't want to modify it, so I just included it in my C++ file like so:
extern "C" {
#include "legacy_C_header.h"
}
(Hat tip to UncaAlby for his clear explanation of the effect of extern "C".)
I think the problem is that when you're trying to compile testpoint.c, it includes point.h but it doesn't know about point.c. Since point.c has the definition for create, not having point.c will cause the compilation to fail.
I'm not familiar with MinGW, but you need to tell the compiler to look for point.c. For example with gcc you might do this:
gcc point.c testpoint.c
As others have pointed out, you also need to remove one of your main functions, since you can only have one.
Add the "extern" keyword to the function definitions in point.h
I saw here that this question
In c programming language, i keep getting this error
has been answered here so the thread seems closed for answers.
I disagree. It is different code.
The answer should be that we don't know what is in custom header file "functions.h".
Also, we don't know what are
MAPA m;
POSICAO heroi;
Are these functions, constants?
If these were some constants, one should expect #define in front of them, and no semicolon e.g.
#define MAPA m
#define POSICAO heroi
If You intended to prototype the function, since there's is semicolon behing, than You did not insert the parentheses ().
In that case MAPA and POSICAO are some custom-type functions, whose content should be determined in "Functions.h"
Also, there's a possibilty that You wanted to import the functions or variable or constant from some other directory, and in that case You're missing the word
extern MAPA m;
I had a similar problem running a bunch of .c files in a directory all linking to one header file with custom function prototypes.
I ran:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c
Getting these errors:
/usr/bin/ld: /tmp/ccovH4zH.o: in function `_puts': 3-puts.c:(.text+0x2f): undefined reference to `_putchar'
/usr/bin/ld: 3-puts.c:(.text+0x51): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o: in function `main': _putchar.c:(.text+0xe): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x18): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x22): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o:_putchar.c:(.text+0x2c): more undefined references to `_putchar' follow
collect2: error: ld returned 1 exit status
Note: All files were linked to the same header file with all the function declarations.
I manage to compile successfully after adding -c option to the gcc compiler like:
$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 -c *.c
This run successfully.
Just in case anyone comes across the same.

Matlab error compiling C files with mex

i'm trying to compile a program for image deblurring.
I try to run
mex apply_blur_kernel_mex.c
where the file apply_blur_kernel_mex.c have the following code
#include <mex.h>
#include <stdlib.h>
#include <math.h>
#include <matrix.h>
#include "ow_homography.h"
...
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
...
compute_homography_matrix(Ksharp, &theta_list[k*3], invKblurry, H);
...
}
The problem is in the function compute_homography_matrix that is in another file ow_homography.h
#ifndef OW_HOMOGRAPHY_H
#define OW_HOMOGRAPHY_H
#include "ow_mat3.h"
INLINE void compute_homography_matrix(const double *Ksharp, const double *theta, const double *invKblurry, double *H) {
double R[9];
/* Compute homography */
cp3(invKblurry,H);
rot3(theta[0],theta[1],theta[2],R);
mmip3(R,H);
mmip3(Ksharp,H);
}
This last operations (cp3, rot3...) are in another file ow_mat3.h that contains all the operations for the program.
So when i try to call
mex apply_blur_kernel_mex.c
i have the following problem:
Error using mex
Undefined symbols for architecture x86_64:
"_compute_homography_matrix", referenced from:
mexFunction in apply_blur_kernel_mex.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any suggestions to solve this problem?
Thank you all.
http://clang.llvm.org/compatibility.html#inline
C compatibility C99 inline functions
By default, Clang builds C code in GNU C11 mode, so it uses standard
C99 semantics for the inline keyword. These semantics are different
from those in GNU C89 mode, which is the default mode in versions of
GCC prior to 5.0. For example, consider the following code:
inline int add(int i, int j) { return i + j; }
int main() { int i = add(4, 5); return i; }
In C99, inline means that a function's definition is provided only for
inlining, and that there is another definition (without inline)
somewhere else in the program. That means that this program is
incomplete, because if add isn't inlined (for example, when compiling
without optimization), then main will have an unresolved reference to
that other definition. Therefore we'll get a (correct) link-time error
like this:
Undefined symbols: "_add", referenced from:
_main in cc-y1jXIr.o
By contrast, GNU C89 mode (used by default in older versions of GCC)
is the C89 standard plus a lot of extensions. C89 doesn't have an
inline keyword, but GCC recognizes it as an extension and just treats
it as a hint to the optimizer.
There are several ways to fix this problem:
1) Change add to a static inline function. This is usually the right solution if only one translation unit needs to use the function.
static inline functions are always resolved within the translation
unit, so you won't have to add a non-inline definition of the function
elsewhere in your program.
2) Remove the inline keyword from this definition of add. The inline keyword is not required for a function to be inlined, nor does it
guarantee that it will be. Some compilers ignore it completely. Clang
treats it as a mild suggestion from the programmer.
3) Provide an external (non-inline) definition of add somewhere else in your program. The two definitions must be equivalent!
4)Compile in the GNU C89 dialect by adding -std=gnu89 to the set of Clang options. This option is only recommended if the program source
cannot be changed or if the program also relies on additional
C89-specific behavior that cannot be changed.
All of this only applies to C code; the meaning of inline in C++ is
very different from its meaning in either GNU89 or C99.

Compile a program using mhash

I am trying to use lessfs and learning how it uses mhash to produce its cryptographic fingerprints, so I am taking a look at mhash to see how it handles the hashing algorithms, so I am trying to run some of the examples provided in the program, but I am running into complications and errors
The Mhash example that I was trying to solve is found here: http://mhash.sourceforge.net/mhash.3.html (or below)
#include <mhash.h>
#include <stdio.h>
int main()
{
char password[] = "Jefe";
int keylen = 4;
char data[] = "what do ya want for nothing?";
int datalen = 28;
MHASH td;
unsigned char *mac;
int j;
td = mhash_hmac_init(MHASH_MD5, password, keylen,
mhash_get_hash_pblock(MHASH_MD5));
mhash(td, data, datalen);
mac = mhash_hmac_end(td);
/*
* The output should be 0x750c783e6ab0b503eaa86e310a5db738
* according to RFC 2104.
*/
printf("0x");
for (j = 0; j < mhash_get_block_size(MHASH_MD5); j++) {
printf("%.2x", mac[j]);
}
printf("\n");
exit(0);
}
But I get the following errors:
mhash.c.text+0x6c): undefined reference to `mhash_get_hash_pblock'
mhash.c.text+0x82): undefined reference to `mhash_hmac_init'
mhash.c.text+0x9c): undefined reference to `mhash'
mhash.c.text+0xa8): undefined reference to `mhash_hmac_end'
mhash.c.text+0xf9): undefined reference to `mhash_get_block_size'
collect2: error: ld returned 1 exit status
This is a linker error — ld is the linker program on Unix systems. The linker is complaining because you're using library functions (mhash_get_hash_pblock, etc.) but you didn't provide a definition for them.
The preprocessor directive #include <mhash.h> declares functions (and types, etc.) from the mhash library. That's good enough to compile your program (produce a .o file) but not to link it (to produce an executable): you also need to define these functions.
Add -lmhash at the end of your compilation command line. This instructs the linker that it can look for functions in the library libmhash.a on its search path; at run time, the functions will be loaded from libmhash.so on the search path. Note that libraries must come on the command line after they're used: the linker builds up a link of required functions, which need to be provided by a subsequent argument.
gcc -o myprogram myprogram.c -lmhash

No warning from gcc when function definition in linked source different from function prototype in header

I had a problem with a part of my code, which after some iterations seemed to read NaN as value of a double of a struct. I think I found the error, but am still wondering why gcc (version 3.2.3 on a embedded Linux with busybox) did not warn me. Here are the important parts of the code:
A c file and its header for functions to acquire data over USB:
// usb_control.h
typedef struct{
double mean;
short *values;
} DATA_POINTS;
typedef struct{
int size;
DATA_POINTS *channel1;
//....7 more channels
} DATA_STRUCT;
DATA_STRUCT *create_data_struct(int N); // N values per channel
int free_data_struct(DATA_STRUCT *data);
int aqcu_data(DATA_STRUCT *data, int N);
A c and header file with helper function (math, bitshift,etc...):
// helper.h
int mean(DATA_STRUCT *data);
// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
// sum in for loop
data->channel1->mean = sum/data->N;
// ...7 more channels
// a printf here displayed the mean values corretly
}
The main file
// main.c
#include "helper.h"
#include "usb_control.h"
// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);
// get data for different delays
for (delay = 0; delay < 500; delay += pw){
acqu_data(data, N);
mean(data);
printf("%.2f",data->channel1->mean); // done for all 8 channels
// printf of the mean values first is correct. Than after 5 iterations
// it is always NaN for channel1. The other channels are displayed correctly;
}
There were no segfaults nor any other missbehavior, just the NaN for channel1 in the main file.
After finding the error, which was not easy, it was of course east to fix. The return type of mean(){} was wrong in the definition. Instead of double mean() it has to be int mean() as the prototype defines. When all the functions are put into one file, gcc warns me that there is a redefinition of the function mean(). But as I compile each c file seperately and link them afterwards gcc seems to miss that.
So my questions would be. Why didn't I get any warnings, even non with gcc -Wall? Or is there still another error hidden which is just not causing problems now?
Regards,
christian
When each .c file is compiled separately, the only information the compiler knows is the function prototype you have given.
Because every file is compiled separately, there is no way the compiler process of main.c knows the definition of mean in helper.c is wrong.
After the .c file is compiled, the signature will be stripped, so the linker cannot know the mean is wrong either.
A simple fix is always include the interface .h file in the implementation .c file
// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);
Then the compiler process of helper.c will notice that inconsistent type and warn you.
A mean usually is a real value so double is ok. Here you define mean as returning double, but the prototype says int mean(...).
The only way gcc can be aware of the fact that there's a redefinition, is if the redefinition occurs for real... When you compile files separately likely the mean prototype is missing... it is not shown in your code fragment at least: you should include helper.h also into helper.c. Doing so, gcc -c helper.c must give you a warning. I have gcc 4.3.2, but I am almost sure it must be so also for the version you have. In the main, you just use mean, so here the gcc trusts what is said in helper.h. When you link, there is no more information about the size of arguments and returning value, and bad things happen (like reading an int as a double).
Another detail: you say you get NaN for an int of the struct... well, in the struct there's a double, and int can't be NaN!

Resources