IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Dec 7, 2008, 3:31:01 PM (17 years ago)
Author:
eugene
Message:

big update from eam_branch_20081124 with updates to Opihi math

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/lib.shell/stack_math.c

    r18078 r20936  
    44   labeled by "m". if one of the input matrices is already a temp variable, we
    55   can continue using it this round
    6    */
     6*/
     7
     8// XXX we temporarily drop the concept of using one of the temporary input vectors for
     9// the output vector (thus saving an ALLOC): we have to juggle the size of the input vectors
     10// as well as their temporary state
    711
    812int VV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    913
    1014  int i, Nx;
    11   float *out, *M1, *M2;
     15  char line[512]; // this is only used to report an error
     16 
     17  // the vectors have to match in length
     18  if (V1[0].vector[0].Nelements != V2[0].vector[0].Nelements) {
     19    return (FALSE);
     20  }
     21
     22  Nx = V1[0].vector[0].Nelements;
     23
     24  // create the output vector guaranteed to be temporary until the very end
     25  OUT[0].vector = InitVector ();
     26  OUT[0].type = 'v';
     27
     28  // set up the possible operations : int OP int -> int, all else yield float
     29  // OP is the operation performed on *M1 and *M2
     30# define VV_FUNC(FTYPE,OP) {                                            \
     31    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type == OPIHI_FLT)) { \
     32      CopyVector (OUT[0].vector, V1[0].vector);                         \
     33      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     34      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;                   \
     35      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     36      for (i = 0; i < Nx; i++, out++, M1++, M2++) {                     \
     37        *out = OP;                                                      \
     38      }                                                                 \
     39      break;                                                            \
     40    }                                                                   \
     41    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type != OPIHI_FLT)) { \
     42      CopyVector (OUT[0].vector, V1[0].vector);                         \
     43      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     44      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     45      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     46      for (i = 0; i < Nx; i++, out++, M1++, M2++) {                     \
     47        *out = OP;                                                      \
     48      }                                                                 \
     49      break;                                                            \
     50    }                                                                   \
     51    if ((V1->vector->type != OPIHI_FLT) && (V2->vector->type == OPIHI_FLT)) { \
     52      CopyVector (OUT[0].vector, V2[0].vector);                         \
     53      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     54      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;                   \
     55      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     56      for (i = 0; i < Nx; i++, out++, M1++, M2++) {                     \
     57        *out = OP;                                                      \
     58      }                                                                 \
     59      break;                                                            \
     60    }                                                                   \
     61    if ((FTYPE == 'S') && (V1->vector->type != OPIHI_FLT) && (V2->vector->type != OPIHI_FLT)) { \
     62      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);             \
     63      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     64      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     65      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     66      for (i = 0; i < Nx; i++, out++, M1++, M2++) {                     \
     67        *out = OP;                                                      \
     68      }                                                                 \
     69      break;                                                            \
     70    }                                                                   \
     71    if ((V1->vector->type != OPIHI_FLT) && (V2->vector->type != OPIHI_FLT)) { \
     72      CopyVector (OUT[0].vector, V1[0].vector);                         \
     73      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     74      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     75      opihi_int *out = OUT[0].vector[0].elements.Int;                   \
     76      for (i = 0; i < Nx; i++, out++, M1++, M2++) {                     \
     77        *out = OP;                                                      \
     78      }                                                                 \
     79      break;                                                            \
     80    }                                                                   \
     81  }
     82
     83  switch (op[0]) {
     84    case '+': VV_FUNC('s', *M1 + *M2);
     85    case '-': VV_FUNC('s', *M1 - *M2);
     86    case '*': VV_FUNC('s', *M1 * *M2);
     87    case '/': VV_FUNC('S', *M1 / (opihi_flt) *M2);
     88    case '%': VV_FUNC('s', (int)*M1 % (int)*M2);
     89    case '^': VV_FUNC('S', pow (*M1, *M2));
     90    case '@': VV_FUNC('S', DEG_RAD*atan2 (*M1, *M2));
     91    case 'D': VV_FUNC('s', MIN (*M1, *M2));
     92    case 'U': VV_FUNC('s', MAX (*M1, *M2));
     93    case '<': VV_FUNC('s', (*M1 < *M2) ? 1 : 0);
     94    case '>': VV_FUNC('s', (*M1 > *M2) ? 1 : 0);
     95    case '&': VV_FUNC('s', ((int)*M1 & (int)*M2));
     96    case '|': VV_FUNC('s', ((int)*M1 | (int)*M2));
     97    case 'E': VV_FUNC('s', (*M1 == *M2) ? 1 : 0);
     98    case 'N': VV_FUNC('s', (*M1 != *M2) ? 1 : 0);
     99    case 'L': VV_FUNC('s', (*M1 <= *M2) ? 1 : 0);
     100    case 'G': VV_FUNC('s', (*M1 >= *M2) ? 1 : 0);
     101    case 'A': VV_FUNC('s', (*M1 && *M2) ? 1 : 0);
     102    case 'O': VV_FUNC('s', (*M1 || *M2) ? 1 : 0);
     103    default:
     104      sprintf (line, "error: op %c not defined!", op[0]);
     105      push_error (line);
     106      return (FALSE);
     107  }
     108# undef VV_FUNC
     109
     110  /** free up any temporary buffers: **/
     111
     112  if (V1[0].type == 'v') {
     113    free (V1[0].vector[0].elements.Ptr);
     114    free (V1[0].vector);
     115  }
     116  if (V2[0].type == 'v') {
     117    free (V2[0].vector[0].elements.Ptr);
     118    free (V2[0].vector);
     119  }
     120  /* at the end, V1 and V2 are deleted only if they were temporary */
     121
     122  clear_stack (V1);
     123  clear_stack (V2);
     124  return (TRUE);
     125
     126}
     127
     128int SV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
     129
     130  int i, Nx;
     131  char line[512]; // this is only used to report an error
     132 
     133  Nx = V2[0].vector[0].Nelements;
     134
     135  OUT[0].vector = InitVector ();
     136  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
     137
     138  // set up the possible operations : int OP int -> int, all else yield float
     139  // OP is the operation performed on *M1 and *M2
     140# define SV_FUNC(FTYPE,OP) {                                            \
     141    if ((V1->type == 'S') && (V2->vector->type == OPIHI_FLT)) {         \
     142      CopyVector (OUT[0].vector, V2[0].vector);                         \
     143      opihi_flt  M1  =  V1[0].FltValue;                                 \
     144      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;                   \
     145      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     146      for (i = 0; i < Nx; i++, out++, M2++) {                           \
     147        *out = OP;                                                      \
     148      }                                                                 \
     149      break;                                                            \
     150    }                                                                   \
     151    if ((V1->type == 'S') && (V2->vector->type != OPIHI_FLT)) {         \
     152      MatchVector (OUT[0].vector, V2[0].vector, OPIHI_FLT);             \
     153      opihi_flt  M1  =  V1[0].FltValue;                                 \
     154      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     155      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     156      for (i = 0; i < Nx; i++, out++, M2++) {                           \
     157        *out = OP;                                                      \
     158      }                                                                 \
     159      break;                                                            \
     160    }                                                                   \
     161    if ((V1->type == 's') && (V2->vector->type == OPIHI_FLT)) {         \
     162      CopyVector (OUT[0].vector, V2[0].vector);                         \
     163      opihi_int  M1  =  V1[0].IntValue;                                 \
     164      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;                   \
     165      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     166      for (i = 0; i < Nx; i++, out++, M2++) {                           \
     167        *out = OP;                                                      \
     168      }                                                                 \
     169      break;                                                            \
     170    }                                                                   \
     171    if ((FTYPE == 'S') && (V1->type == 's') && (V2->vector->type != OPIHI_FLT)) { \
     172      MatchVector (OUT[0].vector, V2[0].vector, OPIHI_FLT);             \
     173      opihi_int  M1  =  V1[0].IntValue;                                 \
     174      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     175      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     176      for (i = 0; i < Nx; i++, out++, M2++) {                           \
     177        *out = OP;                                                      \
     178      }                                                                 \
     179      break;                                                            \
     180    }                                                                   \
     181    if ((V1->type == 's') && (V2->vector->type != OPIHI_FLT)) {         \
     182      CopyVector (OUT[0].vector, V2[0].vector);                         \
     183      opihi_int  M1  =  V1[0].IntValue;                                 \
     184      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     185      opihi_int *out = OUT[0].vector[0].elements.Int;                   \
     186      for (i = 0; i < Nx; i++, out++, M2++) {                           \
     187        *out = OP;                                                      \
     188      }                                                                 \
     189      break;                                                            \
     190    }                                                                   \
     191  }
     192
     193  switch (op[0]) {
     194    case '+': SV_FUNC('s', M1 + *M2);
     195    case '-': SV_FUNC('s', M1 - *M2);
     196    case '*': SV_FUNC('s', M1 * *M2);
     197    case '/': SV_FUNC('S', M1 / (opihi_flt) *M2);
     198    case '%': SV_FUNC('s', (int) M1 % (int) *M2);
     199    case '^': SV_FUNC('S', pow (M1, *M2));
     200    case '@': SV_FUNC('S', DEG_RAD*atan2 (M1, *M2));
     201    case 'D': SV_FUNC('s', MIN (M1, *M2));
     202    case 'U': SV_FUNC('s', MAX (M1, *M2));
     203    case '<': SV_FUNC('s', (M1 < *M2) ? 1 : 0);
     204    case '>': SV_FUNC('s', (M1 > *M2) ? 1 : 0);
     205    case '&': SV_FUNC('s', ((int)M1 & (int)*M2));
     206    case '|': SV_FUNC('s', ((int)M1 | (int)*M2));
     207    case 'E': SV_FUNC('s', (M1 == *M2) ? 1 : 0);
     208    case 'N': SV_FUNC('s', (M1 != *M2) ? 1 : 0);
     209    case 'L': SV_FUNC('s', (M1 <= *M2) ? 1 : 0);
     210    case 'G': SV_FUNC('s', (M1 >= *M2) ? 1 : 0);
     211    case 'A': SV_FUNC('s', (M1 && *M2) ? 1 : 0);
     212    case 'O': SV_FUNC('s', (M1 || *M2) ? 1 : 0);
     213    default:
     214      sprintf (line, "error: op %c not defined!", op[0]);
     215      push_error (line);
     216      return (FALSE);
     217  }
     218# undef SV_FUNC
     219
     220  /** free up any temporary buffers: **/
     221  if (V2[0].type == 'v') {
     222    free (V2[0].vector[0].elements.Ptr);
     223    free (V2[0].vector);
     224  }
     225
     226  clear_stack (V1);
     227  clear_stack (V2);
     228
     229  /* at the end, V1 and V2 are deleted only if they were temporary */
     230  return (TRUE);
     231
     232}
     233
     234int VS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
     235
     236  int i, Nx;
    12237  char line[512]; // this is only used to report an error
    13238 
    14239  Nx = V1[0].vector[0].Nelements;
    15   if (Nx != V2[0].vector[0].Nelements) {
    16     return (FALSE);
    17   }
    18 
    19   if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
    20     OUT[0].vector = V1[0].vector;
    21     V1[0].type = 'V'; /* prevent it from being freed below */
    22   } else {
    23     if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
    24       OUT[0].vector = V2[0].vector;
    25       V2[0].type = 'V'; /* prevent it from being freed below */
    26     } else {  /* no spare temp buffer */
    27       OUT[0].vector = InitVector ();
    28       CopyVector (OUT[0].vector, V1[0].vector);
    29     }
    30   }
    31   OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
    32 
    33   M1  = V1[0].ptr;
    34   M2  = V2[0].ptr;
    35   out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
     240
     241  OUT[0].vector = InitVector ();
     242  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
     243
     244  // set up the possible operations : int OP int -> int, all else yield float
     245  // OP is the operation performed on *M1 and *M2
     246# define VS_FUNC(FTYPE,OP) {                                            \
     247    if ((V2->type == 'S') && (V1->vector->type == OPIHI_FLT)) {         \
     248      CopyVector (OUT[0].vector, V1[0].vector);                         \
     249      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     250      opihi_flt  M2  =  V2[0].FltValue;                                 \
     251      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     252      for (i = 0; i < Nx; i++, out++, M1++) {                           \
     253        *out = OP;                                                      \
     254      }                                                                 \
     255      break;                                                            \
     256    }                                                                   \
     257    if ((V2->type == 'S') && (V1->vector->type != OPIHI_FLT)) {         \
     258      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);             \
     259      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     260      opihi_flt  M2  =  V2[0].FltValue;                                 \
     261      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     262      for (i = 0; i < Nx; i++, out++, M1++) {                           \
     263        *out = OP;                                                      \
     264      }                                                                 \
     265      break;                                                            \
     266    }                                                                   \
     267    if ((V2->type == 's') && (V1->vector->type == OPIHI_FLT)) {         \
     268      CopyVector (OUT[0].vector, V1[0].vector);                         \
     269      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     270      opihi_int  M2  =  V2[0].IntValue;                                 \
     271      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     272      for (i = 0; i < Nx; i++, out++, M1++) {                           \
     273        *out = OP;                                                      \
     274      }                                                                 \
     275      break;                                                            \
     276    }                                                                   \
     277    if ((FTYPE == 'S') && (V2->type == 's') && (V1->vector->type != OPIHI_FLT)) { \
     278      CopyVector (OUT[0].vector, V1[0].vector);                         \
     279      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     280      opihi_int  M2  =  V2[0].IntValue;                                 \
     281      opihi_int *out = OUT[0].vector[0].elements.Int;                   \
     282      for (i = 0; i < Nx; i++, out++, M1++) {                           \
     283        *out = OP;                                                      \
     284      }                                                                 \
     285      break;                                                            \
     286    }                                                                   \
     287    if ((V2->type == 's') && (V1->vector->type != OPIHI_FLT)) {         \
     288      CopyVector (OUT[0].vector, V1[0].vector);                         \
     289      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     290      opihi_int  M2  =  V2[0].IntValue;                                 \
     291      opihi_int *out = OUT[0].vector[0].elements.Int;                   \
     292      for (i = 0; i < Nx; i++, out++, M1++) {                           \
     293        *out = OP;                                                      \
     294      }                                                                 \
     295      break;                                                            \
     296    }                                                                   \
     297  }
    36298
    37299  switch (op[0]) {
    38   case '+':
    39     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    40       *out = *M1 + *M2;
    41     break;
    42   case '-':
    43     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    44       *out = *M1 - *M2;
    45     break;
    46   case '*':
    47     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    48       *out = *M1 * *M2;
    49     break;
    50   case '/':
    51     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    52       *out = *M1 / *M2;
    53     break;
    54   case '%':
    55     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    56       *out = (int) *M1 % (int) *M2;
    57     break;
    58   case 0x5e:
    59     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    60       *out = pow (*M1, *M2);
    61     break;
    62   case '@':
    63     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    64       *out = DEG_RAD*atan2 (*M1, *M2);
    65     break;
    66   case 'D':
    67     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    68       *out = MIN (*M1, *M2);
    69     break;
    70   case 'U':
    71     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    72       *out = MAX (*M1, *M2);
    73     break;
    74   case '<':
    75     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    76       *out = (*M1 < *M2) ? 1 : 0;
    77     break;
    78   case '>':
    79     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    80       *out = (*M1 > *M2) ? 1 : 0;
    81     break;
    82   case '&':
    83     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    84       *out = ((int)*M1 & (int)*M2);
    85     break;
    86   case '|':
    87     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    88       *out = ((int)*M1 | (int)*M2);
    89     break;
    90   case 'E':
    91     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    92       *out = (*M1 == *M2) ? 1 : 0;
    93     break;
    94   case 'N':
    95     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    96       *out = (*M1 != *M2) ? 1 : 0;
    97     break;
    98   case 'L':
    99     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    100       *out = (*M1 <= *M2) ? 1 : 0;
    101     break;
    102   case 'G':
    103     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    104       *out = (*M1 >= *M2) ? 1 : 0;
    105     break;
    106   case 'A':
    107     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    108       *out = (*M1 && *M2) ? 1 : 0;
    109     break;
    110   case 'O':
    111     for (i = 0; i < Nx; i++, out++, M1++, M2++)
    112       *out = (*M1 || *M2) ? 1 : 0;
    113     break;
    114   default:
    115     sprintf (line, "error: op %c not defined!", op[0]);
    116     push_error (line);
    117     return (FALSE);
    118   }
     300    case '+': VS_FUNC('s', *M1 + M2);
     301    case '-': VS_FUNC('s', *M1 - M2);
     302    case '*': VS_FUNC('s', *M1 * M2);
     303    case '/': VS_FUNC('S', *M1 / (opihi_flt) M2);
     304    case '%': VS_FUNC('s', (int) *M1 % (int) M2);
     305    case '^': VS_FUNC('S', pow (*M1, M2));
     306    case '@': VS_FUNC('S', DEG_RAD*atan2 (*M1, M2));
     307    case 'D': VS_FUNC('s', MIN (*M1, M2));
     308    case 'U': VS_FUNC('s', MAX (*M1, M2));
     309    case '<': VS_FUNC('s', (*M1 < M2) ? 1 : 0);
     310    case '>': VS_FUNC('s', (*M1 > M2) ? 1 : 0);
     311    case '&': VS_FUNC('s', ((int)*M1 & (int)M2));
     312    case '|': VS_FUNC('s', ((int)*M1 | (int)M2));
     313    case 'E': VS_FUNC('s', (*M1 == M2) ? 1 : 0);
     314    case 'N': VS_FUNC('s', (*M1 != M2) ? 1 : 0);
     315    case 'L': VS_FUNC('s', (*M1 <= M2) ? 1 : 0);
     316    case 'G': VS_FUNC('s', (*M1 >= M2) ? 1 : 0);
     317    case 'A': VS_FUNC('s', (*M1 && M2) ? 1 : 0);
     318    case 'O': VS_FUNC('s', (*M1 || M2) ? 1 : 0);
     319    default:
     320      sprintf (line, "error: op %c not defined!", op[0]);
     321      push_error (line);
     322      return (FALSE);
     323  }
     324# undef VS_FUNC
    119325
    120326  /** free up any temporary buffers: **/
    121327
    122328  if (V1[0].type == 'v') {
    123     free (V1[0].vector[0].elements);
     329    free (V1[0].vector[0].elements.Ptr);
    124330    free (V1[0].vector);
    125331  }
    126   if (V2[0].type == 'v') {
    127     free (V2[0].vector[0].elements);
    128     free (V2[0].vector);
    129   }
     332
     333  clear_stack (V1);
     334  clear_stack (V2);
     335
    130336  /* at the end, V1 and V2 are deleted only if they were temporary */
    131 
    132   clear_stack (V1);
    133   clear_stack (V2);
    134   return (TRUE);
    135 
    136 }
    137 
    138 int SV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    139 
    140   int i, Nx;
    141   float *out, *M1, *M2;
    142   char line[512]; // this is only used to report an error
    143  
    144   Nx = V2[0].vector[0].Nelements;
    145 
    146   if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
    147     OUT[0].vector = V2[0].vector;
    148     V2[0].type = 'V'; /* prevent it from being freed below */
    149   } else {  /* no spare temp buffer */
    150     OUT[0].vector = InitVector ();
    151     CopyVector (OUT[0].vector, V2[0].vector);
    152   }
    153   OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
    154 
    155   M1  = V1[0].ptr;
    156   M2  = V2[0].ptr;
    157   out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
    158 
    159   switch (op[0]) {
    160   case '+':
    161     for (i = 0; i < Nx; i++, out++, M2++)
    162       *out = *M1 + *M2;
    163     break;
    164   case '-':
    165     for (i = 0; i < Nx; i++, out++, M2++)
    166       *out = *M1 - *M2;
    167     break;
    168   case '*':
    169     for (i = 0; i < Nx; i++, out++, M2++)
    170       *out = *M1 * *M2;
    171     break;
    172   case '/':
    173     for (i = 0; i < Nx; i++, out++, M2++)
    174       *out = *M1 / *M2;
    175     break;
    176   case '%':
    177     for (i = 0; i < Nx; i++, out++, M2++)
    178       *out = (int) *M1 % (int) *M2;
    179     break;
    180   case 0x5e:
    181     for (i = 0; i < Nx; i++, out++, M2++)
    182       *out = pow (*M1, *M2);
    183     break;
    184   case '@':
    185     for (i = 0; i < Nx; i++, out++, M2++)
    186       *out = DEG_RAD*atan2 (*M1, *M2);
    187     break;
    188   case 'D':
    189     for (i = 0; i < Nx; i++, out++, M2++)
    190       *out = MIN (*M1, *M2);
    191     break;
    192   case 'U':
    193     for (i = 0; i < Nx; i++, out++, M2++)
    194       *out = MAX (*M1, *M2);
    195     break;
    196   case '<':
    197     for (i = 0; i < Nx; i++, out++, M2++)
    198       *out = (*M1 < *M2) ? 1 : 0;
    199     break;
    200   case '>':
    201     for (i = 0; i < Nx; i++, out++, M2++)
    202       *out = (*M1 > *M2) ? 1 : 0;
    203     break;
    204   case '&':
    205     for (i = 0; i < Nx; i++, out++, M2++)
    206       *out = ((int)*M1 & (int)*M2);
    207     break;
    208   case '|':
    209     for (i = 0; i < Nx; i++, out++, M2++)
    210       *out = ((int)*M1 | (int)*M2);
    211     break;
    212   case 'E':
    213     for (i = 0; i < Nx; i++, out++, M2++)
    214       *out = (*M1 == *M2) ? 1 : 0;
    215     break;
    216   case 'N':
    217     for (i = 0; i < Nx; i++, out++, M2++)
    218       *out = (*M1 != *M2) ? 1 : 0;
    219     break;
    220   case 'L':
    221     for (i = 0; i < Nx; i++, out++, M2++)
    222       *out = (*M1 <= *M2) ? 1 : 0;
    223     break;
    224   case 'G':
    225     for (i = 0; i < Nx; i++, out++, M2++)
    226       *out = (*M1 >= *M2) ? 1 : 0;
    227     break;
    228   case 'A':
    229     for (i = 0; i < Nx; i++, out++, M2++)
    230       *out = (*M1 && *M2) ? 1 : 0;
    231     break;
    232   case 'O':
    233     for (i = 0; i < Nx; i++, out++, M2++)
    234       *out = (*M1 || *M2) ? 1 : 0;
    235     break;
    236   default:
    237     sprintf (line, "error: op %c not defined!", op[0]);
    238     push_error (line);
    239     return (FALSE);
    240   }
    241 
    242   /** free up any temporary buffers: **/
    243   if (V2[0].type == 'v') {
    244     free (V2[0].vector[0].elements);
    245     free (V2[0].vector);
    246   }
    247 
    248   clear_stack (V1);
    249   clear_stack (V2);
    250 
    251   /* at the end, V1 and V2 are deleted only if they were temporary */
    252   return (TRUE);
    253 
    254 }
    255 
    256 int VS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    257 
    258   int i, Nx;
    259   float *out, *M1, *M2;
    260   char line[512]; // this is only used to report an error
    261  
    262   Nx = V1[0].vector[0].Nelements;
    263 
    264   if (V1[0].type == 'v') { /** use V1 as temp buffer **/
    265     OUT[0].vector = V1[0].vector;
    266     V1[0].type = 'V'; /* prevent it from being freed below */
    267   } else {  /* no spare temp buffer */
    268     OUT[0].vector = InitVector ();
    269     CopyVector (OUT[0].vector, V1[0].vector);
    270   }
    271   OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
    272 
    273   M1  = V1[0].ptr;
    274   M2  = V2[0].ptr;
    275   out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
    276 
    277   switch (op[0]) {
    278   case '+':
    279     for (i = 0; i < Nx; i++, out++, M1++)
    280       *out = *M1 + *M2;
    281     break;
    282   case '-':
    283     for (i = 0; i < Nx; i++, out++, M1++)
    284       *out = *M1 - *M2;
    285     break;
    286   case '*':
    287     for (i = 0; i < Nx; i++, out++, M1++)
    288       *out = *M1 * *M2;
    289     break;
    290   case '/':
    291     for (i = 0; i < Nx; i++, out++, M1++)
    292       *out = *M1 / *M2;
    293     break;
    294   case '%':
    295     for (i = 0; i < Nx; i++, out++, M1++)
    296       *out = (int) *M1 % (int) *M2;
    297     break;
    298   case 0x5e:
    299     for (i = 0; i < Nx; i++, out++, M1++)
    300       *out = pow (*M1, *M2);
    301     break;
    302   case '@':
    303     for (i = 0; i < Nx; i++, out++, M1++)
    304       *out = DEG_RAD*atan2 (*M1, *M2);
    305     break;
    306   case 'D':
    307     for (i = 0; i < Nx; i++, out++, M1++)
    308       *out = MIN (*M1, *M2);
    309     break;
    310   case 'U':
    311     for (i = 0; i < Nx; i++, out++, M1++)
    312       *out = MAX (*M1, *M2);
    313     break;
    314   case '<':
    315     for (i = 0; i < Nx; i++, out++, M1++)
    316       *out = (*M1 < *M2) ? 1 : 0;
    317     break;
    318   case '>':
    319     for (i = 0; i < Nx; i++, out++, M1++)
    320       *out = (*M1 > *M2) ? 1 : 0;
    321     break;
    322   case '&':
    323     for (i = 0; i < Nx; i++, out++, M1++)
    324       *out = ((int)*M1 & (int)*M2);
    325     break;
    326   case '|':
    327     for (i = 0; i < Nx; i++, out++, M1++)
    328       *out = ((int)*M1 | (int)*M2);
    329     break;
    330   case 'E':
    331     for (i = 0; i < Nx; i++, out++, M1++)
    332       *out = (*M1 == *M2) ? 1 : 0;
    333     break;
    334   case 'N':
    335     for (i = 0; i < Nx; i++, out++, M1++)
    336       *out = (*M1 != *M2) ? 1 : 0;
    337     break;
    338   case 'L':
    339     for (i = 0; i < Nx; i++, out++, M1++)
    340       *out = (*M1 <= *M2) ? 1 : 0;
    341     break;
    342   case 'G':
    343     for (i = 0; i < Nx; i++, out++, M1++)
    344       *out = (*M1 >= *M2) ? 1 : 0;
    345     break;
    346   case 'A':
    347     for (i = 0; i < Nx; i++, out++, M1++)
    348       *out = (*M1 && *M2) ? 1 : 0;
    349     break;
    350   case 'O':
    351     for (i = 0; i < Nx; i++, out++, M1++)
    352       *out = (*M1 || *M2) ? 1 : 0;
    353     break;
    354   default:
    355     sprintf (line, "error: op %c not defined!", op[0]);
    356     push_error (line);
    357     return (FALSE);
    358   }
    359 
    360   /** free up any temporary buffers: **/
    361 
    362   if (V1[0].type == 'v') {
    363     free (V1[0].vector[0].elements);
    364     free (V1[0].vector);
    365   }
    366 
    367   clear_stack (V1);
    368   clear_stack (V2);
    369 
    370   /* at the end, V1 and V2 are deleted only if they were temporary */
    371   return (TRUE);
    372 
    373 }
    374 
     337  return (TRUE);
     338
     339}
     340
     341// the vector is applied to each column
    375342int MV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    376343
    377344  int i, j, Nx, Ny;
    378   float *out, *M1, *M2;
    379345  char line[512]; // this is only used to report an error
    380346 
     
    397363  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
    398364
    399   M1  = V1[0].ptr;
    400   M2  = V2[0].ptr;
    401   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     365  float     *M1  = (float *) V1[0].buffer[0].matrix.buffer;
     366  float     *out = (float *)OUT[0].buffer[0].matrix.buffer;
     367
     368# define MV_FUNC(OP) {                                  \
     369    if (V2->vector->type == OPIHI_FLT) {                \
     370      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;   \
     371      for (i = 0; i < Ny; i++, M2++) {                  \
     372        for (j = 0; j < Nx; j++, out++, M1++) {         \
     373          *out = OP;                                    \
     374        }                                               \
     375      }                                                 \
     376      break;                                            \
     377    }                                                   \
     378    if (V2->vector->type != OPIHI_FLT) {                \
     379      opihi_int *M2  =  V2[0].vector[0].elements.Int;   \
     380      for (i = 0; i < Ny; i++, M2++) {                  \
     381        for (j = 0; j < Nx; j++, out++, M1++) {         \
     382          *out = OP;                                    \
     383        }                                               \
     384      }                                                 \
     385      break;                                            \
     386    }                                                   \
     387  }
    402388
    403389  switch (op[0]) {
    404   case '+':
    405     for (i = 0; i < Ny; i++, M2++) {
    406       for (j = 0; j < Nx; j++, out++, M1++)
    407         *out = *M1 + *M2;
    408     }
    409     break;
    410   case '-':
    411     for (i = 0; i < Ny; i++, M2++) {
    412       for (j = 0; j < Nx; j++, out++, M1++)
    413         *out = *M1 - *M2;
    414     }
    415     break;
    416   case '*':
    417     for (i = 0; i < Ny; i++, M2++) {
    418       for (j = 0; j < Nx; j++, out++, M1++)
    419         *out = *M1 * *M2;
    420     }
    421     break;
    422   case '/':
    423     for (i = 0; i < Ny; i++, M2++) {
    424       for (j = 0; j < Nx; j++, out++, M1++)
    425         *out = *M1 / *M2;
    426     }
    427     break;
    428   case '%':
    429     for (i = 0; i < Ny; i++, M2++) {
    430       for (j = 0; j < Nx; j++, out++, M1++)
    431         *out = (int) *M1 % (int) *M2;
    432     }
    433     break;
    434   case 0x5e:
    435     for (i = 0; i < Ny; i++, M2++) {
    436       for (j = 0; j < Nx; j++, out++, M1++)
    437         *out = pow (*M1, *M2);
    438     }
    439     break;
    440   case '@':
    441     for (i = 0; i < Ny; i++, M2++) {
    442       for (j = 0; j < Nx; j++, out++, M1++)
    443         *out = DEG_RAD*atan2 (*M1, *M2);
    444     }
    445     break;
    446   case 'D':
    447     for (i = 0; i < Ny; i++, M2++) {
    448       for (j = 0; j < Nx; j++, out++, M1++)
    449         *out = MIN (*M1, *M2);
    450     }
    451     break;
    452   case 'U':
    453     for (i = 0; i < Ny; i++, M2++) {
    454       for (j = 0; j < Nx; j++, out++, M1++)
    455         *out = MAX (*M1, *M2);
    456     }
    457     break;
    458   case '<':
    459     for (i = 0; i < Ny; i++, M2++) {
    460       for (j = 0; j < Nx; j++, out++, M1++)
    461         *out = (*M1 < *M2) ? 1 : 0;
    462     }
    463     break;
    464   case '>':
    465     for (i = 0; i < Ny; i++, M2++) {
    466       for (j = 0; j < Nx; j++, out++, M1++)
    467         *out = (*M1 > *M2) ? 1 : 0;
    468     }
    469     break;
    470   case '&':
    471     for (i = 0; i < Ny; i++, M2++) {
    472       for (j = 0; j < Nx; j++, out++, M1++)
    473         *out = ((int)*M1 & (int)*M2);
    474     }
    475     break;
    476   case '|':
    477     for (i = 0; i < Ny; i++, M2++) {
    478       for (j = 0; j < Nx; j++, out++, M1++)
    479         *out = ((int)*M1 | (int)*M2);
    480     }
    481     break;
    482   case 'E':
    483     for (i = 0; i < Ny; i++, M2++) {
    484       for (j = 0; j < Nx; j++, out++, M1++)
    485         *out = (*M1 == *M2) ? 1 : 0;
    486     }
    487     break;
    488   case 'N':
    489     for (i = 0; i < Ny; i++, M2++) {
    490       for (j = 0; j < Nx; j++, out++, M1++)
    491         *out = (*M1 != *M2) ? 1 : 0;
    492     }
    493     break;
    494   case 'L':
    495     for (i = 0; i < Ny; i++, M2++) {
    496       for (j = 0; j < Nx; j++, out++, M1++)
    497         *out = (*M1 <= *M2) ? 1 : 0;
    498     }
    499     break;
    500   case 'G':
    501     for (i = 0; i < Ny; i++, M2++) {
    502       for (j = 0; j < Nx; j++, out++, M1++)
    503         *out = (*M1 >= *M2) ? 1 : 0;
    504     }
    505     break;
    506   case 'A':
    507     for (i = 0; i < Ny; i++, M2++) {
    508       for (j = 0; j < Nx; j++, out++, M1++)
    509         *out = (*M1 && *M2) ? 1 : 0;
    510     }
    511     break;
    512   case 'O':
    513     for (i = 0; i < Ny; i++, M2++) {
    514       for (j = 0; j < Nx; j++, out++, M1++)
    515         *out = (*M1 || *M2) ? 1 : 0;
    516     }
    517     break;
    518   default:
    519     sprintf (line, "error: op %c not defined!", op[0]);
    520     push_error (line);
    521     return (FALSE);
    522   }
     390    case '+': MV_FUNC(*M1 + *M2);
     391    case '-': MV_FUNC(*M1 - *M2);
     392    case '*': MV_FUNC(*M1 * *M2);
     393    case '/': MV_FUNC(*M1 / (opihi_flt) *M2);
     394    case '%': MV_FUNC((int) *M1 % (int) *M2);
     395    case '^': MV_FUNC(pow (*M1, *M2));
     396    case '@': MV_FUNC(DEG_RAD*atan2 (*M1, *M2));
     397    case 'D': MV_FUNC(MIN (*M1, *M2));
     398    case 'U': MV_FUNC(MAX (*M1, *M2));
     399    case '<': MV_FUNC((*M1 < *M2) ? 1 : 0);
     400    case '>': MV_FUNC((*M1 > *M2) ? 1 : 0);
     401    case '&': MV_FUNC(((int)*M1 & (int)*M2));
     402    case '|': MV_FUNC(((int)*M1 | (int)*M2));
     403    case 'E': MV_FUNC((*M1 == *M2) ? 1 : 0);
     404    case 'N': MV_FUNC((*M1 != *M2) ? 1 : 0);
     405    case 'L': MV_FUNC((*M1 <= *M2) ? 1 : 0);
     406    case 'G': MV_FUNC((*M1 >= *M2) ? 1 : 0);
     407    case 'A': MV_FUNC((*M1 && *M2) ? 1 : 0);
     408    case 'O': MV_FUNC((*M1 || *M2) ? 1 : 0);
     409    default:
     410      sprintf (line, "error: op %c not defined!", op[0]);
     411      push_error (line);
     412      return (FALSE);
     413  }
     414# undef MV_FUNC
    523415
    524416  /** free up any temporary buffers: **/
     
    530422  }
    531423  if (V2[0].type == 'v') {
    532     free (V2[0].vector[0].elements);
     424    free (V2[0].vector[0].elements.Ptr);
    533425    free (V2[0].vector);
    534426  }
     
    539431  /* at the end, V1 and V2 are deleted only if they were temporary */
    540432  return (TRUE);
    541 
    542 }
    543 
    544 
     433}
     434
     435// the vector is applied to each row
    545436int VM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    546437
    547438  int i, j, Nx, Ny;
    548   float *out, *M1, *M2;
    549439  char line[512]; // this is only used to report an error
    550440 
     
    565455  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
    566456
    567   M1  = V1[0].ptr;
    568   M2  = V2[0].ptr;
    569   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     457  float     *M2  = (float *) V2[0].buffer[0].matrix.buffer;
     458  float     *out = (float *)OUT[0].buffer[0].matrix.buffer;
     459
     460# define VM_FUNC(OP) {                                  \
     461    if (V1->vector->type == OPIHI_FLT) {                \
     462      for (i = 0; i < Ny; i++) {                        \
     463        opihi_flt *M1  = V1[0].vector[0].elements.Flt;  \
     464        for (j = 0; j < Nx; j++, out++, M1++, M2++) {   \
     465          *out = OP;                                    \
     466        }                                               \
     467      }                                                 \
     468      break;                                            \
     469    }                                                   \
     470    if (V1->vector->type != OPIHI_FLT) {                \
     471      for (i = 0; i < Ny; i++) {                        \
     472        opihi_int *M1  =  V1[0].vector[0].elements.Int; \
     473        for (j = 0; j < Nx; j++, out++, M1++, M2++) {   \
     474          *out = OP;                                    \
     475        }                                               \
     476      }                                                 \
     477      break;                                            \
     478    }                                                   \
     479  }
    570480
    571481  switch (op[0]) {
    572   case '+':
    573     for (i = 0; i < Ny; i++) {
    574       M1 = V1[0].ptr;
    575       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    576         *out = *M1 + *M2;
    577     }
    578     break;
    579   case '-':
    580     for (i = 0; i < Ny; i++) {
    581       M1 = V1[0].ptr;
    582       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    583         *out = *M1 - *M2;
    584     }
    585     break;
    586   case '*':
    587     for (i = 0; i < Ny; i++) {
    588       M1 = V1[0].ptr;
    589       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    590         *out = *M1 * *M2;
    591     }
    592     break;
    593   case '/':
    594     for (i = 0; i < Ny; i++) {
    595       M1 = V1[0].ptr;
    596       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    597         *out = *M1 / *M2;
    598     }
    599     break;
    600   case '%':
    601     for (i = 0; i < Ny; i++) {
    602       M1 = V1[0].ptr;
    603       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    604         *out = (int) *M1 % (int) *M2;
    605     }
    606     break;
    607   case 0x5e:
    608     for (i = 0; i < Ny; i++) {
    609       M1 = V1[0].ptr;
    610       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    611         *out = pow (*M1, *M2);
    612     }
    613     break;
    614   case '@':
    615     for (i = 0; i < Ny; i++) {
    616       M1 = V1[0].ptr;
    617       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    618         *out = DEG_RAD*atan2 (*M1, *M2);
    619     }
    620     break;
    621   case 'D':
    622     for (i = 0; i < Ny; i++) {
    623       M1 = V1[0].ptr;
    624       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    625         *out = MIN (*M1, *M2);
    626     }
    627     break;
    628   case 'U':
    629     for (i = 0; i < Ny; i++) {
    630       M1 = V1[0].ptr;
    631       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    632         *out = MAX (*M1, *M2);
    633     }
    634     break;
    635   case '<':
    636     for (i = 0; i < Ny; i++) {
    637       M1 = V1[0].ptr;
    638       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    639         *out = (*M1 < *M2) ? 1 : 0;
    640     }
    641     break;
    642   case '>':
    643     for (i = 0; i < Ny; i++) {
    644       M1 = V1[0].ptr;
    645       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    646         *out = (*M1 > *M2) ? 1 : 0;
    647     }
    648     break;
    649   case '&':
    650     for (i = 0; i < Ny; i++) {
    651       M1 = V1[0].ptr;
    652       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    653         *out = ((int)*M1 & (int)*M2);
    654     }
    655     break;
    656   case '|':
    657     for (i = 0; i < Ny; i++) {
    658       M1 = V1[0].ptr;
    659       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    660         *out = ((int)*M1 | (int)*M2);
    661     }
    662     break;
    663   case 'E':
    664     for (i = 0; i < Ny; i++) {
    665       M1 = V1[0].ptr;
    666       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    667         *out = (*M1 == *M2) ? 1 : 0;
    668     }
    669     break;
    670   case 'N':
    671     for (i = 0; i < Ny; i++) {
    672       M1 = V1[0].ptr;
    673       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    674         *out = (*M1 != *M2) ? 1 : 0;
    675     }
    676     break;
    677   case 'L':
    678     for (i = 0; i < Ny; i++) {
    679       M1 = V1[0].ptr;
    680       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    681         *out = (*M1 <= *M2) ? 1 : 0;
    682     }
    683     break;
    684   case 'G':
    685     for (i = 0; i < Ny; i++) {
    686       M1 = V1[0].ptr;
    687       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    688         *out = (*M1 >= *M2) ? 1 : 0;
    689     }
    690     break;
    691   case 'A':
    692     for (i = 0; i < Ny; i++) {
    693       M1 = V1[0].ptr;
    694       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    695         *out = (*M1 && *M2) ? 1 : 0;
    696     }
    697     break;
    698   case 'O':
    699     for (i = 0; i < Ny; i++) {
    700       M1 = V1[0].ptr;
    701       for (j = 0; j < Nx; j++, out++, M1++, M2++)
    702         *out = (*M1 || *M2) ? 1 : 0;
    703     }
    704     break;
    705   default:
    706     sprintf (line, "error: op %c not defined!", op[0]);
    707     push_error (line);
    708     return (FALSE);
    709   }
     482    case '+': VM_FUNC(*M1 + *M2);
     483    case '-': VM_FUNC(*M1 - *M2);
     484    case '*': VM_FUNC(*M1 * *M2);
     485    case '/': VM_FUNC(*M1 / (opihi_flt) *M2);
     486    case '%': VM_FUNC((int) *M1 % (int) *M2);
     487    case '^': VM_FUNC(pow (*M1, *M2));
     488    case '@': VM_FUNC(DEG_RAD*atan2 (*M1, *M2));
     489    case 'D': VM_FUNC(MIN (*M1, *M2));
     490    case 'U': VM_FUNC(MAX (*M1, *M2));
     491    case '<': VM_FUNC((*M1 < *M2) ? 1 : 0);
     492    case '>': VM_FUNC((*M1 > *M2) ? 1 : 0);
     493    case '&': VM_FUNC(((int)*M1 & (int)*M2));
     494    case '|': VM_FUNC(((int)*M1 | (int)*M2));
     495    case 'E': VM_FUNC((*M1 == *M2) ? 1 : 0);
     496    case 'N': VM_FUNC((*M1 != *M2) ? 1 : 0);
     497    case 'L': VM_FUNC((*M1 <= *M2) ? 1 : 0);
     498    case 'G': VM_FUNC((*M1 >= *M2) ? 1 : 0);
     499    case 'A': VM_FUNC((*M1 && *M2) ? 1 : 0);
     500    case 'O': VM_FUNC((*M1 || *M2) ? 1 : 0);
     501    default:
     502      sprintf (line, "error: op %c not defined!", op[0]);
     503      push_error (line);
     504      return (FALSE);
     505  }
     506# undef VM_FUNC
    710507
    711508  /** free up any temporary buffers: **/
    712509
    713510  if (V1[0].type == 'v') {
    714     free (V1[0].vector[0].elements);
     511    free (V1[0].vector[0].elements.Ptr);
    715512    free (V1[0].vector);
    716513  }
     
    752549  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
    753550
    754   M1  = V1[0].ptr;
    755   M2  = V2[0].ptr;
    756   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     551  M1  = (float *)V1[0].buffer[0].matrix.buffer;
     552  M2  = (float *)V2[0].buffer[0].matrix.buffer;
     553  out = (float *)OUT[0].buffer[0].matrix.buffer;
     554
     555# define MM_FUNC(OP)                                    \
     556  for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) {      \
     557    *out = OP;                                          \
     558  }                                                     \
     559  break;
    757560
    758561  switch (op[0]) {
    759   case '+':
    760     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    761       *out = *M1 + *M2;
    762     break;
    763   case '-':
    764     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    765       *out = *M1 - *M2;
    766     break;
    767   case '*':
    768     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    769       *out = *M1 * *M2;
    770     break;
    771   case '/':
    772     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    773       *out = *M1 / *M2;
    774     break;
    775   case '%':
    776     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    777       *out = (int) *M1 % (int) *M2;
    778     break;
    779   case 0x5e:
    780     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    781       *out = pow (*M1, *M2);
    782     break;
    783   case '@':
    784     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    785       *out = DEG_RAD*atan2 (*M1, *M2);
    786     break;
    787   case 'D':
    788     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    789       *out = MIN (*M1, *M2);
    790     break;
    791   case 'U':
    792     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    793       *out = MAX (*M1, *M2);
    794     break;
    795   case '<':
    796     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    797       *out = (*M1 < *M2) ? 1 : 0;
    798     break;
    799   case '>':
    800     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    801       *out = (*M1 > *M2) ? 1 : 0;
    802     break;
    803   case '&':
    804     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    805       *out = ((int)*M1 & (int)*M2);
    806     break;
    807   case '|':
    808     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    809       *out = ((int)*M1 | (int)*M2);
    810     break;
    811   case 'E':
    812     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    813       *out = (*M1 == *M2) ? 1 : 0;
    814     break;
    815   case 'N':
    816     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    817       *out = (*M1 != *M2) ? 1 : 0;
    818     break;
    819   case 'L':
    820     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    821       *out = (*M1 <= *M2) ? 1 : 0;
    822     break;
    823   case 'G':
    824     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    825       *out = (*M1 >= *M2) ? 1 : 0;
    826     break;
    827   case 'A':
    828     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    829       *out = (*M1 && *M2) ? 1 : 0;
    830     break;
    831   case 'O':
    832     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
    833       *out = (*M1 || *M2) ? 1 : 0;
    834     break;
    835   default:
    836     sprintf (line, "error: op %c not defined!", op[0]);
    837     push_error (line);
    838     return (FALSE);
    839   }
     562    case '+': MM_FUNC(*M1 + *M2);
     563    case '-': MM_FUNC(*M1 - *M2);
     564    case '*': MM_FUNC(*M1 * *M2);
     565    case '/': MM_FUNC(*M1 / (float) *M2);
     566    case '%': MM_FUNC((int) *M1 % (int) *M2);
     567    case '^': MM_FUNC(pow (*M1, *M2));
     568    case '@': MM_FUNC(DEG_RAD*atan2 (*M1, *M2));
     569    case 'D': MM_FUNC(MIN (*M1, *M2));
     570    case 'U': MM_FUNC(MAX (*M1, *M2));
     571    case '<': MM_FUNC((*M1 < *M2) ? 1 : 0);
     572    case '>': MM_FUNC((*M1 > *M2) ? 1 : 0);
     573    case '&': MM_FUNC(((int)*M1 & (int)*M2));
     574    case '|': MM_FUNC(((int)*M1 | (int)*M2));
     575    case 'E': MM_FUNC((*M1 == *M2) ? 1 : 0);
     576    case 'N': MM_FUNC((*M1 != *M2) ? 1 : 0);
     577    case 'L': MM_FUNC((*M1 <= *M2) ? 1 : 0);
     578    case 'G': MM_FUNC((*M1 >= *M2) ? 1 : 0);
     579    case 'A': MM_FUNC((*M1 && *M2) ? 1 : 0);
     580    case 'O': MM_FUNC((*M1 || *M2) ? 1 : 0);
     581    default:
     582      sprintf (line, "error: op %c not defined!", op[0]);
     583      push_error (line);
     584      return (FALSE);
     585  }
     586# undef MM_FUNC
    840587
    841588  /** free up any temporary buffers: **/
     
    857604  /* at the end, V1 and V2 are deleted only if they were temporary */
    858605  return (TRUE);
    859 
    860 }
    861 
     606}
    862607
    863608int MS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    864609
    865610  int i, Nx, Ny;
    866   float *out, *M1, *M2;
    867611  char line[512]; // this is only used to report an error
    868612 
     
    880624  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
    881625
    882   M1  = V1[0].ptr;
    883   M2  = V2[0].ptr;
    884   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     626  float *M1    = (float *)V1[0].buffer[0].matrix.buffer;
     627  float *out   = (float *)OUT[0].buffer[0].matrix.buffer;
     628
     629# define MS_FUNC(OP) {                                  \
     630    if (V2->type == 's')  {                             \
     631      opihi_flt M2 = V2[0].FltValue;                    \
     632      for (i = 0; i < Nx*Ny; i++, out++, M1++) {        \
     633        *out = OP;                                      \
     634      }                                                 \
     635      break;                                            \
     636    }                                                   \
     637    if (V2->type == 'S')  {                             \
     638      opihi_int M2 = V2[0].IntValue;                    \
     639      for (i = 0; i < Nx*Ny; i++, out++, M1++) {        \
     640        *out = OP;                                      \
     641      }                                                 \
     642      break;                                            \
     643    }                                                   \
     644  }
    885645
    886646  switch (op[0]) {
    887   case '+':
    888     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    889       *out = *M1 + *M2;
    890     break;
    891   case '-':
    892     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    893       *out = *M1 - *M2;
    894     break;
    895   case '*':
    896     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    897       *out = *M1 * *M2;
    898     break;
    899   case '/':
    900     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    901       *out = *M1 / *M2;
    902     break;
    903   case '%':
    904     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    905       *out = (int) *M1 % (int) *M2;
    906     break;
    907   case 0x5e:
    908     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    909       *out = pow (*M1, *M2);
    910     break;
    911   case '@':
    912     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    913       *out = DEG_RAD*atan2 (*M1, *M2);
    914     break;
    915   case 'D':
    916     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    917       *out = MIN (*M1, *M2);
    918     break;
    919   case 'U':
    920     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    921       *out = MAX (*M1, *M2);
    922     break;
    923   case '<':
    924     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    925       *out = (*M1 < *M2) ? 1 : 0;
    926     break;
    927   case '>':
    928     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    929       *out = (*M1 > *M2) ? 1 : 0;
    930     break;
    931   case '&':
    932     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    933       *out = ((int)*M1 & (int)*M2);
    934     break;
    935   case '|':
    936     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    937       *out = ((int)*M1 | (int)*M2);
    938     break;
    939   case 'E':
    940     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    941       *out = (*M1 == *M2) ? 1 : 0;
    942     break;
    943   case 'N':
    944     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    945       *out = (*M1 != *M2) ? 1 : 0;
    946     break;
    947   case 'L':
    948     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    949       *out = (*M1 <= *M2) ? 1 : 0;
    950     break;
    951   case 'G':
    952     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    953       *out = (*M1 >= *M2) ? 1 : 0;
    954     break;
    955   case 'A':
    956     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    957       *out = (*M1 && *M2) ? 1 : 0;
    958     break;
    959   case 'O':
    960     for (i = 0; i < Nx*Ny; i++, out++, M1++)
    961       *out = (*M1 || *M2) ? 1 : 0;
    962     break;
    963   default:
    964     sprintf (line, "error: op %c not defined!", op[0]);
    965     push_error (line);
    966     return (FALSE);
    967   }
     647    case '+': MS_FUNC(*M1 + M2);
     648    case '-': MS_FUNC(*M1 - M2);
     649    case '*': MS_FUNC(*M1 * M2);
     650    case '/': MS_FUNC(*M1 / (float) M2);
     651    case '%': MS_FUNC((int) *M1 % (int) M2);
     652    case '^': MS_FUNC(pow (*M1, M2));
     653    case '@': MS_FUNC(DEG_RAD*atan2 (*M1, M2));
     654    case 'D': MS_FUNC(MIN (*M1, M2));
     655    case 'U': MS_FUNC(MAX (*M1, M2));
     656    case '<': MS_FUNC((*M1 < M2) ? 1 : 0);
     657    case '>': MS_FUNC((*M1 > M2) ? 1 : 0);
     658    case '&': MS_FUNC(((int)*M1 & (int)M2));
     659    case '|': MS_FUNC(((int)*M1 | (int)M2));
     660    case 'E': MS_FUNC((*M1 == M2) ? 1 : 0);
     661    case 'N': MS_FUNC((*M1 != M2) ? 1 : 0);
     662    case 'L': MS_FUNC((*M1 <= M2) ? 1 : 0);
     663    case 'G': MS_FUNC((*M1 >= M2) ? 1 : 0);
     664    case 'A': MS_FUNC((*M1 && M2) ? 1 : 0);
     665    case 'O': MS_FUNC((*M1 || M2) ? 1 : 0);
     666    default:
     667      sprintf (line, "error: op %c not defined!", op[0]);
     668      push_error (line);
     669      return (FALSE);
     670  }
     671# undef MS_FUNC
    968672
    969673  if (V1[0].type == 'm') {
     
    976680
    977681  return (TRUE);
    978 
    979682}
    980683
     
    983686
    984687  int i, Nx, Ny;
    985   float *out, *M1, *M2;
    986688  char line[512]; // this is only used to report an error
    987689 
     
    998700  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
    999701
    1000   M1  = V1[0].ptr;
    1001   M2  = V2[0].ptr;
    1002   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     702  float *M2    = (float *)V2[0].buffer[0].matrix.buffer;
     703  float *out   = (float *)OUT[0].buffer[0].matrix.buffer;
     704
     705# define SM_FUNC(OP) {                                  \
     706    if (V1->type == 's')  {                             \
     707      opihi_flt M1 = V1[0].FltValue;                    \
     708      for (i = 0; i < Nx*Ny; i++, out++, M2++) {        \
     709        *out = OP;                                      \
     710      }                                                 \
     711      break;                                            \
     712    }                                                   \
     713    if (V1->type == 'S')  {                             \
     714      opihi_int M1 = V1[0].IntValue;                    \
     715      for (i = 0; i < Nx*Ny; i++, out++, M2++) {        \
     716        *out = OP;                                      \
     717      }                                                 \
     718      break;                                            \
     719    }                                                   \
     720  }
    1003721
    1004722  switch (op[0]) {
    1005   case '+':
    1006     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1007       *out = *M1 + *M2;
    1008     break;
    1009   case '-':
    1010     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1011       *out = *M1 - *M2;
    1012     break;
    1013   case '*':
    1014     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1015       *out = *M1 * *M2;
    1016     break;
    1017   case '/':
    1018     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1019       *out = *M1 / *M2;
    1020     break;
    1021   case '%':
    1022     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1023       *out = (int) *M1 % (int) *M2;
    1024     break;
    1025   case 0x5e:
    1026     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1027       *out = pow (*M1, *M2);
    1028     break;
    1029   case '@':
    1030     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1031       *out = DEG_RAD*atan2 (*M1, *M2);
    1032     break;
    1033   case 'D':
    1034     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1035       *out = MIN (*M1, *M2);
    1036     break;
    1037   case 'U':
    1038     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1039       *out = MAX (*M1, *M2);
    1040     break;
    1041   case '<':
    1042     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1043       *out = (*M1 < *M2) ? 1 : 0;
    1044     break;
    1045   case '>':
    1046     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1047       *out = (*M1 > *M2) ? 1 : 0;
    1048     break;
    1049   case '&':
    1050     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1051       *out = ((int)*M1 & (int)*M2);
    1052     break;
    1053   case '|':
    1054     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1055       *out = ((int)*M1 | (int)*M2);
    1056     break;
    1057   case 'E':
    1058     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1059       *out = (*M1 == *M2) ? 1 : 0;
    1060     break;
    1061   case 'N':
    1062     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1063       *out = (*M1 != *M2) ? 1 : 0;
    1064     break;
    1065   case 'L':
    1066     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1067       *out = (*M1 <= *M2) ? 1 : 0;
    1068     break;
    1069   case 'G':
    1070     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1071       *out = (*M1 >= *M2) ? 1 : 0;
    1072     break;
    1073   case 'A':
    1074     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1075       *out = (*M1 && *M2) ? 1 : 0;
    1076     break;
    1077   case 'O':
    1078     for (i = 0; i < Nx*Ny; i++, out++, M2++)
    1079       *out = (*M1 || *M2) ? 1 : 0;
    1080     break;
    1081   default:
    1082     sprintf (line, "error: op %c not defined!", op[0]);
    1083     push_error (line);
    1084     return (FALSE);
    1085   }
     723    case '+': SM_FUNC(M1 + *M2);
     724    case '-': SM_FUNC(M1 - *M2);
     725    case '*': SM_FUNC(M1 * *M2);
     726    case '/': SM_FUNC(M1 / (float) *M2);
     727    case '%': SM_FUNC((int) M1 % (int) *M2);
     728    case '^': SM_FUNC(pow (M1, *M2));
     729    case '@': SM_FUNC(DEG_RAD*atan2 (M1, *M2));
     730    case 'D': SM_FUNC(MIN (M1, *M2));
     731    case 'U': SM_FUNC(MAX (M1, *M2));
     732    case '<': SM_FUNC((M1 < *M2) ? 1 : 0);
     733    case '>': SM_FUNC((M1 > *M2) ? 1 : 0);
     734    case '&': SM_FUNC(((int)M1 & (int)*M2));
     735    case '|': SM_FUNC(((int)M1 | (int)*M2));
     736    case 'E': SM_FUNC((M1 == *M2) ? 1 : 0);
     737    case 'N': SM_FUNC((M1 != *M2) ? 1 : 0);
     738    case 'L': SM_FUNC((M1 <= *M2) ? 1 : 0);
     739    case 'G': SM_FUNC((M1 >= *M2) ? 1 : 0);
     740    case 'A': SM_FUNC((M1 && *M2) ? 1 : 0);
     741    case 'O': SM_FUNC((M1 || *M2) ? 1 : 0);
     742    default:
     743      sprintf (line, "error: op %c not defined!", op[0]);
     744      push_error (line);
     745      return (FALSE);
     746  }
     747# undef SM_FUNC
    1086748
    1087749  if (V2[0].type == 'm') {
     
    1097759}
    1098760
    1099 
    1100761int SS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
    1101762
    1102   float *M1, *M2, *out;
    1103763  char line[512]; // this is only used to report an error
    1104764
    1105   M1  = V1[0].ptr;
    1106   M2  = V2[0].ptr;
    1107   OUT[0].ptr = V1[0].ptr;
    1108   out = OUT[0].ptr;
    1109 
     765# define SS_FUNC(FTYPE,OP) {                                            \
     766    if ((V1->type == 'S') && (V2->type == 'S')) {                       \
     767      opihi_flt M1 = V1[0].FltValue;                                    \
     768      opihi_flt M2 = V2[0].FltValue;                                    \
     769      OUT[0].type = 'S';                                                \
     770      OUT[0].FltValue = OP;                                             \
     771      break;                                                            \
     772    }                                                                   \
     773    if ((V1->type == 'S') && (V2->type == 's')) {                       \
     774      opihi_flt M1 = V1[0].FltValue;                                    \
     775      opihi_int M2 = V2[0].IntValue;                                    \
     776      OUT[0].type = 'S';                                                \
     777      OUT[0].FltValue = OP;                                             \
     778      break;                                                            \
     779    }                                                                   \
     780    if ((V1->type == 's') && (V2->type == 'S')) {                       \
     781      opihi_int M1 = V1[0].IntValue;                                    \
     782      opihi_flt M2 = V2[0].FltValue;                                    \
     783      OUT[0].type = 'S';                                                \
     784      OUT[0].FltValue = OP;                                             \
     785      break;                                                            \
     786    }                                                                   \
     787    if ((FTYPE == 'S') && (V1->type == 's') && (V2->type == 's')) {     \
     788      opihi_int M1 = V1[0].IntValue;                                    \
     789      opihi_int M2 = V2[0].IntValue;                                    \
     790      OUT[0].type = 'S';                                                \
     791      OUT[0].FltValue = OP;                                             \
     792      break;                                                            \
     793    }                                                                   \
     794    if ((V1->type == 's') && (V2->type == 's')) {                       \
     795      opihi_int M1 = V1[0].IntValue;                                    \
     796      opihi_int M2 = V2[0].IntValue;                                    \
     797      OUT[0].type = 's';                                                \
     798      OUT[0].IntValue = OP;                                             \
     799      break;                                                            \
     800    }                                                                   \
     801  }
    1110802
    1111803  switch (op[0]) {
    1112   case '+':
    1113     *out = *M1 + *M2;
    1114     break;   
    1115   case '-':
    1116     *out = *M1 - *M2;
    1117     break;   
    1118   case '*':
    1119     *out = *M1 * *M2;
    1120     break;   
    1121   case '/':
    1122     *out = *M1 / *M2;
    1123     break;
    1124   case '%':
    1125     *out = (int) *M1 % (int) *M2;
    1126     break;
    1127   case 0x5e:
    1128     *out = pow (*M1, *M2);
    1129     break;
    1130   case '@':
    1131     *out = DEG_RAD*atan2 (*M1, *M2);
    1132     break;
    1133   case 'D':
    1134     *out = MIN (*M1, *M2);
    1135     break;
    1136   case 'U':
    1137     *out = MAX (*M1, *M2);
    1138     break;
    1139   case '<':
    1140     *out = (*M1 < *M2) ? 1 : 0;
    1141     break;
    1142   case '>':
    1143     *out = (*M1 > *M2) ? 1 : 0;
    1144     break;
    1145   case '&':
    1146     *out = ((int)*M1 & (int)*M2);
    1147     break;
    1148   case '|':
    1149     *out = ((int)*M1 | (int)*M2);
    1150     break;
    1151   case 'E':
    1152     *out = (*M1 == *M2) ? 1 : 0;
    1153     break;
    1154   case 'N':
    1155     *out = (*M1 != *M2) ? 1 : 0;
    1156     break;
    1157   case 'L':
    1158     *out = (*M1 <= *M2) ? 1 : 0;
    1159     break;
    1160   case 'G':
    1161     *out = (*M1 >= *M2) ? 1 : 0;
    1162     break;
    1163   case 'A':
    1164     *out = (*M1 && *M2) ? 1 : 0;
    1165     break;
    1166   case 'O':
    1167     *out = (*M1 || *M2) ? 1 : 0;
    1168     break;
    1169   default:
    1170     sprintf (line, "error: op %c not defined!", op[0]);
    1171     push_error (line);
    1172     return (FALSE);
    1173   }
    1174   OUT[0].Float = *(OUT[0].ptr);
    1175   OUT[0].type = 'S';
     804    case '+': SS_FUNC('s', M1 + M2);
     805    case '-': SS_FUNC('s', M1 - M2);
     806    case '*': SS_FUNC('s', M1 * M2);
     807    case '/': SS_FUNC('S', M1 / (opihi_flt) M2);
     808    case '%': SS_FUNC('s', (int) M1 % (int) M2);
     809    case '^': SS_FUNC('S', pow (M1, M2));
     810    case '@': SS_FUNC('S', DEG_RAD*atan2 (M1, M2));
     811    case 'D': SS_FUNC('s', MIN (M1, M2));
     812    case 'U': SS_FUNC('s', MAX (M1, M2));
     813    case '<': SS_FUNC('s', (M1 < M2) ? 1 : 0);
     814    case '>': SS_FUNC('s', (M1 > M2) ? 1 : 0);
     815    case '&': SS_FUNC('s', ((int)M1 & (int)M2));
     816    case '|': SS_FUNC('s', ((int)M1 | (int)M2));
     817    case 'E': SS_FUNC('s', (M1 == M2) ? 1 : 0);
     818    case 'N': SS_FUNC('s', (M1 != M2) ? 1 : 0);
     819    case 'L': SS_FUNC('s', (M1 <= M2) ? 1 : 0);
     820    case 'G': SS_FUNC('s', (M1 >= M2) ? 1 : 0);
     821    case 'A': SS_FUNC('s', (M1 && M2) ? 1 : 0);
     822    case 'O': SS_FUNC('s', (M1 || M2) ? 1 : 0);
     823    default:
     824      sprintf (line, "error: op %c not defined!", op[0]);
     825      push_error (line);
     826      return (FALSE);
     827  }
     828# undef SS_FUNC
    1176829
    1177830  clear_stack (V1);
     
    1188841
    1189842  /* only 'N' and 'E' are allowed for WW_binary operations. anything else is either a
    1190    syntax error or is a string which looks like a math expression. */
     843     syntax error or is a string which looks like a math expression. */
    1191844
    1192845  if ((op[0] != 'N') && (op[0] != 'E')) {
     
    1210863
    1211864  switch (op[0]) {
    1212   case 'E':
    1213     value = strcmp (V1[0].name, V2[0].name) ? 0 : 1;
     865    case 'E':
     866      value = strcmp (V1[0].name, V2[0].name) ? 0 : 1;
    1214867    break;
    1215   case 'N':
    1216     value = strcmp (V1[0].name, V2[0].name) ? 1 : 0;
     868    case 'N':
     869      value = strcmp (V1[0].name, V2[0].name) ? 1 : 0;
    1217870    break;
    1218   default:
    1219     sprintf (line, "error: op %c not defined for string operations!", op[0]);
    1220     push_error (line);
    1221     return (FALSE);
     871    default:
     872      sprintf (line, "error: op %c not defined for string operations!", op[0]);
     873      push_error (line);
     874      return (FALSE);
    1222875  }
    1223876
    1224877escape:
    1225   OUT[0].Float = value;
     878  OUT[0].FltValue = value;
    1226879  OUT[0].type = 'S';
    1227   OUT[0].ptr = &OUT[0].Float;
    1228880
    1229881  clear_stack (V1);
     
    1236888int S_unary (StackVar *OUT, StackVar *V1, char *op) {
    1237889
    1238   float *out, *M1;
     890  char line[512]; // this is only used to report an error
    1239891 
    1240   out = OUT[0].ptr = V1[0].ptr;
    1241   M1  = V1[0].ptr;
    1242 
    1243   if (!strcmp (op, "="))     {    }
    1244   if (!strcmp (op, "abs"))   {    *out = fabs(*M1);           }
    1245   if (!strcmp (op, "int"))   {    *out = (float)(int)(*M1);   }
    1246   if (!strcmp (op, "exp"))   {    *out = exp (*M1);           }
    1247   if (!strcmp (op, "ten"))   {    *out = pow (10.0,*M1);      }
    1248   if (!strcmp (op, "log"))   {    *out = log10 (*M1);         }
    1249   if (!strcmp (op, "ln"))    {    *out = log (*M1);           }
    1250   if (!strcmp (op, "sqrt"))  {    *out = sqrt (*M1);          }
    1251   if (!strcmp (op, "erf"))   {    *out = erf (*M1);           }
    1252 
    1253   if (!strcmp (op, "sinh"))  {    *out = sinh (*M1);          }
    1254   if (!strcmp (op, "cosh"))  {    *out = cosh (*M1);          }
    1255   if (!strcmp (op, "asinh")) {    *out = asinh (*M1);         }
    1256   if (!strcmp (op, "acosh")) {    *out = acosh (*M1);         }
    1257   if (!strcmp (op, "lgamma")) {   *out = lgamma (*M1);        }
    1258 
    1259   if (!strcmp (op, "sin"))   {    *out = sin (*M1);           }
    1260   if (!strcmp (op, "cos"))   {    *out = cos (*M1);           }
    1261   if (!strcmp (op, "tan"))   {    *out = tan (*M1);           }
    1262   if (!strcmp (op, "dsin"))  {    *out = sin (*M1*RAD_DEG);   }
    1263   if (!strcmp (op, "dcos"))  {    *out = cos (*M1*RAD_DEG);   }
    1264   if (!strcmp (op, "dtan"))  {    *out = tan (*M1*RAD_DEG);   }
    1265   if (!strcmp (op, "asin"))  {    *out = asin (*M1);          }
    1266   if (!strcmp (op, "acos"))  {    *out = acos (*M1);          }
    1267   if (!strcmp (op, "atan"))  {    *out = atan (*M1);          }
    1268   if (!strcmp (op, "dasin")) {    *out = asin (*M1)*DEG_RAD;  }
    1269   if (!strcmp (op, "dacos")) {    *out = acos (*M1)*DEG_RAD;  }
    1270   if (!strcmp (op, "datan")) {    *out = atan (*M1)*DEG_RAD;  }
    1271   if (!strcmp (op, "rnd"))   {    *out = drand48();           }
    1272   if (!strcmp (op, "not"))   {    *out = !(*M1);              }
    1273   if (!strcmp (op, "--"))    {    *out = - (*M1);             }
    1274   if (!strcmp (op, "isinf")) {    *out = !finite(*M1);        }
    1275   if (!strcmp (op, "isnan")) {    *out = isnan(*M1);          }
    1276 
    1277   OUT[0].Float = *out;
    1278   OUT[0].type = 'S';
    1279 
    1280   clear_stack (V1);
    1281   return (TRUE);
     892# define S_FUNC(OP,FTYPE) {                     \
     893    if (V1->type == 'S') {                      \
     894      opihi_flt M1  = V1[0].FltValue;           \
     895      OUT[0].type = 'S';                        \
     896      OUT[0].FltValue = OP;                     \
     897      clear_stack (V1);                         \
     898      return (TRUE);                            \
     899    }                                           \
     900    if ((FTYPE == 'S') && (V1->type == 's')) {  \
     901      opihi_int M1  = V1[0].IntValue;           \
     902      OUT[0].type = 'S';                        \
     903      OUT[0].FltValue = OP;                     \
     904      clear_stack (V1);                         \
     905      return (TRUE);                            \
     906    }                                           \
     907    if ((FTYPE == 's') && (V1->type == 's')) {  \
     908      opihi_int M1  = V1[0].IntValue;           \
     909      OUT[0].type = 's';                        \
     910      OUT[0].IntValue = OP;                     \
     911      clear_stack (V1);                         \
     912      return (TRUE);                            \
     913    }                                           \
     914  }
     915
     916  if (!strcmp (op, "="))      S_FUNC(M1, 's');
     917  if (!strcmp (op, "abs"))    S_FUNC(fabs(M1), 's');
     918  if (!strcmp (op, "int"))    S_FUNC((int)(M1), 's');
     919  if (!strcmp (op, "exp"))    S_FUNC(exp (M1), 'S');
     920  if (!strcmp (op, "ten"))    S_FUNC(pow (10.0,M1), 'S');
     921  if (!strcmp (op, "log"))    S_FUNC(log10 (M1), 'S');
     922  if (!strcmp (op, "ln"))     S_FUNC(log (M1), 'S');
     923  if (!strcmp (op, "sqrt"))   S_FUNC(sqrt (M1), 'S');
     924  if (!strcmp (op, "erf"))    S_FUNC(erf (M1), 'S');
     925  if (!strcmp (op, "sinh"))   S_FUNC(sinh (M1), 'S');
     926  if (!strcmp (op, "cosh"))   S_FUNC(cosh (M1), 'S');
     927  if (!strcmp (op, "asinh"))  S_FUNC(asinh (M1), 'S');
     928  if (!strcmp (op, "acosh"))  S_FUNC(acosh (M1), 'S');
     929  if (!strcmp (op, "lgamma")) S_FUNC(lgamma (M1), 'S');
     930  if (!strcmp (op, "sin"))    S_FUNC(sin (M1), 'S');
     931  if (!strcmp (op, "cos"))    S_FUNC(cos (M1), 'S');
     932  if (!strcmp (op, "tan"))    S_FUNC(tan (M1), 'S');
     933  if (!strcmp (op, "dsin"))   S_FUNC(sin (M1*RAD_DEG), 'S');
     934  if (!strcmp (op, "dcos"))   S_FUNC(cos (M1*RAD_DEG), 'S');
     935  if (!strcmp (op, "dtan"))   S_FUNC(tan (M1*RAD_DEG), 'S');
     936  if (!strcmp (op, "asin"))   S_FUNC(asin (M1), 'S');
     937  if (!strcmp (op, "acos"))   S_FUNC(acos (M1), 'S');
     938  if (!strcmp (op, "atan"))   S_FUNC(atan (M1), 'S');
     939  if (!strcmp (op, "dasin"))  S_FUNC(asin (M1)*DEG_RAD, 'S');
     940  if (!strcmp (op, "dacos"))  S_FUNC(acos (M1)*DEG_RAD, 'S');
     941  if (!strcmp (op, "datan"))  S_FUNC(atan (M1)*DEG_RAD, 'S');
     942  if (!strcmp (op, "rnd"))    S_FUNC(M1*0.0 + drand48(), 'S');
     943  if (!strcmp (op, "not"))    S_FUNC(!(M1), 's');
     944  if (!strcmp (op, "--"))     S_FUNC(-1*M1, 's'); // NOTE: opihi_int is signed,
     945  if (!strcmp (op, "isinf"))  S_FUNC(!finite(M1), 'S'); // XXX modify in future
     946  if (!strcmp (op, "isnan"))  S_FUNC(isnan(M1), 'S'); // XXX modify in future   
     947
     948# undef S_FUNC
     949
     950  clear_stack (V1);
     951  sprintf (line, "error: op %s not defined!", op);
     952  push_error (line);
     953  return (FALSE);
    1282954
    1283955}
     
    1286958
    1287959  int i, Nx;
    1288   float *out, *M1;
    1289960 
    1290961  Nx = V1[0].vector[0].Nelements;
    1291  
    1292   if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
    1293     OUT[0].vector = V1[0].vector;
    1294     V1[0].type = 'V'; /* prevent it from being freed below */
    1295   } else {  /* no spare temp buffer */
    1296     OUT[0].vector = InitVector ();
    1297     CopyVector (OUT[0].vector, V1[0].vector);
    1298   }
     962
     963  OUT[0].vector = InitVector ();
    1299964  OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
    1300   M1  = V1[0].ptr;
    1301   out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
    1302 
    1303   if (!strcmp (op, "="))     { } /* already set equal */
    1304   if (!strcmp (op, "abs"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = fabs(*M1);         }}
    1305   if (!strcmp (op, "int"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = (float)(int)(*M1); }}
    1306   if (!strcmp (op, "exp"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = exp(*M1);          }}
    1307   if (!strcmp (op, "ten"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
    1308   if (!strcmp (op, "log"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = log10(*M1);        }}
    1309   if (!strcmp (op, "ln"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = log(*M1);          }}
    1310   if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sqrt(*M1);         }}
    1311   if (!strcmp (op, "erf"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = erf(*M1);          }}
    1312 
    1313   if (!strcmp (op, "sinh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sinh(*M1);        }}
    1314   if (!strcmp (op, "cosh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = cosh(*M1);        }}
    1315   if (!strcmp (op, "asinh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asinh(*M1);       }}
    1316   if (!strcmp (op, "acosh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acosh(*M1);       }}
    1317   if (!strcmp (op, "lgamma")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = lgamma(*M1);      }}
    1318 
    1319   if (!strcmp (op, "sin"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1);          }}
    1320   if (!strcmp (op, "cos"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1);          }}
    1321   if (!strcmp (op, "tan"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1);          }}
    1322   if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
    1323   if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
    1324   if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
    1325   if (!strcmp (op, "asin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1);         }}
    1326   if (!strcmp (op, "acos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1);         }}
    1327   if (!strcmp (op, "atan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1);         }}
    1328   if (!strcmp (op, "dasin")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
    1329   if (!strcmp (op, "dacos")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
    1330   if (!strcmp (op, "datan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
    1331   if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = drand48();         }}
    1332   if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
    1333   if (!strcmp (op, "zero"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
    1334   if (!strcmp (op, "not"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = !(*M1);            }}
    1335   if (!strcmp (op, "--"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = -(*M1);            }}
    1336   if (!strcmp (op, "isinf")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = !finite(*M1);      }}
    1337   if (!strcmp (op, "isnan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = isnan(*M1);        }}
    1338 
    1339   /* xramp and yramp only make sense in for matrices. for vectors, xramp = ramp, yramp = zero */
    1340   if (!strcmp (op, "xramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
    1341   if (!strcmp (op, "yramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
     965
     966# define V_FUNC(OP,FTYPE) {                                     \
     967    if (V1->vector->type == OPIHI_FLT) {                        \
     968      CopyVector (OUT[0].vector, V1[0].vector);                 \
     969      opihi_flt *M1  = V1[0].vector[0].elements.Flt;            \
     970      opihi_flt *out = OUT[0].vector[0].elements.Flt;           \
     971      for (i = 0; i < Nx; i++, out++, M1++) {                   \
     972        *out = OP;                                              \
     973      }                                                         \
     974      clear_stack (V1);                                         \
     975      return (TRUE);                                            \
     976    }                                                           \
     977    if ((V1->vector->type == OPIHI_INT) && (FTYPE == 'S')) {    \
     978      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);     \
     979      opihi_int *M1  = V1[0].vector[0].elements.Int;            \
     980      opihi_flt *out = OUT[0].vector[0].elements.Flt;           \
     981      for (i = 0; i < Nx; i++, out++, M1++) {                   \
     982        *out = OP;                                              \
     983      }                                                         \
     984      clear_stack (V1);                                         \
     985      return (TRUE);                                            \
     986    }                                                           \
     987    if ((V1->vector->type == OPIHI_INT) && (FTYPE == 's')) {    \
     988      CopyVector (OUT[0].vector, V1[0].vector);                 \
     989      opihi_int *M1  = V1[0].vector[0].elements.Int;            \
     990      opihi_int *out = OUT[0].vector[0].elements.Int;           \
     991      for (i = 0; i < Nx; i++, out++, M1++) {                   \
     992        *out = OP;                                              \
     993      }                                                         \
     994      clear_stack (V1);                                         \
     995      return (TRUE);                                            \
     996    } }                                                 
     997
     998  if (!strcmp (op, "="))      V_FUNC(*M1, 's');
     999  if (!strcmp (op, "abs"))    V_FUNC(fabs(*M1), 's');
     1000  if (!strcmp (op, "int"))    V_FUNC((int)(*M1), 's');
     1001  if (!strcmp (op, "exp"))    V_FUNC(exp(*M1), 'S');
     1002  if (!strcmp (op, "ten"))    V_FUNC(pow(10.0,*M1), 'S');
     1003  if (!strcmp (op, "log"))    V_FUNC(log10(*M1), 'S');
     1004  if (!strcmp (op, "ln"))     V_FUNC(log(*M1), 'S');
     1005  if (!strcmp (op, "sqrt"))   V_FUNC(sqrt(*M1), 'S');
     1006  if (!strcmp (op, "erf"))    V_FUNC(erf(*M1), 'S');
     1007  if (!strcmp (op, "sinh"))   V_FUNC(sinh(*M1), 'S');
     1008  if (!strcmp (op, "cosh"))   V_FUNC(cosh(*M1), 'S');
     1009  if (!strcmp (op, "asinh"))  V_FUNC(asinh(*M1), 'S');
     1010  if (!strcmp (op, "acosh"))  V_FUNC(acosh(*M1), 'S');
     1011  if (!strcmp (op, "lgamma")) V_FUNC(lgamma(*M1), 'S');
     1012  if (!strcmp (op, "sin"))    V_FUNC(sin(*M1), 'S');
     1013  if (!strcmp (op, "cos"))    V_FUNC(cos(*M1), 'S');
     1014  if (!strcmp (op, "tan"))    V_FUNC(tan(*M1), 'S');
     1015  if (!strcmp (op, "dsin"))   V_FUNC(sin(*M1*RAD_DEG), 'S');
     1016  if (!strcmp (op, "dcos"))   V_FUNC(cos(*M1*RAD_DEG), 'S');
     1017  if (!strcmp (op, "dtan"))   V_FUNC(tan(*M1*RAD_DEG), 'S');
     1018  if (!strcmp (op, "asin"))   V_FUNC(asin(*M1), 'S');
     1019  if (!strcmp (op, "acos"))   V_FUNC(acos(*M1), 'S');
     1020  if (!strcmp (op, "atan"))   V_FUNC(atan(*M1), 'S');
     1021  if (!strcmp (op, "dasin"))  V_FUNC(asin(*M1)*DEG_RAD, 'S');
     1022  if (!strcmp (op, "dacos"))  V_FUNC(acos(*M1)*DEG_RAD, 'S');
     1023  if (!strcmp (op, "datan"))  V_FUNC(atan(*M1)*DEG_RAD, 'S');
     1024  if (!strcmp (op, "rnd"))    V_FUNC(drand48(), 'S');
     1025  if (!strcmp (op, "ramp"))   V_FUNC(i, 's');
     1026  if (!strcmp (op, "zero"))   V_FUNC(0, 's');
     1027  if (!strcmp (op, "not"))    V_FUNC(!(*M1), 's');
     1028  if (!strcmp (op, "--"))     V_FUNC(-1*(*M1), 's'); // NOTE: opihi_int is signed
     1029  if (!strcmp (op, "isinf"))  V_FUNC(!finite(*M1), 'S');
     1030  if (!strcmp (op, "isnan"))  V_FUNC(isnan(*M1), 'S');
     1031  if (!strcmp (op, "xramp"))  V_FUNC(i, 's');
     1032  if (!strcmp (op, "yramp"))  V_FUNC(0, 's');
     1033  /* xramp and yramp above only make sense for matrices. for vectors, xramp = ramp, yramp = zero */
     1034
     1035# undef V_FUNC
    13421036
    13431037  if (V1[0].type == 'v') {
    1344     free (V1[0].vector[0].elements);
     1038    free (V1[0].vector[0].elements.Ptr);
    13451039    free (V1[0].vector);
    13461040    V1[0].vector = NULL;
     
    13681062  }
    13691063  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
    1370   M1  = V1[0].ptr;
    1371   out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
     1064  M1  = (float *) V1[0].buffer[0].matrix.buffer;
     1065  out = (float *)OUT[0].buffer[0].matrix.buffer;
    13721066
    13731067  if (!strcmp (op, "="))     { }
    13741068  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = fabs(*M1);         }}
    1375   if (!strcmp (op, "int"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = (float)(int)(*M1); }}
     1069  if (!strcmp (op, "int"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = (opihi_flt)(int)(*M1); }}
    13761070  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = exp(*M1);          }}
    13771071  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
     
    14111105    for (j = 0; j < Ny; j++) {
    14121106      for (i = 0; i < Nx; i++, out++, M1++) {
    1413         *out = i;
     1107        *out = i;
    14141108      }
    14151109    }
     
    14181112    for (j = 0; j < Ny; j++) {
    14191113      for (i = 0; i < Nx; i++, out++, M1++) {
    1420         *out = j;
     1114        *out = j;
    14211115      }
    14221116    }
Note: See TracChangeset for help on using the changeset viewer.