//------------------------------------------------------------------------------
// GB_shallow_copy: create a shallow copy of a matrix
//------------------------------------------------------------------------------

// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2025, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//------------------------------------------------------------------------------

// Create a purely shallow copy C of a matrix A.  No typecasting is done.  If A
// has zombies or pending tuples, those are finished first.

// The CSR/CSC format of C and A can differ, but they have they same vlen and
// vdim.  This function is CSR/CSC agnostic, except that C_is_csc is used to
// set the C->is_csc state in C.  The matrix C has the same iso property as
// the matrix A.

// Shallow matrices are never passed back to the user.

// A has any sparsity structure (hypersparse, sparse, bitmap, or full).

// Compare this function with GB_shallow_op.c.  See also GB_get_arena_alias
// and GB_set_arena_alias, which makes an alias of the header (content is not
// shallow).

#include "GB.h"

#define GB_FREE_ALL ;

GrB_Info GB_shallow_copy    // create a purely shallow matrix
(
    GrB_Matrix C,           // output matrix C, with a existing header
    const bool C_is_csc,    // desired CSR/CSC format of C
    const GrB_Matrix A,     // input matrix
    GB_Werk Werk
)
{

    //--------------------------------------------------------------------------
    // check inputs
    //--------------------------------------------------------------------------

    ASSERT (C != NULL) ;
    ASSERT_MATRIX_OK (A, "A for shallow copy", GB0) ;
    GB_MATRIX_WAIT_IF_PENDING_OR_ZOMBIES (A) ;
    ASSERT (!GB_PENDING (A)) ;
    ASSERT (GB_JUMBLED_OK (A)) ;
    ASSERT (!GB_ZOMBIES (A)) ;

    int header_arena = GB_arena (C->header_mem) ;
    int data_arena = C->data_arena ;

    //--------------------------------------------------------------------------
    // construct a shallow copy of A for the pattern of C
    //--------------------------------------------------------------------------

    // allocate the struct for C, but do not allocate C->[p,h,b,i,x].
    // C has the exact same sparsity structure as A.
    #ifdef GB_DEBUG
    GrB_Info info =
    #endif
    GB_new (&C, // sparse or hyper, existing header
        A->type, A->vlen, A->vdim, GB_ph_null, C_is_csc,
        GB_sparsity (A), A->hyper_switch, 0,
        A->p_is_32, A->j_is_32, A->i_is_32, header_arena, data_arena) ;
    ASSERT (info == GrB_SUCCESS) ;

    //--------------------------------------------------------------------------
    // make a shallow copy of the vector pointers
    //--------------------------------------------------------------------------

    ASSERT (C->magic == GB_MAGIC2) ;    // C not yet initialized
    C->p_shallow = (A->p != NULL) ;     // C->p not freed when freeing C
    C->h_shallow = (A->h != NULL) ;     // C->h not freed when freeing C
    C->p = A->p ;                       // C->p is of size A->plen + 1
    C->h = A->h ;                       // C->h is of size A->plen
    C->p_is_32 = A->p_is_32 ;
    C->j_is_32 = A->j_is_32 ;
    C->i_is_32 = A->i_is_32 ;
    C->p_mem = A->p_mem ;
    C->h_mem = A->h_mem ;
    C->plen = A->plen ;                 // C and A have the same hyperlist size
    C->nvec = A->nvec ;
    GB_nvec_nonempty_set (C, GB_nvec_nonempty_get (A)) ;
    C->jumbled = A->jumbled ;           // C is jumbled if A is jumbled
    C->nvals = A->nvals ;
    C->magic = GB_MAGIC ;
    C->iso = A->iso ;                   // C has the same iso property as A
    if (A->iso)
    { 
        GB_BURBLE_MATRIX (A, "(iso copy) ") ;
    }

    //--------------------------------------------------------------------------
    // make a shallow copy of the A->Y hyper_hash
    //--------------------------------------------------------------------------

    C->Y = A->Y ;
    C->Y_shallow = (A->Y != NULL) ;
    C->no_hyper_hash = A->no_hyper_hash ;

    //--------------------------------------------------------------------------
    // check for empty matrix
    //--------------------------------------------------------------------------

    if (GB_nnz_max (A) == 0)
    { 
        // C->p and C->h are shallow but the rest is empty
        C->b = NULL ;
        C->i = NULL ;
        C->x = NULL ;
        C->b_shallow = false ;
        C->i_shallow = false ;
        C->x_shallow = false ;
        C->jumbled = false ;
        C->iso = false ;
        ASSERT_MATRIX_OK (C, "C = quick copy of empty A", GB0) ;
        return (GrB_SUCCESS) ;
    }

    //--------------------------------------------------------------------------
    // make a shallow copy of the pattern and values
    //--------------------------------------------------------------------------

    C->b = A->b ; C->b_shallow = (A->b != NULL) ; C->b_mem = A->b_mem ;
    C->i = A->i ; C->i_shallow = (A->i != NULL) ; C->i_mem = A->i_mem ;
    C->x = A->x ; C->x_shallow = (A->x != NULL) ; C->x_mem = A->x_mem ;

    ASSERT_MATRIX_OK (C, "C = pure shallow (A)", GB0) ;
    return (GrB_SUCCESS) ;
}

