#ifndef OBTC_H
#define OBTC_H


#include "uint256.h"
#include "xoshiro256pp.h"
#include "Svd.h"
#include "DiagonalMatrix.h"
#include "Matrix.h"
#include "Rotator.h"
#include "heavyhash.h"


typedef struct Obtc_opt Obtc_t;
struct Obtc_opt{
	uint8_t data_r[32];
	uint64_t ss[4];
	uint8_t const_data[200];
	CSHA3_256 CSHA3_256_p;
	CHeavyHash CHeavyHash_p;
	uint256 g_hash_first;
	XoShiRo256PlusPlus_t *xo;
	DiagonalMatrix_t g_DiagonalMatrix;

};

//struct Obtc_opt;


bool Is4BitPrecision(const uint64_t matrix[64*64]);
bool IsFullRank(const uint64_t matrix_[64*64]);
void GenerateHeavyHashMatrix(uint256 matrix_seed, uint64_t matrix[64*64]);
void serialize_heavyhash(Obtc_t *Obtc, uint64_t matrix[64*64], const char* in, char* out, int len);
void opticalbtc_hash(const char* in, char* out, int len);

extern void CSHA3_256_init(Obtc_t *Obtc, CSHA3_256 *p);
extern void CSHA3_256_CSHA3_256(Obtc_t *Obtc, CSHA3_256 *p);

extern void CSHA3_256_Write(CSHA3_256 *p, const unsigned char* data, size_t len);

extern void CSHA3_256_Finalize(CSHA3_256 *p, unsigned char hash[OUTPUT_SIZE]);
//extern void CSHA3_256_Reset(Obtc_t *Obtc, CSHA3_256 *p);

extern void CHeavyHash_init(Obtc_t *Obtc, CHeavyHash *p, uint64_t matrix_[64*64]);
extern void CHeavyHash_Write(CHeavyHash *p, const unsigned char* data, size_t len);

extern void CHeavyHash_Finalize(Obtc_t *Obtc, CHeavyHash *p, unsigned char hash[OUTPUT_SIZE]);

extern int sha3_init(Obtc_t *Obtc,sha3_ctx_t *c, int mdlen);    // mdlen = hash output in bytes


#endif // OBTC_H
