Why can't I read this scientific notation into GMP mpf_t? - gmp

I installed the libgmp3-dev package on Ubuntu 18.04 and am learning a bit how to use it. I wrote the following program
#include <stdio.h>
#include <gmp.h>
int main()
{
mpf_t x;
mpf_t y;
mpf_init(x);
mpf_init(y);
mpf_set_str(x, "9.95697589e-06", 10);
mpf_set_str(y, "+9.95697589e-06", 10);
printf("x: ");
mpf_out_str(stdout, 10, 12, x);
printf("\n");
printf("y: ");
mpf_out_str(stdout, 10, 12, y);
printf("\n");
mpf_clear(x);
mpf_clear(y);
return 0;
}
And the output looks like
x: 0.995697589e-5
y: 0.e0
I find it odd that a call like sscanf("+9.0e-5", "%lf", &my_double); handles this kind of format just fine, but mpf_set_str doesn't.
Why is 'y' showing up as 0?

I found why - the code just doesn't handle them.
I downloaded the 6.1.2 release tarball and looked at the file mpf/set_str.c.
It needs the following fix to work with + characters at the beginning of the string.
negative = 0;
if (c == '-')
{
negative = 1;
c = (unsigned char) *++str;
}
/* add this */
else if (c == '+')
{
c = (unsigned char) *++str;
}
and then it worked for me.

Related

Storing int values in an uint8_t array in code composer studio vs 5.4

I have a string in a uint8_t str[] array and I am trying to store the positions of characters within the str in another variable called uint8_t pos[]. The code is written in Code Composer Studio vs 5.4
I tried using sprintf(), type casting as well as changing the type of uint8_t pos[] to int pos[] as well as unsigned int pos[]. None of these work.
The code breaks at the sprintf statement and comes to a halt by reaching an undefined memory location. When I run in assembly after reaching sprintf statement, it gives an error saying that a source code for sprint.c cannot be found in location.
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "tm4c123gh6pm.h"
#include <stdio.h>
void initHw()
{
.
.
}
int main(void)
{
// Initialize hardware
initHw();
char strRx[80];
int count =0;
int count_enter=0;
uint8_t posStr[80];
uint8_t typeStr[80];
int pos=0;
int len;
unsigned int j=0, argCount=0;
while(1)
{
if(count == 0)
{
putsUart0("Enter characters for the string\r\n");
}
if(count <= 80)
{
char c = getcUart0();
if(c=='\b')
if(count>0)
count--;
else
break;
if(c>=' ')
{
strRx[count]=c;
count++;
}
if(count==80 || c==13)//'\r')
{
count_enter++;
if(count_enter==1) //count==80 before carriage return
{
len = count;
strRx[count]='\0';
while(count!=80)
strRx[count++]='\0';
count_enter=0;
putsUart0("\r\nEntered string is:\r\n");
putsUart0(strRx);
putsUart0("\r\n");
}
j=0;
//char a[10];
for(pos=0; pos!=len; pos++)// strRx[pos]!='\0'; pos++)
{
char a[80];
if((strRx[pos]>='A' && strRx[pos]<='Z') || (strRx[pos]>='a' && strRx[pos]<='z'))
{
typeStr[j]='a';
//posStr[j]=pos;
a[j]=pos;
sprintf(a,"%u",pos); //source not found
//a[j]=pos;
//posStr[j]=sprintf("%c",a);
//posStr[j]=(uint8_t)a;//a;
while(strRx[pos]!='\0'&&((strRx[pos]>='A' && strRx[pos]<='Z') || (strRx[pos]>='a' && strRx[pos]<='z')))
{
pos++;
}
pos--;
j++;
}
else if(strRx[pos]>='0' && strRx[pos]<='9')
{
typeStr[j]='n';
a[j]=pos;
sprintf(a,"%u",pos);
//posStr[j]=pos;//a;
while(strRx[pos]!='\0'&&((strRx[pos]>='0' && strRx[pos]<='9')))
{
pos++;
}
pos--;
j++;
}
else
{
while(strRx[pos]!='\0'&&((strRx[pos]<'A' && strRx[pos]>'Z') && (strRx[pos]<'a' && strRx[pos]>'z') && (strRx[pos+1]<'0' && strRx[pos+1]>'9')))
pos++;
}
}
argCount=j;
while(j!=80)
{
typeStr[j++]='\0';
posStr[j++]='\0';
}
count = 0;
}//if(count==80 || c==13)//'\r')
}//if count<=80
}//while(1)
}//main
The "unable to locate sprintf.c" error probably just means that the debugger cannot locate the source file, which means it cannot show the source code in the debugger window. It's possible that you don't have the source code for sprintf.c and all you have is the precompiled library. Or maybe you do have the source code and the debugger is simply looking in the wrong path. If you have the source code then there may be a way to tell the debugger which path to find it.
But that is just a debugger display issue -- It is not what is causing your program to crash. The problem may be in your code but you'd have to share your code for us to identify that. Or the problem may be a couple other issues that can occur with the printf related routines.
1) printf routines can use a relatively large amount of stack space. So check for a stack overflow and increase the stack size if necessary.
2) Some embedded libraries provide multiple implementations of the printf routines such as "small", "no-float", and "full". The limited implementations use less code space but don't support all of the format specifiers. So make sure the implementation of sprintf that you've linked with supports all the format specifiers that you're actually using. Look through the project settings under linker or libraries for an option to select which version of printf is used.

What does PKCS5_PBKDF2_HMAC_SHA1 return value mean?

I'm attempting to use OpenSSL's PKCS5_PBKDF2_HMAC_SHA1 method. I gather that it returns 0 if it succeeds, and some other value otherwise. My question is, what does a non-zero return value mean? Memory error? Usage error? How should my program handle it (retry, quit?)?
Edit: A corollary question is, is there any way to figure this out besides reverse-engineering the method itself?
is there any way to figure this out besides reverse-engineering the method itself?
PKCS5_PBKDF2_HMAC_SHA1 looks like one of those undocumented functions because I can't find it in the OpenSSL docs. OpenSSL has a lot of them, so you should be prepared to study the sources if you are going to use the library.
I gather that it returns 0 if it succeeds, and some other value otherwise.
Actually, its reversed. Here's how I know...
$ grep -R PKCS5_PBKDF2_HMAC_SHA1 *
crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
...
So, you find the function's implementation in crypto/evp/p5_crpt2.c:
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out)
{
return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter,
EVP_sha1(), keylen, out);
}
Following PKCS5_PBKDF2_HMAC:
$ grep -R PKCS5_PBKDF2_HMAC *
...
crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
...
And again, from crypto/evp/p5_crpt2.c:
int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest,
int keylen, unsigned char *out)
{
unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
int cplen, j, k, tkeylen, mdlen;
unsigned long i = 1;
HMAC_CTX hctx_tpl, hctx;
mdlen = EVP_MD_size(digest);
if (mdlen < 0)
return 0;
HMAC_CTX_init(&hctx_tpl);
p = out;
tkeylen = keylen;
if(!pass)
passlen = 0;
else if(passlen == -1)
passlen = strlen(pass);
if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL))
{
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
while(tkeylen)
{
if(tkeylen > mdlen)
cplen = mdlen;
else
cplen = tkeylen;
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
{
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, salt, saltlen)
|| !HMAC_Update(&hctx, itmp, 4)
|| !HMAC_Final(&hctx, digtmp, NULL))
{
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
memcpy(p, digtmp, cplen);
for(j = 1; j < iter; j++)
{
if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
{
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, digtmp, mdlen)
|| !HMAC_Final(&hctx, digtmp, NULL))
{
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
for(k = 0; k < cplen; k++)
p[k] ^= digtmp[k];
}
tkeylen-= cplen;
i++;
p+= cplen;
}
HMAC_CTX_cleanup(&hctx_tpl);
return 1;
}
So it looks like 0 on failure, and 1 on success. You should not see other values. And if you get a 0, then all the OUT parameters are junk.
Memory error? Usage error?
Well, sometimes you can call ERR_get_error. If you call it and it makes sense, then the error code is good. If the error code makes no sense, then its probably not good.
Sadly, that's the way I handle it because the library is not consistent with setting error codes. For example, here's the library code to load the RDRAND engine.
Notice the code clears the error code on failure if its a 3rd generation Ivy Bridge (that's the capability being tested), and does not clear or set an error otherwise!!!
void ENGINE_load_rdrand (void)
{
extern unsigned int OPENSSL_ia32cap_P[];
if (OPENSSL_ia32cap_P[1] & (1<<(62-32)))
{
ENGINE *toadd = ENGINE_rdrand();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
}
How should my program handle it (retry, quit?)?
It looks like a hard failure.
Finally, that's exactly how I navigate the sources in this situation. If you don't like grep you can try ctags or another source code browser.

Determine Position of Most Signifiacntly Set Bit in a Byte

I have a byte I am using to store bit flags. I need to compute the position of the most significant set bit in the byte.
Example Byte: 00101101 => 6 is the position of the most significant set bit
Compact Hex Mapping:
[0x00] => 0x00
[0x01] => 0x01
[0x02,0x03] => 0x02
[0x04,0x07] => 0x03
[0x08,0x0F] => 0x04
[0x10,0x1F] => 0x05
[0x20,0x3F] => 0x06
[0x40,0x7F] => 0x07
[0x80,0xFF] => 0x08
TestCase in C:
#include <stdio.h>
unsigned char check(unsigned char b) {
unsigned char c = 0x08;
unsigned char m = 0x80;
do {
if(m&b) { return c; }
else { c -= 0x01; }
} while(m>>=1);
return 0; //never reached
}
int main() {
unsigned char input[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff };
unsigned char truth[256] = {
0x00,0x01,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08};
int i,r;
int f = 0;
for(i=0; i<256; ++i) {
r=check(input[i]);
if(r !=(truth[i])) {
printf("failed %d : 0x%x : %d\n",i,0x000000FF & ((int)input[i]),r);
f += 1;
}
}
if(!f) { printf("passed all\n"); }
else { printf("failed %d\n",f); }
return 0;
}
I would like to simplify my check() function to not involve looping (or branching preferably). Is there a bit twiddling hack or hashed lookup table solution to compute the position of the most significant set bit in a byte?
Your question is about an efficient way to compute log2 of a value. And because you seem to want a solution that is not limited to the C language I have been slightly lazy and tweaked some C# code I have.
You want to compute log2(x) + 1 and for x = 0 (where log2 is undefined) you define the result as 0 (e.g. you create a special case where log2(0) = -1).
static readonly Byte[] multiplyDeBruijnBitPosition = new Byte[] {
7, 2, 3, 4,
6, 1, 5, 0
};
public static Byte Log2Plus1(Byte value) {
if (value == 0)
return 0;
var roundedValue = value;
roundedValue |= (Byte) (roundedValue >> 1);
roundedValue |= (Byte) (roundedValue >> 2);
roundedValue |= (Byte) (roundedValue >> 4);
var log2 = multiplyDeBruijnBitPosition[((Byte) (roundedValue*0xE3)) >> 5];
return (Byte) (log2 + 1);
}
This bit twiddling hack is taken from Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup where you can see the equivalent C source code for 32 bit values. This code has been adapted to work on 8 bit values.
However, you may be able to use an operation that gives you the result using a very efficient built-in function (on many CPU's a single instruction like the Bit Scan Reverse is used). An answer to the question Bit twiddling: which bit is set? has some information about this. A quote from the answer provides one possible reason why there is low level support for solving this problem:
Things like this are the core of many O(1) algorithms such as kernel schedulers which need to find the first non-empty queue signified by an array of bits.
That was a fun little challenge. I don't know if this one is completely portable since I only have VC++ to test with, and I certainly can't say for sure if it's more efficient than other approaches. This version was coded with a loop but it can be unrolled without too much effort.
static unsigned char check(unsigned char b)
{
unsigned char r = 8;
unsigned char sub = 1;
unsigned char s = 7;
for (char i = 0; i < 8; i++)
{
sub = sub & ((( b & (1 << s)) >> s--) - 1);
r -= sub;
}
return r;
}
I'm sure everyone else has long since moved on to other topics but there was something in the back of my mind suggesting that there had to be a more efficient branch-less solution to this than just unrolling the loop in my other posted solution. A quick trip to my copy of Warren put me on the right track: Binary search.
Here's my solution based on that idea:
Pseudo-code:
// see if there's a bit set in the upper half
if ((b >> 4) != 0)
{
offset = 4;
b >>= 4;
}
else
offset = 0;
// see if there's a bit set in the upper half of what's left
if ((b & 0x0C) != 0)
{
offset += 2;
b >>= 2;
}
// see if there's a bit set in the upper half of what's left
if > ((b & 0x02) != 0)
{
offset++;
b >>= 1;
}
return b + offset;
Branch-less C++ implementation:
static unsigned char check(unsigned char b)
{
unsigned char adj = 4 & ((((unsigned char) - (b >> 4) >> 7) ^ 1) - 1);
unsigned char offset = adj;
b >>= adj;
adj = 2 & (((((unsigned char) - (b & 0x0C)) >> 7) ^ 1) - 1);
offset += adj;
b >>= adj;
adj = 1 & (((((unsigned char) - (b & 0x02)) >> 7) ^ 1) - 1);
return (b >> adj) + offset + adj;
}
Yes, I know that this is all academic :)
It is not possible in plain C. The best I would suggest is the following implementation of check. Despite quite "ugly" I think it runs faster than the ckeck version in the question.
int check(unsigned char b)
{
if(b&128) return 8;
if(b&64) return 7;
if(b&32) return 6;
if(b&16) return 5;
if(b&8) return 4;
if(b&4) return 3;
if(b&2) return 2;
if(b&1) return 1;
return 0;
}
Edit: I found a link to the actual code: http://www.hackersdelight.org/hdcodetxt/nlz.c.txt
The algorithm below is named nlz8 in that file. You can choose your favorite hack.
/*
From last comment of: http://stackoverflow.com/a/671826/315052
> Hacker's Delight explains how to correct for the error in 32-bit floats
> in 5-3 Counting Leading 0's. Here's their code, which uses an anonymous
> union to overlap asFloat and asInt: k = k & ~(k >> 1); asFloat =
> (float)k + 0.5f; n = 158 - (asInt >> 23); (and yes, this relies on
> implementation-defined behavior) - Derrick Coetzee Jan 3 '12 at 8:35
*/
unsigned char check (unsigned char b) {
union {
float asFloat;
int asInt;
} u;
unsigned k = b & ~(b >> 1);
u.asFloat = (float)k + 0.5f;
return 32 - (158 - (u.asInt >> 23));
}
Edit -- not exactly sure what the asker means by language independent, but below is the equivalent code in python.
import ctypes
class Anon(ctypes.Union):
_fields_ = [
("asFloat", ctypes.c_float),
("asInt", ctypes.c_int)
]
def check(b):
k = int(b) & ~(int(b) >> 1)
a = Anon(asFloat=(float(k) + float(0.5)))
return 32 - (158 - (a.asInt >> 23))

GSL: Error reporting

I want to use the GSL for integration
http://www.gnu.org/software/gsl/manual/html_node/Numerical-Integration.html
However, I find no convenient way how the integrated function
(the function f in the example http://www.gnu.org/software/gsl/manual/html_node/Numerical-integration-examples.html)
can report an error to the integrator. I want to integrate a function which itself results from an integration that could fail. This is my sample program
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_errno.h>
double f (double x, void * params) {
GSL_ERROR("test error",GSL_FAILURE);
return 0.0;
}
int main (void)
{
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
double result, error;
gsl_function F;
F.function = &f;
gsl_set_error_handler_off();
int status = gsl_integration_qags (&F, 0, 1, 0, 1e-7, 1000,
w, &result, &error);
printf ("status = %d\n", status);
status = GSL_FAILURE;
printf ("status = %d\n", status);
gsl_integration_workspace_free (w);
return 0;
}
resulting in the output
status = 0
status = -1
I think the integrator should rather stop and return my error code. How can I achieve this?
Thank you very much for your help!!!
2011-04-27: I also tried this variant, after Brian Gough told me,
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_errno.h>
double f (double x, void * params) {
GSL_ERROR("test error",GSL_FAILURE);
return GSL_NAN;
}
int main (void)
{
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
double result, error;
gsl_function F;
F.function = &f;
gsl_set_error_handler_off();
int status = gsl_integration_qags (&F, 0, 1, 0, 1e-7, 1000,
w, &result, &error);
printf ("status = %d\n", status);
status = GSL_FAILURE;
printf ("status = %d\n", status);
gsl_integration_workspace_free (w);
return 0;
}
it did not help either. I will now fill out a bug report.
Thanks to Xuebin Wu from the GSL Mailing list the problem is solved:
Hi,
GSL_ERROR itself is a macro, it looks like
gsl_error (reason, __FILE__, __LINE__, gsl_errno);
return gsl_errno;
The function already returns before you return NAN, because GSL_ERROR
has been called. Turning the handler off just let the first line do
nothing. The default error handler abort the program after printing
error message.
I do not think it is a bug. Maybe you can write your own error handler
to solve your problem. For example, you can use "goto" to jump out of
gsl_integration_qags, or set some global variable to indicate the
integration result is incorrect.
PS: I believe this macro is what you need,
Macro: GSL_ERROR_VAL (reason, gsl_errno, value)
This macro is the same as GSL_ERROR but returns a user-defined value
of value instead of an error code. It can be used for mathematical
functions that return a floating point value.
The following example shows how to return a NaN at a mathematical
singularity using the GSL_ERROR_VAL macro,
if (x == 0)
{
GSL_ERROR_VAL("argument lies on singularity",
GSL_ERANGE, GSL_NAN);
}
So I adjusted the code according to
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_errno.h>
double f (double x, void * params) {
// return GSL_NAN;
GSL_ERROR_VAL ("argument lies on singularity", GSL_ERANGE, GSL_NAN);
}
int main (void)
{
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
double result, error;
gsl_function F;
F.function = &f;
gsl_set_error_handler_off();
int status = gsl_integration_qags (&F, 0, 1, 0, 1e-7, 1000,
w, &result, &error);
printf ("status = %d\n", status);
status = GSL_FAILURE;
printf ("status = %d\n", status);
gsl_integration_workspace_free (w);
return 0;
}
and everything works as expected...
A bit hackish, but I'd probably have your function store some flag. When it encounters an error it sets the flag and returns zero for all subsequent evaluations. Then, after you've integrated it you can check this flag to see if the result is valid.
What about to write a wrapper for the function which returns pointer to a structure, containing function results and error status ? Or if you use c++, this encapsulation can be made with use of objects ....

Create a Fraction array

I have to Create a dynamic array capable of holding 2*n Fractions.
If the dynamic array cannot be allocated, prints a message and calls exit(1).
It next fills the array with reduced random Fractions whose numerator
is between 1 and 20, inclusive; and whose initial denominator
is between 2 and 20, inclusive.
I ready did the function that is going to create the fraction and reduced it. this is what I got. When I compiled and run this program it crashes I cant find out why. If I put 1 instead of 10 in the test.c It doesn't crash but it gives me a crazy fraction. If I put 7,8,or 11 in the test.c it will crash. I would appreciate if someone can help me.
FractionSumTester.c
Fraction randomFraction(int minNum, int minDenom, int max)
{
Fraction l;
Fraction m;
Fraction f;
l.numerator = randomInt(minNum, max);
l.denominator = randomInt(minDenom, max);
m = reduceFraction(l);
while (m.denominator <= 1)
{
l.numerator = randomInt(minNum, max);
l.denominator = randomInt(minDenom, max);
m = reduceFraction(l);
}
return m;
}
Fraction *createFractionArray(int n)
{
Fraction *p;
int i;
p = malloc(n * sizeof(Fraction));
if (p == NULL)
{
printf("error");
exit(1);
}
for(i=0; i < 2*n ; i++)
{
p[i] = randomFraction(1,2,20);
printf("%d/%d\n", p[i].numerator, p[i].denominator);
}
return p;
}
this is the what I am using to test this two functions.
test.c
#include "Fraction.h"
#include "FractionSumTester.h"
#include <stdio.h>
int main()
{
createFractionArray(10);
return 0;
}
In your createFractionArray() function, you malloc() space for n items. Then, in the for loop, you write 2*n items into that space... which overruns your buffer and causes the crash.