/* -----------------------------------------------------------------------------
 * Programmer(s): David J. Gardner @ LLNL
 * -----------------------------------------------------------------------------
 * SUNDIALS Copyright Start
 * Copyright (c) 2002-2024, Lawrence Livermore National Security
 * and Southern Methodist University.
 * All rights reserved.
 *
 * See the top-level LICENSE and NOTICE files for details.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 * SUNDIALS Copyright End
 * -----------------------------------------------------------------------------
 * This is the header file for the implementation of the NVECTOR SensWrapper.
 *
 * Part I contains declarations specific to the implementation of the
 * vector wrapper.
 *
 * Part II defines accessor macros that allow the user to efficiently access
 * the content of the vector wrapper data structure.
 *
 * Part III contains the prototype for the constructors N_VNewEmpty_SensWrapper
 * and N_VNew_SensWrapper, as well as wrappers to NVECTOR vector operations.
 * ---------------------------------------------------------------------------*/

#ifndef _NVECTOR_SENSWRAPPER_H
#define _NVECTOR_SENSWRAPPER_H

#include <stdio.h>
#include <sundials/sundials_nvector.h>

#ifdef __cplusplus /* wrapper to enable C++ usage */
extern "C" {
#endif

/*==============================================================================
  PART I: NVector wrapper content structure
  ============================================================================*/

struct _N_VectorContent_SensWrapper
{
  N_Vector* vecs;          /* array of wrapped vectors                */
  int nvecs;               /* number of wrapped vectors               */
  sunbooleantype own_vecs; /* flag indicating if wrapper owns vectors */
};

typedef struct _N_VectorContent_SensWrapper* N_VectorContent_SensWrapper;

/*==============================================================================
  PART II: Macros to access wrapper content
  ============================================================================*/

#define NV_CONTENT_SW(v)  ((N_VectorContent_SensWrapper)(v->content))
#define NV_VECS_SW(v)     (NV_CONTENT_SW(v)->vecs)
#define NV_NVECS_SW(v)    (NV_CONTENT_SW(v)->nvecs)
#define NV_OWN_VECS_SW(v) (NV_CONTENT_SW(v)->own_vecs)
#define NV_VEC_SW(v, i)   (NV_VECS_SW(v)[i])

/*==============================================================================
  PART III: Exported functions
  ============================================================================*/

/* constructor creates an empty vector wrapper */
SUNDIALS_EXPORT N_Vector N_VNewEmpty_SensWrapper(int nvecs, SUNContext sunctx);
SUNDIALS_EXPORT N_Vector N_VNew_SensWrapper(int count, N_Vector w);

/* clone operations */
SUNDIALS_EXPORT N_Vector N_VCloneEmpty_SensWrapper(N_Vector w);
SUNDIALS_EXPORT N_Vector N_VClone_SensWrapper(N_Vector w);

/* destructor */
SUNDIALS_EXPORT void N_VDestroy_SensWrapper(N_Vector v);

/* standard vector operations */
SUNDIALS_EXPORT void N_VLinearSum_SensWrapper(sunrealtype a, N_Vector x,
                                              sunrealtype b, N_Vector y,
                                              N_Vector z);
SUNDIALS_EXPORT void N_VConst_SensWrapper(sunrealtype c, N_Vector z);
SUNDIALS_EXPORT void N_VProd_SensWrapper(N_Vector x, N_Vector y, N_Vector z);
SUNDIALS_EXPORT void N_VDiv_SensWrapper(N_Vector x, N_Vector y, N_Vector z);
SUNDIALS_EXPORT void N_VScale_SensWrapper(sunrealtype c, N_Vector x, N_Vector z);
SUNDIALS_EXPORT void N_VAbs_SensWrapper(N_Vector x, N_Vector z);
SUNDIALS_EXPORT void N_VInv_SensWrapper(N_Vector x, N_Vector z);
SUNDIALS_EXPORT void N_VAddConst_SensWrapper(N_Vector x, sunrealtype b,
                                             N_Vector z);
SUNDIALS_EXPORT sunrealtype N_VDotProd_SensWrapper(N_Vector x, N_Vector y);
SUNDIALS_EXPORT sunrealtype N_VMaxNorm_SensWrapper(N_Vector x);
SUNDIALS_EXPORT sunrealtype N_VWrmsNorm_SensWrapper(N_Vector x, N_Vector w);
SUNDIALS_EXPORT sunrealtype N_VWrmsNormMask_SensWrapper(N_Vector x, N_Vector w,
                                                        N_Vector id);
SUNDIALS_EXPORT sunrealtype N_VMin_SensWrapper(N_Vector x);
SUNDIALS_EXPORT sunrealtype N_VWL2Norm_SensWrapper(N_Vector x, N_Vector w);
SUNDIALS_EXPORT sunrealtype N_VL1Norm_SensWrapper(N_Vector x);
SUNDIALS_EXPORT void N_VCompare_SensWrapper(sunrealtype c, N_Vector x,
                                            N_Vector z);
SUNDIALS_EXPORT sunbooleantype N_VInvTest_SensWrapper(N_Vector x, N_Vector z);
SUNDIALS_EXPORT sunbooleantype N_VConstrMask_SensWrapper(N_Vector c, N_Vector x,
                                                         N_Vector m);
SUNDIALS_EXPORT sunrealtype N_VMinQuotient_SensWrapper(N_Vector num,
                                                       N_Vector denom);

#ifdef __cplusplus
}
#endif

#endif
