mirror of
https://github.com/TREX-CoE/qmckl.git
synced 2025-01-03 10:06:09 +01:00
Added tests
This commit is contained in:
parent
1879d3a67c
commit
534e11cccb
@ -2,8 +2,8 @@
|
|||||||
# vim: syntax=c
|
# vim: syntax=c
|
||||||
#+TITLE: QMCkl C header
|
#+TITLE: QMCkl C header
|
||||||
|
|
||||||
This file is included in all other C header files, and produces the
|
This file produces the =qmckl.h= header file, which is included in all
|
||||||
=qmckl.h= header file.
|
other C header files. It is the main entry point to the library.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl.h
|
#+BEGIN_SRC C :tangle qmckl.h
|
||||||
#ifndef QMCKL_H
|
#ifndef QMCKL_H
|
||||||
@ -27,13 +27,20 @@ typedef int qmckl_exit_code;
|
|||||||
|
|
||||||
** Precision-related constants
|
** Precision-related constants
|
||||||
|
|
||||||
|
Controlling numerical precision enables optimizations. Here, the
|
||||||
|
default parameters determining the target numerical precision and
|
||||||
|
range are defined.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl.h
|
#+BEGIN_SRC C :tangle qmckl.h
|
||||||
#define QMCKL_DEFAULT_PRECISION 53
|
#define QMCKL_DEFAULT_PRECISION 53
|
||||||
#define QMCKL_DEFAULT_RANGE 2
|
#define QMCKL_DEFAULT_RANGE 11
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
* Header files
|
* Header files
|
||||||
|
|
||||||
|
All the functions expoed in the API are defined in the following
|
||||||
|
header files.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl.h
|
#+BEGIN_SRC C :tangle qmckl.h
|
||||||
#include "qmckl_context.h"
|
#include "qmckl_context.h"
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
@ -5,48 +5,77 @@
|
|||||||
This file is written in C because it is more natural to express the context in
|
This file is written in C because it is more natural to express the context in
|
||||||
C than in Fortran.
|
C than in Fortran.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
3 files are produced:
|
||||||
|
- a header file : =qmckl_context.h=
|
||||||
|
- a source file : =qmckl_context.c=
|
||||||
|
- a test file : =test_qmckl_context.c=
|
||||||
|
|
||||||
|
*** Header
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
#ifndef QMCKL_CONTEXT_H
|
#ifndef QMCKL_CONTEXT_H
|
||||||
#define QMCKL_CONTEXT_H
|
#define QMCKL_CONTEXT_H
|
||||||
#include "qmckl.h"
|
#include "qmckl.h"
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.c
|
*** Source
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
#include <stdlib.h> /* malloc */
|
#include <stdlib.h> /* malloc */
|
||||||
#include "qmckl_context.h"
|
#include "qmckl_context.h"
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
#include "qmckl_context.h"
|
||||||
|
#include "qmckl_test.h"
|
||||||
|
int main() {
|
||||||
|
qmckl_exit_code rc; /* return code */
|
||||||
|
rc = QMCKL_SUCCESS;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
* Context
|
* Context
|
||||||
|
|
||||||
The context variable is a handle for the state of the library, and
|
The context variable is a handle for the state of the library, and
|
||||||
is stored in the following data structure, which can't be seen
|
is stored in the following data structure, which can't be seen
|
||||||
outside of the library.
|
outside of the library. To simplify compatibility with other
|
||||||
|
languages, the pointer to the internal data structure is converted
|
||||||
|
into a 64-bit signed integer, defined in the =qmckl_context= type.
|
||||||
|
A value of 0 for the context is equivalent to a NULL pointer.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
*** Header
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
/* 64-bit integer */
|
/* 64-bit integer */
|
||||||
typedef long long int qmckl_context ;
|
typedef long long int qmckl_context ;
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Source
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.c
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
typedef struct qmckl_context_struct {
|
typedef struct qmckl_context_struct {
|
||||||
struct qmckl_context_struct * prev;
|
struct qmckl_context_struct * prev;
|
||||||
int precision;
|
int precision;
|
||||||
int range;
|
int range;
|
||||||
} qmckl_context_struct;
|
} qmckl_context_struct;
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
We declare here the variables used in the tests.
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
qmckl_context context;
|
||||||
|
qmckl_context new_context;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
** =qmckl_context_create=
|
** =qmckl_context_create=
|
||||||
|
|
||||||
To create a new context, use =qmckl_context_create()=. If the creation
|
To create a new context, use =qmckl_context_create()=.
|
||||||
failed, the function returns =0=. On success, a pointer to a context
|
- On success, returns a pointer to a context using the =qmckl_context= type
|
||||||
is returned as a 64-bit integer.
|
- Returns 0 upon failure to allocate the internal data structure
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
*** Header
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
qmckl_context qmckl_context_create();
|
qmckl_context qmckl_context_create();
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.c
|
*** Source
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
qmckl_context qmckl_context_create() {
|
qmckl_context qmckl_context_create() {
|
||||||
|
|
||||||
qmckl_context_struct* context;
|
qmckl_context_struct* context;
|
||||||
@ -62,20 +91,46 @@ qmckl_context qmckl_context_create() {
|
|||||||
|
|
||||||
return (qmckl_context) context;
|
return (qmckl_context) context;
|
||||||
}
|
}
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
context = qmckl_context_create();
|
||||||
|
if (context == (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_create\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if ( ((qmckl_context_struct*) new_context)->precision != QMCKL_DEFAULT_PRECISION ) {
|
||||||
|
eprintf("qmckl_context_copy: No access to data\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
** =qmckl_context_copy=
|
** =qmckl_context_copy=
|
||||||
|
|
||||||
|
|
||||||
|
This function makes a shallow copy of the current context.
|
||||||
|
- Copying the 0-valued context returns 0
|
||||||
|
- On success, returns a pointer to the new context using the =qmckl_context= type
|
||||||
|
- Returns 0 upon failure to allocate the internal data structure
|
||||||
|
for the new context
|
||||||
|
|
||||||
|
*** Header
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
qmckl_context qmckl_context_copy(const qmckl_context context);
|
qmckl_context qmckl_context_copy(const qmckl_context context);
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Source
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.c
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
qmckl_context qmckl_context_copy(const qmckl_context context) {
|
qmckl_context qmckl_context_copy(const qmckl_context context) {
|
||||||
|
|
||||||
qmckl_context_struct* old_context;
|
qmckl_context_struct* old_context;
|
||||||
qmckl_context_struct* new_context;
|
qmckl_context_struct* new_context;
|
||||||
|
|
||||||
|
if (context == (qmckl_context) 0) {
|
||||||
|
return (qmckl_context) 0;
|
||||||
|
}
|
||||||
|
|
||||||
new_context = (qmckl_context_struct*) malloc (sizeof(qmckl_context_struct));
|
new_context = (qmckl_context_struct*) malloc (sizeof(qmckl_context_struct));
|
||||||
if (new_context == NULL) {
|
if (new_context == NULL) {
|
||||||
return (qmckl_context) 0;
|
return (qmckl_context) 0;
|
||||||
@ -91,32 +146,124 @@ qmckl_context qmckl_context_copy(const qmckl_context context) {
|
|||||||
}
|
}
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
** =qmckl_context_destroy=
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
new_context = qmckl_context_copy(context);
|
||||||
|
if (new_context == (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_copy: Allocation failure\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (new_context == context ) {
|
||||||
|
eprintf("qmckl_context_copy: Same pointer\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if ( ((qmckl_context_struct*) new_context)->precision != QMCKL_DEFAULT_PRECISION ) {
|
||||||
|
eprintf("qmckl_context_copy: No access to data\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
To delete a new context, use =qmckl_context_destroy()=. If the deletion
|
** =qmckl_context_previous=
|
||||||
failed, the function returns =0=. On success, the function returns =1=
|
|
||||||
implying that the context has been freed.
|
Returns the previous context
|
||||||
|
- On success, returns the ancestor of the current context
|
||||||
|
- Returns 0 for the initial context
|
||||||
|
- Returns 0 for the 0-valued context
|
||||||
|
|
||||||
|
*** Header
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
int qmckl_context_destroy(qmckl_context context);
|
qmckl_context qmckl_context_previous(const qmckl_context context);
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Source
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.c
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
int qmckl_context_destroy(qmckl_context context) {
|
qmckl_context qmckl_context_previous(const qmckl_context context) {
|
||||||
|
|
||||||
qmckl_context_struct* ctx;
|
qmckl_context_struct* ctx;
|
||||||
|
|
||||||
|
if (context == (qmckl_context) 0) {
|
||||||
|
return (qmckl_context) 0;
|
||||||
|
}
|
||||||
|
|
||||||
ctx = (qmckl_context_struct*) context;
|
ctx = (qmckl_context_struct*) context;
|
||||||
|
return (qmckl_context) ctx->prev;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
if (qmckl_context_previous(new_context) == (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_copy: Null pointer\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (qmckl_context_previous(new_context) != context) {
|
||||||
|
eprintf("qmckl_context_copy: Wrong pointer\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (qmckl_context_previous(context) != (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_copy: Expected null pointer (1)\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (qmckl_context_previous((qmckl_context) 0) != (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_copy: Expected null pointer (2)\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** =qmckl_context_destroy=
|
||||||
|
|
||||||
|
Destroys the current context, leaving the ancestors untouched.
|
||||||
|
- Succeeds if the current context is properly destroyed
|
||||||
|
- Fails otherwise
|
||||||
|
- Fails is the 0-valued context is given in argument
|
||||||
|
|
||||||
|
The context given in parameter is overwritten by the 0-valued
|
||||||
|
context, so a pointer is passed to the function.
|
||||||
|
|
||||||
|
*** Header
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
|
qmckl_exit_code qmckl_context_destroy(qmckl_context * context);
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Source
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.c
|
||||||
|
qmckl_exit_code qmckl_context_destroy(qmckl_context *context) {
|
||||||
|
|
||||||
|
qmckl_context_struct* ctx;
|
||||||
|
|
||||||
|
ctx = (qmckl_context_struct*) *context;
|
||||||
|
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return 0;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return 1;
|
*context = (qmckl_context) 0;
|
||||||
|
return QMCKL_SUCCESS;
|
||||||
}
|
}
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
if (new_context == (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_destroy: new_context is NULL\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (qmckl_context_destroy(&new_context) == QMCKL_FAILURE) {
|
||||||
|
eprintf("qmckl_context_destroy: Unable to destroy the new_context\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (new_context != (qmckl_context) 0) {
|
||||||
|
eprintf("qmckl_context_destroy: new_context should be NULL\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
if (qmckl_context_destroy((qmckl_context) 0) == QMCKL_SUCCESS) {
|
||||||
|
eprintf("qmckl_context_destroy: Failure expected with NULL pointer\n");
|
||||||
|
rc = QMCKL_FAILURE;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
* Precision
|
* Precision
|
||||||
|
|
||||||
The following functions set and get the expected required precision
|
The following functions set and get the expected required precision
|
||||||
@ -239,9 +386,16 @@ int qmckl_context_get_range(const qmckl_context context) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
* End of header
|
* End of files
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl_context.h
|
*** Header
|
||||||
|
#+BEGIN_SRC C :tangle qmckl_context.h
|
||||||
#endif
|
#endif
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Test
|
||||||
|
#+BEGIN_SRC C :tangle test_qmckl_context.c
|
||||||
|
return QMCKL_SUCCESS;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user