23
23
* [non-decial part | decimal]
26
* Due to how some things work here, we can't reliably use the decimal part
27
* that referents a value less than 0.1. That is, like 5.05 will not work
30
27
public struct FastNumber {
33
* The limitations in the comment above is something
34
* that needs to be fixed.
36
* Look into a different representation?
38
* Perhaps only use raw_number ?
40
* Perhaps ripping out the things that are not needed?
45
29
/** Precision used to output values */
46
30
public const int PRECISION_DIGITS = 2;
53
37
public long raw_number;
39
public long leading_zeros;
42
* I'm not happy using getters/setters in this struct...
43
* But I tink it'll have to do for simplicity.
55
45
public long number {
56
46
public get {return (this.raw_number / MUL_FACTOR);}
57
public set {this.raw_number = (MUL_FACTOR * value);}
61
* Due to implementation details, and how the numbers are normalised,
62
* this value might be wrong.
65
public get {return mask_and_normalize_decimal (raw_number);}
66
public set {set_decimal_of_number (ref raw_number, value);}
69
public double float_rep {
71
long dec = this.decimal;
72
long nbr = this.number;
73
// debug (@"(float_ret_get) Float str: $nbr.$dec");
74
return double.parse (@"$nbr.$dec");
76
// debug (@"(float_ret_set) set float: $value");
77
this.raw_number = parse_raw_number (value.to_string ());
48
this.raw_number = (MUL_FACTOR * value);
91
62
* @param decimal The decimal part of the number. Defaults to 0.
93
public FastNumber (long number = 0, int decimal = 0) {
94
if (! (number == 0)) this.number = number;
95
if (! (decimal == 0)) this.decimal = decimal;
64
public FastNumber (long number = 0) {
66
this.raw_number = (number * MUL_FACTOR);
108
82
* Can be a decimal representation.
110
84
public FastNumber.from_string (string str) {
111
this.raw_number = parse_raw_number (str);
115
* Initialises a FastNumber from a double floating point value.
117
* Due to how floating point numbers works this may not be the exact value
118
* you expect it to be.
120
public FastNumber.from_float (double f) {
121
this.raw_number = parse_raw_number (f.to_string ());
85
parse_raw_number (str);
125
88
* Initialises a FastNumber with the internal representation of that number.
128
91
this.raw_number = raw;
132
* Sets the value of this FastNumber from a string,
134
public void set_from_string (string str) {
135
this.raw_number = parse_raw_number (str);
94
public FastNumber.from_float (double float_number) {
95
// XXX Do we need a faster way of doing this?
96
parse_raw_number (float_number.to_string ());
274
235
* the string. Default = false.
276
237
public string to_string (bool decimal = false) {
278
// FIXME: This will fail with decimal part less than 0.1..?
279
return @"$number.$decimal";
238
string ret_val = null;
240
ret_val = (this.raw_number / MUL_FACTOR).to_string ();
281
return number.to_string ();
242
// Copy stuff so we don't accidentality stomp them.
243
long _raw_number = this.raw_number;
245
long _integer_part = (_raw_number / MUL_FACTOR);
246
long _decimal_part = (_raw_number - (_integer_part * MUL_FACTOR));
248
var strbldr = new GLib.StringBuilder ();
250
// normalise the decimal part.
251
// (XXX This is rather expensive, is there a better way of doing this?).
252
if (_decimal_part != 0) {
253
while ((_decimal_part % 10) == 0) {
254
_decimal_part = _decimal_part / 10;
258
strbldr.append (_integer_part.to_string ())
262
for ( var i = this.leading_zeros ; i > 0 ; i--) {
263
strbldr.append_c ('0');
266
strbldr.append (_decimal_part.to_string ());
268
ret_val = strbldr.str;
273
public double to_float () {
274
// XXX This probobly needs to something faster?
275
return double.parse (this.to_string (true));
278
public long to_int () {
279
return (this.raw_number / MUL_FACTOR);
286
283
* Check if two FastNumbers are equal.
292
289
return (this.raw_number == other.raw_number);
295
// ***** STATIC FUNCTIONS ****//
296
public static long parse_raw_number (string str) {
293
[CCode (cname = "vqdr_common_fast_number_compare")]
294
public static extern long static_compare (FastNumber a, FastNumber b);
296
private void parse_raw_number (string str) {
297
debug (@"(parse_raw_number) str: $str");
297
298
long ret_val = 0;
298
299
int i_of_dot = str.index_of_char ('.');
299
300
if (i_of_dot >= 0) {
301
// debug (@"str: $str");
302
301
// Get the decimal number from the string, if such a thing exists.
303
302
if ((str.length - 1 > i_of_dot)) {
304
ret_val = long.parse ((str + "000").substring (i_of_dot + 1));
303
var intr_str = (str + "000").substring (i_of_dot + 1);
304
// count leading zeros.
306
for (i = 0; intr_str.@get (i) == '0'; i++){}
307
this.leading_zeros = i;
308
// remove leading zeros
309
intr_str = intr_str.substring (i);
310
debug (@"(parse_raw_number) Intermediate string: $intr_str");
311
ret_val = long.parse (intr_str);
307
314
// debug (@"(parse_raw_number) i_of_dot: $i_of_dot, ret_val (decimal): $ret_val\n");
312
319
// debug (@"(parse_raw_number) retval (loop): $ret_val");
322
for (var i = leading_zeros; i > 0; i--) {
323
ret_val = ret_val / 10;
324
// debug (@"(parse_raw_number) retval (loop2): $ret_val");
315
327
// debug (@"ret_val (normalised): $ret_val\n");
317
// get intiger number
329
// get integer number
318
330
ret_val = ret_val + (long.parse (str.substring (0, i_of_dot))
321
// debug (@"(parse_raw_number) ret_val (finished): $ret_val\n");
324
ret_val = long.parse (str) * MUL_FACTOR;
329
public static long mask_and_normalize_decimal (long number) {
330
// debug (@"(mask_and_normalize_decimal) number: $number");
331
long mask = number / MUL_FACTOR;
332
// debug (@"(mask_and_normalize_decimal) mask(1): $mask");
333
mask = mask * MUL_FACTOR;
334
// debug (@"(mask_and_normalize_decimal) mask(2): $mask");
335
long ret = number - mask;
337
// This is a rathor expensive operation.
339
while ((ret % 10) == 0) {
343
// debug (@"(mask_and_normalize_decimal) ret: $ret");
347
public static void set_decimal_of_number (ref long number, long decimal) {
348
// debug (@"(set_decimal_of_number) number(0): $number, decimal(0): $decimal");
349
long masked = number / MUL_FACTOR;
350
// debug (@"(set_decimal_of_number) masked(1): $masked");
351
masked = masked * MUL_FACTOR;
352
// debug (@"(set_decimal_of_number) masked(2): $masked");
356
while (decimal < PRECISION_FACTOR) {
357
decimal = decimal * 10;
358
// debug (@"(set_decimal_of_number) loop, decimal: $decimal");
362
number = masked + decimal;
363
// debug (@"(set_decimal_of_number) number(1): $number");
367
[CCode (cname = "vqdr_common_fast_number_compare")]
368
public static extern long static_compare (FastNumber a, FastNumber b);
334
ret_val = (long.parse (str) * MUL_FACTOR);
336
debug (@"(parse_raw_number) ret_val (finished): $ret_val\n");
337
this.raw_number = ret_val;