Thread overview
There must be a better way
Aug 02, 2006
Emp
Aug 02, 2006
Derek Parnell
Aug 02, 2006
Emp
Aug 02, 2006
Derek Parnell
Aug 04, 2006
Emp
August 02, 2006
I wrap two values (x && y coordinates) like this:

uint wrap(uint axis, int value)
{
 int max=0;
 if (axis==1) max=25;
 if (axis==0) max=10;
 if(value>=max){
  return (value % max);
 }
 if(value<0){
  int newValue;
  newValue=value;
  while(newValue<0){
   newValue+=max;
  }
  return (newValue);
 }
return value;
}

So I need to do things like 'wrap(0,currentX)' everytime to wrap the
currentX. Like:

(the original x && y need to be untouched)
array[wrap(0,currentX)][wrap(1,currentY)];

Is this really the best way, or am I just missing some nifty D programming?

Two small questions:
1. Isn't inout more used than out for functions, in contrast to what the
website says?
    I use inout quite often, or am I just doing something wrong?

2. Is it really difficult to make '>=" correctly compare an unsigned and a
signed int?
    (This took me some time to find out :)

Grtz, Emp





August 02, 2006
On Wed, 2 Aug 2006 03:57:07 +0200, Emp wrote:

> I wrap two values (x && y coordinates) like this:
> 
> uint wrap(uint axis, int value)
> {
>  int max=0;
>  if (axis==1) max=25;
>  if (axis==0) max=10;
>  if(value>=max){
>   return (value % max);
>  }
>  if(value<0){
>   int newValue;
>   newValue=value;
>   while(newValue<0){
>    newValue+=max;
>   }
>   return (newValue);
>  }
> return value;
> }
> 
> So I need to do things like 'wrap(0,currentX)' everytime to wrap the
> currentX. Like:
> 
> (the original x && y need to be untouched)
> array[wrap(0,currentX)][wrap(1,currentY)];
> 
> Is this really the best way, or am I just missing some nifty D programming?

Here is an alternative...

const AXIS0 = 10;
const AXIS1 = 25;

int mwrap(int max, int value)
{
    if(value >= max)
    {
        value %= max;
    }
    else if (value < 0)
    {
        value = max + (value % max);
        if (value == max)
            value = 0;
    }

    return value;
}

unittest
{
    assert(mwrap(AXIS0, 35) == 5);
    assert(mwrap(AXIS0, 0) == 0);
    assert(mwrap(AXIS0, 6) == 6);
    assert(mwrap(AXIS0, 10) == 0);

    assert(mwrap(AXIS1, 35) == 10);
    assert(mwrap(AXIS1, 0) == 0);
    assert(mwrap(AXIS1, 6) == 6);
    assert(mwrap(AXIS1, 25) == 0);

    assert(mwrap(AXIS0, -35) == 5);
    assert(mwrap(AXIS0, -6) == 4);
    assert(mwrap(AXIS0, -10) == 0);

    assert(mwrap(AXIS1, -35) == 15);
    assert(mwrap(AXIS1, -6) == 19);
    assert(mwrap(AXIS1, -25) == 0);
}


The main change I made was to supply the actual maximum value as a parameter. This will make the function more flexible in future. The other change was to not a D trick, just a maths 'trick'.

> Two small questions:
> 1. Isn't inout more used than out for functions, in contrast to what the
> website says?
>     I use inout quite often, or am I just doing something wrong?

Yes, IMHO <g>
The use of return values rather than updating the input parameters leads to
programs that are easier to maintain and re-use.

> 2. Is it really difficult to make '>=" correctly compare an unsigned and a signed int?

No. This is huge wart in D. For some Bob-only-knows reason, D silently interprets the bit-value of an int as if was a uint when doing such comparisons. Daft!

If you know that there is not going to be an overflow issue, you can do this ...

   if (cast(int)my_uint >= my_int) ...

which is saying you want the uint converted to a signed value before comparing the two.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
2/08/2006 12:41:01 PM
August 02, 2006
Thanks for the maths :)
The maximum are not constant and writing out the place they live would yield
to something like:

array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];

So the int was a bit of a hack... sorry :)

About the inout:
How would you do something like this?

bool something(inout structure struc ,int var){
  for (int i=0; i < struc.data[].length; i++){
    if(struc.data[i].count==0){
      struc.data[i].type=var;
      struc.data[i].count=30;
      return true;
    }
  }
  return false;
}







August 02, 2006
On Wed, 2 Aug 2006 05:49:44 +0200, Emp wrote:

> About the inout:
> How would you do something like this?
> 
> bool something(inout structure struc ,int var){
>   for (int i=0; i < struc.data[].length; i++){
>     if(struc.data[i].count==0){
>       struc.data[i].type=var;
>       struc.data[i].count=30;
>       return true;
>     }
>   }
>   return false;
> }

Ah yes... the problem with structs. The way you have done it here is a trade-off for performance and works fine. The alternative would be to pass back and forth the complete structure which is not a generally a good idea. You could make it a class instead of a structure but that would be just pedantic ;-)

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
2/08/2006 2:39:58 PM
August 02, 2006
I'm not clear on where your going, but I like to keep things simpler and thus more maintainable.  Instead of:

array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];

I would probably prefer...

whatever_t getWrapped(whatever_t[][] array, int x, int y, int var)
{
	return array[wrap(something[var].maxX, x)][wrap(something[var].maxY, y)];
}

Then you'd do:

array.getWrapped(currentX, currentY, var);

Which would seem much easier, and should be optimized out the same with inlining.  But this might not be practical depending on what "something" is (I'm guessing here it's a lookup or something.)

Also, fwiw, I use inout all the time.  I think there are specific design patterns and code paths with which it makes complete sense.  Example:

// Attempt to bring item to the top/head of the linked list.
if (!bringToTop(linked_list, item))
	writefln("Uh oh, %s was not found!", item.toString());

I don't think it's ambiguous that linked_list might be modified.  Just my opinion.  I might prefer "linked_list.bringToTop(item)" if it made sense, though (since that's even harder to misunderstand.)

-[Unknown]


> Thanks for the maths :)
> The maximum are not constant and writing out the place they live would yield to something like:
> 
> array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];
> 
> So the int was a bit of a hack... sorry :)
> 
> About the inout:
> How would you do something like this?
> 
> bool something(inout structure struc ,int var){
>   for (int i=0; i < struc.data[].length; i++){
>     if(struc.data[i].count==0){
>       struc.data[i].type=var;
>       struc.data[i].count=30;
>       return true;
>     }
>   }
>   return false;
> }
> 
> 
> 
> 
> 
> 
> 
August 04, 2006
I've been looking through your post but kind quite grasp how I should prog
like that... :/
I want to do stuff like this:
(I hope it is a bit more clear)

type=block.data[wrap(0,x)][wrap(1,y)].type;

with:
uint wrap(uint axis, int value)
{
 int max=1;
 if (axis==1) max=block.maxX; //variable
 if (axis==0) max=block.maxY; //same :)

 if(value >= max){
        value %= max;
    }else if (value < 0){
  value = max + (value % max);
  if (value == max) value = 0;
    }

return value;
}

> I'm not clear on where your going, but I like to keep things simpler and thus more maintainable.  Instead of:
>
> array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];
>
> I would probably prefer...
>
> whatever_t getWrapped(whatever_t[][] array, int x, int y, int var)
> {
> return array[wrap(something[var].maxX, x)][wrap(something[var].maxY, y)];
> }
>
> Then you'd do:
>
> array.getWrapped(currentX, currentY, var);
>
> Which would seem much easier, and should be optimized out the same with inlining.  But this might not be practical depending on what "something" is (I'm guessing here it's a lookup or something.)
>
> Also, fwiw, I use inout all the time.  I think there are specific design patterns and code paths with which it makes complete sense.  Example:
>
> // Attempt to bring item to the top/head of the linked list.
> if (!bringToTop(linked_list, item))
> writefln("Uh oh, %s was not found!", item.toString());
>
> I don't think it's ambiguous that linked_list might be modified.  Just my opinion.  I might prefer "linked_list.bringToTop(item)" if it made sense, though (since that's even harder to misunderstand.)
>
> -[Unknown]
>
>
>> Thanks for the maths :)
>> The maximum are not constant and writing out the place they live would
>> yield to something like:
>>
>> array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];
>>
>> So the int was a bit of a hack... sorry :)
>>
>> About the inout:
>> How would you do something like this?
>>
>> bool something(inout structure struc ,int var){
>>   for (int i=0; i < struc.data[].length; i++){
>>     if(struc.data[i].count==0){
>>       struc.data[i].type=var;
>>       struc.data[i].count=30;
>>       return true;
>>     }
>>   }
>>   return false;
>> }
>>
>>
>>
>>
>>
>> 

August 04, 2006
I guess, then, you'd have block with data inside it, as you do now, but data would have to be a class.  It would have to know about its parent, block.

Then you would be able to do something like that.

However, if you can settle for:

type = block.data(wrap(0, x), wrap(1, y)).type;

Then you don't need a class to proxy things.  But, is the call to wrap mandatory?  It looks like you really want something like below...

Let me note that D, when it sees this:

x.y(z);

Will try:

y(x, z);

If the function is available.  That's what I'm using (abusing?) here.

data_t data(whatever_block_is_t block, uint x, uint y)
{
	return return block.realData[wrap(x, block.maxX)][wrap(y, block.maxY)];
}

uint wrap(uint value, uint max)
{
	if (value >= max)
		return value % max;
	else if (value < 0)
		return max + (value % max);
	else
		return value;
}

So then you'd do:

type = block.data(x, y).type;

Assuming you always want the x and why wrapped.  If you didn't, you could still do:

type = block.realData[x][y].type;

-[Unknown]


> I've been looking through your post but kind quite grasp how I should prog like that... :/
> I want to do stuff like this:
> (I hope it is a bit more clear)
> 
> type=block.data[wrap(0,x)][wrap(1,y)].type;
> 
> with:
> uint wrap(uint axis, int value)
> {
>  int max=1;
>  if (axis==1) max=block.maxX; //variable
>  if (axis==0) max=block.maxY; //same :)
> 
>  if(value >= max){
>         value %= max;
>     }else if (value < 0){
>   value = max + (value % max);
>   if (value == max) value = 0;
>     }
> 
> return value;
> }
> 
>> I'm not clear on where your going, but I like to keep things simpler and thus more maintainable.  Instead of:
>>
>> array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];
>>
>> I would probably prefer...
>>
>> whatever_t getWrapped(whatever_t[][] array, int x, int y, int var)
>> {
>> return array[wrap(something[var].maxX, x)][wrap(something[var].maxY, y)];
>> }
>>
>> Then you'd do:
>>
>> array.getWrapped(currentX, currentY, var);
>>
>> Which would seem much easier, and should be optimized out the same with inlining.  But this might not be practical depending on what "something" is (I'm guessing here it's a lookup or something.)
>>
>> Also, fwiw, I use inout all the time.  I think there are specific design patterns and code paths with which it makes complete sense.  Example:
>>
>> // Attempt to bring item to the top/head of the linked list.
>> if (!bringToTop(linked_list, item))
>> writefln("Uh oh, %s was not found!", item.toString());
>>
>> I don't think it's ambiguous that linked_list might be modified.  Just my opinion.  I might prefer "linked_list.bringToTop(item)" if it made sense, though (since that's even harder to misunderstand.)
>>
>> -[Unknown]
>>
>>
>>> Thanks for the maths :)
>>> The maximum are not constant and writing out the place they live would yield to something like:
>>>
>>> array[wrap(something[var].maxX,currentX)][wrap(something[var].maxY,currentY)];
>>>
>>> So the int was a bit of a hack... sorry :)
>>>
>>> About the inout:
>>> How would you do something like this?
>>>
>>> bool something(inout structure struc ,int var){
>>>   for (int i=0; i < struc.data[].length; i++){
>>>     if(struc.data[i].count==0){
>>>       struc.data[i].type=var;
>>>       struc.data[i].count=30;
>>>       return true;
>>>     }
>>>   }
>>>   return false;
>>> }
>>>
>>>
>>>
>>>
>>>
>>>
>