LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - batcalc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 766 970 79.0 %
Date: 2024-10-03 20:03:20 Functions: 51 60 85.0 %

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

Generated by: LCOV version 1.14