/vqdr/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/vqdr/trunk

« back to all changes in this revision

Viewing changes to src/common/fast_number.vala

  • Committer: Gustav Hartvigsson
  • Date: 2021-09-09 15:40:16 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210909154016-0hm69n49w2slfky5
added more testes for the parser.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contects of this file is in the Public Domain.
 
3
 *
 
4
 * Created by Gustav Hartivgsson.
 
5
 */
 
6
 
1
7
namespace VQDR.Common {
2
8
  
3
9
  /**
8
14
   * Math done on these numbers are done using standard integer operations, and
9
15
   * not floating point math.
10
16
   */
11
 
  class FastNumber {
 
17
  public struct FastNumber {
12
18
    public const long MUL_FACTOR = 1000;
13
19
    
14
 
    public long raw_number { public get; private set; }
 
20
    /** Precision used to output values */
 
21
    public const int PRECISION_DIGITS = 2;
 
22
    /** Precision factor used to evaluate output */
 
23
    public const int PRECISION_FACTOR = 100;
 
24
    
 
25
    public long raw_number;
15
26
    
16
27
    public long number {
17
 
      get {return raw_number / MUL_FACTOR;}
18
 
      set {raw_number = number * MUL_FACTOR;}
 
28
      public get {return (this.raw_number / MUL_FACTOR);}
 
29
      public set {this.raw_number = (MUL_FACTOR * value);}
 
30
    }
 
31
    
 
32
    public long decimal {
 
33
      public get {return mask_and_normalize_decimal (raw_number);}
 
34
      public set {set_decimal_of_number (ref raw_number, value);}
 
35
    }
 
36
    
 
37
    public double float_rep {
 
38
      public get {return double.parse (@"$number" + "." + @"$decimal");}
 
39
      public set {this.raw_number = parse_raw_number (value.to_string ());}
19
40
    }
20
41
    
21
42
    public FastNumber (long val = 0) {
30
51
      this.raw_number = parse_raw_number (str);
31
52
    }
32
53
    
33
 
    private static long parse_raw_number (string str) {
 
54
    public FastNumber.from_float (double f) {
 
55
      this.raw_number = parse_raw_number (f.to_string ());
 
56
    }
 
57
    
 
58
    public FastNumber.raw (long raw) {
 
59
      this.raw_number = raw;
 
60
    }
 
61
    
 
62
    public void set_from_string (string str) {
 
63
      this.raw_number = parse_raw_number (str);
 
64
    }
 
65
    
 
66
    public FastNumber add (FastNumber? other) {
 
67
      if (other == null) {
 
68
        return  FastNumber.copy (this);
 
69
      }
 
70
      
 
71
      var v =  FastNumber ();
 
72
      v.raw_number = (this.raw_number + other.raw_number);
 
73
      return v;
 
74
    }
 
75
    
 
76
    public FastNumber subtract (FastNumber? other) {
 
77
      if (other == null) {
 
78
        return  FastNumber.copy (this);
 
79
      }
 
80
      
 
81
      var v =  FastNumber ();
 
82
      v.raw_number = (this.raw_number - other.raw_number);
 
83
      return v;
 
84
    }
 
85
    
 
86
    public FastNumber multiply (FastNumber? other) {
 
87
      if (other == null || other.raw_number == 0) {
 
88
        return  FastNumber ();
 
89
      }
 
90
      
 
91
      var ret =  FastNumber ();
 
92
      ret.raw_number = ((this.raw_number * other.raw_number) / MUL_FACTOR);
 
93
      return ret;
 
94
    }
 
95
    
 
96
    public FastNumber divide (FastNumber other) throws MathError {
 
97
      if (other.raw_number == 0) {
 
98
        throw new MathError.DIVIDE_BY_ZERO
 
99
                                      ("FantNumber - trying to divide by zero");
 
100
      }
 
101
      var ret =  FastNumber ();
 
102
      ret.raw_number = ((this.raw_number * MUL_FACTOR) / other.raw_number);
 
103
      return ret;
 
104
    }
 
105
    
 
106
    [CCode (cname = "vqdr_common_fast_number_compare")]
 
107
    public long compare (FastNumber other) {
 
108
      return this.raw_number - other.raw_number;
 
109
    }
 
110
    
 
111
    public FastNumber round_up () {
 
112
      FastNumber ret;
 
113
      long decimal = raw_number % PRECISION_FACTOR;
 
114
      if (decimal > 0) {
 
115
        ret = FastNumber.raw (raw_number + PRECISION_FACTOR - decimal);
 
116
      } else {
 
117
        ret = FastNumber.raw (raw_number - decimal);
 
118
      }
 
119
      return ret;
 
120
    }
 
121
    
 
122
    public FastNumber round_down () {
 
123
      FastNumber ret;
 
124
      long decimal = raw_number % PRECISION_FACTOR;
 
125
      if (decimal < 0) {
 
126
        // Is this ever reached?
 
127
        ret = FastNumber.raw (raw_number - PRECISION_FACTOR - decimal);
 
128
      } else {
 
129
        ret = FastNumber.raw (raw_number - decimal);
 
130
      }
 
131
      return ret;
 
132
    }
 
133
    
 
134
    public string to_string (bool decimal = false) {
 
135
      if (decimal) {
 
136
        return number.to_string () + "." + decimal.to_string ();
 
137
      } else {
 
138
        return number.to_string ();
 
139
      }
 
140
    } 
 
141
    
 
142
    // ***** STATIC FUNCTIONS ****//
 
143
    public static long parse_raw_number (string str) {
34
144
      long ret_val = 0;
35
145
      int i_of_dot = str.index_of_char ('.');
36
146
      if (i_of_dot >= 0) {
37
 
      
 
147
        
 
148
        debug (@"str: $str");
 
149
        
38
150
        // Get the decimal number from the string, if such a thing exists.
39
151
        if ((str.length - 1 > i_of_dot)) {
40
152
          ret_val = long.parse ((str + "000").substring (i_of_dot + 1));
41
153
        }
42
154
        
 
155
        debug (@"i_of_dot: $i_of_dot, ret_val (decimal): $ret_val\n");
 
156
        
43
157
        // Normalise the digits.
44
158
        while (ret_val > MUL_FACTOR) {
45
159
          ret_val = ret_val / 10;
46
160
        }
47
161
        
 
162
        debug (@"ret_val (normalised): $ret_val\n");
 
163
        
48
164
        // Add intiger number
49
 
        ret_val = ret_val + (long.parse ("0" + str.substring (0, i_of_dot))
 
165
        ret_val = ret_val + (long.parse (str.substring (0, i_of_dot))
50
166
                            * MUL_FACTOR);
 
167
        
 
168
        debug (@"ret_val (finised): $ret_val\n");
 
169
        
51
170
      } else {
52
171
        ret_val = long.parse (str) * MUL_FACTOR;
53
172
      }
54
173
      return ret_val;
55
174
    }
56
175
    
57
 
    
58
 
    public FastNumber add (FastNumber? other) {
59
 
      if (other == null) {
60
 
        return new FastNumber.copy (this);
61
 
      }
62
 
      
63
 
      var v = new FastNumber (this.raw_number + other.raw_number);
64
 
      
65
 
      return v;
66
 
    }
67
 
    
68
 
    public FastNumber subtract (FastNumber? other) {
69
 
      if (other == null) {
70
 
        return new FastNumber.copy (this);
71
 
      }
72
 
      
73
 
      var v = new FastNumber (this.raw_number - other.raw_number);
74
 
      
75
 
      return v;
76
 
    }
77
 
    
78
 
    public FastNumber multiply (FastNumber? other) {
79
 
      if (other == null || other.raw_value == 0) {
80
 
        return new FastNumber ();
81
 
      }
82
 
      
83
 
      return new FastNumber ((this.raw_number * other.raw_number) / MUL_FACTOR);
84
 
    }
85
 
    
86
 
    public FastNumber divide (FastNumber? other) throws MathError {
87
 
      if (other.raw_number == 0) {
88
 
        throw new MathError.DIVIDE_BY_ZERO
89
 
                                      ("FantNumber - trying to divide by zero");
90
 
      }
91
 
      
92
 
      return new FastNumber ((this.raw_number * MUL_FACTOR) / other.raw_number);
93
 
    }
94
 
    
 
176
    public static long mask_and_normalize_decimal (long number) {
 
177
      var mask = number / MUL_FACTOR;
 
178
      mask = mask * MUL_FACTOR;
 
179
      return number - mask;
 
180
    }
 
181
    
 
182
    public static void set_decimal_of_number (ref long number, long decimal) {
 
183
      var masked = number / MUL_FACTOR;
 
184
      masked = masked * MUL_FACTOR;
 
185
      number = masked + decimal;
 
186
    }
 
187
    
 
188
    [CCode (cname = "vqdr_common_fast_number_compare")]
 
189
    public static extern long static_compare (FastNumber a, FastNumber b);
95
190
  }
96
 
  
97
191
}