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 ....
Related
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.
I want to read analyze a plane (IODeviceTree IOUSB IOService IOACPIPlane)
without using ioreg, by creating a pointer (segment offset) in memory, my question is how to get the address of a plane, that in C or Objective C. Thank you for your answers.
First of all, I'm not sure what you mean by "segment offset" in this context, but the rest of the question makes sense, so I'll just ignore that part for my answer.
Second, the source code for ioreg is available here so you can see exactly how that does it.
A quick summary of how I would do it:
The main function you need to call is IORegistryCreateIterator().
Do not set the options argument to kIORegistryIterateRecursively - otherwise it will be difficult to find the graph structure.
For the plane argument, specify e.g. kIOServicePlane.
Keep calling IOIteratorNext(), and every time you get a registry entry back, try to recurse using IORegistryIteratorEnterEntry() and every time you get IO_OBJECT_NULL back, step one level back out using IORegistryIteratorExitEntry().
Working example code:
#include <stdio.h>
#include <IOKit/IOKitLib.h>
int main(int argc, const char * argv[])
{
io_iterator_t iter = IO_OBJECT_NULL;
unsigned recursion_level = 0;
kern_return_t result = IORegistryCreateIterator(kIOMasterPortDefault, kIOServicePlane, 0, &iter);
if (result == 0 && iter != IO_OBJECT_NULL)
{
while (true)
{
io_object_t entry = IOIteratorNext(iter);
if (entry != IO_OBJECT_NULL)
{
io_name_t name = "";
IORegistryEntryGetName(entry, name);
printf("%*s+ %s\n", recursion_level * 2, "", name);
++recursion_level;
result = IORegistryIteratorEnterEntry(iter);
assert(result == KERN_SUCCESS);
}
else
{
if (recursion_level == 0)
break;
result = IORegistryIteratorExitEntry(iter);
assert(result == KERN_SUCCESS);
--recursion_level;
}
}
}
return 0;
}
(Make sure to link against the IOKit.framework)
Of course, you can do much more interesting things than call IORegistryEntryGetName() on each registry entry.
I am trying to run run my first test in Clion using catch. Clion shows an error, squigly underlined, for the MACRO CATCH_CONFIG_RUNNER which reads: Can't run catch test: MACRO CATCH_CONFIG_RUNNER is never used. The program compiles and runs fine however I can't run the test. I added a configuration to run the test, but if I do Clion just spins while showing: instantiating tests. What am I missing? Please see below the code and makefile.
//This program reads identifies the largest # of three integers
#include <iostream>
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
using namespace std;
int largestInt ( int x, int y, int z); //function declaration/prototype
TEST_CASE("Find the largest of three numbers", "[eight is the answer]") {
REQUIRE(largestInt(8, 5, 4) == 8);
}
int main() {
int num1, num2, num3, max;
cout << "Please enter three integers: ";
cin>> num1 >> num2 >> num3;
max = largestInt(num1, num2, num3);
cout << "The largest number is " << max;
return 0;
}
//this function returns the largest of three ints
int largestInt ( int x, int y, int z) { //function definition
int max = x;
if (y > max) {
max = y;
}
if (z > max) {
max = z;
}
return max;
}
cmake_minimum_required(VERSION 3.7)
project(6_3)
set(CMAKE_CXX_STANDARD 14)
include_directories(/home/mgalactico/Documents/Deitel_Exercises/catch)
set(SOURCE_FILES main.cpp ../catch/catch.hpp)
add_executable(6_3 ${SOURCE_FILES})
You have written your own main() function. I assume you have a good reason for not generating one with the CATCH_CONFIG_MAIN macro. What is missing here is telling the program when to run the tests. This can be before, in between or after the code of your main function. Catch will not guess and decide that for you. You run the tests by calling:
Catch::Session().run(argc, argv);
This will create you an instance of Catch::Session which can also be done in a separate instruction followed by a call of applyCommandLine
Catch::Session session;
auto result = session.applyCommandLine( argc, argv );
// error handling ( result ) ...
...
Pass the command line arguments because the behavior of catch is configured this way. This is used by CLion where Catch is now (2017.1 or later) integrated. That means you get a green/red progress bar test runner as well as statistics and reporting if you have selected catch in your configuration.
Consider the following:
#include <stdio.h>
int main()
{
int first=9;
int second=0;
double ratio;
if(second==0)
ratio="n/a";
else
ratio=(double)singularCount/pluralCount;
printf("ratio is: %f", ratio);
return 0;
}
This obviously wont run as it should.
How can I modify my code/print statement to print a float if there are no problems, and n/a if there is division by 0?
I will be printing many of these ratios in a list, so I'd like to see "n/a" when there is division by 0.
Desired Output:
ratio is: n/a
You are doing something wrong...
you shouldn't put a string into a double variable.
What you want to do is to use isnan on undefined doubles (which are completely legit to hold),
and have an if statement on it.
something like:
if (isinf(ration)) printf("ration is undefined\n");
else printf...
This way you can send the double and get it from methods/procedures/functions (that I urge you to use for code separation) and yet you'll be able to get different behaviors.
by the way - look at this code:
#include <stdio.h>
#include <math.h>
void main()
{
double d = 1.0/0.0;
if (isnan(d)) printf("it is n/a\n");
else if (isinf(d)) printf("it is inf\n");
else printf("%f\n",d);
}
another thing - %f in the case of inf or nan will just print the strings "inf" and "nan", if it's good enough for you - you don't need to change a thing, if it is for your eyes.
if (second == 0) {
printf("ratio is: n/a");
} else {
printf("ratio is: %f", (double)singularCount/pluralCount);
}
When I compiled the following program like:
g++ -O2 -s -static 2.cpp it gave me the warning ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result].
But when I remove -02 from copiling statement no warning is shown.
My 2.cpp program:
#include<stdio.h>
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",a+b);
return 0;
}
What is the meaning of this warning and what is the meaning of -O2 ??
It means that you do not check the return value of scanf.
It might very well return 1 (only a is set) or 0 (neither a nor b is set).
The reason that it is not shown when compiled without optimization is that the analytics needed to see this is not done unless optimization is enabled. -O2 enables the optimizations - http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html.
Simply checking the return value will remove the warning and make the program behave in a predicable way if it does not receive two numbers:
if( scanf( "%d%d", &a, &b ) != 2 )
{
// do something, like..
fprintf( stderr, "Expected at least two numbers as input\n");
exit(1);
}
I took care of the warning by making an if statement that matches the number of arguments:
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int i;
long l;
long long ll;
char ch;
float f;
double d;
//6 arguments expected
if(scanf("%d %ld %lld %c %f %lf", &i, &l, &ll, &ch, &f, &d) == 6)
{
printf("%d\n", i);
printf("%ld\n", l);
printf("%lld\n", ll);
printf("%c\n", ch);
printf("%f\n", f);
printf("%lf\n", d);
}
return 0;
}