~ubuntu-branches/ubuntu/dapper/bygfoot/dapper

« back to all changes in this revision

Viewing changes to src/maths.c

  • Committer: Bazaar Package Importer
  • Author(s): Isaac Clerencia
  • Date: 2005-07-05 23:53:40 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050705235340-akpef5bdm7gsm9m4
Tags: 1.9.0-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "maths.h"
 
2
#include "misc.h"
 
3
#include "variables.h"
 
4
 
 
5
/**
 
6
   Generate a Gauss-distributed (pseudo)random number.
 
7
   "By Box and Muller, and recommended by Knuth".
 
8
   @return A Gauss-distributed random number.
 
9
*/
 
10
gdouble
 
11
math_gaussrand(void)
 
12
{
 
13
    static gdouble V1, V2, S;
 
14
    static gint phase = 0;
 
15
    gdouble X;
 
16
 
 
17
    if(phase == 0) {
 
18
        do {
 
19
            gdouble U1 = g_rand_double(rand_generator);
 
20
            gdouble U2 = g_rand_double(rand_generator);
 
21
 
 
22
            V1 = 2 * U1 - 1;
 
23
            V2 = 2 * U2 - 1;
 
24
            S = V1 * V1 + V2 * V2;
 
25
        } while(S >= 1 || S == 0);
 
26
 
 
27
        X = V1 * sqrt(-2 * log(S) / S);
 
28
    } else
 
29
        X = V2 * sqrt(-2 * log(S) / S);
 
30
 
 
31
    phase = 1 - phase;
 
32
 
 
33
    return X;
 
34
}
 
35
 
 
36
/**
 
37
   Generate a Gauss-distributed random number within given boundaries
 
38
   using math_gaussrand().
 
39
   Expectation value of the distribution is (upper + lower) / 2,
 
40
   the variance is so that the number is between the boundaries with probability
 
41
   99,7 %. If the number isn't between the boundaries, we cut off.
 
42
   @param lower Lower cutoff boundary.
 
43
   @param upper Upper cutoff boundary.
 
44
   @return A Gauss-distributed number 
 
45
*/
 
46
gdouble
 
47
math_gauss_dist(gdouble lower, gdouble upper)
 
48
{                                                  
 
49
    gdouble result;                                
 
50
        
 
51
    result = (upper - lower) / 6 * math_gaussrand()
 
52
        + (upper + lower) / 2;
 
53
 
 
54
    if(result < lower)
 
55
        result = lower;
 
56
 
 
57
    if(result > upper)
 
58
        result = upper;
 
59
 
 
60
    return result;
 
61
}
 
62
 
 
63
/**
 
64
   Get a certain part of an integer number.
 
65
 
 
66
   If 'place' is between 1 and 9, the 'place'th digit beginning
 
67
   from the right is returned, e.g. if the number = 1234 and
 
68
   place = 2, the function returns 3.
 
69
 
 
70
   If 'place' is between 10 and 19, say 10 + x, the first
 
71
   'x' digits are returned, e.g. number = 8765 and place = 12 leads to
 
72
   return value 87.
 
73
 
 
74
   If 'place' is between 20 and 29, say 20 + x, the last
 
75
   'x' digits are returned, e.g. number = 4869 and place = 22
 
76
   leads to return value 69.
 
77
 
 
78
   @param value The number which gets scrutinized.
 
79
   @param place The number telling the function which part of 'value' to return.
 
80
   @return A part of the integer 'value'.
 
81
 */
 
82
gint
 
83
math_get_place(gint value, gint place)
 
84
{
 
85
    if(place < 10)
 
86
        return (value % (gint)powf(10, place) -
 
87
                value % (gint)powf(10, place - 1)) /
 
88
            (gint)powf(10, place - 1);
 
89
 
 
90
    else if(place < 20)
 
91
    {
 
92
        while(value >= (gint)powf(10, place % 10))
 
93
            value = (value - value % 10) / 10;
 
94
        
 
95
        return value;
 
96
    }
 
97
    
 
98
    return value % (gint)powf(10, place % 10);
 
99
}
 
100
 
 
101
/**
 
102
   Round an integer with given precision.
 
103
 
 
104
   If places > 0, round with precision 'places', e.g. 
 
105
   number = 124566 and places = 2 leads to return value
 
106
   124600.
 
107
 
 
108
   If places < 0, precision is length of 'number' minus
 
109
   'places', e.g. number = 654987 and places = -2 leads to return
 
110
   value 65000.
 
111
 
 
112
   @param number The number to be rounded.
 
113
   @param places The precision.
 
114
   @return The rounded integer.
 
115
*/
 
116
gint
 
117
math_round_integer(gint number, gint places)
 
118
{
 
119
    gint length = 0;
 
120
    gfloat copy = (gfloat)number;
 
121
 
 
122
    if(places > 0)
 
123
        return (gint)rint( (gfloat)number / powf(10, places) ) *
 
124
            powf(10, places);
 
125
 
 
126
    while(copy >= 1)
 
127
    {
 
128
        copy /= 10;
 
129
        length++;
 
130
    }
 
131
 
 
132
    return (gint)rint( (gfloat)number / powf(10, length + places) ) *
 
133
        powf(10, length + places);
 
134
}
 
135
 
 
136
/** Generate a permutation of integers and write it to 'array'.
 
137
    @param array The integer array we store the permutation in. 
 
138
    It must have size at least end - start - 1.
 
139
    @param start The integer to start with.
 
140
    @param end The integer to end with. */
 
141
void
 
142
math_generate_permutation(gint *array, gint start, gint end)
 
143
{
 
144
    gint i;
 
145
 
 
146
    for(i = start; i < end + 1; i++)
 
147
        array[i - start] = i;
 
148
 
 
149
    for(i=0;i<end - start;i++)
 
150
        misc_swap_int(&array[i], &array[math_rndi(i, end - start)]);
 
151
}
 
152
 
 
153
/** This function tells us how many teams from 'number' teams
 
154
    have to be left away to obtain a power of 2. */
 
155
gint
 
156
math_get_bye_len(gint number)
 
157
{
 
158
    gint i;
 
159
 
 
160
    for(i=0;i<20;i++)
 
161
        if((gint)powf(2, i) >= number)
 
162
            break;
 
163
 
 
164
    return (gint)powf(2, i) - number;
 
165
}
 
166
 
 
167
/** Return the sum of the integers in the array.
 
168
    @param array The integer array.
 
169
    @param max The size of the array.
 
170
    @return The sum of all the integers in the array. */
 
171
gint
 
172
math_sum_int_array(const gint *array, gint max)
 
173
{
 
174
    gint i, sum = 0;
 
175
 
 
176
    for(i=0;i<max;i++)
 
177
        sum += array[i];
 
178
 
 
179
    return sum;
 
180
}