Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: An exercise, regarding the implementation of an "if"

14 views
Skip to first unread message
Message has been deleted

Richard Harter

unread,
Apr 15, 2010, 10:33:53 AM4/15/10
to
On 15 Apr 2010 14:19:23 GMT, r...@zedat.fu-berlin.de (Stefan Ram)
wrote:

> 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.)

Create an array of pointers to functions. Initialize it so that
location 0 holds the pointer to sin, and location 1 holds the
pointer to log. Then function f returns fp[c](x). Getting the
syntax right will be a good exercise for you. Engrave this in
your mind: Using arrays of function pointers is a fundamental
concept in programming.

Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
It's not much to ask of the universe that it be fair;
it's not much to ask but it just doesn't happen.

Tim Rentsch

unread,
Apr 15, 2010, 10:44:15 AM4/15/10
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> 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 );
}

Kenny McCormack

unread,
Apr 15, 2010, 10:51:04 AM4/15/10
to
In article <if-20100...@ram.dialup.fu-berlin.de>,

Stefan Ram <r...@zedat.fu-berlin.de> wrote:
> 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...

Eric Sosman

unread,
Apr 15, 2010, 11:01:28 AM4/15/10
to
On 4/15/2010 10:19 AM, Stefan Ram wrote:
> 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);
}

--
Eric Sosman
eso...@ieee-dot-org.invalid

Ali Karaali

unread,
Apr 15, 2010, 12:05:29 PM4/15/10
to
On 15 Nisan, 17:44, Tim Rentsch <t...@alumni.caltech.edu> wrote:

>
>   #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

Seebs

unread,
Apr 15, 2010, 12:15:07 PM4/15/10
to
On 2010-04-15, Ali Karaali <ali...@gmail.com> wrote:
> I took an
> syntax error : '{'
> under VC++,08

It doesn't support C99, which is the current C standard.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Army1987

unread,
Apr 15, 2010, 2:02:15 PM4/15/10
to
On Thu, 15 Apr 2010 14:19:23 +0000, Stefan Ram wrote:

> 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);
}

Army1987

unread,
Apr 15, 2010, 2:06:34 PM4/15/10
to

Sorry, I had skimmed the second paragraph of your post too quickly...

Message has been deleted

Alan Curry

unread,
Apr 15, 2010, 6:08:36 PM4/15/10
to
| 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;
}

--
Alan Curry

Ersek, Laszlo

unread,
Apr 15, 2010, 6:48:49 PM4/15/10
to
On Thu, 15 Apr 2010, Stefan Ram wrote:

> r...@zedat.fu-berlin.de (Stefan Ram) writes:

>> 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).

$ 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;
}

Amandil

unread,
Apr 16, 2010, 3:45:36 PM4/16/10
to
On Apr 15, 12:05 pm, Ali Karaali <ali...@gmail.com> wrote:
> On 15 Nisan, 17:44, Tim Rentsch <t...@alumni.caltech.edu> wrote:

.
.
.

> 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

Eric Sosman

unread,
Apr 16, 2010, 4:34:47 PM4/16/10
to
On 4/15/2010 5:21 PM, Stefan Ram wrote:
> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>> 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).

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.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Apr 16, 2010, 5:00:34 PM4/16/10
to
On 4/16/2010 4:34 PM, Eric Sosman wrote:
> On 4/15/2010 5:21 PM, Stefan Ram wrote:
>> [...]

>> 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);
}

--
Eric Sosman
eso...@ieee-dot-org.invalid

Message has been deleted

io_x

unread,
Apr 18, 2010, 1:22:29 AM4/18/10
to

"Eric Sosman" ha scritto nel messaggio
news:hqahm8$10e$1...@news.eternal-september.org...

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

Michael Foukarakis

unread,
Apr 19, 2010, 2:33:20 AM4/19/10
to
On Apr 18, 8:22 am, "io_x" <a...@b.c.invalid> wrote:
> "Eric Sosman"  ha scritto nel messaggionews:hqahm8$10e$1...@news.eternal-september.org...

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).

Morris Keesan

unread,
Apr 19, 2010, 8:46:17 PM4/19/10
to
On Thu, 15 Apr 2010 10:44:15 -0400, Tim Rentsch <t...@alumni.caltech.edu>
wrote:

...


> 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?

--
Morris Keesan -- mke...@post.harvard.edu

burton....@gmail.com

unread,
Apr 23, 2010, 1:06:49 AM4/23/10
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> 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);
}

--
Burton Samograd

Tim Rentsch

unread,
Apr 29, 2010, 1:58:32 AM4/29/10
to
"Morris Keesan" <mke...@post.harvard.edu> writes:

> On Thu, 15 Apr 2010 10:44:15 -0400, Tim Rentsch
> <t...@alumni.caltech.edu> wrote:
>
> ...
>> 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.

0 new messages