LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - batcalc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 649 870 74.6 %
Date: 2021-01-13 20:07:21 Functions: 50 76 65.8 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "gdk.h"
      11             : #include "mal_exception.h"
      12             : #include "mal_interpreter.h"
      13             : 
      14             : static str
      15          16 : mythrow(enum malexception type, const char *fcn, const char *msg)
      16             : {
      17          16 :         char *errbuf = GDKerrbuf;
      18             :         char *s;
      19             : 
      20          16 :         if (errbuf && *errbuf) {
      21          16 :                 if (strncmp(errbuf, "!ERROR: ", 8) == 0)
      22          16 :                         errbuf += 8;
      23          16 :                 if (strchr(errbuf, '!') == errbuf + 5) {
      24           0 :                         s = createException(type, fcn, "%s", errbuf);
      25          16 :                 } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') {
      26          16 :                         s = createException(type, fcn, "%s", s + 2);
      27             :                 } else {
      28           0 :                         s = createException(type, fcn, "%s", errbuf);
      29             :                 }
      30          16 :                 GDKclrerr();
      31          16 :                 return s;
      32             :         }
      33           0 :         return createException(type, fcn, "%s", msg);
      34             : }
      35             : 
      36             : static str
      37        9383 : CMDbatUNARY(MalStkPtr stk, InstrPtr pci,
      38             :                         BAT *(*batfunc)(BAT *, BAT *), const char *malfunc)
      39             : {
      40             :         bat bid;
      41             :         BAT *bn, *b, *s = NULL;
      42             : 
      43        9383 :         bid = *getArgReference_bat(stk, pci, 1);
      44        9383 :         if ((b = BATdescriptor(bid)) == NULL)
      45           0 :                 throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      46        9382 :         if (pci->argc == 3) {
      47         150 :                 bid = *getArgReference_bat(stk, pci, 2);
      48         150 :                 if (!is_bat_nil(bid)) {
      49         129 :                         if ((s = BATdescriptor(bid)) == NULL) {
      50           0 :                                 BBPunfix(b->batCacheid);
      51           0 :                                 throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      52             :                         }
      53             :                 }
      54             :         }
      55             : 
      56        9382 :         bn = (*batfunc)(b, s);
      57        9383 :         BBPunfix(b->batCacheid);
      58        9383 :         if (s)
      59         129 :                 BBPunfix(s->batCacheid);
      60        9383 :         if (bn == NULL) {
      61           0 :                 return mythrow(MAL, malfunc, OPERATION_FAILED);
      62             :         }
      63        9383 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
      64        9383 :         BBPkeepref(bn->batCacheid);
      65        9383 :         return MAL_SUCCEED;
      66             : }
      67             : 
      68             : static str
      69           0 : CMDbatUNARY1(MalStkPtr stk, InstrPtr pci, bool abort_on_error,
      70             :                          BAT *(*batfunc)(BAT *, BAT *, bool), const char *malfunc)
      71             : {
      72             :         bat bid;
      73             :         BAT *bn, *b, *s = NULL;
      74             : 
      75           0 :         bid = *getArgReference_bat(stk, pci, 1);
      76           0 :         if ((b = BATdescriptor(bid)) == NULL)
      77           0 :                 throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      78           0 :         if (pci->argc == 3) {
      79           0 :                 bid = *getArgReference_bat(stk, pci, 2);
      80           0 :                 if (!is_bat_nil(bid)) {
      81           0 :                         if ((s = BATdescriptor(bid)) == NULL) {
      82           0 :                                 BBPunfix(b->batCacheid);
      83           0 :                                 throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      84             :                         }
      85             :                 }
      86             :         }
      87             : 
      88           0 :         bn = (*batfunc)(b, s, abort_on_error);
      89           0 :         BBPunfix(b->batCacheid);
      90           0 :         if (s)
      91           0 :                 BBPunfix(s->batCacheid);
      92           0 :         if (bn == NULL) {
      93           0 :                 return mythrow(MAL, malfunc, OPERATION_FAILED);
      94             :         }
      95           0 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
      96           0 :         BBPkeepref(bn->batCacheid);
      97           0 :         return MAL_SUCCEED;
      98             : }
      99             : 
     100             : static str
     101           0 : CMDbatISZERO(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     102             : {
     103             :         (void) cntxt;
     104             :         (void) mb;
     105             : 
     106           0 :         return CMDbatUNARY(stk, pci, BATcalciszero, "batcalc.iszero");
     107             : }
     108             : 
     109             : static str
     110        2383 : CMDbatISNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     111             : {
     112             :         (void) cntxt;
     113             :         (void) mb;
     114             : 
     115        2383 :         return CMDbatUNARY(stk, pci, BATcalcisnil, "batcalc.isnil");
     116             : }
     117             : 
     118             : static str
     119        2016 : CMDbatISNOTNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     120             : {
     121             :         (void) cntxt;
     122             :         (void) mb;
     123             : 
     124        2016 :         return CMDbatUNARY(stk, pci, BATcalcisnotnil, "batcalc.isnotnil");
     125             : }
     126             : 
     127             : static str
     128         276 : CMDbatNOT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     129             : {
     130             :         (void) cntxt;
     131             :         (void) mb;
     132             : 
     133         276 :         return CMDbatUNARY(stk, pci, BATcalcnot, "batcalc.not");
     134             : }
     135             : 
     136             : static str
     137        4479 : CMDbatABS(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     138             : {
     139             :         (void) cntxt;
     140             :         (void) mb;
     141             : 
     142        4479 :         return CMDbatUNARY(stk, pci, BATcalcabsolute, "batcalc.abs");
     143             : }
     144             : 
     145             : static str
     146           0 : CMDbatINCR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     147             : {
     148             :         (void) cntxt;
     149             :         (void) mb;
     150             : 
     151           0 :         return CMDbatUNARY1(stk, pci, true, BATcalcincr, "batcalc.incr");
     152             : }
     153             : 
     154             : static str
     155           0 : CMDbatDECR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     156             : {
     157             :         (void) cntxt;
     158             :         (void) mb;
     159             : 
     160           0 :         return CMDbatUNARY1(stk, pci, true, BATcalcdecr, "batcalc.decr");
     161             : }
     162             : 
     163             : static str
     164         220 : CMDbatNEG(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     165             : {
     166             :         (void) cntxt;
     167             :         (void) mb;
     168             : 
     169         220 :         return CMDbatUNARY(stk, pci, BATcalcnegate, "batcalc.neg");
     170             : }
     171             : 
     172             : static str
     173           9 : CMDbatSIGN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     174             : {
     175             :         (void) cntxt;
     176             :         (void) mb;
     177             : 
     178           9 :         return CMDbatUNARY(stk, pci, BATcalcsign, "batcalc.sign");
     179             : }
     180             : 
     181             : static int
     182           0 : calctype(int tp1, int tp2)
     183             : {
     184           0 :         int tp1s = ATOMbasetype(tp1);
     185           0 :         int tp2s = ATOMbasetype(tp2);
     186           0 :         if (tp1s == TYPE_str && tp2s == TYPE_str)
     187             :                 return TYPE_str;
     188           0 :         if (tp1s < TYPE_flt && tp2s < TYPE_flt) {
     189           0 :                 if (tp1s > tp2s)
     190             :                         return tp1;
     191           0 :                 if (tp1s < tp2s)
     192             :                         return tp2;
     193           0 :                 return MAX(tp1, tp2);
     194             :         }
     195           0 :         if (tp1s == TYPE_dbl || tp2s == TYPE_dbl)
     196             :                 return TYPE_dbl;
     197           0 :         if (tp1s == TYPE_flt || tp2s == TYPE_flt)
     198             :                 return TYPE_flt;
     199             : #ifdef HAVE_HGE
     200           0 :         if (tp1s == TYPE_hge || tp2s == TYPE_hge)
     201           0 :                 return TYPE_hge;
     202             : #endif
     203             :         return TYPE_lng;
     204             : }
     205             : 
     206             : static int
     207           0 : calctypeenlarge(int tp1, int tp2)
     208             : {
     209           0 :         tp1 = calctype(tp1, tp2);
     210           0 :         switch (tp1) {
     211             :         case TYPE_bte:
     212             :                 return TYPE_sht;
     213           0 :         case TYPE_sht:
     214           0 :                 return TYPE_int;
     215           0 :         case TYPE_int:
     216           0 :                 return TYPE_lng;
     217             : #ifdef HAVE_HGE
     218           0 :         case TYPE_lng:
     219           0 :                 return TYPE_hge;
     220             : #endif
     221           0 :         case TYPE_flt:
     222           0 :                 return TYPE_dbl;
     223           0 :         default:
     224             :                 /* we shouldn't get here */
     225           0 :                 return tp1;
     226             :         }
     227             : }
     228             : 
     229             : static int
     230           0 : calcdivtype(int tp1, int tp2)
     231             : {
     232             :         /* if right hand side is floating point, the result is floating
     233             :          * point, otherwise the result has the type of the left hand
     234             :          * side */
     235           0 :         tp1 = ATOMbasetype(tp1);
     236           0 :         tp2 = ATOMbasetype(tp2);
     237           0 :         if (tp1 == TYPE_dbl || tp2 == TYPE_dbl)
     238             :                 return TYPE_dbl;
     239           0 :         if (tp1 == TYPE_flt || tp2 == TYPE_flt)
     240           0 :                 return TYPE_flt;
     241             :         return tp1;
     242             : }
     243             : 
     244             : #if 0
     245             : static int
     246             : calcdivtypeflt(int tp1, int tp2)
     247             : {
     248             :         (void) tp1;
     249             :         (void) tp2;
     250             :         return TYPE_flt;
     251             : }
     252             : 
     253             : static int
     254             : calcdivtypedbl(int tp1, int tp2)
     255             : {
     256             :         (void) tp1;
     257             :         (void) tp2;
     258             :         return TYPE_dbl;
     259             : }
     260             : #endif
     261             : 
     262             : static int
     263           0 : calcmodtype(int tp1, int tp2)
     264             : {
     265           0 :         tp1 = ATOMbasetype(tp1);
     266           0 :         tp2 = ATOMbasetype(tp2);
     267             :         assert(tp1 > 0 && tp1 < TYPE_str && tp1 != TYPE_bat && tp1 != TYPE_ptr);
     268             :         assert(tp2 > 0 && tp2 < TYPE_str && tp2 != TYPE_bat && tp2 != TYPE_ptr);
     269           0 :         if (tp1 == TYPE_dbl || tp2 == TYPE_dbl)
     270             :                 return TYPE_dbl;
     271           0 :         if (tp1 == TYPE_flt || tp2 == TYPE_flt)
     272             :                 return TYPE_flt;
     273           0 :         return MIN(tp1, tp2);
     274             : }
     275             : 
     276             : /* MAL function has one of the following signatures:
     277             :  * # without candidate list
     278             :  * func(b1:bat, b2:bat) :bat
     279             :  * func(b1:bat, v2:any) :bat
     280             :  * func(v1:any, b2:bat) :bat
     281             :  * # with candidate list
     282             :  * func(b1:bat, b2:bat, s1:bat, s2:bat) :bat
     283             :  * func(b1:bat, v2:any, s1:bat) :bat
     284             :  * func(v1:any, b2:bat, s2:bat) :bat
     285             :  */
     286             : static str
     287      116017 : CMDbatBINARY2(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
     288             :                           BAT *(*batfunc)(BAT *, BAT *, BAT *, BAT *, int, bool),
     289             :                           BAT *(batfunc1)(BAT *, const ValRecord *, BAT *, int, bool),
     290             :                           BAT *(batfunc2)(const ValRecord *, BAT *, BAT *, int, bool),
     291             :                           int (*typefunc)(int, int),
     292             :                           bool abort_on_error, const char *malfunc)
     293             : {
     294             :         bat bid;
     295             :         BAT *bn, *b1 = NULL, *b2 = NULL, *s1 = NULL, *s2 = NULL;
     296             :         int tp1, tp2, tp3;
     297             : 
     298      116017 :         tp1 = stk->stk[getArg(pci, 1)].vtype; /* first argument */
     299      116017 :         tp2 = stk->stk[getArg(pci, 2)].vtype; /* second argument */
     300      116017 :         tp3 = getArgType(mb, pci, 0);             /* return argument */
     301             :         assert(isaBatType(tp3));
     302      116017 :         tp3 = getBatType(tp3);
     303             : 
     304      116017 :         if (tp1 == TYPE_bat || isaBatType(tp1)) {
     305      115578 :                 bid = *getArgReference_bat(stk, pci, 1);
     306      115578 :                 b1 = BATdescriptor(bid);
     307      115574 :                 if (b1 == NULL)
     308           0 :                         goto bailout;
     309             :         }
     310             : 
     311      116013 :         if (tp2 == TYPE_bat || isaBatType(tp2)) {
     312       50287 :                 bid = *getArgReference_bat(stk, pci, 2);
     313       50287 :                 b2 = BATdescriptor(bid);
     314       50281 :                 if (b2 == NULL)
     315           0 :                         goto bailout;
     316             :         }
     317             : 
     318      116007 :         if (pci->argc > 4) {
     319             :                 assert(pci->argc == 5);
     320       49845 :                 bid = *getArgReference_bat(stk, pci, 4);
     321       49845 :                 if (!is_bat_nil(bid)) {
     322         135 :                         s2 = BATdescriptor(bid);
     323         135 :                         if (s2 == NULL)
     324           0 :                                 goto bailout;
     325             :                 }
     326             :         }
     327      116007 :         if (pci->argc > 3) {
     328      115971 :                 bid = *getArgReference_bat(stk, pci, 3);
     329      115971 :                 if (!is_bat_nil(bid)) {
     330        2224 :                         s1 = BATdescriptor(bid);
     331        2224 :                         if (s1 == NULL)
     332           0 :                                 goto bailout;
     333        2224 :                         if (b1 == NULL) {
     334             :                                 s2 = s1;
     335             :                                 s1 = NULL;
     336             :                         }
     337             :                 }
     338             :         }
     339             : 
     340      116007 :         if (b1 && b2) {
     341       49845 :                 if (tp3 == TYPE_any)
     342           0 :                         tp3 = (*typefunc)(b1->ttype, b2->ttype);
     343       49845 :                 bn = (*batfunc)(b1, b2, s1, s2, tp3, abort_on_error);
     344       66162 :         } else if (b1) {
     345       65726 :                 if (tp3 == TYPE_any)
     346           0 :                         tp3 = (*typefunc)(b1->ttype, tp2);
     347       65726 :                 bn = (*batfunc1)(b1, &stk->stk[getArg(pci, 2)], s1, tp3, abort_on_error);
     348         436 :         } else if (b2) {
     349         436 :                 if (tp3 == TYPE_any)
     350           0 :                         tp3 = (*typefunc)(tp1, b2->ttype);
     351         436 :                 bn = (*batfunc2)(&stk->stk[getArg(pci, 1)], b2, s2, tp3, abort_on_error);
     352             :         } else
     353           0 :                 goto bailout;                   /* cannot happen */
     354      116005 :         if (b1)
     355      115569 :                 BBPunfix(b1->batCacheid);
     356      116012 :         if (b2)
     357       50282 :                 BBPunfix(b2->batCacheid);
     358      115995 :         if (s1)
     359        2140 :                 BBPunfix(s1->batCacheid);
     360      115995 :         if (s2)
     361         219 :                 BBPunfix(s2->batCacheid);
     362      115990 :         if (bn == NULL)
     363           6 :                 return mythrow(MAL, malfunc, GDK_EXCEPTION);
     364      115984 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     365      115984 :         BBPkeepref(bn->batCacheid);
     366      115999 :         return MAL_SUCCEED;
     367             : 
     368           0 : bailout:
     369           0 :         if (b1)
     370           0 :                 BBPunfix(b1->batCacheid);
     371           0 :         if (b2)
     372           0 :                 BBPunfix(b2->batCacheid);
     373             : /* cannot happen
     374             :         if (s1)
     375             :                 BBPunfix(s1->batCacheid);
     376             : */
     377           0 :         if (s2)
     378           0 :                 BBPunfix(s2->batCacheid);
     379           0 :         throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     380             : }
     381             : 
     382             : /* MAL function has one of the signatures for CMDbatBINARY2, or one of
     383             :  * the following:
     384             :  * # without candidate list
     385             :  * func(b1:bat, b2:bat, abort_on_error:bit) :bat
     386             :  * func(b1:bat, v2:any, abort_on_error:bit) :bat
     387             :  * func(v1:any, b2:bat, abort_on_error:bit) :bat
     388             :  * # with candidate list
     389             :  * func(b1:bat, b2:bat, s1:bat, s2:bat, abort_on_error:bit) :bat
     390             :  * func(b1:bat, v2:any, s1:bat, abort_on_error:bit) :bat
     391             :  * func(v1:any, b2:bat, s2:bat, abort_on_error:bit) :bat
     392             :  */
     393             : static str
     394       33452 : CMDbatBINARY1(MalStkPtr stk, InstrPtr pci,
     395             :                           BAT *(*batfunc)(BAT *, BAT *, BAT *, BAT *, bool),
     396             :                           BAT *(*batfunc1)(BAT *, const ValRecord *, BAT *, bool),
     397             :                           BAT *(*batfunc2)(const ValRecord *, BAT *, BAT *, bool),
     398             :                           bool abort_on_error,
     399             :                           const char *malfunc)
     400             : {
     401             :         bat bid;
     402             :         BAT *bn, *b1 = NULL, *b2 = NULL, *s1 = NULL, *s2 = NULL;
     403             :         int tp1, tp2;
     404             : 
     405       33452 :         tp1 = stk->stk[getArg(pci, 1)].vtype; /* first argument */
     406       33452 :         tp2 = stk->stk[getArg(pci, 2)].vtype; /* second argument */
     407             : 
     408       33452 :         if (tp1 == TYPE_bat || isaBatType(tp1)) {
     409       33314 :                 bid = *getArgReference_bat(stk, pci, 1);
     410       33314 :                 b1 = BATdescriptor(bid);
     411       33315 :                 if (b1 == NULL)
     412           0 :                         goto bailout;
     413             :         }
     414             : 
     415       33453 :         if (tp2 == TYPE_bat || isaBatType(tp2)) {
     416       29644 :                 bid = *getArgReference_bat(stk, pci, 2);
     417       29644 :                 b2 = BATdescriptor(bid);
     418       29641 :                 if (b2 == NULL)
     419           0 :                         goto bailout;
     420             :         }
     421             : 
     422       33450 :         if (pci->argc > 5) {
     423             :                 assert(pci->argc == 6);
     424           0 :                 abort_on_error = *getArgReference_bit(stk, pci, 5);
     425             :         }
     426       33450 :         if (pci->argc > 4) {
     427        6649 :                 if (stk->stk[getArg(pci, 4)].vtype == TYPE_bat) {
     428        6649 :                         bid = *getArgReference_bat(stk, pci, 4);
     429        6649 :                         if (!is_bat_nil(bid)) {
     430          74 :                                 s2 = BATdescriptor(bid);
     431          74 :                                 if (s2 == NULL)
     432           0 :                                         goto bailout;
     433             :                         }
     434             :                 } else {
     435             :                         assert(pci->argc == 5);
     436           0 :                         abort_on_error = *getArgReference_bit(stk, pci, 4);
     437             :                 }
     438             :         }
     439       33450 :         if (pci->argc > 3) {
     440       16820 :                 if (stk->stk[getArg(pci, 3)].vtype == TYPE_bat) {
     441        9340 :                         bid = *getArgReference_bat(stk, pci, 3);
     442        9340 :                         if (!is_bat_nil(bid)) {
     443        2564 :                                 s1 = BATdescriptor(bid);
     444        2566 :                                 if (s1 == NULL)
     445           0 :                                         goto bailout;
     446        2566 :                                 if (b1 == NULL) {
     447             :                                         s2 = s1;
     448             :                                         s1 = NULL;
     449             :                                 }
     450             :                         }
     451             :                 } else {
     452             :                         assert(pci->argc == 4);
     453        7480 :                         abort_on_error = *getArgReference_bit(stk, pci, 3);
     454             :                 }
     455             :         }
     456             : 
     457       33452 :         if (b1 && b2)
     458       29503 :                 bn = (*batfunc)(b1, b2, s1, s2, abort_on_error);
     459        3949 :         else if (b1)
     460        3811 :                 bn = (*batfunc1)(b1, &stk->stk[getArg(pci, 2)], s1, abort_on_error);
     461         138 :         else if (b2)
     462         138 :                 bn = (*batfunc2)(&stk->stk[getArg(pci, 1)], b2, s2, abort_on_error);
     463             :         else
     464           0 :                 goto bailout;                   /* cannot happen */
     465       33450 :         if (b1)
     466       33312 :                 BBPunfix(b1->batCacheid);
     467       33451 :         if (b2)
     468       29641 :                 BBPunfix(b2->batCacheid);
     469       33448 :         if (s1)
     470        2496 :                 BBPunfix(s1->batCacheid);
     471       33449 :         if (s2)
     472         143 :                 BBPunfix(s2->batCacheid);
     473       33449 :         if (bn == NULL)
     474           0 :                 return mythrow(MAL, malfunc, GDK_EXCEPTION);
     475       33449 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     476       33449 :         BBPkeepref(bn->batCacheid);
     477       33453 :         return MAL_SUCCEED;
     478             : 
     479           0 : bailout:
     480           0 :         if (b1)
     481           0 :                 BBPunfix(b1->batCacheid);
     482           0 :         if (b2)
     483           0 :                 BBPunfix(b2->batCacheid);
     484             : /* cannot happen
     485             :         if (s1)
     486             :                 BBPunfix(s1->batCacheid);
     487             : */
     488           0 :         if (s2)
     489           0 :                 BBPunfix(s2->batCacheid);
     490           0 :         throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     491             : }
     492             : 
     493             : /* MAL function has one of the signatures for CMDbatBINARY2
     494             :  */
     495             : static str
     496       38862 : CMDbatBINARY0(MalStkPtr stk, InstrPtr pci,
     497             :                           BAT *(*batfunc)(BAT *, BAT *, BAT *, BAT *),
     498             :                           BAT *(*batfunc1)(BAT *, const ValRecord *, BAT *),
     499             :                           BAT *(*batfunc2)(const ValRecord *, BAT *, BAT *),
     500             :                           const char *malfunc)
     501             : {
     502             :         bat bid;
     503             :         BAT *bn, *b1 = NULL, *b2 = NULL, *s1 = NULL, *s2 = NULL;
     504             :         int tp1, tp2;
     505             : 
     506       38862 :         tp1 = stk->stk[getArg(pci, 1)].vtype; /* first argument */
     507       38862 :         tp2 = stk->stk[getArg(pci, 2)].vtype; /* second argument */
     508             : 
     509       38862 :         if (tp1 == TYPE_bat || isaBatType(tp1)) {
     510       38797 :                 bid = *getArgReference_bat(stk, pci, 1);
     511       38797 :                 b1 = BATdescriptor(bid);
     512       38791 :                 if (b1 == NULL)
     513           0 :                         goto bailout;
     514             :         }
     515             : 
     516       38856 :         if (tp2 == TYPE_bat || isaBatType(tp2)) {
     517       37941 :                 bid = *getArgReference_bat(stk, pci, 2);
     518       37941 :                 b2 = BATdescriptor(bid);
     519       37942 :                 if (b2 == NULL)
     520           0 :                         goto bailout;
     521             :         }
     522             : 
     523       38857 :         if (pci->argc > 4) {
     524             :                 assert(pci->argc == 5);
     525        5372 :                 bid = *getArgReference_bat(stk, pci, 4);
     526        5372 :                 if (!is_bat_nil(bid)) {
     527        2399 :                         s2 = BATdescriptor(bid);
     528        2400 :                         if (s2 == NULL)
     529           0 :                                 goto bailout;
     530             :                 }
     531             :         }
     532       38858 :         if (pci->argc > 3) {
     533        5676 :                 bid = *getArgReference_bat(stk, pci, 3);
     534        5676 :                 if (!is_bat_nil(bid)) {
     535        2578 :                         s1 = BATdescriptor(bid);
     536        2578 :                         if (s1 == NULL)
     537           0 :                                 goto bailout;
     538        2578 :                         if (b1 == NULL) {
     539             :                                 s2 = s1;
     540             :                                 s1 = NULL;
     541             :                         }
     542             :                 }
     543             :         }
     544             : 
     545       38858 :         if (b1 && b2)
     546       37878 :                 bn = (*batfunc)(b1, b2, s1, s2);
     547         980 :         else if (b1)
     548         915 :                 bn = (*batfunc1)(b1, &stk->stk[getArg(pci, 2)], s1);
     549          65 :         else if (b2)
     550          65 :                 bn = (*batfunc2)(&stk->stk[getArg(pci, 1)], b2, s2);
     551             :         else
     552           0 :                 goto bailout;                   /* cannot happen */
     553       38861 :         if (b1)
     554       38796 :                 BBPunfix(b1->batCacheid);
     555       38864 :         if (b2)
     556       37949 :                 BBPunfix(b2->batCacheid);
     557       38863 :         if (s1)
     558        2578 :                 BBPunfix(s1->batCacheid);
     559       38863 :         if (s2)
     560        2400 :                 BBPunfix(s2->batCacheid);
     561       38862 :         if (bn == NULL)
     562           2 :                 return mythrow(MAL, malfunc, GDK_EXCEPTION);
     563       38860 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     564       38860 :         BBPkeepref(bn->batCacheid);
     565       38862 :         return MAL_SUCCEED;
     566             : 
     567           0 : bailout:
     568           0 :         if (b1)
     569           0 :                 BBPunfix(b1->batCacheid);
     570           0 :         if (b2)
     571           0 :                 BBPunfix(b2->batCacheid);
     572             : /* cannot happen
     573             :         if (s1)
     574             :                 BBPunfix(s1->batCacheid);
     575             : */
     576           0 :         if (s2)
     577           0 :                 BBPunfix(s2->batCacheid);
     578           0 :         throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     579             : }
     580             : 
     581             : static str
     582         357 : CMDbatMIN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     583             : {
     584             :         (void) cntxt;
     585             :         (void) mb;
     586             : 
     587         357 :         return CMDbatBINARY0(stk, pci, BATcalcmin, BATcalcmincst, BATcalccstmin, "batcalc.min");
     588             : }
     589             : 
     590             : static str
     591          19 : CMDbatMIN_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     592             : {
     593             :         (void) cntxt;
     594             :         (void) mb;
     595             : 
     596          19 :         return CMDbatBINARY0(stk, pci, BATcalcmin_no_nil, BATcalcmincst_no_nil, BATcalccstmin_no_nil, "batcalc.min_no_nil");
     597             : }
     598             : 
     599             : static str
     600           3 : CMDbatMAX(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     601             : {
     602             :         (void) cntxt;
     603             :         (void) mb;
     604             : 
     605           3 :         return CMDbatBINARY0(stk, pci, BATcalcmax, BATcalcmaxcst, BATcalccstmax, "batcalc.max");
     606             : }
     607             : 
     608             : static str
     609           7 : CMDbatMAX_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     610             : {
     611             :         (void) cntxt;
     612             :         (void) mb;
     613             : 
     614           7 :         return CMDbatBINARY0(stk, pci, BATcalcmax_no_nil, BATcalcmaxcst_no_nil, BATcalccstmax_no_nil, "batcalc.max_no_nil");
     615             : }
     616             : 
     617             : static str
     618        1097 : CMDbatADD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     619             : {
     620             :         (void) cntxt;
     621             : 
     622        1097 :         return CMDbatBINARY2(mb, stk, pci, BATcalcadd, BATcalcaddcst, BATcalccstadd,
     623             :                                                  calctype, 0, "batcalc.add_noerror");
     624             : }
     625             : 
     626             : static str
     627       60617 : CMDbatADDsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     628             : {
     629             :         (void) cntxt;
     630             : 
     631       60617 :         return CMDbatBINARY2(mb, stk, pci, BATcalcadd, BATcalcaddcst, BATcalccstadd,
     632             :                                                  calctype, 1, "batcalc.+");
     633             : }
     634             : 
     635             : static str
     636           0 : CMDbatADDenlarge(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     637             : {
     638             :         (void) cntxt;
     639             : 
     640           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcadd, BATcalcaddcst, BATcalccstadd,
     641             :                                                  calctypeenlarge, 1, "batcalc.add_enlarge");
     642             : }
     643             : 
     644             : static str
     645           0 : CMDbatSUB(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     646             : {
     647             :         (void) cntxt;
     648             : 
     649           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcsub, BATcalcsubcst, BATcalccstsub,
     650             :                                                  calctype, 0, "batcalc.sub_noerror");
     651             : }
     652             : 
     653             : static str
     654       27633 : CMDbatSUBsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     655             : {
     656             :         (void) cntxt;
     657             : 
     658       27633 :         return CMDbatBINARY2(mb, stk, pci, BATcalcsub, BATcalcsubcst, BATcalccstsub,
     659             :                                                  calctype, 1, "batcalc.-");
     660             : }
     661             : 
     662             : static str
     663           0 : CMDbatSUBenlarge(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     664             : {
     665             :         (void) cntxt;
     666             : 
     667           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcsub, BATcalcsubcst, BATcalccstsub,
     668             :                                                  calctypeenlarge, 1, "batcalc.sub_enlarge");
     669             : }
     670             : 
     671             : static str
     672           0 : CMDbatMUL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     673             : {
     674             :         (void) cntxt;
     675             : 
     676           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcmul, BATcalcmulcst, BATcalccstmul,
     677             :                                                  calctype, 0, "batcalc.mul_noerror");
     678             : }
     679             : 
     680             : static str
     681        1375 : CMDbatMULsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     682             : {
     683             :         (void) cntxt;
     684             : 
     685        1375 :         return CMDbatBINARY2(mb, stk, pci, BATcalcmul, BATcalcmulcst, BATcalccstmul,
     686             :                                                  calctype, 1, "batcalc.*");
     687             : }
     688             : 
     689             : static str
     690       21806 : CMDbatMULenlarge(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     691             : {
     692             :         (void) cntxt;
     693             : 
     694       21806 :         return CMDbatBINARY2(mb, stk, pci, BATcalcmul, BATcalcmulcst, BATcalccstmul,
     695             :                                                  calctypeenlarge, 1, "batcalc.mul_enlarge");
     696             : }
     697             : 
     698             : static str
     699           0 : CMDbatDIV(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     700             : {
     701             :         (void) cntxt;
     702             : 
     703           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcdiv, BATcalcdivcst, BATcalccstdiv,
     704             :                                                  calcdivtype, 0, "batcalc.div_noerror");
     705             : }
     706             : 
     707             : static str
     708        3449 : CMDbatDIVsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     709             : {
     710             :         (void) cntxt;
     711             : 
     712        3449 :         return CMDbatBINARY2(mb, stk, pci, BATcalcdiv, BATcalcdivcst, BATcalccstdiv,
     713             :                                                  calcdivtype, 1, "batcalc./");
     714             : }
     715             : 
     716             : static str
     717           0 : CMDbatMOD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     718             : {
     719             :         (void) cntxt;
     720             : 
     721           0 :         return CMDbatBINARY2(mb, stk, pci, BATcalcmod, BATcalcmodcst, BATcalccstmod,
     722             :                                                  calcmodtype, 0, "batcalc.mod_noerror");
     723             : }
     724             : 
     725             : static str
     726          41 : CMDbatMODsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     727             : {
     728             :         (void) cntxt;
     729             : 
     730          41 :         return CMDbatBINARY2(mb, stk, pci, BATcalcmod, BATcalcmodcst, BATcalccstmod,
     731             :                                                  calcmodtype, 1, "batcalc.%");
     732             : }
     733             : 
     734             : static str
     735           7 : CMDbatXOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     736             : {
     737             :         (void) cntxt;
     738             :         (void) mb;
     739             : 
     740           7 :         return CMDbatBINARY0(stk, pci, BATcalcxor, BATcalcxorcst, BATcalccstxor,
     741             :                                                  "batcalc.xor");
     742             : }
     743             : 
     744             : static str
     745         804 : CMDbatOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     746             : {
     747             :         (void) cntxt;
     748             :         (void) mb;
     749             : 
     750         804 :         return CMDbatBINARY0(stk, pci, BATcalcor, BATcalcorcst, BATcalccstor,
     751             :                                                  "batcalc.or");
     752             : }
     753             : 
     754             : static str
     755        1165 : CMDbatAND(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     756             : {
     757             :         (void) cntxt;
     758             :         (void) mb;
     759             : 
     760        1165 :         return CMDbatBINARY0(stk, pci, BATcalcand, BATcalcandcst, BATcalccstand,
     761             :                                                  "batcalc.and");
     762             : }
     763             : 
     764             : static str
     765           0 : CMDbatLSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     766             : {
     767             :         (void) cntxt;
     768             :         (void) mb;
     769             : 
     770           0 :         return CMDbatBINARY1(stk, pci, BATcalclsh, BATcalclshcst, BATcalccstlsh,
     771             :                                                  false, "batcalc.lsh_noerror");
     772             : }
     773             : 
     774             : static str
     775           6 : CMDbatLSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     776             : {
     777             :         (void) cntxt;
     778             :         (void) mb;
     779             : 
     780           6 :         return CMDbatBINARY1(stk, pci, BATcalclsh, BATcalclshcst, BATcalccstlsh,
     781             :                                                  true, "batcalc.<<");
     782             : }
     783             : 
     784             : static str
     785           0 : CMDbatRSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     786             : {
     787             :         (void) cntxt;
     788             :         (void) mb;
     789             : 
     790           0 :         return CMDbatBINARY1(stk, pci, BATcalcrsh, BATcalcrshcst, BATcalccstrsh,
     791             :                                                  false, "batcalc.rsh_noerror");
     792             : }
     793             : 
     794             : static str
     795          66 : CMDbatRSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     796             : {
     797             :         (void) cntxt;
     798             :         (void) mb;
     799             : 
     800          66 :         return CMDbatBINARY1(stk, pci, BATcalcrsh, BATcalcrshcst, BATcalccstrsh,
     801             :                                                  true, "batcalc.>>");
     802             : }
     803             : 
     804             : static str
     805       12287 : CMDbatLT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     806             : {
     807             :         (void) cntxt;
     808             :         (void) mb;
     809             : 
     810       12287 :         return CMDbatBINARY0(stk, pci, BATcalclt, BATcalcltcst, BATcalccstlt,
     811             :                                                  "batcalc.<");
     812             : }
     813             : 
     814             : static str
     815        5416 : CMDbatLE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     816             : {
     817             :         (void) cntxt;
     818             :         (void) mb;
     819             : 
     820        5416 :         return CMDbatBINARY0(stk, pci, BATcalcle, BATcalclecst, BATcalccstle,
     821             :                                                  "batcalc.<=");
     822             : }
     823             : 
     824             : static str
     825       15751 : CMDbatGT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     826             : {
     827             :         (void) cntxt;
     828             :         (void) mb;
     829             : 
     830       15751 :         return CMDbatBINARY0(stk, pci, BATcalcgt, BATcalcgtcst, BATcalccstgt,
     831             :                                                  "batcalc.>");
     832             : }
     833             : 
     834             : static str
     835        3049 : CMDbatGE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     836             : {
     837             :         (void) cntxt;
     838             :         (void) mb;
     839             : 
     840        3049 :         return CMDbatBINARY0(stk, pci, BATcalcge, BATcalcgecst, BATcalccstge,
     841             :                                                  "batcalc.>=");
     842             : }
     843             : 
     844             : static str
     845       32902 : CMDbatEQ(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     846             : {
     847             :         (void) cntxt;
     848             :         (void) mb;
     849             : 
     850       32902 :         return CMDbatBINARY1(stk, pci, BATcalceq, BATcalceqcst, BATcalccsteq,
     851             :                                                  false, "batcalc.==");
     852             : }
     853             : 
     854             : static str
     855         479 : CMDbatNE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     856             : {
     857             :         (void) cntxt;
     858             :         (void) mb;
     859             : 
     860         479 :         return CMDbatBINARY1(stk, pci, BATcalcne, BATcalcnecst, BATcalccstne,
     861             :                                                  false, "batcalc.!=");
     862             : }
     863             : 
     864             : static str
     865           0 : CMDbatCMP(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     866             : {
     867             :         (void) cntxt;
     868             :         (void) mb;
     869             : 
     870           0 :         return CMDbatBINARY0(stk, pci, BATcalccmp, BATcalccmpcst, BATcalccstcmp,
     871             :                                                  "batcalc.cmp");
     872             : }
     873             : 
     874             : static str
     875       16411 : CMDbatBETWEEN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     876             : {
     877             :         bat bid;
     878             :         BAT *bn, *b = NULL, *lo = NULL, *hi = NULL, *s = NULL, *slo = NULL, *shi = NULL;
     879             :         int tp1, tp2, tp3, tp;
     880             :         int bc = 0;                                     /* number of extra BAT arguments */
     881             :         bool symmetric, linc, hinc, nils_false, anti, has_cand = false;
     882             : 
     883             :         (void) cntxt;
     884             :         (void) mb;
     885             : 
     886       16411 :         tp1 = stk->stk[getArg(pci, 1)].vtype;
     887       16411 :         tp2 = stk->stk[getArg(pci, 2)].vtype;
     888       16411 :         tp3 = stk->stk[getArg(pci, 3)].vtype;
     889       16411 :         if (tp1 != TYPE_bat && !isaBatType(tp1))
     890           0 :                 goto bailout;
     891       16411 :         bid = *getArgReference_bat(stk, pci, 1);
     892       16411 :         b = BATdescriptor(bid);
     893       16410 :         if (b == NULL)
     894           0 :                 goto bailout;
     895       16410 :         if (tp2 == TYPE_bat || isaBatType(tp2)) {
     896       13120 :                 bid = *getArgReference_bat(stk, pci, 2);
     897       13120 :                 lo = BATdescriptor(bid);
     898       13120 :                 if (lo == NULL)
     899           0 :                         goto bailout;
     900             :         }
     901       16410 :         if (tp3 == TYPE_bat || isaBatType(tp3)) {
     902       13099 :                 bid = *getArgReference_bat(stk, pci, 3);
     903       13099 :                 hi = BATdescriptor(bid);
     904       13099 :                 if (hi == NULL)
     905           0 :                         goto bailout;
     906             :         }
     907       16410 :         tp = getArgType(mb, pci, 4);
     908       16410 :         if (tp == TYPE_bat || isaBatType(tp)) {
     909        9420 :                 bid = *getArgReference_bat(stk, pci, 4);
     910             :                 has_cand = true;
     911        9420 :                 if (!is_bat_nil(bid)) {
     912          81 :                         s = BATdescriptor(bid);
     913          81 :                         if (s == NULL)
     914           0 :                                 goto bailout;
     915             :                 }
     916             :                 bc++;
     917             :         }
     918       16410 :         if (has_cand && lo) {
     919        9389 :                 tp = getArgType(mb, pci, 4 + bc);
     920        9389 :                 if (tp == TYPE_bat || isaBatType(tp)) {
     921        9389 :                         bid = *getArgReference_bat(stk, pci, 4 + bc);
     922        9389 :                         if (!is_bat_nil(bid)) {
     923          32 :                                 slo = BATdescriptor(bid);
     924          32 :                                 if (slo == NULL)
     925           0 :                                         goto bailout;
     926             :                         }
     927        9389 :                         bc++;
     928             :                 } else {
     929           0 :                         if (s == NULL) {
     930             :                                 /* apparently the extra bat was a NIL conditional
     931             :                                  * execution bat */
     932             :                                 has_cand = false;
     933             :                         } else
     934           0 :                                 goto bailout;
     935             :                 }
     936             :         }
     937       16410 :         if (has_cand && hi) {
     938        9373 :                 tp = getArgType(mb, pci, 4 + bc);
     939        9373 :                 if (tp != TYPE_bat && !isaBatType(tp))
     940           0 :                         goto bailout;
     941        9373 :                 bid = *getArgReference_bat(stk, pci, 4 + bc);
     942        9373 :                 if (!is_bat_nil(bid)) {
     943          19 :                         shi = BATdescriptor(bid);
     944          19 :                         if (shi == NULL)
     945           0 :                                 goto bailout;
     946             :                 }
     947        9373 :                 bc++;
     948             :         }
     949             : 
     950       16410 :         symmetric = *getArgReference_bit(stk, pci, bc + 4);
     951       16410 :         linc = *getArgReference_bit(stk, pci, bc + 5);
     952       16410 :         hinc = *getArgReference_bit(stk, pci, bc + 6);
     953       16410 :         nils_false = *getArgReference_bit(stk, pci, bc + 7);
     954       16410 :         anti = *getArgReference_bit(stk, pci, bc + 8);
     955             : 
     956       16410 :         if (b && lo && hi)
     957       13071 :                 bn = BATcalcbetween(b, lo, hi, s, slo, shi,
     958             :                                                         symmetric, linc, hinc, nils_false, anti);
     959        3339 :         else if (b && lo)
     960          49 :                 bn = BATcalcbetweenbatcst(b, lo, &stk->stk[getArg(pci, 3)], s, slo,
     961             :                                                                   symmetric, linc, hinc, nils_false, anti);
     962        3290 :         else if (b && hi)
     963          27 :                 bn = BATcalcbetweencstbat(b, &stk->stk[getArg(pci, 2)], hi, s, shi,
     964             :                                                                   symmetric, linc, hinc, nils_false, anti);
     965             :         else
     966        3263 :                 bn = BATcalcbetweencstcst(b, &stk->stk[getArg(pci, 2)],
     967        3263 :                                                                   &stk->stk[getArg(pci, 3)], s,
     968             :                                                                   symmetric, linc, hinc, nils_false, anti);
     969       16397 :         BBPunfix(b->batCacheid);
     970       16409 :         if (lo)
     971       13118 :                 BBPunfix(lo->batCacheid);
     972       16411 :         if (hi)
     973       13098 :                 BBPunfix(hi->batCacheid);
     974       16410 :         if (s)
     975          81 :                 BBPunfix(s->batCacheid);
     976       16410 :         if (slo)
     977          32 :                 BBPunfix(slo->batCacheid);
     978       16410 :         if (shi)
     979          19 :                 BBPunfix(shi->batCacheid);
     980       16409 :         if (bn == NULL)
     981           0 :                 return mythrow(MAL, "batcalc.between", OPERATION_FAILED);
     982       16409 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     983       16409 :         BBPkeepref(bn->batCacheid);
     984       16409 :         return MAL_SUCCEED;
     985             : 
     986           0 :   bailout:
     987           0 :         if (b)
     988           0 :                 BBPunfix(b->batCacheid);
     989           0 :         if (lo)
     990           0 :                 BBPunfix(lo->batCacheid);
     991           0 :         if (hi)
     992           0 :                 BBPunfix(hi->batCacheid);
     993           0 :         if (s)
     994           0 :                 BBPunfix(s->batCacheid);
     995           0 :         if (slo)
     996           0 :                 BBPunfix(slo->batCacheid);
     997             : /* cannot happen
     998             :         if (shi)
     999             :                 BBPunfix(shi->batCacheid);
    1000             : */
    1001           0 :         throw(MAL, "batcalc.between", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1002             : }
    1003             : 
    1004             : static str
    1005        3981 : CMDcalcavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1006             : {
    1007             :         dbl avg;
    1008             :         BUN vals;
    1009             :         bat bid;
    1010             :         BAT *b, *s = NULL;
    1011             :         gdk_return ret;
    1012             :         int scale = 0;
    1013             : 
    1014             :         (void) cntxt;
    1015             :         (void) mb;
    1016             : 
    1017        3981 :         bid = *getArgReference_bat(stk, pci, pci->retc + 0);
    1018        3981 :         if ((b = BATdescriptor(bid)) == NULL)
    1019           0 :                 throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1020        3982 :         if ((pci->argc == pci->retc + 2 &&
    1021           0 :                  stk->stk[pci->argv[pci->retc + 1]].vtype == TYPE_bat) ||
    1022        3982 :                 pci->argc == pci->retc + 3) {
    1023           0 :                 bid = *getArgReference_bat(stk, pci, pci->retc + 1);
    1024           0 :                 if (!is_bat_nil(bid) && (s = BATdescriptor(bid)) == NULL) {
    1025           0 :                         BBPunfix(b->batCacheid);
    1026           0 :                         throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1027             :                 }
    1028             :         }
    1029        3982 :         if (pci->argc >= pci->retc + 2 &&
    1030           0 :                 stk->stk[pci->argv[pci->argc - 1]].vtype == TYPE_int) {
    1031           0 :                 scale = *getArgReference_int(stk, pci, pci->argc - 1);
    1032             :         }
    1033        3982 :         ret = BATcalcavg(b, s, &avg, &vals, scale);
    1034        3982 :         BBPunfix(b->batCacheid);
    1035        3982 :         if (s)
    1036           0 :                 BBPunfix(s->batCacheid);
    1037        3982 :         if (ret != GDK_SUCCEED)
    1038           0 :                 return mythrow(MAL, "aggr.avg", OPERATION_FAILED);
    1039        3982 :         * getArgReference_dbl(stk, pci, 0) = avg;
    1040        3982 :         if (pci->retc == 2)
    1041        3927 :                 * getArgReference_lng(stk, pci, 1) = vals;
    1042             :         return MAL_SUCCEED;
    1043             : }
    1044             : 
    1045             : static str
    1046      138069 : CMDconvertbat(MalStkPtr stk, InstrPtr pci, int tp, bool abort_on_error)
    1047             : {
    1048             :         bat bid;
    1049             :         BAT *b, *bn, *s = NULL;
    1050             : 
    1051      138069 :         bid = *getArgReference_bat(stk, pci, 1);
    1052      138069 :         if ((b = BATdescriptor(bid)) == NULL)
    1053           0 :                 throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1054      138045 :         if (pci->argc == 3) {
    1055       53872 :                 bid = *getArgReference_bat(stk, pci, 2);
    1056       53872 :                 if (!is_bat_nil(bid) && (s = BATdescriptor(bid)) == NULL) {
    1057           0 :                         BBPunfix(b->batCacheid);
    1058           0 :                         throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1059             :                 }
    1060       53890 :                 if (s && ATOMtype(s->ttype) != TYPE_oid) {
    1061           0 :                         BBPunfix(b->batCacheid);
    1062           0 :                         BBPunfix(s->batCacheid);
    1063           0 :                         throw(MAL, "batcalc.convert", SQLSTATE(42000) ILLEGAL_ARGUMENT);
    1064             :                 }
    1065             :         }
    1066             : 
    1067      138062 :         bn = BATconvert(b, s, tp, abort_on_error, 0, 0, 0);
    1068      138055 :         BBPunfix(b->batCacheid);
    1069      138042 :         if (s)
    1070       53875 :                 BBPunfix(s->batCacheid);
    1071      138041 :         if (bn == NULL) {
    1072             :                 char buf[20];
    1073           8 :                 snprintf(buf, sizeof(buf), "batcalc.%s", ATOMname(tp));
    1074           8 :                 return mythrow(MAL, buf, OPERATION_FAILED);
    1075             :         }
    1076      138033 :         *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
    1077      138033 :         BBPkeepref(bn->batCacheid);
    1078      138040 :         return MAL_SUCCEED;
    1079             : }
    1080             : 
    1081             : static str
    1082           1 : CMDconvert_bit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1083             : {
    1084             :         (void) cntxt;
    1085             :         (void) mb;
    1086             : 
    1087           1 :         return CMDconvertbat(stk, pci, TYPE_bit, false);
    1088             : }
    1089             : 
    1090             : static str
    1091          87 : CMDconvertsignal_bit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1092             : {
    1093             :         (void) cntxt;
    1094             :         (void) mb;
    1095             : 
    1096          87 :         return CMDconvertbat(stk, pci, TYPE_bit, true);
    1097             : }
    1098             : 
    1099             : static str
    1100           0 : CMDconvert_bte(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1101             : {
    1102             :         (void) cntxt;
    1103             :         (void) mb;
    1104             : 
    1105           0 :         return CMDconvertbat(stk, pci, TYPE_bte, false);
    1106             : }
    1107             : 
    1108             : static str
    1109         111 : CMDconvertsignal_bte(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1110             : {
    1111             :         (void) cntxt;
    1112             :         (void) mb;
    1113             : 
    1114         111 :         return CMDconvertbat(stk, pci, TYPE_bte, true);
    1115             : }
    1116             : 
    1117             : static str
    1118           0 : CMDconvert_sht(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1119             : {
    1120             :         (void) cntxt;
    1121             :         (void) mb;
    1122             : 
    1123           0 :         return CMDconvertbat(stk, pci, TYPE_sht, false);
    1124             : }
    1125             : 
    1126             : static str
    1127        1372 : CMDconvertsignal_sht(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1128             : {
    1129             :         (void) cntxt;
    1130             :         (void) mb;
    1131             : 
    1132        1372 :         return CMDconvertbat(stk, pci, TYPE_sht, true);
    1133             : }
    1134             : 
    1135             : static str
    1136           0 : CMDconvert_int(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1137             : {
    1138             :         (void) cntxt;
    1139             :         (void) mb;
    1140             : 
    1141           0 :         return CMDconvertbat(stk, pci, TYPE_int, false);
    1142             : }
    1143             : 
    1144             : static str
    1145        7200 : CMDconvertsignal_int(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1146             : {
    1147             :         (void) cntxt;
    1148             :         (void) mb;
    1149             : 
    1150        7200 :         return CMDconvertbat(stk, pci, TYPE_int, true);
    1151             : }
    1152             : 
    1153             : static str
    1154           0 : CMDconvert_lng(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1155             : {
    1156             :         (void) cntxt;
    1157             :         (void) mb;
    1158             : 
    1159           0 :         return CMDconvertbat(stk, pci, TYPE_lng, false);
    1160             : }
    1161             : 
    1162             : static str
    1163       91751 : CMDconvertsignal_lng(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1164             : {
    1165             :         (void) cntxt;
    1166             :         (void) mb;
    1167             : 
    1168       91751 :         return CMDconvertbat(stk, pci, TYPE_lng, true);
    1169             : }
    1170             : 
    1171             : #ifdef HAVE_HGE
    1172             : 
    1173             : static str
    1174           0 : CMDconvert_hge(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1175             : {
    1176             :         (void) cntxt;
    1177             :         (void) mb;
    1178             : 
    1179           0 :         return CMDconvertbat(stk, pci, TYPE_hge, false);
    1180             : }
    1181             : 
    1182             : static str
    1183       34996 : CMDconvertsignal_hge(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1184             : {
    1185             :         (void) cntxt;
    1186             :         (void) mb;
    1187             : 
    1188       34996 :         return CMDconvertbat(stk, pci, TYPE_hge, true);
    1189             : }
    1190             : #endif
    1191             : 
    1192             : static str
    1193           0 : CMDconvert_flt(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1194             : {
    1195             :         (void) cntxt;
    1196             :         (void) mb;
    1197             : 
    1198           0 :         return CMDconvertbat(stk, pci, TYPE_flt, false);
    1199             : }
    1200             : 
    1201             : static str
    1202          81 : CMDconvertsignal_flt(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1203             : {
    1204             :         (void) cntxt;
    1205             :         (void) mb;
    1206             : 
    1207          81 :         return CMDconvertbat(stk, pci, TYPE_flt, true);
    1208             : }
    1209             : 
    1210             : static str
    1211           0 : CMDconvert_dbl(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1212             : {
    1213             :         (void) cntxt;
    1214             :         (void) mb;
    1215             : 
    1216           0 :         return CMDconvertbat(stk, pci, TYPE_dbl, false);
    1217             : }
    1218             : 
    1219             : static str
    1220        2220 : CMDconvertsignal_dbl(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1221             : {
    1222             :         (void) cntxt;
    1223             :         (void) mb;
    1224             : 
    1225        2220 :         return CMDconvertbat(stk, pci, TYPE_dbl, true);
    1226             : }
    1227             : 
    1228             : static str
    1229           0 : CMDconvert_oid(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1230             : {
    1231             :         (void) cntxt;
    1232             :         (void) mb;
    1233             : 
    1234           0 :         return CMDconvertbat(stk, pci, TYPE_oid, false);
    1235             : }
    1236             : 
    1237             : static str
    1238          17 : CMDconvertsignal_oid(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1239             : {
    1240             :         (void) cntxt;
    1241             :         (void) mb;
    1242             : 
    1243          17 :         return CMDconvertbat(stk, pci, TYPE_oid, true);
    1244             : }
    1245             : 
    1246             : static str
    1247           0 : CMDconvert_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1248             : {
    1249             :         (void) cntxt;
    1250             :         (void) mb;
    1251             : 
    1252           0 :         return CMDconvertbat(stk, pci, TYPE_str, false);
    1253             : }
    1254             : 
    1255             : static str
    1256         237 : CMDconvertsignal_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1257             : {
    1258             :         (void) cntxt;
    1259             :         (void) mb;
    1260             : 
    1261         237 :         return CMDconvertbat(stk, pci, TYPE_str, true);
    1262             : }
    1263             : 
    1264             : static str
    1265          65 : CMDifthen(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1266             : {
    1267             :         BAT *b = NULL, *b1 = NULL, *b2 = NULL, *bn;
    1268             :         int tp0, tp1, tp2;
    1269             :         bat *ret;
    1270             :         BUN cnt = BUN_NONE;
    1271             : 
    1272             :         (void) cntxt;
    1273             :         (void) mb;
    1274             : 
    1275          65 :         if (pci->argc != 4)
    1276           0 :                 throw(MAL, "batcalc.ifthen", "Operation not supported.");
    1277             : 
    1278          65 :         ret = getArgReference_bat(stk, pci, 0);
    1279          65 :         tp0 = stk->stk[getArg(pci, 1)].vtype;
    1280          65 :         tp1 = stk->stk[getArg(pci, 2)].vtype;
    1281          65 :         tp2 = stk->stk[getArg(pci, 3)].vtype;
    1282          65 :         if (tp0 == TYPE_bat || isaBatType(tp0)) {
    1283          65 :                 b = BATdescriptor(* getArgReference_bat(stk, pci, 1));
    1284          65 :                 if (b == NULL)
    1285           0 :                         throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1286          65 :                 cnt = BATcount(b);
    1287             :         }
    1288          65 :         if (tp1 == TYPE_bat || isaBatType(tp1)) {
    1289           7 :                 b1 = BATdescriptor(* getArgReference_bat(stk, pci, 2));
    1290           7 :                 if (b1 == NULL) {
    1291           0 :                         if (b)
    1292           0 :                                 BBPunfix(b->batCacheid);
    1293           0 :                         throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1294             :                 }
    1295           7 :                 if (cnt == BUN_NONE)
    1296           0 :                         cnt = BATcount(b1);
    1297           7 :                 else if (BATcount(b1) != cnt) {
    1298           0 :                         BBPunfix(b->batCacheid);
    1299           0 :                         throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT);
    1300             :                 }
    1301             :         }
    1302          65 :         if (tp2 == TYPE_bat || isaBatType(tp2)) {
    1303          58 :                 b2 = BATdescriptor(* getArgReference_bat(stk, pci, 3));
    1304          58 :                 if (b2 == NULL) {
    1305           0 :                         if (b)
    1306           0 :                                 BBPunfix(b->batCacheid);
    1307           0 :                         if (b1)
    1308           0 :                                 BBPunfix(b1->batCacheid);
    1309           0 :                         throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1310             :                 }
    1311          58 :                 if (cnt == BUN_NONE)
    1312             :                         cnt = BATcount(b2);
    1313          58 :                 else if (BATcount(b2) != cnt) {
    1314           0 :                         if (b)
    1315           0 :                                 BBPunfix(b->batCacheid);
    1316           0 :                         if (b1)
    1317           0 :                                 BBPunfix(b1->batCacheid);
    1318           0 :                         throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT);
    1319             :                 }
    1320             :         }
    1321          65 :         if (b == NULL && b1 == NULL && b2 == NULL) {
    1322             :                 /* at least one BAT required */
    1323           0 :                 throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT);
    1324             :         }
    1325          65 :         if (b != NULL) {
    1326          65 :                 if (b1 != NULL) {
    1327           7 :                         if (b2 != NULL) {
    1328           3 :                                 bn = BATcalcifthenelse(b, b1, b2);
    1329             :                         } else {
    1330           4 :                                 bn = BATcalcifthenelsecst(b, b1, &stk->stk[getArg(pci, 3)]);
    1331             :                         }
    1332             :                 } else {
    1333          58 :                         if (b2 != NULL) {
    1334          55 :                                 bn = BATcalcifthencstelse(b, &stk->stk[getArg(pci, 2)], b2);
    1335             :                         } else {
    1336           3 :                                 bn = BATcalcifthencstelsecst(b, &stk->stk[getArg(pci, 2)], &stk->stk[getArg(pci, 3)]);
    1337             :                         }
    1338             :                 }
    1339             :         } else {
    1340           0 :                 bit v = *getArgReference_bit(stk, pci, 1);
    1341           0 :                 if (is_bit_nil(v)) {
    1342           0 :                         if (b1 != NULL)
    1343           0 :                                 bn = BATconstant(b1->hseqbase, b1->ttype, ATOMnilptr(b1->ttype), BATcount(b1), TRANSIENT);
    1344             :                         else
    1345           0 :                                 bn = BATconstant(b2->hseqbase, b2->ttype, ATOMnilptr(b2->ttype), BATcount(b2), TRANSIENT);
    1346           0 :                 } else if (v) {
    1347           0 :                         if (b1 != NULL)
    1348           0 :                                 bn = COLcopy(b1, b1->ttype, false, TRANSIENT);
    1349             :                         else
    1350           0 :                                 bn = BATconstant(b2->hseqbase, b2->ttype, VALptr(&stk->stk[getArg(pci, 2)]), BATcount(b2), TRANSIENT);
    1351             :                 } else {
    1352           0 :                         if (b2 != NULL)
    1353           0 :                                 bn = COLcopy(b2, b2->ttype, false, TRANSIENT);
    1354             :                         else
    1355           0 :                                 bn = BATconstant(b1->hseqbase, b1->ttype, VALptr(&stk->stk[getArg(pci, 3)]), BATcount(b1), TRANSIENT);
    1356             :                 }
    1357             :         }
    1358          65 :         if (b)
    1359          65 :                 BBPunfix(b->batCacheid);
    1360          65 :         if (b1)
    1361           7 :                 BBPunfix(b1->batCacheid);
    1362          65 :         if (b2)
    1363          58 :                 BBPunfix(b2->batCacheid);
    1364          65 :         if (bn == NULL) {
    1365           0 :                 return mythrow(MAL, "batcalc.ifthenelse", OPERATION_FAILED);
    1366             :         }
    1367          65 :         BBPkeepref(*ret = bn->batCacheid);
    1368          65 :         return MAL_SUCCEED;
    1369             : }
    1370             : 
    1371             : #include "mel.h"
    1372             : 
    1373             : static str
    1374         261 : batcalc_init(void)
    1375             : {
    1376             :         int types[16], cur = 0, *tp;
    1377             :         int specials[4];
    1378             :         int *integer, *floats, *extra;
    1379             : 
    1380         261 :         types[cur++] = TYPE_bit;
    1381             :         integer = types+cur;
    1382         261 :         types[cur++] = TYPE_bte;
    1383         261 :         types[cur++] = TYPE_sht;
    1384         261 :         types[cur++] = TYPE_int;
    1385         261 :         types[cur++] = TYPE_lng;
    1386             : #ifdef HAVE_HGE
    1387         261 :         types[cur++] = TYPE_hge;
    1388             : #endif
    1389             :         floats = types+cur;
    1390         261 :         types[cur++] = TYPE_flt;
    1391         261 :         types[cur++] = TYPE_dbl;
    1392             :         extra = types+cur;
    1393         261 :         types[cur++] = TYPE_oid;
    1394         261 :         types[cur++] = TYPE_str;
    1395             : 
    1396             :         cur = 0;
    1397         261 :         specials[cur++] = TYPE_bit;
    1398         261 :         specials[cur++] = TYPE_oid;
    1399         261 :         specials[cur++] = TYPE_str;
    1400             : 
    1401         261 :         mel_func_arg cand = { .type = TYPE_oid, .isbat=1 };
    1402             : 
    1403             :         int err=0;
    1404             :         /* for all numeric types, use reverse order */
    1405        2088 :         for(tp = integer; tp < extra && !err; tp++) {
    1406        1827 :                 mel_func_arg ret = { .type = TYPE_bit, .isbat=1 };
    1407        1827 :                 mel_func_arg arg = { .type = *tp, .isbat=1 };
    1408             : 
    1409        1827 :                 err += melFunction(false, "batcalc", "iszero", (fptr)&CMDbatISZERO, "CMDbatISZERO", false, "Unary check for zero over the tail of the bat", 1, 2, ret, arg);
    1410        1827 :                 err += melFunction(false, "batcalc", "iszero", (fptr)&CMDbatISZERO, "CMDbatISZERO", false, "Unary check for zero over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1411             :         }
    1412        2349 :         for(tp = types; tp < extra && !err; tp++) { /* bit + numeric */
    1413        2088 :                 mel_func_arg ret = { .type = *tp, .isbat =1 };
    1414        2088 :                 mel_func_arg arg = { .type = *tp, .isbat =1 };
    1415             : 
    1416        2088 :                 err += melFunction(false, "batcalc", "not", (fptr)&CMDbatNOT, "CMDbatNOT", false, "Unary bitwise not over the tail of the bat", 1, 2, ret, arg);
    1417        2088 :                 err += melFunction(false, "batcalc", "not", (fptr)&CMDbatNOT, "CMDbatNOT", false, "Unary bitwise not over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1418             :         }
    1419        2088 :         for(tp = integer; tp < extra && !err; tp++) {
    1420        1827 :                 mel_func_arg ret = { .type = TYPE_bte, .isbat =1 };
    1421        1827 :                 mel_func_arg arg = { .type = *tp, .isbat =1 };
    1422             : 
    1423        1827 :                 err += melFunction(false, "batcalc", "sign", (fptr)&CMDbatSIGN, "CMDbatSIGN", false, "Unary sign (-1,0,1) over the tail of the bat", 1, 2, ret, arg);
    1424        1827 :                 err += melFunction(false, "batcalc", "sign", (fptr)&CMDbatSIGN, "CMDbatSIGN", false, "Unary sign (-1,0,1) over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1425             :         }
    1426        2088 :         for(tp = integer; tp < extra && !err; tp++) {
    1427        1827 :                 mel_func_arg ret = { .type = *tp, .isbat =1 };
    1428        1827 :                 mel_func_arg arg = { .type = *tp, .isbat =1 };
    1429             : 
    1430        1827 :                 err += melFunction(false, "batcalc", "abs", (fptr)&CMDbatABS, "CMDbatABS", false, "Unary abs over the tail of the bat", 1, 2, ret, arg);
    1431        1827 :                 err += melFunction(false, "batcalc", "abs", (fptr)&CMDbatABS, "CMDbatABS", false, "Unary abs over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1432             : 
    1433        1827 :                 err += melFunction(false, "batcalc", "-", (fptr)&CMDbatNEG, "CMDbatNEG", false, "Unary neg over the tail of the bat", 1, 2, ret, arg);
    1434        1827 :                 err += melFunction(false, "batcalc", "-", (fptr)&CMDbatNEG, "CMDbatNEG", false, "Unary neg over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1435             : 
    1436        1827 :                 err += melFunction(false, "batcalc", "++", (fptr)&CMDbatINCR, "CMDbatINCR", false, "Unary increment over the tail of the bat", 1, 2, ret, arg);
    1437        1827 :                 err += melFunction(false, "batcalc", "++", (fptr)&CMDbatINCR, "CMDbatINCR", false, "Unary increment over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1438             : 
    1439        1827 :                 err += melFunction(false, "batcalc", "--", (fptr)&CMDbatDECR, "CMDbatDECR", false, "Unary decrement over the tail of the bat", 1, 2, ret, arg);
    1440        1827 :                 err += melFunction(false, "batcalc", "--", (fptr)&CMDbatDECR, "CMDbatDECR", false, "Unary decrement over the tail of the bat with candidates list", 1, 3, ret, arg, cand);
    1441             :         }
    1442             :         /* possibly add the min/max + _no_nil */
    1443             :         /* binops on numeric types */
    1444             :         struct {
    1445             :            char *op;
    1446             :            char *op_ne;
    1447             :            char *fname;
    1448             :            char *fname_ne;
    1449             :            char *fname_el;
    1450             :            fptr fcn;
    1451             :            fptr fcn_ne;
    1452             :            fptr fcn_el;
    1453             :            char *comment;
    1454             :            char *comment_ne;
    1455             :            char *comment_v;
    1456             :            char *comment_v_ne;
    1457             :            char *comment_v_;
    1458             :            char *comment_v__ne;
    1459             :            char *comment_el;
    1460             :            char *comment_el_v;
    1461             :            char *comment_el_v_;
    1462         261 :         } funcs[3] = {
    1463             :           {
    1464             :                 .op = "+",
    1465             :                 .fcn = (fptr)CMDbatADDsignal,
    1466             :                 .fname = "CMDbatADDsignal",
    1467             :                 .op_ne = "add_noerror",
    1468             :                 .fcn_ne = (fptr)&CMDbatADD,
    1469             :                 .fname_ne = "CMDbatADD",
    1470             :                 .fcn_el = (fptr)&CMDbatADDenlarge,
    1471             :                 .fname_el = "CMDbatADDenlarge",
    1472             :                 .comment = "Return B1 + B2 with candidates list, signal error on overflow",
    1473             :                 .comment_ne = "Return B1 + B2 with candidates list, overflow causes NIL value",
    1474             :                 .comment_v = "Return B + V with candidates list, signal error on overflow",
    1475             :                 .comment_v_ne = "Return B + V with candidates list, overflow causes NIL value",
    1476             :                 .comment_v_ = "Return V + B with candidates list, signal error on overflow",
    1477             :                 .comment_v__ne = "Return V + B with candidates list, overflow causes NIL value",
    1478             :                 .comment_el = "Return B1 + B2 with candidates list, guarantee no overflow by returning larger type",
    1479             :                 .comment_el_v = "Return B + V with candidates list, guarantee no overflow by returning larger type",
    1480             :                 .comment_el_v_ = "Return V + B with candidates list, guarantee no overflow by returning larger type",
    1481             :           }, {
    1482             :                 .op = "-",
    1483             :                 .fcn = (fptr)CMDbatSUBsignal,
    1484             :                 .fname = "CMDbatSUBsignal",
    1485             :                 .op_ne = "sub_noerror",
    1486             :                 .fcn_ne = (fptr)&CMDbatSUB,
    1487             :                 .fname_ne = "CMDbatSUB",
    1488             :                 .fcn_el = (fptr)&CMDbatSUBenlarge,
    1489             :                 .fname_el = "CMDbatSUBenlarge",
    1490             :                 .comment = "Return B1 - B2 with candidates list, signal error on overflow",
    1491             :                 .comment_ne = "Return B1 - B2 with candidates list, overflow causes NIL value",
    1492             :                 .comment_v = "Return B - V with candidates list, signal error on overflow",
    1493             :                 .comment_v_ne = "Return B - V with candidates list, overflow causes NIL value",
    1494             :                 .comment_v_ = "Return V - B with candidates list, signal error on overflow",
    1495             :                 .comment_v__ne = "Return V - B with candidates list, overflow causes NIL value",
    1496             :                 .comment_el = "Return B1 - B2 with candidates list, guarantee no overflow by returning larger type",
    1497             :                 .comment_el_v = "Return B - V with candidates list, guarantee no overflow by returning larger type",
    1498             :                 .comment_el_v_ = "Return V - B with candidates list, guarantee no overflow by returning larger type",
    1499             :           }, {
    1500             :                 .op = "*",
    1501             :                 .fcn = (fptr)CMDbatMULsignal,
    1502             :                 .fname = "CMDbatMULsignal",
    1503             :                 .op_ne = "mul_noerror",
    1504             :                 .fcn_ne = (fptr)&CMDbatMUL,
    1505             :                 .fname_ne = "CMDbatMUL",
    1506             :                 .fcn_el = (fptr)&CMDbatMULenlarge,
    1507             :                 .fname_el = "CMDbatMULenlarge",
    1508             :                 .comment = "Return B1 * B2 with candidates list, signal error on overflow",
    1509             :                 .comment_ne = "Return B1 * B2 with candidates list, overflow causes NIL value",
    1510             :                 .comment_v = "Return B * V with candidates list, signal error on overflow",
    1511             :                 .comment_v_ne = "Return B * V with candidates list, overflow causes NIL value",
    1512             :                 .comment_v_ = "Return V * B with candidates list, signal error on overflow",
    1513             :                 .comment_v__ne = "Return V * B with candidates list, overflow causes NIL value",
    1514             :                 .comment_el = "Return B1 * B2 with candidates list, guarantee no overflow by returning larger type",
    1515             :                 .comment_el_v = "Return B * V with candidates list, guarantee no overflow by returning larger type",
    1516             :                 .comment_el_v_ = "Return V * B with candidates list, guarantee no overflow by returning larger type",
    1517             :           }
    1518             :         };
    1519        1044 :         for (int f=0; f<3; f++) {
    1520             :           int *tp1, *tp2, *rt;
    1521        6264 :           for(tp1 = integer; tp1 < extra && !err; tp1++) {
    1522       43848 :             for(tp2 = integer; tp2 < extra && !err; tp2++) {
    1523      306936 :               for(rt = extra-1; rt >= integer && !err; rt--) {
    1524      268569 :                 if (f!=3 && (*rt < *tp1 || *rt < *tp2))
    1525      158949 :                         continue;
    1526      109620 :                 mel_func_arg ret = { .type = *rt, .isbat =1 };
    1527      109620 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1528      109620 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1529      109620 :                 mel_func_arg varg1 = { .type = *tp1 };
    1530      109620 :                 mel_func_arg varg2 = { .type = *tp2 };
    1531             : 
    1532      109620 :                 if (*rt == *tp1 || *rt == *tp2 || f==3) {
    1533       38367 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn, funcs[f].fname, false, funcs[f].comment, 1, 5, ret, arg1, arg2, cand, cand);
    1534       38367 :                   err += melFunction(false, "batcalc", funcs[f].op_ne, funcs[f].fcn_ne, funcs[f].fname_ne, false, funcs[f].comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1535       38367 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn, funcs[f].fname, false, funcs[f].comment_v, 1, 4, ret, arg1, varg2, cand);
    1536       38367 :                   err += melFunction(false, "batcalc", funcs[f].op_ne, funcs[f].fcn_ne, funcs[f].fname_ne, false, funcs[f].comment_v_ne, 1, 4, ret, arg1, varg2, cand);
    1537       38367 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn, funcs[f].fname, false, funcs[f].comment_v_, 1, 4, ret, varg1, arg2, cand);
    1538       38367 :                   err += melFunction(false, "batcalc", funcs[f].op_ne, funcs[f].fcn_ne, funcs[f].fname_ne, false, funcs[f].comment_v__ne, 1, 4, ret, varg1, arg2, cand);
    1539             :                 } else {
    1540       71253 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn_el, funcs[f].fname_el, false, funcs[f].comment_el, 1, 5, ret, arg1, arg2, cand, cand);
    1541       71253 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn_el, funcs[f].fname_el, false, funcs[f].comment_el_v, 1, 4, ret, arg1, varg2, cand);
    1542       71253 :                   err += melFunction(false, "batcalc", funcs[f].op, funcs[f].fcn_el, funcs[f].fname_el, false, funcs[f].comment_el_v_, 1, 4, ret, varg1, arg2, cand);
    1543             :                 }
    1544             :               }
    1545             :             }
    1546             :           }
    1547             :         }
    1548             :         {       /* multiplication between integers and floating-points, returning integers */
    1549             :                 int *tp1, *tp2, *tp3;
    1550        1566 :                 for(tp1 = integer; tp1 < floats && !err; tp1++) {
    1551        3915 :                         for(tp2 = floats; tp2 < extra && !err; tp2++) {
    1552       15660 :                                 for(tp3 = integer; tp3 < floats && !err; tp3++) {
    1553       13050 :                                         int in1 = *tp3, in2 = *tp2;
    1554             : 
    1555       39150 :                                         for (int i = 0 ; i < 2 ; i++) {
    1556       26100 :                                                 mel_func_arg ret = { .type = *tp1, .isbat =1 };
    1557       26100 :                                                 mel_func_arg arg1 = { .type = in1, .isbat =1 };
    1558       26100 :                                                 mel_func_arg arg2 = { .type = in2, .isbat =1 };
    1559       26100 :                                                 mel_func_arg varg1 = { .type = in1 };
    1560       26100 :                                                 mel_func_arg varg2 = { .type = in2 };
    1561             : 
    1562       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op, funcs[2].fcn, funcs[2].fname, false, funcs[2].comment, 1, 5, ret, arg1, arg2, cand, cand);
    1563       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op_ne, funcs[2].fcn_ne, funcs[2].fname_ne, false, funcs[2].comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1564       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op, funcs[2].fcn, funcs[2].fname, false, funcs[2].comment_v, 1, 4, ret, arg1, varg2, cand);
    1565       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op_ne, funcs[2].fcn_ne, funcs[2].fname_ne, false, funcs[2].comment_v_ne, 1, 4, ret, arg1, varg2, cand);
    1566       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op, funcs[2].fcn, funcs[2].fname, false, funcs[2].comment_v_, 1, 4, ret, varg1, arg2, cand);
    1567       26100 :                                                 err += melFunction(false, "batcalc", funcs[2].op_ne, funcs[2].fcn_ne, funcs[2].fname_ne, false, funcs[2].comment_v__ne, 1, 4, ret, varg1, arg2, cand);
    1568             : 
    1569             :                                                 /* swap variables */
    1570             :                                                 in1 ^= in2;
    1571             :                                                 in2 ^= in1;
    1572             :                                                 in1 ^= in2;
    1573             :                                         }
    1574             :                                 }
    1575             :                         }
    1576             :                 }
    1577             :         }
    1578             :         struct {
    1579             :            char *op;
    1580             :            char *op_ne;
    1581             :            char *fname;
    1582             :            char *fname_ne;
    1583             :            char *fname_el;
    1584             :            fptr fcn;
    1585             :            fptr fcn_ne;
    1586             :            fptr fcn_el;
    1587             :            char *comment;
    1588             :            char *comment_ne;
    1589             :            char *comment_v;
    1590             :            char *comment_v_ne;
    1591             :            char *comment_v_;
    1592             :            char *comment_v__ne;
    1593             :            char *comment_el;
    1594             :            char *comment_el_v;
    1595             :            char *comment_el_v_;
    1596         261 :         } div = {
    1597             :                 .op = "/",
    1598             :                 .fcn = (fptr)CMDbatDIVsignal,
    1599             :                 .fname = "CMDbatDIVsignal",
    1600             :                 .op_ne = "div_noerror",
    1601             :                 .fcn_ne = (fptr)&CMDbatDIV,
    1602             :                 .fname_ne = "CMDbatDIV",
    1603             :                 .comment = "Return B1 / B2 with candidates list, signal error on overflow",
    1604             :                 .comment_ne = "Return B1 / B2 with candidates list, overflow causes NIL value",
    1605             :                 .comment_v = "Return B / V with candidates list, signal error on overflow",
    1606             :                 .comment_v_ne = "Return B / V with candidates list, overflow causes NIL value",
    1607             :                 .comment_v_ = "Return V / B with candidates list, signal error on overflow",
    1608             :                 .comment_v__ne = "Return V / B with candidates list, overflow causes NIL value",
    1609             :         };
    1610             :         int *tp1, *tp2, *rt;
    1611        2088 :         for(tp1 = integer; tp1 < extra && !err; tp1++) {
    1612       14616 :             for(tp2 = integer; tp2 < extra && !err; tp2++) {
    1613       63945 :               for(rt = extra-1; rt >= tp1 && !err; rt--) {
    1614       51156 :                 mel_func_arg ret = { .type = *rt, .isbat =1 };
    1615       51156 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1616       51156 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1617       51156 :                 mel_func_arg varg1 = { .type = *tp1 };
    1618       51156 :                 mel_func_arg varg2 = { .type = *tp2 };
    1619             : 
    1620       51156 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment, 1, 5, ret, arg1, arg2, cand, cand);
    1621       51156 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1622       51156 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment_v, 1, 4, ret, arg1, varg2, cand);
    1623       51156 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_v_ne, 1, 4, ret, arg1, varg2, cand);
    1624       51156 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment_v_, 1, 4, ret, varg1, arg2, cand);
    1625       51156 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_v__ne, 1, 4, ret, varg1, arg2, cand);
    1626             :               }
    1627             :             }
    1628             :         }
    1629             :         /* division between integers and floating-points, returning integers */
    1630         783 :         for(tp1 = floats; tp1 < extra && !err; tp1++) {
    1631        3132 :             for(tp2 = integer; tp2 < floats && !err; tp2++) {
    1632       15660 :               for(rt = integer; rt < floats && !err; rt++) {
    1633       13050 :                 mel_func_arg ret = { .type = *rt, .isbat =1 };
    1634       13050 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1635       13050 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1636       13050 :                 mel_func_arg varg1 = { .type = *tp1 };
    1637       13050 :                 mel_func_arg varg2 = { .type = *tp2 };
    1638             : 
    1639       13050 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment, 1, 5, ret, arg1, arg2, cand, cand);
    1640       13050 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1641       13050 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment_v, 1, 4, ret, arg1, varg2, cand);
    1642       13050 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_v_ne, 1, 4, ret, arg1, varg2, cand);
    1643       13050 :                 err += melFunction(false, "batcalc", div.op, div.fcn, div.fname, false, div.comment_v_, 1, 4, ret, varg1, arg2, cand);
    1644       13050 :                 err += melFunction(false, "batcalc", div.op_ne, div.fcn_ne, div.fname_ne, false, div.comment_v__ne, 1, 4, ret, varg1, arg2, cand);
    1645             :               }
    1646             :             }
    1647             :         }
    1648             :         struct {
    1649             :            char *op;
    1650             :            char *op_ne;
    1651             :            char *fname;
    1652             :            char *fname_ne;
    1653             :            fptr fcn;
    1654             :            fptr fcn_ne;
    1655             :            char *comment;
    1656             :            char *comment_ne;
    1657             :            char *comment_v;
    1658             :            char *comment_v_ne;
    1659             :            char *comment_v_;
    1660             :            char *comment_v__ne;
    1661             :         } mods = {
    1662             :                 .op = "%",
    1663             :                 .fcn = (fptr)CMDbatMODsignal,
    1664             :                 .fname = "CMDbatMODsignal",
    1665             :                 .op_ne = "mod_noerror",
    1666             :                 .fcn_ne = (fptr)&CMDbatMOD,
    1667             :                 .fname_ne = "CMDbatMOD",
    1668             :                 .comment = "Return B1 % B2 with candidates list, signal error on overflow",
    1669             :                 .comment_ne = "Return B1 % B2 with candidates list, overflow causes NIL value",
    1670             :                 .comment_v = "Return B % V with candidates list, signal error on overflow",
    1671             :                 .comment_v_ne = "Return B % V with candidates list, overflow causes NIL value",
    1672             :                 .comment_v_ = "Return V % B with candidates list, signal error on overflow",
    1673             :                 .comment_v__ne = "Return V % B with candidates list, overflow causes NIL value",
    1674             :         };
    1675        2088 :         for(tp1 = integer; tp1 < extra && !err; tp1++) {
    1676       14616 :             for(tp2 = integer; tp2 < extra && !err; tp2++) {
    1677      102312 :               for(rt = extra-1; rt >= integer && !err; rt--) {
    1678       89523 :                 if (rt < tp1 && rt < tp2)
    1679       64206 :                         continue;
    1680       65772 :                 if (*rt == TYPE_dbl) {
    1681       12789 :                         if (*tp1 != TYPE_dbl || *tp2 != TYPE_dbl)
    1682       12528 :                                 continue;
    1683       52983 :                 } else if (*rt == TYPE_flt) {
    1684       12528 :                         if (*tp1 != TYPE_flt || *tp2 != TYPE_flt)
    1685       12267 :                                 continue;
    1686             :                 } else {
    1687       40455 :                         if (*tp1 == TYPE_flt || *tp2 == TYPE_flt || *tp1 == TYPE_dbl || *tp2 == TYPE_dbl)
    1688       15660 :                                 continue;
    1689             :                 }
    1690       25317 :                 mel_func_arg ret = { .type = *rt, .isbat =1 };
    1691       25317 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1692       25317 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1693       25317 :                 mel_func_arg varg1 = { .type = *tp1 };
    1694       25317 :                 mel_func_arg varg2 = { .type = *tp2 };
    1695             : 
    1696       25317 :                 err += melFunction(false, "batcalc", mods.op, mods.fcn, mods.fname, false, mods.comment, 1, 5, ret, arg1, arg2, cand, cand);
    1697       25317 :                 err += melFunction(false, "batcalc", mods.op_ne, mods.fcn_ne, mods.fname_ne, false, mods.comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1698       25317 :                 err += melFunction(false, "batcalc", mods.op, mods.fcn, mods.fname, false, mods.comment_v, 1, 4, ret, arg1, varg2, cand);
    1699       25317 :                 err += melFunction(false, "batcalc", mods.op_ne, mods.fcn_ne, mods.fname_ne, false, mods.comment_v_ne, 1, 4, ret, arg1, varg2, cand);
    1700       25317 :                 err += melFunction(false, "batcalc", mods.op, mods.fcn, mods.fname, false, mods.comment_v_, 1, 4, ret, varg1, arg2, cand);
    1701       25317 :                 err += melFunction(false, "batcalc", mods.op_ne, mods.fcn_ne, mods.fname_ne, false, mods.comment_v__ne, 1, 4, ret, varg1, arg2, cand);
    1702             :               }
    1703             :             }
    1704             :         }
    1705             :         struct {
    1706             :            char *op;
    1707             :            char *fname;
    1708             :            fptr fcn;
    1709             :            char *comment;
    1710             :            char *comment_v;
    1711             :            char *comment_v_;
    1712         261 :         } logops[3] = {
    1713             :           {
    1714             :                 .op = "and",
    1715             :                 .fcn = (fptr)CMDbatAND,
    1716             :                 .fname = "CMDbatAND",
    1717             :                 .comment = "Return B1 and B2",
    1718             :                 .comment_v = "Return B and V",
    1719             :                 .comment_v_ = "Return V and B",
    1720             :           }, {
    1721             :                 .op = "or",
    1722             :                 .fcn = (fptr)CMDbatOR,
    1723             :                 .fname = "CMDbatOR",
    1724             :                 .comment = "Return B1 or B2",
    1725             :                 .comment_v = "Return B or V",
    1726             :                 .comment_v_ = "Return V or B",
    1727             :           }, {
    1728             :                 .op = "xor",
    1729             :                 .fcn = (fptr)CMDbatXOR,
    1730             :                 .fname = "CMDbatXOR",
    1731             :                 .comment = "Return B1 xor B2",
    1732             :                 .comment_v = "Return B xor V",
    1733             :                 .comment_v_ = "Return V xor B",
    1734             :           }
    1735             :         };
    1736        1044 :         for (int f=0; f<3; f++) {
    1737        7047 :           for(tp = types+0; tp < extra && !err; tp++) {
    1738        6264 :                 mel_func_arg ret = { .type = *tp, .isbat =1 };
    1739        6264 :                 mel_func_arg arg = { .type = *tp, .isbat =1 };
    1740        6264 :                 mel_func_arg varg = { .type = *tp };
    1741             : 
    1742        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment, 1, 3, ret, arg, arg);
    1743        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment, 1, 5, ret, arg, arg, cand, cand);
    1744        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment_v, 1, 3, ret, arg, varg);
    1745        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment_v, 1, 4, ret, arg, varg, cand);
    1746        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment_v_, 1, 3, ret, varg, arg);
    1747        6264 :                 err += melFunction(false, "batcalc", logops[f].op, logops[f].fcn, logops[f].fname, false, logops[f].comment_v_, 1, 4, ret, varg, arg, cand);
    1748             :           }
    1749             :         }
    1750             :         struct {
    1751             :            char *op;
    1752             :            char *op_ne;
    1753             :            char *fname;
    1754             :            fptr fcn;
    1755             :            char *fname_ne;
    1756             :            fptr fcn_ne;
    1757             :            char *comment;
    1758             :            char *comment_v;
    1759             :            char *comment_v_;
    1760             :            char *comment_ne;
    1761             :            char *comment_ne_v;
    1762             :            char *comment_ne_v_;
    1763         261 :         } shifts[2] = {
    1764             :           {
    1765             :                 .op = "<<",
    1766             :                 .op_ne = "lsh_noerror",
    1767             :                 .fcn = (fptr)CMDbatLSHsignal,
    1768             :                 .fname = "CMDbatLSHsignal",
    1769             :                 .fcn_ne = (fptr)CMDbatLSH,
    1770             :                 .fname_ne = "CMDbatLSH",
    1771             :                 .comment = "Return B1 << B2, raise error on out of range second operand",
    1772             :                 .comment_v = "Return B << V, raise error on out of range second operand",
    1773             :                 .comment_v_ = "Return B << V, raise error on out of range second operand",
    1774             :                 .comment_ne = "Return B1 << B2, out of range second operand causes NIL value",
    1775             :                 .comment_ne_v = "Return B << V, out of range second operand causes NIL value",
    1776             :                 .comment_ne_v_ = "Return V << B, out of range second operand causes NIL value",
    1777             :           }, {
    1778             :                 .op = ">>",
    1779             :                 .op_ne = "rsh_noerror",
    1780             :                 .fcn = (fptr)CMDbatRSHsignal,
    1781             :                 .fname = "CMDbatRSHsignal",
    1782             :                 .fcn_ne = (fptr)CMDbatRSH,
    1783             :                 .fname_ne = "CMDbatRSH",
    1784             :                 .comment = "Return B1 >> B2, raise error on out of range second operand",
    1785             :                 .comment_v = "Return B >> V, raise error on out of range second operand",
    1786             :                 .comment_v_ = "Return B >> V, raise error on out of range second operand",
    1787             :                 .comment_ne = "Return B1 >> B2, out of range second operand causes NIL value",
    1788             :                 .comment_ne_v = "Return B >> V, out of range second operand causes NIL value",
    1789             :                 .comment_ne_v_ = "Return V >> B, out of range second operand causes NIL value",
    1790             :           }
    1791             :         };
    1792         783 :         for (int f=0; f<2; f++) {
    1793             :           int *tp1, *tp2;
    1794        3132 :           for(tp1 = integer; tp1 < floats && !err; tp1++) {
    1795       15660 :             for(tp2 = integer; tp2 < floats && !err; tp2++) {
    1796       13050 :                 mel_func_arg ret = { .type = *tp1, .isbat =1 };
    1797       13050 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1798       13050 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1799       13050 :                 mel_func_arg varg1 = { .type = *tp1 };
    1800       13050 :                 mel_func_arg varg2 = { .type = *tp2 };
    1801             : 
    1802       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment, 1, 3, ret, arg1, arg2);
    1803       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment, 1, 5, ret, arg1, arg2, cand, cand);
    1804       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne, 1, 3, ret, arg1, arg2);
    1805       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne, 1, 5, ret, arg1, arg2, cand, cand);
    1806       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment_v, 1, 3, ret, arg1, varg2);
    1807       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment_v, 1, 4, ret, arg1, varg2, cand);
    1808       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne_v, 1, 3, ret, arg1, varg2);
    1809       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne_v, 1, 4, ret, arg1, varg2, cand);
    1810       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment_v_, 1, 3, ret, varg1, arg2);
    1811       13050 :                 err += melFunction(false, "batcalc", shifts[f].op, shifts[f].fcn, shifts[f].fname, false, shifts[f].comment_v_, 1, 4, ret, varg1, arg2, cand);
    1812       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne_v_, 1, 3, ret, varg1, arg2);
    1813       13050 :                 err += melFunction(false, "batcalc", shifts[f].op_ne, shifts[f].fcn_ne, shifts[f].fname_ne, false, shifts[f].comment_ne_v_, 1, 4, ret, varg1, arg2, cand);
    1814             :             }
    1815             :           }
    1816             :         }
    1817             : 
    1818             :         struct {
    1819             :            char *op;
    1820             :            char *fname;
    1821             :            fptr fcn;
    1822             :            char *comment;
    1823             :            char *comment_v;
    1824             :            char *comment_v_;
    1825         261 :         } cmps[6] = {
    1826             :           {
    1827             :                 .op = "<",
    1828             :                 .fcn = (fptr)CMDbatLT,
    1829             :                 .fname = "CMDbatLT",
    1830             :                 .comment = "Return B1 < B2",
    1831             :                 .comment_v = "Return B < V",
    1832             :                 .comment_v_ = "Return B < V",
    1833             :           }, {
    1834             :                 .op = "<=",
    1835             :                 .fcn = (fptr)CMDbatLE,
    1836             :                 .fname = "CMDbatLE",
    1837             :                 .comment = "Return B1 <= B2",
    1838             :                 .comment_v = "Return B <= V",
    1839             :                 .comment_v_ = "Return B <= V",
    1840             :           }, {
    1841             :                 .op = ">",
    1842             :                 .fcn = (fptr)CMDbatGT,
    1843             :                 .fname = "CMDbatGT",
    1844             :                 .comment = "Return B1 > B2",
    1845             :                 .comment_v = "Return B > V",
    1846             :                 .comment_v_ = "Return B > V",
    1847             :           }, {
    1848             :                 .op = ">=",
    1849             :                 .fcn = (fptr)CMDbatGE,
    1850             :                 .fname = "CMDbatGE",
    1851             :                 .comment = "Return B1 >= B2",
    1852             :                 .comment_v = "Return B >= V",
    1853             :                 .comment_v_ = "Return B >= V",
    1854             :           }, {
    1855             :                 .op = "==",
    1856             :                 .fcn = (fptr)CMDbatEQ,
    1857             :                 .fname = "CMDbatEQ",
    1858             :                 .comment = "Return B1 == B2",
    1859             :                 .comment_v = "Return B == V",
    1860             :                 .comment_v_ = "Return B == V",
    1861             :           }, {
    1862             :                 .op = "!=",
    1863             :                 .fcn = (fptr)CMDbatNE,
    1864             :                 .fname = "CMDbatNE",
    1865             :                 .comment = "Return B1 != B2",
    1866             :                 .comment_v = "Return B != V",
    1867             :                 .comment_v_ = "Return B != V",
    1868             :           }
    1869             :         };
    1870         261 :         int newtypes[6] = { ATOMindex("json"), ATOMindex("uuid"), TYPE_date, TYPE_daytime, TYPE_timestamp };
    1871        1827 :         for (int f=0; f<6; f++) {
    1872        1566 :           mel_func_arg ret = { .type = TYPE_bit, .isbat =1 };
    1873        1566 :           mel_func_arg arg = { .type = TYPE_any, .isbat =1, .nr=1 };
    1874        1566 :           mel_func_arg varg = { .type = TYPE_any, .nr=1 };
    1875             : 
    1876        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 3, ret, arg, arg);
    1877        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 5, ret, arg, arg, cand, cand);
    1878        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 3, ret, arg, varg);
    1879        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg, varg, cand);
    1880        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 3, ret, varg, arg);
    1881        1566 :           err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg, arg, cand);
    1882             : 
    1883        1566 :           if (strcmp(cmps[f].op,"==")==0 || strcmp(cmps[f].op,"!=")==0) {
    1884         522 :                 mel_func_arg nil_matches = { .type = TYPE_bit };
    1885         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 4, ret, arg, arg, nil_matches);
    1886         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 6, ret, arg, arg, cand, cand, nil_matches);
    1887         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg, varg, nil_matches);
    1888         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 5, ret, arg, varg, cand, nil_matches);
    1889         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg, arg, nil_matches);
    1890         522 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 5, ret, varg, arg, cand, nil_matches);
    1891             :           }
    1892             : 
    1893             :           /* uuid, json and mtime (date, daytime, timestamp */
    1894        9396 :           for (int nt = 0; nt < 5; nt++) {
    1895        7830 :              mel_func_arg ret = { .type = TYPE_bit, .isbat =1 };
    1896        7830 :              mel_func_arg arg = { .type = newtypes[nt], .isbat =1, .nr=1 };
    1897        7830 :              mel_func_arg varg = { .type = newtypes[nt], .nr=1 };
    1898             : 
    1899        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 3, ret, arg, arg);
    1900        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 5, ret, arg, arg, cand, cand);
    1901        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 3, ret, arg, varg);
    1902        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg, varg, cand);
    1903        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 3, ret, varg, arg);
    1904        7830 :              err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg, arg, cand);
    1905             : 
    1906        7830 :              if (strcmp(cmps[f].op,"==")==0 || strcmp(cmps[f].op,"!=")==0) {
    1907        2610 :                 mel_func_arg nil_matches = { .type = TYPE_bit };
    1908        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 4, ret, arg, arg, nil_matches);
    1909        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 6, ret, arg, arg, cand, cand, nil_matches);
    1910        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg, varg, nil_matches);
    1911        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 5, ret, arg, varg, cand, nil_matches);
    1912        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg, arg, nil_matches);
    1913        2610 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 5, ret, varg, arg, cand, nil_matches);
    1914             :              }
    1915             :           }
    1916             : 
    1917             :           int *tp1, *tp2;
    1918        9396 :           for(tp1 = integer; tp1 < floats && !err; tp1++) {
    1919       46980 :             for(tp2 = integer; tp2 < floats && !err; tp2++) {
    1920       39150 :                 if (*tp1 == *tp2)
    1921        7830 :                         continue;
    1922       31320 :                 mel_func_arg ret = { .type = TYPE_bit, .isbat =1 };
    1923       31320 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1924       31320 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1925       31320 :                 mel_func_arg varg1 = { .type = *tp1 };
    1926       31320 :                 mel_func_arg varg2 = { .type = *tp2 };
    1927             : 
    1928       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 3, ret, arg1, arg2);
    1929       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 5, ret, arg1, arg2, cand, cand);
    1930       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 3, ret, arg1, varg2);
    1931       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg1, varg2, cand);
    1932       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 3, ret, varg1, arg2);
    1933       31320 :                 err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg1, arg2, cand);
    1934             : 
    1935       31320 :                 if (strcmp(cmps[f].op,"==")==0 || strcmp(cmps[f].op,"!=")==0) {
    1936       10440 :                         mel_func_arg nil_matches = { .type = TYPE_bit };
    1937             : 
    1938       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 3, ret, arg1, arg2, nil_matches);
    1939       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment, 1, 5, ret, arg1, arg2, cand, cand, nil_matches);
    1940       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 3, ret, arg1, varg2, nil_matches);
    1941       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v, 1, 4, ret, arg1, varg2, cand, nil_matches);
    1942       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 3, ret, varg1, arg2, nil_matches);
    1943       10440 :                         err += melFunction(false, "batcalc", cmps[f].op, cmps[f].fcn, cmps[f].fname, false, cmps[f].comment_v_, 1, 4, ret, varg1, arg2, cand, nil_matches);
    1944             :                 }
    1945             :             }
    1946             :           }
    1947             :         }
    1948             : 
    1949             :         struct {
    1950             :            char *op;
    1951             :            char *fname;
    1952             :            fptr fcn;
    1953             :            char *comment;
    1954             :            char *comment_v;
    1955             :            char *comment_v_;
    1956             :         } cmp = {
    1957             :                 .op = "cmp",
    1958             :                 .fcn = (fptr)CMDbatCMP,
    1959             :                 .fname = "CMDbatCMP",
    1960             :                 .comment = "Return -1/0/1 if B1 </==/> B2",
    1961             :                 .comment_v = "Return -1/0/1 if B </==/> V",
    1962             :                 .comment_v_ = "Return -1/0/1 if V </==/> B",
    1963             :         };
    1964        1044 :         for(int i = 0; i < 3 && !err; i++) {
    1965         783 :                 int tp = specials[i];
    1966         783 :                 mel_func_arg ret = { .type = TYPE_bte, .isbat =1 };
    1967         783 :                 mel_func_arg arg = { .type = tp, .isbat =1 };
    1968         783 :                 mel_func_arg varg = { .type = tp };
    1969             : 
    1970         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment, 1, 3, ret, arg, arg);
    1971         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment, 1, 5, ret, arg, arg, cand, cand);
    1972         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v, 1, 3, ret, arg, varg);
    1973         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v, 1, 4, ret, arg, varg, cand);
    1974         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v_, 1, 3, ret, varg, arg);
    1975         783 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v_, 1, 4, ret, varg, arg, cand);
    1976             :         }
    1977        2088 :         for(tp1 = integer; tp1 < extra && !err; tp1++) {
    1978       14616 :             for(tp2 = integer; tp2 < extra && !err; tp2++) {
    1979       12789 :                 mel_func_arg ret = { .type = TYPE_bte, .isbat =1 };
    1980       12789 :                 mel_func_arg arg1 = { .type = *tp1, .isbat =1 };
    1981       12789 :                 mel_func_arg arg2 = { .type = *tp2, .isbat =1 };
    1982       12789 :                 mel_func_arg varg1 = { .type = *tp1 };
    1983       12789 :                 mel_func_arg varg2 = { .type = *tp2 };
    1984             : 
    1985       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment, 1, 3, ret, arg1, arg2);
    1986       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment, 1, 5, ret, arg1, arg2, cand, cand);
    1987       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v, 1, 3, ret, arg1, varg2);
    1988       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v, 1, 4, ret, arg1, varg2, cand);
    1989       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v_, 1, 3, ret, varg1, arg2);
    1990       12789 :                 err += melFunction(false, "batcalc", cmp.op, cmp.fcn, cmp.fname, false, cmp.comment_v_, 1, 4, ret, varg1, arg2, cand);
    1991             :             }
    1992             :         }
    1993        2088 :         for(tp = integer; tp < extra && !err; tp++) {
    1994        1827 :                 mel_func_arg ret = { .type = TYPE_dbl };
    1995        1827 :                 mel_func_arg nr = { .type = TYPE_lng };
    1996        1827 :                 mel_func_arg arg = { .type = *tp, .isbat =1 };
    1997        1827 :                 mel_func_arg scale = { .type = TYPE_int };
    1998             : 
    1999        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average of non-nil values of B", 1, 2, ret, arg);
    2000        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average of non-nil values of B with candidates list", 1, 3, ret, arg, cand);
    2001        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average and number of non-nil values of B", 2, 3, ret, nr, arg);
    2002        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average and number of non-nil values of B with candidates list", 2, 4, ret, nr, arg, cand);
    2003        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average of non-nil values of B", 1, 3, ret, arg, scale);
    2004        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average of non-nil values of B with candidates list", 1, 4, ret, arg, cand, scale);
    2005        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average and number of non-nil values of B", 2, 4, ret, nr, arg, scale);
    2006        1827 :                 err += melFunction(false, "batcalc", "avg", (fptr)&CMDcalcavg, "CMDcalcavg", false, "average and number of non-nil values of B with candidates list", 2, 5, ret, nr, arg, cand, scale);
    2007             :         }
    2008             : 
    2009             :         struct {
    2010             :                 int type;
    2011             :                 char *name;
    2012             :                 char *fname;
    2013             :                 fptr fcn;
    2014             :                 char *name_ne;
    2015             :                 char *fname_ne;
    2016             :                 fptr fcn_ne;
    2017         261 :         } typeops[10] = {
    2018             :           {
    2019             :                 .type = TYPE_bit,
    2020             :                 .name = "bit",
    2021             :                 .name_ne = "bit_noerror",
    2022             :                 .fname = "CMDconvertsignal_bit",
    2023             :                 .fname_ne = "CMDconvert_bit",
    2024             :                 .fcn = (fptr)CMDconvertsignal_bit,
    2025             :                 .fcn_ne = (fptr)CMDconvert_bit,
    2026             :           }, {
    2027             :                 .type = TYPE_bte,
    2028             :                 .name = "bte",
    2029             :                 .name_ne = "bte_noerror",
    2030             :                 .fname = "CMDconvertsignal_bte",
    2031             :                 .fname_ne = "CMDconvert_bte",
    2032             :                 .fcn = (fptr)CMDconvertsignal_bte,
    2033             :                 .fcn_ne = (fptr)CMDconvert_bte,
    2034             :           }, {
    2035             :                 .type = TYPE_sht,
    2036             :                 .name = "sht",
    2037             :                 .name_ne = "sht_noerror",
    2038             :                 .fname = "CMDconvertsignal_sht",
    2039             :                 .fname_ne = "CMDconvert_sht",
    2040             :                 .fcn = (fptr)CMDconvertsignal_sht,
    2041             :                 .fcn_ne = (fptr)CMDconvert_sht,
    2042             :           }, {
    2043             :                 .type = TYPE_int,
    2044             :                 .name = "int",
    2045             :                 .name_ne = "int_noerror",
    2046             :                 .fname = "CMDconvertsignal_int",
    2047             :                 .fname_ne = "CMDconvert_int",
    2048             :                 .fcn = (fptr)CMDconvertsignal_int,
    2049             :                 .fcn_ne = (fptr)CMDconvert_int,
    2050             :           }, {
    2051             :                 .type = TYPE_lng,
    2052             :                 .name = "lng",
    2053             :                 .name_ne = "lng_noerror",
    2054             :                 .fname = "CMDconvertsignal_lng",
    2055             :                 .fname_ne = "CMDconvert_lng",
    2056             :                 .fcn = (fptr)CMDconvertsignal_lng,
    2057             :                 .fcn_ne = (fptr)CMDconvert_lng,
    2058             : #ifdef HAVE_HGE
    2059             :           }, {
    2060             :                 .type = TYPE_hge,
    2061             :                 .name = "hge",
    2062             :                 .name_ne = "hge_noerror",
    2063             :                 .fname = "CMDconvertsignal_hge",
    2064             :                 .fname_ne = "CMDconvert_hge",
    2065             :                 .fcn = (fptr)CMDconvertsignal_hge,
    2066             :                 .fcn_ne = (fptr)CMDconvert_hge,
    2067             : #endif
    2068             :           }, {
    2069             :                 .type = TYPE_flt,
    2070             :                 .name = "flt",
    2071             :                 .name_ne = "flt_noerror",
    2072             :                 .fname = "CMDconvertsignal_flt",
    2073             :                 .fname_ne = "CMDconvert_flt",
    2074             :                 .fcn = (fptr)CMDconvertsignal_flt,
    2075             :                 .fcn_ne = (fptr)CMDconvert_flt,
    2076             :           }, {
    2077             :                 .type = TYPE_dbl,
    2078             :                 .name = "dbl",
    2079             :                 .name_ne = "dbl_noerror",
    2080             :                 .fname = "CMDconvertsignal_dbl",
    2081             :                 .fname_ne = "CMDconvert_dbl",
    2082             :                 .fcn = (fptr)CMDconvertsignal_dbl,
    2083             :                 .fcn_ne = (fptr)CMDconvert_dbl,
    2084             :           }, {
    2085             :                 .type = TYPE_oid,
    2086             :                 .name = "oid",
    2087             :                 .name_ne = "oid_noerror",
    2088             :                 .fname = "CMDconvertsignal_oid",
    2089             :                 .fname_ne = "CMDconvert_oid",
    2090             :                 .fcn = (fptr)CMDconvertsignal_oid,
    2091             :                 .fcn_ne = (fptr)CMDconvert_oid,
    2092             :           }, {
    2093             :                 .type = TYPE_str,
    2094             :                 .name = "str",
    2095             :                 .name_ne = "str_noerror",
    2096             :                 .fname = "CMDconvertsignal_str",
    2097             :                 .fname_ne = "CMDconvert_str",
    2098             :                 .fcn = (fptr)CMDconvertsignal_str,
    2099             :                 .fcn_ne = (fptr)CMDconvert_str,
    2100             :           }
    2101             :         };
    2102             : #ifdef HAVE_HGE
    2103             :         int typeopslen = 10;
    2104             : #else
    2105             :         int typeopslen = 9;
    2106             : #endif
    2107        2871 :         for(int t = 0; t<typeopslen; t++) {
    2108             :                 /* from any 2 string */
    2109        2610 :                 mel_func_arg ret = { .type = typeops[t].type, .isbat =1 };
    2110        2610 :                 if (strcmp(typeops[t].name, "str")==0) {
    2111         261 :                         mel_func_arg arg = { .type = TYPE_any, .isbat =1 };
    2112             : 
    2113         261 :                         err += melFunction(false, "batcalc", typeops[t].name, typeops[t].fcn, typeops[t].fname, false, "", 1, 2, ret, arg);
    2114         261 :                         err += melFunction(false, "batcalc", typeops[t].name, typeops[t].fcn, typeops[t].fname, false, "", 1, 3, ret, arg, cand);
    2115         261 :                         err += melFunction(false, "batcalc", typeops[t].name_ne, typeops[t].fcn_ne, typeops[t].fname_ne, false, "", 1, 2, ret, arg);
    2116         261 :                         err += melFunction(false, "batcalc", typeops[t].name_ne, typeops[t].fcn_ne, typeops[t].fname_ne, false, "", 1, 3, ret, arg, cand);
    2117             :                 } else {
    2118       25839 :                     for(int p = 0; p<typeopslen; p++) {
    2119       23490 :                                 mel_func_arg arg = { .type = typeops[p].type, .isbat =1 };
    2120             : 
    2121       23490 :                                 err += melFunction(false, "batcalc", typeops[t].name, typeops[t].fcn, typeops[t].fname, false, "", 1, 2, ret, arg);
    2122       23490 :                                 err += melFunction(false, "batcalc", typeops[t].name, typeops[t].fcn, typeops[t].fname, false, "", 1, 3, ret, arg, cand);
    2123       23490 :                                 err += melFunction(false, "batcalc", typeops[t].name_ne, typeops[t].fcn_ne, typeops[t].fname_ne, false, "", 1, 2, ret, arg);
    2124       23490 :                                 err += melFunction(false, "batcalc", typeops[t].name_ne, typeops[t].fcn_ne, typeops[t].fname_ne, false, "", 1, 3, ret, arg, cand);
    2125             :                     }
    2126             :                 }
    2127             :         }
    2128         261 :         return MAL_SUCCEED;
    2129             : }
    2130             : 
    2131             : static mel_func batcalc_init_funcs[] = {
    2132             :  /* batcalc */
    2133             :  pattern("batcalc", "isnil", CMDbatISNIL, false, "Unary check for nil over the tail of the bat", args(1,2, batarg("",bit),batargany("b",0))),
    2134             :  pattern("batcalc", "isnil", CMDbatISNIL, false, "Unary check for nil over the tail of the bat with candidates list", args(1,3, batarg("",bit),batargany("b",0),batarg("s",oid))),
    2135             :  pattern("batcalc", "isnotnil", CMDbatISNOTNIL, false, "Unary check for notnil over the tail of the bat", args(1,2, batarg("",bit),batargany("b",0))),
    2136             :  pattern("batcalc", "isnotnil", CMDbatISNOTNIL, false, "Unary check for notnil over the tail of the bat with candidates list", args(1,3, batarg("",bit),batargany("b",0),batarg("s",oid))),
    2137             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,3, batargany("",1),batargany("b1",1),batargany("b2",1))),
    2138             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,5, batargany("",1),batargany("b1",1),batargany("b2",1),batarg("s1",oid),batarg("s2",oid))),
    2139             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,3, batargany("",1),batargany("b",1),argany("v",1))),
    2140             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,4, batargany("",1),batargany("b",1),argany("v",1),batarg("s",oid))),
    2141             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,3, batargany("",1),argany("v",1),batargany("b",1))),
    2142             :  pattern("batcalc", "min", CMDbatMIN, false, "Return bat with minimum value of each pair of inputs", args(1,4, batargany("",1),argany("v",1),batargany("b",1),batarg("s",oid))),
    2143             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),batargany("b1",1),batargany("b2",1))),
    2144             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,5, batargany("",1),batargany("b1",1),batargany("b2",1),batarg("s1",oid),batarg("s2",oid))),
    2145             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),batargany("b",1),argany("v",1))),
    2146             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,4, batargany("",1),batargany("b",1),argany("v",1),batarg("s",oid))),
    2147             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),argany("v",1),batargany("b",1))),
    2148             :  pattern("batcalc", "min_no_nil", CMDbatMIN_no_nil, false, "Return bat with minimum value of each pair of inputs, ignoring nil values", args(1,4, batargany("",1),argany("v",1),batargany("b",1),batarg("s",oid))),
    2149             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,3, batargany("",1),batargany("b1",1),batargany("b2",1))),
    2150             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,5, batargany("",1),batargany("b1",1),batargany("b2",1),batarg("s1",oid),batarg("s2",oid))),
    2151             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,3, batargany("",1),batargany("b",1),argany("v",1))),
    2152             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,4, batargany("",1),batargany("b",1),argany("v",1),batarg("s",oid))),
    2153             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,3, batargany("",1),argany("v",1),batargany("b",1))),
    2154             :  pattern("batcalc", "max", CMDbatMAX, false, "Return bat with maximum value of each pair of inputs", args(1,4, batargany("",1),argany("v",1),batargany("b",1),batarg("s",oid))),
    2155             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),batargany("b1",1),batargany("b2",1))),
    2156             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,5, batargany("",1),batargany("b1",1),batargany("b2",1),batarg("s1",oid),batarg("s2",oid))),
    2157             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),batargany("b",1),argany("v",1))),
    2158             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,4, batargany("",1),batargany("b",1),argany("v",1),batarg("s",oid))),
    2159             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,3, batargany("",1),argany("v",1),batargany("b",1))),
    2160             :  pattern("batcalc", "max_no_nil", CMDbatMAX_no_nil, false, "Return bat with maximum value of each pair of inputs, ignoring nil values", args(1,4, batargany("",1),argany("v",1),batargany("b",1),batarg("s",oid))),
    2161             : 
    2162             :  pattern("batcalc", "+", CMDbatADD, false, "Return concatenation of B1 and B2 with candidates list", args(1,5, batarg("",str),batarg("b1",str),batarg("b2",str),batarg("s1",oid),batarg("s2",oid))),
    2163             :  pattern("batcalc", "+", CMDbatADD, false, "Return concatenation of B and V with candidates list", args(1,4, batarg("",str),batarg("b",str),arg("v",str),batarg("s",oid))),
    2164             :  pattern("batcalc", "+", CMDbatADD, false, "Return concatenation of V and B with candidates list", args(1,4, batarg("",str),arg("v",str),batarg("b",str),batarg("s",oid))),
    2165             : 
    2166             :  pattern("batmmath", "fmod", CMDbatMODsignal, false, "", args(1,3, batarg("",dbl),batarg("x",dbl),arg("y",dbl))),
    2167             :  pattern("batmmath", "fmod", CMDbatMODsignal, false, "", args(1,4, batarg("",dbl),batarg("x",dbl),arg("y",dbl),batarg("s",oid))),
    2168             :  pattern("batmmath", "fmod", CMDbatMODsignal, false, "", args(1,3, batarg("",flt),batarg("x",flt),arg("y",flt))),
    2169             :  pattern("batmmath", "fmod", CMDbatMODsignal, false, "", args(1,4, batarg("",flt),batarg("x",flt),arg("y",flt),batarg("s",oid))),
    2170             : 
    2171             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa)", args(1,9, batarg("",bit),batargany("b",1),batargany("v1",1),batargany("v2",1),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2172             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa) with candidates list", args(1,12, batarg("",bit),batargany("b",1),batargany("v1",1),batargany("v2",1),batarg("s",oid),batarg("s1",oid),batarg("s2",oid),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2173             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa)", args(1,9, batarg("",bit),batargany("b",1),batargany("v1",1),argany("v2",1),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2174             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa) with candidates list", args(1,11, batarg("",bit),batargany("b",1),batargany("v1",1),argany("v2",1),batarg("s",oid),batarg("s1",oid),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2175             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa)", args(1,9, batarg("",bit),batargany("b",1),argany("v1",1),batargany("v2",1),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2176             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa) with candidates list", args(1,11, batarg("",bit),batargany("b",1),argany("v1",1),batargany("v2",1),batarg("s",oid),batarg("s2",oid),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2177             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa)", args(1,9, batarg("",bit),batargany("b",1),argany("v1",1),argany("v2",1),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2178             :  pattern("batcalc", "between", CMDbatBETWEEN, false, "B between V1 and V2 (or vice versa) with candidates list", args(1,10, batarg("",bit),batargany("b",1),argany("v1",1),argany("v2",1),batarg("s",oid),arg("sym",bit),arg("linc",bit),arg("hinc",bit),arg("nils_false",bit),arg("anti",bit))),
    2179             : 
    2180             :  pattern("aggr", "avg", CMDcalcavg, false, "Gives the avg of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
    2181             :  pattern("aggr", "avg", CMDcalcavg, false, "Gives the avg of all tail values", args(1,3, arg("",dbl),batargany("b",2),arg("scale",int))),
    2182             : 
    2183             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),arg("v",bit),batargany("b1",1),batargany("b2",1))),
    2184             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),arg("v",bit),argany("v1",1),batargany("b2",1))),
    2185             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),arg("v",bit),batargany("b1",1),argany("v2",1))),
    2186             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),batarg("b",bit),argany("v1",1),argany("v2",1))),
    2187             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),batarg("b",bit),batargany("b1",1),argany("v2",1))),
    2188             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),batarg("b",bit),argany("v1",1),batargany("b2",1))),
    2189             :  pattern("batcalc", "ifthenelse", CMDifthen, false, "If-then-else operation to assemble a conditional result", args(1,4, batargany("",1),batarg("b",bit),batargany("b1",1),batargany("b2",1))),
    2190             :  { .imp=NULL }
    2191             : };
    2192             : #include "mal_import.h"
    2193             : #ifdef _MSC_VER
    2194             : #undef read
    2195             : #pragma section(".CRT$XCU",read)
    2196             : #endif
    2197         255 : LIB_STARTUP_FUNC(init_batcalc_mal)
    2198         255 : { mal_module2("batcalc", NULL, batcalc_init_funcs, &batcalc_init, NULL); }

Generated by: LCOV version 1.14