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

Help sought writing a loop construct

0 views
Skip to first unread message

Anand Hariharan

unread,
Dec 16, 2008, 3:03:15 PM12/16/08
to
The problem simply put is as follows:

I have a list of entities each of which needs to be assigned a unique
triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
0.0, 0.0) is not allowed.

So, I came with this ('NUMENTITIES' is defined as a compile time
constant):

--- BEGIN ---

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

int main(void)
{
const double Num = pow(NUMENTITIES + 1, (1.0/3.0));
const double FloorNum = floor(Num);
const double Step = Num / ( Num == FloorNum ? FloorNum - 1 :
FloorNum );

double r = 0.0, g = 0.0, b = Step;
int i;

printf("Num = %f, Step = %f\n", Num, Step);

for ( i = 1 ; i <= NUMENTITIES ; ++i )
{
printf("[%d] (%f, %f, %f)\n", i, (r/Num), (g/Num), (b/Num));

b += Step;
if ( b > Num + DBL_EPSILON )
{
b = 0;
g += Step;
if ( g > Num + DBL_EPSILON )
{
g = 0;
r += Step;
if ( r > Num + DBL_EPSILON && i != NUMENTITIES )
{
break;
}
}
}
}

assert( i == NUMENTITIES + 1 );
return 0;
}

--- END ---

This seems to do an adequate job. For example, for NUMENTITIES=8, it
generates:

Num = 2.080084, Step = 1.040042
[1] (0.000000, 0.000000, 0.500000)
[2] (0.000000, 0.000000, 1.000000)
[3] (0.000000, 0.500000, 0.000000)
[4] (0.000000, 0.500000, 0.500000)
[5] (0.000000, 0.500000, 1.000000)
[6] (0.000000, 1.000000, 0.000000)
[7] (0.000000, 1.000000, 0.500000)
[8] (0.000000, 1.000000, 1.000000)


No two triplet of values are the same, so the objective is met.
However, the 'r' component of the triplet is not used at all.

Am hoping that many of you will be able to tell me how to design a
loop construct so that I get a more 'uniform' distribution of values
that uses all three components.

Advance wishes to all for a happy & prosperous new year! :)
- Anand


PS: Feel free to show attitude (e.g., suggest that a high school kid
should be able to do it, but not actually offer any solution or
constructive criticism) but be rest assured this is not homework.

Bartc

unread,
Dec 16, 2008, 4:01:11 PM12/16/08
to

"Anand Hariharan" <mailto.anan...@gmail.com> wrote in message
news:32ab409d-c9d9-4379...@o40g2000prn.googlegroups.com...

> The problem simply put is as follows:
>
> I have a list of entities each of which needs to be assigned a unique
> triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
> 0.0, 0.0) is not allowed.

> Num = 2.080084, Step = 1.040042


> [1] (0.000000, 0.000000, 0.500000)
> [2] (0.000000, 0.000000, 1.000000)
> [3] (0.000000, 0.500000, 0.000000)
> [4] (0.000000, 0.500000, 0.500000)
> [5] (0.000000, 0.500000, 1.000000)
> [6] (0.000000, 1.000000, 0.000000)
> [7] (0.000000, 1.000000, 0.500000)
> [8] (0.000000, 1.000000, 1.000000)
>
>
> No two triplet of values are the same, so the objective is met.
> However, the 'r' component of the triplet is not used at all.

> Am hoping that many of you will be able to tell me how to design a
> loop construct so that I get a more 'uniform' distribution of values
> that uses all three components.

By using a bigger NUMENTITIES, you will eventually get some action in the
first column.

But, if the step size was 1.0 rather than 0.5, you'd simply be counting in
tertiary (001, 002, 010, 011, 012, 020, etc). Each successive value will be
unique (until you hit 222), but is not very interesting.

Do you have examples of a distribution that is more acceptable? What is this
for anyway, it seems colour graphics of some kind.

--
Bartc

Richard Heathfield

unread,
Dec 16, 2008, 4:11:17 PM12/16/08
to
Anand Hariharan said:

> The problem simply put is as follows:
>
> I have a list of entities each of which needs to be assigned a
> unique
> triplet of values, each in the range [0.0, 1.0]. The triplet
> (0.0, 0.0, 0.0) is not allowed.

First, let's work in whole numbers, since it'll be a lot easier,
conceptually speaking. We can always convert later.

Let us assume we can have any of 256 different values in the range
0-255 for any attribute. So we can calculate a three-attribute
unique hash like this:

(A1 << 16) | (A2 << 8) | A3

Alternatively, given a hash value, we can extract attribute values
from it like this:

A1 = (hash & 0xFF0000) >> 16
A2 = (hash & 0xFF00) >> 8
A3 = hash & 0xFF

(If all three are 0, just ++ one of them.)

Now, you have a maximum of NUM_ENTITIES attribute tuples. You want
them to be unique, and presumably you also want them to be
reasonably well spaced out. So this is easy - just divide the
largest possible 24-bit value, 16777215 if memory serves, by
NUM_ENTITIES (or, if you'd like to play a little safe, by
NUM_ENTITIES + 1). Call this value G, say.

Then all you have to do is go through each entity in turn, doing
something like this:

for(e = 0, h = 1; e < NUM_ENTITIES; e++, h += G)
{
entity[e].attrA = ((h & 0xFF0000) >> 16 ) / 256.0;
entity[e].attrB = ((h & 0xFF00) >> 8 ) / 256.0;
entity[e].attrC = ( h & 0xFF ) / 256.0;
}

This will give you pretty nigh-on perfect spread. If you'd like a
less perfect spread, remember that you can perturb h through up to
G/2 or so, randomly, if you wish.

Starting h at 1 should avoid the 0, 0, 0 taboo.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Ben Bacarisse

unread,
Dec 16, 2008, 5:08:42 PM12/16/08
to
Anand Hariharan <mailto.anan...@gmail.com> writes:

> I have a list of entities each of which needs to be assigned a unique
> triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
> 0.0, 0.0) is not allowed.
>
> So, I came with this ('NUMENTITIES' is defined as a compile time
> constant):
>

<snip code>


> This seems to do an adequate job. For example, for NUMENTITIES=8, it
> generates:
>
> Num = 2.080084, Step = 1.040042
> [1] (0.000000, 0.000000, 0.500000)
> [2] (0.000000, 0.000000, 1.000000)
> [3] (0.000000, 0.500000, 0.000000)
> [4] (0.000000, 0.500000, 0.500000)
> [5] (0.000000, 0.500000, 1.000000)
> [6] (0.000000, 1.000000, 0.000000)
> [7] (0.000000, 1.000000, 0.500000)
> [8] (0.000000, 1.000000, 1.000000)
>
> No two triplet of values are the same, so the objective is met.
> However, the 'r' component of the triplet is not used at all.
>
> Am hoping that many of you will be able to tell me how to design a
> loop construct so that I get a more 'uniform' distribution of values
> that uses all three components.

I needed something like this once. In a very simple graphics package
I wanted a method for the user to be able choose the 'i'th colour from
'n' spread round the spectrum -- the fully saturated colour ring. It
turns out to be one the few reasonably commented bits of my code so
here it is:

void Pen::set(int number, int out_of)
{
float posn = float(number) / out_of;

// Each of the RGB values rises and falls in the same way
// but exactly 120 degrees out of phase with the others.
// Since the whole ring is represented by the interval 0 to 1
// 120 degrees is 1/3.

// This picture might help. Look at it while reading the
// code for the cval function below.

// ______ ______
// \ / RED
// \ /
// \______/
// ______
// / \ / GREEN
// / \ /
// ___/ \______/
// ______
// \ / \ BLUE
// \ / \
// \______/ \___
//
// | | | |
// 0 0.33 0.66 1.0

set(cval(posn + 1.0/3.0), cval(posn), cval(posn + 2.0/3.0));
}

The final line is a call to an RGB colour setting method:

Pen::set(double red, double green, double blue);

--
Ben.

Thad Smith

unread,
Dec 18, 2008, 11:26:10 PM12/18/08
to
Anand Hariharan wrote:
> The problem simply put is as follows:
>
> I have a list of entities each of which needs to be assigned a unique
> triplet of values, each in the range [0.0, 1.0]. The triplet (0.0,
> 0.0, 0.0) is not allowed.
---- Code snipped ----

> This seems to do an adequate job. For example, for NUMENTITIES=8, it
> generates:
>
> Num = 2.080084, Step = 1.040042
> [1] (0.000000, 0.000000, 0.500000)
> [2] (0.000000, 0.000000, 1.000000)
> [3] (0.000000, 0.500000, 0.000000)
> [4] (0.000000, 0.500000, 0.500000)
> [5] (0.000000, 0.500000, 1.000000)
> [6] (0.000000, 1.000000, 0.000000)
> [7] (0.000000, 1.000000, 0.500000)
> [8] (0.000000, 1.000000, 1.000000)
>
>
> No two triplet of values are the same, so the objective is met.
> However, the 'r' component of the triplet is not used at all.
>
> Am hoping that many of you will be able to tell me how to design a
> loop construct so that I get a more 'uniform' distribution of values
> that uses all three components.

Good, you are refining your requirements. Can you describe --or better,
quantify -- your desired uniform distribution? Can you define and use
"distance between points"?

--
Thad

Anand Hariharan

unread,
Dec 30, 2008, 6:03:43 PM12/30/08
to
On Dec 16, 2:03 pm, Anand Hariharan <mailto.anand.hariha...@gmail.com>
wrote:

> The problem simply put is as follows:
>
> I have a list of entities each of which needs to be assigned a unique
> triplet of values, each in the range [0.0, 1.0].  The triplet (0.0,
> 0.0, 0.0) is not allowed.
>
(...)

>
> Advance wishes to all for a happy & prosperous new year! :)
> - Anand
>


Sincere thanks to all those who responded.

I was so 'hung-up' on being able to write this as some kind of a loop
that I didn't see there are other ways to approach the same problem.

Happy new year wishes once again,
- Anand

Anand Hariharan

unread,
Dec 30, 2008, 6:16:53 PM12/30/08
to

Even though there are 256 distinct whole numbers in [0, 255], I think
the values are "better" (?) if divided by 255 since the range I want
is [0.0, 1.0]. Also, I think it is "more correct" (??) dividing by
NUM_ENTITIES than NUM_ENTITIES+1. (I realise these are weasely and
vacuous statements, but I write simply after reading your post and
thinking about it for a couple of minutes, not actually implementing
it.)

What I am unable to appreciate is how a whole number spread across
2^24 translates to a uniform bit-wise spread (especially in the left-
most octet). Again, I write this in a rush and am not sure if I
phrased my question sensibly.

thank you for your response,
- Anand

Paavo Helde

unread,
Dec 30, 2008, 6:38:22 PM12/30/08
to
Anand Hariharan <mailto.anan...@gmail.com> kirjutas:

>
> Even though there are 256 distinct whole numbers in [0, 255],
> I think
> the values are "better" (?) if divided by 255 since the range
> I want
> is [0.0, 1.0].

It depends on how do you map integers to the application domain.
For
example, in the color RGB schema it is customary to associate
(0,0,0) to
the black color and (255,255,255) to the white color. Their
difference
in any channel is thus 255, so in order to transform RGB
component
values to the [0..1] range they have to be divided by 255
indeed. Some
other mappings might require a different approach.

Paavo

0 new messages