1 /********************************************************************
2 This file is part of the abs 0.907 distribution.  abs is a spreadsheet
3 with graphical user interface.
4 
5 Copyright (C) 1998-2001  Andr� Bertin (Andre.Bertin@ping.be)
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version if in the same spirit as version 2.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Concact: abs@pi.be
22          http://home.pi.be/bertin/abs.shtml
23 
24 *********************************************************************/
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 #include "mathfct.h"
55 #include "y.tab.h"
56 #include "string.h"
57 #include "math.h"
58 #include "cell_vb.h"
59 #include "typedef.h"
60 #include "application.h"
61 #include "interpret.h"
62 #include "gram_ext.h"
63 #include "abv.h"
64 #include "parser_ext.h"
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117 
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 Fct matharrayfct[] =
129 {
130   {"ABS", &vb_ABS, 1, 1, "ABS(number)", "Returns the absolute value of a number"},
131   {"ACOS", &vb_ACOS, 1, 1, NULL, NULL},
132   {"ACOSH", &vb_ACOSH, 1, 1, NULL, NULL},
133   {"ASIN", &vb_ASIN, 1, 1, NULL, NULL},
134   {"ASINH", &vb_ASINH, 1, 1, NULL, NULL},
135   {"ATAN", &vb_ATAN, 1, 1, NULL, NULL},
136   {"ATAN2", &vb_ATAN2, 1, 1, NULL, NULL},
137   {"ATANH", &vb_ATANH, 1, 1, NULL, NULL},
138   {"CEILING", &vb_CEILING, 1, 1, NULL, NULL},
139   {"COMBIN", &vb_COMBIN, 1, 1, NULL, NULL},
140   {"COS", &vb_COS, 1, 1, NULL, NULL},
141   {"COSH", &vb_COSH, 1, 1, NULL, NULL},
142   {"COUNTIF", &vb_COUNTIF, 1, 1, NULL, NULL},
143   {"DEGREES", &vb_DEGREES, 1, 1, NULL, NULL},
144   {"EVEN", &vb_EVEN, 1, 1, NULL, NULL},
145   {"EXP", &vb_EXP, 1, 1, NULL, NULL},
146   {"FACT", &vb_FACT, 1, 1, NULL, NULL},
147   {"FACTDOUBLE", &vb_FACTDOUBLE, 1, 1, NULL, NULL},
148   {"FLOOR", &vb_FLOOR, 1, 1, NULL, NULL},
149   {"GCD", &vb_GCD, 1, 1, NULL, NULL},
150   {"INT", &vb_INT, 1, 1, NULL, NULL},
151   {"LCM", &vb_LCM, 1, 1, NULL, NULL},
152   {"LN", &vb_LN, 1, 1, NULL, NULL},
153   {"LOG10", &vb_LOG10, 1, 1, NULL, NULL},
154   {"LOG", &vb_LOG, 1, 1, NULL, NULL},
155   {"MDETERM", &vb_MDETERM, 1, 1, NULL, NULL},
156   {"MINVERSE", &vb_MINVERSE, 1, 1, NULL, NULL},
157   {"MMULT", &vb_MMULT, 1, 1, NULL, NULL},
158   {"MOD", &vb_MOD, 1, 1, NULL, NULL},
159   {"MROUND", &vb_MROUND, 1, 1, NULL, NULL},
160   {"MULTINOMIAL", &vb_MULTINOMIAL, 1, 1, NULL, NULL},
161   {"ODD", &vb_ODD, 1, 1, NULL, NULL},
162   {"PI", &vb_PI, 1, 1, NULL, NULL},
163   {"POWER", &vb_POWER, 1, 1, NULL, NULL},
164   {"PRODUCT", &vb_PRODUCT, 1, 1, NULL, NULL},
165   {"QUOTIENT", &vb_QUOTIENT, 1, 1, NULL, NULL},
166   {"RADIANS", &vb_RADIANS, 1, 1, NULL, NULL},
167   {"RAND", &vb_RAND, 1, 1, NULL, NULL},
168   {"RANDBETWEEN", &vb_RANDBETWEEN, 1, 1, NULL, NULL},
169   {"ROMAN", &vb_ROMAN, 1, 1, NULL, NULL},
170   {"ROUND", &vb_ROUND, 1, 1, NULL, NULL},
171   {"ROUNDDOWN", &vb_ROUNDDOWN, 1, 1, NULL, NULL},
172   {"ROUNDUP", &vb_ROUNDUP, 1, 1, NULL, NULL},
173   {"SERIESSUM", &vb_SERIESSUM, 1, 1, NULL, NULL},
174   {"SIGN", &vb_SIGN, 1, 1, NULL, NULL},
175   {"SIN", &vb_SIN, 1, 1, NULL, NULL},
176   {"SINH", &vb_SINH, 1, 1, NULL, NULL},
177   {"SQRT", &vb_SQRT, 1, 1, NULL, NULL},
178   {"SQRTPI", &vb_SQRTPI, 1, 1, NULL, NULL},
179   {"SUM", &vb_SUM, 1, 1, NULL, NULL},
180   {"SUMIF", &vb_SUMIF, 1, 1, NULL, NULL},
181   {"SUMPRODUCT", &vb_SUMPRODUCT, 1, 1, NULL, NULL},
182   {"SUMSQ", &vb_SUMSQ, 1, 1, NULL, NULL},
183   {"SUMX2MY2", &vb_SUMX2MY2, 1, 1, NULL, NULL},
184   {"SUMX2PY2", &vb_SUMX2PY2, 1, 1, NULL, NULL},
185   {"SUMXMY2", &vb_SUMXMY2, 1, 1, NULL, NULL},
186   {"TAN", &vb_TAN, 1, 1, NULL, NULL},
187   {"TANH", &vb_TANH, 1, 1, NULL, NULL},
188   {"TRUNC", &vb_TRUNC, 1, 1, NULL, NULL},
189   {NULL, NULL, 0, 0, NULL, NULL},
190 };
191 
192 
193 
194 
195 
196 
197 #ifndef PI
198 #define PI 3.14159265359
199 #endif
200 
201 int
makeif(obj value,char * criteria)202 makeif (obj value, char *criteria)
203 {
204   obj val;
205   int doit = 0;
206   char *formula = NULL;
207   int len = 0;
208   int ret = 0;
209 
210   if (criteria == NULL)
211     return 0;
212 
213   len = strlen (criteria);
214 
215   switch (value.type)
216     {
217     case INTEGER:
218       formula = (char *) absmalloc ((len + 20) * sizeof (char), "makeif:formula");
219       sprintf (formula, "%d%s", value.rec.i, criteria);
220       doit = 1;
221       break;
222     case DOUBLE:
223       formula = (char *) absmalloc ((len + 32) * sizeof (char), "makeif:formula");
224       sprintf (formula, "%f%s", value.rec.d, criteria);
225       doit = 1;
226       break;
227     case STRING_CONSTANT:
228       if (value.rec.s == NULL)
229 	break;
230       formula = (char *) absmalloc ((len + strlen (value.rec.s) + 8) * sizeof (char), "makeif:formula");
231       sprintf (formula, "\"%s\"=\"%s\"", value.rec.s, criteria);
232       doit = 1;
233       break;
234     }
235   if (doit)
236     {
237       seteqboolean ();
238       val = exint (parseexpression (formula));
239       unseteqboolean ();
240       if (obj2int (val))
241 	ret = 1;
242       absfree (formula, "makeif:formula");
243     }
244   return ret;
245 }
246 
247 
248 obj
vb_ABS(int narg,obj * arg)249 vb_ABS (int narg, obj * arg)
250 {
251   obj o;
252   o.rec.d = abs (obj2double (arg[0]));
253   o.type = DOUBLE;
254   return o;
255 }
256 obj
vb_ACOS(int narg,obj * arg)257 vb_ACOS (int narg, obj * arg)
258 {
259   obj o;
260   o.rec.d = acos (obj2double (arg[0]));
261   o.type = DOUBLE;
262   return o;
263 }
264 obj
vb_ACOSH(int narg,obj * arg)265 vb_ACOSH (int narg, obj * arg)
266 {
267   obj o;
268   o.rec.d = acosh (obj2double (arg[0]));
269   o.type = DOUBLE;
270   return o;
271 }
272 obj
vb_ASIN(int narg,obj * arg)273 vb_ASIN (int narg, obj * arg)
274 {
275   obj o;
276   o.rec.d = asin (obj2double (arg[0]));
277   o.type = DOUBLE;
278   return o;
279 }
280 obj
vb_ASINH(int narg,obj * arg)281 vb_ASINH (int narg, obj * arg)
282 {
283   obj o;
284   o.rec.d = asinh (obj2double (arg[0]));
285   o.type = DOUBLE;
286   return o;
287 }
288 obj
vb_ATAN(int narg,obj * arg)289 vb_ATAN (int narg, obj * arg)
290 {
291   obj o;
292   o.rec.d = atan (obj2double (arg[0]));
293   o.type = DOUBLE;
294   return o;
295 }
296 obj
vb_ATAN2(int narg,obj * arg)297 vb_ATAN2 (int narg, obj * arg)
298 {
299   obj o;
300   o.rec.d = atan2 (obj2double (arg[0]), obj2double (arg[1]));
301   o.type = DOUBLE;
302   return o;
303 }
304 obj
vb_ATANH(int narg,obj * arg)305 vb_ATANH (int narg, obj * arg)
306 {
307   obj o;
308   o.rec.d = atanh (obj2double (arg[0]));
309   o.type = DOUBLE;
310   return o;
311 }
312 obj
vb_CEILING(int narg,obj * arg)313 vb_CEILING (int narg, obj * arg)
314 {
315 
316 
317 
318 
319 
320 
321   obj o;
322   double nombre = obj2double (arg[0]);
323   double multiple = obj2double (arg[1]);
324   double tmp = 0.0;
325   int n = 0;
326 
327   if (nombre * multiple > 0)
328     {
329       tmp = multiple;
330       while (fabs (tmp) < fabs (nombre) && n < 1000)
331 	{
332 	  tmp *= fabs (multiple);
333 	  n++;
334 	}
335       tmp /= multiple;
336     }
337 
338   o.rec.d = tmp;
339   o.type = DOUBLE;
340   return o;
341 }
342 
343 int
fact(int n)344 fact (int n)
345 {
346   int i;
347   int val = 1.0;
348   for (i = 2; i <= n && i < 200; i++)
349     val *= i;
350   return val;
351 }
352 
353 obj
vb_COMBIN(int narg,obj * arg)354 vb_COMBIN (int narg, obj * arg)
355 {
356   obj o;
357   int n;
358   int k;
359   double a, b;
360 
361   k = obj2int (arg[1]);
362   n = obj2int (arg[0]);
363 
364   if (n > 0 && k > 0 && n > k)
365     {
366       a = fact (n);
367       b = fact (k) * fact (n - k);
368       o.rec.d = a / b;
369     }
370   else
371     {
372       o.rec.d = 0;
373     }
374 
375   o.type = DOUBLE;
376   return o;
377 }
378 
379 obj
vb_COS(int narg,obj * arg)380 vb_COS (int narg, obj * arg)
381 {
382   obj o;
383   o.rec.d = cos (obj2double (arg[0]));
384   o.type = DOUBLE;
385   return o;
386 }
387 obj
vb_COSH(int narg,obj * arg)388 vb_COSH (int narg, obj * arg)
389 {
390   obj o;
391   o.rec.d = cosh (obj2double (arg[0]));
392   o.type = DOUBLE;
393   return o;
394 }
395 obj
vb_COUNTIF(int narg,obj * arg)396 vb_COUNTIF (int narg, obj * arg)
397 {
398   obj o;
399   obj tmp;
400   int i, r, c;
401   int ret = 0;
402   tmpRange *ran;
403   o.type = INTEGER;
404   o.rec.i = 0;
405   if (narg < 2)
406     return o;
407   if (arg[0].type != STRING_CONSTANT && arg[0].type != STRING)
408     return o;
409   if (arg[0].rec.s == NULL)
410     return o;
411 
412   for (i = 1; i < narg; i++)
413     {
414       if (arg[i].type == RANGE)
415 	{
416 	  ran = (tmpRange *) arg[i].rec.s;
417 	  if (ran->wks == NULL)
418 	    {
419 	      for (r = ran->r1; r <= ran->r2; r++)
420 		for (c = ran->c1; c <= ran->c2; c++)
421 		  {
422 		    tmp = get_ovalue (r, c);
423 		    ret += makeif (tmp, arg[0].rec.s);
424 		  }
425 	    }
426 	  else
427 	    {
428 	      for (r = ran->r1; r <= ran->r2; r++)
429 		for (c = ran->c1; c <= ran->c2; c++)
430 		  {
431 		    tmp = get_ovalue_wks (ran->wks, r, c);
432 		    ret += makeif (tmp, arg[0].rec.s);
433 		  }
434 	    }
435 	}
436       else
437 	{
438 	  tmp = id2val (arg[i]);
439 	  ret += makeif (tmp, arg[0].rec.s);
440 	}
441     }
442 
443   o.rec.i = ret;
444   return o;
445 }
446 
447 obj
vb_DEGREES(int narg,obj * arg)448 vb_DEGREES (int narg, obj * arg)
449 {
450   obj o;
451   o.rec.d = 180.0 / PI * (obj2double (arg[0]));
452   o.type = DOUBLE;
453   return o;
454 }
455 obj
vb_EVEN(int narg,obj * arg)456 vb_EVEN (int narg, obj * arg)
457 {
458   obj o;
459 
460   ABVInform ("EVEN not yet implemented");
461   o.type = DOUBLE;
462   return o;
463 }
464 
465 obj
vb_EXP(int narg,obj * arg)466 vb_EXP (int narg, obj * arg)
467 {
468   obj o;
469   double x, y;
470 
471   x = obj2double (arg[0]);
472   y = obj2double (arg[1]);
473   o.rec.d = pow (x, y);
474   o.type = DOUBLE;
475   return o;
476 }
477 obj
vb_FACT(int narg,obj * arg)478 vb_FACT (int narg, obj * arg)
479 {
480   obj o;
481   o.rec.d = fact (obj2int (arg[0]));
482   o.type = DOUBLE;
483   return o;
484 }
485 obj
vb_FACTDOUBLE(int narg,obj * arg)486 vb_FACTDOUBLE (int narg, obj * arg)
487 {
488   obj o;
489   o.rec.d = fact (obj2int (arg[0]));
490   o.type = DOUBLE;
491   return o;
492 }
493 obj
vb_FLOOR(int narg,obj * arg)494 vb_FLOOR (int narg, obj * arg)
495 {
496   obj o;
497   o.rec.d = floor (obj2double (arg[0]));
498   o.type = DOUBLE;
499   return o;
500 }
501 obj
vb_GCD(int narg,obj * arg)502 vb_GCD (int narg, obj * arg)
503 {
504   obj o;
505   int i;
506   int f = 1;
507   double div = 2;
508   while (f)
509     {
510       for (i = 0; i < narg; i++)
511 	{
512 	  if (fmod (obj2double (arg[0]), div) != 0)
513 	    f = 0;
514 	}
515       div++;
516     }
517   div--;
518   o.rec.d = div;
519   o.type = DOUBLE;
520   return o;
521 }
522 
523 obj
vb_INT(int narg,obj * arg)524 vb_INT (int narg, obj * arg)
525 {
526   obj o;
527   double val = obj2double (arg[0]);
528   o.rec.d = rint (val);
529   o.type = DOUBLE;
530   return o;
531 }
532 obj
vb_LCM(int narg,obj * arg)533 vb_LCM (int narg, obj * arg)
534 {
535   obj o;
536 
537   ABVInform ("LCM not yet implemented");
538   o.type = DOUBLE;
539   return o;
540 }
541 obj
vb_LN(int narg,obj * arg)542 vb_LN (int narg, obj * arg)
543 {
544   obj o;
545   o.rec.d = log (obj2double (arg[0]));
546   o.type = DOUBLE;
547   return o;
548 }
549 obj
vb_LOG(int narg,obj * arg)550 vb_LOG (int narg, obj * arg)
551 {
552   obj o;
553   o.rec.d = log10 (obj2double (arg[0]));
554   o.type = DOUBLE;
555   return o;
556 }
557 obj
vb_LOG10(int narg,obj * arg)558 vb_LOG10 (int narg, obj * arg)
559 {
560   obj o;
561   o.rec.d = log10 (obj2double (arg[0]));
562   o.type = DOUBLE;
563   return o;
564 }
565 obj
vb_MDETERM(int narg,obj * arg)566 vb_MDETERM (int narg, obj * arg)
567 {
568   obj o;
569 
570   ABVInform ("MDETERM not yet implemented");
571   o.type = DOUBLE;
572   return o;
573 }
574 obj
vb_MINVERSE(int narg,obj * arg)575 vb_MINVERSE (int narg, obj * arg)
576 {
577   obj o;
578 
579   ABVInform ("MINVERSE not yet implemented");
580   o.type = DOUBLE;
581   return o;
582 }
583 obj
vb_MMULT(int narg,obj * arg)584 vb_MMULT (int narg, obj * arg)
585 {
586   obj o;
587 
588   ABVInform ("MMULT not yet implemented");
589   o.type = DOUBLE;
590   return o;
591 }
592 obj
vb_MOD(int narg,obj * arg)593 vb_MOD (int narg, obj * arg)
594 {
595   obj o;
596   o.rec.d = fmod (obj2double (arg[0]), obj2double (arg[1]));
597   o.type = DOUBLE;
598   return o;
599 }
600 obj
vb_MROUND(int narg,obj * arg)601 vb_MROUND (int narg, obj * arg)
602 {
603   obj o;
604 
605   ABVInform (" MROUND not yet implemented");
606 
607   o.type = DOUBLE;
608   return o;
609 }
610 obj
vb_MULTINOMIAL(int narg,obj * arg)611 vb_MULTINOMIAL (int narg, obj * arg)
612 {
613   obj o;
614 
615   ABVInform ("MULTINOMIAL not yet implemented");
616 
617   o.type = DOUBLE;
618   return o;
619 }
620 obj
vb_ODD(int narg,obj * arg)621 vb_ODD (int narg, obj * arg)
622 {
623   obj o;
624 
625   ABVInform ("ODD not yet implemented");
626   o.type = DOUBLE;
627   return o;
628 }
629 obj
vb_PI(int narg,obj * arg)630 vb_PI (int narg, obj * arg)
631 {
632   obj o;
633   o.rec.d = PI;
634   o.type = DOUBLE;
635   return o;
636 }
637 obj
vb_POWER(int narg,obj * arg)638 vb_POWER (int narg, obj * arg)
639 {
640   obj o;
641   o.rec.d = pow (obj2double (arg[0]), obj2double (arg[1]));
642   o.type = DOUBLE;
643   return o;
644 }
645 obj
vb_PRODUCT(int narg,obj * arg)646 vb_PRODUCT (int narg, obj * arg)
647 {
648   obj o;
649   int r, c;
650   tmpRange *ran;
651   double val = 1;
652   int i;
653   for (i = 0; i < narg; i++)
654     {
655       if (arg[i].type == RANGE)
656 	{
657 	  ran = (tmpRange *) arg[i].rec.s;
658 	  if (ran->wks == NULL)
659 	    {
660 	      for (r = ran->r1; r <= ran->r2; r++)
661 		for (c = ran->c1; c <= ran->c2; c++)
662 		  val *= get_value (r, c);
663 	    }
664 	  else
665 	    {
666 	      for (r = ran->r1; r <= ran->r2; r++)
667 		for (c = ran->c1; c <= ran->c2; c++)
668 		  val *= get_value_wks (ran->wks, r, c);
669 	    }
670 	}
671       else
672 	val *= obj2double (arg[i]);
673     }
674   o.rec.d = val;
675   o.type = DOUBLE;
676   return o;
677 }
678 
679 obj
vb_QUOTIENT(int narg,obj * arg)680 vb_QUOTIENT (int narg, obj * arg)
681 {
682   obj o;
683 
684   o.rec.d = 0.0;
685   o.type = DOUBLE;
686   return o;
687 }
688 
689 obj
vb_RADIANS(int narg,obj * arg)690 vb_RADIANS (int narg, obj * arg)
691 {
692   obj o;
693   o.rec.d = PI / 180.0 * (obj2double (arg[0]));
694   o.type = DOUBLE;
695   return o;
696 }
697 obj
vb_RAND(int narg,obj * arg)698 vb_RAND (int narg, obj * arg)
699 {
700   obj o;
701   o.rec.d = 0.0 + (1.0 * rand () / (RAND_MAX + 1.0));
702   o.type = DOUBLE;
703   return o;
704 }
705 obj
vb_RANDBETWEEN(int narg,obj * arg)706 vb_RANDBETWEEN (int narg, obj * arg)
707 {
708   obj o;
709   double low = obj2double (arg[0]);
710   double up = obj2double (arg[1]);
711 
712   o.rec.d = low + (up * rand () / (RAND_MAX + 1.0));
713   o.type = DOUBLE;
714   return o;
715 }
716 obj
vb_ROMAN(int narg,obj * arg)717 vb_ROMAN (int narg, obj * arg)
718 {
719   obj o;
720 
721   ABVInform ("ROMAN not yet implemented");
722   o.type = DOUBLE;
723   return o;
724 }
725 obj
vb_ROUND(int narg,obj * arg)726 vb_ROUND (int narg, obj * arg)
727 {
728   obj o;
729   double val = obj2double (arg[0]);
730   double ndeci = 0;
731   int valint;
732   if (narg > 1)
733     ndeci = obj2double (arg[1]);
734 
735   if (ndeci >= 0)
736     {
737       valint = rint (val * pow (10, ndeci));
738       val = valint * pow (10, -ndeci);
739     }
740   o.rec.d = val;
741 
742   o.type = DOUBLE;
743   return o;
744 }
745 obj
vb_ROUNDDOWN(int narg,obj * arg)746 vb_ROUNDDOWN (int narg, obj * arg)
747 {
748   obj o;
749   double val = obj2double (arg[0]);
750   double ndeci = 0;
751   if (narg > 1)
752     ndeci = obj2double (arg[1]);
753 
754   if (ndeci >= 0)
755     {
756       val *= pow (10, ndeci);
757       val = floor (val);
758       val *= pow (10, -ndeci);
759     }
760   o.rec.d = val;
761   o.type = DOUBLE;
762   return o;
763 }
764 obj
vb_ROUNDUP(int narg,obj * arg)765 vb_ROUNDUP (int narg, obj * arg)
766 {
767   obj o;
768   double val = obj2double (arg[0]);
769   double ndeci = 0;
770   if (narg > 1)
771     ndeci = obj2double (arg[1]);
772 
773   if (ndeci >= 0)
774     {
775       val *= pow (10, ndeci);
776       val = ceil (val);
777       val *= pow (10, -ndeci);
778     }
779   o.rec.d = val;
780   o.type = DOUBLE;
781   return o;
782 }
783 obj
vb_SERIESSUM(int narg,obj * arg)784 vb_SERIESSUM (int narg, obj * arg)
785 {
786   obj o;
787 
788   ABVInform ("SERIESSUM not yet implemented");
789   o.type = DOUBLE;
790   return o;
791 }
792 obj
vb_SIGN(int narg,obj * arg)793 vb_SIGN (int narg, obj * arg)
794 {
795   obj o;
796   double val = obj2double (arg[0]);
797   if (val > 0)
798     o.rec.d = 1;
799   else if (val < 0)
800     o.rec.d = -1;
801   else
802     o.rec.d = 0;
803   o.type = DOUBLE;
804   return o;
805 }
806 obj
vb_SIN(int narg,obj * arg)807 vb_SIN (int narg, obj * arg)
808 {
809   obj o;
810   o.rec.d = sin (obj2double (arg[0]));
811   o.type = DOUBLE;
812   return o;
813 }
814 obj
vb_SINH(int narg,obj * arg)815 vb_SINH (int narg, obj * arg)
816 {
817   obj o;
818   o.rec.d = sinh (obj2double (arg[0]));
819   o.type = DOUBLE;
820   return o;
821 }
822 obj
vb_SQRT(int narg,obj * arg)823 vb_SQRT (int narg, obj * arg)
824 {
825   obj o;
826   o.rec.d = sqrt (obj2double (arg[0]));
827   o.type = DOUBLE;
828   return o;
829 }
830 obj
vb_SQRTPI(int narg,obj * arg)831 vb_SQRTPI (int narg, obj * arg)
832 {
833   obj o;
834   o.rec.d = sqrt (PI * obj2double (arg[0]));
835   o.type = DOUBLE;
836   return o;
837 }
838 
839 obj
vb_SUM(int narg,obj * arg)840 vb_SUM (int narg, obj * arg)
841 {
842   obj o;
843   int r, c;
844   tmpRange *ran;
845   double val = 0;
846   int i;
847 
848   for (i = 0; i < narg; i++)
849     {
850       if (arg[i].type == RANGE)
851 	{
852 	  ran = (tmpRange *) arg[i].rec.s;
853 	  if (ran->wks == NULL)
854 	    {
855 	      for (r = ran->r1; r <= ran->r2; r++)
856 		for (c = ran->c1; c <= ran->c2; c++)
857 		  val += get_value (r, c);
858 	    }
859 	  else
860 	    {
861 	      for (r = ran->r1; r <= ran->r2; r++)
862 		for (c = ran->c1; c <= ran->c2; c++)
863 		  val += get_value_wks (ran->wks, r, c);
864 	    }
865 	}
866       else
867 	val += obj2double (arg[i]);
868     }
869   o.rec.d = val;
870   o.type = DOUBLE;
871   return o;
872 }
873 
874 obj
vb_SUMIF(int narg,obj * arg)875 vb_SUMIF (int narg, obj * arg)
876 {
877   obj o;
878   obj tmp;
879   int i, r, c;
880   double ret = 0;
881   tmpRange *ran;
882   o.type = DOUBLE;
883   o.rec.d = 0;
884   if (narg < 2)
885     return o;
886   if (arg[0].type != STRING_CONSTANT && arg[0].type != STRING)
887     return o;
888   if (arg[0].rec.s == NULL)
889     return o;
890 
891   for (i = 1; i < narg; i++)
892     {
893       if (arg[i].type == RANGE)
894 	{
895 	  ran = (tmpRange *) arg[i].rec.s;
896 	  if (ran->wks == NULL)
897 	    {
898 	      for (r = ran->r1; r <= ran->r2; r++)
899 		for (c = ran->c1; c <= ran->c2; c++)
900 		  {
901 		    tmp = get_ovalue (r, c);
902 		    if (makeif (tmp, arg[0].rec.s))
903 		      ret += obj2double (tmp);
904 		  }
905 	    }
906 	  else
907 	    {
908 	      for (r = ran->r1; r <= ran->r2; r++)
909 		for (c = ran->c1; c <= ran->c2; c++)
910 		  {
911 		    tmp = get_ovalue_wks (ran->wks, r, c);
912 		    if (makeif (tmp, arg[0].rec.s))
913 		      ret += obj2double (tmp);
914 		  }
915 	    }
916 	}
917       else
918 	{
919 	  tmp = id2val (arg[i]);
920 	  if (makeif (tmp, arg[0].rec.s))
921 	    ret += obj2double (tmp);
922 	}
923     }
924 
925   o.rec.d = ret;
926   return o;
927 }
928 
929 obj
vb_SUMPRODUCT(int narg,obj * arg)930 vb_SUMPRODUCT (int narg, obj * arg)
931 {
932   obj o;
933 
934   ABVInform ("SUMPRODUCT not yet implemented");
935   o.type = DOUBLE;
936   return o;
937 }
938 obj
vb_SUMSQ(int narg,obj * arg)939 vb_SUMSQ (int narg, obj * arg)
940 {
941   obj o;
942   int r, c;
943   tmpRange *ran;
944   double val = 0;
945   int i;
946   double tmp;
947   for (i = 0; i < narg; i++)
948     {
949       if (arg[i].type == RANGE)
950 	{
951 	  ran = (tmpRange *) arg[i].rec.s;
952 	  if (ran->wks == NULL)
953 	    {
954 	      for (r = ran->r1; r <= ran->r2; r++)
955 		for (c = ran->c1; c <= ran->c2; c++)
956 		  {
957 		    tmp = get_value (r, c);
958 		    val += tmp * tmp;
959 		  }
960 	    }
961 	  else
962 	    {
963 	      for (r = ran->r1; r <= ran->r2; r++)
964 		for (c = ran->c1; c <= ran->c2; c++)
965 		  {
966 		    tmp = get_value_wks (ran->wks, r, c);
967 		    val += tmp * tmp;
968 		  }
969 	    }
970 	}
971       else
972 	{
973 	  tmp = obj2double (arg[i]);
974 	  val += tmp * tmp;
975 	}
976     }
977   o.rec.d = val;
978   o.type = DOUBLE;
979   return o;
980 
981 }
982 obj
vb_SUMX2MY2(int narg,obj * arg)983 vb_SUMX2MY2 (int narg, obj * arg)
984 {
985   obj o;
986 
987   ABVInform ("SUMX2MY2 not yet implemented");
988   o.type = DOUBLE;
989   return o;
990 }
991 obj
vb_SUMX2PY2(int narg,obj * arg)992 vb_SUMX2PY2 (int narg, obj * arg)
993 {
994   obj o;
995 
996   ABVInform ("SUMX2PY2 not yet implemented");
997   o.type = DOUBLE;
998   return o;
999 }
1000 obj
vb_SUMXMY2(int narg,obj * arg)1001 vb_SUMXMY2 (int narg, obj * arg)
1002 {
1003   obj o;
1004 
1005   ABVInform ("SUMXMY2 not yet implemented");
1006   o.type = DOUBLE;
1007   return o;
1008 }
1009 obj
vb_TAN(int narg,obj * arg)1010 vb_TAN (int narg, obj * arg)
1011 {
1012   obj o;
1013   o.rec.d = tan (obj2double (arg[0]));
1014   o.type = DOUBLE;
1015   return o;
1016 }
1017 obj
vb_TANH(int narg,obj * arg)1018 vb_TANH (int narg, obj * arg)
1019 {
1020   obj o;
1021   o.rec.d = tanh (obj2double (arg[0]));
1022   o.type = DOUBLE;
1023   return o;
1024 }
1025 obj
vb_TRUNC(int narg,obj * arg)1026 vb_TRUNC (int narg, obj * arg)
1027 {
1028   obj o;
1029   double val = obj2double (arg[0]);
1030   double ndeci = 0;
1031   int valint;
1032   if (narg > 1)
1033     ndeci = obj2double (arg[1]);
1034 
1035   if (ndeci >= 0)
1036     {
1037       valint = val * pow (10, ndeci);
1038       val = valint * pow (10, -ndeci);
1039     }
1040   o.rec.d = val;
1041 
1042   o.type = DOUBLE;
1043   return o;
1044 }
1045