An exercise, regarding the implementation of an "if"

S

Stefan Ram

Write a function

double f( int c, double x );

that will return either the sine or the logarithm of its
second argument depending on whether it was called with a
first argument 0 or 1, respectively (that is, 0 for sine and
1 for logarithm), but do not use any control statement (such
as »if« or »while«) nor any operator with conditional
evaluation (such as ?:, &&, ||).

When the first argument is 0, the function must call
(directly or indirectly) »sin« (math.h), but must not call
(directly or indirectly) »log« (math.h). When the first
argument is 1, the function must call »log«, but must not
call »sin«.

The definition of additional helper functions is allowed
under the same restrictions as given above.

(I believe that I could write such a function when the
definition of additional helper functions is allowed, but I
do not have an idea how to do it without additional functions.)
 
T

Tim Rentsch

Write a function

double f( int c, double x );

that will return either the sine or the logarithm of its
second argument depending on whether it was called with a
first argument 0 or 1, respectively (that is, 0 for sine and
1 for logarithm), but do not use any control statement (such
as >>if<< or >>while<<) nor any operator with conditional
evaluation (such as ?:, &&, ||).

When the first argument is 0, the function must call
(directly or indirectly) >>sin<< (math.h), but must not call
(directly or indirectly) >>log<< (math.h). When the first
argument is 1, the function must call >>log<<, but must not
call >>sin<<.

The definition of additional helper functions is allowed
under the same restrictions as given above.

(I believe that I could write such a function when the
definition of additional helper functions is allowed, but I
do not have an idea how to do it without additional functions.)

#include <math.h>

double
f( int c, double x ){
return (double (*[])(double)){ (sin), (log) }[ c&1UL ]( x );
}
 
K

Kenny McCormack

Write a function

double f( int c, double x );

that will return either the sine or the logarithm of its
second argument depending on whether it was called with a
first argument 0 or 1, respectively (that is, 0 for sine and
1 for logarithm), but do not use any control statement (such
as »if« or »while«) nor any operator with conditional
evaluation (such as ?:, &&, ||).

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>

double f(int c,double x) {
static double (*fns[])() = {sin,log};
return fns[c](x);
}

int main(argc,argv)
int argc;
char **argv;
{
assert(argc == 3);
int i = atoi(argv[1]);
double d = strtod(argv[2],NULL);

printf("Result of f(%d,%g) is: %g\n",i,d,f(i,d));
return 0;
}

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch revelations of the childhood
traumas of the participants...
 
E

Eric Sosman

Write a function

double f( int c, double x );

that will return either the sine or the logarithm of its
second argument depending on whether it was called with a
first argument 0 or 1, respectively (that is, 0 for sine and
1 for logarithm), but do not use any control statement (such
as »if« or »while«) nor any operator with conditional
evaluation (such as ?:,&&, ||).

When the first argument is 0, the function must call
(directly or indirectly) »sin« (math.h), but must not call
(directly or indirectly) »log« (math.h). When the first
argument is 1, the function must call »log«, but must not
call »sin«.

The definition of additional helper functions is allowed
under the same restrictions as given above.

(I believe that I could write such a function when the
definition of additional helper functions is allowed, but I
do not have an idea how to do it without additional functions.)

#include <math.h>
double f(int c, double x) {
typedef double (*Fptr)(double);
static const Fptr func[] = { sin, log };
return func[c](x);
}
 
A

Ali Karaali

  #include <math.h>

  double
  f( int c, double x ){
      return  (double (*[])(double)){ (sin), (log) }[ c&1UL ]( x );
  }

I took an
syntax error : '{'
under VC++,08

Ali
 
A

Army1987

Write a function

double f( int c, double x );

that will return either the sine or the logarithm of its second
argument depending on whether it was called with a first argument 0 or
1, respectively (that is, 0 for sine and 1 for logarithm), but do not
use any control statement (such as »if« or »while«) nor any operator
with conditional evaluation (such as ?:, &&, ||).
{
return c * log(x) + (1 - c) * sin(x);
}
 
S

Stefan Ram

1 for logarithm), but do not use any control statement (such
as »if« or »while«) nor any operator with conditional
evaluation (such as ?:, &&, ||).

The implementation using an array was also what I had in
mind (even though I was mistakenly under the impression
that I had to define two helper functions, due to a previous
version of this exercise where this was necessary.)

Of course, it would be very interesting if anyone could
find a solution without using an array (I don't think that
this can be done).
 
A

Alan Curry

|
| Of course, it would be very interesting if anyone could
| find a solution without using an array (I don't think that
| this can be done).
|

With slight loss of portability...

#include <math.h>
#include <stdio.h>
#include <stdint.h>

double f( int c, double x )
{
uintptr_t s = (uintptr_t)sin;
uintptr_t l = (uintptr_t)log;
double (*op)(double) = (double (*)(double))(s + (l-s)*c);
return op(x);
}

int main(void)
{
printf("%f\n", f(0, 3.14159/2));
printf("%f\n", f(1, 2.71828));
return 0;
}
 
E

Ersek, Laszlo

(e-mail address removed)-berlin.de (Stefan Ram) writes:

The implementation using an array was also what I had in
mind (even though I was mistakenly under the impression
that I had to define two helper functions, due to a previous
version of this exercise where this was necessary.)

Of course, it would be very interesting if anyone could
find a solution without using an array (I don't think that
this can be done).

$ gcc -std=c99 -pedantic -Wall -Wextra -Wformat=2 -o sinlog sinlog.c -lm

$ ./sinlog
0.5 0

$ cat sinlog.c

#include <signal.h>
#include <math.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>


static double result,
arg;


static void
comp_sin(int sig)
{
assert(SIGTERM == sig);

result = sin(arg);
}


static void
comp_log(int sig)
{
assert(SIGINT == sig);

errno = 0;
result = log(arg);
assert(0 == errno);
}


static double
comp(int kind, double arg1)
{
assert(1 == (0 == kind) + (1 == kind));

arg = arg1;
raise((1 - kind) * SIGTERM + kind * SIGINT);
return result;
}


int
main(void)
{
{
void (*ret)(int);

ret = signal(SIGTERM, &comp_sin);
assert(SIG_ERR != ret);
ret = signal(SIGINT, &comp_log);
assert(SIG_ERR != ret);
}

(void)fprintf(stdout, "%g %g\n", comp(0, 3.141592654 / 6.0), comp(1, 1.0));

{
int ret;

ret = fflush(stdout);
assert(0 == ret);
}

return 0;
}
 
A

Amandil

..
..
..

Ali

(This is WAY off-topic, but did anyone else notice the date in the
quote? Besides being inaccurate - April 15 was 1 Iyar... - How'd you
do that, Ali?)

;-)

Marty
 
E

Eric Sosman

The implementation using an array was also what I had in
mind (even though I was mistakenly under the impression
that I had to define two helper functions, due to a previous
version of this exercise where this was necessary.)

Of course, it would be very interesting if anyone could
find a solution without using an array (I don't think that
this can be done).

Here's a filthy, filthy dirty approach (I hope I've matched
the parentheses correctly:)

double f(int c, double x) {
return (double(*)(double)(void*)(((uintptr_t)
(void*)sin)^((((uintptr_t)(void*)sin)^
((uintptr_t)(void*)log))*c)))(x);
}

Unfortunately, it relies on the existence of uintptr_t (not
guaranteed) and on the non-portable operations of converting
function pointers to void* and back.
 
E

Eric Sosman

[...]
Of course, it would be very interesting if anyone could
find a solution without using an array (I don't think that
this can be done).

Here's a filthy, filthy dirty approach (I hope I've matched
the parentheses correctly:) [...]

Oh, drat! I mis-matched them. Here's a correction, and
I've also added a little bit of defensive coding:

double f(int c, double x) {
return ((double(*)(double))(void*)(((uintptr_t)
(void*)log)^((((uintptr_t)(void*)sin)^((uintptr_t)
(void*)log))*!c)))(x);
}
 
S

Stefan Ram

Eric Sosman said:
double f(int c, double x) {
return ((double(*)(double))(void*)(((uintptr_t)
(void*)log)^((((uintptr_t)(void*)sin)^((uintptr_t)
(void*)log))*!c)))(x);
}

I was impressed by the ingenuity of all the answers! I have
chosen to respond to the above one, just to reformat it for
(my personal )readability. I have a certain formatting style
that is treating all brackets (parenthesis, braces) in the
same way, and I hope it will help me to read the above.

I am also adding »const« which I do not deem to be part of
the interface of a function, but just of its implementation.

double f( int const c, double const x )
{ return
( ( double( * )( double ) )
( void * )
( ( ( uintptr_t )( void * )log )
^
( ( ( ( uintptr_t )( void * )sin )
^
( ( uintptr_t )( void * )log ))
*
!c )
)
)
( x ); }
 
M

Michael Foukarakis

"Eric Sosman"  ha scritto nel messaggio






i not understand well;
i find the exercise not useful, the answer too much complex;
the problem is not how to make begin the things easy, difficult;
but how difficult exercise can be easy or at last with a chance
of to be understood

The exercise is quite useful in various applications; although some of
the answers are unnecessarily complex and error-prone (such as the one
you quoted).
 
M

Morris Keesan

....
double
f( int c, double x ){
return (double (*[])(double)){ (sin), (log) }[ c&1UL ]( x );
}

Why 1UL instead of just 1U? Is there any particular reason for a long
index into an array with two elements?
 
B

burton.samograd

Write a function

double f( int c, double x );
.
.
.

#include <math.h>

f(int c, double x) {
double (*fun[])(double x) = {
sin,
log
};

return fun[c](x);
}
 
T

Tim Rentsch

Morris Keesan said:
On Thu, 15 Apr 2010 10:44:15 -0400, Tim Rentsch

...
double
f( int c, double x ){
return (double (*[])(double)){ (sin), (log) }[ c&1UL ]( x );
}

Why 1UL instead of just 1U? Is there any particular reason for a long
index into an array with two elements?

Defensive coding reflex. If it isn't clear why just think
of it as 1U rather than 1UL.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,688
Members
48,796
Latest member
Greg L.

Latest Threads

Top