Changed mind about translating short currency names, instead use the full name in...
[gcalctool.git] / src / financial.c
blob94a21c0d160aafa5c83ecde3cfeb13cc14acff6b
1 /* Copyright (c) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
2 * Copyright (c) 2008-2009 Robert Ancell
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include <glib/gi18n.h>
22 #include "financial.h"
23 #include "mp.h"
25 static void
26 calc_ctrm(MathEquation *equation, MPNumber *t, MPNumber *pint, MPNumber *fv, MPNumber *pv)
29 /* Cterm - pint (periodic interest rate).
30 * fv (future value).
31 * pv (present value).
33 * RESULT = log(fv / pv) / log(1 + pint)
35 MPNumber MP1, MP2, MP3, MP4;
37 mp_divide(fv, pv, &MP1);
38 mp_ln(&MP1, &MP2);
39 mp_add_integer(pint, 1, &MP3);
40 mp_ln(&MP3, &MP4);
41 mp_divide(&MP2, &MP4, t);
45 static void
46 calc_ddb(MathEquation *equation, MPNumber *t, MPNumber *cost, MPNumber *life, MPNumber *period)
49 /* Ddb - cost (amount paid for asset).
50 * life (useful life of the asset).
51 * period (time period for depreciation allowance).
53 * bv = 0.0;
54 * for (i = 0; i < life; i++)
55 * {
56 * VAL = ((cost - bv) * 2) / life
57 * bv += VAL
58 * }
59 * RESULT = VAL
63 int i;
64 int len;
65 MPNumber MPbv, MP1, MP2;
67 mp_set_from_integer(0, &MPbv);
68 len = mp_cast_to_int(period);
69 for (i = 0; i < len; i++) {
70 mp_subtract(cost, &MPbv, &MP1);
71 mp_multiply_integer(&MP1, 2, &MP2);
72 mp_divide(&MP2, life, t);
73 mp_set_from_mp(&MPbv, &MP1);
74 mp_add(&MP1, t, &MPbv); /* TODO: why result is MPbv, for next loop? */
77 if (len >= 0) {
78 math_equation_set_status (equation, ("Error: the number of periods must be positive"));
79 mp_set_from_integer(0, t);
84 static void
85 calc_fv(MathEquation *equation, MPNumber *t, MPNumber *pmt, MPNumber *pint, MPNumber *n)
88 /* Fv - pmt (periodic payment).
89 * pint (periodic interest rate).
90 * n (number of periods).
92 * RESULT = pmt * (pow(1 + pint, n) - 1) / pint
95 MPNumber MP1, MP2, MP3, MP4;
97 mp_add_integer(pint, 1, &MP1);
98 mp_xpowy(&MP1, n, &MP2);
99 mp_add_integer(&MP2, -1, &MP3);
100 mp_multiply(pmt, &MP3, &MP4);
101 mp_divide(&MP4, pint, t);
105 static void
106 calc_gpm(MathEquation *equation, MPNumber *t, MPNumber *cost, MPNumber *margin)
109 /* Gpm - cost (cost of sale).
110 * margin (gross profit margin.
112 * RESULT = cost / (1 - margin)
115 MPNumber MP1, MP2;
117 mp_set_from_integer(1, &MP1);
118 mp_subtract(&MP1, margin, &MP2);
119 mp_divide(cost, &MP2, t);
123 static void
124 calc_pmt(MathEquation *equation, MPNumber *t, MPNumber *prin, MPNumber *pint, MPNumber *n)
127 /* Pmt - prin (principal).
128 * pint (periodic interest rate).
129 * n (term).
131 * RESULT = prin * (pint / (1 - pow(pint + 1, -1 * n)))
134 MPNumber MP1, MP2, MP3, MP4;
136 mp_add_integer(pint, 1, &MP1);
137 mp_multiply_integer(n, -1, &MP2);
138 mp_xpowy(&MP1, &MP2, &MP3);
139 mp_multiply_integer(&MP3, -1, &MP4);
140 mp_add_integer(&MP4, 1, &MP1);
141 mp_divide(pint, &MP1, &MP2);
142 mp_multiply(prin, &MP2, t);
146 static void
147 calc_pv(MathEquation *equation, MPNumber *t, MPNumber *pmt, MPNumber *pint, MPNumber *n)
150 /* Pv - pmt (periodic payment).
151 * pint (periodic interest rate).
152 * n (term).
154 * RESULT = pmt * (1 - pow(1 + pint, -1 * n)) / pint
157 MPNumber MP1, MP2, MP3, MP4;
159 mp_add_integer(pint, 1, &MP1);
160 mp_multiply_integer(n, -1, &MP2);
161 mp_xpowy(&MP1, &MP2, &MP3);
162 mp_multiply_integer(&MP3, -1, &MP4);
163 mp_add_integer(&MP4, 1, &MP1);
164 mp_divide(&MP1, pint, &MP2);
165 mp_multiply(pmt, &MP2, t);
169 static void
170 calc_rate(MathEquation *equation, MPNumber *t, MPNumber *fv, MPNumber *pv, MPNumber *n)
173 /* Rate - fv (future value).
174 * pv (present value).
175 * n (term).
177 * RESULT = pow(fv / pv, 1 / n) - 1
180 MPNumber MP1, MP2, MP3, MP4;
182 mp_divide(fv, pv, &MP1);
183 mp_set_from_integer(1, &MP2);
184 mp_divide(&MP2, n, &MP3);
185 mp_xpowy(&MP1, &MP3, &MP4);
186 mp_add_integer(&MP4, -1, t);
190 static void
191 calc_sln(MathEquation *equation, MPNumber *t, MPNumber *cost, MPNumber *salvage, MPNumber *life)
194 /* Sln - cost (cost of the asset).
195 * salvage (salvage value of the asset).
196 * life (useful life of the asset).
198 * RESULT = (cost - salvage) / life
201 MPNumber MP1;
202 mp_subtract(cost, salvage, &MP1);
203 mp_divide(&MP1, life, t);
207 static void
208 calc_syd(MathEquation *equation, MPNumber *t, MPNumber *cost, MPNumber *salvage, MPNumber *life, MPNumber *period)
211 /* Syd - cost (cost of the asset).
212 * salvage (salvage value of the asset).
213 * life (useful life of the asset).
214 * period (period for which depreciation is computed).
216 * RESULT = (cost - salvage) * (life - period + 1) /
217 * (life * (life + 1)) / 2
220 MPNumber MP1, MP2, MP3, MP4;
222 mp_subtract(life, period, &MP2);
223 mp_add_integer(&MP2, 1, &MP3);
224 mp_add_integer(life, 1, &MP2);
225 mp_multiply(life, &MP2, &MP4);
226 mp_set_from_integer(2, &MP2);
227 mp_divide(&MP4, &MP2, &MP1);
228 mp_divide(&MP3, &MP1, &MP2);
229 mp_subtract(cost, salvage, &MP1);
230 mp_multiply(&MP1, &MP2, t);
234 static void
235 calc_term(MathEquation *equation, MPNumber *t, MPNumber *pmt, MPNumber *fv, MPNumber *pint)
238 /* Term - pmt (periodic payment).
239 * fv (future value).
240 * pint (periodic interest rate).
242 * RESULT = log(1 + (fv * pint / pmt)) / log(1 + pint)
245 MPNumber MP1, MP2, MP3, MP4;
247 mp_add_integer(pint, 1, &MP1);
248 mp_ln(&MP1, &MP2);
249 mp_multiply(fv, pint, &MP1);
250 mp_divide(&MP1, pmt, &MP3);
251 mp_add_integer(&MP3, 1, &MP4);
252 mp_ln(&MP4, &MP1);
253 mp_divide(&MP1, &MP2, t);
257 void
258 do_finc_expression(MathEquation *equation, int function, MPNumber *arg1, MPNumber *arg2, MPNumber *arg3, MPNumber *arg4)
260 MPNumber result;
261 switch (function) {
262 case FINC_CTRM_DIALOG:
263 calc_ctrm(equation, &result, arg1, arg2, arg3);
264 break;
265 case FINC_DDB_DIALOG:
266 calc_ddb(equation, &result, arg1, arg2, arg3);
267 break;
268 case FINC_FV_DIALOG:
269 calc_fv(equation, &result, arg1, arg2, arg3);
270 break;
271 case FINC_GPM_DIALOG:
272 calc_gpm(equation, &result, arg1, arg2);
273 break;
274 case FINC_PMT_DIALOG:
275 calc_pmt(equation, &result, arg1, arg2, arg3);
276 break;
277 case FINC_PV_DIALOG:
278 calc_pv(equation, &result, arg1, arg2, arg3);
279 break;
280 case FINC_RATE_DIALOG:
281 calc_rate(equation, &result, arg1, arg2, arg3);
282 break;
283 case FINC_SLN_DIALOG:
284 calc_sln(equation, &result, arg1, arg2, arg3);
285 break;
286 case FINC_SYD_DIALOG:
287 calc_syd(equation, &result, arg1, arg2, arg3, arg4);
288 break;
289 case FINC_TERM_DIALOG:
290 calc_term(equation, &result, arg1, arg2, arg3);
291 break;
293 math_equation_set_number(equation, &result);