/*
This file is part of the FElt finite element analysis package.
Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/************************************************************************
* File: relational.c *
* *
* Description: This file contains the function definitions for the *
* relational virtual machine instructions. *
************************************************************************/
# include <string.h>
# include "debug.h"
# include "coerce.h"
# include "execute.h"
# include "relational.h"
/************************************************************************
* Function: eq_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string == string -> double (string comparison) *
* double == double -> double (scalar comparison) *
* double == matrix -> matrix (matrix element-wise cmp) *
* matrix == double -> matrix (matrix element-wise cmp) *
* matrix == matrix -> matrix (matrix element-wise cmp) *
* object == object -> double (object pointer comparison) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int eq_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) == *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue == mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) == rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareEQMatrices (c, a, b)))
MatrixError ("==", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp == 0);
break;
default:
type_error = F_True;
break;
}
break;
case T_Function:
case T_Intrinsic:
case T_Array:
case T_Pair:
if (D_Type (left) == D_Type (right)) {
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (D_Pointer (left) == D_Pointer (right));
} else
type_error = F_False;
break;
case T_Constraint:
case T_Definition:
case T_Element:
case T_Force:
case T_Load:
case T_Material:
case T_Node:
case T_Stress:
case T_External:
if (D_Type (left) == D_Type (right)) {
cmp = *(void **) D_Pointer (left) == *(void **) D_Pointer (right);
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
} else if (D_Type (right) == T_Null) {
cmp = *(void **) D_Pointer (left) == NULL;
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
} else
type_error = F_True;
break;
case T_Null:
switch (D_Type (right)) {
case T_Constraint:
case T_Definition:
case T_Element:
case T_Force:
case T_Load:
case T_Material:
case T_Node:
case T_Stress:
case T_External:
cmp = *(void **) D_Pointer (right) == NULL;
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError ("==", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("eq ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
/************************************************************************
* Function: ge_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string >= string -> double (string comparison) *
* double >= double -> double (scalar comparison) *
* double >= matrix -> matrix (matrix element-wise cmp) *
* matrix >= double -> matrix (matrix element-wise cmp) *
* matrix >= matrix -> matrix (matrix element-wise cmp) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int ge_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) >= *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue >= mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) >= rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareGTEMatrices (c, a, b)))
MatrixError (">=", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp >= 0);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError (">=", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("ge ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
/************************************************************************
* Function: gt_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string > string -> double (string comparison) *
* double > double -> double (scalar comparison) *
* double > matrix -> matrix (matrix element-wise cmp) *
* matrix > double -> matrix (matrix element-wise cmp) *
* matrix > matrix -> matrix (matrix element-wise cmp) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int gt_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) > *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue > mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) > rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareGTMatrices (c, a, b)))
MatrixError (">", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp > 0);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError (">", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("gt ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
/************************************************************************
* Function: le_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string <= string -> double (string comparison) *
* double <= double -> double (scalar comparison) *
* double <= matrix -> matrix (matrix element-wise cmp) *
* matrix <= double -> matrix (matrix element-wise cmp) *
* matrix <= matrix -> matrix (matrix element-wise cmp) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int le_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) <= *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue <= mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) <= rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareLTEMatrices (c, a, b)))
MatrixError ("<=", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp <= 0);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError ("<=", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("le ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
/************************************************************************
* Function: lt_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string < string -> double (string comparison) *
* double < double -> double (scalar comparison) *
* double < matrix -> matrix (matrix element-wise cmp) *
* matrix < double -> matrix (matrix element-wise cmp) *
* matrix < matrix -> matrix (matrix element-wise cmp) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int lt_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) < *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue < mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) < rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareLTMatrices (c, a, b)))
MatrixError ("<", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp < 0);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError ("<", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("lt ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
/************************************************************************
* Function: ne_op *
* *
* Description: Pops and compares the two descriptors on the top of the *
* stack and places the result on the stack. The *
* following types are legal for comparison: *
* *
* string != string -> double (string comparison) *
* double != double -> double (scalar comparison) *
* double != matrix -> matrix (matrix element-wise cmp) *
* matrix != double -> matrix (matrix element-wise cmp) *
* matrix != matrix -> matrix (matrix element-wise cmp) *
* object != object -> double (object pointer comparison) *
* *
* An attempt is first made to coerce the operands to *
* double values unless both operands are strings. *
************************************************************************/
int ne_op ( )
{
Matrix a;
Matrix b;
Matrix c;
double lvalue;
double rvalue;
descriptor *left;
descriptor *right;
descriptor *result;
descriptor temp;
int type_error;
int status;
int cmp;
unsigned i;
unsigned j;
right = pop ( );
result = top ( );
temp = *result;
left = &temp;
left = deref (left);
right = deref (right);
if (D_Type (left) != T_String || D_Type (right) != T_String) {
left = CoerceData (left, T_Double);
right = CoerceData (right, T_Double);
}
status = 0;
type_error = F_False;
switch (D_Type (left)) {
case T_Double:
switch (D_Type (right)) {
case T_Double:
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (*D_Double (left) != *D_Double (right));
break;
case T_Matrix:
a = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
lvalue = *D_Double (left);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = lvalue != mdata (a, i, j);
break;
default:
type_error = F_True;
break;
}
break;
case T_Matrix:
switch (D_Type (right)) {
case T_Double:
a = D_Matrix (left);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
b = D_Matrix (result);
rvalue = *D_Double (right);
for (i = 1; i <= Mrows (a); i ++)
for (j = 1; j <= Mcols (a); j ++)
sdata (b, i, j) = mdata (a, i, j) != rvalue;
break;
case T_Matrix:
a = D_Matrix (left);
b = D_Matrix (right);
CreateData (result, left, right, T_Matrix, Mrows (a), Mcols (a));
c = D_Matrix (result);
if ((status = CompareNEQMatrices (c, a, b)))
MatrixError ("!=", a, b, status, F_False);
break;
default:
type_error = F_True;
break;
}
break;
case T_String:
switch (D_Type (right)) {
case T_String:
cmp = strcmp (*D_String (left), *D_String (right));
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp != 0);
break;
default:
type_error = F_True;
break;
}
break;
case T_Function:
case T_Intrinsic:
case T_Array:
case T_Pair:
if (D_Type (left) == D_Type (right)) {
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (D_Pointer (left) == D_Pointer (right));
} else
type_error = F_False;
break;
case T_Constraint:
case T_Definition:
case T_Element:
case T_Force:
case T_Load:
case T_Material:
case T_Node:
case T_Stress:
case T_External:
if (D_Type (left) == D_Type (right)) {
cmp = *(void **) D_Pointer (left) != *(void **) D_Pointer (right);
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
} else if (D_Type (right) == T_Null) {
cmp = *(void **) D_Pointer (left) != NULL;
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
} else
type_error = F_True;
break;
case T_Null:
switch (D_Type (right)) {
case T_Constraint:
case T_Definition:
case T_Element:
case T_Force:
case T_Load:
case T_Material:
case T_Node:
case T_Stress:
case T_External:
cmp = *(void **) D_Pointer (right) != NULL;
D_Type (result) = T_Double;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Double (result) = dbllit (cmp);
break;
default:
type_error = F_True;
break;
}
break;
default:
type_error = F_True;
break;
}
if (type_error == F_True)
TypeError ("!=", left, right, NULL, F_False);
RecycleData (left);
RecycleData (right);
d_printf ("ne ans =\n");
d_PrintData (result);
return type_error == F_True || status != 0;
}
syntax highlighted by Code2HTML, v. 0.9.1