Velocity Reviews > Is there a better way to achieve this ?

# Is there a better way to achieve this ?

Francis Moreau
Guest
Posts: n/a

 03-02-2010
Hello,

I have the following requierement: 3 ints (a, b, limit). The sum of
'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
adjusted so that the sum of 'a' and 'b' is equal to 'limit'.

Basically this can be written in C like this:

int a, b, limit;

/* some code that setup the 3 variables */

if (a < 0 || b < 0)
goto end;
if (a + b > b) /* test for overflow (correct with GCC but not
portable) */
goto end;
if (a + b > limit)
a -= a + b - limit;
if (a < 0)
goto end;

/* ... */

So this should work (ok this uses an undefined behaviour but this code
is only intended to be compiled by GCC) but it looks quite
complicated.

Can anybody think to something more 'elegant' ?

Thanks

Malcolm McLean
Guest
Posts: n/a

 03-02-2010
On Mar 2, 4:42*pm, Francis Moreau <(E-Mail Removed)> wrote:
> Hello,
>
> I have the following requierement: 3 ints (a, b, limit). The sum of
> 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> adjusted so that the sum of 'a' and 'b' is equal to 'limit'.
>
> Basically this can be written in C like this:
>
> * *int a, b, limit;
>
> * */* some code that setup the 3 variables */
>
> * *if (a < 0 || b < 0)
> * * * *goto end;
> * *if (a + b > b) /* test for overflow (correct with GCC but not
> portable) */
> * * * *goto end;
> * *if (a + b > limit)
> * * * *a -= a + b - limit;
> * *if (a < 0)
> * * * *goto end;
>
> * */* ... */
>
> So this should work (ok this uses an undefined behaviour but this code
> is only intended to be compiled by GCC) but it looks quite
> complicated.
>
> Can anybody think to something more 'elegant' ?
>
> Thanks

int geta(a, b, limit)
{
unsigned int t;

if(a >= 0 && b >= 0)
{
t = (unsigned) a + (unsigned) b;
if(t > limit)
else
}
/* you haven't specified your other cases. What do we do if one or
both are negative?*/
}

Andrew Poelstra
Guest
Posts: n/a

 03-02-2010
On 2010-03-02, Francis Moreau <(E-Mail Removed)> wrote:
> Hello,
>
> I have the following requierement: 3 ints (a, b, limit). The sum of
> 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> adjusted so that the sum of 'a' and 'b' is equal to 'limit'.
>
> Basically this can be written in C like this:
>
> int a, b, limit;
>
> /* some code that setup the 3 variables */
>
> if (a < 0 || b < 0)
> goto end;
> if (a + b > b) /* test for overflow (correct with GCC but not
> portable) */
> goto end;
> if (a + b > limit)
> a -= a + b - limit;
> if (a < 0)
> goto end;
>
> /* ... */
>
> So this should work (ok this uses an undefined behaviour but this code
> is only intended to be compiled by GCC) but it looks quite
> complicated.
>
> Can anybody think to something more 'elegant' ?
>
> Thanks

I think:

if(a > limit - b)
a = limit - b;

The rest of your code does things you didn't specify, and
it's not clear where 'end' goes to, so I can't tell how to
clean up the rest.

--
Andrew Poelstra
http://www.wpsoftware.net/andrew

CarlosB
Guest
Posts: n/a

 03-02-2010
On Mar 2, 11:42*am, Francis Moreau <(E-Mail Removed)> wrote:
> Hello,
>
> I have the following requierement: 3 ints (a, b, limit). The sum of
> 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> adjusted so that the sum of 'a' and 'b' is equal to 'limit'.
>
> Basically this can be written in C like this:
>
> * *int a, b, limit;
>
> * */* some code that setup the 3 variables */
>
> * *if (a < 0 || b < 0)
> * * * *goto end;
> * *if (a + b > b) /* test for overflow (correct with GCC but not
> portable) */
> * * * *goto end;
> * *if (a + b > limit)
> * * * *a -= a + b - limit;
> * *if (a < 0)
> * * * *goto end;
>
> * */* ... */
>
> So this should work (ok this uses an undefined behaviour but this code
> is only intended to be compiled by GCC) but it looks quite
> complicated.
>
> Can anybody think to something more 'elegant' ?
>
> Thanks

a=(a+b > limit) ? limit-b ? a;

CarlosB
Guest
Posts: n/a

 03-02-2010
On Mar 2, 11:42*am, Francis Moreau <(E-Mail Removed)> wrote:
> Hello,
>
> I have the following requierement: 3 ints (a, b, limit). The sum of
> 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> adjusted so that the sum of 'a' and 'b' is equal to 'limit'.
>
> Basically this can be written in C like this:
>
> * *int a, b, limit;
>
> * */* some code that setup the 3 variables */
>
> * *if (a < 0 || b < 0)
> * * * *goto end;
> * *if (a + b > b) /* test for overflow (correct with GCC but not
> portable) */
> * * * *goto end;
> * *if (a + b > limit)
> * * * *a -= a + b - limit;
> * *if (a < 0)
> * * * *goto end;
>
> * */* ... */
>
> So this should work (ok this uses an undefined behaviour but this code
> is only intended to be compiled by GCC) but it looks quite
> complicated.
>
> Can anybody think to something more 'elegant' ?
>
> Thanks

a=(a+b > limit) ? limit-b : a;

Francis Moreau
Guest
Posts: n/a

 03-02-2010
On Mar 2, 3:53*pm, Malcolm McLean <(E-Mail Removed)>
wrote:
> On Mar 2, 4:42*pm, Francis Moreau <(E-Mail Removed)> wrote:
>
>
>
>
>
> > Hello,

>
> > I have the following requierement: 3 ints (a, b, limit). The sum of
> > 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> > adjusted so that the sum of 'a' and 'b' is equal to 'limit'.

>
> > Basically this can be written in C like this:

>
> > * *int a, b, limit;

>
> > * */* some code that setup the 3 variables */

>
> > * *if (a < 0 || b < 0)
> > * * * *goto end;
> > * *if (a + b > b) /* test for overflow (correct with GCC but not
> > portable) */
> > * * * *goto end;
> > * *if (a + b > limit)
> > * * * *a -= a + b - limit;
> > * *if (a < 0)
> > * * * *goto end;

>
> > * */* ... */

>
> > So this should work (ok this uses an undefined behaviour but this code
> > is only intended to be compiled by GCC) but it looks quite
> > complicated.

>
> > Can anybody think to something more 'elegant' ?

>
> > Thanks

>
> int geta(a, b, limit)
> {
> * unsigned int t;
>
> * if(a >= 0 && b >= 0)
> * {
> * * t = (unsigned) a + (unsigned) b;
> * * if(t > limit)
> * * * answer = limit - b;
> * * else
> * * * answer = a;
> * }

This doesn't seem right: for example if a=5 b=600 limit=500

In your case answer is equal to -100, which shouldn't happen since

> * /* you haven't specified your other cases. What do we do if one or
> both are negative?*/

It should terminate (goto end; statement) for example by calling
exit().

Francis Moreau
Guest
Posts: n/a

 03-02-2010
On Mar 2, 3:54*pm, Andrew Poelstra <(E-Mail Removed)>
wrote:
> On 2010-03-02, Francis Moreau <(E-Mail Removed)> wrote:
>
>
>
>
>
> > Hello,

>
> > I have the following requierement: 3 ints (a, b, limit). The sum of
> > 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> > adjusted so that the sum of 'a' and 'b' is equal to 'limit'.

>
> > Basically this can be written in C like this:

>
> > * *int a, b, limit;

>
> > * */* some code that setup the 3 variables */

>
> > * *if (a < 0 || b < 0)
> > * * * *goto end;
> > * *if (a + b > b) /* test for overflow (correct with GCC but not
> > portable) */
> > * * * *goto end;
> > * *if (a + b > limit)
> > * * * *a -= a + b - limit;
> > * *if (a < 0)
> > * * * *goto end;

>
> > * */* ... */

>
> > So this should work (ok this uses an undefined behaviour but this code
> > is only intended to be compiled by GCC) but it looks quite
> > complicated.

>
> > Can anybody think to something more 'elegant' ?

>
> > Thanks

>
> I think:
>
> * if(a > limit - b)
> * * a = limit - b;
>

This doesn't trap overflow or negative values...

> The rest of your code does things you didn't specify, and
> it's not clear where 'end' goes to, so I can't tell how to
> clean up the rest.

'end' goes to "exit(1);" for example. Otherwise 'a' is used to compute
new values.

Tim Rentsch
Guest
Posts: n/a

 03-02-2010
Francis Moreau <(E-Mail Removed)> writes:

> I have the following requierement: 3 ints (a, b, limit). The sum of
> 'a' and 'b' shouldn't be bigger than limit otherwise 'a' should be
> adjusted so that the sum of 'a' and 'b' is equal to 'limit'.
>
> Basically this can be written in C like this:
>
> int a, b, limit;
>
> /* some code that setup the 3 variables */
>
> if (a < 0 || b < 0)
> goto end;
> if (a + b > b) /* test for overflow (correct with GCC but not
> portable) */

Presumably you meant a + b < b in this test (still bad because
it relies on GCC overflow behavior, but this test is the one
I think you meant).

> goto end;
> if (a + b > limit)
> a -= a + b - limit;
> if (a < 0)
> goto end;
>
> /* ... */
>
> So this should work (ok this uses an undefined behaviour but this code
> is only intended to be compiled by GCC) but it looks quite
> complicated.
>
> Can anybody think to something more 'elegant' ?

if( a<0 || b<0 || limit<b ) goto end;
if( a > limit - b ) a = limit - b;
/* Here a >= 0, b >= 0, a+b <= limit */

Andrew Poelstra
Guest
Posts: n/a

 03-02-2010
On 2010-03-02, Francis Moreau <(E-Mail Removed)> wrote:
> On Mar 2, 3:54*pm, Andrew Poelstra <(E-Mail Removed)>
> wrote:
>>
>> I think:
>>
>> * if(a > limit - b)
>> * * a = limit - b;
>>

>
> This doesn't trap overflow or negative values...
>

Where is there overflow to be trapped?
For negative values, use:

if(a > limit - b)
a = limit - b;

if(a < 0 || b < 0 || limit < 0)
exit(1);

>> The rest of your code does things you didn't specify, and
>> it's not clear where 'end' goes to, so I can't tell how to
>> clean up the rest.

>
> 'end' goes to "exit(1);" for example. Otherwise 'a' is used to compute
> new values.

Given these specifications, the above two conditionals should
be sufficient.

--
Andrew Poelstra
http://www.wpsoftware.net/andrew

Peter Nilsson
Guest
Posts: n/a

 03-02-2010
Tim Rentsch <(E-Mail Removed)> wrote:
> Francis Moreau <(E-Mail Removed)> writes:
> > I have the following requierement: 3 ints (a, b, limit).
> > The sum of 'a' and 'b' shouldn't be bigger than limit
> > otherwise 'a' should be adjusted so that the sum of 'a'
> > and 'b' is equal to 'limit'.

There seem to be more criteria, e.g. a and b are non-negative.

> > Basically this can be written in C like this:

<snip>
> > Can anybody think to something more 'elegant' ?

>
> * * if( *a<0 || b<0 || limit<b *) *goto end;
> * * if( *a > limit - b *) *a = limit - b;
> * * /* Here a >= 0, b >= 0, a+b <= limit */

The purely general case is...

if (b < 0)
{
if (limit <= INT_MAX + b)
if (limit - b < a)
a = limit - b;
else
{
if (limit < INT_MIN + b)
goto end; /* a needs to be < INT_MIN : ERROR! */
if (limit - b < a)
a = limit - b;
}

--
Peter