/*
 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
 *                         University Research and Technology
 *                         Corporation.  All rights reserved.
 * Copyright (c) 2004-2006 The University of Tennessee and The University
 *                         of Tennessee Research Foundation.  All rights
 *                         reserved.
 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
 *                         University of Stuttgart.  All rights reserved.
 * Copyright (c) 2004-2005 The Regents of the University of California.
 *                         All rights reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 */

#ifndef _OPAL_CRC_H_
#define _OPAL_CRC_H_

#include "opal_config.h"

#include <stddef.h>

#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif

#define CRC_POLYNOMIAL ((unsigned int)0x04c11db7)
#define CRC_INITIAL_REGISTER ((unsigned int)0xffffffff)


#define OPAL_CSUM( SRC, LEN )  opal_uicsum( SRC, LEN )
#define OPAL_CSUM_PARTIAL( SRC, LEN, UI1, UI2 ) \
    opal_uicsum_partial( SRC, LEN, UI1, UI2 )
#define OPAL_CSUM_BCOPY_PARTIAL( SRC, DST, LEN1, LEN2, UI1, UI2 ) \
    opal_bcopy_uicsum_partial( SRC, DST, LEN1, LEN2, UI1, UI2 )
#define OPAL_CSUM_ZERO  0


OPAL_DECLSPEC unsigned long
opal_bcopy_csum_partial(
    const void *  source,
    void *  destination,
    size_t copylen,
    size_t csumlen,
    unsigned long*  lastPartialLong,
    size_t*  lastPartialLength
    );

static inline unsigned long
opal_bcopy_csum (
    const void *  source,
    void *  destination,
    size_t copylen,
    size_t csumlen
    )
{
    unsigned long plong = 0;
    size_t plength = 0;
    return opal_bcopy_csum_partial(source, destination, copylen, csumlen, &plong, &plength);
}
                                                                                                                  
OPAL_DECLSPEC unsigned int 
opal_bcopy_uicsum_partial (
    const void *  source,
    void *  destination,
    size_t copylen,
    size_t csumlen,
    unsigned int*  lastPartialInt,
    size_t*  lastPartialLength
    );

static inline unsigned int
opal_bcopy_uicsum (
    const void *  source,
    void *  destination,
    size_t copylen,
    size_t csumlen
    )
{
    unsigned int pint = 0;
    size_t plength = 0;
    return opal_bcopy_uicsum_partial(source, destination, copylen, csumlen, &pint, &plength);
}
                                                                                                                  
OPAL_DECLSPEC unsigned long 
opal_csum_partial (
    const void *  source,
    size_t csumlen,
    unsigned long*  lastPartialLong,
    size_t*  lastPartialLength
    );


static inline unsigned long 
opal_csum(const void *  source, size_t csumlen)
{
    unsigned long lastPartialLong = 0;
    size_t lastPartialLength = 0;
    return opal_csum_partial(source, csumlen, &lastPartialLong, &lastPartialLength);
}

OPAL_DECLSPEC unsigned int
opal_uicsum_partial (
    const void *  source,
    size_t csumlen,
    unsigned int *  lastPartialInt,
    size_t*  lastPartialLength
    );

static inline unsigned int 
opal_uicsum(const void *  source, size_t csumlen)
{
    unsigned int lastPartialInt = 0;
    size_t lastPartialLength = 0;
    return opal_uicsum_partial(source, csumlen, &lastPartialInt, &lastPartialLength);
}
                                                                                                                  
/*
 * CRC Support
 */

void opal_initialize_crc_table(void);

OPAL_DECLSPEC unsigned int 
opal_bcopy_uicrc_partial(
    const void *  source,
    void *  destination,
    size_t copylen,
    size_t crclen,
    unsigned int partial_crc);

static inline unsigned int 
opal_bcopy_uicrc(
    const void *  source, 
    void *  destination,
    size_t copylen, 
    size_t crclen)
{
    return opal_bcopy_uicrc_partial(source, destination, copylen, crclen, CRC_INITIAL_REGISTER);
}

OPAL_DECLSPEC unsigned int 
opal_uicrc_partial(
    const void *  source, 
    size_t crclen, 
    unsigned int partial_crc);


static inline unsigned int 
opal_uicrc(const void *  source, size_t crclen)
{
    return opal_uicrc_partial(source, crclen, CRC_INITIAL_REGISTER);
}
                                                                                                                  
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif

#endif