From b337ae979dad938f1ef72df4f67b612a883040b1 Mon Sep 17 00:00:00 2001
From: Raymond Lu <songyulu@hdfgroup.org>
Date: Thu, 15 Mar 2012 15:53:14 -0500
Subject: [svn-r22076] #Issue 7922 - H5Pset_data_transform had seg fault with
 some operations like x*-100. The parser mistaked "-" as substraction.  I
 fixed it and also fixed another problem with some special cases like 100-x
 and 2/x.

Tested on jam, koala, and ostrich.
---
 release_docs/RELEASE.txt |   4 +-
 src/H5HF.c               |   1 +
 src/H5Ztrans.c           | 187 +++++++++++++++++++++++++++++++++++++++--------
 test/dtransform.c        | 180 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 338 insertions(+), 34 deletions(-)

diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 8055516..63ae2d7 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -364,7 +364,9 @@ Bug Fixes since HDF5-1.8.0 release
 
     Library
     -------
-
+      - H5Pset_data_transform had seg fault in some cases like x*-100.  It
+            works correctly now and handles other cases like 100-x or 2/x.
+            (SLU - 2012/3/15.  Issue 7922) 
       - Fixed rare corruption bugs that could occur when using the new object
             header format. (NAF - 2012/3/15 - HDFFV-7879)
       - Creating a dataset in a read-only file caused seg fault when the file 
diff --git a/src/H5HF.c b/src/H5HF.c
index 9c911fd..801fa8c 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -361,6 +361,7 @@ H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj,
     herr_t ret_value = SUCCEED;
 
     FUNC_ENTER_NOAPI(FAIL)
+
 #ifdef QAK
 HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
 #endif /* QAK */
diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c
index 5a707b5..2a2796d 100644
--- a/src/H5Ztrans.c
+++ b/src/H5Ztrans.c
@@ -94,6 +94,8 @@ static H5Z_node *H5Z_parse_term(H5Z_token *current, H5Z_datval_ptrs* dat_val_poi
 static H5Z_node *H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers);
 static H5Z_node *H5Z_new_node(H5Z_token_type type);
 static void H5Z_do_op(H5Z_node* tree);
+static hbool_t H5Z_op_is_numbs(H5Z_node* _tree);
+static hbool_t H5Z_op_is_numbs2(H5Z_node* _tree);
 static hid_t H5Z_xform_find_type(const H5T_t* type);
 static herr_t H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result* res);
 static void H5Z_xform_destroy_parse_tree(H5Z_node *tree);
@@ -105,41 +107,46 @@ static void H5Z_XFORM_DEBUG(H5Z_node *tree);
 static void H5Z_print(H5Z_node *tree, FILE *stream);
 #endif  /* H5Z_XFORM_DEBUG */
 
-
 #define H5Z_XFORM_DO_OP1(RESL,RESR,TYPE,OP,SIZE)                            \
 {   								  	    \
-    if( (((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type != H5Z_XFORM_SYMBOL)) || (((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL))) \
+    size_t u;                                                               \
+                                                                            \
+    if(((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type != H5Z_XFORM_SYMBOL)) \
+    {   								    \
+	TYPE* p;                                                            \
+	double tree_val;                                                    \
+		                                                            \
+	tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \
+	p = (TYPE*)(RESL).value.dat_val;                                    \
+                                                                            \
+	for(u=0; u<(SIZE); u++)                                             \
+	    *p++ = *p OP tree_val;                                          \
+    }									    \
+    else if(((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL)) \
     {   								    \
-	size_t u;                                                           \
 	TYPE* p;                                                            \
 	double tree_val;                                                    \
 		                                                            \
-	if((RESL).type == H5Z_XFORM_SYMBOL)                                 \
-	{                                                                   \
-	    tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \
-	    p = (TYPE*)(RESL).value.dat_val;                                \
-	}                                                                   \
+        /* The case that the left operand is nothing, like -x or +x */      \
+	if((RESL).type == H5Z_XFORM_ERROR)                                  \
+            tree_val = 0;                                                   \
 	else                                                                \
-	{                                                                   \
 	    tree_val = ((RESL).type==H5Z_XFORM_INTEGER ? (double)(RESL).value.int_val : (RESL).value.float_val); \
-	    p = (TYPE*)(RESR).value.dat_val;                                \
-	}                                                                   \
-		                                                            \
+                                                                            \
+	p = (TYPE*)(RESR).value.dat_val;                                    \
 	for(u=0; u<(SIZE); u++)                                             \
-	    *p++ OP tree_val;                                               \
-    }										\
+	    *p++ = tree_val OP *p;                                          \
+    }									    \
     else if( ((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type==H5Z_XFORM_SYMBOL))  \
     {										\
-	size_t u;                                                           	\
 	TYPE* pl = (TYPE*)(RESL).value.dat_val;                             	\
 	TYPE* pr = (TYPE*)(RESR).value.dat_val;                             	\
 										\
 	for(u=0; u<(SIZE); u++)                                             	\
-	    *pl++ OP *pr++;                                                 	\
+	    *pl++ = *pl OP *pr++;                                           	\
     }										\
     else									\
         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unexpected type conversion operation")	\
-										\
 }
 
 /* Due to the undefined nature of embedding macros/conditionals within macros, we employ
@@ -235,6 +242,7 @@ static void H5Z_print(H5Z_node *tree, FILE *stream);
 }
 #endif /*H5_SIZEOF_LONG_DOUBLE */
 
+
 #define H5Z_XFORM_DO_OP3(OP)                                                                                                                    \
 {                                                                                                                                               \
         if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER))                                                \
@@ -259,6 +267,48 @@ static void H5Z_print(H5Z_node *tree, FILE *stream);
         }																	\
 }
 
+/* The difference of this macro from H5Z_XFORM_DO_OP3 is that it handles the operations when the left operand is empty, like -x or +x.  
+ * The reason that it's seperated from H5Z_XFORM_DO_OP3 is because compilers don't accept operations like *x or /x.  So in H5Z_do_op, 
+ * these two macros are called in different ways. 
+ */
+#define H5Z_XFORM_DO_OP6(OP)                                                                                                                    \
+{                                                                                                                                               \
+        if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_INTEGER))                                                                            \
+        {																	\
+            tree->type = H5Z_XFORM_INTEGER;													\
+            tree->value.int_val = OP tree->rchild->value.int_val;							                        \
+            H5MM_xfree(tree->rchild);														\
+            tree->rchild = NULL;														\
+        }	                                                                                                                                \
+        else if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_FLOAT))                                                                         \
+        {																	\
+            tree->type = H5Z_XFORM_FLOAT;													\
+            tree->value.float_val = OP tree->rchild->value.float_val;							                        \
+            H5MM_xfree(tree->rchild);														\
+            tree->rchild = NULL;														\
+        }	                                                                                                                                \
+        else if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER))                                           \
+        {																	\
+            tree->type = H5Z_XFORM_INTEGER;													\
+            tree->value.int_val = tree->lchild->value.int_val OP tree->rchild->value.int_val;							\
+            H5MM_xfree(tree->lchild);														\
+            H5MM_xfree(tree->rchild);														\
+            tree->lchild = NULL;														\
+            tree->rchild = NULL;														\
+        }																	\
+	else if( ( (tree->lchild->type == H5Z_XFORM_FLOAT) || (tree->lchild->type == H5Z_XFORM_INTEGER)) && 					\
+	            ( (tree->rchild->type == H5Z_XFORM_FLOAT) || (tree->rchild->type == H5Z_XFORM_INTEGER)))					\
+	{																	\
+	    tree->type = H5Z_XFORM_FLOAT;													\
+            tree->value.float_val = ((tree->lchild->type == H5Z_XFORM_FLOAT) ? tree->lchild->value.float_val : (double)tree->lchild->value.int_val) OP 	\
+				    ((tree->rchild->type == H5Z_XFORM_FLOAT) ? tree->rchild->value.float_val : (double)tree->rchild->value.int_val);	\
+            H5MM_xfree(tree->lchild);														\
+            H5MM_xfree(tree->rchild);														\
+            tree->lchild = NULL;														\
+            tree->rchild = NULL;														\
+        }																	\
+}
+
 #define H5Z_XFORM_DO_OP4(TYPE)                                                                                          \
 {                                                                                                                       \
     if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL)                                                \
@@ -1027,6 +1077,9 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size,  const hid_t array_
     /* check args */
     HDassert(tree);
 
+    HDmemset(&resl, 0, sizeof(H5Z_result));
+    HDmemset(&resr, 0, sizeof(H5Z_result));
+
     if (tree->type == H5Z_XFORM_INTEGER) {
 	res->type = H5Z_XFORM_INTEGER;
 	res->value.int_val = tree->value.int_val;
@@ -1044,7 +1097,7 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size,  const hid_t array_
 	res->value.dat_val = *((void**)(tree->value.dat_val));
     } /* end if */
     else {
-	if(H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0)
+	if(tree->lchild && H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0)
 	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
 	if(H5Z_xform_eval_full(tree->rchild, array_size, array_type, &resr) < 0)
 	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
@@ -1059,19 +1112,19 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size,  const hid_t array_
 
 	switch (tree->type) {
 	    case H5Z_XFORM_PLUS:
-		H5Z_XFORM_TYPE_OP(resl, resr, array_type, +=, array_size)
+	 	H5Z_XFORM_TYPE_OP(resl, resr, array_type, +, array_size)
 		break;
 
 	    case H5Z_XFORM_MINUS:
-		H5Z_XFORM_TYPE_OP(resl, resr, array_type, -=, array_size)
+	 	H5Z_XFORM_TYPE_OP(resl, resr, array_type, -, array_size)
 		break;
 
 	    case H5Z_XFORM_MULT:
-		H5Z_XFORM_TYPE_OP(resl, resr, array_type, *=, array_size)
+		H5Z_XFORM_TYPE_OP(resl, resr, array_type, *, array_size)
 		break;
 
 	    case H5Z_XFORM_DIVIDE:
-		H5Z_XFORM_TYPE_OP(resl, resr, array_type, /=, array_size)
+	 	H5Z_XFORM_TYPE_OP(resl, resr, array_type, /, array_size)
 		break;
 
 	    default:
@@ -1274,22 +1327,37 @@ H5Z_xform_reduce_tree(H5Z_node* tree)
     FUNC_ENTER_NOAPI_NOINIT_NOERR
 
     if(tree) {
-        if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_DIVIDE) ||(tree->type == H5Z_XFORM_MULT) ||(tree->type == H5Z_XFORM_MINUS))
+        if((tree->type == H5Z_XFORM_DIVIDE) || (tree->type == H5Z_XFORM_MULT))
         {
-            if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT)))
+            if(H5Z_op_is_numbs(tree))
                 H5Z_do_op(tree);
             else
             {
                 H5Z_xform_reduce_tree(tree->lchild);
-                if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT)))
+                if(H5Z_op_is_numbs(tree))
                     H5Z_do_op(tree);
                 else {
                     H5Z_xform_reduce_tree(tree->rchild);
-                    if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT)))
+                    if(H5Z_op_is_numbs(tree))
+                        H5Z_do_op(tree);
+                }
+            }
+        } else if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_MINUS)) {
+            if(H5Z_op_is_numbs2(tree))
+                H5Z_do_op(tree);
+            else
+            {
+                H5Z_xform_reduce_tree(tree->lchild);
+                if(H5Z_op_is_numbs2(tree))
+                    H5Z_do_op(tree);
+                else {
+                    H5Z_xform_reduce_tree(tree->rchild);
+                    if(H5Z_op_is_numbs2(tree))
                         H5Z_do_op(tree);
                 }
             }
         }
+
     }
 
     FUNC_LEAVE_NOAPI_VOID;
@@ -1297,6 +1365,63 @@ H5Z_xform_reduce_tree(H5Z_node* tree)
 
 
 /*-------------------------------------------------------------------------
+ * Function:    H5Z_op_is_numbs
+ * Purpose:     Internal function to facilitate the condition check in 
+ *              H5Z_xform_reduce_tree to reduce the bulkiness of the code.
+ * Return:      TRUE or FALSE
+ * Programmer:  Raymond Lu
+ *              15 March 2012
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5Z_op_is_numbs(H5Z_node* _tree)
+{
+    hbool_t ret_value = FALSE;
+
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    assert(_tree);
+
+    if(((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT)) && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT)))
+      ret_value = TRUE;
+
+    FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    H5Z_op_is_numbs2
+ * Purpose:     Internal function to facilitate the condition check in 
+ *              H5Z_xform_reduce_tree to reduce the bulkiness of the code.
+ *              The difference from H5Z_op_is_numbs is that the left child
+ *              can be empty, like -x or +x.
+ * Return:      TRUE or FALSE
+ * Programmer:  Raymond Lu
+ *              15 March 2012
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5Z_op_is_numbs2(H5Z_node* _tree)
+{
+    hbool_t ret_value = FALSE;
+
+    FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+    assert(_tree);
+
+    if((!_tree->lchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT))) ||
+       ((_tree->lchild && ((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT))) && (_tree->rchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT)))))
+      ret_value = TRUE;
+
+    FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
  * Function:    H5Z_do_op
  * Purpose:     If the root of the tree passed in points to a simple
  *              arithmetic operation and the left and right subtrees are both
@@ -1307,7 +1432,11 @@ H5Z_xform_reduce_tree(H5Z_node* tree)
  * Programmer:  Leon Arber
  *              April 1, 2004.
  * Modifications:
-*
+ *              Raymond Lu
+ *              15 March 2012
+ *              I added a new macro H5Z_XFORM_DO_OP6 to handle the special
+ *              operations like -x or +x when the left operand is empty.
+ *
  *-------------------------------------------------------------------------
  */
 static void
@@ -1320,9 +1449,9 @@ H5Z_do_op(H5Z_node* tree)
     else if(tree->type == H5Z_XFORM_MULT)
 	H5Z_XFORM_DO_OP3(*)
     else if(tree->type == H5Z_XFORM_PLUS)
-	H5Z_XFORM_DO_OP3(+)
+	H5Z_XFORM_DO_OP6(+)
     else if(tree->type == H5Z_XFORM_MINUS)
-	H5Z_XFORM_DO_OP3(-)
+	H5Z_XFORM_DO_OP6(-)
 
     FUNC_LEAVE_NOAPI_VOID;
 }
diff --git a/test/dtransform.c b/test/dtransform.c
index 5d5cefe..2bcbe8c 100644
--- a/test/dtransform.c
+++ b/test/dtransform.c
@@ -23,6 +23,7 @@ static int init_test(hid_t file_id);
 static int test_copy(const hid_t dxpl_id_c_to_f_copy, const hid_t dxpl_id_polynomial_copy);
 static int test_trivial(const hid_t dxpl_id_simple);
 static int test_poly(const hid_t dxpl_id_polynomial);
+static int test_specials(hid_t file);
 static int test_set(void);
 static int test_getset(const hid_t dxpl_id_simple);
 
@@ -50,14 +51,14 @@ const float windchillFfloat[ROWS][COLS] =
 
 const int transformData[ROWS][COLS] =
     {   {36, 31, 25, 19, 13, 7, 1, 5, 11, 16, 22, 28, 34, 40, 46, 52, 57, 63 },
-        {34, 27, 21, 15, 9, 3, 4, 10, 16, 22, 28, 35, 41, 47, 53, 59, 66, 0 } ,
-        {32, 25, 19, 13, 6, 0, 7, 13, 19, 26, 32, 39, 45, 51, 58, 64, 71, 5 },
+        {34, 27, 21, 15, 9, 3, 4, 10, 16, 22, 28, 35, 41, 47, 53, 59, 66, 1 } ,
+        {32, 25, 19, 13, 6, 2, 7, 13, 19, 26, 32, 39, 45, 51, 58, 64, 71, 5 },
         {30, 24, 17, 11, 4, 2, 9, 15, 22, 29, 35, 42, 48, 55, 61, 68, 2, 9 },
         {29, 23, 16, 9, 3, 4, 11, 17, 24, 31, 37, 44, 51, 58, 64, 71, 6, 12 },
         {28, 22, 15, 8, 1, 5, 12, 19, 26, 33, 39, 46, 53, 60, 67, 1, 8, 15 },
-        {28, 21, 14, 7, 0, 7, 14, 21, 27, 34, 41, 48, 55, 62, 69, 4, 10, 17 },
+        {28, 21, 14, 7, 6, 7, 14, 21, 27, 34, 41, 48, 55, 62, 69, 4, 10, 17 },
         {27, 20, 13, 6, 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 6, 12, 19 },
-        {26, 19, 12, 5, 2, 9, 16, 23, 30, 37, 44, 51, 58, 65, 0, 7, 14, 21 },
+        {26, 19, 12, 5, 2, 9, 16, 23, 30, 37, 44, 51, 58, 65, 5, 7, 14, 21 },
         {26, 19, 12, 4, 3, 10, 17, 24, 31, 38, 45, 52, 60, 67, 2, 9, 16, 23},
         {25, 18, 11, 4, 3, 11, 18, 25, 32, 39, 46, 54, 61, 68, 3, 10, 17, 25},
         {25, 17, 10, 3, 4, 11, 19, 26, 33, 40, 48, 55, 62, 69, 4, 12, 19, 26}
@@ -97,6 +98,22 @@ const int transformData[ROWS][COLS] =
     PASSED();						\
 }
 
+#define COMPARE_INT(VAR1,VAR2)			        \
+{							\
+    size_t i,j;						\
+							\
+    for(i=0; i<ROWS; i++)				\
+        for(j=0; j<COLS; j++)				\
+        {						\
+            if( (VAR1)[i][j] != (VAR2)[i][j] )	        \
+            {						\
+                H5_FAILED();				\
+                fprintf(stderr, "    ERROR: data  failed to match computed data\n");	\
+                goto error;				\
+            }						\
+        }						\
+}
+
 #define TEST_TYPE_CONTIG(XFORM, TYPE, HDF_TYPE, TEST_STR, COMPARE_DATA, SIGNED)	\
 {										\
     TYPE array[ROWS][COLS];							\
@@ -332,6 +349,7 @@ int main(void)
     if(test_trivial(dxpl_id_simple) < 0) TEST_ERROR;
     if(test_poly(dxpl_id_polynomial) < 0) TEST_ERROR;
     if(test_getset(dxpl_id_c_to_f) < 0) TEST_ERROR;
+    if(test_specials(file_id) < 0) TEST_ERROR;
 
     /* Close the objects we opened/created */
     if(H5Dclose(dset_id_int) < 0) TEST_ERROR;
@@ -502,6 +520,160 @@ error:
 }
 
 static int
+test_specials(hid_t file)
+{
+    hid_t dxpl_id, dset_id, dataspace;
+    hsize_t dim[2] = { ROWS, COLS };
+    int read_buf[ROWS][COLS];
+    int data_res[ROWS][COLS];
+    int row, col;
+    const char* special1 = "x*-100";
+    const char* special2 = "100-x";
+    const char* special3 = "1000/x";
+    const char* special4 = "-x";
+    const char* special5 = "+x";
+
+    TESTING("data transform of some special cases")
+
+    if((dataspace = H5Screate_simple(2, dim, NULL)) < 0)
+        TEST_ERROR
+
+    if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) TEST_ERROR;
+
+    /*-----------------------------
+     * Operation 1: x*-100
+     *----------------------------*/
+    if(H5Pset_data_transform(dxpl_id, special1) < 0) TEST_ERROR;
+
+    for(row = 0; row < ROWS; row++)
+        for(col = 0; col < COLS; col++)
+            data_res[row][col] = transformData[row][col] * -100;
+
+    if((dset_id = H5Dcreate2(file, "/special1", H5T_NATIVE_INT,
+            dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+        TEST_ERROR
+    if(H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            dxpl_id, transformData) < 0)
+        TEST_ERROR
+    if(H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            H5P_DEFAULT, read_buf) < 0)
+        TEST_ERROR
+ 
+    COMPARE_INT(read_buf, data_res)
+
+    if(H5Dclose(dset_id) < 0)
+        TEST_ERROR
+
+    /*-----------------------------
+     * Operation 2: 100-x
+     *----------------------------*/
+    if(H5Pset_data_transform(dxpl_id, special2) < 0) TEST_ERROR;
+
+    for(row = 0; row < ROWS; row++)
+        for(col = 0; col < COLS; col++)
+            data_res[row][col] = 100 - transformData[row][col];
+
+    if((dset_id = H5Dcreate2(file, "/special2", H5T_NATIVE_INT,
+            dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+        TEST_ERROR
+    if(H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            dxpl_id, transformData) < 0)
+        TEST_ERROR
+    if(H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            H5P_DEFAULT, read_buf) < 0)
+        TEST_ERROR
+ 
+    COMPARE_INT(read_buf, data_res)
+
+    if(H5Dclose(dset_id) < 0)
+        TEST_ERROR
+
+    /*-----------------------------
+     * Operation 3: 1000/x
+     *----------------------------*/
+    if(H5Pset_data_transform(dxpl_id, special3) < 0) TEST_ERROR;
+
+    for(row = 0; row < ROWS; row++)
+        for(col = 0; col < COLS; col++)
+            data_res[row][col] = 1000 / transformData[row][col];
+
+    if((dset_id = H5Dcreate2(file, "/special3", H5T_NATIVE_INT,
+            dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+        TEST_ERROR
+    if(H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            dxpl_id, transformData) < 0)
+        TEST_ERROR
+    if(H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            H5P_DEFAULT, read_buf) < 0)
+        TEST_ERROR
+ 
+    COMPARE_INT(read_buf, data_res)
+
+    if(H5Dclose(dset_id) < 0)
+        TEST_ERROR
+
+    /*-----------------------------
+     * Operation 4: -x
+     *----------------------------*/
+    if(H5Pset_data_transform(dxpl_id, special4) < 0) TEST_ERROR;
+
+    for(row = 0; row < ROWS; row++)
+        for(col = 0; col < COLS; col++)
+            data_res[row][col] = -1 * transformData[row][col];
+
+    if((dset_id = H5Dcreate2(file, "/special4", H5T_NATIVE_INT,
+            dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+        TEST_ERROR
+    if(H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            dxpl_id, transformData) < 0)
+        TEST_ERROR
+    if(H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            H5P_DEFAULT, read_buf) < 0)
+        TEST_ERROR
+ 
+    COMPARE_INT(read_buf, data_res)
+
+    if(H5Dclose(dset_id) < 0)
+        TEST_ERROR
+
+    /*-----------------------------
+     * Operation 5: +x
+     *----------------------------*/
+    if(H5Pset_data_transform(dxpl_id, special5) < 0) TEST_ERROR;
+
+    for(row = 0; row < ROWS; row++)
+        for(col = 0; col < COLS; col++)
+            data_res[row][col] = transformData[row][col];
+
+    if((dset_id = H5Dcreate2(file, "/special5", H5T_NATIVE_INT,
+            dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+        TEST_ERROR
+    if(H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            dxpl_id, transformData) < 0)
+        TEST_ERROR
+    if(H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+            H5P_DEFAULT, read_buf) < 0)
+        TEST_ERROR
+ 
+    COMPARE_INT(read_buf, data_res)
+
+    if(H5Dclose(dset_id) < 0)
+        TEST_ERROR
+
+
+    if(H5Pclose(dxpl_id) < 0)
+        TEST_ERROR
+    if(H5Sclose(dataspace) < 0)
+        TEST_ERROR
+
+    PASSED();
+    return 0;
+
+error: 
+     return -1;
+}
+
+static int
 test_copy(const hid_t dxpl_id_c_to_f_copy, const hid_t dxpl_id_polynomial_copy)
 {
     int windchillC;
-- 
cgit v0.12