text: //------------------------------------------------------------------------------
  // GB_mex_about2: more basic tests
  //------------------------------------------------------------------------------
  
  // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
  // SPDX-License-Identifier: Apache-2.0
  
  //------------------------------------------------------------------------------
  
  // Test lots of random stuff.  The function otherwise serves no purpose.
  
  #include "GB_mex.h"
  #include "GB_mex_errors.h"
  #include "GB_ij.h"
  
  #define USAGE "GB_mex_about2"
  
  typedef struct
  {
      int stuff [16] ;
  }
  wild ;
  
  void mexFunction
  (
      int nargout,
      mxArray *pargout [ ],
      int nargin,
      const mxArray *pargin [ ]
  )
  {
  
      GrB_Info info ;
      GrB_Matrix A = NULL, B = NULL, C = NULL ;
      GrB_Scalar scalar = NULL ;
      GrB_Vector victor = NULL ;
      GrB_Descriptor desc = NULL ;
      GrB_Type Wild = NULL ;
      char *err ;
  
      //--------------------------------------------------------------------------
      // startup GraphBLAS
      //--------------------------------------------------------------------------
  
      bool malloc_debug = GB_mx_get_global (true) ;
      FILE *f = fopen ("errlog3.txt", "w") ;
      int expected = GrB_SUCCESS ;
  
      //--------------------------------------------------------------------------
      // test removeElement/setElement when jumbled
      //--------------------------------------------------------------------------
  
      OK (GrB_Matrix_new (&A, GrB_INT32, 10, 10)) ;
      OK (GrB_Vector_new (&victor, GrB_INT32, 10)) ;
      OK (GxB_Vector_Option_set_(victor, GxB_BITMAP_SWITCH, 2.0)) ;
      OK (GrB_Scalar_new (&scalar, GrB_INT32)) ;
  
      OK (GxB_Matrix_fprint (A, "A before set", 3, NULL)) ;
      OK (GrB_Matrix_setElement_INT32 (A, 314159, 0, 0)) ;
      OK (GxB_Matrix_fprint (A, "A after set", 3, NULL)) ;
      A->jumbled = true ;
      OK (GrB_Matrix_removeElement (A, 0, 0)) ;
      OK (GxB_Matrix_fprint (A, "A after remove", 3, NULL)) ;
      A->jumbled = true ;
      OK (GrB_Matrix_setElement_INT32 (A, 99099, 0, 0)) ;
      OK (GxB_Matrix_fprint (A, "A after set again", 3, NULL)) ;
  
      OK (GxB_Vector_fprint (victor, "victor before set", 3, NULL)) ;
      OK (GrB_Vector_setElement_INT32 (victor, 44, 0)) ;
      OK (GxB_Vector_fprint (victor, "victor after set", 3, NULL)) ;
      victor->jumbled = true ;
      OK (GrB_Vector_removeElement (victor, 0)) ;
      OK (GxB_Vector_fprint (victor, "victor remove set", 3, NULL)) ;
      victor->jumbled = true ;
      OK (GrB_Vector_setElement_INT32 (victor, 88, 0)) ;
      OK (GxB_Vector_fprint (victor, "victor after set again", 3, NULL)) ;
  
      OK (GxB_Scalar_fprint (scalar, "scalar before set", 3, NULL)) ;
      OK (GrB_Scalar_setElement_INT32 (scalar, 404)) ;
      OK (GxB_Scalar_fprint (scalar, "scalar after set", 3, NULL)) ;
      int i = 0 ;
      OK (GrB_Scalar_extractElement_INT32 (&i, scalar)) ;
      CHECK (i == 404) ;
      OK (GxB_Scalar_fprint (scalar, "scalar after extract", 3, NULL)) ;
      OK (GrB_Matrix_removeElement ((GrB_Matrix) scalar, 0, 0)) ;
      OK (GxB_Scalar_fprint (scalar, "scalar after remove", 3, NULL)) ;
      i = 777 ;
      expected = GrB_NO_VALUE ;
      ERR (GrB_Scalar_extractElement_INT32 (&i, scalar)) ;
      CHECK (i == 777) ;
  
      // force a zombie into the scalar
      OK (GrB_Scalar_setElement_INT32 (scalar, 707)) ;
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Scalar_wait (&scalar)) ;
      #else
      OK (GrB_Scalar_wait (scalar, GrB_MATERIALIZE)) ;
      #endif
      OK (GxB_Scalar_fprint (scalar, "scalar after wait", 3, NULL)) ;
      OK (GxB_Matrix_Option_set (scalar, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
      CHECK (scalar->i != NULL) ;
      scalar->i [0] = GB_FLIP (0) ;
      scalar->nzombies = 1 ;
      OK (GxB_Scalar_fprint (scalar, "scalar with zombie", 3, NULL)) ;
      expected = GrB_NO_VALUE ;
      ERR (GrB_Scalar_extractElement_INT32 (&i, scalar)) ;
      OK (GxB_Scalar_fprint (scalar, "scalar after extract", 3, NULL)) ;
      CHECK (i == 777) ;
  
      GrB_Vector_free_(&victor) ;
      GrB_Matrix_free_(&A) ;
      GrB_Scalar_free_(&scalar) ;
  
      //--------------------------------------------------------------------------
      // builtin comparators not defined for complex types
      //--------------------------------------------------------------------------
  
      int n = 10 ;
      OK (GrB_Matrix_new (&A, GxB_FC32, n, n)) ;
      OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
  
      OK (GrB_Matrix_new (&C, GxB_FC32, n, n)) ;
      OK (GrB_Scalar_new (&scalar, GxB_FC32)) ;
      expected = GrB_DOMAIN_MISMATCH ;
      ERR (GxB_Matrix_select (C, NULL, NULL, GxB_LT_THUNK, A, scalar, NULL)) ;
      char *message = NULL ;
      OK (GrB_Matrix_error (&message, C)) ;
      printf ("expected error: %s\n", message) ;
      GrB_Matrix_free_(&C) ;
      GrB_Scalar_free_(&scalar) ;
  
      //--------------------------------------------------------------------------
      // GB_pslice
      //--------------------------------------------------------------------------
  
      int64_t Slice [30] ;
      GB_pslice (Slice, A->p, n, 2, true) ;
      CHECK (Slice [0] == 0) ;
  
      int64_t Ap [11] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ;
      GB_pslice (Slice, Ap, 10, 10, false) ;
      printf ("Slice: ") ;
      for (int k = 0 ; k <= 10 ; k++) printf (" %ld", Slice [k]) ;
      printf ("\n") ;
  
      GrB_Matrix_free_(&A) ;
  
      //--------------------------------------------------------------------------
      // GrB_Matrix_check
      //--------------------------------------------------------------------------
  
      double bswitch = 1 ;
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GxB_Matrix_Option_set_(A, GxB_BITMAP_SWITCH, 0.125)) ;
      OK (GxB_Matrix_Option_get_(A, GxB_BITMAP_SWITCH, &bswitch)) ;
      CHECK (fabs (bswitch - 0.125) < 1e-5) ;
  
      OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
      OK (GrB_Matrix_assign_INT32 (A, NULL, NULL, 3, GrB_ALL, n, GrB_ALL, n,
          NULL)) ;
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Matrix_wait (&A)) ;
      #else
      OK (GrB_Matrix_wait (A, GrB_MATERIALIZE)) ;
      #endif
      OK (GxB_Matrix_fprint (A, "valid matrix", GxB_SHORT, NULL)) ;
      // mangle the matrix
      GB_FREE (&(A->p), A->p_size) ;
      GB_FREE (&(A->x), A->x_size) ;  // OK
      expected = GrB_INVALID_OBJECT ;
      ERR (GxB_Matrix_fprint (A, "invalid sparse matrix", GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      A->sparsity_control = 999 ;
      ERR (GxB_Matrix_fprint (A, "invalid sparsity control", GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Matrix_assign_INT32 (A, NULL, NULL, 3, GrB_ALL, n, GrB_ALL, n,
          NULL)) ;
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Matrix_wait (&A)) ;
      #else
      OK (GrB_Matrix_wait (A, GrB_MATERIALIZE)) ;
      #endif
  
      A->jumbled = true ;
      ERR (GxB_Matrix_fprint (A, "full matrix cannot be jumbled", GxB_SHORT,
          NULL)) ;
  
      A->jumbled = false ;
      A->plen = 999 ;
      ERR (GxB_Matrix_fprint (A, "invalid full matrix", GxB_SHORT, NULL)) ;
  
      A->plen = -1 ;
      A->nzombies = 1 ;
      ERR (GxB_Matrix_fprint (A, "full matrix cannot have zombies",
          GxB_SHORT, NULL)) ;
      A->nzombies = 0 ;
      CHECK (GB_Pending_alloc (&(A->Pending), false, GrB_INT32, NULL, true, 4)) ;
      ERR (GxB_Matrix_fprint (A, "full matrix cannot have pending tuples",
          GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_BITMAP)) ;
      A->plen = 999 ;
      ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SHORT, NULL)) ;
  
      A->plen = -1 ;
      A->b [0] = 1 ;
      ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SUMMARY, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GxB_Matrix_Option_set_(A, GxB_SPARSITY_CONTROL, GxB_BITMAP)) ;
      OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
      OK (GxB_Matrix_fprint (A, "valid matrix", GxB_SHORT, NULL)) ;
      A->b [0] = 3 ;
      ERR (GxB_Matrix_fprint (A, "invalid bitmap", GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      A->nvec_nonempty = 2 ;
      ERR (GxB_Matrix_fprint (A, "invalid nvec_nonempty", GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
      OK (GxB_Matrix_fprint (A, "valid matrix with 1 pending", GxB_SHORT, NULL)) ;
      A->Pending->size = 900 ;
      ERR (GxB_Matrix_fprint (A, "invalid pending type", GxB_SHORT, NULL)) ;
      GrB_Matrix_free_(&A) ;
  
      //--------------------------------------------------------------------------
      // lo:stride:hi with stride of zero
      //--------------------------------------------------------------------------
  
      OK (GxB_Global_Option_set_(GxB_BURBLE, true)) ;
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      GrB_Index I [3] = { 1, 1, 0 } ;
      OK (GrB_Matrix_new (&C, GrB_INT32, n, 0)) ;
      OK (GrB_Matrix_extract_(C, NULL, NULL, A, GrB_ALL, n, I, GxB_STRIDE,
          NULL)) ;
      OK (GxB_Matrix_fprint (C, "C = A (:,1:0:1)", GxB_COMPLETE, NULL)) ;
      GrB_Matrix_free_(&C) ;
      OK (GrB_Matrix_new (&C, GrB_INT32, 0, n)) ;
      OK (GrB_Matrix_extract_(C, NULL, NULL, A, I, GxB_STRIDE, GrB_ALL, n,
          NULL)) ;
      OK (GxB_Matrix_fprint (C, "C = A (1:0:1,:)", GxB_COMPLETE, NULL)) ;
      GrB_Matrix_free_(&C) ;
      GrB_Matrix_free_(&A) ;
      OK (GxB_Global_Option_set_(GxB_BURBLE, false)) ;
  
      int64_t Icolon [3] = { 1, 1, 0 } ;
      CHECK (!GB_ij_is_in_list (NULL, 0, 0, GB_STRIDE, Icolon)) ;
  
      //--------------------------------------------------------------------------
      // GB_aliased
      //--------------------------------------------------------------------------
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Matrix_setElement_INT32 (A, 12345, 0, 0)) ;
      OK (GrB_Matrix_dup (&C, A)) ;
      CHECK (!GB_aliased (A, C)) ;
      GB_FREE (&(C->p), C->p_size) ;
      C->p = A->p ;
      C->p_shallow = true ;
      CHECK (GB_aliased (A, C)) ;
      C->p = NULL ;
      C->p_shallow = false ;
      CHECK (!GB_aliased (A, C)) ;
      GB_FREE (&(C->i), C->i_size) ;
      C->i = A->i ;
      C->i_shallow = true ;
      CHECK (GB_aliased (A, C)) ;
      C->i = NULL ;
      C->i_shallow = false ;
      GrB_Matrix_free_(&A) ;
      GrB_Matrix_free_(&C) ;
  
      //--------------------------------------------------------------------------
      // GrB_apply with empty scalar
      //--------------------------------------------------------------------------
  
      OK (GrB_Scalar_new (&scalar, GrB_INT32)) ;
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Matrix_new (&C, GrB_INT32, n, n)) ;
      expected = GrB_EMPTY_OBJECT ;
      ERR (GxB_Matrix_apply_BinaryOp2nd (C, NULL, NULL, GrB_PLUS_INT32, A,
          scalar, NULL)) ;
      OK (GrB_Matrix_error (&message, C)) ;
      printf ("expected error: %s\n", message) ;
      GrB_Matrix_free_(&A) ;
      GrB_Matrix_free_(&C) ;
      GrB_Scalar_free_(&scalar) ;
  
      //--------------------------------------------------------------------------
      // invalid descriptor
      //--------------------------------------------------------------------------
  
      int method ;
      OK (GrB_Descriptor_new (&desc)) ;
      OK (GxB_Descriptor_fprint (desc, "descriptor", GxB_COMPLETE, NULL)) ;
  
      OK (GxB_Desc_get (NULL, GxB_AxB_METHOD, &method)) ;
      CHECK (method == GxB_DEFAULT) ;
      OK (GxB_Desc_set (desc, GxB_AxB_METHOD, GxB_AxB_GUSTAVSON)) ;
      OK (GxB_Descriptor_fprint (desc, "descriptor", GxB_COMPLETE, NULL)) ;
      OK (GxB_Desc_get (desc, GxB_AxB_METHOD, &method)) ;
      CHECK (method == GxB_AxB_GUSTAVSON) ;
  
      desc->mask = GrB_REPLACE ;
      expected = GrB_INVALID_OBJECT ;
      ERR (GxB_Descriptor_fprint (desc, "invalid", GxB_COMPLETE, NULL)) ;
      OK (GrB_Descriptor_free (&desc)) ;
  
      //--------------------------------------------------------------------------
      // GrB_build an empty matrix
      //--------------------------------------------------------------------------
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Matrix_build_INT32 (A, I, I, I, 0, GrB_PLUS_INT32)) ;
      OK (GxB_Matrix_fprint (A, "empty", GxB_COMPLETE, NULL)) ;
      CHECK (!GB_is_shallow (A)) ;
      GrB_Matrix_free_(&A) ;
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      expected = GrB_DOMAIN_MISMATCH ;
      ERR (GrB_Matrix_build_INT32 (A, I, I, I, 0, GxB_FIRSTI_INT32)) ;
      OK (GrB_Matrix_error (&message, A)) ;
      printf ("expected error: %s\n", message) ;
      GrB_Matrix_free_(&A) ;
  
      //--------------------------------------------------------------------------
      // reduce with positional op
      //--------------------------------------------------------------------------
  
      OK (GrB_Matrix_new (&A, GrB_INT32, n, n)) ;
      OK (GrB_Vector_new (&victor, GrB_INT32, n)) ;
      OK (GxB_Vector_Option_get_(victor, GxB_BITMAP_SWITCH, &bswitch)) ;
      printf ("vector bitmap switch: %g\n\n", bswitch) ;
  
      expected = GrB_NOT_IMPLEMENTED ;
      ERR (GrB_Matrix_reduce_BinaryOp (victor, NULL, NULL, GxB_FIRSTI_INT32,
          A, NULL)) ;
      OK (GrB_Matrix_error (&message, victor)) ;
      printf ("error expected: %s\n", message) ;
      GrB_Matrix_free_(&A) ;
      GrB_Vector_free_(&victor) ;
  
      //--------------------------------------------------------------------------
      // GrB_init
      //--------------------------------------------------------------------------
  
      expected = GrB_INVALID_VALUE ;
      ERR (GrB_init (GrB_BLOCKING)) ;
  
      //--------------------------------------------------------------------------
      // jumbled user-defined matrix
      //--------------------------------------------------------------------------
  
      wild ww, w2 ;
      n = 3 ;
      memset (ww.stuff, 13, 16 * sizeof (int)) ;
      OK (GrB_Type_new (&Wild, sizeof (wild))) ;
      OK (GrB_Matrix_new (&C, Wild, n, n)) ;
      OK (GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
      OK (GrB_Matrix_assign_UDT (C, NULL, NULL, &ww, GrB_ALL, n, GrB_ALL, n,
          NULL)) ;
      OK (GxB_Matrix_fprint (C, "wild matrix", GxB_SHORT, NULL)) ;
  
      // jumble the matrix
      C->jumbled = true ;
      C->i [0] = 1 ;
      C->i [1] = 0 ;
      OK (GxB_Matrix_fprint (C, "wild matrix jumbled", GxB_SHORT, NULL)) ;
  
      // unjumble the matrix
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Matrix_wait (&C)) ;
      #else
      OK (GrB_Matrix_wait (C, GrB_MATERIALIZE)) ;
      #endif
      OK (GxB_Matrix_fprint (C, "wild matrix unjumbled", GxB_SHORT, NULL)) ;
  
      GrB_Matrix_free_(&C) ;
  
      //--------------------------------------------------------------------------
      // malloc/realloc wrappers
      //--------------------------------------------------------------------------
  
      size_t nbytes ;
      bool ok = false ;
      int *p = GB_malloc_memory (4, sizeof (int), &nbytes) ;
      CHECK (p != NULL) ;
      p = GB_realloc_memory (1024*1024, sizeof (int), p, &nbytes, &ok, NULL) ;
      CHECK (p != NULL) ;
      CHECK (ok) ;
      p = GB_realloc_memory (4, GB_NMAX + 1, p, &nbytes, &ok, NULL) ;
      CHECK (!ok) ;
      GB_free_memory (&p, nbytes) ;
  
      //--------------------------------------------------------------------------
      // try to import a huge full matrix (this will fail):
      //--------------------------------------------------------------------------
  
      GrB_Matrix X = NULL ;
      info = GxB_Matrix_import_FullC (&X, GrB_FP32, GB_NMAX, GB_NMAX,
          NULL, UINT64_MAX, false, NULL) ;
      if (info != GrB_INVALID_VALUE || X != NULL) mexErrMsgTxt ("huge fail1") ;
  
      GrB_Index nhuge = (((GrB_Index) 2) << 50) ;
      info = GxB_Matrix_import_BitmapC (&X, GrB_FP32, nhuge, nhuge,
          NULL, NULL, 0, 0, false, 0, NULL) ;
      if (info != GrB_INVALID_VALUE || X != NULL) mexErrMsgTxt ("huge fail5") ;
  
      // try to convert a huge sparse matrix to bitmap (this will fail too):
      info = GrB_Matrix_new (&X, GrB_FP32, nhuge, nhuge) ;
      if (info != GrB_SUCCESS) mexErrMsgTxt ("huge fail2") ;
      info = GxB_Matrix_Option_set_(X, GxB_SPARSITY_CONTROL, GxB_BITMAP) ;
      if (info != GrB_OUT_OF_MEMORY) mexErrMsgTxt ("huge fail3") ;
      GrB_Matrix_free (&X) ;
  
      //--------------------------------------------------------------------------
      // hypermatrix prune
      //--------------------------------------------------------------------------
  
      OK (GrB_Matrix_new (&C, GrB_FP32, GB_NMAX, GB_NMAX)) ;
      OK (GrB_Matrix_setElement_FP32 (C, (double) 3, 0, 0)) ;
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Matrix_wait (&C)) ;
      #else
      OK (GrB_Matrix_wait (C, GrB_MATERIALIZE)) ;
      #endif
      OK (GxB_Matrix_fprint (C, "huge matrix", GxB_SHORT, NULL)) ;
      C->nvec_nonempty = -1 ;
      OK (GB_hypermatrix_prune (C, NULL)) ;
      CHECK (C->nvec_nonempty == 1) ;
      GrB_Matrix_free (&C) ;
  
      //--------------------------------------------------------------------------
      // vector option set/get
      //--------------------------------------------------------------------------
  
      OK (GrB_Vector_new (&victor, GrB_FP32, 10)) ;
      OK (GxB_Vector_Option_set (victor, GxB_BITMAP_SWITCH, (double) 4.5)) ;
      double bitmap_switch = 8 ;
      OK (GxB_Vector_Option_get (victor, GxB_BITMAP_SWITCH, &bitmap_switch)) ;
      CHECK (bitmap_switch == 4.5) ;
      GrB_Vector_free (&victor) ;
  
      //--------------------------------------------------------------------------
      // split/concat for user-defined types
      //--------------------------------------------------------------------------
  
      printf ("\n ======================== split/concat tests: ") ;
      int sparsity [4] ;
      sparsity [0] = GxB_HYPERSPARSE ;
      sparsity [1] = GxB_SPARSE ;
      sparsity [2] = GxB_BITMAP ;
      sparsity [3] = GxB_FULL ;
      GrB_Matrix Tiles [4] ;
      memset (Tiles, 0, 4 * sizeof (GrB_Matrix)) ;
      n = 20 ;
      GrB_Index Tile_nrows [2] = { 5, 15 } ;
      GrB_Index Tile_ncols [2] = { 12, 8 } ;
  
      for (int k = 0 ; k <= 3 ; k++)
      {
          for (int k2 = 0 ; k2 <= 1 ; k2++)
          {
              OK (GrB_Matrix_new (&C, Wild, n, n)) ;
              OK (GxB_Matrix_Option_set (C, GxB_SPARSITY_CONTROL, sparsity [k])) ;
              if (k2 == 0)
              {
                  // C(:,:) = ww
                  OK (GrB_Matrix_assign_UDT (C, NULL, NULL, &ww, GrB_ALL,
                      n, GrB_ALL, n, NULL)) ;
              }
              else
              {
                  // C = diagonal matrix
                  for (int64_t kk = 0 ; kk < 20 ; kk++)
                  {
                      OK (GrB_Matrix_setElement_UDT (C, &ww, kk, kk)) ;
                  }
              }
              // split C into 4 matrices
              OK (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C,
                  NULL)) ;
              // concatenate the 4 matrices back in X
              OK (GrB_Matrix_new (&X, Wild, n, n)) ;
              OK (GxB_Matrix_Option_set (X, GxB_SPARSITY_CONTROL, sparsity [k])) ;
              OK (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              // ensure C and X are the same (just use a brute force method)
              for (int64_t i = 0 ; i < n ; i++)
              {
                  for (int64_t j = 0 ; j < n ; j++)
                  {
                      wild wc, wx ;
                      int infoc = GrB_Matrix_extractElement_UDT (&wc, C, i, j) ;
                      int infox = GrB_Matrix_extractElement_UDT (&wx, X, i, j) ;
                      CHECK (infoc == GrB_SUCCESS || infoc == GrB_NO_VALUE) ;
                      CHECK (infoc == infox) ;
                      if (infoc == GrB_SUCCESS)
                      {
                          for (int kk = 0 ; kk < 16 ; kk++)
                          {
                              CHECK (wc.stuff [kk] == wx.stuff [kk]) ;
                          }
                      }
                  }
              }
              GrB_Matrix_free (&X) ;
              GrB_Matrix_free (&C) ;
  
              expected = GrB_DOMAIN_MISMATCH ;
              OK (GrB_Matrix_new (&X, GrB_FP32, n, n)) ;
              ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              OK (GrB_Matrix_error (&err, X)) ;
              printf ("expected error: %s\n", err) ;
              GrB_Matrix_free (&X) ;
  
              expected = GrB_DIMENSION_MISMATCH ;
              OK (GrB_Matrix_new (&X, Wild, 100, 100)) ;
              ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              OK (GrB_Matrix_error (&err, X)) ;
              printf ("expected error: %s\n", err) ;
              GrB_Matrix_free (&X) ;
  
              OK (GrB_Matrix_new (&X, Wild, n, n)) ;
              GrB_Matrix_free (&(Tiles [3])) ;
              OK (GrB_Matrix_new (&(Tiles [3]), Wild, 15, 100)) ;
              ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              // GxB_print (X, 3) ;
              OK (GrB_Matrix_error (&err, X)) ;
              printf ("expected error: %s\n", err) ;
              GrB_Matrix_free (&(Tiles [3])) ;
  
              OK (GrB_Matrix_new (&(Tiles [3]), Wild, 100, 8)) ;
              ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              OK (GrB_Matrix_error (&err, X)) ;
              printf ("expected error: %s\n", err) ;
  
              for (int kk = 0 ; kk < 4 ; kk++)
              {
                  GrB_Matrix_free (&(Tiles [kk])) ;
              }
  
              expected = GrB_NULL_POINTER ;
              ERR (GxB_Matrix_concat (X, Tiles, 2, 2, NULL)) ;
              GrB_Matrix_free (&X) ;
          }
      }
  
      //--------------------------------------------------------------------------
      // split/concat error handling
      //--------------------------------------------------------------------------
  
      expected = GrB_INVALID_VALUE ;
      OK (GrB_Matrix_new (&C, GrB_FP32, n, n)) ;
      ERR (GxB_Matrix_split (Tiles, 0, 0, Tile_nrows, Tile_ncols, C, NULL)) ;
      ERR (GxB_Matrix_concat (C, Tiles, 0, 0, NULL)) ;
      GrB_Matrix_free (&C) ;
  
      expected = GrB_DIMENSION_MISMATCH ;
      OK (GrB_Matrix_new (&C, GrB_FP32, n, n)) ;
      Tile_nrows [0] = -1 ;
      ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
      Tile_nrows [0] = 1 ;
      ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
      Tile_nrows [0] = 5 ;
      Tile_ncols [0] = -1 ;
      ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
      Tile_ncols [0] = 1 ;
      ERR (GxB_Matrix_split (Tiles, 2, 2, Tile_nrows, Tile_ncols, C, NULL)) ;
      GrB_Matrix_free (&C) ;
  
      //--------------------------------------------------------------------------
      // C<C,struct> = scalar
      //--------------------------------------------------------------------------
  
      printf ("\n\ntesting C<C,struct> = scalar for user-defined type:\n") ;
      OK (GxB_Global_Option_set (GxB_BURBLE, true)) ;
      OK (GrB_Matrix_new (&C, Wild, n, n)) ;
      memset (ww.stuff,  0, 16 * sizeof (int)) ;
      memset (w2.stuff,  1, 16 * sizeof (int)) ;
      for (int64_t kk = 0 ; kk < 16 ; kk++)
      {
          w2.stuff [kk] = kk ;
      }
      for (int64_t kk = 0 ; kk < 20 ; kk++)
      {
          OK (GrB_Matrix_setElement_UDT (C, &ww, kk, kk)) ;
      }
      #if (GxB_IMPLEMENTATION_MAJOR <= 5)
      OK (GrB_Matrix_wait (&C)) ;
      #else
      OK (GrB_Matrix_wait (C, GrB_MATERIALIZE)) ;
      #endif
      info = GrB_Matrix_assign_UDT (C, C, NULL, &w2, GrB_ALL, 20, GrB_ALL, 20,
          GrB_DESC_S) ;
      wild w3 ;
  
      for (int64_t kk = 0 ; kk < 20 ; kk++)
      {
          memset (w3.stuff,  9, 16 * sizeof (int)) ;
          info = (GrB_Matrix_extractElement_UDT (&w3, C, kk, kk)) ;
          CHECK (info == GrB_SUCCESS) ;
          for (int64_t t = 0 ; t < 16 ; t++)
          {
              CHECK (w3.stuff [t] == t) ;
          }
      }
      GrB_Matrix_free (&C) ;
      OK (GxB_Global_Option_set (GxB_BURBLE, false)) ;
  
      //--------------------------------------------------------------------------
      // GxB_Matrix_diag and GxB_Vector_diag error handling
      //--------------------------------------------------------------------------
  
      expected = GrB_DIMENSION_MISMATCH ;
  
      OK (GrB_Matrix_new (&C, GrB_FP32, 10, 20)) ;
      OK (GrB_Vector_new (&victor, GrB_FP32, 10)) ;
      ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
      OK (GrB_Matrix_error (&err, C)) ;
      printf ("expected error: %s\n", err) ;
      GrB_Matrix_free (&C) ;
  
      OK (GrB_Matrix_new (&C, GrB_FP32, 5, 5)) ;
      ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
      OK (GrB_Matrix_error (&err, C)) ;
      printf ("expected error: %s\n", err) ;
      ERR (GxB_Vector_diag (victor, C, 0, NULL)) ;
      OK (GrB_Vector_error (&err, victor)) ;
      printf ("expected error: %s\n", err) ;
      GrB_Matrix_free (&C) ;
  
      expected = GrB_DOMAIN_MISMATCH ;
  
      OK (GrB_Matrix_new (&C, Wild, 10, 10)) ;
      ERR (GxB_Matrix_diag (C, victor, 0, NULL)) ;
      OK (GrB_Matrix_error (&err, C)) ;
      printf ("expected error: %s\n", err) ;
      ERR (GxB_Vector_diag (victor, C, 0, NULL)) ;
      OK (GrB_Vector_error (&err, victor)) ;
      printf ("expected error: %s\n", err) ;
      GrB_Matrix_free (&C) ;
      GrB_Vector_free (&victor) ;
  
      //--------------------------------------------------------------------------
      // wrapup
      //--------------------------------------------------------------------------
  
      GrB_Type_free_(&Wild) ;
      GB_mx_put_global (true) ;   
      fclose (f) ;
      printf ("\nAll errors printed above were expected.\n") ;
      printf ("GB_mex_about2: all tests passed\n\n") ;
  }
  
  