Index: /tags/V_Fev00/SophyaLib/BaseTools/Makefile
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/Makefile	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/Makefile	(revision 752)
@@ -0,0 +1,33 @@
+include ../Mgr/Makefile.h
+ 
+all: $(LIB)libSysTools.a
+clean:
+	rm -f $(OBJ)ctimer.o $(OBJ)ndatablock.o $(OBJ)pdlmgr.o $(OBJ)peidainit.o $(OBJ)periodic.o $(OBJ)pexceptions.o $(OBJ)ppersist.o $(OBJ)psighand.o $(OBJ)md5.o $(OBJ)timing.o
+	rm -f $(LIB)libSysTools.a
+$(LIB)libSysTools.a : $(OBJ)ctimer.o $(OBJ)md5.o $(OBJ)ndatablock.o $(OBJ)pdlmgr.o $(OBJ)peidainit.o $(OBJ)periodic.o $(OBJ)pexceptions.o $(OBJ)ppersist.o $(OBJ)psighand.o $(OBJ)timing.o
+	$(ARCXX) $(ARCXXFLAGS) $@ $?
+ifeq ($(CXX),cxx)
+	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS) -L$(LIB) -lSysTools -o $(OBJ)xx.x -Hf
+endif 
+ 
+$(OBJ)ctimer.o: ctimer.cc machdefs.h \
+ $(INC)pclassids.h ctimer.h
+$(OBJ)ndatablock.o: ndatablock.cc machdefs.h \
+ $(INC)pclassids.h pexceptions.h \
+ ndatablock.h anydataobj.h ppersist.h md5.h objfio.h piocmplx.h
+$(OBJ)pdlmgr.o: pdlmgr.cc pdlmgr.h machdefs.h \
+ $(INC)pclassids.h
+$(OBJ)peidainit.o: peidainit.cc machdefs.h \
+ $(INC)pclassids.h pexceptions.h ppersist.h \
+ md5.h peidainit.h ndatablock.h anydataobj.h sversion.h
+$(OBJ)periodic.o: periodic.cc machdefs.h \
+ $(INC)pclassids.h periodic.h
+$(OBJ)pexceptions.o: pexceptions.cc pexceptions.h machdefs.h \
+ $(INC)pclassids.h
+$(OBJ)ppersist.o: ppersist.cc machdefs.h \
+ $(INC)pclassids.h pexceptions.h peidainit.h \
+ ppersist.h md5.h
+$(OBJ)psighand.o: psighand.cc psighand.h machdefs.h \
+ $(INC)pclassids.h pexceptions.h
+$(OBJ)md5.o: md5.c md5.h
+$(OBJ)timing.o: timing.c
Index: /tags/V_Fev00/SophyaLib/BaseTools/anydataobj.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/anydataobj.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/anydataobj.h	(revision 752)
@@ -0,0 +1,20 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Ancetre commun de tous les objets pour rtti
+//                          R.Ansari          04/99
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+#ifndef ANYDATAOBJ_H_SEEN
+#define ANYDATAOBJ_H_SEEN
+
+#include "machdefs.h"
+
+namespace SOPHYA {
+
+class AnyDataObj {
+public:
+  AnyDataObj() { } 
+  virtual ~AnyDataObj() { }
+};
+
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/bithelp.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/bithelp.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/bithelp.h	(revision 752)
@@ -0,0 +1,41 @@
+/* bithelp.h  -  Some bit manipulation helpers
+ *	Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef G10_BITHELP_H
+#define G10_BITHELP_H
+
+
+/****************
+ * Rotate a 32 bit integer by n bytes
+ */
+#if defined(__GNUC__) && defined(__i386__)
+static inline uint_4
+rol( uint_4 x, int n)
+{
+	__asm__("roll %%cl,%0"
+		:"=r" (x)
+		:"0" (x),"c" (n));
+	return x;
+}
+#else
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#endif
+
+
+#endif /*G10_BITHELP_H*/
Index: /tags/V_Fev00/SophyaLib/BaseTools/complexios.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/complexios.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/complexios.h	(revision 752)
@@ -0,0 +1,18 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Gestion d impression des complex sur les streams
+//                         C.Magneville          04/99
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef COMPLEXIOS_H
+#define COMPLEXIOS_H
+
+#include "machdefs.h"
+#include <iostream.h>
+
+#if defined(NO_IOS_COMPLEX)
+template<class T> 
+inline ostream& operator << (ostream& os, const complex<T>& c)
+           {os<<"("<<c.real()<<","<<c.imag()<<")"; return os;}
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.c
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.c	(revision 752)
@@ -0,0 +1,415 @@
+/* md5.c - MD5 Message-Digest Algorithm
+ *	Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+ *
+ * according to the definition of MD5 in RFC 1321 from April 1992.
+ * NOTE: This is *not* the same file as the one from glibc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+/* heavily modified for GnuPG by <werner.koch@guug.de> */
+/* Modified by Eric.Aubourg@cea.fr for SOPHYA */
+
+/* Test values:
+ * ""                  D4 1D 8C D9 8F 00 B2 04  E9 80 09 98 EC F8 42 7E
+ * "a"                 0C C1 75 B9 C0 F1 B6 A8  31 C3 99 E2 69 77 26 61
+ * "abc                90 01 50 98 3C D2 4F B0  D6 96 3F 7D 28 E1 7F 72
+ * "message digest"    F9 6B 69 7D 7C B7 93 8D  52 5A 2F 31 AA F1 61 D0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "machdefs.h"
+#include "bithelp.h" 
+#include "gnumd5.h"
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+
+#if SWAP==0
+#define BIG_ENDIAN_HOST 1
+#endif
+
+
+//typedef struct {
+//    uint_4 A,B,C,D;	  /* chaining variables */
+//    uint_4  nblocks;
+//    uint_1 buf[64];
+//    int  count;
+//} MD5_CONTEXT;
+
+
+void
+md5_init( MD5_CONTEXT *ctx )
+{
+    ctx->A = 0x67452301;
+    ctx->B = 0xefcdab89;
+    ctx->C = 0x98badcfe;
+    ctx->D = 0x10325476;
+
+    ctx->nblocks = 0;
+    ctx->count = 0;
+}
+
+
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+
+/****************
+ * transform n*64 bytes
+ */
+static void
+/*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/
+transform( MD5_CONTEXT *ctx, uint_1 *data )
+{
+    uint_4 correct_words[16];
+    uint_4 A = ctx->A;
+    uint_4 B = ctx->B;
+    uint_4 C = ctx->C;
+    uint_4 D = ctx->D;
+    uint_4 *cwp = correct_words;
+
+#ifdef BIG_ENDIAN_HOST
+    { int i;
+      uint_1 *p2, *p1;
+      for(i=0, p1=data, p2=(uint_1*)correct_words; i < 16; i++, p2 += 4 ) {
+	p2[3] = *p1++;
+	p2[2] = *p1++;
+	p2[1] = *p1++;
+	p2[0] = *p1++;
+      }
+    }
+#else
+    memcpy( correct_words, data, 64 );
+#endif
+
+
+#define OP(a, b, c, d, s, T)					    \
+  do								    \
+    {								    \
+      a += FF (b, c, d) + (*cwp++) + T; 	    \
+      a = rol(a, s);						    \
+      a += b;							    \
+    }								    \
+  while (0)
+
+    /* Before we start, one word about the strange constants.
+       They are defined in RFC 1321 as
+
+       T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+     */
+
+    /* Round 1.  */
+    OP (A, B, C, D,  7, 0xd76aa478);
+    OP (D, A, B, C, 12, 0xe8c7b756);
+    OP (C, D, A, B, 17, 0x242070db);
+    OP (B, C, D, A, 22, 0xc1bdceee);
+    OP (A, B, C, D,  7, 0xf57c0faf);
+    OP (D, A, B, C, 12, 0x4787c62a);
+    OP (C, D, A, B, 17, 0xa8304613);
+    OP (B, C, D, A, 22, 0xfd469501);
+    OP (A, B, C, D,  7, 0x698098d8);
+    OP (D, A, B, C, 12, 0x8b44f7af);
+    OP (C, D, A, B, 17, 0xffff5bb1);
+    OP (B, C, D, A, 22, 0x895cd7be);
+    OP (A, B, C, D,  7, 0x6b901122);
+    OP (D, A, B, C, 12, 0xfd987193);
+    OP (C, D, A, B, 17, 0xa679438e);
+    OP (B, C, D, A, 22, 0x49b40821);
+
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)  \
+    do								      \
+      { 							      \
+	a += f (b, c, d) + correct_words[k] + T;		      \
+	a = rol(a, s);						      \
+	a += b; 						      \
+      } 							      \
+    while (0)
+
+    /* Round 2.  */
+    OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+    OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+    OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+    OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+    OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+    OP (FG, D, A, B, C, 10,  9, 0x02441453);
+    OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+    OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+    OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+    OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+    OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+    OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+    OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+    OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+    OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+    OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+    /* Round 3.  */
+    OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+    OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+    OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+    OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+    OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+    OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+    OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+    OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+    OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+    OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+    OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+    OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+    OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+    OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+    OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+    OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+    /* Round 4.  */
+    OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+    OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+    OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+    OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+    OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+    OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+    OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+    OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+    OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+    OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+    OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+    OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+    OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+    OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+    OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+    OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+    /* Put checksum in context given as argument.  */
+    ctx->A += A;
+    ctx->B += B;
+    ctx->C += C;
+    ctx->D += D;
+}
+
+
+
+/* The routine updates the message-digest context to
+ * account for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+ */
+void
+md5_write( MD5_CONTEXT *hd, uint_1 *inbuf, size_t inlen)
+{
+    if( hd->count == 64 ) { /* flush the buffer */
+	transform( hd, hd->buf );
+	hd->count = 0;
+	hd->nblocks++;
+    }
+    if( !inbuf )
+	return;
+    if( hd->count ) {
+	for( ; inlen && hd->count < 64; inlen-- )
+	    hd->buf[hd->count++] = *inbuf++;
+	md5_write( hd, NULL, 0 );
+	if( !inlen )
+	    return;
+    }
+
+    while( inlen >= 64 ) {
+	transform( hd, inbuf );
+	hd->count = 0;
+	hd->nblocks++;
+	inlen -= 64;
+	inbuf += 64;
+    }
+    for( ; inlen && hd->count < 64; inlen-- )
+	hd->buf[hd->count++] = *inbuf++;
+
+}
+
+
+
+/* The routine final terminates the message-digest computation and
+ * ends with the desired message digest in mdContext->digest[0...15].
+ * The handle is prepared for a new MD5 cycle.
+ * Returns 16 bytes representing the digest.
+ */
+
+void
+md5_final( MD5_CONTEXT *hd )
+{
+    uint_4 t, msb, lsb;
+    uint_1 *p;
+
+    md5_write(hd, NULL, 0); /* flush */;
+
+    msb = 0;
+    t = hd->nblocks;
+    if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
+	msb++;
+    msb += t >> 26;
+    t = lsb;
+    if( (lsb = t + hd->count) < t ) /* add the count */
+	msb++;
+    t = lsb;
+    if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
+	msb++;
+    msb += t >> 29;
+
+    if( hd->count < 56 ) { /* enough room */
+	hd->buf[hd->count++] = 0x80; /* pad */
+	while( hd->count < 56 )
+	    hd->buf[hd->count++] = 0;  /* pad */
+    }
+    else { /* need one extra block */
+	hd->buf[hd->count++] = 0x80; /* pad character */
+	while( hd->count < 64 )
+	    hd->buf[hd->count++] = 0;
+	md5_write(hd, NULL, 0);  /* flush */;
+	memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+    }
+    /* append the 64 bit count */
+    hd->buf[56] = lsb	   ;
+    hd->buf[57] = lsb >>  8;
+    hd->buf[58] = lsb >> 16;
+    hd->buf[59] = lsb >> 24;
+    hd->buf[60] = msb	   ;
+    hd->buf[61] = msb >>  8;
+    hd->buf[62] = msb >> 16;
+    hd->buf[63] = msb >> 24;
+    transform( hd, hd->buf );
+
+    p = hd->buf;
+#ifdef BIG_ENDIAN_HOST
+#define X(a) do { *p++ = hd->##a	  ; *p++ = hd->##a >> 8;      \
+		      *p++ = hd->##a >> 16; *p++ = hd->##a >> 24; } while(0)
+#else /* little endian */
+    /*#define X(a) do { *(uint_4*)p = hd->##a ; p += 4; } while(0)*/
+    /* Unixware's cpp doesn't like the above construct so we do it his way:
+     * (reported by Allan Clark) */
+#define X(a) do { *(uint_4*)p = (*hd).a ; p += 4; } while(0)
+#endif
+    X(A);
+    X(B);
+    X(C);
+    X(D);
+#undef X
+
+}
+
+static uint_1 *
+md5_read( MD5_CONTEXT *hd )
+{
+    return hd->buf;
+}
+
+/****************
+ * Return some information about the algorithm.  We need algo here to
+ * distinguish different flavors of the algorithm.
+ * Returns: A pointer to string describing the algorithm or NULL if
+ *	    the ALGO is invalid.
+ */
+static const char *
+md5_get_info( int algo, size_t *contextsize,
+	       uint_1 **r_asnoid, int *r_asnlen, int *r_mdlen,
+	       void (**r_init)( void *c ),
+	       void (**r_write)( void *c, uint_1 *buf, size_t nbytes ),
+	       void (**r_final)( void *c ),
+	       uint_1 *(**r_read)( void *c )
+	     )
+{
+    static uint_1 asn[18] = /* Object ID is 1.2.840.113549.2.5 */
+		    { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
+		      0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
+
+    if( algo != 1 )
+	return NULL;
+
+    *contextsize = sizeof(MD5_CONTEXT);
+    *r_asnoid = asn;
+    *r_asnlen = DIM(asn);
+    *r_mdlen = 16;
+    *r_init  = (void (*)(void *))md5_init;
+    *r_write = (void (*)(void *, uint_1*, size_t))md5_write;
+    *r_final = (void (*)(void *))md5_final;
+    *r_read  = (uint_1 *(*)(void *))md5_read;
+
+    return "MD5";
+}
+
+
+#ifndef IS_MODULE
+static
+#endif
+const char * const gnupgext_version = "MD5 ($Revision: 1.2 $)";
+
+static struct {
+    int class;
+    int version;
+    int  value;
+    void (*func)(void);
+} func_table[] = {
+    { 10, 1, 0, (void(*)(void))md5_get_info },
+    { 11, 1, 1 },
+};
+
+
+#ifndef IS_MODULE
+static
+#endif
+void *
+gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
+{
+    void *ret;
+    int i = *sequence;
+
+    do {
+	if( i >= DIM(func_table) || i < 0 )
+	    return NULL;
+	*class = func_table[i].class;
+	*vers  = func_table[i].version;
+	switch( *class ) {
+	  case 11: case 21: case 31: ret = &func_table[i].value; break;
+	  default:		     ret = func_table[i].func; break;
+	}
+	i++;
+    } while( what && what != *class );
+
+    *sequence = i;
+    return ret;
+}
+
+
+
+/*
+#ifndef IS_MODULE
+void
+md5_constructor(void)
+{
+    register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
+}
+#endif
+*/
+
+
+/* end of file */
Index: /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/gnumd5.h	(revision 752)
@@ -0,0 +1,34 @@
+#ifndef GNUMD5_H
+#define GNUMD5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    uint_4 A,B,C,D;	  /* chaining variables */
+    uint_4  nblocks;
+    uint_1 buf[64];
+    int  count;
+} MD5_CONTEXT;
+
+
+void
+md5_init( MD5_CONTEXT *ctx );
+
+void
+md5_write( MD5_CONTEXT *hd, uint_1 *inbuf, size_t inlen);
+
+void
+md5_final( MD5_CONTEXT *hd );
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/hashtable.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/hashtable.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/hashtable.h	(revision 752)
@@ -0,0 +1,195 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+// This is a hash table. Some implementations of the STL have one, like the
+// Modena Standard Library.
+
+#ifndef HASHTABLE_H_SEEN
+#define HASHTABLE_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+
+namespace SOPHYA {
+
+template <class T, class K>
+struct HashtableEntry {
+  uint_4         hash;
+  K              key;
+  T              value;
+  HashtableEntry<T,K> *next;
+};
+
+
+template <class T, class K>
+class Hashtable {
+public:
+  typedef uint_4 (*HashFunction)(K const& key);
+
+  Hashtable(uint_4 initialCapacity, float loadFactor) {
+    Init(initialCapacity,loadFactor);
+  }
+  
+  Hashtable(int initialCapacity) {
+    Init(initialCapacity, 0.75);
+  }
+  
+  Hashtable() {
+    Init(101, 0.75);
+  }
+
+  ~Hashtable() {
+    for (int i = count ; i-- > 0 ;) {
+      for (HashtableEntry<T,K>* e = table[i] ; e != NULL ; ) {
+	HashtableEntry<T,K>* ee = e->next;
+	delete e;
+	e = ee;
+      }
+    }
+    delete[] table;
+  }
+
+  void setHash(HashFunction f) {
+    hf = f;
+  }
+
+  uint_4 size() {
+    return count;
+  }
+
+  bool contains(T const& value) {
+    for (int i = count ; i-- > 0 ;) {
+      for (HashtableEntry<T,K>* e = table[i] ; e != NULL ; e = e->next) {
+	if (e->value == value) {
+	  return true;
+	}
+      }
+    }
+    return false;
+  }
+  
+  bool containsKey(K const& key) {
+    uint_4 hash = hf(key);
+    uint_4 index = (hash & 0x7FFFFFFF) % length;
+    for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
+      if ((e->hash == hash) && e->key == key) {
+	return true;
+      }
+    }
+    return false;
+  }
+  
+  T const& get(K const& key) {
+    uint_4 hash = hf(key);
+    uint_4 index = (hash & 0x7FFFFFFF) % length;
+    for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
+      if ((e->hash == hash) && e->key == key) {
+	return e->value;
+      }
+    }
+    throw(NotFoundExc("Hashtable::get"));
+  }
+  
+  
+  void put(K const& key, T const& value) {
+    // Makes sure the key is not already in the hashtable.
+    uint_4 hash = hf(key);
+    uint_4 index = (hash & 0x7FFFFFFF) % length;
+    for (HashtableEntry<T,K>* e = table[index] ; e != NULL ; e = e->next) {
+      if ((e->hash == hash) && e-> key == key) {
+	//T const& old = e.value;
+	e->value = value;
+	//return old;
+      }
+    }
+    
+    if (count >= threshold) {
+      // Rehash the table if the threshold is exceeded
+      rehash();
+      return;// put(key, value);
+    } 
+
+    // Creates the new entry.
+    HashtableEntry<T,K>* e = new HashtableEntry<T,K>;
+    e->hash = hash;
+    e->key = key;
+    e->value = value;
+    e->next = table[index];
+    table[index] = e;
+    count++;
+    //return null;
+  }
+  
+  
+  void remove(K const& key) {
+    uint_4 hash = hf(key);
+    uint_4 index = (hash & 0x7FFFFFFF) % tab.length;
+    for (HashtableEntry<T,K>* e = table[index], prev = null ; e != null ; prev = e, e = e->next) {
+      if ((e>hash == hash) && e>key == key) {
+	if (prev != NULL) {
+	  prev->next = e->next;
+	} else {
+	  table[index] = e->next;
+	}
+	count--;
+	//return e.value;
+      }
+    }
+    //return null;
+  }
+  
+private:
+  
+  void Init(uint_4 initialCapacity, float loadFactor) {
+    if ((initialCapacity == 0) || (loadFactor <= 0.0)) {
+      throw ParmError("Hashtable::Hashtable");
+    }
+    this->loadFactor = loadFactor;
+    this->length = initialCapacity;
+    this->count = 0;
+    table = new (HashtableEntry<T,K>*[initialCapacity]);
+    for (int i=0; i<length; i++) table[i] = NULL;
+    threshold = (uint_4)(initialCapacity * loadFactor);
+    hf = defaultHash;
+  }
+
+  static uint_4 defaultHash(K const& key) {
+    if (sizeof(K) <= sizeof(void*))
+      return (uint_4)(uint_8)(key);
+    else
+      return (uint_4)(uint_8)(&key);
+  }
+
+  void rehash() {
+    uint_4 oldCapacity = length;
+    HashtableEntry<T,K>** oldTable = table;
+
+    uint_4 newCapacity = oldCapacity * 2 + 1;
+    HashtableEntry<T,K>** newTable = new (HashtableEntry<T,K>*[newCapacity]);
+
+    threshold = (int)(newCapacity * loadFactor);
+    table = newTable;
+    length = newCapacity;
+
+    for (int i = oldCapacity ; i-- > 0 ;) {
+      for (HashtableEntry<T,K>* old = oldTable[i] ; old != NULL ; ) {
+	HashtableEntry<T,K>* e = old;
+	old = old->next;
+	
+	int index = (e->hash & 0x7FFFFFFF) % newCapacity;
+	e->next = newTable[index];
+	newTable[index] = e;
+      }
+    }
+    delete[] oldTable;
+  }
+  
+  HashtableEntry<T,K>  **table;
+  uint_4         length;
+  uint_4         count;
+  uint_4         threshold;
+  float          loadFactor;
+  HashFunction   hf;
+};
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/history_eros
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/history_eros	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/history_eros	(revision 752)
@@ -0,0 +1,55 @@
+SysTools from LibsUtil
+machdefs.h from machine.h defs.h
+-----------> defs.h
+   Repository revision:	1.21	/projects/Eros/CVSEros/LibsUtil/defs.h,v
+   MAJ                  1.24
+-----------> machine.h
+   Repository revision:	1.9	/projects/Eros/CVSEros/LibsUtil/machine.h,v
+   MAJ                  1.12
+-----------> timing.c
+   Repository revision:	1.2	/projects/Eros/CVSEros/LibsUtil/timing.c,v
+   OK                   1.2
+-----------> timing.h
+   Repository revision:	1.2	/projects/Eros/CVSEros/LibsUtil/timing.h,v
+   OK                   1.2
+SysTools from Outils++
+-----------> ctimer.cc
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Outils/ctimer.cc,v
+   OK                   1.11
+-----------> ctimer.h
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/ctimer.h,v
+   OK                   1.11
+-----------> exceptions.cc
+   Repository revision:	1.7	/projects/Eros/CVSEros/CodeCxx/Outils/exceptions.cc,v
+   OK                   1.8     modifs pour CCPN AIX pas mis
+-----------> exceptions.h
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/exceptions.h,v
+   OK                   1.8
+-----------> pdlmgr.cc
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/pdlmgr.cc,v
+   MAJ                  1.6
+-----------> pdlmgr.h
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/pdlmgr.h,v
+   MAJ                  1.4
+-----------> peidainit.h
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Outils/peidainit.h,v
+-----------> periodic.cc
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/periodic.cc,v
+-----------> periodic.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/periodic.h,v
+   MAJ                  1.5
+-----------> perrors.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/perrors.h,v
+   OK                   1.5     Attention  COMPATIBLE_ASSERT pas mis
+-----------> ppersist.cc
+   Repository revision:	1.40	/projects/Eros/CVSEros/CodeCxx/Outils/ppersist.cc,v
+   MAJ - OK             1.43    Attention aux asserts
+-----------> ppersist.h
+   Repository revision:	1.23	/projects/Eros/CVSEros/CodeCxx/Outils/ppersist.h,v
+   MAJ                  1.25
+-----------> psighand.cc
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/psighand.cc,v
+   MAJ                  1.3
+-----------> psighand.h
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Outils/psighand.h,v
+   MAJ                  1.2
Index: /tags/V_Fev00/SophyaLib/BaseTools/machdefs.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/machdefs.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/machdefs.h	(revision 752)
@@ -0,0 +1,354 @@
+#ifndef MACHDEFS_SEEN
+#define MACHDEFS_SEEN
+
+/***********************************************************************/
+/* Find hardware, OS and compiler combination                          */
+/***********************************************************************/
+
+#if defined(__alpha) || defined(__alpha__) || defined(OSF1) || defined(DECALPHA)
+#define MACH_ALPHA
+#define OS_OSF1
+#endif
+
+#if defined(_AIX) || defined(AIX)
+#define MACH_IBMRS
+#define OS_AIX
+#endif
+
+#if defined(__hpux__) || defined(HPUX)
+#define MACH_HP
+#define OS_HPUX
+#endif
+
+#ifdef __MWERKS__
+#define MACH_POWERMAC
+#define OS_MACOS
+#endif
+
+#if defined(SunOS)  || defined ( sun )
+#define MACH_SUN
+#define OS_SOLARIS
+#endif
+
+#ifdef IRIX64
+#define MACH_SGI
+#define OS_IRIX64
+#endif
+
+#if defined(Linux)  || defined(linux)
+#define MACH_INTEL
+#define OS_LINUX
+#endif
+
+
+/***********************************************************************/
+/* Hardware/OS dependent stuff                                         */
+/***********************************************************************/
+
+#if defined(OS_OSF1)
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 1
+#define  SWAPDEFAUT 1
+
+#elif  defined(OS_HPUX)
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4 ;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 0
+#define  SWAPDEFAUT   0
+
+
+#elif  defined( OS_AIX )
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 0
+#define  SWAPDEFAUT   0
+
+/* Check for solaris on intel... */
+#elif  defined( OS_SOLARIS ) && defined( MACH_SUN )
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 0
+#define  SWAPDEFAUT   0
+
+#elif  defined( OS_IRIX64 )
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 0
+#define  SWAPDEFAUT   0
+
+/* Check linux on other machines than Intel */
+#elif defined(OS_LINUX)
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef int int_4;
+  typedef unsigned int uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#ifdef powerpc
+#define SWAP 0
+#define SWAPDEFAUT 0
+#else
+#define  SWAP 1
+#define  SWAPDEFAUT   1
+#endif
+
+#elif defined(OS_MACOS)
+
+  typedef signed char int_1;
+  typedef unsigned char uint_1;
+  typedef long int_4;
+  typedef unsigned long uint_4;
+  typedef short int_2;
+  typedef unsigned short uint_2;
+  typedef float r_4;
+  typedef double r_8;
+  typedef long long int_8;
+  typedef unsigned long long uint_8;
+
+#define  SWAP 0
+#define  SWAPDEFAUT   0
+
+#else
+#error  Undefined Machine/OS type in machdefs.h
+#endif
+
+
+
+#if SWAP==1
+#define IS_BIG_ENDIAN 0
+#else
+#define IS_BIG_ENDIAN 1
+#endif
+
+
+/***********************************************************************/
+/* Find Compiler                                                       */
+/***********************************************************************/
+
+/*    __MWERKS__   : Metrowerks Codewarrior (>= PRO 4)                 */
+/*    __DECCXX     : DEC CXX, version >= 6 is required                 */
+/*    __GNUG__     : GNU C++ 2.8.1, egcs ??                            */
+/*    __aCC__      : aCC on HP                                         */
+/*    __KCC__      : KCC, version >= 3.3 is required                   */
+/*    __SGICC__    : SGI (IRIX64) CC compiler                          */
+
+/***********************************************************************/
+/* Compiler-specific stuff                                             */
+/***********************************************************************/
+
+/* Some features will be *required* for Planck. Which ones ?               */
+  
+/*   ANSI_TEMPLATES        : use ANSI syntax for explicit templates        */
+/*   GNUG_TEMPLATES        : use GNU syntax for explicit templates         */
+/*   PRAGMA_TEMPLATES      : use pragma template, a la cxx                 */
+/*   COMPILER_EXCEPTIONS   : knows about exceptions  --- required ?        */ 
+/*   STREAMPOS_IS_CLASS    : streampos is a real class                     */
+/*   ITER_TAG              : use iter_tag for iterator qualifiers in STL   */
+/*   NO_STRSTREAM          : does not have strstream                       */
+/*   HAS_EXPLICIT          : knows about explicit keyword - constructors   */
+/*   HAS_IOS_BIN                                                           */
+/*   HAS_IOS_NOCREATE                                                      */
+/*   HAS_VEC_NEW           : operator new[]                                */
+/*   CC_HAS_RTTI_SUPPORT     has Run Time Type Identification support      */
+/*   ANSI_IO               : rdbuf()->pubseekoff rather than seekg         */
+/*   HAS_STR_NPOS          : has string::npos and not a global NPOS        */
+/*   NO_IOS_COMPLEX        : does not have operator << defined for complex */
+
+
+/* The following is true for most compilers */
+
+#ifndef HAS_VEC_NEW
+#define HAS_VEC_NEW
+#endif
+
+#ifndef COMPILER_EXCEPTIONS
+#define COMPILER_EXCEPTIONS
+#endif
+
+#ifndef  CC_HAS_RTTI_SUPPORT 
+#define  CC_HAS_RTTI_SUPPORT 
+#endif
+
+/* now the specific things */
+
+#ifdef __MWERKS__
+#define ANSI_TEMPLATES
+#undef  HAS_VEC_NEW
+#define NO_STRSTREAM
+//#define STREAMPOS_IS_CLASS
+#define ITER_TAG
+#define HAS_IOS_BIN 
+#define HAS_IOS_NOCREATE 
+#define HAS_STR_NPOS
+#endif
+
+#ifdef __GNUG__
+#define ANSI_TEMPLATES
+// #define GNU_TEMPLATES
+#define HAS_STR_NPOS
+#define HAS_EXPLICIT
+#define HAS_IOS_BIN
+#define HAS_IOS_NOCREATE
+#endif
+
+#ifdef __DECCXX
+#define HAS_STR_NPOS
+#define ITER_TAG
+#define __CXX_PRAGMA_TEMPLATES__
+#define PRAGMA_TEMPLATES
+#endif
+
+#if defined (__aCC__)  
+#ifndef ANSI_TEMPLATES
+#define ANSI_TEMPLATES
+#endif
+#endif
+
+#if defined(__KCC__)
+/* KCC V 3.2 ne compile pas  i/ostream s ; long p = s.tellg();  OK en  V 3.3 */
+#define STREAMPOS_IS_CLASS
+#define HAS_STR_NPOS
+#ifndef ANSI_TEMPLATES
+#define ANSI_TEMPLATES
+#endif
+/* Standard C++ library classes are in the namespace std  */
+#ifdef __cplusplus
+namespace std { }
+using namespace std;
+#endif
+#endif
+
+#if defined(__SGICC__)
+/* Standard C++ library classes are in the namespace std  */
+#define HAS_STR_NPOS
+#ifndef ANSI_TEMPLATES
+#define ANSI_TEMPLATES
+#endif
+#ifdef __cplusplus
+namespace std { }
+using namespace std;
+#endif
+#endif
+
+/* Get things has homogeneous as possible between compilers */
+
+#ifdef HAS_STR_NPOS
+#define NPOS string::npos
+#else
+#define NPOS (size_t)-1
+#endif
+
+#ifndef __GNUG__
+#define __PRETTY_FUNCTION__ __FILE__ " __LINE__ "
+#ifndef __FUNCTION__
+#define __FUNCTION__ __FILE__ " __LINE__ "
+#endif
+#ifndef __KCC__
+#define __attribute__(_x_)
+#endif
+#endif
+
+#ifndef HAS_EXPLICIT
+#define explicit
+#endif
+
+#ifdef HAS_IOS_BIN
+#define IOS_BIN ios::binary
+#else
+#define IOS_BIN 0
+#endif
+
+#ifdef ANSI_IO
+#define seekg(p_, m_) rdbuf()->pubseekoff(p_,m_)
+#define seekp(p_, m_) rdbuf()->pubseekoff(p_,m_)
+#endif
+
+#ifdef __MWERKS__
+//#define hypot(_x_,_y_) sqrt((_x_)*(_x_) + (_y_)*(_y_))
+#define random() (rand()*65538.0 + rand()*2. + rand())
+#define srandom srand
+#define initstate(seed, tab, n) srand(seed)
+#define nice(_x)
+
+#ifdef __cplusplus
+#include <string.h>
+#include <string>
+inline bool operator< (string const& s1, string const& s2)
+{ return (strcmp(s1.c_str(), s2.c_str()) < 0); }
+#endif
+#endif
+
+
+/********************************************************/
+/* Outil d'impressions pour debug */
+#define PR(_data_)  {cout<<" "<<#_data_<<" "<<_data_;}
+#define CR {cout<<"\n"<<flush;}
+/* ********************************************************/
+
+/* Compatibilite, avant de migrer tout le code en "PLANCK" */
+
+#ifdef __cplusplus
+namespace SOPHYA {}
+using namespace SOPHYA;
+#define EXPLICIT explicit
+#include "pclassids.h"
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.cc	(revision 752)
@@ -0,0 +1,751 @@
+// Gestion de block de donnees avec partage de references
+// malheureusement tres mal concu...  C.Magneville 04/99
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <complex>
+#include "pexceptions.h"
+#include "ndatablock.h"
+#include "objfio.h"
+
+// define DEBUG_NDATABLOCK
+
+#ifdef DEBUG_NDATABLOCK
+  static size_t NallocData = 0;
+  static size_t NallocSRef = 0;
+#endif
+
+////////////////////////////////////////////////////////////////
+//************ Createur, Destructeur
+
+template <class T>
+NDataBlock<T>::NDataBlock(size_t n)
+// Createur d'une structure de "n" donnees
+: mSz(0), mSRef(NULL), mIsTemp(false)
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::NDataBlock("<<this<<",n="<<n<<")"<<endl;
+#endif
+
+Alloc(n);
+}
+
+template <class T>
+NDataBlock<T>::NDataBlock(size_t n, T* data, Bridge* br)
+// Createur d'une structure de "n" donnees, avec donnees preallouees.
+// Attention createur TRES DANGEREUX (Voir explications dans Alloc()).
+: mSz(0), mSRef(NULL), mIsTemp(false)
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::NDataBlock("<<this
+    <<",data="<<data<<",br="<<br<<")"<<endl;
+#endif
+
+Alloc(n,data,br);
+}
+
+template <class T>
+NDataBlock<T>::NDataBlock()
+// Createur par default
+: mSz(0), mSRef(NULL), mIsTemp(false)
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::NDataBlock("<<this<<") default"<<endl;
+#endif
+}
+
+template <class T>
+NDataBlock<T>::NDataBlock(const NDataBlock<T>& a)
+// Createur par copie: partage les donnees si "a" temporaire, clone sinon.
+: mSz(0), mSRef(NULL), mIsTemp(false)
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<")"<<endl;
+#endif
+
+CloneOrShare(a);
+}
+
+template <class T>
+NDataBlock<T>::NDataBlock(const NDataBlock<T>& a,bool share)
+// Createur avec choix de partager ou non selon "share"
+: mSz(0), mSRef(NULL), mIsTemp(false)
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<",sh=<<"<<share<<")"<<endl;
+#endif
+
+if(share) Share(a); else Clone(a);
+}
+
+template <class T>
+NDataBlock<T>::~NDataBlock()
+// Destructeur
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::~NDataBlock("<<this<<")"<<endl;
+#endif
+
+Delete();
+}
+
+////////////////////////////////////////////////////////////////
+//************ Gestion de donnees
+
+template <class T>
+void NDataBlock<T>::Alloc(size_t n,T* data,Bridge* br)
+// Allocation d'un NOUVEL espace de stoquage de "n" donnees
+// Si data==NULL : allocation de l'espace memoire (remplit de zeros)
+//    data!=NULL : partage des donnees avec l'adresse data
+// Si br==NULL   : les donnees nous appartiennent
+//    br!=NULL   : les donnees ne nous appartiennent pas (ex: Blitz)
+//
+// Exemple: on veut connecter a un tableau de T*
+// > float *x = new float[5]; ... remplissage de x[] ...;
+// 1- On veut que NDataBlock NE DESALLOUE PAS le tableau "x[]"
+//    a- Premiere solution
+//       > NDataBlock A(5,x,new Bridge);
+//       ......
+//       > delete [] x;
+//          - Il faut deleter x[] explicitement.
+//          - Le destructeur de "A" ne detruit pas x[].
+//          ATTENTION: Une fois x[] detruit, "A" ne peut
+//                     plus acceder les donnees!
+//          - Bridge est detruit par le destructeur de "A"
+//    b- Autre solution:
+//       > NDataBlock A(5); A.FillFrom(5,x);
+//       > delete [] x;
+//       ......
+//          - Il faut deleter x[] explicitement.
+//          - "A" possede une copie en local de x[].
+//          - Le destructeur de "A" ne detruit pas x[] mais la copie locale.
+// 2- On veut que NDataBlock desalloue le tableau
+//       > NDataBlock A(5,x);
+//          - Ne Pas Faire "delete [] x;"
+//          - "A" partage les donnees avec x[].
+//          - Le destructeur de "A" detruit x[].
+//
+// --- REMARQUE SUR LE DANGER DE CERTAINES SITUATIONS (CMV):
+// 1-/ x = new float[n1]; NDataBlock A(n2,x);
+//     1er danger: si n2>n1 depassement de tableaux (core dump)
+//     2sd danger: celui qui alloue x[] ne doit pas faire le "delete"
+//                 en desaccord avec toutes les regles de bonne conduite.
+// 2-/ float x[5]={1,2,3,4,5}; {NDataBlock A(n2,&x[0]);} cout<<x[2];
+//     Ici, a la sortie du bloc {}, le destructeur de "A" va detruire
+//     l'adresse de &x[0]: je n'ose imaginer que ca se fasse sans probleme
+//     et de toute facon, cout<<x[2]; va surement faire des etincelles.
+// 3-/ x = new float[n1]; NDataBlock A(n2,x,new Bridge);
+//     1er danger: si n2>n1 depassement de tableaux (core dump)
+//     2sd danger: si la methode bridgee (blitz?) detruit x[]
+//                 "A" n'a plus de donnees connectees!
+// --- CONCLUSION
+// Cette classe est franchement merdique.
+// - On peut accepter la prise de risque liee a NDataBlock(n2,x,new Bridge);
+//   car je ne vois pas comment on pourrait faire autrement pour connecter
+//   un tableau de type blitz par exemple.
+// - Par contre le createur NDataBlock(n2,x); doit etre interdit
+//   dans sa forme actelle car trop dangereux et il me semble inutile.
+// - Dans cette nouvelle optique:
+//   NDataBlock(n2,x,new Bridge) et NDataBlock(n2,x) disparaissent
+//   On remplace par NDataBlock(n2,x) {Alloc(n2,x,new Bridge);}
+//      qui force le Bridge dans tout les cas puisque NDataBlock
+//      ne possede pas les donnees.
+//   Mais puis-je encore le faire vu que NDataBlock est a la base
+//   de TVector,TMatrix et qu'il faut donc reprendre tout le code DPC
+// - Quoiqu'il arrive Alloc est une methode privee et peut donc rester
+//   sous sa forme actuelle.
+//            
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::Alloc("<<this<<","
+    <<n<<","<<data<<","<<br<<") mSz="<<mSz
+    <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
+#endif
+
+if(br && !data)
+  throw(NullPtrError("NDataBlock::Alloc br!=NULL && data==NULL\n"));
+if(n==0) throw(SzMismatchError("NDataBlock::Alloc n==0\n"));
+if(mSRef) Delete();
+mSz = n;
+mSRef = new NDREF;
+mSRef->nref = 1;
+if(data) mSRef->data = data;
+else {mSRef->data = new T[n]; memset(mSRef->data,0,n*sizeof(T));}
+mSRef->bridge = br;
+
+#ifdef DEBUG_NDATABLOCK
+// Meme dans le cas data!=0 et br==0 (connexion d'un tableau
+// avec destruction geree par ~NDataBlock (cas 2-) on compte
+// comme si on avait fait une allocation du tableau (ce qui a ete
+// fait au niveau du dessus!).
+if(!br) NallocData++; NallocSRef++;
+cout<<"...?_NDataBlock::Alloc mSz="<<mSz<<" mSRef="<<mSRef
+    <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
+    <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp
+    <<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
+#endif
+}
+
+template <class T>
+void NDataBlock<T>::Clone(const NDataBlock<T>& a)
+// Clone: copie de donnees a partir de "a"
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::Clone("<<this<<","<<&a<<") a.(mSz="
+    <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
+    <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
+#endif
+
+if(&a==NULL) throw(NullPtrError("NDataBlock::Clone  &a==NULL\n"));
+if(!a.mSRef || a.mSz==0) throw(SzMismatchError("NDataBlock::Clone a.mSz==0\n"));
+Alloc(a.mSz);
+memcpy(Data(),a.Data(),mSz*sizeof(T));
+}
+
+template <class T>
+void NDataBlock<T>::CloneOrShare(const NDataBlock<T>& a)
+// CloneOrShare: Share si "a" temporaire, Clone sinon.
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::CloneOrShare("<<this<<","<<&a<<")"<<endl;
+#endif
+
+if(&a==NULL) throw(NullPtrError("NDataBlock::CloneOrShare  &a==NULL\n"));
+if(a.IsTemp()) Share(a); else Clone(a);
+}
+
+template <class T>
+void NDataBlock<T>::Share(const NDataBlock<T>& a)
+// Share: Partage les donnees avec "a"
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::Share("<<this<<","<<&a<<")";
+if(&a!=NULL) cout<<" a.(mSz="<<a.mSz<<" mSRef="<<a.mSRef
+                 <<" IsTemp="<<a.IsTemp()<<")";
+cout<<", mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
+#endif
+
+if(&a==NULL) throw(NullPtrError("NDataBlock::Share  &a==NULL\n"));
+if(!a.mSRef || a.mSz==0) throw(NullPtrError("NDataBlock::Share a.mSz=0\n"));
+if(mSRef) Delete();
+mSz = a.mSz; mSRef = a.mSRef; mSRef->nref++;
+
+#ifdef DEBUG_NDATABLOCK
+cout<<"...?_NDataBlock::Share mSz="<<mSz<<" mSRef="<<mSRef
+    <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
+    <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp<<endl;
+#endif
+}
+
+template <class T>
+void NDataBlock<T>::Delete(void)
+// Pour detruire les pointeurs en tenant compte des references
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::Delete("<<this<<") mSz="<<mSz
+    <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp;
+if(mSRef)
+  cout<<" mSRef->nref="<<mSRef->nref<<" mSRef->data="
+      <<mSRef->data<<" mSRef->bridge="<<mSRef->bridge;
+cout<<endl;
+#endif
+
+if(mSRef==NULL) return;
+mSRef->nref--;
+if(mSRef->nref != 0) {
+
+#ifdef DEBUG_NDATABLOCK
+  cout<<"...?_NDataBlock::Delete() pas de desallocation il reste nref="
+      <<mSRef->nref<<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
+#endif
+
+  mSz = 0; mSRef=NULL;
+  return;
+}
+
+#ifdef DEBUG_NDATABLOCK
+if(!mSRef->bridge) NallocData--; NallocSRef--;
+cout<<"...?_NDataBlock::Delete() desallocation complete il reste nref="
+    <<mSRef->nref<<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
+#endif
+
+// Si il y a un Bridge les donnees ne n'appartiennent pas, on detruit le Bridge
+// sinon, les donnees ont ete allouees par nos soins, on libere l'espace
+if(mSRef->bridge) delete mSRef->bridge; else delete [] mSRef->data;
+mSRef->bridge=NULL; mSRef->data=NULL;
+delete mSRef; mSRef=NULL; mSz = 0;
+}
+
+template <class T>
+void NDataBlock<T>::FillFrom(size_t n,T* data)
+// Remplissage par un tableau de donnees
+// - Si classe vide : creation de l'espace memoire
+// - Si classe connectee : on ecrit selon la longueur minimale
+//                         (cad this->mSz ou "n")
+{
+if(data==NULL) throw(NullPtrError("NDataBlock::FillFrom  data==NULL\n"));
+if(n==0) throw(ParmError("NDataBlock::FillFrom  n<=0\n"));
+if(mSRef==NULL) Alloc(n);
+if(mSz<n) n = mSz;
+memcpy(Data(),data,n*sizeof(T));
+}
+
+template <class T>
+void NDataBlock<T>::Realloc(size_t nnew,bool force)
+// Re-allocation de "nnew" place memoire pour les donnees
+// avec conservation des "nold" donnees precedentes si possible.
+// "force" gere la re-allocation de la place memoire pour les donnees.
+// Divers cas se presentent:
+// a-/ *** nnew>nold force=quelconque ***
+//     place re-allouee, donnees [0,nold[ copiees, surplus [nold,new[ mis a zero
+// b-/ *** nnew<=nold force=true ***
+//     place re-allouee, donnees [0,nnew[ copiees, pas de surplus
+// c-/ *** nnew<=nold force=false ***
+//     place non re-allouee, seule la valeur de la taille est diminuee
+// - On tient compte du partage des donnees dans tous les cas.
+// - Si il n'y a pas de donnees connectees a la classe, on re-alloue
+//   dans tous les cas
+{
+if(nnew==0) throw(ParmError("NDataBlock::Realloc  n<=0\n"));
+
+// Cas sans re-allocation memoire
+if(mSRef && nnew<=mSz && ! force) { mSz=nnew; return;}
+
+// Cas avec re-allocation memoire
+size_t ncop;
+if(!mSRef || mSz==0) ncop=0; else if(mSz<nnew) ncop=mSz; else ncop=nnew;
+T* dataloc = new T[nnew];
+if(ncop>0) memcpy(dataloc,mSRef->data,ncop*sizeof(T));
+if(nnew>ncop) memset(dataloc+ncop,0,(nnew-ncop)*sizeof(T));
+Alloc(nnew,dataloc,NULL); //Alloc gere partage de reference et bridge
+}
+
+////////////////////////////////////////////////////////////////
+//**** Impression
+
+template <class T>
+void NDataBlock<T>::Print(ostream& os,size_t i1,size_t n) const
+// Impression de n elements a partir de i1
+{
+size_t nr = 0;
+T* p = NULL; Bridge* br = NULL;
+if(mSRef) {nr = mSRef->nref; p = mSRef->data; br = mSRef->bridge;}
+os<<"NDataBlock::Print("<<this<<",Sz="<<mSz<<",IsTemp="<<mIsTemp<<")\n"
+  <<"            mSRef="<<mSRef<<"(nref="<<nr<<",data="<<p
+  <<",bridge="<<br<<")"<<endl;
+if(i1>=mSz || n<=0 || !p) return;
+size_t i2 = i1+n; if(i2>mSz) i2=mSz;
+size_t im = 1; bool enl=false;
+while(i1<i2) {
+  enl = false;
+  os<<" "<<(*this)(i1);  i1++;
+  if(im==8) {os<<"\n"; im=1; enl=true;} else im++;
+}
+if(!enl) os<<endl;
+}
+
+////////////////////////////////////////////////////////////////
+
+template <class T>
+T NDataBlock<T>::Sum(size_t i1,size_t n) const
+// Somme des elements de i1 a i1+n-1
+{
+if(i1>=mSz) return 0;
+if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
+T const *p=Begin()+i1, *pe=p+n;
+T val = 0;
+while (p<pe) val += *p++;
+return val;
+}
+
+template <class T>
+T NDataBlock<T>::Product(size_t i1,size_t n) const
+// Produit des elements de i1 a i1+n-1
+{
+if(i1>=mSz) return 0;
+if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
+T const *p=Begin()+i1, *pe=p+n;
+T val = 0;
+while (p<pe) val *= *p++;
+return val;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de = : NDataBlock=NDataBlock; NDataBlock=<T> b; 
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator = (const NDataBlock<T>& a)
+// Affectation: partage des donnees si "a" temporaire, clone sinon.
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::operator=("<<this<<","<<&a<<") a.(mSz="
+    <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
+    <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
+#endif
+
+if(this == &a) return *this;
+if(a.mSz==0)
+  throw(SzMismatchError("NDataBlock::operator=A null size\n"));
+CloneOrShare(a);
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator = (T v)
+// Affectation de tous les elements a une constante "v"
+{
+#ifdef DEBUG_NDATABLOCK
+cout<<"?_NDataBlock::operator=("<<this<<","<<v<<")"
+    <<" mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
+#endif
+
+if(mSz==0) throw(SzMismatchError("NDataBlock::operator=v null size\n"));
+T *p=Begin(), *pe=End();
+while (p<pe) *p++ = v;
+return *this;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += <T> b;
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator += (T b)
+{
+if(mSz==0) throw(SzMismatchError("NDataBlock::operator+=v null size\n"));
+T *p=Begin(), *pe=End();
+while (p<pe) *p++ += b;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator -= (T b)
+{
+if(mSz==0) throw(SzMismatchError("NDataBlock::operator-=v null size\n"));
+T *p=Begin(), *pe=End();
+while (p<pe) *p++ -= b;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator *= (T b)
+{
+if(mSz==0) throw(SzMismatchError("NDataBlock::operator*=v null size\n"));
+T *p=Begin(), *pe=End();
+while (p<pe) *p++ *= b;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator /= (T b)
+{
+if(b==(T) 0) throw(ParmError("NDataBlock::operator/=v divide by zero\n"));
+if(mSz==0) throw(SzMismatchError("NDataBlock::operator/=v null size\n"));
+T *p=Begin(), *pe=End();
+while (p<pe) *p++ /= b;
+return *this;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += NDataBlock;
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator += (const NDataBlock<T>& a)
+{
+if(mSz==0 || mSz!=a.mSz)
+  throw(SzMismatchError("NDataBlock::operator+=A size mismatch/null"));
+T *p=Begin(), *pe=End();
+T const * pa=a.Begin();
+while (p<pe) *p++ += *pa++;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator -= (const NDataBlock<T>& a)
+{
+if(mSz==0 || mSz!=a.mSz)
+  throw(SzMismatchError("NDataBlock::operator-=A size mismatch/null"));
+T *p=Begin(), *pe=End();
+T const *pa=a.Begin();
+while (p<pe) *p++ -= *pa++;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator *= (const NDataBlock<T>& a)
+{
+if(mSz==0 || mSz!=a.mSz)
+  throw(SzMismatchError("NDataBlock::operator*=A size mismatch/null"));
+T *p=Begin(), *pe=End();
+T const *pa=a.Begin();
+while (p<pe) *p++ *= *pa++;
+return *this;
+}
+
+template <class T>
+NDataBlock<T>& NDataBlock<T>::operator /= (const NDataBlock<T>& a)
+// Attention, aucune protection si un element de "a" est nul.
+{
+if(mSz==0 || mSz!=a.mSz)
+  throw(SzMismatchError("NDataBlock::operator/=A size mismatch/null"));
+T *p=Begin(), *pe=End();
+T const *pa=a.Begin();
+while (p<pe) *p++ /= *pa++;
+return *this;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+<T>b;
+//                            NDataBlock = <T>b+NDataBlock;
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Add(T b) const
+// Pour A+b
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+result += b;
+return result;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Sub(T b) const
+// Pour A-b
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+return result -= b;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::SubInv(T b) const
+// Pour b-A
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+T *p=result.Begin(), *pe=result.End();
+T const *pa=this->Begin();
+while(p<pe) {*p++ = b - *pa++;}
+return result;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Mul(T b) const
+// Pour A*b
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+return result *= b;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Div(T b) const
+// Pour A/b
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+return result /= b;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::DivInv(T b) const
+// Pour b/A
+{
+NDataBlock<T> result(*this); result.SetTemp(true);
+T *p=result.Begin(), *pe=result.End();
+T const *pa = this->Begin();
+while(p<pe) {*p++ = b / *pa++;}
+return result;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+NDataBlock;
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Add(const NDataBlock<T>& b) const
+// Pour A+B
+{
+if(mSz!=b.mSz)
+  throw(SzMismatchError("NDataBlock operator C=A+B size mismatch/null\n"));
+NDataBlock<T> result; result.SetTemp(true);
+if(b.IsTemp()) {result.Share(b);            result += *this;}
+  else         {result.CloneOrShare(*this); result += b;}
+return result;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Mul(const NDataBlock<T>& b) const
+// Pour A*B
+{
+if(mSz!=b.mSz)
+  throw(SzMismatchError("NDataBlock operator C=A*B size mismatch/null\n"));
+NDataBlock<T> result; result.SetTemp(true);
+if(b.IsTemp()) {result.Share(b);            result *= *this;}
+  else         {result.CloneOrShare(*this); result *= b;}
+return result;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Sub(const NDataBlock<T>& b) const
+// Pour A-B
+{
+if(mSz!=b.mSz)
+  throw(SzMismatchError("NDataBlock operator C=A-B size mismatch/null\n"));
+NDataBlock<T> result; result.SetTemp(true);
+if(b.IsTemp()) {
+  result.Share(b);
+  T *p=result.Begin(), *pe=result.End(); T const *pa=Begin();
+  while(p<pe) {*p = *pa++  - *p; p++;}
+} else {result.CloneOrShare(*this); result -= b;}
+return result;
+}
+
+template <class T>
+NDataBlock<T> NDataBlock<T>::Div(const NDataBlock<T>& b) const
+// Pour A/B
+{
+if(mSz!=b.mSz)
+  throw(SzMismatchError("NDataBlock operator C=A/B size mismatch/null\n"));
+NDataBlock<T> result; result.SetTemp(true);
+if(b.IsTemp()) {
+  result.Share(b);
+  T *p=result.Begin(), *pe=result.End(); T const *pa=Begin();
+  while(p<pe) {*p = *pa++  / *p; p++;}
+} else {result.CloneOrShare(*this); result /= b;}
+return result;
+}
+
+////////////////////////////////////////////////////////////////
+// -------------------------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// -------------------------------------------------------------------------
+
+/*
+template <class T>
+void ObjFileIO< NDataBlock<T> >::ReadSelf(PInPersist& is)
+template <class T>
+void ObjFileIO< NDataBlock<T> >::WriteSelf(POutPersist& os)
+*/
+
+// Pour pouvoir ecrire des tableaux de complex, en attendant 
+// PIn/POutPersist::Get/Put(complex<>)
+#include "piocmplx.h"
+
+template <class T>
+FIO_NDataBlock<T>::FIO_NDataBlock()
+{
+dobj=new NDataBlock<T>;
+ownobj=true;
+}
+
+template <class T>
+FIO_NDataBlock<T>::FIO_NDataBlock(string const & filename) 
+{
+dobj=new NDataBlock<T>;
+ownobj=true; 
+Read(filename);
+}
+
+template <class T>
+FIO_NDataBlock<T>::FIO_NDataBlock(const NDataBlock<T> & obj) 
+{ 
+dobj = new NDataBlock<T>(obj);
+ownobj=true; 
+}
+
+template <class T>
+FIO_NDataBlock<T>::FIO_NDataBlock(NDataBlock<T> * obj) 
+{ 
+dobj = obj;
+ownobj=false; 
+}
+
+template <class T>
+FIO_NDataBlock<T>::~FIO_NDataBlock()
+{
+if (ownobj && dobj) delete dobj;
+}
+
+template <class T>
+AnyDataObj* FIO_NDataBlock<T>::DataObj()
+{
+return(dobj);
+}
+
+
+template <class T>
+void FIO_NDataBlock<T>::ReadSelf(PInPersist& is)
+{
+// On lit les 3 premiers uint_8
+uint_8 itab[3];
+is.Get(itab, 3);
+if (dobj == NULL) dobj = new NDataBlock<T>(itab[1]);
+else if (itab[1] != dobj->Size()) dobj->ReSize(itab[1]);
+// On lit le tableau de nombres
+PIOSReadArray(is, dobj->Data(), dobj->Size()); 
+}
+
+
+template <class T>
+void FIO_NDataBlock<T>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;  // Attention - $CHECK$ Reza 26/04/99
+//  On ecrit 3 uint_8 
+//  0 : Numero de version,  1 : Taille,  2  reserve a l
+uint_8 itab[3];
+itab[0] = 1;
+itab[1] = dobj->Size();
+itab[2] = 0;
+os.Put(itab, 3);
+//  On ecrit le tableau de nombres 
+PIOSWriteArray(os, dobj->Data(), dobj->Size()); 
+}
+
+///////////////////////////////////////////////////////////////
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template NDataBlock<uint_1>
+#pragma define_template NDataBlock<uint_2>
+#pragma define_template NDataBlock<int_2>
+#pragma define_template NDataBlock<int_4>
+#pragma define_template NDataBlock<int_8>
+#pragma define_template NDataBlock<uint_4>
+#pragma define_template NDataBlock<uint_8>
+#pragma define_template NDataBlock<r_4>
+#pragma define_template NDataBlock<r_8>
+#pragma define_template NDataBlock< complex<float> >
+#pragma define_template NDataBlock< complex<double> >
+// Instances des delegues FileIO (PPersist)
+#pragma define_template FIO_NDataBlock<uint_1>
+#pragma define_template FIO_NDataBlock<uint_2>
+#pragma define_template FIO_NDataBlock<int_2>
+#pragma define_template FIO_NDataBlock<int_4>
+#pragma define_template FIO_NDataBlock<int_8>
+#pragma define_template FIO_NDataBlock<uint_4>
+#pragma define_template FIO_NDataBlock<uint_8>
+#pragma define_template FIO_NDataBlock<r_8>
+#pragma define_template FIO_NDataBlock<r_4>
+#pragma define_template FIO_NDataBlock< complex<float> >
+#pragma define_template FIO_NDataBlock< complex<double> >
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class NDataBlock<uint_1>;
+template class NDataBlock<uint_2>;
+template class NDataBlock<int_2>;
+template class NDataBlock<int_4>;
+template class NDataBlock<int_8>;
+template class NDataBlock<uint_4>;
+template class NDataBlock<uint_8>;
+template class NDataBlock<r_4>;
+template class NDataBlock<r_8>;
+template class NDataBlock< complex<float> >;
+template class NDataBlock< complex<double> >;
+// Instances des delegues FileIO (PPersist)
+template class FIO_NDataBlock<uint_1>;
+template class FIO_NDataBlock<uint_2>;
+template class FIO_NDataBlock<int_2>;
+template class FIO_NDataBlock<int_4>;
+template class FIO_NDataBlock<int_8>;
+template class FIO_NDataBlock<uint_4>;
+template class FIO_NDataBlock<uint_8>;
+template class FIO_NDataBlock<r_8>;
+template class FIO_NDataBlock<r_4>;
+template class FIO_NDataBlock< complex<float> >;
+template class FIO_NDataBlock< complex<double> >;
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/ndatablock.h	(revision 752)
@@ -0,0 +1,189 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Gestion de block de donnees avec partage de references
+//                         C.Magneville          04/99
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+#ifndef NDATABLOCK_H
+#define NDATABLOCK_H
+
+#include "machdefs.h"
+#include "anydataobj.h"
+#include "ppersist.h"
+#include <iostream.h>
+
+namespace SOPHYA {
+
+// Classe pour permettre de partager des donnees avec 
+// un autre systeme de gestion de references (ex avec Blitz)
+class Bridge {
+public:
+  Bridge() { } 
+  virtual ~Bridge() { }
+};
+
+// classe de container avec partage de reference
+template <class T>
+class NDataBlock : public AnyDataObj {
+
+public:
+
+  // Creation / destruction 
+  NDataBlock(size_t n);
+  NDataBlock(size_t n, T* data, Bridge* br=NULL);
+  NDataBlock();
+  NDataBlock(const NDataBlock<T>& a);
+  NDataBlock(const NDataBlock<T>& a,bool share);
+  virtual ~NDataBlock();
+
+  // Temporaire?
+  inline bool IsTemp(void) const {return mIsTemp;}
+  inline void SetTemp(bool temp=false) const {mIsTemp = temp;}
+
+  // Gestion taille/Remplissage
+  void Clone(const NDataBlock<T>& a);
+  void CloneOrShare(const NDataBlock<T>& a);
+  void Share(const NDataBlock<T>& a);
+  void FillFrom(size_t n,T* data);
+  inline void Reset(T v=0)
+         {if(mSz==0) return; T *p=Begin(),*pe=End(); while(p<pe) *p++=v;}
+
+  // ReSize redimmensionne une structure pour "n" donnees.
+  // Les donnees precedentes sont perdues (pour cette classe)
+  // et le nouveau tableau mis a zero. La nouvelle structure de
+  // donnees n'a qu'une reference (celle de cette classe).
+  inline void ReSize(size_t n) {Alloc(n);}
+
+  void Realloc(size_t nnew,bool force=false);
+  
+  // Informations pointeur/data
+  inline T* Data()
+         {if(mSRef) return mSRef->data; else return NULL;}
+  inline T* Data() const
+         {if(mSRef) return mSRef->data; else return NULL;}
+  inline size_t Size() const    {return mSz;}
+  inline T& operator()(size_t i)       {return *(mSRef->data+i);}
+  inline T  operator()(size_t i) const {return *(mSRef->data+i);}
+  inline T*        Begin()        {return mSRef->data;}
+  inline T const*  Begin() const  {return mSRef->data;} 
+  inline T*        End()          {return mSRef->data+mSz;}
+  inline T const*  End() const    {return mSRef->data+mSz;}
+  inline size_t NRef() const {if(mSRef) return 0; else return mSRef->nref;}
+
+  // Impression
+  void Print(ostream& os, size_t i1=0,size_t n=10) const;
+  inline void Print(size_t i1=0,size_t n=0) const {Print(cout,i1,n);}
+
+  //
+  T Sum(size_t i1=0,size_t n=0) const;
+  T Product(size_t i1=0,size_t n=0) const;
+
+  // Surcharge d'operateurs INPLACE: A = x , A = B , A @= x , A @= B
+  NDataBlock<T>& operator = (const NDataBlock<T>& a);
+  NDataBlock<T>& operator = (T v);
+
+  NDataBlock<T>& operator += (T b);
+  NDataBlock<T>& operator -= (T b);
+  NDataBlock<T>& operator *= (T b);
+  NDataBlock<T>& operator /= (T b);
+
+  NDataBlock<T>& operator += (const NDataBlock<T>& a);
+  NDataBlock<T>& operator -= (const NDataBlock<T>& a);
+  NDataBlock<T>& operator *= (const NDataBlock<T>& a);
+  NDataBlock<T>& operator /= (const NDataBlock<T>& a);
+
+  // Surcharge d'operateurs: C = A @ x , C = A @ B
+  NDataBlock<T> Add(T b) const;
+  NDataBlock<T> Sub(T b) const;
+  NDataBlock<T> SubInv(T b) const;
+  NDataBlock<T> Mul(T b) const;
+  NDataBlock<T> Div(T b) const;
+  NDataBlock<T> DivInv(T b) const;
+
+  NDataBlock<T> Add(const NDataBlock<T>& b) const;
+  NDataBlock<T> Sub(const NDataBlock<T>& b) const;
+  NDataBlock<T> SubInv(const NDataBlock<T>& b) const;
+  NDataBlock<T> Mul(const NDataBlock<T>& b) const;
+  NDataBlock<T> Div(const NDataBlock<T>& b) const;
+  NDataBlock<T> DivInv(const NDataBlock<T>& b) const;
+
+protected:
+  typedef struct {size_t nref; T* data; Bridge* bridge; } NDREF;
+
+  void Alloc(size_t n,T* data=NULL,Bridge* br=NULL);
+  void Delete(void);
+
+  size_t       mSz;
+  NDREF*       mSRef;
+  mutable bool mIsTemp;
+};
+
+
+template<class T>
+inline ostream& operator << (ostream& os, const NDataBlock<T>& a)
+                      {a.Print(os); return(os);}
+template<class T>
+inline NDataBlock<T> operator + (const NDataBlock<T>& a,T b)
+                      {return a.Add(b);}
+template<class T>
+inline NDataBlock<T> operator + (T b,const NDataBlock<T>& a)
+                      {return a.Add(b);}
+template<class T>
+inline NDataBlock<T> operator - (const NDataBlock<T>& a,T b)
+                      {return a.Sub(b);}
+template<class T>
+inline NDataBlock<T> operator - (T b,const NDataBlock<T>& a)
+                      {return a.SubInv(b);}
+template<class T>
+inline NDataBlock<T> operator * (const NDataBlock<T>& a,T b)
+                      {return a.Mul(b);}
+template<class T>
+inline NDataBlock<T> operator * (T b,const NDataBlock<T>& a)
+                      {return a.Mul(b);}
+template<class T>
+inline NDataBlock<T> operator / (const NDataBlock<T>& a,T b)
+                      {return a.Div(b);}
+template<class T>
+inline NDataBlock<T> operator / (T b,const NDataBlock<T>& a)
+                      {return a.DivInv(b);}
+
+template<class T>
+inline NDataBlock<T> operator + (const NDataBlock<T>& a,const NDataBlock<T>& b)
+                      {return a.Add(b);}
+template<class T>
+inline NDataBlock<T> operator - (const NDataBlock<T>& a,const NDataBlock<T>& b)
+                      {return a.Sub(b);}
+template<class T>
+inline NDataBlock<T> operator * (const NDataBlock<T>& a,const NDataBlock<T>& b)
+                      {return a.Mul(b);}
+template<class T>
+inline NDataBlock<T> operator / (const NDataBlock<T>& a,const NDataBlock<T>& b)
+                      {return a.Div(b);}
+
+
+// Classe pour la gestion de persistance
+template <class T>
+class FIO_NDataBlock : public  PPersist  {
+public:
+  FIO_NDataBlock();
+  FIO_NDataBlock(string const & filename); 
+  FIO_NDataBlock(const NDataBlock<T> & obj);
+  FIO_NDataBlock(NDataBlock<T> * obj);
+  virtual ~FIO_NDataBlock();
+  virtual AnyDataObj* DataObj();
+  inline operator NDataBlock<T>() { return(*dobj); }
+protected :
+  virtual void       ReadSelf(PInPersist&);           
+  virtual void       WriteSelf(POutPersist&) const;  
+  NDataBlock<T> * dobj;
+  bool ownobj;
+};
+
+template <class T>
+inline POutPersist& operator << (POutPersist& os, NDataBlock<T> & obj)
+{ FIO_NDataBlock<T> fio(&obj);  fio.Write(os);  return(os); }
+template <class T>
+inline PInPersist& operator >> (PInPersist& is, NDataBlock<T> & obj)
+{ FIO_NDataBlock<T> fio(&obj);  fio.Read(is);  return(is); }
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/objfio.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/objfio.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/objfio.h	(revision 752)
@@ -0,0 +1,51 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe de gestion des I/O fichiers des objets 
+//                          R.Ansari          04/99
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef OBJFILEIO_H_SEEN
+#define OBJFILEIO_H_SEEN
+
+#include "machdefs.h"
+#include "anydataobj.h"
+#include "ppersist.h"
+
+namespace SOPHYA {
+
+
+template <class T>
+class ObjFileIO : public PPersist {
+
+public :
+	    ObjFileIO() { dobj=new T; ownobj=true; }
+	    ObjFileIO(string const & filename) 
+                        { dobj=new T; ownobj=true; Read(filename); }
+	    ObjFileIO(const T & obj) { dobj = new T(obj); ownobj=true; }
+	    ObjFileIO(T * obj) { dobj = obj; ownobj=false; }
+  virtual   ~ObjFileIO() { if (ownobj && dobj) delete dobj; }
+
+  virtual   AnyDataObj* DataObj() { return(dobj); }
+  inline operator T() { return(*dobj); }
+
+protected :
+  virtual void       ReadSelf(PInPersist&);           
+  virtual void       WriteSelf(POutPersist&) const;  
+
+  T * dobj;
+  bool ownobj;       // True si dobj obtenu par new
+};
+
+/*
+template <class T>
+inline POutPersist& operator << (POutPersist& os, T const & obj)
+{ ObjFileIO<T> fio((const_cast)&obj);  fio.Write(os);  return(os); } 
+
+template <class T>
+inline PInPersist& operator >> (PInPersist& is, T & obj)
+{ ObjFileIO<T> fio(&obj);  fio.Read(is);  return(is); }  
+*/
+
+
+} // Fin namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/objlist.list
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/objlist.list	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/objlist.list	(revision 752)
@@ -0,0 +1,10 @@
+ctimer.o
+md5.o
+ndatablock.o
+pdlmgr.o
+peidainit.o
+periodic.o
+pexceptions.o
+ppersist.o
+psighand.o
+timing.o
Index: /tags/V_Fev00/SophyaLib/BaseTools/peidainit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/peidainit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/peidainit.cc	(revision 752)
@@ -0,0 +1,100 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <complex>
+#include "pexceptions.h"
+#include "ppersist.h"
+#include "peidainit.h"
+#include "ndatablock.h"
+#include "sversion.h"
+
+// ---  Classe d'initialisation de PEIDA++, (PPersistMgr en particulier)
+int PeidaInitiator::FgInit = 0;
+
+PeidaInitiator::PeidaInitiator()
+{
+  FgInit++;
+  if (FgInit > 1)  return;
+
+  InitFailNewHandler();
+
+  #ifdef xx__mac__
+  //InitToolBox();
+  //SIOUXSettings.initializeTB = FALSE;
+  SIOUXSettings.autocloseonquit = FALSE;
+  SIOUXSettings.asktosaveonclose = FALSE;
+  SIOUXSettings.showstatusline = TRUE;
+  #endif
+
+  PIOPersist::Initialize();
+  PPRegister(FIO_NDataBlock<uint_1>);
+  PPRegister(FIO_NDataBlock<uint_2>);
+  PPRegister(FIO_NDataBlock<int_2>);
+  PPRegister(FIO_NDataBlock<int_4>);
+  PPRegister(FIO_NDataBlock<int_8>);
+  PPRegister(FIO_NDataBlock<uint_4>);
+  PPRegister(FIO_NDataBlock<uint_8>);
+  PPRegister(FIO_NDataBlock<r_4>);
+  PPRegister(FIO_NDataBlock<r_8>);
+  PPRegister(FIO_NDataBlock< complex<float> >);
+  PPRegister(FIO_NDataBlock< complex<double> >);
+
+//DEL  PPersistMgr::classList = new PPersistMgr::ClassList;
+//DEL  PShPersist::objList    = new PShPersist::ObjList;
+  
+
+#if (!defined(__GNUG__) && !defined(__MWERKS__) && !defined(HPUX))
+  // pas de bufferisation pour printf   cmv 18/3/97 selon E.A.
+  // setvbuf(stdout,NULL,_IOLBF,0); setvbuf(stderr,NULL,_IOLBF,0);
+  setlinebuf(stdout);
+  setlinebuf(stderr);
+#endif
+
+  // si var env PEIDA_NOPRTVER definie pas de print
+  if(!getenv("SOPHYA_NOPRTVER")) Version(true);
+}
+
+PeidaInitiator::~PeidaInitiator()
+{
+  FgInit--;
+/*
+  if (FgInit == 0)
+    {
+    delete PPersistMgr::classList; PPersistMgr::classList = NULL;
+    delete PShPersist::objList;    PShPersist::objList = NULL;
+    }
+    */
+}
+
+double PeidaInitiator::Version(bool fgprt)
+{
+if (fgprt) {
+  char* compiler = 0;
+  #ifdef __GNUG__
+  compiler = "gcc " __VERSION__;
+  #endif
+  #ifdef __DECCXX
+  compiler = "cxx " ;
+  #endif
+  #ifdef __aCC__
+  compiler = const_cast<char *>("HP-aCC ") ;
+  #endif
+  #ifdef __KCC__
+  compiler = const_cast<char *>("KCC ") ;
+  #endif
+  #ifdef __SGICC__
+  compiler = const_cast<char *>("SGI-CC ") ;
+  #endif
+  #ifdef __MWERKS__
+  compiler = const_cast<char *>("Codewarrior ");
+  #endif
+  fprintf(stderr,"SOPHYA Version %4.1f Revision %d (%s) -- %s %s %s\n",
+          SOPHYA_VERSION, SOPHYA_REVISION, SOPHYA_TAG,
+          __DATE__, __TIME__, compiler);
+}
+return(SOPHYA_VERSION + (SOPHYA_REVISION/1000.));
+}
+ 
+// On met un objet initiator en statique, pour les loaders qui savent 
+// appeler le constructeur des objets statiques   Reza 08/98
+static PeidaInitiator ppeidainit;
Index: /tags/V_Fev00/SophyaLib/BaseTools/peidainit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/peidainit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/peidainit.h	(revision 752)
@@ -0,0 +1,26 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe d'initialiseur de module de PEIDA 
+
+#ifndef PEIDAINIT_H_SEEN
+#define PEIDAINIT_H_SEEN
+
+#include "machdefs.h"
+
+void PrintPeidaVersion(void);
+double PeidaVersion(void); /* Version + (Revision/1000) */
+
+// Classe d''initialisation pour les modules de PEIDA++
+
+class PeidaInitiator {
+private:
+  static int FgInit;
+public:
+  			PeidaInitiator();
+  virtual		~PeidaInitiator();
+  virtual double 	Version(bool fgprt=true);
+};
+
+#define PeidaInit() PeidaInitiator peidainitiator
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/BaseTools/perrors.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/perrors.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/perrors.h	(revision 752)
@@ -0,0 +1,1 @@
+#include "pexceptions.h"
Index: /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.cc	(revision 752)
@@ -0,0 +1,24 @@
+#include "pexceptions.h"
+#include <iostream.h>
+
+void PFailHandler(void); 
+
+// egcs ne semble pas connaitre set_new_handler (Reza 26/04/99)
+#ifdef __GNUG__
+void PFailHandler(void) {}
+void InitFailNewHandler() {}
+#else
+
+void PFailHandler(void)
+{
+  set_new_handler(NULL);
+  cerr << "Allocation exception -- out of memory" << endl;
+  throw(AllocationError("new"));
+}
+
+void InitFailNewHandler()
+{
+   set_new_handler(PFailHandler);
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/pexceptions.h	(revision 752)
@@ -0,0 +1,191 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef PEXCEPTIONS_SEEN
+#define PEXCEPTIONS_SEEN
+
+#include "machdefs.h"
+#include <string>
+
+using namespace std;
+
+namespace SOPHYA {
+
+  // Ancestor for PError and PException
+  // It has a message, and an id to give more
+  // information on the exception.
+  class PThrowable {
+  public:
+    explicit PThrowable(const string& m, int ident=0) 
+      : msg(m), id(ident) {}
+    virtual ~PThrowable() { }
+    virtual string const& Msg() const  {return msg;}
+  private:
+    string msg;
+    int    id;
+  };
+  
+  // A PError is a serious logic error. Usually not caught...
+  class PError : public PThrowable {
+  public:
+    explicit PError(const string& m, int id=0) : PThrowable(m,id) {}
+  };
+  
+  // A PException is not as serious... Can be caught.
+  class PException : public PThrowable {
+  public:
+    explicit PException(const string& m, int id=0) : PThrowable(m,id) {}
+  };
+  
+  // Errors
+  // Memory allocation failure
+  class AllocationError : public PError {
+  public:
+    explicit AllocationError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Null pointer error
+  class NullPtrError : public PError {
+  public:
+    explicit NullPtrError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Size mismatch between objects
+  class SzMismatchError : public PError {
+  public:
+    explicit SzMismatchError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Out of bounds for array, matrix, etc.
+  class RangeCheckError : public PError {
+  public:
+    explicit RangeCheckError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Invalid parameter to method/constructor...
+  class ParmError : public PError {
+  public:
+    explicit ParmError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Calling a forbidden method, trying a forbidden operation
+  class ForbiddenError : public PError {
+  public:
+    explicit ForbiddenError(const string& m, int id=0) : PError(m,id) {}
+  };
+
+  // Calling a non available / not implemented method
+  class NotAvailableOperation : public PException {
+  public:
+    explicit NotAvailableOperation(const string& m, int id=0) : PException(m,id) {}
+  };
+  
+  // ASSERT macro failure. The message is the assertion...
+  class AssertionFailedError : public PError {
+  public:
+    explicit AssertionFailedError(const string& m, int id=0) : PError(m,id) {}
+  };
+  
+  // Standard exceptions
+  //
+  // PException
+  //   IOExc
+  //     FileFormatExc
+  //   TypeMismatchExc
+  //   DuplicateIdExc
+  //   NotFoundExc
+  //   MathExc
+  //     SingMatxExc
+  
+  // generic IO Exception
+  class IOExc : public PException {
+  public:
+    explicit IOExc(const string& m, int id=0) : PException(m,id) {}
+  };
+
+  // Bad type -> keep ?
+  class TypeMismatchExc : public PException {
+  public:
+    explicit TypeMismatchExc(const string& m, int id=0) : PException(m,id) {}
+  };
+  
+  class MathExc : public PException {
+  public:
+    explicit MathExc(const string& m, int id=0) : PException(m,id) {}
+  };
+  
+  class DuplicateIdExc : public PException {
+  public:
+    explicit DuplicateIdExc(const string& m, int id=0) : PException(m,id) {}
+  };
+  
+  class NotFoundExc : public PException {
+  public:
+    explicit NotFoundExc(const string& m, int id=0) : PException(m,id) {}
+  };
+  
+  class CaughtSignalExc : public PException {
+  public:
+    explicit CaughtSignalExc(const string& m, int id=0) : PException(m,id) {}
+  };
+
+  // Bad file format
+  class FileFormatExc : public IOExc {
+  public:
+    explicit FileFormatExc(const string& m, int id=0) : IOExc(m,id) {}
+  };
+  
+  class SingMatrixExc : public MathExc {
+  public:
+    explicit SingMatrixExc(const string& m, int id=0) : MathExc(m,id) {}
+  };
+  
+  
+}
+
+
+#define ASSERT(_a_) if (!(_a_)) { \
+     cerr << "Assertion failed " #_a_ " file " __FILE__ " line " << __LINE__ \
+          << endl; \
+		     throw(AssertionFailedError(#_a_)); }
+   
+#define FAILNIL(_x_) \
+       {if (!(_x_)) throw(NullPtrError(#_x_))}
+
+void InitFailNewHandler();
+  
+     
+// Compatibility with EROS-PEIDA exceptions
+
+#define EXC_ABORT_NEG(_x)
+#define EXC_ABORT_ALL(_x)
+
+#define EXC_AWARE
+
+#define END_CONSTRUCTOR
+
+#define TRY try
+#define CATCH(_var) catch(long _var)
+#define CATCHALL catch(...)
+#define ENDTRY
+
+#define THROW(_i) throw( _i);
+
+#define THROW_ THROW(0)
+
+#define THROW_SAME throw;
+
+#define RETURN(x) return(x)
+#define RETURN_ return
+
+#define rangeCheckErr    RangeCheckError("")
+#define typeMismatchErr  TypeMismatchExc("")
+#define allocationErr    AllocationError("")
+#define parmErr          ParmError("")
+#define inconsistentErr  ParmError("")
+#define sizeMismatchErr  SzMismatchError("")
+#define fileErr          IOExc("")
+#define nullPtrErr       NullPtrError("")
+#define singMatxErr      SingMatrixExc("")
+
+#define DBASSERT(_x_) ASSERT(_x_)
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/piocmplx.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/piocmplx.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/piocmplx.h	(revision 752)
@@ -0,0 +1,154 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Fonctions d'ecriture de tableaux numeriques
+#ifndef PIOCMPLX_H_SEEN
+#define PIOCMPLX_H_SEEN
+
+/*
+// Pour gerer les Persist I/O de tableaux numerique templates
+template <class T>
+void PIOSReadArray(PInPersist & is, T* arr, size_t n);
+template <class T>
+void PIOSWriteArray(POutPersist & os, T const * arr, size_t n);
+*/
+
+// Pour pouvoir ecrire des tableau de complex, en attendant 
+// PIn/POutPersist::Get/Put(complex<>)
+
+inline
+void PIOSReadArray(PInPersist & is, uint_1 * arr, size_t n)
+{
+is.GetBytes(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, uint_2 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, int_2 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, uint_4 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, int_4 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, uint_8 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, int_8 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, r_4 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, r_8 * arr, size_t n)
+{
+is.Get(arr, n);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, complex<float> * arr, size_t n)
+{
+r_4 * pr = (r_4 *)arr;
+is.Get(pr, n*2);
+}
+
+inline
+void PIOSReadArray(PInPersist & is, complex<double> * arr, size_t n)
+{
+r_8 * pr = (r_8 *)arr;
+is.Get(pr, n*2);
+}
+
+// Fonctions d ecriture de tableaux de nombre
+inline
+void PIOSWriteArray(POutPersist & os, uint_1 const * arr, size_t n)
+{
+os.PutBytes(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, uint_2 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, int_2 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, uint_4 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, int_4 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, uint_8 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, int_8 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, r_4 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, r_8 const * arr, size_t n)
+{
+os.Put(arr, n);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, complex<float> const * arr, size_t n)
+{
+r_4 const * pr = (r_4 const *)arr;
+os.Put(pr, n*2);
+}
+
+inline
+void PIOSWriteArray(POutPersist & os, complex<double> const * arr, size_t n)
+{
+r_8 const * pr = (r_8 const *)arr;
+os.Put(pr, n*2);
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/ppersist.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/ppersist.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/ppersist.cc	(revision 752)
@@ -0,0 +1,1263 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+#include "pexceptions.h"
+#include "peidainit.h"
+#include "ppersist.h"
+#include <fstream.h>
+#include <iostream.h>
+#include <typeinfo>
+
+
+#ifdef __mac__
+#include "unixmac.h"
+#include <SIOUX.h>
+#endif
+
+#define MAXTAGLEN 255
+
+//++
+// Class	PIOPersist
+// Lib		Outils++
+// include	ppersist.h
+//
+//	Root class for persistant files. Handles the registration of
+//	persistant classes
+//--
+
+//++
+// Links	See
+// PPersist
+// PInPersist
+// POutPersist
+//--
+
+
+MD5_CONTEXT PIOPersist::ctx;
+PIOPersist::ClassList * PIOPersist::classList = NULL;   // $CHECK$ Reza 26/04/99
+map<string, uint_8> * PIOPersist::typeids = NULL;
+
+//++
+void
+PIOPersist::Initialize()
+//  Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
+//--
+{
+classList = new PIOPersist::ClassList;
+typeids = new map<string, uint_8>;
+}
+
+//++
+void
+PIOPersist::RegisterClass(uint_8 classId, string typname, ClassCreatorFunc f)
+//
+//	Register a new persistant class.
+//	The classId is usually a hash of the class name, and this
+//	method is called only through the PPersistRegistrar template
+//	class, with the PPRegister(className) macro.
+//
+//--
+{
+  if (classList->size() && (classList->find(classId) != classList->end())) {
+      cerr << "RegisterClass : Error, " << hex << classId << dec 
+           << " already registered." << endl;
+      throw(DuplicateIdExc("PIOPersist::RegisterClass"));
+    }
+  
+  (*classList)[classId] = f;
+  (*typeids)[typname]  = classId;
+}
+
+
+PIOPersist::ClassCreatorFunc
+PIOPersist::FindCreatorFunc(uint_8 classId)
+{
+  ClassList::iterator i = classList->find(classId);
+  if (i == classList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
+  return (*i).second;
+}
+
+
+//++
+// Class	PPersist
+// Lib		Outils++
+// include	ppersist.h
+//
+//	Classe de base pour des objets persistants. Pour créer un objet
+//	persistant :
+//	- Hériter de PPersist.
+//	- Définir un numéro d'identification de la classe, unique dans Peida
+//	- Implémenter "ClassId()"
+//	- Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
+//	  membres que l'on souhaite écrire, et les relire dans le même ordre.
+//	  Pour écrire une référence à un objet : l'objet doit être un PPersist,
+//	  et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
+//	  Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
+//	  fois, il faut que cet objet soit un PShPersist.
+//	- Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
+//	  les fonctions PutXX/GetXX de PInPersist/POutPersist.
+//
+//	Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
+//	les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
+//--
+
+//++
+// Links	See
+// PInPersist
+// POutPersist
+// PIOPersist
+//--
+  
+//++
+void
+PPersist::Write(string const& fn) const
+//
+//	Ecrit l'objet dans un nouveau fichier ppersist "fn".
+//--
+{
+  POutPersist of(fn);
+  Write(of);
+}
+
+//++
+void
+PPersist::Read(string const& fn) 
+//
+//	Relit l'objet dans le fichier ppersist "fn". Il faut connaître a priori
+//	le type de l'objet. Pour une relecture avec création automatique du bon
+//	objet, utiliser PPersistMgr::ReadObject.
+//--
+{
+  PInPersist inf(fn);
+  Read(inf);
+}
+
+//++
+void
+PPersist::Write(POutPersist& s) const
+//
+//	Ecrit l'objet dans le fichier PPersist.
+//--
+{
+   s.PutObject(this);
+}
+
+
+//++
+void
+PPersist::Read(PInPersist& s)
+//
+//	Relit l'objet dans le fichier ppersist. Il faut connaître a priori
+//	le type de l'objet. Pour une relecture avec création automatique du bon
+//	objet, utiliser PInPersist::ReadObject.
+//  Il faut qu'on soit un objet ecrit 
+//--
+{
+  // We should be the exact type  
+  // Check tag value
+  char ppstype;
+  s.GetTypeTag(ppstype);
+  if (ppstype != PInPersist::PPS_OBJECT) {
+    throw FileFormatExc("PPersist::Read : not an object in flow");
+  }
+  
+  // Check class id
+  uint_8 classId;
+  s.GetRawU8(classId);
+  uint_8 myClassId = PIOPersist::getTypeId(typeid(*this).name());
+  if (classId != myClassId) {
+    throw FileFormatExc("PPersist::Read : not the same object type");
+  }
+
+  ReadSelf(s);
+}
+
+//++
+void
+PPersist::Write(POutPersist& s, string const& tag) const
+//
+//	Ecrit l'objet dans le fichier PPersist avec un tag 
+//--
+{
+  s.WriteTag(tag);
+  s.PutObject(this);
+}
+
+//++
+void
+PPersist::ReadAtTag(PInPersist& s, string const& tag)
+//
+//	Lit l'objet à la position du tag numéro "tagid".
+//--
+{
+  if (!s.GotoTag(tag))
+    throw NotFoundExc("PPersist::ReadAtTag  tag not found");
+  Read(s);
+}
+
+
+//++
+//  virtual void PPersist::ReadSelf(PInPersist&)=0
+//	Méthode virtuelle pure à redéfinir. Elle est appelée par Read
+//	et PPersistMgr::ReadObject. Il faut relire les variables membres,
+//	dans l'ordre où elles ont été écrites par WriteSelf.
+//  virtual void PPersist::WriteSelf(POutPersist&) const=0
+//	Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
+//	Il faut écrire les variables membres,
+//	dans l'ordre où elles seront relues par ReadSelf.
+//--
+
+
+
+//++
+// Class	PInPersist
+// Lib		Outils++
+// include	ppersist.h
+//
+//	Fichier d'objets persistants, en lecture.
+//--
+
+//++
+PInPersist::PInPersist(string const& flnm, bool scan)
+//
+//	Constructeur. Ouvre le fichier.
+//--
+{
+  s = new ifstream(flnm.c_str(),ios::in | IOS_BIN); 
+
+  // Read and check header
+
+  char rbuf[36];
+  GetRawBytes(rbuf, 32);
+  if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0)  {
+    throw FileFormatExc("PInPersist::PInPersist  bad header");
+  }
+  version = atoi(rbuf+24);
+
+  // read endianness
+  GetRawBytes(rbuf, 32);
+  if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
+    bigEndian = true;
+  else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
+    bigEndian = false;
+  else {
+    throw FileFormatExc("PInPersist::PInPersist  bad header - endianness");
+  }
+
+  // read creation date
+  GetRawBytes(rbuf, 32);
+  rbuf[32] = '\0'; 
+  struct tm tm;
+  #ifndef __MWERKS__
+  strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
+  #else
+  sscanf(rbuf,"%2d/%2d/%4d %2d:%2d:%2d GMT",&tm.tm_mday,&tm.tm_mon,&tm.tm_year,
+                                            &tm.tm_hour,&tm.tm_min,&tm.tm_sec);
+  tm.tm_mon  --;
+  tm.tm_year -= 1900;
+  #endif
+  creationdate = mktime(&tm);
+
+  if (scan) Scan();
+}
+
+
+
+PInPersist::~PInPersist()
+{
+  delete s;
+}
+
+
+void
+PInPersist::Scan()
+{
+  // On cherche la liste des tags, a la fin du fichier
+
+  char ppstype;
+  size_t debut;
+#ifdef STREAMPOS_IS_CLASS
+  debut = s->tellg().offset();
+#else
+  debut = s->tellg();
+#endif
+
+  // Find tag entries at end of file
+  s->seekg(-(sizeof(int_8)+1), ios::end);
+  GetTypeTag(ppstype);
+  if (ppstype != PPS_EOF)
+    throw FileFormatExc("PInPersist::Scan   corrupted file, no eof entry at end of file");
+
+  int_8 pos;
+  GetRawI8(pos);
+  if (pos < 0) {  // no tags
+    s->seekg(debut);
+    return;
+  }
+
+  char buffer[MAXTAGLEN+1];
+  s->seekg(pos);
+  while (true) {
+    GetTypeTag(ppstype);
+    if (ppstype == PPS_EOF) break;
+    
+    if (ppstype != PPS_TAG)
+      throw FileFormatExc("PInPersist::Scan   corrupted file, bad tag entry");
+
+    GetRawI8(pos);
+    int_4 len;
+    GetRawI4(len);
+    if (len > MAXTAGLEN) 
+      throw FileFormatExc("PInPersist::Scan   corrupted file, tag name too long");
+    GetRawBytes(buffer, len);
+    buffer[len] = '\0';
+
+    tags[buffer] = pos;
+  }
+  s->seekg(debut);
+}
+
+
+int
+PInPersist::NbTags()
+{
+  return tags.size();
+}
+
+bool 
+PInPersist::GotoTag(string const& name)
+{
+  map<string, int_8>::iterator i = tags.find(name);
+  if (i == tags.end()) 
+    return false;
+      //    throw NotFoundExc("PInPersist::GotoTag   tag not found");
+  s->seekg((*i).second);
+  objList.clear(); // $CHECK$ EA 171199
+  return(true); 
+}
+
+bool
+PInPersist::GotoTagNum(int itag)
+{
+  if (itag<0 || itag >= (int)tags.size()) return false;
+  map<string, int_8>::iterator i = tags.begin();
+  for (int j=0; j<itag; j++) i++;
+  s->seekg((*i).second);
+  objList.clear(); // $CHECK$ EA 171199
+  return(true);
+}
+
+string
+PInPersist::GetTagName(int itag)
+{
+  if (itag<0 || itag >= (int)tags.size()) return "";
+  map<string, int_8>::iterator i = tags.begin();
+  for (int j=0; j<itag; j++) i++;
+  return((*i).first);
+}
+
+static vector<string> * ret_tag_names = NULL;
+vector<string> const &
+PInPersist::GetTagNames()
+{
+if (ret_tag_names) delete ret_tag_names;
+ret_tag_names = new vector<string> ;
+map<string, int_8>::iterator i;
+for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
+return(*ret_tag_names);  
+}
+
+//++
+// void PInPersist::GetByte(char& c)
+// void PInPersist::GetBytes(void* ptr, size_t bytes)
+// void PInPersist::GetR4   (r_4& result)
+// void PInPersist::GetR4s  (r_4* tab, size_t n)
+// void PInPersist::GetR8   (r_8& result)
+// void PInPersist::GetR8s  (r_8* tab, size_t n)
+// void PInPersist::GetI2   (int_2& result)
+// void PInPersist::GetI2s  (int_2* tab, size_t n)
+// void PInPersist::GetU2   (uint_2& result)
+// void PInPersist::GetU2s  (uint_2* tab, size_t n)
+// void PInPersist::GetI4   (int_4& result)
+// void PInPersist::GetI4s  (int_4* tab, size_t n)
+// void PInPersist::GetU4   (uint_4& result)
+// void PInPersist::GetU4s  (uint_4* tab, size_t n)
+// void PInPersist::GetI8   (int_8& result)
+// void PInPersist::GetI8s  (int_8* tab, size_t n)
+// void PInPersist::GetU8   (uint_8& result)
+// void PInPersist::GetU8s  (uint_8* tab, size_t n)
+//	Lecture de données portables depuis le fichier PPersist. Pour chaque type
+//	de données, on peut lire une valeur, ou un tableau de valeurs.
+// void PInPersist::GetLine(char* ptr, size_t len)
+//	Lecture d'une ligne de texte depuis le fichier PPersist.
+//--
+
+
+static inline void bswap8(void* p)
+{
+  uint_8 tmp = *(uint_8*)p;
+  *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) | 
+                ((tmp >> (5*8)) & 0x0000FF00) |
+                ((tmp >> (3*8)) & 0x00FF0000) |
+                ((tmp >> (1*8)) & 0xFF000000) |
+                ((tmp & 0xFF000000) << (1*8))  |
+                ((tmp & 0x00FF0000) << (3*8))  |
+                ((tmp & 0x0000FF00) << (5*8))  |
+                ((tmp & 0x000000FF) << (7*8));
+}
+
+static inline void bswap4(void* p)
+{
+  uint_4 tmp = *(uint_4*)p;
+  *(uint_4*)p = ((tmp >> 24) & 0x000000FF) | 
+                ((tmp >> 8)  & 0x0000FF00) |
+                ((tmp & 0x0000FF00) << 8)  |
+                ((tmp & 0x000000FF) << 24);
+}
+
+static inline void bswap2(void* p)
+{
+  uint_2 tmp = *(uint_2*)p;
+  *(uint_2*)p = ((tmp >> 8) & 0x00FF) | 
+                ((tmp & 0x00FF) << 8);
+}
+
+void
+PInPersist::GetTypeTag(char& c) 
+{
+  GetRawByte(c);
+  while (c == PPS_TAG_MARK) {
+    objList.clear();
+    GetRawByte(c);
+  }
+}
+
+
+void
+PInPersist::GetRawByte(char& c)
+{
+  GetRawBytes(&c, 1);
+}
+
+void
+PInPersist::GetRawBytes(void* ptr, size_t bytes)
+{
+  s->read((char*)ptr, bytes);
+}
+
+void
+PInPersist::GetRawI2   (int_2& result)
+{
+  GetRawBytes(&result, sizeof(int_2));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&result);
+}
+
+void
+PInPersist::GetRawI4   (int_4& result)
+{
+  GetRawBytes(&result, sizeof(int_4));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&result);
+}
+
+void
+PInPersist::GetRawI8   (int_8& result)
+{
+  GetRawBytes(&result, sizeof(int_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::GetRawU8   (uint_8& result)
+{
+  GetRawBytes(&result, sizeof(uint_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::CheckTag(short datasz)
+{
+  char ppstype;
+  GetTypeTag(ppstype);
+  if (ppstype != PPS_SIMPLE + datasz)
+    throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+}
+
+void
+PInPersist::CheckArrayTag(short datasz, size_t sz)
+{
+  char ppstype;
+  GetTypeTag(ppstype);
+  size_t filesz;
+  if (sz <= 0x7fff) {
+    if (ppstype != PPS_SIMPLE_ARRAY + datasz)
+      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+    int_2 ff;
+    GetRawI2(ff); filesz=ff;
+  } else if (sz <= 0x7fffffff) {
+    if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
+      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+    int_4 ff;
+    GetRawI4(ff); filesz=ff;
+  } else {
+    if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
+      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+    uint_8 ff;
+    GetRawU8(ff); filesz=ff;
+  }
+  if (filesz != sz)
+    throw FileFormatExc("PInPersist::CheckTag   bad array size in ppersist file");
+}
+
+void
+PInPersist::GetByte(char& c)
+{
+  CheckTag(1);
+  GetRawBytes(&c, 1);
+}
+
+void
+PInPersist::GetBytes(void* ptr, size_t bytes)
+{
+  CheckArrayTag(1, bytes);
+  GetRawBytes(ptr, bytes);
+}
+void
+PInPersist::GetR4   (r_4& result)
+{
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(r_4));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&result);
+}
+
+
+void
+PInPersist::GetR4s  (r_4* tab, size_t n)
+{
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(r_4));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap4(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetR8   (r_8& result)
+{
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(r_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::GetR8s  (r_8* tab, size_t n)
+{
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(r_8));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap8(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetI2   (int_2& result)
+{
+  CheckTag(2);
+  GetRawBytes(&result, sizeof(int_2));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&result);
+}
+
+void
+PInPersist::GetI2s  (int_2* tab, size_t n)
+{
+  CheckArrayTag(2,n);
+  GetRawBytes(tab, n*sizeof(int_2));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap2(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetU2   (uint_2& result)
+{
+  CheckTag(2);
+  GetRawBytes(&result, sizeof(uint_2));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&result);
+}
+
+void
+PInPersist::GetU2s  (uint_2* tab, size_t n)
+{
+  CheckArrayTag(2,n);
+  GetRawBytes(tab, n*sizeof(uint_2));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap2(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetI4   (int_4& result)
+{
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(int_4));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&result);
+}
+
+void
+PInPersist::GetI4s  (int_4* tab, size_t n)
+{
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(int_4));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap4(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetU4   (uint_4& result)
+{
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(uint_4));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&result);
+}
+
+void
+PInPersist::GetU4s  (uint_4* tab, size_t n)
+{
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(uint_4));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap4(tab+i);
+
+  return;
+}
+
+
+void
+PInPersist::GetI8   (int_8& result)
+{
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(int_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::GetI8s  (int_8* tab, size_t n)
+{
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(int_8));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap8(tab+i);
+
+  return;
+}
+
+void
+PInPersist::GetU8   (uint_8& result)
+{
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(uint_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::GetU8s  (uint_8* tab, size_t n)
+{
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(uint_8));
+  if (bigEndian == IS_BIG_ENDIAN) return;
+
+  for (unsigned int i=0; i<n; i++)
+    bswap8(tab+i);
+
+  return;
+}
+
+
+void
+PInPersist::GetLine(char* ptr, size_t len)
+{
+  char ppstype;
+  GetTypeTag(ppstype);
+  if (ppstype != PPS_LINE) 
+    throw FileFormatExc("PInPersist::GetLine   bad type in ppersist file");
+  s->getline(ptr, len, '\n');
+}
+
+void
+PInPersist::GetStr(string& str)
+{
+  char ppstype;
+  GetTypeTag(ppstype);
+  if (ppstype != PPS_STRING) 
+    throw FileFormatExc("PInPersist::GetLine   bad type in ppersist file");
+  int_2 len;
+  GetRawI2(len);
+  char * buff = new char[len+1];
+  GetRawBytes(buff, len);
+  buff[len] = '\0';
+  str = buff;
+  delete[] buff;
+}
+
+PPersist*
+PInPersist::ReadObject()
+{
+  // Get tag
+  char ppstype;
+  GetTypeTag(ppstype);
+  if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
+    throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
+  }
+
+  if (ppstype == PPS_NULL) {
+    return NULL;
+  } else if (ppstype == PPS_OBJECT) {
+    // Get class id
+    uint_8 classId;
+    GetRawU8(classId);
+    
+    // Get factory method
+    ClassCreatorFunc f = FindCreatorFunc(classId);
+    if (!f) {
+      throw NotFoundExc("PInPersist::ReadObject   class not registered");
+    }
+    
+    // Create object
+    PPersist* object = f();
+    object->ReadSelf(*this);
+    assignObjectId(object);
+    return object;
+  } else {
+    // Get object id
+    int_4 id;
+    GetRawI4(id);
+    if (id <0 || id>=objList.size()) {
+      char msg[200];
+      sprintf(msg, "PInPersist::ReadObject    invalid object id for reference: %d/%d",id,objList.size());
+      throw FileFormatExc(msg);
+    }
+    return objList[id];
+  }
+}
+
+int_4 
+PInPersist::assignObjectId(PPersist* x)
+{
+  objList.push_back(x);
+  return objList.size()-1;
+}
+
+//++
+// Class	POutPersist
+// Lib		Outils++
+// include	ppersist.h
+//
+//	Fichier d'objets persistants, en écriture.
+//--
+
+
+//++
+//  POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
+//
+//	Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
+//	sur machines petit-boutiennes, et gros-boutien sur machines
+//	gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
+//	ou PPersist::PPS_BIG_ENDIAN.
+//--
+POutPersist::POutPersist(string const& flnm, int endianness)
+{
+  if (endianness == -1)
+    bigEndian = IS_BIG_ENDIAN;
+  else
+    bigEndian = endianness;
+
+  // Output stream creation
+  s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);  
+
+  // Header
+  PutRawBytes("SOS-SOPHYA-PPersistFile V1               ",32);
+  PutRawBytes(bigEndian 
+	   ? "BIG-ENDIAN                             "
+	   : "LITTLE-ENDIAN                          ",32);
+
+// ---- GMT creation date of the file
+  time_t tm = time(NULL);
+  char datestring[33];
+  int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
+  for(int i=l; i<32; i++)  datestring[i] = ' ';
+  datestring[32] = '\0'; 
+  PutRawBytes(datestring, 32);
+}
+
+POutPersist::~POutPersist()
+{
+  if (tags.size() == 0) {
+    PutRawByte(PPS_EOF);
+    PutRawI8(-1);
+  } else {
+    int_8 tagPos;
+#ifdef STREAMPOS_IS_CLASS
+    tagPos = s->tellp().offset();
+#else
+    tagPos = s->tellp();
+#endif
+    for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
+      string name = (*i).first;
+      int_8 pos = (*i).second;
+      PutRawByte(PPS_TAG);                       // This is a tag
+      PutRawI8(pos);                             // position of previous tag
+      PutRawI4(name.length());                   // length of the name
+      PutRawBytes(name.c_str(), name.length());  // name, without final "0".
+    }
+    PutRawByte(PPS_EOF);
+    PutRawI8(tagPos);
+  }
+
+  delete s;   // Close the stream
+}
+
+
+void
+POutPersist::WriteTag(string const& name)
+{
+  if (name.length() > MAXTAGLEN) 
+    throw ParmError("POutPersist::WriteTag   tag name too long");
+
+  if (tags.find(name) != tags.end())
+    throw DuplicateIdExc("POutPersist::WriteTag   duplicate tag name");
+
+  // Get current file position
+  int_8 tagPos;
+
+  #ifdef STREAMPOS_IS_CLASS
+  tagPos = s->tellp().offset();
+  #else
+  tagPos = s->tellp();
+  #endif
+
+  tags[name] = tagPos;
+  PutRawByte(PPS_TAG_MARK);                       // This is a tag
+  objList.clear(); // $CHECK$ EA 171199
+}
+
+//++
+// void POutPersist::PutByte(char& c)
+// void POutPersist::PutBytes(void const* ptr, size_t bytes)
+// void POutPersist::PutR4   (r_4 result)
+// void POutPersist::PutR4s  (r_4 const* tab, size_t n)
+// void POutPersist::PutR8   (r_8 result)
+// void POutPersist::PutR8s  (r_8 const* tab, size_t n)
+// void POutPersist::PutI2   (int_2 result)
+// void POutPersist::PutI2s  (int_2 const* tab, size_t n)
+// void POutPersist::PutU2   (uint_2 result)
+// void POutPersist::PutU2s  (uint_2 const* tab, size_t n)
+// void POutPersist::PutI4   (int_4 result)
+// void POutPersist::PutI4s  (int_4 const* tab, size_t n)
+// void POutPersist::PutU4   (uint_4 result)
+// void POutPersist::PutU4s  (uint_4 const* tab, size_t n)
+// void POutPersist::PutI8   (int_8 result)
+// void POutPersist::PutI8s  (int_8 const* tab, size_t n)
+// void POutPersist::PutU8   (uint_8 result)
+// void POutPersist::PutU8s  (uint_8 const* tab, size_t n)
+// void POutPersist::PutStr  (string const&)
+//	Ecriture de données portables.. Pour chaque type
+//	de données, on peut écrire une valeur, ou un tableau de valeurs.
+// void POutPersist::PutLine(char const* ptr, size_t len)
+//	Ecriture d'une ligne de texte dans le fichier PPersist.
+//--
+
+
+
+
+void
+POutPersist::PutRawBytes(void const* ptr, size_t bytes)
+{
+  s->write((char const*)ptr, bytes);
+}
+
+void
+POutPersist::PutRawByte(char c)
+{
+  PutRawBytes(&c, 1);
+}
+
+void
+POutPersist::PutRawI2   (int_2 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&val);
+
+  PutRawBytes(&val, sizeof(int_2));
+}
+
+void
+POutPersist::PutRawI4   (int_4 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&val);
+
+  PutRawBytes(&val, sizeof(int_4));
+}
+
+void
+POutPersist::PutRawI8   (int_8 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(int_8));
+}
+
+void
+POutPersist::PutRawU8   (uint_8 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(uint_8));
+}
+
+void
+POutPersist::PutArrayTag(short datasz, size_t sz)
+{
+  if (sz <= 0x7fff) {
+    PutRawByte(PPS_SIMPLE_ARRAY + datasz);
+    PutRawI2(sz);
+  } else if (sz <= 0x7fffffff) {
+    PutRawByte(PPS_SIMPLE_ARRAY4 + datasz);
+    PutRawI4(sz);
+  } else {
+    PutRawByte(PPS_SIMPLE_ARRAY8 + datasz);
+    PutRawU8(sz);
+  } 
+}
+
+void
+POutPersist::PutByte(char c)
+{
+  PutRawByte(PPS_SIMPLE + 1);
+  PutRawBytes(&c, 1);
+}
+
+
+
+void
+POutPersist::PutBytes(void const* ptr, size_t bytes)
+{
+  PutArrayTag(1, bytes);
+  PutRawBytes(ptr, bytes);
+}
+
+void
+POutPersist::PutR4   (r_4 val)
+{
+  PutRawByte(PPS_SIMPLE + 4);
+  
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&val);
+
+  PutRawBytes(&val, sizeof(r_4));
+}
+
+void
+POutPersist::PutR4s  (r_4 const* tab, size_t n)
+{
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(r_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      r_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(r_4));
+    }
+  }
+}
+
+void
+POutPersist::PutR8   (r_8 val)
+{
+  PutRawByte(PPS_SIMPLE + 8);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(r_8));
+}
+
+void
+POutPersist::PutR8s  (r_8 const* tab, size_t n)
+{
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(r_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      r_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(r_8));
+    }
+  }
+}
+
+void
+POutPersist::PutI2   (int_2 val)
+{
+  PutRawByte(PPS_SIMPLE + 2);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&val);
+
+  PutRawBytes(&val, sizeof(int_2));
+}
+
+void
+POutPersist::PutI2s  (int_2 const* tab, size_t n)
+{
+  PutArrayTag(2, n);
+  
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_2));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_2 val = tab[i];
+      bswap2(&val);
+      PutRawBytes(&val, sizeof(int_2));
+    }
+  }
+}
+
+void
+POutPersist::PutU2   (uint_2 val)
+{
+  PutRawByte(PPS_SIMPLE + 2);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&val);
+
+  PutRawBytes(&val, sizeof(uint_2));
+}
+
+void
+POutPersist::PutU2s  (uint_2 const* tab, size_t n)
+{
+  PutArrayTag(2, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_2));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_2 val = tab[i];
+      bswap2(&val);
+      PutRawBytes(&val, sizeof(uint_2));
+    }
+  }
+}
+
+void
+POutPersist::PutI4   (int_4 val)
+{
+  PutRawByte(PPS_SIMPLE + 4);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&val);
+
+  PutRawBytes(&val, sizeof(int_4));
+}
+
+void
+POutPersist::PutI4s  (int_4 const* tab, size_t n)
+{
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(int_4));
+    }
+  }
+}
+
+void
+POutPersist::PutU4   (uint_4 val)
+{
+  PutRawByte(PPS_SIMPLE + 4);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&val);
+
+  PutRawBytes(&val, sizeof(uint_4));
+}
+
+void
+POutPersist::PutU4s  (uint_4 const* tab, size_t n)
+{
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(uint_4));
+    }
+  }
+}
+
+void
+POutPersist::PutI8   (int_8 val)
+{
+  PutRawByte(PPS_SIMPLE + 8);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(int_8));
+}
+
+void
+POutPersist::PutI8s  (int_8 const* tab, size_t n)
+{
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(int_8));
+    }
+  }
+}
+
+void
+POutPersist::PutU8   (uint_8 val)
+{
+  PutRawByte(PPS_SIMPLE + 8);
+
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(uint_8));
+}
+
+void
+POutPersist::PutU8s  (uint_8 const* tab, size_t n)
+{
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(uint_8));
+    }
+  }
+}
+
+void
+POutPersist::PutStr(string const& str) 
+{
+  PutRawByte(PPS_STRING);
+  PutRawI2(str.length());
+  PutRawBytes(str.c_str(), str.length());
+}
+
+void
+POutPersist::PutLine(char const* ptr, size_t len)
+{
+  PutRawByte(PPS_LINE);
+
+  if (len == 0)  len = strlen(ptr);
+  PutRawBytes(ptr, len);
+  PutRawByte('\n');
+}
+
+void
+POutPersist::PutObject(PPersist const* obj) 
+{
+  if (serializeNullAndRepeat(obj)) return;
+
+  PutRawByte(PPS_OBJECT);
+  PutRawU8(getTypeId(typeid(*obj).name()));
+  //PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
+  assignObjectId(obj);
+  obj->WriteSelf(*this);
+}
+
+bool
+POutPersist::serializeNullAndRepeat(PPersist const* x)
+{
+  if (x == NULL) {
+    PutRawByte(PPS_NULL);
+    return true;
+  }
+
+  int_4 id = findObjectId(x);
+  if (id >= 0) {
+    PutRawByte(PPS_REFERENCE);
+    PutRawI4(id);
+    return true;
+  }
+  
+  return false;
+}
+
+int_4 
+POutPersist::assignObjectId(PPersist const* x)
+{
+  int_4 id = objList.size();
+  objList[x] = id;
+  return id;
+}
+
+int_4 
+POutPersist::findObjectId(PPersist const* x)
+{
+  ObjList::iterator i = objList.find(x);
+  if (i == objList.end()) return -1;
+  return (*i).second;
+}
+
+
Index: /tags/V_Fev00/SophyaLib/BaseTools/ppersist.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/ppersist.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/ppersist.h	(revision 752)
@@ -0,0 +1,337 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef PPERSIST_H_SEEN
+#define PPERSIST_H_SEEN
+
+// Flat file persistance, similar to Java serialization
+//
+// E. Aubourg     CEA DAPNIA/SPP  1999
+
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "gnumd5.h"
+
+
+#include <time.h>
+
+#include <string>
+#include <map>
+#include <vector>
+#include <typeinfo>
+
+
+// Classe de base pour les objets qui peuvent devenir PPersist
+
+namespace SOPHYA {
+  
+  class AnyDataObj;
+
+  class PIOPersist;
+  class PInPersist;
+  class POutPersist;
+  class PPersist;
+
+  /* Persistant (delegate or mixin) object */
+
+  class PPersist  {
+  public:
+    virtual           ~PPersist() {}
+// J'ajoute cette fonction pour assurer la compatibilite 
+// avec l'ancien PPersist d'Eros     (Reza 23/04/99)
+    virtual int_4      ClassId() const { return(0); }
+
+    void               Write(string const& fn) const;
+    void               Read(string const& fn);
+
+    virtual void       Write(POutPersist&) const;
+    void               Read(PInPersist& s);               // Reads the type tag and the object
+    void               Write(POutPersist&, string const& tag) const; 
+    void               ReadAtTag(PInPersist& s, string const& tag);
+
+    virtual AnyDataObj* DataObj()       // Retourne l'objet reel $CHECK$ - Reza 
+                  { return(NULL); }     // Devrait etre virtuelle pure
+  protected:  
+    virtual void       ReadSelf(PInPersist&)=0;           
+    virtual void       WriteSelf(POutPersist&) const=0;  
+
+    friend class       PInPersist;
+    friend class       POutPersist;
+  };
+
+
+
+  // Ancestor for PInPersist and POutPersist
+  // Handles (statically) the registration of classes.
+
+  class PIOPersist {
+  public:
+    enum                         {PPS_NATIVE = -1, PPS_LITTLE_ENDIAN = 0, PPS_BIG_ENDIAN = 1};
+    typedef PPersist*            (*ClassCreatorFunc)();
+  
+    static void                  RegisterClass(uint_8 classId, string typname, ClassCreatorFunc f);
+    static ClassCreatorFunc      FindCreatorFunc(uint_8 classId);
+    static uint_8 Hash(string const& typname) {
+	md5_init(&ctx);
+	md5_write(&ctx, (unsigned char*) typname.c_str(), typname.size());
+	md5_final(&ctx);
+	return ( *((uint_8*) ctx.buf) + *((uint_8*) (ctx.buf+8)));
+    }
+    static MD5_CONTEXT ctx;
+  
+    static void Initialize();   // Pour initialiser classList
+    static uint_8 getTypeId(string s) {return (*typeids)[s];}
+  private:
+
+    typedef map<uint_8, ClassCreatorFunc, less<uint_8> > ClassList;  
+    // Pas de createur appele pour objets statiques sur Linux - $CHECK$ Reza 26/04/99
+    static ClassList *           classList;  
+    static map<string, uint_8> * typeids;
+
+  protected:
+
+    enum {PPS_NULL = 0,             // this is a null object
+	  PPS_STRING = 1,           // string, length (2b) + data
+	  PPS_OBJECT = 2,           // classId, data...
+	  PPS_REFERENCE = 3,        // objectId
+          PPS_TAG = 4,              // tag entries
+	  PPS_EOF = 5,              // Just before tag infomation, offset to PPS_TAG
+	  PPS_LINE = 6,             // '\n'-terminated, deprecated ?
+          PPS_TAG_MARK = 7,         // to reset object count when skipped
+          PPS_SIMPLE = 16,          // 16 + number of bytes, up to 8 bytes
+          PPS_SIMPLE_ARRAY = 32,    // 32 + number of bytes, up to 8 bytes, then 2 bytes of length
+          PPS_SIMPLE_ARRAY4 = 64,   // 64 + number of bytes, up to 8 bytes, then 4 bytes of length
+          PPS_SIMPLE_ARRAY8 = 128   // 64 + number of bytes, up to 8 bytes, then 8 bytes of length
+   };
+
+    map<string, int_8> tags;
+  };
+
+
+  // TBD : use hash tables instead of maps. Check hashtbl status in STL.
+
+  class PInPersist : public PIOPersist {
+  public:
+    PInPersist(string const& flnm, bool scan=true);
+    ~PInPersist();
+
+    bool   GotoTag(string const& name);
+    int    NbTags();
+    bool   GotoTagNum(int itag);  // 0..NbTags-1
+    string GetTagName(int itag);  // 0..NbTags-1
+    vector<string> const &  GetTagNames();  
+
+    void   GetByte (char& c);
+    void   GetBytes(void* ptr, size_t bytes);
+    void   GetR4   (r_4&);
+    void   GetR4s  (r_4*, size_t);
+    void   GetR8   (r_8&);
+    void   GetR8s  (r_8*, size_t);
+    void   GetI2   (int_2&);
+    void   GetI2s  (int_2*, size_t);
+    void   GetU2   (uint_2&);
+    void   GetU2s  (uint_2*, size_t);
+    void   GetI4   (int_4&);
+    void   GetI4s  (int_4*, size_t);
+    void   GetU4   (uint_4&);
+    void   GetU4s  (uint_4*, size_t);
+    void   GetI8   (int_8&);
+    void   GetI8s  (int_8*, size_t);
+    void   GetU8   (uint_8&);
+    void   GetU8s  (uint_8*, size_t);
+    void   GetLine (char* ptr, size_t len);
+    void   GetStr  (string&);
+
+    void   Get(char&   c) {GetByte(c);}
+    void   Get(r_4&    x) {GetR4(x);}
+    void   Get(r_8&    x) {GetR8(x);}
+    void   Get(uint_2& x) {GetU2(x);}
+    void   Get(int_2&  x) {GetI2(x);}
+    void   Get(uint_4& x) {GetU4(x);}
+    void   Get(int_4&  x) {GetI4(x);}
+    void   Get(uint_8& x) {GetU8(x);}
+    void   Get(int_8&  x) {GetI8(x);}
+    void   Get(r_4*    x, size_t n) {GetR4s(x,n);}
+    void   Get(r_8*    x, size_t n) {GetR8s(x,n);}
+    void   Get(uint_2* x, size_t n) {GetU2s(x,n);}
+    void   Get(int_2*  x, size_t n) {GetI2s(x,n);}
+    void   Get(uint_4* x, size_t n) {GetU4s(x,n);}
+    void   Get(int_4*  x, size_t n) {GetI4s(x,n);}
+    void   Get(uint_8* x, size_t n) {GetU8s(x,n);}
+    void   Get(int_8*  x, size_t n) {GetI8s(x,n);}
+    void   Get(string& x) {GetStr(x);}
+  
+    PPersist*  ReadObject();
+
+
+    int    Version() {return version;}
+    time_t CreationDate() { return creationdate; }
+
+  protected:
+    void   CheckTag   (short datasz);
+    void   CheckArrayTag(short datasz, size_t sz);
+    void   GetTypeTag (char& c);
+    void   GetRawByte (char& c);
+    void   GetRawBytes(void* ptr, size_t bytes);
+    void   GetRawI2   (int_2&);
+    void   GetRawI4   (int_4&);
+    void   GetRawI8   (int_8&);
+    void   GetRawU8   (uint_8&);
+    void   GetObject(PPersist*);               // Object has been allocated with correct type
+    int_4  assignObjectId(PPersist* x);
+    void   Scan();
+    char*  GetCStr(uint_2 l);
+
+    istream* s;
+
+    bool bigEndian;
+    int version;
+
+    time_t creationdate;
+
+    // already read objects, id = order in array 
+    typedef vector<PPersist*> ObjList;
+    ObjList objList;
+
+    friend class PPersist;
+  };
+
+  class POutPersist : public PIOPersist {
+  public:
+    POutPersist(string const& flnm, int endianness = PPS_NATIVE);
+    ~POutPersist();
+
+    void WriteTag(string const& name);
+  
+    void PutByte (char c);
+    void PutBytes(void const* ptr, size_t bytes);
+    void PutR4   (r_4);
+    void PutR4s  (r_4 const*, size_t);
+    void PutR8   (r_8);
+    void PutR8s  (r_8 const*, size_t);
+    void PutI2   (int_2);
+    void PutI2s  (int_2 const*, size_t);
+    void PutU2   (uint_2);
+    void PutU2s  (uint_2 const*, size_t);
+    void PutI4   (int_4);
+    void PutI4s  (int_4 const*, size_t);
+    void PutU4   (uint_4);
+    void PutU4s  (uint_4 const*, size_t);
+    void PutI8   (int_8);
+    void PutI8s  (int_8 const*, size_t);
+    void PutU8   (uint_8);
+    void PutU8s  (uint_8 const*, size_t);
+    void PutLine (char const* ptr, size_t len=0); // deprecated ?
+    void PutStr  (string const&);
+    void PutObject (PPersist const*); // Like doing Write(stream) on object
+
+    void   Put(char   c) {PutByte(c);}
+    void   Put(r_4    x) {PutR4(x);}
+    void   Put(r_8    x) {PutR8(x);}
+    void   Put(uint_2 x) {PutU2(x);}
+    void   Put(int_2  x) {PutI2(x);}
+    void   Put(uint_4 x) {PutU4(x);}
+    void   Put(int_4  x) {PutI4(x);}
+    void   Put(uint_8 x) {PutU8(x);}
+    void   Put(int_8  x) {PutI8(x);}
+    void   Put(r_4 const*    x, size_t n) {PutR4s(x,n);}
+    void   Put(r_8 const*    x, size_t n) {PutR8s(x,n);}
+    void   Put(uint_2 const* x, size_t n) {PutU2s(x,n);}
+    void   Put(int_2 const*  x, size_t n) {PutI2s(x,n);}
+    void   Put(uint_4 const* x, size_t n) {PutU4s(x,n);}
+    void   Put(int_4 const*  x, size_t n) {PutI4s(x,n);}
+    void   Put(uint_8 const* x, size_t n) {PutU8s(x,n);}
+    void   Put(int_8 const*  x, size_t n) {PutI8s(x,n);}
+    void   Put(string const& s) {PutStr(s);}
+    void   Put(PPersist const* x) {PutObject(x);}
+
+
+  protected:
+    ostream* s;
+    bool bigEndian;
+
+    void     PutArrayTag(short datasz, size_t sz);
+    void     PutRawByte (char);
+    void     PutRawI2   (int_2);
+    void     PutRawI4   (int_4);
+    void     PutRawI8   (int_8);
+    void     PutRawU8   (uint_8);
+    void     PutRawBytes(void const* ptr, size_t bytes);
+    bool     serializeNullAndRepeat(PPersist const* x);
+    int_4    findObjectId(PPersist const* x);
+    int_4    assignObjectId(PPersist const* x);
+
+    // already serialized objects
+    typedef map<PPersist const*, int_4, less<PPersist const*> >  ObjList;
+    ObjList objList;
+  };
+  
+  
+#define RAWPERSISTIO(_Type_,_xtyp_)                                             \
+  inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
+  {                                                                               \
+    c.Put##_xtyp_(data);                                                          \
+    return c;                                                                     \
+  }                                                                               \
+                                                                                \
+  inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
+  {                                                                               \
+    c.Get##_xtyp_(data);                                                          \
+    return c;                                                                     \
+  }                                                                               
+
+  RAWPERSISTIO(int_4,I4);
+  RAWPERSISTIO(uint_4,U4);
+  RAWPERSISTIO(int_2,I2);
+  RAWPERSISTIO(uint_2,U2);
+  RAWPERSISTIO(char,Byte);
+  RAWPERSISTIO(r_4,R4);
+  RAWPERSISTIO(r_8,R8);
+  
+#if 0
+#define STRUCTPERSISTIO(_Type_, _field_, _size_)                                \
+  inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
+  {                                                                               \
+    c.PutBytes(&data._field_, _size_);                                            \
+    return c;                                                                     \
+  }                                                                               \
+                                                                                \
+  inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
+  {                                                                               \
+    c.GetBytes(&data._field_, _size_);                                            \
+    return c;                                                                     \
+  }                                                                               
+
+#endif
+  
+  inline POutPersist& operator << (POutPersist& c, PPersist const& obj)
+    {
+      obj.Write(c);
+      return c;
+    }
+  
+  inline PInPersist& operator >> (PInPersist& c, PPersist& obj)
+    {
+      obj.Read(c);
+      return c;
+    }
+  
+  // Utility class to
+  //   - compute the class ID from a MD5 hash of the class name
+  //   - register classes with PIOPersist, through PPRegister macro
+  
+  template <class T>
+    class PPersistRegistrar {
+    public:
+      static PPersist* Create() {return new T();}
+      static void Register(string id) {PIOPersist::RegisterClass(Hash(id),typeid(T).name(),Create);}
+      static uint_8 Hash(string id) {
+	return PIOPersist::Hash(id);
+      }
+    };
+  
+#define PPRegister(className) PPersistRegistrar<className>::Register(#className);
+  
+} // namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/rcptr.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/rcptr.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/rcptr.h	(revision 752)
@@ -0,0 +1,121 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef RCPTR_H
+#define RCPTR_H
+
+// This implements a very simple "smart pointer" with reference counting.
+// Many refinements are possible
+
+// Principle :  use RCPtr<T> instead of T*
+// To use with type X, define
+//  typedef RCPtr<X> Xp;
+//  When creating a new object, use
+//    Xp xp = new X(...);
+// xp can be used like a X*   xp->field, xp->method(), *xp ...
+//    can be passed by reference, copied, etc
+// the object is destroyed when the last Xp is destroyed.
+
+// The class RCCPtr<X> is a const smart pointer, to be used like
+// a X const *.
+
+// Eric Aubourg  1999   CEA/DAPNIA/SPP
+
+
+template <class T> class RCCPtr;
+
+template <class T>
+class RCPtr {
+public:
+  RCPtr(T* obj=0) {
+    x = obj;
+    cnt = new int;
+    *cnt = 1;
+  }
+  
+  RCPtr(RCPtr<T> const& other) {
+    x = other.x;
+    cnt = other.cnt;
+    (*cnt)++;
+  }
+
+  RCPtr<T>& operator = (RCPtr<T> const& other) {
+    (*cnt)--;
+    if (!*cnt) {
+      delete x;
+      delete cnt;
+    }
+    x = other.x;
+    cnt = other.cnt;
+    (*cnt)++;
+    return *this;
+  }
+  
+  ~RCPtr() {
+    (*cnt)--;
+    if (!*cnt) {
+      delete x;
+      delete cnt;
+    }
+  }
+
+  T* operator->() {return x;}
+  T& operator*()  {return *x;}
+
+private:
+  T* x;                  // the object we are referring
+  int* cnt;              // how many smart pointers ?
+  friend class RCCPtr<T>;
+};
+
+
+// A const smart pointer
+template <class T>
+class RCCPtr {
+public:
+  RCCPtr(T const* obj=0) {
+    x = obj;
+    cnt = new int;
+    *cnt = 1;
+  }
+  
+  RCCPtr(RCCPtr<T> const& other) {
+    x = other.x;
+    cnt = other.cnt;
+    (*cnt)++;
+  }
+
+  RCCPtr(RCPtr<T> const& other) {
+    x = other.x;
+    cnt = other.cnt;
+    (*cnt)++;
+  }
+
+  RCCPtr<T>& operator = (RCCPtr<T> const& other) {
+    (*cnt)--;
+    if (!*cnt) {
+      delete (T*) x;
+      delete cnt;
+    }
+    x = other.x;
+    cnt = other.cnt;
+    (*cnt)++;
+    return *this;
+  }
+  
+  ~RCCPtr() {
+    (*cnt)--;
+    if (!*cnt) {
+      delete (T*) x;
+      delete cnt;
+    }
+  }
+
+  T const* operator->() {return x;}
+  T const& operator*()  {return *x;}
+
+private:
+  T const * x;           // the object we are referring
+  int* cnt;              // how many smart pointers ?
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/BaseTools/sversion.h
===================================================================
--- /tags/V_Fev00/SophyaLib/BaseTools/sversion.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/BaseTools/sversion.h	(revision 752)
@@ -0,0 +1,8 @@
+#ifndef SVERSION_H
+#define SVERSION_H
+
+#define SOPHYA_VERSION   0.8 
+#define SOPHYA_REVISION  13
+#define SOPHYA_TAG       "V_Fev2000"
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Mgr/Makefile
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/Makefile	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/Makefile	(revision 752)
@@ -0,0 +1,214 @@
+include Mgr/Makefile.h
+LIBF =  $(LIB)libSysTools.a $(LIB)libNTools.a $(LIB)libSamba.a $(LIB)libSkyT.a $(LIB)libFitsIOServer.a
+LIBS = -L$(LIB) -lSysTools -lNTools -lSamba -lSkyT -lFitsIOServer -lm
+LIBG = -L$(GLB) -lstdc++
+ifeq ($(HOSTTYPE), powerpc)
+  LIBG = -L$(GLB)
+endif
+
+defaut: libs
+
+all: libs PI
+
+
+libs: cxxlibs
+# Dans cet ordre pour les templates de cxx, a cause des dependances
+# pour instantiation automatique/manuels
+
+cxxlibs: FitsIOServer SkyT Samba NTools SysTools Blitz
+
+.PHONY:  FitsIOServer
+FitsIOServer:
+	if [ -d FitsIOServer ] ; then cd  FitsIOServer ; $(MAKE) ; fi
+ 
+.PHONY:  SkyT
+SkyT:
+	if [ -d SkyT ] ; then cd  SkyT ; $(MAKE) ; fi
+ 
+.PHONY:  Samba
+Samba:
+	if [ -d Samba ] ; then cd  Samba ; $(MAKE) ; fi
+ 
+.PHONY:  NTools
+NTools:
+	if [ -d NTools ] ; then cd  NTools ; $(MAKE) ; fi
+ 
+.PHONY:  SysTools
+SysTools:
+	if [ -d SysTools ] ; then cd  SysTools ; $(MAKE) ; fi
+ 
+.PHONY:  Blitz
+Blitz:
+	if [ -d Blitz ] ; then cd  Blitz ; $(MAKE) ; fi
+ 
+.PHONY: PI
+PI:
+	if [ -d PI ] ; then cd PI ; $(MAKE) ; fi
+	if [ -d PIext ] ; then cd PIext ; $(MAKE) ; fi
+
+ifndef NOSHLIB
+
+ifdef CFITSIODIR
+PSLB = $(LIB)libSysTools.a $(LIB)libNTools.a $(LIB)libSamba.a $(LIB)libSkyT.a $(LIB)libFitsIOServer.a 
+else
+PSLB = $(LIB)libSysTools.a $(LIB)libNTools.a $(LIB)libSamba.a $(LIB)libSkyT.a
+endif
+slb : $(SLB)libtools.so
+slbpi: slb $(SLB)libPI.so
+
+#  Chemin des librairies Motifs / X11 (pour chemin non standard)
+LIBXPATH :=
+#  Commande de construction de shared-lib 
+CMDSHL := ld -partage
+#  Flag d'inclusion/fin d'inclusion de tous les points  d'entree
+FGSHLA := -tout
+FGSHLN := -rien
+#  Librairies specifiques 
+LIBLSHL := 
+#  Librairie d'instanciation des templates 
+TILSHL := 
+TILSHLPI := 
+#   Commande de construction de la librairie d'instanciation des templates 
+CMDTILSHL := echo 'Cas Non Prevu'
+CMDTILSHLPI := echo 'Cas Non Prevu'
+# Utilisation du compilo C++ comme driver pour fabrication des shared-libs
+CMDSHLCXX := $(LINK.cc) 
+FGSHLACXX :=  
+FGSHLNCXX := 
+#  S'il faut utiliser $(CMDSHLCXX) pour fabrication des shared-libs
+USECXX4SO := N
+# On utilise le compilo g++ pour la fabrication des shared libs
+ifeq ($(EROSCXX), g++)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc) -shared
+endif
+
+# On utilise le compilo KCC pour la fabrication des shared libs
+ifeq ($(EROSCXX), KCC)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc)
+endif
+
+# On utilise le compilo aCC (HP) pour la fabrication des shared libs
+ifeq ($(EROSCXX), aCC)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc) -b
+endif
+
+# Construction de shared-libs sous OSF1
+ifeq ($(MACHEROS),OSF1)
+  override CMDSHL := ld -shared -update_registry $(SLB)so_locations
+  override FGSHLA := -all
+  override FGSHLN := -none 
+  override LIBLSHL := -lcxxstd -lcxx -lexc -lm -lc -lrt
+  override TILSHL := $(LIB)libertcxx.a
+  override CMDTILSHL := rm -f $(LIB)libertcxx.a ; cd $(REP); $(AR) $(ARFLAGS) $(LIB)libertcxx.a *.o
+  override TILSHLPI := $(LIB)libertcxxpi.a
+  override CMDTILSHLPI := rm -f $(LIB)libertcxxpi.a ; cd $(REPPI); $(AR) $(ARFLAGS) $(LIB)libertcxxpi.a *.o
+  ifeq ($(CXX),g++)
+    override LIBLSHL := $(LIBG) -lm -lc
+    override TILSHL := 
+    override CMDTILSHL := echo 'No Template instanciation library'
+    override TILSHLPI := 
+    override CMDTILSHLPI := echo 'No Template instanciation library'
+    override USECXX4SO := N
+  endif
+#  Attention - Dangereux de mettre -expect_unresolved , enleve  Reza 17/11/99
+  override CMDSHLCXX := $(LINK.cc) -shared  
+  override FGSHLACXX := 
+  override FGSHLNCXX := 
+endif
+
+# Construction de shared-libs sous Linux
+ifeq ($(MACHEROS),Linux)
+  override CMDSHL := ld -shared 
+  override FGSHLA := --whole-archive
+  override FGSHLN := --no-whole-archiv
+  override CMDSHLCXX := $(LINK.cc) -shared 
+  ifeq ($(EROSCXX), KCC)
+    override CMDSHLCXX := $(LINK.cc)
+  endif
+  override FGSHLACXX := 
+  override FGSHLNCXX := 
+  override LIBLSHL := $(LIBG) -lm -ldl
+  override TILSHL := 
+  override CMDTILSHL := echo 'No Template instanciation library'
+  override LIBXPATH := -L/usr/X11/lib -L/usr/X11R6/lib
+endif
+
+# Construction de shared-libs sous Sun-OS
+ifeq ($(MACHEROS),SunOS)
+  override CMDSHL := ld -G
+  override FGSHLA := -z allextract
+  override FGSHLN := -z weakextract
+  override LIBLSHL := $(LIBG) -lm -lc
+  override TILSHL := 
+  override CMDTILSHL := echo 'No Template instanciation library'
+  override LIBXPATH := -L/usr/X11/lib
+  override USECXX4SO := Y
+endif
+
+# Construction de shared-libs sous SGI
+ifeq ($(MACHEROS), IRIX64)
+  override CMDSHL := ld -shared
+  override FGSHLA := -all
+  override FGSHLN := -notall
+  override LIBLSHL := $(LIBG) -lm -lc
+  override TILSHL := 
+  override CMDTILSHL := echo 'No Template instanciation library'
+  ifeq ($(EROSCXX), CC)
+    override CMDSHLCXX := CC -shared 
+    override LIBLSHL := -lm -lc
+  endif
+  override LIBXPATH := -L/usr/X11/lib
+  override USECXX4SO := Y
+endif
+
+# Liste des .o associes a une librairie
+OBJSysTools = $(shell echo `cat ./SysTools/objlist.list`)
+OBJNTools = $(shell echo `cat ./NTools/objlist.list`)
+# OBJBlitz = $(shell echo `cat ./Blitz/objlist.list`)
+OBJSamba = $(shell echo `cat ./Samba/objlist.list`)
+OBJSkyT = $(shell echo `cat ./SkyT/objlist.list`)
+OBJFitsIOServer = $(shell echo `cat ./FitsIOServer/objlist.list`)
+OBJPI         = $(shell echo `cat ./PI/objlist.list`)
+OBJPIext      = $(shell echo `cat ./PIext/objlist.list`)
+
+ifdef CFITSIODIR
+AllObjs := $(OBJSysTools) $(OBJNTools) $(OBJSamba) $(OBJSkyT) $(OBJFitsIOServer)
+else
+AllObjs := $(OBJSysTools) $(OBJNTools) $(OBJSamba) $(OBJSkyT) 
+endif
+
+# Creation des librairies partagees
+
+
+#------------------------------------------------------------
+$(SLB)libtools.so : $(PSLB) 
+	$(CMDTILSHL)
+	cd $(OBJ); \
+	$(CMDSHLCXX) -o $(SLB)libtools.so \
+	$(FGSHLACXX) $(AllObjs)  $(TILSHL) \
+	$(FGSHLNCXX) -L$(SLB) $(LIBLSHL)  $(FITSIOLIB) 
+
+
+$(SLB)libPI.so : $(LIB)libPI.a $(LIB)libPIext.a
+	$(CMDTILSHLPI)
+	cd $(OBJ); \
+	$(CMDSHLCXX) -o $(SLB)libPI.so \
+	$(FGSHLACXX) $(OBJPI) $(OBJPIext) $(TILSHLPI) \
+	$(FGSHLN) -L$(SLB) -ltools \
+	$(LIBXPATH) -lXm -lXt -lX11 $(LIBLSHL)
+
+else
+slb :
+endif
+
+
+clean:
+	if [ -d $(LIB) ] ; then cd $(LIB)/. ; rm -f *.a  ; fi
+	if [ -d $(SLB) ] ; then cd $(SLB)/. ; rm -f *.so ; fi
+	if [ -d $(OBJ) ] ; then cd $(OBJ)/. ; rm -f *.o  ; fi
+	if [ -d $(OBJ)/cxxrep ] ; then cd $(OBJ)/cxxrep/. ; rm -f *.o  ; fi
+	if [ -d PI ]     ; then cd PI/.     ; $(MAKE) clean ; fi
+
Index: /tags/V_Fev00/SophyaLib/Mgr/Makefile.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/Makefile.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/Makefile.h	(revision 752)
@@ -0,0 +1,367 @@
+#  -*- makefile -*-
+# #########################  Sophya ############################# 
+# ##### LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA #####
+# ############################################################### 
+# General setup GNU Makefile for Sopyha/Planck. To be included in all makefiles.  
+# Define  makefile variables according to CPU 
+# MACHEROSD = `uname | sed 's/-//'`   i.e. { AIX HPUX OSF1 Linux ... }
+# and compilers {g++, cxx, KCC, xlC, aCC, ...}
+# 
+# Makefile variables set are:
+# - Path to Exec, Include, Libs, Obj directories (from DPCDEVREP env. var.)
+#     i.e. variables LIB, OBJ, EXE, INC 
+#---------------------------------------------------------------------------
+
+# define MACHEROS from uname
+MACHEROS := $(shell echo `uname`)
+# define the -D option
+MACHEROSD := $(shell echo `uname | sed 's/-//'`)
+# Le sous-repertoire des objets specifique machine-compilo
+#   OSF1 : Alpha avec gcc
+#   OSF1-cxx : Alpha avec cxx
+
+#### C++
+ifdef EROSCXX
+  CXX := $(EROSCXX)
+endif
+
+ifeq ($(CXX),gcc)
+  override CXX := g++
+endif
+
+ifeq ($(EROSCXX),egcs++)
+  # en fait de compilo de egcs++ s'appelle g++ !
+  # comme il faut bien differentier ln -s /usr/bin/g++ /usr/bin/egcs++
+  override CXX := egcs++
+endif
+
+ifeq ($(CC),xlC)
+  override CXX := xlC
+endif
+
+#### C
+ifeq ($(CXX), xlC)
+  override CC := xlC
+endif
+
+ifeq ($(CXX), g++)
+  CC := gcc
+endif
+
+ifeq ($(EROSCXX), egcs++)
+  CC := egcs
+endif
+
+#### Fortran (tout ce qui est lie au Fortran est defini ici #############
+FC = f77
+ifeq (${MACHEROS},Linux)
+#  override FC := f77
+  override FC := g77
+endif
+
+ifeq (${MACHEROS},OSF1)
+  LIBFORT = -lfor -lFutil -lots -lUfor
+endif
+ifeq (${MACHEROS},Linux)
+  LIBFORT = -lf2c
+endif
+#########################################################################
+
+
+MACHDIR := $(MACHEROS)-$(CXX)
+
+
+#-
+#-   Define Makefile paths
+#-  (NE PAS TOUCHER CES LIGNES: generation automatique de MakefileUser.h)
+#-  
+PP  := ${DPCDEVREP}/${MACHDIR}/
+LIB := ${PP}/Libs/
+SLB := ${PP}/ShLibs/
+OBJ := ${PP}/Objs/
+EXE := ${PP}/Exec/
+INC := ${DPCDEVREP}/Include/
+GLB := /usr/local/lib/
+#--
+
+#-   Flag for optimisation/ debug
+# Pour forcer sans debug, DBGFLAG = -g0
+ifndef OPTFLAG
+  OPTFLAG  := -O
+endif
+
+ifndef DBGFLAG
+  DBGFLAG  := -g
+#  Probleme sur DEC/OSF1 -g avec g++/egcs pose probleme a l'assembleur
+#                    Reza 09/99 - On met -gcoff
+  ifeq (${MACHEROS},OSF1)
+    ifeq ($(CXX), g++)
+      override DBGFLAG := -gcoff
+    endif
+  endif
+endif
+
+# DBGFLAG a -g0 veut dire pas de debug. Tout le monde a ca par defaut...
+ifeq ($(DBGFLAG), -g0)
+  override DBGFLAG :=
+endif
+
+# xlC ne connait pas -O0, par defaut il n'optimise pas.
+ifeq ($(OPTFLAG), -O0)
+  ifeq ($(CC), xlC)
+    override OPTFLAG :=
+  endif
+endif
+
+AR       := ar
+ARFLAGS  := -rcs
+
+# le gnu ar ne fonctionne pas bien sur OSF...
+ifeq (${MACHEROS},OSF1)
+AR       := /usr/bin/ar
+endif
+# et sur AIX il nous sort des tas de warnings inutiles
+ifeq ($(MACHEROS),AIX)
+AR := /usr/bin/ar
+endif
+
+#   Avec certains compilateurs C++ (KCC, aCC) , il faut fabriquer les librairies et 
+# les shared libs avec la meme commande 
+override ARCXX := $(AR) 
+override ARCXXFLAGS := $(ARFLAGS) 
+#RZ0999 ifeq ($(CXX),KCC)
+#RZ0999 override  ARCXX  := KCC
+#RZ0999 override ARCXXFLAGS  := -o
+#RZ0999 endif
+ifeq ($(CXX),aCC)
+override ARCXX  := aCC 
+override ARCXXFLAGS  := -o
+endif
+
+# Les chemins speciaux pour includes systemes et bibliotheques
+ifeq (${MACHEROS},HP-UX)
+  XLDLIBS := -L.
+  XCFLAGS := -I.
+endif
+
+
+#  Pour compiler PI, sous Linux, les includes et libs se trouve souvent ds /usr/X11/include /usr/X11/lib/
+ifeq (${MACHEROS},Linux)
+  XLDLIBS := -L/usr/X11/lib -L/usr/X11R6/lib
+  XCFLAGS := -I/usr/X11/include -I/usr/X11R6/include
+  LDLIBS := -ldl
+endif
+
+# Chemin pour les include et fichiers d'autres librairies
+EXTINCPI := 
+EXTLIBPL := 
+EXTSLBPL := 
+EXTINCPATH := 
+EXTLIBPATH := 
+EXTSLBPATH := 
+
+ifdef EXTLIBDIR
+ EXTINCPI := -I$(EXTLIBDIR)/Include/
+ EXTLIBPL := -L$(EXTLIBDIR)/$(MACHDIR)/Libs/
+ EXTSLBPL := -L$(EXTLIBDIR)/$(MACHDIR)/ShLibs/
+ EXTINCPATH := $(EXTLIBDIR)/Include/
+ EXTLIBPATH := $(EXTLIBDIR)/$(MACHDIR)/Libs/
+ EXTSLBPATH := $(EXTLIBDIR)/$(MACHDIR)/ShLibs/
+endif
+
+#  S'il y a des flags particulier pour un module de compilation
+#ifndef MODULECPPFLAGS
+  override MODULECPPFLAGS :=
+#endif
+
+CPPFLAGS     :=  -I${INC} $(EXTINCPI) -D${MACHEROSD} $(MODULECPPFLAGS)
+
+# Les options selon les divers compilateurs
+# GNU
+ifeq ($(CC), gcc)
+  CFLAGS       := -Wall -Wpointer-arith \
+                  -Wmissing-prototypes -Wsynth -I$(INC) $(XCFLAGS) \
+                  $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS)
+  LDLIBS       := $(LDLIBS) $(XLDLIBS)
+endif
+ifeq ($(CC), egcs)
+  CFLAGS       := -Wall -Wpointer-arith \
+                  -Wmissing-prototypes -Wsynth -I$(INC) $(XCFLAGS) \
+                  $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS)
+  LDLIBS       := $(LDLIBS) $(XLDLIBS)
+endif
+
+ifeq ($(CXX), g++)
+  CXXFLAGS       := -Wall -Wpointer-arith \
+                    -Wmissing-prototypes -Wsynth -I$(INC) $(XCFLAGS) \
+                    $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) 
+  LDLIBS      := $(LDLIBS) $(XLDLIBS)
+#  ifdef NOSHLIB 
+#    LDFLAGS := -static
+#  endif
+endif
+ifeq ($(CXX), egcs++)
+  CXXFLAGS       := -Wall -Wpointer-arith \
+                    -Wmissing-prototypes -Wsynth -I$(INC) $(XCFLAGS) \
+                    $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) 
+  LDLIBS      := $(LDLIBS) $(XLDLIBS)
+  ifdef NOSHLIB 
+    LDFLAGS := -static
+  endif
+endif
+
+# Compilateur C natif HP-UX
+ifeq (${MACHEROS},HP-UX)
+ifeq ($(CC),cc)                                    
+  CFLAGS       :=  +Z -Aa -Ae $(XCFLAGS) $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) 
+  FFLAGS       :=  -Aa -I${INC}   -D${MACHEROSD}  
+  CPPFLAGS     :=  -I${INC}  -I$(INC)/tnt -D${MACHEROSD} \
+               -D_HPUX_SOURCE $(MODULECPPFLAGS)
+  LDLIBS      := $(XLDLIBS)
+  override NOSHLIB := Y
+
+endif
+ifeq ($(CXX),aCC)
+  CXXFLAGS := $(XCFLAGS) $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) +Z -D__aCC__
+#  -DCOMPILER_EXCEPTIONS -D__ANSI_TEMPLATES__  definis ds defs.h
+endif
+endif
+
+# AIX, xlC comme compilateur C et C++
+ifeq ($(CXX), xlC)
+  CFLAGS := $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) $(XCFLAGS)
+  CPPFLAGS := -I$(INC)/Syst -I${INC}  -I$(INC)/tnt -D${MACHEROSD} $(MODULECPPFLAGS)
+  CXXFLAGS     := $(CFLAGS) -D__xlC -DCOMPILER_EXCEPTIONS
+# -DCOMPILER_EXCEPTIONS defini ds defs.h
+  LDLIBS      := $(XLDLIBS)
+
+# Pour faire des bibliotheques partagees, il faut faire un truc du
+# style 
+#ld -o shrsub.o subs1.o subs2.o -bE:shrsub.exp -bM:SRE -lc
+
+# Pour le moment on ne se fatigue pas, tant pis
+  override NOSHLIB := Y
+
+# Et puis 1540-293: (W) est un FAUX warning, on supprime les warnings
+  CXXFLAGS := -qflag=e $(CXXFLAGS)
+endif
+
+
+ifeq ($(CXX), cxx)
+  ifeq ($(DBGFLAG), -g)
+    ifdef OPTFLAG
+      override DBGFLAG := -g1
+    endif
+#    ifdef XOPT
+#      override DBGFLAG := -g1
+#    endif
+  endif
+
+# chemin pour repository CXX
+ REP := $(OBJ)/cxxrep/
+ REPPI := $(OBJ)/cxxrep_PI/
+ REPCXX := -ptr $(OBJ)/cxxrep/
+ ifdef MODULECXXREPNAME
+   REPCXX := -ptr $(OBJ)/cxxrep_$(MODULECXXREPNAME)/  -ptr $(OBJ)/cxxrep/
+   REPM := $(OBJ)/cxxrep_$(MODULECXXREPNAME)/
+ endif
+
+  LDLIBS      := $(XLDLIBS) -lrt
+
+  CXXFLAGS := $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) -DCOMPILER_EXCEPTIONS  \
+              $(REPCXX) -no_implicit_include 
+# $(REPCXX) -no_implicit_include -D__USE_STD_IOSTREAM  passe pas avec cxx 6.0 Reza 23/12/99
+  CFLAGS := $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS)
+#  CXXFLAGS := $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS) -DCOMPILER_EXCEPTIONS \
+#	      -nopt -define_templates
+  ifeq ($(XOPT), 1)
+    override DBGFLAG :=
+    CXXFLAGS := $(DBGFLAG) $(MYCFLAGS) -DCOMPILER_EXCEPTIONS \
+	        $(REPCXX) -fp_reorder \
+	        -O5 -inline speed -tune host
+  endif
+  ifeq ($(XOPT), 2)
+    override DBGFLAG :=
+    CXXFLAGS := $(DBGFLAG) $(MYCFLAGS) -DCOMPILER_EXCEPTIONS \
+	      $(REPCXX) -fp_reorder \
+	      -O5 -inline speed -tune host \
+	      -assume trusted_short_alignment
+  endif
+  ifeq ($(XOPT), 3)
+    override DBGFLAG :=
+    CXXFLAGS := $(DBGFLAG) $(MYCFLAGS) -DCOMPILER_EXCEPTIONS \
+	      $(REPCXX) -fp_reorder \
+	      -O5 -inline speed -tune host \
+	      -assume trusted_short_alignment \
+	      -non_shared -om
+    override NOSHLIB := Y
+  endif
+
+# le fichier X11/Xlib.h contient des declarations de fonctions sans type
+# Cela genere un grand nombre de warning avec cxx V6
+# La variable MODULEDECCXXFLAGS permet de specifier des options de compilation 
+# pour un module donne  
+  ifdef MODULEDECCXXFLAGS
+    CXXFLAGS := $(CXXFLAGS) $(MODULEDECCXXFLAGS)
+  endif
+endif
+ifeq ($(CC),cc)
+  ifeq ($(MACHEROS),OSF1)
+  ifeq ($(XOPT), 1)
+    CFLAGS :=  $(DBGFLAG) $(MYCFLAGS) -fp_reorder \
+	      -O4 -inline speed -tune host
+  endif
+  ifeq ($(XOPT), 2)
+    CFLAGS :=  $(DBGFLAG) $(MYCFLAGS) -fp_reorder \
+	      -O4 -inline speed -tune host \
+	      -assume trusted_short_alignment -fast
+  endif
+  ifeq ($(XOPT), 3)
+    CFLAGS :=  $(DBGFLAG) $(MYCFLAGS) -fp_reorder \
+	      -O4 -inline speed -tune host \
+	      -assume trusted_short_alignment -fast \
+	      -non_shared -om
+  endif
+  endif
+endif
+
+# --- Compilateur KAI  (OK pour v 3.3)
+ifeq ($(CXX), KCC)
+  CXXFLAGS     :=  --exceptions --rtti  --auto_instantiation --one_instantiation_per_object -D__KCC__
+# Flag --one_instantiation_per_object mis - Reza 02/03/99
+# -DCOMPILER_EXCEPTIONS -D__ANSI_TEMPLATES__  definis ds defs.h 
+endif
+
+# --- Compilateur natif CC de SGI 
+ifeq ($(MACHEROS), IRIX64)
+  ifeq ($(CXX), CC)
+    CXXFLAGS     :=  -prelink -D__SGICC__
+    LINK.cc := CC $(CPPFLAGS) -D__SGICC__ $(DBGFLAG) $(OPTFLAG)
+  endif
+endif
+
+# Autres compilateurs natifs.
+
+#  CFLAGS       :=  -I$(INC) $(XCFLAGS) $(OPTFLAG) $(DBGFLAG) $(MYCFLAGS)
+#  CXXFLAGS     := $(CFLAGS)
+#  LDLIBS      := $(XLDLIBS)
+
+#- redefine implicit rule. Les .o sont dans $(OBJ).
+$(OBJ)%.o:%.c
+	$(COMPILE.c) -o $@ $<
+
+$(OBJ)%.o:%.cc
+	$(COMPILE.cc) -o $@ $<
+
+$(OBJ)%.o:%.f
+	$(COMPILE.f) -o $@ $< 
+
+#OSF1
+#LDFC est f77
+#LDFCFLAGS est rien
+
+#parfois
+#LDFC est cc
+#LDFCFLAGS est -ltruc
+
+#------------------------------------------------- End of Makefile.h ------- 
Index: /tags/V_Fev00/SophyaLib/Mgr/Makefile.slb
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/Makefile.slb	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/Makefile.slb	(revision 752)
@@ -0,0 +1,118 @@
+#  -*- makefile -*-
+# #########################  Sophya ############################# 
+# ##### LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA #####
+# ############################################################### 
+# General setup GNU Makefile for Sopyha/Planck. To be included 
+# for building shared libraries
+#---------------------------------------------------------------------------
+
+#  Chemin des librairies Motifs / X11 (pour chemin non standard)
+LIBXPIPATH :=
+# et liste des librairies pour PI (X11, Motif) 
+LIBXPILIST := -lXm -lXt -lX11
+
+#  External libraries
+EXTLIB := 
+EXTSLB := 
+
+#  Commande de construction de shared-lib 
+CMDSHL := ld -partage
+#  Flag d'inclusion/fin d'inclusion de tous les points  d'entree
+FGSHLA := -tout
+FGSHLN := -rien
+#  Librairies specifiques 
+LIBLSHL := -lm -lc
+#  Librairie d'instanciation des templates 
+TILSHL := 
+TILSHLPI := 
+#   Commande de construction de la librairie d'instanciation des templates 
+CMDTILSHL := echo 'No Template instanciation library (.a)'
+CMDTILSHLPI  := echo 'No Template instanciation library (.a)'
+# Utilisation du compilo C++ comme driver pour fabrication des shared-libs
+CMDSHLCXX := $(LINK.cc) 
+FGSHLACXX :=  
+FGSHLNCXX := 
+#  S'il faut utiliser $(CMDSHLCXX) pour fabrication des shared-libs
+USECXX4SO := Y
+# On utilise le compilo g++ pour la fabrication des shared libs
+ifeq ($(EROSCXX), g++)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc) -shared
+endif
+
+# On utilise le compilo KCC pour la fabrication des shared libs
+ifeq ($(EROSCXX), KCC)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc)
+endif
+
+# On utilise le compilo aCC (HP) pour la fabrication des shared libs
+ifeq ($(EROSCXX), aCC)
+  override USECXX4SO := Y
+  override CMDSHLCXX := $(LINK.cc) -b
+endif
+
+# Construction de shared-libs sous OSF1
+ifeq ($(MACHEROS),OSF1)
+  override CMDSHL := ld -shared -update_registry $(SLB)so_locations
+  override FGSHLA := -all
+  override FGSHLN := -none 
+  override LIBLSHL := -lcxxstd -lcxx -lexc -lm -lc -lrt
+  override TILSHL := $(LIB)libertcxx.a
+  override CMDTILSHL := rm -f $(LIB)libsotcxx.a ; cd $(REP); $(AR) $(ARFLAGS) $(LIB)libsotcxx.a *.o
+  override TILSHLPI := $(LIB)libsotcxxpi.a
+  override CMDTILSHLPI := rm -f $(LIB)libsotcxxpi.a ; cd $(REPPI); $(AR) $(ARFLAGS) $(LIB)libsotcxxpi.a *.o
+  ifeq ($(CXX),g++)
+    override LIBLSHL := $(LIBG) -lm -lc
+    override TILSHL := 
+    override TILSHLPI := 
+  endif
+#  Attention - Dangereux de mettre -expect_unresolved , enleve  Reza 17/11/99
+  override CMDSHLCXX :=  $(CXX) $(CXXFLAGS) -shared 
+  override FGSHLACXX := 
+  override FGSHLNCXX := 
+endif
+
+# Construction de shared-libs sous Linux
+ifeq ($(MACHEROS),Linux)
+  override CMDSHL := ld -shared 
+  override FGSHLA := --whole-archive
+  override FGSHLN := --no-whole-archiv
+  override CMDSHLCXX := $(LINK.cc) -shared 
+  ifeq ($(EROSCXX), KCC)
+    override CMDSHLCXX := $(LINK.cc)
+  endif
+  override FGSHLACXX := 
+  override FGSHLNCXX := 
+  override LIBLSHL := $(LIBG) -lm -ldl
+  override TILSHL := 
+  override LIBXPIPATH := -L/usr/X11/lib 
+  override LIBXPILIST := -lXm -lXt -lXext -lX11
+endif
+
+# Construction de shared-libs sous Sun-OS
+ifeq ($(MACHEROS),SunOS)
+  override CMDSHL := ld -G
+  override FGSHLA := -z allextract
+  override FGSHLN := -z weakextract
+  override LIBLSHL := $(LIBG) -lm -lc
+  override TILSHL := 
+  override LIBXPIPATH := -L/usr/X11/lib 
+  override USECXX4SO := Y
+endif
+
+# Construction de shared-libs sous SGI
+ifeq ($(MACHEROS), IRIX64)
+  override CMDSHL := ld -shared
+  override FGSHLA := -all
+  override FGSHLN := -notall
+  override LIBLSHL := $(LIBG) -lm -lc
+  override TILSHL := 
+  ifeq ($(EROSCXX), CC)
+    override CMDSHLCXX := CC -shared 
+    override LIBLSHL := -lm -lc
+  endif
+  override LIBXPIPATH := -L/usr/X11/lib 
+  override USECXX4SO := Y
+endif
+
Index: /tags/V_Fev00/SophyaLib/Mgr/README
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/README	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/README	(revision 752)
@@ -0,0 +1,83 @@
+=================== Module Mgr ==================
+===== Outils de gestion de code EROS/Planck =====
+=================================================
+
+Mini guide des scripts de gestion du code
+                          Reza 04/99
+
+
+* chk_cvs.csh
+--------------
+  Permet de comparer/ updater par rapport a la base CVS
+  Usage chk_cvs.csh [-a] [-all] [-nos] [-u] [r]
+  Exemple : se mettre au dessus de Mgr/
+  Mgr/chk_cvs.csh -u  
+  Update tous les modules   
+
+* crerep_peida 
+--------------
+  Creation des repertoires   $DEV/BASEREP/Include
+                                         /OSF1-cxx/
+                                         /OSF1-cxx/Objs
+                                         /OSF1-cxx/Libs
+                                         /OSF1-cxx/ShLibs
+                                         /OSF1-cxx/Exec/
+                                         ....
+  Usage crerep_peida <nom des repertoires> [nom_machine-compilateur]
+  Exemple crerep_peida $DPCDEVREP OSF1-cxx 
+          crerep_peida ~/Work/ Linux-g++
+
+* install_peida
+----------------
+  Script d'installation PEIDA (du soft)
+  depuis le repertoire de developpement vers le repertoire d'install
+  Copie des Include/*.h Libs/*.a ShLibs/*.so Exec/*
+
+  Usage install_peida <-s repertoire source> <-d repertoire destination>
+                      [-m nom_machine-compilateur]
+  Exemple install_peida -s  ~/Work  /exp/Planck/DPC
+
+* mkmf
+-------
+  Script de creation des GNUmakefile des differents modules,
+  et le GNUmakefile global, mis au niveau au dessus
+  Pour le makefile global, Makefile.slb est utilise
+
+  Les etapes :
+  - mkmflien : Cree des liens symboliques pour tous les .h des modules
+               ds $DEVREP/Include
+  - Creation du GNUmakefile global (pour appeler le make de chaque module)
+  - mkmflib 
+    Creation des GNUmakefile pour chaque module librairie
+    Note : Dans chaque module, un fichier exclude peut contenir 
+    la liste des fichiers (.cc, .c) qui ne doivent pas etre compile,
+    faire partie de la librairie
+
+  - mkmfPI
+    Creation des GNUmakefile pour les modules PI
+    note idem a mkmflib
+
+  - mkmfprog
+    Creation de GNUmakefile pour les modules ne contenant que des 
+    executables 
+
+
+En pratique, il suffit de se mettre ds Mgr/, avec la variable DPCDEVREP
+definie, et taper :
+mkmf, qui fait les etapes ci-dessus
+(a faire a chaque fois que l'on rajoute des fichiers),
+cree un GNUmakefile ds chaque module (SysTools/GNUmakefile, ...
+ et ../GNUmakefile )
+
+
+Pour construire le soft, se mettre au niveau de dessus
+tapez :
+make libs  # Pour construire les librairies .a
+           # Equivalent de faire make ds chaque module
+
+make slb   # Construit la(les) librairie(s) partagee(s)
+
+make PI    # Construit les modules PI (actuellement PI, PIext)
+
+make slbpi # construit la shared-lib libPI.so 
+
Index: /tags/V_Fev00/SophyaLib/Mgr/chk_cvs.csh
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/chk_cvs.csh	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/chk_cvs.csh	(revision 752)
@@ -0,0 +1,61 @@
+#!/bin/csh
+
+unset A
+unset U
+unset NOS
+unset R
+if( "$1" == '-h' ) then
+  echo "usage chk_cvs.csh [-a] [-all] [-nos] [-u] [r]"
+  echo "    -nos : pas de cvs status demande"
+  echo "      -a   : cvs status reduit  pour tous les fichiers"
+  echo "      -all : cvs status complet pour tous les fichiers"
+  echo "    -u   : update demande"
+  echo "    -r   : chmod a+r demande"
+  exit -1
+else
+  while( $#argv>0 )
+    if( "$1" == "-a") set A = 1
+    if( "$1" == "-all") set A = 2
+    if( "$1" == "-nos") set NOS
+    if( "$1" == "-u") set U
+    if( "$1" == "-r") set R
+    shift
+  end
+endif
+if( $?U || $?R ) set NOS
+
+set fall = (`ls -1`)
+set dcvs = ( )
+foreach f ( $fall )
+  if( -e $f/CVS ) set dcvs = ( $dcvs $f )
+end
+
+set CURDIR = `pwd`
+if( $?U ) echo "attention...... UPDATE demande"
+
+foreach d ( $dcvs )
+  if (-e $CURDIR/$d)  then
+    echo " " ; echo " "
+    echo "******************************************"
+    echo "   --- $d ---" ; echo " "
+    cd $CURDIR/$d
+    if( ! $?NOS ) then
+      if( $?A ) then
+        if( $A == 1 ) then
+          cvs status | grep Status
+        else if( $A == 2 ) then
+          cvs status
+        endif
+      else
+        cvs status | grep Status | grep -v "Up-to-date"
+      endif
+    endif
+    if( $?U ) cvs update
+    if( $?R ) then
+      chmod -R a+r *
+    endif
+  endif
+end
+
+cd $CURDIR
+exit 0
Index: /tags/V_Fev00/SophyaLib/Mgr/crecxx.file
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/crecxx.file	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/crecxx.file	(revision 752)
@@ -0,0 +1,16 @@
+cimage.h
+circrfix.h
+daofind.h
+deflat.h
+dynccd.h
+fitsimage.h
+imageop.h
+killbad.h
+photfitpsf.h
+photfixedap.h
+pixeliter.h
+psf2dfit.h
+qualite.h
+rebinimage.h
+rzimage.h
+sharedimage.h
Index: /tags/V_Fev00/SophyaLib/Mgr/crerep_peida
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/crerep_peida	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/crerep_peida	(revision 752)
@@ -0,0 +1,50 @@
+#!/bin/csh
+
+if( $#argv < 1 ) then
+  echo "crerep_peida <nom des repertoires> [nom_machine-compilateur]"
+  echo " - ex: crerep_peida "\$"GROUP_DIR/PeidaWork HP-UX"
+  echo " - possibilites nom_machine-compilateur"
+  echo "    [AIX-xlC AIX-g++ HP-UX-aCC HP-UX-g++ OSF1-cxx OSF1-g++ Linux-g++ ...]"
+  if($?EROSCXX) then
+    echo "    defaut: `uname`-$EROSCXX"
+  else
+    echo "    pas de defaut donnez explicitement nom_machine-compilateur"
+  endif
+  exit -1
+endif
+
+set dirl = $1
+if ( ! -e ${dirl} ) then
+  echo ATTENTION REPERTOIRE INEXISTANT:
+  echo ${dirl}
+  exit -1
+endif
+echo "rep. de base: ${dirl}"
+
+shift
+if( $#argv > 0 ) then
+  set diru = $1
+  echo "machine-compilateur: ${diru}"
+else if ($?EROSCXX) then
+  echo uname=`uname` EROSCXX = $EROSCXX
+  set diru = `uname`-$EROSCXX
+  echo "AUTOMATIQUE machine-compilateur: ${diru}"
+else
+  echo "precisez nom_machine-compilateur ou EROSCXX"
+  exit -1
+endif
+
+foreach d ( ${dirl}/${diru} \
+            ${dirl}/Include \
+            ${dirl}/${diru}/Exec \
+            ${dirl}/${diru}/Libs ${dirl}/${diru}/ShLibs \
+            ${dirl}/${diru}/Objs )
+  if ( -e $d ) then
+    echo "rep. existant: $d"
+  else
+    echo "rep. cree: $d"
+    mkdir $d
+  endif
+end
+
+exit 0
Index: /tags/V_Fev00/SophyaLib/Mgr/extlibdirs
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/extlibdirs	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/extlibdirs	(revision 752)
@@ -0,0 +1,2 @@
+FitsIOServer
+
Index: /tags/V_Fev00/SophyaLib/Mgr/history_eros
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/history_eros	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/history_eros	(revision 752)
@@ -0,0 +1,38 @@
+Mgr from Mgr
+Mgr from Mgr
+-----------> Makefile.h
+   Nettoyage et MAJ Repository revision:	1.61
+-----------> Makefile.slb
+   Nettoyage et MAJ Repository revision:	1.26
+-----------> chk_cvs.csh
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Mgr/chk_cvs.csh,v
+-----------> crecxx.file
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Mgr/crecxx.file,v
+-----------> crerep_peida
+   Repository revision:	1.5	/projects/Eros/CVSEros/CodeCxx/Mgr/crerep_peida,v
+-----------> install_peida
+   Repository revision:	1.5	/projects/Eros/CVSEros/CodeCxx/Mgr/install_peida,v
+-----------> libdirs
+   Repository revision:	1.7	/projects/Eros/CVSEros/CodeCxx/Mgr/libdirs,v
+-----------> libdirs_ccpn
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Mgr/libdirs_ccpn,v
+-----------> makefileuser.awk
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Mgr/makefileuser.awk,v
+-----------> mkmf
+   Repository revision:	1.36	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmf,v
+   MAJ                  1.39    pour flag powerpc - mais pas pour HP-UX slb (.sl)
+-----------> mkmfPI
+   Repository revision:	1.15	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmfPI,v
+-----------> mkmflib
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmflib,v
+   MAJ                  1.12    $(AR) et $(ARFLAGS) -> $(ARCXX) et $(ARCXXFLAGS)
+-----------> mkmflien
+   Repository revision:	1.15	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmflien,v
+-----------> mkmfprog
+   Repository revision:	1.20	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmfprog,v
+-----------> mkmfprog.awk
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Mgr/mkmfprog.awk,v
+-----------> progdirs
+   Repository revision:	1.3	/projects/Eros/CVSEros/CodeCxx/Mgr/progdirs,v
+-----------> progdirs_ccpn
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Mgr/progdirs_ccpn,v
Index: /tags/V_Fev00/SophyaLib/Mgr/install_peida
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/install_peida	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/install_peida	(revision 752)
@@ -0,0 +1,122 @@
+#!/bin/csh
+#  Script d'installation SOPHYA 
+#  Version preliminaire - Reza 27/11/97 +cmv
+
+if( "$1" == "-h" ) then
+  echo "install_peida <-s repertoire source> <-d repertoire destination>"
+  echo "              [-m nom_machine-compilateur]"
+  if($?DPCDEVREP) then
+    echo " - defaut repertoire source: $DPCDEVREP"
+  else
+    echo "   pas de defaut donnez explicitement le repertoire source"
+  endif
+  if($?DPCBASEREP) then
+    echo " - defaut repertoire destination: $DPCBASEREP"
+  else
+    echo "   pas de defaut donnez explicitement le repertoire destination"
+  endif
+  echo " - possibilites nom_machine-compilateur"
+  echo "    [AIX-xlC AIX-g++ HP-UX-aCC HP-UX-g++ OSF1-cxx OSF1-g++  Linux-g++ ...]"
+  if($?EROSCXX) then
+    echo "    defaut: `uname`-$EROSCXX"
+  else
+    echo "    pas de defaut donnez explicitement nom_machine-compilateur"
+  endif
+  exit -1
+endif
+
+unset srcdir
+unset dstdir
+unset macomp
+
+while( $#argv > 1 )
+  if( "$1" == "-s" ) then
+    set srcdir = $2
+  endif
+  if( "$1" == "-d" ) then
+    set dstdir = $2
+  endif
+  if( "$1" == "-m" ) then
+    set macomp = $2
+  endif
+  shift
+  shift
+end
+
+if( ! $?srcdir && $?DPCDEVREP ) then
+  echo "defaut srcdir set to DPCDEVREP"
+  set srcdir = $DPCDEVREP
+endif
+if( ! $?dstdir && $?DPCBASEREP ) then
+  echo "defaut dstdir set to DPCBASEREP"
+  set dstdir = $DPCBASEREP
+endif
+if( ! $?macomp && $?EROSCXX ) then
+  echo "defaut macomp set to uname-EROSCXX"
+  set macomp = `uname`-$EROSCXX
+endif
+
+if( ! $?srcdir || ! $?dstdir || ! $?macomp ) then
+  echo "precisez ce que vous voulez:"
+  echo srcdir=$?srcdir dstdir=$?dstdir macomp=$?macomp
+  exit -1
+else
+  set SRC = $srcdir/$macomp
+  set DST = $dstdir/$macomp
+  echo "************** SOPHYA_Install script : ****************** "
+  echo "copie de $srcdir"
+  echo "      vers $dstdir pour $macomp"
+  echo "      pour $macomp"
+  # echo "SRC= $SRC , DST= $DST"
+  echo "********************************************************"
+endif
+
+#set DO = echo
+set DO =
+
+# d'abord les includes
+#foreach d ( Include Include/tnt Include/CInc Include/SystCxx Include/Syst )
+foreach d ( Include  Include/ArchTOI )
+  echo "SOPHYA_Install: Installing $d ... "
+  if( ! -e $srcdir/$d ) then
+    echo "rep. inexistant: $SRC/$d"
+#  else  if( ! -e $dstdir/$d ) then
+#    echo "rep. inexistant: $DST/$d"
+#    endif
+  else
+    if( ! -e $dstdir/$d ) then
+	echo "rep. inexistant: $dstdir/$d -> mkdir"
+	mkdir $dstdir/$d
+    endif
+    cd $srcdir/$d
+    $DO cp * $dstdir/$d/
+    $DO chmod -R a+r $dstdir/$d/
+  endif
+end
+
+# puis le reste
+foreach d ( Libs ShLibs Exec )
+  echo "SOPHYA_Install: Installing $d ... "
+  if( ! -e $SRC/$d ) then
+    echo "rep. inexistant: $SRC/$d"
+  else if( ! -e $DST/$d ) then
+    echo "rep. inexistant: $DST/$d"
+  else
+    if( "$d" == "Exec" ) then
+      foreach f ( scanppf tobjio tspm tspm2 spiapp tgsky tgrsr skymixer )
+        if( -e $SRC/$d/$f ) then
+          $DO cp $SRC/$d/$f $DST/$d/.
+        endif
+      end
+      $DO chmod -R a+x $DST/$d/
+    else
+      cd $SRC/$d/.
+      $DO cp * $DST/$d/.
+    endif
+    $DO chmod -R a+r $DST/$d/
+  endif
+end
+
+echo 'SOPHYA_Install complete'
+
+exit 0
Index: /tags/V_Fev00/SophyaLib/Mgr/libdirs
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/libdirs	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/libdirs	(revision 752)
@@ -0,0 +1,4 @@
+SysTools
+NTools
+Samba
+SkyT
Index: /tags/V_Fev00/SophyaLib/Mgr/libdirs_ccpn
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/libdirs_ccpn	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/libdirs_ccpn	(revision 752)
@@ -0,0 +1,3 @@
+Outils++
+Images++
+StarReco++
Index: /tags/V_Fev00/SophyaLib/Mgr/lnktofftw.csh
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/lnktofftw.csh	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/lnktofftw.csh	(revision 752)
@@ -0,0 +1,10 @@
+#! /bin/csh 
+#  Pour creer des liens sur libFFTW et creer le shared-lib correspondant
+#        Reza 04/99
+#
+cd ~/DPC/Linux-g++/Libs/
+ln -s /usr/local/lib/libfftw.a libfftw.a
+ln -s /usr/local/lib/librfftw.a librfftw.a
+ln -s /usr/local/include/fftw.h ../../Include/
+ln -s /usr/local/include/rfftw.h ../../Include/
+ld -shared -o ../ShLibs/libfftw.so -L. --whole-archive -lfftw -lrfftw --no-whole-archive -lm -lc
Index: /tags/V_Fev00/SophyaLib/Mgr/makefileuser.awk
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/makefileuser.awk	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/makefileuser.awk	(revision 752)
@@ -0,0 +1,25 @@
+BEGIN {change=0;}
+/^PP  := \$\{DPCDEVREP\}\/\$\{MACHDIR\}\// {
+  print "PP  := \$\{DPCBASEREP\}\/\$\{MACHDIR\}\/";
+  print "PPH := \$\{HOME\}\/\$\{MACHDIR\}\/";
+  change=1;
+}
+/^OBJ := \$\{PP\}\/Objs\// {
+  print "OBJ := \$\{PPH\}\/Objs\/";
+  change=1;
+}
+/^EXE := \$\{PP\}\/Exec\// {
+  print "EXE := \$\{PPH\}\/Exec\/";
+  change=1;
+}
+/^INC := \$\{DPCDEVREP\}\/Include\// {
+  print "INC := \$\{DPCBASEREP\}\/Include\/";
+  change=1;
+}
+{
+  if(change==0) print $0
+  change=0;
+}
+END {
+print "# fin gene auto MakefileUser.h"
+}
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmf
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmf	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmf	(revision 752)
@@ -0,0 +1,222 @@
+#!/bin/csh 
+# $Id: mkmf,v 1.10 2000-03-02 10:57:51 ansari Exp $
+
+#  Pour debugger 
+set DODBG = 'echo'
+set DODBG = ''
+
+# Librairies externe
+if( ! $?EXTLIBDIR ) then
+  echo 'mkmf- WARNING (External libraries) EXTLIBDIR variable not set'
+endif
+
+# creation de MakefileUser.h a partir de Makefile.h
+echo 'mkmf: Creating MakefileUser.h'
+cat Makefile.h | awk -f makefileuser.awk >! MakefileUser.h
+
+# creation des liens pour les includes
+echo 'mkmf: Creating links for *.h (call mkmflien)'
+$DODBG ./mkmflien
+
+# Liste des modules a construire
+# modules : Liste de module SOPHYA, sans dependance exterieure
+# extmodules : Liste de modules avec dependance exterieures
+#        _pres : Liste des modules presents
+
+set modules = `cat libdirs`
+set extmodules = `cat extlibdirs` 
+set modules_pres = ''
+set extmodules_pres = ''
+
+set module_libnames = ''
+set extmodule_libnames = ''
+set extlib_list = ''
+set extslb_list = ''
+#  Constitution de la liste de modules present
+foreach f ($modules)
+  if (-d ../$f ) then
+    set modules_pres = ( $modules_pres $f )
+    set module_libnames = ( $module_libnames '$(LIB)lib'$f.a )
+  endif
+end
+foreach f ($extmodules)
+  if (-d ../$f ) then
+    set extmodules_pres = ( $extmodules_pres $f )
+    set extmodule_libnames = ( $extmodule_libnames '$(LIB)lib'$f.a )
+    set lil = "../$f/extlib_list"
+    if (-f $lil ) set extlib_list = ($extlib_list `sed -e 's/.*/-l&/' $lil`) 
+    set lil = "../$f/extslb_list"
+    if (-f $lil ) set extslb_list = ($extslb_list `sed -e 's/.*/-l&/' $lil`) 
+  endif
+end
+
+echo 'mkmf: List of modules ' 
+echo '  ... modules= ' $modules_pres
+echo $module_libnames 
+echo '  ... extmodules= ' $extmodules_pres
+echo $extmodule_libnames 
+
+echo 'mkmf: Creating makefile global :'
+rm -f GNUmakefile
+
+echo '# include files defining compiler/linker options '  >> GNUmakefile
+echo 'MODULECXXREPNAME := PI'  >> GNUmakefile
+echo 'include Mgr/Makefile.h' >> GNUmakefile
+echo 'include Mgr/Makefile.slb' >> GNUmakefile
+echo ''   >> GNUmakefile
+
+echo 'LIBF = ' `sed -e 's/.*/$(LIB)lib&.a/' libdirs` >> GNUmakefile
+echo 'LIBS = -L$(LIB)' `sed -e 's/.*/-l&/' libdirs` '-lm' >> GNUmakefile
+echo 'LIBG = -L$(GLB) -lstdc++' >> GNUmakefile
+echo 'ifeq ($(HOSTTYPE), powerpc)' >> GNUmakefile
+echo '  LIBG = -L$(GLB)' >> GNUmakefile
+echo 'endif' >> GNUmakefile
+
+cat >> GNUmakefile <<EOF
+
+defaut: libs
+
+all: libs extlibs PI
+
+libs: cxxlibs
+
+extlibs: cxxextlibs
+
+EOF
+
+# Dans cet ordre pour les templates de cxx, a cause des dependances
+# pour instantiation automatique/manuels
+
+echo 'cxxlibs: ' $modules_pres >>    GNUmakefile
+echo ' ' >> GNUmakefile 
+echo 'cxxextlibs: ' $extmodules_pres >> GNUmakefile
+
+
+#  Attention, ne pas changer l'ordre de libnames dependances cxx  ????? 
+set libnames = ($modules_pres $extmodules_pres)
+set i = 1
+set j = $#libnames ; @ j--
+while ($i <= $#libnames)
+  set f = $libnames[$i]
+  set k = $i ; @ k++
+  if ( -d ../$f ) then 
+    set cmd = "./mkmflib $f "
+    echo "mkmf: Creation makefile lib $f"
+    echo "   execution $cmd"
+    $DODBG $cmd
+  endif
+  echo '.PHONY: ' $f >> GNUmakefile
+  echo $f':' >> GNUmakefile
+  echo '	if [ -d '$f' ] ; then cd ' $f '; $(MAKE) ; fi' >> GNUmakefile
+  echo ' ' >> GNUmakefile
+  @ i++
+end
+
+
+if ( -d ../PI ) then 
+  set cmd = './mkmfPI PI SysTools'
+  echo "mkmf: Creation makefile lib PI"
+  echo "   execution $cmd"
+  $DODBG  $cmd
+endif
+if ( -d ../PIext ) then 
+  set cmd = "./mkmfPI PIext $libnames PI"
+  echo "mkmf: Creation makefile lib PIext"
+  echo "   execution $cmd"
+  $DODBG $cmd
+endif
+echo '.PHONY: PI' >> GNUmakefile
+echo 'PI:' >> GNUmakefile
+echo '	if [ -d PI ] ; then cd PI ; $(MAKE) ; fi' >> GNUmakefile
+echo '	if [ -d PIext ] ; then cd PIext ; $(MAKE) ; fi' >> GNUmakefile
+
+
+echo 'mkmf: Writing shared library building part of the makefile :'
+
+echo '#  Shared library creation part of the Makefile'       >> GNUmakefile
+echo ' '                                 >> GNUmakefile
+echo '#  List of libraries (.a)'         >> GNUmakefile
+echo 'PSLB = ' $module_libnames          >> GNUmakefile
+echo 'EXTPSLB = ' $extmodule_libnames    >> GNUmakefile
+echo 'PIPSLB =  $(LIB)libPI.a  $(LIB)libPIext.a'   >> GNUmakefile
+echo '#  List of external library references'       >> GNUmakefile
+echo 'EXTLIB  = -L$(EXTLIBPATH)' $extlib_list       >> GNUmakefile
+echo 'EXTSLB  = -L$(EXTSLBPATH)' $extslb_list       >> GNUmakefile
+echo 'XPILIBS = $(LIBXPIPATH) $(LIBXPILIST)'        >> GNUmakefile
+echo ''                                  >> GNUmakefile
+echo '#  main dependence list'           >> GNUmakefile
+echo 'slball : slb slbext slbpi '        >> GNUmakefile
+echo 'slb : $(SLB)libsophya.so '         >> GNUmakefile
+echo 'slbext : $(SLB)libextsophya.so   ' >> GNUmakefile
+echo 'slbpi : $(SLB)libPI.so'            >> GNUmakefile
+echo ' '                                 >> GNUmakefile
+
+echo '# List of .o files for each module'  >> GNUmakefile
+set objalls =  ''
+foreach f ($modules_pres)
+  echo 'OBJ'$f '= $(shell echo' '`cat' "./$f/$f.o.list" '`)'  >> GNUmakefile
+  set objalls = ( $objalls '$(OBJ'$f')' )
+end
+echo 'ALLOBJS =' $objalls                >> GNUmakefile
+echo ' '                                 >> GNUmakefile
+
+echo '# List of .o files modules with reference to external libraries'  >> GNUmakefile
+set objalls =  ''
+foreach f ($extmodules_pres)
+  echo 'OBJ'$f '= $(shell echo' '`cat' "./$f/$f.o.list" '`)'  >> GNUmakefile
+  set objalls = ( $objalls '$(OBJ'$f')' )
+end
+echo 'ALLEXTOBJS =' $objalls             >> GNUmakefile
+echo ' '                                 >> GNUmakefile
+
+echo '# List of .o files for PI modules '  >> GNUmakefile
+set objalls =  ''
+foreach f (PI PIext)
+  echo 'OBJ'$f '= $(shell echo' '`cat' "./$f/$f.o.list" '`)'  >> GNUmakefile
+  set objalls = ( $objalls '$(OBJ'$f')' )
+end
+echo 'ALLPIOBJS =' $objalls              >> GNUmakefile
+echo ' '                                 >> GNUmakefile
+
+echo '# Building Sophya shared library'  >> GNUmakefile
+echo '$(SLB)libsophya.so : $(PSLB)'                             >> GNUmakefile
+echo '	$(CMDTILSHL) '                                          >> GNUmakefile
+echo '	cd  $(OBJ); \'                                          >> GNUmakefile
+echo '	$(CMDSHLCXX) -o $(SLB)libsophya.so  \'                  >> GNUmakefile
+echo '	$(FGSHLACXX) $(ALLOBJS)  $(FGSHLNCXX)\'                 >> GNUmakefile
+echo '	-L$(SLB) $(LIBLSHL)'                                    >> GNUmakefile
+echo ' '                                                        >> GNUmakefile
+
+echo '# Building ExtSophya shared library'  >> GNUmakefile
+echo '$(SLB)libextsophya.so : $(EXTPSLB)'                       >> GNUmakefile
+echo '	$(CMDTILSHL) '                                          >> GNUmakefile
+echo '	cd  $(OBJ); \'                                          >> GNUmakefile
+echo '	$(CMDSHLCXX) -o $(SLB)libextsophya.so  \'               >> GNUmakefile
+echo '	$(FGSHLACXX) $(ALLEXTOBJS)  $(FGSHLNCXX)\'              >> GNUmakefile
+echo '	-L$(SLB) -lsophya $(EXTLIB) $(LIBLSHL)'                 >> GNUmakefile
+echo ' '                                                        >> GNUmakefile
+
+echo '# Building PI shared library'  >> GNUmakefile
+echo '$(SLB)libPI.so : $(PIPSLB)'                               >> GNUmakefile
+echo '	$(CMDTILSHL) '                                          >> GNUmakefile
+echo '	cd  $(OBJ); \'                                          >> GNUmakefile
+echo '	$(CMDSHLCXX) -o $(SLB)libPI.so  \'                      >> GNUmakefile
+echo '	$(FGSHLACXX) $(ALLPIOBJS) $(FGSHLNCXX) \'               >> GNUmakefile
+echo '	-L$(SLB) -lsophya -lextsophya $(EXTLIB) $(XPILIBS) $(LIBLSHL)'      >> GNUmakefile
+echo ' '                                                        >> GNUmakefile
+
+
+cat >> GNUmakefile << __END__
+
+clean:
+	if [ -d \$(LIB) ] ; then cd \$(LIB)/. ; rm -f *.a  ; fi
+	if [ -d \$(SLB) ] ; then cd \$(SLB)/. ; rm -f *.so ; fi
+	if [ -d \$(OBJ) ] ; then cd \$(OBJ)/. ; rm -f *.o  rm -rf cxxrep* ; fi
+#	if [ -d PI ]     ; then cd PI/.     ; \$(MAKE) clean ; fi
+
+__END__
+
+mv GNUmakefile ../GNUmakefile
+
+echo '*** mkmf done ***'
+
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmfPI
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmfPI	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmfPI	(revision 752)
@@ -0,0 +1,85 @@
+#!/bin/csh
+# $Id: mkmfPI,v 1.2 1999-10-22 09:23:25 ansari Exp $
+
+set makefname = 'GNUmakefile'
+
+cd ../$1
+
+if ( ! -f exclude_dpc ) touch exclude_dpc
+if ( ! $?TMPDIR ) set TMPDIR = /tmp
+sort exclude_dpc >! $TMPDIR/exclude.sort
+
+##############################################
+########### fichier de la liste des .o #######
+##############################################
+
+set liblist = $1.o.list
+rm -f $liblist
+ls *.{c,cc} | comm -3 -1 $TMPDIR/exclude.sort - | sed -e 's/\.cc/.o/' | sed -e 's/\.c/.o/' >> $liblist
+unset liblist
+
+##############################################
+########### Creation de GNUmakefile ##########
+##############################################
+
+set libf='$(LIB)lib'$1'.a'
+
+rm -f $makefname
+
+echo "MODULECXXREPNAME := PI" >>  $makefname
+
+set hfcxxlibs = '-L$(LIB)' 
+set i = 1
+while ($i <= $#argv)
+  set hfcxxlibs = "$hfcxxlibs -l$argv[$i]"
+  @ i++
+end
+
+
+
+# 04/98: le fichier X11/Xlib.h contient des declarations de fonctions sans type  
+# Cela genere un grand nombre de warning avec cxx V6 
+# On specifie donc -msg_quiet pour PI, ProgPI, ...
+echo 'MODULEDECCXXFLAGS := -msg_quiet' >> $makefname
+echo 'include ../Mgr/Makefile.h' >> $makefname
+
+echo " " >> $makefname
+
+set ccfiles  = `ls *.cc  | comm -3 -1 $TMPDIR/exclude.sort -`
+set objfiles = `ls *.cc  | comm -3 -1 $TMPDIR/exclude.sort - | sed -e 's/\.cc/.o/g' | sed -e 's/^/$(OBJ)/'`
+
+rm -f $TMPDIR/exclude.sort
+
+echo 'all:' $libf >> $makefname 
+
+echo $libf ':' $objfiles  >> $makefname
+echo '	$(AR) $(ARFLAGS)  $@ $? ' >> $makefname
+echo 'ifeq ($(CXX),cxx)' >> $makefname
+echo '	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS)' $hfcxxlibs '-o $(OBJ)xx.x -Hf' >> $makefname
+echo 'endif ' >> $makefname
+
+echo " " >> $makefname
+
+echo 'clean:' >> $makefname 
+echo '	rm -f '$objfiles >> $makefname
+echo 'ifeq ($(CXX),cxx)' >> $makefname
+echo '	cd $(REPM); rm -f *.o'  >> $makefname
+echo 'endif ' >> $makefname
+
+echo " " >> $makefname
+
+set inc = $DPCDEVREP/Include
+set incxx = $inc/CxxInc
+
+foreach f ( $ccfiles )
+  gcc -MM -I$inc -I$incxx $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/'  \
+       | sed -e 's?'$incxx/'?$(CXI)?g' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> $makefname
+end
+
+
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmflib
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmflib	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmflib	(revision 752)
@@ -0,0 +1,88 @@
+#!/bin/csh
+# $Id: mkmflib,v 1.4 2000-02-25 18:34:49 ansari Exp $
+
+cd ../$1
+
+if ( ! -f exclude ) touch exclude
+if ( ! -f flags_compil ) touch flags_compil
+if ( ! -f extlib_list ) touch extlib_list
+if ( ! -f extslb_list ) touch extslb_list
+
+if ( ! $?TMPDIR ) set TMPDIR = /tmp
+sort exclude >! $TMPDIR/exclude.sort
+
+##############################################
+########### fichier de la liste des .o #######
+##############################################
+
+set liblist = $1.o.list
+rm -f $liblist
+ls *.{c,cc} | comm -3 -1 $TMPDIR/exclude.sort - | sed -e 's/\.cc/.o/' | sed -e 's/\.c/.o/' >> $liblist
+unset liblist
+
+##############################################
+########### Creation de GNUmakefile ##########
+##############################################
+
+set libf='$(LIB)lib'$1'.a'
+
+set hfcxxlibs = '-L$(LIB)' 
+set i = 1
+while ($i <= $#argv)
+  set hfcxxlibs = "$hfcxxlibs -l$argv[$i]"
+  @ i++
+end
+
+set extlib_list = `cat extlib_list`
+set hfcxxlibs = ($hfcxxlibs '-L$(EXTLIBPATH)' $extlib_list)
+
+rm -f GNUmakefile
+
+cat flags_compil >> GNUmakefile 
+echo 'include ../Mgr/Makefile.h' >> GNUmakefile 
+
+echo " " >> GNUmakefile
+echo 'all:' $libf  >> GNUmakefile 
+
+echo 'clean:' >> GNUmakefile
+set toto='rm -f'
+foreach f (*.cc *.c) 
+  set toto= ( $toto '$(OBJ)'$f:r.o )
+end
+echo '	'$toto >> GNUmakefile
+echo '	rm -f '$libf >> GNUmakefile
+
+echo $libf ':' \
+ `ls *.{c,cc} | comm -3 -1 $TMPDIR/exclude.sort - | sed -e 's/\.cc/.o/' | sed -e 's/\.c/.o/' | sed -e 's/^/$(OBJ)/'` >> GNUmakefile
+echo '	$(ARCXX) $(ARCXXFLAGS) $@ $?' >> GNUmakefile
+#  Pour faire compiler les instantiations automatique de cxx (DEC)
+echo 'ifeq ($(CXX),cxx)' >> GNUmakefile
+echo '	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS)' $hfcxxlibs '-o $(OBJ)xx.x -Hf' >> GNUmakefile
+echo 'endif ' >> GNUmakefile
+
+rm -f $TMPDIR/exclude.sort
+
+echo " " >> GNUmakefile
+
+set inc = $DPCDEVREP/Include
+set incxx = $inc/CxxInc
+
+foreach f ( *.cc )
+  grep -q '^'$f'$' exclude && continue
+  gcc -MM -I$inc -I$incxx $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/'  \
+       | sed -e 's?'$incxx/'?$(CXI)?g' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> GNUmakefile
+end
+
+foreach f ( *.c )
+  grep -q '^'$f'$' exclude && continue
+  gcc -MM -I$inc -I$incxx $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/'  \
+       | sed -e 's?'$incxx/'?$(CXI)?g' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> GNUmakefile
+end 
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmflib_save
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmflib_save	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmflib_save	(revision 752)
@@ -0,0 +1,67 @@
+#!/bin/csh
+# $Id: mkmflib_save,v 1.2 1999-10-25 16:24:49 ansari Exp $
+
+cd ../$1
+set libf='$(LIB)lib'$1'.a'
+
+set hfcxxlibs = '-L$(LIB)' 
+set i = 1
+while ($i <= $#argv)
+  set hfcxxlibs = "$hfcxxlibs -l$argv[$i]"
+  @ i++
+end
+
+
+rm -f GNUmakefile
+
+echo 'include ../Mgr/Makefile.h' >> GNUmakefile 
+
+echo " " >> GNUmakefile
+echo 'all:' $libf  >> GNUmakefile 
+
+echo 'clean:' >> GNUmakefile
+set toto='rm -f'
+foreach f (*.cc *.c) 
+  set toto= ( $toto '$(OBJ)'$f:r.o )
+end
+echo '	'$toto >> GNUmakefile
+echo '	rm -f '$libf >> GNUmakefile
+
+if ( ! -f exclude ) touch exclude
+if ( ! $?TMPDIR ) set TMPDIR = /tmp
+sort exclude >! $TMPDIR/exclude.sort
+
+echo $libf ':' \
+ `ls *.{c,cc} | comm -3 -1 $TMPDIR/exclude.sort - | sed -e 's/\.cc/.o/' | sed -e 's/\.c/.o/' | sed -e 's/^/$(OBJ)/'` >> GNUmakefile
+echo '	$(AR) $(ARFLAGS) $@ $?' >> GNUmakefile
+#  Pour faire compiler les instantiations automatique de cxx (DEC)
+echo 'ifeq ($(CXX),cxx)' >> GNUmakefile
+echo '	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS)' $hfcxxlibs '-o $(OBJ)xx.x -Hf' >> GNUmakefile
+echo 'endif ' >> GNUmakefile
+
+rm -f $TMPDIR/exclude.sort
+
+echo " " >> GNUmakefile
+
+set inc = $DPCDEVREP/Include
+set incxx = $inc/CxxInc
+
+foreach f ( *.cc )
+  grep -q '^'$f'$' exclude && continue
+  gcc -MM -I$inc -I$incxx $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/'  \
+       | sed -e 's?'$incxx/'?$(CXI)?g' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> GNUmakefile
+end
+
+foreach f ( *.c )
+  grep -q '^'$f'$' exclude && continue
+  gcc -MM -I$inc -I$incxx $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/'  \
+       | sed -e 's?'$incxx/'?$(CXI)?g' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> GNUmakefile
+end 
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmflien
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmflien	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmflien	(revision 752)
@@ -0,0 +1,63 @@
+#!/bin/csh 
+# $Id: mkmflien,v 1.5 2000-02-25 18:34:49 ansari Exp $
+
+#########################################################
+#### repertoire contenant les repertoires du code+include
+#########################################################
+pushd ../.      > /dev/null
+set src = ` pwd | sed 's?^/tmp_mnt??' `
+popd            > /dev/null
+
+#############################################################
+#### repertoire contenant les liens a creer pour les includes
+#############################################################
+if( $#argv >= 1 ) then
+  set dst = $1
+else
+  set dst = $DPCDEVREP/Include
+endif
+if ( ! -d $dst/ ) then
+  echo repertoire $dst inconnu
+  exit -1
+endif
+
+#########################################################
+### Les includes a mettre dans Include pour les Makefiles
+#########################################################
+foreach f ( $src/Mgr/Makefile.h $src/Mgr/Makefile.slb $src/Mgr/MakefileUser.h )
+  if( -e $f ) then
+    ln -sf $f $dst/
+  endif
+end
+
+###################################################
+####  Les includes de tnt a mettre dans Include/tnt
+###################################################
+#if( -d $dst/tnt ) then
+#  if( -d $src/tnt ) then
+#    foreach f ( $src/tnt/*.h )
+#      ln -sf $f $dst/tnt/
+#    end
+#  endif
+#endif
+
+###################################################
+####  Les includes de Blitz++ lien ds Include
+###################################################
+if( -d $src/Blitz ) then
+  ln -sf $src/Blitz/blitz $dst/blitz
+endif
+
+####################################################
+####  Les includes du code C++ a mettre dans Include
+####################################################
+foreach d (`cat libdirs` `cat extlibdirs` PI PIext  )
+  if ( -d $src/$d ) then
+    echo $src/$d
+    foreach f ( $src/$d/*.h )
+      ln -sf $f $dst/
+    end
+  endif
+end
+
+exit 0
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmfprog
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmfprog	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmfprog	(revision 752)
@@ -0,0 +1,91 @@
+#!/bin/csh 
+# $Id: mkmfprog,v 1.1.1.1 1999-04-09 17:55:32 ansari Exp $
+
+# $1 : nom du repertoire
+# dans le repertoire, programs : liste des programs
+#                     usedlibs : liste des -L -l utilises
+#                     usedslibs : idem pour shlibs
+
+cd ../$1
+
+rm -f GNUmakefile
+
+
+echo 'MODULECXXREPNAME := ' $1  >> GNUmakefile
+# 04/98 : le fichier X11/Xlib.h contient des declarations de fonctions sans type
+# Cela genere un grand nombre de warning avec cxx V6 
+# On specifie donc -msg_quiet pour ProgPI
+if ($1 == 'ProgPI')  then
+  echo 'MODULEDECCXXFLAGS := -msg_quiet' >> GNUmakefile 
+endif
+echo 'include ../Mgr/Makefile.h' >> GNUmakefile
+
+echo ' ' >> GNUmakefile
+
+echo 'ifdef NOSHLIB'                                        >> GNUmakefile
+echo 'LIBF = ' `sed -e 's/.*/$(LIB)lib&.a/' usedlibs`       >> GNUmakefile
+echo 'LIBS = -L$(LIB)' `sed -e 's/.*/-l&/' usedlibs` ' -lm' >> GNUmakefile
+echo 'ifeq ($(CXX),cxx)'                                    >> GNUmakefile
+echo '# librairie des instances de templates cxx'           >> GNUmakefile
+echo 'LIBS := $(LIBS) -lertcxx'                             >> GNUmakefile
+echo 'endif' >> GNUmakefile 
+echo 'else'                                                 >> GNUmakefile
+echo 'LIBF = ' `sed -e 's/.*/$(SLB)lib&.so/' usedslibs`     >> GNUmakefile
+echo 'LIBS = -L$(SLB)' `sed -e 's/.*/-l&/' usedslibs` ' -lm'>> GNUmakefile
+echo 'endif'                                                >> GNUmakefile
+
+echo 'LIBSORA := $(LIBS)' >> GNUmakefile
+echo 'ifdef ORACLE_HOME' >> GNUmakefile
+echo 'LIBSORA := -L$(LIB) -lDb++ $(LIBS) -lErosDb -L$(ORACLE_HOME)/lib -lclntsh' >> GNUmakefile
+echo 'endif' >> GNUmakefile
+
+echo 'LDLIBS := $(LIBS) $(LDLIBS)' >> GNUmakefile
+
+set progaexe = programs
+if( -e programs_exe ) set progaexe = programs_exe
+echo 'PROGS = '`cut -d \  -f1 $progaexe | awk '{if(length($1)>0) print $1}' | sed -e 's/^/\$(EXE)/'` >> GNUmakefile
+unset progaexe
+
+echo " " >> GNUmakefile
+echo 'all: $(PROGS)' >> GNUmakefile 
+
+set cxxrepname = cxxrep_$1
+
+cat >> GNUmakefile << __END__
+
+clean:
+	rm -f \$(PROGS)
+	if [ -d \$(OBJ)$cxxrepname ] ; then cd \$(OBJ)$cxxrepname ; rm -f *.o ; fi
+
+__END__
+
+awk -f ../Mgr/mkmfprog.awk programs >> GNUmakefile
+
+#foreach f (`cat programs`)
+#  echo $f ': $(EXE)'$f >> GNUmakefile
+#  echo '	' >> GNUmakefile
+#  echo '$(EXE)'$f ':' '$(OBJ)'$f.o '$(LIBF)' >> GNUmakefile
+#  echo '	g++ $(LDFLAGS) -o $@ $< $(LIBS)' >> GNUmakefile
+#  echo " ">> GNUmakefile
+#end
+
+#foreach f (`cat ../Mgr/programs_db`)
+#  echo $f ': $(EXE)'$f >> GNUmakefile
+#  echo '	' >> GNUmakefile
+#  echo '$(EXE)'$f ':' '$(OBJ)'$f.o '$(LIBF)' >> GNUmakefile
+#  echo '	g++ $(LDFLAGS) -o $@ $< $(LIBSORA)' >> GNUmakefile
+#  echo " ">> GNUmakefile
+#end
+
+set inc = $DPCDEVREP/Include
+
+
+foreach f ( *.cc )
+  gcc -MM -I$inc $f  \
+       | sed -e 's/.*\.o/\$(OBJ)&/' \
+       | sed -e 's?'$inc/'?$(INC)?g' >> GNUmakefile
+end 
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/Mgr/mkmfprog.awk
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/mkmfprog.awk	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/mkmfprog.awk	(revision 752)
@@ -0,0 +1,22 @@
+{ print $1 ": $(EXE)"$1 ;
+  print "	" ;
+  xlib = ""
+  if (NF == 1) 
+     obj = "$(OBJ)"$1".o";
+  else if (NF == 2 && $2 == "DB") {
+     obj = "$(OBJ)"$1".o";
+     xlib = "$(LIBSORA)";
+  }
+  else {
+    obj = "";
+    for (i=2;i<=NF;i++) {
+      if ($i == "DB")
+       xlib = "$(LIBSORA)"
+      else
+       obj = obj " $(OBJ)"$i;
+     }
+  }
+  print "$(EXE)"$1 ":" obj;
+  print "	$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@ " xlib
+  print "  "  
+}
Index: /tags/V_Fev00/SophyaLib/Mgr/progdirs
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/progdirs	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/progdirs	(revision 752)
@@ -0,0 +1,3 @@
+Prog
+ProgAcq
+ProgPI
Index: /tags/V_Fev00/SophyaLib/Mgr/progdirs_ccpn
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/progdirs_ccpn	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/progdirs_ccpn	(revision 752)
@@ -0,0 +1,1 @@
+Prog
Index: /tags/V_Fev00/SophyaLib/Mgr/ttsz.c
===================================================================
--- /tags/V_Fev00/SophyaLib/Mgr/ttsz.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Mgr/ttsz.c	(revision 752)
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+/*  programme pour imprimer les tailles des types et le 
+    byte-swap                                            */
+
+main(int narg, char* arg)
+{
+int i,k;
+char* pc;
+
+printf(" Sizeof short int = %d \n", (int)(sizeof(short int)));
+printf(" Sizeof int = %d \n", (int)(sizeof(int)));
+printf(" Sizeof long = %d \n", (int)(sizeof(long)));
+printf(" Sizeof long long = %d \n", (int)(sizeof(long long)));
+printf(" Sizeof float = %d \n", (int)(sizeof(float)));
+printf(" Sizeof double = %d \n", (int)(sizeof(double)));
+printf(" Sizeof long double = %d \n", (int)(sizeof(long double)));
+
+
+i = 65;
+pc = (char *)(&i);
+for(k=0; k<4; k++)  { printf("I=%d  B%d = %d \n", i, k, (int)(*pc)); pc++; }
+i = 65*65536+16;
+pc = (char *)(&i);
+for(k=0; k<4; k++)  { printf("I=%d  B%d = %d \n", i, k, (int)(*pc)); pc++; }
+
+exit(0);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/Makefile
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/Makefile	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/Makefile	(revision 752)
@@ -0,0 +1,289 @@
+include ../Mgr/Makefile.h
+ 
+all: $(LIB)libNTools.a
+clean:
+	rm -f $(OBJ)cimage.o $(OBJ)cspline.o $(OBJ)cvector.o $(OBJ)datacards.o $(OBJ)datatypes.o $(OBJ)dates.o $(OBJ)difeq.o $(OBJ)dvlist.o $(OBJ)dynccd.o $(OBJ)fct1dfit.o $(OBJ)fct2dfit.o $(OBJ)fftserver.o $(OBJ)generaldata.o $(OBJ)generalfit.o $(OBJ)hisprof.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)imageop.o $(OBJ)integ.o $(OBJ)linfit.o $(OBJ)matrix.o $(OBJ)median.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)outilsinit.o $(OBJ)perandom.o $(OBJ)poly.o $(OBJ)rk4cdifeq.o $(OBJ)rzimage.o $(OBJ)simplesort.o $(OBJ)tabmath.o $(OBJ)tmatrix.o $(OBJ)tvector.o $(OBJ)utils.o $(OBJ)datime.o $(OBJ)fftpackc.o $(OBJ)matxop.o $(OBJ)nbmath.o $(OBJ)nbrandom.o $(OBJ)nbtri.o $(OBJ)strutil.o
+	rm -f $(LIB)libNTools.a
+$(LIB)libNTools.a : $(OBJ)cimage.o $(OBJ)cspline.o $(OBJ)cvector.o $(OBJ)datacards.o $(OBJ)datatypes.o $(OBJ)dates.o $(OBJ)datime.o $(OBJ)difeq.o $(OBJ)dvlist.o $(OBJ)dynccd.o $(OBJ)fct1dfit.o $(OBJ)fct2dfit.o $(OBJ)fftpackc.o $(OBJ)fftserver.o $(OBJ)generaldata.o $(OBJ)generalfit.o $(OBJ)hisprof.o $(OBJ)histos.o $(OBJ)histos2.o $(OBJ)imageop.o $(OBJ)integ.o $(OBJ)linfit.o $(OBJ)matrix.o $(OBJ)matxop.o $(OBJ)median.o $(OBJ)nbmath.o $(OBJ)nbrandom.o $(OBJ)nbtri.o $(OBJ)ntupintf.o $(OBJ)ntuple.o $(OBJ)outilsinit.o $(OBJ)perandom.o $(OBJ)poly.o $(OBJ)rk4cdifeq.o $(OBJ)rzimage.o $(OBJ)simplesort.o $(OBJ)strutil.o $(OBJ)tabmath.o $(OBJ)tmatrix.o $(OBJ)tvector.o $(OBJ)utils.o
+	$(ARCXX) $(ARCXXFLAGS) $@ $?
+ifeq ($(CXX),cxx)
+	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS) -L$(LIB) -lNTools -lSysTools -o $(OBJ)xx.x -Hf
+endif 
+ 
+$(OBJ)cimage.o: cimage.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h cimage.h rzimage.h \
+ rzvect.h datatypes.h $(INC)ppersist.h \
+ $(INC)md5.h dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h fct1dfit.h generalfit.h \
+ tvector.h tmatrix.h $(INC)ndatablock.h \
+ generaldata.h ntupintf.h poly.h peida.h utils.h fmath.h histos.h \
+ nbconst.h
+$(OBJ)cspline.o: cspline.cc $(INC)machdefs.h \
+ $(INC)pclassids.h nbtri.h cspline.h \
+ $(INC)pexceptions.h
+$(OBJ)cvector.o: cvector.cc $(INC)machdefs.h \
+ $(INC)pclassids.h cvector.h matrix.h \
+ peida.h utils.h $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h generalfit.h tvector.h \
+ tmatrix.h $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h
+$(OBJ)datacards.o: datacards.cc $(INC)machdefs.h \
+ $(INC)pclassids.h datacards.h peida.h \
+ utils.h $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h
+$(OBJ)datatypes.o: datatypes.cc datatypes.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h
+$(OBJ)dates.o: dates.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h dates.h
+$(OBJ)difeq.o: difeq.cc difeq.h $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h tvector.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h \
+ $(INC)ctimer.h
+$(OBJ)dvlist.o: dvlist.cc $(INC)machdefs.h \
+ $(INC)pclassids.h dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h strutil.h
+$(OBJ)dynccd.o: dynccd.cc $(INC)machdefs.h \
+ $(INC)pclassids.h fmath.h perandom.h \
+ histos.h $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h peida.h utils.h \
+ $(INC)perrors.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h nbrandom.h cimage.h \
+ rzimage.h rzvect.h datatypes.h dvlist.h dynccd.h
+$(OBJ)fct1dfit.o: fct1dfit.cc $(INC)machdefs.h \
+ $(INC)pclassids.h fct1dfit.h generalfit.h \
+ $(INC)pexceptions.h tvector.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h peida.h \
+ utils.h $(INC)perrors.h fmath.h nbconst.h \
+ tabmath.h
+$(OBJ)fct2dfit.o: fct2dfit.cc $(INC)machdefs.h \
+ $(INC)pclassids.h fct2dfit.h generalfit.h \
+ $(INC)pexceptions.h tvector.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h peida.h \
+ utils.h $(INC)perrors.h fmath.h nbconst.h \
+ tabmath.h simps2d.h
+$(OBJ)fftserver.o: fftserver.cc fftserver.h tvector.h tmatrix.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h
+$(OBJ)generaldata.o: generaldata.cc \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h strutil.h nbtri.h \
+ generalfit.h $(INC)pexceptions.h tvector.h \
+ tmatrix.h $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h peida.h \
+ utils.h $(INC)perrors.h fmath.h
+$(OBJ)generalfit.o: generalfit.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h generalfit.h tvector.h \
+ tmatrix.h $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h peida.h \
+ utils.h $(INC)perrors.h fmath.h
+$(OBJ)hisprof.o: hisprof.cc $(INC)machdefs.h \
+ $(INC)pclassids.h hisprof.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h tvector.h \
+ tmatrix.h $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h histos.h \
+ $(INC)objfio.h
+$(OBJ)histos.o: histos.cc $(INC)machdefs.h \
+ $(INC)pclassids.h histos.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h peida.h utils.h \
+ $(INC)perrors.h fmath.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h poly.h strutil.h \
+ generalfit.h generaldata.h ntupintf.h
+$(OBJ)histos2.o: histos2.cc $(INC)machdefs.h \
+ $(INC)pclassids.h histos2.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h histos.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h generalfit.h \
+ generaldata.h ntupintf.h poly.h
+$(OBJ)imageop.o: imageop.cc $(INC)machdefs.h \
+ $(INC)pclassids.h simplesort.h peida.h \
+ utils.h $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h nbmath.h \
+ histos.h $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h datatypes.h imageop.h \
+ cimage.h rzimage.h rzvect.h dvlist.h cspline.h dynccd.h nbtri.h
+$(OBJ)integ.o: integ.cc integ.h $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h generalfit.h tvector.h \
+ tmatrix.h $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h generaldata.h \
+ $(INC)objfio.h ntupintf.h poly.h peida.h \
+ utils.h $(INC)perrors.h fmath.h
+$(OBJ)linfit.o: linfit.cc $(INC)machdefs.h \
+ $(INC)pclassids.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h linfit.h \
+ tvector.h tmatrix.h $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h
+$(OBJ)matrix.o: matrix.cc $(INC)machdefs.h \
+ $(INC)pclassids.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h matrix.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h cvector.h generalfit.h \
+ tvector.h tmatrix.h $(INC)ndatablock.h \
+ generaldata.h $(INC)objfio.h ntupintf.h \
+ poly.h
+$(OBJ)median.o: median.cc
+$(OBJ)ntupintf.o: ntupintf.cc ntupintf.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h
+$(OBJ)ntuple.o: ntuple.cc strutil.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h ntuple.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h ntupintf.h dvlist.h
+$(OBJ)outilsinit.o: outilsinit.cc outilsinit.h \
+ $(INC)peidainit.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h matrix.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h cvector.h poly.h \
+ $(INC)objfio.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h dvlist.h histos.h \
+ histos2.h hisprof.h ntuple.h ntupintf.h generaldata.h cimage.h \
+ rzimage.h rzvect.h datatypes.h tabmath.h nbconst.h dates.h datime.h
+$(OBJ)perandom.o: perandom.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h perandom.h histos.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h peida.h utils.h \
+ $(INC)perrors.h fmath.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h nbrandom.h pemath.h
+$(OBJ)poly.o: poly.cc $(INC)machdefs.h \
+ $(INC)pclassids.h poly.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h peida.h utils.h \
+ $(INC)perrors.h fmath.h tvector.h tmatrix.h \
+ $(INC)ndatablock.h linfit.h
+$(OBJ)rk4cdifeq.o: rk4cdifeq.cc $(INC)machdefs.h \
+ $(INC)pclassids.h rk4cdifeq.h difeq.h \
+ $(INC)pexceptions.h tvector.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h \
+ $(INC)ctimer.h
+$(OBJ)rzimage.o: rzimage.cc $(INC)machdefs.h \
+ $(INC)pclassids.h rzimage.h rzvect.h \
+ $(INC)pexceptions.h \
+ $(INC)perrors.h datatypes.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h generalfit.h tvector.h \
+ tmatrix.h $(INC)ndatablock.h generaldata.h \
+ ntupintf.h poly.h peida.h utils.h fmath.h
+$(OBJ)simplesort.o: simplesort.cc $(INC)machdefs.h \
+ $(INC)pclassids.h simplesort.h peida.h \
+ utils.h $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h
+$(OBJ)tabmath.o: tabmath.cc $(INC)machdefs.h \
+ $(INC)pclassids.h tabmath.h peida.h utils.h \
+ $(INC)perrors.h \
+ $(INC)pexceptions.h fmath.h nbconst.h
+$(OBJ)tmatrix.o: tmatrix.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h \
+ $(INC)objfio.h generalfit.h tvector.h \
+ generaldata.h ntupintf.h poly.h peida.h utils.h \
+ $(INC)perrors.h fmath.h
+$(OBJ)tvector.o: tvector.cc $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h tvector.h tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h \
+ $(INC)objfio.h generalfit.h generaldata.h \
+ ntupintf.h poly.h peida.h utils.h \
+ $(INC)perrors.h fmath.h
+$(OBJ)utils.o: utils.cc $(INC)machdefs.h \
+ $(INC)pclassids.h utils.h \
+ $(INC)pexceptions.h
+$(OBJ)datime.o: datime.c $(INC)machdefs.h \
+ strutil.h nbconst.h datime.h
+$(OBJ)fftpackc.o: fftpackc.c fftpackc.h \
+ $(INC)machdefs.h
+$(OBJ)matxop.o: matxop.c matxop.h nbmath.h \
+ $(INC)machdefs.h
+$(OBJ)nbmath.o: nbmath.c nbmath.h $(INC)machdefs.h \
+ matxop.h nbinteg.h nbtri.h
+$(OBJ)nbrandom.o: nbrandom.c $(INC)machdefs.h \
+ nbmath.h nbrandom.h
+$(OBJ)nbtri.o: nbtri.c nbtri.h $(INC)machdefs.h
+$(OBJ)strutil.o: strutil.c strutil.h
Index: /tags/V_Fev00/SophyaLib/NTools/NTools.o.list
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/NTools.o.list	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/NTools.o.list	(revision 752)
@@ -0,0 +1,41 @@
+arrfitter.o
+cimage.o
+cspline.o
+cvector.o
+datacards.o
+datatypes.o
+dates.o
+datime.o
+difeq.o
+dvlist.o
+dynccd.o
+fct1dfit.o
+fct2dfit.o
+fftmayer_r4.o
+fftmayer_r8.o
+fftmserver.o
+fftpackc.o
+fftpserver.o
+fftserver.o
+fftservintf.o
+generaldata.o
+generalfit.o
+imageop.o
+integ.o
+linfit.o
+matrix.o
+matxop.o
+median.o
+nbmath.o
+nbrandom.o
+nbtri.o
+ntupintf.o
+outilsinit.o
+perandom.o
+poly.o
+rk4cdifeq.o
+rzimage.o
+simplesort.o
+strutil.o
+tabmath.o
+utils.o
Index: /tags/V_Fev00/SophyaLib/NTools/cimage.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cimage.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cimage.cc	(revision 752)
@@ -0,0 +1,2007 @@
+//  Classes image typee      
+//                    E.Aubourg , E. Lesquoy  01-03/95   
+//                    Modifs R. Ansari   04/95
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+// $Id: cimage.cc,v 1.5 1999-10-21 15:25:42 ansari Exp $        
+
+
+#include "machdefs.h"
+#include <string.h>
+#include <stdio.h>
+
+#include "perrors.h"
+#include "cimage.h"
+#include "fct1dfit.h"
+#include "histos.h"
+#include "nbconst.h"
+#include "utils.h"
+
+/* ..............   Classe  Image<T>    ...............   */
+
+//++
+// Class 	Image<T>
+// Lib 		Images++
+// include	cimage.h
+//
+//
+//	Classe descendant (heritier) de la classe *RzImage*, permettant
+//	l'instantiation d'objets image avec un typage fort (entier, reel, ...)
+//
+//	Des objets de type "Image<uint_1>, Image<uint_2>, Image<int_2>, Image<int_4>"
+//	(entier) et "Image<r_4>" (flottant) peuvent etre crees.
+//	Des typedef (*ImageU1*, *ImageU2*, *ImageI2*, *ImageI4*, *ImageR4*) 
+//	facilite l'utilisation de ces classes.
+//--
+//++
+// Links	Parents
+// RzImage
+//--
+//++
+// Links	Descendants
+// FitsImage<T>
+//--
+//++
+// Links	Voir aussi
+// DVList
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+// Image<T>(int sizx, sizy, int zero)
+//	Creation d'une image de type "T", de taille "sizx*sizy" pixels.
+//	Si "zero" non nul, tous les pixels de l'image sont mis a zero.
+// Image<T>(char* flnm)
+//	Cree une image a partir du fichier "flnm". Celui-ci doit etre 
+//	au format "PPF" et cree par la methode "Save() ou "Write()".
+//--
+
+template <class T>
+Image<T>::Image(int sizx, int sizy, int zero)
+: RzImage(DataType((T)0), sizx, sizy), imagePtr( (T*) voidP )
+{
+  if (zero) Zero();
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+template <class T>
+Image<T>::Image()
+: RzImage(DataType((T)0)), imagePtr(0)
+{
+  END_CONSTRUCTOR
+}
+
+
+/* --Methode-- */
+template <class T>
+void Image<T>::Allocate(int sizx, int sizy, int zero, ImgVectP* pvpsh)
+{
+  RzImage::Allocate(DataType((T)0), sizx, sizy, pvpsh);
+  imagePtr = (T*) voidP;
+  if (!imagePtr) THROW(allocationErr);
+  if (zero) Zero();
+}
+
+template <class T>
+void Image<T>::SetPixels(int szx, int szy, T* pim)
+{
+  RzImage::SetPixels(DataType((T)0), szx, szy, pim);
+  imagePtr = pim;
+}
+
+/* --Methode-- */
+template <class T>
+Image<T>::~Image()
+{}
+
+
+//++
+// Image<T>(const Image<T>& src, int sharePixels)
+//	Constructeur par copie. Fabrique une image identique a l'image "src".
+//	Si "sharePixels" est non nul, le tableau des pixels est commun 
+//	aux deux images ("src" et celle creee)
+// Image<T>(const Image<T>& src, int orgx, int orgy, int sizx, int sizy)
+//	Construit une image de type "T", a partir des pixels de l'image
+//	"src" (du meme type), de taille "sizx*sizy" et de l'origine
+//	"orgx, orgy" dans "src". Si "orgx" et/ou "orgy" sont negatifs,
+//	la taille de la nouvelle image est automatiquement calculee 
+//	pour contenir toute l'image source a partir de l'origine specifiee.
+//	Genere l'exception "sizeMismatchErr" en cas d'incompatibilite 
+//	taille/origine. 
+//--
+
+/* --Methode-- */
+template <class T> 
+Image<T>::Image(const Image<T>& src, int sharePixels)
+: RzImage(src, sharePixels)
+{
+  imagePtr = (T*) voidP;
+  if (!imagePtr) THROW(allocationErr);
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>::Image(const Image<T>& src, int orgx, int orgy, int sizx, int sizy)
+:RzImage()
+{
+  // A optimiser...
+  if (sizx < 0) sizx = src.XSize()-orgx;
+  if (sizy < 0) sizy = src.YSize()-orgy;
+  if (orgx+sizx > src.XSize() || orgy+sizy > src.YSize())
+    THROW(sizeMismatchErr);
+
+  Allocate(sizx, sizy);
+  for (int i=0; i<sizx; i++)
+    for (int j=0; j<sizy; j++)
+      (*this)(i,j) = src(i+orgx, j+orgy);
+
+  SetOrg(src.XOrg()+orgx, src.YOrg()+orgy);
+  SetPxSize(src.XPxSize(), src.YPxSize());    
+  END_CONSTRUCTOR
+}
+
+//++
+// LaTeX 	Pour contrer un mauvais espacement des paragraphes de LaTeX
+// \newpage
+//--
+//++
+// Image<T>()
+//	Creation d'une image de type "T" sans allocation du tableau des pixels.
+//	Le tableau des pixels devra etre ensuite alloue par la methode "Allocate()"
+//--
+
+//++
+// Image<T>(const RzImage& rzimg)
+//	Permet de construire une image typee a partir d'une RzImage ("rzimg")
+//	Le tableau des pixels est commun aux deux images.
+//	Les pixels de l'image "rzimg" doivent etre du type "T", sinon 
+//	l'exception "typeMismatchErr" est generee.
+//--
+/* --Methode-- */
+template <class T>
+Image<T>::Image(const RzImage& rzimg)
+:RzImage(rzimg,1)
+{
+
+  if (rzimg.PixelType() != DataType((T)0))
+    THROW(typeMismatchErr);
+  imagePtr = (T*) voidP;
+  if (!imagePtr) THROW(allocationErr);
+
+  END_CONSTRUCTOR
+}
+
+//++
+// void Allocate(int sizx, int sizy, int zero=1, ImgVectP* pvpsh=NULL)
+//	Alloue le tableau des pixels.
+//--
+//++
+// ~Image<T>
+//	Destructeur. supprime le tableau des pixels en memoire si celui-ci
+//	n'est pas utilise par d'autres objets image.
+//--
+
+/* --Methode-- */
+template <class T> 
+Image<T>::Image(char *flnm)
+:RzImage(flnm)
+{
+  imagePtr = (T*) voidP;
+  if (!imagePtr) THROW(allocationErr);
+
+  END_CONSTRUCTOR
+}
+
+
+/* --Methode-- */
+template <class T> 
+void  Image<T>::ReadSelf(PInPersist& s)
+{
+  RzImage::ReadSelf(s);
+  imagePtr = (T*) voidP;
+}
+
+//++
+// Titre	Operateurs
+//	Un grand nombre des operations pouvant etre effectuees sur un 
+//	tableau de nombre ont ete defini pour les objets "Image<T>"
+//	Dans les operations faisant intervenir deux images, l'exception
+//	"sizeMismatchErr" est generee si les tailles (en X ou en Y) des 
+//	deux images ne sont pas identiques.
+//--
+
+//++
+// Image<T>& operator= (const Image<T>& rhs)
+//	Copie le contenu (valeurs des pixels) de l'image "rhs".
+//	Si l'image destination (membre gauche de =) n'a pas son 
+//	tableau de pixels alloue, celui-ci est cree a une taille
+//	identique a celle de "rhs"
+// Image<T>& operator= (T val)
+//	Met tous les pixels de l'image a la valeur "val"
+//--
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator = (const Image<T>& src)
+{
+  if (imagePtr) {
+    if (siz_x != src.siz_x || siz_y != src.siz_y)
+      THROW(sizeMismatchErr);
+  } else
+    Allocate(src.siz_x, src.siz_y);
+  
+  (RzImage)(*this) = (RzImage)src;
+  return *this;
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator = (T a)
+{
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pDst++)
+    *pDst = a;
+
+  return *this;
+}
+
+/* --Methode-- */
+template <class T>
+void Image<T>::Zero()
+{
+  memset(imagePtr,0,siz_x * siz_y * sizeof(T));
+}
+
+/* --Methode-- */
+#if 0 // a la mort de RzImage
+template <class T>
+void Image<T>::Clear()
+{
+  if (imagePtr) {
+    delete[] imagePtr;
+    imagePtr = 0;
+    siz_x = 0;
+    siz_y = 0;
+  }
+}
+#endif
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator+= (Image<T> const& a)
+{
+  if (siz_x != a.siz_x || siz_y != a.siz_y)
+    THROW(sizeMismatchErr);
+  T* pSrc = a.imagePtr;
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pSrc++, pDst++)
+    *pDst = PutInRange((double)*pSrc + (double)*pDst, *pDst);
+
+  return *this;
+}
+
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator-= (Image<T> const& a)
+{
+  if (siz_x != a.siz_x || siz_y != a.siz_y)
+    THROW(sizeMismatchErr);
+  T* pSrc = a.imagePtr;
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pSrc++, pDst++)
+    *pDst = PutInRange((double)*pDst - (double)*pSrc, *pDst);
+
+  return *this;
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator*= (Image<T> const& a)
+{
+  if (siz_x != a.siz_x || siz_y != a.siz_y)
+    THROW(sizeMismatchErr);
+  T* pSrc = a.imagePtr;
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pSrc++, pDst++)
+    *pDst = PutInRange((double)*pDst * (double)*pSrc, *pDst);
+
+  return *this;
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator/= (Image<T> const& a)
+{
+  if (siz_x != a.siz_x || siz_y != a.siz_y)
+    THROW(sizeMismatchErr);
+  T* pSrc = a.imagePtr;
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pSrc++, pDst++)
+    if (*pSrc)
+      *pDst = PutInRange((double)*pDst / (double)*pSrc, *pDst);
+    else *pDst = (T) MaxRange(*pDst);
+
+  return *this;
+}
+
+//++
+//  Image<T>& operator += -= *= /= (Image<T> const& rhs)
+//	Ajoute (+=), soustrait(-=), multiplie(*=), divise(/=) les valeurs des pixels 
+//	de l'image a gauche de l'operateur par les pixels correspondants
+//	de l'image a droite de l'operateur ("rhs")
+//  Image<T>& operator += -= *= /= (double crhs)
+//	Ajoute (+=), soustrait(-=), multiplie(*=), divise(/=) les valeurs des pixels 
+//	de l'image a gauche de l'operateur par la constante "crhs"
+//--
+
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator+= (double a)
+{
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pDst++)
+    *pDst = PutInRange((double)*pDst + a, *pDst);
+
+  return *this;
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator-= (double a)
+{
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pDst++)
+    *pDst = PutInRange((double)*pDst - a, *pDst);
+
+  return *this;
+}
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator*= (double a)
+{
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+
+  for (int i=0; i<nPix; i++, pDst++)
+    *pDst = PutInRange((double)*pDst * a, *pDst);
+
+  return *this;
+}
+
+
+/* --Methode-- */
+template <class T> 
+Image<T>& Image<T>::operator/= (double a)
+{
+  T* pDst = imagePtr;
+  int nPix = siz_x * siz_y;
+  
+  for (int i=0; i<nPix; i++, pDst++)
+    *pDst = PutInRange((double)*pDst / a, *pDst);
+  
+  return *this;
+}
+
+
+
+//++
+// Image<T> operator + - * / (Image<T> const& a, Image<T> const& b)
+//	Ajoute, soustrait, multiplie, divise les pixels des deux 
+//	images "a" et "b" et l'affecte a gauche de l'operateur egal.
+// operator + - * / (Image<T> const& a, double cb)
+//	Ajoute, soustrait, multiplie, divise le contenu de l'image "a"
+//	par la constante "cb" et l'affecte a l'image a gauche de l'operateur = .
+// 
+//	Il est preferable d'utiliser dans la mesure du possible, les 
+//	operateurs "+=", "-=", "*=", "/=" afin d'eviter des copies 
+//	inutiles.
+//
+//	*Exemples:*
+//| // Creation des images
+//| ImageR4  ai(200,300), bi, ci;
+//| // Tous les pixels a 238.5
+//| ai = 238.5;
+//| // Image bi meme taille, meme valeurs de pixels que ai
+//| bi = ai;    
+//| // On soustrait 13.2 a tous les pixels de ai
+//| ai -= 13.2;
+//| // Je divise bi par ai (pixel par pixel) qu'on affecte a bi
+//| bi /= ai;
+//| // On somme ai et bi (pixel par pixel) qu'on affecte a ci
+//| ci = ai + bi; 
+//--
+
+
+/* --Methode-- */
+template <class T>
+Image<T> Image<T>::WhereNonZero()
+{
+  Image<T> c(*this);
+  for (int i=0; i<XSize(); i++)
+    for (int j=0; j<YSize(); j++)
+      c(i,j) = c(i,j) ? 1 : 0;
+  return c;
+}
+
+//++
+// void PrintImage(ostream& os) const
+//	Envoie le contenu de l'image (formatte, texte) sur le 
+//	flot (stream) de sortie "os".
+//	Attention: Ca peut faire beaucoup de ligne !
+// void PrintImage() const
+//	Appel a PrintImage(cout) - Sortie sur cout .
+//--
+
+
+/* --Methode-- */
+template <class T>
+void Image<T>::PrintImage(ostream& os) const
+//  Impression de tout le contenu de l'image
+{
+#define PrPvLn 10
+#define PrSize 6
+int i,j,k,ido,ideb,ifin;
+int siz_x,siz_y;
+
+siz_x= XSize();
+siz_y= YSize();
+
+os << " Image::PrintImage: type pixel " ;
+os << DataName(dataType) ;  
+os << ", NbPix=("<<siz_x<<","<<siz_y<<") \n";  
+
+
+/* segmentation avec des lignes de PrPvLn valeurs */
+
+ido = (siz_x-1) / PrPvLn + 1;
+
+char buff[256];
+
+for(k=0;k<ido;k++)
+  {
+  ideb = k*PrPvLn;
+  ifin = ideb + PrPvLn;
+  if ( ifin >siz_x ) ifin =  siz_x ;
+  sprintf(buff, "    ---- colonnes   %d   a   %d  ----\n",ideb,ifin-1);
+  os << buff ;
+  for(j=0; j<siz_y; j++)
+    {
+    sprintf(buff, "%3d - ",j);
+    os << buff;
+    for (i=ideb; i<ifin; i++)
+      {
+        os.width(PrSize);
+// les uint_1 sont traites comme characteres par les ostream ...
+        if (PixelType() == kuint_1) os << ((int)((*this)(i,j))) << " ";
+        else os << (*this)(i,j) << " ";
+      }
+     os << endl;
+     }
+   }
+
+ return;
+}
+
+
+//++
+// Titre	Acces aux pixels
+//--
+//++
+// T&  operator() (int x, int y)
+//	Acces au pixel "(x,y)" de l'image (lecture/ecriture)
+// T&  operator[] (int i)
+//	Acces au pixel numero "i" de l'image (lecture/ecriture)
+//
+//| ImageU2 img(100,100);
+//| int i,j,k;
+//| // Remplissage de la moitie de l'image
+//| for(k=0; k<100*50; k++)  img[k] = k%500;
+//| img(50, 10); // Valeur du pixel (50, 10)
+//
+// T*  ImagePtr()
+//	Renvoie un pointeur du type "T (uint_2, r_4, ...)" sur le
+//	tableau des pixels de l'image. A n'utiliser que si un reelle
+//	optimisation de l'acces aux pixels peut etre effectuee.
+//--
+
+
+
+//++
+// Titre	Traitements simples
+//--
+//++
+// int  CheckDyn(double min=-9.e19, double max=9.e19)
+//	Cette methode retourne le nombre de pixels hors dynamique "( <min ou >max )"
+//	Met a jour les donnees membres "min/maxPix nbNul/Sat".
+//	Calcule aussi la moyenne et le sigma des pixels -> "moyPix, sigPix"
+//	Implementation plus efficace de la methode "RzImage::CheckDyn()"
+//--
+
+/* --Methode-- */
+template <class T>
+int Image<T>::CheckDyn(double min, double max)
+
+/*  Cette methode retourne le nombre de pixels hors dynamique    */
+/* ds le pave ( <min ou >max )                                   */
+/* Met a jour la structure image Min/MaxPix nbNul/Sat            */
+/* Calcule aussi la moyenne et le sigma des pixels, met a jour   */
+/* moypix et sigpix dans la structure                            */
+
+{
+T pixv=0;
+double dv;
+
+T minadu = PutInRange(min, pixv);
+T maxadu = PutInRange(max, pixv);
+T minpix = PutInRange(maxadu+1, pixv);
+T maxpix = PutInRange(minadu-1, pixv);
+
+double m = 0.;
+double s = 0.;
+int n9 = 0;
+int n0 = 0;
+int n = XSize()*YSize();
+for(int i=0; i<n; i++) 
+  {
+  pixv = imagePtr[i];
+  if (pixv <= maxadu && pixv >= minadu) 
+    {  
+    if (pixv < minpix)  minpix = pixv;
+    else if (pixv > maxpix)  maxpix = pixv;  
+    dv = (double)pixv;
+    m += dv;  s += (dv*dv);
+    }
+  else 
+    {  
+    if (pixv > maxadu)  n9++;
+    if (pixv < minadu)  n0++; 
+    }
+  }
+
+nbNul = n0;
+nbSat = n9;
+minPix = minpix;
+maxPix = maxpix;
+
+n -= (n0+n9);
+if (n > 0)
+  { dv = (double)n;  m /= dv;  s = s/dv - m*m;
+  if (s>0.)  s = sqrt(s);  else s = 0.;
+  moyPix = m;  sigPix = s; }
+else { moyPix = 0.;  sigPix = -1.; }
+
+return(n0+n9);
+}
+
+//++
+// SeuilBas(double seuil, double val)
+//	Met les pixels en dessous du "seuil" (< seuil) a la valeur "val".
+// SeuilBas(double seuil)
+//	Met les pixels en dessous du "seuil" (< seuil) a zero
+// SeuilHaut(double seuil, double val)
+//	Met les pixels au dessus du "seuil" (> seuil) a la valeur "val".
+// SeuilHaut(double seuil)
+//	Met les pixels au dessus du "seuil" (> seuil) a zero
+//--
+
+/* --Methode-- */
+template <class T>
+void Image<T>::SeuilBas(double seuil, double val)
+
+/*   Met a une valeur definie tous les pixels    */
+/*   en dessous du seuil                         */
+
+{
+  if (!ImagePtr())   THROW(nullPtrErr);
+  T* PtPix=ImagePtr();
+  int nPix=XSize()*YSize();
+  for(int i=0 ; i<nPix;i++,PtPix++) {if(*PtPix < (T) seuil) *PtPix = (T) val;};
+}
+
+/* --Methode-- */
+template <class T>
+void Image<T>::SeuilHaut(double seuil, double val)
+
+/*   Met a une valeur definie tous les pixels    */
+/*   en dessus du seuil                         */
+
+{
+  if (!ImagePtr())   THROW(nullPtrErr);
+  T* PtPix=ImagePtr();
+  int nPix=XSize()*YSize();
+  for(int i=0 ; i<nPix;i++,PtPix++) {if(*PtPix > (T) seuil) *PtPix = (T) val;};
+}
+
+/* --Methode-- */
+template <class T>
+void Image<T>::SeuilBas(double seuil)
+{
+  SeuilBas(seuil,seuil);
+}
+
+/* --Methode-- */
+template <class T>
+void Image<T>::SeuilHaut(double seuil)
+{
+  SeuilHaut(seuil,seuil);
+}
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+void Image<T>::HBinInt(int& nbin,float& xmin,float& xmax)
+//
+//	Valeur pour avoir un bin entier quand on fait un
+//	histogramme 1D des pixels (pour les images entieres).
+//--
+{
+if( PixelType()<kuint_2 || PixelType()>kint_4 ) return;
+double binw = (xmax-xmin)/nbin;
+binw = (double) ( (int)(binw+0.5) );
+if( binw <= 0. ) binw = 1.;
+xmin = (float) ( (int) xmin );
+xmax = (float) ( (int) (xmax + binw) );
+nbin = (int)( (xmax-xmin)/binw + 0.1 );
+}
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+int Image<T>::EstimeFdSg(float& xbmax,float& sgbmax
+             ,float nbsig,float frac,float lowbad,float highbad,int deb)
+//
+//	Pour donner une estimation  du fond de ciel et du sigma ciel.
+//	Il est conseille de faire ceci sur une image partielle.
+//	Une premiere estimation du fond et du sigma est faite en nettoyant
+//	iterativement (cf MoySigmaIter).
+//	Puis un histogramme est rempli et rebinne jusqu'a ce que son maximum
+//	soit statistiquement significatif. Le fond et le sigma sont ensuite
+//	calcules par les methodes `FitMax' et `EstimeWidthS' de la classe Histo.
+//| xbmax = position du maximum
+//| sgbmax = valeur du sigma
+//| nbsig = dimensionnement de l'histo de depart en nombre
+//|         de sigma autour de la valeur maximum
+//| frac = valeur maximum principale / maximum secondaire a partir
+//|        de laquelle on considere qu'elle a une signification
+//|        statistique. 
+//| lowbad,highbad = dynamique utile de l'image traitee
+//| deb = niveau de debug
+//| Return : 0 = OK, -1 = echec MoySigmaIter, -2 = echec FitMax,
+//|                  -3 = echec FindWidth
+//--
+{
+T pixv=0;
+T minadu = PutInRange((double) lowbad , pixv);
+T maxadu = PutInRange((double) highbad, pixv);
+bool testl = (lowbad<highbad) ? true : false;
+lowbad  = (float) minadu;  highbad = (float) maxadu;
+
+if(deb<0) deb=0;
+int envd = 0;
+GetIntEnv("PDEBUG_FOND", envd);
+if (deb < envd) deb = envd;
+
+// moyenne et sigma bruts (iteratifs)
+int rc;
+float fd,sg;
+rc = MoySigmaIter(fd,sg,lowbad,highbad,1,5,0.1,3.5,deb-1);
+if(deb>0) cout<<"EstimeFdSg: MoySigmaIter rc="<<rc<<" fd="<<fd<<" sg="<<sg<<endl;
+if(rc<=0) return -1;
+
+// remplissage histogramme avec beaucoup de bins
+int nbin;
+float xmin,xmax;
+xmin = fd - nbsig*sg; if(testl && xmin<lowbad ) xmin = lowbad;
+xmax = fd + nbsig*sg; if(testl && xmax>highbad) xmax = highbad;
+nbin = XSize()*YSize()/20; if(nbin>2000) nbin=2000;
+Histo H(xmin,xmax,nbin);
+for(int i=0;i<XSize()*YSize();i++) H.Add((float) (*this)[i],1.);
+
+// redimensionnement de l'histo pour avoir une bonne signification stat.
+for(;;) {
+  float max1,max2;
+  int imax1,imax2;
+  rc = H.MaxiLocal(max1,imax1,max2,imax2);
+  float rap = 1.;
+  if( max1 != 0. ) rap = max2/max1;
+  // if(nbin<100) H.Print(80);
+  if(deb>1)
+     cout<<"nbin="<<nbin
+         <<"   maxloc="<<rc
+         <<"   maxi="<<max1<<" imax="<<imax1<<" xmax="<<H.BinCenter(imax1)
+         <<"   maxn="<<max2<<" imaxn="<<imax2<<" xmaxn="<<H.BinCenter(imax2)
+         <<" -> "<<rap<<endl;
+  if( rap<frac || nbin<=10 ) break;
+  nbin = (int)(nbin/1.5);
+  H.HRebin(nbin);
+}
+if(deb>1) { if(nbin<250) H.Print(80); else H.Print(80,-1.,1.,-1);}
+
+TRY {
+  xbmax = H.FitMax(2,0.5f,deb-2);
+  if(deb>1) cout<<"H.FitMax = "<<xbmax<<endl;
+} CATCHALL {
+   if(deb) cout<< "Echec H.FitMax"<< endl;
+   return(-2);
+} ENDTRY
+
+TRY {
+  float sdroit = -2.;
+  H.EstimeWidthS(0.5f,sgbmax,sdroit);
+  if(sgbmax<=0.) sgbmax = H.FindWidth(0.5f,deb-2);
+  sgbmax /= 2.36;
+  if(deb>1) cout<<"H.FindWidth = "<<sgbmax<<" (droit="<<sdroit<<")"<<endl;
+} CATCHALL {
+   cout<< "Echec H.FindWidth"<< endl;
+   return(-3);
+} ENDTRY
+
+return 0;
+}
+
+/* --Methode--  (cmv 23/09/96) */
+template <class T>
+//++
+float Image<T>::FondCiel(int nbin,float bin_low,float bin_high
+                         ,int degre,float frac,int modu,int deb)
+//
+//	Calcul du fond de ciel:
+//	Remplissage d'un histogramme avec le contenu des pixels du pave,
+//	recherche du bin contenant le maximum,
+//	recheche des limites a frac% de chaque cote du maximum
+//	et fit d'un polynome du 2sd ou 3ieme degre dans cette zone.
+//| Input:
+//|   nbin,bin_low,bin_high : definition de l'histogramme
+//|   degre : degre du fit (2 ou 3)
+//|   frac : definition de la zone de fit a frac% du maximum
+//|   modu : on prend 1 px sur modu
+//|   deb : debug flag
+//| Output: renvoie le maximum de l'histogramme (fond de ciel)
+//|         et update le membre protected fond (si succes)
+//--
+{
+T pixv;
+
+if(modu<=0) modu = 1;
+if(frac<=0.) frac = 0.5;
+if(degre<2 || degre>3) degre = 2;
+if(deb>0)
+  printf("Image::FondCiel: nbin=%d dyn=%g,%g deg=%d frac=%g modu=%d\n"
+        ,nbin,bin_low,bin_high,degre,frac,modu);
+if(nbin<=degre) THROW(inconsistentErr);
+
+TRY {
+
+  Histo tab(bin_low,bin_high,nbin);
+  double sum = 0.;
+  volatile int n = 0, nsum = 0;
+  for(int i=0;i<XSize()*YSize();i++) {
+    n++;
+    if( n%modu != 0 ) continue;
+    pixv = imagePtr[i];
+    tab.Add( (float) pixv );
+    sum += (double) pixv;
+    nsum++;
+  }
+  if(deb>1) { int im = tab.IMax();
+              tab.Print(80,1.,-1.,0,im-50,im+50); }
+
+  float xf = 0.;
+  // tout dans moins de degre bins
+  if( tab.BinNonNul() <= degre ) {
+    if(nsum<=0) THROW(inconsistentErr);
+    xf = sum / (double) nsum;
+    if(deb>0) printf("%d bins <= %d -> Succes Mean = %g\n"
+                    ,tab.BinNonNul(),degre,xf);
+    fond = xf;
+    RETURN(xf);
+  }
+
+  TRY {
+    xf = tab.FitMax(degre,frac,deb-1);
+    if(deb>0) printf("Succes tab.FitMax = %g\n",xf);
+    fond = xf;
+    RETURN(xf);
+  } CATCHALL {
+    if(deb>0)
+       printf("Echec tab.FitMax BinNonNul=%d\n",tab.BinNonNul());
+    THROW(inconsistentErr);
+  } ENDTRY
+
+} CATCHALL {
+   THROW_SAME;
+} ENDTRY
+}
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+float Image<T>::SigmaCiel(int nbin,float bin_low,float bin_high
+                         ,float& means,float lowbad,float highbad
+                         ,float nsig,int modu,int deb)
+//
+//	Calcul du sigma du fond de ciel:
+//	Remplissage d'un histogramme avec px-<px8> pour les pixels
+//	entre lowbad et highbad (px=valeur du pixel etudie,
+//	<px8>=moyenne des 8 pixels qui lui sont contigus).
+//	Une premiere estimation du sigma (s1) et realisee en cherchant
+//	la largeur a mi-hauteur de cet histogramme. Puis un fit non-lineaire
+//	d'une gaussienne est effectue dans +/- nsig*s1
+//| Input:
+//|   nbin,bin_low,bin_high : definition de l'histogramme
+//|   lowbad,highbad : limites des pixels a utiliser
+//|   nsig : la zone de fit est definie a +/- nsig*sigma du maximum
+//|   modu : on prend 1 px sur modu
+//|   deb : debug flag
+//| Output:
+//|   means = moyenne fittee de l'histogramme (normalement -> 0)
+//|   renvoie le sigma du fond de ciel
+//|     et update le membre protected sigmaFond (si succes)
+//--
+{
+T pixv=0;
+T minadu = PutInRange((double) lowbad , pixv);
+T maxadu = PutInRange((double) highbad, pixv);
+volatile bool testl = (lowbad<highbad) ? true : false;
+
+if(nbin<5) THROW(inconsistentErr);
+if(nsig<=0.) nsig = 4.;
+if(modu<=0) modu = 1;
+means = 0.;
+if(deb>0)
+  cout << "SigmaCiel( nbin=" << nbin
+       << ", bin_low=" << bin_low
+       << ", bin_high=" << bin_high
+       << ", lowbad=" << lowbad
+       << ", highbad=" << highbad
+       << ", nsig=" << nsig
+       << ", modu=" << modu
+       << ", deb=" << deb << endl;
+
+// coeff pour corriger le sigma de (S-<S8>) par rapport au sigma de S
+// sigma(S) = sigma(S-<S8>) * 1/sqrt(1+1/8) = 2*sqrt(2)/3
+double coeff = 2.*Rac2/3.;
+
+TRY {
+
+  Histo tab(bin_low,bin_high,nbin);
+  tab.Errors();
+
+  int nmod = 0, nsum = 0;
+  double sum= 0., sum2 = 0.;
+  for(int j=1;j<YSize()-1;j++) for(int i=1;i<XSize()-1;i++) {
+    nmod++;
+    if( nmod%modu != 0 ) continue;
+    pixv = (*this)(i,j);
+    if ( testl && (pixv < minadu || pixv > maxadu) ) continue;
+    double vp = (double) pixv;
+    double pxv = 0.;
+    volatile int n = 0;
+    for(int j1=j-1;j1<=j+1;j1++) for(int i1=i-1;i1<=i+1;i1++) {
+      if ( i1 == i && j1 == j ) continue;
+      pixv = (*this)(i1,j1);
+      if ( testl && (pixv < minadu || pixv > maxadu) ) continue;
+      pxv += (double) pixv;
+      n++;
+    }
+    if ( n != 8 ) continue;
+    vp = vp - pxv/(double) n;
+    tab.Add( (float) vp );
+    nsum++;
+    sum += vp;
+    sum2 += vp*vp;
+  }
+
+  float ms = tab.BinCenter( tab.IMax() );
+  volatile float sg = 0.;
+  if( tab.BinNonNul() == 1 ) {
+    if(deb>0) cout << tab.BinNonNul()
+                   << " bins non nul dans l'histogramme" << endl;
+    if(nsum<=1) THROW(inconsistentErr);
+    sum /= (double) nsum;
+    sum2 = sum2/(double) nsum - sum*sum;
+    if(sum2<0.) THROW(inconsistentErr);
+    means = sum;
+    sum2 = sqrt(sum2) * coeff;
+    sigmaFond = sum2;
+    RETURN((float) sum2);
+  } else {
+    TRY {
+      sg = tab.FindWidth(0.5,deb-1) / 2.36;
+    } CATCHALL {
+      THROW_SAME;
+    } ENDTRY
+  }
+  double h = tab.VMax();
+  if(deb>0) cout << "from histo: ms=" << ms 
+                           << "  sg=" << sg
+                           << "  h=" << h << endl;
+
+  float xmin = ms - nsig*sg;
+  float xmax = ms + nsig*sg;
+  int imin = tab.FindBin(xmin);
+  int imax = tab.FindBin(xmax);
+  if( imax-imin+1 < 4 ) {imax++; imin--;}
+  if(imin<0) imin=0;
+  if(imax>=tab.NBins()) imax=tab.NBins()-1;
+  int nb = imax-imin+1;
+  if( nb < 4 ) THROW(inconsistentErr);
+  if(deb>0) printf("xrange=[%g,%g] irange=[%d,%d] nb=%d\n"
+                  ,xmin,xmax,imin,imax,nb);
+  if(deb>2) tab.Print(80,1.,-1.,0,imin,imax);
+
+  Gauss1DPol     myfunc;
+  GeneralFit     myfit(&myfunc);
+  GeneralFitData mydata(1,nb);
+  for(int i=imin;i<=imax;i++) {
+     float e = tab.Error(i);
+     if( e <= 0. ) e = 1.;
+     mydata.AddData1(tab.BinCenter(i),tab(i),e);
+   }
+
+  myfit.SetData(&mydata);
+  myfit.SetParam(0,h,h/50.);
+  myfit.SetParam(1,ms,sg/10.);
+  myfit.SetParam(2,sg,sg/10.);
+  myfit.SetBound(2,0.,sg*5.);
+  int rc = myfit.Fit();
+  if(rc<0) THROW(inconsistentErr);
+  if(deb>1) myfit.PrintFit();
+
+  means = myfit.GetParm(1);
+  sum2 = myfit.GetParm(2) * coeff;
+  sigmaFond = sum2;
+  RETURN((float) sum2);
+
+} CATCHALL {
+   THROW_SAME;
+} ENDTRY
+
+}
+
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+int Image<T>::MoySigma(float& mean,float& sigma,float lowbad,float highbad,int modu)
+//
+//	Calcul de la moyenne (mean) et du sigma (sigma) dans un pave
+//	en ne considerant que les pixels compris entre lowbad et highbad.
+//	Seul 1 px sur modu est utilise.
+//	La fonction retourne le nombre de pixels utilises pour le calcul.
+//--
+{
+T pixv=0;
+T minadu = PutInRange((double) lowbad , pixv);
+T maxadu = PutInRange((double) highbad, pixv);
+bool testl = (lowbad<highbad) ? true : false;
+
+if(modu<=0) modu = 1;
+mean = sigma = 0.;
+
+int rc = 0, n = 0;
+double m = 0., s = 0., mm, ss, v;
+
+for(int j=0;j<YSize();j++) {
+  mm = ss = 0.;
+  for(int i=0;i<XSize();i++) {
+    n++;
+    if( n%modu != 0 ) continue;
+    pixv = (*this)(i,j);
+    if( testl && (pixv < minadu || pixv > maxadu) ) continue;
+    v = (double) pixv;
+    rc++;
+    mm += v;
+    ss += v*v;
+  }
+  m += mm;
+  s += ss;
+}
+
+if(rc==0) return(-1);
+
+m /= (double) rc;
+s = s/(double) rc - m*m;
+if(s<0.) return(-2);
+
+mean  = (float) m;
+sigma = (float) sqrt(s);
+
+moyPix = mean;     // Mise a jour de la structure
+sigPix = sigma;
+
+return rc;
+}
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+int Image<T>::MoySigmaIter(float& mean,float& sigma,float lowbad,float highbad
+                          ,int modu,int nitermx,float perdiff,float scut,int deb)
+//
+//	Calcul de moyenne et sigma iterativement:
+//| lowbad,highbad = dynamique permise pour la valeur
+//|                  des pixels en ADU
+//| modu = 1 px sur modu est utilise
+//| nitermx = nombre maximum d'iterations permises
+//| perdiff = condition d'arret en pourcent sur la variation du sigma
+//| scut = coupure en nombre de sigma courant pour l'iteration suivante
+//| mean = moyenne retournee
+//| sigma = sigma retourne
+//| return <= 0 probleme, sinon (>0) nombre de pixels utilises
+//--
+{
+if( scut<=0. || nitermx<=0 || perdiff<=0. ) return 0;
+if(modu<=0) modu = 1;
+bool testl = (lowbad<highbad) ? true : false;
+
+mean = sigma = 0.;
+float sigmaold = 0;
+float xmin = lowbad;
+float xmax = highbad;
+int rc = 0;
+
+for(int it=0;it<nitermx;it++) {
+  rc = MoySigma(mean,sigma,xmin,xmax,modu);
+  if(deb>0) cout<<"MoySigmaIter mean="<<mean<<" sigma="<<sigma
+                <<" npix="<<rc<<" entre "<<xmin<<","<<xmax<<endl;
+  if( rc <= 0 || sigma<=0. ) return rc;
+  if( it>=1 && fabs((double)(sigma-sigmaold))/sigma < perdiff ) break;
+  xmin = mean - scut*sigma; if(testl && xmin<lowbad ) xmin = lowbad;
+  xmax = mean + scut*sigma; if(testl && xmax>highbad) xmax = highbad;
+  sigmaold = sigma;
+}
+
+return rc;
+}
+
+/* --Methode-- (cmv 23/09/96) */
+template <class T>
+//++
+int Image<T>::FondSigmaCiel(float lowbad,float highbad,int pvsz
+              ,float nbsig1,float nbsig2,float nbsig3
+              ,float binsg,float frac,int modu,int deb)
+//
+//	Calcul automatique du fond de ciel et du sigma ciel en utilisant
+//	les methodes precedentes et en calculant au mieux le binning.
+//| lowbad,highbad: dynamoque utile de l'image (ADU)
+//| pvsz : taille du pave a traiter (centre au milieu de l'image)
+//| nbsig1 : pour EstimeFdSg  -> calcul sgbmax (def=3.5).
+//| nbsig2 : pour FondCiel (histo entre X maxi +/- nbsig2*sgbmax
+//|                        nbin = 2.*nbsig2*binsg) (def=5).
+//| nbsig3 : pour SigmaCiel (histo entre 0 +/- nbsig3*sgbmax
+//|                         nbin = 2.*nbsig3*binsg) (def=5).
+//| binsg : taille du bin pour les histos de FondCiel et SigmaCiel
+//|                        (def=0.33)
+//| frac : pour EstimeFdSg(...,frac,...)  (def=0.33)
+//--
+{
+if(pvsz<=0) pvsz = 100;
+if(nbsig1<=0) nbsig1 = 3.5;
+if(nbsig2<=0) nbsig2 = 5.0;
+if(nbsig3<=0) nbsig3 = 5.0;
+if(binsg<=0) binsg = 0.33; binsg = 1./binsg;
+if(frac<=0.) frac = 0.33;
+if(deb<0) deb=0;
+int lpdb = (deb>=3) ? deb-2 : 0;
+int envd = 0;
+GetIntEnv("PDEBUG_FOND", envd);
+if (lpdb < envd) lpdb = envd;
+if (deb < envd) deb = envd;
+float xbmax = 0., sgbmax = 0.;
+int nbin,rc;
+float xmin,xmax,binw,means;
+
+// creation sous image
+int pvsx = pvsz, pvsy = pvsz;
+if( pvsx > XSize() ) pvsx = XSize();
+if( pvsy > YSize() ) pvsy = YSize();
+Image<T> *ssima = NULL;
+bool cree = false;
+if( pvsx == XSize() && pvsy == YSize() ) {
+  ssima = this;
+} else {
+  int orgx = XSize()/2 - pvsx/2;  if( orgx < 0 ) orgx = 0;
+  int orgy = YSize()/2 - pvsy/2;  if( orgy < 0 ) orgy = 0;
+  if( orgx + pvsx > XSize() ) pvsx = XSize() - orgx;
+  if( orgy + pvsy > YSize() ) pvsy = YSize() - orgy;
+  ssima = new Image<T>(pvsx,pvsy);
+  cree = true;
+  CopieImageF(*ssima,*this,orgx,orgy,pvsx,pvsy,0,0,0.,0.);
+}
+
+// moyenne et sigma approches sur sous-image
+rc = ssima->EstimeFdSg(xbmax,sgbmax,nbsig1,frac,lowbad,highbad,deb-1);
+if( cree ) delete ssima;
+if(rc<0) return -2;
+fond = xbmax;
+sigmaFond = sgbmax;
+
+// bin entier... pas forcement necessaire.
+xmin = xbmax - nbsig2*sgbmax;
+xmax = xbmax + nbsig2*sgbmax;
+nbin = (int)(2.*nbsig2*binsg); if(nbin<5) nbin=5;
+binw = (xmax-xmin)/nbin;
+if(deb>0) cout<<"bin auto: xmin="<<xmin<<" xmax="<<xmax
+              <<" nbin="<<nbin<<" binw="<<binw<<endl;
+HBinInt(nbin,xmin,xmax);
+binw = (xmax-xmin)/nbin;
+if(deb>0) cout<<"bin auto entier:  nbin="<<nbin<<" binw="<<binw
+              <<" entre "<<xmin<<","<<xmax<<endl;
+
+// Optimisation de modu
+if( modu <= 0 ) {
+  // 4 fois plus de pixels que dans le pre-pave
+  int npv = 4*pvsz*pvsz;
+  int nima = XSize()*YSize();
+  if( npv >= nima || nima < 10000 ) modu = 1;
+      else modu = (int)( (float) nima / (float) npv );
+  if(deb) cout<<"modulo choisi a "<<modu<<endl;
+}
+
+// moyenne evoluee
+TRY {
+  fond = FondCiel(nbin,xmin,xmax,3,0.5,modu,lpdb);
+  if(deb>0) cout <<"Fond de ciel = "<<fond<< endl;
+} CATCHALL {
+  if(deb>0) cout << "Echec FondCiel" << endl;
+  return(-3);
+} ENDTRY
+  
+// sigma evolue
+TRY {
+  float dyn = nbsig3*sgbmax;
+  int nbins = (int) (2.*nbsig3*binsg);
+  float binws = (2.*dyn)/nbins;
+  sigmaFond = SigmaCiel(nbins,-dyn,dyn,means,lowbad,highbad,4.,modu,lpdb);
+  if(deb>0) cout <<"Sigma fond de ciel = "<<sigmaFond
+                <<" (ms="<<means<<") sur "<<nbins
+                <<" bins de largeur "<<binws<< endl;
+} CATCHALL {
+  if(deb>0) cout << "Echec SigmaCiel" << endl;
+  return(-4);
+} ENDTRY
+
+// Impression finale
+if(deb) cout <<"ImgSigmaCiel: fond= "<<xbmax<<" / "<< fond
+             <<"   sigma= "<<sgbmax<<" / "<<sigmaFond<<endl;
+
+return 0;
+}
+
+
+
+/*  .......................................................  */
+/*         Fonctions de copie d'images et de paves           */
+/*  .......................................................  */
+
+
+/* Nouvelle-Fonction */ 
+template <class T2, class T1>
+void CopieImageF(Image<T2>& copie, Image<T1> const& pim,
+         int org_pim_x, int org_pim_y,            /* origine pave a copier */
+         int pim_lpav_x, int pim_lpav_y,          /* largeur pave a copier */
+         int org_copie_x, int org_copie_y,        /* origine copie         */
+         double cutmin, double cutmax)            /* coupure pour max range*/
+
+/* Copie d'une image (pim) ds l'autre (copie) a partir d'un  */
+/* offset specifie en pixel                                  */
+/* attention: pas d'offset -> org_x = org_y = 0              */
+{
+int i,j;
+// int x,y;  $CHECK$ Reza 21/06/99 changement de methode de calcul des bornes
+const T1* pt_pim;
+T2* pt_copie;
+double pim_pix;
+int l_copie_x,l_copie_y;
+int step_copie_x;
+int step_pim_x;
+int pim_siz_x, pim_siz_y;
+// int copie_siz_x, copie_siz_y;  $CHECK$ Reza 21/06/99 changement de methode de calcul des bornes
+int switch_copie;
+
+pim_siz_x=pim.XSize();
+pim_siz_y=pim.YSize();
+if((org_pim_x < 0) || (org_pim_x > pim_siz_x))
+  { cout<< "CopieImage_erreure : org_pim_x: " <<org_pim_x<<" < 0 ou > a "<<pim_siz_x<<endl;
+    THROW(rangeCheckErr);}
+if((org_pim_y < 0) || (org_pim_y > pim_siz_y))
+  { cout<< "CopieImage_erreure : org_pim_y: " <<org_pim_y<<" < 0 ou > a "<<pim_siz_y<<endl;
+    THROW(rangeCheckErr);}
+
+if( (org_copie_x < 0) || (org_copie_x > copie.XSize()) )
+  { cout<< "CopieImage_erreure : org_copie_x: " <<org_copie_x<<" < 0 ou > a "<< copie.XSize() << endl;
+    THROW(rangeCheckErr);}
+if( (org_copie_y < 0) || (org_copie_y > copie.YSize()) )
+  { cout<< "CopieImage_erreure : org_copie_y: " <<org_copie_y<<" < 0 ou > a "<< copie.YSize() << endl;
+    THROW(rangeCheckErr);}
+
+/* $CHECK$ Reza 21/06/99  Changement de methode de calcul ------
+$CHECK$ Reza 21/06/99 , je change la taille a copier en fonction de l'origine de copie 
+copie_siz_x=copie.XSize()-org_copie_x;
+copie_siz_y=copie.YSize()-org_copie_y;
+
+x=pim_lpav_x;
+if(x > (pim_siz_x-org_pim_x)) x=pim_siz_x-org_pim_x;
+step_pim_x = pim_siz_x-x;
+
+if(x < copie_siz_x)
+  {
+   l_copie_x=x;
+   step_copie_x=copie_siz_x-x;
+  }
+else
+  {
+   l_copie_x=copie_siz_x;
+   step_copie_x=0;
+   step_pim_x=step_pim_x+x-copie_siz_x;
+   }
+
+if(org_copie_x  > 0 )
+  {
+  int x=copie_siz_x-org_copie_x;
+  if(x < l_copie_x )
+    {
+     step_pim_x=step_pim_x+l_copie_x-x;
+     l_copie_x=x;
+     step_copie_x=org_copie_x;
+    }
+  else
+    { 
+     step_copie_x=copie_siz_x-l_copie_x;
+    }
+  }
+
+y=pim_lpav_y;
+if(y > (pim_siz_y-org_pim_y)) y=pim_siz_y-org_pim_y;
+
+if(y < copie_siz_y)
+  {
+   l_copie_y=y;
+  }
+else
+  {
+   l_copie_y=copie_siz_y;
+   }
+
+*/
+
+l_copie_x = copie.XSize()-org_copie_x;
+l_copie_y = copie.YSize()-org_copie_y;
+if ( pim_lpav_x > (pim.XSize()-org_pim_x) )  pim_lpav_x = pim.XSize()-org_pim_x;
+if ( pim_lpav_y > (pim.YSize()-org_pim_y) )  pim_lpav_y = pim.YSize()-org_pim_y;
+if ( (pim_lpav_x > 0) && (l_copie_x > pim_lpav_x) )  l_copie_x = pim_lpav_x;
+if ( (pim_lpav_y > 0) && (l_copie_y > pim_lpav_y) )  l_copie_y = pim_lpav_y;
+step_pim_x = pim.XSize()-l_copie_x;
+step_copie_x = copie.XSize()-l_copie_x;
+
+pt_pim  = pim.ImagePtr() + org_pim_y*pim.XSize() + org_pim_x;
+pt_copie=copie.ImagePtr() + org_copie_y*copie.XSize() + org_copie_x;
+
+switch((int)ConvType(*pt_pim,*pt_copie)) {
+  case t_same: case t_up:
+    switch_copie=0;
+  break;
+  case t_spe: case t_down:
+    switch_copie=1;
+  break;
+}
+
+if(cutmin < cutmax) switch_copie *= 2;
+
+switch(switch_copie) {
+  case 0:
+    for (j=0; j< l_copie_y; j++)
+      {
+      for(i=0; i< l_copie_x; i++)
+        {
+        *pt_copie++ =(T2)*pt_pim++;
+        }
+      pt_pim   += step_pim_x;
+      pt_copie += step_copie_x;
+      }
+  break;
+  case 1:
+    for (j=0; j< l_copie_y; j++)
+      {
+      for(i=0; i< l_copie_x; i++)
+        {
+        pim_pix = *pt_pim++;
+        *pt_copie++ = PutInRange(pim_pix, *pt_copie);
+        }
+      pt_pim   += step_pim_x;
+      pt_copie += step_copie_x;
+      }
+  break;
+  case 2:
+    for (j=0; j< l_copie_y; j++)
+      {
+      for(i=0; i< l_copie_x; i++)
+        {
+        pim_pix = *pt_pim++;
+        *pt_copie++ = (T2)SharePix(pim_pix,*pt_copie,cutmin,cutmax);
+        }
+      pt_pim   += step_pim_x;
+      pt_copie += step_copie_x;
+      }
+  break;
+}
+
+copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
+}
+
+
+/* Nouvelle-Fonction */ 
+template <class T2, class T1>
+void CopieImage(Image<T2>& copie , Image<T1> const& pim)
+{
+if (!pim.ImagePtr())   THROW(nullPtrErr);
+if (!copie.ImagePtr()) copie.Allocate(pim.XSize(),pim.YSize());
+
+CopieImageF(copie, pim,0,0,pim.XSize(),pim.YSize(),0,0,0., 0.);
+}
+
+/* Nouvelle-Fonction */ 
+template <class T2, class T1>
+void CopieImage(Image<T2>& copie , Image<T1> const& pim,
+                int org_pim_x    , int org_pim_y,
+                int pim_lpav_x   , int pim_lpav_y,
+                int org_copie_x  , int org_copie_y,
+                double cutmin    , double cutmax )
+{
+if (!pim.ImagePtr())   THROW(nullPtrErr);
+if (!copie.ImagePtr()) THROW(nullPtrErr);
+copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
+// copie.SetOrg(org_pim_x,org_pim_y);
+
+/* Reza 28/04/95 : Je protege pour le moment contre les pave en
+dehors de l'image, mais je veux pouvoir copier des paves decale par
+rapport aux bornes de l'image source  Re- CMV+Reza 30/09/96 */
+/* $CHECK$ Reza 21/06/99 - Ca devrait etre OK  */
+if ( (org_pim_x < 0) || (org_pim_y < 0) ||
+     (org_pim_x >= pim.XSize() ) || (org_pim_y >= pim.YSize() ) ||
+     ((org_pim_x+copie.XSize()) > pim.XSize()) ||
+     ((org_pim_y+copie.YSize()) > pim.YSize()) ) copie.Zero(); 
+
+if ( (org_pim_x >= pim.XSize()) || (org_pim_y >= pim.YSize()) ) {
+  copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
+  return;
+}   
+// if ( (org_pim_x < 0) || (org_pim_y < 0) ||
+//      (org_pim_x >= pim.XSize() ) || (org_pim_y >= pim.YSize() )) return;
+
+int oox = org_pim_x;
+int ooy = org_pim_y;
+int ocx = org_copie_x;
+int ocy = org_copie_y;
+if (oox < 0)  { ocx -= oox;  oox = 0; }
+if (ooy < 0)  { ocy -= ooy;  ooy = 0; }
+/*  Fin de $CHECK$  */
+
+// void CopieImageF(Image<T2>& copie, Image<T1> const& pim,
+//         int org_pim_x, int org_pim_y,            /* origine pave a copier */
+//         int pim_lpav_x, int pim_lpav_y,          /* largeur pave a copier */
+//         int org_copie_x, int org_copie_y,        /* origine copie         */
+//         double cutmin, double cutmax)            /* coupure pour max range*/
+
+if((pim_lpav_x <= 0) || (pim_lpav_x > pim.XSize())) pim_lpav_x=pim.XSize();
+if((pim_lpav_y <= 0) || (pim_lpav_y > pim.YSize())) pim_lpav_y=pim.YSize();
+try {
+  CopieImageF(copie, pim, oox, ooy, 
+              pim_lpav_x, pim_lpav_y,
+              ocx, ocy, cutmin,cutmax);
+  }  catch(RangeCheckError) {
+// $PLANCKCHECK$   if (merr != rangeCheckErr) THROW(merr);  // Re- $CHECK$ CMV+Reza 30/09/96
+  } ENDTRY
+
+copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
+}
+
+
+/* Nouvelle-Fonction */ 
+template <class T2, class T1>
+void CopiePave ( Image<T2>& pave , Image<T1> const& pim,
+                 float xc, float yc,
+                 double cutmin, double cutmax) 
+{
+int ix, iy;
+
+xc -= 0.5 * (float)(pave.XSize()-1);
+yc -= 0.5 * (float)(pave.YSize()-1);
+//  CopiePave tient compte de l'origine de l'image de depart   Reza 18/9/96
+xc -= pim.XOrg();     yc -= pim.YOrg();
+
+if ( xc >= 0.)  ix = (int)xc;
+else ix = (int)(xc-1.0);
+if ( yc >= 0.)  iy = (int)yc;
+else iy = (int)(yc-1.0);
+CopieImage(pave, pim, ix, iy, 0, 0, 0, 0, cutmin, cutmax ) ;
+}
+
+
+/* Nouvelle-Fonction */ 
+template <class T>
+void RzCopieImage(Image<T>& copie, RzImage const& pim,
+                  int org_pim_x , int org_pim_y,
+                  int pim_lpav_x, int pim_lpav_y,
+                  int org_copie_x, int org_copie_y,
+                  double cutmin , double cutmax)
+{
+  switch (pim.PixelType()) {
+  case kuint_2: {
+    ImageU2 src((RzImage&)pim);
+    CopieImage(copie, src, org_pim_x , org_pim_y,
+               pim_lpav_x, pim_lpav_y, org_copie_x, 
+               org_copie_y, cutmin, cutmax );
+    break;
+    }
+  case kint_2: {
+    ImageI2 src((RzImage&)pim);
+    CopieImage(copie, src, org_pim_x , org_pim_y,
+               pim_lpav_x, pim_lpav_y, org_copie_x, 
+               org_copie_y, cutmin, cutmax );
+    break;
+    }
+  case kint_4: {
+    ImageI4 src((RzImage&)pim);
+    CopieImage(copie, src, org_pim_x , org_pim_y,
+               pim_lpav_x, pim_lpav_y, org_copie_x, 
+               org_copie_y, cutmin, cutmax );
+    break;
+    }
+  case kr_4: {
+    ImageR4 src((RzImage&)pim);
+    CopieImage(copie, src, org_pim_x , org_pim_y,
+               pim_lpav_x, pim_lpav_y, org_copie_x, 
+               org_copie_y, cutmin, cutmax );
+    break;
+    }
+  case kr_8:
+  case kuint_4:
+  case kuint_1:
+  case kint_1:
+    cerr << " RzCopieImage(...) / Error, Unsupported image type (kr_8/ kuint_4/ kuint_1/ kint_1) " 
+         << (int)pim.PixelType() << "\n";
+    break;
+  default:
+    cerr << " RzCopieImage(...) / Error, Unknown image type !" <<  (int)pim.PixelType() << "\n";
+    break;
+  } 
+}
+
+
+/* Nouvelle-Fonction */ 
+template <class T>
+void RzCopieImage(Image<T>& copie, RzImage const& pim)
+{
+  switch (pim.PixelType()) {
+  case kuint_2: {
+    ImageU2 src((RzImage&)pim);
+    CopieImage(copie, src);
+    break;
+    }
+  case kint_2: {
+    ImageI2 src((RzImage&)pim);
+    CopieImage(copie, src);
+    break;
+    }
+  case kint_4: {
+    ImageI4 src((RzImage&)pim);
+    CopieImage(copie, src);
+    break;
+    }
+  case kr_4: {
+    ImageR4 src((RzImage&)pim);
+    CopieImage(copie, src);
+    break;
+    }
+  case kr_8:
+  case kuint_4:
+  case kuint_1:
+  case kint_1:
+    cerr << " RzCopieImage() / Error, Unsupported image type (kr_8/ kuint_4/ kuint_1/ kint_1) " 
+         << (int)pim.PixelType() << "\n";
+    break;
+  default:
+    cerr << " RzCopieImage() / Error, Unknown image type ! " <<  (int)pim.PixelType() << "\n";
+    break;
+  } 
+}
+
+/* Nouvelle-Fonction */ 
+template <class T>
+void RzCopiePave(Image<T> & pave, RzImage const & pim,
+                 float xc, float yc, 
+                 double cutmin, double cutmax) 
+{
+int ix, iy;
+
+xc -= 0.5 * (float)(pave.XSize()-1);
+yc -= 0.5 * (float)(pave.YSize()-1);
+//  RzCopiePave tient compte de l'origine de l'image de depart   Reza 18/9/96
+xc -= pim.XOrg();     yc -= pim.YOrg();
+
+if ( xc >= 0.)  ix = (int)xc;
+else ix = (int)(xc-1.0);
+if ( yc >= 0.)  iy = (int)yc;
+else iy = (int)(yc-1.0);
+
+RzCopieImage(pave, pim, ix, iy, 0, 0, 0, 0, cutmin, cutmax) ;
+}
+
+
+/* Nouvelle-Fonction */ 
+void RzPrintImage(RzImage & img)
+{
+switch (img.PixelType()) 
+  {
+  case kuint_1: 
+    {
+    ImageU1 src((RzImage&)img);
+    cout << src ;
+    break;
+    }
+  case kuint_2: 
+    {
+    ImageU2 src((RzImage&)img);
+    cout << src ;
+    break;
+    }
+  case kint_2: 
+    {
+    ImageI2 src((RzImage&)img);
+    cout << src ;
+    break;
+    }
+  case kint_4: 
+    {
+    ImageI4 src((RzImage&)img);
+    cout << src ;
+    break;
+    }
+  case kr_4: 
+    {
+    ImageR4 src((RzImage&)img);
+    cout << src ;
+    break;
+    }
+  case kr_8:
+  case kuint_4:
+  case kint_1:
+    cerr << " RzPrintImage() / Error, Unsupported image type (kr_8/kuint_4/ kint_1) " 
+         << (int)img.PixelType() << "\n";
+    break;
+  default:
+    cerr << " RzPrintImage() / Error, Unknown image type " <<  (int)img.PixelType() << "\n";
+    break;
+  } 
+}
+
+
+// ********** INSTANCES
+#if defined(__xlC) || defined(__aCC__)
+void instancetempcimage(int n)
+{
+// #pragma define_template
+/* Cette fonction sert uniquement a forcer le compilo a instancier les
+  classes/fonctions template   */
+
+int m = n-50;
+ImageU1  iu1(n,n), xiu1(m,m);
+ImageU2  iu2(n,n), xiu2(m,m);
+ImageI2  ii2(n,n), xii2(m,m);
+ImageI4  ii4(n,n), xii4(m,m);
+ImageR4  ir4(n,n), xir4(m,m);
+RzImage  rzi(kr_4, n, n);
+
+cout << iu1;
+cout << iu2;
+cout << ii2;
+cout << ii4;
+cout << ir4;
+
+CopieImageF(iu2, xiu2, 50, 50);
+CopieImageF(iu2, xii2, 50, 50);
+CopieImageF(iu2, xii4, 50, 50);
+CopieImageF(iu2, xir4, 50, 50);
+CopieImageF(ii2, xiu2, 50, 50);
+CopieImageF(ii2, xii2, 50, 50);
+CopieImageF(ii2, xii4, 50, 50);
+CopieImageF(ii2, xir4, 50, 50);
+CopieImageF(ii4, xiu2, 50, 50);
+CopieImageF(ii4, xii2, 50, 50);
+CopieImageF(ii4, xii4, 50, 50);
+CopieImageF(ii4, xir4, 50, 50);
+CopieImageF(ir4, xiu2, 50, 50);
+CopieImageF(ir4, xii2, 50, 50);
+CopieImageF(ir4, xii4, 50, 50);
+CopieImageF(ir4, xir4, 50, 50);
+
+CopieImage(iu2, xiu2);
+CopieImage(iu2, xii2);
+CopieImage(iu2, xii4);
+CopieImage(iu2, xir4);
+CopieImage(ii2, xiu2);
+CopieImage(ii2, xii2);
+CopieImage(ii2, xii4);
+CopieImage(ii2, xir4);
+CopieImage(ii4, xiu2);
+CopieImage(ii4, xii2);
+CopieImage(ii4, xii4);
+CopieImage(ii4, xir4);
+CopieImage(ir4, xiu2);
+CopieImage(ir4, xii2);
+CopieImage(ir4, xii4);
+CopieImage(ir4, xir4);
+
+CopieImage(iu2, xiu2, 50, 50);
+CopieImage(iu2, xii2, 50, 50);
+CopieImage(iu2, xii4, 50, 50);
+CopieImage(iu2, xir4, 50, 50);
+CopieImage(ii2, xiu2, 50, 50);
+CopieImage(ii2, xii2, 50, 50);
+CopieImage(ii2, xii4, 50, 50);
+CopieImage(ii2, xir4, 50, 50);
+CopieImage(ii4, xiu2, 50, 50);
+CopieImage(ii4, xii2, 50, 50);
+CopieImage(ii4, xii4, 50, 50);
+CopieImage(ii4, xir4, 50, 50);
+CopieImage(ir4, xiu2, 50, 50);
+CopieImage(ir4, xii2, 50, 50);
+CopieImage(ir4, xii4, 50, 50);
+CopieImage(ir4, xir4, 50, 50);
+
+CopiePave(iu2, xiu2, (float)25., (float)25.);
+CopiePave(iu2, xii2, (float)25., (float)25.);
+CopiePave(iu2, xii4, (float)25., (float)25.);
+CopiePave(iu2, xir4, (float)25., (float)25.);
+CopiePave(ii2, xiu2, (float)25., (float)25.);
+CopiePave(ii2, xii2, (float)25., (float)25.);
+CopiePave(ii2, xii4, (float)25., (float)25.);
+CopiePave(ii2, xir4, (float)25., (float)25.);
+CopiePave(ii4, xiu2, (float)25., (float)25.);
+CopiePave(ii4, xii2, (float)25., (float)25.);
+CopiePave(ii4, xii4, (float)25.,(float) 25.);
+CopiePave(ii4, xir4, (float)25., (float)25.);
+CopiePave(ir4, xiu2, (float)25., (float)25.);
+CopiePave(ir4, xii2, (float)25., (float)25.);
+CopiePave(ir4, xii4, (float)25., (float)25.);
+CopiePave(ir4, xir4, (float)25., (float)25.);
+
+RzCopieImage(iu2, rzi, 50, 50);
+RzCopieImage(ii2, rzi, 50, 50);
+RzCopieImage(ii4, rzi, 50, 50);
+RzCopieImage(ir4, rzi, 50, 50);
+
+RzCopieImage(iu2, rzi);
+RzCopieImage(ii2, rzi);
+RzCopieImage(ii4, rzi);
+RzCopieImage(ir4, rzi);
+
+RzCopiePave(iu2, rzi, (float)25., (float)25.);
+RzCopiePave(ii2, rzi, (float)25., (float)25.);
+RzCopiePave(ii4, rzi, (float)25., (float)25.);
+RzCopiePave(ir4, rzi, (float)25., (float)25.);
+
+return;
+}
+
+#endif
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template Image<uint_1>
+#pragma define_template Image<uint_2>
+#pragma define_template Image<int_2>
+#pragma define_template Image<int_4>
+#pragma define_template Image<r_4>
+
+// pour supprimer les message Warning: Unresolved:
+//                                     __ls__XR7ostreamRC10Image__TUc
+
+ostream& operator << (ostream& s, ImageU1 const& pim)
+{
+cout << "operator << (ostream, ImageU1) Not implemented ..." << endl;
+return(s);
+}
+
+// CopieImageF
+#pragma define_template CopieImageF < uint_1 , uint_1 >
+#pragma define_template CopieImageF < uint_1 , uint_2 >
+#pragma define_template CopieImageF < uint_1 , int_2 >
+#pragma define_template CopieImageF < uint_1 , int_4 >
+#pragma define_template CopieImageF < uint_1 , r_4 >
+
+#pragma define_template CopieImageF < uint_2 , uint_2 >
+#pragma define_template CopieImageF < uint_2 , int_2 >
+#pragma define_template CopieImageF < uint_2 , int_4 >
+#pragma define_template CopieImageF < uint_2 , r_4 >
+
+#pragma define_template CopieImageF < int_2 , uint_2 >
+#pragma define_template CopieImageF < int_2 , int_2 >
+#pragma define_template CopieImageF < int_2 , int_4 >
+#pragma define_template CopieImageF < int_2 , r_4 >
+
+#pragma define_template CopieImageF < int_4 , uint_2 >
+#pragma define_template CopieImageF < int_4 , int_2 >
+#pragma define_template CopieImageF < int_4 , int_4 >
+#pragma define_template CopieImageF < int_4 , r_4 >
+
+#pragma define_template CopieImageF < r_4 , uint_2 >
+#pragma define_template CopieImageF < r_4 , int_2 >
+#pragma define_template CopieImageF < r_4 , int_4 >
+#pragma define_template CopieImageF < r_4 , r_4 >
+
+// CopieImage
+#pragma define_template CopieImage < uint_2 , uint_2 >
+#pragma define_template CopieImage < uint_2 , int_2 >
+#pragma define_template CopieImage < uint_2 , int_4 >
+#pragma define_template CopieImage < uint_2 , r_4 >
+
+#pragma define_template CopieImage < int_2 , uint_2 >
+#pragma define_template CopieImage < int_2 , int_2 >
+#pragma define_template CopieImage < int_2 , int_4 >
+#pragma define_template CopieImage < int_2 , r_4 >
+
+#pragma define_template CopieImage < int_4 , uint_2 >
+#pragma define_template CopieImage < int_4 , int_2 >
+#pragma define_template CopieImage < int_4 , int_4 >
+#pragma define_template CopieImage < int_4 , r_4 >
+
+#pragma define_template CopieImage < r_4 , uint_2 >
+#pragma define_template CopieImage < r_4 , int_2 >
+#pragma define_template CopieImage < r_4 , int_4 >
+#pragma define_template CopieImage < r_4 , r_4 >
+
+// CopiePave
+#pragma define_template CopiePave < uint_2 , uint_2 >
+#pragma define_template CopiePave < uint_2 , int_2 >
+#pragma define_template CopiePave < uint_2 , int_4 >
+#pragma define_template CopiePave < uint_2 , r_4 >
+
+#pragma define_template CopiePave < int_2 , uint_2 >
+#pragma define_template CopiePave < int_2 , int_2 >
+#pragma define_template CopiePave < int_2 , int_4 >
+#pragma define_template CopiePave < int_2 , r_4 >
+
+#pragma define_template CopiePave < int_4 , uint_2 >
+#pragma define_template CopiePave < int_4 , int_2 >
+#pragma define_template CopiePave < int_4 , int_4 >
+#pragma define_template CopiePave < int_4 , r_4 >
+
+#pragma define_template CopiePave < r_4 , uint_2 >
+#pragma define_template CopiePave < r_4 , int_2 >
+#pragma define_template CopiePave < r_4 , int_4 >
+#pragma define_template CopiePave < r_4 , r_4 >
+
+//RzCopieImage
+#pragma define_template RzCopieImage < uint_2 >
+#pragma define_template RzCopieImage < int_2 >
+#pragma define_template RzCopieImage < int_4 >
+#pragma define_template RzCopieImage < r_4 >
+
+//RzCopiePave
+#pragma define_template RzCopiePave < uint_2 >
+#pragma define_template RzCopiePave < int_2 >
+#pragma define_template RzCopiePave < int_4 >
+#pragma define_template RzCopiePave < r_4 >
+
+
+#endif
+
+
+#if defined(ANSI_TEMPLATES) 
+template class Image<uint_1>;
+template class Image<uint_2>;
+template class Image<int_2>;
+template class Image<int_4>;
+template class Image<r_4>;
+
+#if !defined(__aCC__)     // HP - aCC a du mal avec les fonctions templates 
+
+template void CopieImageF<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+
+template void CopieImage<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&);
+template void CopieImage<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&);
+template void CopieImage<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&);
+template void CopieImage<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&);
+template void CopieImage< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&);
+template void CopieImage< int_2,  int_2>(Image< int_2>&, Image< int_2> const&);
+template void CopieImage< int_2,  int_4>(Image< int_2>&, Image< int_4> const&);
+template void CopieImage< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&);
+template void CopieImage< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&);
+template void CopieImage< int_4,  int_2>(Image< int_4>&, Image< int_2> const&);
+template void CopieImage< int_4,  int_4>(Image< int_4>&, Image< int_4> const&);
+template void CopieImage< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&);
+template void CopieImage<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&);
+template void CopieImage<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&);
+template void CopieImage<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&);
+template void CopieImage<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&);
+
+template void CopieImage<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+
+template void CopiePave<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, float, float, double, double);
+
+
+template void RzCopieImage<uint_2>(Image<uint_2> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage< int_2>(Image< int_2> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage< int_4>(Image< int_4> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage<   r_4>(Image<   r_4> &, RzImage const &, int, int, int, int, int, int, double, double);
+
+template void RzCopieImage<uint_2>(Image<uint_2> &, RzImage const &);
+template void RzCopieImage< int_2>(Image< int_2> &, RzImage const &);
+template void RzCopieImage< int_4>(Image< int_4> &, RzImage const &);
+template void RzCopieImage<   r_4>(Image<   r_4> &, RzImage const &);
+
+template void RzCopiePave<uint_2>(Image<uint_2> &, RzImage const &, float, float, double, double);
+template void RzCopiePave< int_2>(Image< int_2> &, RzImage const &, float, float, double, double);
+template void RzCopiePave< int_4>(Image< int_4> &, RzImage const &, float, float, double, double);
+template void RzCopiePave<   r_4>(Image<   r_4> &, RzImage const &, float, float, double, double);
+
+#endif   // Pb avec HP aCC
+
+#endif
+
+
+#ifdef __GNU_TEMPLATES__
+template class Image<bool>;
+template class Image<uint_1>;
+template class Image<uint_2>;
+template class Image<int_2>;
+template class Image<int_4>;
+template class Image<r_4>;
+
+
+template void CopieImageF(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImageF(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+
+template void CopieImage(Image<uint_2>&, Image<uint_2> const&);
+template void CopieImage(Image<uint_2>&, Image< int_2> const&);
+template void CopieImage(Image<uint_2>&, Image< int_4> const&);
+template void CopieImage(Image<uint_2>&, Image<   r_4> const&);
+template void CopieImage(Image< int_2>&, Image<uint_2> const&);
+template void CopieImage(Image< int_2>&, Image< int_2> const&);
+template void CopieImage(Image< int_2>&, Image< int_4> const&);
+template void CopieImage(Image< int_2>&, Image<   r_4> const&);
+template void CopieImage(Image< int_4>&, Image<uint_2> const&);
+template void CopieImage(Image< int_4>&, Image< int_2> const&);
+template void CopieImage(Image< int_4>&, Image< int_4> const&);
+template void CopieImage(Image< int_4>&, Image<   r_4> const&);
+template void CopieImage(Image<   r_4>&, Image<uint_2> const&);
+template void CopieImage(Image<   r_4>&, Image< int_2> const&);
+template void CopieImage(Image<   r_4>&, Image< int_4> const&);
+template void CopieImage(Image<   r_4>&, Image<   r_4> const&);
+
+template void CopieImage(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
+template void CopieImage(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
+
+template void CopiePave(Image<uint_2>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave(Image<uint_2>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave(Image<uint_2>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave(Image<uint_2>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave(Image< int_2>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave(Image< int_2>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave(Image< int_2>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave(Image< int_2>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave(Image< int_4>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave(Image< int_4>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave(Image< int_4>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave(Image< int_4>&, Image<   r_4> const&, float, float, double, double);
+template void CopiePave(Image<   r_4>&, Image<uint_2> const&, float, float, double, double);
+template void CopiePave(Image<   r_4>&, Image< int_2> const&, float, float, double, double);
+template void CopiePave(Image<   r_4>&, Image< int_4> const&, float, float, double, double);
+template void CopiePave(Image<   r_4>&, Image<   r_4> const&, float, float, double, double);
+
+
+template void RzCopieImage(Image<uint_2> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage(Image< int_2> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage(Image< int_4> &, RzImage const &, int, int, int, int, int, int, double, double);
+template void RzCopieImage(Image<   r_4> &, RzImage const &, int, int, int, int, int, int, double, double);
+
+template void RzCopieImage(Image<uint_2> &, RzImage const &);
+template void RzCopieImage(Image< int_2> &, RzImage const &);
+template void RzCopieImage(Image< int_4> &, RzImage const &);
+template void RzCopieImage(Image<   r_4> &, RzImage const &);
+
+template void RzCopiePave(Image<uint_2> &, RzImage const &, float, float, double, double);
+template void RzCopiePave(Image< int_2> &, RzImage const &, float, float, double, double);
+template void RzCopiePave(Image< int_4> &, RzImage const &, float, float, double, double);
+template void RzCopiePave(Image<   r_4> &, RzImage const &, float, float, double, double);
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/cimage.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cimage.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cimage.h	(revision 752)
@@ -0,0 +1,299 @@
+// This may look like C code, but it is really -*- C++ -*-
+//  Classes image typee      E.Aubourg , E. Lesquoy     
+//                           Modifs R. Ansari   04/95
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef CIMAGE_SEEN
+#define CIMAGE_SEEN
+
+#include <iostream.h>
+#include <iomanip.h>
+#include "rzimage.h"
+
+// Flags de verifications sur les indices  dans rzimage.h 
+
+//#define IMGRGCHECK
+//#define IMGVOIDCHECK
+
+
+// **********************************************************
+// Classe Image
+
+
+template <class T>
+class Image : public RzImage {
+
+public:
+  Image(int sizx, int sizy, int zero=1);
+  Image();
+  Image(const Image<T>&, int sharePixels=0);
+  Image(const Image<T>&, int orgx, int orgy, int sizx=-1, int sizy=-1);
+  EXPLICIT Image(const RzImage&); // Pour Reza. Partage les pixels
+  Image(char *flnm);
+  virtual ~Image();
+
+  int_4                 ClassId() const       { return (ClassId_Image+DataType((T)0)); }
+  static PPersist*      Create()              { return new Image<T>;}
+
+  virtual void    ReadSelf(PInPersist&);
+
+  Image<T>&       operator= (const Image<T> &);
+  Image<T>&       operator= (T);
+
+  Image<T>&       operator+= (Image<T> const&);
+  Image<T>&       operator-= (Image<T> const&);
+  Image<T>&       operator*= (Image<T> const&);
+  Image<T>&       operator/= (Image<T> const&);
+
+  Image<T>&       operator+= (double);
+  Image<T>&       operator-= (double);
+  Image<T>&       operator*= (double);
+  Image<T>&       operator/= (double);
+
+  Image<T>        WhereNonZero();
+
+
+//   Impression de tout le contenu de l'image 
+  virtual void    PrintImage(ostream& os) const;
+  inline void     PrintImage() const  { PrintImage(cout); }
+
+  void            Zero();
+  void            Allocate(int sizx, int sizy, int zero=1, ImgVectP* pvpsh=NULL);
+
+  inline T&       operator() (int x, int y);
+  inline T        operator() (int x, int y) const;
+  inline T&       operator[] (int i);
+  inline T        operator[] (int i) const;
+  T*              ImagePtr()         {return imagePtr;}
+  const T*        ImagePtr() const   {return imagePtr;}
+                                            
+  int             CheckDyn(double min=-9.e19, double max=9.e19);
+
+  void            SeuilBas(double seuil, double val);
+  void            SeuilHaut(double seuil, double val);
+  void            SeuilBas(double seuil);
+  void            SeuilHaut(double seuil);
+  void            SetPixels(int szx, int szy, T* pim);
+
+  int EstimeFdSg(float& xbmax,float& sgbmax,float nbsig=3.5,float frac=0.33
+                ,float lowbad=1.,float highbad=-1.,int deb=0);
+  float FondCiel(int nbin,float bin_low,float bin_high
+                ,int degre=2,float frac=0.5f,int modu=1,int deb=0);
+  float SigmaCiel(int nbin,float bin_low,float bin_high,float& means
+                 ,float lowbad=1.,float highbad=-1.
+                 ,float nsig=4.f,int modu=1,int deb=0);
+  int   MoySigma(float& mean,float& sigma
+                ,float lowbad=1.,float highbad=-1.,int modu=1);
+  int   MoySigmaIter(float& mean,float& sigma,float lowbad=1.,float highbad=-1.
+                    ,int modu=1,int nitermx=10
+                    ,float perdiff=0.1f,float scut=3.5f, int deb=0);
+  int   FondSigmaCiel(float lowbad,float highbad,int pvsz=100
+              ,float nbsig1=3.5f,float nbsig2=7.f,float nbsig3=5.f
+              ,float binsg=0.5f,float frac=0.33f,int modu=1,int deb=0);
+
+
+protected:
+
+  void HBinInt(int& nbin,float& xmin,float& xmax);
+
+  T*              imagePtr;
+};
+
+// Definition de l'operateur << 
+//template <class T> 
+//ostream& operator << (ostream& s, Image<T> const& img)
+//  {  img.Print(s);  return(s);  }
+
+
+/*  .......................................................  */
+/*          Implementation inline des acces pixels           */
+/*  .......................................................  */
+
+// ----- Macro de verification des indices  ------ 
+
+#ifdef IMGRGCHECK
+#define CHECKIMG(_x_,_y_)                                  \
+      if ((_x_ >= siz_x) || (_y_ >= siz_y) ||              \
+          (_x_ < 0) || (_y_ < 0)) THROW(rangeCheckErr);  \
+      if (!imagePtr) THROW(nullPtrErr)
+#else
+#if defined(IMGVOIDCHECK)
+#define CHECKIMG(_x_,_y_) \
+      if (!imagePtr) THROW(NullPtrErr)
+#else
+#define CHECKIMG(_x_,_y_)
+#endif
+#endif /* IMGRGCHECK */
+
+#define INRANGE(_x_,_y_) ((_x_ < siz_x) && (_y_ < siz_y) && \
+                          (_x_ >= 0) && (_y_ >= 0))
+
+
+// Fin des macros  ------ 
+
+
+template <class T>
+inline T & Image<T>::operator() (int x, int y)
+{
+  CHECKIMG(x,y);
+  return imagePtr[x+y*siz_x];
+}
+
+template <class T>
+inline T Image<T>::operator() (int x, int y) const
+{
+  CHECKIMG(x,y);
+  return imagePtr[x+y*siz_x];
+}
+
+template <class T>
+inline T & Image<T>::operator[] (int i)
+{
+  CHECKIMG(0,0);
+  return imagePtr[i];
+}
+
+template <class T>
+inline T Image<T>::operator[] (int i) const
+{
+  CHECKIMG(0,0);
+  return imagePtr[i];
+}
+
+// Operateurs addition, multiplication, ... (+ - * / ) avec des doubles 
+
+template <class T> 
+Image<T> operator+ (Image<T> const& a, double b) 
+{
+  Image<T> c(a);
+  c += b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator- (Image<T> const& a, double b) 
+{
+  Image<T> c(a);
+  c -= b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator* (Image<T> const& a, double b) 
+{
+  Image<T> c(a);
+  c *= b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator/ (Image<T> const& a, double b) 
+{
+  Image<T> c(a);
+  c /= b;
+  return c;
+}
+
+// Operateurs addition, multiplication, ... (+ - * / ) entre images
+template <class T> 
+Image<T> operator+ (Image<T> const& a, Image<T> const& b)
+{
+  Image<T> c(a);
+  c += b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator- (Image<T> const& a, Image<T> const& b) 
+{
+  Image<T> c(a);
+  c -= b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator* (Image<T> const& a, Image<T> const& b) 
+{
+  Image<T> c(a);
+  c *= b;
+  return c;
+}
+
+template <class T> 
+Image<T> operator/ (Image<T> const& a, Image<T> const& b) 
+{
+  Image<T> c(a);
+  c /= b;
+  return c;
+}
+
+/*  .......................................................  */
+/*         Fonctions de copie d'images et de paves           */
+/*  .......................................................  */
+
+template <class T2, class T1>
+void CopieImageF(Image<T2>& copie, Image<T1> const& pim,
+                 int org_pim_x=0, int org_pim_y=0,
+                 int pim_lpav_x=0, int pim_lpav_y=0,
+                 int org_copie_x=0, int org_copie_y=0,
+                 double cutmin=0., double cutmax=0.);
+                
+template <class T2, class T1>
+void CopieImage(Image<T2>& copie, Image<T1> const& pim);
+
+template <class T2, class T1>
+void CopieImage(Image<T2>& copie, Image<T1> const& pim,
+                int org_pim_x, int org_pim_y,
+                int pim_lpav_x=0, int pim_lpav_y=0,
+                int org_copie_x=0, int org_copie_y=0,
+                double cutmin=0, double cutmax=0);
+
+
+template <class T2, class T1>
+void 
+CopiePave(Image<T2>& pave, Image<T1> const& pim,
+	  float xc, float yc, 
+	  double cutmin=0, double cutmax=0);
+
+
+template <class T>
+void 
+RzCopieImage(Image<T>& copie, RzImage const& pim,
+	     int org_pim_x, int org_pim_y,
+	     int pim_lpav_x=0, int pim_lpav_y=0,
+	     int org_copie_x=0, int org_copie_y=0,
+	     double cutmin=0, double cutmax=0);
+
+template <class T>
+void 
+RzCopieImage(Image<T>& copie, RzImage const& pim);
+
+template <class T>
+void 
+RzCopiePave(Image<T> & pave, RzImage const & pim,
+	    float xc, float yc,
+	    double cutmin=0, double cutmax=0);
+/*  .......................................................  */
+/*         Autres fonctions utilitaires pour RzImage         */
+/*  .......................................................  */
+
+void RzPrintImage(RzImage & img);
+
+/*  Images de types usuels   */
+
+typedef Image<uint_1> ImageU1;
+typedef Image<uint_2> ImageU2;
+typedef Image<int_2>  ImageI2;
+typedef Image<int_4>  ImageI4;
+typedef Image<r_4>    ImageR4;
+
+
+#ifdef __MWERKS__
+template <class T>
+ostream& operator << (ostream& s, Image<T> const& pim);
+#endif
+
+#endif
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/cspline.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cspline.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cspline.cc	(revision 752)
@@ -0,0 +1,483 @@
+#include "machdefs.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <iostream.h>
+
+#ifdef __MWERKS__
+   #include <iostream>
+#endif
+
+#include "nbtri.h"
+#include "cspline.h"
+
+//++
+// Class	CSpline
+// Lib	Outils++ 
+// include	cspline.h
+//
+//	Classe de spline 1D
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+CSpline::CSpline(int n,double* x,double* y,double yp1,double ypn
+                ,int natural,bool order)
+//
+//	Createur pour spline 3 sur "x[0->n],y[0->n]" avec "yp1,ypn" derivees
+//	au premier et dernier points et "natural" indiquant les types de
+//	contraintes sur les derivees 2sd au premier et dernier point.
+//	"order" doit etre mis a "true" si le tableau de "x[]" n'est pas ordonne
+//	dans l'ordre des "x" croissants ("x[i]<x[i+1]"): cette option
+//	realloue la place pour les tableaux "x,y" autrement seule une
+//	connection aux tableaux "x,y" externes est realisee.
+//--
+  : Nel(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
+  , YP1(yp1), YPn(ypn), X(NULL), Y(NULL), Y2(NULL), tmp(NULL)
+{
+SetNewTab(n,x,y,order,true);
+if( x != NULL && y != NULL) ComputeCSpline();
+
+END_CONSTRUCTOR
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+CSpline::CSpline(double yp1,double ypn,int natural)
+//
+//	Createur par defaut.
+//--
+  : Nel(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
+  , YP1(yp1), YPn(ypn), X(NULL), Y(NULL), Y2(NULL), tmp(NULL)
+{
+END_CONSTRUCTOR
+}
+
+//////////////////////////////////////////////////////////////////////////////
+CSpline::~CSpline()
+// destructeur
+{
+DelTab();
+}
+
+//++
+// Titre	Methodes
+//--
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+void CSpline::SetNewTab(int n,double* x,double* y,bool order,bool force)
+//
+//	Pour changer les tableaux sans recreer la classe,
+//	memes arguments que dans le createur.
+//	Pour connecter les tableaux "x[n],y[n]" aux pointeurs internes "X,Y"
+//	Si "order=true", on considere que x n'est pas range par ordre
+//	des "x" croissants. La methode alloue de la place pour des tableaux
+//	internes "X,Y" qu'elle re-ordonne par "x" croissant.
+//	"force=true" impose la reallocation des divers buffers, sinon
+//	la reallocation n'a lieu que si le nombre de points augmente.
+//--
+{
+ASSERT( n>3 );
+
+// allocation des buffers Y2 et tmp
+if( n>Nel || force ) {
+  if( Y2  != NULL ) delete [] Y2;
+  if( tmp != NULL ) delete [] tmp;
+  Y2   = new double[n];
+  tmp  = new double[n];
+}
+// des-allocation eventuelle de X,Y
+if( XY_Created ) {
+  if( !order || n>Nel || force ) {
+    if( X != NULL ) delete [] X;  X = NULL;
+    if( Y != NULL ) delete [] Y;  Y = NULL;
+    XY_Created = false;
+  }
+}
+// allocation eventuelle de X,Y
+if( order ) {
+  if( !XY_Created || n>Nel || force ) {
+    X = new double[n];
+    Y = new double[n];
+    XY_Created = true;
+  }
+}
+Nel = n;
+corrupt_Y2 = true;
+
+if( x==NULL || y==NULL ) return;
+
+// Classement eventuel par ordre des x croissants
+if( order ) {
+  if( tmp == NULL ) tmp = new double[n];
+  ind = (int_4 *) tmp;
+  tri_double(x,ind,(int_4) Nel);
+  for(int i=0;i<Nel;i++) {
+    X[i] = x[ind[i]];
+    Y[i] = y[ind[i]];
+    if( i>0 ) if( X[i-1]>= X[i] ) {
+      printf("CSpline::SetNewTab_Erreur: X[%d]>=X[%d] (%g>=%g)\n"
+            ,i-1,i,X[i-1],X[i]);
+      THROW(inconsistentErr);
+    }
+  }
+} else { X = x; Y = y; }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CSpline::DelTab()
+// destruction des divers tableaux en tenant compte des allocations/connections
+{
+if( X   != NULL && XY_Created ) delete [] X;    X   = NULL;
+if( Y   != NULL && XY_Created ) delete [] Y;    Y   = NULL;
+if( Y2  != NULL ) delete [] Y2;   Y2  = NULL;
+if( tmp != NULL ) delete [] tmp;  tmp = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+void CSpline::SetBound1er(double yp1,double ypn)
+//
+//	Pour changer les valeurs des derivees 1ere au 1er et dernier points
+//	Valeurs imposees des derivees 1ere au points "X[0]" et "X[Nel-1]".
+//--
+{
+if( yp1 == YP1 && ypn == YPn ) return;
+
+YP1 = yp1;
+YPn = ypn;
+
+corrupt_Y2 = true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+void CSpline::ComputeCSpline()
+//
+//	Pour calculer les tableaux de coeff permettant le calcul
+//	des interpolations spline.
+//--
+{
+// on ne fait rien si les tableaux ne sont pas connectes
+if( X == NULL || Y == NULL ) {
+  printf("CSpline::ComputeCSpline()_Erreur: tableaux non connectes X=%p Y=%p\n"
+        ,X,Y);
+  return;
+}
+// On ne fait rien si rien n'a change!
+if( ! corrupt_Y2 ) return;
+// protection si tmp a ete desalloue pour gain de place (ex: CSpline2)
+if( tmp == NULL ) tmp = new double[Nel];
+
+double p,qn,sig,un;
+
+if (Natural & Natural1)
+  Y2[0] = tmp[0] = 0.0;
+else {
+  Y2[0] = -0.5;
+  tmp[0] = (3.0/(X[1]-X[0]))*((Y[1]-Y[0])/(X[1]-X[0])-YP1);
+}
+
+for (int i=1;i<Nel-1;i++) {
+  sig = (X[i]-X[i-1])/(X[i+1]-X[i-1]);
+  p = sig * Y2[i-1] + 2.0;
+  Y2[i] = (sig-1.0)/p;
+  tmp[i]= (Y[i+1]-Y[i])/(X[i+1]-X[i]) - (Y[i]-Y[i-1])/(X[i]-X[i-1]);
+  tmp[i]= (6.0*tmp[i]/(X[i+1]-X[i-1])-sig*tmp[i-1])/p;
+}
+
+if (Natural & NaturalN)
+   qn = un = 0.0;
+else {
+   qn = 0.5;
+   un = (3.0/(X[Nel-1]-X[Nel-2]))
+       *(YPn-(Y[Nel-1]-Y[Nel-2])/(X[Nel-1]-X[Nel-2]));
+}
+Y2[Nel-1] = (un-qn*tmp[Nel-2])/(qn*Y2[Nel-2]+1.0);
+for (int k=Nel-2;k>=0;k--) Y2[k] = Y2[k]*Y2[k+1] + tmp[k];
+
+corrupt_Y2 = false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+double CSpline::CSplineInt(double x)
+//
+//	Interpolation spline en "x"
+//--
+{
+int klo,khi,k;
+double h,b,a,y = 0.;
+
+if( corrupt_Y2 ) {
+  cout<<"CSpline::CSplineInt: calcul des coef du spline corrupted"<<endl;
+  THROW(inconsistentErr);
+}
+
+klo = 0;
+khi = Nel-1;
+while (khi-klo > 1) {
+  k = (khi+klo) >> 1;
+  if (X[k] > x) khi=k;
+    else klo=k;
+}
+h=X[khi]-X[klo];
+
+if (h == 0.0) {
+  cout<<"CSpline::CSplineInt: pout khi="<<khi<<" klo="<<klo
+      <<" memes valeurs de X[]: "<<X[khi]<<endl;
+  THROW(inconsistentErr);
+}
+
+a = (X[khi]-x)/h;
+b = (x-X[klo])/h;
+y = a*Y[klo]+b*Y[khi]+((a*a*a-a)*Y2[klo]+(b*b*b-b)*Y2[khi])*(h*h)/6.0;
+
+return y;
+}
+
+///////////////////////////////////////////////////////////////
+///////// rappel des inlines pour commentaires ////////////////
+///////////////////////////////////////////////////////////////
+
+//++
+// inline void SetNaturalCSpline(int type = NaturalAll)
+//	Pour changer le type de contraintes sur les derivees 2sd
+//--
+//++
+// inline void Free_Tmp()
+//	Pour liberer la place tampon qui ne sert que
+//	dans ComputeCSpline() et pas dans CSplineInt
+//--
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//++
+// Class	CSpline2
+// Lib	Outils++ 
+// include	cspline.h
+//
+//	Classe de spline 2D
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+CSpline2::CSpline2(int n1,double* x1,int n2,double* x2,double* y
+                  ,int natural,bool order)
+//
+//	Meme commentaire que pour CSpline avec:
+//| x1[n1]: liste des coordonnees selon l axe 1
+//| x2[n2]: liste des coordonnees selon l axe 2
+//| y[n1*n2]: liste des valeurs avec le rangement suivant
+//| x1[0]......x1[n1-1]  x1[0]......x1[n1-1]  ... x1[0]......x1[n1-1]
+//| |    0<=i<n1      |  |    0<=i<n1      |  ... |    0<=i<n1      |
+//|      j=0 X2[0]            j=1 X2[1]              j=n2-1 X2[n2-1]
+//--
+  : Nel1(0), Nel2(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
+  , X1(NULL), X2(NULL), Y(NULL), Y2(NULL)
+  , Nel_S(0), S(NULL), Sint(NULL), tmp(NULL)
+{
+SetNewTab(n1,x1,n2,x2,y,order,true);
+if( x1 != NULL && x2 != NULL && y != NULL) ComputeCSpline();
+
+END_CONSTRUCTOR
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+CSpline2::CSpline2(int natural)
+//
+//	Createur par defaut.
+//--
+  : Nel1(0), Nel2(0), corrupt_Y2(true), XY_Created(false), Natural(natural)
+  , X1(NULL), X2(NULL), Y(NULL), Y2(NULL)
+  , Nel_S(0), S(NULL), Sint(NULL), tmp(NULL)
+{
+END_CONSTRUCTOR
+}
+
+//////////////////////////////////////////////////////////////////////////////
+CSpline2::~CSpline2()
+{
+DelTab();
+}
+
+//++
+// Titre	Methodes
+//--
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+void CSpline2::SetNewTab(int n1,double* x1,int n2,double* x2,double* y
+                        ,bool order,bool force)
+//
+//	Voir commentaire meme methode de CSpline
+//--
+{
+ASSERT( n1>3 && n2>3 );
+
+int n = ( n1 < n2 ) ? n2 : n1;
+
+// allocation des buffers Y2 et tmp et des CSpline 1D
+if( n1>Nel1 || n2>Nel2 || force ) {
+  if( Y2  != NULL ) delete [] Y2;
+  if( tmp != NULL ) delete [] tmp;
+  Y2   = new double[n1*n2];
+  tmp  = new double[n];
+
+  // et les CSpline[n1] pour memoriser les interpolations sur x1(0->n1)
+  if( S != NULL ) {
+    for(int i=0;i<Nel_S;i++) if(S[i] != NULL) { delete S[i]; S[i]=NULL;}
+    delete S; S = NULL;
+  }
+  S = new CSpline * [n2];
+  for(int j=0;j<n2;j++) {
+    S[j] = new CSpline(n1,NULL,NULL,0.,0.,Natural);
+    S[j]->Free_Tmp();
+  }
+  Nel_S = n2;
+
+  if( S != NULL ) { delete Sint; Sint = NULL;}
+  Sint = new CSpline(n2,NULL,NULL,0.,0.,Natural);
+
+}
+// des-allocation eventuelle de X1,X2,Y
+if( XY_Created ) {
+  if( !order || n1>Nel1 || n2>Nel2 || force ) {
+    if( X1 != NULL ) delete [] X1; X1 = NULL;
+    if( X2 != NULL ) delete [] X2; X2 = NULL;
+    if( Y != NULL )  delete [] Y;  Y  = NULL;
+    XY_Created = false;
+  }
+}
+// allocation eventuelle de X1,X2,Y
+if( order ) {
+  if( !XY_Created || n1>Nel1 || n2>Nel1 || force ) {
+    X1 = new double[n1];
+    X2 = new double[n2];
+    Y  = new double[n1*n2];
+    XY_Created = true;
+  }
+}
+Nel1 = n1;  Nel2 = n2;
+corrupt_Y2 = true;
+
+if( x1==NULL || x2==NULL || y==NULL ) return;
+
+// Classement eventuel par ordre des x1 et x2 croissants
+if( order ) {
+
+  if( tmp == NULL ) tmp = new double[n];
+  ind = (int_4 *) tmp;
+  double* Ytmp = new double[n1*n2];
+
+  // tri par valeur croissantes de x1
+  tri_double(x1,ind,(int_4) Nel1);
+  for(int i=0;i<Nel1;i++) {
+    X1[i] = x1[ind[i]];
+    if( i>0 ) if( X1[i-1] >= X1[i] )
+      { printf("CSpline::SetNewTab_Erreur: X1[%d]>=X1[%d] (%g>=%g)\n"
+              ,i-1,i,X1[i-1],X1[i]);
+        THROW(inconsistentErr); }
+    for(int j=0;j<Nel2;j++) Ytmp[j*Nel1+i]  = y[j*Nel1+ind[i]];
+  }
+
+  // tri par valeur croissantes de x2
+  tri_double(x2,ind,(int_4) Nel2);
+  for(int j=0;j<Nel2;j++) {
+    X2[j] = x2[ind[j]];
+    if( j>0 ) if( X2[j-1] >= X2[j] )
+      { printf("CSpline::SetNewTab_Erreur: X2[%d]>=X2[%d] (%g>=%g)\n"
+              ,j-1,j,X2[j-1],X2[j]);
+        THROW(inconsistentErr); }
+    for(int i=0;i<Nel1;i++) Y[j*Nel1+i] = Ytmp[j*Nel1+ind[i]];
+  }
+  delete [] Ytmp;
+
+} else {
+
+  X1 = x1;
+  X2 = x2;
+  Y  = y;
+
+}
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CSpline2::DelTab()
+{
+if( X1  != NULL && XY_Created ) delete [] X1;  X1   = NULL;
+if( X2  != NULL && XY_Created ) delete [] X2;  X2   = NULL;
+if( Y   != NULL && XY_Created ) delete [] Y;   Y   = NULL;
+if( Y2  != NULL ) delete [] Y2;   Y2  = NULL;
+if( tmp != NULL ) delete [] tmp;  tmp = NULL;
+if( S != NULL ) {
+  for(int i=0;i<Nel_S;i++) if(S[i] != NULL) { delete S[i]; S[i]=NULL;}
+  delete S; S = NULL;
+}
+if( Sint != NULL ) { delete Sint; Sint=NULL;}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+void CSpline2::ComputeCSpline()
+//
+//	Voir commentaire meme methode de CSpline
+//--
+{
+// on ne fait rien si X1 ou X2 ou Y non connectes
+if( X1 == NULL || X2 == NULL || Y == NULL ) return;
+// On ne fait rien si rien n'a change
+if( ! corrupt_Y2 ) return;
+
+for(int j=0; j<Nel2; j++) {
+  // on n'alloue pas de place nouvelle, on utilise CSpline2::tmp
+  S[j]->tmp = tmp;
+  // connection de X1,Y au spline 1D sans ordre demande
+  S[j]->SetNewTab(Nel1,X1,&Y[j*Nel1],false,false);
+  // calcul des coeff splien pour l'interpolation future
+  S[j]->ComputeCSpline();
+}
+
+corrupt_Y2 = false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//++
+double CSpline2::CSplineInt(double x1,double x2)
+//
+//	Voir commentaire meme methode de CSpline
+//--
+{
+// calcul de la valeur Y pour x=x1 et remplissage du tampon tmp
+for(int j=0;j<Nel2;j++) tmp[j] = S[j]->CSplineInt(x1);
+
+// connection X2,tmp pour interpolation selon x=x2
+Sint->SetNewTab(Nel2,X2,tmp,false,false);
+// calcul des coeff pour interpolation selon X2
+Sint->ComputeCSpline();
+// Interpolation finale
+return Sint->CSplineInt(x2);
+}
+
+///////////////////////////////////////////////////////////////
+///////// rappel des inlines pour commenatires ////////////////
+///////////////////////////////////////////////////////////////
+
+//++
+// inline void SetNaturalCSpline(int type = NaturalAll)
+//	Voir commentaire meme methode de CSpline
+//--
Index: /tags/V_Fev00/SophyaLib/NTools/cspline.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cspline.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cspline.h	(revision 752)
@@ -0,0 +1,118 @@
+#ifndef CSPLINE_H_SEEN
+#define CSPLINE_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+
+///////////////////////////////////////////////////////////////////
+// Class CSpline et CSpline2 selon Numerical Receipes (cmv 17/02/97)
+///////////////////////////////////////////////////////////////////
+class CSpline EXC_AWARE {
+
+public:
+
+  friend class CSpline2;
+
+  enum { NaturalAll = 3, NoNatural = 0, Natural1 = 1, NaturalN = 2 };
+
+  CSpline(int n,double* x,double* y,double yp1=0.,double ypn=0.
+         ,int natural=NaturalAll,bool order=true);
+
+  CSpline(double yp1=0.,double ypn=0.,int natural=NaturalAll);
+
+  virtual ~CSpline();
+
+  void SetNewTab(int n,double* x,double* y
+                ,bool order=true,bool force=false);
+
+  void SetBound1er(double yp1 = 0.,double yp2 = 0.);
+
+  inline void SetNaturalCSpline(int type = NaturalAll)
+                 { Natural = type;}
+
+  inline void Free_Tmp()
+                { if(tmp != NULL) delete [] tmp; tmp=NULL;}
+
+  void ComputeCSpline();
+
+  double CSplineInt(double x);
+
+protected:
+
+  void DelTab();
+
+  // nombre d elements dans les tableaux X et Y
+  int Nel;
+  // true si les tableaux ont ete changes
+  // et qu il faut recalculer ComputeCSpline()
+  bool corrupt_Y2;
+  // true si les tableaux X,Y ont ete alloues
+  bool XY_Created;
+  // type de contraintes sur la derivee 2sd
+  int Natural;
+  // valeurs imposees de la derivee 1ere aux limites
+  double YP1, YPn;
+
+  // tableaux rellement alloues si "order=true" ou seulement
+  // connectes aux tableaux externes si "order=false"
+  double* X;
+  double* Y;
+
+  // tableau des coeff permettant l interpolation,
+  // remplis par ComputeCSpline()
+  double* Y2;
+
+  // tableau tampon utilise dans ComputeCSpline()
+  double* tmp;
+  int_4*  ind;
+
+};
+
+
+///////////////////////////////////////////////////////////////////
+class CSpline2 EXC_AWARE {
+
+public:
+  CSpline2(int n1,double* x1,int n2,double* x2,double* y
+          ,int natural=CSpline::NaturalAll,bool order=true);
+
+  CSpline2(int natural=CSpline::NaturalAll);
+
+  virtual ~CSpline2();
+
+  void SetNewTab(int n1,double* x1,int n2,double* x2,double* y
+                ,bool order=true,bool force=false);
+
+  inline void SetNaturalCSpline(int type = CSpline::NaturalAll)
+                 { Natural = type;}
+
+  void ComputeCSpline();
+
+  double CSplineInt(double x1,double x2);
+
+protected:
+  void DelTab();
+
+  int Nel1, Nel2;
+  bool corrupt_Y2;
+  bool XY_Created;
+  int Natural;
+
+  double* X1;
+  double* X2;
+  double* Y;
+  double* Y2;
+
+  // nombre d elements alloues dans S
+  int Nel_S;
+  // tableau de CSpline pour interpolation selon X1
+  CSpline** S;       // S[0->n2]
+  CSpline*  Sint;
+
+  // tableau tampon utilise dans CSplineInt()
+  double* tmp;  // tmp[max(n1,n2)]
+  int_4*  ind;
+
+};
+
+#endif /* CSPLINE_H_SEEN */
Index: /tags/V_Fev00/SophyaLib/NTools/cvector.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cvector.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cvector.cc	(revision 752)
@@ -0,0 +1,212 @@
+#include "machdefs.h"
+#include <string.h>
+#include "cvector.h"
+#include "generalfit.h"
+#include "tvector.h"
+
+//++
+// Class	OVector
+// Lib	Outils++
+// include	cvector.h
+//
+//    Vecteur colonne, en fait une matrice avec une seule colonne, pour faire
+//    des opérations matricielles.      
+//--
+
+//++
+// Links	Parents
+// OMatrix
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+OVector::OVector(int n)
+//
+//	Constructeur, n = nombre d'éléments.
+//--
+: OMatrix(n, 1)
+{END_CONSTRUCTOR}
+
+
+//++
+OVector::OVector(int n, double* values)
+//
+//	Constructeur, à partir des valeurs. Pas d'allocation.
+//--
+: OMatrix(n, 1, values)
+{END_CONSTRUCTOR}
+
+
+//++
+OVector::OVector(const OVector& v)
+//
+//	Constructeur par copie.
+//--
+: OMatrix(v)
+{END_CONSTRUCTOR}
+
+
+//++
+OVector::OVector(const OMatrix& a)
+//
+//	Constructeur par "copie" à partir d'une matrice, qui doit avoir une seule colonne.
+//
+//	*Exceptions :*
+//	sizeMismatchErr    si la matrice a plus d'une colonne
+//--
+: OMatrix(a.nr,1)      // OMatrix(a) ne marche pas, pourquoi ???? bug gcc ???
+{
+  if (a.nc != 1) THROW(sizeMismatchErr);
+  memcpy(data, a.data, a.nr * sizeof(double));
+  END_CONSTRUCTOR
+}
+
+//++
+OVector::OVector(const TVector<r_8>& v)
+//
+//	Constructeur par "copie" a partir d'un TVector<r_8>.
+//	Attention, les donnees sont partagees.
+//--
+: OMatrix(v)
+{
+}
+
+//++
+// Titre	Opérateurs
+//--
+
+//++
+// double& operator()(int n)
+// double const& operator()(int n) const
+//	Accès aux éléments.
+//--
+
+
+//++
+OVector& OVector::operator = (double x)
+//
+//	Affectation à partir d'un scalaire. Tous les éléments prennent cette valeur.
+//--
+{
+  for (int i=0; i<nr; i++)
+    (*this)(i) = x ;
+  return *this;
+}
+
+//++
+double operator* (const OVector& v1, const OVector& v2)
+//
+//	Produit scalaire entre deux vecteurs.
+//--
+{
+  if (v1.nr != v2.nr) THROW(sizeMismatchErr);
+  double *p    = v1.data;
+  double *pEnd = v1.data + v1.ndata;
+  double *q    = v2.data;
+
+  double r = 0;
+
+  while (p<pEnd)
+    r += *p++ * *q++;
+
+  return r;
+}
+
+//++
+// OVector operator* (const OVector& v, double b)
+//	multiplication par un scalaire.
+//--
+
+//++
+// OVector operator* (const OMatrix& a, const OVector& b)
+//	produit matrice*vecteur.
+//--
+
+//++
+// Titres	Méthodes
+//--
+
+//++
+// int NElts() const
+//
+//	Nombre de lignes du vecteur.
+//--
+
+//++
+// void Realloc(int n, bool force=false)
+//
+//	Change la taille du vecteur. Réallocation physique seulement si
+//	pas assez de place, ou forcée si force=true.
+//--
+
+//++
+double LinSolveInPlace(OMatrix& a, OVector& b)
+//
+//	Résolution du système A*C = B
+//--
+{
+  if (a.NCol() != b.NRows()) THROW(sizeMismatchErr);
+  if (a.NCol() != a.NRows()) THROW(sizeMismatchErr);
+
+  return OMatrix::GausPiv(a,b);
+}
+
+
+//++
+double LinSolve(const OMatrix& a, const OVector& b, OVector& c)
+//
+//	Résolution du système A*C = B, avec C retourné dans B
+//--
+{ 
+  if (a.NCol() != b.NRows()) THROW(sizeMismatchErr);
+  if (a.NCol() != a.NRows()) THROW(sizeMismatchErr);
+  c = b;
+  OMatrix a1(a);
+  return OMatrix::GausPiv(a1,c);
+}
+
+//////////////////////////////////////////////////////////
+//++
+OVector OVector::FitResidus(GeneralFit& gfit,double xorg,double dx)
+//
+//	Retourne une classe contenant les residus du fit ``gfit''.
+//	La coordonnee de l'element (i) est -> x = xorg + i*dx
+//--
+{
+if(NElts()<=0)
+  throw(SzMismatchError("OVector::FitResidus: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("OVector::FitResidus: NULL pointer\n"));
+OVector par = gfit.GetParm();
+OVector v(*this);
+for(int i=0;i<NElts();i++) {
+  double x = xorg+i*dx;
+  v(i) -= f->Value(&x,par.Data());
+}
+return v;
+}
+
+//++
+OVector OVector::FitFunction(GeneralFit& gfit,double xorg,double dx)
+//
+//	Retourne une classe contenant la fonction du fit ``gfit''.
+//	La coordonnee de l'element (i) est -> x = xorg + i*dx
+//--
+{
+if(NElts()<=0)
+  throw(SzMismatchError("OVector::FitResidus: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("OVector::FitResidus: NULL pointer\n"));
+OVector par = gfit.GetParm();
+OVector v(*this);
+for(int i=0;i<NElts();i++) {
+  double x = xorg+i*dx;
+  v(i) = f->Value(&x,par.Data());
+}
+return v;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/cvector.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/cvector.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/cvector.h	(revision 752)
@@ -0,0 +1,101 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef VECTOR_SEEN
+#define VECTOR_SEEN
+#include "matrix.h"
+
+namespace SOPHYA {
+  class GeneralFit;
+  template <class T> class TVector;
+}
+
+// <summary> Vecteur colonne pour operations matricielles </summary>
+// Vecteur colonne, en fait une matrice avec une seule colonne, pour faire
+// des operations matricielles.
+class OVector : public OMatrix {
+  friend class TVector<r_8>;
+public:
+  // Constructeur, n = nombre d'elements.
+  EXPLICIT OVector(int n=1);
+  // Constructeur, a partir des valeurs. Pas d'allocation.
+  OVector(int n, double* values);
+  // Constructeur par copie
+  OVector(const OVector& v);
+  // Constructeur par "copie" a partir d'une matrice, qui doit avoir une colonne
+  // <thrown> sizeMismatchErr </thrown>
+  OVector(const OMatrix& a);
+  // Constructeur par copie a partir d'un TVector<r_8>
+  OVector(const TVector<r_8>& v);
+
+  // Construction automatique pour PPF
+  // <group>
+  enum {classId = ClassId_Vector};
+  int_4                 ClassId() const         { return classId; }
+  static PPersist*      Create() {return new OVector(1);}
+  // </group>
+  
+  // Change la taille du vecteur. Reallocation physique seulement si
+  // pas assez de place, ou forcee si force=true
+  void Realloc(int n, bool force=false);
+
+  OVector& operator = (const OVector& v);
+  OVector& operator = (double x);
+
+  // Acces aux elements
+  // <group>
+  double& operator()(int n);
+  double const& operator()(int n) const;
+  // </group>
+
+  // produit scalaire
+  // <group>
+  friend double operator* (const OVector& v1, const OVector& v2);
+  friend OVector operator* (const OVector& v, double b)
+  {return OVector(((OMatrix const&)v) * b);}
+  // </group>
+  // produit matrice*vecteur
+  friend OVector operator* (const OMatrix& a, const OVector& b)
+  {return OVector(a * ((OMatrix const&) (b)));}
+
+  // Nombre de lignes du vecteur
+  int NElts() const {return nr;}
+
+  // Resolution du systeme A*C = B
+  friend double LinSolve(const OMatrix& a, const OVector& b, OVector& c);
+  
+  // Resolution du systeme A*C = B, avec C retourne dans B
+  friend double LinSolveInPlace(OMatrix& a, OVector& b);
+
+  // Residus et fonction fittees.
+  OVector FitResidus(GeneralFit& gfit,double xorg=0.,double dx=1.);
+  OVector FitFunction(GeneralFit& gfit,double xorg=0.,double dx=1.);
+
+};
+
+
+inline OVector& OVector::operator = (const OVector& v)
+{ OMatrix::operator =(v); return *this; }
+
+
+inline double const& OVector::operator()(int n) const
+{
+#ifdef RGCHECK
+  if (n<0 || n>=ndata) THROW(rangeCheckErr);
+#endif
+  return data[n];
+}
+
+
+inline double& OVector::operator()(int n)
+{ 
+#ifdef RGCHECK
+  if (n<0 || n>=ndata) THROW(rangeCheckErr);
+#endif
+  return data[n];
+}
+
+inline void OVector::Realloc(int n, bool force)
+{ OMatrix::Realloc(n,1,force);}
+
+
+#endif /* VECTOR_SEEN */
Index: /tags/V_Fev00/SophyaLib/NTools/datacards.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datacards.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datacards.cc	(revision 752)
@@ -0,0 +1,312 @@
+// $Id: datacards.cc,v 1.3 1999-11-20 21:03:16 ansari Exp $
+//
+// Datacards, acquisition EROS II
+//
+//
+// Eric Aubourg, Decembre 95
+//
+// DAPNIA/SPP (Saclay) / CEA
+
+#include "machdefs.h"
+#include "datacards.h"
+#include "pexceptions.h"
+#include <algorithm>
+#include <iostream.h>
+#include <iomanip.h>
+#include <stdio.h>
+
+//++
+// Class	DataCards
+// Lib		Outils++ 
+// include	datacards.h
+//
+//   	Cette classe permet la gestion des parametres d'un programme a partir 
+//   	de mot-cle (lecture d'un fichier par exemple)
+//--
+
+//++
+// Titre	Constructeurs
+//--
+//++
+//
+// DataCards()
+// DataCards(string const& fn)
+//    Createur avec lecture des parametres ds le fichier de nom "fn"
+//--
+
+DataCards::DataCards()
+{
+}
+
+DataCards::DataCards(string const& fn)
+{
+  ReadFile(fn);
+}
+
+//++
+// Titre	Methodes
+//--
+//++
+// AddProcF(ProcCard f, string const& mtch="*")
+//	Ajoute une fonction de traitement a la liste pour les mots cle
+//      compatibles avec la chaine "mtch" ("mtch" peut contenir "*" en debut 
+//      fin de mot) 
+//
+// Clear()
+//	Supprime les cartes existantes
+//
+// ReadFile(string const& fn) 
+//      Lit le contenu du fichiers "fn" et ajoute les cartes a la liste
+//
+// AppendCard(string const& line)
+//	Rajoute la carte "line" a la liste
+//--
+
+void
+DataCards::AddProcF(ProcCard f, string const& mtch)
+{
+CrdPF mpf;
+if (f == NULL)  return;
+mpf.pf = f;
+if (mtch.length() <= 0)  mpf.patt = "*";
+else  mpf.patt = mtch;
+cpfs.push_back(mpf);
+
+// On applique cette nouvelle fonction aux cartes existantes
+CardList::iterator  ic;
+for(ic = cards.begin(); ic != cards.end(); ic ++)
+  {
+  vector<string>::iterator ik;
+  string tks;
+  for(ik = (*ic).tokens.begin(); ik != (*ic).tokens.end(); ik++)
+    tks = tks + " " + (*ik);
+  ApplyPF(mpf, (*ic).kw, tks);
+  }
+}
+
+void
+DataCards::Clear()
+{
+cards.erase(cards.begin(), cards.end());
+}
+
+void
+DataCards::ReadFile(string const& fn)
+{
+  string file = fn;
+  if (file == "") {
+    char * efn = getenv("PEIDA_DATACARDS");
+    if (efn != NULL)    file = efn;  
+  }
+  if (file == "")  return;
+
+  try {
+    DoReadFile(file);
+  } catch(...) {
+    char* wdp = getenv("PEIDA_WORK");
+    if (wdp) {
+      cerr << "DataCards::ReadFile() Error reading file " << fn << " (Trying with PEIDA_WORK) \n";
+      file = wdp + file;
+      DoReadFile(file);
+    }
+    else cerr << "DataCards::ReadFile() Error reading file " << fn << "\n";
+    throw IOExc("DataCards::ReadFile() Error");  
+  } 
+}
+
+void
+DataCards::AppendCard(string const& crd)
+{
+Card c;
+size_t p = 1;
+size_t q = crd.find_first_of(" \t");
+size_t l = crd.length();
+
+string toks;
+if (l < 2)  return;
+if (crd[0] != '@')  return;
+
+if (q < l)
+  {  c.kw = crd.substr(p,q-p);  toks = crd.substr(q, l-q); }
+else { c.kw = crd.substr(p,l-p);  toks = ""; }
+//  On applique les ProcFunc's
+ApplyPFL(c.kw, toks);
+while (q < l) 
+  {
+  p = crd.find_first_not_of(" \t",q+1); // au debut d'un token
+  if (p>=l) break;
+  q = crd.find_first_of(" \t",p); // la fin du token;
+  string token = crd.substr(p,q-p);
+  c.tokens.push_back(token);
+  }
+// On supprime la carte de la liste, si elle existe deja ...
+RemoveCard(c.kw);
+cards.push_back(c);
+}
+
+void
+DataCards::DoReadFile(string const& fn)
+{
+char line_buff[512];
+FILE *fip;
+
+if ( (fip = fopen(fn.c_str(),"r")) == NULL )  
+  throw IOExc("DataCards::DoReadFile() fopen Error ") ;
+while (fgets(line_buff,511,fip) != NULL)
+  {
+  line_buff[strlen(line_buff)-1] = '\0';   /*  LF/CR de la fin */
+  string line(line_buff);
+  AppendCard(line);
+  }
+}
+
+int
+DataCards::ApplyPF(CrdPF & cpf, string const& key, string const& toks)
+{
+int l,lk;
+int rc = 0;
+// On verifie si le "pattern" correspond
+bool mtch = false;
+l = cpf.patt.length(); 
+if (cpf.patt == "*")  mtch = true;
+else if (cpf.patt[0] == '*')   
+  {
+  lk = key.length();
+  if (cpf.patt[l-1] != '*')
+    {
+    if (strcmp(key.c_str()+(lk-l+1), cpf.patt.c_str()+1) == 0)   mtch = true;
+    }
+  else if  (key.find(cpf.patt.substr(1,l-2)) < lk)  mtch = true;
+  }
+else if (cpf.patt[l-1] == '*')
+  {
+  if ( strncmp(key.c_str(), cpf.patt.c_str(),l-1) == 0)  mtch = true;
+  }
+else if (key == cpf.patt)  mtch = true;
+
+// Si oui, on appelle la fonction correspondante
+if (mtch)  rc = cpf.pf(key, toks); 
+
+return(rc);
+}
+
+
+int
+DataCards::ApplyPFL(string const& key, string const& toks)
+{
+int rc = 0;
+CrdPFList::iterator icf;
+for(icf = cpfs.begin(); icf != cpfs.end(); icf++)
+  rc += ApplyPF((*icf), key, toks);
+return(rc);
+}
+
+void  
+DataCards::RemoveCard(string const& key)
+{
+CardList::iterator i;
+for(i=cards.begin(); i != cards.end(); i++)
+  if ((*i).kw == key) { cards.erase(i);  break;  }
+}
+
+DataCards::Card *
+DataCards::FindKey(string const& key)
+{
+/*
+  CardList::iterator i = find_if(cards.begin(), cards.end(), bind2nd(KeyEq(),key));
+  if (i == cards.end() ) return NULL;
+*/
+  CardList::iterator i;
+  for(i=cards.begin(); i != cards.end(); i++)
+    if ((*i).kw == key) return &*i;
+
+  return NULL;
+}
+
+//++
+// Titre	Acces aux parametres
+//--
+//++
+// int   NbCards()
+//	Renvoie le nombre de cartes data
+// bool	 HasKey(string const& key) 
+//	Indique l'existence d'une carte avec la cle "key"
+// int   NbParam(string const& key)
+//	Indique le nombre de parametre (separes par des espaces) pour la cle "key"
+// string  SParam(string const& key, int num = 0, string def="")
+//	Renvoie la valeur du parametre numero "num" ( 0..(NbParam()-1) ) sous forme de
+//	chaine de caracteres ("string")
+// long    IParam(string const& key, int numero = 0, long def = 0)
+//	Renvoie la valeur du parametre numero "num" ( 0..(NbParam()-1) ) convertie 
+//	en entier ("long")
+// double  DParam(string const& key, int numero = 0, double def = 0)
+//	Renvoie la valeur du parametre numero "num" ( 0..(NbParam()-1) ) convertie 
+//	en flottant ("double")
+//--
+
+
+bool
+DataCards::HasKey(string const& key)
+{
+  return FindKey(key) != NULL;
+}
+
+int 
+DataCards::NbCards()
+{
+return(cards.size());
+}
+
+int 
+DataCards::NbParam(string const& key)
+{
+  DataCards::Card * p = FindKey(key);
+  if (!p) return(-1);
+  else return(p->tokens.size());
+}
+
+string
+DataCards::SParam(string const& key, int numero, string def)
+{
+  DataCards::Card * p = FindKey(key);
+  if (!p) return def;
+  if ( (numero < 0) || (numero >= p->tokens.size()) )  return def;
+  return p->tokens[numero];
+}
+
+long
+DataCards::IParam(string const& key, int numero, long def)
+{
+  string p = SParam(key, numero, "");
+  if (p == "") return def;
+  long i;
+  //istrstream(p.c_str(), p.length()) >> i;
+  sscanf(p.c_str(),"%ld",&i);
+  return i;
+}
+
+double
+DataCards::DParam(string const& key, int numero, double def)
+{
+  string p = SParam(key, numero, "");
+  if (p == "") return def;
+  double i;
+  //istrstream(p.c_str(), p.length()) >> i;
+  sscanf(p.c_str(),"%lg",&i);
+  return i;
+}
+
+   
+ostream& operator << (ostream& s, DataCards c)
+{
+  for (DataCards::CardList::iterator i = c.cards.begin(); i != c.cards.end(); i++) {
+    s << setw(10) << (*i).kw << " ";
+    for (vector<string>::iterator j = (*i).tokens.begin(); j != (*i).tokens.end(); j++)
+      s << (*j) << " ";
+    s << endl;
+  }
+  return s;
+}
+
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/datacards.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datacards.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datacards.h	(revision 752)
@@ -0,0 +1,83 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: datacards.h,v 1.2 1999-10-21 15:25:42 ansari Exp $
+//
+// Datacards, acquisition EROS II
+//
+//
+// Eric Aubourg, Decembre 95
+// Reza Ansari, Aout 96
+//
+// DAPNIA/SPP (Saclay) / CEA    LAL - IN2P3/CNRS  (Orsay)
+
+#ifndef DATACARDS_SEEN
+#define DATACARDS_SEEN
+
+#include <string.h>
+#include <string>
+#include <functional>
+#include <list>
+#include <vector>
+#include <string>
+
+#include "peida.h"
+
+typedef int (*ProcCard)(string const& key, string const& toks);
+ 
+class DataCards EXC_AWARE {
+public:
+   DataCards();                  
+   DataCards(string const& fn);
+
+           // nom dans variable d'environnement PEIDA_DATACARDS
+           // par defaut, peida.datacards                        
+           // Si pas chemin complet, on tente dans repertoire 
+           // en cours, puis dans PEIDA_WORK
+
+   virtual ~DataCards() {}
+
+   void    AddProcF(ProcCard f, string const& mtch="*");
+
+   void    Clear();
+   void    ReadFile(string const& fn);
+   void    AppendCard(string const& line);
+
+   int     NbCards();
+   bool    HasKey(string const& key);
+   int     NbParam(string const& key);
+   string  SParam(string const& key, int numero = 0, string def="");
+   long    IParam(string const& key, int numero = 0, long def = 0);
+   double  DParam(string const& key, int numero = 0, double def = 0);
+   
+   friend ostream& operator << (ostream& s, DataCards c);
+
+public:
+   struct Card {
+     string kw;
+     vector<string> tokens;
+	 STRUCTCOMPF(Card,kw)
+   };
+   typedef list<Card> CardList;
+   struct CrdPF {
+     ProcCard pf;
+     string  patt;
+	 STRUCTCOMPF(CrdPF,pf)
+   };
+   typedef list<CrdPF> CrdPFList;
+protected:
+   CardList cards;
+   CrdPFList cpfs;
+
+   void  DoReadFile(string const& fn);
+
+   int   ApplyPF(CrdPF & cpf, string const& key, string const& toks);
+   int   ApplyPFL(string const& key, string const& toks);
+
+   void  RemoveCard(string const& key);
+   
+   Card* FindKey(string const& key);
+   struct KeyEq : binary_function<Card, string, bool> {
+    bool operator()(const Card& x, const string& y) const { return x.kw == y; }
+   };
+};
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/datatypes.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datatypes.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datatypes.cc	(revision 752)
@@ -0,0 +1,82 @@
+// Type de donnees de base 
+//                E. Lesquoy , E. Aubourg 
+//                             R. Ansari 04/95
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#include "datatypes.h"
+
+/* Nouvelle-Fonction */
+char * DataName(PBaseDataTypes typ)
+{
+switch (typ)
+  {
+  case kuint_1 :
+    return ("uint_1");
+  case kint_1 :
+    return ("int_1");
+  case kuint_2 :
+    return ("uint_2");
+  case kint_2 :
+    return ("int_2");
+  case kint_4:
+    return ("int_4");
+  case kr_4 :
+    return ("r_4");
+  case kr_8 :
+    return ("r_8");
+  default :
+    return ("unknown");
+  }
+}
+
+/* Nouvelle-Fonction */
+char * DataLongName(PBaseDataTypes typ)
+{
+switch (typ)
+  {
+  case kuint_1 :
+    return ("unsigned char (*1)");
+  case kint_1 :
+    return ("signed char (*1)");
+  case kuint_2 :
+    return ("unsigned short int (*2)");
+  case kint_2 :
+    return ("short int (*2)");
+  case kint_4:
+    return ("int (*4)");
+  case kr_4 :
+    return ("float (*4)");
+  case kr_8 :
+    return ("double (*8)");
+  default :
+    return ("unknown");
+  }
+}
+
+/* Nouvelle-Fonction */
+int DataSize(PBaseDataTypes typ)
+{
+switch (typ)
+  {
+  case kuint_1 :
+    return (sizeof(uint_1));
+  case kint_1 :
+    return (sizeof(int_1));
+  case kuint_2 :
+    return (sizeof(uint_2));
+  case kint_2 :
+    return (sizeof(int_2));
+  case kint_4:
+    return (sizeof(int_4));
+  case kr_4 :
+    return (sizeof(r_4));
+  case kr_8 :
+    return (sizeof(r_8));
+  default :
+    return (0);
+  }
+}
+
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/datatypes.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datatypes.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datatypes.h	(revision 752)
@@ -0,0 +1,140 @@
+/*   Manipulation et conversion des types de bases     */
+/*          E. Aubourg, E. Lesquoy                     */
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef DATATYPES_H_SEEN
+#define DATATYPES_H_SEEN
+
+#include "machdefs.h"
+
+
+enum PBaseDataTypes {kpbdt_unknown=-1, kuint_1=1, kint_1=2, 
+                     kuint_2=3, kint_2=4, kuint_4=5, kint_4=6, 
+                     kr_4=7, kr_8=8};
+
+inline PBaseDataTypes DataType(uint_1) {return kuint_1;}
+inline PBaseDataTypes DataType(int_1)  {return kint_1;}
+inline PBaseDataTypes DataType(uint_2) {return kuint_2;}
+inline PBaseDataTypes DataType(int_2)  {return kint_2;}
+inline PBaseDataTypes DataType(uint_4) {return kuint_4;}
+inline PBaseDataTypes DataType(int_4)  {return kint_4;}
+inline PBaseDataTypes DataType(r_4)    {return kr_4;}
+inline PBaseDataTypes DataType(r_8)    {return kr_8;}
+
+char * DataName(PBaseDataTypes);
+char * DataLongName(PBaseDataTypes);
+int    DataSize(PBaseDataTypes);
+
+// Limites des types
+
+inline double   MinRange(uint_1) {return  0.0;}
+inline double   MaxRange(uint_1) {return  255.0;}
+inline double   MinRange(uint_2) {return  0.0;}
+inline double   MaxRange(uint_2) {return  65535.0;}
+inline double   MinRange(int_2)  {return -32768.0;}
+inline double   MaxRange(int_2)  {return  32767.0;}
+inline double   MinRange(int_4)  {return -2147483648.0;}
+inline double   MaxRange(int_4)  {return  2147483647.0;}
+inline double   MinRange(r_4)    {return -3.40282347e+38f;}
+inline double   MaxRange(r_4)    {return  3.40282347e+38f;}
+
+// reduction range donnee si on va du type 1 au type 2 (y/n)
+// ReducRange(type 1 , type 2 )
+// retour:
+
+enum {t_same,t_up,t_spe,t_down}; 
+//         t_same: meme type
+//         t_up  : ascendant   (I,U2)->(I4,R4), I4->R4 
+//         t_spe:  speciaux    I2->U2 , U2->I2 
+//         t_down: descendants R4->I4, (R4,I4)->(U2,I2) 
+
+inline int ConvType(uint_1 , uint_1 ) {return  t_same;}
+inline int ConvType(uint_1 , uint_2 ) {return  t_up;}
+inline int ConvType(uint_1 , int_2 )  {return  t_up;}
+inline int ConvType(uint_1 , int_4 )  {return  t_up;}
+inline int ConvType(uint_1 , r_4 )    {return  t_up;}
+inline int ConvType(uint_2 , uint_1 ) {return  t_down;}
+inline int ConvType(uint_2 , uint_2 ) {return  t_same;}
+inline int ConvType(uint_2 , int_2 )  {return  t_spe;}
+inline int ConvType(uint_2 , int_4 )  {return  t_up;}
+inline int ConvType(uint_2 , r_4 )    {return  t_up;}
+inline int ConvType(int_2 , uint_1 )  {return  t_down;}
+inline int ConvType(int_2 , uint_2 )  {return  t_spe;}
+inline int ConvType(int_2 , int_2 )   {return  t_same;}
+inline int ConvType(int_2 , int_4 )   {return  t_up;}
+inline int ConvType(int_2 , r_4 )     {return  t_up;}
+inline int ConvType(int_4 , uint_1 )  {return  t_down;}
+inline int ConvType(int_4 , uint_2 )  {return  t_down;}
+inline int ConvType(int_4 , int_2 )   {return  t_down;}
+inline int ConvType(int_4 , int_4 )   {return  t_same;}
+inline int ConvType(int_4 , r_4 )     {return  t_up;}
+inline int ConvType(r_4 , uint_1 )    {return  t_down;}
+inline int ConvType(r_4 , uint_2 )    {return  t_down;}
+inline int ConvType(r_4 , int_2 )     {return  t_down;}
+inline int ConvType(r_4 , int_4 )     {return  t_down;}
+inline int ConvType(r_4 , r_4 )       {return  t_same;}
+
+/*
+template <class T> 
+inline T PutInRange(double x,T t) {
+           return (T)( x < MinRange(t) ? MinRange(t) : \
+		      (x > MaxRange(t) ? MaxRange(t) : x));
+	 }
+// BUG GCC 2.6.1. Unresolved: xxx..ng
+*/
+
+inline uint_1 PutInRange(double x, uint_1 t) {
+  return (uint_1)( x < MinRange(t) ? MinRange(t) : \
+	     (x > MaxRange(t) ? MaxRange(t) : x));
+	 }
+inline uint_2 PutInRange(double x, uint_2 t) {
+  return (uint_2)( x < MinRange(t) ? MinRange(t) : \
+	     (x > MaxRange(t) ? MaxRange(t) : x));
+	 }
+inline int_2 PutInRange(double x, int_2 t) {
+  return (int_2)( x < MinRange(t) ? MinRange(t) : \
+	     (x > MaxRange(t) ? MaxRange(t) : x));
+	 }
+inline int_4 PutInRange(double x, int_4 t) {
+  return (int_4)( x < MinRange(t) ? MinRange(t) : \
+	     (x > MaxRange(t) ? MaxRange(t) : x));
+	 }
+inline r_4 PutInRange(double x  , r_4)  {return x;} 
+
+/*
+template <class T> 
+inline T SharePix(double x, T t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+// BUG GCC 2.6.1. Unresolved: xxx..ng
+*/
+inline double SharePix(double x, uint_1 t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+inline double SharePix(double x, uint_2 t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+inline double SharePix(double x, int_2 t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+inline double SharePix(double x, int_4 t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+inline double SharePix(double x, r_4 t, double cutmin, double cutmax)
+         { double tmp = (((x - cutmin)/(cutmax-cutmin))* \
+          ( MaxRange(t)-MinRange(t)))+ MinRange(t);
+	   return PutInRange(tmp, t);
+	 }
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/dates.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dates.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dates.cc	(revision 752)
@@ -0,0 +1,882 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <iostream.h>
+#include <time.h>
+#include <ctype.h>
+#include <math.h>
+#include "perrors.h"
+#include "dates.h"
+
+//++
+// Class	TimeZone
+// Lib		Outils++ 
+// include	dates.h
+//
+//	Classe de fuseau horaire. Permet les conversion
+//	GMT <-> temps local, en gérant les changements
+//	d'heure hiver-été.
+//	Deux fuseaux horaires sont prédéfinis, "France"
+//	et "Chili".
+//--
+
+TimeZone* gTimeZone = NULL;
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+TimeZone::TimeZone()
+//
+//	Constructeur par défaut. Il lit la variable
+//	d'environnement ACQ_TZ pour choisir le fuseau
+//	horaire. Si la variable n'est pas définie, nous
+//	sommes en France...
+//--
+{
+  char* p = getenv("ACQ_TZ");
+#if defined(__DECCXX) || defined(__KCC__) || defined(__aCC__)
+  if (!p) p = const_cast<char *>("France");
+#else
+  if (!p) p = "France";
+#endif
+  SetZone(p);
+  END_CONSTRUCTOR;
+}
+
+//++
+TimeZone::TimeZone(const char* nom)
+//
+//	Constructeur à partir du nom d'un fuseau horaire.
+//--
+{
+  SetZone(nom);
+  END_CONSTRUCTOR
+}
+
+//++
+void TimeZone::SetZone(const char* nom)
+//	
+//	Choisit un fuseau horaire. Contient la définition
+//	du fuseau "France" (GMT+1, DST : dernier dimanche
+//	de mars - dernier dimanche de septembre, c'est-à-dire
+//	pré-gouvernement Juppé), et Chili (GMT-4, DST :
+//	deuxième dimanche d'octobre - deuxième dimanche de mars).
+//--
+{
+  if (!strcmp(nom,"France")) {
+     strcpy(code,"MET");
+     strcpy(name,nom);
+     gmtOffset      = 1;
+     hasDST         = 1;
+     dstByWeekDay   = 1;
+     dstStartDay    = Date::jour_Dimanche; // dernier dimanche de mars
+     dstStartNum    = -1;
+     dstStartMonth  = Date::mois_Mars;
+     dstStopDay     = Date::jour_Dimanche; // dernier dimanche de septembre
+     dstStopNum     = -1;
+     dstStopMonth   = Date::mois_Septembre;
+     dstOffset      = 1;
+  } else if (!strcmp(nom,"Chili") || !strcmp(nom,"Chile")) {
+// # Chile has 2nd Sunday in October to 2nd Sunday in March DST
+    strcpy(code,"CST");
+    strcpy(name,"Chili");
+    gmtOffset      = -4;
+    hasDST         = 1;
+    dstByWeekDay   = 1;
+    dstStartDay    = Date::jour_Dimanche; // 2e dimanche d'octobre
+    dstStartNum    = 2;
+    dstStartMonth  = Date::mois_Octobre;
+    dstStopDay     = Date::jour_Dimanche; // 2e dimanche de mars
+    dstStopNum     = 2;
+    dstStopMonth   = Date::mois_Mars;
+    dstOffset      = 1;
+  } else THROW(parmErr);
+}
+
+//++
+int TimeZone::IsDst(const Date& date)
+//
+//	Teste si une date est en heure d'été (DST).
+//--
+{
+  Date dt = date;
+  if (dt.MM < 0 || dt.JJ < 0) THROW(inconsistentErr)
+  if (dt.hh >= 0) dt += gmtOffset/24.0; // date "fictive" en local d'hiver
+  else dt.ss = dt.hh = dt.mm = 0;       // minuit local si heure indeterminee
+  // On est en-dehors des mois frontiere ?
+  if (dstStartMonth < dstStopMonth) {
+     if (dt.MM < dstStartMonth) return 0;
+     if (dt.MM > dstStopMonth)  return 0;
+     if (dt.MM > dstStartMonth && dt.MM < dstStopMonth) return 1;
+  } else {
+     if (dt.MM < dstStopMonth)  return 1;
+     if (dt.MM > dstStartMonth) return 1;
+     if (dt.MM > dstStopMonth && dt.MM < dstStartMonth) return 0;
+  }
+  
+  // Nous sommes dans un mois-frontiere
+  DBASSERT(dt.MM == dstStopMonth || dt.MM == dstStartMonth);
+  
+  if (dt.MM == dstStartMonth) {
+    int jour;
+    if (dstByWeekDay) jour = Date::NthMonthDay(dstStartNum,dstStartDay, dt.MM, dt.AA);
+    else jour = (dstStartNum>0) ? dstStartNum : Date::MonthDays(dt.MM, dt.AA)+1-dstStartNum;
+    if (dt.JJ < jour) return 0;
+    if (dt.JJ > jour) return 1;
+    if (dt.hh > 1) return 1;
+    return 0;
+  } else {
+    int jour;
+    if (dstByWeekDay) jour = Date::NthMonthDay(dstStopNum,dstStopDay, dt.MM, dt.AA);
+    else jour = (dstStopNum>0) ? dstStopNum : Date::MonthDays(dt.MM, dt.AA)+1-dstStopNum;
+    if (dt.JJ < jour) return 1;
+    if (dt.JJ > jour) return 0;
+    if (dt.hh < 2) return 0;
+    return 1;
+  }
+}
+
+//++
+int TimeZone::GetOffset(const Date& date)
+//
+//	Retourne la difference TL-GMT pour une date donnée,
+//	en tenant compte de l'heure d'été éventuelle.
+//--
+{
+  return IsDst(date) ? gmtOffset+dstOffset : gmtOffset;
+}
+
+//++
+// Class	Date
+// Lib		Outils++ 
+// include	dates.h
+//
+//	Une classe date comme une autre, avec gestion
+//	temps local / GMT / changement d'heure, et un 
+//	jour temps sidéral.
+//
+//	Une partie de la date (heure, jour...) peut être
+//	indéterminée. Les comparaisons sont alors faites
+//	de façon astucieuse...
+//
+//	La date peut être déterminée de minuit à minuit
+//	ou de midi à midi (nuit d'observation). Logique
+//	complexe et peut-être foireuse pour passer de
+//	l'un à l'autre, mais pas encore d'ennuis pour le
+//	moment... Une date-nuit doit avoir une heure
+//	indéterminée.
+//
+//	Il faut que Date::gTimeZone soit initialisé pour
+//	éviter des gros pépins, mais PeidaInit() le fait.
+//
+//	An 2000 : Lorsqu'on gère des dates sous forme de chaine :
+//	* En sortie, 2 caractères pour l'année entre 1950 et 1999
+//	  et 4 caractères sinon
+//	* En entrée, si AA<100 on ajoute 1900.
+//--
+
+//++
+short Date::MonthDays(short mois, short annee)
+//
+//	Retourne le nombre de jours dans le mois
+//--
+{
+  if (mois<1 || mois>12) THROW(inconsistentErr);
+  
+  switch(mois) {
+    case mois_Janvier:
+    case mois_Mars:
+    case mois_Mai:
+    case mois_Juillet:
+    case mois_Aout:
+    case mois_Octobre:
+    case mois_Decembre:
+      return 31;
+    case mois_Avril:
+    case mois_Juin:
+    case mois_Septembre:
+    case mois_Novembre:
+      return 30;
+    case mois_Fevrier:
+     return (((annee%4 == 0) && (annee%100 != 0)) || (annee%400 == 0)) ? 29 : 28;
+  }
+  return -1;
+}
+    
+//++
+short Date::YearDays(short annee)
+//
+//	Retourne le nombre de jours dans l'année
+//--
+{
+  return (((annee%4 == 0) && (annee%100 != 0)) || (annee%400 == 0)) ? 366 : 365;
+}
+
+//++
+bool Date::UndetDate() const
+//
+//	Retourne true si une partie de la date (jour
+//	ou mois ou année) est indéterminée.
+//--
+{
+  return ((AA == -1) || (MM == -1) || (JJ == -1));
+}
+
+//++
+bool Date::AllUndetDate() const
+//
+//	Retourne true si toute la date (jour
+//	et mois et année) est indéterminée.
+//--
+{
+  return ((AA == -1) && (MM == -1) && (JJ == -1));
+}
+
+//++
+bool Date::UndetTime() const
+//
+//	Retourne true si une partie de l'heure (heure
+//	ou minutes ou secondes) est indéterminée.
+//--
+{
+  return ((hh == -1) || (mm == -1) || (ss == -1));
+}
+
+//++
+bool Date::AllUndetTime() const
+//
+//	Retourne true si toute l'heure (heure
+//	et minutes et secondes) est indéterminée.
+//--
+{
+  return ((hh == -1) && (mm == -1) && (ss == -1));
+}
+
+//Date::operator double() const
+
+//++
+double
+Date::GetDays() const
+//
+//	Jours écoulés depuis le 0 janvier 1901 0h TU
+//--
+{
+   if (UndetTime() && !AllUndetTime()) THROW(inconsistentErr);
+   if (UndetDate() && !AllUndetDate()) THROW(inconsistentErr);
+   double t=0;
+   if (!UndetDate()) {
+     int nban = AA-1901;
+     if (nban >= 0)  
+       t = nban*365 + (nban/4) - (nban/100) + ((nban+300)/400);
+     else 
+       t = nban*365 + (nban/4) - (nban/100) + ((nban-100)/400);
+     for (int i=1; i<MM; i++)  t += Date::MonthDays(i,AA);
+     t += JJ;
+   }
+   if (!UndetTime()) t += hh/24.0 + mm/1440.0 + ss/86400.0;
+   else if (nuit) t += 0.5;
+   return t;
+}
+
+//++
+void Date::Set(double t)
+//
+//	Jours écoulés depuis le 0 janvier 1901 0h TU
+//--
+{
+   t += 1/8640000.0;
+   int nban = int(floor((t/*-1*/) / 365.2425));
+   if (nban >= 0)  
+     t -= nban*365 + ((nban)/4) - ((nban)/100) + ((nban+300)/400);
+   else 
+     t -= nban*365 + ((nban)/4) - ((nban)/100) + ((nban-100)/400);
+     
+   AA = 1901 + nban;
+   if (t > Date::YearDays(AA)+1) {
+     t -= Date::YearDays(AA);
+     AA++;
+   } else if (t<1) {
+     AA--;
+     t += Date::YearDays(AA);
+   }
+   
+   MM = 1;
+   while (t > Date::MonthDays(MM,AA)+1) {
+     t -= Date::MonthDays(MM,AA);
+     MM++;
+   }
+   
+   JJ = int(t);
+   t -= JJ;
+   
+   t *= 24;
+   hh = int(t);
+   
+   t = (t-hh)*60;
+   mm = int(t);
+   
+   t = (t-mm)*60;
+   ss = t;
+   
+   nuit = 0;
+}
+//++
+Date::Date()
+//
+//	Constructeur. Prend l'heure courante...
+//--
+: timeZone(gTimeZone)
+{
+  time_t t = time(NULL);
+  struct tm* TM = gmtime(&t);
+  
+  AA = TM->tm_year + 1900;
+  MM = TM->tm_mon+1;
+  JJ = TM->tm_mday;
+  hh = TM->tm_hour;
+  mm = TM->tm_min;
+  ss = TM->tm_sec;
+  nuit = 0;
+  END_CONSTRUCTOR
+}
+
+//++
+Date::Date(int J, int M, int A, int h, int m, double s)
+//
+//	Constructeur simple.
+//--
+: JJ(J), MM(M), AA(A), hh(h), mm(m), ss(s), timeZone(gTimeZone), nuit(0)
+{
+  END_CONSTRUCTOR
+}
+
+//++
+Date::Date(double t)
+//
+//	Constructeur à partir des 
+//	jours écoulés depuis le 0 janvier 1901 0h TU
+//
+//--
+: timeZone(gTimeZone)
+{
+  Set(t);
+  END_CONSTRUCTOR
+}
+
+//++
+void Date::SetTimeZone(TimeZone* tz)
+// 
+//	On change de fuseau horaire.
+//--
+{
+  timeZone = tz;
+}
+
+//++
+Date::Date(const char* date, const char* heure, int tOpt)
+//
+//	Constructeur à partir de la date sous la forme
+//	'DD/MM/YYYY'  'HH/MM/SS', et tOpt est Date::kGMTTime
+//	(par défaut) ou Date::kLocalTime.
+//
+//	Tout ou partie de la date peut être indéterminée ('??').
+//--
+: timeZone(gTimeZone)
+{
+  Set(date,heure,tOpt);
+  END_CONSTRUCTOR
+}
+
+//++
+Date::Date(string const& date, string const& heure, int tOpt)
+//
+//	Constructeur à partir de la date sous la forme
+//	'DD/MM/YYYY'  'HH/MM/SS', et tOpt est Date::kGMTTime
+//	(par défaut) ou Date::kLocalTime.
+//
+//	Tout ou partie de la date peut être indéterminée ('??').
+//--
+: timeZone(gTimeZone)
+{
+  Set(date,heure,tOpt);
+  END_CONSTRUCTOR
+}
+
+//++
+void Date::Set(string const& date, string const& heure, int tOpt)
+//
+//	Positionne la date sous la forme
+//	'DD/MM/YYYY'  'HH/MM/SS', et tOpt est Date::kGMTTime
+//	(par défaut) ou Date::kLocalTime.
+//
+//	Tout ou partie de la date peut être indéterminée ('??').
+//--
+{
+  Set(date.c_str(), heure == "" ? (char*)NULL : heure.c_str(), tOpt);
+}
+
+//++
+void Date::Set(const char* date, const char* heure, int tOpt)
+//
+//	Positionne la date sous la forme
+//	'DD/MM/YYYY'  'HH/MM/SS', et tOpt est Date::kGMTTime
+//	(par défaut) ou Date::kLocalTime.
+//
+//	Tout ou partie de la date peut être indéterminée ('??').
+//--
+{
+  nuit = 0;
+  if (date) {
+   if (strlen(date) >= 5) {         //  J(J)/M(M)/AA(AA), ?/?/?, combinaison
+    const char* p = date;
+    if (p[0] == '?' && (p[1] == '?' || p[1] == '/'))   JJ = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
+      JJ = atoi(p);
+      if (JJ <= 0) THROW(inconsistentErr);
+    }
+    
+    if (p[1] == '/') p += 2;
+    else if (p[2] == '/') p+= 3;
+    else THROW(inconsistentErr);
+
+    if (p[0] == '?' && (p[1] == '?' || p[1] == '/'))   MM = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
+      MM = atoi(p);
+      if (MM <= 0 || MM >12) THROW(inconsistentErr);
+    }
+
+    if (p[1] == '/') p += 2;
+    else if (p[2] == '/') p+= 3;
+    else THROW(inconsistentErr);
+
+    if (p[0] == '?')  AA = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      if (!isdigit(p[1])) THROW(inconsistentErr);
+      AA = atoi(p);
+      if (AA < 100 && AA >= 0 && date[6] != '0') AA += 1900;
+    }
+    
+    if (AA > 0 && MM > 0 && JJ > 0 && JJ > MonthDays(MM,AA)) THROW(inconsistentErr);
+    
+   } else if (strlen(date)==4) {      // Code EROS de date
+     if (date[0] == '?') AA = -1;
+     else {
+       if (!isdigit(date[0])) THROW(inconsistentErr);
+       AA = 1990 + date[0] - '0';
+     }
+     
+     if (date[1] == '?') MM = -1;
+     else {
+       if (!isalpha(date[1])) THROW(inconsistentErr);
+       if (islower(date[1]))
+         MM = date[1] - 'a' + 1;
+       else
+         MM = date[1] - 'A' + 1;
+       if (MM<1 || MM>12) THROW(inconsistentErr);
+     }
+     
+     if (date[2] == '?' && date[3] == '?') JJ = -1;
+     else {
+       if (!isdigit(date[2])) THROW(inconsistentErr);
+       if (!isdigit(date[3])) THROW(inconsistentErr);
+       JJ = atoi(date+2);
+     }
+     
+     if (AA > 0 && MM > 0 && JJ > 0 && JJ > MonthDays(MM,AA)) THROW(inconsistentErr);
+     nuit = 1;
+   } else THROW(inconsistentErr);   // Mauvaise longueur
+  } else {                          // Pas de date
+    JJ = MM = AA = -1;
+  }
+  
+  if (heure) {
+    const char* p = heure;
+    if (p[0] == '?' && (p[1] == '?' || p[1] == ':'))   hh = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      if (!isdigit(p[1]) && p[1] != ':') THROW(inconsistentErr);
+      hh = atoi(p);
+    }
+
+    if (p[1] == ':') p += 2;
+    else if (p[2] == ':') p+= 3;
+    else THROW(inconsistentErr);
+
+    if (p[0] == '?' && (p[1] == '?' || p[1] == ':'))   mm = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
+      mm = atoi(p);
+    }
+
+    if (p[1] == ':') p += 2;
+    else if (p[2] == ':') p+= 3;
+    else THROW(inconsistentErr);
+
+    if (p[0] == '?')   ss = -1;
+    else {
+      if (!isdigit(p[0])) THROW(inconsistentErr);
+      ss = atoi(p);
+    }
+  } else {
+    ss = hh = mm = -1;
+  }
+  
+  if (tOpt == kLocalTime) {
+    DBASSERT(timeZone != NULL);
+    operator -= (timeZone->gmtOffset/24.0);
+    if (timeZone->IsDst(*this))
+      operator -= (timeZone->dstOffset/24.0);   // A VERIFIER SANS DOUTE INEXACT
+  } 
+  
+  if (nuit && !UndetTime() && hh < 12)
+    *this += 1;
+}
+
+//++
+void Date::GetDateStr(char* s, int tOpt) const
+//
+//	Récupère la date sous la forme d'une chaîne 'DD/MM/YYYY'
+//	en tOpt = Date::kGMTTime ou Date::kLocalTime.
+//--
+{
+  Date dt(*this);
+  if (tOpt == kLocalTime && !UndetTime()) {
+    DBASSERT(timeZone != NULL);
+    dt += timeZone->GetOffset(*this)/24.0;
+  }
+  
+  if (dt.AA < 1950 || dt.AA > 1999) 
+    sprintf(s, "%02d/%02d/%04d", dt.JJ, dt.MM, dt.AA);
+  else
+    sprintf(s, "%02d/%02d/%02d", dt.JJ, dt.MM, dt.AA-1900);
+    
+  if (dt.JJ == -1)
+    s[0] = s[1] = '?';
+  if (dt.MM == -1)
+    s[3] = s[4] = '?';
+  if (dt.AA == -1) {
+    s[6] = s[7] = '?';
+    s[8] = '\0';
+  }
+}
+
+//++
+void Date::GetDateCode(char* s, int tOpt) const
+//
+//	Code EROS de la date.
+//--
+{
+  Date dt(*this);
+  if (tOpt == kLocalTime && !UndetTime()) {
+    DBASSERT(timeZone != NULL);
+    dt += timeZone->GetOffset(*this)/24.0;
+  }
+
+  if (!dt.UndetTime() && dt.hh<12) dt -= 1;
+
+  if (dt.AA != -1) {
+    if (dt.AA < 1990 || dt.AA > 2016) THROW(inconsistentErr);
+    int i = dt.AA - 1990;
+    if (i<10)
+      s[0] = '0' + i;
+    else
+      s[0] = 'a' + i - 10;
+  } else
+    s[0] = '?';
+    
+  if (dt.MM != -1)
+    s[1] = 'a' + dt.MM - 1;
+  else
+    s[1] = '?';
+    
+  if (dt.JJ != -1)
+    sprintf(s+2, "%02d", dt.JJ);
+  else
+    s[2] = s[3] = '?';
+  
+  s[4] = 0;
+}
+
+//++
+void Date::GetTimeStr(char* s, int tOpt) const
+//
+//	Récupère l'heure sous la forme 'HH:MM:SS'
+//--
+{
+  Date dt(*this);
+  if (tOpt == kLocalTime) {
+    DBASSERT(timeZone != NULL);
+    dt += timeZone->GetOffset(*this)/24.0;
+  }
+
+  sprintf(s, "%02d:%02d:%02d", dt.hh, dt.mm, int(dt.ss));
+  if (dt.hh == -1)
+    s[0] = s[1] = '?';
+  if (dt.mm == -1)
+    s[3] = s[4] = '?';
+  if (dt.ss == -1)
+    s[6] = s[7] = '?';
+}
+
+//++
+void Date::GetSidTStr(char* s) const
+//
+//	Récupèrera un jour le temps sidéral.
+//--
+{
+  strcpy(s,"TOBEDONE!!");
+}
+
+//++
+string Date::DateStr(int tOpt) const
+//
+//	Récupère la date sous la forme d'une chaîne 'DD/MM/YYYY'
+//	en tOpt = Date::kGMTTime ou Date::kLocalTime.
+//--
+{
+   char s[20];
+   GetDateStr(s,tOpt);
+   return s;
+}
+
+//++
+string Date::DateCode(int tOpt) const
+//
+//	Code EROS de la date.
+//--
+{
+   char s[20];
+   GetDateCode(s,tOpt);
+   return s;
+}
+
+//++
+string Date::TimeStr(int tOpt) const
+//
+//	Récupère l'heure sous la forme 'HH:MM:SS'
+//--
+{
+   char s[20];
+   GetTimeStr(s,tOpt);
+   return s;
+}
+
+//++
+string Date::SidTStr() const
+//
+//	Récupèrera un jour le temps sidéral.
+//--
+{
+   char s[20];
+   GetSidTStr(s);
+   return s;
+}
+
+//++
+int Date::DayOfWeek(int tOpt) const
+//
+//	Retourne le jour dans la semaine, 0-6
+//	avec 0 = Date::jour_Lundi.
+//--
+{
+  double t = GetDays();
+  if (tOpt == kLocalTime && hh >=0) {
+    DBASSERT(timeZone != NULL);
+    t += timeZone->GetOffset(*this)/24.0;
+  }
+  int ndays = int(t);  // nb de jours depuis 0 janvier 1901
+  ndays = (ndays + 1) % 7;
+  if (ndays<0) ndays += 7;
+  return ndays;
+}
+
+//++
+short Date::NthMonthDay(short i, short joursem, short mois, short annee)
+//
+//	Retourne la date correspondant au ieme joursem dans le mois 
+//	correspondant (exemple, 2e dimanche de mars 1960).
+//--
+{
+   if (i>0) {
+     int jprem = Date(1, mois, annee, 0, 0, 0).DayOfWeek();
+     int d = (joursem - jprem);
+     if (d<0) d+=7;
+     return d + 1 + (i-1)*7;
+   } else {
+     int ider = MonthDays(mois, annee);
+     int jder = Date(ider, mois, annee, 0, 0, 0).DayOfWeek();
+     int d = (joursem - jder);
+     if (d>0) d-=7;
+     return d + ider + (i+1)*7;
+   }
+}
+
+//++
+Date& Date::operator += (double dt)     
+//
+//	dt en jours
+//--
+{
+  int u = UndetTime();
+  Set(GetDays()+dt);
+  if (u) ss = hh = mm = -1;
+  return *this;
+}
+
+//++
+Date& Date::operator -= (double dt)    
+//
+//	dt en jours
+//--
+{
+  int u = UndetTime();
+  Set(GetDays()-dt);
+  if (u) ss = hh = mm = -1;
+  return *this;
+}
+
+//++
+Date operator + (Date const& d, double dt)
+//
+//--
+{
+  Date a(d);
+  a += dt;
+  return a;
+}
+
+//++
+Date operator - (Date const& d, double dt)
+//
+//--
+{
+  Date a(d);
+  a -= dt;
+  return a;
+}
+
+//++
+double operator - (Date const& a, Date const& b)
+//
+//	Résultat en jours
+//--
+{
+  if (a.UndetTime() != b.UndetTime()) THROW(inconsistentErr);
+  if (a.UndetDate() != b.UndetDate()) THROW(inconsistentErr);
+  return a.GetDays() - b.GetDays();
+}
+
+//++
+bool operator == (Date const& a, Date const& b)
+//
+//	On n'a pas égalite dès que des éléments déterminés sont différents
+//--
+{
+  if (a.nuit && a.UndetTime() && !b.nuit && !b.UndetTime() && b.hh<12)
+    {Date d = a+1; d.nuit = 0; return d == b;}
+  else if (b.nuit && b.UndetTime() && !a.nuit && !a.UndetTime() && a.hh<12)
+    {Date d = b+1; d.nuit = 0; return a == d;}
+
+  if (a.AA != -1 && b.AA != -1 && a.AA != b.AA) return false;
+  if (a.MM != -1 && b.MM != -1 && a.MM != b.MM) return false;
+  if (a.JJ != -1 && b.JJ != -1 && a.JJ != b.JJ) return false;
+  if (a.hh != -1 && b.hh != -1 && a.hh != b.hh) return false;
+  if (a.mm != -1 && b.mm != -1 && a.mm != b.mm) return false;
+  if (a.ss != -1 && b.ss != -1 && a.ss != b.ss) return false;
+  return true;
+}
+
+//++
+bool operator != (Date const& a, Date const& b)
+//
+//--
+{
+  return !(a == b);
+}
+
+//++
+bool operator <= (Date const& a, Date const& b)
+//
+//	Inégalité large. Pas de subtilités
+//--
+{
+  if (a.nuit && a.UndetTime() && !b.nuit && !b.UndetTime() && b.hh<12)
+    {Date d = a+1; d.nuit = 0; return d <= b;}
+  else if (b.nuit && b.UndetTime() && !a.nuit && !a.UndetTime() && a.hh<12)
+    {Date d = b+1; d.nuit = 0; return a <= d;}
+
+  if (a.AA != -1 && b.AA != -1) {
+    if (a.AA < b.AA) return true;
+    if (a.AA > b.AA) return false;
+  }
+  if (a.MM != -1 && b.MM != -1) {
+    if (a.MM < b.MM) return true;
+    if (a.MM > b.MM) return false;
+  }
+  if (a.JJ != -1 && b.JJ != -1) {
+    if (a.JJ < b.JJ) return true;
+    if (a.JJ > b.JJ) return false;
+  }
+  if (a.hh != -1 && b.hh != -1) {
+    if (a.hh < b.hh) return true;
+    if (a.hh > b.hh) return false;
+  }
+  if (a.mm != -1 && b.mm != -1) {
+    if (a.mm < b.mm) return true;
+    if (a.mm > b.mm) return false;
+  }
+  if (a.ss != -1 && b.ss != -1) {
+    if (a.ss < b.ss) return true;
+    if (a.ss > b.ss) return false;
+  }
+  return true;
+}
+
+//++
+bool operator < (Date const& a, Date const& b)
+//
+//	Inégalité stricte, codée à partir de la large pour résoudre
+//	sans cas particuliers les subtilités 
+//	01/02/95 < ??/03/95 mais pas 01/02/95 < ??/02/95
+//--
+{
+  return (a <= b) && !(a == b);
+}
+
+//++
+bool operator >= (Date const& a, Date const& b)
+//
+//--
+{
+  return (b <= a);
+}
+
+//++
+bool operator > (Date const& a, Date const& b)
+//
+//--
+{
+  return (b < a);
+}
+
+//++
+ostream& operator << (ostream& s, Date const& d)
+//
+//--
+{
+  char x[20];
+  d.GetDateStr(x);
+  s << x << " ";
+  d.GetTimeStr(x);
+  s << x;
+  return s;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/dates.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dates.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dates.h	(revision 752)
@@ -0,0 +1,146 @@
+#ifndef DATES_SEEN
+#define DATES_SEEN
+
+#include <string.h>
+#include <string>
+#include <iostream.h>
+#include "pexceptions.h"
+
+class TimeZone;
+// <summary> Dates, conversions, operations </summary>
+// Classe generale de date et heure, operation, TU/TL ...
+class Date EXC_AWARE {
+public:
+  // Enumerations jours et mois
+  // <group>
+  enum Jour {jour_Lundi=0, jour_Mardi, jour_Mercredi, jour_Jeudi, jour_Vendredi, jour_Samedi, jour_Dimanche};
+  enum Mois {mois_Janvier=1, mois_Fevrier, mois_Mars, mois_Avril, mois_Mai, mois_Juin, mois_Juillet,
+             mois_Aout, mois_Septembre, mois_Octobre, mois_Novembre, mois_Decembre};
+  enum {kGMTTime=0, kLocalTime=1};
+  // </group>  
+
+  // Constructeur : maintenant 
+  Date();
+  // Constructeur : jours ecoules depuis 0/1/1901 0h TU
+  Date(double);
+  // Constructeur : "jj/mm/aa" ou "amjj", "hh:mm:ss"
+  // topt : kGMTTime (par defaut) ou kLocalTime
+  // <group>
+  Date(const char*, const char* = 0, int topt=0); 
+  Date(string const&, string const& = "", int topt=0); 
+  // </group>
+  // Constructeur : Jour Mois An, Heure Minutes Secondes
+  Date(int J, int M, int A, int h, int m, double s);
+
+  /*operator double() const;*/
+  // Jours depuis le 0 janvier 1901 0h TU
+  double GetDays() const;
+  // Jours depuis le 0 janvier 1901 0h TU
+  void Set(double);
+  //  "jj/mm/aa" ou "amjj", "hh:mm:ss"
+  // <group>
+  void Set(const char*, const char* = 0, int topt=0);
+  void Set(string const&, string const& = "", int topt=0);
+  // </group>
+  
+  // Change de zone horaire.
+  void SetTimeZone(TimeZone* tz);
+
+  // Verifie si des parties de la date sont indeterminees
+  // <group>
+  // Date partiellement indeterminee
+  bool UndetDate() const;
+  // Date totalement indeterminee
+  bool AllUndetDate() const;
+  // Heure partiellement indeterminee
+  bool UndetTime() const;
+  // Heure totalement indeterminee
+  bool AllUndetTime() const;
+  // </group>
+
+  // Conversion vers des chaines de caractere,
+  // date en clair ou code Eros, heure, et temps sideral
+  // en heure local ou GMT.
+  // <group>
+  void GetDateStr(char*, int tOpt=0) const;
+  void GetDateCode(char*, int tOpt=0) const;
+  void GetTimeStr(char*, int tOpt=0) const;
+  void GetSidTStr(char*) const;
+  
+  string DateStr(int tOpt=0) const;
+  string DateCode(int tOpt=0) const;
+  string TimeStr(int tOpt=0) const;
+  string SidTStr() const;
+  // </group>
+
+  // Jour de la semaine, jour_Lundi == 0
+  int  DayOfWeek(int tOpt=0) const;
+  
+  // Ajoute ou soustrait un intervalle en jour et fraction de jour
+  // <group>
+  Date& operator += (double);
+  Date& operator -= (double);
+
+  friend Date operator + (Date const&, double);
+  friend Date operator - (Date const&, double);
+  // </group>
+  
+  // Nombre de jour (et fraction) entre deux dates
+  friend double operator - (Date const&, Date const&);
+  
+  // Comparaisons entre dates
+  // <group>
+  friend bool operator == (Date const&, Date const&);
+  friend bool operator <  (Date const&, Date const&);
+  friend bool operator <= (Date const&, Date const&);
+  friend bool operator >  (Date const&, Date const&);
+  friend bool operator >= (Date const&, Date const&);
+  friend bool operator != (Date const&, Date const&);
+  // </group>
+  
+  // Impression
+  friend ostream& operator << (ostream&, Date const&);
+
+  // Nombre de jours dans le mois
+  static short MonthDays(short mois, short annee);
+  
+  // Nombre de jours dans l'annee
+  static short YearDays(short annee);
+  
+  // Ieme jourssem dans le mois
+  // (2, jour_Dimanche, 5, 1996) : deuxieme dimanche de mai 96
+  static short NthMonthDay(short i, short joursem, short mois, short annee);
+
+  short JJ,MM,AA,hh,mm;
+  double ss; 
+  TimeZone* timeZone;
+  int nuit;  // est-ce une date midi-midi ?
+
+/* void GetSysTimeZone(); */
+};
+
+// <summary> Gestion des fuseaux horaires </summary>
+// Classe de gestion des fuseaux horaires. Tient compte des heures d'ete.
+class TimeZone EXC_AWARE {
+public:
+  char code[4];
+  char name[20];
+
+  short  gmtOffset;
+
+  short  hasDST;
+  short  dstByWeekDay;
+  short  dstStartDay, dstStartNum, dstStartMonth;   // -1 : le dernier, dstStartDay : apres cette date
+  short  dstStopDay, dstStopNum, dstStopMonth;
+  short  dstOffset;
+
+  TimeZone();                 // Tente de deviner le timezone systeme
+  TimeZone(const char*);      // Par nom
+  void SetZone(const char*);
+  int IsDst(Date const& date);
+  int GetOffset(Date const& date);
+};
+
+extern TimeZone* gTimeZone;
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/datime.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datime.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datime.c	(revision 752)
@@ -0,0 +1,1266 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#ifdef __MWERKS__
+#include "unixmac.h"
+#endif
+
+#define DATIMEPRIVEE
+#include "strutil.h"
+#include "nbconst.h"
+#include "datime.h"
+
+
+/*       Fonctions de calcule de date et temps (Heure)       */
+/* 
+++ 
+  Module 	Dates (C)
+  Lib	LibsUtil
+  include	datime.h
+
+	Ce groupe de fonctions permettent de manipuler des dates et heures.
+	En particulier, il est possible de calculer l'ecart (en nombre de jours
+	ou de secondes separant deux dates, ou le temps sideral correspondant 
+	a une date et heure legale. Deux structures simples sont definies
+	afin de faciliter le passage des arguments entre differentes fonctions:
+	- *JMA* : Jour, Mois, Annee
+ 	- *HMS* : Heure, Minutes, Secondes
+
+--
+*/
+/*
+++
+  Links	Voir aussi:
+ Temps Sideral, Universel (C)
+--
+*/
+/*
+++
+Titre	Quelques Macros 
+--
+*/
+
+/*
+++
+  StrgtoJMA(strg, jma)
+	Decodage d'une chaine de caracteres "strg" sous forme de "12/3/97" en structure 
+	JMA "jma".
+  JMAtoStrg(jma, strg)
+	Ecrit le contenu de la structure JMA "jma" sous forme de "jj/mm/aaaa" dans la chaine
+	de caracteres "strg"
+  JMAtoStrgLong(jma, strg)
+	Ecriture de date en format long , par ex : "Jeudi , 19 Juin 1997"
+  StrgtoHMS(strg, hms)
+	Decodage d'une chaine de caracteres "strg" sous forme de "hh:mm:ss 10:43:60.5"
+	en structure HMS "hms".
+  HMStoStrg(hms, strg)
+	Ecrit le contenu de la structure HMS "hms" sous forme de "hh:mm:ss" dans la chaine
+	de caracteres "strg"
+  StrtoHMS(strg, hms)
+	Decodage d'une chaine de caracteres "strg" sous forme de "hh:mm:ss 10:43:60.5"
+	en structure HMS "hms" avec gestion des signes (decodage correcte de -44:30:05.23)
+  HMStoStr(hms, strg)
+	Ecrit le contenu de la structure HMS "hms" sous forme de "hh:mm:ss" dans la chaine
+	de caracteres "strg" avec gestion des signes
+--
+*/
+
+void StrtoHMS(char *s,HMS* h)
+/* On ne peut pas ecrire 1:-05:-45 pas gere et debile! (mn et sec >=0.)  cmv 12/8/97 */
+{
+int imoins, i2pt;
+h->Heures = h->Minutes = 0; h->Secondes = 0.;
+/* decodage de la chaine de characteres */
+sscanf(s,"%d:%d:%lf", &(h->Heures),&(h->Minutes),&(h->Secondes));
+/* cas du type 5:34:45.5 */
+if( h->Heures > 0 ) return;
+/* cas du type -5:34:45.5 */
+if( h->Heures < 0 ) {
+  h->Minutes *= -1; h->Secondes *= -1.;
+  return;
+}
+/* Ici les Heures sont donc nulles "0:..." ou "-0:..." */
+/* on n'a donne que l'heure nulle cas "0" ou "-0" sans ":" (idiot mais bon!) */
+i2pt = posc(s,':');
+if( i2pt < 0 ) return;
+/* Ici on a au moins un ou 2 ":" */
+/* cas du type 0:34:45.5 ou 0:0:45.5 sans signe - */
+imoins = posc(s,'-');
+if( imoins < 0 ) return;
+/* cas du type -0:34:45.5 ou -0:0:45.5, le signe - n'est pas decode par sscanf */
+if( imoins < i2pt ) {   /* on a donne -0:34 ou -0:34:45.5 */
+  h->Minutes *= -1; h->Secondes *= -1.;
+  return;
+}
+/* Ici il reste les cas mal codes ou le signe "-" est n'importe ou! */
+/* On laisse le decodage par sscanf */
+return;
+}
+
+
+void HMStoStr(HMS h,char *s)
+/* L'ecriture est forcee a h:mn:sec avec mn et sec >=0  cmv 12/8/97 */
+{
+double v;
+v = HMStoH(h);
+h =  DoubletoHMS(v);
+if( v < 0. ) {
+  h.Heures *= -1; h.Minutes *= -1; h.Secondes *= -1.;
+  sprintf(s,"-%02d:%02d:%04.1f", h.Heures,h.Minutes,h.Secondes);
+} else {
+  sprintf(s,"%02d:%02d:%04.1f", h.Heures,h.Minutes,h.Secondes);
+}
+}
+
+/* Nouvelle-Fonction */
+int NbJourMois(int a, int m)
+/* Retourne le nombre de jours dans le mois m, annee a */
+{
+if(a<100) a+=1900;
+if( m<1 || m>12 ) return(-1);
+m--;
+if(m!=1) return(NbJoMois[m]);
+/* traitement du mois de fevrier bissextile ou non */
+if(  ((a%4==0) && (a%100!=0))
+  ||       (a%400==0)         ) return(NbJoMois[m]+1);
+else return(NbJoMois[m]);
+}
+
+/* Nouvelle-Fonction */
+long JMAtoJ(JMA jma)
+/*           Calcule le Nb. de jours ecoules depuis 0 Jan 1901         */
+/*   Si annee < 100  On considere annee = annee+1900  (1900-1999)      */
+
+{
+long rc,nban;
+int i;
+
+/* Protection */
+if ( (jma.Mois < 1) || (jma.Mois > 12) )  jma.Mois = 1;
+if ( (jma.Jour < 1) || (jma.Jour > 31) )  jma.Jour = 1;
+
+if (jma.Annee < 100)  jma.Annee+=1900;
+nban = jma.Annee - 1901;
+
+/*  Annee Normale = 365 Jours - Bissextile = 366 Jours    */
+/*  366 Jours  :  Divisible par 4 et non divisible par 100  (1972,1976)   */
+/*             :  Divisible par 400 (1900 Non-Biss. et 2000 Biss.)        */
+
+if (nban >= 0)  
+  rc = nban*365 + (nban/4) - (nban/100) + ((nban+300)/400);
+else 
+  rc = nban*365 + (nban/4) - (nban/100) + ((nban-300)/400);
+
+/*    Comptabilisation du nb. des jours des mois ecoule   */
+for (i=1; i<jma.Mois; i++)  rc += NbJourMois(jma.Annee, i);
+rc += jma.Jour;
+
+return(rc);
+}
+
+/* Nouvelle-Fonction */
+JMA JtoJMA(long j)
+/* retourne la date correspondant a j jours ecoules depuis le 0/1/1901 */
+{
+long i;
+int inc,m;
+JMA buf;
+
+inc = (j>=0) ? 1 : -1;
+buf.Jour = buf.Mois = 1; buf.Annee = 1901;
+
+/* recherche de l'annee */
+for(;;) {
+  i = j-JMAtoJ(buf);
+  if( i==0 ) return(buf);
+  if( inc*i<0 ) {
+    /* printf("...annee j=%ld scan=%ld test=%ld\n"
+          ,j,JMAtoJ(buf),inc*i); */
+    break;
+  }
+  buf.Annee += inc;
+}
+if(inc>0) buf.Annee--;
+/* printf("Annee trouvee: %d\n",buf.Annee); */
+
+/* recherche du mois */
+for(m=1;m<=12;m++) {
+  buf.Mois=m;
+  i = j-JMAtoJ(buf);
+  if( i==0 ) return(buf);
+  if(i<0) {
+    /* printf("...mois j=%ld scan=%ld test=%ld\n"
+          ,j,JMAtoJ(buf),i); */
+    buf.Mois--;
+    break;
+  }
+}
+/* printf("Mois trouve: %d\n",buf.Mois); */
+
+/* recherche du jour */
+for(m=1;m<=31;m++) {
+  buf.Jour=m;
+  i = j-JMAtoJ(buf);
+  if( i==0 ) return(buf);
+}
+/* printf("Jour trouve: %d\n",buf.Jour); */
+
+/* on a pas trouve !!! normallement impossible! */
+printf("**** JtoJMA_Erreur: date non trouvee j=%ld ****\n",j);
+buf.Jour = buf.Mois = 1; buf.Annee = 0;
+return(buf);
+}
+
+/* Nouvelle-Fonction */
+int NumJour(JMA jma)
+/*        Cette fonction calcule le numero de jour de la semaine    */
+/*        (Lundi=1 .. Dimanche=7)                                   */
+
+{
+int l;
+
+/*  On appelle JMAtoJ() pour avoir le nb de jours ecoule depuis 1/01/1901  */
+/*  Le premier janvier 1901 etait un Mardi (JMAtoJ = 1 , NumJour = 2)      */
+l = JMAtoJ(jma)%7 ;
+if (l >= 0)  return(l+1);
+else return(l+8);
+}
+
+/* Nouvelle-Fonction */
+JMA JsmmaatoJMA(int nj, int mm, int aa)
+
+/*   Pour "nj=kj*10+jj", calcule la date correspondant au "kj" eme 
+     jour "jj" (1 .. 7 - Lundi .. Dimanche) du mois mm , annee aa
+     Si "nj" est negatif ->  Dernier jour "jj". Si "kj=0", premier jour "jj".
+     Si "kj" ne peut etre atteint -> Dernier jour "jj".
+     Si annee "aa" <= 99   ->  annee de 1901 - 1999       */
+
+{
+JMA  jma;
+int i,k;
+int jj, kj;
+
+kj = nj/10;
+jj = nj%10;
+if (kj < 0)  kj = 0;
+
+if (mm > 12)  mm = 12;
+if (mm < 1 ) mm = 1;
+if (aa < 100)  aa += 1900;
+jma.Mois = mm;
+jma.Annee = aa;
+
+if (kj == 0) {
+  if (jj >= 0)  {      /*   Premier jour du mois   */    
+    if (jj > 7)  jj = 7;
+    if (jj < 1)  jj = 1;
+    jma.Jour = 1;
+    i = NumJour(jma);
+    if (i > jj)  jma.Jour = (7-i)+jj+1;
+    else jma.Jour = 1+(jj-i);
+    }
+  else   {             /*   Dernier jour du mois   */
+    jj = -jj;
+    if (jj > 7)  jj = 7;
+    if (jj < 1)  jj = 1;
+    jma.Jour = NbJourMois(aa,mm);  
+    i = NumJour(jma);
+    if (i >= jj)   jma.Jour -= (i-jj);
+    else  jma.Jour -= (7+i-jj);
+  }
+}
+else {  /*  On demande le kj eme jour jj du mois  */
+  if (jj > 7)  jj = 7;
+  if (jj < 1)  jj = 1;
+  k = 0;
+  for(i=1; i<=NbJourMois(aa,mm); i++) {
+    jma.Jour = i;
+    if (NumJour(jma) == jj)  k++;
+    if (k == kj)  break;
+  }
+/*  On n'a pas kj jour jj ds ce mois, on renvoie le dernier jj */
+  if (k<kj) return(JsmmaatoJMA(-jj, mm, aa));  
+}
+
+return(jma);
+}
+
+JMA JApmmaatoJMA(int nj, int mm, int aa)
+/*    Pour "nj=dd*10+jj", calcule la date correspondant au jour
+      "jj" (1 .. 7 - Lundi .. Dimanche) du mois "mm" , annee "aa"
+      se trouvant apres (ou egal a) la date "dd/mm/aa" .
+      Si annee "aa" <= 99   ->  annee de 1901 - 1999       */
+{
+int i, dd, jj;
+JMA jma;
+
+if (nj < 0) nj = -nj;
+if (nj < 1) nj = 1;
+dd = nj/10;
+jj = nj%10;
+for(i=1; i<=6; i++) {
+  jma = JsmmaatoJMA(jj+10*i, mm, aa);
+  if(jma.Jour >= dd) return(jma);
+}
+printf("JApmmaatoJMA(%d...) Erreur / Pas de jour %d >= %d/%d/%d\n", nj, jj,dd, mm, aa);
+jma.Jour = jma.Mois = jma.Annee = 0;
+return(jma);
+}
+
+/* Nouvelle-Fonction */
+double HMStoH(HMS hms)
+
+/* Cette fonction calcule le nb d'heures en decimales pour hms */
+/* Heures/Minutes/Secondes peuvent etre +/- avec toutes les combi possibles */
+{
+return ((double)hms.Heures + ((double)hms.Minutes)/60. + hms.Secondes/3600.);
+}
+
+
+
+/* Nouvelle-Fonction */
+double HMStoSec(HMS hms)
+/*    Calcul du nb de secondes pour hms    */
+/* Heures/Minutes/Secondes peuvent etre +/- avec toutes les combi possibles */
+{
+return ((double)hms.Heures*3600. + (double)hms.Minutes*60. + hms.Secondes);
+}
+
+/* Nouvelle-Fonction */
+long DatetoSec(char const* date, char const* heure)
+/*   Calcul du nombre de secondes correspondant a date/heure    */
+/*  a partir de l'origine 1er Janv 1990  0H00                   */
+/*  Date entre 1930 - 2050                                      */
+{
+JMA jma,jma0;
+HMS hms;
+long dj;
+
+StrgtoJMA(date,jma);   StrgtoHMS(heure,hms);
+StrgtoJMA("01/01/1990",jma0);
+dj = JMAtoJ(jma) - JMAtoJ(jma0);
+if (dj < -24000)  return(-0x7FFFFFFF);
+if (dj > 24000)  return(0x7FFFFFFF);
+return( dj*3600*24 + (int)(HMStoSec(hms)) );    
+}
+
+/* Nouvelle-Fonction */
+long DatetoSecOff(char const* date, char const* heure)
+{
+JMA jma,jma0;
+HMS hms, hms0;
+long dj,tdec;
+
+StrgtoJMA(date,jma);   StrgtoHMS(heure,hms);
+StrgtoJMA("01/01/1990",jma0);   StrgtoHMS("00:00:00",hms0);
+dj = JMAtoJ(jma) - JMAtoJ(jma0);
+if (dj < -24000)  return(-0x7FFFFFFF);
+if (dj > 24000)  return(0x7FFFFFFF);
+
+/* H_vrai+TOff=H_leg : H_vrai-H_vrai0 = (H_leg-TOff)-(H_leg0-TOff0) */
+tdec  = 3600*(TLegOffset(jma, hms)-TLegOffset(jma0, hms0));
+
+dj = dj*3600*24 + (int)(HMStoSec(hms)) - tdec;
+return(dj);    
+}
+
+/* Nouvelle-Fonction */
+HMS HtoHMS(double h)
+/* Heures decimales en H , M , Sec  Il y a un modulo 24  */
+/* la sortie est telle que 0 <= heures < 24 */
+{
+HMS hms; 
+
+while (h < 0.) h += 24.;
+  
+hms.Heures = (int) h;
+h = (h-hms.Heures)*60.;
+hms.Minutes = (int) h;
+hms.Secondes = (h-hms.Minutes)*60.;
+hms.Heures = hms.Heures % 24;
+
+return(hms);
+}
+
+/* Nouvelle-Fonction */
+HMS DtoDMS(double h)
+/* Degres decimaux en D , M , Sec  Il y a un modulo 360  */
+/* la sortie est telle que -180 < deg <= 180. */
+{
+HMS hms;
+int sgn = 1;
+
+while (h > 180.) h -= 360.;
+while (h <= -180.) h += 360.;
+if( h < 0. ) {h *= -1.; sgn = -1;}
+  
+hms.Heures = (int) h;
+h = (h-hms.Heures)*60.;
+hms.Minutes = (int) h;
+hms.Secondes = (h-hms.Minutes)*60.;
+hms.Heures = hms.Heures % 360;
+
+if( sgn<0 ) {hms.Heures *= -1; hms.Minutes *= -1; hms.Secondes *= -1.;}
+return(hms);
+}
+
+/* Nouvelle-Fonction */
+HMS DoubletoHMS(double h)
+/*    Degres/Heures decimaux en D/H , M , Sec  SANS modulo 360/24  */
+{
+HMS hms;
+
+int sgn = 1;
+if( h < 0. ) {h *= -1.; sgn = -1;}
+
+hms.Heures = (int) h;
+h = (h-hms.Heures)*60.;
+hms.Minutes = (int) h;
+hms.Secondes = (h-hms.Minutes)*60.;
+hms.Heures = hms.Heures;
+
+if( sgn<0 ) {hms.Heures *= -1; hms.Minutes *= -1; hms.Secondes *= -1.;}
+return(hms);
+}
+
+/*
+++
+ Titre	Calcule sur dates et heures
+--
+*/
+
+/*
+++
+int NbJourMois(int a, int m)
+	Retourne le nombre de jours dans le mois "m", annee "a".
+long JMAtoJ(JMA jma)
+	Calcule le Nb. de jours ecoules depuis 0 Jan 1901, 
+	Si annee < 100  On considere annee = annee+1900  (1900-1999)
+JMA JtoJMA(long j)
+	Retourne la date correspondant a un nombre de jours "j"
+	ecoules depuis le 0 Jan 1901.
+int NumJour(JMA jma)
+	Calcule le numero du jour de la semaine correspondant a la date indiquee
+	par la structure JMA "jma". (Lundi=1 .. Dimanche=7)
+JMA JsmmaatoJMA(int nj, int mm, int aa)
+	Pour "nj=kj*10+jj", calcule la date correspondant au "kj" eme 
+	jour "jj" (1 .. 7 - Lundi .. Dimanche) du mois mm , annee aa
+  	Si "nj" est negatif ->  Dernier jour "jj". Si "kj=0", premier jour "jj".
+	Si "kj" ne peut etre atteint -> Dernier jour "jj".
+	Si annee "aa" <= 99   ->  annee de 1901 - 1999       
+JMA JApmmaatoJMA(int nj, int mm, int aa)
+	Pour "nj=dd*10+jj", calcule la date correspondant au jour
+	"jj" (1 .. 7 - Lundi .. Dimanche) du mois "mm" , annee "aa"
+	se trouvant apres (ou egal a) la date "dd/mm/aa" .
+	Si annee "aa" <= 99   ->  annee de 1901 - 1999       
+double HMStoH(HMS hms)
+	Conversion en heures decimales de la structure  "hms"
+double HMStoSec(HMS hms)
+	Conversion en secondes de la structure HMS  "hms"
+HMS HtoHMS(double h)
+	Conversion heures en decimales en structure HMS
+HMS DtoDMS(double h)
+	Conversion degres decimaux en structure HMS (deg,min,sec)
+HMS DoubletoHMS(double h)
+	Conversion degres/heures decimaux en structure HMS (deg/heure,min,sec)
+                   SANS modulo 360/24
+long DatetoSec(char const* date, char const* heure)
+	Calcule le nombre de secondes correspondant a "date,heure" 
+	a partir de l'origine 1er Janv 1990  0H00 ( Date entre 1930 - 2050 )		
+long DatetoSecOff(char const* date, char const* heure)
+	Calcule le nombre de secondes correspondant a "date,heure" 
+	a partir de l'origine 1er Janv 1990  0H00 ( Date entre 1930 - 2050 )
+        en tenant compte des decalages des heures legales.
+--
+*/
+
+
+
+/*   Variables contenant les informations pour conversion  */
+/*  Temps Legal <> TU <> Temps solaire moyen               */
+
+static double  TSolMOff = 0.;     /*  TSol.Moyen - TU  (en heures) */
+static char SiteName[128];           /*  Nom de site  */
+
+static struct
+  {
+  char fg;         /*  Flag (=A ou B) Type de specification  */
+  int jj[2];       /*  Numero ou date du jour                */
+  int mm[2];       /*  Mois    */
+  int Off[3];      /*  Decalage = TLegal - TU    */
+  }  TLegInfo = {'\0',{0,0},{0,0},{0,0,0}} ;
+
+static HMS HChgH = {0,0,0.} ; /*  Heure de changement d'heure */
+
+/* 
+++ 
+  Module 	Temps Sideral, Universel (C)
+  Lib	LibsUtil
+  include	datime.h
+
+	Ce groupe de fonctions permet convertir differentes heures:
+	les temps local, le temps universel (TU), le temps legal (TLeg). Il est 
+	aussi possible de calculer le temps sideral (TS). 
+--
+*/
+/*
+++
+  Links	Voir aussi:
+  Dates (C)
+--
+*/
+/*
+++
+ Titre	T-Legal, TU
+	Conversion entre l'heure legale, le temps universel (TU) et le temps solaire
+	moyen
+--
+*/
+
+/*
+++
+SetTSolMOff(double tsmoff, char *name)
+	Definit pour un site donne, le decalage T Sol. Moyen - TU (en heures) "tmsoff"
+	et le nom du site 
+PrtTSolMOff()
+	Imprime les infos definis par "SetTSolMOff()"
+--
+*/
+
+/* Nouvelle-Fonction */
+void SetTSolMOff(double tsmoff, char *name)
+
+/*     Offset  T Sol. Moyen - TU (en hh:mm:ss) ,  Nom de site name   */
+{
+TSolMOff = tsmoff;
+strcpy(SiteName,name);
+return;
+}
+
+
+/* Nouvelle-Fonction */
+void PrtTSolMOff(void)
+{
+printf("  **Site : %s , T Sol.Moy.-TU  %g  (heures) \n",SiteName,TSolMOff);
+return;
+}
+
+/*
+++
+int SetTLegOff(char* dtz, char* dhz)
+	Initialise la structure TLegInfo. L'argument *dtz peut etre 
+	sous 2 forme differentes et permet de  definir 3 plages 
+	de temps avec 3 decalages horaires (nb entier). 
+	Les dates pivots sont les jours de changement d'heure a 
+	l'heure indiquee par dhz ("hh:mm:ss"), si "dhz==NULL ou 
+	chaine vide, alors changement a 0 heure.  
+|   1) dtz = "A Off1 j1/m1 Off2 j2/m2 Off3"
+|      jx/mx Jour/Mois - Offx : Decalage TLeg - TU                  
+|      pour 01/01 <= jj/mm <  j1/m1   ->  Off1 
+|           j1/m1 <= jj/mm <  j2/m2   ->  Off2 
+|           j2/m2 <= jj/mm <= 31/12   ->  off3 
+|   2) dtz = "B off1 Js1/m1 Off2 Js2/m2 Off3"
+|      Jsx/mx  Numero du jour de la semaine (Js) et numero du mois
+|      Js =  1 ..  7  (Lundi .. Dimanche)  :  1er Jour Js du mois    
+|         = -1 .. -7   Dernier jour Js du mois                  
+|         = k1 .. k7   k eme jour Js du mois                  
+|   3) dtz = "C off1 Js1/m1 Off2 Js2/m2 Off3"
+|      Jsx/mx  Numero du jour de la semaine (Js) et numero du mois avec une 
+|      precision d'une date butee inferieurs    
+|      Js =  ddj ..  (j=1..7  Lundi .. Dimanche)  :  1er Jour j du mois
+|      apres (ou egal a) la date dd/mm    
+	Retour : 0 si Ok -1 Sinon                                          
+void PrtTLegInfo(int aa)	
+	Imprime les informations de decalage TLeg ,  TU - Annee "aa"
+int  TLegOffset(JMA date, HMS heure)
+	Indique le decalage (en nombre d'heures) TLeg-TU	
+--
+*/
+
+/* Nouvelle-Fonction */
+int SetTLegOff(char* dtz, char* dhz)
+
+                        
+{
+int is;
+
+HChgH.Heures = HChgH.Minutes = 0;
+HChgH.Secondes = 0.;
+
+if (dhz) StrgtoHMS(dhz, HChgH);
+if ( (HChgH.Heures < 0) || (HChgH.Heures > 23) )
+  { HChgH.Heures = HChgH.Minutes = 0;  HChgH.Secondes = 0.; }
+
+is = sscanf(dtz,"%c %d %d/%d %d %d/%d %d", &(TLegInfo.fg), &(TLegInfo.Off[0]), &(TLegInfo.jj[0]),  &(TLegInfo.mm[0]), &(TLegInfo.Off[1]), &(TLegInfo.jj[1]),  &(TLegInfo.mm[1]), &(TLegInfo.Off[2]) );
+
+if ( (TLegInfo.fg != 'A') && (TLegInfo.fg != 'B')
+     && (TLegInfo.fg != 'C') )  TLegInfo.fg = '\0';
+if (is != 8) TLegInfo.fg = '\0';
+if (TLegInfo.fg != '\0') return(0);
+else { printf("SetTLegOff()/Erreur %s \n", dtz); return(-1); }
+}
+
+/* Nouvelle-Fonction */
+void PrtTLegInfo(int aa)
+
+/*    Cette fonction  print les infos de TLegInfo     */
+{
+int i,k,j;
+char ForL[2][128];
+JMA jma;
+
+if (TLegInfo.fg == '\0')    printf ("  !!! TlegInfo not set or Error \n");
+
+
+HMStoStrg(HChgH, ForL[0]);
+printf("  ==== TLegInfo : Changement d'heure a %s \n", ForL[0]);
+ForL[0][0] = '\0';
+if (TLegInfo.fg == 'A')  
+  {
+  printf("  ---- TLegInfo : Selection par date (Flag = A)  ---- \n");
+  printf("   -> 01 Janvier - %d %s   :  %d heures \n",TLegInfo.jj[0], NomMo[TLegInfo.mm[0]-1], TLegInfo.Off[0]);
+  printf("   -> %d %s - %d %s  :  %d heures \n",TLegInfo.jj[0], NomMo[TLegInfo.mm[0]-1],TLegInfo.jj[1], NomMo[TLegInfo.mm[1]-1],TLegInfo.Off[1]);
+  printf("   -> %d %s - 31 Decembre  :  %d heures \n",TLegInfo.jj[1], NomMo[TLegInfo.mm[1]-1], TLegInfo.Off[2]);
+  }
+
+if (TLegInfo.fg == 'B')  
+  {
+  printf("  --- TLegInfo : Selection par Jour de semaine et mois (Flag = B)  --- \n");
+  for (i=0;i<2;i++) {
+    k = TLegInfo.jj[i]/10;
+    if (k < 1)  k = 1;
+    j = TLegInfo.jj[i]%10;
+    if (j < 0)  j = -j;
+    if (j < 1) j = 1;
+    if (j > 7) j = 7;
+    if (TLegInfo.jj[i] < 0)  sprintf(ForL[i]," Dernier  %s  de  %s  (KJ=%d)", NomJo[j-1], 
+                                     NomMo[TLegInfo.mm[i]-1], TLegInfo.jj[i]);
+    else  sprintf(ForL[i]," %d eme  %s  de  %s (KJ=%d)", k, NomJo[j-1], 
+                  NomMo[TLegInfo.mm[i]-1], TLegInfo.jj[i]);
+    }
+  printf(" Butees: %s  -  %s \n", ForL[0], ForL[1]);
+  for (i=0;i<2;i++) {
+    jma = JsmmaatoJMA(TLegInfo.jj[i], TLegInfo.mm[i], aa);
+    JMAtoStrg(jma, ForL[i]);
+  }
+  printf("   -> 01 Janvier %d - %s  :  %d heures \n",aa, ForL[0], TLegInfo.Off[0]);
+  printf("   -> %s - %s  :  %d heures \n",ForL[0], ForL[1], TLegInfo.Off[1]);
+  printf("   -> %s - 31 Decembre %d :  %d heures \n",ForL[1], aa, TLegInfo.Off[2]);
+ }
+
+if (TLegInfo.fg == 'C')  
+  {
+  printf("  --- TLegInfo : Selection par Jour de semaine >= dd et mois (Flag = C)  --- \n");
+  for (i=0;i<2;i++) {
+    k = TLegInfo.jj[i]/10;
+    j = TLegInfo.jj[i]%10;
+    if (j < 0)  j = -j;
+    if (j < 1) j = 1;
+    if (j > 7) j = 7;
+    sprintf(ForL[i],"1er %s  apres le %d %s ", NomJo[j-1], k, NomMo[TLegInfo.mm[i]-1]);
+    }
+  printf(" Butees: %s - %s \n", ForL[0], ForL[1]);
+  for (i=0;i<2;i++) {
+    jma = JApmmaatoJMA(TLegInfo.jj[i], TLegInfo.mm[i], aa);
+    JMAtoStrg(jma, ForL[i]);
+  }
+  printf("   -> 01 Janvier %d - %s  :  %d heures \n",aa, ForL[0], TLegInfo.Off[0]);
+  printf("   -> %s - %s  :  %d heures \n",ForL[0], ForL[1], TLegInfo.Off[1]);
+  printf("   -> %s - 31 Decembre %d :  %d heures \n",ForL[1], aa, TLegInfo.Off[2]);
+ }
+
+return;
+}
+
+
+/* Nouvelle-Fonction */
+int  TLegOffset(JMA date, HMS heure)
+
+/*     Cette fonction calcule l'offset   TLeg - TU  pour la date donnee date  */
+{
+JMA jma1,jma2;
+long nbj1,nbj2,nbj;
+double decj1, decj2, decj;
+int Off;
+
+/*   On recherche l'offset correspondant a la date   */
+jma1.Annee = jma2.Annee = date.Annee;
+if (TLegInfo.fg == 'A')
+/*    Periode defini par des dates ds les mois   */ 
+  {
+  jma1.Mois = TLegInfo.mm[0];
+  jma1.Jour = TLegInfo.jj[0];
+  jma2.Mois = TLegInfo.mm[1];
+  jma2.Jour = TLegInfo.jj[1];
+  }
+if (TLegInfo.fg == 'B')
+/*    Periodes definies par jour de semaine et mois   */
+  {
+  jma1 = JsmmaatoJMA(TLegInfo.jj[0],TLegInfo.mm[0],date.Annee);
+  jma2 = JsmmaatoJMA(TLegInfo.jj[1],TLegInfo.mm[1],date.Annee);
+  }
+
+if (TLegInfo.fg == 'C')
+/*    Periodes definies par jour de semaine et mois  avec date inferieure */
+  {
+  jma1 = JApmmaatoJMA(TLegInfo.jj[0],TLegInfo.mm[0],date.Annee);
+  jma2 = JApmmaatoJMA(TLegInfo.jj[1],TLegInfo.mm[1],date.Annee);
+  }
+
+nbj = JMAtoJ(date);
+nbj1 = JMAtoJ(jma1);
+nbj2 = JMAtoJ(jma2);
+
+/*  Les dates pivots sont les jours de changement d'heure a Heure= HChgH */
+decj = (double)nbj + HMStoH(heure)/24.;
+decj1 = (double)nbj1 + HMStoH(HChgH)/24.;
+decj2 = (double)nbj2 + HMStoH(HChgH)/24.;
+
+if ( decj < decj1 )  Off = TLegInfo.Off[0];
+else if (decj < decj2)  Off = TLegInfo.Off[1];
+     else Off = TLegInfo.Off[2];
+
+/*     Impression de debugging   */
+/*Debug--  printf ("   @@@ Debug_TLegOffset (date= %d/%d/%d)  :  %d H. \n",date.Jour,date.Mois,date.Annee,Off);
+printf("  @-1 %s , %d %s %d \n", NomJo[NumJour(jma1)-1], jma1.Jour, NomMo[jma1.Mois-1], jma1.Annee) ;
+printf("  @-2 %s , %d %s %d \n", NomJo[NumJour(jma2)-1], jma2.Jour, NomMo[jma2.Mois-1], jma2.Annee) ;  --*/
+
+
+return (Off);
+}
+
+/*
+++
+HMS TLegtoTU(JMA date, HMS TLeg)
+	Conversion TLegal en TU pour une date donnée
+HMS TUtoTLeg(JMA date, HMS TLeg)
+	Conversion TU en TLegal pour une date donnée. L'heure légale calculée
+	peut être erronnée autour des dates de changement d'heure.
+HMS TUtoTSolM(HMS TU)
+	Conversion TU en temps solaire moyen
+--
+*/
+
+/* Nouvelle-Fonction */
+HMS TLegtoTU(JMA date, HMS hmsz)
+
+/*   Cette fonction transforme le temps legal en temps universel   */
+{
+HMS  TU;
+int Off;
+
+Off = TLegOffset(date, hmsz);
+TU = hmsz;
+TU.Heures -= Off;
+if (TU.Heures >= 24)  TU.Heures -= 24;
+if (TU.Heures < 0)  TU.Heures += 24;
+return(TU);
+}
+
+
+
+/* Nouvelle-Fonction */
+HMS TUtoTLeg(JMA date, HMS hms)
+
+/*   Cette fonction transforme le temps universel en temps legal */
+{
+HMS  TLeg;
+int Off;
+
+Off = TLegOffset(date, hms);    /*  $CHECK$  */
+TLeg = hms;
+TLeg.Heures += Off;
+TLeg.Heures = TLeg.Heures%24;
+if (TLeg.Heures < 0)  TLeg.Heures += 24;
+return(TLeg);
+}
+
+
+/* Nouvelle-Fonction  */
+HMS TUtoTSolM(HMS TU)
+
+/*   Passage  TU  ->  Temps local    */
+{
+double t;
+t = HMStoH(TU) + TSolMOff;
+return(HtoHMS(t));
+}
+
+/*
+++
+ Titre	Temps Sideral
+|      Jour Sideral = 86400 Sec. Sid.  ( = 24 H Sid. )    
+|      Annee Solaire = 365 J 5H 48' 46"  =~  365.2422 J                       
+|      Annee Solaire = 365.2422 Jours Solaire Moyen = 366.2422 Jours Sideraux 
+|      Jour Sol. Moyem = 24 H Sol. = 24 H Sid. * (366.2422 / 365.2422)        
+|      Jour Solaire Moyen = 86636.555359 Sec. Sid. = 24 H 3' 56.555359"       
+|      Heure Solaire Moyen = 3609.85647 Sec. Sid.                             
+|      Sec. Sol. = 1.0027379 Sec. Sid.                                        
+|      Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral 
+--
+*/
+
+/*
+++
+HMS TLegtoTSid(JMA date, HMS TZ)
+	Cette fonction calcule le temps sideral a partir du temps
+	legal et de la date
+GMST_at_0h_UT(JMA date)
+	Cette fonction calcule le temps sideral moyen a greenwich a 0h UT
+--
+*/
+
+/* Nouvelle-Fonction  */
+HMS TLegtoTSid(JMA date, HMS TZ)
+
+/*  Cette fonction  donne le temps sideral a partir du temps legal  */
+/*  et la date                                                      */
+{
+HMS  Orgh,TU,TSid;
+JMA  Orgd;
+int off;
+long lj;
+double ts,ratio;
+
+/* Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral */
+StrgtoJMA("1/1/1989",Orgd);
+StrgtoHMS("6:42:30",Orgh);
+
+
+
+/*    Nb de jours / Date Origine   */
+lj = JMAtoJ(date) - JMAtoJ(Orgd);
+
+/*  On calcule l'heure TU et on tient compte du decalage eventuel de + ou - 1 jour  */
+off = TLegOffset(date, TZ);
+TU = TZ;
+TU.Heures -= off;
+if (TU.Heures < 0)  
+  {
+  lj -= 1;
+  TU.Heures += 24;
+  }
+if (TU.Heures >= 24)  
+  {
+  lj += 1;
+  TU.Heures -= 24;
+  }
+
+
+
+ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
+ratio = (ratio+1) / ratio ;
+
+/*   Calcul du decalage en heures du temps Sideral par rapport a          */
+/*   l'origine choisie :  ts                                              */
+
+ts = lj * (24. * (ratio - 1) );
+ts += ( TU.Heures * ratio );
+ts += ( ( TU.Minutes / 60. ) * ratio );
+ts += ( (TU.Secondes / 3600. ) * ratio );
+
+ts += HMStoH(Orgh);
+
+/*   On tient compte de l'offset du temps solaire moyen  */
+ts += TSolMOff;
+
+TSid = HtoHMS(ts);
+TSid.Heures = TSid.Heures % 24;
+if (TSid.Heures < 0)  TSid.Heures += 24;
+
+return(TSid);
+}
+
+
+/* Nouvelle-Fonction  */
+HMS GMST_at_0h_UT (JMA date)
+
+/*  Cette fonction  donne le temps sideral moyen a greenwich a 0h UT */
+/*                                                       CMV 5/11/93 */
+{
+HMS Orgh, TSid;
+JMA  Orgd;
+long lj, ejs;
+double js, hs, hs0;
+
+/*  J H ' " sont les vraies valeurs indiscutables (cf metre etalon etc..)  */
+/*  Annee Solaire  = 365 J 5H 48' 45.2" =~  365.2421898148 J               */
+/*  Annee Siderale = 365 J 6H  9'  9.8" =~  365.2563634259 J               */
+/*  Le 1er Janvier 1994 0H TU Il sera 6h 41' 40.4305" GMT_Sideral          */
+StrgtoJMA("1/1/1994",Orgd);
+StrgtoHMS("6:41:40.4305",Orgh);
+hs0 = HMStoH(Orgh);
+
+/*   Nb de jours ecoules depuis la Date Origine */
+lj = JMAtoJ(date) - JMAtoJ(Orgd);
+/* printf("nombre de jours ecoules depuis 1/1/94 %d\n",lj); */
+
+/*   Nb de jours sideraux depuis la Date Origine */
+js = (double) lj * 366.2421898148 / 365.2421898148;
+/*   Nb d'heures siderales depuis Date Origine (modulo un jour) */
+ejs = (int) js;
+hs = js - (double) ejs;
+hs *= 24.;
+hs += hs0;
+
+TSid = HtoHMS(hs);
+/* printf("nombre d'heures siderales depuis la reference (modulo un jour) %d %d %f\n"
+         ,TSid.Heures,TSid.Minutes,TSid.Secondes); */
+
+return(TSid);
+}
+
+/*
+++
+HMS TUtoTSid(JMA date, HMS TU)
+	Cette fonction calcule le temps sideral GMT a partir du temps
+	universel et de la date GMT.
+int TSidtoTU(JMA date, HMS TS, HMS *TU1, HMS *TU2)
+	Cette fonction calcule les temps universels a partir du temps
+	sideral GMT et de la date GMT. Selon la valeur du TS, il peut y avoir
+	une ou deux possibilites pour le TU (return code).
+--
+*/
+
+/* Nouvelle-Fonction  */
+HMS TUtoTSid(JMA date, HMS TU)
+
+/*  Cette fonction  donne le temps sideral GMT a partir du temps universel  */
+/*  et la date  GMT                                                         */
+{
+HMS  Orgh,TSid;
+JMA  Orgd;
+long lj;
+double ts,ratio;
+
+/*   Le 1er Janvier 1989 0H TU Il etait 6H 42' 30" GMT_Sideral */
+StrgtoJMA("1/1/1989",Orgd);
+StrgtoHMS("6:42:30",Orgh);
+
+/*    Nb de jours / Date Origine   */
+lj = JMAtoJ(date) - JMAtoJ(Orgd);
+
+ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
+ratio = (ratio+1) / ratio ;
+
+/*   Calcul du decalage en heures du temps Sideral par rapport a          */
+/*   l'origine choisie :  ts                                              */
+
+ts = lj * (24. * (ratio - 1) );
+ts += ( TU.Heures * ratio );
+ts += ( ( TU.Minutes / 60. ) * ratio );
+ts += ( (TU.Secondes / 3600. ) * ratio );
+
+ts += HMStoH(Orgh);
+
+TSid = HtoHMS(ts);
+TSid.Heures = TSid.Heures % 24;
+if (TSid.Heures < 0)  TSid.Heures += 24;
+
+return(TSid);
+}
+
+/* Nouvelle-Fonction  */
+int TSidtoTU(JMA date, HMS TS, HMS *TU1, HMS *TU2)
+
+/*  Cette fonction  donne les temps universels a partir du temps sideral GMT */
+/*  et la date GMT                                                           */
+{
+int rc = 0;
+HMS  Orgh,T0;
+double ratio,delt,deltt,jsecsid;
+char strd[16],strh[16];
+/* char strh1[16]; */
+
+TU1->Heures = TU2->Heures = -1;
+TU1->Minutes = TU2->Minutes = 0;
+TU1->Secondes = TU2->Secondes = 0.;
+
+ratio = ((365.*24.) + 5. + (48. / 60.) + (46. / 3600.)) / 24.;
+ratio = (ratio / (ratio+1));
+jsecsid = 86400./ratio;
+
+/* temps sideral pour la date a 0h TU */
+StrgtoHMS("00:00:00",T0);
+Orgh =  TUtoTSid(date,T0);
+/* JMAtoStrg(date,strd); HMStoStrg(T0,strh); HMStoStrg(Orgh,strh1);
+printf("... date=%s tu=%s -> org_ts=%s\n",strd,strh,strh1); */
+
+/* difference de temps sideral / a 0h TU */
+delt = HMStoSec(TS) - HMStoSec(Orgh);
+/* printf("... ts=%f org_ts=%f en sec -> delt=%f (jsecsid=%g)\n"
+      ,HMStoSec(TS),HMStoSec(Orgh),delt,jsecsid); */
+
+if(fabs(delt)<1.e-10) delt=0.;
+if(delt<0.) delt += 86400.;
+if( fabs(delt-86400.)<1.e-10 ) delt = 86400. - 1.e-10;
+if(delt<0. || delt>=86400.+1.e-10) {
+  HMStoStrg(TS,strh);
+  JMAtoStrg(date,strd);
+  printf("*** BUG *** TSidtoTU_erreur: delt=%g<0. (d=%s,ts=%s) *******\n"
+        ,delt,strd,strh);
+  return(0);
+}
+
+/* difference de temps / a 0h TU 1ere solution */
+/* printf("... delt=%f en sec sid",delt); */
+deltt = delt*ratio;
+*TU1 = SectoHMS(deltt);
+*TU2 = *TU1;
+rc++;
+/* HMStoStrg((*TU1),strh1);
+printf("... deltt=%f en sec -> TU1=%s\n",deltt,strh1); */
+
+/* Y a t-il une seconde solution ? */
+if(delt>=jsecsid-86400.-1.e-10) return(rc);
+delt += 86400.;
+deltt = delt*ratio;
+*TU2 = SectoHMS(deltt);
+/* HMStoStrg((*TU2),strh1);
+printf("... deltt=%f en sec -> TU2=%s\n",deltt,strh1); */
+rc++;
+
+return (rc);
+}
+
+/*
+++
+void TSidSetupLaSilla()
+	Fonction d'initialisation de conversion  de temps sideral et legal 
+	pour la ESO-Silla "SetTSolMOff() , SetTLegOff()".
+|       Longitude = 70 deg 43.8 min ouest
+|       Latitude  = 29 deg 15.4 min Sud    
+|       T Sol. Moyen - TU = -4.715333 Heures
+|       TLegal-TU : -4 Heures de Mars a Octobre, -3 Heures sinon
+|       Changement le 1er dimanche >= 8/03  8/10 a midi (12:00:00)
+--
+*/
+
+/* Fonction d'initialisation de calcul de temps sideral pour la Silla */
+void TSidSetupLaSilla()
+{
+SetTSolMOff((double)(-4.715333),"La Silla (Chili)");
+if (SetTLegOff("C -3 87/3 -4 87/10 -3","12:00:00") != 0)
+  printf("  TSidSetupLaSilla / Erreur SetTLegOff \n"); 
+/*  Position de l'observatoire */
+/* SetObsPos("La Silla (Chili)","O 70:43:48","S 29:15:24",2347);  */
+return;
+}
+
+
+
+/*
+++
+double ToJulianDay(JMA dateTU, HMS hmsTU);
+	Calcul du jour Julien pour une date TU.
+	Uniquement valable a partir du 15/10/1582 00:00:00.
+--
+*/
+
+double ToJulianDay(JMA dateTU, HMS hmsTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 4/12/98 */
+{
+double j_dat_0_ut;
+long int f,g,a;
+f = (dateTU.Mois>=3) ? dateTU.Annee: dateTU.Annee-1;
+g = (dateTU.Mois>=3) ? dateTU.Mois: dateTU.Mois+12;
+a = 2 - (int)((double)f/100.) + (int)((double)f/400.);
+/* Julian date at 0h UT */
+j_dat_0_ut = (int)(365.25*(double)f)+(int)(30.6001*(double)(g+1))+dateTU.Jour+a+1720994.5;
+return j_dat_0_ut + HMStoH(hmsTU)/24.;
+}
+
+/*
+++
+int FromJulianDay(double JD,JMA* dateTU, HMS* hmsTU);
+	Calcul de la date date et l'heure TU a partir d'un jour Julien.
+	Retourne 0 si succes.
+--
+*/
+
+int FromJulianDay(double JD,JMA* dateTU, HMS* hmsTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 4/12/98 */
+{
+double jd,i,f,a,x,b,c,d,e,h;
+if(JD<0.) return 1;
+
+i = JD - (int)(JD);
+if(i<0.5) jd = (int)(JD)-0.5; else jd = (int)(JD)+0.5;
+
+i = (int)(jd+0.5);
+f = jd+0.5 - i;
+if(i<2299161.0) a = i;
+else {x = (int)((i-1867216.25)/36524.25); a = i+1.+x-(int)(x/4.);}
+b = a+1524.;
+c = (int)((b-122.1)/365.25);
+d = (int)(365.25*c);
+e = (int)((b-d)/30.6001);
+
+x = b-d-(int)(30.6001*e)+f;
+dateTU->Jour = (int)(x);
+
+if(e<13.5) dateTU->Mois = (int)(e-1.); else dateTU->Mois = (int)(e-13.);
+
+if(dateTU->Mois>2.5) dateTU->Annee = (int)(c-4716.); else dateTU->Annee = (int)(c-4715.);
+
+hmsTU->Heures = hmsTU->Minutes = 0; hmsTU->Secondes = 0.;
+h = (JD-ToJulianDay(*dateTU,*hmsTU)) * 24.;
+*hmsTU = HtoHMS(h);
+
+return 0;
+}
+
+
+/*
+++
+double StrgtoDegDec(char *strg)
+	Cette fonction renvoie la valeur decimale en heures
+	d'un angle specifie sous forme de [-][+]dd:mm:ss.
+--
+*/
+
+double StrgtoDegDec(char *strg)
+/*         cmv 4/12/98 */
+{
+int dd,mm;
+float ss;
+char sgn;
+double deg;
+
+dd = mm = 0;
+ss = 0.;
+sgn = *strg;
+if (isdigit(sgn))
+  sscanf(strg,"%d:%d:%f",&dd,&mm,&ss);
+else
+  sscanf(strg+1,"%d:%d:%f",&dd,&mm,&ss);
+deg = (double)(dd) + (double)(mm)/60. + (double)(ss)/3600.;
+if (sgn == '-')  deg = (-deg);
+return(deg);
+}
+
+/*
+++
+char * DegDectoStrg(double deg, char *strg)
+	Cette fonction ecrit une valeur en degre decimal sous 
+	forme de [-]dd:mm:ss.
+--
+*/
+
+char * DegDectoStrg(double deg, char *strg)
+/*         cmv 4/12/98 */
+{
+int dd,mm;
+float ss;
+char sgn;
+
+if (deg < (double)(0.))
+  { deg = (-deg) ; sgn = '-' ; }
+else sgn = '+';
+dd = (int)deg;
+deg = (deg-(double)(dd)) * (double)60.;
+mm = (int)deg;
+ss = (deg-(double)(mm)) * (double)60.;
+if (sgn == '-')
+  sprintf(strg,"-%d:%d:%f",dd,mm,ss);
+else
+  sprintf(strg,"%d:%d:%f",dd,mm,ss);
+return(strg);
+}
+
+/*
+++
+double EccEarth(JMA dateTU)
+	Valeur de l'eccentricite de l'orbite terrestre
+	a la date TU ``dateTU''.
+--
+*/
+double EccEarth(JMA dateTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
+{
+double JD,T;
+HMS hmsTU;
+hmsTU.Heures = 12; hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
+JD = ToJulianDay(dateTU,hmsTU);
+/* T en siecles juliens depuis 31/12/1899 a 12h TU --> JD=2415020. */
+T = (JD-2415020.)/36525;
+return(0.0167498 - 0.00004258*T - 0.000000137*T*T);
+}
+
+/*
+++
+double ObliqEarth(JMA dateTU)
+	Valeur de l'obliquite de l'orbite terrestre
+	a la date TU ``dateTU'' (en degres decimaux).
+--
+*/
+double ObliqEarth(JMA dateTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed.  cmv 9/12/98 */
+/* le 1/1/1900 a 0h00 TU --> jd = 2415020.5 */
+{
+double jd;
+HMS hmsTU;
+hmsTU.Heures = hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
+jd = ToJulianDay(dateTU,hmsTU) - 2415020.5;
+return(23.452294 - 0.00013 *jd/365.25);
+}
+
+/*
+++
+double LongEcPerihelie(JMA dateTU)
+	Retourne la Longitude Ecliptique du perihelie de
+	l'orbite terrestre a la date TU ``dateTU'' (en degres decimaux).
+--
+*/
+double LongEcPerihelie(JMA dateTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
+{
+double JD,T;
+HMS hmsTU;
+hmsTU.Heures = 12; hmsTU.Minutes = 0; hmsTU.Secondes = 0.;
+JD = ToJulianDay(dateTU,hmsTU);
+/* T en siecles juliens depuis 31/12/1899 a 12h TU --> JD=2415020. */
+T = (JD-2415020.)/36525;
+/* l = 101d 13' 07.15" + 6171.77" *T + 1.823" *T^2 */
+return(101.218652778 + 1.71438055556*T + 0.000506388889*T*T);
+}
+
+/*
+++
+void EquatToEclip(double a,double d,double* l,double *b,JMA dateTU);
+	Renvoie les coordonnees ecliptiques ``l,b'' a partir de
+	coordonnees equatoriales ``a,d'' a la date TU ``dateTU''.
+	La date permet de corriger la variation annuelle
+	de l'obliquite terrestre.
+--
+*/
+void EquatToEclip(double a,double d,double* l,double *b,JMA dateTU)
+/* Cf Fundamental astronomie, Springer Verlag 2sd ed p477 table E10.  cmv 9/12/98 */
+/* l=[0,360[, b=[-90,90] */
+{
+double e,sinb,cosb,sinl,cosl;
+
+e = ObliqEarth(dateTU)*DegenRad;
+a *= DegenRad; d *= DegenRad;
+
+sinb = sin(d)*cos(e)-cos(d)*sin(e)*sin(a);
+if(sinb>1.) sinb=1.; if(sinb<-1.) sinb=-1.;
+*b = asin(sinb);
+cosb = cos(*b);
+
+*l = 0.;
+if(cosb!=0.) {
+  sinl = (sin(d)*sin(e)+cos(d)*cos(e)*sin(a))/cosb;
+  cosl = cos(d)*cos(a)/cosb;
+  if(cosl>1.) cosl=1.; if(cosl<-1.) cosl=-1.;
+  *l = acos(cosl);
+  if(sinl<0.) *l += M_PI;
+  if(*l>2.*M_PI) *l -= 2.*M_PI;
+}
+
+*b /= DegenRad;
+*l /= DegenRad;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/datime.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/datime.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/datime.h	(revision 752)
@@ -0,0 +1,125 @@
+/*    ------ 1)  Declaration de structure temps et date  ----- */
+/*                            Reza 92/93                       */
+
+#ifndef DATIME_H_SEEN
+#define DATIME_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct 
+  {
+  int Jour;
+  int Mois;
+  int Annee;
+  }  JMA ;
+
+
+typedef struct 
+  {
+  int  Heures;
+  int Minutes;
+  double Secondes;
+  } HMS ;
+
+/*   ----------    2) Donnees constantes  ---------- */
+#ifdef  DATIMEPRIVEE
+/*   Noms des jours de la semaine - des mois  */
+char *NomJo[7] =  {"Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"};
+char *NomMo[12] = 
+  {"Janvier","Fevrier","Mars","Avril","Mai","Juin","Juillet",
+  "Aout","Septembre","Octobre","Novembre","Decembre"};
+
+/*   Nombre de jours des mois   */
+static int NbJoMois[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+#else
+
+extern char *NomJo[7];
+extern char *NomMo[12];
+
+#endif
+
+/*    ------ 3) Macro de manipulation de date et heure  -------  */
+
+#define  NomJour(d)      (NomJo[NumJour(d)-1])
+#define  NomMois(d)      (NomMo[d.Mois-1])
+
+/*   Chaine de forme  hh:mm:sec  <->  structure HMS   */
+#define  StrgtoHMS(s,h)  ( sscanf(s,"%d:%d:%lf", &(h.Heures),&(h.Minutes),&(h.Secondes)) )
+#define  HMStoStrg(h,s)  ( sprintf(s,"%02d:%02d:%02.0f", h.Heures,h.Minutes,h.Secondes) )
+
+/*    Chaine de forme jj/mm/aa  <-> structure JMA     */
+/* EA 140998, machin infame pour que ca marche pour 1998/09/14... Pourquoi avoir fait */
+/* des macros ??????????????????????????????????????????????????????????????????????? */
+#define  StrgtoJMA(strg,j)  ( sscanf(strg,"%d/%d/%d", &(j.Jour),&(j.Mois),&(j.Annee)),\
+    (j.Jour>1900 ? sscanf(strg,"%d/%d/%d", &(j.Annee),&(j.Mois),&(j.Jour)) : 1) ) 
+
+#define  JMAtoStrg(j,strg)  ( sprintf(strg,"%02d/%02d/%4d", j.Jour,j.Mois,j.Annee) )
+#define  JMAtoStrgLong(j,strg)   ( sprintf(strg,"%s , %d %s %d", NomJo[NumJour(j)-1], j.Jour, NomMo[j.Mois-1], j.Annee) )
+
+#define  HtoSec(h)        (h*3600.) 
+#define  SectoHMS(s)      ( HtoHMS(s/3600.) )
+
+
+#define  TLegtoTSolM(d,h)    ( TUtoTSolM(TLegtoTU(d,h)) )
+
+/*  -------  4)  Declaration des fonctions    ----------  */
+
+void StrtoHMS(char *s,HMS* hms);
+void HMStoStr(HMS hms,char *s);
+
+int NbJourMois(int a, int m);
+long JMAtoJ(JMA jma);
+JMA JtoJMA(long j);
+int NumJour(JMA jma);
+JMA JsmmaatoJMA(int jj, int mm, int aa);
+JMA JApmmaatoJMA(int nj, int mm, int aa);
+
+double HMStoH(HMS hms);
+double HMStoSec(HMS hms);
+
+long DatetoSec(char const* date, char const* heure);
+long DatetoSecOff(char const* date, char const* heure);
+
+HMS HtoHMS(double h);
+HMS DtoDMS(double h);
+HMS DoubletoHMS(double h);
+
+void SetTSolMOff(double tsmoff, char *name);
+void PrtTSolMOff(void);
+int  SetTLegOff(char *dtz, char* dhz);
+void PrtTLegInfo(int aa);
+int  TLegOffset(JMA date, HMS heure);
+
+HMS TLegtoTU(JMA date, HMS TLeg);
+HMS TUtoTLeg(JMA date, HMS TLeg);
+HMS TUtoTSolM(HMS TU);
+HMS TLegtoTSid(JMA date, HMS TLeg);
+HMS GMST_at_0h_UT(JMA date);
+HMS TUtoTSid(JMA date, HMS TU);
+int TSidtoTU(JMA date, HMS TS, HMS *TU1, HMS *TU2);
+void TSidSetupLaSilla(void);
+
+double ToJulianDay(JMA dateTU, HMS hmsTU);
+int FromJulianDay(double JD,JMA* dateTU, HMS* hmsTU);
+
+double StrgtoDegDec(char *strg);   
+char * DegDectoStrg(double deg, char *strg);
+
+double EccEarth(JMA dateTU);
+double ObliqEarth(JMA dateTU);
+double LongEcPerihelie(JMA dateTU);
+void EquatToEclip(double alpha,double delta,double* l,double *b,JMA dateTU);
+
+/*   -------------------------------------------------------  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/difeq.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/difeq.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/difeq.cc	(revision 752)
@@ -0,0 +1,625 @@
+#include "difeq.h"
+#include "ctimer.h"
+
+//++
+// Class	DiffEqSolver
+// Lib  	Outils++ 
+// include	difeq.h
+//
+//	Classe abstraite de résolveur d'équation différentielles.
+//	Beaucoup de méthodes renvoient l'objet afin de pouvoir
+//	utiliser une notation chaînée du type
+//|	s.Step(...).Start(...).Solve(...)
+//--
+//++ 
+// Links	Implementations
+// RK4DiffEq
+// RK4CDiffEq
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+DiffEqSolver::DiffEqSolver()
+//
+//	Constructeur vide. 
+//--
+: mFunc(NULL), mOwnFunc(false),
+  mYStart(1), mXStart(0), mStep(0.01)
+{}
+
+//++
+DiffEqSolver::DiffEqSolver(DiffEqFunction* f)
+//
+//	Constructeur général. L'équation est donnée sous forme
+//	de DiffEqFunction
+//--
+: mFunc(f), mOwnFunc(false),
+  mYStart(mFunc->NFuncReal()), mXStart(0), mStep(0.01)
+{}
+
+//++
+DiffEqSolver::DiffEqSolver(DIFEQFCN1 f)
+//
+//	Constructeur pour le cas particulier d'une équation du premier
+//	ordre. Voir DiffEqFcn1. La fonction f correspond à l'équation
+//	y' = f(y).
+//--
+: mFunc(new DiffEqFcn1(f)), mOwnFunc(true),
+  mYStart(mFunc->NFuncReal()), mXStart(0), mStep(0.01)
+{}
+
+DiffEqSolver::~DiffEqSolver()
+{
+  if (mOwnFunc) delete mFunc;
+}
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+DiffEqSolver&
+DiffEqSolver::Func(DiffEqFunction* f)
+//
+//	Permet de spécifier l'équation différentielle, sous la forme
+//	d'une DiffEqFunction. Retourne l'objet DiffEqSolver : notation
+//	chaînée possible
+//--
+{
+  if (mFunc && mOwnFunc) delete mFunc;
+  mFunc    = f;
+  mOwnFunc = false;
+  return *this;
+}
+
+//++
+DiffEqSolver&
+DiffEqSolver::Func(DIFEQFCN1 f)
+//
+//	Permet de spécifier l'équation différentielle, sous la forme
+//	d'une fonction f telle que y' = f(y). Retourne l'objet DiffEqSolver : 
+//	notation chaînée possible.
+//--
+{
+  if (mFunc && mOwnFunc) delete mFunc;
+  mFunc    = new DiffEqFcn1(f);
+  mOwnFunc = true;
+  return *this;
+}
+
+//++
+DiffEqSolver&
+DiffEqSolver::Step(double step)
+//
+//	Spécifie le pas d'intégration de l'équation différentielle (pour
+//	les méthodes où ce pas a un sens). La valeur par défaut est 0.01.
+//	Retourne l'objet DiffEqSolver : notation chaînée possible.
+//--
+{
+  mStep = step;
+  return *this;
+}
+
+//++
+DiffEqSolver&
+DiffEqSolver::StartV(Vector const& yi, double t)
+//
+//	Spécifie le point de départ de l'intégration de l'équadif.
+//	Le vecteur y contient les valeurs intiales. Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément du vecteur. t est la valeur initiale 
+//	du temps.
+//	La dimension de y doit correspondre au nombre apparent de fonctions.
+//	Retourne l'objet DiffEqSolver : notation chaînée possible.
+//--
+{
+  ASSERT(mFunc != NULL);
+  ASSERT(yi.NElts() == mFunc->NFunc());   // Nombre apparent
+  mYStart = yi;
+  mXStart = t;
+  mFunc->AdjustStart(mYStart,t);
+  ASSERT(mYStart.NElts() == mFunc->NFuncReal());
+  return *this;
+}
+
+//++
+DiffEqSolver&
+DiffEqSolver::Start1(double y, double t)
+//
+//	Spécifie le point de départ de l'intégration de l'équadif,
+//	pour une équation y' = f(y). On donne le temps et la valeur de y.
+//	Retourne l'objet DiffEqSolver : notation chaînée possible.
+//--
+{
+  ASSERT(mFunc != NULL);
+  ASSERT(mFunc->NFunc() == 1);   // Nombre apparent
+  mYStart.Realloc(1);
+  mYStart(0) = y;
+  mXStart = t;
+  mFunc->AdjustStart(mYStart,t);
+  ASSERT(mYStart.NElts() == mFunc->NFuncReal());
+  return *this;
+}
+
+//++
+DiffEqSolver&
+DiffEqSolver::Start(double const* yi, double t)
+//
+//	Spécifie le point de départ de l'intégration de l'équadif.
+//	Le tableau yi contient les valeurs intiales. Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément du tableau. t est la valeur initiale 
+//	du temps.
+//	Le nombre d'éléments de yi doit correspondre au nombre apparent
+//	de fonctions.
+//	Retourne l'objet DiffEqSolver : notation chaînée possible.
+//--
+{
+  mYStart.Realloc(mFunc->NFunc());
+  for (int i=0; i<mFunc->NFunc(); i++)
+    mYStart(i) = yi[i];
+  mXStart = t;
+  mFunc->AdjustStart(mYStart,t);
+  ASSERT(mYStart.NElts() == mFunc->NFuncReal());
+  return *this;
+}
+
+//++
+// virtual void DiffEqSolver::SolveArr(Matrix&  y, double* t, double tf, int n)=0
+//	Lance la résolution de l'équadif, jusqu'à la valeur
+//	tf du temps. N valeurs intermédiaires sont retournées dans 
+//	les tableaux y et t :
+//	t[i] est le temps au pas i, pour 0<=i<n
+//	y[i] sont les valeurs des fonctions au pas i.
+//	Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément de y[i].
+//	t[n-1] vaut tf.
+//	Le nombre d'éléments de y[i] doit correspondre au nombre apparent
+//	de fonctions.
+//	Cette fonction doit être redéfinie pour chaque méthode de résolution
+//	d'équations. Elle est appelée par toutes les autres fonctions de
+//	résolution (autres SolveArr, et Solve).
+//--
+
+
+//++
+void
+DiffEqSolver::SolveV(Vector& yf, double tf)
+//
+//	Lance la résolution de l'équadif, jusqu'à la valeur
+//	tf du temps. Les valeurs finales sont retournées dans yf.
+//	Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément de yf.
+//	Le nombre d'éléments de yf doit correspondre au nombre apparent
+//	de fonctions.
+//--
+{
+  double t;
+  Matrix m(1, mFunc->NFuncReal());
+  SolveArr(m, &t, tf, 1);
+  yf.Realloc(mFunc->NFunc());
+  for (int i=0; i<mFunc->NFunc(); i++)
+    yf(i) = m(0,i);
+}
+
+//++
+void
+DiffEqSolver::Solve1(double& yf, double tf)
+//
+//	Lance la résolution de l'équadif, jusqu'à la valeur
+//	tf du temps, pour une équation du premier ordre y' = f(y).
+//	La valeur finale de y est retournée dans yf.
+//--
+{
+  ASSERT(mFunc->NFunc() == 1);
+  double t;
+  Matrix m(1,mFunc->NFuncReal());
+  SolveArr(m, &t, tf, 1);
+  yf = m(0,0);
+}
+
+//++
+void
+DiffEqSolver::Solve(double* yf, double tf)
+//
+//	Lance la résolution de l'équadif, jusqu'à la valeur
+//	tf du temps. Les valeurs finales sont retournées dans yf.
+//	Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément de yf.
+//	Le nombre d'éléments de yf doit correspondre au nombre apparent
+//	de fonctions.
+//--
+{
+  double t;
+  Matrix m(1, mFunc->NFuncReal());
+  SolveArr(m, &t, tf, 1);
+  for (int i=0; i<mFunc->NFunc(); i++)
+    yf[i] = m(0,i);
+}
+
+//++
+void
+DiffEqSolver::SolveArr1(double*  y, double* t, double tf, int n)
+//
+//	Lance la résolution de l'équadif (du premier ordre), jusqu'à la valeur
+//	tf du temps. N valeurs intermediaires sont retournées dans 
+//	les tableaux y et t :
+//	t[i] est le temps au pas i, pour 0<=i<n
+//	y[i] est la valeur de la fonction au pas i.
+//	t[n-1] vaut tf.
+//--
+
+{
+  ASSERT(mFunc->NFunc() == 1);
+  Matrix m(n, mFunc->NFuncReal());
+  SolveArr(m, t, tf, n);
+  for (int i=0; i<n; i++)
+    y[i] = m(i,0);
+}
+
+//++
+void
+DiffEqSolver::SolveArr2(double** y, double* t, double tf, int n)
+//
+//	Lance la résolution de l'équadif, jusqu'à la valeur
+//	tf du temps. N valeurs intermédiaires sont retournées dans 
+//	les tableaux y et t :
+//	t[i] est le temps au pas i, pour 0<=i<n
+//	y[i] sont les valeurs des fonctions au pas i.
+//	Voir la description
+//	de chaque fonction-objet-équation différentielle pour connaître
+//	le rôle de chaque élément de y[i].
+//	t[n-1] vaut tf.
+//	Le nombre d'éléments de y[i] doit correspondre au nombre apparent
+//	de fonctions.
+//--
+{
+   Matrix m(n, mFunc->NFuncReal());
+   SolveArr(m, t, tf, n);
+   for (int i=0; i<n; i++)
+     for (int j=0; j<mFunc->NFunc(); j++)
+       y[i][j] = m(i,j);
+}
+
+
+//++
+// Class	DiffEqFunction
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Classe de fonctions pour la résolution d'équations différentielles.
+//	On résoud de facon générale un système de n équations différentielles
+//	du premier ordre, donnant les dérivées fpi de n fonctions fi. 
+//	Cette méthode permet de résoudre toutes les sortes d'équations :
+//	pour une équation du second ordre on crée une fonction intermédiaire
+//	qui est la dérivée de la fonction cherchée.
+//--
+
+//++
+// DiffEqFunction::DiffEqFunction(int n)
+//	Constructeur. N est le nombre de fonctions dans le
+//	système.
+//--
+
+//++
+// DiffEqFunction::DiffEqFunction(int n, int napp)
+//	Constructeur. N est le nombre réel de fonctions dans le
+//	système, et napp le nombre apparent (pour l'utilisateur).
+//	En effet, dans certains cas, on peut avoir besoin de fonctions
+//	supplémentaires masquées à l'utilisateur, par exemple la fonction
+//	constante valant 1, si l'équadif fait intervenir le temps (t).
+//--
+
+//++
+//  virtual void ComputeV(Vector& fpi, Vector const& fi)
+//	Calcule les valeurs des dérivées fpi à partir des valeurs 
+//	des fonctions fi. A redéfinir.
+//--
+
+//++
+//  virtual void Compute(double& fp, double f)
+//	Dans le cas où il y a une seule fonction, calcule la dérivée
+//      fp à partir de la valeur de la fonction f. A redéfinir.
+//--
+
+//++
+// int NFunc()
+// 	Nombre apparent de fonctions dans le système
+//--
+  
+//++
+// int NFuncReal() {return mNFunc;}
+// 	Nombre réel de fonctions dans le système
+//--
+
+//++
+// virtual void AdjustStart(Vector& start, double tstart)
+//	Pour ajuster le vecteur de départ quand il y a des 
+//	fonctions à usage interne...
+//--
+
+
+
+//++
+// Class	DiffEqFcn1
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Objet-fonction générique pour la résolution d'équations
+//	différentielles de la forme y' = f(y).
+//	On fournit une fonction de type
+//|	typedef double(*DIFEQFCN1)(double);
+//	qui retourne y' en fonction de y.
+//--
+//++
+// Links	Parents
+// DiffEqFunction
+//--
+
+//++
+DiffEqFcn1::DiffEqFcn1(DIFEQFCN1 fcn)
+//
+//	Constructeur. On fournit la fonction f tq y'=f(y)
+//--
+: DiffEqFunction(1), mFcn(fcn)
+{}
+
+void
+DiffEqFcn1::Compute(double& fp, double f)
+{
+   fp = (*mFcn)(f);
+}
+
+//++
+// Class	DiffEqFcnT1
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Objet-fonction générique pour la résolution d'équations
+//	différentielles de la forme y' = f(y,t).
+//	On fournit une fonction de type
+//|	typedef double(*DIFEQFCNT1)(double, double);
+//	qui retourne y' en fonction de y et t.
+//	Note : le système résolu est alors en fait
+//|	y'[0] = fcn(y[0], y[1])
+//|	y'[1] = 1
+//--
+//++
+// Links	Parents
+// DiffEqFunction
+//--
+
+//++
+DiffEqFcnT1::DiffEqFcnT1(DIFEQFCNT1 fcn)
+//
+//	Constructeur. On fournit la fonction f tq y' = f(y,t)
+//--
+: DiffEqFunction(2, 1), mFcn(fcn)
+{}
+
+void
+DiffEqFcnT1::ComputeV(Vector& fpi, Vector const& fi)
+{
+  fpi(0) = (*mFcn)(fi(0), fi(1));
+  fpi(1) = 1;
+}
+
+void
+DiffEqFcnT1::AdjustStart(Vector& start, double tstart)
+{
+  start.Realloc(2);
+  start(1) = tstart;
+}
+
+//++
+// Class	DiffEqFcn2
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Objet-fonction générique pour la résolution d'équations
+//	différentielles de la forme y'' = f(y',y).
+//	On fournit une fonction de type
+//|	typedef double(*DIFEQFCN2)(double, double);
+//	qui retourne y'' en fonction de y' et y.
+//	Note : le système résolu est en fait
+//|	y'[0] = y[1]
+//|	y'[1] = f(y[1], y[0])
+//--
+//++
+// Links	Parents
+// DiffEqFunction
+//--
+
+//++
+DiffEqFcn2::DiffEqFcn2(DIFEQFCN2 fcn)
+//
+//	Constructeur. On fournit la fonction f tq y''=f(y',y)
+//--
+: DiffEqFunction(2), mFcn(fcn)
+{}
+
+void
+DiffEqFcn2::ComputeV(Vector& fpi, Vector const& fi)
+{
+  fpi(0) = fi(1);
+  fpi(1) = (*mFcn)(fi(1), fi(0));
+}
+
+//++
+// Class	DiffEqFcnT2
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Objet-fonction générique pour la résolution d'équations
+//	différentielles de la forme y'' = f(y',y,t).
+//	On fournit une fonction de type
+//|	typedef double(*DIFEQFCNT2)(double, double, double);
+//	qui retourne y'' en fonction de y', y et t.
+//	Note : le système résolu est alors en fait
+//|	y'[0] = y[1]
+//|	y'[1] = f(y[1], y[0], y[2])
+//|	y'[2] = 1
+//--
+//++
+// Links	Parents
+// DiffEqFunction
+//--
+
+//++
+DiffEqFcnT2::DiffEqFcnT2(DIFEQFCNT2 fcn)
+//
+//	Constructeur. On fournit la fonction f tq y'' = f(y',y,t)
+//--
+: DiffEqFunction(3,2), mFcn(fcn)
+{}
+
+void
+DiffEqFcnT2::ComputeV(Vector& fpi, Vector const& fi)
+{
+  fpi(0) = fi(1);
+  fpi(1) = (*mFcn)(fi(1), fi(0), fi(2));
+  fpi(2) = 1;
+}
+
+void
+DiffEqFcnT2::AdjustStart(Vector& start, double tstart)
+{
+  start.Realloc(3);
+  start(2) = tstart;
+}
+
+
+//++
+// Class	DiffEqFcnV
+// Lib	Outils++ 
+// include	difeq.h
+//
+//	Objet-fonction générique pour la résolution d'équations
+//	différentielles 3D de la forme y'' = f(y',y), ou y est
+//	un vecteur de dimension 3.
+//	On fournit une fonction de type
+//|	typedef void(*DIFEQFCNV)(Vector& y2, Vector const& y1, 
+//|	                         Vector const& y);
+//	qui retourne y'' en fonction de y' et y.
+//	Note : le système résolu est alors en fait
+//|	v(0-2) = y, v(3-5) = y'
+//|
+//|	v'[0] = v[3]
+//|	v'[1] = v[4]
+//|	v'[2] = v[5]
+//|	v'[3-5] = f(v[3-5], v[0-2])
+//--
+//++
+// Links	Parents
+// DiffEqFunction
+//--
+
+DiffEqFcnV::DiffEqFcnV(DIFEQFCNV fcn)
+: DiffEqFunction(6), mFcn(fcn),
+  tmp1(3), tmp2(3), tmp3(3)
+{}
+
+void
+DiffEqFcnV::ComputeV(Vector& fpi, Vector const& fi)
+{
+  fpi(0) = fi(3);
+  fpi(1) = fi(4);
+  fpi(2) = fi(5);
+  
+  tmp2(0) = fi(3); tmp2(1) = fi(4); tmp2(2) = fi(5);
+  tmp3(0) = fi(0); tmp3(1) = fi(1); tmp3(2) = fi(2);
+  
+  (*mFcn)(tmp1, tmp2, tmp3);
+  
+  fpi(3) = tmp1(0); fpi(4) = tmp1(1); fpi(5) = tmp1(2);
+}
+
+
+//++
+// Class	RK4DiffEq
+// Lib  	Outils++ 
+// include	difeq.h
+//
+//	Classe de résolution d'équadif par la méthode de
+//	Runge-Kutta d'ordre 4.
+//	Voir DiffEqSolver pour les méthodes.
+//--
+//++
+// Links	Parents
+// DiffEqSolver
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+RK4DiffEq::RK4DiffEq()
+: DiffEqSolver(), k1(10), k2(10), k3(10), k4(10)
+{}
+
+//++
+RK4DiffEq::RK4DiffEq(DiffEqFunction* f)
+//
+//	Constructeur général
+//--
+: DiffEqSolver(f), k1(f->NFuncReal()), 
+  k2(f->NFuncReal()), k3(f->NFuncReal()), k4(f->NFuncReal())
+{}
+
+//++
+RK4DiffEq::RK4DiffEq(DIFEQFCN1 f)
+//
+//	Constructeur pour y' = f(y)
+//--
+: DiffEqSolver(f), k1(1), k2(1), k3(1), k4(1)
+{}
+
+void
+RK4DiffEq::SolveArr(Matrix& y, double* t, double tf, int n)
+{
+  //TIMEF;
+  // On calcule le nombre de sous-pas par pas
+   
+   int nStep = (mStep > 0) ? int((tf - mXStart)/n/mStep) : 1;
+   if (nStep <= 1) nStep = 1;
+   
+   double dx = (tf - mXStart)/(n*nStep);
+   
+   Vector yt = mYStart;
+
+   k1.Realloc(mFunc->NFuncReal());
+   k2.Realloc(mFunc->NFuncReal());
+   k3.Realloc(mFunc->NFuncReal());
+   k4.Realloc(mFunc->NFuncReal());
+   
+      
+   for (int i=0; i<n; i++) {
+     for (int j=0; j<nStep; j++)
+       RKStep(yt, yt, dx);
+     for (int k=0; k<mFunc->NFunc(); k++)
+       y(i,k) = yt(k);
+     t[i] = (i+1)*dx*nStep + mXStart;  
+   }
+}
+
+void
+RK4DiffEq::RKStep(Vector& newY, Vector const& y0, double dt)
+{
+    mFunc->ComputeV(k1, y0);
+    k1 *= dt;
+    mFunc->ComputeV(k2, y0 + k1/2.);
+    k2 *= dt;
+    mFunc->ComputeV(k3, y0 + k2/2.);
+    k3 *= dt;
+    mFunc->ComputeV(k4, y0 + k3);
+    k4 *= dt;
+    
+    newY = y0 + (k1 + k2*2. + k3*2. + k4)/6.;
+}
+
Index: /tags/V_Fev00/SophyaLib/NTools/difeq.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/difeq.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/difeq.h	(revision 752)
@@ -0,0 +1,231 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef DIFEQ_H_SEEN
+#define DIFEQ_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "tvector.h"
+
+namespace SOPHYA {
+
+class GeneralFunction;
+
+// <summary> fonction pour equadifs </summary>
+// Une fonction utilisee pour les equations differentielles.
+// On resoud de facon generale un systeme de n equations differentielles,
+// donnant les derivees fpi de n fonctions fi.
+class DiffEqFunction EXC_AWARE {
+public:
+  // Constructeur. n = nombre de fonctions dans le systeme
+  DiffEqFunction(int n)          : mNFunc(n), mNFuncApp(n) {}
+  
+  // Constructeur. n = nombre reel de fonctions dans le systeme,
+  // m = nombre apparent (il y a dans certaines cas des fonctions a 
+  // usage interne,  par exemple la fonction constante valant 1...)
+  
+  DiffEqFunction(int n, int m)   : mNFunc(n), mNFuncApp(m) {}
+  
+  // Destructeur
+  virtual ~DiffEqFunction()      {}
+  
+  // Calcule les valeurs des derivees fpi a partir des valeurs des fonctions fi
+  virtual void ComputeV(Vector& fpi, Vector const& fi)
+       { Compute(fpi(0), fi(0)); }
+
+  // Dans le cas ou on a une seule fonction, calcule la valeur de la derivee fp
+  // a partir de la valeur de la fonction
+  virtual void Compute(double& /*fp*/, double /*f*/)
+       { ASSERT(mNFunc == 1); }
+  
+  // Nombre apparent de fonctions dans le systeme
+  int NFunc()     {return mNFuncApp;}
+  
+  // Nombre reel de fonctions dans le systeme
+  int NFuncReal() {return mNFunc;}
+  
+  // Pour ajuster vecteur de depart quand il y a des fonctions a usage
+  // interne...
+  virtual void AdjustStart(Vector& /*start*/, double /*tstart*/) 
+    {}   
+protected:
+  // Nombre de fonctions dans le systeme
+  int mNFunc;                   
+  // Nombre apparent de fonctions                 
+  int mNFuncApp;                               
+};
+
+
+// Cas y' = f(y)
+typedef double(*DIFEQFCN1)(double);
+
+// <summary> Cas y' = f(y) </summary>
+// Cas y' = f(y), on fournit la fonction f, sous la forme
+// double f(double), et ca construit la bonne DiffEqFunction
+class DiffEqFcn1 : public DiffEqFunction {
+public:
+  // Constructeur, on fournit une fonction double->double
+  // qui donne y' en fonction de y.
+  DiffEqFcn1(DIFEQFCN1);
+
+  // Implementation de Compute qui va utiliser la fonction fournie
+  // au constructeur.
+  virtual void Compute(double& fp, double f);
+protected:
+  DIFEQFCN1 mFcn;
+};
+
+// Cas y' = f(y,t)
+typedef double(*DIFEQFCNT1)(double, double);
+
+// <summary> y' = f(y,t) </summary>
+// Cas y' = f(y,t), on fournit la fonction f, sous la forme
+// double f(double, double), et ca construit la bonne DiffEqFunction
+class DiffEqFcnT1 : public DiffEqFunction {
+public:
+  // Constructeur, on fournit une fonction (double, double)->double
+  // qui donne y' en fonction de y et t.
+  DiffEqFcnT1(DIFEQFCNT1);
+
+  // Implementation de Compute qui va utiliser la fonction fournie
+  // au constructeur.
+  virtual void ComputeV(Vector& fpi, Vector const& fi);
+
+  // Implementation de AdjustStart qui gere la fonction a usage interne.
+  virtual void AdjustStart(Vector& start, double tstart);
+protected:
+  DIFEQFCNT1 mFcn;
+};
+
+// Cas y'' = f(y',y)
+typedef double(*DIFEQFCN2)(double, double);
+
+class DiffEqFcn2 : public DiffEqFunction {
+public:
+  DiffEqFcn2(DIFEQFCN2);
+
+  virtual void ComputeV(Vector& fpi, Vector const& fi);
+protected:
+  DIFEQFCN2 mFcn;
+};
+
+// Cas y'' = f(y',y,t)
+typedef double(*DIFEQFCNT2)(double, double, double);
+
+// <summary> y'' = f(y',y,t) </summary>
+// Cas y'' = f(y',y,t), on fournit la fonction f, sous la forme
+// double f(double, double, double), et ca construit la bonne DiffEqFunction
+class DiffEqFcnT2 : public DiffEqFunction {
+public:
+  // Constructeur, on fournit une fonction (double, double, double)->double
+  // qui donne y'' en fonction de y', y et t.
+  DiffEqFcnT2(DIFEQFCNT2);
+
+  // Implementation de Compute qui va utiliser la fonction fournie
+  // au constructeur.
+  virtual void ComputeV(Vector& fpi, Vector const& fi);
+
+  // Implementation de AdjustStart qui gere la fonction a usage interne.
+  virtual void AdjustStart(Vector& start, double tstart);
+protected:
+  DIFEQFCNT2 mFcn;
+};
+
+// Cas y'' = f(y',y) avec des 3-vecteurs
+typedef void(*DIFEQFCNV)(Vector&, Vector const&, Vector const&);
+
+// <summary> y'' = f(y',y,t) </summary>
+// Cas y'' = f(y',y,t), on fournit la fonction f, sous la forme
+// double f(Vector), et ca construit la bonne DiffEqFunction
+class DiffEqFcnV : public DiffEqFunction {
+public:
+  // Constructeur, on fournit une fonction (Vector)->double
+  // qui donne y'' en fonction du vecteur (t, y, y')
+  DiffEqFcnV(DIFEQFCNV);
+
+  // Implementation de Compute qui va utiliser la fonction fournie
+  // au constructeur.
+  virtual void ComputeV(Vector& fpi, Vector const& fi);
+protected:
+  DIFEQFCNV mFcn;
+  Vector tmp1, tmp2, tmp3;
+};
+
+// <summary> Classe abstraite de resolveur d'equadif </summary>
+// Classe abstraite de resolveur d'equadif
+// Beaucoup de fonctions renvoient l'objet pour pouvoir faire une
+// notation chainee s.Step(...).Start(...).Solve(...)
+class DiffEqSolver EXC_AWARE {
+public:
+  // Constructeurs. L'equadif est donnee sous forme de DiffEqFunction.
+  // On a prevu le cas particulier du premier degre directement
+  // <group>
+  DiffEqSolver();
+  DiffEqSolver(DiffEqFunction*);
+  DiffEqSolver(DIFEQFCN1);
+  // </group>
+  
+  // Destructeur
+  virtual ~DiffEqSolver();
+
+  // Change la fonction. Notation chainee possible
+  // <group>
+  DiffEqSolver& Func(DiffEqFunction*);
+  DiffEqSolver& Func(DIFEQFCN1);
+  // </group>
+  // Change le pas d'integration. Notation chainee possible
+  DiffEqSolver& Step(double);
+  
+  // Change les conditions initiales. Notation chainee possible.
+  // <group>
+  DiffEqSolver& StartV(Vector const& yi, double t);
+  // si NFunc == 1
+  DiffEqSolver& Start1(double        yi, double t);
+  DiffEqSolver& Start(double const* yi, double t);
+  // </group>
+  
+  // Lance la resolution, avec ou sans conservation de n valeurs intermediaires
+  // <group>
+  virtual void SolveV(Vector& yf, double tf);
+  // si NFunc == 1
+  virtual void Solve1(double& yf, double tf);  
+  virtual void Solve(double* yf, double tf);
+  virtual void SolveArr(Matrix&  y, double* t, double tf, int n)=0;
+  // si NFunc == 1
+  virtual void SolveArr1(double*  y, double* t, double tf, int n);   
+  virtual void SolveArr2(double** y, double* t, double tf, int n);
+  // </group>
+  
+protected:
+  DiffEqFunction* mFunc;
+  bool mOwnFunc;
+
+  Vector  mYStart;
+  double  mXStart;
+  double  mStep;
+};
+
+// <summary> Runge-Kutta ordre 4 </summary>
+// Runge-Kutta ordre 4
+class RK4DiffEq : public DiffEqSolver {
+public:
+  // Constructeurs. Voir <linkto class=DiffEqSolver>DiffEqSolver</linkto>
+  // <group>
+  RK4DiffEq();
+  RK4DiffEq(DiffEqFunction*);
+  RK4DiffEq(DIFEQFCN1);
+  // </group>
+
+  // Implementation de RK4
+  virtual void SolveArr(Matrix& y, double* t, double tf, int n);
+
+protected:
+  // Un pas RK4
+  void RKStep(Vector& newY, Vector const& y0, double dt);
+  // Vecteurs utilises en interne, pour ne pas les reallouer.
+  Vector k1, k2, k3, k4;
+};
+
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/dvlist.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dvlist.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dvlist.cc	(revision 752)
@@ -0,0 +1,450 @@
+//  Classe Dynamic Variable List (DVList) de PEIDA
+//                  R. Ansari  1997
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "dvlist.h"
+#include "strutil.h"
+
+//++
+// Class	DVList
+// Lib		Outils++
+// include	dvlist.h
+//
+//	Cette classe permet de gérer une ensemble de variables (ou paramètres)
+//	pouvant être définies dynamiquement à l'execution. Le nom des 
+//	variables ne doit pas contenir de blancs ("<espace>") et est 
+//	limité à 64 caractères maximum. Cette classe 
+//	offre la possibilité de sauvegarder l'ensemble 
+//	des variables (Nom, Type, Valeur) dans un fichier, ou de
+//	recréer l'objet DVList et l'ensemble de ses variables à 
+//	partir d'un fichier (Objet PPersist). Une zone commentaire (max=320 c.) 
+//	est associée à chaque objet DVList, accessible à travers  
+//	la méthode "Comment()". Les objets de cette classe sont  
+//	en particulier destinés à être inclus dans d'autres objets 
+//	PPersist plus complexes. La classe DVList gère des 
+//	variables de type entier ("int_8"), réél double précision ("r_8")
+//	et de type chaine de caracteres ("string, char*", maxi 30 caracteres ).
+//	Une classe intermédiaire (*MuTyV*) est utilisée pour représenter une 
+//	variable et fournit les services de conversion entre les différents types.
+//--
+//--
+//++
+// Links	Parents
+// PPersist
+//--
+
+char MuTyV::myStrBuf[64];   // Declare static ds le .h 
+
+static MuTyV ddvdum(-9.e19);
+
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+// DVList()
+//	Constructeur par défaut
+// DVList(DVList& cfd)
+//	Constructeur par copie. Le nouvel objet est une copie complète de "cfd"
+// DVList(char* flnm)
+//	Constructeur avec initialisation à partir du contenu du fichier (PPF)
+//	"flnm". Le fichier doit avoir été créé par la méthode "Write()"
+//--
+
+/* --Methode-- */
+DVList::DVList()
+{
+comment = "";
+}
+
+/* --Methode-- */
+DVList::DVList(const DVList& dvl)
+{
+Merge(dvl);
+}
+
+/* --Methode-- */
+DVList::DVList(char *flnm)
+{
+PInPersist s(flnm);
+ObjFileIO<DVList> fiodvl(this);
+fiodvl.Read(s);
+}
+
+
+/* --Methode-- */
+DVList::~DVList()
+{
+}
+
+//++
+// Titre	Gestion des variables et opérateurs
+//--
+
+//++
+// void  Clear()
+//	Supprime la définition de toutes les variables de l'objet.
+// DVList&  Merge(const DVList& lv)
+//	Fusionne l'objet avec la liste des variables de l'objet "lv"
+// DVList&  operator= (const DVList& cofr)
+//	Remplace la liste des variables de l'objet par celle de l'objet "cofr".   
+//--
+
+/* --Methode-- */
+DVList&     DVList::operator= (const DVList& dvl)
+{
+Clear();
+return(Merge(dvl));
+}
+
+
+/* --Methode-- */
+void        DVList::Clear()
+{
+mvlist.erase(mvlist.begin(), mvlist.end());
+comment = "";
+}
+
+/* --Methode-- */
+DVList&     DVList::Merge(const DVList& dvl)
+{
+ValList::const_iterator it;
+for(it = dvl.mvlist.begin(); it != dvl.mvlist.end(); it++)
+  {
+  switch ((*it).second.elval.typ) 
+    {
+    case 'I' :
+      SetI((*it).first, (*it).second.elval.mtv.iv);
+      break;
+    case 'D' : 
+      SetD((*it).first, (*it).second.elval.mtv.dv);
+      break;
+    case 'S' : 
+      SetS((*it).first, (*it).second.elval.mtv.strv);
+      break;
+    default :
+      break;
+    }
+  }
+comment = comment + "\n" + dvl.comment;
+return(*this);
+}
+
+
+//++
+// int_8   GetI(string const& key, int_8  def=-1)
+// r_8     GetD(string const& key, r_8 def=-9.e19)
+// string  GetS(string const& key, char* def="")
+//	Retourne la valeur de la variable de nom "key" et de type entier, réél, 
+//	chaine de caracteres.
+//	Si la variable n'existe pas, la valeur par défaut "def" est renvoyée.
+// string  GetComment(string const& key)
+//	Retourne le commentaire associé à la variable de nom "key".
+//--
+
+/* --Methode-- */
+int_8       DVList::GetI(string const& key, int_8 def)
+{
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end())  return(def);
+if ( (*it).second.elval.typ != 'I') return(def);
+return((*it).second.elval.mtv.iv);
+}
+
+/* --Methode-- */
+r_8      DVList::GetD(string const& key, r_8 def)
+{
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end())  return(def);
+if ( (*it).second.elval.typ != 'D') return(def);
+return((*it).second.elval.mtv.dv);
+}
+
+/* --Methode-- */
+string      DVList::GetS(string const& key, char* def)
+{
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end())  return(def);
+if ( (*it).second.elval.typ != 'S') return(def);
+return((*it).second.elval.mtv.strv);
+}
+
+/* --Methode-- */
+string      DVList::GetComment(string const& key)
+{
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end())  return("");
+return((*it).second.elcomm);
+}
+
+//++
+// void  SetI(string const& key, int_8  val)
+// void  SetD(string const& key, r_8 val)
+// void  SetS(string const& key, char*  val)
+// void  SetS(string const& key, string val)
+//	Crée la variable de nom "key", de type entier, double, string et 
+//	lui attribue la valeur "val". Si une variable du même nom existe, 
+//	sa valeur et eventuellement son type sont modifiés.  Les noms de
+//	variables ne doivent pas contenir de caractères spéciaux, 
+//	en particulier pas de CR/LF.
+// void  SetComment(string const& key, string const& comm)
+//	Modifie le commentaire associé à la variable de nom "key", si
+//	celle-ci existe. Le texte du commentaire ne doit pas contenir
+//	de caractères spéciaux, et en particulier pas de CR/LF. 
+//--
+
+/* --Methode-- */
+void        DVList::SetI(string const& key, int_8 val)
+{
+Get(key) = (int_8)val;
+}
+
+/* --Methode-- */
+void        DVList::SetD(string const& key, r_8 val)
+{
+Get(key) = (r_8)val;
+}
+
+/* --Methode-- */
+void        DVList::SetS(string const& key, char const* val)
+{
+MuTyV div(val);
+Get(key) = div;
+}
+
+/* --Methode-- */
+void        DVList::SetS(string const& key, string val)
+{
+MuTyV div(val);
+Get(key) = div;
+}
+
+/* --Methode-- */
+void        DVList::SetComment(string const& key, string const& comm)
+{
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end())  return;
+(*it).second.elcomm = comm;
+}
+
+//++
+// MuTyV&  Get(string const& key) 
+//	Renvoie une référence sur l'objet "MuTyV" de la liste avec le nom "key".
+//	Si cet objet (variable) n'existe pas, il est créé.
+// MuTyV&     operator()  (string const& key) 
+// MuTyV&     operator[]  (string const& key) 
+//
+//	Renvoie la variable de nom "key". Equivalent à "Get(key)". 
+// string&  Comment()
+//	Renvoie une référence sur le champ commentaire de l'objet.
+//--
+
+/* --Methode-- */
+MuTyV&      DVList::Get(string const& key)
+{
+size_t l = key.length();
+if ( (l < 1) || (key.find_first_of(" ") < l) )  return(ddvdum);
+// dvlElement xxx = {(int_8)0 , ""};  marche pas sur mac/CW (!) - cf DY
+dvlElement xxx; xxx.elval = (int_8)0;  xxx.elcomm = "";
+ValList::iterator it = mvlist.find(key);
+if (it == mvlist.end()) mvlist[key] = xxx;  
+it = mvlist.find(key);
+if (it == mvlist.end()) return(ddvdum); 
+else return((*it).second.elval);
+}
+
+//++
+// Titre	Entrée-Sortie
+//--
+
+//++
+//  void  Print()
+//	Imprime (sur "cout") la liste des variables et leurs valeurs.
+//  void  Print(ostream& os)
+//	Imprime sur le flot "os" la liste des variables et leurs valeurs.
+//  ostream&    operator << (ostream& s, DVList& dvl)
+//	sortie sur flot "s" (Appel a "Print(s)").
+//  void  Write(string const& fn)
+//	Ecriture d'un fichier PPersist de nom "fn"
+//  void  Read(string const& fn)
+//	Lecture d'un fichier PPersist de nom "fn"
+//--
+
+
+/* --Methode-- */
+void        DVList::Print(ostream& os) const
+{
+os << "DVList::Print() - NVar= " << (int)mvlist.size() << "\n";
+if (comment.length() > 0)  os << comment << endl;
+char buff[256];
+ValList::const_iterator it;
+for(it = mvlist.begin(); it != mvlist.end(); it++)  {
+  switch ((*it).second.elval.typ) 
+    {
+    case 'I' :
+      sprintf(buff, "%s = %d (int) %s\n", (*it).first.substr(0,64).c_str(), 
+	      (*it).second.elval.mtv.iv, (*it).second.elcomm.substr(0,128).c_str());
+      break;
+    case 'D' : 
+      sprintf(buff, "%s = %.20g (double) %s\n", (*it).first.substr(0,64).c_str(), 
+	      (*it).second.elval.mtv.dv, (*it).second.elcomm.substr(0,128).c_str());
+      break;
+    case 'S' : 
+      sprintf(buff, "%s = %s (string) %s\n", (*it).first.substr(0,64).c_str(), 
+	      (*it).second.elval.mtv.strv, (*it).second.elcomm.substr(0,128).c_str());
+      break;
+    default :
+      break;
+    }
+  os << (string)buff;
+  }
+os << endl;
+}
+
+
+//++
+// Titre	Exemples
+//	Utilisation des objets *MuTyV* :
+//|	MuTyV mvu;         // Declaration d'une variable 
+//|	mvu = 60;          // mvu est de type entier (= 60)
+//|	mvu = 66.6;        // et double (= 66.6) maintenant ...   
+//|	MuTyV mvi(14);     // On construit une variable entiere = 14
+//|	r_4 x = mvi;     // x vaut 14.0
+//|	MuTyV mvd(44.4);   // Variable double = 44.4
+//|	int k = mvd;       // k vaut 44  
+//|	MuTyV mvs("Bonjour, Ca va ?");   // Variable chaine de caracteres 
+//|	string s = mvs;    // s vaut "Bonjour, Ca va ?"  
+//	Utilisation des *DVList* :		 
+//|	DVList  dvl;
+//|	dvl("toto") = 14;
+//|	dvl("titi") = 25.5;
+//|	dvl("tata") = "Bonjour, Ca va ?";
+//	Majuscules et minuscules sont differenciees pour les noms, pas de blanc ...
+//|	dvl("hello") = 88;
+//|	dvl("Hello") = 77.77;
+//|	dvl.Comment() = "Test d'objet DVList, avec variables hello, Hello ";
+//|	dvl.Write("dvlist.ppf");
+//	Plus loin, ou dans un autre programme, on relit le fichier fabrique plus haut 
+//|	DVList dvlr("dvlist.ppf");
+//|	int k = dvlr["toto"] ;     //  k = 14
+//|	r_8 b = dvlr["titi"] ;  //  b = 25.5
+//|	string s =  dvlr["tata"] ; //  s = "Bonjour, Ca va ?"
+//|	r_4 c = dvlr["Hello"] ;  //  c = 77.77
+//|	int l =  dvlr["Hello"] ;   //  l = 77
+//|	int m =  dvlr["hello"] ;   //  m = 88
+//--
+
+
+//----------------------------------------------------------
+// Classe pour la gestion de persistance
+// ObjFileIO<DVList>
+//----------------------------------------------------------
+
+/* --Methode-- */
+void        ObjFileIO<DVList>::WriteSelf(POutPersist& s) const
+{
+char buf[512];
+
+int lc = dobj->Comment().length();
+if (lc > 511) lc = 511;
+if (lc > 0) {
+  sprintf(buf,"Comment: ( %6d ) ", lc); 
+  s.PutLine(buf);
+  s.PutBytes(dobj->Comment().c_str(), lc);
+  }
+s.PutLine("----Variable-List---------------");
+DVList::ValList::const_iterator it;
+for(it = dobj->Begin(); it != dobj->End(); it++)  {
+  switch ((*it).second.elval.typ) {
+    case 'I' :
+      sprintf(buf,"I %s %d", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.iv );
+      s.PutLine(buf); 
+      break;
+    case 'D' : 
+      sprintf(buf,"D %s %.20g", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.dv );
+      s.PutLine(buf); 
+      break;
+    case 'S' : 
+      sprintf(buf,"S %s %s", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.strv );
+      s.PutLine(buf); 
+      break;
+    default :
+      break;
+  }
+// Ecriture eventuelle du commentaire associe
+  if ((*it).second.elcomm.length() > 0) {
+    sprintf(buf,"# %s", (*it).second.elcomm.substr(0,256).c_str());
+    s.PutLine(buf); 
+  }
+}
+
+s.PutLine("ZZZZZ--End-of-Varible-List------");
+}
+
+/* --Methode-- */
+void        ObjFileIO<DVList>::ReadSelf(PInPersist& s)
+{
+char buf[512];
+int_8 j,iv;
+r_8 dv;
+bool ok=true;
+buf[0] = '\0';
+dobj->Clear();
+
+s.GetLine(buf, 511);  // Pour lire les "------- "
+if (buf[0] != '-') {  // Il y a un champ commentaire a lire 
+  buf[18] ='\0';
+  int lc = atoi(buf+11);
+  if (lc > 511)  { 
+    cerr << "DVList::ReadSelf() Pb/Bug ??  CommentLength= " << lc << endl;
+    lc = 511;
+    }
+  s.GetBytes(buf, lc);
+  buf[lc] ='\0';
+  dobj->Comment() = buf;
+  }
+
+string key="";
+while(ok) {
+  s.GetLine(buf, 511);
+  buf[511] = '\0';
+  if (strncmp(buf,"ZZZZZ",5) == 0)  { ok=false; break; }
+  if (buf[0] == '#') {
+    dobj->SetComment(key, buf+2);
+    continue;
+  }
+  j = posc(buf+2, ' ')+2;
+  buf[j] = '\0';
+  switch (buf[0]) {
+    case 'I' :
+      iv = (int_8)atol(buf+j+1);
+      key = buf+2;
+      dobj->SetI(key, iv);
+      break;
+    case 'D' :
+      dv = atof(buf+j+1);
+      key = buf+2;
+      dobj->SetD(key, dv);
+      break;
+    case 'S' :
+      key = buf+2;
+      dobj->SetS(key, buf+j+1);
+      break;
+    default :
+      break;
+    }
+  } 
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<DVList>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<DVList>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/dvlist.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dvlist.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dvlist.h	(revision 752)
@@ -0,0 +1,136 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe DVList : Liste dynamique de variables (valeurs) 
+// identifiees par un nom    Reza Ansari - Dec 96
+
+#ifndef DVLIST_H_SEEN
+#define DVLIST_H_SEEN
+
+#include "objfio.h"
+
+#include <stdio.h>
+
+#include <iostream.h>
+
+#include <list>
+#include <map>
+#include <string.h>
+#include <string>
+
+namespace SOPHYA {
+
+// Classe utilitaire pour manipuler des variables typees 
+class MuTyV {
+public:
+  union {
+  int_8 iv;
+  r_8 dv;
+  char strv[31];
+  } mtv; 
+  char typ;
+
+  static char myStrBuf[64];  
+
+  inline MuTyV() { typ = 'I'; mtv.iv = 0;  mtv.dv = 0.;  mtv.strv[0] ='\0'; }
+  inline MuTyV(int_4 i) { typ = 'I'; mtv.iv = (int_8)i; mtv.dv = 0.;  mtv.strv[0] ='\0'; }
+  inline MuTyV(int_8 i) { typ = 'I'; mtv.iv = i; mtv.dv = 0.;  mtv.strv[0] ='\0'; }
+  inline MuTyV(r_4 f) { typ = 'D'; mtv.dv = (r_8)f;  mtv.iv = 0;  mtv.strv[0] ='\0'; }
+  inline MuTyV(r_8 d) { typ = 'D'; mtv.dv = d; mtv.iv = 0;  mtv.strv[0] ='\0'; }
+  inline MuTyV(char const* s)  { typ = 'S'; strncpy(mtv.strv, s, 31); mtv.strv[30] = '\0'; }
+  inline MuTyV(string const& s) { typ = 'S'; strncpy(mtv.strv, s.c_str(), 31); mtv.strv[30] = '\0'; }
+  inline int_4  operator= (int_4 v)  { typ = 'I'; mtv.iv = (int_8)v; return(v); }
+  inline int_8  operator= (int_8 v)  { typ = 'I'; mtv.iv = v; return(v); }
+  inline r_4  operator= (r_4 v)  { typ = 'D'; mtv.dv = (r_8)v; return(v); }
+  inline r_8 operator= (r_8 v) { typ = 'D'; mtv.dv = v; return(v); }
+  inline char*  operator= (char* s)  { typ = 'S'; strncpy(mtv.strv, s, 31); 
+                                       mtv.strv[30] = '\0';  return(s); }
+  inline string& operator= (string& s)    { typ = 'S'; strncpy(mtv.strv, s.c_str(), 31); 
+                                            mtv.strv[30] = '\0'; return(s); }
+
+  inline operator int_4() { if (typ == 'I')  return((int_4)mtv.iv);
+                            else if (typ == 'D') return((int_4)mtv.dv); 
+                            else return(atol(mtv.strv)); }
+  inline operator int_8() { if (typ == 'I')  return((int_8)mtv.iv);
+                            else if (typ == 'D') return((int_8)mtv.dv); 
+                            else return(atol(mtv.strv)); }
+  inline operator r_4() { if (typ == 'I')  return((r_4)mtv.iv);
+                            else if (typ == 'D') return((r_4)mtv.dv); 
+                            else return((r_4)atof(mtv.strv)); }
+  inline operator r_8() { if (typ == 'I')  return((r_8)mtv.iv);
+                            else if (typ == 'D') return(mtv.dv); 
+                            else return(atof(mtv.strv)); }
+  inline operator string() { char *ss=myStrBuf;
+                            if (typ == 'I')  sprintf(ss,"%ld", mtv.iv);
+                            else if (typ == 'D') sprintf(ss,"%.20g", mtv.dv);
+                            else ss = mtv.strv;
+                            return(ss); }
+};
+
+//  Classe liste de variables  Dynamic Variable List  
+
+class DVList : public AnyDataObj {
+public:
+//  enum {classId = ClassId_DVList };
+
+                    DVList();
+                    DVList(const DVList&);
+                    DVList(char *flnm);
+
+  virtual           ~DVList();
+
+  DVList&           operator= (const DVList&);
+
+  void              Clear();
+  DVList&           Merge(const DVList&);
+
+  int_8             GetI(string const& key, int_8 def=-1);
+  r_8               GetD(string const& key, r_8 def=-9.e19);
+  string            GetS(string const& key, char* def="");
+  string            GetComment(string const& key);
+
+  void              SetI(string const& key, int_8 val);
+  void              SetD(string const& key, r_8 val);
+  void              SetS(string const& key, char const*  val);
+  void              SetS(string const& key, string val);
+  void              SetComment(string const& key, string const& comm);
+
+  MuTyV&            Get(string const& key);
+  inline MuTyV&     operator()  (string const& key)  { return Get(key); }
+  inline MuTyV&     operator[]  (string const& key)  { return Get(key); }
+  inline string&    Comment() { return(comment); }
+
+  inline void       Print() const  { Print(cout); }  
+  virtual void      Print(ostream& os)  const;
+
+// Chaque element dans un DVList est constitue desormais d'un MuTyV
+// et d'une chaine de caracteres (commentaire) regroupe dans la structure
+// dvlElement. Ces elements sont associes aux noms de variables dans un 
+// map<...> ValList.            Reza 02/2000
+
+  struct dvlElement {MuTyV elval; string elcomm; } ;
+  typedef map<string, dvlElement, less<string> >  ValList; 
+  inline ValList::const_iterator Begin() { return(mvlist.begin()); } 
+  inline ValList::const_iterator End() { return(mvlist.end()); } 
+  
+
+private:
+  
+  ValList mvlist;
+  string comment;
+};
+
+inline ostream& operator << (ostream& s, DVList const & dvl)
+  {  dvl.Print(s);  return(s);  }
+
+inline POutPersist& operator << (POutPersist& os, DVList & obj)
+{ ObjFileIO<DVList> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, DVList & obj)
+{ ObjFileIO<DVList> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<DVList>
+
+} // namespace SOPHYA
+
+#endif /* DVLIST_H__SEEN */
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/dynccd.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dynccd.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dynccd.cc	(revision 752)
@@ -0,0 +1,388 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "fmath.h"
+#include "perandom.h"
+
+#include "cimage.h"
+
+#include "dynccd.h"
+
+//++
+// Class	DynCCD
+// Lib		Images++ 
+// include	dynccd.h
+// 
+//	Cette classe permet la specification des parametres 
+//	definissant la dynamique du CCD, et doit etre utilise
+//      pour le calcul des images de bruit.
+//	- TypNoise = 1 :
+//	Bruit = Sqrt( (RONoise/Gain)**2 + ValPix/Gain )      
+//	- TypNoise = 2 :                                     
+//	Bruit = Sqrt( RefSFond**2 + (ValPix-RefFond)/Gain )  
+//	- TypNoise = 0 
+//	Bruit = 1  (Constant pour tous les pixels) 
+//	- TypNoise = 3         
+//	Bruit = Sqrt(Abs(ValPix)) 
+//
+//	Les pixels hors dynamique sont marques (Bruit = 0)
+//	( < MinADU ou > MaxADU) pour toutes valeurs de TypNoise.
+//	Gain est exprime en electron par ADU, RONoise en electron,
+//	Bruit, ValPix et RefFond en ADU.
+//--
+
+//++
+// Links	Parents
+// PPersist
+//--
+//++
+// Links	Autres
+// RzImage
+// Image<T> 
+//--
+//++
+// Titre	Methodes
+//--
+//++
+// DynCCD(int TypNoise=0, float MinADU=-9.e19, float MaxADU=9.e19, float Gain=1., float RONoise=0., float RefFond=0., float RefSFond=0.);
+//	Creation d'un objet DynCCD ("typ" determine la methode de calcul du bruit)
+//	|Test verbatim 
+//
+// void Set(int TypNoise=0, float MinADU=-9.e19, float MaxADU=9.e19, float Gain=1., float RONoise=0., float RefFond=0., float RefSFond=0.);
+//	Modification des parametres de la dynamique
+// void Print()
+// float Noise(float pixel) const
+//	Renvoie la valeur du bruit pour "pixel" en ADU.
+//--
+
+/* ............................................................ */
+/* :::::::::::::  methode de la classe  DynCCD :::::::::::::::: */
+/* ............................................................ */
+
+/* --Methode-- */
+DynCCD::DynCCD(int typ, float min, float max, float g,
+               float ron, float rf, float rfs)
+{
+if ( (typ >= kConstantNoise) && (typ <= kSqrtADUNoise) )  TypNoise = typ;
+else  TypNoise = kConstantNoise;
+MinADU = min;  MaxADU = max;
+Gain = g;  RONoise = ron;
+RefFond = rf;  RefSFond = rfs;
+}
+
+/* --Methode-- */
+void DynCCD::Set(int typ, float min, float max, float g,
+               float ron, float rf, float rfs)
+{
+if ( (typ >= kConstantNoise) && (typ <= kSqrtADUNoise) )  TypNoise = typ;
+MinADU = min;  MaxADU = max;
+Gain = g;  RONoise = ron;
+RefFond = rf;  RefSFond = rfs;
+}
+
+/* --Methode-- */
+void DynCCD::Print()
+{
+printf("DynCCD: Type= %d Min/MaxADU= %g %g Gain/RoN= %g %g\n",
+       TypNoise, MinADU, MaxADU, Gain, RONoise);
+if (TypNoise == 2)
+  printf("... RefFond= %g  RefSFond= %g \n", RefFond, RefSFond);
+return;
+}
+
+/* --Methode-- */
+float DynCCD::Noise(float pixel) const
+
+/* Cette fonction calcule la valeur du bruit pour pixel     */
+/*  Si TypNoise = 1 :                                       */
+/*     Bruit = Sqrt( (RONoise/Gain)**2 + ValPix/Gain )      */
+/*  Si TypNoise = 2 :                                       */
+/*     Bruit = Sqrt( RefSFond**2 + (ValPix-RefFond)/Gain )  */
+/*  Si TypNoise = 0                                         */
+/*     Bruit = 1  (Constant pour tous les pixels)           */
+/*  Si TypNoise = 3                                         */
+/*     Bruit = Sqrt(Abs(PixelADU))                          */
+/*  Les pixels hors dynamique sont marques (Bruit = 0)      */
+/*  ( < MinADU ou > MaxADU) pour tout valeur de TypNoise    */
+
+{
+float h,s,ronsq;
+float fond;
+
+if ( (pixel > MaxADU) || (pixel < MinADU) )   return(0.);
+if ( TypNoise == kConstantNoise)  return(1.);
+if ( TypNoise == kSqrtADUNoise )  return(fsqrt(fabsf(pixel)));
+
+if ( TypNoise == kSigFondNoise)
+  { fond = RefFond;
+  ronsq = RefSFond * RefSFond; }
+else
+  { fond = 0;
+  ronsq = RONoise/Gain;  ronsq *= ronsq; }
+
+h = (pixel>fond) ? (float)(pixel-fond) : 0.;
+s = ronsq+h/Gain;
+s = fsqrt(s);
+return(s);
+}
+
+/* --------------------------------------------------------------  */
+/*      Quelques fonctions pour manipuler des images de bruit      */
+/* --------------------------------------------------------------  */
+
+//++
+// Module	Images de bruit 
+// Lib		Images++ 
+// include	dynccd.h
+//
+//	Ces fonctions permettent le calcul d'image de bruit a partir d'une 
+//	image (RzImage ou Image<T>) et d'un objet DynCCD 
+//--
+//++
+// Links 	Voir classes
+// DynCCD
+// RzImage
+// Image<T>
+//--
+//++
+// Titre	Les fonctions 
+//--
+
+//++
+// Function	RzImage * NoiseImage(RzImage const *pim, DynCCD const * dynccd)
+//	Construit et renvoie l'image du bruit pour l'image "*pim" (RzImage)
+// Function	Image<T> * NoiseImage(Image<T> const * pim, DynCCD const * dynccd)
+//      Meme fonctionalite pour une image typee (ImageU2, ImageR4, ...)
+// Function	ImgAddNoise(Image<T>&, DynCCD const&)
+//	Calcule l'image du bruit et le rajoute a l'image originale
+//--
+
+/* Nouvelle-Fonction */
+template <class T>
+Image<T> * NoiseImage(Image<T> const * pim, DynCCD const * dynccd)
+
+/* Creation et Calcul d'une image de bruit a partir de l'image */
+/* pim et de dynccd. Voir la methode DynCCD::Noise() pour la   */
+/* description du calcul                                       */
+
+{
+float h,s,ronsq;
+float fond, min,max;
+int i, npix;
+float minois, offnois;
+
+if (pim == NULL)  return(NULL);
+
+const T * pix = pim->ImagePtr();
+npix = pim->XSize()*pim->YSize();
+Image<T> * nois = new Image<T>(pim->XSize(), pim->YSize(), false);
+nois->SetOrg(pim->XOrg(), pim->YOrg());
+T * pno = nois->ImagePtr();
+
+min = dynccd->MinADU;   max = dynccd->MaxADU;
+
+
+switch (dynccd->TypNoise)
+  {
+  case kConstantNoise :
+    for(i=0; i<npix; i++)
+      {
+      if ( (*pix <= max) && (*pix >= min) )  *pno = 1;
+      else *pno = 0;
+      pix++;   pno++;
+      }
+    break;
+
+  case kSqrtADUNoise :
+    for(i=0; i<npix; i++)
+      {
+      if ( (*pix <= max) && (*pix >= min) )  *pno = 1;
+      else *pno = (T) fsqrt(fabsf((float)(*pix)));    
+      pix++;   pno++;
+      }
+    break;
+
+  case kPhotonNoise :
+  case kSigFondNoise :
+    if ( dynccd->TypNoise == kSigFondNoise)
+      { fond = dynccd->RefFond;
+      ronsq = dynccd->RefSFond * dynccd->RefSFond; }
+    else
+      { fond = 0;
+      ronsq = dynccd->RONoise/dynccd->Gain;  ronsq *= ronsq; }
+
+// Calcul de minois / offnois pour obtenir un bruit correct malgre 
+// les conversions (float) -> (entier)
+
+    switch(pim->PixelType())
+      {
+      case kuint_2:
+      case kint_2:
+      case kint_4:
+        minois = 1.001;
+        offnois = 0.5;
+        break;
+      case kr_4:
+      case kr_8:
+        minois = 1.e-9;
+        offnois = 0.;
+        break;
+      default:
+        minois = 1.e-9;
+        offnois = 0.;
+        break;
+      }
+
+    for(i=0; i<npix; i++)
+      {
+      if ( (*pix <= max) && (*pix >= min) ) 
+        {
+        h = (*pix>fond) ? (float)(*pix)-fond : 0.;
+        s = ronsq+h/dynccd->Gain;
+        s = fsqrt(s)+offnois;
+        *pno = (s > minois) ? (T)s : (T)minois;
+        } 
+      else *pno = 0;
+      pix++;   pno++;
+      }
+    break;
+  }
+
+return(nois);
+}
+
+
+/* Nouvelle-Fonction */
+template <class T>
+void ImgAddNoise(Image<T>& img, DynCCD const& dyn)
+{
+	T* p = img.ImagePtr();
+	int nPix = img.XSize() * img.YSize();
+	
+	for (int i=0; i<nPix; i++, p++)
+		*p += (T) (dyn.Noise(*p)*NorRand());
+}
+
+
+
+/* Nouvelle-Fonction */
+RzImage * NoiseImage(RzImage const * pim, DynCCD const * dynccd)
+
+/* Creation et Calcul d'une image de bruit a partir de l'image */
+/* pim et de dynccd. Voir la methode DynCCD::Noise() pour la   */
+/* description du calcul                                       */
+{
+RzImage * nois = NULL;
+
+switch (pim->PixelType()) 
+  {
+  case kuint_2: 
+    {
+    ImageU2 pix((RzImage&)(*pim));
+    nois = NoiseImage(&pix, dynccd);
+    break;
+    }
+  case kint_2:
+    {
+    ImageI2 pix((RzImage&)(*pim));
+    nois = NoiseImage(&pix, dynccd);
+    break;
+    }
+  case kint_4:
+    {
+    ImageI4 pix((RzImage&)(*pim));
+    nois = NoiseImage(&pix, dynccd);
+    break;
+    }
+  case kr_4:
+    {
+    ImageR4 pix((RzImage&)(*pim));
+    nois = NoiseImage(&pix, dynccd);
+    break;
+    }  
+  case kuint_4:
+  case kr_8:
+    cerr << "NoiseImage(RzImage, ...) Unsupported image type (kuint_4/kr_8) " 
+         << int(pim->PixelType()) << "\n" ; 
+    break;
+  default:
+    cerr << "NoiseImage(RzImage, ...) Unknown image type !! " << int(pim->PixelType()) << "\n" ;
+    break;
+  }   
+
+return(nois);
+}
+
+
+// ******** INSTANCES
+
+#if defined(__xlC) || defined(__aCC__)
+void instancetempdynccd(int n)
+{
+/* Cette fonction sert uniquement a forcer le compilo a instancier les
+  classes/fonctions template   */
+
+ImageU2  iu2(n,n), *piu2;
+ImageI2  ii2(n,n), *pii2;
+ImageI4  ii4(n,n), *pii4;
+ImageR4  ir4(n,n), *pir4;
+DynCCD dyn(1,0.,65000., 4., 20.);
+
+piu2 = NoiseImage(&iu2, &dyn);
+pii2 = NoiseImage(&ii2, &dyn);
+pii4 = NoiseImage(&ii4, &dyn);
+pir4 = NoiseImage(&ir4, &dyn);
+
+ImgAddNoise(*piu2, dyn);
+ImgAddNoise(*pii2, dyn);
+ImgAddNoise(*pii4, dyn);
+ImgAddNoise(*pir4, dyn);
+
+return;
+}
+#endif
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+
+#pragma define_template NoiseImage<uint_2>
+#pragma define_template NoiseImage<int_2>
+#pragma define_template NoiseImage<int_4>
+#pragma define_template NoiseImage<r_4>
+
+#pragma define_template ImgAddNoise<uint_2>
+#pragma define_template ImgAddNoise<int_2>
+#pragma define_template ImgAddNoise<int_4>
+#pragma define_template ImgAddNoise<r_4>
+
+#endif
+
+
+#if ( defined(ANSI_TEMPLATES) && !defined(__aCC__) )
+template Image<uint_2> * NoiseImage<uint_2>(Image<uint_2> const * , DynCCD const *);
+template Image< int_2> * NoiseImage< int_2>(Image< int_2> const * , DynCCD const *);
+template Image< int_4> * NoiseImage< int_4>(Image< int_4> const * , DynCCD const *);
+template Image<   r_4> * NoiseImage<   r_4>(Image<   r_4> const * , DynCCD const *);
+
+template void ImgAddNoise<uint_2>(Image<uint_2>&, DynCCD const&);
+template void ImgAddNoise< int_2>(Image< int_2>&, DynCCD const&);
+template void ImgAddNoise< int_4>(Image< int_4>&, DynCCD const&);
+template void ImgAddNoise<   r_4>(Image<   r_4>&, DynCCD const&);
+
+#endif
+
+#if defined(__GNU_TEMPLATES__)
+template Image<uint_2> * NoiseImage(Image<uint_2> const *, DynCCD const *);
+template Image< int_2> * NoiseImage(Image< int_2> const *, DynCCD const *);
+template Image< int_4> * NoiseImage(Image< int_4> const *, DynCCD const *);
+template Image<   r_4> * NoiseImage(Image<   r_4> const *, DynCCD const *);
+
+template void ImgAddNoise(Image<uint_2>&, DynCCD const&);
+template void ImgAddNoise(Image< int_2>&, DynCCD const&);
+template void ImgAddNoise(Image< int_4>&, DynCCD const&);
+template void ImgAddNoise(Image<   r_4>&, DynCCD const&);
+
+#endif
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/dynccd.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/dynccd.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/dynccd.h	(revision 752)
@@ -0,0 +1,65 @@
+/*  Caracteristique du CCD      Reza  03/95  -*- C++ -*- */
+
+#ifndef DYNCCD_H_SEEN
+#define DYNCCD_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "ppersist.h"
+
+enum {kConstantNoise = 0, kPhotonNoise, kSigFondNoise, kSqrtADUNoise};
+
+class DynCCD EXC_AWARE
+{
+  public :
+
+  int_4 TypNoise;        // Type de calcul du bruit 
+  float MinADU,MaxADU;   // Valeur min et max des pixels 
+  float Gain;            // Gain en electron/ADU 
+  float RONoise;         // Bruit de lecture en electron  
+  float RefFond;         // Fond de ciel de ref (TypNoise=2) 
+  float RefSFond;        // Sigma du fond  (TypNoise=2) */
+
+/*    ===>  Les methodes   */
+  DynCCD(int typ=0, float min=-9.e19, float max=9.e19,
+         float g=1., float ron=0., float rf=0., float rfs=0.);
+
+  void Set(int typ=0, float min=-9.e19, float max=9.e19,
+         float g=1., float ron=0., float rf=0., float rfs=0.);
+  void Print();
+  float Noise(float pixel) const;
+};
+
+// Quelques fonctions pour manipuler des images de bruit
+
+class RzImage;
+RzImage * NoiseImage(RzImage const *pim, DynCCD const * dynccd);
+
+template <class T> class Image;
+
+template <class T>
+Image<T> * NoiseImage(Image<T> const * pim, DynCCD const * dynccd);
+
+template <class T>
+void ImgAddNoise(Image<T>&, DynCCD const&);
+
+// Les entrees-sortie
+
+inline POutPersist& operator << (POutPersist& c, DynCCD const& data)
+{
+  c.PutI4(data.TypNoise);
+  c.PutR4s(&data.MinADU, 6);
+  return c;
+}
+
+inline 
+PInPersist& operator >> (PInPersist& c, DynCCD& data)
+{
+  c.GetI4(data.TypNoise);
+  c.GetR4s(&data.MinADU, 6);
+  return c;
+}
+
+//STRUCTPERSISTIO(DynCCD, TypNoise, sizeof(int_4)+6*sizeof(float))
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/exclude
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/exclude	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/exclude	(revision 752)
@@ -0,0 +1,1 @@
+
Index: /tags/V_Fev00/SophyaLib/NTools/fct1dfit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fct1dfit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fct1dfit.cc	(revision 752)
@@ -0,0 +1,536 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <math.h>
+#include "fct1dfit.h"
+#include "perrors.h"
+#include "nbconst.h"
+#include "tabmath.h"
+
+//define EXPO exp
+#define EXPO tabFExp
+#define MINEXPM (100.)
+
+//================================================================
+// CLASSES DE FONCTIONS 1D AVEC PARAMETRES POUR LE FIT
+//================================================================
+
+/////////////////////////////////////////////////////////////////
+//++ 
+// Module	Classes de fonctions 1D
+// Lib	Outils++ 
+// include	fct1dfit.h
+//--
+/////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Gauss1DPol
+// \index{Gauss1DPol}
+//
+//|  Gaussienne+polynome:
+//|  Si polcenter=true: xc=(x-par[1]), sinon xc=x
+//|  f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ]
+//|        +par[3] + par[4]*xc + .... + par[3+NDegPol]*xc**NDegPol
+//|  NDegPol = degre du polynome, si <0 pas de polynome
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Gauss1DPol::Gauss1DPol(unsigned int ndegpol,bool polcenter)
+//
+//	Createur.
+//--
+: GeneralFunction(1,ndegpol+4), NDegPol(ndegpol), PolCenter(polcenter)
+{
+}
+
+//++
+Gauss1DPol::Gauss1DPol(bool polcenter)
+//
+//	Createur.
+//--
+: GeneralFunction(1,3), NDegPol(-1), PolCenter(polcenter)
+{
+}
+
+Gauss1DPol::~Gauss1DPol()
+{
+}
+
+double Gauss1DPol::Value(double const xp[], double const* Par)
+{
+double xc = (xp[0]-Par[1])/Par[2];
+double e = 0.5*xc*xc;
+if( e<MINEXPM ) e = EXPO(-e); else e = 0.;
+double f = Par[0]*e;
+
+if(NDegPol>=0) {
+  double xcp = (PolCenter) ? Par[1] : 0.;
+  double xpow = 1.;
+  for(int i=0;i<=NDegPol;i++) {
+    f += Par[3+i]*xpow;
+    xpow *= xp[0]-xcp;
+  }
+}
+return (f);
+}
+
+double Gauss1DPol::Val_Der(double const xp[],double const* Par
+                          ,double *DgDpar)
+{
+
+ double xc = (xp[0]-Par[1])/Par[2];
+ double xc2 = xc*xc;
+ double e = 0.5*xc2;
+ if( e<MINEXPM ) e = EXPO(-e); else e = 0.;
+ double f = Par[0]*e;
+
+ DgDpar[0] = e;
+ DgDpar[1] = xc / Par[2] *f;
+ DgDpar[2] = xc2/ Par[2] *f;
+
+ if(NDegPol>=0) {
+   double xcp = (PolCenter) ? Par[1] : 0.;
+   double xpow = 1.;
+   for(int i=0;i<=NDegPol;i++) {
+     DgDpar[3+i] = xpow;
+     f += Par[3+i]*xpow;
+     if(PolCenter && i<NDegPol) DgDpar[2] += -(i+1)*xpow*Par[4+i];
+     xpow *= xp[0]-xcp;
+   }
+ }
+return f;
+}
+
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	GaussN1DPol
+// \index{GaussN1DPol}
+//
+//| Gaussienne_Normalisee+polynome (par[0]=Volume:
+//|  Si polcenter=true: xc=(x-par[1]), sinon xc=x
+//|  f(x) = par[0]/(sqrt(2*Pi)*par[2])*exp[-0.5*((x-par[1])/par[2])**2 ]
+//|        +par[3] + par[4]*xc + .... + par[3+NDegPol]*xc**NDegPol
+//|  NDegPol = degre du polynome, si <0 pas de polynome
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+GaussN1DPol::GaussN1DPol(unsigned int ndegpol,bool polcenter)
+//
+//	Createur.
+//--
+: GeneralFunction(1,ndegpol+4), NDegPol(ndegpol), PolCenter(polcenter)
+{
+}
+
+//++
+GaussN1DPol::GaussN1DPol(bool polcenter)
+//
+//	Createur.
+//--
+: GeneralFunction(1,3), NDegPol(-1), PolCenter(polcenter)
+{
+}
+
+GaussN1DPol::~GaussN1DPol()
+{
+}
+
+double GaussN1DPol::Value(double const xp[], double const* Par)
+{
+ double xc = (xp[0]-Par[1])/Par[2];
+ double xc2 = xc*xc;
+ double e = 0.5*xc2;
+ if( e<MINEXPM ) e = EXPO(-e)/(S2Pi*Par[2]); else e = 0.;
+ double f = Par[0]*e;
+
+ if(NDegPol>=0) {
+   double xcp = (PolCenter) ? Par[1] : 0.;
+   double xpow = 1.;
+   for(int i=0;i<=NDegPol;i++) {
+     f += Par[3+i]*xpow;
+     xpow *= xp[0]-xcp;
+   }
+ }
+
+return (f);
+}
+
+double GaussN1DPol::Val_Der(double const xp[], double const* Par
+                           , double *DgDpar)
+{
+ double xc = (xp[0]-Par[1])/Par[2];
+ double xc2 = xc*xc;
+ double e = 0.5*xc2;
+ if( e<MINEXPM ) e = EXPO(-e)/(S2Pi*Par[2]); else e = 0.;
+ double f = Par[0]*e;
+
+ DgDpar[0] = e;
+ DgDpar[1] = xc / Par[2] *f;
+ DgDpar[2] = (xc2-1.)/ Par[2] *f;
+
+ if(NDegPol>=0) {
+   double xcp = (PolCenter) ? Par[1] : 0.;
+   double xpow = 1.;
+   for(int i=0;i<=NDegPol;i++) {
+     DgDpar[3+i] = xpow;
+     f += Par[3+i]*xpow;
+     if(PolCenter && i<NDegPol) DgDpar[2] += -(i+1)*xpow*Par[4+i];
+     xpow *= xp[0]-xcp;
+   }
+ }
+
+ return f;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Exp1DPol
+// \index{Exp1DPol}
+//
+//|  Exponentielle+polynome:
+//|  xx = x - X_Center
+//|  f(x) = exp[par[0]+par[1]*xx]
+//|        +par[2] + par[3]*xx + .... + par[2+NDegPol]*xx**NDegPol
+//|  NDegPol = degre du polynome, si <0 pas de polynome
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Exp1DPol::Exp1DPol(unsigned int ndegpol,double x0)
+//
+//	Createur.
+//--
+: GeneralFunction(1,ndegpol+3), NDegPol(ndegpol), X_Center(x0)
+{
+}
+
+//++
+Exp1DPol::Exp1DPol(double x0)
+//
+//	Createur.
+//--
+: GeneralFunction(1,2), NDegPol(-1), X_Center(x0)
+{
+}
+
+Exp1DPol::~Exp1DPol()
+{
+}
+
+double Exp1DPol::Value(double const xp[], double const* Par)
+{
+double xc = Par[0]+Par[1]*(xp[0]-X_Center);
+double f = ( xc>-MINEXPM ) ? EXPO(xc): 0.;
+
+if(NDegPol>=0) {
+  double xpow = 1.;
+  for(int i=0;i<=NDegPol;i++) {
+    f += Par[2+i]*xpow;
+    xpow *= xp[0]-X_Center;
+  }
+}
+return (f);
+}
+
+double Exp1DPol::Val_Der(double const xp[],double const* Par
+                          ,double *DgDpar)
+{
+double xc = Par[0]+Par[1]*(xp[0]-X_Center);
+double f = ( xc>-MINEXPM ) ? EXPO(xc): 0.;
+
+DgDpar[0] = f;
+DgDpar[1] = (xp[0]-X_Center) * f;
+
+if(NDegPol>=0) {
+  double xpow = 1.;
+  for(int i=0;i<=NDegPol;i++) {
+    DgDpar[2+i] = xpow;
+    f += Par[2+i]*xpow;
+    xpow *= xp[0]-X_Center;
+  }
+}
+return f;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Polyn1D
+// \index{Polyn1D}
+//
+//| polynome 1D:
+//|  xx = x - X_Center
+//|  f(x) = par[0] + par[1]*xx + .... + par[NDegPol+1]*xx**NDegPol
+//|  NDegPol = degre du polynome
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Polyn1D::Polyn1D(unsigned int ndegpol,double x0)
+//
+//	Createur.
+//--
+: GeneralFunction(1,ndegpol+1), NDegPol(ndegpol), X_Center(x0)
+{
+}
+
+Polyn1D::~Polyn1D()
+{
+}
+
+double Polyn1D::Value(double const xp[], double const* Par)
+{
+ double xpow = 1.;
+ double f = 0.;
+ for(int i=0;i<=NDegPol;i++) {
+   f += Par[i]*xpow;
+   xpow *= xp[0]-X_Center;
+ }
+ return (f);
+}
+
+double Polyn1D::Val_Der(double const xp[], double const* Par
+                       , double *DgDpar)
+{
+ double xpow = 1.;
+ double f = 0.;
+ for(int i=0;i<=NDegPol;i++) {
+   DgDpar[i] = xpow;
+   f += Par[i]*xpow;
+   xpow *= xp[0]-X_Center;
+ }
+ return f;
+}
+
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	HarmonieNu
+// \index{HarmonieNu}
+//
+//| Analyse harmonique:
+//|  f(t) = par(1) + Sum[par(2k)  *cos(2*pi*k*par(0)*(t-t0)]
+//|                + Sum[par(2k+1)*sin(2*pi*k*par(0)*(t-t0)]
+//|  la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1]
+//|  avec la convention   k=1  pour le fondamental
+//|                       k>1  pour le (k-1)ieme harmonique
+//--
+//++
+//|  par(0) = inverse de la periode (frequence)
+//|  par(1) = terme constant
+//|  par(2), par(3) = termes devant le cosinus et le sinus
+//|                   du fondamental
+//|  par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus
+//|                   et le sinus de l'harmonique m (m>=1).
+//|  NHarm() = nombre d'harmoniques a fitter.
+//|  T0() = centrage des temps, ce n'est pas un parametre du fit.
+//	`Conseil:' Avant de faire un fit avec les `NHarm()'
+//	harmoniques, il est preferable de faire un pre-fit
+//	ou seuls les parametres 1,2 et 3 sont libres et d'injecter
+//	le resultat du fit sur ces 3 parametres comme valeurs
+//	de depart pour le fit global avec les `NHarm()' harmoniques.
+//	De toute facon, le fit ne marchera que si la periode
+//	est initialisee de facon tres precise.
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+HarmonieNu::HarmonieNu(unsigned int nharm,double t0)
+//
+//	Createur.
+//--
+: GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0)
+{
+}
+
+HarmonieNu::~HarmonieNu()
+{
+}
+
+double HarmonieNu::Value(double const xp[], double const* Par)
+{
+ double a = 2.*Pi*(xp[0]-T0)*Par[0];
+ double f = Par[1];
+ for(int k=1;k<=NHarm+1;k++) {
+   // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm
+   f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a);
+ }
+ return f;
+}
+
+double HarmonieNu::Val_Der(double const xp[], double const* Par
+                        , double *DgDpar)
+{
+ double cs,sn;
+ double dadp0 = 2.*Pi*(xp[0]-T0);
+ double a = dadp0*Par[0];
+ double f = Par[1];
+ DgDpar[0] = 0.;
+ DgDpar[1] = 1.;
+ for(int k=1;k<=NHarm+1;k++) {
+   cs = cos(k*a); sn = sin(k*a);
+   f += Par[2*k]*cs + Par[2*k+1]*sn;
+   DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs);
+   DgDpar[2*k]   = cs;
+   DgDpar[2*k+1] = sn;
+ }
+ return f;
+}
+
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	HarmonieT
+// \index{HarmonieT}
+//
+//| Analyse harmonique:
+//|  f(t) = par(1) + Sum[par(2k)  *cos(2*pi*k*(t-t0)/par(0)]
+//|                + Sum[par(2k+1)*sin(2*pi*k*(t-t0)/par(0)]
+//|  la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1]
+//|  avec la convention   k=1  pour le fondamental
+//|                       k>1  pour le (k-1)ieme harmonique
+//--
+//++
+//|  par(0) = periode
+//|  par(1) = terme constant
+//|  par(2), par(3) = termes devant le cosinus et le sinus
+//|                   du fondamental
+//|  par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus
+//|                   et le sinus de l'harmonique m (m>=1).
+//|  NHarm() = nombre d'harmoniques a fitter.
+//|  T0() = centrage des temps, ce n'est pas un parametre du fit.
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+HarmonieT::HarmonieT(unsigned int nharm,double t0)
+//
+//	Createur.
+//--
+: GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0)
+{
+}
+
+HarmonieT::~HarmonieT()
+{
+}
+
+double HarmonieT::Value(double const xp[], double const* Par)
+{
+ double a = 2.*Pi*(xp[0]-T0)/Par[0];
+ double f = Par[1];
+ for(int k=1;k<=NHarm+1;k++) {
+   // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm
+   f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a);
+ }
+ return f;
+}
+
+double HarmonieT::Val_Der(double const xp[], double const* Par
+                        , double *DgDpar)
+{
+ double cs,sn;
+ double dadp0 = 2.*Pi*(xp[0]-T0);
+ double a = dadp0/Par[0];
+ double f = Par[1];
+ DgDpar[0] = 0.;
+ DgDpar[1] = 1.;
+ for(int k=1;k<=NHarm+1;k++) {
+   cs = cos(k*a); sn = sin(k*a);
+   f += Par[2*k]*cs + Par[2*k+1]*sn;
+   DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs)/(-Par[0]*Par[0]);
+   DgDpar[2*k]   = cs;
+   DgDpar[2*k+1] = sn;
+ }
+ return f;
+}
+
+//================================================================
+// CLASSES DE FONCTIONS 2D AVEC PARAMETRES POUR LE FIT
+//================================================================
+
+/////////////////////////////////////////////////////////////////
+//++ 
+// Module	Classes de fonctions 2D
+// Lib	Outils++ 
+// include	fct1dfit.h
+//--
+/////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Polyn2D
+// \index{Polyn2D}
+//
+//| polynome 2D de degre total degre:
+//|  NDegPol = degre du polynome (note N dans la suite)
+//|  x = x - X_Center,  y = y - Y_Center
+//|  f(x,y) = p[0] +sum(k=1,n){ sum(i=0,k){ p[ki]*x^i*y^(k-i) }}
+//|  Il y a k+1 termes de degre k  (ex: x^i*y^(k-i))
+//|  terme de degre k avec x^i: p[ki] avec  ki = k*(k+1)/2 + i
+//| C'est a dire:
+//| deg0:   p0
+//| deg1: + p1*y + p2*x
+//| deg2: + p3*y^2 + p4*x*y + p5*x^2
+//| deg3: + p6*y^3 + p7*x*y^2 + p8*x^2*y + p9*x^3
+//| deg4: + p10*y^4 + p11*x*y^3 + p12*x^2*y^2 + p13*x^3*y + p14*x^4
+//| deg5: + p15*y^5 + ...                       ... + ... + p20*x^5
+//| ...
+//| degk: + p[k*(k+1)/2]*y^k + ...           ... + p[k*(k+3)/2]*x^k
+//| ...
+//| degn: + p[n*(n+1)/2]*y^n + ...           ... + p[n*(n+3)/2]*x^n
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Polyn2D::Polyn2D(unsigned int ndegpol,double x0,double y0)
+//
+//	Createur.
+//--
+: GeneralFunction(2,ndegpol*(ndegpol+3)/2+1), NDegPol(ndegpol), X_Center(x0), Y_Center(y0)
+{
+}
+
+Polyn2D::~Polyn2D()
+{
+}
+
+double Polyn2D::Value(double const xp[], double const* Par)
+{
+ double f = 0.;
+ double xpow = 1.;
+ for(int i=0;i<=NDegPol;i++) { // On gere la puissance x^i i<ndeg
+   int ip;
+   double ypow = 1.;
+   for(int j=0;j<=NDegPol-i;j++) { // On gere la puissance x^j tq degre=i+j<=ndeg
+     ip = (i+j)*(i+j+1)/2+i;
+     f += Par[ip]*xpow*ypow;
+     ypow *= xp[1]-Y_Center;
+   }
+   xpow *= xp[0]-X_Center;
+ }
+ return f;
+}
+
+double Polyn2D::Val_Der(double const xp[], double const* Par
+                       , double *DgDpar)
+{
+ double f = 0.;
+ double xpow = 1.;
+ for(int i=0;i<=NDegPol;i++) { // On gere la puissance x^i i<ndeg
+   int ip;
+   double ypow = 1.;
+   for(int j=0;j<=NDegPol-i;j++) { // On gere la puissance x^j tq degre=i+j<=ndeg
+     ip = (i+j)*(i+j+1)/2+i;
+     DgDpar[ip] = xpow*ypow;
+     f += Par[ip]*DgDpar[ip];
+     ypow *= xp[1]-Y_Center;
+   }
+   xpow *= xp[0]-X_Center;
+ }
+ return f;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fct1dfit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fct1dfit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fct1dfit.h	(revision 752)
@@ -0,0 +1,140 @@
+#ifndef FCT1DFIT_SEEN
+#define FCT1DFIT_SEEN
+
+#include "generalfit.h"
+
+namespace SOPHYA {
+
+//================================================================
+// CLASSES DE FONCTIONS 1D AVEC PARAMETRES POUR LE FIT
+//================================================================
+
+//////////////////////////////////////////////////////////////////
+class Gauss1DPol : public GeneralFunction {
+public:
+  Gauss1DPol(unsigned int ndegpol,bool polcenter=false);
+  Gauss1DPol(bool polcenter=false);
+  virtual ~Gauss1DPol();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NDegP() const {return NDegPol;}
+
+protected:
+  int NDegPol;    // degre du polynome
+  bool PolCenter; // centrage du polynome
+};
+
+//////////////////////////////////////////////////////////////////
+class GaussN1DPol : public GeneralFunction {
+public:
+  GaussN1DPol(unsigned int ndegpol,bool polcenter=false);
+  GaussN1DPol(bool polcenter=false);
+  virtual ~GaussN1DPol();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NDegP() const {return NDegPol;}
+
+protected:
+  int NDegPol;    // degre du polynome
+  bool PolCenter; // centrage du polynome
+};
+
+//////////////////////////////////////////////////////////////////
+class Exp1DPol : public GeneralFunction {
+public:
+  Exp1DPol(unsigned int ndegpol,double x0=0.);
+  Exp1DPol(double x0=0.);
+  virtual ~Exp1DPol();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NDegP() const {return NDegPol;}
+  inline double XCenter() {return X_Center;}
+
+protected:
+  int NDegPol;     // degre du polynome
+  double X_Center; // Centrage en X pour stabilitee
+};
+
+//////////////////////////////////////////////////////////////////
+class Polyn1D : public GeneralFunction {
+public:
+  Polyn1D(unsigned int ndegpol,double x0=0.);
+  virtual ~Polyn1D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NDegP() const {return NDegPol;}
+  inline double XCenter() {return X_Center;}
+
+protected:
+  int NDegPol;     // degre du polynome
+  double X_Center; // Centrage en X pour stabilitee
+};
+
+//////////////////////////////////////////////////////////////////
+class HarmonieNu : public GeneralFunction {
+public:
+  HarmonieNu(unsigned int nharm=0, double t0=0.);
+  virtual ~HarmonieNu();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NHarmonic()  {return NHarm;}
+  inline double  T0Center() const {return T0;}
+  inline double& T0Center()       {return T0;}
+
+protected:
+  int NHarm;
+  double T0;
+};
+
+//////////////////////////////////////////////////////////////////
+class HarmonieT : public GeneralFunction {
+public:
+  HarmonieT(unsigned int nharm=0, double t0=0.);
+  virtual ~HarmonieT();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NHarmonic()  {return NHarm;}
+  inline double  T0Center() const {return T0;}
+  inline double& T0Center()       {return T0;}
+
+protected:
+  int NHarm;
+  double T0;
+};
+
+//================================================================
+// CLASSES DE FONCTIONS 2D AVEC PARAMETRES POUR LE FIT
+//================================================================
+
+//////////////////////////////////////////////////////////////////
+class Polyn2D : public GeneralFunction {
+public:
+  Polyn2D(unsigned int ndegpol,double x0=0.,double y0=0.);
+  virtual ~Polyn2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+  inline int NDegP() const {return NDegPol;}
+
+protected:
+  int NDegPol;     // degre du polynome
+  double X_Center; // Centrage en X pour stabilitee
+  double Y_Center; // Centrage en Y pour stabilitee
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fct2dfit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fct2dfit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fct2dfit.cc	(revision 752)
@@ -0,0 +1,1567 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <math.h>
+#include "fct2dfit.h"
+#include "perrors.h"
+#include "nbconst.h"
+#include "tabmath.h"
+
+// define SIMPSON4  c'etait la prod 91-95 rcecile
+#define SIMPSON9
+#include "simps2d.h"
+
+// define EXPO exp
+#define EXPO tabFExp
+#define MINEXPM (100.)
+
+//================================================================
+// GeneralFunction 2D pour PSF pixel taille 1x1
+//================================================================
+
+/////////////////////////////////////////////////////////////////
+//++
+// Class	GeneralPSF2D
+// Lib	Outils++ 
+// include	fct2dfit.h
+//
+//	Classe de definition d'une PSF 2D a nPar parametres
+//	Pour definir une PSF, il faut creer une classe qui herite
+//	de ``GeneralPSF2D'' (cf par exemple GauRho2D...).
+//	La disposition des parametres definissant la PSF est indifferente,
+//	toutefois il est conseille de suivre l'ordre:
+//--
+//++
+//  - PSF 2D a NPar parametres:
+//  p[0] = Volume (ou hauteur)
+//  p[1] = centre X0, p[2] = centre Y0
+//  p[3] = SigmaX   , p[4] = SigmaY,    p[5] = Rho
+//  p[6],p[7],... = autres parametres (eventuels) definissant la PSF.
+//                  (ex: pour la Moffat p[6] = exposant Beta et NPar=8).
+//  p[NPar-1] = Fond
+//--
+//++
+//	L'emploi de certaines classes comme par exemple ``GenMultiPSF2D''
+//	necessite de suivre rigoureusement l'ordre indique ci-dessus
+//	pour les parametres.
+//--
+
+//++
+GeneralPSF2D::GeneralPSF2D(unsigned int nPar)
+//
+//--
+: GeneralFunction(2,nPar), VolEps(1.e-4)
+{
+ASSERT( nPar>0 );
+}
+
+GeneralPSF2D::~GeneralPSF2D()
+{
+}
+
+//++
+double GeneralPSF2D::ValueH(double const xp[], double const* parm)
+//
+//| ValueH = hauteur*forme(x,y)+fond tq forme(0,0)=1.
+//|     alors que Value = volume*forme(x,y)+fond tq volume(forme)=1.
+//| Dans notre convention le dernier parametre est le fond,
+//| le premier le volume et les 2 suivants le centrage x0,y0
+//| ---> Ici parm[0] = hauteur
+//--
+{
+double x0[2];
+int mm1 = mNPar - 1;
+
+// point central en [x0,y0]
+x0[0] = parm[1];  x0[1] = parm[2];
+
+// retour avec hauteur = 1
+return   (Value(xp,parm) - parm[mm1]) / (Value(x0,parm) - parm[mm1])
+         * parm[0] + parm[mm1];
+}
+
+//++
+double GeneralPSF2D::VolPSF(double const* parm)
+//
+//| Cette fonction calcule le volume d'une PSF de hauteur=1
+//| avec une precision de "VolEps"
+//| dans le but de connaitre le coefficient permettant
+//| de convertir le volume d'une PSF en son amplitude
+//| ou vice-versa: " volume = VolPSF * hauteur "
+//|  L'integration se fait 1/4 de pixel par 1/4 de pixel
+//|  ATTENTION: Il s'agit de PSF donc x,y,x0,y0,Sigma.. sont en pixels
+//--
+{
+ double x[2],step;
+ double vol,volprec;
+ int ecart,i,j,k;
+ int mm1 = mNPar-1;
+
+ step = 1. / 4.;
+ vol = volprec = 0.;
+ ecart = 1;
+
+ /* pixel central */
+ for(k=0;k<nd2d;k++) {
+   x[0] = parm[1] + dx2d[k]*step;
+   x[1] = parm[2] + dy2d[k]*step;
+   vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
+ }
+
+/* increment en couronnes carrees de 2*ecart+1 de cote */
+ while ( ecart < 2 || fabs((vol-volprec)/vol) > VolEps ) {
+   volprec = vol;
+   for (i= -ecart;i<=ecart;i++) for(k=0;k<nd2d;k++) {
+     x[0] = parm[1] + (i+dx2d[k])*step;
+     x[1] = parm[2] + (-ecart+dy2d[k])*step;
+     vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
+     x[1] = parm[2] + ( ecart+dy2d[k])*step;
+     vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
+   }
+   for (j= -ecart+1;j<=ecart-1;j++) for(k=0;k<nd2d;k++) {
+     x[1] = parm[2] + (j+dy2d[k])*step;
+     x[0] = parm[1] + (-ecart+dx2d[k])*step;
+     vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
+     x[0] = parm[1] + ( ecart+dx2d[k])*step;
+     vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
+   }
+   ecart++;
+   // printf("ec=%d v=%f prec=%f %f\n",ecart,vol,fabs((vol-volprec)/vol),VolEps);
+ }
+
+ vol *= step * step / parm[0];
+ return vol;
+}
+
+//++
+void GeneralPSF2D::DefaultParam(double *parm)
+//
+//	Definition des defauts des parametres
+//--
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+}
+
+//++
+void GeneralPSF2D::SetVolEps(double const prec)
+//
+//	Definition de la precision sur le calcul du volume
+//--
+{
+  VolEps = prec;
+}
+
+//================================================================
+// GeneralFunction 2D pour MULTI-PSF pixel taille 1x1
+//================================================================
+
+/////////////////////////////////////////////////////////////////
+//++
+// Class	GenMultiPSF2D
+// Lib	Outils++ 
+// include	fct2dfit.h
+//
+//	Classe de definition d'un ensemble de PSF2D
+//	pour fiter simultanement plusieurs etoiles et un fond constant.
+//	Les parametres de forme de la PSF (Sx, Sy, Rho etc... et Fond)
+//	sont les memes pour toutes les etoiles, seuls le centre
+//	(X0,Y0) et le volume (ou la hauteur) V varient pour chaque etoile.
+//	La disposition des parametres definissant la PSF generique
+//	est obligatoirement la suivante:
+//--
+//++
+//|  - PSF 2D a NPar parametres:
+//|  p[0] = Volume (ou hauteur)
+//|  p[1] = centre X0, p[2] = centre Y0
+//|  p[3] = SigmaX   , p[4] = SigmaY,    p[5] = Rho
+//|  p[6],p[7],... = autres parametres (eventuels) definissant la PSF.
+//|                  (ex: pour la Moffat p[6] = exposant Beta et NPar=8).
+//|  p[NPar-1] = Fond
+//|
+//--
+//++
+//|  - La Multi-PSF a ses parametres arranges dans l'ordre suivant:
+//|    Soit NStar le nombre d'etoiles a fiter simultanement
+//|         NP = le nombre de parametres de la PSF 2D generique
+//|    On a NF = NP-7 parametres de forme supplementaires
+//|         (ex: nf=0 pour GauRho2D, nf=1 pour MofRho2D)
+//|  p[0],p[1],p[2] = V0,X0,Y0 pour la premiere etoile
+//|  p[3],p[4],p[5] = V1,X1,Y1 pour la deuxieme etoile
+//|  ...
+//|  p[3*i],p[3*i+1],p[3*i+2] = Vi,Xi,Yi pour la (i+1) ieme etoile
+//|  ...
+//|  p[m*i],p[m*i+1],p[m*i+2] = Vm,Xm,Ym   ;   m = NStar-1
+//|                       pour la NStar ieme et derniere etoile
+//|  p[3*NStar],p[3*NStar+1],p[3*NStar+2] = SigmaX, SigmaY et Rho
+//|  p[3*NStar+3],...,p[3*NStar+2+NF] = parametres de forme
+//|                        supplementaires pour definir la PSF 2D
+//|  p[3*NStar+2+NF+1] = Fond
+//--
+
+//++
+GenMultiPSF2D::GenMultiPSF2D(GeneralPSF2D* psf2d,unsigned int nstar)
+//
+//	Createur. ``psf2d'' est le nom de la PSF generique a utiliser,
+//	et ``nstar'' est le nombre d'etoiles a fiter simultanement.
+//--
+  : GeneralPSF2D((psf2d!=NULL) ? 3*nstar+4+psf2d->NPar()-7: 0)
+  , mPsf2D(psf2d), mNStar(nstar)
+{
+ASSERT( nstar>0 && psf2d!=NULL );
+mNForme = mPsf2D->NPar() - 7;
+ASSERT( mNForme>=0 );
+mNParm = mPsf2D->NPar();
+mParm = new double[mNParm];
+mDer = new double[mNParm];
+mNParmTot = GeneralPSF2D::NPar();
+cout<<"mNStar="<<mNStar<<" mNParmTot="<<mNParmTot
+    <<" mNParm="<<mNParm<<" mNForme="<<mNForme<<endl;
+}
+
+GenMultiPSF2D::~GenMultiPSF2D()
+{
+delete [] mParm; mParm = NULL;
+delete [] mDer;  mDer = NULL;
+}
+
+double GenMultiPSF2D::Value(double const xp[], double const* Par)
+{
+// Fond commun
+double val = Par[mNParmTot-1];
+
+// Remplissage le tableau des parametres pour la PSF generique
+// ... Communs a toutes les PSF individuelles: Sx,Sy,Rho,[Forme],Fond
+const double *pt = &Par[3*mNStar];
+double *p = &mParm[3];
+{for(int i=0;i<3+mNForme;i++) *(p++) = *(pt++);}  // Sx,Sy,Rho,[Forme...]
+*(p++) = 0.;   // Fond
+
+// ... Propres a chaque etoiles: Vi,Xi,Yi
+pt = Par;
+{for(int i=0;i<mNStar;i++) {
+  mParm[0] = *(pt++);  // Vi (ou Hi)
+  mParm[1] = *(pt++);  // Xi
+  mParm[2] = *(pt++);  // Yi
+  val += mPsf2D->Value(xp,mParm);
+}}
+
+return val;
+}
+
+double GenMultiPSF2D::Val_Der(double const xp[], double const* Par
+                             ,double *DgDpar)
+{
+{for(int i=3*mNStar;i<mNParmTot-1;i++) DgDpar[i] = 0.;}
+
+// Fond commun
+double val = Par[mNParmTot-1];
+DgDpar[mNParmTot-1] = 1.;  // D./DFond
+
+// Remplissage le tableau des parametres pour la PSF generique
+// ... Communs a toutes les PSF individuelles: Sx,Sy,Rho,[Forme],Fond
+const double *pt = &Par[3*mNStar];
+double *p = &mParm[3];
+{for(int i=0;i<3+mNForme;i++) *(p++) = *(pt++);}  // Sx,Sy,Rho,[Forme...]
+*(p++) = 0.;   // Fond
+
+// ... Propres a chaque etoiles: Vi,Xi,Yi
+double *dpt = DgDpar, *dpt2 = &DgDpar[3*mNStar];
+pt = Par;
+{for(int i=0;i<mNStar;i++) {
+  mParm[0] = *(pt++);  // Vi (ou Hi)
+  mParm[1] = *(pt++);  // Xi
+  mParm[2] = *(pt++);  // Yi
+  val += mPsf2D->Val_Der(xp,mParm,mDer);
+  {for(int j=0;j<3;j++) *(dpt++) = mDer[j];}  // D./DVi,D./DXi,D./DYi
+  {for(int j=0;j<3+mNForme;j++) *(dpt2+j) += mDer[3+j];} // D./DSx,D./DSy,D./DRho,[D./DForme]
+}}
+
+return val;
+}
+
+//==============================================================================
+// CLASSES DE FONCTIONS 2D type PSF AVEC PARAMETRES POUR LE FIT pixel taille 1x1
+// la taille du pixel est importante quand on utilise les PSF integrees
+//    (x,y x0,y0 sigmaX.... sont en unites de pixels !!!)
+//==============================================================================
+
+#define _x0_   Par[1]
+#define _y0_   Par[2]
+#define _sigx_ Par[3]
+#define _sigy_ Par[4]
+#define _rho_  Par[5]
+#define _Gm_   Par[6]
+#define _B4_   Par[6]
+#define _B6_   Par[7]
+#define _B2_   Par[8]
+
+/////////////////////////////////////////////////////////////////
+//++ 
+// Module	Classes de PSF 2D
+// Lib	Outils++ 
+// include	fct2dfit.h
+//--
+/////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	GauRho2D
+// \index{GauRho2D}
+//
+//| gaussienne+fond 2D
+//| Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=fond
+//|   sigx,sigy,rho = sigma et rho de la gaussienne
+//|   x0,y0 = centre de la gaussienne
+//|  PSF(x,y) = N * exp[ - 1/2 (X**2 + Y**2 -2*rho*X*Y) ]
+//|           avec X = (x-x0)/sigx et Y = (y-y0)/sigy
+//|                N = sqrt(1-rho**2)/(2*Pi*sigx*sigy)
+//|  le volume de cette gaussienne est V=1.
+//|  F(x,y) = Par[0]*PSF(x,y)+Par[6] (volume=Par[0],fond=Par[6])
+//--
+//++
+//| -*- Remarque: De la facon dont est ecrite la PSF gaussienne
+//| sigx,sigy representent les sigmas des gaussiennes 1D
+//| qui sont les coupes de la gaussienne 2D pour y=0 et x=0.
+//| Les moments centres d'ordre 2 sont
+//|   sx = sigx/sqrt(1-ro^2) et sy = sigy/sqrt(1-ro^2)
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+GauRho2D::GauRho2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(7)
+{
+}
+
+GauRho2D::~GauRho2D()
+{
+}
+
+double GauRho2D::Value(double const xp[], double const* Par)
+{
+ double N = sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ if( z2<MINEXPM ) return Par[0] * N*EXPO(-z2) + Par[6];
+   else return Par[6];
+}
+
+double GauRho2D::ValueH(double const xp[], double const* Par)
+{
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ //double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ double z2 = 0.5*(X-Y)*(X-Y) - (_rho_ - 1)*X*Y;
+ if( z2<MINEXPM ) return Par[0] * EXPO(-z2) + Par[6];
+   else return Par[6];
+}
+
+double GauRho2D::VolPSF(double const* Par)
+{
+ return DeuxPi * _sigx_ * _sigy_ / sqrt(1.-_rho_*_rho_);
+}
+
+double GauRho2D::Val_Der(double const xp[], double const* Par
+                        , double *DgDpar)
+{
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+
+ double XmrY = X-_rho_*Y;
+ double YmrX = Y-_rho_*X;
+ double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+
+ /* g(x,y) */
+ double PSF = 0.;
+ if( z2<MINEXPM ) PSF = N * EXPO(-z2);
+ /* dg(x,y)/d(x0) */
+ DgDpar[1] =  Par[0]* PSF* XmrY/_sigx_;
+ /* dg(x,y)/d(y0) */
+ DgDpar[2] =  Par[0]* PSF* YmrX/_sigy_;
+ /* dg(x,y)/d(sx)*/
+ DgDpar[3] =  Par[0]* PSF* (X*XmrY-1.)/_sigx_;
+ /* dg(x,y)/d(sy) */
+ DgDpar[4] =  Par[0]* PSF* (Y*YmrX-1.)/_sigy_;
+ /* dg(x,y)/d(rho) */
+ DgDpar[5] =  Par[0]* PSF* (X*Y-2.*_rho_/unmr2);
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = PSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[6] = 1.;
+
+ return Par[0] * PSF + Par[6];
+}
+
+void GauRho2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+}
+
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	GauRhInt2D
+// \index{GauRhInt2D}
+//
+//| Cette fonction calcule une approximation a l'integrale d'une
+//| gaussienne 2D sur un carre de longueur unite (x,y-05 -> x,y+0.5)
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+GauRhInt2D::GauRhInt2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(7)
+{
+}
+
+GauRhInt2D::~GauRhInt2D()
+{
+}
+
+double GauRhInt2D::Value(double const xp[], double const* Par)
+{
+ double N = sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF = 0.;
+ double X,Y,z2;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
+ }
+ return Par[0]* N*SPSF + Par[6];
+}
+
+double GauRhInt2D::ValueH(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF = 0.;
+ double X,Y,z2;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
+ }
+ return Par[0] *SPSF + Par[6];
+}
+
+double GauRhInt2D::VolPSF(double const* Par)
+{
+ return DeuxPi * _sigx_ * _sigy_ / sqrt(1.-_rho_*_rho_);
+}
+
+double GauRhInt2D::Val_Der(double const xp[], double const* Par
+                          ,double *DgDpar)
+{
+ for(int i=0; i<=6; i++) DgDpar[i] = 0.;
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+
+ double z2,PSF,X,Y,XmrY,YmrX;
+ double SPSF = 0.;
+ {
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   XmrY = X-_rho_*Y;
+   YmrX = Y-_rho_*X;
+   z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+   /* g(x,y) */
+   if(z2<MINEXPM) PSF = N * EXPO(-z2) * w2d[i]; else PSF = 0.;
+   SPSF += PSF;
+   /* dg(x,y)/d(x0) */
+   DgDpar[1] += Par[0] * PSF* XmrY/_sigx_;
+   /* dg(x,y)/d(y0) */
+   DgDpar[2] += Par[0] * PSF* YmrX/_sigy_;
+   /* dg(x,y)/d(sx)*/
+   DgDpar[3] += Par[0] * PSF* (X*XmrY-1.)/_sigx_;
+   /* dg(x,y)/d(sy) */
+   DgDpar[4] += Par[0] * PSF* (Y*YmrX-1.)/_sigy_;
+   /* dg(x,y)/d(rho) */
+   DgDpar[5] += Par[0] * PSF* (X*Y-2.*_rho_/unmr2);
+ }
+ }
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = SPSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[6] = 1.;
+
+ return Par[0] *SPSF + Par[6];
+}
+
+void GauRhInt2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+}
+
+#define B4 1.
+#define B6 1.
+#define KB4B6 0.136887
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	GdlRho2D
+// \index{GdlRho2D}
+//
+//| Cette fonction calcule une gaussienne 2D de volume 1 approchee
+//|  par son developpement limite au 3ieme ordre (see dophot)
+//|  Meme commentaire que GauRho2D, cf plus haut sauf que:
+//|  Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=fond
+//|    z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
+//|    PSF(x,y) = N / [ 1 + z**2 + B4/2 *z**4 + B6/6 *z**6 ]
+//|               N = KB4B6
+//|    le coefficient KB4B6 etant trop dur a calculer analytiquement
+//|    Il doit etre calcule numeriquement et entre dans ce programme
+//|  ATTENTION: dans cette routine B4 et B6 sont imposes et pas fites!
+//|  - DL de la gaussienne:  B4=1., B6=1., KB4B6=0.13688679
+//|  le volume de cette gaussienne est V=1.
+//|  F(x,y) = Par[0]*PSF(x,y)+Par[6] (volume=Par[0],fond=Par[6])
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+GdlRho2D::GdlRho2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(7)
+{
+}
+
+GdlRho2D::~GdlRho2D()
+{
+}
+
+double GdlRho2D::Value(double const xp[], double const* Par)
+{
+ double N = KB4B6*sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_);
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+ return Par[0] *N/D + Par[6];
+}
+
+double GdlRho2D::ValueH(double const xp[], double const* Par)
+{
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+ return Par[0] /D + Par[6];
+}
+
+double GdlRho2D::VolPSF(double const* Par)
+{
+ return _sigx_*_sigy_/(KB4B6*sqrt(1.-_rho_*_rho_));
+}
+
+double GdlRho2D::Val_Der(double const xp[], double const* Par
+                        , double *DgDpar)
+{
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = KB4B6*sqrt(unmr2)/(_sigx_*_sigy_);
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double XmrY = X-_rho_*Y;
+ double YmrX = Y-_rho_*X;
+ double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+ double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+ double dDsD = (1.+z2*(B4+B6/2.*z2))/D;
+
+ /* g(x,y) */
+ double PSF = N / D;
+ /* dg(x,y)/d(x0) */
+ DgDpar[1] = Par[0]* PSF* dDsD*XmrY/_sigx_;
+ /* dg(x,y)/d(y0) */
+ DgDpar[2] = Par[0]* PSF* dDsD*YmrX/_sigy_;
+ /* dg(x,y)/d(sx)*/
+ DgDpar[3] = Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+ /* dg(x,y)/d(sy) */
+ DgDpar[4] = Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+ /* dg(x,y)/d(rho) */
+ DgDpar[5] = Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = PSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[6] = 1.;
+
+ return Par[0] *PSF + Par[6];
+}
+
+void GdlRho2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+}
+
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	GdlRhInt2D
+// \index{GdlRhInt2D}
+//
+//	fonction integree de  GdlRho2d
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+GdlRhInt2D::GdlRhInt2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(7)
+{
+}
+
+GdlRhInt2D::~GdlRhInt2D()
+{
+}
+
+double GdlRhInt2D::Value(double const xp[], double const* Par)
+{
+ double N = KB4B6*sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+
+ double z2,X,Y,D;
+ double SPSF = 0.;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+   SPSF += w2d[i] / D;
+  }
+ return Par[0] *N*SPSF + Par[6];
+}
+
+double GdlRhInt2D::ValueH(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+
+ double z2,X,Y,D;
+ double SPSF = 0.;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+   SPSF += w2d[i] / D;
+  }
+ return Par[0] *SPSF + Par[6];
+}
+
+double GdlRhInt2D::VolPSF(double const* Par)
+{
+ return _sigx_*_sigy_/(KB4B6*sqrt(1.-_rho_*_rho_));
+}
+
+double GdlRhInt2D::Val_Der(double const xp[], double const* Par
+                          , double *DgDpar)
+{
+ for(int i=0; i<=6; i++) DgDpar[i] = 0.;
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = KB4B6*sqrt(unmr2)/(_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+
+ double z2,PSF,X,Y,XmrY,YmrX,D,dDsD;
+ double SPSF = 0.;
+ {
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   XmrY = X-_rho_*Y;
+   YmrX = Y-_rho_*X;
+   z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+   D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
+   dDsD = (1.+z2*(B4+B6/2.*z2))/D;
+   /* g(x,y) */
+   PSF = N / D  * w2d[i];
+   SPSF += PSF;
+   /* dg(x,y)/d(x0) */
+   DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
+   /* dg(x,y)/d(y0) */
+   DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
+   /* dg(x,y)/d(sx)*/
+   DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+   /* dg(x,y)/d(sy) */
+   DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+   /* dg(x,y)/d(rho) */
+   DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+ }
+ }
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = SPSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[6] = 1.;
+
+ return Par[0] *SPSF + Par[6];
+}
+
+void GdlRhInt2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+}
+
+#undef B4
+#undef B6
+#undef KB4B6
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Gdl1Rho2D
+// \index{Gdl1Rho2D}
+//
+//| Cette fonction calcule une gaussienne 2D approchee
+//| par son developpement limite au 2sd ordre (see dophot)
+//| Meme commentaire que GauRho2D, cf plus haut sauf que:
+//|   z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
+//|   PSF(x,y) = N / [ 1 + z**2 + B4/2 *z**4 ]
+//|   Le coefficient B4 est fitte (6ieme parametres)
+//| ATTENTION: les normalisations N dependent de B4
+//|  1-/ B4 est suppose etre toujours positif pour que la PSF tendent
+//|      vers 0+ quand z2 tend vers l'infini
+//|  2-/ Il y a 3 cas de calcul de K(B4) = int(PSF(x,y)) de 0 a l'infini
+//|             0<B4<1/2, 1/2<B4, et B4=1/2
+//|      mais pour des raisons d'analyse
+//|      numerique j'ai pris 3 intervalles:
+//|             0.<B4<0.499, 0.501<B4, 0.499<=B4<=0.501
+//|      dans le 3ieme intervalle, comme K est continue est derivable
+//|      en B4=1/2, j'ai represente K par la droite tangeante
+//|      ce qui, apres verification dans paw est une tres bonne approx.
+//|      (je tiens les calculs a disposition.. me demander)
+//|  Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=B4 [7]=fond
+//|  F(x,y) = Par[0]*PSF(x,y)+Par[7]
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Gdl1Rho2D::Gdl1Rho2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(8)
+{
+}
+
+Gdl1Rho2D::~Gdl1Rho2D()
+{
+}
+
+double Gdl1Rho2D::Value(double const xp[], double const* Par)
+{
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   return(0.);
+ }
+ double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
+
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ double D = 1.+z2*(1.+z2*_B4_/2.);
+ return Par[0] *N/D + Par[7];
+}
+
+double Gdl1Rho2D::ValueH(double const xp[], double const* Par)
+{
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+ double D = 1.+z2*(1.+z2*_B4_/2.);
+ return Par[0] /D + Par[7];
+}
+
+double Gdl1Rho2D::VolPSF(double const* Par)
+{
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   return(0.);
+ }
+ double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
+ return 1./N;
+}
+
+double Gdl1Rho2D::Val_Der(double const xp[], double const* Par
+                         , double *DgDpar)
+{
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   for(int i=0;i<=7;i++) DgDpar[i] = 0.;
+   return(0.);
+ }
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = sqrt(unmr2)/(_sigx_*_sigy_*DeuxPi*K);
+
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double XmrY = X-_rho_*Y;
+ double YmrX = Y-_rho_*X;
+ double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+ double D = 1.+z2*(1.+z2*_B4_/2.);
+ double dDsD = (1.+z2*_B4_)/D;
+
+ /* g(x,y) */
+ double PSF = N / D;
+ /* dg(x,y)/d(x0) */
+ DgDpar[1] =  Par[0]* PSF* dDsD*XmrY/_sigx_;
+ /* dg(x,y)/d(y0) */
+ DgDpar[2] =  Par[0]* PSF* dDsD*YmrX/_sigy_;
+ /* dg(x,y)/d(sx)*/
+ DgDpar[3] =  Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+ /* dg(x,y)/d(sy) */
+ DgDpar[4] =  Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+ /* dg(x,y)/d(rho) */
+ DgDpar[5] =  Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+ /* dg(x,y)/d(B4) */
+ DgDpar[6] =  Par[0]* PSF* (-dKdB4/K-z2*z2/2./D);
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = PSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[7] = 1.;
+
+ return Par[0] *PSF + Par[7];
+}
+
+void Gdl1Rho2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = 1.;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Gdl1RhInt2D
+// \index{Gdl1RhInt2D}
+//
+//	fonction integree de Gdl1Rho2D
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Gdl1RhInt2D::Gdl1RhInt2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(8)
+{
+}
+
+Gdl1RhInt2D::~Gdl1RhInt2D()
+{
+}
+
+double Gdl1RhInt2D::Value(double const xp[], double const* Par)
+{
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   return(0.);
+ }
+ double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
+
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF=0.;
+ double z2,X,Y,D;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
+   D = 1.+z2*(1.+z2*_B4_/2.);
+   SPSF += w2d[i] / D;
+ }
+ return Par[0] *N*SPSF + Par[7];
+}
+
+double Gdl1RhInt2D::ValueH(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF=0.;
+ double z2,X,Y,D;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
+   D = 1.+z2*(1.+z2*_B4_/2.);
+   SPSF += w2d[i] / D;
+ }
+ return Par[0] *SPSF + Par[7];
+}
+
+double Gdl1RhInt2D::VolPSF(double const* Par)
+{
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   return(0.);
+ }
+ double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
+ return 1./N;
+}
+
+double Gdl1RhInt2D::Val_Der(double const xp[], double const* Par
+                           , double *DgDpar)
+{
+ for(int i=0; i<7; i++) DgDpar[i] = 0.;
+
+ double K,W,V,dKdB4;
+ if ( 0. < _B4_ && _B4_ < 0.499 ) {
+   V = 1.-2.*_B4_;
+   W = sqrt(V);
+   K = -log( (1.-W)/(1.+W) )/W;
+   dKdB4 = ( K-2./(1.-V) )/V;
+ } else if ( 0.501 < _B4_ ) {
+   V = 1./(2.*_B4_-1.);
+   W = sqrt(V);
+   K = 2.*W*( Pi/2.-atan(W) );
+   dKdB4 = V*( 2.*V/(1.+V) - K );
+ } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
+   dKdB4 = -4./3.;
+   K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
+ } else {
+   return(0.);
+ }
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = sqrt(unmr2)/(_sigx_*_sigy_*DeuxPi*K);
+
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double z2,PSF,X,Y,XmrY,YmrX,D,dDsD;
+ double SPSF=0.;
+ {for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   XmrY = X-_rho_*Y;
+   YmrX = Y-_rho_*X;
+   z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+   D = 1.+z2*(1.+z2*_B4_/2.);
+   dDsD = (1.+z2*_B4_)/D;
+   /* dg(x,y) */
+   PSF = N / D  * w2d[i];
+   SPSF += PSF;
+   /* dg(x,y)/d(x0) */
+   DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
+   /* dg(x,y)/d(y0) */
+   DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
+   /* dg(x,y)/d(sx)*/
+   DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+   /* dg(x,y)/d(sy) */
+   DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+   /* dg(x,y)/d(rho) */
+   DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+   /* dg(x,y)/d(B4) */
+   DgDpar[6] += Par[0]* PSF* (-dKdB4/K-z2*z2/2./D);
+ }}
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = SPSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[7] = 1.;
+
+ return Par[0] *SPSF + Par[7];
+}
+
+void Gdl1RhInt2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = 1.;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Gdl2Rho2D
+// \index{Gdl2Rho2D}
+//
+//| Cette fonction calcule une gaussienne 2D de hauteur 1 approchee
+//| par son developpement limite ordre 3 (see dophot)
+//| Meme commentaire que GauRho2D, cf plus haut sauf que:
+//|   z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
+//|   Z**2 = B2*z2
+//|   PSF(x,y) = h / [ 1 + Z**2 + B4**2/2 *Z**4 + B6**2/6 *Z**6 ]
+//|   B2,B4,B6 peuvent etre fittes
+//| - DL de la gaussienne:  B2=B4=B6=1.
+//|  Par [0]=hauteur [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho
+//|      [6]=B4 [7]=B6 [8]=B2 [9]= fond
+//|  F(x,y) = Par[0]*PSF(x,y)+Par[9]
+//--
+/////////////////////////////////////////////////////////////////
+
+
+//++
+Gdl2Rho2D::Gdl2Rho2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(10)
+{
+}
+
+Gdl2Rho2D::~Gdl2Rho2D()
+{
+}
+
+double Gdl2Rho2D::Value(double const xp[], double const* Par)
+{
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2*_rho_*X*Y)/2.;
+ double Z2 = _B2_ * _B2_ * z2;
+ double Z4 = Z2*Z2;
+ double Z6 = Z4*Z2;
+ double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+ return Par[0] /D + Par[9];
+}
+
+double Gdl2Rho2D::ValueH(double const xp[], double const* Par)
+{
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double z2 = (X*X + Y*Y - 2*_rho_*X*Y)/2.;
+ double Z2 = _B2_ * _B2_ * z2;
+ double Z4 = Z2*Z2;
+ double Z6 = Z4*Z2;
+ double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+ return Par[0] /D + Par[9];
+}
+
+double Gdl2Rho2D::Val_Der(double const xp[], double const* Par
+                         , double *DgDpar)
+{
+ double unmr2 = 1.-_rho_*_rho_;
+ double X = (xp[0]-_x0_)/_sigx_;
+ double Y = (xp[1]-_y0_)/_sigy_;
+ double XmrY = X-_rho_*Y;
+ double YmrX = Y-_rho_*X;
+ double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+ double Z2 = _B2_ * _B2_ * z2;
+ double Z4 = Z2*Z2;
+ double Z6 = Z4*Z2;
+ double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+ double dDsDB2 = (1. + _B4_*_B4_*Z2    + _B6_*_B6_/2.*Z4 )/D;
+ double dDsD = _B2_*_B2_ * dDsDB2;
+ /* g(x,y) */
+ double PSF = 1. / D;
+ /* dg(x,y)/d(x0) */
+ DgDpar[1] = Par[0]* PSF* dDsD*XmrY/_sigx_;
+ /* dg(x,y)/d(y0) */
+ DgDpar[2] = Par[0]* PSF* dDsD*YmrX/_sigy_;
+ /* dg(x,y)/d(sx)*/
+ DgDpar[3] = Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+ /* dg(x,y)/d(sy) */
+ DgDpar[4] = Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+ /* dg(x,y)/d(rho) */
+ DgDpar[5] = Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+ /* dg(x,y)/d(B4) */
+ DgDpar[6] = Par[0]* PSF* (-_B4_*Z4/D);
+ /* dg(x,y)/d(B6) */
+ DgDpar[7] = Par[0]* PSF* (-_B6_*Z6/3./D);
+ /* dg(x,y)/d(B2)  */
+ DgDpar[8] = Par[0]* PSF* (-2.*_B2_*z2*dDsDB2);
+ /* dg(x,y)/d(hauteur) */
+ DgDpar[0] = PSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[9] = 1.;
+
+ return Par[0] *PSF + Par[9];
+}
+
+void Gdl2Rho2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = parm[7] = parm[8] = 1.;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	Gdl2RhInt2D
+// \index{Gdl2RhInt2D}
+//
+//	fonction integree de Gdl2Rho2d
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+Gdl2RhInt2D::Gdl2RhInt2D()
+//
+//	Createur
+//--
+: GeneralPSF2D(10)
+{
+}
+
+Gdl2RhInt2D::~Gdl2RhInt2D()
+{
+}
+
+double Gdl2RhInt2D::Value(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF=0.;
+ double X,Y,z2,Z2,Z4,Z6,D;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   Z2 = _B2_ * _B2_ * z2;
+   Z4 = Z2*Z2;
+   Z6 = Z4*Z2;
+   D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+   /* g(x,y) */
+   SPSF += w2d[i] / D;
+ }
+ return Par[0] *SPSF + Par[9];
+}
+
+double Gdl2RhInt2D::ValueH(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF=0.;
+ double X,Y,z2,Z2,Z4,Z6,D;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   Z2 = _B2_ * _B2_ * z2;
+   Z4 = Z2*Z2;
+   Z6 = Z4*Z2;
+   D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+   /* g(x,y) */
+   SPSF += w2d[i] / D;
+ }
+ return Par[0] *SPSF + Par[9];
+}
+
+double Gdl2RhInt2D::Val_Der(double const xp[], double const* Par
+                           , double *DgDpar)
+{
+ for(int i=0; i<=9; i++) DgDpar[i] = 0.;
+
+ double unmr2 = 1.-_rho_*_rho_;
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF=0.;
+ double X,Y,XmrY,YmrX,z2,Z2,Z4,Z6,D,dDsD,dDsDB2,PSF;
+ {for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   XmrY = X-_rho_*Y;
+   YmrX = Y-_rho_*X;
+   z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+   Z2 = _B2_ * _B2_ * z2;
+   Z4 = Z2*Z2;
+   Z6 = Z4*Z2;
+   D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
+   dDsDB2 = (1. + _B4_*_B4_*Z2    + _B6_*_B6_/2.*Z4 )/D;
+   dDsD = _B2_*_B2_ * dDsDB2;
+   /* dg(x,y) */
+   PSF = w2d[i] / D;
+   SPSF += PSF;
+   /* dg(x,y)/d(x0) */
+   DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
+   /* dg(x,y)/d(y0) */
+   DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
+   /* dg(x,y)/d(sx)*/
+   DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
+   /* dg(x,y)/d(sy) */
+   DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
+   /* dg(x,y)/d(rho) */
+   DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
+   /* dg(x,y)/d(B4) */
+   DgDpar[6] += Par[0]* PSF* (-_B4_*Z4/D);
+   /* dg(x,y)/d(B6) */
+   DgDpar[7] += Par[0]* PSF* (-_B6_*Z6/3./D);
+   /* dg(x,y)/d(B2)  */
+   DgDpar[8] += Par[0]* PSF* (-2.*_B2_*z2*dDsDB2);
+ }}
+ /* dg(x,y)/d(hauteur) */
+ DgDpar[0] = SPSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[9] = 1.;
+
+ return Par[0] *SPSF + Par[9];
+}
+
+void Gdl2RhInt2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = parm[7] = parm[8] = 1.;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	MofRho2D
+// \index{MofRho2D}
+//
+//| Cette fonction calcule une Moffat 2D
+//|   Par [0]=hauteur [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho
+//|       [6]=Gm [7]= fond
+//|  PSF(x,y)  = valeur de la Moffat normalisee a un volume = 1
+//|  PSF(x,y) = N / [ 1. +  0.5*(X**2 + Y**2 -2*rho*X*Y) ]**Gm
+//|           avec X = (x-x0)/sigx et Y = (y-y0)/sigy et Gm>1
+//|                N = (1-Gm)*sqrt(1-rho**2)/(2*Pi*sigx*sigy)
+//|  le volume de cette Moffat est V=1.
+//|  F(x,y) = Par[0]*PSF(x,y)+Par[7]
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+MofRho2D::MofRho2D()
+//
+//	Createur 
+//--
+: GeneralPSF2D(8)
+{
+}
+
+MofRho2D::~MofRho2D()
+{
+}
+
+double MofRho2D::Value(double const xp[], double const* Par)
+{
+ double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
+ z2 = _Gm_*log(1. + z2);
+ if( z2<MINEXPM ) return Par[0] *N*EXPO(-z2) + Par[7];
+    else return Par[7];
+}
+
+double MofRho2D::ValueH(double const xp[], double const* Par)
+{
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
+ z2 = _Gm_*log(1. + z2);
+ if( z2<MINEXPM ) return Par[0] *EXPO(-z2) + Par[7];
+    else return Par[7];
+}
+
+double MofRho2D::VolPSF(double const* Par)
+{
+ double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ return 1./N;
+}
+
+double MofRho2D::Val_Der(double const xp[], double const* Par
+                        , double *DgDpar)
+{
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = (_Gm_-1.)*sqrt(unmr2)/DeuxPi/_sigx_/_sigy_;
+ double X = (xp[0] - _x0_)/_sigx_;
+ double Y = (xp[1] - _y0_)/_sigy_;
+ double XmrY = X-_rho_*Y;
+ double YmrX = Y-_rho_*X;
+ double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+ double D = 1. + z2;
+ double lD = log(D);
+ /* g(x,y) */
+ double PSF = _Gm_*lD;
+ if( PSF<MINEXPM ) PSF = N * EXPO(-PSF); else PSF = 0.;
+ /* dg(x,y)/d(x0) */
+ DgDpar[1] = Par[0]* PSF* XmrY/_sigx_ * _Gm_/D;
+ /* dg(x,y)/d(y0) */
+ DgDpar[2] = Par[0]* PSF* YmrX/_sigy_ * _Gm_/D;
+ /* dg(x,y)/d(sx)*/
+ DgDpar[3] = Par[0]* PSF* (X*XmrY*_Gm_/D - 1.)/_sigx_;
+ /* dg(x,y)/d(sy) */
+ DgDpar[4] = Par[0]* PSF* (Y*YmrX*_Gm_/D - 1.)/_sigy_;
+ /* dg(x,y)/d(rho) */
+ DgDpar[5] = Par[0]* PSF* (X*Y*_Gm_/D - 2.*_rho_/unmr2);
+ /* dg(x,y)/d(Gm) */
+ DgDpar[6] = Par[0]* PSF* (1./(_Gm_-1.) - lD);
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = PSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[7] = 1.;
+
+ return Par[0] *PSF + Par[7];
+}
+
+void MofRho2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = 3.;
+}
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	MofRhInt2D
+// \index{MofRhInt2D}
+//
+//	fonction integree de MofRho2d
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+MofRhInt2D::MofRhInt2D()
+//
+//	Createur 
+//--
+: GeneralPSF2D(8)
+{
+}
+
+MofRhInt2D::~MofRhInt2D()
+{
+}
+
+double MofRhInt2D::Value(double const xp[], double const* Par)
+{
+ double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF = 0.;
+ double z2,X,Y;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   /* g(x,y) */
+   z2  = _Gm_*log(1. + z2);
+   if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
+ }
+ return Par[0] * N*SPSF + Par[7];
+}
+
+double MofRhInt2D::ValueH(double const xp[], double const* Par)
+{
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF = 0.;
+ double z2,X,Y;
+ for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
+   /* g(x,y) */
+   z2  = _Gm_*log(1. + z2);
+   if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
+ }
+ return Par[0] *SPSF + Par[7];
+}
+
+double MofRhInt2D::VolPSF(double const* Par)
+{
+ double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
+ return 1./N;
+}
+
+double MofRhInt2D::Val_Der(double const xp[], double const* Par
+                          , double *DgDpar)
+{
+ for(int i=0; i<=7; i++) DgDpar[i] = 0.;
+
+ double unmr2 = 1.-_rho_*_rho_;
+ double N = (_Gm_-1.)*sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
+ double x = xp[0] - _x0_;
+ double y = xp[1] - _y0_;
+ double SPSF = 0.;
+ double X,Y,XmrY,YmrX,z2,D,lD,PSF;
+ {for(int i=0; i<nd2d; i++) {
+   X = (x+dx2d[i])/_sigx_;
+   Y = (y+dy2d[i])/_sigy_;
+   XmrY = X-_rho_*Y;
+   YmrX = Y-_rho_*X;
+   z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
+   D = 1. + z2;
+   lD = log(D);
+   /* g(x,y) */
+   PSF = _Gm_*lD;
+   if( PSF<MINEXPM ) PSF = N * EXPO(-PSF) * w2d[i]; else PSF = 0.;
+   SPSF += PSF;
+   /* dg(x,y)/d(x0) */
+   DgDpar[1] += Par[0]* PSF* XmrY/_sigx_ * _Gm_/D;
+   /* dg(x,y)/d(y0) */
+   DgDpar[2] += Par[0]* PSF* YmrX/_sigy_ * _Gm_/D;
+   /* dg(x,y)/d(sx)*/
+   DgDpar[3] += Par[0]* PSF* (X*XmrY*_Gm_/D - 1.)/_sigx_;
+   /* dg(x,y)/d(sy) */
+   DgDpar[4] += Par[0]* PSF* (Y*YmrX*_Gm_/D - 1.)/_sigy_;
+   /* dg(x,y)/d(rho) */
+   DgDpar[5] += Par[0]* PSF* (X*Y*_Gm_/D - 2.*_rho_/unmr2);
+   /* dg(x,y)/d(Gm) */
+   DgDpar[6] += Par[0]* PSF* (1./(_Gm_-1.) - lD);
+ }}
+ /* dg(x,y)/d(Vol) */
+ DgDpar[0] = SPSF;
+ /* dg(x,y)/d(Fond) */
+ DgDpar[7] = 1.;
+
+ return Par[0] *SPSF + Par[7];
+}
+
+void MofRhInt2D::DefaultParam(double *parm)
+{
+  for (int i=0; i<mNPar; i++) parm[i] = 0.;
+  parm[3] = parm[4] = 1.;  // Sigx Sigy
+  parm[6] = 3.;
+}
+
+
+#undef _sigx_
+#undef _sigy_
+#undef _rho_
+#undef _x0_
+#undef _y0_
+#undef _Gm_
+#undef _B4_
+#undef _B6_
+#undef _B2_
+
+//==============================================================================
+// CLASSES DE FONCTIONS 2D type Xi2 AVEC PARAMETRES POUR LE FIT pixel taille 1x1
+// la taille du pixel est importante quand on utilise les PSF integrees
+//    (x,y x0,y0 sigmaX.... sont en unites de pixels !!!)
+//==============================================================================
+
+/////////////////////////////////////////////////////////////////
+//++
+// Titre	X2-GauRho2D
+// \index{X2-GauRho2D}
+//
+//	Chi2 pour une Gaussienne+fond 2D (voir detail dans GauRho2D).
+//--
+/////////////////////////////////////////////////////////////////
+
+//++
+// X2-GauRho2D::X2-GauRho2D()
+//	Createur 
+//--
+X2_GauRho2D::X2_GauRho2D()
+: GeneralXi2(7)
+{
+  gaurho2d = new GauRho2D;
+}
+
+X2_GauRho2D::~X2_GauRho2D()
+{
+  delete gaurho2d;
+}
+
+double X2_GauRho2D::Value(GeneralFitData& data, double* parm, int& ndataused)
+{
+ ASSERT( data.NVar()==2 );
+ double x[2],z;
+
+ double c2 = 0.;
+ ndataused = 0;
+ for(int k=0;k<data.NData();k++) {
+   if( ! data.IsValid(k) ) continue;
+   x[0] = data.X(k); x[1] = data.Y(k);
+   z = (data.Val(k)-gaurho2d->Value(x,parm))/data.EVal(k);
+   c2 += z*z;
+   ndataused++;
+ }
+ return c2;
+}
+
+double X2_GauRho2D::Derivee2(GeneralFitData& data, int i,int j, double* parm)
+{
+ ASSERT( data.NVar()==2 && i<7 && j<7);
+ double x[2],dparm[7];
+
+ double d2c2 = 0.;
+ for(int k=0;k<data.NData();k++) {
+   if( ! data.IsValid(k) ) continue;
+   x[0] = data.X(k); x[1] = data.Y(k);
+   gaurho2d->Val_Der(x,parm,dparm);
+   d2c2 += 2.*dparm[i]*dparm[j]/(data.EVal(k)*data.EVal(k));
+ }
+ return d2c2;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fct2dfit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fct2dfit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fct2dfit.h	(revision 752)
@@ -0,0 +1,199 @@
+#ifndef FCT2DFIT_SEEN
+#define FCT2DFIT_SEEN
+
+#include "generalfit.h"
+
+namespace SOPHYA {
+
+//================================================================
+// GeneralFunction 2D pour PSF pixel taille 1x1
+//================================================================
+
+class GeneralPSF2D : public GeneralFunction {
+public:
+  GeneralPSF2D(unsigned int nPar);
+  virtual ~GeneralPSF2D();
+
+  virtual double ValueH(double const xp[], double const* parm);
+  virtual double VolPSF(double const* parm);
+  virtual void   DefaultParam(double *parm);
+
+  void SetVolEps(double const prec) ;
+protected:
+  double VolEps;
+};
+
+//================================================================
+// GeneralFunction 2D pour MULTI-PSF pixel taille 1x1
+//================================================================
+
+class GenMultiPSF2D : public GeneralPSF2D {
+public:
+  GenMultiPSF2D(GeneralPSF2D* psf2d,unsigned int nstar);
+  virtual ~GenMultiPSF2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+
+protected:
+  GeneralPSF2D* mPsf2D; // Type de PSF generique a fiter.
+  int mNStar;           // Nombre d etoiles a fiter.
+  int mNParmTot;        // Nombre total de parametres pour le fit.
+  int mNParm;           // Nombre de parametre pour la PSF generique.
+  int mNForme;          // Nombre de parametres de forme autres que Sx,Sy,Rho
+  double* mParm;        // pour la PSF generique. Buffer pour PSF generique
+  double* mDer;         // et pour le stoquage temporaire des derivees.
+};
+
+//==============================================================================
+// CLASSES DE FONCTIONS 2D type PSF AVEC PARAMETRES POUR LE FIT pixel taille 1x1
+//==============================================================================
+
+//////////////////////////////////////////////////////////////////
+class GauRho2D : public GeneralPSF2D {
+public:
+  GauRho2D();
+  virtual ~GauRho2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class GauRhInt2D : public GeneralPSF2D {
+public:
+  GauRhInt2D();
+  virtual ~GauRhInt2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class GdlRho2D : public GeneralPSF2D {
+public:
+  GdlRho2D();
+  virtual ~GdlRho2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class GdlRhInt2D : public GeneralPSF2D {
+public:
+  GdlRhInt2D();
+  virtual ~GdlRhInt2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class Gdl1Rho2D : public GeneralPSF2D {
+public:
+  Gdl1Rho2D();
+  virtual ~Gdl1Rho2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class Gdl1RhInt2D : public GeneralPSF2D {
+public:
+  Gdl1RhInt2D();
+  virtual ~Gdl1RhInt2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class Gdl2Rho2D : public GeneralPSF2D {
+public:
+  Gdl2Rho2D();
+  virtual ~Gdl2Rho2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class Gdl2RhInt2D : public GeneralPSF2D {
+public:
+  Gdl2RhInt2D();
+  virtual ~Gdl2RhInt2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class MofRho2D : public GeneralPSF2D {
+public:
+  MofRho2D();
+  virtual ~MofRho2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//////////////////////////////////////////////////////////////////
+class MofRhInt2D : public GeneralPSF2D {
+public:
+  MofRhInt2D();
+  virtual ~MofRhInt2D();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
+  virtual double ValueH(double const xp[], double const* Par);
+  virtual double VolPSF(double const* Par);
+  virtual void   DefaultParam(double *Par);
+};
+
+//==============================================================================
+// CLASSES DE FONCTIONS 2D type Xi2 AVEC PARAMETRES POUR LE FIT pixel taille 1x1
+//==============================================================================
+
+//////////////////////////////////////////////////////////////////
+class X2_GauRho2D : public GeneralXi2 {
+public:
+  X2_GauRho2D();
+  virtual ~X2_GauRho2D();
+
+  virtual double Value(GeneralFitData& data, double* parm, int& ndataused);
+  virtual double Derivee2(GeneralFitData& data, int i,int j, double* parm);
+
+protected:
+  GauRho2D* gaurho2d;
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fftmayer.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftmayer.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftmayer.h	(revision 752)
@@ -0,0 +1,71 @@
+#ifndef  FFTMAYER_H_SEEN
+#define  FFTMAYER_H_SEEN
+/*
+** FFT and FHT routines
+**  Copyright 1988, 1993; Ron Mayer
+**  
+**  fht(fz,n);
+**      Does a hartley transform of "n" points in the array "fz".
+**  fft(n,real,imag)
+**      Does a fourier transform of "n" points of the "real" and
+**      "imag" arrays.
+**  ifft(n,real,imag)
+**      Does an inverse fourier transform of "n" points of the "real"
+**      and "imag" arrays.
+**  realfft(n,real)
+**      Does a real-valued fourier transform of "n" points of the
+**      "real" arrays.  The real part of the transform ends
+**      up in the first half of the array and the imaginary part of the
+**      transform ends up in the second half of the array.
+**  realifft(n,real)
+**      The inverse of the realfft() routine above.
+**      
+**      
+** NOTE: This routine uses at least 2 patented algorithms, and may be
+**       under the restrictions of a bunch of different organizations.
+**       Although I wrote it completely myself; it is kind of a derivative
+**       of a routine I once authored and released under the GPL, so it
+**       may fall under the free software foundation's restrictions;
+**       it was worked on as a Stanford Univ project, so they claim
+**       some rights to it; it was further optimized at work here, so
+**       I think this company claims parts of it.  The patents are
+**       held by R. Bracewell (the FHT algorithm) and O. Buneman (the
+**       trig generator), both at Stanford Univ.
+**       If it were up to me, I'd say go do whatever you want with it;
+**       but it would be polite to give credit to the following people
+**       if you use this anywhere:
+**           Euler     - probable inventor of the fourier transform.
+**           Gauss     - probable inventor of the FFT.
+**           Hartley   - probable inventor of the hartley transform.
+**           Buneman   - for a really cool trig generator
+**           Mayer(me) - for authoring this particular version and
+**                       including all the optimizations in one package.
+**       Thanks,
+**       Ron Mayer; mayer@acuson.com
+**
+*/
+
+/*   Reza 4/02/99 : Introduced double AND float version   */
+#include "machdefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fht_r4( r_4 *fz,int n);
+void ifft_r4(int n, r_4 *real, r_4 *imag);
+void realfft_r4(int n, r_4 *real);
+void fft_r4(int n, r_4 *real,r_4 *imag);
+void realifft_r4(int n,r_4 *real);
+
+void fht_r8( r_8 *fz,int n);
+void ifft_r8(int n, r_8 *real, r_8 *imag);
+void realfft_r8(int n, r_8 *real);
+void fft_r8(int n, r_8 *real,r_8 *imag);
+void realifft_r8(int n,r_8 *real);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fftmayer_r4.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftmayer_r4.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftmayer_r4.c	(revision 752)
@@ -0,0 +1,259 @@
+/*
+** FFT and FHT routines
+**  Copyright 1988, 1993; Ron Mayer
+**  
+**  fht(fz,n);
+**      Does a hartley transform of "n" points in the array "fz".
+**  fft(n,real,imag)
+**      Does a fourier transform of "n" points of the "real" and
+**      "imag" arrays.
+**  ifft(n,real,imag)
+**      Does an inverse fourier transform of "n" points of the "real"
+**      and "imag" arrays.
+**  realfft(n,real)
+**      Does a real-valued fourier transform of "n" points of the
+**      "real" array. The real part of the transform ends
+**      up in the first half of the array and the imaginary part of the
+**      transform ends up in the second half of the array.
+**  realifft(n,real)
+**      The inverse of the realfft() routine above.
+**      
+**      
+** NOTE: This routine uses at least 2 patented algorithms, and may be
+**       under the restrictions of a bunch of different organizations.
+**       Although I wrote it completely myself; it is kind of a derivative
+**       of a routine I once authored and released under the GPL, so it
+**       may fall under the free software foundation's restrictions;
+**       it was worked on as a Stanford Univ project, so they claim
+**       some rights to it; it was further optimized at work here, so
+**       I think this company claims parts of it.  The patents are
+**       held by R. Bracewell (the FHT algorithm) and O. Buneman (the
+**       trig generator), both at Stanford Univ.
+**       If it were up to me, I'd say go do whatever you want with it;
+**       but it would be polite to give credit to the following people
+**       if you use this anywhere:
+**           Euler     - probable inventor of the fourier transform.
+**           Gauss     - probable inventor of the FFT.
+**           Hartley   - probable inventor of the hartley transform.
+**           Buneman   - for a really cool trig generator
+**           Mayer(me) - for authoring this particular version and
+**                       including all the optimizations in one package.
+**       Thanks,
+**       Ron Mayer; mayer@acuson.com
+**
+*/
+
+#include "fftmayer.h"
+
+#define GOOD_TRIG
+#define REAL r_4
+#include "trigtbl.h"
+
+char fht_r4_version[] = "Brcwl-Hrtly-Ron-dbld";
+
+#define SQRT2_2   0.70710678118654752440084436210484
+#define SQRT2   2*0.70710678118654752440084436210484
+
+void fht_r4(r_4 *fz,int n)
+{
+ r_4 a,b;
+ r_4 c1,s1,s2,c2,s3,c3,s4,c4;
+ r_4 f0,g0,f1,g1,f2,g2,f3,g3;
+ int i,k,k1,k2,k3,k4,kx;
+ r_4 *fi,*fn,*gi;
+ TRIG_VARS;
+
+ for (k1=1,k2=0;k1<n;k1++)
+    {
+     r_4 a;
+     for (k=n>>1; (!((k2^=k)&k)); k>>=1);
+     if (k1>k2)
+	{
+	     a=fz[k1];fz[k1]=fz[k2];fz[k2]=a;
+	}
+    }
+ for ( k=0 ; (1<<k)<n ; k++ );
+ k  &= 1;
+ if (k==0)
+    {
+	 for (fi=fz,fn=fz+n;fi<fn;fi+=4)
+	    {
+	     r_4 f0,f1,f2,f3;
+	     f1     = fi[0 ]-fi[1 ];
+	     f0     = fi[0 ]+fi[1 ];
+	     f3     = fi[2 ]-fi[3 ];
+	     f2     = fi[2 ]+fi[3 ];
+	     fi[2 ] = (f0-f2);	
+	     fi[0 ] = (f0+f2);
+	     fi[3 ] = (f1-f3);	
+	     fi[1 ] = (f1+f3);
+	    }
+    }
+ else
+    {
+	 for (fi=fz,fn=fz+n,gi=fi+1;fi<fn;fi+=8,gi+=8)
+	    {
+	     r_4 s1,c1,s2,c2,s3,c3,s4,c4,g0,f0,f1,g1,f2,g2,f3,g3;
+	     c1     = fi[0 ] - gi[0 ];
+	     s1     = fi[0 ] + gi[0 ];
+	     c2     = fi[2 ] - gi[2 ];
+	     s2     = fi[2 ] + gi[2 ];
+	     c3     = fi[4 ] - gi[4 ];
+	     s3     = fi[4 ] + gi[4 ];
+	     c4     = fi[6 ] - gi[6 ];
+	     s4     = fi[6 ] + gi[6 ];
+	     f1     = (s1 - s2);	
+	     f0     = (s1 + s2);
+	     g1     = (c1 - c2);	
+	     g0     = (c1 + c2);
+	     f3     = (s3 - s4);	
+	     f2     = (s3 + s4);
+	     g3     = SQRT2*c4;		
+	     g2     = SQRT2*c3;
+	     fi[4 ] = f0 - f2;
+	     fi[0 ] = f0 + f2;
+	     fi[6 ] = f1 - f3;
+	     fi[2 ] = f1 + f3;
+	     gi[4 ] = g0 - g2;
+	     gi[0 ] = g0 + g2;
+	     gi[6 ] = g1 - g3;
+	     gi[2 ] = g1 + g3;
+	    }
+    }
+ if (n<16) return;
+
+ do
+    {
+     r_4 s1,c1;
+     k  += 2;
+     k1  = 1  << k;
+     k2  = k1 << 1;
+     k4  = k2 << 1;
+     k3  = k2 + k1;
+     kx  = k1 >> 1;
+	 fi  = fz;
+	 gi  = fi + kx;
+	 fn  = fz + n;
+	 do
+	    {
+	     r_4 g0,f0,f1,g1,f2,g2,f3,g3;
+	     f1      = fi[0 ] - fi[k1];
+	     f0      = fi[0 ] + fi[k1];
+	     f3      = fi[k2] - fi[k3];
+	     f2      = fi[k2] + fi[k3];
+	     fi[k2]  = f0	  - f2;
+	     fi[0 ]  = f0	  + f2;
+	     fi[k3]  = f1	  - f3;
+	     fi[k1]  = f1	  + f3;
+	     g1      = gi[0 ] - gi[k1];
+	     g0      = gi[0 ] + gi[k1];
+	     g3      = SQRT2  * gi[k3];
+	     g2      = SQRT2  * gi[k2];
+	     gi[k2]  = g0	  - g2;
+	     gi[0 ]  = g0	  + g2;
+	     gi[k3]  = g1	  - g3;
+	     gi[k1]  = g1	  + g3;
+	     gi     += k4;
+	     fi     += k4;
+	    } while (fi<fn);
+     TRIG_INIT(k,c1,s1);
+     for (i=1;i<kx;i++)
+        {
+	 r_4 c2,s2;
+         TRIG_NEXT(k,c1,s1);
+         c2 = c1*c1 - s1*s1;
+         s2 = 2*(c1*s1);
+	     fn = fz + n;
+	     fi = fz +i;
+	     gi = fz +k1-i;
+	     do
+		{
+		 r_4 a,b,g0,f0,f1,g1,f2,g2,f3,g3;
+		 b       = s2*fi[k1] - c2*gi[k1];
+		 a       = c2*fi[k1] + s2*gi[k1];
+		 f1      = fi[0 ]    - a;
+		 f0      = fi[0 ]    + a;
+		 g1      = gi[0 ]    - b;
+		 g0      = gi[0 ]    + b;
+		 b       = s2*fi[k3] - c2*gi[k3];
+		 a       = c2*fi[k3] + s2*gi[k3];
+		 f3      = fi[k2]    - a;
+		 f2      = fi[k2]    + a;
+		 g3      = gi[k2]    - b;
+		 g2      = gi[k2]    + b;
+		 b       = s1*f2     - c1*g3;
+		 a       = c1*f2     + s1*g3;
+		 fi[k2]  = f0        - a;
+		 fi[0 ]  = f0        + a;
+		 gi[k3]  = g1        - b;
+		 gi[k1]  = g1        + b;
+		 b       = c1*g2     - s1*f3;
+		 a       = s1*g2     + c1*f3;
+		 gi[k2]  = g0        - a;
+		 gi[0 ]  = g0        + a;
+		 fi[k3]  = f1        - b;
+		 fi[k1]  = f1        + b;
+		 gi     += k4;
+		 fi     += k4;
+		} while (fi<fn);
+        }
+     TRIG_RESET(k,c1,s1);
+    } while (k4<n);
+}
+
+
+void ifft_r4(int n, r_4 *real, r_4 *imag)
+{
+ r_4 a,b,c,d;
+ r_4 q,r,s,t;
+ int i,j,k;
+ fht_r4(real,n);
+ fht_r4(imag,n);
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i]; b = real[j];  q=a+b; r=a-b;
+  c = imag[i]; d = imag[j];  s=c+d; t=c-d;
+  imag[i] = (s+r)*0.5;  imag[j] = (s-r)*0.5;
+  real[i] = (q-t)*0.5;  real[j] = (q+t)*0.5;
+ }
+}
+
+void realfft_r4(int n, r_4 *real)
+{
+ r_4 a,b,c,d;
+ int i,j,k;
+ fht_r4(real,n);
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i];
+  b = real[j];
+  real[j] = (a-b)*0.5;
+  real[i] = (a+b)*0.5;
+ }
+}
+
+void fft_r4(int n, r_4 *real,r_4 *imag)
+{
+ r_4 a,b,c,d;
+ r_4 q,r,s,t;
+ int i,j,k;
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i]; b = real[j];  q=a+b; r=a-b;
+  c = imag[i]; d = imag[j];  s=c+d; t=c-d;
+  real[i] = (q+t)*.5; real[j] = (q-t)*.5;
+  imag[i] = (s-r)*.5; imag[j] = (s+r)*.5;
+ }
+ fht_r4(real,n);
+ fht_r4(imag,n);
+}
+
+void realifft_r4(int n,r_4 *real)
+{
+ r_4 a,b,c,d;
+ int i,j,k;
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i];
+  b = real[j];
+  real[j] = (a-b);
+  real[i] = (a+b);
+ }
+ fht_r4(real,n);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fftmayer_r8.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftmayer_r8.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftmayer_r8.c	(revision 752)
@@ -0,0 +1,259 @@
+/*
+** FFT and FHT routines
+**  Copyright 1988, 1993; Ron Mayer
+**  
+**  fht(fz,n);
+**      Does a hartley transform of "n" points in the array "fz".
+**  fft(n,real,imag)
+**      Does a fourier transform of "n" points of the "real" and
+**      "imag" arrays.
+**  ifft(n,real,imag)
+**      Does an inverse fourier transform of "n" points of the "real"
+**      and "imag" arrays.
+**  realfft(n,real)
+**      Does a real-valued fourier transform of "n" points of the
+**      "real" array. The real part of the transform ends
+**      up in the first half of the array and the imaginary part of the
+**      transform ends up in the second half of the array.
+**  realifft(n,real)
+**      The inverse of the realfft() routine above.
+**      
+**      
+** NOTE: This routine uses at least 2 patented algorithms, and may be
+**       under the restrictions of a bunch of different organizations.
+**       Although I wrote it completely myself; it is kind of a derivative
+**       of a routine I once authored and released under the GPL, so it
+**       may fall under the free software foundation's restrictions;
+**       it was worked on as a Stanford Univ project, so they claim
+**       some rights to it; it was further optimized at work here, so
+**       I think this company claims parts of it.  The patents are
+**       held by R. Bracewell (the FHT algorithm) and O. Buneman (the
+**       trig generator), both at Stanford Univ.
+**       If it were up to me, I'd say go do whatever you want with it;
+**       but it would be polite to give credit to the following people
+**       if you use this anywhere:
+**           Euler     - probable inventor of the fourier transform.
+**           Gauss     - probable inventor of the FFT.
+**           Hartley   - probable inventor of the hartley transform.
+**           Buneman   - for a really cool trig generator
+**           Mayer(me) - for authoring this particular version and
+**                       including all the optimizations in one package.
+**       Thanks,
+**       Ron Mayer; mayer@acuson.com
+**
+*/
+
+#include "fftmayer.h"
+
+#define GOOD_TRIG
+#define REAL r_8
+#include "trigtbl.h"
+
+char fht_r8_version[] = "Brcwl-Hrtly-Ron-dbld";
+
+#define SQRT2_2   0.70710678118654752440084436210484
+#define SQRT2   2*0.70710678118654752440084436210484
+
+void fht_r8(r_8 *fz,int n)
+{
+ r_8 a,b;
+ r_8 c1,s1,s2,c2,s3,c3,s4,c4;
+ r_8 f0,g0,f1,g1,f2,g2,f3,g3;
+ int i,k,k1,k2,k3,k4,kx;
+ r_8 *fi,*fn,*gi;
+ TRIG_VARS;
+
+ for (k1=1,k2=0;k1<n;k1++)
+    {
+     r_8 a;
+     for (k=n>>1; (!((k2^=k)&k)); k>>=1);
+     if (k1>k2)
+	{
+	     a=fz[k1];fz[k1]=fz[k2];fz[k2]=a;
+	}
+    }
+ for ( k=0 ; (1<<k)<n ; k++ );
+ k  &= 1;
+ if (k==0)
+    {
+	 for (fi=fz,fn=fz+n;fi<fn;fi+=4)
+	    {
+	     r_8 f0,f1,f2,f3;
+	     f1     = fi[0 ]-fi[1 ];
+	     f0     = fi[0 ]+fi[1 ];
+	     f3     = fi[2 ]-fi[3 ];
+	     f2     = fi[2 ]+fi[3 ];
+	     fi[2 ] = (f0-f2);	
+	     fi[0 ] = (f0+f2);
+	     fi[3 ] = (f1-f3);	
+	     fi[1 ] = (f1+f3);
+	    }
+    }
+ else
+    {
+	 for (fi=fz,fn=fz+n,gi=fi+1;fi<fn;fi+=8,gi+=8)
+	    {
+	     r_8 s1,c1,s2,c2,s3,c3,s4,c4,g0,f0,f1,g1,f2,g2,f3,g3;
+	     c1     = fi[0 ] - gi[0 ];
+	     s1     = fi[0 ] + gi[0 ];
+	     c2     = fi[2 ] - gi[2 ];
+	     s2     = fi[2 ] + gi[2 ];
+	     c3     = fi[4 ] - gi[4 ];
+	     s3     = fi[4 ] + gi[4 ];
+	     c4     = fi[6 ] - gi[6 ];
+	     s4     = fi[6 ] + gi[6 ];
+	     f1     = (s1 - s2);	
+	     f0     = (s1 + s2);
+	     g1     = (c1 - c2);	
+	     g0     = (c1 + c2);
+	     f3     = (s3 - s4);	
+	     f2     = (s3 + s4);
+	     g3     = SQRT2*c4;		
+	     g2     = SQRT2*c3;
+	     fi[4 ] = f0 - f2;
+	     fi[0 ] = f0 + f2;
+	     fi[6 ] = f1 - f3;
+	     fi[2 ] = f1 + f3;
+	     gi[4 ] = g0 - g2;
+	     gi[0 ] = g0 + g2;
+	     gi[6 ] = g1 - g3;
+	     gi[2 ] = g1 + g3;
+	    }
+    }
+ if (n<16) return;
+
+ do
+    {
+     r_8 s1,c1;
+     k  += 2;
+     k1  = 1  << k;
+     k2  = k1 << 1;
+     k4  = k2 << 1;
+     k3  = k2 + k1;
+     kx  = k1 >> 1;
+	 fi  = fz;
+	 gi  = fi + kx;
+	 fn  = fz + n;
+	 do
+	    {
+	     r_8 g0,f0,f1,g1,f2,g2,f3,g3;
+	     f1      = fi[0 ] - fi[k1];
+	     f0      = fi[0 ] + fi[k1];
+	     f3      = fi[k2] - fi[k3];
+	     f2      = fi[k2] + fi[k3];
+	     fi[k2]  = f0	  - f2;
+	     fi[0 ]  = f0	  + f2;
+	     fi[k3]  = f1	  - f3;
+	     fi[k1]  = f1	  + f3;
+	     g1      = gi[0 ] - gi[k1];
+	     g0      = gi[0 ] + gi[k1];
+	     g3      = SQRT2  * gi[k3];
+	     g2      = SQRT2  * gi[k2];
+	     gi[k2]  = g0	  - g2;
+	     gi[0 ]  = g0	  + g2;
+	     gi[k3]  = g1	  - g3;
+	     gi[k1]  = g1	  + g3;
+	     gi     += k4;
+	     fi     += k4;
+	    } while (fi<fn);
+     TRIG_INIT(k,c1,s1);
+     for (i=1;i<kx;i++)
+        {
+	 r_8 c2,s2;
+         TRIG_NEXT(k,c1,s1);
+         c2 = c1*c1 - s1*s1;
+         s2 = 2*(c1*s1);
+	     fn = fz + n;
+	     fi = fz +i;
+	     gi = fz +k1-i;
+	     do
+		{
+		 r_8 a,b,g0,f0,f1,g1,f2,g2,f3,g3;
+		 b       = s2*fi[k1] - c2*gi[k1];
+		 a       = c2*fi[k1] + s2*gi[k1];
+		 f1      = fi[0 ]    - a;
+		 f0      = fi[0 ]    + a;
+		 g1      = gi[0 ]    - b;
+		 g0      = gi[0 ]    + b;
+		 b       = s2*fi[k3] - c2*gi[k3];
+		 a       = c2*fi[k3] + s2*gi[k3];
+		 f3      = fi[k2]    - a;
+		 f2      = fi[k2]    + a;
+		 g3      = gi[k2]    - b;
+		 g2      = gi[k2]    + b;
+		 b       = s1*f2     - c1*g3;
+		 a       = c1*f2     + s1*g3;
+		 fi[k2]  = f0        - a;
+		 fi[0 ]  = f0        + a;
+		 gi[k3]  = g1        - b;
+		 gi[k1]  = g1        + b;
+		 b       = c1*g2     - s1*f3;
+		 a       = s1*g2     + c1*f3;
+		 gi[k2]  = g0        - a;
+		 gi[0 ]  = g0        + a;
+		 fi[k3]  = f1        - b;
+		 fi[k1]  = f1        + b;
+		 gi     += k4;
+		 fi     += k4;
+		} while (fi<fn);
+        }
+     TRIG_RESET(k,c1,s1);
+    } while (k4<n);
+}
+
+
+void ifft_r8(int n, r_8 *real, r_8 *imag)
+{
+ r_8 a,b,c,d;
+ r_8 q,r,s,t;
+ int i,j,k;
+ fht_r8(real,n);
+ fht_r8(imag,n);
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i]; b = real[j];  q=a+b; r=a-b;
+  c = imag[i]; d = imag[j];  s=c+d; t=c-d;
+  imag[i] = (s+r)*0.5;  imag[j] = (s-r)*0.5;
+  real[i] = (q-t)*0.5;  real[j] = (q+t)*0.5;
+ }
+}
+
+void realfft_r8(int n, r_8 *real)
+{
+ r_8 a,b,c,d;
+ int i,j,k;
+ fht_r8(real,n);
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i];
+  b = real[j];
+  real[j] = (a-b)*0.5;
+  real[i] = (a+b)*0.5;
+ }
+}
+
+void fft_r8(int n, r_8 *real,r_8 *imag)
+{
+ r_8 a,b,c,d;
+ r_8 q,r,s,t;
+ int i,j,k;
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i]; b = real[j];  q=a+b; r=a-b;
+  c = imag[i]; d = imag[j];  s=c+d; t=c-d;
+  real[i] = (q+t)*.5; real[j] = (q-t)*.5;
+  imag[i] = (s-r)*.5; imag[j] = (s+r)*.5;
+ }
+ fht_r8(real,n);
+ fht_r8(imag,n);
+}
+
+void realifft_r8(int n,r_8 *real)
+{
+ r_8 a,b,c,d;
+ int i,j,k;
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = real[i];
+  b = real[j];
+  real[j] = (a-b);
+  real[i] = (a+b);
+ }
+ fht_r8(real,n);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fftmserver.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftmserver.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftmserver.cc	(revision 752)
@@ -0,0 +1,364 @@
+#include "fftmserver.h"
+#include <iostream.h>
+#include "fftmayer.h"
+
+
+/* --Methode-- */
+FFTMayerServer::FFTMayerServer()
+   : FFTServerInterface("FFTMayerServer using extended FFTMayer package")
+
+{
+}
+
+/* --Methode-- */
+FFTMayerServer::~FFTMayerServer()
+{
+}
+
+/* --Methode-- */
+FFTServerInterface * FFTMayerServer::Clone()
+{
+  return (new FFTMayerServer);
+}
+
+
+/* --Methode-- */
+void FFTMayerServer::FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out)
+{
+ r_8 a,b,c,d;
+ r_8 q,r,s,t;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTForward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+ TVector< r_8 > inoutre(n);
+ TVector< r_8 > inoutim(n);
+ inoutre(0) = in(0).real();
+ inoutim(0) = in(0).imag();
+ inoutre(n/2) = in(n/2).real();
+ inoutim(n/2) = in(n/2).imag();
+ if (n > 2) {
+   inoutre(n/2+1) = in(n/2).real();
+   inoutim(n/2+1) = in(n/2).imag();
+ }
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = in(i).real(); b = in(j).real();  q=a+b; r=a-b;
+  c = in(i).imag(); d = in(j).imag();  s=c+d; t=c-d;
+  inoutre(i) = (q+t)*.5; inoutre(j) = (q-t)*.5;
+  inoutim(i) = (s-r)*.5; inoutim(j) = (s+r)*.5;
+ }
+ fht_r8(inoutre.Data(),inoutre.NElts());
+ fht_r8(inoutim.Data(),inoutim.NElts());
+
+ out.ReSize(in.NElts());
+ r_8 fn = 1./n;
+ if (getNormalize()) 
+   for(k=0; k<out.NElts(); k++)
+     out(k) = complex<r_8>(inoutre(k)*fn, inoutim(k)*fn);
+ else 
+   for(k=0; k<out.NElts(); k++)
+     out(k) = complex<r_8>(inoutre(k), inoutim(k));
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out)
+{
+ r_8 a,b,c,d;
+ r_8 q,r,s,t;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTBackward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+ TVector< r_8 > inoutre(n);
+ TVector< r_8 > inoutim(n);
+ for(k=0; k<out.NElts(); k++) {
+   inoutre(k) = in(k).real();
+   inoutim(k) = in(k).imag();
+ }
+ fht_r8(inoutre.Data(),inoutre.NElts());
+ fht_r8(inoutim.Data(),inoutim.NElts());
+
+ out.ReSize(in.NElts());
+ out(0) = complex<r_8>(inoutre(0), inoutim(0));
+ out(n/2) = complex<r_8>(inoutre(n/2), inoutim(n/2));
+ if (n > 2) out(n/2+1) = complex<r_8>(inoutre(n/2+1), inoutim(n/2+1));
+
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = inoutre(i); b = inoutre(j);  q=a+b; r=a-b;
+  c = inoutim(i); d = inoutim(j);  s=c+d; t=c-d;
+  out(i) = complex<r_8>( (q-t)*0.5 , (s+r)*0.5 );
+  out(j) = complex<r_8>( (q+t)*0.5 , (s-r)*0.5 );
+ }
+
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out)
+{
+ r_4 a,b,c,d;
+ r_4 q,r,s,t;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTForward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+ TVector< r_4 > inoutre(n);
+ TVector< r_4 > inoutim(n);
+ inoutre(0) = in(0).real();
+ inoutim(0) = in(0).imag();
+ inoutre(n/2) = in(n/2).real();
+ inoutim(n/2) = in(n/2).imag();
+ if (n > 2) {
+   inoutre(n/2+1) = in(n/2).real();
+   inoutim(n/2+1) = in(n/2).imag();
+ }
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = in(i).real(); b = in(j).real();  q=a+b; r=a-b;
+  c = in(i).imag(); d = in(j).imag();  s=c+d; t=c-d;
+  inoutre(i) = (q+t)*.5; inoutre(j) = (q-t)*.5;
+  inoutim(i) = (s-r)*.5; inoutim(j) = (s+r)*.5;
+ }
+ fht_r4(inoutre.Data(),inoutre.NElts());
+ fht_r4(inoutim.Data(),inoutim.NElts());
+
+ out.ReSize(in.NElts());
+ r_4 fn = 1./n;
+ if (getNormalize()) 
+   for(k=0; k<out.NElts(); k++)
+     out(k) = complex<r_4>(inoutre(k)*fn, inoutim(k)*fn);
+ else 
+   for(k=0; k<out.NElts(); k++)
+     out(k) = complex<r_4>(inoutre(k), inoutim(k));
+
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out)
+{
+ r_4 a,b,c,d;
+ r_4 q,r,s,t;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTBackward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+
+ TVector< r_4 > inoutre(n);
+ TVector< r_4 > inoutim(n);
+ for(k=0; k<out.NElts(); k++) {
+   inoutre(k) = in(k).real();
+   inoutim(k) = in(k).imag();
+ }
+ fht_r4(inoutre.Data(),inoutre.NElts());
+ fht_r4(inoutim.Data(),inoutim.NElts());
+
+ out.ReSize(in.NElts());
+ out(0) = complex<r_4>(inoutre(0), inoutim(0));
+ out(n/2) = complex<r_4>(inoutre(n/2), inoutim(n/2));
+ if (n > 2) out(n/2+1) = complex<r_4>(inoutre(n/2+1), inoutim(n/2+1));
+
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = inoutre(i); b = inoutre(j);  q=a+b; r=a-b;
+  c = inoutim(i); d = inoutim(j);  s=c+d; t=c-d;
+  out(i) = complex<r_4>( (q-t)*0.5 , (s+r)*0.5 );
+  out(j) = complex<r_4>( (q+t)*0.5 , (s-r)*0.5 );
+ }
+
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out)
+{
+ r_4 a,b,c,d;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTForward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+
+ TVector< r_4 > inout(in);
+ fht_r4(inout.Data(),inout.NElts());
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = inout(i);  
+  b = inout(j);
+  inout(j) = (a-b)*0.5;
+  inout(i) = (a+b)*0.5;
+  out(i) = complex<r_4>( (a+b)*0.5 , (a-b)*0.5 );
+ }
+
+  
+ out.ReSize(n/2+1);
+ out(0) = complex<r_4>(inout(0), 0.);
+
+ if (n%2 == 0) { // n pair
+   for (i=1,j=n/2+1; i<n/2; i++,j++) 
+     out(i) = complex<r_4>(inout(i), inout(j));
+
+   out(n/2) = complex<r_4>(inout(n/2), 0.);
+ }
+ else { // n impair
+   for (i=1,j=n/2+2; i<n/2; i++,j++) 
+     out(i) = complex<r_4>(inout(i), inout(j));
+
+   out(n/2) = complex<r_4>(inout(n/2), inout(n/2+1));
+ }
+
+ if (getNormalize()) out *= (1./(r_4)(in.NElts()));
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out)
+{
+ r_4 a,b,c,d;
+ int i,j,k;
+ int n = in.NElts();
+ int nc = (fabs(in(n-1).imag()) < 1.e-9) ? nc = n*2-2 : nc = n*2-1;
+ if (checkLength(nc))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTBackward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   nc, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+
+ out.ReSize(nc);
+ out(0) = in(0).real();
+ if (nc%2 == 0) { // nc pair
+   for (i=1,j=nc/2+1; i<nc/2; i++,j++) {
+     out(i) = in(i).real();
+     out(j) = in(i).imag();
+   }
+   out(nc/2) = in(nc/2).real();
+ }
+ else { // nc impair
+   for (i=1,j=nc/2+2; i<nc/2; i++,j++) {
+     out(i) = in(i).real();
+     out(j) = in(i).imag();
+   }
+   out(nc/2) = in(nc/2).real();
+   out(nc/2+1) = in(nc/2).imag();
+ }
+
+ for (i=1,j=nc-1,k=nc/2;i<k;i++,j--) {
+  a = out(i);
+  b = out(j);
+  out(j) = (a-b);
+  out(i) = (a+b);
+ }
+ fht_r4(out.Data(),out.NElts());
+}
+
+
+/* --Methode-- */
+void FFTMayerServer::FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out)
+{
+ r_8 a,b,c,d;
+ int i,j,k;
+ int n = in.NElts();
+ if (checkLength(n))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTForward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   n, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+
+ TVector< r_8 > inout(in);
+ fht_r8(inout.Data(),inout.NElts());
+ for (i=1,j=n-1,k=n/2;i<k;i++,j--) {
+  a = inout(i);  
+  b = inout(j);
+  inout(j) = (a-b)*0.5;
+  inout(i) = (a+b)*0.5;
+  out(i) = complex<r_8>( (a+b)*0.5 , (a-b)*0.5 );
+ }
+
+  
+ out.ReSize(n/2+1);
+ out(0) = complex<r_8>(inout(0), 0.);
+
+ if (n%2 == 0) { // n pair
+   for (i=1,j=n/2+1; i<n/2; i++,j++) 
+     out(i) = complex<r_8>(inout(i), inout(j));
+
+   out(n/2) = complex<r_8>(inout(n/2), 0.);
+ }
+ else { // n impair
+   for (i=1,j=n/2+2; i<n/2; i++,j++) 
+     out(i) = complex<r_8>(inout(i), inout(j));
+
+   out(n/2) = complex<r_8>(inout(n/2), inout(n/2+1));
+ }
+ if (getNormalize()) out *= (1./(r_4)(in.NElts()));
+}
+
+/* --Methode-- */
+void FFTMayerServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out)
+{
+ r_8 a,b,c,d;
+ int i,j,k;
+ int n = in.NElts();
+ int nc = (fabs(in(n-1).imag()) < 1.e-18) ? nc = n*2-2 : nc = n*2-1;
+ if (checkLength(nc))  {
+   char buff[256];
+   sprintf(buff, "FFTMayerServer::FFTBackward/Error Size(%d) != 2^n ! (File=%s Line=%d)",
+	   nc, __FILE__,__LINE__);
+   throw ParmError(string(buff));
+ }
+
+ out.ReSize(nc);
+ out(0) = in(0).real();
+ if (nc%2 == 0) { // nc pair
+   for (i=1,j=nc/2+1; i<nc/2; i++,j++) {
+     out(i) = in(i).real();
+     out(j) = in(i).imag();
+   }
+   out(nc/2) = in(nc/2).real();
+ }
+ else { // nc impair
+   for (i=1,j=nc/2+2; i<nc/2; i++,j++) {
+     out(i) = in(i).real();
+     out(j) = in(i).imag();
+   }
+   out(nc/2) = in(nc/2).real();
+   out(nc/2+1) = in(nc/2).imag();
+ }
+
+ for (i=1,j=nc-1,k=nc/2;i<k;i++,j--) {
+  a = out(i);
+  b = out(j);
+  out(j) = (a-b);
+  out(i) = (a+b);
+ }
+ fht_r8(out.Data(),out.NElts());
+}
+
+
+
+/* --Methode-- */
+bool FFTMayerServer::checkLength(int n)
+{
+  if (n < 2) return(true);
+  int nc = n;
+  int r;
+  while (nc > 1) {
+    if (nc%2 != 0)  return(true);
+    nc /= 2;
+  }
+  return(false);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fftmserver.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftmserver.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftmserver.h	(revision 752)
@@ -0,0 +1,42 @@
+#ifndef  FFTMServer_H_SEEN
+#define  FFTMServer_H_SEEN
+
+#include "fftservintf.h"
+
+// implementation de FFTServerInterface en utilisant FFTPack 
+
+namespace SOPHYA {
+
+class FFTMayerServer : public FFTServerInterface {
+ public:
+  FFTMayerServer();
+  virtual ~FFTMayerServer();
+
+  // Implementation de l'interface FFTServerInterface
+
+  virtual FFTServerInterface * Clone();
+
+  // Transforme unidimensionnel sur des doubles
+  virtual void FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out);
+
+
+  // Transforme unidimensionnel sur des float
+  virtual void FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out);
+
+
+protected:
+  virtual bool checkLength(int n);
+};
+
+} // Fin du namespace
+
+
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fftpackc.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftpackc.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftpackc.c	(revision 752)
@@ -0,0 +1,8890 @@
+/* fftpackc.c is the fortran FFTPACK package retrieved from netlib */
+
+/* allf.f -- translated by f2c (version 19970805).
+   You must link the resulting object file with the libraries:
+	-lf2c -lm   (in that order)
+*/
+
+/* #include "f2c.h" -- Remplace par ce qui suit */
+#include "fftpackc.h"
+#include <math.h>
+
+/*  ------ File cfftb.f ------ */
+/* Subroutine */ int cfftb_(integer *n, r_4 *c__, r_4 *wsave)
+{
+    extern /* Subroutine */ int cfftb1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    int_4 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --c__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cfftb1_(n, &c__[1], &wsave[1], &wsave[iw1], (int *)&wsave[iw2]);  /* (int *) ajoute - Reza 29/11/99 */
+    return 0;
+} /* cfftb_ */
+
+/*  ------ File cfftb1.f ------ */
+/* Subroutine */ int cfftb1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, 
+	int_4 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer idot, i__;
+    extern /* Subroutine */ int passb_(integer *, integer *, integer *, 
+	    integer *, integer *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *);
+    static integer k1, l1, l2, n2;
+    extern /* Subroutine */ int passb2_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *), passb3_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *), passb4_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *), passb5_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idot = ido + ido;
+	idl1 = idot * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	if (na != 0) {
+	    goto L101;
+	}
+	passb4_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	passb4_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	passb2_(&idot, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	passb2_(&idot, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + idot;
+	if (na != 0) {
+	    goto L107;
+	}
+	passb3_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	passb3_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	ix4 = ix3 + idot;
+	if (na != 0) {
+	    goto L110;
+	}
+	passb5_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	passb5_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	passb_(&nac, &idot, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1]
+		, &ch[1], &wa[iw]);
+	goto L114;
+L113:
+	passb_(&nac, &idot, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], 
+		&c__[1], &wa[iw]);
+L114:
+	if (nac != 0) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * idot;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    n2 = *n + *n;
+    i__1 = n2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* cfftb1_ */
+
+/*  ------ File cfftf.f ------ */
+/* Subroutine */ int cfftf_(integer *n, r_4 *c__, r_4 *wsave)
+{
+    extern /* Subroutine */ int cfftf1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    int_4 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --c__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cfftf1_(n, &c__[1], &wsave[1], &wsave[iw1], (int *)&wsave[iw2]);   /* (int *) ajoute - Reza 29/11/99 */
+    return 0;
+} /* cfftf_ */
+
+/*  ------ File cfftf1.f ------ */
+/* Subroutine */ int cfftf1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, 
+	int_4 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer idot, i__;
+    extern /* Subroutine */ int passf_(integer *, integer *, integer *, 
+	    integer *, integer *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *);
+    static integer k1, l1, l2, n2;
+    extern /* Subroutine */ int passf2_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *), passf3_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *), passf4_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *), passf5_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idot = ido + ido;
+	idl1 = idot * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	if (na != 0) {
+	    goto L101;
+	}
+	passf4_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	passf4_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	passf2_(&idot, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	passf2_(&idot, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + idot;
+	if (na != 0) {
+	    goto L107;
+	}
+	passf3_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	passf3_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	ix4 = ix3 + idot;
+	if (na != 0) {
+	    goto L110;
+	}
+	passf5_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	passf5_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	passf_(&nac, &idot, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1]
+		, &ch[1], &wa[iw]);
+	goto L114;
+L113:
+	passf_(&nac, &idot, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], 
+		&c__[1], &wa[iw]);
+L114:
+	if (nac != 0) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * idot;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    n2 = *n + *n;
+    i__1 = n2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* cfftf1_ */
+
+/*  ------ File cffti.f ------ */
+/* Subroutine */ int cffti_(integer *n, r_4 *wsave)
+{
+    extern /* Subroutine */ int cffti1_(integer *, r_4 *, int_4 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cffti1_(n, &wsave[iw1], (int *)&wsave[iw2]);  /*  (int *) ajoute Reza 29/11/99 */
+    return 0;
+} /* cffti_ */
+
+/*  ------ File cffti1.f ------ */
+/* Subroutine */ int cffti1_(integer *n, r_4 *wa, int_4 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 3,4,2,5 };
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */ 
+/*    r_8 cos(r_8truc), sin(r_8truc);   commente, remplace par math.h - Reza  29/11/99 */
+
+    /* Local variables */
+    static r_4 argh;
+    static integer idot, ntry, i__, j;
+    static r_4 argld;
+    static integer i1, k1, l1, l2, ib;
+    static r_4 fi;
+    static integer ld, ii, nf, ip, nl, nq, nr;
+    static r_4 arg;
+    static integer ido, ipm;
+    static r_4 tpi;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    tpi = 6.28318530717959f;
+    argh = tpi / (r_4) (*n);
+    i__ = 2;
+    l1 = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	ld = 0;
+	l2 = l1 * ip;
+	ido = *n / l2;
+	idot = ido + ido + 2;
+	ipm = ip - 1;
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    i1 = i__;
+	    wa[i__ - 1] = 1.f;
+	    wa[i__] = 0.f;
+	    ld += l1;
+	    fi = 0.f;
+	    argld = (r_4) ld * argh;
+	    i__3 = idot;
+	    for (ii = 4; ii <= i__3; ii += 2) {
+		i__ += 2;
+		fi += 1.f;
+		arg = fi * argld;
+		wa[i__ - 1] = cos(arg);
+		wa[i__] = sin(arg);
+/* L108: */
+	    }
+	    if (ip <= 5) {
+		goto L109;
+	    }
+	    wa[i1 - 1] = wa[i__ - 1];
+	    wa[i1] = wa[i__];
+L109:
+	    ;
+	}
+	l1 = l2;
+/* L110: */
+    }
+    return 0;
+} /* cffti1_ */
+
+/*  ------ File cosqb.f ------ */
+/* Subroutine */ int cosqb_(integer *n, r_4 *x, r_4 *wsave)
+{
+    /* Initialized data */
+
+    static r_4 tsqrt2 = 2.82842712474619f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static r_4 x1;
+    extern /* Subroutine */ int cosqb1_(integer *, r_4 *, r_4 *, r_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    x[1] *= 4.f;
+    return 0;
+L102:
+    x1 = (x[1] + x[2]) * 4.f;
+    x[2] = tsqrt2 * (x[1] - x[2]);
+    x[1] = x1;
+    return 0;
+L103:
+    cosqb1_(n, &x[1], &wsave[1], &wsave[*n + 1]);
+    return 0;
+} /* cosqb_ */
+
+/*  ------ File cosqb1.f ------ */
+/* Subroutine */ int cosqb1_(integer *n, r_4 *x, r_4 *w, r_4 *xh)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int rfftb_(integer *, r_4 *, r_4 *);
+    static integer kc, np2, ns2;
+    static r_4 xim1;
+
+    /* Parameter adjustments */
+    --xh;
+    --w;
+    --x;
+
+    /* Function Body */
+    ns2 = (*n + 1) / 2;
+    np2 = *n + 2;
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xim1 = x[i__ - 1] + x[i__];
+	x[i__] -= x[i__ - 1];
+	x[i__ - 1] = xim1;
+/* L101: */
+    }
+    x[1] += x[1];
+    modn = *n % 2;
+    if (modn == 0) {
+	x[*n] += x[*n];
+    }
+    rfftb_(n, &x[1], &xh[1]);
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	xh[k] = w[k - 1] * x[kc] + w[kc - 1] * x[k];
+	xh[kc] = w[k - 1] * x[k] - w[kc - 1] * x[kc];
+/* L102: */
+    }
+    if (modn == 0) {
+	x[ns2 + 1] = w[ns2] * (x[ns2 + 1] + x[ns2 + 1]);
+    }
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	x[k] = xh[k] + xh[kc];
+	x[kc] = xh[k] - xh[kc];
+/* L103: */
+    }
+    x[1] += x[1];
+    return 0;
+} /* cosqb1_ */
+
+/*  ------ File cosqf.f ------ */
+/* Subroutine */ int cosqf_(integer *n, r_4 *x, r_4 *wsave)
+{
+    /* Initialized data */
+
+    static r_4 sqrt2 = 1.4142135623731f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static r_4 tsqx;
+    extern /* Subroutine */ int cosqf1_(integer *, r_4 *, r_4 *, r_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L102;
+    } else if (i__1 == 0) {
+	goto L101;
+    } else {
+	goto L103;
+    }
+L101:
+    tsqx = sqrt2 * x[2];
+    x[2] = x[1] - tsqx;
+    x[1] += tsqx;
+L102:
+    return 0;
+L103:
+    cosqf1_(n, &x[1], &wsave[1], &wsave[*n + 1]);
+    return 0;
+} /* cosqf_ */
+
+/*  ------ File cosqf1.f ------ */
+/* Subroutine */ int cosqf1_(integer *n, r_4 *x, r_4 *w, r_4 *xh)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int rfftf_(integer *, r_4 *, r_4 *);
+    static integer kc, np2, ns2;
+    static r_4 xim1;
+
+    /* Parameter adjustments */
+    --xh;
+    --w;
+    --x;
+
+    /* Function Body */
+    ns2 = (*n + 1) / 2;
+    np2 = *n + 2;
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	xh[k] = x[k] + x[kc];
+	xh[kc] = x[k] - x[kc];
+/* L101: */
+    }
+    modn = *n % 2;
+    if (modn == 0) {
+	xh[ns2 + 1] = x[ns2 + 1] + x[ns2 + 1];
+    }
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	x[k] = w[k - 1] * xh[kc] + w[kc - 1] * xh[k];
+	x[kc] = w[k - 1] * xh[k] - w[kc - 1] * xh[kc];
+/* L102: */
+    }
+    if (modn == 0) {
+	x[ns2 + 1] = w[ns2] * xh[ns2 + 1];
+    }
+    rfftf_(n, &x[1], &xh[1]);
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xim1 = x[i__ - 1] - x[i__];
+	x[i__] = x[i__ - 1] + x[i__];
+	x[i__ - 1] = xim1;
+/* L103: */
+    }
+    return 0;
+} /* cosqf1_ */
+
+/*  ------ File cosqi.f ------ */
+/* Subroutine */ int cosqi_(integer *n, r_4 *wsave)
+{
+    /* Initialized data */
+
+    static r_4 pih = 1.57079632679491f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc);    commente - Remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int rffti_(integer *, r_4 *);
+    static r_4 fk, dt;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    dt = pih / (r_4) (*n);
+    fk = 0.f;
+    i__1 = *n;
+    for (k = 1; k <= i__1; ++k) {
+	fk += 1.f;
+	wsave[k] = cos(fk * dt);
+/* L101: */
+    }
+    rffti_(n, &wsave[*n + 1]);
+    return 0;
+} /* cosqi_ */
+
+/*  ------ File cost.f ------ */
+/* Subroutine */ int cost_(integer *n, r_4 *x, r_4 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int rfftf_(integer *, r_4 *, r_4 *);
+    static r_4 c1, t1, t2;
+    static integer kc;
+    static r_4 xi;
+    static integer nm1, np1;
+    static r_4 x1h;
+    static integer ns2;
+    static r_4 tx2, x1p3, xim2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    nm1 = *n - 1;
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    if ((i__1 = *n - 2) < 0) {
+	goto L106;
+    } else if (i__1 == 0) {
+	goto L101;
+    } else {
+	goto L102;
+    }
+L101:
+    x1h = x[1] + x[2];
+    x[2] = x[1] - x[2];
+    x[1] = x1h;
+    return 0;
+L102:
+    if (*n > 3) {
+	goto L103;
+    }
+    x1p3 = x[1] + x[3];
+    tx2 = x[2] + x[2];
+    x[2] = x[1] - x[3];
+    x[1] = x1p3 + tx2;
+    x[3] = x1p3 - tx2;
+    return 0;
+L103:
+    c1 = x[1] - x[*n];
+    x[1] += x[*n];
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np1 - k;
+	t1 = x[k] + x[kc];
+	t2 = x[k] - x[kc];
+	c1 += wsave[kc] * t2;
+	t2 = wsave[k] * t2;
+	x[k] = t1 - t2;
+	x[kc] = t1 + t2;
+/* L104: */
+    }
+    modn = *n % 2;
+    if (modn != 0) {
+	x[ns2 + 1] += x[ns2 + 1];
+    }
+    rfftf_(&nm1, &x[1], &wsave[*n + 1]);
+    xim2 = x[2];
+    x[2] = c1;
+    i__1 = *n;
+    for (i__ = 4; i__ <= i__1; i__ += 2) {
+	xi = x[i__];
+	x[i__] = x[i__ - 2] - x[i__ - 1];
+	x[i__ - 1] = xim2;
+	xim2 = xi;
+/* L105: */
+    }
+    if (modn != 0) {
+	x[*n] = xim2;
+    }
+L106:
+    return 0;
+} /* cost_ */
+
+/*  ------ File costi.f ------ */
+/* Subroutine */ int costi_(integer *n, r_4 *wsave)
+{
+    /* Initialized data */
+
+    static r_4 pi = 3.14159265358979f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 sin(r_8truc), cos(r_8truc);  commente - Remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int rffti_(integer *, r_4 *);
+    static integer kc;
+    static r_4 fk, dt;
+    static integer nm1, np1, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n <= 3) {
+	return 0;
+    }
+    nm1 = *n - 1;
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    dt = pi / (r_4) nm1;
+    fk = 0.f;
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np1 - k;
+	fk += 1.f;
+	wsave[k] = sin(fk * dt) * 2.f;
+	wsave[kc] = cos(fk * dt) * 2.f;
+/* L101: */
+    }
+    rffti_(&nm1, &wsave[*n + 1]);
+    return 0;
+} /* costi_ */
+
+/*  ------ File ezfft1.f ------ */
+/* Subroutine */ int ezfft1_(integer *n, r_4 *wa, int_4 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 4,2,3,5 };
+    static r_4 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);  commente - Remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static r_4 argh;
+    static integer ntry, i__, j, k1, l1, l2, ib, ii, nf, ip, nl, is, nq, nr;
+    static r_4 ch1, sh1;
+    static integer ido, ipm;
+    static r_4 dch1, ch1h, arg1, dsh1;
+    static integer nfm1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    argh = tpi / (r_4) (*n);
+    is = 0;
+    nfm1 = nf - 1;
+    l1 = 1;
+    if (nfm1 == 0) {
+	return 0;
+    }
+    i__1 = nfm1;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = l1 * ip;
+	ido = *n / l2;
+	ipm = ip - 1;
+	arg1 = (r_4) l1 * argh;
+	ch1 = 1.f;
+	sh1 = 0.f;
+	dch1 = cos(arg1);
+	dsh1 = sin(arg1);
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    ch1h = dch1 * ch1 - dsh1 * sh1;
+	    sh1 = dch1 * sh1 + dsh1 * ch1;
+	    ch1 = ch1h;
+	    i__ = is + 2;
+	    wa[i__ - 1] = ch1;
+	    wa[i__] = sh1;
+	    if (ido < 5) {
+		goto L109;
+	    }
+	    i__3 = ido;
+	    for (ii = 5; ii <= i__3; ii += 2) {
+		i__ += 2;
+		wa[i__ - 1] = ch1 * wa[i__ - 3] - sh1 * wa[i__ - 2];
+		wa[i__] = ch1 * wa[i__ - 2] + sh1 * wa[i__ - 3];
+/* L108: */
+	    }
+L109:
+	    is += ido;
+/* L110: */
+	}
+	l1 = l2;
+/* L111: */
+    }
+    return 0;
+} /* ezfft1_ */
+
+/*  ------ File ezfftb.f ------ */
+/* Subroutine */ int ezfftb_(integer *n, r_4 *r__, r_4 *azero, r_4 *a, 
+	r_4 *b, r_4 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int rfftb_(integer *, r_4 *, r_4 *);
+    static integer ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --b;
+    --a;
+    --r__;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    r__[1] = *azero;
+    return 0;
+L102:
+    r__[1] = *azero + a[1];
+    r__[2] = *azero - a[1];
+    return 0;
+L103:
+    ns2 = (*n - 1) / 2;
+    i__1 = ns2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	r__[i__ * 2] = a[i__] * .5f;
+	r__[(i__ << 1) + 1] = b[i__] * -.5f;
+/* L104: */
+    }
+    r__[1] = *azero;
+    if (*n % 2 == 0) {
+	r__[*n] = a[ns2 + 1];
+    }
+    rfftb_(n, &r__[1], &wsave[*n + 1]);
+    return 0;
+} /* ezfftb_ */
+
+/*  ------ File ezfftf.f ------ */
+/* Subroutine */ int ezfftf_(integer *n, r_4 *r__, r_4 *azero, r_4 *a, 
+	r_4 *b, r_4 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int rfftf_(integer *, r_4 *, r_4 *);
+    static r_4 cf;
+    static integer ns2;
+    static r_4 cfm;
+    static integer ns2m;
+
+
+/*                       VERSION 3  JUNE 1979 */
+
+    /* Parameter adjustments */
+    --wsave;
+    --b;
+    --a;
+    --r__;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    *azero = r__[1];
+    return 0;
+L102:
+    *azero = (r__[1] + r__[2]) * .5f;
+    a[1] = (r__[1] - r__[2]) * .5f;
+    return 0;
+L103:
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wsave[i__] = r__[i__];
+/* L104: */
+    }
+    rfftf_(n, &wsave[1], &wsave[*n + 1]);
+    cf = 2.f / (r_4) (*n);
+    cfm = -cf;
+    *azero = cf * .5f * wsave[1];
+    ns2 = (*n + 1) / 2;
+    ns2m = ns2 - 1;
+    i__1 = ns2m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	a[i__] = cf * wsave[i__ * 2];
+	b[i__] = cfm * wsave[(i__ << 1) + 1];
+/* L105: */
+    }
+    if (*n % 2 == 1) {
+	return 0;
+    }
+    a[ns2] = cf * .5f * wsave[*n];
+    b[ns2] = 0.f;
+    return 0;
+} /* ezfftf_ */
+
+/*  ------ File ezffti.f ------ */
+/* Subroutine */ int ezffti_(integer *n, r_4 *wsave)
+{
+    extern /* Subroutine */ int ezfft1_(integer *, r_4 *, int_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    ezfft1_(n, &wsave[(*n << 1) + 1], (integer*)&wsave[*n * 3 + 1]);
+    return 0;
+} /* ezffti_ */
+
+/*  ------ File passb.f ------ */
+/* Subroutine */ int passb_(integer *nac, integer *ido, integer *ip, integer *
+	l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, 
+	r_4 *wa)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer idij, idlj, idot, ipph, i__, j, k, l, jc, lc, ik, nt, idj, 
+	    idl, inc, idp;
+    static r_4 wai, war;
+    static integer ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    idot = *ido / 2;
+    nt = *ip * *idl1;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    idp = *ip * *ido;
+
+    if (*ido < *l1) {
+	goto L106;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L101: */
+	    }
+/* L102: */
+	}
+/* L103: */
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+    goto L112;
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L107: */
+	    }
+/* L108: */
+	}
+/* L109: */
+    }
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L110: */
+	}
+/* L111: */
+    }
+L112:
+    idl = 2 - *ido;
+    inc = 0;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	idl += *ido;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + wa[idl - 1] * ch2[ik 
+		    + (ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = wa[idl] * ch2[ik + *ip * ch2_dim1];
+/* L113: */
+	}
+	idlj = idl;
+	inc += *ido;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    idlj += inc;
+	    if (idlj > idp) {
+		idlj -= idp;
+	    }
+	    war = wa[idlj - 1];
+	    wai = wa[idlj];
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += war * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] += wai * ch2[ik + jc * ch2_dim1];
+/* L114: */
+	    }
+/* L115: */
+	}
+/* L116: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L117: */
+	}
+/* L118: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *idl1;
+	for (ik = 2; ik <= i__2; ik += 2) {
+	    ch2[ik - 1 + j * ch2_dim1] = c2[ik - 1 + j * c2_dim1] - c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik - 1 + jc * ch2_dim1] = c2[ik - 1 + j * c2_dim1] + c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik + j * ch2_dim1] = c2[ik + j * c2_dim1] + c2[ik - 1 + jc * 
+		    c2_dim1];
+	    ch2[ik + jc * ch2_dim1] = c2[ik + j * c2_dim1] - c2[ik - 1 + jc * 
+		    c2_dim1];
+/* L119: */
+	}
+/* L120: */
+    }
+    *nac = 1;
+    if (*ido == 2) {
+	return 0;
+    }
+    *nac = 0;
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L121: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+	    c1[(k + j * c1_dim2) * c1_dim1 + 2] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 2];
+/* L122: */
+	}
+/* L123: */
+    }
+    if (idot > *l1) {
+	goto L127;
+    }
+    idij = 0;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idij += 2;
+	i__2 = *ido;
+	for (i__ = 4; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L124: */
+	    }
+/* L125: */
+	}
+/* L126: */
+    }
+    return 0;
+L127:
+    idj = 2 - *ido;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idj += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = idj;
+	    i__3 = *ido;
+	    for (i__ = 4; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L128: */
+	    }
+/* L129: */
+	}
+/* L130: */
+    }
+    return 0;
+} /* passb_ */
+
+/*  ------ File passb2.f ------ */
+/* Subroutine */ int passb2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    if (*ido > 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 + 2] + 
+		cc[((k << 1) + 2) * cc_dim1 + 2];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 
+		+ 2] - cc[((k << 1) + 2) * cc_dim1 + 2];
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[i__ - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] + cc[i__ + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] - cc[i__ + ((k << 1) + 2)
+		     * cc_dim1];
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ti2 + 
+		    wa1[i__] * tr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * tr2 
+		    - wa1[i__] * ti2;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passb2_ */
+
+/*  ------ File passb3.f ------ */
+/* Subroutine */ int passb3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2)
+{
+    /* Initialized data */
+
+    static r_4 taur = -.5f;
+    static r_4 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[(k * 3 + 2) * cc_dim1 + 1] + cc[(k * 3 + 3) * cc_dim1 + 1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ti2 = cc[(k * 3 + 2) * cc_dim1 + 2] + cc[(k * 3 + 3) * cc_dim1 + 2];
+	ci2 = cc[(k * 3 + 1) * cc_dim1 + 2] + taur * ti2;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 3 + 1) * cc_dim1 + 2] + ti2;
+	cr3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 1] - cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ci3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 2] - cc[(k * 3 + 3) * 
+		cc_dim1 + 2]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci2 - cr3;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    tr2 = cc[i__ - 1 + (k * 3 + 2) * cc_dim1] + cc[i__ - 1 + (k * 3 + 
+		    3) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 2) * cc_dim1] + cc[i__ + (k * 3 + 3) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 2) * cc_dim1] - cc[i__ - 1 + (
+		    k * 3 + 3) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 2) * cc_dim1] - cc[i__ + (k * 3 + 
+		    3) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 + 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    - wa1[i__] * di2;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 + wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 - 
+		    wa2[i__] * di3;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passb3_ */
+
+/*  ------ File passb4.f ------ */
+/* Subroutine */ int passb4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 1) * cc_dim1 + 2] - cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	ti2 = cc[((k << 2) + 1) * cc_dim1 + 2] + cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	tr4 = cc[((k << 2) + 4) * cc_dim1 + 2] - cc[((k << 2) + 2) * cc_dim1 
+		+ 2];
+	ti3 = cc[((k << 2) + 2) * cc_dim1 + 2] + cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ti4 = cc[((k << 2) + 2) * cc_dim1 + 1] - cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	tr3 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = ti2 + ti3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ti2 - ti3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 + tr4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ti1 + ti4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ti1 - ti4;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 2) * cc_dim1] + cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 4) * cc_dim1] - cc[i__ + ((k << 2) + 2)
+		     * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 + tr4;
+	    cr4 = tr1 - tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * cr2 
+		    - wa1[i__] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ci2 + 
+		    wa1[i__] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * cr3 - 
+		    wa2[i__] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * ci3 + wa2[
+		    i__] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * cr4 
+		    - wa3[i__] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * ci4 + 
+		    wa3[i__] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passb4_ */
+
+/*  ------ File passb5.f ------ */
+/* Subroutine */ int passb5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4)
+{
+    /* Initialized data */
+
+    static r_4 tr11 = .309016994374947f;
+    static r_4 ti11 = .951056516295154f;
+    static r_4 tr12 = -.809016994374947f;
+    static r_4 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 2) * cc_dim1 + 2] - cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti2 = cc[(k * 5 + 2) * cc_dim1 + 2] + cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti4 = cc[(k * 5 + 3) * cc_dim1 + 2] - cc[(k * 5 + 4) * cc_dim1 + 2];
+	ti3 = cc[(k * 5 + 3) * cc_dim1 + 2] + cc[(k * 5 + 4) * cc_dim1 + 2];
+	tr5 = cc[(k * 5 + 2) * cc_dim1 + 1] - cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[(k * 5 + 2) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr4 = cc[(k * 5 + 3) * cc_dim1 + 1] - cc[(k * 5 + 4) * cc_dim1 + 1];
+	tr3 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 4) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 5 + 1) * cc_dim1 + 2] + ti2 
+		+ ti3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	ci2 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr11 * ti2 + tr12 * ti3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci3 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr12 * ti2 + tr11 * ti3;
+	cr5 = ti11 * tr5 + ti12 * tr4;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	cr4 = ti12 * tr5 - ti11 * tr4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci3 + cr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ci3 - cr4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 2] = ci2 - cr5;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti5 = cc[i__ + (k * 5 + 2) * cc_dim1] - cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 2) * cc_dim1] + cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    - wa1[i__] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 + 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 - 
+		    wa2[i__] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 + wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * dr4 
+		    - wa3[i__] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * di4 + 
+		    wa3[i__] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * dr5 - 
+		    wa4[i__] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * di5 + wa4[
+		    i__] * dr5;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passb5_ */
+
+/*  ------ File passf.f ------ */
+/* Subroutine */ int passf_(integer *nac, integer *ido, integer *ip, integer *
+	l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, 
+	r_4 *wa)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer idij, idlj, idot, ipph, i__, j, k, l, jc, lc, ik, nt, idj, 
+	    idl, inc, idp;
+    static r_4 wai, war;
+    static integer ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    idot = *ido / 2;
+    nt = *ip * *idl1;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    idp = *ip * *ido;
+
+    if (*ido < *l1) {
+	goto L106;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L101: */
+	    }
+/* L102: */
+	}
+/* L103: */
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+    goto L112;
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L107: */
+	    }
+/* L108: */
+	}
+/* L109: */
+    }
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L110: */
+	}
+/* L111: */
+    }
+L112:
+    idl = 2 - *ido;
+    inc = 0;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	idl += *ido;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + wa[idl - 1] * ch2[ik 
+		    + (ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = -wa[idl] * ch2[ik + *ip * ch2_dim1];
+/* L113: */
+	}
+	idlj = idl;
+	inc += *ido;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    idlj += inc;
+	    if (idlj > idp) {
+		idlj -= idp;
+	    }
+	    war = wa[idlj - 1];
+	    wai = wa[idlj];
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += war * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] -= wai * ch2[ik + jc * ch2_dim1];
+/* L114: */
+	    }
+/* L115: */
+	}
+/* L116: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L117: */
+	}
+/* L118: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *idl1;
+	for (ik = 2; ik <= i__2; ik += 2) {
+	    ch2[ik - 1 + j * ch2_dim1] = c2[ik - 1 + j * c2_dim1] - c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik - 1 + jc * ch2_dim1] = c2[ik - 1 + j * c2_dim1] + c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik + j * ch2_dim1] = c2[ik + j * c2_dim1] + c2[ik - 1 + jc * 
+		    c2_dim1];
+	    ch2[ik + jc * ch2_dim1] = c2[ik + j * c2_dim1] - c2[ik - 1 + jc * 
+		    c2_dim1];
+/* L119: */
+	}
+/* L120: */
+    }
+    *nac = 1;
+    if (*ido == 2) {
+	return 0;
+    }
+    *nac = 0;
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L121: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+	    c1[(k + j * c1_dim2) * c1_dim1 + 2] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 2];
+/* L122: */
+	}
+/* L123: */
+    }
+    if (idot > *l1) {
+	goto L127;
+    }
+    idij = 0;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idij += 2;
+	i__2 = *ido;
+	for (i__ = 4; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] + wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] - wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L124: */
+	    }
+/* L125: */
+	}
+/* L126: */
+    }
+    return 0;
+L127:
+    idj = 2 - *ido;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idj += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = idj;
+	    i__3 = *ido;
+	    for (i__ = 4; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] + wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] - wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L128: */
+	    }
+/* L129: */
+	}
+/* L130: */
+    }
+    return 0;
+} /* passf_ */
+
+/*  ------ File passf2.f ------ */
+/* Subroutine */ int passf2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    if (*ido > 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 + 2] + 
+		cc[((k << 1) + 2) * cc_dim1 + 2];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 
+		+ 2] - cc[((k << 1) + 2) * cc_dim1 + 2];
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[i__ - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] + cc[i__ + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] - cc[i__ + ((k << 1) + 2)
+		     * cc_dim1];
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ti2 - 
+		    wa1[i__] * tr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * tr2 
+		    + wa1[i__] * ti2;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passf2_ */
+
+/*  ------ File passf3.f ------ */
+/* Subroutine */ int passf3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2)
+{
+    /* Initialized data */
+
+    static r_4 taur = -.5f;
+    static r_4 taui = -.866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[(k * 3 + 2) * cc_dim1 + 1] + cc[(k * 3 + 3) * cc_dim1 + 1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ti2 = cc[(k * 3 + 2) * cc_dim1 + 2] + cc[(k * 3 + 3) * cc_dim1 + 2];
+	ci2 = cc[(k * 3 + 1) * cc_dim1 + 2] + taur * ti2;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 3 + 1) * cc_dim1 + 2] + ti2;
+	cr3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 1] - cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ci3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 2] - cc[(k * 3 + 3) * 
+		cc_dim1 + 2]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci2 - cr3;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    tr2 = cc[i__ - 1 + (k * 3 + 2) * cc_dim1] + cc[i__ - 1 + (k * 3 + 
+		    3) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 2) * cc_dim1] + cc[i__ + (k * 3 + 3) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 2) * cc_dim1] - cc[i__ - 1 + (
+		    k * 3 + 3) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 2) * cc_dim1] - cc[i__ + (k * 3 + 
+		    3) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 - 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    + wa1[i__] * di2;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 - wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 + 
+		    wa2[i__] * di3;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passf3_ */
+
+/*  ------ File passf4.f ------ */
+/* Subroutine */ int passf4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 1) * cc_dim1 + 2] - cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	ti2 = cc[((k << 2) + 1) * cc_dim1 + 2] + cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	tr4 = cc[((k << 2) + 2) * cc_dim1 + 2] - cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	ti3 = cc[((k << 2) + 2) * cc_dim1 + 2] + cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ti4 = cc[((k << 2) + 4) * cc_dim1 + 1] - cc[((k << 2) + 2) * cc_dim1 
+		+ 1];
+	tr3 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = ti2 + ti3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ti2 - ti3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 + tr4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ti1 + ti4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ti1 - ti4;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 2) * cc_dim1] + cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 2) * cc_dim1] - cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 4) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 2) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 + tr4;
+	    cr4 = tr1 - tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * cr2 
+		    + wa1[i__] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ci2 - 
+		    wa1[i__] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * cr3 + 
+		    wa2[i__] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * ci3 - wa2[
+		    i__] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * cr4 
+		    + wa3[i__] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * ci4 - 
+		    wa3[i__] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passf4_ */
+
+/*  ------ File passf5.f ------ */
+/* Subroutine */ int passf5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4)
+{
+    /* Initialized data */
+
+    static r_4 tr11 = .309016994374947f;
+    static r_4 ti11 = -.951056516295154f;
+    static r_4 tr12 = -.809016994374947f;
+    static r_4 ti12 = -.587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_4 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 2) * cc_dim1 + 2] - cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti2 = cc[(k * 5 + 2) * cc_dim1 + 2] + cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti4 = cc[(k * 5 + 3) * cc_dim1 + 2] - cc[(k * 5 + 4) * cc_dim1 + 2];
+	ti3 = cc[(k * 5 + 3) * cc_dim1 + 2] + cc[(k * 5 + 4) * cc_dim1 + 2];
+	tr5 = cc[(k * 5 + 2) * cc_dim1 + 1] - cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[(k * 5 + 2) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr4 = cc[(k * 5 + 3) * cc_dim1 + 1] - cc[(k * 5 + 4) * cc_dim1 + 1];
+	tr3 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 4) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 5 + 1) * cc_dim1 + 2] + ti2 
+		+ ti3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	ci2 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr11 * ti2 + tr12 * ti3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci3 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr12 * ti2 + tr11 * ti3;
+	cr5 = ti11 * tr5 + ti12 * tr4;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	cr4 = ti12 * tr5 - ti11 * tr4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci3 + cr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ci3 - cr4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 2] = ci2 - cr5;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti5 = cc[i__ + (k * 5 + 2) * cc_dim1] - cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 2) * cc_dim1] + cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    + wa1[i__] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 - 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 + 
+		    wa2[i__] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 - wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * dr4 
+		    + wa3[i__] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * di4 - 
+		    wa3[i__] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * dr5 + 
+		    wa4[i__] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * di5 - wa4[
+		    i__] * dr5;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* passf5_ */
+
+/*  ------ File radb2.f ------ */
+/* Subroutine */ int radb2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[*ido + ((k << 1) + 2) * cc_dim1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[*ido + ((k << 1) + 2) * cc_dim1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[ic - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[ic - 1 + ((k << 
+		    1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] - cc[ic + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] + cc[ic + ((k << 1) + 2) 
+		    * cc_dim1];
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * tr2 
+		    - wa1[i__ - 1] * ti2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * ti2 + 
+		    wa1[i__ - 1] * tr2;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[*ido + (k + ch_dim2) * ch_dim1] = cc[*ido + ((k << 1) + 1) * 
+		cc_dim1] + cc[*ido + ((k << 1) + 1) * cc_dim1];
+	ch[*ido + (k + (ch_dim2 << 1)) * ch_dim1] = -(cc[((k << 1) + 2) * 
+		cc_dim1 + 1] + cc[((k << 1) + 2) * cc_dim1 + 1]);
+/* L106: */
+    }
+L107:
+    return 0;
+} /* radb2_ */
+
+/*  ------ File radb3.f ------ */
+/* Subroutine */ int radb3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2)
+{
+    /* Initialized data */
+
+    static r_4 taur = -.5f;
+    static r_4 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[*ido + (k * 3 + 2) * cc_dim1] + cc[*ido + (k * 3 + 2) * 
+		cc_dim1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ci3 = taui * (cc[(k * 3 + 3) * cc_dim1 + 1] + cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    tr2 = cc[i__ - 1 + (k * 3 + 3) * cc_dim1] + cc[ic - 1 + (k * 3 + 
+		    2) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 3) * cc_dim1] - cc[ic + (k * 3 + 2) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 3) * cc_dim1] - cc[ic - 1 + (
+		    k * 3 + 2) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 3) * cc_dim1] + cc[ic + (k * 3 + 
+		    2) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * dr2 
+		    - wa1[i__ - 1] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * di2 + 
+		    wa1[i__ - 1] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * dr3 - 
+		    wa2[i__ - 1] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * di3 + wa2[
+		    i__ - 1] * dr3;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* radb3_ */
+
+/*  ------ File radb4.f ------ */
+/* Subroutine */ int radb4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3)
+{
+    /* Initialized data */
+
+    static r_4 sqrt2 = 1.414213562373095f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[*ido + ((k << 2) + 4) * 
+		cc_dim1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[*ido + ((k << 2) + 4) * 
+		cc_dim1];
+	tr3 = cc[*ido + ((k << 2) + 2) * cc_dim1] + cc[*ido + ((k << 2) + 2) *
+		 cc_dim1];
+	tr4 = cc[((k << 2) + 3) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 + tr4;
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[ic + ((k << 2) + 4) 
+		    * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[ic + ((k << 2) + 4) 
+		    * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 3) * cc_dim1] - cc[ic + ((k << 2) + 2) 
+		    * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 3) * cc_dim1] + cc[ic + ((k << 2) + 2) 
+		    * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[ic - 1 + ((k << 
+		    2) + 4) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[ic - 1 + ((k << 
+		    2) + 4) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 3) * cc_dim1] - cc[ic - 1 + ((k << 
+		    2) + 2) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 3) * cc_dim1] + cc[ic - 1 + ((k << 
+		    2) + 2) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 - tr4;
+	    cr4 = tr1 + tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * cr2 
+		    - wa1[i__ - 1] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * ci2 + 
+		    wa1[i__ - 1] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * cr3 - 
+		    wa2[i__ - 1] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * ci3 + wa2[
+		    i__ - 1] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * cr4 
+		    - wa3[i__ - 1] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * ci4 + 
+		    wa3[i__ - 1] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ti2 = cc[((k << 2) + 4) * cc_dim1 + 1] - cc[((k << 2) + 2) * cc_dim1 
+		+ 1];
+	tr1 = cc[*ido + ((k << 2) + 1) * cc_dim1] - cc[*ido + ((k << 2) + 3) *
+		 cc_dim1];
+	tr2 = cc[*ido + ((k << 2) + 1) * cc_dim1] + cc[*ido + ((k << 2) + 3) *
+		 cc_dim1];
+	ch[*ido + (k + ch_dim2) * ch_dim1] = tr2 + tr2;
+	ch[*ido + (k + (ch_dim2 << 1)) * ch_dim1] = sqrt2 * (tr1 - ti1);
+	ch[*ido + (k + ch_dim2 * 3) * ch_dim1] = ti2 + ti2;
+	ch[*ido + (k + (ch_dim2 << 2)) * ch_dim1] = -sqrt2 * (tr1 + ti1);
+/* L106: */
+    }
+L107:
+    return 0;
+} /* radb4_ */
+
+/*  ------ File radb5.f ------ */
+/* Subroutine */ int radb5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4)
+{
+    /* Initialized data */
+
+    static r_4 tr11 = .309016994374947f;
+    static r_4 ti11 = .951056516295154f;
+    static r_4 tr12 = -.809016994374947f;
+    static r_4 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 3) * cc_dim1 + 1];
+	ti4 = cc[(k * 5 + 5) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[*ido + (k * 5 + 2) * cc_dim1] + cc[*ido + (k * 5 + 2) * 
+		cc_dim1];
+	tr3 = cc[*ido + (k * 5 + 4) * cc_dim1] + cc[*ido + (k * 5 + 4) * 
+		cc_dim1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ti5 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[ic + (k * 5 + 2) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[ic + (k * 5 + 2) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 5) * cc_dim1] + cc[ic + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 5) * cc_dim1] - cc[ic + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[ic - 1 + (k * 5 + 
+		    2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[ic - 1 + (k * 5 + 
+		    2) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 5) * cc_dim1] - cc[ic - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 5) * cc_dim1] + cc[ic - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * dr2 
+		    - wa1[i__ - 1] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * di2 + 
+		    wa1[i__ - 1] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * dr3 - 
+		    wa2[i__ - 1] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * di3 + wa2[
+		    i__ - 1] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * dr4 
+		    - wa3[i__ - 1] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * di4 + 
+		    wa3[i__ - 1] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 2] * dr5 - 
+		    wa4[i__ - 1] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 2] * di5 + wa4[
+		    i__ - 1] * dr5;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* radb5_ */
+
+/*  ------ File radbg.f ------ */
+/* Subroutine */ int radbg_(integer *ido, integer *ip, integer *l1, integer *
+	idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa)
+{
+    /* Initialized data */
+
+    static r_4 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);  commente - Remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer idij, ipph, i__, j, k, l, j2, ic, jc, lc, ik, is;
+    static r_4 dc2, ai1, ai2, ar1, ar2, ds2;
+    static integer nbd;
+    static r_4 dcp, arg, dsp, ar1h, ar2h;
+    static integer idp2, ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    arg = tpi / (r_4) (*ip);
+    dcp = cos(arg);
+    dsp = sin(arg);
+    idp2 = *ido + 2;
+    nbd = (*ido - 1) / 2;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    if (*ido < *l1) {
+	goto L103;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L101: */
+	}
+/* L102: */
+    }
+    goto L106;
+L103:
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = cc[*ido + (j2 - 2 + k * 
+		    cc_dim2) * cc_dim1] + cc[*ido + (j2 - 2 + k * cc_dim2) * 
+		    cc_dim1];
+	    ch[(k + jc * ch_dim2) * ch_dim1 + 1] = cc[(j2 - 1 + k * cc_dim2) *
+		     cc_dim1 + 1] + cc[(j2 - 1 + k * cc_dim2) * cc_dim1 + 1];
+/* L107: */
+	}
+/* L108: */
+    }
+    if (*ido == 1) {
+	goto L116;
+    }
+    if (nbd < *l1) {
+	goto L112;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ic = idp2 - i__;
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] + cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] - cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] - cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] + cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+/* L109: */
+	    }
+/* L110: */
+	}
+/* L111: */
+    }
+    goto L116;
+L112:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] + cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] - cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] - cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] + cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+/* L113: */
+	    }
+/* L114: */
+	}
+/* L115: */
+    }
+L116:
+    ar1 = 1.f;
+    ai1 = 0.f;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	ar1h = dcp * ar1 - dsp * ai1;
+	ai1 = dcp * ai1 + dsp * ar1;
+	ar1 = ar1h;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + ar1 * ch2[ik + (
+		    ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = ai1 * ch2[ik + *ip * ch2_dim1];
+/* L117: */
+	}
+	dc2 = ar1;
+	ds2 = ai1;
+	ar2 = ar1;
+	ai2 = ai1;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    ar2h = dc2 * ar2 - ds2 * ai2;
+	    ai2 = dc2 * ai2 + ds2 * ar2;
+	    ar2 = ar2h;
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += ar2 * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] += ai2 * ch2[ik + jc * ch2_dim1];
+/* L118: */
+	    }
+/* L119: */
+	}
+/* L120: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L121: */
+	}
+/* L122: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1] - c1[(k + jc * c1_dim2) * c1_dim1 + 1];
+	    ch[(k + jc * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1] + c1[(k + jc * c1_dim2) * c1_dim1 + 1];
+/* L123: */
+	}
+/* L124: */
+    }
+    if (*ido == 1) {
+	goto L132;
+    }
+    if (nbd < *l1) {
+	goto L128;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k + 
+			j * c1_dim2) * c1_dim1] - c1[i__ + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k 
+			+ j * c1_dim2) * c1_dim1] + c1[i__ + (k + jc * 
+			c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] + c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] - c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+/* L125: */
+	    }
+/* L126: */
+	}
+/* L127: */
+    }
+    goto L132;
+L128:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k + 
+			j * c1_dim2) * c1_dim1] - c1[i__ + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k 
+			+ j * c1_dim2) * c1_dim1] + c1[i__ + (k + jc * 
+			c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] + c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] - c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+/* L129: */
+	    }
+/* L130: */
+	}
+/* L131: */
+    }
+L132:
+    if (*ido == 1) {
+	return 0;
+    }
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L133: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+/* L134: */
+	}
+/* L135: */
+    }
+    if (nbd > *l1) {
+	goto L139;
+    }
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	idij = is;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L136: */
+	    }
+/* L137: */
+	}
+/* L138: */
+    }
+    goto L143;
+L139:
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = is;
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L140: */
+	    }
+/* L141: */
+	}
+/* L142: */
+    }
+L143:
+    return 0;
+} /* radbg_ */
+
+/*  ------ File radf2.f ------ */
+/* Subroutine */ int radf2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_offset, cc_dim1, cc_dim2, cc_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 3 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[((k << 1) + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+	ch[*ido + ((k << 1) + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] 
+		- cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    tr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    ti2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    ch[i__ + ((k << 1) + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ti2;
+	    ch[ic + ((k << 1) + 2) * ch_dim1] = ti2 - cc[i__ + (k + cc_dim2) *
+		     cc_dim1];
+	    ch[i__ - 1 + ((k << 1) + 1) * ch_dim1] = cc[i__ - 1 + (k + 
+		    cc_dim2) * cc_dim1] + tr2;
+	    ch[ic - 1 + ((k << 1) + 2) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2)
+		     * cc_dim1] - tr2;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[((k << 1) + 2) * ch_dim1 + 1] = -cc[*ido + (k + (cc_dim2 << 1)) * 
+		cc_dim1];
+	ch[*ido + ((k << 1) + 1) * ch_dim1] = cc[*ido + (k + cc_dim2) * 
+		cc_dim1];
+/* L106: */
+    }
+L107:
+    return 0;
+} /* radf2_ */
+
+/*  ------ File radf3.f ------ */
+/* Subroutine */ int radf3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2)
+{
+    /* Initialized data */
+
+    static r_4 taur = -.5f;
+    static r_4 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_offset, cc_dim1, cc_dim2, cc_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = (ch_dim1 << 2) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	cr2 = cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[(k * 3 + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + cr2;
+	ch[(k * 3 + 3) * ch_dim1 + 1] = taui * (cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1] - cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1]);
+	ch[*ido + (k * 3 + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		taur * cr2;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    dr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    di2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    dr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    di3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    cr2 = dr2 + dr3;
+	    ci2 = di2 + di3;
+	    ch[i__ - 1 + (k * 3 + 1) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2) *
+		     cc_dim1] + cr2;
+	    ch[i__ + (k * 3 + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ci2;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + taur * cr2;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + taur * ci2;
+	    tr3 = taui * (di2 - di3);
+	    ti3 = taui * (dr3 - dr2);
+	    ch[i__ - 1 + (k * 3 + 3) * ch_dim1] = tr2 + tr3;
+	    ch[ic - 1 + (k * 3 + 2) * ch_dim1] = tr2 - tr3;
+	    ch[i__ + (k * 3 + 3) * ch_dim1] = ti2 + ti3;
+	    ch[ic + (k * 3 + 2) * ch_dim1] = ti3 - ti2;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* radf3_ */
+
+/*  ------ File radf4.f ------ */
+/* Subroutine */ int radf4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3)
+{
+    /* Initialized data */
+
+    static r_4 hsqt2 = .7071067811865475f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_dim2, cc_offset, ch_dim1, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 5 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr1 = cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1] + cc[(k + (cc_dim2 << 2))
+		 * cc_dim1 + 1];
+	tr2 = cc[(k + cc_dim2) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[((k << 2) + 1) * ch_dim1 + 1] = tr1 + tr2;
+	ch[*ido + ((k << 2) + 4) * ch_dim1] = tr2 - tr1;
+	ch[*ido + ((k << 2) + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] 
+		- cc[(k + cc_dim2 * 3) * cc_dim1 + 1];
+	ch[((k << 2) + 3) * ch_dim1 + 1] = cc[(k + (cc_dim2 << 2)) * cc_dim1 
+		+ 1] - cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    cr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    ci2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    cr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    ci3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    cr4 = wa3[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * cc_dim1] 
+		    + wa3[i__ - 1] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1];
+	    ci4 = wa3[i__ - 2] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1] - 
+		    wa3[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * 
+		    cc_dim1];
+	    tr1 = cr2 + cr4;
+	    tr4 = cr4 - cr2;
+	    ti1 = ci2 + ci4;
+	    ti4 = ci2 - ci4;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + ci3;
+	    ti3 = cc[i__ + (k + cc_dim2) * cc_dim1] - ci3;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + cr3;
+	    tr3 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] - cr3;
+	    ch[i__ - 1 + ((k << 2) + 1) * ch_dim1] = tr1 + tr2;
+	    ch[ic - 1 + ((k << 2) + 4) * ch_dim1] = tr2 - tr1;
+	    ch[i__ + ((k << 2) + 1) * ch_dim1] = ti1 + ti2;
+	    ch[ic + ((k << 2) + 4) * ch_dim1] = ti1 - ti2;
+	    ch[i__ - 1 + ((k << 2) + 3) * ch_dim1] = ti4 + tr3;
+	    ch[ic - 1 + ((k << 2) + 2) * ch_dim1] = tr3 - ti4;
+	    ch[i__ + ((k << 2) + 3) * ch_dim1] = tr4 + ti3;
+	    ch[ic + ((k << 2) + 2) * ch_dim1] = tr4 - ti3;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = -hsqt2 * (cc[*ido + (k + (cc_dim2 << 1)) * cc_dim1] + cc[*ido + 
+		(k + (cc_dim2 << 2)) * cc_dim1]);
+	tr1 = hsqt2 * (cc[*ido + (k + (cc_dim2 << 1)) * cc_dim1] - cc[*ido + (
+		k + (cc_dim2 << 2)) * cc_dim1]);
+	ch[*ido + ((k << 2) + 1) * ch_dim1] = tr1 + cc[*ido + (k + cc_dim2) * 
+		cc_dim1];
+	ch[*ido + ((k << 2) + 3) * ch_dim1] = cc[*ido + (k + cc_dim2) * 
+		cc_dim1] - tr1;
+	ch[((k << 2) + 2) * ch_dim1 + 1] = ti1 - cc[*ido + (k + cc_dim2 * 3) *
+		 cc_dim1];
+	ch[((k << 2) + 4) * ch_dim1 + 1] = ti1 + cc[*ido + (k + cc_dim2 * 3) *
+		 cc_dim1];
+/* L106: */
+    }
+L107:
+    return 0;
+} /* radf4_ */
+
+/*  ------ File radf5.f ------ */
+/* Subroutine */ int radf5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, 
+	r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4)
+{
+    /* Initialized data */
+
+    static r_4 tr11 = .309016994374947f;
+    static r_4 ti11 = .951056516295154f;
+    static r_4 tr12 = -.809016994374947f;
+    static r_4 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_dim2, cc_offset, ch_dim1, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_4 ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, 
+	    dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 6 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	cr2 = cc[(k + cc_dim2 * 5) * cc_dim1 + 1] + cc[(k + (cc_dim2 << 1)) * 
+		cc_dim1 + 1];
+	ci5 = cc[(k + cc_dim2 * 5) * cc_dim1 + 1] - cc[(k + (cc_dim2 << 1)) * 
+		cc_dim1 + 1];
+	cr3 = cc[(k + (cc_dim2 << 2)) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ci4 = cc[(k + (cc_dim2 << 2)) * cc_dim1 + 1] - cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[(k * 5 + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + cr2 
+		+ cr3;
+	ch[*ido + (k * 5 + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		tr11 * cr2 + tr12 * cr3;
+	ch[(k * 5 + 3) * ch_dim1 + 1] = ti11 * ci5 + ti12 * ci4;
+	ch[*ido + (k * 5 + 4) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		tr12 * cr2 + tr11 * cr3;
+	ch[(k * 5 + 5) * ch_dim1 + 1] = ti12 * ci5 - ti11 * ci4;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    dr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    di2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    dr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    di3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    dr4 = wa3[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * cc_dim1] 
+		    + wa3[i__ - 1] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1];
+	    di4 = wa3[i__ - 2] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1] - 
+		    wa3[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * 
+		    cc_dim1];
+	    dr5 = wa4[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 5) * cc_dim1] + 
+		    wa4[i__ - 1] * cc[i__ + (k + cc_dim2 * 5) * cc_dim1];
+	    di5 = wa4[i__ - 2] * cc[i__ + (k + cc_dim2 * 5) * cc_dim1] - wa4[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 5) * cc_dim1];
+	    cr2 = dr2 + dr5;
+	    ci5 = dr5 - dr2;
+	    cr5 = di2 - di5;
+	    ci2 = di2 + di5;
+	    cr3 = dr3 + dr4;
+	    ci4 = dr4 - dr3;
+	    cr4 = di3 - di4;
+	    ci3 = di3 + di4;
+	    ch[i__ - 1 + (k * 5 + 1) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2) *
+		     cc_dim1] + cr2 + cr3;
+	    ch[i__ + (k * 5 + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ci2 + ci3;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + tr11 * cr2 + tr12 * 
+		    cr3;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + tr11 * ci2 + tr12 * ci3;
+	    tr3 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + tr12 * cr2 + tr11 * 
+		    cr3;
+	    ti3 = cc[i__ + (k + cc_dim2) * cc_dim1] + tr12 * ci2 + tr11 * ci3;
+	    tr5 = ti11 * cr5 + ti12 * cr4;
+	    ti5 = ti11 * ci5 + ti12 * ci4;
+	    tr4 = ti12 * cr5 - ti11 * cr4;
+	    ti4 = ti12 * ci5 - ti11 * ci4;
+	    ch[i__ - 1 + (k * 5 + 3) * ch_dim1] = tr2 + tr5;
+	    ch[ic - 1 + (k * 5 + 2) * ch_dim1] = tr2 - tr5;
+	    ch[i__ + (k * 5 + 3) * ch_dim1] = ti2 + ti5;
+	    ch[ic + (k * 5 + 2) * ch_dim1] = ti5 - ti2;
+	    ch[i__ - 1 + (k * 5 + 5) * ch_dim1] = tr3 + tr4;
+	    ch[ic - 1 + (k * 5 + 4) * ch_dim1] = tr3 - tr4;
+	    ch[i__ + (k * 5 + 5) * ch_dim1] = ti3 + ti4;
+	    ch[ic + (k * 5 + 4) * ch_dim1] = ti4 - ti3;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* radf5_ */
+
+/*  ------ File radfg.f ------ */
+/* Subroutine */ int radfg_(integer *ido, integer *ip, integer *l1, integer *
+	idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa)
+{
+    /* Initialized data */
+
+    static r_4 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);    */
+
+    /* Local variables */
+    static integer idij, ipph, i__, j, k, l, j2, ic, jc, lc, ik, is;
+    static r_4 dc2, ai1, ai2, ar1, ar2, ds2;
+    static integer nbd;
+    static r_4 dcp, arg, dsp, ar1h, ar2h;
+    static integer idp2, ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    arg = tpi / (r_4) (*ip);
+    dcp = cos(arg);
+    dsp = sin(arg);
+    ipph = (*ip + 1) / 2;
+    ipp2 = *ip + 2;
+    idp2 = *ido + 2;
+    nbd = (*ido - 1) / 2;
+    if (*ido == 1) {
+	goto L119;
+    }
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	ch2[ik + ch2_dim1] = c2[ik + c2_dim1];
+/* L101: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1];
+/* L102: */
+	}
+/* L103: */
+    }
+    if (nbd > *l1) {
+	goto L107;
+    }
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	idij = is;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[
+			i__ - 1 + (k + j * c1_dim2) * c1_dim1] + wa[idij] * 
+			c1[i__ + (k + j * c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[i__ 
+			+ (k + j * c1_dim2) * c1_dim1] - wa[idij] * c1[i__ - 
+			1 + (k + j * c1_dim2) * c1_dim1];
+/* L104: */
+	    }
+/* L105: */
+	}
+/* L106: */
+    }
+    goto L111;
+L107:
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = is;
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[
+			i__ - 1 + (k + j * c1_dim2) * c1_dim1] + wa[idij] * 
+			c1[i__ + (k + j * c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[i__ 
+			+ (k + j * c1_dim2) * c1_dim1] - wa[idij] * c1[i__ - 
+			1 + (k + j * c1_dim2) * c1_dim1];
+/* L108: */
+	    }
+/* L109: */
+	}
+/* L110: */
+    }
+L111:
+    if (nbd < *l1) {
+	goto L115;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + 
+			j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		c1[i__ - 1 + (k + jc * c1_dim2) * c1_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = ch[i__ + (k + j * 
+			ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + jc * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + jc 
+			* ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + j * ch_dim2)
+			 * ch_dim1];
+/* L112: */
+	    }
+/* L113: */
+	}
+/* L114: */
+    }
+    goto L121;
+L115:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + 
+			j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		c1[i__ - 1 + (k + jc * c1_dim2) * c1_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = ch[i__ + (k + j * 
+			ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + jc * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + jc 
+			* ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + j * ch_dim2)
+			 * ch_dim1];
+/* L116: */
+	    }
+/* L117: */
+	}
+/* L118: */
+    }
+    goto L121;
+L119:
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L120: */
+    }
+L121:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1] + ch[(k + jc * ch_dim2) * ch_dim1 + 1];
+	    c1[(k + jc * c1_dim2) * c1_dim1 + 1] = ch[(k + jc * ch_dim2) * 
+		    ch_dim1 + 1] - ch[(k + j * ch_dim2) * ch_dim1 + 1];
+/* L122: */
+	}
+/* L123: */
+    }
+
+    ar1 = 1.f;
+    ai1 = 0.f;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	ar1h = dcp * ar1 - dsp * ai1;
+	ai1 = dcp * ai1 + dsp * ar1;
+	ar1 = ar1h;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + l * ch2_dim1] = c2[ik + c2_dim1] + ar1 * c2[ik + (
+		    c2_dim1 << 1)];
+	    ch2[ik + lc * ch2_dim1] = ai1 * c2[ik + *ip * c2_dim1];
+/* L124: */
+	}
+	dc2 = ar1;
+	ds2 = ai1;
+	ar2 = ar1;
+	ai2 = ai1;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    ar2h = dc2 * ar2 - ds2 * ai2;
+	    ai2 = dc2 * ai2 + ds2 * ar2;
+	    ar2 = ar2h;
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		ch2[ik + l * ch2_dim1] += ar2 * c2[ik + j * c2_dim1];
+		ch2[ik + lc * ch2_dim1] += ai2 * c2[ik + jc * c2_dim1];
+/* L125: */
+	    }
+/* L126: */
+	}
+/* L127: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += c2[ik + j * c2_dim1];
+/* L128: */
+	}
+/* L129: */
+    }
+
+    if (*ido < *l1) {
+	goto L132;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    cc[i__ + (k * cc_dim2 + 1) * cc_dim1] = ch[i__ + (k + ch_dim2) * 
+		    ch_dim1];
+/* L130: */
+	}
+/* L131: */
+    }
+    goto L135;
+L132:
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    cc[i__ + (k * cc_dim2 + 1) * cc_dim1] = ch[i__ + (k + ch_dim2) * 
+		    ch_dim1];
+/* L133: */
+	}
+/* L134: */
+    }
+L135:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    cc[*ido + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[(k + j * ch_dim2)
+		     * ch_dim1 + 1];
+	    cc[(j2 - 1 + k * cc_dim2) * cc_dim1 + 1] = ch[(k + jc * ch_dim2) *
+		     ch_dim1 + 1];
+/* L136: */
+	}
+/* L137: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    if (nbd < *l1) {
+	goto L141;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ic = idp2 - i__;
+		cc[i__ - 1 + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + 
+			(k + j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[ic - 1 + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + (
+			k + j * ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[i__ + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		cc[ic + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + jc *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + j * ch_dim2) * 
+			ch_dim1];
+/* L138: */
+	    }
+/* L139: */
+	}
+/* L140: */
+    }
+    return 0;
+L141:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		cc[i__ - 1 + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + 
+			(k + j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[ic - 1 + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + (
+			k + j * ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[i__ + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		cc[ic + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + jc *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + j * ch_dim2) * 
+			ch_dim1];
+/* L142: */
+	    }
+/* L143: */
+	}
+/* L144: */
+    }
+    return 0;
+} /* radfg_ */
+
+/*  ------ File rfftb.f ------ */
+/* Subroutine */ int rfftb_(integer *n, r_4 *r__, r_4 *wsave)
+{
+    extern /* Subroutine */ int rfftb1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    int_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --r__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    rfftb1_(n, &r__[1], &wsave[1], &wsave[*n + 1], (int_4 *)&wsave[(*n << 1) + 1]);   /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* rfftb_ */
+
+/*  ------ File rfftb1.f ------ */
+/* Subroutine */ int rfftb1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, 
+	int_4 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    extern /* Subroutine */ int radb2_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *), radb3_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *), radb4_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *), radb5_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer i__;
+    extern /* Subroutine */ int radbg_(integer *, integer *, integer *, 
+	    integer *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idl1 = ido * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	if (na != 0) {
+	    goto L101;
+	}
+	radb4_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	radb4_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	radb2_(&ido, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	radb2_(&ido, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + ido;
+	if (na != 0) {
+	    goto L107;
+	}
+	radb3_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	radb3_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	ix4 = ix3 + ido;
+	if (na != 0) {
+	    goto L110;
+	}
+	radb5_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	radb5_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	radbg_(&ido, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1], &ch[
+		1], &wa[iw]);
+	goto L114;
+L113:
+	radbg_(&ido, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], &c__[1]
+		, &wa[iw]);
+L114:
+	if (ido == 1) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * ido;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* rfftb1_ */
+
+/*  ------ File rfftf.f ------ */
+/* Subroutine */ int rfftf_(integer *n, r_4 *r__, r_4 *wsave)
+{
+    extern /* Subroutine */ int rfftf1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    int_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --r__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    rfftf1_(n, &r__[1], &wsave[1], &wsave[*n + 1], (int_4 *)&wsave[(*n << 1) + 1]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* rfftf_ */
+
+/*  ------ File rfftf1.f ------ */
+/* Subroutine */ int rfftf1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, 
+	int_4 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    extern /* Subroutine */ int radf2_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *), radf3_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *), radf4_(integer *, integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *), radf5_(integer *, integer *, r_4 *, r_4 *, 
+	    r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer i__;
+    extern /* Subroutine */ int radfg_(integer *, integer *, integer *, 
+	    integer *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *, r_4 *);
+    static integer k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 1;
+    l2 = *n;
+    iw = *n;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	kh = nf - k1;
+	ip = ifac[kh + 3];
+	l1 = l2 / ip;
+	ido = *n / l2;
+	idl1 = ido * l1;
+	iw -= (ip - 1) * ido;
+	na = 1 - na;
+	if (ip != 4) {
+	    goto L102;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	if (na != 0) {
+	    goto L101;
+	}
+	radf4_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L110;
+L101:
+	radf4_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L110;
+L102:
+	if (ip != 2) {
+	    goto L104;
+	}
+	if (na != 0) {
+	    goto L103;
+	}
+	radf2_(&ido, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L110;
+L103:
+	radf2_(&ido, &l1, &ch[1], &c__[1], &wa[iw]);
+	goto L110;
+L104:
+	if (ip != 3) {
+	    goto L106;
+	}
+	ix2 = iw + ido;
+	if (na != 0) {
+	    goto L105;
+	}
+	radf3_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L110;
+L105:
+	radf3_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+	goto L110;
+L106:
+	if (ip != 5) {
+	    goto L108;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	ix4 = ix3 + ido;
+	if (na != 0) {
+	    goto L107;
+	}
+	radf5_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L110;
+L107:
+	radf5_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L110;
+L108:
+	if (ido == 1) {
+	    na = 1 - na;
+	}
+	if (na != 0) {
+	    goto L109;
+	}
+	radfg_(&ido, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1], &ch[
+		1], &wa[iw]);
+	na = 1;
+	goto L110;
+L109:
+	radfg_(&ido, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], &c__[1]
+		, &wa[iw]);
+	na = 0;
+L110:
+	l2 = l1;
+/* L111: */
+    }
+    if (na == 1) {
+	return 0;
+    }
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L112: */
+    }
+    return 0;
+} /* rfftf1_ */
+
+/*  ------ File rffti.f ------ */
+/* Subroutine */ int rffti_(integer *n, r_4 *wsave)
+{
+    extern /* Subroutine */ int rffti1_(integer *, r_4 *, int_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    rffti1_(n, &wsave[*n + 1], (int_4 *)&wsave[(*n << 1) + 1]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* rffti_ */
+
+/*  ------ File rffti1.f ------ */
+/* Subroutine */ int rffti1_(integer *n, r_4 *wa, int_4 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 4,2,3,5 };
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*   r_8 cos(r_8truc), sin(r_8truc);  Remplace par math.h , Reza 29/11/99 */
+
+    /* Local variables */
+    static r_4 argh;
+    static integer ntry, i__, j;
+    static r_4 argld;
+    static integer k1, l1, l2, ib;
+    static r_4 fi;
+    static integer ld, ii, nf, ip, nl, is, nq, nr;
+    static r_4 arg;
+    static integer ido, ipm;
+    static r_4 tpi;
+    static integer nfm1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    tpi = 6.28318530717959f;
+    argh = tpi / (r_4) (*n);
+    is = 0;
+    nfm1 = nf - 1;
+    l1 = 1;
+    if (nfm1 == 0) {
+	return 0;
+    }
+    i__1 = nfm1;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	ld = 0;
+	l2 = l1 * ip;
+	ido = *n / l2;
+	ipm = ip - 1;
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    ld += l1;
+	    i__ = is;
+	    argld = (r_4) ld * argh;
+	    fi = 0.f;
+	    i__3 = ido;
+	    for (ii = 3; ii <= i__3; ii += 2) {
+		i__ += 2;
+		fi += 1.f;
+		arg = fi * argld;
+		wa[i__ - 1] = cos(arg);
+		wa[i__] = sin(arg);
+/* L108: */
+	    }
+	    is += ido;
+/* L109: */
+	}
+	l1 = l2;
+/* L110: */
+    }
+    return 0;
+} /* rffti1_ */
+
+/*  ------ File sinqb.f ------ */
+/* Subroutine */ int sinqb_(integer *n, r_4 *x, r_4 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int cosqb_(integer *, r_4 *, r_4 *);
+    static r_4 xhold;
+    static integer kc, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if (*n > 1) {
+	goto L101;
+    }
+    x[1] *= 4.f;
+    return 0;
+L101:
+    ns2 = *n / 2;
+    i__1 = *n;
+    for (k = 2; k <= i__1; k += 2) {
+	x[k] = -x[k];
+/* L102: */
+    }
+    cosqb_(n, &x[1], &wsave[1]);
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = *n - k;
+	xhold = x[k];
+	x[k] = x[kc + 1];
+	x[kc + 1] = xhold;
+/* L103: */
+    }
+    return 0;
+} /* sinqb_ */
+
+/*  ------ File sinqf.f ------ */
+/* Subroutine */ int sinqf_(integer *n, r_4 *x, r_4 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int cosqf_(integer *, r_4 *, r_4 *);
+    static r_4 xhold;
+    static integer kc, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    ns2 = *n / 2;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = *n - k;
+	xhold = x[k];
+	x[k] = x[kc + 1];
+	x[kc + 1] = xhold;
+/* L101: */
+    }
+    cosqf_(n, &x[1], &wsave[1]);
+    i__1 = *n;
+    for (k = 2; k <= i__1; k += 2) {
+	x[k] = -x[k];
+/* L102: */
+    }
+    return 0;
+} /* sinqf_ */
+
+/*  ------ File sinqi.f ------ */
+/* Subroutine */ int sinqi_(integer *n, r_4 *wsave)
+{
+    extern /* Subroutine */ int cosqi_(integer *, r_4 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    cosqi_(n, &wsave[1]);
+    return 0;
+} /* sinqi_ */
+
+/*  ------ File sint.f ------ */
+/* Subroutine */ int sint_(integer *n, r_4 *x, r_4 *wsave)
+{
+    extern /* Subroutine */ int sint1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    r_4 *, int_4 *);
+    static integer np1, iw1, iw2, iw3;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    np1 = *n + 1;
+    iw1 = *n / 2 + 1;
+    iw2 = iw1 + np1;
+    iw3 = iw2 + np1;
+    sint1_(n, &x[1], &wsave[1], &wsave[iw1], &wsave[iw2], (int_4 *)&wsave[iw3]);  /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* sint_ */
+
+/*  ------ File sint1.f ------ */
+/* Subroutine */ int sint1_(integer *n, r_4 *war, r_4 *was, r_4 *xh, r_4 *
+	x, int_4 *ifac)
+{
+    /* Initialized data */
+
+    static r_4 sqrt3 = 1.73205080756888f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    static r_4 xhold, t1, t2;
+    extern /* Subroutine */ int rfftf1_(integer *, r_4 *, r_4 *, r_4 *, 
+	    int_4 *);
+    static integer kc, np1, ns2;
+
+    /* Parameter adjustments */
+    --ifac;
+    --x;
+    --xh;
+    --was;
+    --war;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	xh[i__] = war[i__];
+	war[i__] = x[i__];
+/* L100: */
+    }
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    xh[1] += xh[1];
+    goto L106;
+L102:
+    xhold = sqrt3 * (xh[1] + xh[2]);
+    xh[2] = sqrt3 * (xh[1] - xh[2]);
+    xh[1] = xhold;
+    goto L106;
+L103:
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    x[1] = 0.f;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = np1 - k;
+	t1 = xh[k] - xh[kc];
+	t2 = was[k] * (xh[k] + xh[kc]);
+	x[k + 1] = t1 + t2;
+	x[kc + 1] = t2 - t1;
+/* L104: */
+    }
+    modn = *n % 2;
+    if (modn != 0) {
+	x[ns2 + 2] = xh[ns2 + 1] * 4.f;
+    }
+    rfftf1_(&np1, &x[1], &xh[1], &war[1], &ifac[1]);
+    xh[1] = x[1] * .5f;
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xh[i__ - 1] = -x[i__];
+	xh[i__] = xh[i__ - 2] + x[i__ - 1];
+/* L105: */
+    }
+    if (modn != 0) {
+	goto L106;
+    }
+    xh[*n] = -x[*n + 1];
+L106:
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	x[i__] = war[i__];
+	war[i__] = xh[i__];
+/* L107: */
+    }
+    return 0;
+} /* sint1_ */
+
+/*  ------ File sinti.f ------ */
+/* Subroutine */ int sinti_(integer *n, r_4 *wsave)
+{
+    /* Initialized data */
+
+    static r_4 pi = 3.14159265358979f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 sin(r_8truc);  remplace par math.h , Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int rffti_(integer *, r_4 *);
+    static r_4 dt;
+    static integer np1, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    ns2 = *n / 2;
+    np1 = *n + 1;
+    dt = pi / (r_4) np1;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	wsave[k] = sin(k * dt) * 2.f;
+/* L101: */
+    }
+    rffti_(&np1, &wsave[ns2 + 1]);
+    return 0;
+} /* sinti_ */
+
+/* --------------------------------------------------------------- */
+/* -------------- make a r_8 version of the library ----------- */
+/* --------------------------------------------------------------- */
+
+/* Subroutine */ int cdfftb_(integer *n, r_8 *c__, r_8 *wsave)
+{
+    extern /* Subroutine */ int cdfftb1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    int_8 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --c__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cdfftb1_(n, &c__[1], &wsave[1], &wsave[iw1], (int_8 *)&wsave[iw2]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* cdfftb_ */
+
+/*  ------ File cdfftb1.f ------ */
+/* Subroutine */ int cdfftb1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, 
+	int_8 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer idot, i__;
+    extern /* Subroutine */ int dpassb_(integer *, integer *, integer *, 
+	    integer *, integer *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *);
+    static integer k1, l1, l2, n2;
+    extern /* Subroutine */ int dpassb2_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *), dpassb3_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *), dpassb4_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *), dpassb5_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idot = ido + ido;
+	idl1 = idot * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	if (na != 0) {
+	    goto L101;
+	}
+	dpassb4_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	dpassb4_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	dpassb2_(&idot, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	dpassb2_(&idot, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + idot;
+	if (na != 0) {
+	    goto L107;
+	}
+	dpassb3_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	dpassb3_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	ix4 = ix3 + idot;
+	if (na != 0) {
+	    goto L110;
+	}
+	dpassb5_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	dpassb5_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	dpassb_(&nac, &idot, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1]
+		, &ch[1], &wa[iw]);
+	goto L114;
+L113:
+	dpassb_(&nac, &idot, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], 
+		&c__[1], &wa[iw]);
+L114:
+	if (nac != 0) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * idot;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    n2 = *n + *n;
+    i__1 = n2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* cdfftb1_ */
+
+/*  ------ File cdfftf.f ------ */
+/* Subroutine */ int cdfftf_(integer *n, r_8 *c__, r_8 *wsave)
+{
+    extern /* Subroutine */ int cdfftf1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    int_8 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --c__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cdfftf1_(n, &c__[1], &wsave[1], &wsave[iw1], (int_8 *)&wsave[iw2]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* cdfftf_ */
+
+/*  ------ File cdfftf1.f ------ */
+/* Subroutine */ int cdfftf1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, 
+	int_8 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer idot, i__;
+    extern /* Subroutine */ int dpassf_(integer *, integer *, integer *, 
+	    integer *, integer *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *);
+    static integer k1, l1, l2, n2;
+    extern /* Subroutine */ int dpassf2_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *), dpassf3_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *), dpassf4_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *), dpassf5_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idot = ido + ido;
+	idl1 = idot * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	if (na != 0) {
+	    goto L101;
+	}
+	dpassf4_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	dpassf4_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	dpassf2_(&idot, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	dpassf2_(&idot, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + idot;
+	if (na != 0) {
+	    goto L107;
+	}
+	dpassf3_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	dpassf3_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + idot;
+	ix3 = ix2 + idot;
+	ix4 = ix3 + idot;
+	if (na != 0) {
+	    goto L110;
+	}
+	dpassf5_(&idot, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	dpassf5_(&idot, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	dpassf_(&nac, &idot, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1]
+		, &ch[1], &wa[iw]);
+	goto L114;
+L113:
+	dpassf_(&nac, &idot, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], 
+		&c__[1], &wa[iw]);
+L114:
+	if (nac != 0) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * idot;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    n2 = *n + *n;
+    i__1 = n2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* cdfftf1_ */
+
+/*  ------ File cdffti.f ------ */
+/* Subroutine */ int cdffti_(integer *n, r_8 *wsave)
+{
+    extern /* Subroutine */ int cdffti1_(integer *, r_8 *, int_8 *);
+    static integer iw1, iw2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    iw1 = *n + *n + 1;
+    iw2 = iw1 + *n + *n;
+    cdffti1_(n, &wsave[iw1], (int_8 *)&wsave[iw2]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* cdffti_ */
+
+/*  ------ File cdffti1.f ------ */
+/* Subroutine */ int cdffti1_(integer *n, r_8 *wa, int_8 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 3,4,2,5 };
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);  remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static r_8 argh;
+    static integer idot, ntry, i__, j;
+    static r_8 argld;
+    static integer i1, k1, l1, l2, ib;
+    static r_8 fi;
+    static integer ld, ii, nf, ip, nl, nq, nr;
+    static r_8 arg;
+    static integer ido, ipm;
+    static r_8 tpi;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    tpi = 6.28318530717959f;
+    argh = tpi / (r_8) (*n);
+    i__ = 2;
+    l1 = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	ld = 0;
+	l2 = l1 * ip;
+	ido = *n / l2;
+	idot = ido + ido + 2;
+	ipm = ip - 1;
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    i1 = i__;
+	    wa[i__ - 1] = 1.f;
+	    wa[i__] = 0.f;
+	    ld += l1;
+	    fi = 0.f;
+	    argld = (r_8) ld * argh;
+	    i__3 = idot;
+	    for (ii = 4; ii <= i__3; ii += 2) {
+		i__ += 2;
+		fi += 1.f;
+		arg = fi * argld;
+		wa[i__ - 1] = cos(arg);
+		wa[i__] = sin(arg);
+/* L108: */
+	    }
+	    if (ip <= 5) {
+		goto L109;
+	    }
+	    wa[i1 - 1] = wa[i__ - 1];
+	    wa[i1] = wa[i__];
+L109:
+	    ;
+	}
+	l1 = l2;
+/* L110: */
+    }
+    return 0;
+} /* cdffti1_ */
+
+/*  ------ File dcosqb.f ------ */
+/* Subroutine */ int dcosqb_(integer *n, r_8 *x, r_8 *wsave)
+{
+    /* Initialized data */
+
+    static r_8 tsqrt2 = 2.82842712474619f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static r_8 x1;
+    extern /* Subroutine */ int dcosqb1_(integer *, r_8 *, r_8 *, r_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    x[1] *= 4.f;
+    return 0;
+L102:
+    x1 = (x[1] + x[2]) * 4.f;
+    x[2] = tsqrt2 * (x[1] - x[2]);
+    x[1] = x1;
+    return 0;
+L103:
+    dcosqb1_(n, &x[1], &wsave[1], &wsave[*n + 1]);
+    return 0;
+} /* dcosqb_ */
+
+/*  ------ File dcosqb1.f ------ */
+/* Subroutine */ int dcosqb1_(integer *n, r_8 *x, r_8 *w, r_8 *xh)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int dfftb_(integer *, r_8 *, r_8 *);
+    static integer kc, np2, ns2;
+    static r_8 xim1;
+
+    /* Parameter adjustments */
+    --xh;
+    --w;
+    --x;
+
+    /* Function Body */
+    ns2 = (*n + 1) / 2;
+    np2 = *n + 2;
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xim1 = x[i__ - 1] + x[i__];
+	x[i__] -= x[i__ - 1];
+	x[i__ - 1] = xim1;
+/* L101: */
+    }
+    x[1] += x[1];
+    modn = *n % 2;
+    if (modn == 0) {
+	x[*n] += x[*n];
+    }
+    dfftb_(n, &x[1], &xh[1]);
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	xh[k] = w[k - 1] * x[kc] + w[kc - 1] * x[k];
+	xh[kc] = w[k - 1] * x[k] - w[kc - 1] * x[kc];
+/* L102: */
+    }
+    if (modn == 0) {
+	x[ns2 + 1] = w[ns2] * (x[ns2 + 1] + x[ns2 + 1]);
+    }
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	x[k] = xh[k] + xh[kc];
+	x[kc] = xh[k] - xh[kc];
+/* L103: */
+    }
+    x[1] += x[1];
+    return 0;
+} /* dcosqb1_ */
+
+/*  ------ File dcosqf.f ------ */
+/* Subroutine */ int dcosqf_(integer *n, r_8 *x, r_8 *wsave)
+{
+    /* Initialized data */
+
+    static r_8 sqrt2 = 1.4142135623731f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static r_8 tsqx;
+    extern /* Subroutine */ int dcosqf1_(integer *, r_8 *, r_8 *, r_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L102;
+    } else if (i__1 == 0) {
+	goto L101;
+    } else {
+	goto L103;
+    }
+L101:
+    tsqx = sqrt2 * x[2];
+    x[2] = x[1] - tsqx;
+    x[1] += tsqx;
+L102:
+    return 0;
+L103:
+    dcosqf1_(n, &x[1], &wsave[1], &wsave[*n + 1]);
+    return 0;
+} /* dcosqf_ */
+
+/*  ------ File dcosqf1.f ------ */
+/* Subroutine */ int dcosqf1_(integer *n, r_8 *x, r_8 *w, r_8 *xh)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int dfftf_(integer *, r_8 *, r_8 *);
+    static integer kc, np2, ns2;
+    static r_8 xim1;
+
+    /* Parameter adjustments */
+    --xh;
+    --w;
+    --x;
+
+    /* Function Body */
+    ns2 = (*n + 1) / 2;
+    np2 = *n + 2;
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	xh[k] = x[k] + x[kc];
+	xh[kc] = x[k] - x[kc];
+/* L101: */
+    }
+    modn = *n % 2;
+    if (modn == 0) {
+	xh[ns2 + 1] = x[ns2 + 1] + x[ns2 + 1];
+    }
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np2 - k;
+	x[k] = w[k - 1] * xh[kc] + w[kc - 1] * xh[k];
+	x[kc] = w[k - 1] * xh[k] - w[kc - 1] * xh[kc];
+/* L102: */
+    }
+    if (modn == 0) {
+	x[ns2 + 1] = w[ns2] * xh[ns2 + 1];
+    }
+    dfftf_(n, &x[1], &xh[1]);
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xim1 = x[i__ - 1] - x[i__];
+	x[i__] = x[i__ - 1] + x[i__];
+	x[i__ - 1] = xim1;
+/* L103: */
+    }
+    return 0;
+} /* dcosqf1_ */
+
+/*  ------ File dcosqi.f ------ */
+/* Subroutine */ int dcosqi_(integer *n, r_8 *wsave)
+{
+    /* Initialized data */
+
+    static r_8 pih = 1.57079632679491f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc); remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int dffti_(integer *, r_8 *);
+    static r_8 fk, dt;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    dt = pih / (r_8) (*n);
+    fk = 0.f;
+    i__1 = *n;
+    for (k = 1; k <= i__1; ++k) {
+	fk += 1.f;
+	wsave[k] = cos(fk * dt);
+/* L101: */
+    }
+    dffti_(n, &wsave[*n + 1]);
+    return 0;
+} /* dcosqi_ */
+
+/*  ------ File dcost.f ------ */
+/* Subroutine */ int dcost_(integer *n, r_8 *x, r_8 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    extern /* Subroutine */ int dfftf_(integer *, r_8 *, r_8 *);
+    static r_8 c1, t1, t2;
+    static integer kc;
+    static r_8 xi;
+    static integer nm1, np1;
+    static r_8 x1h;
+    static integer ns2;
+    static r_8 tx2, x1p3, xim2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    nm1 = *n - 1;
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    if ((i__1 = *n - 2) < 0) {
+	goto L106;
+    } else if (i__1 == 0) {
+	goto L101;
+    } else {
+	goto L102;
+    }
+L101:
+    x1h = x[1] + x[2];
+    x[2] = x[1] - x[2];
+    x[1] = x1h;
+    return 0;
+L102:
+    if (*n > 3) {
+	goto L103;
+    }
+    x1p3 = x[1] + x[3];
+    tx2 = x[2] + x[2];
+    x[2] = x[1] - x[3];
+    x[1] = x1p3 + tx2;
+    x[3] = x1p3 - tx2;
+    return 0;
+L103:
+    c1 = x[1] - x[*n];
+    x[1] += x[*n];
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np1 - k;
+	t1 = x[k] + x[kc];
+	t2 = x[k] - x[kc];
+	c1 += wsave[kc] * t2;
+	t2 = wsave[k] * t2;
+	x[k] = t1 - t2;
+	x[kc] = t1 + t2;
+/* L104: */
+    }
+    modn = *n % 2;
+    if (modn != 0) {
+	x[ns2 + 1] += x[ns2 + 1];
+    }
+    dfftf_(&nm1, &x[1], &wsave[*n + 1]);
+    xim2 = x[2];
+    x[2] = c1;
+    i__1 = *n;
+    for (i__ = 4; i__ <= i__1; i__ += 2) {
+	xi = x[i__];
+	x[i__] = x[i__ - 2] - x[i__ - 1];
+	x[i__ - 1] = xim2;
+	xim2 = xi;
+/* L105: */
+    }
+    if (modn != 0) {
+	x[*n] = xim2;
+    }
+L106:
+    return 0;
+} /* dcost_ */
+
+/*  ------ File dcosti.f ------ */
+/* Subroutine */ int dcosti_(integer *n, r_8 *wsave)
+{
+    /* Initialized data */
+
+    static r_8 pi = 3.14159265358979f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 sin(r_8truc), cos(r_8truc);  remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int dffti_(integer *, r_8 *);
+    static integer kc;
+    static r_8 fk, dt;
+    static integer nm1, np1, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n <= 3) {
+	return 0;
+    }
+    nm1 = *n - 1;
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    dt = pi / (r_8) nm1;
+    fk = 0.f;
+    i__1 = ns2;
+    for (k = 2; k <= i__1; ++k) {
+	kc = np1 - k;
+	fk += 1.f;
+	wsave[k] = sin(fk * dt) * 2.f;
+	wsave[kc] = cos(fk * dt) * 2.f;
+/* L101: */
+    }
+    dffti_(&nm1, &wsave[*n + 1]);
+    return 0;
+} /* dcosti_ */
+
+/*  ------ File dezfft1.f ------ */
+/* Subroutine */ int dezfft1_(integer *n, r_8 *wa, int_8 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 4,2,3,5 };
+    static r_8 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);  remplace par math.h  Reza 29/11/99  */
+
+    /* Local variables */
+    static r_8 argh;
+    static integer ntry, i__, j, k1, l1, l2, ib, ii, nf, ip, nl, is, nq, nr;
+    static r_8 ch1, sh1;
+    static integer ido, ipm;
+    static r_8 dch1, ch1h, arg1, dsh1;
+    static integer nfm1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    argh = tpi / (r_8) (*n);
+    is = 0;
+    nfm1 = nf - 1;
+    l1 = 1;
+    if (nfm1 == 0) {
+	return 0;
+    }
+    i__1 = nfm1;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = l1 * ip;
+	ido = *n / l2;
+	ipm = ip - 1;
+	arg1 = (r_8) l1 * argh;
+	ch1 = 1.f;
+	sh1 = 0.f;
+	dch1 = cos(arg1);
+	dsh1 = sin(arg1);
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    ch1h = dch1 * ch1 - dsh1 * sh1;
+	    sh1 = dch1 * sh1 + dsh1 * ch1;
+	    ch1 = ch1h;
+	    i__ = is + 2;
+	    wa[i__ - 1] = ch1;
+	    wa[i__] = sh1;
+	    if (ido < 5) {
+		goto L109;
+	    }
+	    i__3 = ido;
+	    for (ii = 5; ii <= i__3; ii += 2) {
+		i__ += 2;
+		wa[i__ - 1] = ch1 * wa[i__ - 3] - sh1 * wa[i__ - 2];
+		wa[i__] = ch1 * wa[i__ - 2] + sh1 * wa[i__ - 3];
+/* L108: */
+	    }
+L109:
+	    is += ido;
+/* L110: */
+	}
+	l1 = l2;
+/* L111: */
+    }
+    return 0;
+} /* dezfft1_ */
+
+/*  ------ File dezfftb.f ------ */
+/* Subroutine */ int dezfftb_(integer *n, r_8 *r__, r_8 *azero, r_8 *a, 
+	r_8 *b, r_8 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int dfftb_(integer *, r_8 *, r_8 *);
+    static integer ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --b;
+    --a;
+    --r__;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    r__[1] = *azero;
+    return 0;
+L102:
+    r__[1] = *azero + a[1];
+    r__[2] = *azero - a[1];
+    return 0;
+L103:
+    ns2 = (*n - 1) / 2;
+    i__1 = ns2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	r__[i__ * 2] = a[i__] * .5f;
+	r__[(i__ << 1) + 1] = b[i__] * -.5f;
+/* L104: */
+    }
+    r__[1] = *azero;
+    if (*n % 2 == 0) {
+	r__[*n] = a[ns2 + 1];
+    }
+    dfftb_(n, &r__[1], &wsave[*n + 1]);
+    return 0;
+} /* dezfftb_ */
+
+/*  ------ File dezfftf.f ------ */
+/* Subroutine */ int dezfftf_(integer *n, r_8 *r__, r_8 *azero, r_8 *a, 
+	r_8 *b, r_8 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int dfftf_(integer *, r_8 *, r_8 *);
+    static r_8 cf;
+    static integer ns2;
+    static r_8 cfm;
+    static integer ns2m;
+
+
+/*                       VERSION 3  JUNE 1979 */
+
+    /* Parameter adjustments */
+    --wsave;
+    --b;
+    --a;
+    --r__;
+
+    /* Function Body */
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    *azero = r__[1];
+    return 0;
+L102:
+    *azero = (r__[1] + r__[2]) * .5f;
+    a[1] = (r__[1] - r__[2]) * .5f;
+    return 0;
+L103:
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wsave[i__] = r__[i__];
+/* L104: */
+    }
+    dfftf_(n, &wsave[1], &wsave[*n + 1]);
+    cf = 2.f / (r_8) (*n);
+    cfm = -cf;
+    *azero = cf * .5f * wsave[1];
+    ns2 = (*n + 1) / 2;
+    ns2m = ns2 - 1;
+    i__1 = ns2m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	a[i__] = cf * wsave[i__ * 2];
+	b[i__] = cfm * wsave[(i__ << 1) + 1];
+/* L105: */
+    }
+    if (*n % 2 == 1) {
+	return 0;
+    }
+    a[ns2] = cf * .5f * wsave[*n];
+    b[ns2] = 0.f;
+    return 0;
+} /* dezfftf_ */
+
+/*  ------ File dezffti.f ------ */
+/* Subroutine */ int dezffti_(integer *n, r_8 *wsave)
+{
+    extern /* Subroutine */ int dezfft1_(integer *, r_8 *, int_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    dezfft1_(n, &wsave[(*n << 1) + 1], (int_8 *)&wsave[*n * 3 + 1]);
+    return 0;
+} /* dezffti_ */
+
+/*  ------ File dpassb.f ------ */
+/* Subroutine */ int dpassb_(integer *nac, integer *ido, integer *ip, integer *
+	l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, 
+	r_8 *wa)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer idij, idlj, idot, ipph, i__, j, k, l, jc, lc, ik, nt, idj, 
+	    idl, inc, idp;
+    static r_8 wai, war;
+    static integer ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    idot = *ido / 2;
+    nt = *ip * *idl1;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    idp = *ip * *ido;
+
+    if (*ido < *l1) {
+	goto L106;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L101: */
+	    }
+/* L102: */
+	}
+/* L103: */
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+    goto L112;
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L107: */
+	    }
+/* L108: */
+	}
+/* L109: */
+    }
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L110: */
+	}
+/* L111: */
+    }
+L112:
+    idl = 2 - *ido;
+    inc = 0;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	idl += *ido;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + wa[idl - 1] * ch2[ik 
+		    + (ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = wa[idl] * ch2[ik + *ip * ch2_dim1];
+/* L113: */
+	}
+	idlj = idl;
+	inc += *ido;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    idlj += inc;
+	    if (idlj > idp) {
+		idlj -= idp;
+	    }
+	    war = wa[idlj - 1];
+	    wai = wa[idlj];
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += war * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] += wai * ch2[ik + jc * ch2_dim1];
+/* L114: */
+	    }
+/* L115: */
+	}
+/* L116: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L117: */
+	}
+/* L118: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *idl1;
+	for (ik = 2; ik <= i__2; ik += 2) {
+	    ch2[ik - 1 + j * ch2_dim1] = c2[ik - 1 + j * c2_dim1] - c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik - 1 + jc * ch2_dim1] = c2[ik - 1 + j * c2_dim1] + c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik + j * ch2_dim1] = c2[ik + j * c2_dim1] + c2[ik - 1 + jc * 
+		    c2_dim1];
+	    ch2[ik + jc * ch2_dim1] = c2[ik + j * c2_dim1] - c2[ik - 1 + jc * 
+		    c2_dim1];
+/* L119: */
+	}
+/* L120: */
+    }
+    *nac = 1;
+    if (*ido == 2) {
+	return 0;
+    }
+    *nac = 0;
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L121: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+	    c1[(k + j * c1_dim2) * c1_dim1 + 2] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 2];
+/* L122: */
+	}
+/* L123: */
+    }
+    if (idot > *l1) {
+	goto L127;
+    }
+    idij = 0;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idij += 2;
+	i__2 = *ido;
+	for (i__ = 4; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L124: */
+	    }
+/* L125: */
+	}
+/* L126: */
+    }
+    return 0;
+L127:
+    idj = 2 - *ido;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idj += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = idj;
+	    i__3 = *ido;
+	    for (i__ = 4; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L128: */
+	    }
+/* L129: */
+	}
+/* L130: */
+    }
+    return 0;
+} /* dpassb_ */
+
+/*  ------ File dpassb2.f ------ */
+/* Subroutine */ int dpassb2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    if (*ido > 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 + 2] + 
+		cc[((k << 1) + 2) * cc_dim1 + 2];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 
+		+ 2] - cc[((k << 1) + 2) * cc_dim1 + 2];
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[i__ - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] + cc[i__ + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] - cc[i__ + ((k << 1) + 2)
+		     * cc_dim1];
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ti2 + 
+		    wa1[i__] * tr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * tr2 
+		    - wa1[i__] * ti2;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassb2_ */
+
+/*  ------ File dpassb3.f ------ */
+/* Subroutine */ int dpassb3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2)
+{
+    /* Initialized data */
+
+    static r_8 taur = -.5f;
+    static r_8 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[(k * 3 + 2) * cc_dim1 + 1] + cc[(k * 3 + 3) * cc_dim1 + 1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ti2 = cc[(k * 3 + 2) * cc_dim1 + 2] + cc[(k * 3 + 3) * cc_dim1 + 2];
+	ci2 = cc[(k * 3 + 1) * cc_dim1 + 2] + taur * ti2;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 3 + 1) * cc_dim1 + 2] + ti2;
+	cr3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 1] - cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ci3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 2] - cc[(k * 3 + 3) * 
+		cc_dim1 + 2]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci2 - cr3;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    tr2 = cc[i__ - 1 + (k * 3 + 2) * cc_dim1] + cc[i__ - 1 + (k * 3 + 
+		    3) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 2) * cc_dim1] + cc[i__ + (k * 3 + 3) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 2) * cc_dim1] - cc[i__ - 1 + (
+		    k * 3 + 3) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 2) * cc_dim1] - cc[i__ + (k * 3 + 
+		    3) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 + 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    - wa1[i__] * di2;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 + wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 - 
+		    wa2[i__] * di3;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassb3_ */
+
+/*  ------ File dpassb4.f ------ */
+/* Subroutine */ int dpassb4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 1) * cc_dim1 + 2] - cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	ti2 = cc[((k << 2) + 1) * cc_dim1 + 2] + cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	tr4 = cc[((k << 2) + 4) * cc_dim1 + 2] - cc[((k << 2) + 2) * cc_dim1 
+		+ 2];
+	ti3 = cc[((k << 2) + 2) * cc_dim1 + 2] + cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ti4 = cc[((k << 2) + 2) * cc_dim1 + 1] - cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	tr3 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = ti2 + ti3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ti2 - ti3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 + tr4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ti1 + ti4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ti1 - ti4;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 2) * cc_dim1] + cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 4) * cc_dim1] - cc[i__ + ((k << 2) + 2)
+		     * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 + tr4;
+	    cr4 = tr1 - tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * cr2 
+		    - wa1[i__] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ci2 + 
+		    wa1[i__] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * cr3 - 
+		    wa2[i__] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * ci3 + wa2[
+		    i__] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * cr4 
+		    - wa3[i__] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * ci4 + 
+		    wa3[i__] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassb4_ */
+
+/*  ------ File dpassb5.f ------ */
+/* Subroutine */ int dpassb5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4)
+{
+    /* Initialized data */
+
+    static r_8 tr11 = .309016994374947f;
+    static r_8 ti11 = .951056516295154f;
+    static r_8 tr12 = -.809016994374947f;
+    static r_8 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 2) * cc_dim1 + 2] - cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti2 = cc[(k * 5 + 2) * cc_dim1 + 2] + cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti4 = cc[(k * 5 + 3) * cc_dim1 + 2] - cc[(k * 5 + 4) * cc_dim1 + 2];
+	ti3 = cc[(k * 5 + 3) * cc_dim1 + 2] + cc[(k * 5 + 4) * cc_dim1 + 2];
+	tr5 = cc[(k * 5 + 2) * cc_dim1 + 1] - cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[(k * 5 + 2) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr4 = cc[(k * 5 + 3) * cc_dim1 + 1] - cc[(k * 5 + 4) * cc_dim1 + 1];
+	tr3 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 4) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 5 + 1) * cc_dim1 + 2] + ti2 
+		+ ti3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	ci2 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr11 * ti2 + tr12 * ti3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci3 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr12 * ti2 + tr11 * ti3;
+	cr5 = ti11 * tr5 + ti12 * tr4;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	cr4 = ti12 * tr5 - ti11 * tr4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci3 + cr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ci3 - cr4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 2] = ci2 - cr5;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti5 = cc[i__ + (k * 5 + 2) * cc_dim1] - cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 2) * cc_dim1] + cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    - wa1[i__] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 + 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 - 
+		    wa2[i__] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 + wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * dr4 
+		    - wa3[i__] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * di4 + 
+		    wa3[i__] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * dr5 - 
+		    wa4[i__] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * di5 + wa4[
+		    i__] * dr5;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassb5_ */
+
+/*  ------ File dpassf.f ------ */
+/* Subroutine */ int dpassf_(integer *nac, integer *ido, integer *ip, integer *
+	l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, 
+	r_8 *wa)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer idij, idlj, idot, ipph, i__, j, k, l, jc, lc, ik, nt, idj, 
+	    idl, inc, idp;
+    static r_8 wai, war;
+    static integer ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    idot = *ido / 2;
+    nt = *ip * *idl1;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    idp = *ip * *ido;
+
+    if (*ido < *l1) {
+	goto L106;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L101: */
+	    }
+/* L102: */
+	}
+/* L103: */
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+    goto L112;
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] + cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + (j + k * 
+			cc_dim2) * cc_dim1] - cc[i__ + (jc + k * cc_dim2) * 
+			cc_dim1];
+/* L107: */
+	    }
+/* L108: */
+	}
+/* L109: */
+    }
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L110: */
+	}
+/* L111: */
+    }
+L112:
+    idl = 2 - *ido;
+    inc = 0;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	idl += *ido;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + wa[idl - 1] * ch2[ik 
+		    + (ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = -wa[idl] * ch2[ik + *ip * ch2_dim1];
+/* L113: */
+	}
+	idlj = idl;
+	inc += *ido;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    idlj += inc;
+	    if (idlj > idp) {
+		idlj -= idp;
+	    }
+	    war = wa[idlj - 1];
+	    wai = wa[idlj];
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += war * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] -= wai * ch2[ik + jc * ch2_dim1];
+/* L114: */
+	    }
+/* L115: */
+	}
+/* L116: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L117: */
+	}
+/* L118: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *idl1;
+	for (ik = 2; ik <= i__2; ik += 2) {
+	    ch2[ik - 1 + j * ch2_dim1] = c2[ik - 1 + j * c2_dim1] - c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik - 1 + jc * ch2_dim1] = c2[ik - 1 + j * c2_dim1] + c2[ik + 
+		    jc * c2_dim1];
+	    ch2[ik + j * ch2_dim1] = c2[ik + j * c2_dim1] + c2[ik - 1 + jc * 
+		    c2_dim1];
+	    ch2[ik + jc * ch2_dim1] = c2[ik + j * c2_dim1] - c2[ik - 1 + jc * 
+		    c2_dim1];
+/* L119: */
+	}
+/* L120: */
+    }
+    *nac = 1;
+    if (*ido == 2) {
+	return 0;
+    }
+    *nac = 0;
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L121: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+	    c1[(k + j * c1_dim2) * c1_dim1 + 2] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 2];
+/* L122: */
+	}
+/* L123: */
+    }
+    if (idot > *l1) {
+	goto L127;
+    }
+    idij = 0;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idij += 2;
+	i__2 = *ido;
+	for (i__ = 4; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] + wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] - wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L124: */
+	    }
+/* L125: */
+	}
+/* L126: */
+    }
+    return 0;
+L127:
+    idj = 2 - *ido;
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	idj += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = idj;
+	    i__3 = *ido;
+	    for (i__ = 4; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] + wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] - wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L128: */
+	    }
+/* L129: */
+	}
+/* L130: */
+    }
+    return 0;
+} /* dpassf_ */
+
+/*  ------ File dpassf2.f ------ */
+/* Subroutine */ int dpassf2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    if (*ido > 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[((k << 1) + 2) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 + 2] + 
+		cc[((k << 1) + 2) * cc_dim1 + 2];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = cc[((k << 1) + 1) * cc_dim1 
+		+ 2] - cc[((k << 1) + 2) * cc_dim1 + 2];
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[i__ - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] + cc[i__ + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] - cc[i__ + ((k << 1) + 2)
+		     * cc_dim1];
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ti2 - 
+		    wa1[i__] * tr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * tr2 
+		    + wa1[i__] * ti2;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassf2_ */
+
+/*  ------ File dpassf3.f ------ */
+/* Subroutine */ int dpassf3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2)
+{
+    /* Initialized data */
+
+    static r_8 taur = -.5f;
+    static r_8 taui = -.866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[(k * 3 + 2) * cc_dim1 + 1] + cc[(k * 3 + 3) * cc_dim1 + 1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ti2 = cc[(k * 3 + 2) * cc_dim1 + 2] + cc[(k * 3 + 3) * cc_dim1 + 2];
+	ci2 = cc[(k * 3 + 1) * cc_dim1 + 2] + taur * ti2;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 3 + 1) * cc_dim1 + 2] + ti2;
+	cr3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 1] - cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ci3 = taui * (cc[(k * 3 + 2) * cc_dim1 + 2] - cc[(k * 3 + 3) * 
+		cc_dim1 + 2]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci2 - cr3;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    tr2 = cc[i__ - 1 + (k * 3 + 2) * cc_dim1] + cc[i__ - 1 + (k * 3 + 
+		    3) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 2) * cc_dim1] + cc[i__ + (k * 3 + 3) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 2) * cc_dim1] - cc[i__ - 1 + (
+		    k * 3 + 3) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 2) * cc_dim1] - cc[i__ + (k * 3 + 
+		    3) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 - 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    + wa1[i__] * di2;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 - wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 + 
+		    wa2[i__] * di3;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassf3_ */
+
+/*  ------ File dpassf4.f ------ */
+/* Subroutine */ int dpassf4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 1) * cc_dim1 + 2] - cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	ti2 = cc[((k << 2) + 1) * cc_dim1 + 2] + cc[((k << 2) + 3) * cc_dim1 
+		+ 2];
+	tr4 = cc[((k << 2) + 2) * cc_dim1 + 2] - cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	ti3 = cc[((k << 2) + 2) * cc_dim1 + 2] + cc[((k << 2) + 4) * cc_dim1 
+		+ 2];
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ti4 = cc[((k << 2) + 4) * cc_dim1 + 1] - cc[((k << 2) + 2) * cc_dim1 
+		+ 1];
+	tr3 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = ti2 + ti3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ti2 - ti3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 + tr4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ti1 + ti4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ti1 - ti4;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[i__ + ((k << 2) + 3)
+		     * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 2) * cc_dim1] + cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 2) * cc_dim1] - cc[i__ + ((k << 2) + 4)
+		     * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 3) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 4) * cc_dim1] - cc[i__ - 1 + ((k <<
+		     2) + 2) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 2) * cc_dim1] + cc[i__ - 1 + ((k <<
+		     2) + 4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 + tr4;
+	    cr4 = tr1 - tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * cr2 
+		    + wa1[i__] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * ci2 - 
+		    wa1[i__] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * cr3 + 
+		    wa2[i__] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * ci3 - wa2[
+		    i__] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * cr4 
+		    + wa3[i__] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * ci4 - 
+		    wa3[i__] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassf4_ */
+
+/*  ------ File dpassf5.f ------ */
+/* Subroutine */ int dpassf5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4)
+{
+    /* Initialized data */
+
+    static r_8 tr11 = .309016994374947f;
+    static r_8 ti11 = -.951056516295154f;
+    static r_8 tr12 = -.809016994374947f;
+    static r_8 ti12 = -.587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k;
+    static r_8 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    if (*ido != 2) {
+	goto L102;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 2) * cc_dim1 + 2] - cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti2 = cc[(k * 5 + 2) * cc_dim1 + 2] + cc[(k * 5 + 5) * cc_dim1 + 2];
+	ti4 = cc[(k * 5 + 3) * cc_dim1 + 2] - cc[(k * 5 + 4) * cc_dim1 + 2];
+	ti3 = cc[(k * 5 + 3) * cc_dim1 + 2] + cc[(k * 5 + 4) * cc_dim1 + 2];
+	tr5 = cc[(k * 5 + 2) * cc_dim1 + 1] - cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[(k * 5 + 2) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr4 = cc[(k * 5 + 3) * cc_dim1 + 1] - cc[(k * 5 + 4) * cc_dim1 + 1];
+	tr3 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 4) * cc_dim1 + 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	ch[(k + ch_dim2) * ch_dim1 + 2] = cc[(k * 5 + 1) * cc_dim1 + 2] + ti2 
+		+ ti3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	ci2 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr11 * ti2 + tr12 * ti3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci3 = cc[(k * 5 + 1) * cc_dim1 + 2] + tr12 * ti2 + tr11 * ti3;
+	cr5 = ti11 * tr5 + ti12 * tr4;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	cr4 = ti12 * tr5 - ti11 * tr4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 2] = ci2 + cr5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 2] = ci3 + cr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 2] = ci3 - cr4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 2] = ci2 - cr5;
+/* L101: */
+    }
+    return 0;
+L102:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 2; i__ <= i__2; i__ += 2) {
+	    ti5 = cc[i__ + (k * 5 + 2) * cc_dim1] - cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 2) * cc_dim1] + cc[i__ + (k * 5 + 5) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[i__ + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 2) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    5) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[i__ - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * dr2 
+		    + wa1[i__] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 1] * di2 - 
+		    wa1[i__] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * dr3 + 
+		    wa2[i__] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 1] * di3 - wa2[
+		    i__] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * dr4 
+		    + wa3[i__] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 1] * di4 - 
+		    wa3[i__] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * dr5 + 
+		    wa4[i__] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 1] * di5 - wa4[
+		    i__] * dr5;
+/* L103: */
+	}
+/* L104: */
+    }
+    return 0;
+} /* dpassf5_ */
+
+/*  ------ File dadb2.f ------ */
+/* Subroutine */ int dadb2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1)
+{
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 3 + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 + 1] + 
+		cc[*ido + ((k << 1) + 2) * cc_dim1];
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cc[((k << 1) + 1) * cc_dim1 
+		+ 1] - cc[*ido + ((k << 1) + 2) * cc_dim1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + ((k << 1) + 
+		    1) * cc_dim1] + cc[ic - 1 + ((k << 1) + 2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 1) + 1) * cc_dim1] - cc[ic - 1 + ((k << 
+		    1) + 2) * cc_dim1];
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + ((k << 1) + 1) * 
+		    cc_dim1] - cc[ic + ((k << 1) + 2) * cc_dim1];
+	    ti2 = cc[i__ + ((k << 1) + 1) * cc_dim1] + cc[ic + ((k << 1) + 2) 
+		    * cc_dim1];
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * tr2 
+		    - wa1[i__ - 1] * ti2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * ti2 + 
+		    wa1[i__ - 1] * tr2;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[*ido + (k + ch_dim2) * ch_dim1] = cc[*ido + ((k << 1) + 1) * 
+		cc_dim1] + cc[*ido + ((k << 1) + 1) * cc_dim1];
+	ch[*ido + (k + (ch_dim2 << 1)) * ch_dim1] = -(cc[((k << 1) + 2) * 
+		cc_dim1 + 1] + cc[((k << 1) + 2) * cc_dim1 + 1]);
+/* L106: */
+    }
+L107:
+    return 0;
+} /* dadb2_ */
+
+/*  ------ File dadb3.f ------ */
+/* Subroutine */ int dadb3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2)
+{
+    /* Initialized data */
+
+    static r_8 taur = -.5f;
+    static r_8 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = (cc_dim1 << 2) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr2 = cc[*ido + (k * 3 + 2) * cc_dim1] + cc[*ido + (k * 3 + 2) * 
+		cc_dim1];
+	cr2 = cc[(k * 3 + 1) * cc_dim1 + 1] + taur * tr2;
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 3 + 1) * cc_dim1 + 1] + tr2;
+	ci3 = taui * (cc[(k * 3 + 3) * cc_dim1 + 1] + cc[(k * 3 + 3) * 
+		cc_dim1 + 1]);
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci3;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr2 + ci3;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    tr2 = cc[i__ - 1 + (k * 3 + 3) * cc_dim1] + cc[ic - 1 + (k * 3 + 
+		    2) * cc_dim1];
+	    cr2 = cc[i__ - 1 + (k * 3 + 1) * cc_dim1] + taur * tr2;
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 3 + 1) *
+		     cc_dim1] + tr2;
+	    ti2 = cc[i__ + (k * 3 + 3) * cc_dim1] - cc[ic + (k * 3 + 2) * 
+		    cc_dim1];
+	    ci2 = cc[i__ + (k * 3 + 1) * cc_dim1] + taur * ti2;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 3 + 1) * 
+		    cc_dim1] + ti2;
+	    cr3 = taui * (cc[i__ - 1 + (k * 3 + 3) * cc_dim1] - cc[ic - 1 + (
+		    k * 3 + 2) * cc_dim1]);
+	    ci3 = taui * (cc[i__ + (k * 3 + 3) * cc_dim1] + cc[ic + (k * 3 + 
+		    2) * cc_dim1]);
+	    dr2 = cr2 - ci3;
+	    dr3 = cr2 + ci3;
+	    di2 = ci2 + cr3;
+	    di3 = ci2 - cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * dr2 
+		    - wa1[i__ - 1] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * di2 + 
+		    wa1[i__ - 1] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * dr3 - 
+		    wa2[i__ - 1] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * di3 + wa2[
+		    i__ - 1] * dr3;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* dadb3_ */
+
+/*  ------ File dadb4.f ------ */
+/* Subroutine */ int dadb4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3)
+{
+    /* Initialized data */
+
+    static r_8 sqrt2 = 1.414213562373095f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 5 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr1 = cc[((k << 2) + 1) * cc_dim1 + 1] - cc[*ido + ((k << 2) + 4) * 
+		cc_dim1];
+	tr2 = cc[((k << 2) + 1) * cc_dim1 + 1] + cc[*ido + ((k << 2) + 4) * 
+		cc_dim1];
+	tr3 = cc[*ido + ((k << 2) + 2) * cc_dim1] + cc[*ido + ((k << 2) + 2) *
+		 cc_dim1];
+	tr4 = cc[((k << 2) + 3) * cc_dim1 + 1] + cc[((k << 2) + 3) * cc_dim1 
+		+ 1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = tr2 + tr3;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = tr1 - tr4;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = tr2 - tr3;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = tr1 + tr4;
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ti1 = cc[i__ + ((k << 2) + 1) * cc_dim1] + cc[ic + ((k << 2) + 4) 
+		    * cc_dim1];
+	    ti2 = cc[i__ + ((k << 2) + 1) * cc_dim1] - cc[ic + ((k << 2) + 4) 
+		    * cc_dim1];
+	    ti3 = cc[i__ + ((k << 2) + 3) * cc_dim1] - cc[ic + ((k << 2) + 2) 
+		    * cc_dim1];
+	    tr4 = cc[i__ + ((k << 2) + 3) * cc_dim1] + cc[ic + ((k << 2) + 2) 
+		    * cc_dim1];
+	    tr1 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] - cc[ic - 1 + ((k << 
+		    2) + 4) * cc_dim1];
+	    tr2 = cc[i__ - 1 + ((k << 2) + 1) * cc_dim1] + cc[ic - 1 + ((k << 
+		    2) + 4) * cc_dim1];
+	    ti4 = cc[i__ - 1 + ((k << 2) + 3) * cc_dim1] - cc[ic - 1 + ((k << 
+		    2) + 2) * cc_dim1];
+	    tr3 = cc[i__ - 1 + ((k << 2) + 3) * cc_dim1] + cc[ic - 1 + ((k << 
+		    2) + 2) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = tr2 + tr3;
+	    cr3 = tr2 - tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = ti2 + ti3;
+	    ci3 = ti2 - ti3;
+	    cr2 = tr1 - tr4;
+	    cr4 = tr1 + tr4;
+	    ci2 = ti1 + ti4;
+	    ci4 = ti1 - ti4;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * cr2 
+		    - wa1[i__ - 1] * ci2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * ci2 + 
+		    wa1[i__ - 1] * cr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * cr3 - 
+		    wa2[i__ - 1] * ci3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * ci3 + wa2[
+		    i__ - 1] * cr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * cr4 
+		    - wa3[i__ - 1] * ci4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * ci4 + 
+		    wa3[i__ - 1] * cr4;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = cc[((k << 2) + 2) * cc_dim1 + 1] + cc[((k << 2) + 4) * cc_dim1 
+		+ 1];
+	ti2 = cc[((k << 2) + 4) * cc_dim1 + 1] - cc[((k << 2) + 2) * cc_dim1 
+		+ 1];
+	tr1 = cc[*ido + ((k << 2) + 1) * cc_dim1] - cc[*ido + ((k << 2) + 3) *
+		 cc_dim1];
+	tr2 = cc[*ido + ((k << 2) + 1) * cc_dim1] + cc[*ido + ((k << 2) + 3) *
+		 cc_dim1];
+	ch[*ido + (k + ch_dim2) * ch_dim1] = tr2 + tr2;
+	ch[*ido + (k + (ch_dim2 << 1)) * ch_dim1] = sqrt2 * (tr1 - ti1);
+	ch[*ido + (k + ch_dim2 * 3) * ch_dim1] = ti2 + ti2;
+	ch[*ido + (k + (ch_dim2 << 2)) * ch_dim1] = -sqrt2 * (tr1 + ti1);
+/* L106: */
+    }
+L107:
+    return 0;
+} /* dadb4_ */
+
+/*  ------ File dadb5.f ------ */
+/* Subroutine */ int dadb5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4)
+{
+    /* Initialized data */
+
+    static r_8 tr11 = .309016994374947f;
+    static r_8 ti11 = .951056516295154f;
+    static r_8 tr12 = -.809016994374947f;
+    static r_8 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_offset, ch_dim1, ch_dim2, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, 
+	    ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_offset = cc_dim1 * 6 + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti5 = cc[(k * 5 + 3) * cc_dim1 + 1] + cc[(k * 5 + 3) * cc_dim1 + 1];
+	ti4 = cc[(k * 5 + 5) * cc_dim1 + 1] + cc[(k * 5 + 5) * cc_dim1 + 1];
+	tr2 = cc[*ido + (k * 5 + 2) * cc_dim1] + cc[*ido + (k * 5 + 2) * 
+		cc_dim1];
+	tr3 = cc[*ido + (k * 5 + 4) * cc_dim1] + cc[*ido + (k * 5 + 4) * 
+		cc_dim1];
+	ch[(k + ch_dim2) * ch_dim1 + 1] = cc[(k * 5 + 1) * cc_dim1 + 1] + tr2 
+		+ tr3;
+	cr2 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr11 * tr2 + tr12 * tr3;
+	cr3 = cc[(k * 5 + 1) * cc_dim1 + 1] + tr12 * tr2 + tr11 * tr3;
+	ci5 = ti11 * ti5 + ti12 * ti4;
+	ci4 = ti12 * ti5 - ti11 * ti4;
+	ch[(k + (ch_dim2 << 1)) * ch_dim1 + 1] = cr2 - ci5;
+	ch[(k + ch_dim2 * 3) * ch_dim1 + 1] = cr3 - ci4;
+	ch[(k + (ch_dim2 << 2)) * ch_dim1 + 1] = cr3 + ci4;
+	ch[(k + ch_dim2 * 5) * ch_dim1 + 1] = cr2 + ci5;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    ti5 = cc[i__ + (k * 5 + 3) * cc_dim1] + cc[ic + (k * 5 + 2) * 
+		    cc_dim1];
+	    ti2 = cc[i__ + (k * 5 + 3) * cc_dim1] - cc[ic + (k * 5 + 2) * 
+		    cc_dim1];
+	    ti4 = cc[i__ + (k * 5 + 5) * cc_dim1] + cc[ic + (k * 5 + 4) * 
+		    cc_dim1];
+	    ti3 = cc[i__ + (k * 5 + 5) * cc_dim1] - cc[ic + (k * 5 + 4) * 
+		    cc_dim1];
+	    tr5 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] - cc[ic - 1 + (k * 5 + 
+		    2) * cc_dim1];
+	    tr2 = cc[i__ - 1 + (k * 5 + 3) * cc_dim1] + cc[ic - 1 + (k * 5 + 
+		    2) * cc_dim1];
+	    tr4 = cc[i__ - 1 + (k * 5 + 5) * cc_dim1] - cc[ic - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    tr3 = cc[i__ - 1 + (k * 5 + 5) * cc_dim1] + cc[ic - 1 + (k * 5 + 
+		    4) * cc_dim1];
+	    ch[i__ - 1 + (k + ch_dim2) * ch_dim1] = cc[i__ - 1 + (k * 5 + 1) *
+		     cc_dim1] + tr2 + tr3;
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * 5 + 1) * 
+		    cc_dim1] + ti2 + ti3;
+	    cr2 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr11 * tr2 + tr12 * 
+		    tr3;
+	    ci2 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr11 * ti2 + tr12 * ti3;
+	    cr3 = cc[i__ - 1 + (k * 5 + 1) * cc_dim1] + tr12 * tr2 + tr11 * 
+		    tr3;
+	    ci3 = cc[i__ + (k * 5 + 1) * cc_dim1] + tr12 * ti2 + tr11 * ti3;
+	    cr5 = ti11 * tr5 + ti12 * tr4;
+	    ci5 = ti11 * ti5 + ti12 * ti4;
+	    cr4 = ti12 * tr5 - ti11 * tr4;
+	    ci4 = ti12 * ti5 - ti11 * ti4;
+	    dr3 = cr3 - ci4;
+	    dr4 = cr3 + ci4;
+	    di3 = ci3 + cr4;
+	    di4 = ci3 - cr4;
+	    dr5 = cr2 + ci5;
+	    dr2 = cr2 - ci5;
+	    di5 = ci2 - cr5;
+	    di2 = ci2 + cr5;
+	    ch[i__ - 1 + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * dr2 
+		    - wa1[i__ - 1] * di2;
+	    ch[i__ + (k + (ch_dim2 << 1)) * ch_dim1] = wa1[i__ - 2] * di2 + 
+		    wa1[i__ - 1] * dr2;
+	    ch[i__ - 1 + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * dr3 - 
+		    wa2[i__ - 1] * di3;
+	    ch[i__ + (k + ch_dim2 * 3) * ch_dim1] = wa2[i__ - 2] * di3 + wa2[
+		    i__ - 1] * dr3;
+	    ch[i__ - 1 + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * dr4 
+		    - wa3[i__ - 1] * di4;
+	    ch[i__ + (k + (ch_dim2 << 2)) * ch_dim1] = wa3[i__ - 2] * di4 + 
+		    wa3[i__ - 1] * dr4;
+	    ch[i__ - 1 + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 2] * dr5 - 
+		    wa4[i__ - 1] * di5;
+	    ch[i__ + (k + ch_dim2 * 5) * ch_dim1] = wa4[i__ - 2] * di5 + wa4[
+		    i__ - 1] * dr5;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* dadb5_ */
+
+/*  ------ File dadbg.f ------ */
+/* Subroutine */ int dadbg_(integer *ido, integer *ip, integer *l1, integer *
+	idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa)
+{
+    /* Initialized data */
+
+    static r_8 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);  remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer idij, ipph, i__, j, k, l, j2, ic, jc, lc, ik, is;
+    static r_8 dc2, ai1, ai2, ar1, ar2, ds2;
+    static integer nbd;
+    static r_8 dcp, arg, dsp, ar1h, ar2h;
+    static integer idp2, ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    arg = tpi / (r_8) (*ip);
+    dcp = cos(arg);
+    dsp = sin(arg);
+    idp2 = *ido + 2;
+    nbd = (*ido - 1) / 2;
+    ipp2 = *ip + 2;
+    ipph = (*ip + 1) / 2;
+    if (*ido < *l1) {
+	goto L103;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L101: */
+	}
+/* L102: */
+    }
+    goto L106;
+L103:
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[i__ + (k + ch_dim2) * ch_dim1] = cc[i__ + (k * cc_dim2 + 1) * 
+		    cc_dim1];
+/* L104: */
+	}
+/* L105: */
+    }
+L106:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = cc[*ido + (j2 - 2 + k * 
+		    cc_dim2) * cc_dim1] + cc[*ido + (j2 - 2 + k * cc_dim2) * 
+		    cc_dim1];
+	    ch[(k + jc * ch_dim2) * ch_dim1 + 1] = cc[(j2 - 1 + k * cc_dim2) *
+		     cc_dim1 + 1] + cc[(j2 - 1 + k * cc_dim2) * cc_dim1 + 1];
+/* L107: */
+	}
+/* L108: */
+    }
+    if (*ido == 1) {
+	goto L116;
+    }
+    if (nbd < *l1) {
+	goto L112;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ic = idp2 - i__;
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] + cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] - cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] - cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] + cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+/* L109: */
+	    }
+/* L110: */
+	}
+/* L111: */
+    }
+    goto L116;
+L112:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] + cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = cc[i__ - 1 + ((j 
+			<< 1) - 1 + k * cc_dim2) * cc_dim1] - cc[ic - 1 + ((j 
+			<< 1) - 2 + k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] - cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = cc[i__ + ((j << 1) - 
+			1 + k * cc_dim2) * cc_dim1] + cc[ic + ((j << 1) - 2 + 
+			k * cc_dim2) * cc_dim1];
+/* L113: */
+	    }
+/* L114: */
+	}
+/* L115: */
+    }
+L116:
+    ar1 = 1.f;
+    ai1 = 0.f;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	ar1h = dcp * ar1 - dsp * ai1;
+	ai1 = dcp * ai1 + dsp * ar1;
+	ar1 = ar1h;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    c2[ik + l * c2_dim1] = ch2[ik + ch2_dim1] + ar1 * ch2[ik + (
+		    ch2_dim1 << 1)];
+	    c2[ik + lc * c2_dim1] = ai1 * ch2[ik + *ip * ch2_dim1];
+/* L117: */
+	}
+	dc2 = ar1;
+	ds2 = ai1;
+	ar2 = ar1;
+	ai2 = ai1;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    ar2h = dc2 * ar2 - ds2 * ai2;
+	    ai2 = dc2 * ai2 + ds2 * ar2;
+	    ar2 = ar2h;
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		c2[ik + l * c2_dim1] += ar2 * ch2[ik + j * ch2_dim1];
+		c2[ik + lc * c2_dim1] += ai2 * ch2[ik + jc * ch2_dim1];
+/* L118: */
+	    }
+/* L119: */
+	}
+/* L120: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += ch2[ik + j * ch2_dim1];
+/* L121: */
+	}
+/* L122: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1] - c1[(k + jc * c1_dim2) * c1_dim1 + 1];
+	    ch[(k + jc * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1] + c1[(k + jc * c1_dim2) * c1_dim1 + 1];
+/* L123: */
+	}
+/* L124: */
+    }
+    if (*ido == 1) {
+	goto L132;
+    }
+    if (nbd < *l1) {
+	goto L128;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k + 
+			j * c1_dim2) * c1_dim1] - c1[i__ + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k 
+			+ j * c1_dim2) * c1_dim1] + c1[i__ + (k + jc * 
+			c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] + c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] - c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+/* L125: */
+	    }
+/* L126: */
+	}
+/* L127: */
+    }
+    goto L132;
+L128:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k + 
+			j * c1_dim2) * c1_dim1] - c1[i__ + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ - 1 + (k + jc * ch_dim2) * ch_dim1] = c1[i__ - 1 + (k 
+			+ j * c1_dim2) * c1_dim1] + c1[i__ + (k + jc * 
+			c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] + c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+		ch[i__ + (k + jc * ch_dim2) * ch_dim1] = c1[i__ + (k + j * 
+			c1_dim2) * c1_dim1] - c1[i__ - 1 + (k + jc * c1_dim2) 
+			* c1_dim1];
+/* L129: */
+	    }
+/* L130: */
+	}
+/* L131: */
+    }
+L132:
+    if (*ido == 1) {
+	return 0;
+    }
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L133: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1];
+/* L134: */
+	}
+/* L135: */
+    }
+    if (nbd > *l1) {
+	goto L139;
+    }
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	idij = is;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L136: */
+	    }
+/* L137: */
+	}
+/* L138: */
+    }
+    goto L143;
+L139:
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = is;
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[
+			i__ - 1 + (k + j * ch_dim2) * ch_dim1] - wa[idij] * 
+			ch[i__ + (k + j * ch_dim2) * ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = wa[idij - 1] * ch[i__ 
+			+ (k + j * ch_dim2) * ch_dim1] + wa[idij] * ch[i__ - 
+			1 + (k + j * ch_dim2) * ch_dim1];
+/* L140: */
+	    }
+/* L141: */
+	}
+/* L142: */
+    }
+L143:
+    return 0;
+} /* dadbg_ */
+
+/*  ------ File dadf2.f ------ */
+/* Subroutine */ int dadf2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1)
+{
+    /* System generated locals */
+    integer ch_dim1, ch_offset, cc_dim1, cc_dim2, cc_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ti2, tr2;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 3 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[((k << 1) + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+	ch[*ido + ((k << 1) + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] 
+		- cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    tr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    ti2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    ch[i__ + ((k << 1) + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ti2;
+	    ch[ic + ((k << 1) + 2) * ch_dim1] = ti2 - cc[i__ + (k + cc_dim2) *
+		     cc_dim1];
+	    ch[i__ - 1 + ((k << 1) + 1) * ch_dim1] = cc[i__ - 1 + (k + 
+		    cc_dim2) * cc_dim1] + tr2;
+	    ch[ic - 1 + ((k << 1) + 2) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2)
+		     * cc_dim1] - tr2;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ch[((k << 1) + 2) * ch_dim1 + 1] = -cc[*ido + (k + (cc_dim2 << 1)) * 
+		cc_dim1];
+	ch[*ido + ((k << 1) + 1) * ch_dim1] = cc[*ido + (k + cc_dim2) * 
+		cc_dim1];
+/* L106: */
+    }
+L107:
+    return 0;
+} /* dadf2_ */
+
+/*  ------ File dadf3.f ------ */
+/* Subroutine */ int dadf3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2)
+{
+    /* Initialized data */
+
+    static r_8 taur = -.5f;
+    static r_8 taui = .866025403784439f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_offset, cc_dim1, cc_dim2, cc_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = (ch_dim1 << 2) + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	cr2 = cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[(k * 3 + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + cr2;
+	ch[(k * 3 + 3) * ch_dim1 + 1] = taui * (cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1] - cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1]);
+	ch[*ido + (k * 3 + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		taur * cr2;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    dr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    di2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    dr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    di3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    cr2 = dr2 + dr3;
+	    ci2 = di2 + di3;
+	    ch[i__ - 1 + (k * 3 + 1) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2) *
+		     cc_dim1] + cr2;
+	    ch[i__ + (k * 3 + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ci2;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + taur * cr2;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + taur * ci2;
+	    tr3 = taui * (di2 - di3);
+	    ti3 = taui * (dr3 - dr2);
+	    ch[i__ - 1 + (k * 3 + 3) * ch_dim1] = tr2 + tr3;
+	    ch[ic - 1 + (k * 3 + 2) * ch_dim1] = tr2 - tr3;
+	    ch[i__ + (k * 3 + 3) * ch_dim1] = ti2 + ti3;
+	    ch[ic + (k * 3 + 2) * ch_dim1] = ti3 - ti2;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* dadf3_ */
+
+/*  ------ File dadf4.f ------ */
+/* Subroutine */ int dadf4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3)
+{
+    /* Initialized data */
+
+    static r_8 hsqt2 = .7071067811865475f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_dim2, cc_offset, ch_dim1, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, 
+	    tr3, tr4;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 5 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	tr1 = cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1] + cc[(k + (cc_dim2 << 2))
+		 * cc_dim1 + 1];
+	tr2 = cc[(k + cc_dim2) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[((k << 2) + 1) * ch_dim1 + 1] = tr1 + tr2;
+	ch[*ido + ((k << 2) + 4) * ch_dim1] = tr2 - tr1;
+	ch[*ido + ((k << 2) + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] 
+		- cc[(k + cc_dim2 * 3) * cc_dim1 + 1];
+	ch[((k << 2) + 3) * ch_dim1 + 1] = cc[(k + (cc_dim2 << 2)) * cc_dim1 
+		+ 1] - cc[(k + (cc_dim2 << 1)) * cc_dim1 + 1];
+/* L101: */
+    }
+    if ((i__1 = *ido - 2) < 0) {
+	goto L107;
+    } else if (i__1 == 0) {
+	goto L105;
+    } else {
+	goto L102;
+    }
+L102:
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    cr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    ci2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    cr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    ci3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    cr4 = wa3[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * cc_dim1] 
+		    + wa3[i__ - 1] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1];
+	    ci4 = wa3[i__ - 2] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1] - 
+		    wa3[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * 
+		    cc_dim1];
+	    tr1 = cr2 + cr4;
+	    tr4 = cr4 - cr2;
+	    ti1 = ci2 + ci4;
+	    ti4 = ci2 - ci4;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + ci3;
+	    ti3 = cc[i__ + (k + cc_dim2) * cc_dim1] - ci3;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + cr3;
+	    tr3 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] - cr3;
+	    ch[i__ - 1 + ((k << 2) + 1) * ch_dim1] = tr1 + tr2;
+	    ch[ic - 1 + ((k << 2) + 4) * ch_dim1] = tr2 - tr1;
+	    ch[i__ + ((k << 2) + 1) * ch_dim1] = ti1 + ti2;
+	    ch[ic + ((k << 2) + 4) * ch_dim1] = ti1 - ti2;
+	    ch[i__ - 1 + ((k << 2) + 3) * ch_dim1] = ti4 + tr3;
+	    ch[ic - 1 + ((k << 2) + 2) * ch_dim1] = tr3 - ti4;
+	    ch[i__ + ((k << 2) + 3) * ch_dim1] = tr4 + ti3;
+	    ch[ic + ((k << 2) + 2) * ch_dim1] = tr4 - ti3;
+/* L103: */
+	}
+/* L104: */
+    }
+    if (*ido % 2 == 1) {
+	return 0;
+    }
+L105:
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	ti1 = -hsqt2 * (cc[*ido + (k + (cc_dim2 << 1)) * cc_dim1] + cc[*ido + 
+		(k + (cc_dim2 << 2)) * cc_dim1]);
+	tr1 = hsqt2 * (cc[*ido + (k + (cc_dim2 << 1)) * cc_dim1] - cc[*ido + (
+		k + (cc_dim2 << 2)) * cc_dim1]);
+	ch[*ido + ((k << 2) + 1) * ch_dim1] = tr1 + cc[*ido + (k + cc_dim2) * 
+		cc_dim1];
+	ch[*ido + ((k << 2) + 3) * ch_dim1] = cc[*ido + (k + cc_dim2) * 
+		cc_dim1] - tr1;
+	ch[((k << 2) + 2) * ch_dim1 + 1] = ti1 - cc[*ido + (k + cc_dim2 * 3) *
+		 cc_dim1];
+	ch[((k << 2) + 4) * ch_dim1 + 1] = ti1 + cc[*ido + (k + cc_dim2 * 3) *
+		 cc_dim1];
+/* L106: */
+    }
+L107:
+    return 0;
+} /* dadf4_ */
+
+/*  ------ File dadf5.f ------ */
+/* Subroutine */ int dadf5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, 
+	r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4)
+{
+    /* Initialized data */
+
+    static r_8 tr11 = .309016994374947f;
+    static r_8 ti11 = .951056516295154f;
+    static r_8 tr12 = -.809016994374947f;
+    static r_8 ti12 = .587785252292473f;
+
+    /* System generated locals */
+    integer cc_dim1, cc_dim2, cc_offset, ch_dim1, ch_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, k, ic;
+    static r_8 ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, 
+	    dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
+    static integer idp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_offset = ch_dim1 * 6 + 1;
+    ch -= ch_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *l1;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    --wa1;
+    --wa2;
+    --wa3;
+    --wa4;
+
+    /* Function Body */
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	cr2 = cc[(k + cc_dim2 * 5) * cc_dim1 + 1] + cc[(k + (cc_dim2 << 1)) * 
+		cc_dim1 + 1];
+	ci5 = cc[(k + cc_dim2 * 5) * cc_dim1 + 1] - cc[(k + (cc_dim2 << 1)) * 
+		cc_dim1 + 1];
+	cr3 = cc[(k + (cc_dim2 << 2)) * cc_dim1 + 1] + cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ci4 = cc[(k + (cc_dim2 << 2)) * cc_dim1 + 1] - cc[(k + cc_dim2 * 3) * 
+		cc_dim1 + 1];
+	ch[(k * 5 + 1) * ch_dim1 + 1] = cc[(k + cc_dim2) * cc_dim1 + 1] + cr2 
+		+ cr3;
+	ch[*ido + (k * 5 + 2) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		tr11 * cr2 + tr12 * cr3;
+	ch[(k * 5 + 3) * ch_dim1 + 1] = ti11 * ci5 + ti12 * ci4;
+	ch[*ido + (k * 5 + 4) * ch_dim1] = cc[(k + cc_dim2) * cc_dim1 + 1] + 
+		tr12 * cr2 + tr11 * cr3;
+	ch[(k * 5 + 5) * ch_dim1 + 1] = ti12 * ci5 - ti11 * ci4;
+/* L101: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    idp2 = *ido + 2;
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    dr2 = wa1[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * cc_dim1] 
+		    + wa1[i__ - 1] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1];
+	    di2 = wa1[i__ - 2] * cc[i__ + (k + (cc_dim2 << 1)) * cc_dim1] - 
+		    wa1[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 1)) * 
+		    cc_dim1];
+	    dr3 = wa2[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1] + 
+		    wa2[i__ - 1] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1];
+	    di3 = wa2[i__ - 2] * cc[i__ + (k + cc_dim2 * 3) * cc_dim1] - wa2[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 3) * cc_dim1];
+	    dr4 = wa3[i__ - 2] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * cc_dim1] 
+		    + wa3[i__ - 1] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1];
+	    di4 = wa3[i__ - 2] * cc[i__ + (k + (cc_dim2 << 2)) * cc_dim1] - 
+		    wa3[i__ - 1] * cc[i__ - 1 + (k + (cc_dim2 << 2)) * 
+		    cc_dim1];
+	    dr5 = wa4[i__ - 2] * cc[i__ - 1 + (k + cc_dim2 * 5) * cc_dim1] + 
+		    wa4[i__ - 1] * cc[i__ + (k + cc_dim2 * 5) * cc_dim1];
+	    di5 = wa4[i__ - 2] * cc[i__ + (k + cc_dim2 * 5) * cc_dim1] - wa4[
+		    i__ - 1] * cc[i__ - 1 + (k + cc_dim2 * 5) * cc_dim1];
+	    cr2 = dr2 + dr5;
+	    ci5 = dr5 - dr2;
+	    cr5 = di2 - di5;
+	    ci2 = di2 + di5;
+	    cr3 = dr3 + dr4;
+	    ci4 = dr4 - dr3;
+	    cr4 = di3 - di4;
+	    ci3 = di3 + di4;
+	    ch[i__ - 1 + (k * 5 + 1) * ch_dim1] = cc[i__ - 1 + (k + cc_dim2) *
+		     cc_dim1] + cr2 + cr3;
+	    ch[i__ + (k * 5 + 1) * ch_dim1] = cc[i__ + (k + cc_dim2) * 
+		    cc_dim1] + ci2 + ci3;
+	    tr2 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + tr11 * cr2 + tr12 * 
+		    cr3;
+	    ti2 = cc[i__ + (k + cc_dim2) * cc_dim1] + tr11 * ci2 + tr12 * ci3;
+	    tr3 = cc[i__ - 1 + (k + cc_dim2) * cc_dim1] + tr12 * cr2 + tr11 * 
+		    cr3;
+	    ti3 = cc[i__ + (k + cc_dim2) * cc_dim1] + tr12 * ci2 + tr11 * ci3;
+	    tr5 = ti11 * cr5 + ti12 * cr4;
+	    ti5 = ti11 * ci5 + ti12 * ci4;
+	    tr4 = ti12 * cr5 - ti11 * cr4;
+	    ti4 = ti12 * ci5 - ti11 * ci4;
+	    ch[i__ - 1 + (k * 5 + 3) * ch_dim1] = tr2 + tr5;
+	    ch[ic - 1 + (k * 5 + 2) * ch_dim1] = tr2 - tr5;
+	    ch[i__ + (k * 5 + 3) * ch_dim1] = ti2 + ti5;
+	    ch[ic + (k * 5 + 2) * ch_dim1] = ti5 - ti2;
+	    ch[i__ - 1 + (k * 5 + 5) * ch_dim1] = tr3 + tr4;
+	    ch[ic - 1 + (k * 5 + 4) * ch_dim1] = tr3 - tr4;
+	    ch[i__ + (k * 5 + 5) * ch_dim1] = ti3 + ti4;
+	    ch[ic + (k * 5 + 4) * ch_dim1] = ti4 - ti3;
+/* L102: */
+	}
+/* L103: */
+    }
+    return 0;
+} /* dadf5_ */
+
+/*  ------ File dadfg.f ------ */
+/* Subroutine */ int dadfg_(integer *ido, integer *ip, integer *l1, integer *
+	idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa)
+{
+    /* Initialized data */
+
+    static r_8 tpi = 6.28318530717959f;
+
+    /* System generated locals */
+    integer ch_dim1, ch_dim2, ch_offset, cc_dim1, cc_dim2, cc_offset, c1_dim1,
+	     c1_dim2, c1_offset, c2_dim1, c2_offset, ch2_dim1, ch2_offset, 
+	    i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc);   */
+
+    /* Local variables */
+    static integer idij, ipph, i__, j, k, l, j2, ic, jc, lc, ik, is;
+    static r_8 dc2, ai1, ai2, ar1, ar2, ds2;
+    static integer nbd;
+    static r_8 dcp, arg, dsp, ar1h, ar2h;
+    static integer idp2, ipp2;
+
+    /* Parameter adjustments */
+    ch_dim1 = *ido;
+    ch_dim2 = *l1;
+    ch_offset = ch_dim1 * (ch_dim2 + 1) + 1;
+    ch -= ch_offset;
+    c1_dim1 = *ido;
+    c1_dim2 = *l1;
+    c1_offset = c1_dim1 * (c1_dim2 + 1) + 1;
+    c1 -= c1_offset;
+    cc_dim1 = *ido;
+    cc_dim2 = *ip;
+    cc_offset = cc_dim1 * (cc_dim2 + 1) + 1;
+    cc -= cc_offset;
+    ch2_dim1 = *idl1;
+    ch2_offset = ch2_dim1 + 1;
+    ch2 -= ch2_offset;
+    c2_dim1 = *idl1;
+    c2_offset = c2_dim1 + 1;
+    c2 -= c2_offset;
+    --wa;
+
+    /* Function Body */
+    arg = tpi / (r_8) (*ip);
+    dcp = cos(arg);
+    dsp = sin(arg);
+    ipph = (*ip + 1) / 2;
+    ipp2 = *ip + 2;
+    idp2 = *ido + 2;
+    nbd = (*ido - 1) / 2;
+    if (*ido == 1) {
+	goto L119;
+    }
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	ch2[ik + ch2_dim1] = c2[ik + c2_dim1];
+/* L101: */
+    }
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    ch[(k + j * ch_dim2) * ch_dim1 + 1] = c1[(k + j * c1_dim2) * 
+		    c1_dim1 + 1];
+/* L102: */
+	}
+/* L103: */
+    }
+    if (nbd > *l1) {
+	goto L107;
+    }
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	idij = is;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    idij += 2;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[
+			i__ - 1 + (k + j * c1_dim2) * c1_dim1] + wa[idij] * 
+			c1[i__ + (k + j * c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[i__ 
+			+ (k + j * c1_dim2) * c1_dim1] - wa[idij] * c1[i__ - 
+			1 + (k + j * c1_dim2) * c1_dim1];
+/* L104: */
+	    }
+/* L105: */
+	}
+/* L106: */
+    }
+    goto L111;
+L107:
+    is = -(*ido);
+    i__1 = *ip;
+    for (j = 2; j <= i__1; ++j) {
+	is += *ido;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    idij = is;
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		idij += 2;
+		ch[i__ - 1 + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[
+			i__ - 1 + (k + j * c1_dim2) * c1_dim1] + wa[idij] * 
+			c1[i__ + (k + j * c1_dim2) * c1_dim1];
+		ch[i__ + (k + j * ch_dim2) * ch_dim1] = wa[idij - 1] * c1[i__ 
+			+ (k + j * c1_dim2) * c1_dim1] - wa[idij] * c1[i__ - 
+			1 + (k + j * c1_dim2) * c1_dim1];
+/* L108: */
+	    }
+/* L109: */
+	}
+/* L110: */
+    }
+L111:
+    if (nbd < *l1) {
+	goto L115;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + 
+			j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		c1[i__ - 1 + (k + jc * c1_dim2) * c1_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = ch[i__ + (k + j * 
+			ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + jc * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + jc 
+			* ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + j * ch_dim2)
+			 * ch_dim1];
+/* L112: */
+	    }
+/* L113: */
+	}
+/* L114: */
+    }
+    goto L121;
+L115:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		c1[i__ - 1 + (k + j * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + 
+			j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		c1[i__ - 1 + (k + jc * c1_dim2) * c1_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + j * c1_dim2) * c1_dim1] = ch[i__ + (k + j * 
+			ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		c1[i__ + (k + jc * c1_dim2) * c1_dim1] = ch[i__ - 1 + (k + jc 
+			* ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + j * ch_dim2)
+			 * ch_dim1];
+/* L116: */
+	    }
+/* L117: */
+	}
+/* L118: */
+    }
+    goto L121;
+L119:
+    i__1 = *idl1;
+    for (ik = 1; ik <= i__1; ++ik) {
+	c2[ik + c2_dim1] = ch2[ik + ch2_dim1];
+/* L120: */
+    }
+L121:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    c1[(k + j * c1_dim2) * c1_dim1 + 1] = ch[(k + j * ch_dim2) * 
+		    ch_dim1 + 1] + ch[(k + jc * ch_dim2) * ch_dim1 + 1];
+	    c1[(k + jc * c1_dim2) * c1_dim1 + 1] = ch[(k + jc * ch_dim2) * 
+		    ch_dim1 + 1] - ch[(k + j * ch_dim2) * ch_dim1 + 1];
+/* L122: */
+	}
+/* L123: */
+    }
+
+    ar1 = 1.f;
+    ai1 = 0.f;
+    i__1 = ipph;
+    for (l = 2; l <= i__1; ++l) {
+	lc = ipp2 - l;
+	ar1h = dcp * ar1 - dsp * ai1;
+	ai1 = dcp * ai1 + dsp * ar1;
+	ar1 = ar1h;
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + l * ch2_dim1] = c2[ik + c2_dim1] + ar1 * c2[ik + (
+		    c2_dim1 << 1)];
+	    ch2[ik + lc * ch2_dim1] = ai1 * c2[ik + *ip * c2_dim1];
+/* L124: */
+	}
+	dc2 = ar1;
+	ds2 = ai1;
+	ar2 = ar1;
+	ai2 = ai1;
+	i__2 = ipph;
+	for (j = 3; j <= i__2; ++j) {
+	    jc = ipp2 - j;
+	    ar2h = dc2 * ar2 - ds2 * ai2;
+	    ai2 = dc2 * ai2 + ds2 * ar2;
+	    ar2 = ar2h;
+	    i__3 = *idl1;
+	    for (ik = 1; ik <= i__3; ++ik) {
+		ch2[ik + l * ch2_dim1] += ar2 * c2[ik + j * c2_dim1];
+		ch2[ik + lc * ch2_dim1] += ai2 * c2[ik + jc * c2_dim1];
+/* L125: */
+	    }
+/* L126: */
+	}
+/* L127: */
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	i__2 = *idl1;
+	for (ik = 1; ik <= i__2; ++ik) {
+	    ch2[ik + ch2_dim1] += c2[ik + j * c2_dim1];
+/* L128: */
+	}
+/* L129: */
+    }
+
+    if (*ido < *l1) {
+	goto L132;
+    }
+    i__1 = *l1;
+    for (k = 1; k <= i__1; ++k) {
+	i__2 = *ido;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    cc[i__ + (k * cc_dim2 + 1) * cc_dim1] = ch[i__ + (k + ch_dim2) * 
+		    ch_dim1];
+/* L130: */
+	}
+/* L131: */
+    }
+    goto L135;
+L132:
+    i__1 = *ido;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    cc[i__ + (k * cc_dim2 + 1) * cc_dim1] = ch[i__ + (k + ch_dim2) * 
+		    ch_dim1];
+/* L133: */
+	}
+/* L134: */
+    }
+L135:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    cc[*ido + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[(k + j * ch_dim2)
+		     * ch_dim1 + 1];
+	    cc[(j2 - 1 + k * cc_dim2) * cc_dim1 + 1] = ch[(k + jc * ch_dim2) *
+		     ch_dim1 + 1];
+/* L136: */
+	}
+/* L137: */
+    }
+    if (*ido == 1) {
+	return 0;
+    }
+    if (nbd < *l1) {
+	goto L141;
+    }
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *l1;
+	for (k = 1; k <= i__2; ++k) {
+	    i__3 = *ido;
+	    for (i__ = 3; i__ <= i__3; i__ += 2) {
+		ic = idp2 - i__;
+		cc[i__ - 1 + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + 
+			(k + j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[ic - 1 + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + (
+			k + j * ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[i__ + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		cc[ic + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + jc *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + j * ch_dim2) * 
+			ch_dim1];
+/* L138: */
+	    }
+/* L139: */
+	}
+/* L140: */
+    }
+    return 0;
+L141:
+    i__1 = ipph;
+    for (j = 2; j <= i__1; ++j) {
+	jc = ipp2 - j;
+	j2 = j + j;
+	i__2 = *ido;
+	for (i__ = 3; i__ <= i__2; i__ += 2) {
+	    ic = idp2 - i__;
+	    i__3 = *l1;
+	    for (k = 1; k <= i__3; ++k) {
+		cc[i__ - 1 + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + 
+			(k + j * ch_dim2) * ch_dim1] + ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[ic - 1 + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ - 1 + (
+			k + j * ch_dim2) * ch_dim1] - ch[i__ - 1 + (k + jc * 
+			ch_dim2) * ch_dim1];
+		cc[i__ + (j2 - 1 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + j *
+			 ch_dim2) * ch_dim1] + ch[i__ + (k + jc * ch_dim2) * 
+			ch_dim1];
+		cc[ic + (j2 - 2 + k * cc_dim2) * cc_dim1] = ch[i__ + (k + jc *
+			 ch_dim2) * ch_dim1] - ch[i__ + (k + j * ch_dim2) * 
+			ch_dim1];
+/* L142: */
+	    }
+/* L143: */
+	}
+/* L144: */
+    }
+    return 0;
+} /* dadfg_ */
+
+/*  ------ File dfftb.f ------ */
+/* Subroutine */ int dfftb_(integer *n, r_8 *r__, r_8 *wsave)
+{
+    extern /* Subroutine */ int dfftb1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    int_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --r__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    dfftb1_(n, &r__[1], &wsave[1], &wsave[*n + 1], (int_8 *)&wsave[(*n << 1) + 1]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* dfftb_ */
+
+/*  ------ File dfftb1.f ------ */
+/* Subroutine */ int dfftb1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, 
+	int_8 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    extern /* Subroutine */ int dadb2_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *), dadb3_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *), dadb4_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *), dadb5_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer i__;
+    extern /* Subroutine */ int dadbg_(integer *, integer *, integer *, 
+	    integer *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 0;
+    l1 = 1;
+    iw = 1;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	l2 = ip * l1;
+	ido = *n / l2;
+	idl1 = ido * l1;
+	if (ip != 4) {
+	    goto L103;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	if (na != 0) {
+	    goto L101;
+	}
+	dadb4_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L102;
+L101:
+	dadb4_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+L102:
+	na = 1 - na;
+	goto L115;
+L103:
+	if (ip != 2) {
+	    goto L106;
+	}
+	if (na != 0) {
+	    goto L104;
+	}
+	dadb2_(&ido, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L105;
+L104:
+	dadb2_(&ido, &l1, &ch[1], &c__[1], &wa[iw]);
+L105:
+	na = 1 - na;
+	goto L115;
+L106:
+	if (ip != 3) {
+	    goto L109;
+	}
+	ix2 = iw + ido;
+	if (na != 0) {
+	    goto L107;
+	}
+	dadb3_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L108;
+L107:
+	dadb3_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+L108:
+	na = 1 - na;
+	goto L115;
+L109:
+	if (ip != 5) {
+	    goto L112;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	ix4 = ix3 + ido;
+	if (na != 0) {
+	    goto L110;
+	}
+	dadb5_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L111;
+L110:
+	dadb5_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+L111:
+	na = 1 - na;
+	goto L115;
+L112:
+	if (na != 0) {
+	    goto L113;
+	}
+	dadbg_(&ido, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1], &ch[
+		1], &wa[iw]);
+	goto L114;
+L113:
+	dadbg_(&ido, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], &c__[1]
+		, &wa[iw]);
+L114:
+	if (ido == 1) {
+	    na = 1 - na;
+	}
+L115:
+	l1 = l2;
+	iw += (ip - 1) * ido;
+/* L116: */
+    }
+    if (na == 0) {
+	return 0;
+    }
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L117: */
+    }
+    return 0;
+} /* dfftb1_ */
+
+/*  ------ File dfftf.f ------ */
+/* Subroutine */ int dfftf_(integer *n, r_8 *r__, r_8 *wsave)
+{
+    extern /* Subroutine */ int dfftf1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    int_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+    --r__;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    dfftf1_(n, &r__[1], &wsave[1], &wsave[*n + 1], (int_8 *)&wsave[(*n << 1) + 1]);/* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* dfftf_ */
+
+/*  ------ File dfftf1.f ------ */
+/* Subroutine */ int dfftf1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, 
+	int_8 *ifac)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    extern /* Subroutine */ int dadf2_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *), dadf3_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *), dadf4_(integer *, integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *), dadf5_(integer *, integer *, r_8 *, r_8 *, 
+	    r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer i__;
+    extern /* Subroutine */ int dadfg_(integer *, integer *, integer *, 
+	    integer *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *, r_8 *);
+    static integer k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+    --ch;
+    --c__;
+
+    /* Function Body */
+    nf = ifac[2];
+    na = 1;
+    l2 = *n;
+    iw = *n;
+    i__1 = nf;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	kh = nf - k1;
+	ip = ifac[kh + 3];
+	l1 = l2 / ip;
+	ido = *n / l2;
+	idl1 = ido * l1;
+	iw -= (ip - 1) * ido;
+	na = 1 - na;
+	if (ip != 4) {
+	    goto L102;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	if (na != 0) {
+	    goto L101;
+	}
+	dadf4_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L110;
+L101:
+	dadf4_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3]);
+	goto L110;
+L102:
+	if (ip != 2) {
+	    goto L104;
+	}
+	if (na != 0) {
+	    goto L103;
+	}
+	dadf2_(&ido, &l1, &c__[1], &ch[1], &wa[iw]);
+	goto L110;
+L103:
+	dadf2_(&ido, &l1, &ch[1], &c__[1], &wa[iw]);
+	goto L110;
+L104:
+	if (ip != 3) {
+	    goto L106;
+	}
+	ix2 = iw + ido;
+	if (na != 0) {
+	    goto L105;
+	}
+	dadf3_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2]);
+	goto L110;
+L105:
+	dadf3_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2]);
+	goto L110;
+L106:
+	if (ip != 5) {
+	    goto L108;
+	}
+	ix2 = iw + ido;
+	ix3 = ix2 + ido;
+	ix4 = ix3 + ido;
+	if (na != 0) {
+	    goto L107;
+	}
+	dadf5_(&ido, &l1, &c__[1], &ch[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L110;
+L107:
+	dadf5_(&ido, &l1, &ch[1], &c__[1], &wa[iw], &wa[ix2], &wa[ix3], &wa[
+		ix4]);
+	goto L110;
+L108:
+	if (ido == 1) {
+	    na = 1 - na;
+	}
+	if (na != 0) {
+	    goto L109;
+	}
+	dadfg_(&ido, &ip, &l1, &idl1, &c__[1], &c__[1], &c__[1], &ch[1], &ch[
+		1], &wa[iw]);
+	na = 1;
+	goto L110;
+L109:
+	dadfg_(&ido, &ip, &l1, &idl1, &ch[1], &ch[1], &ch[1], &c__[1], &c__[1]
+		, &wa[iw]);
+	na = 0;
+L110:
+	l2 = l1;
+/* L111: */
+    }
+    if (na == 1) {
+	return 0;
+    }
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = ch[i__];
+/* L112: */
+    }
+    return 0;
+} /* dfftf1_ */
+
+/*  ------ File dffti.f ------ */
+/* Subroutine */ int dffti_(integer *n, r_8 *wsave)
+{
+    extern /* Subroutine */ int dffti1_(integer *, r_8 *, int_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    dffti1_(n, &wsave[*n + 1], (int_8 *)&wsave[(*n << 1) + 1]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* dffti_ */
+
+/*  ------ File dffti1.f ------ */
+/* Subroutine */ int dffti1_(integer *n, r_8 *wa, int_8 *ifac)
+{
+    /* Initialized data */
+
+    static integer ntryh[4] = { 4,2,3,5 };
+
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Builtin functions */
+/*    r_8 cos(r_8truc), sin(r_8truc); remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static r_8 argh;
+    static integer ntry, i__, j;
+    static r_8 argld;
+    static integer k1, l1, l2, ib;
+    static r_8 fi;
+    static integer ld, ii, nf, ip, nl, is, nq, nr;
+    static r_8 arg;
+    static integer ido, ipm;
+    static r_8 tpi;
+    static integer nfm1;
+
+    /* Parameter adjustments */
+    --ifac;
+    --wa;
+
+    /* Function Body */
+    nl = *n;
+    nf = 0;
+    j = 0;
+L101:
+    ++j;
+    if (j - 4 <= 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L102:
+    ntry = ntryh[j - 1];
+    goto L104;
+L103:
+    ntry += 2;
+L104:
+    nq = nl / ntry;
+    nr = nl - ntry * nq;
+    if (nr != 0) {
+	goto L101;
+    } else {
+	goto L105;
+    }
+L105:
+    ++nf;
+    ifac[nf + 2] = ntry;
+    nl = nq;
+    if (ntry != 2) {
+	goto L107;
+    }
+    if (nf == 1) {
+	goto L107;
+    }
+    i__1 = nf;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	ib = nf - i__ + 2;
+	ifac[ib + 2] = ifac[ib + 1];
+/* L106: */
+    }
+    ifac[3] = 2;
+L107:
+    if (nl != 1) {
+	goto L104;
+    }
+    ifac[1] = *n;
+    ifac[2] = nf;
+    tpi = 6.28318530717959f;
+    argh = tpi / (r_8) (*n);
+    is = 0;
+    nfm1 = nf - 1;
+    l1 = 1;
+    if (nfm1 == 0) {
+	return 0;
+    }
+    i__1 = nfm1;
+    for (k1 = 1; k1 <= i__1; ++k1) {
+	ip = ifac[k1 + 2];
+	ld = 0;
+	l2 = l1 * ip;
+	ido = *n / l2;
+	ipm = ip - 1;
+	i__2 = ipm;
+	for (j = 1; j <= i__2; ++j) {
+	    ld += l1;
+	    i__ = is;
+	    argld = (r_8) ld * argh;
+	    fi = 0.f;
+	    i__3 = ido;
+	    for (ii = 3; ii <= i__3; ii += 2) {
+		i__ += 2;
+		fi += 1.f;
+		arg = fi * argld;
+		wa[i__ - 1] = cos(arg);
+		wa[i__] = sin(arg);
+/* L108: */
+	    }
+	    is += ido;
+/* L109: */
+	}
+	l1 = l2;
+/* L110: */
+    }
+    return 0;
+} /* dffti1_ */
+
+/*  ------ File dsinqb.f ------ */
+/* Subroutine */ int dsinqb_(integer *n, r_8 *x, r_8 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int dcosqb_(integer *, r_8 *, r_8 *);
+    static r_8 xhold;
+    static integer kc, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if (*n > 1) {
+	goto L101;
+    }
+    x[1] *= 4.f;
+    return 0;
+L101:
+    ns2 = *n / 2;
+    i__1 = *n;
+    for (k = 2; k <= i__1; k += 2) {
+	x[k] = -x[k];
+/* L102: */
+    }
+    dcosqb_(n, &x[1], &wsave[1]);
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = *n - k;
+	xhold = x[k];
+	x[k] = x[kc + 1];
+	x[kc + 1] = xhold;
+/* L103: */
+    }
+    return 0;
+} /* dsinqb_ */
+
+/*  ------ File dsinqf.f ------ */
+/* Subroutine */ int dsinqf_(integer *n, r_8 *x, r_8 *wsave)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int dcosqf_(integer *, r_8 *, r_8 *);
+    static r_8 xhold;
+    static integer kc, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    if (*n == 1) {
+	return 0;
+    }
+    ns2 = *n / 2;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = *n - k;
+	xhold = x[k];
+	x[k] = x[kc + 1];
+	x[kc + 1] = xhold;
+/* L101: */
+    }
+    dcosqf_(n, &x[1], &wsave[1]);
+    i__1 = *n;
+    for (k = 2; k <= i__1; k += 2) {
+	x[k] = -x[k];
+/* L102: */
+    }
+    return 0;
+} /* dsinqf_ */
+
+/*  ------ File dsinqi.f ------ */
+/* Subroutine */ int dsinqi_(integer *n, r_8 *wsave)
+{
+    extern /* Subroutine */ int dcosqi_(integer *, r_8 *);
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    dcosqi_(n, &wsave[1]);
+    return 0;
+} /* dsinqi_ */
+
+/*  ------ File dsint.f ------ */
+/* Subroutine */ int dsint_(integer *n, r_8 *x, r_8 *wsave)
+{
+    extern /* Subroutine */ int dsint1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    r_8 *, int_8 *);
+    static integer np1, iw1, iw2, iw3;
+
+    /* Parameter adjustments */
+    --wsave;
+    --x;
+
+    /* Function Body */
+    np1 = *n + 1;
+    iw1 = *n / 2 + 1;
+    iw2 = iw1 + np1;
+    iw3 = iw2 + np1;
+    dsint1_(n, &x[1], &wsave[1], &wsave[iw1], &wsave[iw2], (int_8 *) &wsave[iw3]); /* (int *) rajoute Reza 29/11/99 */
+    return 0;
+} /* dsint_ */
+
+/*  ------ File dsint1.f ------ */
+/* Subroutine */ int dsint1_(integer *n, r_8 *war, r_8 *was, r_8 *xh, r_8 *
+	x, int_8 *ifac)
+{
+    /* Initialized data */
+
+    static r_8 sqrt3 = 1.73205080756888f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer modn, i__, k;
+    static r_8 xhold, t1, t2;
+    extern /* Subroutine */ int dfftf1_(integer *, r_8 *, r_8 *, r_8 *, 
+	    int_8 *);
+    static integer kc, np1, ns2;
+
+    /* Parameter adjustments */
+    --ifac;
+    --x;
+    --xh;
+    --was;
+    --war;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	xh[i__] = war[i__];
+	war[i__] = x[i__];
+/* L100: */
+    }
+    if ((i__1 = *n - 2) < 0) {
+	goto L101;
+    } else if (i__1 == 0) {
+	goto L102;
+    } else {
+	goto L103;
+    }
+L101:
+    xh[1] += xh[1];
+    goto L106;
+L102:
+    xhold = sqrt3 * (xh[1] + xh[2]);
+    xh[2] = sqrt3 * (xh[1] - xh[2]);
+    xh[1] = xhold;
+    goto L106;
+L103:
+    np1 = *n + 1;
+    ns2 = *n / 2;
+    x[1] = 0.f;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	kc = np1 - k;
+	t1 = xh[k] - xh[kc];
+	t2 = was[k] * (xh[k] + xh[kc]);
+	x[k + 1] = t1 + t2;
+	x[kc + 1] = t2 - t1;
+/* L104: */
+    }
+    modn = *n % 2;
+    if (modn != 0) {
+	x[ns2 + 2] = xh[ns2 + 1] * 4.f;
+    }
+    dfftf1_(&np1, &x[1], &xh[1], &war[1], &ifac[1]);
+    xh[1] = x[1] * .5f;
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; i__ += 2) {
+	xh[i__ - 1] = -x[i__];
+	xh[i__] = xh[i__ - 2] + x[i__ - 1];
+/* L105: */
+    }
+    if (modn != 0) {
+	goto L106;
+    }
+    xh[*n] = -x[*n + 1];
+L106:
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	x[i__] = war[i__];
+	war[i__] = xh[i__];
+/* L107: */
+    }
+    return 0;
+} /* dsint1_ */
+
+/*  ------ File dsinti.f ------ */
+/* Subroutine */ int dsinti_(integer *n, r_8 *wsave)
+{
+    /* Initialized data */
+
+    static r_8 pi = 3.14159265358979f;
+
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+/*    r_8 sin(r_8truc);  remplace par math.h  Reza 29/11/99 */
+
+    /* Local variables */
+    static integer k;
+    extern /* Subroutine */ int dffti_(integer *, r_8 *);
+    static r_8 dt;
+    static integer np1, ns2;
+
+    /* Parameter adjustments */
+    --wsave;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    ns2 = *n / 2;
+    np1 = *n + 1;
+    dt = pi / (r_8) np1;
+    i__1 = ns2;
+    for (k = 1; k <= i__1; ++k) {
+	wsave[k] = sin(k * dt) * 2.f;
+/* L101: */
+    }
+    dffti_(&np1, &wsave[ns2 + 1]);
+    return 0;
+} /* dsinti_ */
+
Index: /tags/V_Fev00/SophyaLib/NTools/fftpackc.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftpackc.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftpackc.h	(revision 752)
@@ -0,0 +1,133 @@
+#ifndef FFTPACK_H_SEEN
+#define FFTPACK_H_SEEN
+
+#include "machdefs.h"
+/* #include "f2c.h" -- Remplace par ce qui suit */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int integer;
+typedef unsigned uinteger;
+typedef char *address;
+typedef short int shortint;
+  // typedef float real;
+  // typedef double doublereal;
+  //typedef struct { float r, i; } complex;
+  //typedef struct { double r, i; } doublecomplex;
+
+/* typedef int_4 logical;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1; */
+
+/* ---------------------- */
+
+extern int cfftb_(integer *n, r_4 *c__, r_4 *wsave);
+extern int cfftb1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, int_4 *ifac);
+extern int cfftf_(integer *n, r_4 *c__, r_4 *wsave);
+extern int cfftf1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, int_4 *ifac);
+extern int cffti_(integer *n, r_4 *wsave);
+extern int cffti1_(integer *n, r_4 *wa, int_4 *ifac);
+extern int cosqb_(integer *n, r_4 *x, r_4 *wsave);
+extern int cosqb1_(integer *n, r_4 *x, r_4 *w, r_4 *xh);
+extern int cosqf_(integer *n, r_4 *x, r_4 *wsave);
+extern int cosqf1_(integer *n, r_4 *x, r_4 *w, r_4 *xh);
+extern int cosqi_(integer *n, r_4 *wsave);
+extern int cost_(integer *n, r_4 *x, r_4 *wsave);
+extern int costi_(integer *n, r_4 *wsave);
+extern int ezfft1_(integer *n, r_4 *wa, int_4 *ifac);
+extern int ezfftb_(integer *n, r_4 *r__, r_4 *azero, r_4 *a, r_4 *b, r_4 *wsave);
+extern int ezfftf_(integer *n, r_4 *r__, r_4 *azero, r_4 *a, r_4 *b, r_4 *wsave);
+extern int ezffti_(integer *n, r_4 *wsave);
+extern int passb_(integer *nac, integer *ido, integer *ip, integer *l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa);
+extern int passb2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1);
+extern int passb3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2);
+extern int passb4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3);
+extern int passb5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4);
+extern int passf_(integer *nac, integer *ido, integer *ip, integer *l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa);
+extern int passf2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1);
+extern int passf3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2);
+extern int passf4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3);
+extern int passf5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4);
+extern int radb2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1);
+extern int radb3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2);
+extern int radb4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3);
+extern int radb5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4);
+extern int radbg_(integer *ido, integer *ip, integer *l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa);
+extern int radf2_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1);
+extern int radf3_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2);
+extern int radf4_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3);
+extern int radf5_(integer *ido, integer *l1, r_4 *cc, r_4 *ch, r_4 *wa1, r_4 *wa2, r_4 *wa3, r_4 *wa4);
+extern int radfg_(integer *ido, integer *ip, integer *l1, integer *idl1, r_4 *cc, r_4 *c1, r_4 *c2, r_4 *ch, r_4 *ch2, r_4 *wa);
+extern int rfftb_(integer *n, r_4 *r__, r_4 *wsave);
+extern int rfftb1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, int_4 *ifac);
+extern int rfftf_(integer *n, r_4 *r__, r_4 *wsave);
+extern int rfftf1_(integer *n, r_4 *c__, r_4 *ch, r_4 *wa, int_4 *ifac);
+extern int rffti_(integer *n, r_4 *wsave);
+extern int rffti1_(integer *n, r_4 *wa, int_4 *ifac);
+extern int sinqb_(integer *n, r_4 *x, r_4 *wsave);
+extern int sinqf_(integer *n, r_4 *x, r_4 *wsave);
+extern int sinqi_(integer *n, r_4 *wsave);
+extern int sint_(integer *n, r_4 *x, r_4 *wsave);
+extern int sint1_(integer *n, r_4 *war, r_4 *was, r_4 *xh, r_4 *x, int_4 *ifac);
+extern int sinti_(integer *n, r_4 *wsave);
+
+/* ---------------------- */
+
+extern int cdfftb_(integer *n, r_8 *c__, r_8 *wsave);
+extern int cdfftb1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, int_8 *ifac);
+extern int cdfftf_(integer *n, r_8 *c__, r_8 *wsave);
+extern int cdfftf1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, int_8 *ifac);
+extern int cdffti_(integer *n, r_8 *wsave);
+extern int cdffti1_(integer *n, r_8 *wa, int_8 *ifac);
+extern int dcosqb_(integer *n, r_8 *x, r_8 *wsave);
+extern int dcosqb1_(integer *n, r_8 *x, r_8 *w, r_8 *xh);
+extern int dcosqf_(integer *n, r_8 *x, r_8 *wsave);
+extern int dcosqf1_(integer *n, r_8 *x, r_8 *w, r_8 *xh);
+extern int dcosqi_(integer *n, r_8 *wsave);
+extern int dcost_(integer *n, r_8 *x, r_8 *wsave);
+extern int dcosti_(integer *n, r_8 *wsave);
+extern int dezfft1_(integer *n, r_8 *wa, int_8 *ifac);
+extern int dezfftb_(integer *n, r_8 *r__, r_8 *azero, r_8 *a, r_8 *b, r_8 *wsave);
+extern int dezfftf_(integer *n, r_8 *r__, r_8 *azero, r_8 *a, r_8 *b, r_8 *wsave);
+extern int dezffti_(integer *n, r_8 *wsave);
+extern int dpassb_(integer *nac, integer *ido, integer *ip, integer *l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa);
+extern int dpassb2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1);
+extern int dpassb3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2);
+extern int dpassb4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3);
+extern int dpassb5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4);
+extern int dpassf_(integer *nac, integer *ido, integer *ip, integer *l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa);
+extern int dpassf2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1);
+extern int dpassf3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2);
+extern int dpassf4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3);
+extern int dpassf5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4);
+extern int dadb2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1);
+extern int dadb3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2);
+extern int dadb4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3);
+extern int dadb5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4);
+extern int dadbg_(integer *ido, integer *ip, integer *l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa);
+extern int dadf2_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1);
+extern int dadf3_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2);
+extern int dadf4_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3);
+extern int dadf5_(integer *ido, integer *l1, r_8 *cc, r_8 *ch, r_8 *wa1, r_8 *wa2, r_8 *wa3, r_8 *wa4);
+extern int dadfg_(integer *ido, integer *ip, integer *l1, integer *idl1, r_8 *cc, r_8 *c1, r_8 *c2, r_8 *ch, r_8 *ch2, r_8 *wa);
+extern int dfftb_(integer *n, r_8 *r__, r_8 *wsave);
+extern int dfftb1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, int_8 *ifac);
+extern int dfftf_(integer *n, r_8 *r__, r_8 *wsave);
+extern int dfftf1_(integer *n, r_8 *c__, r_8 *ch, r_8 *wa, int_8 *ifac);
+extern int dffti_(integer *n, r_8 *wsave);
+extern int dffti1_(integer *n, r_8 *wa, int_8 *ifac);
+extern int dsinqb_(integer *n, r_8 *x, r_8 *wsave);
+extern int dsinqf_(integer *n, r_8 *x, r_8 *wsave);
+extern int dsinqi_(integer *n, r_8 *wsave);
+extern int dsint_(integer *n, r_8 *x, r_8 *wsave);
+extern int dsint1_(integer *n, r_8 *war, r_8 *was, r_8 *xh, r_8 *x, int_8 *ifac);
+extern int dsinti_(integer *n, r_8 *wsave);
+
+/* Rerunning f2c -P may change prototypes or declarations. */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*  FFTPACK_H_SEEN */
Index: /tags/V_Fev00/SophyaLib/NTools/fftpserver.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftpserver.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftpserver.cc	(revision 752)
@@ -0,0 +1,309 @@
+#include "fftpserver.h"
+#include "fftpackc.h"
+
+#include <iostream.h>
+
+
+/*! \class FFTPackServer
+ \brief An FFT server based on fftpack
+
+A class that calculates Fourier transforms forwards and backwards.
+
+The class calls the c library ``fftpack'', which is accessible and documented
+at http://www.netlib.org/fftpack/.  However, the class functions do not
+necessarily correspond with the equivalent fftpack function.  For example,
+fftpack "forward" transformations are in fact inverse fourier transformations.
+Otherwise, the output is in the fftpack format.
+
+Complex input must be entered using the <complex> template.  Otherwise,
+all input is assumed to be real.
+
+Due to the way that fftpack manages
+its work arrays, an object can run faster if the length of the input arrays
+does not change.  For example, if you need to do a series of FFT's
+of differing length, it may be more efficient to create an fftserver object
+for each length.
+*/
+
+/*! \fn virtual void FFTServer::fftf(int l, r_4* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, r_4* inout)
+  \param l length of array
+  \param inout input array /output backward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftf(int l, r_8* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+  \param inout input/output array (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, r_8* inout)
+  \param l length of array
+  \param inout input array /output backward FFT(original array destroyed)
+*/
+/*!\fn  virtual void FFTServer::fftf(int l, complex<r_4>* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, complex<r_4>* inout)
+  \param l length of array
+  \param inout input array /output backward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftf(int l, complex<r_8>* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, complex<r_8>* inout)
+  \param l length of array
+  \param inout input array /output backward FFT(original array destroyed)
+*/
+/*!\fn  virtual void FFTServer::fftf(Vector& in, Vector& out)
+  \param in input array
+  \param out forward FFT
+*/
+/*! \fn virtual void FFTServer::fftb(Vector& in, Vector& out)
+  \param in input array
+  \param out backward FFT
+*/
+
+FFTPackServer::FFTPackServer()
+   : FFTServerInterface("FFTPackServer using extended FFTPack (C-version) package")
+
+{
+  sz_rfft = 0;     //the working array and its size for the different
+  ws_rfft = NULL;  //possible numerical types
+  sz_cfft = 0;
+  ws_cfft = NULL;
+  sz_cdfft = 0;
+  ws_cdfft = NULL;
+}
+
+FFTPackServer::~FFTPackServer()
+{
+if (ws_rfft) delete[] ws_rfft;
+if (ws_cfft) delete[] ws_cfft;
+if (ws_cdfft) delete[] ws_cdfft;
+}
+
+FFTServerInterface * FFTPackServer::Clone()
+{
+  return (new FFTPackServer);
+}
+
+
+void FFTPackServer::FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out)
+{
+  out = in;
+  fftf(out.NElts(), out.Data());
+  if (getNormalize()) out *= (1./(r_8)(in.NElts()));
+}
+
+void FFTPackServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out)
+{
+  out = in;
+  fftb(out.NElts(), out.Data());
+}
+
+
+
+void FFTPackServer::FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out)
+{
+  out = in;
+  fftf(out.NElts(), out.Data());
+  if (getNormalize()) out *= (1./(r_4)(in.NElts()));
+}
+
+void FFTPackServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out)
+{
+  out = in;
+  fftb(out.NElts(), out.Data());
+}
+
+void FFTPackServer::FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out)
+{
+  TVector< r_4 > inout(in);
+  fftf(inout.NElts(), inout.Data());
+  ReShapetoCompl(inout, out);
+  if (getNormalize()) out *= (1./(r_4)(in.NElts()));
+}
+
+void FFTPackServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out)
+{
+  ReShapetoReal(in, out);
+  fftb(out.NElts(), out.Data());
+}
+
+
+void FFTPackServer::FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out)
+{
+  TVector< r_8 > inout(in);
+  fftf(inout.NElts(), inout.Data());
+  ReShapetoCompl(inout, out);
+  if (getNormalize()) out *= (1./(r_8)(in.NElts()));
+}
+
+void FFTPackServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out)
+{
+  ReShapetoReal(in, out);
+  fftb(out.NElts(), out.Data());
+}
+
+ 
+
+void FFTPackServer::checkint_rfft(int l)
+{
+  if (sz_rfft == l) return;       //checkint functions check and reallocate
+                                  //memory for the work arrays when performing
+  if (ws_rfft) delete[] ws_rfft;  //a transform
+  sz_rfft = l;
+  ws_rfft = new r_4[2*l+15];
+  rffti_(&l, ws_rfft);
+}
+
+void FFTPackServer::checkint_cfft(int l)
+{
+  if (sz_cfft == l) return;
+
+  if (ws_cfft) delete[] ws_cfft;
+  sz_cfft = l;
+  ws_cfft = new r_4[4*l+15];
+  cffti_(&l, ws_cfft);
+}
+
+void FFTPackServer::checkint_dfft(int l)
+{
+  if (sz_dfft == l) return;
+
+  if (ws_dfft) delete[] ws_dfft;
+  sz_dfft = l;
+  ws_dfft = new r_8[2*l+15];
+  dffti_(&l, ws_dfft);
+}
+
+void FFTPackServer::checkint_cdfft(int l)
+{
+  if (sz_cdfft == l) return;
+
+  if (ws_cdfft) delete[] ws_cdfft;
+  sz_cdfft = l;
+  ws_cdfft = new r_8[4*l+15];
+  cdffti_(&l, ws_cdfft);
+}
+
+/* In general forward transformations are resorted since fftpack functions
+   return inverse transformations */
+
+void FFTPackServer::fftf(int l, r_4* inout)
+{
+  checkint_rfft(l);
+  rfftf_(&l, inout, ws_rfft);
+  //  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
+}
+
+void FFTPackServer::fftf(int l, r_8* inout)
+{
+  checkint_dfft(l);
+  dfftf_(&l, inout, ws_dfft);
+  //  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
+}
+
+void FFTPackServer::fftf(int l, complex<r_4>* inout)
+{
+  checkint_cfft(l);
+  cfftf_(&l, (r_4 *)(inout), ws_cfft);
+}
+
+void FFTPackServer::fftf(int l, complex<r_8>* inout)
+{
+  checkint_cdfft(l);
+  cdfftf_(&l, (r_8*)(inout), ws_cdfft);
+}
+
+void FFTPackServer::fftb(int l, r_4* inout)
+{
+  checkint_rfft(l);
+  rfftb_(&l, inout, ws_rfft);
+}
+
+void FFTPackServer::fftb(int l, r_8* inout)
+{
+  checkint_dfft(l);
+  dfftb_(&l, inout, ws_dfft);
+}
+
+void FFTPackServer::fftb(int l, complex<r_4>* inout)
+{
+  checkint_cfft(l);
+  cfftb_(&l, (r_4 *)(inout), ws_cfft);
+}
+
+void FFTPackServer::fftb(int l, complex<r_8>* inout)
+{
+  checkint_cdfft(l);
+  cdfftb_(&l, (r_8 *)(inout), ws_cdfft);
+}
+
+// Methodes pour reordonner les donnees 
+
+/* --Methode-- */
+void FFTPackServer::ReShapetoReal( TVector< complex<r_8> > const & in, TVector< r_8 >  & out)
+{
+  int n = in.NElts();
+  int ncs = (fabs(in(n-1).imag()) > 1.e-12) ? ncs = 2*n-1 : ncs = n*2-2; 
+  out.ReSize(ncs);
+  int k;
+  out(0) = in(0).real();
+  for(k=1;k<n-1;k++) {
+    out(2*k-1) = in(k).real();
+    out(2*k) = in(k).imag();
+  }
+  if (ncs == n*2-2)  out(ncs-1) = in(n-1).real();
+  else { out(ncs-2) = in(n-1).real();  out(ncs-1) = in(n-1).imag(); }
+}
+
+/* --Methode-- */
+void FFTPackServer::ReShapetoReal( TVector< complex<r_4> > const & in, TVector< r_4 >  & out)
+{
+  int n = in.NElts();
+  int ncs = (fabs(in(n-1).imag()) > 1.e-12) ? ncs = 2*n-1 : ncs = n*2-2; 
+  out.ReSize(ncs);
+  int k;
+  out(0) = in(0).real();
+  for(k=1;k<n-1;k++) {
+    out(2*k-1) = in(k).real();
+    out(2*k) = in(k).imag();
+  }
+  if (ncs == n*2-2)  out(ncs-1) = in(n-1).real();
+  else { out(ncs-2) = in(n-1).real();  out(ncs-1) = in(n-1).imag(); }
+}
+
+
+/* --Methode-- */
+void FFTPackServer::ReShapetoCompl(TVector< r_8 > const & in, TVector< complex<r_8> > & out)
+{
+  uint_4 n =  in.NElts();
+  uint_4 ncs = n/2+1;
+  uint_4 nc = (n%2 != 0) ? n/2+1 : n/2;
+  out.ReSize(ncs);
+  out(0) = complex<r_8> (in(0),0.);
+  int k;
+  for(int k=1;k<nc;k++) 
+    out(k) =  complex<r_4> (in(2*k-1), in(2*k));
+  if (n%2 == 0) out(ncs-1) = complex<r_8>(in(n-1), 0.);
+
+}
+
+/* --Methode-- */
+void FFTPackServer::ReShapetoCompl(TVector< r_4 > const & in, TVector< complex<r_4> > & out)
+{
+  uint_4 n =  in.NElts();
+  uint_4 ncs = n/2+1;
+  uint_4 nc = (n%2 != 0) ? n/2+1 : n/2;
+  out.ReSize(ncs);
+  out(0) = complex<r_4> (in(0),0.);
+  int k;
+  for(int k=1;k<nc;k++) 
+    out(k) =  complex<r_4> (in(2*k-1), in(2*k));
+  if (n%2 == 0) out(ncs-1) = complex<r_4>(in(n-1), 0.);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/fftpserver.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftpserver.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftpserver.h	(revision 752)
@@ -0,0 +1,72 @@
+#ifndef  FFTPServer_H_SEEN
+#define  FFTPServer_H_SEEN
+
+#include "fftservintf.h"
+
+// implementation de FFTServerInterface en utilisant FFTPack 
+
+namespace SOPHYA {
+
+class FFTPackServer : public FFTServerInterface {
+ public:
+  FFTPackServer();
+  virtual ~FFTPackServer();
+
+  // Implementation de l'interface FFTServerInterface
+
+  virtual FFTServerInterface * Clone();
+
+  // Transforme unidimensionnel sur des double
+  virtual void FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out);
+
+  // Transforme unidimensionnel sur des float
+  virtual void FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out);
+
+  //  Methodes propres a cette classe
+  virtual void fftf(int l, float* inout);
+  virtual void fftb(int l, float* inout);
+  virtual void fftf(int l, double* inout);
+  virtual void fftb(int l, double* inout);
+  virtual void fftf(int l, complex<float>* inout);
+  virtual void fftb(int l, complex<float>* inout);
+  virtual void fftf(int l, complex<double>* inout);
+  virtual void fftb(int l, complex<double>* inout);
+
+// Methodes statiques pour reordonner les donnees 
+  virtual  void ReShapetoReal( TVector< complex<r_8> > const & in, TVector< r_8 >  & out);
+  virtual  void ReShapetoReal( TVector< complex<r_4> > const & in, TVector< r_4 >  & out);
+
+  virtual void ReShapetoCompl(TVector< r_8 > const & in, TVector< complex<r_8> > & out);
+  virtual void ReShapetoCompl(TVector< r_4 > const & in, TVector< complex<r_4> > & out);
+
+ protected:
+  virtual void checkint_rfft(int l);
+  virtual void checkint_dfft(int l);
+  virtual void checkint_cfft(int l);
+  virtual void checkint_cdfft(int l);
+
+  int sz_rfft;
+  float* ws_rfft;
+
+  int sz_cfft;
+  float* ws_cfft;
+
+  int sz_dfft;
+  double* ws_dfft;
+
+  int sz_cdfft;
+  double* ws_cdfft;
+};
+
+} // Fin du namespace
+
+
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fftserver.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftserver.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftserver.cc	(revision 752)
@@ -0,0 +1,204 @@
+#include "fftserver.h"
+#include <iostream.h>
+
+extern "C" {
+  int rffti_(int *n, float *wsave);             //fftpack functions
+  int rfftf_(int *n, float *r__, float *wsave);
+  int rfftb_(int *n, float *r__, float *wsave);
+  int dffti_(int *n, double *wsave);
+  int dfftf_(int *n, double *r__, double *wsave);
+  int dfftb_(int *n, double *r__, double *wsave);
+  int cffti_(int *n, float *wsave);
+  int cfftf_(int *n, float *c__, float *wsave);
+  int cfftb_(int *n, float *c__, float *wsave);
+  int cdffti_(int *n, double *wsave);
+  int cdfftf_(int *n, double *c__, double *wsave);
+  int cdfftb_(int *n, double *c__, double *wsave);
+           }
+
+FFTServer::FFTServer()
+{
+  sz_rfft = 0;     //the working array and its size for the different
+  ws_rfft = NULL;  //possible numerical types
+  sz_cfft = 0;
+  ws_cfft = NULL;
+  sz_cdfft = 0;
+  ws_cdfft = NULL;
+}
+
+FFTServer::~FFTServer()
+{
+if (ws_rfft) delete[] ws_rfft;
+if (ws_cfft) delete[] ws_cfft;
+if (ws_cdfft) delete[] ws_cdfft;
+}
+
+void FFTServer::checkint_rfft(int l)
+{
+  if (sz_rfft == l) return;       //checkint functions check and reallocate
+                                  //memory for the work arrays when performing
+  if (ws_rfft) delete[] ws_rfft;  //a transform
+  sz_rfft = l;
+  ws_rfft = new float[2*l+15];
+  rffti_(&l, ws_rfft);
+}
+
+void FFTServer::checkint_cfft(int l)
+{
+  if (sz_cfft == l) return;
+
+  if (ws_cfft) delete[] ws_cfft;
+  sz_cfft = l;
+  ws_cfft = new float[4*l+15];
+  cffti_(&l, ws_cfft);
+}
+
+void FFTServer::checkint_dfft(int l)
+{
+  if (sz_dfft == l) return;
+
+  if (ws_dfft) delete[] ws_dfft;
+  sz_dfft = l;
+  ws_dfft = new double[2*l+15];
+  dffti_(&l, ws_dfft);
+}
+
+void FFTServer::checkint_cdfft(int l)
+{
+  if (sz_cdfft == l) return;
+
+  if (ws_cdfft) delete[] ws_cdfft;
+  sz_cdfft = l;
+  ws_cdfft = new double[4*l+15];
+  cdffti_(&l, ws_cdfft);
+}
+
+/* In general forward transformations are resorted since fftpack functions
+   return inverse transformations */
+
+void FFTServer::fftf(int l, float* inout)
+{
+  checkint_rfft(l);
+  rfftf_(&l, inout, ws_rfft);
+  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
+}
+
+void FFTServer::fftf(int l, double* inout)
+{
+  checkint_dfft(l);
+  dfftf_(&l, inout, ws_dfft);
+  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
+}
+
+void FFTServer::fftf(int l, complex<float>* inout)
+{
+  checkint_cfft(l);
+  float* foo = new float[2*l];
+  int i;
+  for (i=0;i<l;i++){
+    foo[2*i]=inout[i].real();
+    foo[2*i+1]=inout[i].imag();
+  }
+  cfftf_(&l, foo, ws_cfft);
+  inout[0]=complex<float> (foo[0],foo[1]);
+  for (i=1;i<l;i++) inout[l-i]= complex<float> (foo[2*i], foo[2*i+1]);
+  delete[] foo;
+}
+
+void FFTServer::fftf(int l, complex<double>* inout)
+{
+  checkint_cdfft(l);
+  double* foo=new double[2*l];
+  int i;
+  for (i=0;i<l;i++){
+    foo[2*i]=inout[i].real();
+    foo[2*i+1]=inout[i].imag();
+  }
+  cdfftf_(&l, foo, ws_cdfft);
+  inout[0]=complex<double> (foo[0],foo[1]);
+  for (i=1;i<l;i++) {
+    inout[l-i]= complex<double> (foo[2*i],foo[2*i+1]);
+  }
+  delete[] foo;
+}
+
+void FFTServer::fftb(int l, float* inout)
+{
+  checkint_rfft(l);
+  rfftf_(&l, inout, ws_rfft);
+}
+
+void FFTServer::fftb(int l, double* inout)
+{
+  checkint_dfft(l);
+  dfftf_(&l, inout, ws_dfft);
+}
+
+void FFTServer::fftb(int l, complex<float>* inout)
+{
+  checkint_cfft(l);
+  float* foo = new float[2*l];
+  int i;
+  for (i=0;i<l;i++){
+    foo[2*i]=inout[i].real();
+    foo[2*i+1]=inout[i].imag();
+  }
+  cfftf_(&l, foo, ws_cfft);
+  for (i=0;i<l;i++) inout[i]=complex<float> (foo[2*i],foo[2*i+1]);
+  delete[] foo;
+}
+
+void FFTServer::fftb(int l, complex<double>* inout)
+{
+  checkint_cdfft(l);
+  double* foo = new double[2*l];
+  int i;
+  for (i=0;i<l;i++){
+    foo[2*i]=inout[i].real();
+    foo[2*i+1]=inout[i].imag();
+  }
+  cdfftf_(&l, foo, ws_cdfft);
+  for (i=0;i<l;i++) inout[i]=complex<double> (foo[2*i],foo[2*i+1]);
+  delete[] foo;
+}
+
+void FFTServer::fftf(Vector& in, Vector& out)
+{
+  int l = in.NElts();
+/* ----- Si c'etait un Vector<float> on aurait ecrit comme ca 
+   Pour le moment Vector est double, on passe donc par un tableau 
+   intermediare
+// La transformee sur le tableau de flaot se fait en place,
+// on utilise donc out comme in-out
+  out = in;
+  fftf_float(l, out.Data() );
+  ------------------------------------------------------------- */
+  float * inout = new float[l];
+  int i;
+  for(i=0; i<l; i++) inout[i] = in(i);
+  fftf(l, inout);
+  out.Realloc(l);
+  for(i=0; i<l; i++) out(i) = inout[i];
+  delete[] inout;
+}
+
+void FFTServer::fftb(Vector& in, Vector& out)
+{
+  int l = in.NElts();
+/* ----- Si c'etait un Vector<float> on aurait ecrit comme ca 
+   Pour le moment Vector est double, on passe donc par un tableau 
+   intermediare
+// La transformee sur le tableau de flaot se fait en place,
+// on utilise donc out comme in-out
+  out = in;
+  fftf_float(l, out.Data() );
+  ------------------------------------------------------------- */
+  float * inout = new float[l];
+  int i;
+  for(i=0; i<l; i++) inout[i] = in(i);
+  fftb(l, inout);
+  out.Realloc(l);
+  for(i=0; i<l; i++) out(i) = inout[i];
+  delete[] inout;
+}
+
Index: /tags/V_Fev00/SophyaLib/NTools/fftserver.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftserver.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftserver.h	(revision 752)
@@ -0,0 +1,103 @@
+#ifndef  FFTServ_H_SEEN
+#define  FFTServ_H_SEEN
+
+#include <complex>
+#include "tvector.h"
+
+class FFTServer{
+ public:
+  FFTServer();
+  virtual ~FFTServer();
+  virtual void fftf(int l, float* inout);
+  virtual void fftb(int l, float* inout);
+  virtual void fftf(int l, double* inout);
+  virtual void fftb(int l, double* inout);
+  virtual void fftf(int l, complex<float>* inout);
+  virtual void fftb(int l, complex<float>* inout);
+  virtual void fftf(int l, complex<double>* inout);
+  virtual void fftb(int l, complex<double>* inout);
+  virtual void fftf(Vector& in, Vector& out);
+  virtual void fftb(Vector& in, Vector& out);
+
+ protected:
+  virtual void checkint_rfft(int l);
+  virtual void checkint_dfft(int l);
+  virtual void checkint_cfft(int l);
+  virtual void checkint_cdfft(int l);
+
+  int sz_rfft;
+  float* ws_rfft;
+
+  int sz_cfft;
+  float* ws_cfft;
+
+  int sz_dfft;
+  double* ws_dfft;
+
+  int sz_cdfft;
+  double* ws_cdfft;
+};
+#endif
+
+/*! \class FFTServer
+ \brief An FFT server
+
+A class that calculates Fourier transforms forwards and backwards.
+
+The class calls the c library ``fftpack'', which is accessible and documented
+at http://www.netlib.org/fftpack/.  However, the class functions do not
+necessarily correspond with the equivalent fftpack function.  For example,
+fftpack "forward" transformations are in fact inverse fourier transformations.
+Otherwise, the output is in the fftpack format.
+
+Complex input must be entered using the <complex> template.  Otherwise,
+all input is assumed to be real.
+
+Due to the way that fftpack manages
+its work arrays, an object can run faster if the length of the input arrays
+does not change.  For example, if you need to do a series of FFT's
+of differing length, it may be more efficient to create an fftserver object
+for each length.
+*/
+
+/*! \fn virtual void FFTServer::fftf(int l, float* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, float* inout)
+  \param l length of array
+  \param inout input array /output backward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftf(int l, double* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+  \param inout input/output array (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, double* inout)
+  \param l length of array
+  \param inout input array /output backward FFT(original array destroyed)
+*/
+/*!\fn  virtual void FFTServer::fftf(int l, complex<float>* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, complex<float>* inout)
+  \param l length of array
+  \param inout input array /output backward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftf(int l, complex<double>* inout)
+  \param l length of array
+  \param inout input array /output forward FFT (original array destroyed)
+*/
+/*! \fn virtual void FFTServer::fftb(int l, complex<double>* inout)
+  \param l length of array
+  \param inout input array /output backward FFT(original array destroyed)
+*/
+/*!\fn  virtual void FFTServer::fftf(Vector& in, Vector& out)
+  \param in input array
+  \param out forward FFT
+*/
+/*! \fn virtual void FFTServer::fftb(Vector& in, Vector& out)
+  \param in input array
+  \param out backward FFT
+*/
Index: /tags/V_Fev00/SophyaLib/NTools/fftservintf.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftservintf.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftservintf.cc	(revision 752)
@@ -0,0 +1,116 @@
+#include "fftservintf.h"
+
+
+
+/* --Methode-- */
+FFTServerInterface::FFTServerInterface(string info)
+{
+  _info = info;
+  _fgnorm = true;
+}
+
+/* --Methode-- */
+FFTServerInterface::~FFTServerInterface()
+{
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TVector< complex<r_8> > const &, TVector< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TVector...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TVector< complex<r_8> > const &, TVector< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TVector...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TVector< r_8 > const &, TVector< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TVector...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TVector< complex<r_8> > const &, TVector< r_8 > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TVector...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TMatrix< complex<r_8> > const &, TMatrix< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TMatrix...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TMatrix< complex<r_8> > const &, TMatrix< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TMatrix...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TMatrix< r_8 > const &, TMatrix< complex<r_8> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TMatrix...) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TMatrix< complex<r_8> > const &, TMatrix< r_8 > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TMatrix...) Unsupported operation !");
+}
+
+
+// ----------------- Transforme pour les float -------------------
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TVector< complex<r_4> > const &, TVector< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TVector r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TVector< complex<r_4> > const &, TVector< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TVector r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TVector< r_4 > const &, TVector< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TVector r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TVector< complex<r_4> > const &, TVector< r_4 > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TVector r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TMatrix< complex<r_4> > const &, TMatrix< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TMatrix r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TMatrix< complex<r_4> > const &, TMatrix< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TMatrix r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTForward(TMatrix< r_4 > const &, TMatrix< complex<r_4> > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTForward(TMatrix r_4 ... ) Unsupported operation !");
+}
+
+/* --Methode-- */
+void FFTServerInterface::FFTBackward(TMatrix< complex<r_4> > const &, TMatrix< r_4 > &)
+{
+  throw NotAvailableOperation("FFTServer::FFTBackward(TMatrix r_4 ... ) Unsupported operation !");
+}
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/fftservintf.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fftservintf.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fftservintf.h	(revision 752)
@@ -0,0 +1,64 @@
+#ifndef  FFTServerIntf_H_SEEN
+#define  FFTServerIntf_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include <complex>
+#include "tmatrix.h"
+#include "tvector.h"
+
+// Classe definissant l'interface pour les transformees de Fourier 
+// L'implementation par defaut est vide et lance une exception 
+
+namespace SOPHYA {
+
+class FFTServerInterface {
+ public:
+
+// Methodes de la classe 
+  FFTServerInterface(string info);
+  virtual ~FFTServerInterface();
+
+  
+  virtual FFTServerInterface * Clone() = 0;
+
+  inline void setNormalize(bool fg=false) { _fgnorm = fg; }
+  inline bool getNormalize() const { return(_fgnorm); } 
+  inline string getInfo() const { return _info; }
+
+  // Transforme unidimensionnel sur des doubles
+  virtual void FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out);
+  virtual void FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out);
+
+  // Transforme unidimensionnel sur des float
+  virtual void FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out);
+  virtual void FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out);
+
+
+  //---------------------------------------------------
+  // Transforme 2D sur des doubles
+  virtual void FFTForward(TMatrix< complex<r_8> > const & in, TMatrix< complex<r_8> > & out);
+  virtual void FFTBackward(TMatrix< complex<r_8> > const & in, TMatrix< complex<r_8> > & out);
+  virtual void FFTForward(TMatrix< r_8 > const & in, TMatrix< complex<r_8> > & out);
+  virtual void FFTBackward(TMatrix< complex<r_8> > const & in, TMatrix< r_8 > & out);
+
+  // Transforme 2D sur des float
+  virtual void FFTForward(TMatrix< complex<r_4> > const & in, TMatrix< complex<r_4> > & out);
+  virtual void FFTBackward(TMatrix< complex<r_4> > const & in, TMatrix< complex<r_4> > & out);
+  virtual void FFTForward(TMatrix< r_4 > const & in, TMatrix< complex<r_4> > & out);
+  virtual void FFTBackward(TMatrix< complex<r_4> > const & in, TMatrix< r_4 > & out);
+
+
+
+ protected:
+  bool _fgnorm;
+  string _info;
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/fmath.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/fmath.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/fmath.h	(revision 752)
@@ -0,0 +1,39 @@
+/*    Declaration de fonctions math pour float   */
+
+#ifndef  FMATH_H_SEEN
+#define  FMATH_H_SEEN
+
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(OSF1)
+#define   fexp(x)       expf(x)
+#define   fsqrt(x)      sqrtf(x)
+#define   flog10(x)     log10f(x)
+#define   flog(x)       logf(x)
+#elif !defined(IRIX64)
+#define   fexp(x)     ((float)(exp((double)(x))))
+#define   expf(x)     ((float)(exp((double)(x))))
+#define   fabsf(x)    ((float)(fabs((double)(x))))
+#define   fsqrt(x)    ((float)(sqrt((double)(x))))
+#define   sqrtf(x)    ((float)(sqrt((double)(x))))
+#define   flog10(x)   ((float)(log10((double)(x))))
+#define   log10f(x)   ((float)(log10((double)(x))))
+#define   flog(x)     ((float)(log((double)(x))))
+#define   logf(x)     ((float)(log((double)(x))))
+#define   floorf(x)   ((float) floor((double)(x)))
+#define   ceilf(x)    ((float) ceil((double)(x)))
+#define   powf(x,y)    ((float) pow((double)(x), (double)(y)))
+#define   nintf (int)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/generaldata.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/generaldata.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/generaldata.cc	(revision 752)
@@ -0,0 +1,1191 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <values.h>
+#include <math.h>
+#include <string.h>
+#include <string>
+
+#include "strutil.h"
+#include "nbtri.h"
+#include "generalfit.h"
+#include "generaldata.h"
+#include "pexceptions.h"
+#include "objfio.h"
+
+//================================================================
+// GeneralFitData
+//================================================================
+
+//++
+// Class	GeneralFitData
+// Lib		Outils++ 
+// include	generaldata.h
+//
+//	Classe de stoquage de donnees a plusieurs variables avec erreur
+//	sur l'ordonnee et sur les abscisses (options).
+//|   {x0(i),Ex0(i), x1(i),Ex1(i), x2(i),Ex2(i) ... ; Y(i),EY(i)}
+//--
+
+// Pour memoire, structure du rangement (n=mNVar):
+// - Valeur des abscisses mXP (idem pour mErrXP):
+//   x0,x1,x2,...,xn   x0,x1,x2,...,xn  ....  x0,x1,x2,....,xn
+//   |  1er point  |   |  2sd point  |  ....  | point mNData |
+//   Donc abscisse J=[0,mNVar[ du point numero I=[0,mNData[: mXP[I*mNVar+J]
+// - Valeur de l'ordonnee mF (idem pour mErr et mOK):
+//          f                f                      f
+//   |  1er point  |  |  2sd point  |  .... | point mNData |
+//   Donc point numero I [0,mNData[ : mF[i]
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFitData::GeneralFitData(unsigned int nVar, unsigned int ndatalloc, uint_2 errx)
+//
+//	Constructeur. ``nVar'' represente la dimension de l'espace des abscisses,
+//	``ndatalloc'' le nombre maximum de points et ``errx'' si non nul
+//	indique que l'on fournit des erreurs sur les ``nVar'' variables en abscisse.
+//--
+  : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
+  , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
+  , BuffVar(NULL), BuffVarR4(NULL)
+{
+try {
+  Alloc(nVar,ndatalloc,errx);
+} catch(PException e) {
+  cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl;
+  throw;
+}
+}
+
+//++
+GeneralFitData::GeneralFitData(const GeneralFitData& data, bool clean)
+//
+//	Constructeur par copie. Si ``clean'' est ``true''
+//	seules les donnees valides de ``data'' sont copiees.
+//	Si ``clean'' est ``false'' (defaut) toutes les donnees
+//	sont copiees et la taille totale de ``data'' est allouee
+//	meme si elle est plus grande que la taille des donnees stoquees.
+//--
+  : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
+  , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
+  , BuffVar(NULL), BuffVarR4(NULL)
+{
+try {
+  Alloc(data.mNVar,((clean)?data.mNDataGood:data.mNDataAlloc),((data.mErrXP)?1:0));
+} catch(PException e) {
+  cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl;
+  throw;
+}
+
+ // Remplissage
+ if(data.mNData>0) {
+   r_8* ret;
+   for(int i=0;i<data.mNData;i++) {
+     if( clean && data.mOK[i]==0 ) continue;
+       ret = data.GetVec(i,NULL);
+       memcpy(mXP+mNData*mNVar,ret,mNVar*sizeof(r_8));
+       if(mErrXP) memcpy(mErrXP+mNData*mNVar,ret+mNVar,mNVar*sizeof(r_8));
+       mF[mNData]   = ret[2*mNVar];
+       mErr[mNData] = ret[2*mNVar+1];
+       mOK[mNData]  = (uint_2) (ret[2*mNVar+2]+0.001);
+       if(mOK[mNData]!=0) mNDataGood++;
+       mNData++;
+   }
+ }
+
+ END_CONSTRUCTOR
+}
+
+//++
+GeneralFitData::GeneralFitData()
+//
+//	Constructeur par defaut.
+//--
+  : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
+  , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
+  , BuffVar(NULL), BuffVarR4(NULL)
+{
+ END_CONSTRUCTOR
+}
+
+//++
+GeneralFitData::~GeneralFitData()
+//
+//	Destructeur
+//--
+{
+ Delete();
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::Alloc(unsigned int nVar, unsigned int ndatalloc, int_2 errx)
+//
+//	Pour redefinir la structure de donnees (ou la creer si on a utilise
+//	le createur par defaut). Voir les explications des arguments
+//	dans les commentaires du constructeur. Si ``errx''<0 alors
+//	la valeur prise est celle definie auparavent.
+//--
+{
+ASSERT( nVar>0 && ndatalloc>0 );
+
+Delete();
+
+if(errx>=0) mOk_EXP = (uint_2) errx;
+mNVar = nVar;
+mNDataAlloc = ndatalloc;
+
+try {
+  mXP  = new r_8[nVar*ndatalloc];
+  if(mOk_EXP) mErrXP  = new r_8[nVar*ndatalloc];
+  mF   = new r_8[ndatalloc];
+  mErr = new r_8[ndatalloc];
+  mOK  = new uint_2[ndatalloc];
+  BuffVar   = new r_8[2*nVar+3];
+  BuffVarR4 = (r_4 *) BuffVar;
+} catch(PException e) {
+  throw(AllocationError("GeneralFitData::Alloc allocation error\n"));
+}
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFitData::Delete()
+{
+mNVar = mNDataAlloc = mNData = mNDataGood = 0;
+if( mXP  != NULL ) {delete [] mXP;  mXP  = NULL;}
+if( mErrXP  != NULL ) {delete [] mErrXP;  mErrXP  = NULL;}
+if( mF   != NULL ) {delete [] mF;   mF   = NULL;}
+if( mErr != NULL ) {delete [] mErr; mErr = NULL;}
+if( mOK  != NULL ) {delete [] mOK;  mOK  = NULL;}
+if( BuffVar  != NULL ) {delete [] BuffVar; BuffVar = NULL; BuffVarR4 = NULL;}
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::SetDataPtr(int ptr)
+//
+//	Remise a zero de la structure pour nouveau remplissage (pas d'arg)
+//	ou remise a la position ``ptr'' (si arg). Les donnees apres ``ptr''
+//	sont sur-ecrites.
+//--
+{
+ ASSERT(ptr >= 0 && ptr < mNDataAlloc);
+ mNData = ptr;
+ mNDataGood = 0;
+ if(ptr==0) return;
+ for(int i=0;i<mNData;i++) if(mOK[i]) mNDataGood++;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::KillData(int i)
+//
+//	Pour tuer un point
+//--
+{
+ ASSERT(i >= 0 && i < mNData);
+
+ if( ! mOK[i] ) return;
+ mOK[i] = 0;
+ mNDataGood--;
+}
+
+//++
+void GeneralFitData::KillData(int i1,int i2)
+//
+//	Pour tuer une serie de points
+//--
+{
+ ASSERT(i1 >= 0 && i1 < mNData);
+ ASSERT(i2 >= 0 && i2 < mNData);
+ ASSERT(i1 <= i2 );
+
+ for(int i=i1;i<=i2;i++) KillData(i);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::ValidData(int i)
+//
+//	Pour re-valider le point numero i ([0,NData]).
+//--
+{
+ ASSERT(i >= 0 && i < mNData);
+
+ if( mOK[i] ) return;
+ if( mErr[i]<=0. ) return;
+ if(mOk_EXP) {
+   for(int j=0;j<mNVar;j++) if(mErrXP[i*mNVar+j]<=0.) return;
+ }
+ mOK[i] = 1;
+ mNDataGood++;
+}
+
+//++
+void GeneralFitData::ValidData(int i1,int i2)
+//
+//	Pour re-valider les points numeros i1 a i2.
+//--
+{
+ ASSERT(i1 >= 0 && i1 < mNData);
+ ASSERT(i2 >= 0 && i2 < mNData);
+ ASSERT(i1 <= i2 );
+
+ for(int i=i1;i<=i2;i++) ValidData(i);
+}
+
+//++
+void GeneralFitData::ValidData()
+//
+//	Pour re-valider tous les points.
+//--
+{
+ for(int i=0;i<mNData;i++) ValidData(i);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::RedefineData1(int i,double x,double f,double err,double errx)
+//
+//	Pour redefinir un point a
+//|     {x,[errx] ; f,err}
+//--
+{
+ RedefineData(i,&x,f,err,&errx);
+}
+
+//++
+void GeneralFitData::RedefineData2(int i,double x,double y,double f
+                                  ,double err,double errx,double erry)
+//
+//	Pour redefinir un point a
+//|     {x,[errx], y,[erry] ; f,err}
+//--
+{
+ double xp[2] = {x,y};
+ double errxp[2] = {errx,erry};
+ RedefineData(i,xp,f,err,errxp);
+}
+
+//++
+void GeneralFitData::RedefineData(int i,double* xp,double f,double err,double* errxp)
+//
+//	Pour redefinir un point a
+//| {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err}
+//--
+{
+ ASSERT(i>=0 && i<mNData);
+ bool ok = true;
+
+ int ip = mNVar*i;
+ for(int j=0;j<mNVar;j++) mXP[ip+j] = xp[j];
+ if(mOk_EXP) {
+   if(errxp) {
+     for(int j=0;j<mNVar;j++)
+       {mErrXP[ip+j] = errxp[j]; if(errxp[j]<=0.) ok=false;}
+   } else {
+     for(int j=0;j<mNVar;j++) mErrXP[ip+j] = Def_ErrX;
+     ok=false;
+   }
+ }
+ mF[i] = f;
+ mErr[i] = err;  if(err<=0.) ok = false;
+ if(ok) {
+   if(! mOK[i]) {mOK[i]=1; mNDataGood++;}
+ } else {
+   if(  mOK[i]) {mOK[i]=0; mNDataGood--;}
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::AddData1(double x, double f, double err, double errx)
+//
+//	Pour ajouter un point
+//|     {x,[errx] ; f,err}
+//--
+{
+ AddData(&x,f,err,&errx);
+}
+
+//++
+void GeneralFitData::AddData2(double x, double y, double f
+                             , double err, double errx, double erry)
+//
+//	Pour ajouter un point
+//|     {x,[errx], y,[erry] ; f,err}
+//--
+{
+ double xp[2] = {x,y};
+ double errxp[2] = {errx,erry};
+ AddData(xp,f,err,errxp);
+}
+
+//++
+void GeneralFitData::AddData(double* xp, double f, double err,double* errxp)
+//
+//	Pour ajouter un point
+//| {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err}
+//--
+{
+ ASSERT(mNData < mNDataAlloc);
+ bool ok = true;
+
+ int ip = mNVar*mNData;
+ for(int i=0;i<mNVar;i++) mXP[ip+i] = xp[i];
+ if(mOk_EXP) {
+   if(errxp) {
+     for(int j=0;j<mNVar;j++)
+       {mErrXP[ip+j] = errxp[j]; if(errxp[j]<=0.) ok=false;}
+   } else {
+     for(int j=0;j<mNVar;j++) mErrXP[ip+j] = Def_ErrX;
+     ok=false;
+   }
+ }
+ mF[mNData] = f;
+ mErr[mNData] = err;
+ if(err<=0.) ok = false;
+ if(ok) { mOK[mNData]=1; mNDataGood++; } else mOK[mNData]=0;
+ mNData++;
+}
+
+//++
+void GeneralFitData::AddData(float* xp, float f, float err, float* errxp)
+//
+//	Pour ajouter un point
+//| {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err}
+//--
+{
+ {for(int i=0;i<mNVar;i++) BuffVar[i] = (double) xp[i];}
+ if(errxp) for(int i=0;i<mNVar;i++) BuffVar[mNVar+i] = (double) errxp[i];
+ AddData(BuffVar,(double) f,(double)  err,BuffVar+mNVar);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::SetData1(int nData
+            , double* x, double* f, double *err, double *errx)
+//
+//	Pour remplir la structure de donnees d'un seul coup avec
+//|     {x(i),[errx(i)] ; f(i),err(i)}
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+
+ for(int i=0;i<nData;i++) {
+   double ex = (errx) ? errx[i]: Def_ErrX;
+   double ef = (err ) ? err[i]:  Def_ErrF;
+   AddData1(x[i],f[i],ef,ex);
+ }
+}
+
+//++
+void GeneralFitData::SetData1(int nData
+            , float* x, float* f, float* err, float *errx)
+//
+//	Pour remplir la structure de donnees d'un seul coup avec
+//|     {x(i),[errx(i)] ; f(i),err(i)}
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+
+ for(int i=0;i<nData;i++) {
+   double ex = (errx) ? (double) errx[i]: Def_ErrX;
+   double ef = (err ) ? (double) err[i]:  Def_ErrF;
+   AddData1((double) x[i],(double) f[i],ef,ex);
+ }
+}
+
+//++
+void GeneralFitData::SetData2(int nData, double* x, double* y, double* f
+                             ,double *err,double *errx,double *erry)
+//
+//	Pour remplir la structure de donnees d'un seul coup avec
+//|     {x(i),[errx(i)], y(i),[erry(i)], ; f(i),err(i)}
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+
+ for(int i=0;i<nData;i++) {
+   double ex = (errx) ? (double) errx[i]: Def_ErrX;
+   double ey = (erry) ? (double) erry[i]: Def_ErrX;
+   double ef = (err ) ? (double) err[i]:  Def_ErrF;
+   AddData2(x[i],y[i],f[i],ef,ex,ey);
+ }
+}
+
+//++
+void GeneralFitData::SetData2(int nData, float* x, float* y, float* f
+                             ,float *err,float *errx,float *erry)
+//
+//	Pour remplir la structure de donnees d'un seul coup avec
+//|     {x(i),[errx(i)], y(i),[erry(i)], ; f(i),err(i)}
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+
+ for(int i=0;i<nData;i++) {
+   double ex = (errx) ? (double) errx[i]: Def_ErrX;
+   double ey = (erry) ? (double) erry[i]: Def_ErrX;
+   double ef = (err ) ? (double) err[i]:  Def_ErrF;
+   AddData2((double) x[i],(double) y[i],(double) f[i],ef,ex,ey);
+ }
+}
+
+//++
+void GeneralFitData::SetData(int nData,double** xp, double *f
+                            , double *err, double** errxp)
+//
+//	Pour remplir la structure de donnees d'un seul coup avec
+//|   {X0(i),[EX0(i)], X1(i),[EX1(i)], X2(i),[EX2(i)], ... ; F(i),Err(i)}
+//	Attention: si la structure est n'est pas vide, les tableaux sont copies
+//	apres les donnees pre-existantes (qui ne sont donc pas detruites). Pour
+//	effacer les donnees pre-existantes utiliser SetDataPtr(0).
+//|   Ici **xp est un pointeur sur un tableau de pointeurs tq
+//|     xp[0] = &X0[0], xp[1] = &X1[0], xp[2] = &X2[0] ...
+//|   ou X0,X1,X2,... sont les tableaux X0[nData] X1[nData] X2[nData] ...
+//|   des variables (meme commentaire pour errxp).
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+ if(mOk_EXP && !errxp) {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = Def_ErrX;}
+
+ for(int i=0;i<nData;i++) {
+   {for(int j=0;j<mNVar;j++) BuffVar[j] = *(xp[j]+i);}
+   if(mOk_EXP && errxp)
+     {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = *(errxp[j]+i);}
+   double ef = (err) ? err[i]:  Def_ErrF;
+   AddData(BuffVar,f[i],ef,BuffVar+mNVar);
+ }
+}
+
+//++
+void GeneralFitData::SetData(int nData,float** xp, float *f
+                            , float *err, float** errxp)
+//
+//	Voir commentaire ci-dessus.
+//--
+{
+ ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
+
+ if(mOk_EXP && !errxp) {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = Def_ErrX;}
+
+ for(int i=0;i<nData;i++) {
+   {for(int j=0;j<mNVar;j++) BuffVar[j] = (double) *(xp[j]+i);}
+   if(mOk_EXP && errxp)
+     {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = (double) *(errxp[j]+i);}
+   double ef = (err) ? err[i]:  Def_ErrF;
+   AddData(BuffVar,(double) f[i],ef,BuffVar+mNVar);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFitData::PrintStatus()
+//
+//	Impression de l'etat de la structure de donnees
+//--
+{
+  cout<<"GeneralFitData:: "<<endl
+      <<"NVar="<<mNVar<<" NDataAlloc="<<mNDataAlloc<<" Ok_EXP="<<mOk_EXP
+      <<" ,NData="<<mNData<<" NDataGood="<<mNDataGood<<endl
+      <<"  mXP="<<mXP<<"  [mErrXP="<<mErrXP<<"] mF="<<mF<<" mErr="<<mErr
+      <<" mOK="<<mOK<<endl;
+}
+
+//++
+void GeneralFitData::PrintData(int i)
+//
+//	Impression du point i
+//--
+{
+ ASSERT(i>=0 && i<mNData);
+
+ cout<<" "<<i<<" F( ";
+ {for(int j=0;j<mNVar;j++) cout<<" "<<Absc(j,i);}
+ if(mOk_EXP) {
+   cout<<"  ;  ";
+   for(int j=0;j<mNVar;j++) cout<<" "<<EAbsc(j,i);
+ }
+ cout<<")= "<<Val(i)<<" "<<EVal(i)<<" ("<<IsValid(i)<<")\n";
+}
+
+//++
+void GeneralFitData::PrintData(int i1,int i2)
+//
+//	Impression des points i1 a i2
+//--
+{
+ if(i1<0) i1=0;
+ if(i1>=mNData) i1 = mNData-1;
+ if(i2>=mNData) i2 = mNData-1;
+ if(i1>i2) i2 = mNData-1;
+
+ cout<<"GeneralFitData::PrintData[NData="
+     <<mNData<<"/ NDataGood="<<mNDataGood<<"]"<<endl;
+ for(int i=i1;i<=i2;i++) PrintData(i);
+ cout<<flush;
+}
+
+//++
+void GeneralFitData::PrintData()
+//
+//	Impression de tous les points
+//--
+{
+ ASSERT(mNData>0);
+
+ PrintData(0,mNData-1);
+}
+
+//++
+void GeneralFitData::Show(ostream& os) const
+//
+//	Impression de l'etat de la structure de donnees avec bornes sur "s"
+//--
+{
+double min,max;
+os<<"GeneralFitData:: NVar,ErrX="<<mNVar<<","<<mOk_EXP
+  <<" Data: "<<mNData<<" Good,Alloc="<<mNDataGood<<","<<mNDataAlloc<<endl;
+for(int k=0;k<2*NVar()+3;k++) {
+  GetMinMax(k,min,max);
+  os<<" - "<<k<<" "<<ColumnName(k)<<"  ,  "<<min<<","<<max<<endl;
+}
+return;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+int GeneralFitData::GetMnMx(int var,int& imin,int& imax) const
+//
+//	Retourne les numeros des points de valeurs minimum et maximum
+//	de la variable ``var'':
+//| La variable "var" est de la forme : var = AB avec
+//|  B = 0 : variable d'ordonnee Y (valeur de A indifferente)
+//|  B = 1 : erreur variable d'ordonnee EY (valeur de A indifferente)
+//|  B = 2 : variable d'abscisse X numero A #[0,NVar[
+//|  B = 3 : erreur variable d'abscisse EX numero A #[0,NVar[
+//| - Return NData checked si ok, -1 si probleme.
+//--
+{
+imin = imax = -1;
+int ix = var/10;
+var = var%10;
+if(var<0 || var>3) return -1;
+if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
+double min, max;
+int ntest = 0;
+for(int i=0;i<mNData;i++) {
+  if( ! IsValid(i) ) continue;
+  double v;
+  if(var==0)      v = Val(i);
+  else if(var==1) v = EVal(i);
+  else if(var==2) v = Absc(ix,i);
+  else if(var==3) v = EAbsc(ix,i);
+  if(ntest==0) {min = max = v; imin = imax = i;}
+  if(v<min) {min = v; imin = i;}
+  if(v>max) {max = v; imax = i;}
+  ntest++;
+}
+return ntest;
+}
+
+//++
+int GeneralFitData::GetMnMx(int var,double& min,double& max) const
+//
+//	Retourne le minimum et le maximum de la variable ``var''
+//	(cf commentaires GetMnMx).
+//--
+{
+min = 1.; max = -1.;
+int imin,imax;
+int ntest = GetMnMx(var,imin,imax);
+if(ntest<=0) return ntest;
+int ix = var/10;
+var = var%10;
+if(var==0) {
+  if(imin>=0) min = Val(imin);
+  if(imax>=0) max = Val(imax);
+} else if(var==1) {
+  if(imin>=0) min = EVal(imin);
+  if(imax>=0) max = EVal(imax);
+} else if(var==2) {
+  if(imin>=0) min = Absc(ix,imin);
+  if(imax>=0) max = Absc(ix,imax);
+} else if(var==3) {
+  if(imin>=0) min = EAbsc(ix,imin);
+  if(imax>=0) max = EAbsc(ix,imax);
+}
+return ntest;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+int GeneralFitData::GetMeanSigma(int var,double& mean,double& sigma,double min,double max)
+//
+//	Retourne la moyenne et le sigma de la variable ``var''
+//	(cf commentaires GetMnMx).
+//| - Return : nombre de donnees utilisees, -1 si pb, -2 si sigma<0.
+//| - Seuls les points valides de valeur entre min,max sont utilises.
+//|   Si min>=max pas de coupures sur les valeurs.
+//--
+{
+mean = sigma = 0.;
+int ix = var/10;
+var = var%10;
+if(var<0 || var>3) return -1;
+if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
+int ntest = 0;
+for(int i=0;i<mNData;i++) {
+  if( ! IsValid(i) ) continue;
+  double v;
+  if(var==0)      v = Val(i);
+  else if(var==1) v = EVal(i);
+  else if(var==2) v = Absc(ix,i);
+  else if(var==3) v = EAbsc(ix,i);
+  if(min<max && (v<min || max<v)) continue;
+  mean += v;
+  sigma += v*v;
+  ntest++;
+}
+if(ntest==0) {
+  mean = sigma = 0.;
+} else {
+  mean /= (double)ntest;
+  sigma = sigma/(double)ntest - mean*mean;
+  if(sigma<0.) ntest = -2;
+  else if(sigma>0.) sigma = sqrt(sigma);
+}
+return ntest;
+}
+
+//++
+int GeneralFitData::GetMoMeMed(int var,double& mode,double& mean,double& median,
+                               double min,double max,double coeff)
+//
+//	Retourne le mode de la variable ``var''
+//	(cf commentaires GetMnMx).
+//| - Return : nombre de donnees utilisees, -1 si pb.
+//| - Seuls les points valides de valeur entre min,max sont utilises.
+//|   Si min>=max pas de coupures sur les valeurs.
+//| - Le calcul du mode est approximee par la formule:
+//|     Mode = Median - coeff*(Mean-Median)   (def: coeff=0.8)
+//| - Kendall and Stuart donne coeff=2., mais coeff peut etre regle.
+//--
+{
+mode = mean = median = 0.;
+if(mNData<=0) return -1;
+int ix = var/10;
+var = var%10;
+if(var<0 || var>3) return -1;
+if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
+double* buff = new double[mNData];
+int ntest = 0;
+for(int i=0;i<mNData;i++) {
+  if( ! IsValid(i) ) continue;
+  double v;
+  if(var==0)      v = Val(i);
+  else if(var==1) v = EVal(i);
+  else if(var==2) v = Absc(ix,i);
+  else if(var==3) v = EAbsc(ix,i);
+  if(min<max && (v<min || max<v)) continue;
+  buff[ntest] = v;
+  mean += v;
+  ntest++;
+}
+if(ntest==0) {
+  mean = 0.;
+} else {
+  mean /= (double)ntest;
+  qsort(buff,(size_t) ntest,sizeof(double),qSort_Dble);
+  int im;
+  if(ntest%2==1) {
+    // nombre impair de points
+    im = ntest/2;
+    median = buff[im];
+  } else {
+    // nombre pair de points
+    im = (ntest-1)/2;
+    median = (buff[im]+buff[im+1])/2.;
+  }
+  mode = median - coeff*(mean-median);
+}
+delete [] buff;
+return ntest;
+}
+
+//++
+int GeneralFitData::GetMode(int var,double& mode,double min,double max,double coeff)
+//
+//	Cf description ci-dessus ``GetMoMeMed''.
+//--
+{
+double mean,median;
+return GetMoMeMed(var,mode,mean,median,min,max,coeff);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralFitData::PolFit(int varx,Poly& pol,int degre,bool ey)
+//
+//	Pour fiter un polynome de degre ``degre''. On fite
+//	Y=f(X) ou Y=Val et X=Absc(varx). Si ``ey'' est ``true''
+//	le fit prend en compte les erreurs stoquees dans EVal,
+//	sinon fit sans erreurs. Le resultat du fit est retourne
+//	dans le polynome ``pol''.
+//| Return:
+//|  -   Res = le residu du fit
+//|  -   -1 si degre<0
+//|  -   -2 si probleme sur numero de variable X
+//|  -   -4 si NDataGood<0
+//|  -   -5 si nombre de data trouves different de NDataGood
+//--
+{
+if(degre<0) return -1.;
+if(varx<0 || varx>=mNVar) return -2.;
+if(mNDataGood<=0) return -4.;
+Vector x(mNDataGood);
+Vector y(mNDataGood);
+Vector ey2(1);
+if(ey) ey2.Realloc(mNDataGood,true);
+int ntest = 0;
+for(int i=0;i<mNData;i++) {
+  if( ! IsValid(i) ) continue;
+  if(ntest>=mNDataGood) return -5.;
+  x(ntest) = Absc(varx,i);
+  y(ntest) = Val(i);
+  if(ey) ey2(ntest) = EVal(i)*EVal(i);
+  ntest++;
+}
+double res = 0.;
+if(ey) {
+  Vector errcoef(1);
+  res = pol.Fit(x,y,ey2,degre,errcoef);
+} else {
+  res = pol.Fit(x,y,degre);
+}
+return res;
+}
+
+//++
+double GeneralFitData::PolFit(int varx,int vary,Poly2& pol,int degre1,int degre2,bool ez)
+//
+//
+//	Pour fiter un polynome de degre ``degre1''. On fite
+//	Z=f(X,Y) ou Z=Val et X=Absc(varx) et Y=Absc(vary).
+//	Si ``ey'' est ``true'' le fit prend en compte les erreurs
+//	stoquees dans EVal, sinon fit sans erreurs. Si ``degre2''
+//	negatif, le fit determine un polynome en X,Y de degre
+//	total ``degre`''. Si ``degre2'' positif ou nul, le fit
+//	demande un fit de ``degre1'' pour la variable X et de degre
+//	``degre2'' sur la variable Y. Le resultat du fit est retourne
+//	dans le polynome ``pol''.
+//| Return:
+//|  -   Res = le residu du fit
+//|  -   -1 si degre<0
+//|  -   -2 si probleme sur numero de variable X
+//|  -   -3 si probleme sur numero de variable Y
+//|  -   -4 si NDataGood<0
+//|  -   -5 si nombre de data trouves different de NDataGood
+//--
+{
+if(degre1<0) return -1.;
+if(varx<0 || varx>=mNVar) return -2.;
+if(vary<0 || vary>=mNVar || vary==varx) return -3.;
+if(mNDataGood<=0) return -4.;
+Vector x(mNDataGood);
+Vector y(mNDataGood);
+Vector z(mNDataGood);
+Vector ez2(1);
+if(ez) ez2.Realloc(mNDataGood,true);
+int ntest = 0;
+for(int i=0;i<mNData;i++) {
+  if( ! IsValid(i) ) continue;
+  if(ntest>=mNDataGood) return -5.;
+  x(ntest) = Absc(varx,i);
+  y(ntest) = Absc(vary,i);
+  z(ntest) = Val(i);
+  if(ez) ez2(ntest) = EVal(i)*EVal(i);
+  ntest++;
+}
+double res = 0.;
+if(ez) {
+  Vector errcoef(1);
+  if(degre2>0) res = pol.Fit(x,y,z,ez2,degre1,degre2,errcoef);
+  else         res = pol.Fit(x,y,z,ez2,degre1,errcoef);
+} else {
+  if(degre2>0) res = pol.Fit(x,y,z,degre1,degre2);
+  else         res = pol.Fit(x,y,z,degre1);
+}
+return res;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFitData GeneralFitData::FitResidus(GeneralFit& gfit)
+//
+//	Retourne une classe contenant les residus du fit ``gfit''.
+//--
+{
+if(gfit.GetNVar()!=mNVar)
+  throw(SzMismatchError("GeneralFitData::FitResidus: size mismatch\n"));
+return gfit.DataResidus(true);
+}
+
+//++
+GeneralFitData GeneralFitData::FitFunction(GeneralFit& gfit)
+//
+//	Retourne une classe contenant la function du fit ``gfit''.
+//--
+{
+if(gfit.GetNVar()!=mNVar)
+  throw(SzMismatchError("GeneralFitData::FitFunction: size mismatch\n"));
+return gfit.DataFunction(true);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+r_8* GeneralFitData::GetVec(int n, r_8* ret)   const
+//
+//	Retourne la donnee `n' dans le vecteur de double `ret'.
+//| Par defaut, ret=NULL et le buffer interne de la classe est retourne
+//| - Les donnees sont rangees dans l'ordre:
+//|    x0,x1,x2,... ; ex0,ex1,ex2,...  ; y ; ey ; ok(0/1)
+//|    |<- NVar ->| + |<-   NVar   ->| + 1 +  1 +  1
+//|   Le vecteur ret a la taille 2*NVar+2+1
+//--
+{
+int i;
+if (ret == NULL) ret = BuffVar;
+for(i=0; i<2*mNVar+3; i++)  ret[i] = 0.;
+if (n >= mNData) return(ret);
+
+memcpy(ret, mXP+n*mNVar, mNVar*sizeof(r_8));
+if(mErrXP) memcpy(ret+mNVar, mErrXP+n*mNVar, mNVar*sizeof(r_8));
+ret[2*mNVar] = mF[n];
+ret[2*mNVar+1] = mErr[n];
+ret[2*mNVar+2] = (double) mOK[n];
+return(ret);
+}
+
+//++
+r_4* GeneralFitData::GetVecR4(int n, r_4* ret)   const
+//
+//	Retourne la donnee `n' dans le vecteur de float `ret'
+//	(meme commentaires que pour GetVec).
+//--
+{
+if (ret == NULL) ret = BuffVarR4;
+double *buff = new double[2*mNVar+3];
+GetVec(n,buff);
+for(int i=0;i<2*mNVar+3;i++) ret[i] = (float) buff[i];
+delete [] buff;
+return ret;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+// int inline int GetSpaceFree() const
+//	Retourne la place restante dans la structure (nombre de
+//	donnees que l'on peut encore stoquer).
+//--
+//++
+// inline int  NVar()       const
+//	Retourne le nombre de variables Xi
+//--
+//++
+// inline int  NData()
+//	Retourne le nombre de donnees
+//--
+//++
+// inline int  NDataGood()  const
+//	Retourne le nombre de bonnes donnees (utilisees pour le fit)
+//--
+//++
+// inline int  NDataAlloc() const
+//	Retourne la place maximale allouee pour les donnees
+//--
+//++
+// inline unsigned short int IsValid(int i) const
+//	Retourne 1 si point valide, sinon 0
+//--
+//++
+// inline bool HasXErrors()
+//	Retourne ``true'' si il y a des erreurs sur les variables
+//	d'abscisse, ``false'' sinon.
+//--
+//++
+// inline double X1(int i) const
+//	Retourne l'abscisse pour 1 dimension (y=f(x)) donnee I
+//--
+//++
+// inline double X(int i) const
+//	Retourne la 1er abscisse (X) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double Y(int i) const
+//	Retourne la 2sd abscisse (Y) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double Z(int i) const
+//	Retourne la 3ieme abscisse (Z) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double Absc(int j,int i) const
+//	Retourne la Jieme abscisse (Xj) pour (v=f(x0,x1,x2,...)) donnee I
+//--
+//++
+// inline double Val(int i) const
+//	Retourne la valeur de la Ieme donnee
+//--
+//++
+// inline double EX1(int i) const
+//	Retourne l'erreur (dx) sur l'abscisse pour 1 dimension (y=f(x)) donnee I
+//--
+//++
+// inline double EX(int i) const
+//	Retourne l'erreur (dx) sur la 1er abscisse (X) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double EY(int i) const
+//	Retourne l'erreur (dy) sur la 2sd abscisse (Y) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double EZ(int i) const
+//	Retourne l'erreur (dz) sur la 3ieme abscisse (Z) pour (v=f(x,y,z,...)) donnee I
+//--
+//++
+// inline double EAbsc(int j,int i) const
+//	Retourne l'erreur (dxj) sur la Jieme abscisse (Xj) pour (v=f(x0,x1,x2,...)) donnee I
+//--
+//++
+// inline double EVal(int i) const {return mErr[i];}
+//	Retourne l'erreur de la Ieme donnee
+//--
+
+
+//////////////////////////////////////////////////////////////////////
+// ------- Implementation de  l interface NTuple  ---------
+
+uint_4 GeneralFitData::NbLines() const
+{
+return(NData());
+}
+
+//++
+uint_4 GeneralFitData::NbColumns() const
+//
+//	Retourne le nombre de colonnes du ntuple equivalent:
+//| Exemple: on a une fonction sur un espace a 4 dimensions:
+//| "x0,x1,x2,x3    , ex0,ex1,ex2,ex3    , y,   ey ,    ok"
+//|   0  1  2  3        4   5   6   7      8     9      10
+//|   |        |        |           |      |     |       |        
+//|   0       nv-1     nv         2*nv-1  2*nv  2*nv+1  2*nv+2
+//| soit 2*nvar+3 variables/colonnes.
+//--
+{
+return(2*NVar()+3);
+}
+
+r_8 * GeneralFitData::GetLineD(int n) const
+{
+return(GetVec(n,NULL));
+}
+
+r_8 GeneralFitData::GetCell(int n, int k) const
+{
+if(k<0 || k>=2*NVar()+3) return 0.;
+r_8 * val = GetVec(n,NULL);
+return val[k];
+}
+
+r_8 GeneralFitData::GetCell(int n, string const & nom) const
+{
+int k = ColumnIndex(nom);
+return(GetCell(n,k));
+}
+
+//++
+void GeneralFitData::GetMinMax(int k, double& min, double& max)  const
+//
+//	Retourne le minimum et le maximum de la variable `k'.
+//--
+{
+int var;
+if(k<0 || k>=2*NVar()+3) return;
+else if(k<NVar())      var = 10*k+2;          // Variable Xi
+else if(k<2*NVar())    var = 10*(k-NVar())+3; // Variable EXi
+else if(k==2*NVar())   var = 0;               // Variable Y
+else if(k==2*NVar()+1) var = 1;               // Variable EY
+else {min=0.; max=1.; return;}                // Variable Ok
+GetMnMx(var,min,max);
+return;
+}
+
+void GeneralFitData::GetMinMax(string const & nom, double& min, double& max)   const
+{
+int k = ColumnIndex(nom);
+GetMinMax(k,min,max);
+}
+
+int GeneralFitData::ColumnIndex(string const & nom)  const
+{
+char str[64]; int k = -1;
+strcpy(str,nom.c_str()); strip(str,'L',' ');
+if(str[0]=='y') return 2*NVar();
+if(str[0]=='o') return 2*NVar()+2;
+if(str[0]=='x') {sscanf(str,"x%d",&k); return k;}
+if(str[0]=='e')
+  if(str[1]=='y') return 2*NVar()+1;
+  else if(str[1]=='x') {sscanf(str,"ex%d",&k); return NVar()+k;}
+return -1;
+}
+
+string GeneralFitData::ColumnName(int k) const
+{
+if(k==2*NVar())                return string("y");
+else if(k==2*NVar()+1)         return string("ey");
+else if(k==2*NVar()+2)         return string("ok");
+else if(k<0 || k>=2*NVar()+3)  return string("");
+
+char str[64] = "";
+if(k<NVar()) sprintf(str,"x%d",k);
+else if(k<2*NVar()) sprintf(str,"ex%d",k-NVar());
+return string(str);
+}
+
+//++
+string GeneralFitData::VarList_C(const char* nomx)  const
+//
+//	Retourne une chaine de caracteres avec la declaration des noms de 
+//	variables. si "nomx!=NULL" , des instructions d'affectation
+//	a partir d'un tableau "nomx[i]" sont ajoutees. 
+//--
+{
+char buff[256];
+string rets;
+int i;
+rets = "\ndouble";
+for(i=0; i<mNVar; i++) {
+  sprintf(buff," x%d, ex%d",i,i);
+  rets += buff;
+  if(i!=mNVar-1) rets += ","; else rets += ";\n";
+}
+sprintf(buff,"\ndouble y, ey, ok;\n");
+rets += buff;
+if (nomx) {
+  for(i=0; i<mNVar; i++) {
+    sprintf(buff,"x%d=%s[%d];\n", i, nomx, i);
+    rets += buff;
+  }
+  for(i=0; i<mNVar; i++) {
+    sprintf(buff,"ex%d=%s[%d];\n", i, nomx, mNVar+i);
+    rets += buff;
+  }
+}
+sprintf(buff,"y=%s[%d];\ney=%s[%d];\nok=%s[%d];\n"
+       ,nomx,2*mNVar,nomx,2*mNVar+1,nomx,2*mNVar+2);
+rets += buff;
+
+return(rets);
+}
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+
+void ObjFileIO<GeneralFitData>::ReadSelf(PInPersist& is)
+{
+char strg[256];
+
+if(dobj==NULL) dobj=new GeneralFitData;
+  else         dobj->Delete();
+
+// Lecture entete
+is.GetLine(strg, 255);
+
+// Ecriture des valeurs de definitions
+int_4 nvar,ndatalloc,ndata,ndatagood;
+is.Get(nvar);
+is.Get(ndatalloc);
+is.Get(ndata);
+is.Get(ndatagood);
+is.Get(dobj->mOk_EXP);
+if(nvar<=0 || ndatalloc<=0 || ndata<=0 || ndatagood<0 || ndatalloc<ndata) return;
+
+// Allocation de la place (attention Alloc efface mNData,mNDataGood);
+dobj->Alloc(nvar,ndatalloc,-1);
+dobj->mNData = ndata;
+dobj->mNDataGood = ndatagood;
+
+// Lecture des datas
+is.GetLine(strg, 255);
+int blen = dobj->mNVar + 3;
+if(dobj->mOk_EXP) blen += dobj->mNVar;
+double *buff = new double[blen];
+for(int i=0;i<dobj->mNData;i++) {
+  is.Get(buff, blen);
+  int ip = i*dobj->mNVar;
+  {for(int j=0;j<dobj->mNVar;j++)  dobj->mXP[ip+j] = buff[j];}
+  dobj->mF[i] = buff[dobj->mNVar];
+  dobj->mErr[i] = buff[dobj->mNVar+1];
+  dobj->mOK[i] = (uint_2)(buff[dobj->mNVar+2]+0.01);
+  if(dobj->mOk_EXP) {for(int j=0;j<dobj->mNVar;j++)
+                        dobj->mErrXP[ip+j] = buff[dobj->mNVar+3+j];}
+}
+delete [] buff;
+
+return;
+}
+
+void ObjFileIO<GeneralFitData>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+char strg[256];
+
+// Ecriture entete pour identifier facilement
+sprintf(strg,"GeneralFitData: NVar=%d NDataAlloc=%d NData=%d NDataGood=%d Ok_EXP=%d"
+       ,dobj->mNVar,dobj->mNDataAlloc,dobj->mNData,dobj->mNDataGood,dobj->mOk_EXP);
+os.PutLine(strg);
+
+// Ecriture des valeurs de definitions
+os.Put(dobj->mNVar);
+os.Put(dobj->mNDataAlloc);
+os.Put(dobj->mNData);
+os.Put(dobj->mNDataGood);
+os.Put(dobj->mOk_EXP);
+if(dobj->mNVar<=0 || dobj->mNDataAlloc<=0 || dobj->mNData<=0 || dobj->mNDataGood<0) return;
+
+// Ecriture des datas (on n'ecrit que mNData / mNDataAlloc)
+sprintf(strg
+       ,"GeneralFitData: Abscisses, Ordonnee, Erreur Ordonnee, Flag, Erreur Abscisses");
+os.PutLine(strg);
+
+int blen = dobj->mNVar + 3;
+if(dobj->mOk_EXP) blen += dobj->mNVar;
+double *buff = new double[blen];
+for(int i=0;i<dobj->mNData;i++) {
+  {for(int j=0;j<dobj->mNVar;j++) buff[j] = dobj->Absc(j,i);}
+  buff[dobj->mNVar] = dobj->Val(i);
+  buff[dobj->mNVar+1] = dobj->EVal(i);
+  buff[dobj->mNVar+2] = (double) dobj->IsValid(i);
+  if(dobj->mOk_EXP) {for(int j=0;j<dobj->mNVar;j++) buff[dobj->mNVar+3+j] = dobj->EAbsc(j,i);}
+  os.Put(buff, blen);
+}
+delete [] buff;
+
+return;
+}
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<GeneralFitData>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<GeneralFitData>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/generaldata.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/generaldata.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/generaldata.h	(revision 752)
@@ -0,0 +1,166 @@
+// This may look like C code, but it is really -*- C++ -*-
+//                         C.Magneville          04/99
+#ifndef GENERALDATA_SEEN
+#define GENERALDATA_SEEN
+
+#include "objfio.h"
+#include <iostream.h>
+#include "pexceptions.h"
+#include "ppersist.h"
+#include "ntupintf.h"
+#include "poly.h"
+
+namespace SOPHYA {
+
+class GeneralFit;
+
+//================================================================
+// GENERALFITDATA
+//================================================================
+
+class GeneralFitData : public AnyDataObj , public NTupleInterface {
+  friend class GeneralFit;
+  friend class ObjFileIO<GeneralFitData>;
+public:
+  enum {Def_ErrF = 1, Def_ErrX = 0};
+
+  GeneralFitData(unsigned int nVar, unsigned int nDataAlloc, uint_2 errx=0);
+  GeneralFitData(const GeneralFitData& data, bool clean=false);
+  GeneralFitData();
+  virtual ~GeneralFitData();
+
+  void Alloc(unsigned int nVar, unsigned int nDataAlloc, int_2 errx=-1);
+  void SetDataPtr(int ptr = 0);
+
+  void KillData(int i);
+  void KillData(int i1,int i2);
+
+  void ValidData(int i);
+  void ValidData(int i1,int i2);
+  void ValidData();
+
+  void RedefineData1(int i,double x,double f,double err=Def_ErrF,double errx=Def_ErrX);
+  void RedefineData2(int i,double x,double y,double f,double err=Def_ErrF
+                    ,double errx=Def_ErrX,double erry=Def_ErrX);
+  void RedefineData(int i,double* xp,double f,double err=Def_ErrF,double* errxp=NULL);
+
+  void AddData1(double x, double f, double err=Def_ErrF,double errx=Def_ErrX);
+  void AddData2(double x, double y, double f, double err=Def_ErrF
+               ,double errx=Def_ErrX,double erry=Def_ErrX);
+  void AddData(double* xp, double f, double err=Def_ErrF,double* errxp=NULL);
+  void AddData(float* xp, float f, float err=Def_ErrF,float* errxp=NULL);
+
+  void SetData1(int nData,double* x,double* f,double *err=NULL,double *errx=NULL);
+  void SetData1(int nData,float* x,float* f,float* err=NULL,float *errx=NULL);
+  void SetData2(int nData,double* x,double* y,double* f,double *err=NULL
+               ,double *errx=NULL,double *erry=NULL);
+  void SetData2(int nData,float* x,float* y,float* f,float* err=NULL
+               ,float *errx=NULL,float *erry=NULL);
+  void SetData(int nData,double** xp,double *f,double *err=NULL,double** errxp=NULL);
+  void SetData(int nData,float** xp,float* f,float* err=NULL,float** errxp=NULL);
+
+  void PrintStatus();
+  void PrintData(int i);
+  void PrintData(int i1,int i2);
+  void PrintData();
+  void Show(ostream& os) const;
+  inline void Show() const {Show(cout);}
+
+  inline int GetSpaceFree() const { return mNDataAlloc - mNData; }
+  inline int NVar()       const {return mNVar;}
+  inline int NData()      const {return mNData;}
+  inline int NDataGood()  const {return mNDataGood;}
+  inline int NDataAlloc() const {return mNDataAlloc;}
+
+  inline unsigned short int IsValid(int i) const
+                {if(i>=0 && i<mNData) return mOK[i]; else return 0;}
+  inline bool HasXErrors() {if(mErrXP) return true; else return false;}
+
+  inline double X1(int i) const
+                {if(i>=0 && i<mNData) return mXP[i]; else return 0.;}
+  inline double X(int i) const
+                {if(i>=0 && i<mNData) return mXP[i*mNVar]; else return 0.;}
+  inline double Y(int i) const
+                {if(i>=0 && i<mNData && 1<mNVar) return mXP[i*mNVar+1]; else return 0.;}
+  inline double Z(int i) const
+                {if(i>=0 && i<mNData && 2<mNVar) return mXP[i*mNVar+2]; else return 0.;}
+  inline double Absc(int j,int i) const
+                {if(i>=0 && i<mNData && j<mNVar)return mXP[i*mNVar+j]; else return 0.;}
+  inline double Val(int i) const
+                {if(i>=0 && i<mNData) return mF[i]; else return 0.;}
+
+  inline double EX1(int i) const
+                {if(mErrXP && i>=0 && i<mNData) return mErrXP[i]; else return 0.;}
+  inline double EX(int i) const
+                {if(mErrXP && i>=0 && i<mNData) return mErrXP[i*mNVar]; else return 0.;}
+  inline double EY(int i) const
+                {if(mErrXP && i>=0 && i<mNData && 1<mNVar) return mErrXP[i*mNVar+1];
+                 else return 0.;}
+  inline double EZ(int i) const
+                {if(mErrXP && i>=0 && i<mNData && 2<mNVar) return mErrXP[i*mNVar+2];
+                 else return 0.;}
+  inline double EAbsc(int j,int i) const
+                {if(mErrXP && i>=0 && i<mNData && j<mNVar) return mErrXP[i*mNVar+j];
+                 else return 0.;}
+  inline double EVal(int i) const
+                {if(i>=0 && i<mNData) return mErr[i]; else return 0.;}
+
+  r_8* GetVec(int n, r_8* ret=NULL)  const;
+  r_4* GetVecR4(int n, r_4* ret=NULL)  const;
+  int GetMnMx(int var,int& imin,int& imax) const;
+  int GetMnMx(int var,double& min,double& max) const;
+  int GetMeanSigma(int var,double& mean,double& sigma,double min=1.,double max=-1.);
+  int GetMoMeMed(int var,double& mode,double& mean,double& median,
+                 double min=1.,double max=-1.,double coeff=0.8);
+  int GetMode(int var,double& mode,double min=1.,double max=-1.,double coeff=0.8);
+  double PolFit(int varx,Poly& pol,int degre,bool ey=true);
+  double PolFit(int varx,int vary,Poly2& pol,int degre1,int degre2=-1,bool ez=true);
+  GeneralFitData FitResidus(GeneralFit& gfit);
+  GeneralFitData FitFunction(GeneralFit& gfit);
+
+// Declaration de l interface NTuple
+  virtual uint_4        NbLines() const;
+  virtual uint_4        NbColumns() const;
+  virtual r_8 *         GetLineD(int n) const;
+  virtual r_8		GetCell(int n, int k) const;
+  virtual r_8		GetCell(int n, string const & nom) const;
+  virtual void		GetMinMax(int k, double& min, double& max) const; 
+  virtual void		GetMinMax(string const & nom, double& min, double& max) const;
+  virtual int           ColumnIndex(string const & nom) const;
+  virtual string        ColumnName(int k) const;
+  virtual string	VarList_C(const char* nomx=NULL) const;
+
+protected:
+  void Delete();
+
+  int_4   mNVar;
+  int_4   mNDataAlloc;
+  int_4   mNData;
+  int_4   mNDataGood;
+  uint_2  mOk_EXP;
+  r_8* mXP;             // x0 y0 z0, x1 y1 z1, ..., xn yn zn 
+  r_8* mErrXP;          // Ex0 Ey0 Ez0, Ex1 Ey1 Ez1, ..., Exn Eyn Ezn 
+  r_8* mF;              // F0, F1, ...., Fn
+  r_8* mErr;            // EF0, EF1, ...., EFn
+  uint_2* mOK; // 1 si pt valid, 0 sinon
+  r_8* BuffVar;
+  r_4* BuffVarR4;
+};
+
+inline ostream& operator << (ostream& s, GeneralFitData const & g)
+                         {g.Show(s); return(s);}
+
+/////////////////////////////////////////////////////////////////////////
+// Classe pour la gestion de persistance
+
+inline POutPersist& operator << (POutPersist& os, GeneralFitData & obj)
+{ ObjFileIO<GeneralFitData> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, GeneralFitData & obj)
+{ ObjFileIO<GeneralFitData> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<GeneralFitData>
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/generalfit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/generalfit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/generalfit.cc	(revision 752)
@@ -0,0 +1,1881 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <math.h>
+#ifdef __MWERKS__
+   #include "mwerksmath.h" // Portage mac D. Y.
+#include "unixmac.h"
+#endif
+#include <string.h>
+#include <string>
+
+#include "pexceptions.h"
+#include "generalfit.h"
+
+#define EPS_FIT_MIN 1.e-8
+
+//================================================================
+// GeneralFunction
+//================================================================
+
+//++
+// Class	GeneralFunction
+// Lib	Outils++ 
+// include	generalfit.h
+//
+//	Classe de fonctions parametrees a plusieurs variables.
+//|           F[x1,x2,x3,...:a1,a2,a3,...]
+//--
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFunction::GeneralFunction(unsigned int nVar, unsigned int nPar)
+//
+//	Creation d'une fonction de `nVar' variables et `nPar' parametres.
+//|  F[x(1),x(2),x(3),...x(nVar) : a(1),a(2),a(3),...,a(nPar)]
+//--
+  : mNVar(nVar), mNPar(nPar)
+{
+ ASSERT( nVar > 0 && nPar > 0 );
+ deltaParm = new double[nPar];
+ tmpParm   = new double[nPar];
+ END_CONSTRUCTOR
+}
+
+//++
+GeneralFunction::~GeneralFunction()
+//
+//--
+{
+ delete[] deltaParm;
+ delete[] tmpParm;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralFunction::Val_Der(double const xp[], double const* parm
+                               , double *DgDpar)
+//
+//	Valeur et Derivees de la fonction (fct virtuelle par defaut).
+//--
+{
+ for(int i=0;i<mNPar;i++) tmpParm[i] = parm[i];
+ {for(int i=0;i<mNPar;i++) {
+   double d = deltaParm[i];
+   if(d==0.) { DgDpar[i] = 0.; continue;}
+   tmpParm[i] -= d/2.;
+   double vg = Value(xp,tmpParm);
+   tmpParm[i] += d;
+   double vd = Value(xp,tmpParm);
+   DgDpar[i] = (vd - vg)/d;
+   tmpParm[i] = parm[i];
+ }}
+ return Value(xp, parm);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFunction::SetDeltaParm(int numPar, double d)
+//
+//	Definition de la variation du parametre numPar
+//	pour calculer la derivee automatiquement.
+//--
+{
+ ASSERT(numPar >= 0 && numPar < mNPar);
+ deltaParm[numPar] = d;
+}
+
+//++
+void GeneralFunction::SetDeltaParm(double const* dparam)
+//
+//	Idem precedente fonction mais pour tous les parametres
+//--
+{
+ for(int i=0;i<mNPar;i++) deltaParm[i] = dparam[i];
+}
+
+//////////////////////////////////////////////////////////////////////
+// Rappel des inline functions pour commentaires
+//++
+// virtual double Value(double const xp[], double const* parm)=0;
+//	Valeur de la fonction a definir par l'utilisateur (fct virtuelle pure)
+//--
+//++
+// inline int     NVar() const
+//	Retourne le nombre de variables Xi
+//--
+//++
+// inline int     NPar() const
+//	Retourne le nombre de parametres Ai
+//--
+
+//================================================================
+// GeneralFunc
+//================================================================
+
+//++
+// Class	GeneralFunc
+// Lib	Outils++ 
+// include	generalfit.h
+//
+//	Classe de fonctions parametrees a plusieurs variables
+//	derivant de ``GeneralFunction''. Permet de definir
+//	une fonction a fiter sans passer par une classe derivee
+//	en utilisant l'ecriture courante du C. La fonction
+//	retournant les derivees par rapport aux parametres du fit
+//	peut etre egalement fournie (optionnel).
+//--
+
+/////////////////////////////////////////////////////////////////
+//++
+GeneralFunc::GeneralFunc(unsigned int nvar, unsigned int npar, double (*fun) (double const*, double const*)
+                        , double (*funder) (double const*, double const*, double*) )
+//
+//	Createur, on passe le nom ``fun'' de la fonction a la mode C.
+//	On peut optionellement egalement passer le nom de la fonction
+//	``funder'' qui retourne les valeurs des derivees par rapport
+//	aux parametres du fit.
+//--
+//++
+//| ----------------------
+//| Exemple d'utilisation:
+//| ----------------------
+//| include "generalfit.h"
+//| ...
+//| double   gaussc(double const* x,double const* p);
+//| double d_gaussc(double const* x,double const* p,double* dp);
+//| ...
+//| main {
+//|  ...
+//|  // Fit SANS calcul automatique des derivees
+//|  GeneralFunc      myfunc(2,7,gaussc);
+//|  GeneralFit       myfit(&myfunc);
+//|  ...
+//|  myfit.Fit();
+//|  ...
+//|  // Fit AVEC calcul automatique des derivees
+//|  GeneralFunc      myfunc(2,7,gaussc,d_gaussc);
+//|  GeneralFit       myfit(&myfunc);
+//|  ...
+//|  myfit.Fit();
+//| }
+//--
+//++
+//| // Definition de la fonction a fitter a la mode C
+//| double gaussc(double const* x,double const* p)
+//| // Fonction: X=(x[0]-p[1])/p[3], Y=(x[1]-p[2])/p[4],
+//| //  f = p[0]*exp{-0.5*[X^2+Y^2-2*p[5]*X*Y]} + p[6]
+//| {
+//|  double X = (x[0]-p[1])/p[3];
+//|  double Y = (x[1]-p[2])/p[4];
+//|  return p[0]*exp(-(X*X+Y*Y-2*p[5]*X*Y)/2)+p[6];
+//| }
+//| // Definition de la fonction des derivees / parametres
+//| // Cette fonction retourne aussi la valeur de la fonction a fitter.
+//| double d_gaussc(double const* x,double const* p,double* dp)
+//| {
+//|  dp[0] = derivee de gaussc par rapport au parametre p[0]
+//|  ...
+//|  dp[6] = derivee de gaussc par rapport au parametre p[6]
+//|  return gaussc(x,p);
+//| }
+//--
+: GeneralFunction(nvar,npar), tmpFun(fun), tmpFunDer(funder)
+{
+}
+
+GeneralFunc::~GeneralFunc()
+{
+}
+
+double GeneralFunc::Value(double const xp[], double const* Par)
+{
+return tmpFun(xp,Par);
+}
+
+double GeneralFunc::Val_Der(double const xp[],double const* parm, double* DgDpar)
+{
+if(tmpFunDer) return tmpFunDer(xp,parm,DgDpar);
+  else        return GeneralFunction::Val_Der(xp,parm,DgDpar);
+}
+
+//================================================================
+// GeneralXi2
+//================================================================
+
+//++
+// Class	GeneralXi2
+// Lib	Outils++ 
+// include	generalfit.h
+//
+//	Classe de Xi2 a plusieurs parametres.
+//|           Xi2[a1,a2,a3,...]
+//--
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralXi2::GeneralXi2(unsigned int nPar)
+//
+//	Creation d'un Xi2 de `nPar' parametres.
+//|  Xi2[a(1),a(2),a(3),...,a(nPar)]
+//--
+  : mNPar(nPar)
+{ 
+ ASSERT( nPar>0 );
+ deltaParm = new double[nPar];
+ END_CONSTRUCTOR
+}
+
+//++
+GeneralXi2::~GeneralXi2()
+//
+//--
+{
+ delete[] deltaParm;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralXi2::Derivee(GeneralFitData& data, int i, double* parm)
+//
+//	Derivee du Xi2 par rapport au parametre `i'
+//	pour les valeurs `parm' des parametres.
+//--
+{
+ int dum;
+ double d = deltaParm[i];
+ parm[i] -= d/2.;
+ double vg = Value(data, parm,dum);
+ parm[i] += d;
+ double vd = Value(data, parm,dum);
+ parm[i] -= d/2.;
+ return (vd - vg)/d;
+}
+
+//++
+double GeneralXi2::Derivee2(GeneralFitData& data, int i, int j, double* parm)
+//
+//	Derivee seconde du Xi2 par rapport aux parametres `i' et `j'
+//	pour les valeurs `parm' des parametres. Attention, cette fonction
+//	calcule d/di(dC2/dj), valeur qui est numeriquement differente
+//	de d/dj(dC2/di).
+//--
+//++
+//|
+//| **** Remarque: Derivee2 = dXi2/dPi.dPj represente le Hessien.
+//| Derivee2(k,l)= dXi2/dPk.dPl
+//|              = 2*SUMi{1/Si^2*[df(xi;P)/dPk * df(xi;P)/dPl]
+//|                       + [yi-f(xi;P)] * df(xi;P)/dPk.dPl }
+//| ou (xi,yi) sont les points de mesure. "Si" l'erreur sur le point i
+//|    SUMi represente la somme sur les points de mesure
+//|    f(x;P) represente le modele parametrique a fitter
+//|    "P" represente l'ensemble des parametres et "Pi" le ieme parametre
+//| Les composantes du Hessien dependent des derivees 1ere et 2sd du modele
+//| a fitter f(x;P) selon les parametres "Pi". La prise en compte des derivees
+//| secondes est un facteur destabilisant. De plus le facteur [yi-f(xi;P)]
+//| devant la derivee 2sd est seulement l'erreur de mesure aleatoire qui
+//| n'est pas correlee avec le modele. Le terme avec la derivee 2sd
+//| tend donc a s'annuler et peut donc etre omis.
+//| (cf. Numerical Recipes in C, chap 15 Modeling of Data, Nonlinear Models,
+//|  Calculation of the Gradient and Hessian p682,683)
+//|
+//| **** Conseil: Il est conseille a l'utilisateur de sur-ecrire
+//| la fonction virtuelle Derivee2 et de la remplacer par:
+//| Derivee2(k,l) = 2*SUMi{1/Si^2*[df(xi;P)/dPk * df(xi;P)/dPl]}
+//--
+{
+ double d = deltaParm[i];
+ parm[i] -= d/2.;
+ double vg = Derivee(data,j,parm);
+ parm[i] += d;
+ double vd = Derivee(data,j,parm);
+ parm[i] -= d/2.;
+ d = (vd - vg)/d;
+ return d;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralXi2::SetDeltaParm(int numPar, double d)
+//
+//	Definition de la variation du parametre numPar
+//	pour calculer la derivee automatiquement.
+//--
+{
+ ASSERT(numPar >= 0 && numPar < mNPar);
+  
+ deltaParm[numPar] = d;
+}
+
+//++
+void GeneralXi2::SetDeltaParm(double const* dparam)
+//
+//	Idem precedente fonction mais pour tous les parametres.
+//--
+{
+ for(int i=0;i<mNPar;i++) deltaParm[i] = dparam[i];
+}
+
+//////////////////////////////////////////////////////////////////////
+// Rappel des inline functions pour commentaires
+//++
+// virtual double Value(GeneralFitData& data, double const* parm, int& ndataused)=0;
+//	Valeur du Xi2 a definir par l'utilisateur (fct virtuelle pure)
+//	a partir des donnees de `data'. l'utilisateur doit egalement
+//	retourner le nombre de points de mesure utilises dans le calcul
+//	du Xi2 (`ndataused').
+//--
+//++
+// inline int     NPar() const
+//	Retourne le nombre de parametres Ai.
+//--
+
+//================================================================
+// GeneralFit
+//================================================================
+//                                Christophe 8/11/93 La Silla
+//                                re-codage C++ 16/01/96 Saclay
+
+//++
+// Class	GeneralFit
+// Lib		Outils++
+// include	generalfit.h
+//
+//	Classe de fit d'une GeneralFunction sur une GeneralFitData
+//--
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFit::GeneralFit(GeneralFunction* f)
+//
+//	Creation d'une classe de fit pour la `GeneralFunction f'.
+//--
+  : mNVar         (f->NVar()),
+    mNPar         (f->NPar()),
+    mFunction     (f),
+    mFuncXi2      (NULL),
+
+    Param         (f->NPar()),
+    errParam      (f->NPar()),
+    stepParam     (f->NPar()),
+    minParam      (f->NPar()),
+    maxParam      (f->NPar()),
+    minStepDeriv  (f->NPar()),
+    Eps           (f->NPar()),
+  
+    ATGA          (f->NPar(), f->NPar()),
+    BETA          (f->NPar()),
+    ATGA_Try      (f->NPar(), f->NPar()),
+    BETA_Try      (f->NPar()),
+    C             (f->NPar()),
+    D             (f->NPar())
+{
+ ASSERT(mNVar>0 && mNPar>0);
+ ASSERT(mNPar<1000000);
+
+ TRY {
+   General_Init();
+ } CATCHALL {
+   THROW_SAME;
+ } ENDTRY
+
+ END_CONSTRUCTOR
+}
+
+//++
+GeneralFit::GeneralFit(GeneralXi2* f)
+//
+//	Creation d'une classe de fit pour le `GeneralXi2 f'.
+//	L'emploi de cette methode n'est pas conseillee car elle
+//	calcule automatiquement la derivee 2sd du Xi2 par rapport
+//	aux parametres, ce qui entraine un manque de robustesse
+//	et qui ne garanti pas que la matrice de covariance soit
+//	definie positive (il est possible de surecrire
+//	la methode virtuelle Derivee2 pour palier ce probleme).
+//--
+  : mNVar         (0),
+    mNPar         (f->NPar()),
+    mFunction     (NULL),
+    mFuncXi2      (f),
+
+    Param         (f->NPar()),
+    errParam      (f->NPar()),
+    stepParam     (f->NPar()),
+    minParam      (f->NPar()),
+    maxParam      (f->NPar()),
+    minStepDeriv  (f->NPar()),
+    Eps           (f->NPar()),
+  
+    ATGA          (f->NPar(), f->NPar()),
+    BETA          (f->NPar()),
+    ATGA_Try      (f->NPar(), f->NPar()),
+    BETA_Try      (f->NPar()),
+    C             (f->NPar()),
+    D             (f->NPar())
+{
+ ASSERT( mNPar>0 );
+ ASSERT( mNPar < 1000000 );
+
+ TRY {
+   General_Init();
+ } CATCHALL {
+   THROW_SAME;
+ } ENDTRY
+
+ END_CONSTRUCTOR
+}
+
+//
+void GeneralFit::General_Init(void)
+// Initialisation des diverses variables
+{
+ mNtry      = 0;
+ mNParFree  = mNPar;
+ mNParBound = 0;
+
+ mData      = NULL;
+
+ fixParam   = NULL;
+ boundParam = NULL;
+ nameParam  = NULL;
+
+ Lambda_Fac = 10.;
+ stopChi2   = 0.01;
+ maxStep    = 100;
+ nStopMx    = 3;
+ stopChi2SMx = stopChi2;
+ nStopLent  = 0;
+ debugLevel = 0;
+ FileStep = NULL;
+  
+ Chi2       = 0.;
+ mNddl      = -1;
+ nStep      = 0;
+ nStop      = 0;
+ nStopL     = 0;
+ Lambda     = 0.001;
+
+ GetIntEnv("PDEBUG_GENERALFIT",debugLevel);
+
+ TRY {
+   fixParam   = new unsigned short int[mNPar];
+   boundParam = new unsigned short int[mNPar];
+   nameParam  = new string[mNPar];
+ } CATCHALL {
+   cout<<"GeneralFit::GeneralFit Impossible d'allouer l'espace"<<endl;
+   THROW_SAME;
+ } ENDTRY
+
+ Param        = (double)  0.;
+ errParam     = (double)  0.;
+ stepParam    = (double)  1.;
+ minParam     = (double)  1.;
+ maxParam     = (double) -1.;
+ minStepDeriv = (double) 0.;
+ Eps          = (double) EPS_FIT_MIN;
+ char str[8];
+ for(int i=0;i<mNPar;i++) {
+   sprintf(str,"P%d",i);
+   fixParam[i]   = 0;
+   boundParam[i] = 0;
+   nameParam[i]  = str;
+ }
+}
+
+//++
+GeneralFit::~GeneralFit()
+//
+//--
+{
+ delete[] fixParam;
+ delete[] boundParam;
+ delete[] nameParam;
+ if(FileStep!=NULL) fclose(FileStep);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::WriteStep(char *filename)
+//
+//	Pour ecrire les iterations dans le fichier filename
+//--
+{
+
+#if defined(__DECCXX) || defined(__KCC__) || defined(__aCC__)
+if(filename==NULL) filename = const_cast<char *>("generalfit.iter");
+#else
+if(filename==NULL) filename = "generalfit.iter";
+#endif
+FileStep = fopen(filename,"w");
+if(FileStep==NULL) THROW(nullPtrErr);
+}
+
+//++
+void GeneralFit::SetDebug(int level)
+//
+//	Niveau de debug
+//	(voir aussi la variable d'environnement PDEBUG_GENERALFIT).
+//--
+{
+ debugLevel = ( level < 0 ) ? 0: level;
+ if(debugLevel>0) cout<<"SetDebug_level "<<debugLevel<<endl;
+}
+
+//++
+void GeneralFit::SetMaxStep(int n)
+//
+//	Nombre maximum d'iterations permis.
+//--
+{
+ maxStep = ( n <= 1 ) ? 100: n;
+ if(debugLevel>0) cout<<"SetMaxStep "<<maxStep<<endl;
+}
+
+//++
+void GeneralFit::SetLambda_Fac(double fac)
+//
+//	Facteur de multiplication/division de Lambda selon
+//	que le Chi2 a augmente ou diminue.
+//--
+{
+  Lambda_Fac = (fac>1.) ? fac : 10.;
+}
+
+//++
+void GeneralFit::SetStopChi2(double s)
+//
+//	Critere de convergence sur le Chi2.
+//--
+{
+ stopChi2 = ( s <= 0. ) ? 0.01: s;
+ if(debugLevel>0) cout<<"SetStopChi2 "<<stopChi2<<endl;
+}
+
+//++
+void GeneralFit::SetEps(double ep)
+//
+//	Precision des calculs (cf descriptif general).
+//--
+{
+ ep = (ep<=0.) ? EPS_FIT_MIN: ep;
+ if(debugLevel>0) cout<<"SetEps "<<ep<<endl;
+ for(int i=0;i<mNPar;i++) SetEps(i,ep);
+}
+
+//++
+void GeneralFit::SetEps(int n,double ep)
+//
+//	Precision des calculs pour le parametre n.
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ Eps(n) = (ep<=0.) ? EPS_FIT_MIN: ep;
+ if(debugLevel>0) cout<<"SetEps("<<n<<") = "<<Eps(n)<<endl;
+}
+
+//++
+void GeneralFit::SetStopMx(int nstopmx,double stopchi2)
+//
+//	Critere de convergence sur le nombre de stop en chi2
+//	dans le cas ou le chi2 augmente de moins de stopchi2
+//	(cf descriptif general).
+//	Si nstopmx<=0, alors ce critere de convergence n'est pas applique.
+//	Si stopchi2<=0, alors la valeur generale mise par SetStopChi2()
+//	est utilisee.
+//--
+{
+ nStopMx = (nstopmx>0) ? nstopmx : 0;
+ stopChi2SMx = (stopchi2>0.) ? stopchi2 : stopChi2;
+ if(debugLevel>0) cout<<"SetStopMx: nStopMx="<<nStopMx
+                      <<" stopChi2SMx="<<stopChi2SMx<<endl;
+}
+
+//++
+void GeneralFit::SetStopLent(int nstoplent)
+//
+//	Critere de convergence sur le nombre de stop en chi2
+//	dans le cas ou le chi2 diminue (cf descriptif general).
+//	Si nstopl<=0, alors ce critere de convergence n'est pas applique.
+//--
+{
+ nStopLent = (nstoplent>0) ? nstoplent : 0;
+ if(debugLevel>0) cout<<"SetStopLent "<<nStopLent<<endl;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetFunction(GeneralFunction* f)
+//
+//	Pour changer la fonction a fitter en cours de route
+//	(On ne peut passer d'un fit sur une GeneralFunction
+//	a un fit sur un GeneralXi2 sans recreer la classe).
+//--
+{
+ ASSERT( mFuncXi2  == NULL );
+ ASSERT( f != NULL );
+ ASSERT( f->NVar() == mNVar );
+ ASSERT( f->NPar() == mNPar );
+ mFunction = f;
+ if(debugLevel>0) cout<<"SetFunction "<<mFunction<<endl;
+}
+
+//++
+void GeneralFit::SetFuncXi2(GeneralXi2* f)
+//
+//	Pour changer le Xi2 a fitter en cours de route
+//	(On ne peut passer d'un fit sur une GeneralFunction
+//	a un fit sur un GeneralXi2 sans recreer la classe).
+//--
+{
+ ASSERT( mFunction == NULL );
+ ASSERT( f != NULL );
+ ASSERT( f->NPar() == mNPar );
+ mFuncXi2  = f;
+ if(debugLevel>0) cout<<"SetFuncXi2 "<<mFuncXi2<<endl;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetData(GeneralFitData* data)
+//
+//	Pour connecter une structure de donnees.
+//--
+{
+ ASSERT( data->NVar()==mNVar );
+ mData = data;
+ mNddl = mData->NDataGood() - mNParFree;
+ if(debugLevel>0)
+   cout<<"SetData "<<mData<<" data pour "<<mNddl<<" ddl"<<endl;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetParam(int n,double value,double step
+                         ,double min,double max)
+//
+//	Definition du parametre "n" a fitter.
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+
+ Param(n)     = value;
+ if(step>0.) {
+   if( fixParam[n] ) { fixParam[n]=0; mNParFree++;}
+ } else {
+   if( ! fixParam[n] ) { fixParam[n]=1; mNParFree--;}
+ }
+ stepParam(n) = step;
+ minParam(n)  = min;
+ maxParam(n)  = max;
+ if(max>min) {
+   if( ! boundParam[n] ) {boundParam[n]=1; mNParBound++;}
+ } else {
+   if( boundParam[n] ) {boundParam[n]=0; mNParBound--;}
+ }
+  
+ if(debugLevel) {cout<<"Set_"; PrintParm(n);}
+}
+
+//++
+void GeneralFit::SetParam(int n, string const& name
+                        ,double value,double step,double min,double max)
+//
+//	Definition du parametre "n" a fitter
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ SetParam(n,value,step,min,max);
+ nameParam[n] = name;
+ if(debugLevel) {cout<<"Set_Param "; PrintParm(n);}
+}
+
+//++
+void GeneralFit::SetParam(int n,double value)
+//
+//	Definition du parametre "n" a fitter
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ Param(n) = value;
+ if(debugLevel) {cout<<"Set_Param "; PrintParm(n);}
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetStep(int n,double step)
+//
+//	Definition du pas de depart du parametre "n"
+//	Si negatif ou nul, parametre fixe.
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ if(step>0.) {
+   if( fixParam[n] ) { fixParam[n]=0; mNParFree++;}
+ } else {
+   if( ! fixParam[n] ) { fixParam[n]=1; mNParFree--;}
+ }
+ stepParam(n) = step;
+ if(debugLevel) {cout<<"Set_Step"; PrintParm(n);}
+}
+
+//++
+void GeneralFit::SetMinStepDeriv(int i,double val)
+//
+//	Definition du pas minimum `val' pour le parametre `i'
+//	pouvant etre utilise dans le calcul automatique des derivees
+//	(soit de la fonction, soit du Xi2 selon les parametres du fit).
+//	Si nul pas de limite, si negatif alors `EPS(i)' (cf SetEps).
+//	Inutile dans le cas ou les derivees sont donnees
+//	par l'utilisateur.
+//--
+{
+ ASSERT(i>=0 && i<mNPar);
+ if(val<0.) minStepDeriv(i) = Eps(i);
+   else     minStepDeriv(i) = val;
+ if(debugLevel>0) cout<<"SetMinStepDeriv("<<i<<") = "<<minStepDeriv(i)<<endl;
+}
+
+//++
+void GeneralFit::SetMinStepDeriv(double val)
+//
+//	Definition du pas minimum `val' pour tout les parametres
+//	(voir description SetMinStepDeriv ci-dessus).
+//--
+{
+ if(debugLevel>0) cout<<"SetMinStepDeriv "<<val<<endl;
+ for(int i=0;i<mNPar;i++) SetMinStepDeriv(i,val);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetBound(int n, double min, double max)
+//
+//	Definition des bornes du parametre "n"
+//	Si max<=min, parametre non-borne.
+//--
+{
+ ASSERT(n>=0 && n<mNPar && max>min);
+
+ minParam(n)  = min;
+ maxParam(n)  = max;
+ if( ! boundParam[n] ) {
+   boundParam[n] = 1;
+   mNParBound++;
+   if(debugLevel>0)
+     cout<<"SetBound "<<n<<" min="<<min<<" max="<<max
+         <<" (Nbound="<<mNParBound<<")"<<endl;
+ }
+}
+
+//++
+void GeneralFit::SetBound(int n)
+//
+//	Pour re-borner le parametre "n" aux bornes par defaut
+//--
+{
+ ASSERT(n>=0 && n<mNPar && maxParam(n)>minParam(n));
+ SetBound(n,minParam(n),maxParam(n));
+}
+
+//++
+void GeneralFit::SetUnBound(int n)
+//
+//	Pour ne plus borner le parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+
+ if( boundParam[n] ) {
+   boundParam[n] = 0;
+   mNParBound++;
+   if(debugLevel>0) cout<<" SetUnBound "<<n
+                        <<" (Nbound="<<mNParBound<<")"<<endl;
+ }
+}
+
+//++
+void GeneralFit::SetUnBound()
+//
+//	Pour ne plus borner tous les parametres
+//--
+{
+ for(int i=0;i<mNPar;i++) SetUnBound(i);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::SetFix(int n,double v)
+//
+//	Pour fixer le parametre "n" a la valeur "v"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+
+ Param(n) = v;
+ if( ! fixParam[n] ) {
+   fixParam[n] = 1;
+   mNParFree--;
+ }
+ if(debugLevel>0) cout<<" SetFix "<<n
+                      <<" v="<<v
+                      <<" (Nfree="<<mNParFree
+                      <<")"<<endl;
+}
+
+//++
+void GeneralFit::SetFix(int n)
+//
+//	Pour fixer le parametre "n" a la valeur par defaut
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ SetFix(n,Param(n));
+}
+
+//++
+void GeneralFit::SetFree(int n)
+//
+//	Pour liberer le parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+
+ if( fixParam[n] ) {
+   fixParam[n] = 0;
+   mNParFree++;
+   if(debugLevel>0) cout<<" SetFree "<<n
+                        <<"   Step "<<stepParam(n)
+                        <<" (Nfree="<<mNParFree<<")"<<endl;
+   if(stepParam(n)<=0.)
+     cout<<"ATTENTION SetFree["<<n<<"] avec step<=0 "
+         <<stepParam(n)<<endl;
+ }
+}
+
+//++
+void GeneralFit::SetFree()
+//
+//	Pour liberer tous les parametres
+//--
+{
+ for(int i=0;i<mNPar;i++) SetFree(i);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralFit::GetParm(int n)
+//
+//	Retourne la valeur du parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ return Param(n);
+}
+
+//++
+Vector GeneralFit::GetParm()
+//
+//	Retourne les valeurs des parametres dans un vecteur.
+//--
+{
+return Param;
+}
+
+//++
+double GeneralFit::GetParmErr(int n)
+//
+//	Retourne la valeur de l'erreur du parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ return errParam(n);
+}
+
+//++
+double GeneralFit::GetCoVar(int i,int j)
+//
+//	Retourne la covariance pour les parametre `i' et `j'
+//--
+{
+ ASSERT(i>=0 && i<mNPar && j>=0 && j<mNPar);
+ return ATGA(i,j);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralFit::GetStep(int n)
+//
+//	Retourne la valeur du pas du parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ return stepParam(n);
+}
+
+//++
+double GeneralFit::GetMax(int n)
+//
+//	Retourne la valeur de la borne superieure du parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ return maxParam(n);
+}
+
+//++
+double GeneralFit::GetMin(int n)
+//
+//	Retourne la valeur de la borne inferieure du parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+ return minParam(n);
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::PrintStatus()
+//
+//	Impression du status du fit
+//--
+{
+ cout<<"GeneralFit::PrintStatus"
+     <<" mData="<<mData
+     <<" mFunction="<<mFunction
+     <<" mFuncXi2="<<mFuncXi2
+     <<endl;
+ cout<<" mNVar="<<mNVar
+     <<" mNPar="<<mNPar
+     <<" mNParFree="<<mNParFree
+     <<" mNParBound="<<mNParBound
+     <<endl;
+ cout<<" Lambda_Fac="<<Lambda_Fac
+     <<" stopChi2="<<stopChi2
+     <<" maxStep="<<maxStep
+     <<" nStopMx="<<nStopMx<<" stopChi2SMx="<<stopChi2SMx
+     <<" nStopLent="<<nStopLent
+     <<" debugLevel="<<debugLevel
+     <<endl;
+ PrintParm();
+}
+
+//++
+void GeneralFit::PrintFit()
+//
+//	Impression des resultats du fit
+//--
+{
+ cout<<"PrintFit: Chi2="<<Chi2
+     <<" Lambda="<<Lambda
+     <<" nStep="<<nStep
+     <<" nStop="<<nStop
+     <<" nStopL="<<nStopL
+     <<" nDDL="<<mNddl
+     <<endl;
+ PrintParm();
+}
+
+//++
+void GeneralFit::PrintParm(int n)
+//
+//	Impression des informations relatives au parametre "n"
+//--
+{
+ ASSERT(n>=0 && n<mNPar);
+
+ cout<<"Par["<<n<<"] "<<nameParam[n]
+     <<" F"<<fixParam[n]
+     <<" B"<<boundParam[n]
+     <<" : "<<Param(n)
+     <<" +/- "<<errParam(n)
+     <<" : "<<stepParam(n)
+     <<" "<<minParam(n)
+     <<" "<<maxParam(n)
+     <<" : "<<Eps(n)
+     <<" "<<minStepDeriv(n)
+     <<endl;
+}
+
+//++
+void GeneralFit::PrintParm()
+//
+//	Impression des informations relatives a tous les parametres
+//--
+{
+ cout<<"*** Parametres : fix bnd : par err : step min max : eps dmin\n";
+ for (int i=0; i<mNPar; i++) PrintParm(i);
+ cout<<endl;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+int GeneralFit::Fit()
+//
+//--
+//++
+//|  Fonction de fit de la fonction f(x,y,z,...:p1,p2,...,pn)
+//|          sur les donnees x[i],y[i],z[i],...,F[i],ErrF[i]
+//|  - Methode:   fit des moindres carres dans le cas non lineaire
+//|  - Reference: Statistical and Computational Methods in Data Analysis
+//|              Siegmund Brandt, North-Holland 1970  p 204-206.
+//|              Introduction des limites pour la variation des parametres (cmv).
+//|              Increment des parametres selon la methode de Levenberg-Marquardt
+//|  (Numerical Recipes in C, chap 15 Modeling of Data, Nonlinear Models,
+//|   Levenberg-Marquardt Method p683)
+//--
+//++
+//|  - Gestion des parametres bornes:
+//|     si p est un parametre borne entre pmin et pmax, le parametre fitte est q
+//|     tel que     q = tang((p-C)/D)    ....   p = C + D*atan(q)
+//|     ou   C = (pmin+pmax)/2.  et   D = (pmax-pmin)/Pi
+//|     On a  dq = (1+q**2)/D * dp    ....   dp = D/(1+q**2) * dq
+//|     et    dF/dq = dF/dp * dp/dq = D/(1+q**2) * dF/dp
+//|           dF/dp = dF/dq * dq/dp = (1+q**2)/D * dF/dp
+//|                                   ^ q
+//|                   |               |              *| "tang()"
+//|                   |               |              *|
+//|                   |               |              *|
+//|                   |               |             * |
+//|                   |               |            *  |
+//|                   |               |          *    |
+//|                   |               |       *       |
+//|               Pmin|              C|   *           |Pmax
+//|     --------------|---------------*---------------|--------------> p
+//|              -Pi/2|           *   |0              |Pi/2
+//|                   |       *       |               |
+//|                   |    *          |               |
+//|                   |  *            |               |
+//|                   | *             |               |
+//|                   |*              |               |
+//|                   |*              |               |
+//|                   |*              |               |
+//|                   <------------------- D --------->
+//--
+//++
+//|  - Criteres de convergence, arrets standards:
+//|    - SOIT: le Chi2 est descendu de moins de stopChi2
+//|            entre l'iteration n et n+1
+//|            (stopChi2 est change par SetStopChi2)
+//|    - SOIT: 1. le chi2 est remonte de moins de stopChi2SMx et
+//|            2. les parametres libres ont varie de moins de Eps(i)
+//|               pendant les nStopmx dernieres iterations
+//|            Si nStopmx<=0, alors ce critere n'est pas applique (def=3).
+//|            (nStopmx,stopChi2SMx sont changes par SetStopMx, Eps par SetEps)
+//|
+//|  - Criteres de convergence, arrets par non-convergence:
+//|    - plus de "maxStep" iterations.
+//|
+//|  - Criteres de convergence, arrets speciaux:
+//|    - Si l'utilisateur a demande explicitement la methode d'arret
+//|      "SetStopLent()", arret si :
+//|        1. le Chi2 est descendu et
+//|        2. les parametres libres ont varies de moins de Eps
+//|           pendant les nStopLent dernieres iterations.
+//|           (nStopLent est change par SetStopLent, Eps par SetEps)
+//|
+//--
+//++
+//|  - Remarques diverses:
+//|     Les points avec erreurs <=0 ne sont pas utilises dans le fit.
+//|     Les bornes des parametres ne peuvent etre atteintes
+//|  - entrees:
+//|     la fonction est definie par une classe GeneralFunction
+//|     les donnees sont passees par une classe GeneralFitData
+//|     le nombre de parametres et le nombre de variables doivent etre
+//|        coherents entre GeneralFunction GeneralFitData GeneralFit
+//|  - Return: 
+//|       la function elle meme retourne le nombre d'iterations  du fit si succes
+//|       -1  : si le nombre de degre de liberte est <0
+//|       -10 : si l'inversion de la matrice des erreurs n'a pas ete possible
+//|       -11 : si un element diagonal de la matrice des covariances est <=0
+//|       -20 : si le fit n'a pas converge (nstep>nNstepMX)
+//|       -100-N : si le parametre "N" est initialise hors limites
+//|       -200-N : si le parametre "N" atteint sa limite inferieure
+//|       -300-N : si le parametre "N" atteint sa limite superieure
+//--
+{
+ volatile double oldChi2;
+ Matrix COVAR(mNPar,mNPar);
+ Vector DA(mNPar);
+ Vector dparam(mNPar);
+ Vector paramTry(mNPar);
+ Vector param_tr(mNPar);
+ Vector paramTry_tr(mNPar);
+ Vector step_tr(mNPar);
+ nStop = nStopL = nStep = 0;
+ Chi2 = oldChi2 = 0.;
+ Lambda = 0.001;
+ mNddl = mData->NDataGood() - mNParFree;
+ if(mNddl<0) return -1;
+ mNtry++;
+
+ if(debugLevel>= 2)
+   cout<<"\n********* DEBUT GENERALFIT.FIT() **************"<<endl;
+
+ // set matrices C,D dans le cas de parametres bornes
+ if(mNParBound>0) Set_Bound_C_D();
+
+ if(debugLevel>= 2) PrintStatus();
+
+ // check de la coherence des operations et assignations
+ CheckSanity();
+
+ // Pour les parametres bornes on verifie
+ // qu'ils sont initialises dans leurs limites
+ {for(int i=0;i<mNPar;i++) {
+   if( !boundParam[i] || fixParam[i] ) continue;
+   if( minParam(i)<Param(i) && Param(i)<maxParam(i) ) continue;
+   /* if(debugLevel>= 1) */
+    cout<<"Parametre "<<i<<" initialise hors limites "
+        <<minParam(i)<<" < "<<Param(i)
+        <<" < "<<maxParam(i)<<endl;
+   return(-100-i);
+ }}
+
+ // premier essai d'initialisation
+ param_tr = p_vers_tr(Param);
+ dparam = stepParam / 2.;
+ put_in_limits_for_deriv(Param,dparam);
+ if(mFunction!=NULL) mFunction->SetDeltaParm(dparam.Data());
+   else if(mFuncXi2!=NULL) mFuncXi2->SetDeltaParm(dparam.Data());
+ step_tr = dp_vers_dtr(stepParam,param_tr);
+
+ if(debugLevel>= 2) {
+   cout<<"ESSAI numero 1: Param:"<<endl;
+   cout<<Param;
+   cout<<"param_tr:"<<endl;
+   cout<<param_tr;
+   cout<<"step_tr:"<<endl;
+   cout<<step_tr;
+ }
+ if(mFunction!=NULL) TryFunc(Param,param_tr);
+   else if(mFuncXi2!=NULL) TryXi2(Param,param_tr);
+ ATGA = ATGA_Try;
+ BETA = BETA_Try;
+ oldChi2 = Chi2;
+
+ // Iterations
+ while (1) {
+   nStep++;
+
+   // un nouvel essai (si Lambda!=0)
+   {for(int i=0; i<mNPar; i++)
+       if(! fixParam[i] ) ATGA(i,i) *= 1 + Lambda;
+          else  ATGA(i,i) = 1.;}
+
+   // Calcul de la matrice des covariances
+#ifdef __mac__
+   COVAR = ATGA.Inverse();
+#else
+   TRY {
+     COVAR = ATGA.Inverse();
+   } CATCHALL {
+     if(debugLevel>0) {
+       cout<<"Pb inversion matrice ATGA:"<<endl;
+       cout<<ATGA;
+     }
+     return(-10);
+   } ENDTRY
+#endif
+
+   if (debugLevel >= 3) {
+     cout<<"Matrice (tA G A)^-1 = \n";
+     cout<<COVAR;
+   }
+
+   // calculs des deplacements a effectuer
+   DA = COVAR * BETA;
+   if (debugLevel >=2) {
+     cout<<"Correction parametres DA : \n";
+     cout<<DA;
+   }
+   
+
+   //////////////////////////////////////////////////
+   ////////////////// Arret du Fit //////////////////
+   // si Lambda = 0, le fit a converge on s'arrete
+   //                ou bien on a trop d'iterations
+   //////////////////////////////////////////////////
+   if(Lambda == 0 || nStep > maxStep) {
+     // trop d'iterations
+     if(nStep>maxStep) 
+       cout<<"GeneralFit : pas de convergence"<<endl;
+     // Probleme de matrice de covariance non-definie positive?
+     bool bad_covar = false;
+     {for(int i=0; i<mNPar; i++) {
+       if( fixParam[i] ) errParam(i) = 0.;
+       else {
+         stepParam(i) = DA(i);
+         if( COVAR(i,i)<=0. ) {
+            if( debugLevel>0 )
+              cout<<"Erreur: Par["<<i<<"]="<<param_tr(i)
+                  <<" ("<<Param(i)<<") COVAR()="<<COVAR(i,i)
+                  <<" step="<<DA(i)<<endl;
+             errParam(i) = 0.;
+             bad_covar = true;
+         } else {
+           errParam(i) = sqrt( COVAR(i,i) );
+	 }
+       }
+     }}
+     // print de debug pour parametres bornes
+     if(debugLevel>= 2) {
+       cout<<"param_tr:"<<endl;
+       cout<<param_tr;
+       cout<<"stepParam_tr:"<<endl;
+       cout<<stepParam;
+       cout<<"errParam_tr:"<<endl;
+       cout<<errParam;
+     }
+     // Calcul de la matrice des covariances
+     {for(int i=0; i<mNPar; i++) {
+        for(int j=0; j<mNPar; j++) {
+          if( fixParam[i] || fixParam[j] ) {
+            // Parametre fixe, on retourne l'identite
+            if(i==j) ATGA(i,j) = 1.; else ATGA(i,j) = 0.;
+	  } else if( errParam(i)<=0. || errParam(j)<=0.) {
+            // parametres avec mauvaise variance, on retourne 0
+            ATGA(i,j) = 0;
+	  } else {
+            // parametres OK
+            ATGA(i,j) = COVAR(i,j)/(errParam(i)*errParam(j));
+	  }
+	}
+     }}
+     if (debugLevel >= 1) {
+       cout<<">>> Matrice des Covariances = \n";
+       cout<<ATGA;
+     }
+     // Calcul du step et de l'erreur finale en tenant
+     // compte des parametres bornes
+     stepParam = dtr_vers_dp(stepParam,param_tr);
+     errParam  = dtr_vers_dp(errParam,param_tr);
+     // Print si demande et code de retour.
+     if (debugLevel>0 ) PrintFit();
+     if(nStep>maxStep) return(-20);
+       else if(bad_covar) return(-11);
+         else return(nStep);
+   }
+   ////////////////////////////////////////////////////////
+   ////////////////// Fin d'Arret du Fit //////////////////
+   ////////////////////////////////////////////////////////
+
+   // Gestion des deplacements
+   {for (int i=0; i<mNPar; i++) {
+     if( fixParam[i] ) { DA(i) = 0; continue;}
+     // le premier deplacement ne peut etre plus grand que stepParam
+     if( nStep == 1 && fabs(DA(i)) > step_tr(i) ) {
+       DA(i) = DA(i) < 0. ? -step_tr(i) : step_tr(i);
+       if(debugLevel>1 ) cout<<"Excursion parametre "<<i
+                             <<" limitee a "<<DA(i)<<endl;
+     }
+   }}
+   paramTry_tr = param_tr + DA;
+   paramTry = tr_vers_p(paramTry_tr);
+   dparam = dtr_vers_dp(DA,paramTry_tr);
+   dparam /= 2.;
+   put_in_limits_for_deriv(paramTry,dparam);
+   {for(int i=0; i<mNPar; i++) {
+     if( ! boundParam[i] ) continue;
+     if(paramTry(i) <= minParam(i)) {
+       if(debugLevel>0) cout<<"Parametre "<<i
+                            <<" limite au minimum"<<endl;
+       Param(i) = minParam(i);
+       return(-200-i);
+     } else if (paramTry(i) >= maxParam(i)) {
+       if(debugLevel>0) cout<<"Parametre "<<i
+                            <<" limite au maximum"<<endl;
+       Param(i) = maxParam(i);
+       return(-300-i);
+     }
+   }}
+
+   // Nouvel essai
+   if(mFunction!=NULL) mFunction->SetDeltaParm(dparam.Data());
+     else if(mFuncXi2!=NULL) mFuncXi2->SetDeltaParm(dparam.Data());
+   if(debugLevel >= 2) {
+     cout<<">>>>>>>>>>> ESSAI avec nouveaux parametres\n";
+     cout<<"paramTry:\n";
+     cout<<paramTry;
+     cout<<"paramTry_tr:\n";
+     cout<<paramTry_tr;
+     cout<<"dparam:\n";
+     cout<<dparam;
+   }
+   if(mFunction!=NULL) TryFunc(paramTry,paramTry_tr);
+     else if(mFuncXi2!=NULL) TryXi2(paramTry,paramTry_tr);
+
+   if (debugLevel >= 2)
+     cout<<"step "<<nStep<<" Chi2 : old="<<oldChi2
+         <<" new="<<Chi2<<" d="<<Chi2-oldChi2<<endl;
+   if(FileStep) write_in_step(Chi2,paramTry);
+
+   // *************************************************************
+   // ****************** quelle strategie sur Lambda ???? *********
+   // *************************************************************
+   if (Chi2 < oldChi2) {
+     // ****************** le Chi2 est descendu ******************
+     nStop = 0;
+     if(nStopLent>0) {
+       // Arret special demande, comment se comporte les parametres?
+       int k=0;
+       for (int i=0; i<mNPar; i++) if( (!fixParam[i]) &&
+              (fabs(param_tr(i)-paramTry_tr(i))<Eps(i))) k++;
+       if (k==mNParFree) nStopL++; // Tous les parametres ont peu varies
+          else nStopL=0;
+       if (debugLevel>=2) cout<<k<<" parametres sur "<<mNParFree
+                              <<" ont peu varies, nStopL="<<nStopL<<endl;
+     } else nStopL = 0;
+     // Preparation des parametres pour iteration suivante
+     ATGA = ATGA_Try;
+     BETA = BETA_Try;
+     param_tr = paramTry_tr;
+     Param = paramTry;
+     Lambda *= 1./Lambda_Fac;
+     // Arret ?
+     if (oldChi2-Chi2<stopChi2) {
+       // arret normal, convergence
+        Lambda = 0;
+        if (debugLevel >= 2)
+          cout<<"Arret>> demande car Chi2 decroit et oldChi2-Chi2= "
+	      <<oldChi2-Chi2<<"<"<<stopChi2<<endl;
+     } else if (nStopLent>0 && nStopL >= nStopLent) {
+       // arret demande par SetStopLent, variation lente des parametres
+       Lambda = 0.;
+       if (debugLevel >= 2) 
+         cout<<"Arret>> demande car Chi2 decroit et nStop(lent)= "
+             <<nStopL<<">="<<nStopLent<<endl;
+     }
+     oldChi2 = Chi2;
+     if (debugLevel >= 2) cout<<"Succes essai: Lambda divided by "
+                              <<Lambda_Fac<<" -> "<<Lambda<<endl;
+   } else {
+     // ****************** le Chi2 est remonte ******************
+     nStopL = 0;
+     if(nStopMx>0 && Chi2-oldChi2<stopChi2SMx) {
+       // Il est remonte tres peu, comment se comporte les parametres?
+       int k=0;
+       for (int i=0; i<mNPar; i++) if( (!fixParam[i]) &&
+              (fabs(param_tr(i)-paramTry_tr(i))<Eps(i))) k++;
+       if (k==mNParFree) nStop++; // Tous les parametres ont peu varies
+          else nStop=0;
+       if (debugLevel>=2) cout<<k<<" parametres sur "<<mNParFree
+                              <<" ont peu varies, nStop="<<nStop<<endl;
+     } else nStop = 0;
+     // Preparation des parametres pour iteration suivante
+     Lambda *= Lambda_Fac;
+     // Arret ?
+     if (nStopMx>0 && nStop>=nStopMx) {
+       // arret normal, convergence car ci2 varie peu et parametres aussi
+       Lambda = 0.;
+       if (debugLevel >= 2) 
+         cout<<"Arret>> demande car Chi2 croit et nstop= "
+             <<nStop<<">="<<nStopMx<<endl;
+     }
+     Chi2 = oldChi2;
+     if (debugLevel >= 2)
+       cout<<"Echec essai: Lambda multiplied by "<<Lambda_Fac
+           <<" -> "<<Lambda<<" nStop="<<nStop<<endl;
+   }
+
+ } // fin des iterations
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+double GeneralFit::ReCalChi2(int& nddl, double *par)
+//
+//	Recalcul du Chi2 a partir des parametres courants (`par==NULL')
+//	ou a partir du tableau de parametres `par'.
+//	Retourne le chi2 et le nombre de degres de liberte.
+//	Si nddl<0 probleme.
+//--
+{
+double c2 = -1.;
+if(par==NULL) par = Param.Data();
+if( mData->NData() <= 0 ) {nddl = -100; return 0.;}
+
+if( mFunction != NULL ) {
+
+  double e,result;
+
+  nddl = 0; c2  = 0.;
+  for(int k=0; k<mData->NData(); k++) {
+    if (! mData->mOK[k]) continue;
+    e = mData->mErr[k];
+    result = mFunction->Value(&mData->mXP[mNVar*k],par);
+    c2 += (mData->mF[k]-result)*(mData->mF[k]-result)/(e*e);
+    nddl++;
+  }
+  nddl -= mNParFree;
+
+  return c2;
+
+} else if( mFuncXi2 != NULL ) {
+
+  c2 = mFuncXi2->Value(*mData,par,nddl);
+  nddl -= mNParFree;
+  return c2;
+
+} else {
+
+  cout<<"GeneralFit::ReCalChi2_Erreur: mFunction && mFuncXi2 == NULL"<<endl;
+  nddl = -1;
+  return c2;
+}
+
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFitData GeneralFit::DataResidus(bool clean)
+//
+//	Retourne une structure ``GeneralFitData'' contenant
+//	les residus du fit (val-func) pour les points du fit.
+//	Si ``clean'' est ``true''
+//	seules les donnees valides de ``data'' sont copiees.
+//	Si ``clean'' est ``false'' (defaut) toutes les donnees
+//	sont copiees et la taille totale de ``data'' est allouee
+//	meme si elle est plus grande que la taille des donnees stoquees.
+//--
+{
+if(!mData || !mFunction)
+  throw(NullPtrError("GeneralFit::DataResidus: NULL pointer\n"));
+GeneralFitData datres(*mData,clean);
+for(int k=0; k<mData->NData(); k++)
+  datres.mF[k] -= mFunction->Value(&datres.mXP[mNVar*k],Param.Data());
+return datres;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+GeneralFitData GeneralFit::DataFunction(bool clean)
+//
+//	Retourne une structure ``GeneralFitData'' contenant
+//	les valeurs de la fonction fittee pour les points du fit.
+//	(voir commentaires pour ``clean'' dans ``DataResidus'')
+//--
+{
+if(!mData || !mFunction)
+  throw(NullPtrError("GeneralFit::DataFunction: NULL pointer\n"));
+GeneralFitData datres(*mData,clean);
+for(int k=0; k<mData->NData(); k++)
+  datres.mF[k] = mFunction->Value(&datres.mXP[mNVar*k],Param.Data());
+return datres;
+}
+
+//////////////////////////////////////////////////////////////////////
+//++
+void GeneralFit::PrintFitErr(int rc)
+//
+//	Imprime le commentaire lie a l'erreur rc retournee par Fit()
+//	(voir le commentaire de la methode `Fit()')
+//--
+{
+int n;
+if(rc>0) return;
+
+if(rc==-1)
+  cout<<"rc = "<<rc<<"  : le nombre de degre de liberte est <0"<<endl;
+
+else if(rc==-10)
+  cout<<"rc = "<<rc<<" : l'inversion de la matrice des erreurs n'a pas ete possible"<<endl;
+
+else if(rc==-11)
+  cout<<"rc = "<<rc<<" : un element diagonal de la matrice des covariances est <=0"<<endl;
+
+else if(rc==-20)
+  cout<<"rc = "<<rc<<" : le fit n'a pas converge (nstep>nNstepMX="<<maxStep<<")"<<endl;
+
+else if(rc>-200 && rc<=-100) {
+  n = -100-rc;
+  cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
+      <<") est initialise hors limites"<<endl;
+}
+
+else if(rc>-300 && rc<=-200) {
+  n = -200-rc;
+  cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
+      <<") atteint sa limite inferieure"<<endl;
+}
+
+else if(rc>-400 && rc<=-300) {
+  n = -300-rc;
+  cout<<"rc = "<<rc<<" : le parametre "<<n<<" ("<<nameParam[n]
+      <<") atteint sa limite superieure"<<endl;
+}
+
+else cout<<"rc = "<<rc<<" : type d'erreur inconnue"<<endl;
+
+}
+
+//////////////////////////////////////////////////////////////////////
+// Fonctions privees
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::write_in_step(double ci2,Vector& par)
+{
+if(FileStep==NULL) return;
+fprintf(FileStep,"%d %d %f",mNtry,nStep,ci2);
+for(int i=0; i<mNPar; i++) fprintf(FileStep," %f",par(i));
+fprintf(FileStep,"\n");
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::TryFunc(Vector& par,Vector& par_tr)
+{
+  BETA_Try = 0;
+  ATGA_Try = 0;
+  Chi2  = 0;
+  Vector deriv(mNPar);
+  Vector derivtr(mNPar);
+  double result;
+
+  for(int k=0; k<mData->NData(); k++) {
+    if (! mData->mOK[k]) continue;
+    double e = mData->mErr[k];
+    if(mNParBound==0)
+       result = mFunction->Val_Der(&mData->mXP[mNVar*k]
+                                  ,par.Data(),derivtr.Data());
+    else {
+       result = mFunction->Val_Der(&mData->mXP[mNVar*k]
+                                  ,par.Data(),deriv.Data());
+       dtr_vers_dp(deriv,par_tr,derivtr);
+    }
+    double Gkk = 1/(e*e);
+    double Ck  = mData->mF[k] - result;
+    Chi2 += Ck*Ck*Gkk;
+    for(int j=0; j<mNPar; j++) {
+      if( fixParam[j] ) continue;
+      for(int i=0; i<mNPar; i++)
+        if(!fixParam[i]) ATGA_Try(i,j) += derivtr(i)*Gkk*derivtr(j);
+      BETA_Try(j) += derivtr(j) * Gkk * Ck;
+    }
+  }
+
+  if (debugLevel >= 3) {
+    cout<<"Try: matrice ( At * G * A )_Try\n";
+    cout<<ATGA_Try;
+    cout<<"Try: beta_Try:\n";
+    cout<<BETA_Try;
+  }
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::TryXi2(Vector& par,Vector& par_tr)
+{
+  double c, *parloc;
+  BETA_Try = 0;
+  ATGA_Try = 0;
+  Chi2  = 0;
+
+  parloc = par.Data();  // He oui, encore ces ... de const*
+  Chi2 = mFuncXi2->Value(*mData,parloc,mNddl);
+  mNddl -= mNParFree;
+
+  // Calcul des derivees du Xi2 (vecteur du gradient)
+  {for(int i=0;i<mNPar; i++) {
+    if( fixParam[i] ) continue;
+    c = c_dtr_vers_dp(i,par_tr(i));
+    BETA_Try(i) = -0.5 * mFuncXi2->Derivee(*mData,i,parloc) * c;
+  }}
+
+  // Calcul des derivees 2sd du Xi2 (matrice de courbure ou 0.5*Hessien)
+  double c1,c2;
+  {for(int i=0;i<mNPar; i++) {
+    if( fixParam[i] ) continue;
+    c1 = c_dtr_vers_dp(i,par_tr(i));
+    for(int j=0;j<mNPar; j++) {
+      if( fixParam[j] ) continue;
+      c2 = c_dtr_vers_dp(j,par_tr(j));
+      ATGA_Try(i,j) = 0.5 * mFuncXi2->Derivee2(*mData,i,j,parloc) *c1*c2;
+    }
+  }}
+  // et on symetrise car d/di(dC2/dj) =  d/dj(dC2/di) mathematiquement
+  // mais malheureusement pas numeriquement.
+  if( mNPar>1) {
+    for(int i=0;i<mNPar-1; i++) {
+      if( fixParam[i] ) continue;
+      for(int j=i+1;j<mNPar; j++) {
+        if( fixParam[j] ) continue;
+        c1 = 0.5*(ATGA_Try(i,j) + ATGA_Try(j,i));
+        ATGA_Try(i,j) = c1;
+        ATGA_Try(j,i) = c1;
+      }
+    }
+  }
+  
+  if (debugLevel >= 3) {
+    cout<<"Try: matrice ( At * G * A )_Try\n";
+    cout<<ATGA_Try;
+    cout<<"Try: beta_Try:\n";
+    cout<<BETA_Try;
+  }
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::CheckSanity()
+{
+  ASSERT( mData != NULL );
+  ASSERT( mFunction != NULL || mFuncXi2 != NULL );
+  if( mFunction != NULL ) {
+    ASSERT( mFunction->NVar() == mNVar );
+    ASSERT( mData->NVar() == mNVar );
+  }
+  ASSERT( mNParFree > 0 && mNParFree <= mNPar );
+  ASSERT( mNParBound >= 0 && mNParBound <= mNPar );
+  ASSERT( mNParFree <= mData->NDataGood() );
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::Set_Bound_C_D(int i)
+// C = (min+max)/2
+// D = (max-min)/Pi
+{
+  // ASSERT(i>=0 && i<mNPar);
+ C(i) = D(i) = 0.;
+ if( !boundParam[i] || fixParam[i] ) return;
+ C(i) = (maxParam(i)+minParam(i))/2.;
+ D(i) = (maxParam(i)-minParam(i))/M_PI;
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::Set_Bound_C_D()
+{
+ for(int i=0;i<mNPar;i++) Set_Bound_C_D(i);
+ if(debugLevel>= 2) {
+   cout<<"Set_Bound_C_D: C=\n";
+   cout<<C;
+   cout<<"Set_Bound_C_D: D=\n";
+   cout<<D;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+double GeneralFit::p_vers_tr(int i,double p)
+// tr = tan( (p-C)/D )
+{
+ // ASSERT(i>=0 && i<mNPar);
+ double tr = p;
+ if(boundParam[i]) tr = tan((p-C(i))/D(i));
+ return(tr);
+}
+
+//////////////////////////////////////////////////////////////////////
+Vector GeneralFit::p_vers_tr(Vector const& p)
+{
+ Vector tr(p);
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] || ! boundParam[i] ) continue;
+   tr(i) = p_vers_tr(i,p(i));
+ }
+ return(tr);
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::p_vers_tr(Vector const& p,Vector& tr)
+{
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] ) continue;
+   if( ! boundParam[i] ) tr(i) = p(i);
+     else tr(i) = tan((p(i)-C(i))/D(i));
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+double GeneralFit::tr_vers_p(int i,double tr)
+// p = C+D*atan(tr)
+{
+ // ASSERT(i>=0 && i<mNPar);
+ double p = tr;
+ if(boundParam[i]) p = C(i)+D(i)*atan(tr);
+ return(p);
+}
+
+//////////////////////////////////////////////////////////////////////
+Vector GeneralFit::tr_vers_p(Vector const& tr)
+{
+ Vector p(tr);
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] || ! boundParam[i] ) continue;
+   p(i) = tr_vers_p(i,tr(i));
+ }
+ return(p);
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::tr_vers_p(Vector const& tr,Vector& p)
+{
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] ) continue;
+   if( ! boundParam[i] ) p(i) = tr(i);
+     else p(i) = C(i)+D(i)*atan(tr(i));
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+double GeneralFit::c_dp_vers_dtr(int i,double tr)
+// dtr = (1+tr**2)/D * dp = (1+tan( (p-C)/D )**2)/D * dp = coeff * dp
+// attention: df/dp = (1+tr**2)/D * dF/dtr = coeff * dF/dtr
+{
+ // ASSERT(i>=0 && i<mNPar);
+ double coeff = 1.;
+ if(boundParam[i]) coeff = (1.+tr*tr)/D(i);
+ return(coeff);
+}
+
+//////////////////////////////////////////////////////////////////////
+Vector GeneralFit::dp_vers_dtr(Vector const& dp,Vector const& tr)
+{
+ Vector dtr(dp);
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] || ! boundParam[i] ) continue;
+   dtr(i) *= c_dp_vers_dtr(i,tr(i));
+ }
+ return(dtr);
+}
+
+//////////////////////////////////////////////////////////////////////
+void GeneralFit::dp_vers_dtr(Vector const& dp,Vector const& tr,Vector& dtr)
+{
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] ) continue;
+   if( ! boundParam[i] ) dtr(i) = dp(i);
+     else dtr(i) = (1.+tr(i)*tr(i))/D(i) * dp(i);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+double GeneralFit::c_dtr_vers_dp(int i,double tr)
+// dp = D/(1+tr**2) * dtr = coeff * dtr
+// attention: df/dtr = D/(1+tr**2) * dF/dp = coeff * dF/dp
+{
+  // ASSERT(i>=0 && i<mNPar);
+ double coeff = 1.;
+ if(boundParam[i]) coeff = D(i)/(1.+tr*tr);
+ return(coeff);
+}
+
+//////////////////////////////////////////////////////////////////////
+Vector GeneralFit::dtr_vers_dp(Vector const& dtr,Vector const& tr)
+{
+ Vector dp(dtr);
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] || ! boundParam[i] ) continue;
+   dp(i) *= c_dtr_vers_dp(i,tr(i));
+ }
+ return(dp);
+}
+
+//////////////////////////////////////////////////////////////////////
+// inline fonction pour aller + vite dans le try()
+//void GeneralFit::dtr_vers_dp(Vector const& dtr,Vector const& tr,Vector& dp)
+
+//////////////////////////////////////////////////////////////////////
+int GeneralFit::put_in_limits_for_deriv(Vector const& p,Vector& dp,double dist)
+// 1-/ Redefinit dp pour qu'il soit superieur a minStepDeriv
+// 2-/ Redefinit dp pour que p+/-dp reste dans les limites (parametre borne)
+// Si hors limites alors:
+//     p-dp <= min_p : dp = (p-min_p)*dist
+//     p+dp >= max_p : dp = (max_p-p)*dist
+{
+ int nchanged = 0;
+ bool changed;
+ double dp_old;
+
+ for(int i=0;i<mNPar;i++) {
+   if( fixParam[i] ) {dp(i)=0.; continue;} // Pas calcul derivee pour param fixe
+
+   if( fabs(dp(i))<minStepDeriv(i) ) {
+     // On ne redefinit dp que si minStepDeriv>0.
+     dp_old = dp(i);
+     if(dp(i)>=0.) dp(i) = minStepDeriv(i); else dp(i) = -minStepDeriv(i);
+     if(debugLevel>=2)
+       cout<<"put_in_limits_for_deriv(range) dp["<<i<<"]=abs("<<dp_old
+           <<") <"<<minStepDeriv(i)<<" changed to "<<dp(i)<<endl;
+   }
+
+   if( !boundParam[i] ) continue;
+
+   changed = false;
+   if( p(i)-dp(i)<=minParam(i) ) {
+     dp_old = dp(i);
+     dp(i) = dist*(p(i)-minParam(i));
+     changed = true;
+     if(debugLevel>=2)
+       cout<<"put_in_limits_for_deriv(min) p["<<i<<"}="<<p(i)<<" >="
+           <<minParam(i)<<" .. dp="<<dp_old<<" -> dp="<<dp(i)<<endl;
+   }
+
+   if( p(i)+dp(i)>=maxParam(i) ) {
+     dp_old = dp(i);
+     dp(i) = dist*(maxParam(i)-p(i));
+     changed = true;
+     if(debugLevel>=2)
+       cout<<"put_in_limits_for_deriv(max) p["<<i<<"]="<<p(i)<<" <="
+           <<maxParam(i)<<" .. dp="<<dp_old<<" -> dp="<<dp(i)<<endl;
+   }
+
+   if(changed) nchanged++;
+ }
+
+ return nchanged;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Rappel des inline functions pour commentaires
+//++
+// inline double   GetChi2()
+//	Retourne le Chi2
+//--
+//++
+// inline double   GetChi2Red() const
+//	Retourne le Chi2 reduit
+//--
+//++
+// inline int      GetNddl()    const
+//	Retourne le nombre de degres de liberte
+//--
+//++
+// inline int      GetNStep()   const
+//	Retourne le nombre d'iterations
+//--
+//++
+// inline int      GetNVar()    const
+//	Retourne le nombre de variables
+//--
+//++
+// inline int      GetNPar()    const
+//	Retourne le nombre de parametres
+//--
+//++
+// inline int      GetNFree()   const
+//	Retourne le nombre de parametres libres
+//--
+//++
+// inline int      GetNBound()  const
+//	Retourne le nombre de parametres bornes
+//--
+//++
+// inline int      GetNStop()   const
+//	Retourne le nstop de convergence
+//--
+//++
+// inline int      GetNStopLent()   const
+//	Retourne le nstop de convergence lente.
+//--
+//++
+// inline double   GetEps(int i)
+//	Retourne la precision de convergence pour le parametre i.
+//--
+//++
+// inline GeneralFunction*  GetFunction()
+//	Retourne le pointeur sur la GeneralFunction utilisee.
+//--
+//++
+// inline GeneralFitData*   GetGData()
+//	Retourne le pointeur sur la GeneralFitData utilisee.
+//--
Index: /tags/V_Fev00/SophyaLib/NTools/generalfit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/generalfit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/generalfit.h	(revision 752)
@@ -0,0 +1,232 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef GENERALFIT_SEEN
+#define GENERALFIT_SEEN
+
+#include "pexceptions.h"
+#include "tvector.h"
+#include "generaldata.h"
+
+namespace SOPHYA {
+
+//================================================================
+// GeneralFunction
+//================================================================
+
+class GeneralFunction {
+public:
+  GeneralFunction(unsigned int nVar, unsigned int nPar);
+  virtual ~GeneralFunction();
+
+  virtual double Value(double const xp[], double const* parm)=0;
+  virtual double Val_Der(double const xp[], double const* parm
+                        , double* DgDpar);
+
+  void SetDeltaParm(int numPar, double delta=0.);
+  void SetDeltaParm(double const* dparam);
+
+  inline int     NVar() const {return mNVar;}
+  inline int     NPar() const {return mNPar;}
+
+protected:
+  const int mNVar;  // nombre de variables f(x,y,z,...)
+  const int mNPar;  // nombre de parametres
+
+  double *deltaParm;
+  double *tmpParm;
+};
+
+//================================================================
+// GeneralFunc
+//================================================================
+
+class GeneralFunc : public GeneralFunction {
+public:
+  GeneralFunc(unsigned int nvar, unsigned int npar
+        ,double (*fun)(double const*,double const*) 
+        ,double (*funder)(double const*, double const*, double*)=NULL);
+  virtual ~GeneralFunc();
+
+  virtual double Value(double const xp[], double const* Par);
+  virtual double Val_Der(double const xp[],double const* parm
+                        , double* DgDpar);
+
+protected:
+  double (*tmpFun)   (double const*, double const*);
+  double (*tmpFunDer)(double const*, double const*, double*);
+};
+
+//================================================================
+// GeneralXi2
+//================================================================
+
+class GeneralFitData;
+
+class GeneralXi2 {
+public:
+  GeneralXi2(unsigned int nPar);
+  virtual ~GeneralXi2();
+
+  virtual double Value(GeneralFitData& data, double* parm, int& ndataused)=0;
+  virtual double Derivee(GeneralFitData& data, int i, double* parm);
+  virtual double Derivee2(GeneralFitData& data, int i,int j, double* parm);
+
+  void SetDeltaParm(int numPar, double delta=0.);
+  void SetDeltaParm(double const* dparam);
+
+  inline int     NPar() const {return mNPar;}
+
+protected:
+  const int mNPar;  // nombre de parametres
+
+  double *deltaParm;
+};
+
+//================================================================
+// GENERALFIT
+//================================================================
+
+class GeneralFit {
+public:
+  GeneralFit(GeneralFunction* f);
+  GeneralFit(GeneralXi2* f);
+  ~GeneralFit();
+
+  void            WriteStep(char *filename = NULL);
+  void            SetDebug(int level = 0);
+  void            SetMaxStep(int n = 100);
+  void            SetLambda_Fac(double fac = 10.);
+  void            SetStopChi2(double s = 0.01);
+  void            SetEps(double ep = 1.e-8);
+  void            SetEps(int n,double ep = 1.e-8);
+  void            SetStopMx(int nstopmx = 3, double stopchi2 = -1.);
+  void            SetStopLent(int nstoplent = 3);
+  void            SetFunction(GeneralFunction*);
+  void            SetFuncXi2(GeneralXi2*);
+  void            SetData(GeneralFitData*);
+  void            SetParam(int n,double value, double step
+                          ,double min=1., double max=-1.);
+  void            SetParam(int n,string const&
+                          ,double value, double step
+                          ,double min=1., double max=-1.);
+  void            SetParam(int n,double value);
+  void            SetStep(int n,double value);
+  void            SetMinStepDeriv(int i,double val = 0.);
+  void            SetMinStepDeriv(double val = 0.);
+  void            SetBound(int n,double min,double max);
+  void            SetBound(int n);
+  void            SetUnBound(int n);
+  void            SetUnBound();
+  void            SetFix(int n,double v);
+  void            SetFix(int n);
+  void            SetFree(int n);
+  void            SetFree();
+
+  double          GetParm(int);
+  Vector          GetParm();
+  double          GetParmErr(int);
+  double          GetCoVar(int,int);
+  double          GetStep(int n);
+  double          GetMax(int n);
+  double          GetMin(int n);
+  inline double   GetChi2()    const {return Chi2;};
+  inline double   GetChi2Red() const {
+                        if(mNddl<=0) return (double) mNddl;
+                        return Chi2/(double) mNddl;
+                                     };
+  inline double   GetEps(int i) const {return Eps(i);};
+  inline int      GetNddl()    const {return mNddl;};
+  inline int      GetNStep()   const {return nStep;};
+  inline int      GetNVar()    const {return mNVar;};
+  inline int      GetNPar()    const {return mNPar;};
+  inline int      GetNFree()   const {return mNParFree;};
+  inline int      GetNBound()  const {return mNParBound;};
+  inline int      GetNStop()   const {return nStop;};
+  inline int      GetNStopLent()   const {return nStopLent;};
+  inline GeneralFunction*  GetFunction() const {return mFunction;};
+  inline GeneralFitData*   GetGData() const {return mData;};
+
+  void            PrintStatus();
+  void            PrintFit();
+  void            PrintParm(int n);
+  void            PrintParm();
+
+  int             Fit();
+  double          ReCalChi2(int& nddl, double* par = NULL);
+  GeneralFitData  DataResidus(bool clean=true);
+  GeneralFitData  DataFunction(bool clean=true);
+  void            PrintFitErr(int rc);
+
+protected:
+  int             mNtry;       // numero d'appel de la routine de fit.
+  int             mNVar;       // nombre de variables f(x,y,z,...)
+  int             mNPar;       // nombre de parametres
+  int             mNParFree;   // nombre de parametres libres
+  int             mNParBound;  // nombre de parametres bornes
+  GeneralFunction*  mFunction;
+  GeneralXi2*       mFuncXi2;
+  GeneralFitData*   mData;
+
+  Vector          Param;
+  Vector          errParam;
+  Vector          stepParam;
+  Vector          minParam;
+  Vector          maxParam;
+  Vector          minStepDeriv;
+  Vector          Eps;
+  unsigned short int* fixParam;
+  unsigned short int* boundParam;
+  string*             nameParam;
+  
+  double          Lambda_Fac;
+  double          stopChi2;
+  int             maxStep;
+  int             nStopMx;
+  double          stopChi2SMx;
+  int             nStopLent;
+  int             debugLevel;
+  FILE            *FileStep;
+  
+  Matrix          ATGA;
+  Vector          BETA;
+  Matrix          ATGA_Try;
+  Vector          BETA_Try;
+  Vector          C;
+  Vector          D;
+  
+  double          Chi2;
+  int             mNddl;
+  int             nStep;
+  int             nStop, nStopL;
+  double          Lambda;
+  
+  // Fonctions privees
+  void       write_in_step(double ci2,Vector& par);
+  void       General_Init(void);
+  void       TryFunc(Vector& par,Vector& par_tr);
+  void       TryXi2(Vector& par,Vector& par_tr);
+  void       CheckSanity();
+  void       Set_Bound_C_D(int i);
+  void       Set_Bound_C_D();
+  double     p_vers_tr(int i,double p);
+  Vector     p_vers_tr(Vector const& p);
+  void       p_vers_tr(Vector const& p,Vector& tr);
+  double     tr_vers_p(int i,double tr);
+  Vector     tr_vers_p(Vector const& tr);
+  void       tr_vers_p(Vector const& tr,Vector& p);
+  double     c_dp_vers_dtr(int i,double tr);
+  Vector       dp_vers_dtr(Vector const& dp,Vector const& tr);
+  void         dp_vers_dtr(Vector const& dp,Vector const& tr,Vector& dtr);
+  double     c_dtr_vers_dp(int i,double tr);
+  Vector       dtr_vers_dp(Vector const& dtr,Vector const& tr);
+  int        put_in_limits_for_deriv(Vector const& p,Vector& dp,double dist=0.66);
+  inline void dtr_vers_dp(Vector const& dtr,Vector const& tr,Vector& dp)
+              {  for(int i=0;i<mNPar;i++)
+                   { if( fixParam[i] ) continue;
+                     if( ! boundParam[i] ) dp(i) = dtr(i);
+                       else dp(i) = D(i)/(1.+tr(i)*tr(i)) * dtr(i); }
+              };
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/hbook.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/hbook.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/hbook.h	(revision 752)
@@ -0,0 +1,83 @@
+/* link to hbook     */
+/*      CMV  94      */
+
+#ifndef HBOOK_H_SEEN
+#define HBOOK_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void hbandx_(int_4 *,float *,float *,float *);
+void hbandy_(int_4 *,float *,float *,float *);
+
+void hbarx_(int_4 *);
+void hbary_(int_4 *);
+
+void hbfun1_(int_4 *,char *,int_4 *,float *,float *,float fun(float *),int_4);
+void hbfun2_(int_4 *,char *,int_4 *,float *,float *,int_4 *,float *,float *
+            ,float fun(float *,float *),int_4);
+void hbigbi_(int_4 *,int_4 *);
+void hbook1_(int_4 *,char *,int_4 *,float *,float *,float *,int_4);
+void hbook2_(int_4 *,char *,int_4 *,float *,float *
+            ,int_4 *,float *,float *,float *,int_4);
+void hbpro_(int_4 *,float *);
+void hbprof_(int_4 *,char *,int_4 *,float *,float *
+            ,float *,float *,char *,int_4,int_4);
+void hbprox_(int_4 *,float *);
+void hbproy_(int_4 *,float *);
+void hbslix_(int_4 *,int_4 *,float *);
+void hbsliy_(int_4 *,int_4 *,float *);
+void hcdir_(char *,char *,int_4,int_4);
+void hdelet_(int_4 *);
+void hfill_(int_4 *,float *,float *,float *);
+void hfithn_(int_4 *,char *,char *,int_4 *,float *
+            ,float *,float *,float *,float *,float *,int_4,int_4);
+void hfn_(int_4 *,float *);
+void hfunc_(int_4 *,float fun(float *));
+void hgive_(int_4 *,char *,int_4 *,float *,float *
+                          ,int_4 *,float *,float *,int_4 *,int_4 *);
+void hgn_(int_4 *,int_4 *,int_4 *,float *,int_4 *);
+void hgnf_(int_4 *,int_4 *,float *,int_4 *);
+void hgnpar_(int_4 *,char *,int_4);
+float hi_(int_4 *,int_4 *);
+void hidopt_(int_4 *,char *,int_4);
+float hie_(int_4 *,int_4 *);
+float hif_(int_4 *,int_4 *);
+float hij_(int_4 *,int_4 *,int_4 *);
+void hijxy_(int_4 *,int_4 *,int_4 *,float *,float *);
+void hix_(int_4 *,int_4 *,float *);
+void hldir_(char *,char *,int_4,int_4);
+void hmdir_(char *,char *,int_4,int_4);
+float hmax_(int_4 *);
+void hmaxim_(int_4 *,float *);
+float hmin_(int_4 *);
+void hminim_(int_4 *,float *);
+void hnorma_(int_4 *,float *);
+void hnoent_(int_4 *,int_4 *);
+void hpak_(int_4 *,float *);
+void hpake_(int_4 *,float *);
+void hprint_(int_4 *);
+void hrend_(char *,int_4);
+void hrin_(int_4 *,int_4 *,int_4 *);
+float hrndm1_(int_4 *);
+void hrndm2_(int_4 *,float *,float *);
+void hropen_(int_4 *,char *,char *,char *,int_4 *,int_4 *,int_4,int_4,int_4);
+void hrout_(int_4 *,int_4 *,char *,int_4);
+void hscale_(int_4 *,float *);
+float hstati_(int_4 *,int_4 *,char *,int_4 *,int_4);
+float hsum_(int_4 *);
+void hunpak_(int_4 *,float *,char *,int_4 *,int_4);
+void hunpke_(int_4 *,float *,char *,int_4 *,int_4);
+float hx_(int_4 *,float *);
+float hxe_(int_4 *,float *);
+float hxi_(int_4 *,float *,int_4 *);
+float hxyij_(int_4 *,float *,float *,int_4 *,int_4 *);
+float hxy_(int_4 *,float *,float *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/hisprof.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/hisprof.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/hisprof.cc	(revision 752)
@@ -0,0 +1,372 @@
+#include "machdefs.h"
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include "hisprof.h"
+#include "perrors.h"
+
+//++
+// Class	HProf
+// Lib	Outils++ 
+// include	hisprof.h
+//
+//	Classe de profil d'histogrammes.
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+/********* Methode *********/
+//++
+HProf::HProf()
+//
+//	Constructeur par defaut.
+//--
+: Histo()
+, SumY(NULL), SumY2(NULL), SumW(NULL), Ok(false), YMin(1.), YMax(-1.), Opt(0)
+{
+ END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+//++
+HProf::HProf(float xMin, float xMax, int nBin, float yMin, float yMax)
+//
+//	Constructeur. Histogramme de profil de ``nBin'' bins entre ``xMin''
+//	et ``xMax'' avec coupure d'acceptance sur y entre ``yMin'' et ``yMax''.
+//	Si yMin>=yMax alors pas de coupure d'acceptance sur y.
+//	Par defaut l'erreur du profil represente la dispersion dans le bin,
+//	SetErrOpt(1) permet de demander de calculer l'erreur sur la moyenne.
+//--
+: Histo(xMin,xMax,nBin)
+, SumY(new double[nBin]), SumY2(new double[nBin]), SumW(new double[nBin])
+, Ok(false), YMin(yMin), YMax(yMax), Opt(0)
+{
+  Histo::Errors();
+  Zero();
+  END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+//++
+HProf::HProf(const HProf& H)
+//
+//	Constructeur par copie.
+//--
+: Histo(H)
+, SumY(new double[H.bins]), SumY2(new double[H.bins]), SumW(new double[H.bins])
+, Ok(H.Ok), YMin(H.YMin), YMax(H.YMax), Opt(H.Opt)
+{
+  memcpy(SumY,  H.SumY,  bins*sizeof(double));
+  memcpy(SumY2, H.SumY2, bins*sizeof(double));
+  memcpy(SumW,  H.SumW,  bins*sizeof(double));
+  END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+void HProf::Delete()
+{
+  if( SumY  != NULL ) { delete[] SumY;  SumY = NULL;}
+  if( SumY2 != NULL ) { delete[] SumY2; SumY2 = NULL;}
+  if( SumW  != NULL ) { delete[] SumW;  SumW = NULL;}
+  Ok = false;
+}
+
+/********* Methode *********/
+HProf::~HProf()
+{
+Delete();
+}
+
+//++
+// Titre	Methodes
+//--
+
+/********* Methode *********/
+//++
+void HProf::Zero()
+//
+//	Remise a zero
+//--
+{
+  memset(SumY,  0, bins*sizeof(double));
+  memset(SumY2, 0, bins*sizeof(double));
+  memset(SumW,  0, bins*sizeof(double));
+  Ok = false;
+  Histo::Zero();
+}
+
+/********* Methode *********/
+//++
+void HProf::SetErrOpt(bool spread)
+//
+//	Pour changer l'option de calcul de l'erreur du profile.
+//	Si ``spread'' = true alors l'erreur represente la dispersion
+//	des donnees dans le bin, si = false elle represente l'erreur
+//	sur la moyenne du bin.
+//| - Pour le bin (j):
+//| H(j) = sum(y), E(j) = sum(y^2), L(j) = sum(w)
+//| ->  s(j) = sqrt(E(j)/L(j) - (H(j)/L(j))^2)  dispersion
+//| ->  e(j) = s(j)/sqrt(L(j)) erreur sur la moyenne
+//| spread=true:  opt=0 : dispersion des donnees dans le bin = s(j)
+//| spread=false: opt=1 : erreur sur la moyenne du bin = e(j)
+//--
+{
+int opt = (spread) ? 0 : 1;
+if(opt!=Opt) {Opt=opt; Ok=false;}
+}
+
+/********* Methode *********/
+//++
+void HProf::UpdateHisto() const
+//
+//	Pour mettre a jour l'histogramme de profil.
+//	Il est important d'appeler cette methode si on veut
+//	utiliser les methodes de la classe Histo qui ne sont
+//	pas redefinies dans la classe HProf.
+//	En effet, pour des raisons de precision la classe
+//	HProf travaille avec des tableaux en double precision
+//	et seulement au moment ou l'on a besoin de l'histogramme
+//	ce dernier est rempli avec les valeurs demandees (moyenne
+//	et dispersion/erreur sur la moyenne).
+//--
+{
+
+float m,e2;
+for(int i=0;i<bins;i++) {
+  if(SumW[i]<=0.) {
+    m = e2 = 0.;
+  } else {
+    m  = SumY[i]/SumW[i];
+    e2 = SumY2[i]/SumW[i] - m*m;
+    if(Opt) e2 /= SumW[i];
+  }
+  data[i] = m;
+  err2[i] = e2;
+}
+// Attention, a cause de "WriteSelf const" UpdateHisto doit etre "const".
+// Comme on veut modifier Ok, on est oblige de faire cette entourloupe:
+HProf *buff = (HProf *) this;
+buff->Ok = true;
+}
+
+/********* Methode *********/
+//++
+void HProf::Add(float x, float y, float w)
+//
+//	Addition au contenu de l'histo pour abscisse x de la valeur y et poids w
+//--
+{
+  if(YMax>YMin && (y<YMin || YMax<y)) return;
+  int numBin = FindBin(x);
+  if (numBin<0) under += w;
+  else if (numBin>=bins) over += w;
+  else {
+    Ok = false;
+    SumY[numBin]  += y;
+    SumY2[numBin] += y*y;
+    SumW[numBin]  += w;
+    nHist += w;
+    nEntries++;
+  }
+}
+
+/********* Methode *********/
+//++
+void HProf::AddBin(int numBin, float y, float w)
+//
+//	Addition au contenu de l'histo bin numBin de la valeur y poids w
+//--
+{
+  if(YMax>YMin && (y<YMin || YMax<y)) return;
+  if (numBin<0) under += w;
+  else if (numBin>=bins) over += w;
+  else {
+    Ok = false;
+    SumY[numBin]  += y;
+    SumY2[numBin] += y*y;
+    SumW[numBin]  += w;
+    nHist += w;
+    nEntries++;
+  }
+}
+
+/********* Methode *********/
+//++
+HProf& HProf::operator = (const HProf& h)
+//
+//--
+{
+if(this == &h) return *this;
+if( h.bins > bins ) Delete();
+Histo *hthis = (Histo *) this;
+*hthis = (Histo) h;
+if(!SumY)  SumY  = new double[bins];
+if(!SumY2) SumY2 = new double[bins];
+if(!SumW)  SumW  = new double[bins];
+memcpy(SumY,  h.SumY,  bins*sizeof(double));
+memcpy(SumY2, h.SumY2, bins*sizeof(double));
+memcpy(SumW,  h.SumW,  bins*sizeof(double));
+Ok = h.Ok;
+YMin = h.YMin;
+YMax = h.YMax;
+Opt = h.Opt;
+
+return *this;
+}
+
+/********* Methode *********/
+//++
+HProf& HProf::operator += (const HProf& a)
+//
+//	Attention dans cette addition il n'y a pas de gestion
+//	des YMin et YMax. L'addition est faite meme si les limites
+//	en Y de ``a'' sont differentes de celles de ``this''.
+//--
+{
+if(bins!=a.bins) THROW(sizeMismatchErr);
+Histo *hthis = (Histo *) this;
+*hthis += (Histo) a;
+for(int i=0;i<bins;i++) {
+  SumY[i]  += a.SumY[i];
+  SumY2[i] += a.SumY2[i];
+  SumW[i]  += a.SumW[i];
+}
+Ok = false;
+
+return *this;
+}
+
+/********* Methode *********/
+//++
+HProf operator + (const HProf& a, const HProf& b)
+//
+//	Meme commentaire que pour l'operateur +=
+//--
+{
+if (b.NBins()!=a.NBins()) THROW(sizeMismatchErr);
+HProf c(a);
+return (c += b);
+}
+
+// Rappel des inlines functions pour commentaires
+//++
+//   inline Histo GetHisto()
+//	Retourne l'histogramme de profil.
+//--
+//++
+// inline void GetMean(Vector& v)
+//	Retourne le contenu de la moyenne dans le vecteur v
+//--
+//++
+// inline void GetError2(Vector& v)
+//	Retourne le contenu au carre de la dispersion/erreur dans le vecteur v
+//--
+//++
+// inline float operator()(int i) const
+//	Retourne le contenu du bin i
+//--
+//++
+// inline float Error2(int i) const
+//	Retourne le carre de la dispersion/erreur du bin i
+//--
+//++
+// inline float Error(int i) const
+//	Retourne la dispersion/erreur du bin i
+//--
+//++
+// inline int Fit(GeneralFit& gfit)
+//	Fit du profile par ``gfit''.
+//--
+//++
+// inline Histo* FitResidus(GeneralFit& gfit)
+//	Retourne l'Histogramme des residus par ``gfit''.
+//--
+//++
+// inline Histo* FitFunction(GeneralFit& gfit)
+//	Retourne l'Histogramme de la fonction fittee par ``gfit''.
+//--
+//++
+// inline void Print(int dyn,float hmin,float hmax,int pflag,int il,int ih)
+//	Print, voir detail dans Histo::Print
+//--
+
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+
+void ObjFileIO<HProf>::ReadSelf(PInPersist& is)
+{
+char strg[256];
+
+if(dobj==NULL) dobj=new HProf;
+  else         dobj->Delete();
+
+// Lecture entete
+is.GetLine(strg,255);
+
+// Ecriture des valeurs
+is.Get(dobj->bins);
+is.Get(dobj->YMin);
+is.Get(dobj->YMax);
+is.Get(dobj->Opt);
+dobj->Ok = true;
+
+// Ecriture des donnees propres a l'histogramme de profil.
+is.GetLine(strg,255);
+dobj->SumY  = new double[dobj->bins];
+dobj->SumY2 = new double[dobj->bins];
+dobj->SumW  = new double[dobj->bins];
+is.Get(dobj->SumY,  dobj->bins);
+is.Get(dobj->SumY2, dobj->bins);
+is.Get(dobj->SumW,  dobj->bins);
+
+// Ecriture de l'histogramme
+is >> (Histo&)(*dobj);
+return;
+}
+
+void ObjFileIO<HProf>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+char strg[256];
+
+dobj->UpdateHisto();
+
+// Ecriture entete pour identifier facilement
+sprintf(strg,"HProf: YMin=%f  YMax=%f  Opt=%1d",dobj->YMin,dobj->YMax,dobj->Opt);
+os.PutLine(strg);
+
+// Ecriture des valeurs
+os.Put(dobj->bins);
+os.Put(dobj->YMin);
+os.Put(dobj->YMax);
+os.Put(dobj->Opt);
+
+// Ecriture des donnees propres a l'histogramme de profil.
+sprintf(strg,"HProf: SumY SumY2 SumW");
+os.PutLine(strg);
+os.Put(dobj->SumY,  dobj->bins);
+os.Put(dobj->SumY2, dobj->bins);
+os.Put(dobj->SumW,  dobj->bins);
+
+// Ecriture de l'histogramme
+// FIO_Histo fio_h((Histo&)*dobj);
+// fio_h.Write(os);
+os << (Histo&)(*dobj);
+
+return;
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<HProf>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<HProf>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/hisprof.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/hisprof.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/hisprof.h	(revision 752)
@@ -0,0 +1,78 @@
+#ifndef HISPROF_SEEN
+#define HISPROF_SEEN
+
+#include <stdio.h>
+#include "peida.h"
+#include "tvector.h"
+#include "ppersist.h"
+#include "histos.h"
+
+namespace SOPHYA {
+
+class HProf : public Histo {
+  friend class ObjFileIO<HProf>;
+public:
+
+  // CREATOR / DESTRUCTOR
+  HProf();
+  HProf(float xMin, float xMax, int nBin=100, float yMin=1., float yMax=-1.);
+  HProf(const HProf& H);
+  virtual ~HProf();
+
+  // UPDATING or SETTING
+  void   Zero();
+  void   UpdateHisto() const;
+  void   SetErrOpt(bool spread = true);
+  void   Add(float x, float y, float w = 1.);
+  void   AddBin(int numBin, float y, float w = 1.);
+  
+  // Acces a l information
+  inline Histo GetHisto() {if(!Ok) UpdateHisto(); return (Histo) *this;}
+  inline void GetMean(Vector& v) {if(!Ok) UpdateHisto(); Histo::GetValue(v);}
+  inline void GetError2(Vector& v) {if(!Ok) UpdateHisto(); Histo::GetError2(v);}
+  inline float operator()(int i) const {if(!Ok) UpdateHisto(); return data[i];}
+  inline float Error2(int i) const {if(!Ok) UpdateHisto(); return (float) err2[i];}
+  inline float Error(int i) const
+         {if(!Ok) UpdateHisto(); return err2[i]>0. ? (float) sqrt(err2[i]) : 0.f;}
+
+  // Operators
+  HProf& operator = (const HProf& h);
+  HProf& operator += (const HProf& a);
+  friend HProf operator + (const HProf& a, const HProf& b);
+
+  // Fit
+  inline int    Fit(GeneralFit& gfit)
+         {if(!Ok) UpdateHisto(); return Histo::Fit(gfit,0);}
+  inline Histo  FitResidus(GeneralFit& gfit)
+         {if(!Ok) UpdateHisto(); return Histo::FitResidus(gfit);}
+  inline Histo  FitFunction(GeneralFit& gfit)
+         {if(!Ok) UpdateHisto(); return Histo::FitFunction(gfit);}
+
+  // Print
+  inline void Print(int dyn=100,float hmin=1.,float hmax=-1.,int pflag=0,int il=1,int ih=-1)
+                           {if(!Ok) UpdateHisto(); Histo::Print(dyn,hmin,hmax,pflag,il,ih);}
+
+protected:
+  void Delete();
+
+  double*        SumY;
+  double*        SumY2;
+  double*        SumW;
+  bool           Ok;
+  float          YMin;
+  float          YMax;
+  uint_2         Opt;
+};
+
+
+inline POutPersist& operator << (POutPersist& os, HProf & obj)
+{ ObjFileIO<HProf> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, HProf & obj)
+{ ObjFileIO<HProf> fio(&obj);  fio.Read(is);  return(is); }
+// Classe pour la gestion de persistance
+// ObjFileIO<HProf>
+
+
+} // Fin du namespace
+
+#endif // HISPROF_SEEN
Index: /tags/V_Fev00/SophyaLib/NTools/history_eros
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/history_eros	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/history_eros	(revision 752)
@@ -0,0 +1,224 @@
+NTools from Outils++
+-----------> cspline.cc
+   Repository revision:	1.5	/projects/Eros/CVSEros/CodeCxx/Outils/cspline.cc,v
+   OK                   1.5
+-----------> cspline.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/cspline.h,v
+   OK                   1.4
+-----------> cvector.cc
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/cvector.cc,v
+   OK                   1.8
+-----------> cvector.h
+   Repository revision:	1.7	/projects/Eros/CVSEros/CodeCxx/Outils/cvector.h,v
+   OK                   1.7
+-----------> datacards.cc
+   Repository revision:	1.18	/projects/Eros/CVSEros/CodeCxx/Outils/datacards.cc,v
+   OK                   1.18
+-----------> datacards.h
+   Repository revision:	1.10	/projects/Eros/CVSEros/CodeCxx/Outils/datacards.h,v
+   MAJ                  1.11   (pour namespace std de KCC)
+-----------> datatypes.cc
+   Repository revision:	1.5	/projects/Eros/CVSEros/CodeCxx/Outils/datatypes.cc,v
+   OK                   1.5
+-----------> datatypes.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/datatypes.h,v
+   OK                   1.4
+-----------> dates.cc
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Outils/dates.cc,v
+   OK                   1.11
+-----------> dates.h
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/dates.h,v
+   MAJ                  1.10
+-----------> difeq.cc
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/difeq.cc,v
+   OK                   1.9
+-----------> difeq.h
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Outils/difeq.h,v
+   OK                   1.6
+-----------> dvlist.cc
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/dvlist.cc,v
+   OK                   1.9
+-----------> dvlist.h
+   Repository revision:	1.14	/projects/Eros/CVSEros/CodeCxx/Outils/dvlist.h,v
+   MAJ                  1.16
+-----------> fct1dfit.cc
+   Repository revision:	1.7	/projects/Eros/CVSEros/CodeCxx/Outils/fct1dfit.cc,v
+   OK                   1.7
+-----------> fct1dfit.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/fct1dfit.h,v
+   OK                   1.4
+-----------> fct2dfit.cc
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/fct2dfit.cc,v
+   MAJ                  1.9
+-----------> fct2dfit.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/fct2dfit.h,v
+   OK                   1.4
+-----------> generaldata.cc
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Outils/generaldata.cc,v
+   MAJ                  1.9
+-----------> generaldata.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/generaldata.h,v
+   MAJ                  1.5
+-----------> generalfit.cc
+   Repository revision:	1.47	/projects/Eros/CVSEros/CodeCxx/Outils/generalfit.cc,v
+   MAJ                  1.51
+-----------> generalfit.h
+   Repository revision:	1.20	/projects/Eros/CVSEros/CodeCxx/Outils/generalfit.h,v
+   OK                   1.20
+-----------> hisprof.cc
+   Repository revision:	1.3	/projects/Eros/CVSEros/CodeCxx/Outils/hisprof.cc,v
+   OK                   1.3
+-----------> hisprof.h
+   Repository revision:	1.3	/projects/Eros/CVSEros/CodeCxx/Outils/hisprof.h,v
+   OK                   1.3
+-----------> histos.cc
+   Repository revision:	1.27	/projects/Eros/CVSEros/CodeCxx/Outils/histos.cc,v
+   OK                   1.27
+-----------> histos.h
+   Repository revision:	1.19	/projects/Eros/CVSEros/CodeCxx/Outils/histos.h,v
+   OK                   1.19
+-----------> histos2.cc
+   Repository revision:	1.17	/projects/Eros/CVSEros/CodeCxx/Outils/histos2.cc,v
+   MAJ                  1.19
+-----------> histos2.h
+   Repository revision:	1.15	/projects/Eros/CVSEros/CodeCxx/Outils/histos2.h,v
+   MAJ                  1.16
+-----------> integ.cc
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/integ.cc,v
+   OK                   1.8
+-----------> integ.h
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Outils/integ.h,v
+   MAJ                  1.7
+-----------> linfit.cc
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/linfit.cc,v
+   OK                   1.4
+-----------> linfit.h
+   Repository revision:	1.7	/projects/Eros/CVSEros/CodeCxx/Outils/linfit.h,v
+   OK                   1.7
+-----------> matrix.cc
+   Repository revision:	1.17	/projects/Eros/CVSEros/CodeCxx/Outils/matrix.cc,v
+   MAJ                  1.18
+-----------> matrix.h
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/matrix.h,v
+   OK                   1.8
+-----------> median.cc
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Outils/median.cc,v
+   OK                   1.1
+-----------> median.h
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Outils/median.h,v
+   OK                   1.1
+-----------> nbconst.h
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Outils/nbconst.h,v
+   MAJ                  1.7     juste un commentaire /**/ en //
+
+-----------> ntupintf.cc 
+   Repository revision: 1.3     /projects/Eros/CVSEros/CodeCxx/Outils/ntupintf.h,v
+   OK - ajoute
+-----------> ntupintf.h 
+   Repository revision: 1.4     /projects/Eros/CVSEros/CodeCxx/Outils/ntupintf.h,v
+   OK - ajoute
+-----------> ntuple.cc
+   Repository revision:	1.12	/projects/Eros/CVSEros/CodeCxx/Outils/ntuple.cc,v
+   OK                   1.19
+-----------> ntuple.h
+   MAJ                  1.15
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/ntuple.h,v
+-----------> outilsinit.cc
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/outilsinit.cc,v
+                        1.3   Ajout de XNTuple, pas fait
+-----------> outilsinit.h
+   Repository revision:	1.3	/projects/Eros/CVSEros/CodeCxx/Outils/outilsinit.h,v
+   OK                   1.3
+-----------> pclassids.h
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/pclassids.h,v
+   MAJ                  1.9     ClassId_XNTuple 
+-----------> peida.h
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/peida.h,v
+   OK                   1.4
+-----------> pemath.h
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/pemath.h,v
+   OK                   1.2
+-----------> perandom.cc
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Outils/perandom.cc,v
+   OK                   1.11
+-----------> perandom.h
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/perandom.h,v
+   OK                   1.8
+-----------> poly.cc
+   Repository revision:	1.10	/projects/Eros/CVSEros/CodeCxx/Outils/poly.cc,v
+   MAJ                  1.12
+-----------> poly.h
+   Repository revision:	1.8	/projects/Eros/CVSEros/CodeCxx/Outils/poly.h,v
+   OK                   1.8
+-----------> pversion.cc
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/pversion.cc,v
+   OK                   1.4
+-----------> pversion.h
+   Repository revision:	1.37	/projects/Eros/CVSEros/CodeCxx/Outils/pversion.h,v
+   OK                   1.42    rien a faire - numero de version
+   
+-----------> rk4cdifeq.cc
+   Repository revision:	1.4	/projects/Eros/CVSEros/CodeCxx/Outils/rk4cdifeq.cc,v
+   OK                   1.4
+-----------> rk4cdifeq.h
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/rk4cdifeq.h,v
+   OK                   1.2
+-----------> simplesort.cc
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/simplesort.cc,v
+   OK                   1.9
+-----------> simplesort.h
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Outils/simplesort.h,v
+   MAJ                  1.12    KCC std
+   
+-----------> simps2d.h
+   Repository revision:	1.1	/projects/Eros/CVSEros/CodeCxx/Outils/simps2d.h,v
+   OK                   1.1
+-----------> tabmath.cc
+   Repository revision:	1.3	/projects/Eros/CVSEros/CodeCxx/Outils/tabmath.cc,v
+   OK                   1.3
+-----------> tabmath.h
+   Repository revision:	1.2	/projects/Eros/CVSEros/CodeCxx/Outils/tabmath.h,v
+   OK                   1.2
+-----------> utils.cc
+   Repository revision:	1.9	/projects/Eros/CVSEros/CodeCxx/Outils/utils.cc,v
+   OK                   1.9
+-----------> utils.h
+   Repository revision:	1.14	/projects/Eros/CVSEros/CodeCxx/Outils/utils.h,v
+   OK                   1.15    KCC std
+-----------> xntuple.cc
+   Repository revision: 1.8     /projects/Eros/CVSEros/CodeCxx/Outils/xntuple.cc,v
+   OK
+-----------> xntuple.h
+   Repository revision: 1.6     /projects/Eros/CVSEros/CodeCxx/Outils/xntuple.h,v
+   OK
+
+NTools from Images++
+-----------> cimage.cc
+   Repository revision:	1.36	/projects/Eros/CVSEros/CodeCxx/Images/cimage.cc,v
+   MAJ                  1.38
+-----------> cimage.h
+   Repository revision:	1.22	/projects/Eros/CVSEros/CodeCxx/Images/cimage.h,v
+   OK                   1.22
+-----------> dynccd.cc
+   Repository revision:	1.20	/projects/Eros/CVSEros/CodeCxx/Images/dynccd.cc,v
+   OK                   1.20
+-----------> dynccd.h
+   Repository revision:	1.11	/projects/Eros/CVSEros/CodeCxx/Images/dynccd.h,v
+   OK                   1.11
+-----------> imageop.cc
+   Repository revision:	1.27	/projects/Eros/CVSEros/CodeCxx/Images/imageop.cc,v
+   MAJ                  1.28    NoiseFiltImage
+-----------> imageop.h
+   Repository revision:	1.17	/projects/Eros/CVSEros/CodeCxx/Images/imageop.h,v
+   MAJ                  1.18    
+-----------> rzimage.cc
+   Repository revision:	1.29	/projects/Eros/CVSEros/CodeCxx/Images/rzimage.cc,v
+   OK                   1.29
+-----------> rzimage.h
+   Repository revision:	1.13	/projects/Eros/CVSEros/CodeCxx/Images/rzimage.h,v
+   OK                   1.13
+-----------> rzvect.h
+   Repository revision:	1.6	/projects/Eros/CVSEros/CodeCxx/Images/rzvect.h,v
+   OK                   1.6
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/histos.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/histos.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/histos.cc	(revision 752)
@@ -0,0 +1,1827 @@
+//
+// $Id: histos.cc,v 1.7 1999-12-10 16:55:51 ansari Exp $
+//
+
+#include "machdefs.h"
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include "histos.h"
+#include "perrors.h"
+#include "poly.h"
+#include "strutil.h"
+#include "generalfit.h"
+
+//++
+// Class	Histo
+// Lib	Outils++ 
+// include	histos.h
+//
+//	Classe d'histogrammes 1D
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+/********* Methode *********/
+//++
+Histo::Histo()
+//
+//--
+: data(NULL), err2(NULL),
+  under(0), over(0), nHist(0), nEntries(0),
+  bins(0), min(0), max(0),
+  binWidth(0)
+{
+ END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+//++
+Histo::Histo(float xMin, float xMax, int nBin)
+//
+//--
+: data(new float[nBin]), err2(NULL),
+  under(0), over(0), nHist(0), nEntries(0),
+  bins(nBin), min(xMin), max(xMax),
+  binWidth((max - min)/nBin)
+{
+  Zero();
+  END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+//++
+Histo::Histo(const Histo& H)
+//
+//--
+: data(new float[H.bins]), err2(NULL),
+  under(H.under), over(H.over), nHist(H.nHist), nEntries(H.nEntries),
+  bins(H.bins), min(H.min), max(H.max),
+  binWidth(H.binWidth)
+{
+  memcpy(data, H.data, bins*sizeof(float));
+  if( H.err2 != NULL ) {
+    err2 = new double[bins];
+    memcpy(err2, H.err2, bins*sizeof(double));
+  }
+  END_CONSTRUCTOR
+}
+
+/********* Methode *********/
+void Histo::Delete()
+{
+  if( data != NULL ) { delete[] data; data = NULL;}
+  if( err2 != NULL ) { delete[] err2; err2 = NULL;}
+  under = over = min = max = binWidth= 0.;
+  nHist = 0.;
+  nEntries = bins = 0;
+}
+
+/********* Methode *********/
+Histo::~Histo()
+{
+Delete();
+}
+
+//++
+// Titre	Methodes
+//--
+
+/********* Methode *********/
+//++
+void Histo::Zero()
+//
+//	Remise a zero
+//--
+{
+  memset(data, 0, bins*sizeof(float));
+  under = over = 0;
+  nHist = 0;
+  nEntries = 0;
+  if( err2 != NULL ) memset(err2, 0, bins*sizeof(double));
+}
+
+/********* Methode *********/
+//++
+void Histo::Errors()
+//
+//	Pour avoir le calcul des erreurs
+//--
+{
+ if( bins > 0 ) {
+   if(err2==NULL) err2 = new double[bins];
+   memset(err2, 0, bins*sizeof(double));
+ }
+}
+
+/********* Methode *********/
+//++
+Histo& Histo::operator = (const Histo& h)
+//
+//--
+{
+  if(this == &h) return *this;
+  if( h.bins > bins ) Delete();
+  if(!data) data = new float[h.bins];
+  if( !h.err2 && err2 ) { delete [] err2; err2=NULL;}
+  if( h.err2 && !err2 ) err2 = new double[h.bins];
+
+  under = h.under;
+  over = h.over;
+  nHist = h.nHist;
+  nEntries = h.nEntries;
+  bins = h.bins;
+  min = h.min;
+  max = h.max;
+  binWidth = h.binWidth;
+  
+  memcpy(data, h.data, bins*sizeof(float));
+  if(err2) memcpy(err2, h.err2, bins*sizeof(double));
+
+  return *this;
+}
+
+/********* Methode *********/
+//++
+Histo& Histo::operator *= (double b)
+//
+//--
+{
+double b2 = b*b;
+for(int i=0;i<bins;i++) {
+  data[i] *= b;
+  if(err2) err2[i] *= b2;
+}
+under *= b;
+over *= b;
+nHist *= b;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator /= (double b)
+//
+//--
+{
+if (b==0.) THROW(inconsistentErr);
+double b2 = b*b;
+for(int i=0;i<bins;i++) {
+  data[i] /= b;
+  if(err2) err2[i] /= b2;
+}
+under /= b;
+over /= b;
+nHist /= b;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator += (double b)
+//
+//--
+{
+for(int i=0;i<bins;i++) data[i] += b;
+under += b;
+over += b;
+nHist += bins*b;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator -= (double b)
+//
+//--
+{
+for(int i=0;i<bins;i++) data[i] -= b;
+under -= b;
+over -= b;
+nHist -= bins*b;
+
+return *this;
+}
+
+/********* Methode *********/
+//++
+Histo operator * (const Histo& a, double b)
+//
+//--
+{
+  Histo result(a);
+  return (result *= b);
+}
+
+//++
+Histo operator * (double b, const Histo& a)
+//
+//--
+{
+  Histo result(a);
+  return (result *= b);
+}
+
+//++
+Histo operator / (const Histo& a, double b)
+//
+//--
+{
+  Histo result(a);
+  return (result /= b);
+}
+
+//++
+Histo operator + (const Histo& a, double b)
+//
+//--
+{
+  Histo result(a);
+  return (result += b);
+}
+
+//++
+Histo operator + (double b, const Histo& a)
+//
+//--
+{
+  Histo result(a);
+  return (result += b);
+}
+
+//++
+Histo operator - (const Histo& a, double b)
+//
+//--
+{
+  Histo result(a);
+  return (result -= b);
+}
+
+//++
+Histo operator - (double b, const Histo& a)
+//
+//--
+{
+  Histo result(a);
+  result *= -1.;
+  return (result += b);
+}
+
+/********* Methode *********/
+//++
+Histo& Histo::operator += (const Histo& a)
+//
+//--
+{
+if(bins!=a.bins) THROW(sizeMismatchErr);
+for(int i=0;i<bins;i++) {
+  data[i] += a(i);
+  if(err2 && a.err2) err2[i] += a.Error2(i);
+    else err2[i] = 0.;
+}
+under += a.under;
+over += a.over;
+nHist += a.nHist;
+nEntries += a.nEntries;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator -= (const Histo& a)
+//
+//--
+{
+if(bins!=a.bins) THROW(sizeMismatchErr);
+for(int i=0;i<bins;i++) {
+  data[i] -= a(i);
+  if(err2 && a.err2) err2[i] += a.Error2(i);
+    else err2[i] = 0.;
+}
+under -= a.under;
+over -= a.over;
+nHist -= a.nHist;
+nEntries += a.nEntries;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator *= (const Histo& a)
+//
+//--
+{
+if(bins!=a.bins) THROW(sizeMismatchErr);
+nHist = 0.;
+for(int i=0;i<bins;i++) {
+  if(err2 && a.err2)
+      err2[i] = a(i)*a(i)*err2[i] + data[i]*data[i]*a.Error2(i);
+    else err2[i] = 0.;
+  data[i] *= a(i);
+  nHist += data[i];
+}
+under *= a.under;
+over *= a.over;
+nEntries += a.nEntries;
+
+return *this;
+}
+
+//++
+Histo& Histo::operator /= (const Histo& a)
+//
+//--
+{
+if(bins!=a.bins) THROW(sizeMismatchErr);
+nHist = 0.;
+for(int i=0;i<bins;i++) {
+  if(a(i)==0.) {
+    data[i]=0.;
+    if(err2) err2[i]=0.;
+    continue;
+  }
+  if(err2 && a.err2)
+      err2[i] = (err2[i] + data[i]/a(i)*data[i]/a(i)*a.Error2(i))
+                /(a(i)*a(i));
+    else err2[i] = 0.;
+  data[i] /= a(i);
+  nHist += data[i];
+}
+if(a.under!=0.) under /= a.under; else under = 0.;
+if(a.over!=0.)  over  /= a.over;  else over  = 0.;
+nEntries += a.nEntries;
+
+return *this;
+}
+
+/********* Methode *********/
+//++
+Histo operator + (const Histo& a, const Histo& b)
+//
+//--
+{
+if (b.NBins()!=a.NBins()) THROW(sizeMismatchErr);
+Histo c(a);
+return (c += b);
+}
+
+//++
+Histo operator - (const Histo& a, const Histo& b)
+//
+//--
+{
+if (b.NBins()!=a.NBins()) THROW(sizeMismatchErr);
+Histo c(a);
+return (c -= b);
+}
+
+//++
+Histo operator * (const Histo& a, const Histo& b)
+//
+//--
+{
+if (b.NBins()!=a.NBins()) THROW(sizeMismatchErr);
+Histo c(a);
+return (c *= b);
+}
+
+//++
+Histo operator / (const Histo& a, const Histo& b)
+//
+//--
+{
+if (b.NBins()!=a.NBins()) THROW(sizeMismatchErr);
+Histo c(a);
+return (c /= b);
+}
+
+/********* Methode *********/
+//++
+void Histo::GetAbsc(Vector &v)
+//
+//	Remplissage d'un tableau avec la valeur des abscisses
+//--
+{
+v.Realloc(bins);
+for(int i=0;i<bins;i++) v(i) = BinLowEdge(i);
+return;
+}
+
+//++
+void Histo::GetValue(Vector &v)
+//
+//	Remplissage d'un tableau avec la valeur du contenu
+//--
+{
+v.Realloc(bins);
+for(int i=0;i<bins;i++) v(i) = data[i];
+return;
+}
+
+//++
+void Histo::GetError2(Vector &v)
+//
+//	Remplissage d'un tableau avec la valeur des erreurs au carre
+//--
+{
+v.Realloc(bins);
+if(!err2) {for(int i=0;i<bins;i++) v(i) = 0.; return;}
+for(int i=0;i<bins;i++) v(i) = err2[i];
+return;
+}
+
+//++
+void Histo::GetError(Vector &v)
+//
+//	Remplissage d'un tableau avec la valeur des erreurs
+//--
+{
+v.Realloc(bins);
+if(!err2) {for(int i=0;i<bins;i++) v(i) = 0.; return;}
+for(int i=0;i<bins;i++) v(i) = Error(i);
+return;
+}
+
+/********* Methode *********/
+//++
+void Histo::PutValue(Vector &v, int ierr)
+//
+//	Remplissage du contenu de l'histo avec les valeurs d'un vecteur
+//--
+{
+if(v.NElts()<bins) THROW(sizeMismatchErr);
+for(int i=0;i<bins;i++) {
+  data[i] = v(i);
+  if(err2&&ierr) err2[i] = fabs(v(i));
+}
+return;
+}
+
+//++
+void Histo::PutValueAdd(Vector &v, int ierr)
+//
+//	Addition du contenu de l'histo avec les valeurs d'un vecteur
+//--
+{
+if(v.NElts()<bins) THROW(sizeMismatchErr);
+for(int i=0;i<bins;i++) {
+  data[i] += v(i);
+  if(err2&&ierr) err2[i] += fabs(v(i));
+}
+return;
+}
+
+//++
+void Histo::PutError2(Vector &v)
+//
+//	Remplissage des erreurs au carre de l'histo avec les valeurs d'un vecteur
+//--
+{
+if(v.NElts()<bins) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(int i=0;i<bins;i++) err2[i] = v(i);
+return;
+}
+
+//++
+void Histo::PutError2Add(Vector &v)
+//
+//	Addition des erreurs au carre de l'histo avec les valeurs d'un vecteur
+//--
+{
+if(v.NElts()<bins) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(int i=0;i<bins;i++) if(v(i)>0.) err2[i] += v(i);
+return;
+}
+
+//++
+void Histo::PutError(Vector &v)
+//
+//	Remplissage des erreurs de l'histo avec les valeurs d'un vecteur
+//--
+{
+if(v.NElts()<bins) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(int i=0;i<bins;i++)
+  if(v(i)>0.) err2[i]=v(i)*v(i); else err2[i]=-v(i)*v(i);
+return;
+}
+
+/********* Methode *********/
+//++
+void Histo::Add(float x, float w)
+//
+//	Addition du contenu de l'histo pour abscisse x poids w
+//--
+{
+  int numBin = FindBin(x);
+  if (numBin<0) under += w;
+  else if (numBin>=bins) over += w;
+  else {
+    data[numBin] += w;
+    if(err2!=NULL) err2[numBin] += w*w;
+    nHist += w;
+    nEntries++;
+  }
+}
+
+/********* Methode *********/
+//++
+void Histo::AddBin(int numBin, float w)
+//
+//	Addition du contenu de l'histo bin numBin poids w
+//--
+{
+  if (numBin<0) under += w;
+  else if (numBin>=bins) over += w;
+  else {
+    data[numBin] += w;
+    if(err2!=NULL) err2[numBin] += w*w;
+    nHist += w;
+    nEntries++;
+  }
+}
+
+/********* Methode *********/
+//++
+void Histo::SetBin(float x, float w)
+//
+//	Remplissage du contenu de l'histo pour abscisse x poids w
+//--
+{
+  int numBin = FindBin(x);
+  SetBin(numBin,w);
+}
+
+/********* Methode *********/
+//++
+void Histo::SetBin(int numBin, float w)
+//
+//	Remplissage du contenu de l'histo pour numBin poids w
+//--
+{
+  if (numBin<0) under = w;
+  else if (numBin>=bins) over = w;
+  else {
+    nHist -= data[numBin];
+    data[numBin] = w;
+    nHist += w;
+  }
+}
+
+/********* Methode *********/
+//++
+void Histo::SetErr2(float x, double e2)
+//
+//	Remplissage des erreurs au carre pour abscisse x
+//--
+{
+  int numBin = FindBin(x);
+  SetErr2(numBin,e2);
+}
+
+/********* Methode *********/
+//++
+void Histo::SetErr2(int numBin, double e2)
+//
+//	Remplissage des erreurs au carre pour numBin poids
+//--
+{
+  if( err2==NULL) return;
+  if ( numBin<0 || numBin>=bins ) return;
+  err2[numBin] = e2;
+}
+
+/********* Methode *********/
+//++
+void Histo::SetErr(float x, float e)
+//
+//	Remplissage des erreurs pour abscisse x
+//--
+{
+SetErr2(x, (double) e*e);
+}
+
+/********* Methode *********/
+//++
+void Histo::SetErr(int numBin, float e)
+//
+//	Remplissage des erreurs pour numBin
+//--
+{
+SetErr2(numBin, (double) e*e);
+}
+
+/********* Methode *********/
+//++
+int Histo::IMax() const
+//
+//	Numero du bin ayant le contenu maximum
+//--
+{
+  int imx=0;
+  if(bins==1) return imx;
+  float mx=data[0];
+  for (int i=1; i<bins; i++)
+    if (data[i]>mx) {imx = i; mx=data[i];}
+  return imx;
+}
+
+/********* Methode *********/
+//++
+int Histo::IMin() const
+//
+//	Numero du bin ayant le contenu minimum
+//--
+{
+  int imx=0;
+  if(bins==1) return imx;
+  float mx=data[0];
+  for (int i=1; i<bins; i++)
+    if (data[i]<mx) {imx = i; mx=data[i];}
+  return imx;
+}
+
+/********* Methode *********/
+//++
+float Histo::VMax() const
+//
+//	Valeur le contenu maximum
+//--
+{
+  float mx=data[0];
+  if(bins==1) return mx;
+  for (int i=1;i<bins;i++) if(data[i]>mx) mx=data[i];
+  return mx;
+}
+
+/********* Methode *********/
+//++
+float Histo::VMin() const
+//
+//	Valeur le contenu minimum
+//--
+{
+  float mx=data[0];
+  if(bins==1) return mx;
+  for (int i=1;i<bins;i++) if(data[i]<mx) mx=data[i];
+  return mx;
+}
+
+/********* Methode *********/
+//++
+float Histo::Mean() const
+//
+//	Valeur moyenne
+//--
+{
+  double n = 0;
+  double sx = 0;
+  for (int i=0; i<bins; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    n += v;
+    sx += BinCenter(i)*v;
+  }
+  if(n>0.) return sx/n; else return min;
+}
+
+/********* Methode *********/
+//++
+float Histo::Sigma() const
+//
+//	Valeur du sigma
+//--
+{
+  double n = 0;
+  double sx = 0;
+  double sx2= 0;
+  for (int i=0; i<bins; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    n += v;
+    sx += BinCenter(i)*v;
+    sx2+= BinCenter(i)*BinCenter(i)*v;
+  }
+  // attention a l'erreur d'arrondi si un seul bin rempli!!
+  if( n == 0 ) return 0.;
+  sx2 = sx2/n - (sx/n)*(sx/n);
+  if( sx2>0. ) return sqrt( sx2 );
+      else return 0.;
+}
+
+/********* Methode *********/
+//++
+float Histo::MeanLH(int il,int ih) const
+//
+//	Valeur de la moyenne calculee entre les bin il et ih
+//--
+{
+  if( ih < il ) { il = 0; ih = bins-1; }
+  if( il < 0 ) il = 0;
+  if( ih >= bins ) ih = bins-1;
+  double n = 0;
+  double sx = 0;
+  for (int i=il; i<=ih; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    n += v;
+    sx += BinCenter(i)*v;
+  }
+  if(n>0.) return sx/n; else return BinLowEdge(il);
+}
+
+/********* Methode *********/
+//++
+float Histo::SigmaLH(int il,int ih) const
+//
+//	Valeur de la moyenne calculee entre les bin il et ih
+//--
+{
+  if( ih < il ) { il = 0; ih = bins - 1; }
+  if( il < 0 ) il = 0;
+  if( ih >= bins ) ih = bins - 1;
+  double n = 0;
+  double sx = 0;
+  double sx2= 0;
+  for (int i=il; i<=ih; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    n += v;
+    sx += BinCenter(i)*v;
+    sx2+= BinCenter(i)*BinCenter(i)*v;
+  }
+  if( n == 0 ) return 0.;
+  sx2 = sx2/n - (sx/n)*(sx/n);
+  if( sx2>0. ) return sqrt( sx2 );
+      else return 0.;
+}
+
+/********* Methode *********/
+//++
+float Histo::Mean(float x0, float dx) const
+//
+//	Valeur de la moyenne calculee entre x0-dx et x0+dx
+//--
+{
+  double sdata = 0;
+  double sx = 0;
+  int iMin = FindBin(x0-dx);
+  if (iMin<0) iMin = 0;
+  int iMax = FindBin(x0+dx);
+  if (iMax>bins) iMax=bins;
+  for (int i=iMin; i<iMax; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    sx += BinCenter(i)*v;
+    sdata += v;
+  }
+  if(sdata>0.) return sx/sdata; else return min;
+}
+
+/********* Methode *********/
+//++
+float Histo::Sigma(float x0, float dx) const
+//
+//	Valeur du sigma calcule entre x0-dx et x0+dx
+//--
+{
+  double sx = 0;
+  double sx2= 0;
+  double sdata = 0;
+  int iMin = FindBin(x0-dx);
+  if (iMin<0) iMin = 0;
+  int iMax = FindBin(x0+dx);
+  if (iMax>bins) iMax=bins;
+  for (int i=iMin; i<iMax; i++) {
+    double v = (data[i]>=0.) ? data[i] : -data[i];
+    sx += BinCenter(i)*v;
+    sx2+= BinCenter(i)*BinCenter(i)*v;
+    sdata += v;
+  }
+  if(sdata>0.) return sqrt( sx2/sdata - (sx/sdata)*(sx/sdata) );
+          else return 0.;
+}
+
+/********* Methode *********/
+//++
+float Histo::CleanedMean(float& sigma) const
+//
+//	Valeur de la moyenne et du sigma nettoyes
+//--
+{
+  if (!nHist) return 0;
+  // on fait ca de facon bete, on pourra raffiner apres...
+  float x0 = Mean();
+  float s  = Sigma()+binWidth;
+  
+  for (int i=0; i<3; i++) {
+    float xx0 = Mean(x0,5*s);
+    s  = Sigma(x0,5*s)+binWidth;
+    x0 = xx0;
+  }
+  sigma = s;
+  return x0;
+}
+
+/********* Methode *********/
+//++
+float Histo::CleanedMean() const
+//
+//	Valeur de la moyenne nettoyee
+//--
+{
+  if (!nHist) return 0;
+  float s=0;
+  return CleanedMean(s);
+}
+
+/********* Methode *********/
+//++
+int Histo::BinNonNul() const
+//
+//	Retourne le nombre de bins non-nul
+//--
+{
+int non=0;
+for (int i=0;i<bins;i++) if( data[i] != 0. ) non++;
+return non;
+}
+
+/********* Methode *********/
+//++
+int Histo::ErrNonNul() const
+//
+//	Retourne le nombre de bins ayant une erreur non-nulle
+//--
+{
+if(err2==NULL) return -1;
+int non=0;
+for (int i=0;i<bins;i++) if( err2[i] != 0. ) non++;
+return non;
+}
+
+/********* Methode *********/
+//++
+int Histo::BinPercent(float per) const
+//
+//	Renvoie le numero de bin tel que il y ait "per" pourcent entrees
+//	entre le bin 0 et ce bin (y compris le contenu de ce bin).
+//--
+{
+double n = nHist*per;
+double s = 0.;
+int i;
+for(i=0; i<bins; i++ ) {
+  s += data[i];
+  if( s >= n ) break;
+}
+if( i == bins ) i = bins-1;
+return i;
+}
+
+/********* Methode *********/
+//++
+int Histo::BinPercent(float x,float per,int& imin,int& imax)
+//
+//	Renvoie les numeros de bins imin,imax (0=<i<bins) tels que:
+//|    notons I = bin contenant l'abscisse x
+//|           N1 = nombre d'entrees entre bin 0 et I compris
+//|           N2 = nombre d'entrees entre bin I et bins-1 compris
+//|    imin = bin tel que nombre d'entrees entre imin et I = N1 * per
+//|    imax = bin tel que nombre d'entrees entre I et imax = N2 * per
+//|  Return: <0 si echec
+//|          min(I-imin,imax-I) si ok
+//--
+{
+imin = imax = -1;
+if( per <= 0. ) return -1;
+
+int I = FindBin(x);
+if( I<0 || I>=bins ) return -2;
+
+double N1 = 0.; for(int i=0; i<=I;   i++) N1 += data[i]; N1 *= per;
+double N2 = 0.; {for(int i=I; i<bins; i++) N2 += data[i]; N2 *= per;}
+
+double n = 0.;
+for(imin=I; imin>=0; imin--)   { n += data[imin]; if(n>=N1) break; }
+if( imin<0 ) imin = 0;
+// cout<<"I="<<I<<" imin="<<imin<<" n="<<n<<" N1="<<N1<<endl;
+
+n = 0.;
+for(imax=I; imax<bins; imax++) { n += data[imax]; if(n>=N2) break; }
+if( imax>=bins ) imax = bins-1;
+// cout<<"I="<<I<<" imax="<<imax<<" n="<<n<<" N2="<<N2<<endl;
+
+return ( imax-I > I-imin ) ? I-imin : imax-I ;
+}
+
+/********* Methode *********/
+//++
+int Histo::BinPercent(float x,float per,float& xmin,float& xmax)
+//
+//	Idem precedent mais renvoie xmin et xmax
+//--
+{
+xmin = xmax = 0.;
+int imin,imax;
+int rc = BinPercent(x,per,imin,imax);
+if( rc >= 0 ) { xmin = BinLowEdge(imin); xmax = BinHighEdge(imax); }
+return rc;
+}
+
+/********* Methode *********/
+//++
+void Histo::HInteg(float norm)
+//
+//	Remplace l'histogramme par son integrale normalise a norm:
+//	si norm <= 0 : pas de normalisation, integration seule
+//--
+{
+if(bins>1)
+  for(int i=1; i<bins; i++) {
+    data[i] += data[i-1];
+    if(err2!=NULL) err2[i] += err2[i-1];
+  }
+if( norm <= 0. ) return;
+norm /= data[bins-1];
+for(int i=0; i<bins; i++) {
+  data[i] *= norm;
+  if(err2!=NULL) err2[i] *= norm*norm;
+}
+}
+
+/********* Methode *********/
+//++
+void Histo::HDeriv()
+//
+//	Remplace l'histogramme par sa derivee
+//--
+{
+if( bins <= 1 ) return;
+float *temp = new float[bins];
+memcpy(temp, data, bins*sizeof(float));
+if(bins>=3) for(int i=1; i<bins-1; i++)
+              temp[i] = (data[i+1]-data[i-1])/(2.*binWidth);
+temp[0] = (data[1]-data[0])/binWidth;
+temp[bins-1] = (data[bins-1]-data[bins-2])/binWidth;
+memcpy(data, temp, bins*sizeof(float));
+delete [] temp;
+}
+
+/********* Methode *********/
+//++
+void Histo::HRebin(int nbinew)
+//
+//	Pour rebinner l'histogramme sur nbinew bins
+//--
+{
+  if( nbinew <= 0 ) return;
+
+  // memoraisation de l'histogramme original
+  Histo H(*this);
+
+  // Le nombre de bins est il plus grand ??
+  if( nbinew > bins ) {
+    delete [] data; data = NULL;
+    data = new float[nbinew];
+    if( err2 != NULL ) {
+      delete [] err2; err2 = NULL;
+      err2 = new double[nbinew];
+    }
+  }
+
+  // remise en forme de this
+  bins = nbinew;
+  this->Zero();
+  binWidth = (max-min)/bins;
+  // On recopie les parametres qui n'ont pas changes
+  under = H.under;
+  over  = H.over;
+
+
+  // Remplissage
+  for(int i=0;i<bins;i++) {
+    float xmi = BinLowEdge(i);
+    float xma = BinHighEdge(i);
+    int imi =  H.FindBin(xmi);
+    if( imi < 0 ) imi = 0;
+    int ima =  H.FindBin(xma);
+    if( ima >= H.bins ) ima = H.bins-1;
+    double w = 0.;
+    if( ima == imi ) {
+      w = H(imi) * binWidth/H.binWidth;
+    } else {
+      w += H(imi) * (H.BinHighEdge(imi)-xmi)/H.binWidth;
+      w += H(ima) * (xma -H.BinLowEdge(ima))/H.binWidth;
+      if( ima > imi+1 )
+          for(int ii=imi+1;ii<ima;ii++) w += H(ii);
+    }
+    AddBin(i,(float) w);
+  }
+
+}
+
+/********* Methode *********/
+//++
+int Histo::MaxiLocal(float& maxi,int& imax,float& maxn,int& imaxn)
+//
+//	Retourne le nombre de maxima locaux, la valeur du maximum (maxi)
+//	et sa position (imax), ainsi que la valeur du second maximum
+//	local (maxn) et sa position (imaxn).
+//	Attention: si un maximum a la meme valeur sur plusieurs bins
+//	consecutifs, le bin le plus a droite est pris.
+//--
+{
+int nml = 0;
+imax = imaxn = -1;
+maxi = maxn = -1.f;
+
+bool up = true;
+bool down = false;
+for(int i=0;i<bins;i++) {
+  if( !up ) if( data[i] > data[i-1] ) up = true;
+  if( up && !down ) {
+    if( i == bins-1 ) down=true;
+      else if( data[i] > data[i+1] ) down=true;
+  }
+
+  if( up && down ) {
+    nml++;
+    up = down = false;
+    if( imax < 0 ) {
+      imax = i; maxi = data[i];
+    } else if( data[i] >= maxi ) {
+      imaxn = imax; maxn = maxi;
+      imax = i; maxi = data[i];
+    } else {
+      if( imaxn < 0 || data[i] >= maxn ) { imaxn = i; maxn = data[i]; }
+    }
+  }
+
+}
+return nml;
+}
+
+/********* Methode *********/
+//++
+float Histo::FitMax(int degree, float frac, int debug) const
+//
+//	Fit de la position du maximum de l'histo par un polynome
+//	de degre `degree' a `frac' pourcent du maximum.
+//	L'histo est suppose etre remplit de valeurs positives
+//--
+{
+  if (degree < 2 || degree > 3) degree = 3;
+  if (frac <= 0. || frac >= 1.) frac = 0.5;
+
+  if (debug > 1)
+    cout<<"Histo::FitMax : Nb Entrees histo ="<<NEntries()<<endl;
+
+  if (NEntries() < 1) THROW(inconsistentErr);
+
+  int iMax = IMax();
+  float hmax = (*this)(iMax);
+  float xCenter = BinCenter(iMax);
+
+  if(debug>1)
+    cout<<"Max histo i="<<iMax<<" x="<<xCenter<<" v="<<hmax<<endl;
+
+  /* find limits at frac*hmax */
+
+  float limit = frac*hmax;
+
+  volatile int iLow = iMax;
+  while (iLow>0 && (*this)(iLow)>limit) iLow--;
+
+  volatile int iHigh = iMax;
+  while (iHigh<NBins()-1 && (*this)(iHigh)>limit) iHigh++;
+
+  int nLowHigh;
+  for(;;) {
+    nLowHigh = 0;
+    for (int i=iLow; i<=iHigh; i++) if((*this)(i)>0) {
+      if(!err2) nLowHigh++;
+        else if(Error2(i)>0.) nLowHigh++;
+    }
+    if (debug > 1) cout <<"Limites histo "<<iLow<<" - "<<iHigh
+                        <<" ("<<nLowHigh<<" non nuls)"<<endl;
+    if( nLowHigh >= degree+1 ) break;
+    iLow--;  iHigh++;
+    if(iLow<0 && iHigh>=NBins()) {
+      if (debug>1)
+        cout<<"Mode histogramme = "<<xCenter
+            <<"   BinCenter("<<iMax<<")"<<endl;
+      return xCenter;
+    }
+    if(iLow  < 0       ) iLow  = 0;
+    if(iHigh >= NBins()) iHigh = NBins()-1;
+  }
+
+  Vector xFit(nLowHigh);
+  Vector yFit(nLowHigh);
+  Vector e2Fit(nLowHigh);
+  Vector errcoef(1);
+  int ii = 0;
+  for (int j=iLow; j<=iHigh; j++) {
+    if ((*this)(j)>0) {
+      if(!err2) {
+        xFit(ii) = BinCenter(j)-xCenter;
+        yFit(ii) = (*this)(j);
+        e2Fit(ii) = yFit(ii);
+        ii++;
+      } else if(Error2(j)>0.) {
+        xFit(ii) = BinCenter(j)-xCenter;
+        yFit(ii) = (*this)(j);
+        e2Fit(ii) = Error2(j);
+        ii++;
+      }
+    }
+  }
+  if(debug>4) {
+    int k;
+    for(k=0;k<nLowHigh;k++) cout<<" "<<xFit(k);  cout<<endl;
+    for(k=0;k<nLowHigh;k++) cout<<" "<<yFit(k);  cout<<endl;
+    for(k=0;k<nLowHigh;k++) cout<<" "<<e2Fit(k); cout<<endl;
+  }
+  if( ii != nLowHigh ) THROW(inconsistentErr);
+  Poly pol(degree);
+  TRY {
+    pol.Fit(xFit, yFit, e2Fit, degree, errcoef);
+    if (debug>1) cout << "resultat fit = " << pol << endl;
+    pol.Derivate();
+  } CATCHALL {
+    THROW_SAME;
+  } ENDTRY
+
+  int DPolDeg = pol.Degre();
+  float fd = 0.;
+
+  if (DPolDeg == 0) {
+    // on est dans le cas d'un fit de droite
+    if( pol[0] > 0. ) {
+      // on a fitte une droite de pente >0.
+      fd = xFit(nLowHigh-1) + binWidth/2. + xCenter;
+    } else if( pol[0] < 0. ) {
+      // on a fitte une droite de pente <0.
+      fd = xFit(0) - binWidth/2. + xCenter;
+    } else {
+      // on a fitte une droite de pente =0. (creneau)
+      fd = (xFit(0)+xFit(nLowHigh-1))/2. + xCenter;
+    }
+  } else if (DPolDeg == 1) {
+    // on est dans le cas d'un fit de parabole
+    double r=0;
+    if (pol.Root1(r)==0) THROW(inconsistentErr);
+    fd = r + xCenter;
+  } else if (DPolDeg == 2) {
+    // on est dans le cas d'un fit de cubique
+    double r1=0;
+    double r2=0;
+    if (pol.Root2(r1,r2) == 0) THROW(inconsistentErr);
+    pol.Derivate();
+    fd = (pol(r1)<0) ? r1 + xCenter : r2 + xCenter;
+  } else {
+    // on est dans un cas non prevu
+    THROW(inconsistentErr);
+  }
+
+  if(fd>max) fd = max;
+  if(fd<min) fd = min;
+
+  if (debug>1)
+    cout << "Mode histogramme = " << fd
+         << "    (DerPol.degre =" << DPolDeg
+         << " pol.coeff[0] =" << pol[0]
+         << ")" << endl;
+
+  return fd;
+}
+
+
+/********* Methode *********/
+//++
+float Histo::FindWidth(float frac, int debug) const
+//
+//	Calcul de la largeur a frac pourcent du maximum
+//	autour du bin du maximum.
+//	L'histo est suppose etre remplit de valeurs positives
+//--
+{
+  float xmax = BinCenter( IMax() );
+  return FindWidth(xmax,frac,debug);
+}
+
+/********* Methode *********/
+//++
+float Histo::FindWidth(float xmax,float frac, int debug) const
+//
+//	Calcul de la largeur a frac pourcent de la valeur du bin xmax.
+//	L'histo est suppose etre remplit de valeurs positives
+//--
+{
+  if (frac <= 0 || frac >= 1.) frac = 0.5;
+
+  if (debug > 1)
+    cout << "Histo::FindWidth a " << frac
+         << " de xmax= " << xmax
+         << " , ndata= " << NData()
+         << " , nent= " << NEntries()
+         << " , nbin= " << NBins() << endl;
+
+  if (NEntries() < 1) THROW(inconsistentErr);
+  if (NBins() < 3) THROW(inconsistentErr);
+
+  int iMax = FindBin(xmax);
+  if (iMax<0 || iMax>=NBins()) THROW(inconsistentErr);
+  float hmax = data[iMax];
+  float limit = frac*hmax;
+  if (debug > 1)
+    cout << "  Max histo[" << iMax << "] = " << hmax
+         << ", limite " << limit << endl;
+
+  int iLow = iMax;
+  while (iLow>=0 && data[iLow]>limit) iLow--;
+  if( iLow < 0 ) iLow = 0;
+
+  int iHigh = iMax;
+  while (iHigh<NBins() && data[iHigh]>limit) iHigh++;
+  if( iHigh >=NBins() ) iHigh = NBins()-1;
+
+  float xlow   = BinCenter(iLow);
+  float ylow   = data[iLow];
+
+  float xlow1=xlow, ylow1=ylow;
+  if(iLow+1<NBins()) {
+    xlow1  = BinCenter(iLow+1);
+    ylow1  = data[iLow+1];
+  }
+
+  float xhigh  = BinCenter(iHigh);
+  float yhigh  = data[iHigh];
+
+  float xhigh1=xhigh, yhigh1=yhigh;
+  if(iHigh-1>=0) {
+    xhigh1 = BinCenter(iHigh-1);
+    yhigh1 = data[iHigh-1];
+  }
+
+  float xlpred,xhpred,wd;
+
+  if(ylow1>ylow) {
+    xlpred = xlow + (xlow1-xlow)/(ylow1-ylow)*(limit-ylow);
+    if(xlpred < xlow) xlpred = xlow;
+  } else xlpred = xlow;
+
+  if(yhigh1>yhigh) {
+    xhpred = xhigh + (xhigh1-xhigh)/(yhigh1-yhigh)*(limit-yhigh);
+    if(xhpred > xhigh) xhpred = xhigh;
+  } else xhpred = xhigh;
+
+  wd = xhpred - xlpred;
+
+  if (debug > 1) {
+    cout << "Limites histo: " << "  Width " << wd << endl;
+    cout << "  Low: [" << iLow  << "]=" << ylow << " pred-> " << xlpred
+         << " - High: [" << iHigh  << "]=" << yhigh << " pred-> " << xhpred
+         << endl;
+  }
+
+  return wd;
+}
+
+
+/********* Methode *********/
+//++
+int Histo::EstimeMax(float& xm,int SzPav)
+//
+//	Cf suivant mais im est le bin du maximum de l'histo
+//--
+{
+int im = IMax();
+return EstimeMax(im,xm,SzPav);
+}
+
+/********* Methode *********/
+//++
+int Histo::EstimeMax(int& im,float& xm,int SzPav)
+//
+//	Determine l'abscisses du maximum donne par im
+//	en moyennant dans un pave SzPav  autour du maximum
+//|  Return:
+//|     0 = si fit maximum reussi avec SzPav pixels
+//|     1 = si fit maximum reussi avec moins que SzPav pixels
+//|     2 = si fit maximum echoue et renvoit BinCenter()
+//|    -1 = si echec: SzPav <= 0 ou im hors limites
+//--
+{
+xm = 0;
+if( SzPav <= 0 ) return -1;
+if( im < 0 || im >= bins ) return -1;
+
+if( SzPav%2 == 0 ) SzPav++;
+SzPav = (SzPav-1)/2;
+
+int rc = 0;
+double dxm = 0, wx = 0;
+for(int i=im-SzPav;i<=im+SzPav;i++) {
+  if( i<0 || i>= bins ) {rc=1; continue;}
+  dxm += BinCenter(i) * (*this)(i);
+  wx  += (*this)(i);
+}
+
+if( wx > 0. ) {
+  xm = dxm/wx;
+  return rc;
+} else {
+  xm = BinCenter(im);
+  return 2;
+}
+
+}
+
+/********* Methode *********/
+//++
+void Histo::EstimeWidthS(float frac,float& widthG,float& widthD)
+//
+//	Determine la largeur a frac% du maximum a gauche (widthG)
+//	et a droite (widthD)
+//--
+{
+int i;
+widthG = widthD = -1.;
+if( bins<=1 || frac<=0. || frac>=1. ) return;
+
+int imax = 0;
+float maxi = data[0];
+for(i=1;i<bins;i++) if(data[i]>maxi) {imax=i; maxi=data[i];}
+float xmax = BinCenter(imax);
+float maxf = maxi * frac;
+
+// recherche du sigma a gauche
+widthG = 0.;
+for(i=imax;i>=0;i--) if( data[i] <= maxf ) break;
+if(i<0) i=0;
+if(i<imax) {
+  if( data[i+1] != data[i] ) {
+    widthG = BinCenter(i) + binWidth
+           * (maxf-data[i])/(data[i+1]-data[i]);
+    widthG = xmax - widthG;
+  } else widthG = xmax - BinCenter(i);
+}
+
+// recherche du sigma a droite
+widthD = 0.;
+for(i=imax;i<bins;i++) if( data[i] <= maxf ) break;
+if(i>=bins) i=bins-1;
+if(i>imax) {
+  if( data[i] != data[i-1] ) {
+    widthD = BinCenter(i) - binWidth
+           * (maxf-data[i])/(data[i-1]-data[i]);
+    widthD -= xmax;
+  } else widthD = BinCenter(i) - xmax;
+}
+
+}
+
+//////////////////////////////////////////////////////////
+//++
+int  Histo::Fit(GeneralFit& gfit,unsigned short typ_err)
+//
+//	Fit de l'histogramme par ``gfit''.
+//| typ_err = 0 :
+//|    - erreur attachee au bin si elle existe
+//|    - sinon 1
+//| typ_err = 1 :
+//|    - erreur attachee au bin si elle existe
+//|    - sinon max( sqrt(abs(bin) ,1 )
+//| typ_err = 2 :
+//|    - erreur forcee a 1
+//| typ_err = 3 :
+//|    - erreur forcee a max( sqrt(abs(bin) ,1 )
+//| typ_err = 4 :
+//|    - erreur forcee a 1, nulle si bin a zero.
+//| typ_err = 5 :
+//|    - erreur forcee a max( sqrt(abs(bin) ,1 ),
+//|      nulle si bin a zero.
+//--
+{
+if(NBins()<=0) return -1000;
+if(typ_err>5) typ_err=0;
+
+GeneralFitData mydata(1,NBins());
+
+for(int i=0;i<NBins();i++) {
+  double x = (double) BinCenter(i);
+  double f = (double) (*this)(i);
+  double saf = sqrt(fabs((double) f)); if(saf<1.) saf=1.;
+  double e;
+  if(typ_err==0)      {if(HasErrors()) e=Error(i); else e=1.;}
+  else if(typ_err==1) {if(HasErrors()) e=Error(i); else e=saf;}
+  else if(typ_err==2) e=1.;
+  else if(typ_err==3) e=saf;
+  else if(typ_err==4) e=(f==0.)?0.:1.;
+  else if(typ_err==5) e=(f==0.)?0.:saf;
+  mydata.AddData1(x,f,e);
+}
+
+gfit.SetData(&mydata);
+
+return gfit.Fit();
+}
+
+//++
+Histo Histo::FitResidus(GeneralFit& gfit)
+//
+//	Retourne une classe contenant les residus du fit ``gfit''.
+//--
+{
+if(NBins()<=0)
+  throw(SzMismatchError("Histo::FitResidus: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("Histo::FitResidus: NULL pointer\n"));
+Vector par = gfit.GetParm();
+Histo h(*this);
+for(int i=0;i<NBins();i++) {
+  double x = (double) BinCenter(i);
+  h(i) -= (float) f->Value(&x,par.Data());
+}
+return h;
+}
+
+//++
+Histo Histo::FitFunction(GeneralFit& gfit)
+//
+//	Retourne une classe contenant la fonction du fit ``gfit''.
+//--
+{
+if(NBins()<=0)
+  throw(SzMismatchError("Histo::FitFunction: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("Histo::FitFunction: NULL pointer\n"));
+Vector par = gfit.GetParm();
+Histo h(*this);
+for(int i=0;i<NBins();i++) {
+  double x = (double) BinCenter(i);
+  h(i) = (float) f->Value(&x,par.Data());
+}
+return h;
+}
+
+/********* Methode *********/
+//++
+void Histo::PrintF(FILE * fp, int hdyn,float hmin, float hmax,int pflag,
+	      int il, int ih)
+//
+//	Impression de l'histogramme dans le fichier fp
+//|   hdyn = nombre de colonnes pour imprimer les etoiles
+//|       si =0 alors defaut(100),
+//|       si <0 pas de print histo seulement infos
+//|   hmin = minimum de la dynamique
+//|   hmax = maximum de la dynamique
+//|       si hmax<=hmin           : hmin=VMin() hmax=VMax()
+//|       si hmax<=hmin et hmin=0 : hmin=0 hmax=VMax()
+//|       sinon : hmin hmax
+//|   pflag < 0 : on imprime les informations (nbin,min,...) sans l'histogramme
+//|         = 0 : on imprime  "BinCenter(i) data[i]"  (note "... ...")
+//|         bit 0 on : (v=1): numero_bin "... ..."
+//|         bit 1 on : (v=2): "... ..." erreur
+//--
+{
+
+ 
+ if( il > ih ) { il = 0; ih = bins-1; }
+ if( il < 0 ) il = 0;
+ if( ih >= bins ) ih = bins-1;
+
+ double dhmin = (double) hmin;
+ double dhmax = (double) hmax;
+ double hb,hbmn,hbmx;
+
+ if(hdyn==0) hdyn = 100;
+
+ cout << "~Histo::Print  "
+      << " nHist=" << nHist << "  nEntries=" << nEntries
+      << "  under=" << under << "  over=" << over << endl;
+ cout << "       bins=" << bins
+      << "  min=" << min << "  max=" << max
+      << "  binWidth=" << binWidth << endl;
+ cout << "       mean=" << Mean() << " r.m.s=" << Sigma() << endl;
+
+ if(hdyn<0 || pflag<0 ) return;
+
+ if(dhmax<=dhmin) { if(hmin != 0.) dhmin = (double) VMin(); else dhmin=0.;
+                  dhmax = (double) VMax(); }
+ if(dhmin>dhmax) return;
+ if(dhmin==dhmax) {dhmin -= 1.; dhmax += 1.;}
+ double wb = (dhmax-dhmin) / (double) hdyn;
+
+ // determination de la position de la valeur zero
+ int i0 = (int)(-dhmin/wb);
+
+ // si le zero est dans la dynamique,
+ //  il doit imperativement etre une limite de bin
+ if( 0 <= i0 && i0 < hdyn ) {
+   hbmn = dhmin + i0*wb;
+   hbmx = hbmn + wb;
+   if( hbmn != 0. ) {
+     hbmn *= -1.;
+     if( hbmn < hbmx ) {
+       // le zero est + pres du bord negatif du bin
+       dhmin += hbmn;
+       dhmax += hbmn;
+     } else {
+       // le zero est + pres du bord positif du bin
+       dhmin -= hbmx;
+       dhmax -= hbmx;
+     }
+     wb = (dhmax-dhmin) / (double) hdyn;
+     i0 = (int)(-dhmin/wb);
+   }
+ }
+
+ cout <<"       bin minimum="<<dhmin<<"   bin maximum="<<dhmax
+      <<"   binw="<<wb<< endl;
+
+ char* s = new char[hdyn+1];
+ s[hdyn] = '\0';
+
+ // premiere ligne
+ {for(int i=0;i<hdyn;i++) s[i] = '=';}
+ if( 0 <= i0 && i0 < hdyn ) s[i0] = '0';
+ if(pflag&1) fprintf( fp, "====");
+ fprintf( fp, "======================");
+ if(pflag&2 && err2!=NULL) fprintf( fp, "===========");
+ fprintf( fp, "==%s\n",s);
+
+ // histogramme
+ {for(int i=il;i<=ih;i++) {
+   for(int k=0;k<hdyn;k++) s[k] = ' ';
+   hb = (*this)(i);
+
+   //choix du bin (hdyn bin entre [dhmin,dhmax[
+   int ii = (int)( (hb-dhmin)/wb );
+   if(ii<0) ii = 0; else if(ii>=hdyn) ii = hdyn-1;
+
+   // limite du bin
+   hbmn = dhmin + ii*wb;
+   hbmx = hbmn + wb;
+
+   // remplissage de s[] en tenant compte des courbes +/-
+   if(i0<0) {
+     // courbe entierement positive
+     for(int k=0;k<=ii;k++) s[k] = 'X';
+   } else if(i0>=hdyn) {
+     // courbe entierement negative
+     for(int k=hdyn-1;k>=ii;k--) s[k] = 'X';
+   } else {
+     // courbe positive et negative
+     s[i0] = '|';
+     if(ii>i0)        for(int k=i0+1;k<=ii;k++) s[k] = 'X';
+       else if(ii<i0) for(int k=ii;k<i0;k++)    s[k] = 'X';
+          else s[ii] = 'X';
+   }
+
+   // valeur a mettre dans le bin le plus haut/bas
+   int ib;
+   if(hb>0.) ib = (int)( 10.*(hb-hbmn)/(hbmx-hbmn) );
+     else if(hb<0.) ib = (int)( 10.*(hbmx-hb)/(hbmx-hbmn) );
+       else ib = -1;
+   if(ib==-1) s[ii] = '|';
+     else if(ib==0) s[ii] = '.';
+       else if(ib>0 && ib<10) s[ii] = (char)((int) '0' + ib);
+
+   // traitement des saturations +/-
+   if( hb < dhmin ) s[0] = '*';
+    else if( hb > dhmax ) s[hdyn-1] = '*';
+
+   if(pflag&1) fprintf( fp, "%3d ",i);
+   fprintf( fp, "%10.4g %10.4g ",BinCenter(i),hb);
+   if(pflag&2 && err2!=NULL) fprintf( fp, "%10.4g ",Error(i));
+   fprintf( fp, "= %s\n",s);
+ }}
+
+ // derniere ligne
+ for(int i=0;i<hdyn;i++) s[i] = '=';
+ if( 0 <= i0 && i0 < hdyn ) s[i0] = '0';
+ if(pflag&1) fprintf( fp, "====");
+ fprintf( fp, "======================");
+ if(pflag&2 && err2!=NULL) fprintf( fp, "===========");
+ fprintf( fp, "==%s\n",s);
+
+ // valeur basse des bins (sur ["ndig-1" digits + signe] =  ndig char (>=3))
+ const int ndig = 7;
+ char sn[2*ndig+10];
+ hb = ( fabs(dhmin) > fabs(dhmax) ) ? fabs(dhmin) : fabs(dhmax);
+ int n;
+ if( hb > 0. ) n = (int)(log10(hb*1.00000001)); else n = 1;
+ double scaledig = pow(10.,(double) ndig-2);
+ double expo = scaledig/pow(10.,(double) n);
+ // cout <<"n="<<n<<" hb="<<hb<<" scaledig="<<scaledig<<" expo="<<expo<<endl;
+ for(int k=0;k<ndig;k++) {
+   for(int i=0;i<hdyn;i++) s[i] = ' ';
+   {for(int i=0;i<hdyn;i++) {
+     n = (int)( (dhmin + i*wb)*expo );
+     for(int j=0;j<2*ndig+10;j++) sn[j] = ' ';
+     sprintf(sn,"%d%c",n,'\0');
+     strip(sn,'B',' ');
+     // cout <<"n="<<n<<" sn=("<<sn<<")  l="<<strlen(sn)<<" k="<<k;
+     if( (int) strlen(sn) > k ) s[i] = sn[k];
+     // cout <<"  s=("<<s<<")"<<endl;
+   }}
+   if(pflag&1) fprintf( fp, "    ");
+   fprintf( fp, "                      ");
+   if(pflag&2 && err2!=NULL) fprintf( fp, "           ");
+   fprintf( fp, "  %s\n",s);
+ }
+ fprintf( fp, "  (valeurs a multiplier par %.0e)\n",1./expo);
+
+ delete[] s;
+}
+
+/********* Methode *********/
+//++
+void Histo::Print(int hdyn,float hmin, float hmax,int pflag,
+	     int il, int ih)
+//
+//	Impression de l'histogramme sur stdout
+//--
+{
+ Histo::PrintF(stdout, hdyn, hmin, hmax, pflag, il, ih);
+}
+
+
+// Rappel des inlines functions pour commentaires
+//++
+// inline float          XMin() const
+//	Retourne l'abscisse minimum
+//--
+//++
+// inline float          XMax() const
+//	Retourne l'abscisse maximum
+//--
+//++
+// inline int            NBins() const
+//	Retourne le nombre de bins
+//--
+//++
+// inline float          BinWidth() const
+//	Retourne la largeur du bin
+//--
+//++
+// inline float*         Bins() const
+//	Retourne le pointeur sur le tableaux des contenus
+//--
+//++
+// inline float          operator()(int i) const
+//	Retourne le contenu du bin i
+//--
+//++
+// inline float&         operator()(int i)
+//	Remplit le contenu du bin i
+//--
+//++
+// inline float          Error(int i) const
+//	Retourne l'erreur du bin i
+//--
+//++
+// inline double         Error2(int i) const
+//	Retourne l'erreur au carre du bin i
+//--
+//++
+// inline double&        Error2(int i)
+//	Remplit l'erreur au carre du bin i
+//--
+//++
+// inline float          NData() const
+//	Retourne la somme ponderee
+//--
+//++
+// inline float          NEntries()
+//	Retourne le nombre d'entrees
+//--
+//++
+// inline float          NOver() const
+//	Retourne le nombre d'overflow
+//--
+//++
+// inline float          NUnder() const
+//	Retourne le nombre d'underflow
+//--
+//++
+// inline float          BinLowEdge(int i)  const
+//	Retourne l'abscisse du bord inferieur du bin i
+//--
+//++
+// inline float          BinCenter(int i)   const
+//	Retourne l'abscisse du centre du bin i
+//--
+//++
+// inline float          BinHighEdge(int i) const
+//	Retourne l'abscisse du bord superieur du bin i
+//--
+//++
+// inline int            FindBin(float x) const   
+//	Retourne le numero du bin contenant l'abscisse x
+//--
+
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+void ObjFileIO<Histo>::ReadSelf(PInPersist& is)
+{
+char strg[256];
+
+if(dobj==NULL) dobj=new Histo;
+  else         dobj->Delete();
+
+// Lecture entete
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+
+// Lecture des valeurs
+is.Get(dobj->bins);
+is.Get(dobj->nEntries);
+int_4 errok;
+is.Get(errok);
+
+is.Get(dobj->binWidth);
+is.Get(dobj->min);
+is.Get(dobj->max);
+is.Get(dobj->under);
+is.Get(dobj->over);
+
+is.Get(dobj->nHist);
+
+// Lecture des donnees Histo 1D
+dobj->data = new float[dobj->bins];
+is.GetLine(strg, 255);
+is.Get(dobj->data, dobj->bins);
+
+// Lecture des erreurs
+if(errok) {
+  is.GetLine(strg, 255);
+  dobj->err2 = new double[dobj->bins];
+  is.Get(dobj->err2, dobj->bins);
+}
+
+return;
+}
+
+void ObjFileIO<Histo>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+char strg[256];
+
+// Que faut-il ecrire?
+int_4 errok = (dobj->err2) ? 1 : 0;
+
+// Ecriture entete pour identifier facilement
+sprintf(strg,"bins=%6d  NEnt=%15d  errok=%1d",dobj->bins,dobj->nEntries,errok);
+os.PutLine(strg);
+sprintf(strg,"binw=%g  min=%g max=%g",dobj->binWidth,dobj->min,dobj->max);
+os.PutLine(strg);
+sprintf(strg, "under=%g over=%g nHist=%g",dobj->under,dobj->over,dobj->nHist);
+os.PutLine(strg);
+
+// Ecriture des valeurs
+os.Put(dobj->bins);
+os.Put(dobj->nEntries);
+os.Put(errok);
+
+os.Put(dobj->binWidth);
+os.Put(dobj->min);
+os.Put(dobj->max);
+os.Put(dobj->under);
+os.Put(dobj->over);
+
+os.Put(dobj->nHist);
+
+// Ecriture des donnees Histo 1D
+sprintf(strg,"Histo: Tableau des donnees %d",dobj->bins);
+os.PutLine(strg);
+os.Put(dobj->data, dobj->bins);
+
+// Ecriture des erreurs
+if(errok) {
+  sprintf(strg,"Histo: Tableau des erreurs %d",dobj->bins);
+  os.PutLine(strg);
+  os.Put(dobj->err2, dobj->bins);
+}
+
+return;
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<Histo>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<Histo>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/histos.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/histos.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/histos.h	(revision 752)
@@ -0,0 +1,172 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: histos.h,v 1.6 1999-11-05 13:08:29 ansari Exp $
+//
+
+#ifndef HISTOS_SEEN
+#define HISTOS_SEEN
+
+#include "objfio.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "peida.h"
+#include "tvector.h"
+#include "ppersist.h"
+#include "anydataobj.h"
+
+namespace SOPHYA {
+
+class GeneralFit;
+
+class Histo : public AnyDataObj {
+  friend class ObjFileIO<Histo>;
+public:
+
+  // CREATOR / DESTRUCTOR
+  Histo();
+  Histo(float xMin, float xMax, int nBin=100);
+  Histo(const Histo& H);
+  virtual        ~Histo();
+
+  // OPTIONS
+  void   Errors();
+
+  // UPDATING or SETTING
+  void   Zero();
+  void   Add(float x, float w = 1.);
+  void   AddBin(int numBin, float w = 1.);
+  void   SetBin(float x, float w = 1.);
+  void   SetBin(int numBin, float w = 1.);
+  void   SetErr2(float x, double e2);
+  void   SetErr2(int numBin, double e2);
+  void   SetErr(float x, float e);
+  void   SetErr(int numBin, float e);
+
+  // Operators
+  Histo& operator = (const Histo& h);
+  Histo& operator *= (double b);
+  Histo& operator /= (double b);
+  Histo& operator += (double b);
+  Histo& operator -= (double b);
+  friend Histo operator * (const Histo& a, double b);
+  friend Histo operator * (double b, const Histo& a);
+  friend Histo operator / (const Histo& a, double b);
+  friend Histo operator + (const Histo& a, double b);
+  friend Histo operator + (double b, const Histo& a);
+  friend Histo operator - (const Histo& a, double b);
+  friend Histo operator - (double b, const Histo& a);
+  Histo& operator += (const Histo& a);
+  Histo& operator -= (const Histo& a);
+  Histo& operator *= (const Histo& a);
+  Histo& operator /= (const Histo& a);
+  friend Histo operator + (const Histo& a, const Histo& b);
+  friend Histo operator - (const Histo& a, const Histo& b);
+  friend Histo operator * (const Histo& a, const Histo& b);
+  friend Histo operator / (const Histo& a, const Histo& b);
+
+  // get/put dans/depuis un vector
+  void GetAbsc(Vector& v);
+  void GetValue(Vector& v);
+  void GetError2(Vector& v);
+  void GetError(Vector& v);
+  void PutValue(Vector& v, int ierr=0);
+  void PutValueAdd(Vector &v, int ierr=0);
+  void PutError2(Vector& v);
+  void PutError2Add(Vector& v);
+  void PutError(Vector& v);
+
+  // INLINES
+  inline float          XMin() const             {return min;}
+  inline float          XMax() const             {return max;}
+  inline int_4          NBins() const            {return bins;}
+  inline float          BinWidth() const         {return binWidth;}
+  inline float*         Bins() const             {return data;}
+  inline float          operator()(int i) const  {return data[i];}
+  inline float&         operator()(int i)        {return data[i];}
+  inline bool           HasErrors() { if(err2) return true; else return false;}
+  inline float          Error(int i) const
+                          {if(err2) {if(err2[i]>0.) return sqrt(err2[i]); else return 0.;}
+                           else return 0.;}
+  inline double         Error2(int i) const
+                          {if(err2) return err2[i]; else return 0.;}
+  inline double&        Error2(int i) {return err2[i];}
+  inline float          NData() const            {return (float) nHist;}
+  inline float          NEntries() const         {return nEntries;}
+  inline float          NOver() const            {return over;}
+  inline float          NUnder() const           {return under;}
+
+  inline float          BinLowEdge(int i)  const {return min + i*binWidth;}
+  inline float          BinCenter(int i)   const {return min + (i+0.5)*binWidth;}
+  inline float          BinHighEdge(int i) const {return min + (i+1)*binWidth;} 
+  inline int_4          FindBin(float x) const   
+                            {return (int_4) floorf((x - min) / binWidth);}
+
+  // Info, statistique et calculs sur les histogrammes
+  int            BinNonNul() const;
+  int            ErrNonNul() const;
+  int            IMax() const;
+  int            IMin() const;
+  float          VMax() const;
+  float          VMin() const;
+  float          Mean() const;
+  float          Sigma() const;
+  float          MeanLH(int il,int ih) const;
+  float          SigmaLH(int il,int ih) const;
+  float          Mean(float x0, float dx) const;
+  float          Sigma(float x0, float dx) const;
+  float          CleanedMean() const;
+  float          CleanedMean(float& sigma) const;
+  int            BinPercent(float per) const;
+  int            BinPercent(float x,float per,int& imin,int& imax);
+  int            BinPercent(float x,float per,float& xmin,float& xmax);
+  void           HInteg(float norm = 0.);
+  void           HDeriv();
+  void           HRebin(int nbinew);
+
+  int            MaxiLocal(float& maxi,int& imax,float& maxn,int& imaxn);
+  float          FitMax(int degree=2, float frac=0.5f, int debug=0) const;
+  float          FindWidth(float xmax,float frac=0.5f, int debug=0) const;
+  float          FindWidth(float frac=0.5f, int debug=0) const;
+  int            EstimeMax(float& xm,int SzPav = 3);
+  int            EstimeMax(int& im,float& xm,int SzPav = 3);
+  void           EstimeWidthS(float frac,float& widthG,float& widthD);
+
+  // Fit
+  int    Fit(GeneralFit& gfit,unsigned short typ_err=0);
+  Histo  FitResidus(GeneralFit& gfit);
+  Histo  FitFunction(GeneralFit& gfit);
+
+  // Print et Display ASCII
+  void           PrintF(FILE * fp, int dyn = 100, float hmin = 1., float hmax = -1.,
+			int pflag = 0, int il = 1, int ih = -1);
+  void           Print(int dyn = 100, float hmin = 1., float hmax = -1.,
+			int pflag = 0, int il = 1, int ih = -1);
+
+protected:
+  void Delete();
+
+  float*         data;		 
+  double*        err2;		 
+  float          under;
+  float          over;
+  double         nHist;
+  int_4          nEntries;
+  int_4          bins;
+  float          min;
+  float          max;
+  float          binWidth;
+};
+
+
+inline POutPersist& operator << (POutPersist& os, Histo & obj)
+{ ObjFileIO<Histo> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, Histo & obj)
+{ ObjFileIO<Histo> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<Histo>
+
+
+} // Fin du namespace
+
+#endif // HISTOS_SEEN
Index: /tags/V_Fev00/SophyaLib/NTools/histos2.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/histos2.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/histos2.cc	(revision 752)
@@ -0,0 +1,2038 @@
+//
+//    cmv 05/08/96
+//
+
+#include "machdefs.h"
+
+#include <string.h>
+#include <new.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef __mac__
+#include <values.h>
+#endif
+
+#include "histos2.h"
+#include "generalfit.h"
+
+//++
+// Class	Histo2D
+// Lib	Outils++ 
+// include	histos2.h
+//
+//	Classe d'histogrammes 2D
+//--
+
+///////////////////////////////////////////////////////////////////
+//++
+// Titre	Constructeurs
+//--
+
+//++
+Histo2D::Histo2D(float xMin, float xMax, int nxBin
+                ,float yMin, float yMax, int nyBin)
+//
+//	Createur d'un histogramme 2D ayant nxBin,nyBin bins
+//	entre xMin,xMax et yMin,yMax.
+//--
+      : data(new float[nxBin*nyBin]), err2(NULL)
+      , nHist(0), nEntries(0)
+      , nx(nxBin), ny(nyBin), nxy(nxBin*nyBin)
+      , xmin(xMin), xmax(xMax), ymin(yMin), ymax(yMax)
+      , wbinx((xMax - xMin)/nxBin), wbiny((yMax - yMin)/nyBin)
+      , hprojx(NULL), hprojy(NULL)
+{
+ASSERT(nxBin>0 && nyBin>0 && xMin<xMax && yMin<yMax);
+for(int i=0;i<3;i++) for(int j=0;j<3;j++) over[i][j]=0.;
+Zero();
+b_s.H = NULL;
+END_CONSTRUCTOR
+}
+
+//++
+Histo2D::Histo2D(const Histo2D& h)
+//
+//	Constructeur par copie.
+//--
+{
+int i,j;
+data = new float[h.nxy];
+memcpy(data, h.data, h.nxy*sizeof(float));
+
+err2 = NULL;
+if(h.err2) {
+  err2 = new double[h.nxy];
+  memcpy(err2, h.err2, h.nxy*sizeof(double));
+}
+
+nHist = h.nHist; nEntries = h.nEntries;
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j]=h.over[i][j];
+nx = h.nx;  ny = h.ny;  nxy = h.nxy;
+xmin = h.xmin; xmax = h.xmax; ymin = h.ymin; ymax = h.ymax;
+wbinx = h.wbinx; wbiny = h.wbiny;
+b_s.H = NULL;
+
+hprojx = hprojy = NULL;
+if(h.hprojx) {
+  SetProjX();
+  *hprojx = *(h.hprojx);
+}
+if(h.hprojy) {
+  SetProjY();
+  *hprojy = *(h.hprojy); 
+}
+
+int nb;
+float min,max;
+nb = h.NSliX();
+if(nb>0) {
+  SetSliX(nb);
+  for(i=0; i<NSliX();i++) *HSliX(i) = *(h.HSliX(i));
+}
+nb = h.NSliY();
+if(nb>0) {
+  SetSliY(nb);
+  for(i=0; i<NSliY();i++) *HSliY(i) = *(h.HSliY(i));
+}
+
+nb = h.NBandX();
+if(nb>0) {
+  for(i=0; i<nb;i++) {
+    h.GetBandX(i,min,max);
+    SetBandX(min,max);
+    *HBandX(i) = *(h.HBandX(i));
+  }
+  for(i=0; i<NBandX();i++) *HBandX(i) = *(h.HBandX(i));
+}
+nb = h.NBandY();
+if(nb>0) {
+  for(i=0; i<nb;i++) {
+    h.GetBandY(i,min,max);
+    SetBandY(min,max);
+    *HBandY(i) = *(h.HBandY(i));
+  }
+  for(i=0; i<NBandY();i++) *HBandY(i) = *(h.HBandY(i));
+}
+
+END_CONSTRUCTOR
+}
+
+//++
+Histo2D::Histo2D()
+//
+//	Constructeur par defaut.
+//--
+      : data(NULL), err2(NULL)
+      , nHist(0), nEntries(0)
+      , nx(0), ny(0), nxy(0)
+      , xmin(0), xmax(0), ymin(0), ymax(0)
+      , wbinx(0), wbiny(0)
+      , hprojx(NULL), hprojy(NULL)
+{
+for(int i=0;i<3;i++) for(int j=0;j<3;j++) over[i][j]=0.;
+b_s.H = NULL;
+END_CONSTRUCTOR
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::Delete()
+//
+//	Desallocation de la place de l'histogramme (fct privee).
+//--
+{
+  if( data != NULL ) { delete[] data; data = NULL;}
+
+  if( err2 != NULL ) { delete[] err2; err2 = NULL;}
+
+  DelProj();
+
+  DelBandX();
+  DelBandY();
+
+  DelSliX();
+  DelSliY();
+
+  nHist = 0;
+  nEntries = 0;
+  nx = 0; ny = 0; nxy = 0;
+  xmin = 0; xmax = 0; ymin = 0; ymax = 0;
+  wbinx = 0; wbiny = 0;
+  for(int i=0;i<3;i++) for(int j=0;j<3;j++) over[i][j]=0.;
+  b_s.H = NULL;
+}
+
+//++
+Histo2D::~Histo2D()
+//
+//	Destructeur.
+//--
+{
+Delete();
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+// Titre	Methodes generales
+//--
+
+//++
+void Histo2D::Zero()
+//
+//	Remise a zero du contenu, des erreurs et des valeurs.
+//--
+{
+  nHist = nEntries = 0;
+  for(int i=0;i<3;i++) for(int j=0;j<3;j++) over[i][j]=0.;
+  memset(data, 0, nxy*sizeof(float));
+  memset(over, 0, 9*sizeof(float));
+
+  if( err2 != NULL ) memset(err2, 0, nxy*sizeof(double));
+
+  ZeroProj();
+
+  ZeroBandX();
+  ZeroBandY();
+
+  ZeroSliX();
+  ZeroSliY();
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::Errors()
+//
+//	Pour avoir le calcul des erreurs.
+//--
+{
+ if( nxy > 0 ) {
+   if(err2==NULL) err2 = new double[nxy];
+   memset(err2, 0, nxy*sizeof(double));
+ }
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+Histo2D& Histo2D::operator = (const Histo2D& h)
+//
+//--
+{
+  int i,j,nb;
+  float min,max;
+
+  if(this == &h) return *this;
+  if( h.nxy > nxy ) Delete();
+  if(!data) data = new float[h.nxy];
+  if( !h.err2 && err2 ) { delete [] err2; err2=NULL;}
+  if( h.err2 && !err2 ) err2 = new double[h.nxy];
+
+  for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] = h.over[i][j];
+  nHist = h.nHist;
+  nEntries = h.nEntries;
+  nx = h.nx;  ny = h.ny;  nxy = h.nxy;
+  xmin = h.xmin; xmax = h.xmax; wbinx = h.wbinx;
+  ymin = h.ymin; ymax = h.ymax; wbiny = h.wbiny;
+  
+  memcpy(data, h.data, nxy*sizeof(float));
+  if(err2) memcpy(err2, h.err2, nxy*sizeof(double));
+
+  DelProjX();
+  if(h.hprojx) {
+    SetProjX();
+    *hprojx = *(h.hprojx);
+  }
+  DelProjY();
+  if(h.hprojy) {
+    SetProjY();
+    *hprojy = *(h.hprojy);
+  }
+
+  DelSliX();
+  nb = h.NSliX();
+  if(nb>0) {
+    SetSliX(nb);
+    for(i=0; i<NSliX();i++) *HSliX(i) = *(h.HSliX(i));
+  }
+  DelSliY();
+  nb = h.NSliY();
+  if(nb>0) {
+    SetSliY(nb);
+    for(i=0; i<NSliY();i++) *HSliY(i) = *(h.HSliY(i));
+  }
+
+  DelBandX();
+  nb = h.NBandX();
+  if(nb>0) {
+    for(i=0; i<nb;i++) {
+      h.GetBandX(i,min,max);
+      SetBandX(min,max);
+      *HBandX(i) = *(h.HBandX(i));
+    }
+    for(i=0; i<NBandX();i++) *HBandX(i) = *(h.HBandX(i));
+  }
+  DelBandY();
+  nb = h.NBandY();
+  if(nb>0) {
+    for(i=0; i<nb;i++) {
+      h.GetBandY(i,min,max);
+      SetBandY(min,max);
+      *HBandY(i) = *(h.HBandY(i));
+    }
+    for(i=0; i<NBandY();i++) *HBandY(i) = *(h.HBandY(i));
+  }
+
+  return *this;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+Histo2D& Histo2D::operator *= (double b)
+//
+//--
+{
+int i,j;
+double b2 = b*b;
+for(i=0;i<nxy;i++) {
+  data[i] *= b;
+  if(err2) err2[i] *= b2;
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] *= b;
+nHist *= b;
+
+if(hprojx) *hprojx *= b;
+if(hprojy) *hprojy *= b;
+if(NSliX()>0) for(i=0; i<NSliX();i++) *HSliX(i) *= b;
+if(NSliY()>0) for(i=0; i<NSliY();i++) *HSliY(i) *= b;
+if(NBandX()>0) for(i=0; i<NBandX();i++) *HBandX(i) *= b;
+if(NBandY()>0) for(i=0; i<NBandY();i++) *HBandY(i) *= b;
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator /= (double b)
+//
+//--
+{
+int i,j;
+if (b==0.) THROW(inconsistentErr);
+double b2 = b*b;
+for(i=0;i<nxy;i++) {
+  data[i] /= b;
+  if(err2) err2[i] /= b2;
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] /= b;
+nHist /= b;
+
+if(hprojx) *hprojx /= b;
+if(hprojy) *hprojy /= b;
+if(NSliX()>0) for(i=0; i<NSliX();i++) *HSliX(i) /= b;
+if(NSliY()>0) for(i=0; i<NSliY();i++) *HSliY(i) /= b;
+if(NBandX()>0) for(i=0; i<NBandX();i++) *HBandX(i) /= b;
+if(NBandY()>0) for(i=0; i<NBandY();i++) *HBandY(i) /= b;
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator += (double b)
+//
+//--
+{
+int i,j;
+float min,max;
+for(i=0;i<nxy;i++) data[i] += b;
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] += b;
+nHist += nxy*b;
+
+if(hprojx) *hprojx += b*ny;
+if(hprojy) *hprojy += b*nx;
+if(NSliX()>0) for(i=0; i<NSliX();i++) *HSliX(i) += b*ny/NSliX();
+if(NSliY()>0) for(i=0; i<NSliY();i++) *HSliY(i) += b*nx/NSliY();
+if(NBandX()>0) for(i=0; i<NBandX();i++) {
+  GetBandX(i,min,max);
+  *HBandX(i) += b*(max-min)/(ymax-ymin)*ny;
+}
+if(NBandY()>0) for(i=0; i<NBandY();i++) {
+  GetBandY(i,min,max);
+  *HBandY(i) += b*(max-min)/(xmax-xmin)*nx;
+}
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator -= (double b)
+//
+//--
+{
+int i,j;
+float min,max;
+for(i=0;i<nxy;i++) data[i] -= b;
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] -= b;
+nHist -= nxy*b;
+
+if(hprojx) *hprojx -= b*ny;
+if(hprojy) *hprojy -= b*nx;
+if(NSliX()>0) for(i=0; i<NSliX();i++) *HSliX(i) -= b*ny/NSliX();
+if(NSliY()>0) for(i=0; i<NSliY();i++) *HSliY(i) -= b*nx/NSliY();
+if(NBandX()>0) for(i=0; i<NBandX();i++) {
+  GetBandX(i,min,max);
+  *HBandX(i) -= b*(max-min)/(ymax-ymin)*ny;
+}
+if(NBandY()>0) for(i=0; i<NBandY();i++) {
+  GetBandY(i,min,max);
+  *HBandY(i) -= b*(max-min)/(xmax-xmin)*nx;
+}
+
+return *this;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+Histo2D operator * (const Histo2D& a, double b)
+//
+//--
+{
+  Histo2D result(a);
+  return (result *= b);
+}
+
+//++
+Histo2D operator * (double b, const Histo2D& a)
+//
+//--
+{
+  Histo2D result(a);
+  return (result *= b);
+}
+
+//++
+Histo2D operator / (const Histo2D& a, double b)
+//
+//--
+{
+  Histo2D result(a);
+  return (result /= b);
+}
+
+//++
+Histo2D operator + (const Histo2D& a, double b)
+//
+//--
+{
+  Histo2D result(a);
+  return (result += b);
+}
+
+//++
+Histo2D operator + (double b, const Histo2D& a)
+//
+//--
+{
+  Histo2D result(a);
+  return (result += b);
+}
+
+//++
+Histo2D operator - (const Histo2D& a, double b)
+//
+//--
+{
+  Histo2D result(a);
+  return (result -= b);
+}
+
+//++
+Histo2D operator - (double b, const Histo2D& a)
+//
+//--
+{
+  Histo2D result(a);
+  result *= -1.;
+  return (result += b);
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+Histo2D& Histo2D::operator += (const Histo2D& a)
+//
+//--
+{
+int i,j;
+if(nx!=a.nx || ny!=a.ny) THROW(sizeMismatchErr);
+for(i=0;i<nxy;i++) {
+  data[i] += a.data[i];
+  if(err2 && a.err2) err2[i] += a.err2[i];
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] += a.over[i][j];
+nHist += a.nHist;
+nEntries += a.nEntries;
+
+if(hprojx && a.hprojx) *hprojx += *(a.hprojx);
+if(hprojy && a.hprojy) *hprojy += *(a.hprojy);
+ZeroSliX();  ZeroSliY();
+ZeroBandX(); ZeroBandY();
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator -= (const Histo2D& a)
+//
+//--
+{
+int i,j;
+if(nx!=a.nx || ny!=a.ny) THROW(sizeMismatchErr);
+for(i=0;i<nxy;i++) {
+  data[i] -= a.data[i];
+  if(err2 && a.err2) err2[i] += a.err2[i];
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] += a.over[i][j];
+nHist -= a.nHist;
+nEntries += a.nEntries;
+
+if(hprojx && a.hprojx) *hprojx -= *(a.hprojx);
+if(hprojy && a.hprojy) *hprojy -= *(a.hprojy);
+ZeroSliX();  ZeroSliY();
+ZeroBandX(); ZeroBandY();
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator *= (const Histo2D& a)
+//
+//--
+{
+int i,j;
+if(nx!=a.nx || ny!=a.ny) THROW(sizeMismatchErr);
+nHist = 0.;
+for(i=0;i<nxy;i++) {
+  if(err2 && a.err2)
+      err2[i] = a.data[i]*a.data[i]*err2[i] + data[i]*data[i]*a.err2[i];
+  data[i] *= a.data[i];
+  nHist += data[i];
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) over[i][j] *= a.over[i][j];
+nEntries += a.nEntries;
+
+if(hprojx && a.hprojx) *hprojx *= *(a.hprojx);
+if(hprojy && a.hprojy) *hprojy *= *(a.hprojy);
+ZeroSliX();  ZeroSliY();
+ZeroBandX(); ZeroBandY();
+
+return *this;
+}
+
+//++
+Histo2D& Histo2D::operator /= (const Histo2D& a)
+//
+//--
+{
+int i,j;
+if(nx!=a.nx || ny!=a.ny) THROW(sizeMismatchErr);
+nHist = 0.;
+for(i=0;i<nxy;i++) {
+  if(a.data[i]==0.) {
+    data[i]=0.;
+    if(err2) err2[i]=0.;
+    continue;
+  }
+  if(err2 && a.err2)
+      err2[i] = (err2[i] + data[i]/a.data[i]*data[i]/a.data[i]*a.err2[i])
+                /(a.data[i]*a.data[i]);
+  data[i] /= a.data[i];
+  nHist += data[i];
+}
+for(i=0;i<3;i++) for(j=0;j<3;j++) 
+  if(a.over[i][j]!=0.) over[i][j] *= a.over[i][j]; else over[i][j] = 0.;
+nEntries += a.nEntries;
+
+if(hprojx && a.hprojx) *hprojx /= *(a.hprojx);
+if(hprojy && a.hprojy) *hprojy /= *(a.hprojy);
+ZeroSliX();  ZeroSliY();
+ZeroBandX(); ZeroBandY();
+
+return *this;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+Histo2D operator + (const Histo2D& a, const Histo2D& b)
+//
+//--
+{
+if (b.NBinX()!=a.NBinX() || b.NBinY()!=a.NBinY()) THROW(sizeMismatchErr);
+Histo2D c(a);
+return (c += b);
+}
+
+//++
+Histo2D operator - (const Histo2D& a, const Histo2D& b)
+//
+//--
+{
+if (b.NBinX()!=a.NBinX() || b.NBinY()!=a.NBinY()) THROW(sizeMismatchErr);
+Histo2D c(a);
+return (c -= b);
+}
+
+//++
+Histo2D operator * (const Histo2D& a, const Histo2D& b)
+//
+//--
+{
+if (b.NBinX()!=a.NBinX() || b.NBinY()!=a.NBinY()) THROW(sizeMismatchErr);
+Histo2D c(a);
+return (c *= b);
+}
+
+//++
+Histo2D operator / (const Histo2D& a, const Histo2D& b)
+//
+//--
+{
+if (b.NBinX()!=a.NBinX() || b.NBinY()!=a.NBinY()) THROW(sizeMismatchErr);
+Histo2D c(a);
+return (c /= b);
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::GetXCoor(Vector &v)
+//
+//	Remplissage d'un tableau avec les valeurs des abscisses.
+//--
+{
+float x,y;
+v.Realloc(nx);
+for(int i=0;i<nx;i++) {BinLowEdge(i,0,x,y); v(i) = x;}
+return;
+}
+
+//++
+void Histo2D::GetYCoor(Vector &v)
+//
+//	Remplissage d'un tableau avec les valeurs des ordonnees.
+//--
+{
+float x,y;
+v.Realloc(ny);
+for(int i=0;i<ny;i++) {BinLowEdge(0,i,x,y); v(i) = y;}
+return;
+}
+
+//++
+//| Remarque sur les indices:
+//|  H(i,j)   -> i  = coord x (0<i<nx),     j  = coord y (0<j<ny)
+//|  v(ii,jj) -> ii = ligne (0<i<NRows()),  jj = colonne (0<i<NCol())
+//|  On fait une correspondance directe i<->ii et j<->jj
+//|  ce qui, en representation classique des histos2D et des matrices
+//|  entraine une inversion x<->y cad une symetrie / diagonale principale
+//|  H(0,...)  represente ^         mais v(0,...) represente
+//|                       |x.......               |xxxxxxxx|
+//|                       |x.......               |........|
+//|                       |x.......               |........|
+//|                       |x.......               |........|
+//|                       |x.......               |........|
+//|                       --------->
+//|                       colonne no 1            ligne no 1
+//--
+
+//++
+void Histo2D::GetValue(Matrix &v)
+//
+//	Remplissage d'un tableau avec les valeurs du contenu.
+//--
+{
+v.Realloc(nx,ny);
+for(int i=0;i<nx;i++)
+  for(int j=0;j<ny;j++) v(i,j) = (*this)(i,j);
+return;
+}
+
+//++
+void Histo2D::GetError2(Matrix &v)
+//
+//	Remplissage d'un tableau avec les valeurs du carre des erreurs.
+//--
+{
+int i,j;
+v.Realloc(nx,ny);
+if(!err2)
+  {for(i=0;i<nx;i++) for(j=0;j<ny;j++) v(i,j) = 0.; return;}
+for(i=0;i<nx;i++) for(j=0;j<ny;j++) v(i,j) = Error2(i,j);
+return;
+}
+
+//++
+void Histo2D::GetError(Matrix &v)
+//
+//	Remplissage d'un tableau avec les valeurs des erreurs.
+//--
+{
+int i,j;
+v.Realloc(nx,ny);
+if(!err2)
+  {for(i=0;i<nx;i++) for(j=0;j<ny;j++) v(i,j) = 0.; return;}
+for(i=0;i<nx;i++) for(j=0;j<ny;j++) v(i,j) = Error(i,j);
+return;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::PutValue(Matrix &v, int ierr)
+//
+//	Remplissage du contenu de l'histo avec les valeurs d'un tableau.
+//--
+{
+int i,j;
+if(v.NRows()!=nx || v.NCol()!=ny) THROW(sizeMismatchErr);
+for(i=0;i<nx;i++) for(j=0;j<ny;j++) {
+  (*this)(i,j) = v(i,j);
+  if(err2 && ierr) Error2(i,j) = fabs(v(i,j));
+}
+return;
+}
+
+//++
+void Histo2D::PutValueAdd(Matrix &v, int ierr)
+//
+//	Addition du contenu de l'histo avec les valeurs d'un tableau.
+//--
+{
+int i,j;
+if(v.NRows()!=nx || v.NCol()!=ny) THROW(sizeMismatchErr);
+for(i=0;i<nx;i++) for(j=0;j<ny;j++) {
+  (*this)(i,j) += v(i,j);
+  if(err2 && ierr) Error2(i,j) += fabs(v(i,j));
+}
+return;
+}
+
+//++
+void Histo2D::PutError2(Matrix &v)
+//
+//	Remplissage des erreurs au carre de l'histo
+//	avec les valeurs d'un tableau.
+//--
+{
+int i,j;
+if(v.NRows()!=nx || v.NCol()!=ny) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(i=0;i<nx;i++) for(j=0;j<ny;j++) Error2(i,j) = v(i,j);
+return;
+}
+
+//++
+void Histo2D::PutError2Add(Matrix &v)
+//
+//	Addition des erreurs au carre de l'histo
+//	avec les valeurs d'un tableau.
+//--
+{
+int i,j;
+if(v.NRows()!=nx || v.NCol()!=ny) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(i=0;i<nx;i++) for(j=0;j<ny;j++)
+          if(v(i,j)>0.) Error2(i,j) += v(i,j);
+return;
+}
+
+//++
+void Histo2D::PutError(Matrix &v)
+//
+//	Remplissage des erreurs de l'histo avec les valeurs d'un tableau.
+//--
+{
+int i,j;
+if(v.NRows()!=nx || v.NCol()!=ny) THROW(sizeMismatchErr);
+if(!err2) Errors();
+for(i=0;i<nx;i++) for(j=0;j<ny;j++)
+  if(v(i,j)>0.) Error2(i,j)=v(i,j)*v(i,j); else Error2(i,j)= -v(i,j)*v(i,j);
+return;
+}
+
+///////////////////////////////////////////////////////////////////
+/********* Methode *********/
+//++
+void Histo2D::Add(float x, float y, float w)
+//
+//	Addition du contenu de l'histo pour x,y poids w.
+//--
+{
+list<bande_slice>::iterator it;
+int i,j;
+FindBin(x,y,i,j);
+
+if( hprojx != NULL ) hprojx->Add(x,w);
+if( hprojy != NULL ) hprojy->Add(y,w);
+
+if(lbandx.size()>0)
+  for( it = lbandx.begin(); it != lbandx.end(); it++)
+    if( (*it).min <= y && y < (*it).max ) (*it).H->Add(x,w);
+
+if(lbandy.size()>0)
+  for( it = lbandy.begin(); it != lbandy.end(); it++)
+    if( (*it).min <= x && x < (*it).max ) (*it).H->Add(y,w);
+
+if(lslix.size()>0)
+  for( it = lslix.begin(); it != lslix.end(); it++)
+    if( (*it).min <= y && y < (*it).max ) (*it).H->Add(x,w);
+
+if(lsliy.size()>0)
+  for( it = lsliy.begin(); it != lsliy.end(); it++)
+    if( (*it).min <= x && x < (*it).max ) (*it).H->Add(y,w);
+
+if( i<0 || i>=nx || j<0 || j>=ny ) {
+  if(i<0) i=0; else if(i>=nx) i=2; else i=1;
+  if(j<0) j=0; else if(j>=ny) j=2; else j=1;
+  over[i][j] += w;
+  over[1][1] += w;
+  return;
+}
+
+data[j*nx+i] += w;
+if(err2!=NULL) err2[j*nx+i] += w*w;
+nHist += w;
+nEntries++;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::IJMax(int& imax,int& jmax,int il,int ih,int jl,int jh)
+//
+//	Recherche du bin du maximum dans le pave [il,ih][jl,jh].
+//--
+{
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+
+imax = jmax = 0;
+if(nxy==1) return;
+
+float mx=(*this)(il,jl);
+for (int i=il; i<=ih; i++)
+   for (int j=jl; j<=jh; j++)
+      if ((*this)(i,j)>mx) {imax = i; jmax = j; mx=(*this)(i,j);}
+}
+
+//++
+void Histo2D::IJMin(int& imax,int& jmax,int il,int ih,int jl,int jh)
+//
+//	Recherche du bin du minimum dans le pave [il,ih][jl,jh].
+//--
+{
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+
+imax = jmax = 0;
+if(nxy==1) return;
+
+float mx=(*this)(il,jl);
+for (int i=il; i<=ih; i++)
+   for (int j=jl; j<=jh; j++)
+      if ((*this)(i,j)<mx) {imax = i; jmax = j; mx=(*this)(i,j);}
+}
+
+
+//++
+float Histo2D::VMax(int il,int ih,int jl,int jh) const
+//
+//	Recherche du maximum dans le pave [il,ih][jl,jh].
+//--
+{
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+
+float mx=(*this)(il,jl);
+if(nxy==1) return mx;
+for (int i=il; i<=ih; i++)
+   for (int j=jl; j<=jh; j++)
+      if ((*this)(i,j)>mx) mx=(*this)(i,j);
+return mx;
+}
+
+//++
+float Histo2D::VMin(int il,int ih,int jl,int jh) const
+//
+//	Recherche du minimum dans le pave [il,ih][jl,jh].
+//--
+{
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+
+float mx=(*this)(il,jl);
+if(nxy==1) return mx;
+for (int i=il; i<=ih; i++)
+   for (int j=jl; j<=jh; j++)
+      if ((*this)(i,j)<mx) mx=(*this)(i,j);
+return mx;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+float Histo2D::NOver(int i,int j) const
+//
+//	Renvoie les under.overflow dans les 8 quadrants.
+//|  over[3][3]:        20 | 21 | 22
+//|                        |    |
+//|                    --------------
+//|                        |    |
+//|                     10 | 11 | 12        11 = all overflow+underflow
+//|                        |    |
+//|                    --------------
+//|                        |    |
+//|                     00 | 01 | 02
+//--
+{
+if( i < 0 || i>=3 || j < 0 || j>=3 ) return over[1][1];
+return over[i][j];
+}
+
+
+///////////////////////////////////////////////////////////////////
+//++
+int Histo2D::BinNonNul() const
+//
+//	Retourne le nombre de bins non-nuls.
+//--
+{
+int non=0;
+for (int i=0;i<nxy;i++) if( data[i] != 0. ) non++;
+return non;
+}
+
+//++
+int Histo2D::ErrNonNul() const
+//
+//	Retourne le nombre de bins avec erreurs non-nulles.
+//--
+{
+if(err2==NULL) return -1;
+int non=0;
+for (int i=0;i<nxy;i++) if( err2[i] != 0. ) non++;
+return non;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+int Histo2D::EstimeMax(float& xm,float& ym,int SzPav
+                      ,int il,int ih,int jl,int jh)
+//
+//	Idem EstimeMax(int...) mais retourne x,y.
+//--
+{
+int im,jm;
+IJMax(im,jm,il,ih,jl,jh);
+return EstimeMax(im,jm,xm,ym,SzPav);
+}
+
+//++
+int Histo2D::EstimeMax(int im,int jm,float& xm,float& ym,int SzPav)
+//
+//	Determine les abscisses et ordonnees du maximum donne par im,jm
+//	en moyennant dans un pave SzPav x SzPav autour du maximum.
+//|  Return:
+//|    0 = si fit maximum reussi avec SzPav pixels
+//|    1 = si fit maximum reussi avec moins que SzPav pixels
+//|                                dans au moins 1 direction
+//|    2 = si fit maximum echoue et renvoit BinCenter()
+//|   -1 = si echec: SzPav <= 0 ou im,jm hors limites
+//--
+{
+xm = ym = 0;
+if( SzPav <= 0 ) return -1;
+if( im < 0 || im >= nx ) return -1;
+if( jm < 0 || jm >= ny ) return -1;
+
+if( SzPav%2 == 0 ) SzPav++;
+SzPav = (SzPav-1)/2;
+
+int rc = 0;
+double dxm = 0, dym = 0, wx = 0;
+for(int i=im-SzPav;i<=im+SzPav;i++) {
+  if( i<0 || i>= nx ) {rc=1; continue;}
+  for(int j=jm-SzPav;j<=jm+SzPav;j++) {
+    if( j<0 || j>= ny ) {rc=1; continue;}
+    float x,y;
+    BinCenter(i,j,x,y);
+    dxm += x * (*this)(i,j);
+    dym += y * (*this)(i,j);
+    wx  += (*this)(i,j);
+  }
+}
+
+if( wx > 0. ) {
+  xm = dxm/wx;
+  ym = dym/wx;
+  return rc;
+} else {
+  BinCenter(im,jm,xm,ym);
+  return 2;
+}
+
+}
+
+//++
+int Histo2D::FindMax(int& im,int& jm,int SzPav,float Dz
+                    ,int il,int ih,int jl,int jh)
+//
+//	Pour trouver le maximum de l'histogramme en tenant compte
+//	des fluctuations.
+//| Methode:
+//| 1-/ On recherche le bin maximum MAX de l'histogramme
+//| 2-/ On considere que tous les pixels compris entre [MAX-Dz,MAX]
+//|     peuvent etre des pixels maxima.
+//| 3-/ On identifie le bin maximum en choissisant le pixel du 2-/
+//|     tel que la somme des pixels dans un pave SzPav x SzPav soit maximale.
+//| INPUT:
+//|  SzPav = taille du pave pour departager
+//|  Dz    = tolerance pour identifier tous les pixels "maximum"
+//| OUTPUT:
+//|  im,jm = pixel maximum trouve
+//| RETURN:
+//|   <0 =  Echec
+//|   >0 =  nombre de pixels possibles pour le maximum
+//--
+{
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+if( SzPav < 0 ) SzPav = 0;
+  else { if( SzPav%2 == 0 ) SzPav++; SzPav = (SzPav-1)/2;}
+if( Dz < 0 ) Dz = 0.;
+float max = VMax(il,ih,jl,jh) - Dz;
+int nmax = 0;
+float sumx = -MAXFLOAT;
+for(int i=il;i<=ih;i++) for(int j=jl;j<=jh;j++) {
+  if( (*this)(i,j) < max) continue;
+  nmax++;
+  float sum = 0.;
+  for(int ii=i-SzPav;ii<=i+SzPav;ii++) {
+    if( ii<0 || ii >= nx ) continue;
+    for(int jj=j-SzPav;jj<=j+SzPav;jj++) {
+      if( jj<0 || jj >= ny ) continue;
+      sum += (*this)(ii,jj);
+    }
+  }
+  if( sum > sumx ) { im = i; jm = j; sumx = sum;}
+}
+if( nmax <= 0 ) { IJMax(im,jm,il,ih,jl,jh); return 1;}
+return nmax;
+}
+
+//////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////
+//++
+int  Histo2D::Fit(GeneralFit& gfit,unsigned short typ_err)
+//
+//	Fit de l'histogramme par ``gfit''.
+//| typ_err = 0 :
+//|    - erreur attachee au bin si elle existe
+//|    - sinon 1
+//| typ_err = 1 :
+//|    - erreur attachee au bin si elle existe
+//|    - sinon max( sqrt(abs(bin) ,1 )
+//| typ_err = 2 :
+//|    - erreur forcee a 1
+//| typ_err = 3 :
+//|    - erreur forcee a max( sqrt(abs(bin) ,1 )
+//| typ_err = 4 :
+//|    - erreur forcee a 1, nulle si bin a zero.
+//| typ_err = 5 :
+//|    - erreur forcee a max( sqrt(abs(bin) ,1 ),
+//|      nulle si bin a zero.
+//--
+{
+if(NBinX()*NBinY()<=0) return -1000;
+if(typ_err>5) typ_err=0;
+
+GeneralFitData mydata(2,NBinX()*NBinY());
+
+for(int i=0;i<NBinX();i++) for(int j=0;j<NBinY();j++) {
+  float x,y;
+  BinCenter(i,j,x,y);
+  double f = (double) (*this)(i,j);
+  double saf = sqrt(fabs(f)); if(saf<1.) saf=1.;
+  double e;
+  if(typ_err==0)      {if(HasErrors()) e=Error(i,j); else e=1.;}
+  else if(typ_err==1) {if(HasErrors()) e=Error(i,j); else e=saf;}
+  else if(typ_err==2) e=1.;
+  else if(typ_err==3) e=saf;
+  else if(typ_err==4) e=(f==0.)?0.:1.;
+  else if(typ_err==5) e=(f==0.)?0.:saf;
+  mydata.AddData2((double) x,(double) y,f,e);
+}
+
+gfit.SetData(&mydata);
+
+return gfit.Fit();
+}
+
+//++
+Histo2D Histo2D::FitResidus(GeneralFit& gfit)
+//
+//	Retourne une classe contenant les residus du fit ``gfit''.
+//--
+{
+if(NBinX()<=0 || NBinY()<=0)
+  throw(SzMismatchError("Histo2D::FitResidus: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("Histo2D::FitResidus: NULL pointer\n"));
+Vector par = gfit.GetParm();
+Histo2D h2(*this);
+for(int i=0;i<NBinX();i++) for(int j=0;j<NBinY();j++) {
+  float xc,yc;
+  BinCenter(i,j,xc,yc);
+  double x[2] = {(double)xc,(double)yc};
+  h2(i,j) -= (float) f->Value(x,par.Data());
+}
+return h2;
+}
+
+//++
+Histo2D Histo2D::FitFunction(GeneralFit& gfit)
+//
+//	Retourne une classe contenant la fonction du fit ``gfit''.
+//--
+{
+if(NBinX()<=0 || NBinY()<=0)
+  throw(SzMismatchError("Histo2D::FitFunction: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("Histo2D::FitFunction: NULL pointer\n"));
+Vector par = gfit.GetParm();
+Histo2D h2(*this);
+for(int i=0;i<NBinX();i++) for(int j=0;j<NBinY();j++) {
+  float xc,yc;
+  BinCenter(i,j,xc,yc);
+  double x[2] = {(double)xc,(double)yc};
+  h2(i,j) = (float) f->Value(x,par.Data());
+}
+return h2;
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::PrintStatus()
+//
+//	Impression des informations sur l'histogramme.
+//--
+{
+printf("~Histo::Print    nHist=%g nEntries=%d\n",nHist,nEntries);
+printf("over: [ %g %g %g // %g %g %g  // %g %g %g ]\n"
+      ,over[2][0],over[2][1],over[2][2]
+      ,over[1][0],over[1][1],over[1][2]
+      ,over[0][0],over[0][1],over[0][2]);
+printf("  nx=%d xmin=%g xmax=%g binx=%g  ",nx,xmin,xmax,wbinx);
+printf("  ny=%d ymin=%g ymax=%g biny=%g\n",ny,ymin,ymax,wbiny);
+}
+
+///////////////////////////////////////////////////////////////////
+//++
+void Histo2D::Print(float min,float max
+                   ,int il,int ih,int jl,int jh)
+//
+//	Impression de l'histogramme sur stdout entre [il,ih] et [jl,jh].
+//--
+{
+int ns = 35;
+// numero d'index:  00000000001111111111222222222233333
+//                  01234567890123456789012345678901234
+// valeur entiere:  00000000001111111111222222222233333
+//                  12345678901234567890123456789012345
+const char *s =    "+23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+if( il > ih ) { il = 0; ih = nx-1; }
+if( jl > jh ) { jl = 0; jh = ny-1; }
+if( il < 0 ) il = 0;
+if( jl < 0 ) jl = 0;
+if( ih >= nx ) ih = nx-1;
+if( jh >= ny ) jh = ny-1;
+
+PrintStatus();
+
+if( il != 0 || ih != nx-1 || jl != 0 || jh != ny-1 ) {
+  float xl,xh,yl,yh;
+  BinLowEdge(il,jl,xl,yl);
+  BinHighEdge(ih,jh,xh,yh);
+  printf("  impression");
+  printf("  en X: %d=[%d,%d] xmin=%g xmax=%g  "
+        ,ih-il+1,il,ih,xl,xh);
+  printf("  en Y: %d=[%d,%d] ymin=%g ymax=%g\n"
+        ,jh-jl+1,jl,jh,yl,yh);
+}
+
+if(min >= max) { if(min != 0.) min = VMin(il,ih,jl,jh); else min=0.;
+                 max = VMax(il,ih,jl,jh); }
+if(min>max) return;
+if(min==max) {min -= 1.; max += 1.;}
+printf("   min=%g max=%g\n",min,max);
+
+// imprime numero de bin en colonne
+printf("\n");
+if( nx-1 >= 100 ) {
+  printf("     ");
+  for(int i=il;i<=ih;i++) printf("%1d",(int) (i%1000)/100);
+  printf("\n");
+}
+if( nx-1 >= 10 ) {
+  printf("     ");
+  for(int i=il;i<=ih;i++) printf("%1d",(int) (i%100)/10);
+  printf("\n");
+}
+printf("     ");
+for(int i=il;i<=ih;i++) printf("%1d",i%10);
+printf("\n");
+printf("     "); {for(int i=il;i<=ih;i++) printf("-"); printf("\n");}
+
+// imprime histogramme
+for(int j=jh;j>=jl;j--) {
+  printf("%3d: ",j);
+  for(int i=il;i<=ih;i++) {
+    int h;
+    if( 1<=max-min && max-min<=35 ) h = (int)( (*this)(i,j) - min ) - 1;
+      else h = (int)( ((*this)(i,j)-min)/(max-min) * ns ) - 1;
+    char c;
+    if(h<0 && (*this)(i,j)>min) c = '.';
+      else if(h<0) c = ' ';
+        else if(h>=ns) c = '*';
+          else c = s[h];
+    printf("%c",c);
+  }
+  printf("\n");
+}
+
+// imprime numero de bin en colonne
+printf("     "); {for(int i=il;i<=ih;i++) printf("-"); printf("\n");}
+if( nx-1 >= 100 ) {
+  printf("     ");
+  for(int i=il;i<=ih;i++) printf("%1d",(int) (i%1000)/100);
+  printf("\n");
+}
+if( nx-1 >= 10 ) {
+  printf("     ");
+  for(int i=il;i<=ih;i++) printf("%1d",(int) (i%100)/10);
+  printf("\n");
+}
+printf("     ");
+{for(int i=il;i<=ih;i++) printf("%1d",i%10);}
+printf("\n");
+
+}
+
+// Rappel des inline functions pour commentaires
+//++
+// inline float   XMin()
+//	Retourne l'abscisse minimum.
+//--
+//++
+// inline float   XMax()
+//	Retourne l'abscisse maximum.
+//--
+//++
+// inline float   YMin()
+//	Retourne l'ordonnee minimum.
+//--
+//++
+// inline float   YMax()
+//	Retourne l'ordonnee maximum.
+//--
+//++
+// inline int     NBinX()
+//	Retourne le nombre de bins selon X.
+//--
+//++
+// inline int     NBinY()
+//	Retourne le nombre de bins selon Y.
+//--
+//++
+// inline float   WBinX()
+//	Retourne la largeur du bin selon X.
+//--
+//++
+// inline float   WBinY()
+//	Retourne la largeur du bin selon Y.
+//--
+//++
+// inline float*  Bins() const
+//	Retourne le pointeur sur le tableaux des contenus.
+//--
+//++
+// inline float   operator()(int i,int j) const
+//	Retourne le contenu du bin i,j.
+//--
+//++
+// inline float&  operator()(int i,int j)
+//	Remplit le contenu du bin i,j.
+//--
+//++
+// inline float   Error(int i,int j)  const
+//	Retourne l'erreur du bin i,j.
+//--
+//++
+// inline double  Error2(int i,int j) const
+//	Retourne l'erreur au carre du bin i,j.
+//--
+//++
+// inline double& Error2(int i,int j)
+//	Remplit l'erreur au carre du bin i,j.
+//--
+//++
+// inline float   NData() const
+//	Retourne la somme ponderee.
+//--
+//++
+// inline int     NEntries() const
+//	Retourne le nombre d'entrees.
+//--
+//++
+// inline void BinLowEdge(int i,int j,float& x,float& y)
+//	Retourne l'abscisse et l'ordonnee du coin inferieur du bin i,j.
+//--
+//++
+// inline void BinCenter(int i,int j,float& x,float& y)
+//	Retourne l'abscisse et l'ordonnee du centre du bin i,j.
+//--
+//++
+// inline void BinHighEdge(int i,int j,float& x,float& y)
+//	Retourne l'abscisse et l'ordonnee du coin superieur du bin i,j.
+//--
+//++
+// inline void FindBin(float x,float y,int& i,int& j)
+//	Retourne les numeros du bin contenant l'abscisse et l'ordonnee x,y.
+//--
+
+///////////////////////////////////////////////////////////////////
+//++
+// Titre	Methodes pour gerer les projections
+//--
+
+//++
+void Histo2D::SetProjX()
+//
+//	Pour creer la projection X.
+//--
+{
+if( hprojx != NULL ) DelProjX();
+hprojx = new Histo(xmin,xmax,nx);
+if( err2 != NULL && hprojx != NULL ) hprojx->Errors();
+}
+
+//++
+void Histo2D::SetProjY()
+//
+//	Pour creer la projection Y.
+//--
+{
+if( hprojy != NULL ) DelProjY();
+hprojy = new Histo(ymin,ymax,ny);
+if( err2 != NULL && hprojy != NULL  ) hprojy->Errors();
+}
+
+//++
+void Histo2D::SetProj()
+//
+//	Pour creer les projections X et Y.
+//--
+{
+SetProjX();
+SetProjY();
+}
+
+//++
+void Histo2D::ShowProj()
+//
+//	Informations sur les projections.
+//--
+{
+if( hprojx != NULL ) cout << ">>>> Projection X set : "<< hprojx <<endl;
+  else cout << ">>>> NO Projection X set"<<endl;
+if( hprojy != NULL ) cout << ">>>> Projection Y set : "<< hprojy <<endl;
+  else cout << ">>>> NO Projection Y set"<<endl;
+}
+
+//++
+void Histo2D::DelProjX()
+//
+//	Destruction de l'histogramme de la projection selon X.
+//--
+{
+if( hprojx == NULL ) return;
+delete hprojx;
+hprojx = NULL;
+}
+
+//++
+void Histo2D::DelProjY()
+//
+//	Destruction de l'histogramme de la projection selon X.
+//--
+{
+if( hprojy == NULL ) return;
+delete hprojy;
+hprojy = NULL;
+}
+
+//++
+void Histo2D::DelProj()
+//
+//	Destruction des histogrammes des projections selon X et Y.
+//--
+{
+DelProjX();
+DelProjY();
+}
+
+//++
+void Histo2D::ZeroProjX()
+//
+//	Remise a zero de la projection selon X.
+//--
+{
+if( hprojx == NULL ) return;
+hprojx->Zero();
+}
+
+//++
+void Histo2D::ZeroProjY()
+//
+//	Remise a zero de la projection selon Y.
+//--
+{
+if( hprojy == NULL ) return;
+hprojy->Zero();
+}
+
+//++
+void Histo2D::ZeroProj()
+//
+//	Remise a zero des projections selon X et Y.
+//--
+{
+ZeroProjX();
+ZeroProjY();
+}
+
+// Rappel des inline functions pour commentaires
+//++
+// inline Histo*  HProjX()
+//	Retourne le pointeur sur l'histo 1D de la projection selon X.
+//--
+//++
+// inline Histo*  HProjY()
+//	Retourne le pointeur sur l'histo 1D de la projection selon Y.
+//--
+
+///////////////////////////////////////////////////////////////////
+//++
+// Titre	Methodes pour gerer les bandes
+//--
+
+//++
+int Histo2D::SetBandX(float ybmin,float ybmax)
+//
+//	Pour creer une bande en X entre ybmin et ybmax.
+//--
+{
+b_s.num = lbandx.size();
+b_s.min = ybmin;
+b_s.max = ybmax;
+b_s.H = new Histo(xmin,xmax,nx);
+lbandx.push_back(b_s);
+b_s.H = NULL;
+return lbandx.size()-1;
+}
+
+//++
+int Histo2D::SetBandY(float xbmin,float xbmax)
+//
+//	Pour creer une bande en Y entre xbmin et xbmax.
+//--
+{
+b_s.num = lbandy.size();
+b_s.min = xbmin;
+b_s.max = xbmax;
+b_s.H = new Histo(ymin,ymax,ny);
+lbandy.push_back(b_s);
+b_s.H = NULL;
+return lbandy.size()-1;
+}
+
+//++
+void Histo2D::DelBandX()
+//
+//	Destruction des histogrammes des bandes selon X.
+//--
+{
+if( lbandx.size() <= 0 ) return;
+for(list<bande_slice>::iterator i = lbandx.begin(); i != lbandx.end(); i++)
+       if( (*i).H != NULL ) {delete (*i).H; (*i).H=NULL;}
+lbandx.erase(lbandx.begin(),lbandx.end());
+}
+
+//++
+void Histo2D::DelBandY()
+//
+//	Destruction des histogrammes des bandes selon Y.
+//--
+{
+if( lbandy.size() <= 0 ) return;
+for(list<bande_slice>::iterator i = lbandy.begin(); i != lbandy.end(); i++)
+       if( (*i).H != NULL ) {delete (*i).H; (*i).H=NULL;}
+lbandy.erase(lbandy.begin(),lbandy.end());
+}
+
+//++
+void Histo2D::ZeroBandX()
+//
+//	Remise a zero des bandes selon X.
+//--
+{
+if( lbandx.size() <= 0 ) return;
+list<bande_slice>::iterator i;
+for(i = lbandx.begin(); i != lbandx.end(); i++)
+              (*i).H->Zero();
+}
+
+//++
+void Histo2D::ZeroBandY()
+//
+//	Remise a zero des bandes selon Y.
+//--
+{
+if( lbandy.size() <= 0 ) return;
+list<bande_slice>::iterator i;
+for(i = lbandy.begin(); i != lbandy.end(); i++)
+              (*i).H->Zero();
+}
+
+//++
+Histo* Histo2D::HBandX(int n) const
+//
+//	Retourne un pointeur sur la bande numero `n' selon X.
+//--
+{
+if( lbandx.size() <= 0 || n < 0 || n >= (int) lbandx.size() ) return NULL;
+for(list<bande_slice>::const_iterator i = lbandx.begin(); i != lbandx.end(); i++)
+              if( (*i).num == n ) return (*i).H;
+return NULL;
+}
+
+//++
+Histo* Histo2D::HBandY(int n) const
+//
+//	Retourne un pointeur sur la bande numero `n' selon Y.
+//--
+{
+if( lbandy.size() <= 0 || n < 0 || n >= (int) lbandy.size() ) return NULL;
+for(list<bande_slice>::const_iterator i = lbandy.begin(); i != lbandy.end(); i++)
+              if( (*i).num == n ) return (*i).H;
+return NULL;
+}
+
+//++
+void Histo2D::GetBandX(int n,float& ybmin,float& ybmax) const
+//
+//	Retourne les limites de la bande numero `n' selon X.
+//--
+{
+ybmin = 0.; ybmax = 0.;
+if( lbandx.size() <= 0 || n < 0 || n >= (int) lbandx.size() ) return;
+for(list<bande_slice>::const_iterator i = lbandx.begin(); i != lbandx.end(); i++)
+  if( (*i).num == n ) { ybmin = (*i).min; ybmax = (*i).max; return;}
+return;
+}
+
+//++
+void Histo2D::GetBandY(int n,float& xbmin,float& xbmax) const
+//
+//	Retourne les limites de la bande numero `n' selon Y.
+//--
+{
+xbmin = 0.; xbmax = 0.;
+if( lbandy.size() <= 0 || n < 0 || n >= (int) lbandy.size() ) return;
+for(list<bande_slice>::const_iterator i = lbandy.begin(); i != lbandy.end(); i++)
+  if( (*i).num == n ) { xbmin = (*i).min; xbmax = (*i).max; return;}
+return;
+}
+
+//++
+void Histo2D::ShowBand(int lp)
+//
+//	Informations sur les bandes.
+//--
+{
+  cout << ">>>> Nombre de bande X : " << lbandx.size() << endl;
+if( lp>0 && lbandx.size()>0 ) {
+  list<bande_slice>::iterator i;
+  for(i = lbandx.begin(); i != lbandx.end(); i++) {
+    cout<<"  "<<(*i).num<<" de ymin="<<(*i).min<<" a ymax="<<(*i).max;
+    if(lp>1) cout << "   H=" << (*i).H;
+    cout << endl;
+  }
+}
+
+cout << ">>>> Nombre de bande Y : " << lbandy.size() << endl;
+if( lp>0 && lbandy.size()>0 ) {
+  list<bande_slice>::iterator i;
+  for(i = lbandy.begin(); i != lbandy.end(); i++) {
+    cout<<"  "<<(*i).num<<" de xmin="<<(*i).min<<" a xmax="<<(*i).max;
+    if(lp>1) cout << "   H=" << (*i).H;
+    cout << endl;
+  }
+}
+}
+
+// Rappel des inline functions pour commentaires
+//++
+// inline int     NBandX()
+//	Retourne le nombre de bandes selon X
+//--
+//++
+// inline int     NBandY()
+//	Retourne le nombre de bandes selon Y
+//--
+
+///////////////////////////////////////////////////////////////////
+//++
+// Titre	Methodes pour gerer les bandes equidistantes
+//--
+
+//++
+int Histo2D::SetSliX(int nsli)
+//
+//	Pour creer `nsli' bandes equidistantes selon X.
+//--
+{
+if( nsli <= 0 ) return -1;
+if( nsli >  ny ) nsli = ny;
+if( lslix.size() > 0 ) DelSliX();
+float w = (ymax-ymin)/nsli;
+
+for(int i=0; i<nsli; i++ ) {
+  b_s.num = i;
+  b_s.min = ymin + i*w;
+  b_s.max = b_s.min + w;
+  b_s.H = new Histo(xmin,xmax,nx);
+  lslix.push_back(b_s);
+  b_s.H = NULL;
+}
+return (int) lslix.size();
+}
+
+//++
+int Histo2D::SetSliY(int nsli)
+//
+//	Pour creer `nsli' bandes equidistantes selon Y.
+//--
+{
+if( nsli <= 0 ) return -1;
+if( nsli >  nx ) nsli = nx;
+if( lsliy.size() > 0 ) DelSliY();
+float w = (xmax-xmin)/nsli;
+
+for(int i=0; i<nsli; i++ ) {
+  b_s.num = i;
+  b_s.min = xmin + i*w;
+  b_s.max = b_s.min + w;
+  b_s.H = new Histo(ymin,ymax,ny);
+  lsliy.push_back(b_s);
+  b_s.H = NULL;
+}
+return (int) lsliy.size();
+}
+
+//++
+void Histo2D::DelSliX()
+//
+//	Destruction des bandes equidistantes selon X.
+//--
+{
+if( lslix.size() <= 0 ) return;
+for(list<bande_slice>::iterator i = lslix.begin(); i != lslix.end(); i++)
+       if( (*i).H != NULL ) {delete (*i).H; (*i).H=NULL;}
+lslix.erase(lslix.begin(),lslix.end());
+}
+
+//++
+void Histo2D::DelSliY()
+//
+//	Destruction des bandes equidistantes selon Y.
+//--
+{
+if( lsliy.size() <= 0 ) return;
+for(list<bande_slice>::iterator i = lsliy.begin(); i != lsliy.end(); i++)
+       if( (*i).H != NULL ) {delete (*i).H; (*i).H=NULL;}
+lsliy.erase(lsliy.begin(),lsliy.end());
+}
+
+//++
+void Histo2D::ZeroSliX()
+//
+//	Remise a zero des bandes equidistantes selon X.
+//--
+{
+if( lslix.size() <= 0 ) return;
+list<bande_slice>::iterator i;
+for(i = lslix.begin(); i != lslix.end(); i++)
+              (*i).H->Zero();
+}
+
+//++
+void Histo2D::ZeroSliY()
+//
+//	Remise a zero des bandes equidistantes selon Y.
+//--
+{
+if( lsliy.size() <= 0 ) return;
+list<bande_slice>::iterator i;
+for(i = lsliy.begin(); i != lsliy.end(); i++)
+              (*i).H->Zero();
+}
+
+//++
+Histo* Histo2D::HSliX(int n) const
+//
+//	Retourne un pointeur sur la bande equidistante numero `n'
+//	selon X.
+//--
+{
+if( lslix.size() <= 0 || n < 0 || n >= (int) lslix.size() ) return NULL;
+for(list<bande_slice>::const_iterator i = lslix.begin(); i != lslix.end(); i++)
+              if( (*i).num == n ) return (*i).H;
+return NULL;
+}
+
+//++
+Histo* Histo2D::HSliY(int n) const
+//
+//	Retourne un pointeur sur la bande equidistante numero `n'
+//	selon Y.
+//--
+{
+if( lsliy.size() <= 0 || n < 0 || n >= (int) lsliy.size() ) return NULL;
+for(list<bande_slice>::const_iterator i = lsliy.begin(); i != lsliy.end(); i++)
+              if( (*i).num == n ) return (*i).H;
+return NULL;
+}
+
+//++
+void Histo2D::ShowSli(int lp)
+//
+//	Informations sur les bandes equidistantes.
+//--
+{
+list<bande_slice>::iterator i;
+cout << ">>>> Nombre de slice X : " << lslix.size() << endl;
+if( lp>0 && lslix.size() > 0 )
+  for(i = lslix.begin(); i != lslix.end(); i++) {
+    cout<<"  "<<(*i).num<<" de ymin="<<(*i).min<<" a ymax="<<(*i).max;
+    if(lp>1) cout << "   H=" << (*i).H;
+    cout << endl;
+  }
+
+cout << ">>>> Nombre de slice Y : " << lsliy.size() << endl;
+if( lp>0 && lsliy.size()>0 )
+  for(i = lsliy.begin(); i != lsliy.end(); i++) {
+    cout<<"  "<<(*i).num<<" de xmin="<<(*i).min<<" a xmax="<<(*i).max;
+    if(lp>1) cout << "   H=" << (*i).H;
+    cout << endl;
+  }
+}
+
+// Rappel des inline functions pour commentaires
+//++
+// inline int     NSliX()
+//	Retourne le nombre de slices selon X
+//--
+//++
+// inline int     NSliY()
+//	Retourne le nombre de slices selon Y
+//--
+
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+
+void  ObjFileIO<Histo2D>::ReadSelf(PInPersist& is)
+{
+char strg[256];
+
+if(dobj==NULL) dobj=new Histo2D;
+  else         dobj->Delete();
+
+float min,max;
+int_4 errok, projx, projy, nslix, nsliy, nbanx, nbany;
+
+// Lecture entete
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+is.GetLine(strg, 255);
+
+// Lecture variables de definitions
+is.Get(dobj->nx);
+is.Get(dobj->ny);
+is.Get(dobj->nxy);
+is.Get(errok);
+is.Get(dobj->nEntries);
+is.Get(dobj->nHist);
+
+is.Get(dobj->xmin);
+is.Get(dobj->xmax);
+is.Get(dobj->ymin);
+is.Get(dobj->ymax);
+is.Get(dobj->wbinx);
+is.Get(dobj->wbiny);
+
+is.Get(&(dobj->over[0][0]),9);
+
+is.Get(projx);
+is.Get(projy);
+is.Get(nslix);
+is.Get(nsliy);
+is.Get(nbanx);
+is.Get(nbany);
+
+// Lecture histo2D
+dobj->data = new float[dobj->nxy];
+is.GetLine(strg, 255);
+{for(int j=0;j<dobj->ny;j++) is.Get(dobj->data+j*dobj->nx,dobj->nx);}
+
+// Lecture erreurs
+if(errok) {
+  is.GetLine(strg, 255);
+  dobj->err2 = new double[dobj->nxy];
+  for(int j=0;j<dobj->ny;j++) is.Get(dobj->err2+j*dobj->nx,dobj->nx);
+}
+
+// Lecture des projections
+if(projx) {
+  is.GetLine(strg, 255);
+  dobj->SetProjX();
+  ObjFileIO<Histo> fio_h(dobj->hprojx);
+  fio_h.Read(is);
+}
+if(projy) {
+  is.GetLine(strg, 255);
+  dobj->SetProjY();
+  ObjFileIO<Histo> fio_h(dobj->hprojy);
+  fio_h.Read(is);
+}
+
+// Lecture des slices
+if(nslix>0) {
+  is.GetLine(strg, 255);
+  dobj->SetSliX(nslix);
+  ASSERT (nslix==dobj->NSliX());
+  for(int j=0;j<dobj->NSliX();j++)
+    {ObjFileIO<Histo> fio_h(dobj->HSliX(j)); fio_h.Read(is);}
+}
+if(nsliy>0) {
+  is.GetLine(strg, 255);
+  dobj->SetSliY(nsliy);
+  ASSERT (nsliy==dobj->NSliY());
+  for(int j=0;j<dobj->NSliY();j++)
+    {ObjFileIO<Histo> fio_h(dobj->HSliY(j)); fio_h.Read(is);}
+}
+
+// Lecture des bandes
+if( nbanx>0 ) {
+  is.GetLine(strg, 255);
+  {for(int j=0; j<nbanx; j++) {
+    is.Get(min); is.Get(max);
+    dobj->SetBandX(min,max);
+  }}
+  ASSERT (nbanx==dobj->NBandX());
+  {for(int j=0; j<dobj->NBandX(); j++) {
+    ObjFileIO<Histo> fio_h(dobj->HBandX(j));
+    fio_h.Read(is);
+  }}
+}
+if( nbany>0 ) {
+  is.GetLine(strg, 255);
+  {for(int j=0; j<nbany; j++) {
+    is.Get(min); is.Get(max);
+    dobj->SetBandY(min,max);
+  }}
+  ASSERT (nbany==dobj->NBandY());
+  {for(int j=0; j<dobj->NBandY(); j++) {
+    ObjFileIO<Histo> fio_h(dobj->HBandY(j));
+    fio_h.Read(is);
+  }}
+}
+
+return;
+}
+
+void ObjFileIO<Histo2D>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+char strg[256];
+
+// Que faut-il ecrire?
+int_4 errok = (dobj->err2) ? 1 : 0;
+int_4 projx = (dobj->hprojx) ? 1 : 0;
+int_4 projy = (dobj->hprojy) ? 1 : 0;
+int_4 nslix = dobj->NSliX();
+int_4 nsliy = dobj->NSliY();
+int_4 nbanx = dobj->NBandX();
+int_4 nbany = dobj->NBandY();
+
+// Ecriture entete pour identifier facilement
+sprintf(strg,"nx=%d  ny=%d  nxy=%d errok=%1d"
+       ,dobj->nx,dobj->ny,dobj->nxy,errok);
+os.PutLine(strg);
+sprintf(strg,"nHist=%g nEntries=%d",dobj->nHist,dobj->nEntries);
+os.PutLine(strg);
+sprintf(strg,"wbinx=%g wbiny=%g",dobj->wbinx,dobj->wbiny);
+os.PutLine(strg);
+sprintf(strg,"xmin=%g xmax=%g ymin=%g ymax=%g"
+       ,dobj->xmin,dobj->xmax,dobj->ymin,dobj->ymax);
+os.PutLine(strg);
+sprintf(strg,"projx/y=%d %d nbandx/y=%d %d nbslix/y=%d %d"
+       ,projx,projy,nbanx,nbany,nslix,nsliy);
+os.PutLine(strg);
+sprintf(strg,"over %g %g %g %g %g %g %g %g %g"
+       ,dobj->over[0][0],dobj->over[0][1],dobj->over[0][2]
+       ,dobj->over[1][0],dobj->over[1][1],dobj->over[1][2]
+       ,dobj->over[2][0],dobj->over[2][1],dobj->over[2][2]);
+os.PutLine(strg);
+
+// Ecriture variables de definitions
+os.Put(dobj->nx);
+os.Put(dobj->ny);
+os.Put(dobj->nxy);
+os.Put(errok);
+os.Put(dobj->nEntries);
+os.Put(dobj->nHist);
+
+os.Put(dobj->xmin);
+os.Put(dobj->xmax);
+os.Put(dobj->ymin);
+os.Put(dobj->ymax);
+os.Put(dobj->wbinx);
+os.Put(dobj->wbiny);
+
+os.Put(&(dobj->over[0][0]),9);
+
+os.Put(projx);
+os.Put(projy);
+os.Put(nslix);
+os.Put(nsliy);
+os.Put(nbanx);
+os.Put(nbany);
+
+// Ecriture histo2D
+sprintf(strg,"Histo2D: Tableau des donnees %d = %d * %d"
+       ,dobj->nxy,dobj->nx,dobj->ny);
+os.PutLine(strg);
+{for(int j=0;j<dobj->ny;j++) os.Put(dobj->data+j*dobj->nx,dobj->nx);}
+
+// Ecriture erreurs
+if(errok) {
+  sprintf(strg,"Histo2D: Tableau des erreurs %d = %d * %d"
+         ,dobj->nxy,dobj->nx,dobj->ny);
+  os.PutLine(strg);
+  for(int j=0;j<dobj->ny;j++) os.Put(dobj->err2+j*dobj->nx,dobj->nx);
+}
+
+// Ecriture des projections
+if(projx) {
+  sprintf(strg,"Histo2D: Projection X");
+  os.PutLine(strg);
+  ObjFileIO<Histo> fio_h(dobj->hprojx); fio_h.Write(os);
+}
+if(projy) {
+  sprintf(strg,"Histo2D: Projection Y");
+  os.PutLine(strg);
+  ObjFileIO<Histo> fio_h(dobj->hprojy); fio_h.Write(os);
+}
+
+// Ecriture des slices
+if(nslix>0) {
+  sprintf(strg,"Histo2D: Slices X %d",nslix);
+  os.PutLine(strg);
+  for(int j=0;j<nslix;j++) {
+    Histo* h = dobj->HSliX(j);
+    ObjFileIO<Histo> fio_h(h); fio_h.Write(os);
+  }
+}
+if(nsliy>0) {
+  sprintf(strg,"Histo2D: Slices Y %d",nsliy);
+  os.PutLine(strg);
+  for(int j=0;j<nsliy;j++) {
+    Histo* h = dobj->HSliY(j);
+    ObjFileIO<Histo> fio_h(h); fio_h.Write(os);
+  }
+}
+
+// Ecriture des bandes
+if( nbanx>0 ) {
+  sprintf(strg,"Histo2D: Bandes X %d",nbanx);
+  os.PutLine(strg);
+  list<Histo2D::bande_slice>::const_iterator it;
+  for(it = dobj->lbandx.begin(); it != dobj->lbandx.end(); it++) {
+    float min = (*it).min; float max = (*it).max;
+    os.Put(min); os.Put(max);
+  }
+  for(it = dobj->lbandx.begin(); it != dobj->lbandx.end(); it++) {
+    Histo* h = (*it).H;
+    ObjFileIO<Histo> fio_h(h); fio_h.Write(os);
+  }
+}
+if( nbany>0 ) {
+  sprintf(strg,"Histo2D: Bandes Y %d",nbany);
+  os.PutLine(strg);
+  list<Histo2D::bande_slice>::const_iterator it;
+  for(it = dobj->lbandy.begin(); it != dobj->lbandy.end(); it++) {
+    float min = (*it).min; float max = (*it).max;
+    os.Put(min); os.Put(max);
+  }
+  for(it = dobj->lbandy.begin(); it != dobj->lbandy.end(); it++) {
+    Histo* h = (*it).H;
+    ObjFileIO<Histo> fio_h(h); fio_h.Write(os);
+  }
+}
+
+return;
+}
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<Histo2D>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<Histo2D>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/histos2.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/histos2.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/histos2.h	(revision 752)
@@ -0,0 +1,229 @@
+//
+// histogrammes 2D     cmv 2/8/96
+//
+
+#ifndef HISTOS2_SEEN
+#define HISTOS2_SEEN
+
+#include "machdefs.h"
+#include <string>
+
+#include <list>
+#if defined(__KCC__)
+#include <list.h>
+#endif
+
+#include "peida.h"
+#include "utils.h"
+#include "histos.h"
+
+namespace SOPHYA {
+
+class GeneralFit;
+
+class Histo2D : public AnyDataObj {
+  friend class ObjFileIO<Histo2D>;
+public:
+
+  // CREATOR / DESTRUCTOR
+  Histo2D(float xMin, float xMax, int nxBin
+         ,float yMin, float yMax, int nyBin);
+  Histo2D(const Histo2D& h);
+  Histo2D();
+  virtual  ~Histo2D();
+
+  // OPTIONS
+  void   Errors();  
+  
+  // UPDATING
+  void   Zero();
+  void   Add(float x, float y, float w = 1.);
+
+  // Operators
+  Histo2D& operator = (const Histo2D& h);
+  Histo2D& operator *= (double b);
+  Histo2D& operator /= (double b);
+  Histo2D& operator += (double b);
+  Histo2D& operator -= (double b);
+  friend Histo2D operator * (const Histo2D& a, double b);
+  friend Histo2D operator * (double b, const Histo2D& a);
+  friend Histo2D operator / (const Histo2D& a, double b);
+  friend Histo2D operator + (const Histo2D& a, double b);
+  friend Histo2D operator + (double b, const Histo2D& a);
+  friend Histo2D operator - (const Histo2D& a, double b);
+  friend Histo2D operator - (double b, const Histo2D& a);
+  Histo2D& operator += (const Histo2D& a);
+  Histo2D& operator -= (const Histo2D& a);
+  Histo2D& operator *= (const Histo2D& a);
+  Histo2D& operator /= (const Histo2D& a);
+  friend Histo2D operator + (const Histo2D& a, const Histo2D& b);
+  friend Histo2D operator - (const Histo2D& a, const Histo2D& b);
+  friend Histo2D operator * (const Histo2D& a, const Histo2D& b);
+  friend Histo2D operator / (const Histo2D& a, const Histo2D& b);
+
+  // get/put dans/depuis une matrice / vector
+  void GetXCoor(Vector& v);
+  void GetValue(Matrix &v);
+  void GetYCoor(Vector& v);
+  void GetError2(Matrix& v);
+  void GetError(Matrix& v);
+  void PutValue(Matrix& v, int ierr=0);
+  void PutValueAdd(Matrix& v, int ierr=0);
+  void PutError2(Matrix& v);
+  void PutError2Add(Matrix& v);
+  void PutError(Matrix& v);
+
+  // INLINES
+  inline float   XMin() const {return xmin;}
+  inline float   XMax() const {return xmax;}
+  inline float   YMin() const {return ymin;}
+  inline float   YMax() const {return ymax;}
+  inline int_4   NBinX() const {return nx;}
+  inline int_4   NBinY() const {return ny;}
+  inline float   WBinX() const {return wbinx;}
+  inline float   WBinY() const {return wbiny;}
+  inline float*  Bins() const  {return data;}
+  inline float   operator()(int i,int j) const {return data[j*nx+i];}
+  inline float&  operator()(int i,int j)       {return data[j*nx+i];}
+  inline bool    HasErrors() { if(err2) return true; else return false;}
+  inline float   Error(int i,int j)  const
+                   {if(err2)
+                      {if(err2[j*nx+i]>0.) return sqrt(err2[j*nx+i]); else return 0.;}
+                    else return 0.;}
+  inline double  Error2(int i,int j) const
+                   {if(err2) return err2[j*nx+i]; else return 0.;}
+  inline double& Error2(int i,int j) {return err2[j*nx+i];}
+  inline float   NData() const    {return (float) nHist;}
+  inline int_4   NEntries() const {return nEntries;}
+  inline void BinLowEdge(int i,int j,float& x,float& y)
+                 {x = xmin + i*wbinx; y = ymin + j*wbiny;}
+  inline void BinCenter(int i,int j,float& x,float& y)
+                 {x = xmin + (i+0.5)*wbinx; y = ymin + (j+0.5)*wbiny;}
+  inline void BinHighEdge(int i,int j,float& x,float& y)
+                 {x = xmin + (i+1)*wbinx; y = ymin + (j+1)*wbiny;}
+  inline void FindBin(float x,float y,int& i,int& j)
+    { i = (int) floorf((x - xmin)/wbinx); j = (int) floorf((y - ymin)/wbiny);}
+
+  // Info, statistique et calculs sur les histogrammes
+  float   NOver(int i=-1,int j=-1) const;
+  int     BinNonNul() const;
+  int     ErrNonNul() const;
+  void    IJMax(int& imax,int& jmax,int il=1,int ih= -1,int jl=1,int jh= -1);
+  void    IJMin(int& imax,int& jmax,int il=1,int ih= -1,int jl=1,int jh= -1);
+  float   VMax(int il=1,int ih= -1,int jl=1,int jh= -1) const;
+  float   VMin(int il=1,int ih= -1,int jl=1,int jh= -1) const;
+  int     EstimeMax(float& xm,float& ym,int SzPav = 3
+                   ,int il=1,int ih= -1,int jl=1,int jh= -1);
+  int     EstimeMax(int im,int jm,float& xm,float& ym,int SzPav = 3);
+  int     FindMax(int& im,int& jm,int SzPav = 3,float Dz = 0.
+                 ,int il=1,int ih= -1,int jl=1,int jh= -1);
+
+  // Fit
+  int      Fit(GeneralFit& gfit,unsigned short typ_err=0);
+  Histo2D  FitResidus(GeneralFit& gfit);
+  Histo2D  FitFunction(GeneralFit& gfit);
+
+  // Print et Display ASCII
+  void    PrintStatus();
+  void    Print(float min=1.,float max=-1.
+               ,int il=1,int ih= -1,int jl=1,int jh= -1);
+
+  // PROJECTIONS
+  void           SetProjX();
+  void           SetProjY();
+  void           SetProj();
+  void           DelProjX();
+  void           DelProjY();
+  void           DelProj();
+  void           ZeroProjX();
+  void           ZeroProjY();
+  void           ZeroProj();
+  inline Histo*  HProjX() const {return hprojx;}
+  inline Histo*  HProjY() const {return hprojy;}
+  void           ShowProj();
+
+  // BANDES
+  inline int     NBandX() const {return lbandx.size();}
+  inline int     NBandY() const {return lbandy.size();}
+  int            SetBandX(float ybmin,float ybmax);
+  int            SetBandY(float xbmin,float xbmax);
+  void           DelBandX();
+  void           DelBandY();
+  void           ZeroBandX();
+  void           ZeroBandY();
+  Histo*         HBandX(int n) const;
+  Histo*         HBandY(int n) const;
+  void           GetBandX(int n,float& ybmin,float& ybmax) const;
+  void           GetBandY(int n,float& xbmin,float& xbmax) const;
+  void           ShowBand(int lp = 0);
+
+  // SLICES
+  inline int     NSliX() const {return lslix.size();}
+  inline int     NSliY() const {return lsliy.size();}
+  int            SetSliX(int nsli);
+  int            SetSliY(int nsli);
+  void           DelSliX();
+  void           DelSliY();
+  void           ZeroSliX();
+  void           ZeroSliY();
+  Histo*         HSliX(int n) const;
+  Histo*         HSliY(int n) const;
+  void           ShowSli(int lp = 0);
+
+#ifndef __DECCXX
+protected:
+#endif
+  struct bande_slice {
+    int num;
+    float min, max;
+    Histo* H;
+    STRUCTCOMP(bande_slice)
+  };
+#ifdef __DECCXX
+protected:
+#endif
+
+  void Delete();
+
+  float*         data;
+  double*        err2;
+
+  float          over[3][3];
+  double         nHist;
+  int_4          nEntries;
+
+  int_4          nx,ny,nxy;
+  float          xmin;
+  float          xmax;
+  float          ymin;
+  float          ymax;
+  float          wbinx;
+  float          wbiny;
+
+  bande_slice    b_s;
+
+  Histo*         hprojx;
+  Histo*         hprojy;
+
+  list<bande_slice>  lbandx;
+  list<bande_slice>  lbandy;
+  
+  list<bande_slice>  lslix;
+  list<bande_slice>  lsliy;
+
+};
+
+/////////////////////////////////////////////////////////////////////////
+// Classe pour la gestion de persistance
+
+inline POutPersist& operator << (POutPersist& os, Histo2D & obj)
+{ ObjFileIO<Histo2D> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, Histo2D & obj)
+{ ObjFileIO<Histo2D> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<Histo2D>
+
+} // Fin du namespace
+
+#endif // HISTOS2_SEEN
Index: /tags/V_Fev00/SophyaLib/NTools/imageop.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/imageop.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/imageop.cc	(revision 752)
@@ -0,0 +1,1313 @@
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "simplesort.h"
+#include "nbmath.h"
+#include "histos.h"
+#include "datatypes.h"
+#include "imageop.h"
+#include "nbtri.h"
+
+
+//++
+//  Module	Operations sur les images (C++)
+//  Lib	Images++
+//  include	imageop.h
+//
+//	Operations sur les images.
+//--
+
+
+// Outils prives.
+template <class T>
+float RzCmvSigmaCiel(T const * pix,int nx,int ny,int ndata,int bin,
+		     int taille,float frac,int deg,
+		     float low,float high,int deb);
+
+#ifdef IMGRGCHECK
+#define CHECKIMG2(_img_,_x_,_y_)                                  \
+      if ((_x_ >= (_img_).siz_x) || (_y_ >= (_img_).siz_y) ||              \
+          (_x_ < 0) || (_y_ < 0)) THROW(rangeCheckErr);  \
+      if (!(_img_).ImagePtr()) THROW(nullPtrErr)
+#else
+#if defined(IMGVOIDCHECK)
+#define CHECKIMG2(_img_,_x_,_y_) \
+      if (!(_img_).ImagePtr()) THROW(NullPtrErr)
+#else
+#define CHECKIMG2(_img_,_x_,_y_)
+#endif
+#endif /* IMGRGCHECK */
+
+// Les fonctions
+
+/* Nouvelle-Fonction */
+
+template <class T>
+void CleanImagesOld(int nImg, Image<T>** imgTab, double nSig,
+                 double lowbad, double highbad)
+
+/*  Nettoie une serie d'image a partir de l'histo de la  */
+/* serie de valeurs pour chaque pixel (Voir E. Aubourg)  */
+
+{
+  if (lowbad < MinRange((T)0))
+    lowbad = MinRange((T)0);
+
+  if (highbad > MaxRange((T)0))
+    highbad = MaxRange((T)0);
+
+  if (lowbad >= highbad)
+    {lowbad = MinRange((T)0); highbad = MaxRange((T)0);}
+  Histo h(lowbad, highbad, 500);
+
+  for (int i=0; i<imgTab[0]->XSize(); i++)
+    for (int j=0; j<imgTab[0]->YSize(); j++) {
+      h.Zero();
+      for (int k=0; k<nImg; k++)
+        h.Add((*imgTab[k])(i,j));
+      float x0, s0=0;
+      x0 = h.CleanedMean(s0);
+      float low = x0 - s0*nSig; if (low < lowbad) low = lowbad;
+      float hi  = x0 + s0*nSig; // if (hi  > highbad) hi = highbad;
+      for (k=0; k<nImg; k++)
+        if ((*imgTab[k])(i,j) > hi || (*imgTab[k])(i,j) < low)
+          (*imgTab[k])(i,j) = 0;
+    }
+}
+
+/* Nouvelle-Fonction */
+
+template <class T>
+//++
+void CleanImages(int nImg, Image<T>** imgTab, double nSig,
+                 double lowbad, double highbad)
+//
+//	Nettoie une serie de `nImg' images `imgTab' a partir
+//	d'une moyenne tronquee a `nSig' sigma
+//	de la serie de valeurs pour chaque pixel.
+//	Les valeurs des pixels sont prises entre `lowbad' et `highbad'.
+//--
+{
+  if (lowbad < MinRange((T)0))
+    lowbad = MinRange((T)0);
+
+  if (highbad > MaxRange((T)0))
+    highbad = MaxRange((T)0);
+
+  if (lowbad >= highbad)
+    {lowbad = MinRange((T)0); highbad = MaxRange((T)0);}
+  
+  double sx, sx2, sig, mean;
+  int n;
+
+  for (int i=0; i<imgTab[0]->XSize(); i++)
+    for (int j=0; j<imgTab[0]->YSize(); j++) {
+      sig = 1e20; mean = 0;
+      for (int l = 0; l<3; l++) {
+        double low = mean - nSig*sig;
+        if (low < lowbad) low = lowbad;
+        double high = mean + nSig*sig;
+        if (high > highbad) high = highbad;
+        sx = sx2 = n = 0;
+        for (int k=0; k<nImg; k++) {
+          double p = (*imgTab[k])(i,j);
+          if (p > low && p < high) {
+            sx += p;
+            sx2 += p*p;
+            n++;
+          }
+        }
+        if (n>0) {
+          mean = sx / n;
+          sig  = sqrt( sx2/n - (sx/n)*(sx/n) );
+        } // sinon on laisse tel quel, ca sera coupe...
+      }
+      double low = mean - nSig*sig;
+      if (low < lowbad) low = lowbad;
+      double high = mean + nSig*sig;
+      if (high > highbad) high = highbad;
+      for (int k=0; k<nImg; k++)
+        if ((*imgTab[k])(i,j) > high || (*imgTab[k])(i,j) < low)
+          (*imgTab[k])(i,j) = 0;
+    }
+}
+
+/* Nouvelle-Fonction */
+
+template <class T>
+//++
+float ImgFondCielHisto(Image<T> const& img, float binWidth, int degree, float frac,
+                       float low, float high, int debug)
+//
+//	Calcul du fond de ciel par histogrammation. L'histogramme
+//	va de `low' a `high' avec une largeur de bin `binWidth'.
+//	La valeur la plus probalbe est fittee par un polynome de degre
+//	`degree' en utilisant les bins entourant le maximum
+//	a `frac' pourcent de sa hauteur.
+//--
+{
+  // CHECKIMG2(img,0,0);
+
+  if (degree < 2 || degree > 3)
+    degree = 3;
+
+  if (frac <= 0 || frac >= 1)
+    frac = 0.5;
+
+  if (low < MinRange((T)0)+2)
+    low = MinRange((T)0)+2;
+
+  if (high > MaxRange((T)0)-2)
+    high = MaxRange((T)0)-2;
+
+  if (low >= high)
+    {low = MinRange((T)0); high = MaxRange((T)0);}
+
+// verifier binwidth
+
+//  if ( binWidth < 65536.0/img.XSize()*img.YSize() )
+//    binWidth = 65536.0/img.XSize()*img.YSize();
+
+  if (binWidth<0)
+    binWidth = 1;
+
+  if (debug > 1)
+    cout << __FUNCTION__ << " binWidth =" << binWidth <<
+      ", degree = " << degree <<
+      ", frac = "   << frac   <<
+      ", low = "    << low    <<
+      ", high = "   << high   << endl;
+
+  int nBins = int(((double)high-(double)low)/(double)binWidth + 1);
+  Histo hist(low, high, nBins);
+
+  int nPix = img.XSize()*img.YSize();
+  for (int i=0; i<nPix; i++)
+    hist.Add(img[i]);
+
+  hist(0) = 0;
+
+  float fd = hist.FitMax(degree, frac, debug);
+
+  (float&) img.fond = fd;
+
+  return fd;
+}
+
+
+/* Nouvelle-Fonction */
+
+template <class T>
+float ImgSigmaCiel(Image<T> const& img, int ndata, int binWidth,
+		   int taille, float frac, int degree,
+		   float low, float high, int debug)
+{
+  (float&) img.sigmaFond = RzCmvSigmaCiel(img.ImagePtr(), img.XSize(), img.YSize(),
+				 ndata, binWidth, taille, frac,
+				 degree, low, high, debug);
+  return img.sigmaFond;
+}
+
+
+/* Nouvelle-Fonction */
+
+template <class T>
+//++
+float RzCmvSigmaCiel(T const* pix,int nx,int ny,int ndata,int bin,
+		     int taille,float frac,int deg,
+		     float low,float high,int deb)
+//
+//	Calcul du fond de ciel par histogrammation
+//
+//| INPUT:
+//|   - pix   : tableau pix[nx][ny]
+//|   - nx,ny : dimensions du tableau pix
+//|   - ndata : nombre de donnees a utiliser
+//|   - bin   : largeur du bin en ADU
+//|   - taille: 1/2 dimension de l'histogramme en ADU
+//|   - frac  : fraction du maximum au dessus de laquelle on fite
+//|   - deg   : degre fit polynome sous la gaussienne (0 ou 2)
+//|   - low   : valeur basse limite en ADU
+//|   - high  : valeur haute limite en ADU
+//|   - deb   : flag de debug
+//--
+//++
+//| OUTPUT:
+//|   - retourne : le sigma du fond de ciel si OK
+//|                -1 si probleme definition
+//|                -2 si probleme allocation
+//|                -3 si probleme remplissage histogramme
+//|                -4 si probleme recherche maximum
+//|                -5 si probleme calcul fraction du maximum
+//|                -6 si probleme nombre de bin
+//|                -7 si probleme nombre de fit
+//| 
+//--
+//                // EA seul changement par rapport a la version C :
+//                // pix est un T*, en template. -> C++ necessaire.
+{
+FLOATDOUBLE X,Y,EY;
+double (*Fun) (double ,double *,double *);
+int_4 npar;
+double par[6], epar[6],minpar[6],maxpar[6],stepar[6],stochi2;
+int_4 i,j,i1,j1,j2,n,ip,nbin,inc,ibin0,max,imax,lmax,b1,b2;
+float *histo,*xbin,*ehisto,fwhm,rc;
+double vp,pxv;
+
+/* set reasonable parameters */
+Fun = Gauss1DPolF ;
+if ( deg<=1 ) deg=0;  else deg=2;
+low = ( low < 0 ) ? 0 : low;
+high = ( high > 65530 ) ? 65530 : high;
+if ( low >= high ) { low=0; high = 65530;}
+bin = ( bin <= 0 ) ? 1 : bin;
+nbin = int(2.*taille /bin + 1);
+if ( nbin < 20 ) nbin = 20;
+if ( nbin >= 65530 ) nbin = 65530;
+ibin0 = int(-nbin*bin/2.);
+inc = int(nx*ny / ndata); inc = int(sqrt( (double) inc ));
+inc = (inc<1) ? 1 : inc;
+if(deb>1)
+  { printf("Sigma_Ciel: pix[%d,%d] ndata=%d bin=%d taille=%d"
+          ,nx,ny,ndata,bin,taille);
+  printf(" frac=%f low=%g high=%g nbin=%d ibin0=%d inc=%d\n"
+        ,frac,low,high,nbin,ibin0,inc); }
+if ( nx < 5 || ny < 5 ) return (-1.);
+
+/* allocate place for histogramme */
+if ( (histo  = (float *) calloc(nbin, sizeof(float)) ) == NULL )
+       return(-2.);
+if ( (xbin   = (float *) calloc(nbin, sizeof(float)) ) == NULL )
+       {free(histo); return(-2.);}
+if ( (ehisto = (float *) calloc(nbin, sizeof(float)) ) == NULL )
+       {free(histo); free(xbin); return(-2.);}
+
+/* fill histogramme */
+ndata=0;
+for (j=1;j<ny-1;j=j+inc) { for (i=1;i<nx-1;i=i+inc) {
+  ip = (int)(*(pix+j*nx+i));
+  if ( ip < low || ip > high ) continue;
+  vp = (double) ip;
+  pxv = 0.; n=0;
+  for(j1=j-1;j1<=j+1;j1++) { for(i1=i-1;i1<=i+1;i1++) {
+    if ( i1 == i && j1 == j ) continue;
+    ip = (int)(*(pix+j1*nx+i1));
+    if ( ip < low || ip > high ) continue;
+    pxv += (double) ip;
+    n++;
+  } }
+  if ( n != 8 ) continue;
+  vp = vp - pxv/n;
+  ip = int((vp-ibin0)/bin);
+  if( ip<0 || ip >= nbin ) continue;
+  histo[ip]++;
+  ndata++;
+} }
+for(i=0;i<nbin;i++)
+  { xbin[i] = (float) ibin0 + ( (float) i + 0.5 ) * (float) bin;
+  ehisto[i] = (histo[i]<1.) ? -1. : sqrt((double) histo[i]);}
+
+if(deb>1) printf("     nombre de data corrects = %d\n",ndata);
+if( ndata < 1 ) {rc= -3.; goto END;}
+
+/* find maximum */
+max = -1; imax = -1;
+for(i=nbin-1;i>=0;i--) if(histo[i]>max) { max=int(histo[i]); imax=i;}
+if(deb>1) printf("     maxi histo = %d (bin=%d)\n",max,imax);
+if ( imax == -1 || imax == 0 || imax == nbin-1 ) {rc= -4.; goto END;}
+if(deb>2) {
+  for(i=imax-10;i<=imax+10;i++) if(i>=0 && i<nbin) printf(" %5f",xbin[i]);
+  printf("\n");
+  for(i=imax-10;i<=imax+10;i++) if(i>=0 && i<nbin) printf(" %5d",(int) histo[i]);
+  printf("\n"); }
+
+/* find limites a half maximum */
+lmax = (int) ( (float) max * 0.5 );
+for(b1=imax;b1>0;b1--)    if(histo[b1]<=lmax) break;
+for(b2=imax;b2<nbin;b2++)  if(histo[b2]<=lmax) break;
+fwhm = (xbin[b2]-xbin[b1]);
+if(deb>1) printf("     fwhm = %f (%d,%d)\n",fwhm,b1,b2);
+
+/* find limites a frac*max */
+lmax = (int) ( (float) max * frac ) + 1;
+if( lmax < 1 )
+   {if(deb>1) printf("     lmax=%d\n",lmax); rc= -5.; goto END;}
+for(b1=imax;b1>0;b1--)    if(histo[b1]<=lmax) break;
+for(b2=imax;b2<nbin;b2++)  if(histo[b2]<=lmax) break;
+
+n=0;
+for(i=b1;i<=b2;i++) if( histo[i] > 0 ) n++;
+if(deb>1) printf("     limites bin %d %d (v=%d) bin non nuls=%d\n"
+                ,b1,b2,lmax,n);
+/* pas assez de bin, on en ajoute artificiellement */
+/* 8 est une borne large pour fiter gauss + parab (3+3) */
+if( n < 8 ) {
+  j1 = b1; j2 = b2;
+  for(i=1;i<nbin;i++) {
+    if ( b1-i >= 0 ) j1=b1-i;
+    if ( b2+i < nbin ) j2=b2+i;
+    if ( histo[j1] > 0 ) n++;
+    if ( histo[j2] > 0 ) n++;
+    if( n >= 6 ) break;
+  }
+  b1 = j1; b2 = j2;
+  if(deb>1) printf("     Re-update des limites bin %d %d (v=%d) bin non nuls=%d\n"
+                  ,b1,b2,lmax,n);
+}
+if( n < 4 ) {rc= -6.; goto END;}
+ndata = n;
+
+/* fit dans les limites */
+npar = 3+deg+1; Set_FitFunDPol(deg);
+if(ndata<8) {npar=4; Set_FitFunDPol(0);}
+if(ndata<5) {npar=3; Set_FitFunDPol(-1);}
+X.fx  = xbin;
+Y.fx  = histo;
+EY.fx = ehisto;
+stochi2 = 0.0001;
+n = nbin;
+par[0] = max;
+par[1] = histo[imax-1]*xbin[imax-1]+histo[imax]*xbin[imax]+histo[imax+1]*xbin[imax+1];
+par[1] = par[1]/(histo[imax-1]+histo[imax]+histo[imax+1]);
+par[2] = (fwhm<1.) ? 1. : fwhm/2.36;
+par[3] = par[4] = par[5] = 0.;
+stepar[0] = par[0]/20.; stepar[1] = 1.; stepar[2] = par[2]/5.;
+stepar[3] = 1.; stepar[5] = 0.1;
+stepar[4] =  0.;
+for(i=0;i<6;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
+minpar[2] = 0.1; maxpar[2] = 65530.;
+if(deb>1) printf("     choix de fit a %d parametres b1=%d,b2=%d,ndata=%d)\n"
+                ,npar,b1,b2,ndata);
+
+i = (deb>=3) ? deb-2 : 0 ;
+vp = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,b1,b2,par
+           ,epar,stepar,minpar,maxpar,npar,stochi2,50,i);
+
+if( vp<=0. && vp != -4. ) {rc= -7.; goto END;}
+rc = par[2];
+if(deb>1) printf("     sigma=%f (h=%f centrage=%f) xi2=%f (%f pour %d)\n"
+                ,rc,par[0],par[1],vp,vp/(n-npar),npar);
+
+END:
+free(histo); free(xbin); free(ehisto);
+return(rc);
+}
+
+/* ................................................................................. */
+/*                  Filtrage ( Convolution ) d' images                               */
+/* ................................................................................. */
+
+/* Nouvelle-Fonction */
+template <class T>
+//++
+Image<T> * FilterImage(Image<T> const * pim, Image<T> * pom, ImageR4 *matx)
+//
+//	Filtrage ( Convolution ) d'une image `pim' par une matrice carree
+//	representee par l'ImageR4 `matx'.
+//	Le resultat se retrouve dans `pom'.
+//	Si `pom' = NULL, elle est cree.
+//	`pim' et `pom' doivent avoir la meme taille.
+//--
+{
+ 
+float vpix, *mxe;
+bool fgcr;
+int i,j,k,l,m,n;
+int ndim, nd2;
+
+fgcr = false;
+
+if ((pim == NULL) || (matx == NULL))
+  { printf(" FilterImage_Erreur : pim ou matx = NULL ! \n");
+  return(NULL);  }
+if (matx->XSize() != matx->YSize())
+  { printf("FilterImage_Erreur: Filtrage par matrice carre uniquement (%d,%d)\n",
+            matx->XSize(), matx->YSize());  return(NULL); }
+ndim = matx->XSize();
+if ( (ndim < 3) || ((ndim%2) == 0) || (ndim > 25))
+  { printf("FilterImage_Erreur: Pb dimension matrice (%d) (Impair, entre 3 et 25)\n", ndim);
+  return(NULL); }
+if (pom == NULL)
+  {  pom = new Image<T>(pim->XSize(), pim->YSize(), false);   fgcr = true; }
+
+if ( (pim->XSize() != pom->XSize()) || (pim->YSize() != pom->YSize()) )
+  { printf("FilterImage_Erreur : Taille pim et pom differentes ! \n") ;
+  if (fgcr) delete pom;   return(NULL) ;}
+
+nd2 = ndim/2;
+
+/*  Traitement de la partie centrale */
+for(j=nd2; j<(pom->YSize()-nd2); j++)
+  {
+  for(i=nd2; i<(pom->XSize()-nd2); i++)
+    {
+    vpix = 0.;   mxe = matx->ImagePtr();
+    for(l=-nd2; l<=nd2; l++)
+      for(k=-nd2; k<=nd2; k++)
+         { vpix += (float)((*pim)((i+k), (j+l))) * (*mxe);
+         mxe++; }
+    (*pom)(i, j) = (T)vpix;
+    }
+  }
+
+/*  Traitement bord en Y  en haut */
+for(j=0; j<nd2; j++)
+  {
+  for(i=nd2; i<(pom->XSize()-nd2); i++)
+    {
+    vpix = 0.;  mxe = matx->ImagePtr();
+    for(l=-nd2; l<=nd2; l++)
+
+      for(k=-nd2; k<=nd2; k++)
+        {
+        m = i+k;  n = j+l;
+        if (n < 0)  n = 0;
+        vpix += (float)((*pim)(m, n)) * (*mxe);
+        mxe++;
+        }
+    (*pom)(i, j) = (T)vpix;
+    }
+  }
+
+/* Traitement bord en Y en bas  */
+for(j=(pom->YSize()-nd2); j<pom->YSize(); j++)
+  {
+  for(i=nd2; i<(pom->XSize()-nd2); i++)
+    {
+    vpix = 0.;  mxe = matx->ImagePtr();
+    for(l=-nd2; l<=nd2; l++)
+      for(k=-nd2; k<=nd2; k++)
+        {
+        m = i+k;  n = j+l;
+        if (n >= pim->YSize())  n = (pim->YSize()-1);
+        vpix += (float)((*pim)(m, n)) * (*mxe);
+        mxe++;
+        }
+    (*pom)(i, j) = (T)vpix;
+    }
+  }
+
+/*  traitement bords en X et coins */
+for(j=0; j<pom->YSize(); j++)
+  {
+  for(i=0; i<nd2; i++)
+    {
+    vpix = 0.;  mxe = matx->ImagePtr();
+    for(l=-nd2; l<=nd2; l++)
+      for(k=-nd2; k<=nd2; k++)
+        {
+        m = i+k;  n = j+l;
+        if (m < 0)  m = 0;
+        if (n < 0)  n = 0;
+        if (n >= pim->YSize())  n = (pim->YSize()-1);
+        vpix += (float)((*pim)(m, n)) * (*mxe);
+        mxe++;
+        }
+    (*pom)(i, j) = (T)vpix;
+    }
+  for(i=(pom->XSize()-nd2); i<pom->XSize(); i++)
+    {
+    vpix = 0.;  mxe = matx->ImagePtr();
+    for(l=-nd2; l<=nd2; l++)
+      for(k=-nd2; k<=nd2; k++)
+        {
+        m = i+k;  n = j+l;
+        if (m >= pim->XSize())  m = (pim->XSize()-1);
+        if (n < 0)  n = 0;
+        if (n >= pim->YSize())  n = (pim->YSize()-1);
+        vpix += (float)((*pim)(m, n)) * (*mxe);
+        mxe++;
+        }
+    (*pom)(i, j) = (T)vpix;
+    }
+  }
+
+
+return(pom);
+
+}
+
+/* Nouvelle-Fonction */
+//++
+ImageR4* NoiseFiltImage(ImageR4& img, ImageR4& filtre, DynCCD& dynccd)
+//	Calcule une image de bruit, a partir de "img" et de "dynccd"
+//	prenant en compte le filtre de convolution "filtre".
+//	L'image de bruit renvoyee contient les correlations de bruit entre
+//	pixels, du au filtrage (convolution) de l'image "img" par le 
+//	filtre "filtre".
+//--
+{
+  ImageR4* ImgBrt = NoiseImage(&img,&dynccd);
+
+  int i,j;  
+  for (i=0; i<ImgBrt->XSize(); i++)
+    for (j=0; j<ImgBrt->YSize(); j++)  (*ImgBrt)(i,j) =(*ImgBrt)(i,j) *(*ImgBrt)(i,j);
+
+  ImageR4 Filter2(filtre.XSize(), filtre.YSize()) ;
+  for (i=0; i<filtre.XSize(); i++)
+    for (j=0; j<filtre.YSize(); j++) (Filter2)(i,j) = filtre(i,j) * filtre(i,j);  
+ 
+  ImageR4* out2;
+  out2 = new ImageR4(ImgBrt->XSize(), ImgBrt->YSize());
+  FilterImage(ImgBrt, out2, &Filter2);   
+  for (i=0; i<out2->XSize(); i++)
+    for (j=0; j<out2->YSize(); j++)  (*out2)(i,j) =sqrt((*out2)(i,j));
+  delete ImgBrt;
+  return(out2);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+/* Nouvelle-Fonction    CMV 14/10/97 */
+template <class T>
+//++
+Image<T> * FilterStat(Image<T> const * pim, Image<T> * pom
+                     ,int N,int M,float lowbad,float highbad)
+//
+//	Filtrage median d'une image `(*pim)'.
+//	Le resultat se retrouve dans `(*pom)'.
+//	Si pom = NULL l'image de sortie est cree automatiquement.
+//	pim et pom doivent avoir la meme taille.
+//	Le masque de calcul du filtre median est un rectangle `N'x`M'
+//	La dynamique de l'image est `lowbad,highbad'.
+//	Si lowbad>=highbad dynamique infinie.
+//--
+{
+if(pim == NULL)
+  {printf(" FilterStat_Erreur : pim = NULL ! \n");
+  return(NULL);}
+if( N<=0 || M<=0 )
+  {printf("FilterStat_Erreur: Filtrage par matrice (%d,%d)\n",N,M);
+  return(NULL);}
+bool fgcr = false;
+if(pom == NULL)
+  {pom = new Image<T>(pim->XSize(), pim->YSize(), false);   fgcr = true;}
+if( (pim->XSize() != pom->XSize()) || (pim->YSize() != pom->YSize()) )
+  { printf("FilterImage_Erreur : Taille pim et pom differentes ! \n");
+  if(fgcr) delete pom;   return(NULL);}
+
+T low  = (T) lowbad;
+T high = (T) highbad;
+if(high>low) fgcr = true; else fgcr = false;
+
+N /= 2; M /= 2;
+double * tab = new double[(2*N+1)*(2*M+1)];
+
+for(int j=0;j<pom->YSize();j++) {
+  for(int i=0;i<pom->XSize();i++) {
+    int n=0;
+    for(int jj=j-M;jj<=j+M;jj++) {
+      if( jj<0 || jj >= pom->YSize() ) continue;
+      for(int ii=i-N;ii<=i+N;ii++) {
+        if( ii<0 || ii >= pom->XSize() ) continue;
+          if( fgcr && ( (*pim)(ii,jj)<=low || high<=(*pim)(ii,jj) ) ) continue;
+          tab[n] = (double) (*pim)(ii,jj);
+          n++;
+      }
+    }
+    if(n==0) (*pom)(i,j) = 0;
+    else if(n==1) (*pom)(i,j) = (T) tab[0];
+    else {
+      HeapSort(n,tab);
+      if(n%2==1) (*pom)(i,j) = (T) tab[(n-1)/2];
+      else (*pom)(i,j) = (T) (tab[n/2]+tab[n/2-1])/2.;
+    }
+  }
+}
+
+delete [] tab;
+return(pom);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+/* Nouvelle-Fonction    CMV 7/8/98 */
+template <class T>
+//++
+Image<T> * CSplineImage(Image<T> const & f1,double pxsz,double x0,double y0,int natural)
+//
+//	Fonction retournant un pointeur sur une image qui contient
+//	le Spline 3 a 2 dimensions de l'images f1 (NULL est retourne si probleme).
+//	`pxsz' est la taille du pixel de l'image retournee en considerant
+//	que l'image `f1' en entree a une taille de pixel egale a 1.
+//	`x0,y0' est le decalage eventuel a appliquer de l'image origine a
+//	l'image retournee, ce decalage etant mesure en unites de pixels
+//	de l'image origine (1).
+//	`natural' a la signification decrite dans la classe `CSpline2'.
+//	Attention, la taille de l'image retournee sera `nx/pxsz' et `ny/pxsz'.
+//	Pour eviter les problemes d'extrapolation sur les bords de l'image
+//	d'origine, il leurs est assigne la valeur du centre du pixel auquel ils
+//	appartiennent.
+//--
+{
+//// open for result
+int nx = f1.XSize();
+int ny = f1.YSize();
+float dum;
+dum = nx/pxsz;
+int dx = (int) (dum+0.5);
+dum = ny/pxsz;
+int dy = (int) (dum+0.5);
+cout<<"Taille image en entree: "<<nx<<" "<<ny<<endl
+    <<"Taille image en sortie: "<<dx<<" "<<dy<<" (pix size="<<pxsz<<")"<<endl
+    <<"Decalage en x="<<x0<<" en y="<<y0<<endl;
+if(nx<=1 || ny<=1) return NULL;
+if(dx<=0 || dy<=0) return NULL;
+
+Image<T> *f2 = NULL;
+TRY {
+  f2 = new Image<T>(dx,dy);
+} CATCHALL {
+  cout<<"Impossible d'ouvrir le fichier resultat"<<endl;
+  return NULL;
+} ENDTRY
+
+//// Spline 3 2D ... nx+2 pour tenir compte des effets de bords !
+double *x = new double[nx+2];
+double *y = new double[ny+2];
+double *z = new double[(nx+2)*(ny+2)];
+{
+int k;
+// Centre pixel (0,0) en (0.5,0.5) et on ajoute les coordonnees
+// des bords pour extrapolation sur tout l'intervalle.
+// Les coordonnees vont de [0,nx] et [0,ny] (valeurs extremes comprises).
+x[0] = 0.; x[nx+1] = nx;
+y[0] = 0.; y[ny+1] = ny;
+for(k=1;k<=nx;k++) x[k] = k-0.5;
+for(k=1;k<=ny;k++) y[k] = k-0.5;
+// Remplissage des valeurs avec effet de bord [0] et [nx+1],[ny+1].
+k = 0;
+int ii,jj;
+for(int j=0;j<ny+2;j++) {
+  jj = j-1;
+  if(jj<0) jj=0; else if(jj>=ny) jj=ny-1;
+  for(int i=0;i<nx+2;i++) {
+    ii = i-1;
+    if(ii<0) ii=0; else if(ii>=nx) ii=nx-1;
+    z[k] = (double) f1(ii,jj);
+    k++;
+  }
+}
+}
+
+CSpline2 spl(nx+2,x,ny+2,y,z,natural,true);
+spl.ComputeCSpline();
+
+*f2 = 0.;
+{
+// Attention au decalage possible !
+// Les valeurs vont de [0.5*pxsz,(dx-0.5)*pxsz] idem pour y...
+// a corriger eventuellement du decalage x0,y0.
+double xmin = -pxsz/10000., xmax = nx+pxsz/10000.;
+double ymin = -pxsz/10000., ymax = ny+pxsz/10000.;
+for(int j=0;j<dy;j++) {
+  double yy = (j+0.5)*pxsz - y0;
+  if( yy<=ymin || yy>=ymax ) continue;
+  for(int i=0;i<dx;i++) {
+    double xx = (i+0.5)*pxsz - x0;
+    if( xx<=xmin || xx>=xmax ) continue;
+    (*f2)(i,j) = (T) spl.CSplineInt(xx,yy);
+}}}
+
+//// nettoyage
+delete [] x;
+delete [] y;
+delete [] z;
+
+return f2;
+}
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+/* Nouvelle-Fonction */
+int FondSigmaCiel(RzImage *pim, float low, float high,int pvsz
+              ,float nbsig1,float nbsig2,float nbsig3
+              ,float binsg,float frac,int modu,int deb)
+{
+int rc;
+
+  switch (pim->PixelType())
+    {
+    case kuint_2:
+      {
+      ImageU2 imt((RzImage&)(*pim));
+      rc = imt.FondSigmaCiel(low, high, pvsz, nbsig1, nbsig2, nbsig3, binsg, frac, modu, deb);
+      pim->fond = imt.fond;
+      pim->sigmaFond = imt.sigmaFond;
+      break;
+      }
+    case kint_2:
+      {
+      ImageI2 imt((RzImage&)(*pim));
+      rc = imt.FondSigmaCiel(low, high, pvsz, nbsig1, nbsig2, nbsig3, binsg, frac, modu, deb);
+      pim->fond = imt.fond;
+      pim->sigmaFond = imt.sigmaFond;
+      break;
+      }
+    case kint_4:
+      {
+      ImageI4 imt((RzImage&)(*pim));
+      rc = imt.FondSigmaCiel(low, high, pvsz, nbsig1, nbsig2, nbsig3, binsg, frac, modu, deb);
+      pim->fond = imt.fond;
+      pim->sigmaFond = imt.sigmaFond;
+      break;
+      }
+    case kr_4:
+      {
+      ImageR4 imt((RzImage&)(*pim));
+      rc = imt.FondSigmaCiel(low, high, pvsz, nbsig1, nbsig2, nbsig3, binsg, frac, modu, deb);
+      pim->fond = imt.fond;
+      pim->sigmaFond = imt.sigmaFond;
+      break;
+      }
+    default:
+      {
+      cout<<"FindSigmaCiel: type d'image non-prevu "<<(int) pim->PixelType()<<endl;
+      exit(-1);
+      }
+    }
+
+return(rc);
+}
+
+/* Nouvelle-Fonction */
+int CalFondImage(RzImage *pim, double low, double high, int action)
+
+/*  ATTENTION: Adaptation a partir d'une version C              */ 
+/*             CalculFond() de imgstat.c                        */
+ 
+/*  Cette fonction calcule le fond et le sigma du ciel a la CMV */
+/*  CMV / E.Aubourg / Reza                                      */
+/*  action Bit 0  CheckDyn()                                    */
+/*         Bit 1  ImgFondCielHisto()                            */
+/*         Bit 2  ImgSigmaCiel                                  */
+/*         Bit 3  FondSig2Ciel()                                */
+/*         Bit 1+2+3 (=14)   Fond_Ciel() + Sigma_Ciel() Si OK   */
+/*                            FondSig2Ciel()  sinon             */
+/*  action = 0  ou  >= 15  CheckDyn + Bit 1+2+3 (=14)           */
+/*  Rc=0 OK  Erreur Sinon                                       */
+/*  Sortie : Mise a jour de la struct RzImage                   */
+
+{
+int n,ok,rc,fga;
+float fnd, sg;
+
+int nbsig, vitesse, nbin;
+float minaff, maxaff, minpix, maxpix;
+float fracmax,fracnul,fracsat;
+char *meth;
+
+#define DBG  0
+
+if (action >= 15)   action = 15;
+if (action <= 0)  action = 15;
+fga = action;
+fnd = sg = -1.;
+ok = 1;
+
+if (action & 1)  
+  { pim->CheckDyn(low, high); 
+   action--;  }
+
+n = pim->XSize()*pim->YSize();
+
+if (action & 6)
+  {
+  int npu = (n/4 < 5000) ? 5000 : n/4;
+  meth = (char *)"Fond/Sig";
+  switch (pim->PixelType())
+    {
+    case kuint_2:
+      {
+      ImageU2 imt((RzImage&)(*pim));
+      if (action & 2) 
+        fnd = ImgFondCielHisto(imt, 1.0f, 2, 0.5f, (float)low, (float)high, DBG);
+      if (action & 4)
+        {  sg = ImgSigmaCiel(imt, npu, 1, 200, 0.1f, 2, 
+			     (float)low, (float)high, DBG);
+          if (sg < -1.e-3 )  ok = 0; }
+      break;
+      }
+    case kint_2:
+      {
+      ImageI2 imt((RzImage&)(*pim));
+      if (action & 2) 
+        fnd = ImgFondCielHisto(imt, 1.0f, 2, 0.5f, (float)low, (float)high, DBG);
+      if (action & 4)
+        {  sg = ImgSigmaCiel(imt, npu, 1, 200, 0.1f, 2,
+			     (float)low, (float)high, DBG);
+          if (sg < -1.e-3 )  ok = 0; }
+      break;
+      }
+    case kint_4:
+      {
+      ImageI4 imt((RzImage&)(*pim));
+      if (action & 2) 
+        fnd = ImgFondCielHisto(imt, 1.0f, 2, 0.5f, (float)low, (float)high, DBG);
+      if (action & 4)
+        {  sg = ImgSigmaCiel(imt, npu, 1, 200, 0.1f, 2, 
+			     (float)low, (float)high, DBG);
+          if (sg < -1.e-3 )  ok = 0; }
+      break;
+      }
+    case kr_4:
+      {
+      ImageR4 imt((RzImage&)(*pim));
+      if (action & 2) 
+        fnd = ImgFondCielHisto(imt, 1.0f, 2, 0.5f, (float)low, (float)high, DBG);
+      if (action & 4)
+        {  sg = ImgSigmaCiel(imt, npu, 1, 200, 0.1f, 2, 
+			     (float)low,(float) high, DBG);
+          if (sg < -1.e-3 )  ok = 0; }
+      break;
+      }
+
+    case kuint_4:
+    case kr_8:
+      cerr << "CalFondImage(RzImage *, ...) Unsupported image type (kuint_4/kr_8) " 
+           << (int) pim->PixelType() << "\n" ; 
+      break;
+    default:
+      cerr << "CalFondImage(RzImage *, ...) Unknown image type !! " << (int) pim->PixelType() << "\n" ;
+    break;
+    }
+
+  }
+
+if ( (action == 8) || (!ok && (action & 8)) )
+  {
+  fracmax = 0.85;   nbsig = 1;     vitesse = 3;
+  minpix = low;   maxpix = high;  nbin = 10000;
+  rc = RzFondSig2Ciel(pim, vitesse, fracmax, nbsig, nbin,  
+                      &minpix, &maxpix, &fnd, &sg,
+                      &minaff, &maxaff, &fracnul, &fracsat);
+  if (rc != 0)   ok = 0;
+  meth = (char *)"FondSig2";
+  }
+
+if (ok > 0)     /*  Mise a jour */ 
+  {
+  if (fnd > -1.)  pim->fond = fnd; 
+  if (sg > -1. )  pim->sigmaFond = sg;     
+  printf("CalculFond_Info: Meth=%s (%d) Fond/Sig= %5g %4g Nul/Sat=%d %d\n",
+         meth, fga, fnd, sg, pim->nbNul, pim->nbSat);
+  return(0);
+  }
+else
+  {
+  printf("CalculFond_Erreur: Action=%d  NbNul/Sat=%d %d\n",fga,
+          pim->nbNul, pim->nbSat);
+  return(1);
+  }
+
+}
+
+
+
+/* Nouvelle-Fonction */
+
+int RzFondSig2Ciel(RzImage * pim, int vitesse, float FracMax, int NbSigmas, int NBin,
+	           float *MinPix, float *MaxPix, float *Fond, float *SigFond,
+                   float *MinAff, float *MaxAff, float *FracNul, float *FracSature)
+
+/*   ATTENTION : Cette fonction a ete mis en C++, pour traiter des   */
+/*               RzImage a partir de la fonction FondSig2Ciel()      */
+/*               de imgstat.c                                        */
+/*                                        R. Ansari  04/95           */
+
+/*    Cette fonction calcule les valeurs suivantes pour une image    */
+/*    Arguments d'entree :                                           */
+/*     - pim : Pointeur RzImage                                      */
+/*     - vitesse : 1 pixel / vitesse pris en compte                  */
+/*     - FracMax : Parametre de calcul (voir ci-dessous)             */
+/*     - NbSigmas: MinAff =  Fond + NbSigmas*SigFond                 */
+/*       **Note : Si NbSigmas < 0 , on prend :                       */
+/*                 MinAff =  Fond + NbSigmas*SigFond                 */
+/*              et MaxAff =  Fond - NbSigmas*SigFond                 */
+/*         Dans ce cas la gamme d'affichage fait ressortir le fond.  */
+/*     - NBin : Nb de bins de l'histo                                */
+/*     - La valeur mini des pixels et la valeur de saturation        */
+/*       (ValNul et ValSat) doivent etre fournies ds Min/MaxPix      */
+/*              sorties :                                            */
+/*  - MinPix,MaxPix = Valeurs Min et Max des pixels  (<ValSat)       */
+/*  - Fond =  Pic de l'histo des pixels                              */
+/*  - SigFond = sigma du fond calcule par la relation                */
+/*     NbPixel(Fond+SigFond) =  Pic histo * 0.606 (=Exp(-0.5))       */
+/*  - MinAff = Bruit + NbSigmas * Sigma bruit                        */
+/*  - MaxAff est calcule tel que la relation suivante soit verifie   */
+/*     NbPixel(MinAff<Pixel<MaxAff) =  Nb de pixel entre Min-MaxAff  */
+/*      = FracMax * NbPixel(MinAff<Pixel<ValSat                      */
+/*  - FracNul = Nb pixel < ValNul / Nb total pixel                   */
+/*  - FracSat = Nb pixel satures (>ValSat) / Nb total pixel          */
+
+/*     return code : 0 OK , 1 Erreur calloc                          */
+/*                   2 : Pic histos non trouve                       */
+/*                   3,4 : Probleme de Min/MaxAff avec ValSat        */
+/*                   5 : Gamme dynamique minimale non respectee      */
+/*                         (MaxAff - MinAff > MINDYNAMIC             */
+
+{
+
+#define MINNBIN 100
+#define MAXNBIN 32765
+
+int nbin;
+
+float minhis = 0., maxhis = 65530. , binwidth;
+int xdim, ydim;
+int_4 under,over,tothis;
+int_4 *phis;
+float ValNul,ValSat;
+int_4 *q;
+
+float val;
+int i;
+float min, max;
+int_4 nbpix,nbpix2, imin, imax;
+int bin,binmax;
+int sigl,sigr;
+float fracfond,fracsignal;
+
+float MINDYNAMIC = 5;          /* Gamme dynamique minimale (MaxAff-MinAff)*/
+
+#define FRACPIC		0.6065     /*  Valeur de exp(-0.5)   */
+
+xdim = pim->XSize();
+ydim = pim->YSize();
+
+ValNul = *MinPix;
+ValSat = *MaxPix;
+if ((ValSat < ValNul+0.01))  ValSat = ValNul+0.01;  
+
+nbin = NBin;
+if (nbin < MINNBIN)  nbin = MINNBIN;
+if (nbin > MAXNBIN)  nbin = MAXNBIN;
+
+if (vitesse < 1)  vitesse = 1;
+if (vitesse > xdim*ydim/100)  vitesse = xdim*ydim/100;
+
+
+/*  Je modifie min et max histo et nbin en fonction de valnul et valsat */
+/*  je garde binwidth constant     */
+
+binwidth = (ValSat-ValNul) / nbin;
+minhis = ValNul;
+maxhis = minhis + nbin*binwidth;
+
+
+(*MinAff) = minhis;
+(*MaxAff) = maxhis;
+*MinPix = 0.;
+*MaxPix = -1.;
+*Fond = -1.;
+*SigFond = -1.;
+*FracNul = 0.0;
+*FracSature = 0.0;
+
+/* allocation dynamique de memoire */
+phis = new int_4[nbin];
+
+/* mise a zero de l'histogramme */
+for ( q=phis ; q<phis+nbin ; *q++ = 0 )  ;
+under = over = tothis = 0;
+
+
+
+nbpix2 = nbpix = 0;
+min = ValSat+1.;
+max = ValNul-1;
+
+/*   Boucle sur les pixels   */
+/*     Pour aller plus vite, on prend un pixel sur 7   */
+for ( i = 0 ; i < xdim*ydim ; i += vitesse )
+  {
+  val = pim->IValue(i);
+
+   /*   Calcul PixMax/Min et NbPix sature  */
+  if (val > ValSat)  nbpix++;
+  else {
+    if(val < ValNul) nbpix2++;
+    else {
+	    if (val > max) max = val;
+	    else if (val < min) min = val;
+	}
+  }
+
+   /* remplissage de l'histogramme */
+  bin = (int)((val - minhis) / binwidth) ;
+  if ( bin < 0 )  under++;
+  else 
+    {
+    if (bin < nbin) { (*(phis+bin))++; tothis++; }
+    else   over++; 
+    }
+  }     /*  Fin de for : Boucle sur les pixels   */
+
+(*MinPix) = min; 
+(*MaxPix) = max;
+/*       Ne pas oublier le facteur vitesse pour le calcul FracSatue  */
+(*FracNul) = (float)(nbpix2 * vitesse) / (float)(xdim*ydim); 
+(*FracSature) = (float)(nbpix * vitesse) / (float)(xdim*ydim); 
+
+/*  On verifie qu'il y a eu une entree ds l'histo */
+if (tothis <= 0)
+  { delete[] phis;  return(2); }
+  
+/* recherche du maximum */
+binmax = -1 ; imax = -1 ; q = phis;
+for ( i = 0 ; i < nbin ;  i++, q++ )
+  if ( *(q) > imax ) {imax = *(q) ; binmax = i ;}
+
+if ( (binmax < 0) || (binmax >= nbin) )
+  { delete[] phis;  return(2); }
+
+*Fond = minhis + binmax * binwidth;   
+
+/*   On va chercher le sigma du fond  */
+imin = (int_4) ( (float)(imax) * FRACPIC ) ;
+
+/*
+printf("StatsDebug : min/maxhis  %g  %g  (nbin= %d) w=%g\n",
+        minhis,maxhis,nbin,binwidth);
+printf(".binmax= %d  imax(=pic) = %d  , imin= %d  \n ",binmax,imax,imin);   
+*/
+
+nbpix = 0;
+
+sigr = 0;
+q = phis+binmax;
+while ( ((*q) > imin) && (sigr < (nbin-binmax)) ) 
+  { sigr++; nbpix += (*q) ; q++; }
+
+sigl = 0;
+q = phis+binmax;
+while ( ((*q) > imin) && (sigl < binmax) ) 
+  { sigl++; nbpix += (*q) ; q--; }
+nbpix -= (*(phis+binmax));
+
+(*SigFond) = (float)(sigl+sigr)*binwidth/2.; 
+fracfond = (float)(nbpix) / (float)(tothis);
+
+(*MinAff) = minhis+(binmax-sigl)*binwidth;
+(*MaxAff) = minhis+(binmax+sigr)*binwidth;
+
+
+/*   Check sur NbSigmas  :  */
+if (NbSigmas == 0) NbSigmas = 1;
+if (NbSigmas < 0)    /*   On considere le cas ou NbSigmas est negatif   */
+  {
+  if ( (bin = binmax+NbSigmas*sigr) < 0 )  bin = 0;
+  (*MinAff) = minhis + (float)bin*binwidth;
+  if ( (bin = binmax-NbSigmas*sigr) >= nbin ) bin = nbin-1;
+  (*MaxAff) = minhis + (float)bin*binwidth;
+  goto sortie;
+  }
+
+if ( (bin = binmax+NbSigmas*sigl) >= nbin ) 
+  { delete[] phis;  return(4); }
+
+(*MinAff) = minhis + bin*binwidth;
+
+/*   Calcul du nb de pixel entre MinAff et ValSat  */
+nbpix = 0;
+for( q = phis+bin ; q < phis+nbin ; q++)  nbpix += (*q);
+
+fracsignal = (float)(nbpix) / (float)(tothis+over+under);
+nbpix = (int_4)((float)nbpix * FracMax);
+nbpix2 = 0; q = phis+bin; i = bin;
+while( (nbpix2 < nbpix) && (i < nbin) )  
+  { nbpix2 += (*q); i++; q++; }
+
+(*MaxAff) = minhis + (float)i*binwidth;
+
+
+sortie:        /*   On sort en liberant l'espace   */
+
+/*
+printf("  Stats..Debug : Fond,sigl,sigr,SigFond = %g,%d,%d,%g \n",
+(*Fond),sigl,sigr,(*SigFond));
+ printf("    Min/MaxPix= %g  %g , Min/MaxAff= %g  %g \n",(*MinPix),
+(*MaxPix),(*MinAff),(*MaxAff));
+printf("    FracFond,FracSignal %g  %g  FracNul,FracSat  %g  %g\n",
+       fracfond,fracsignal,(*FracNul),(*FracSature));   
+*/
+
+delete[] phis;
+if ( (*MaxAff) < ((*MinAff)+MINDYNAMIC) )  return(5);
+return(0);
+
+}
+
+
+// ********** INSTANCES
+
+#if defined(__xlC) || defined(__aCC__)
+void instancetempimageop(int n)
+{
+/* Cette fonction sert uniquement a forcer le compilo a instancier les
+  classes/fonctions template   */
+
+int m = n-50;
+ImageU2  iu2(n,n), *tiu2[5], xiu2(n,n);
+ImageI2  ii2(n,n), *tii2[5], xii2(n,n);
+ImageI4  ii4(n,n), *tii4[5], xii4(n,n);
+ImageR4  ir4(n,n), *tir4[5], xir4(n,n);
+
+ImageR4  matx(5,5);
+
+RzCmvSigmaCiel(iu2.ImagePtr(), n, n, 100, 50, 50, (float)0.5, 2, (float)0., (float)65000., 0);
+RzCmvSigmaCiel(ii2.ImagePtr(), n, n, 100, 50, 50, (float)0.5, 2, (float)0., (float)65000., 0);
+RzCmvSigmaCiel(ii4.ImagePtr(), n, n, 100, 50, 50, (float)0.5, 2, (float)0., (float)65000., 0);
+RzCmvSigmaCiel(ir4.ImagePtr(), n, n, 100, 50, 50, (float)0.5, 2, (float)0., (float)65000., 0);
+
+ImgFondCielHisto(iu2);
+ImgFondCielHisto(ii2);
+ImgFondCielHisto(ii4);
+ImgFondCielHisto(ir4);
+
+ImgSigmaCiel(iu2, 100, 1, 100);
+ImgSigmaCiel(ii2, 100, 1, 100);
+ImgSigmaCiel(ii4, 100, 1, 100);
+ImgSigmaCiel(ir4, 100, 1, 100);
+
+CleanImages(5, tiu2); 
+CleanImages(5, tii2); 
+CleanImages(5, tii4); 
+CleanImages(5, tir4); 
+
+
+FilterImage(&iu2, &xiu2, &matx);
+FilterImage(&ii2, &xii2, &matx);
+FilterImage(&ii4, &xii4, &matx);
+FilterImage(&ir4, &xir4, &matx);
+
+FilterStat(&iu2, &xiu2,(int)3,(int)3,(float)1.,(float)-1.);
+FilterStat(&ii2, &xii2,(int)3,(int)3,(float)1.,(float)-1.);
+FilterStat(&ii4, &xii4,(int)3,(int)3,(float)1.,(float)-1.);
+FilterStat(&ir4, &xir4,(int)3,(int)3,(float)1.,(float)-1.);
+
+CSplineImage(iu2,(double)1,(double)0,(double)0,(int)0);
+CSplineImage(ii2,(double)1,(double)0,(double)0,(int)0);
+CSplineImage(ii4,(double)1,(double)0,(double)0,(int)0);
+CSplineImage(ir4,(double)1,(double)0,(double)0,(int)0);
+
+return;
+}
+
+#endif
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+
+#pragma define_template RzCmvSigmaCiel<uint_2>
+#pragma define_template RzCmvSigmaCiel<int_2>
+#pragma define_template RzCmvSigmaCiel<int_4>
+#pragma define_template RzCmvSigmaCiel<r_4>
+
+#pragma define_template ImgFondCielHisto<uint_2>
+#pragma define_template ImgFondCielHisto<int_2>
+#pragma define_template ImgFondCielHisto<int_4>
+#pragma define_template ImgFondCielHisto<r_4>
+
+#pragma define_template ImgSigmaCiel<uint_2>
+#pragma define_template ImgSigmaCiel<int_2>
+#pragma define_template ImgSigmaCiel<int_4>
+#pragma define_template ImgSigmaCiel<r_4>
+
+#pragma define_template CleanImages<uint_2>
+#pragma define_template CleanImages<int_2>
+#pragma define_template CleanImages<int_4>
+#pragma define_template CleanImages<r_4>
+
+
+#pragma define_template FilterImage<uint_2>
+#pragma define_template FilterImage<int_2>
+#pragma define_template FilterImage<int_4>
+#pragma define_template FilterImage<r_4>
+
+#pragma define_template FilterStat<uint_2>
+#pragma define_template FilterStat<int_2>
+#pragma define_template FilterStat<int_4>
+#pragma define_template FilterStat<r_4>
+
+#pragma define_template CSplineImage<uint_2>
+#pragma define_template CSplineImage<int_2>
+#pragma define_template CSplineImage<int_4>
+#pragma define_template CSplineImage<r_4>
+
+#endif
+
+
+#if ( defined(ANSI_TEMPLATES) && !defined(__aCC__) )
+template float RzCmvSigmaCiel<uint_2 const>(uint_2 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel< int_2 const>( int_2 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel< int_4 const>( int_4 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel<   r_4 const>(   r_4 const*, int, int, int, int, int, float, int, float, float, int);
+template float ImgFondCielHisto<uint_2>(Image<uint_2> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto< int_2>(Image< int_2> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto< int_4>(Image< int_4> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto<   r_4>(Image<   r_4> const&, float, int, float, float , float , int);
+template float ImgSigmaCiel<uint_2>(Image<uint_2> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel< int_2>(Image< int_2> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel< int_4>(Image< int_4> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel<   r_4>(Image<   r_4> const& img, int, int, int, float, int, float , float, int);
+template void CleanImages<uint_2>(int, Image<uint_2>**, double, double, double);
+template void CleanImages< int_2>(int, Image< int_2>**, double, double, double);
+template void CleanImages< int_4>(int, Image< int_4>**, double, double, double);
+template void CleanImages<   r_4>(int, Image<   r_4>**, double, double, double);
+
+
+template Image<uint_2>* FilterImage<uint_2>(Image<uint_2> const *, Image<uint_2>*, ImageR4 *);
+template Image< int_2>* FilterImage< int_2>(Image< int_2> const *, Image< int_2>*, ImageR4 *);
+template Image< int_4>* FilterImage< int_4>(Image< int_4> const *, Image< int_4>*, ImageR4 *);
+template Image<   r_4>* FilterImage<   r_4>(Image<   r_4> const *, Image<   r_4>*, ImageR4 *);
+
+template Image<uint_2>* FilterStat<uint_2>(Image<uint_2> const *, Image<uint_2>*,int,int,float,float);
+template Image< int_2>* FilterStat< int_2>(Image< int_2> const *, Image< int_2>*,int,int,float,float);
+template Image< int_4>* FilterStat< int_4>(Image< int_4> const *, Image< int_4>*,int,int,float,float);
+template Image<   r_4>* FilterStat<   r_4>(Image<   r_4> const *, Image<   r_4>*,int,int,float,float);
+
+template Image<uint_2>* CSplineImage<uint_2>(Image<uint_2> const &,double,double,double,int);
+template Image< int_2>* CSplineImage< int_2>(Image< int_2> const &,double,double,double,int);
+template Image< int_4>* CSplineImage< int_4>(Image< int_4> const &,double,double,double,int);
+template Image<   r_4>* CSplineImage<   r_4>(Image<   r_4> const &,double,double,double,int);
+
+#endif
+
+
+#ifdef GNU_TEMPLATES
+template float RzCmvSigmaCiel(uint_2 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel( int_2 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel( int_4 const*, int, int, int, int, int, float, int, float, float, int);
+template float RzCmvSigmaCiel(   r_4 const*, int, int, int, int, int, float, int, float, float, int);
+template float ImgFondCielHisto(Image<uint_2> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto(Image< int_2> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto(Image< int_4> const&, float, int, float, float , float , int);
+template float ImgFondCielHisto(Image<   r_4> const&, float, int, float, float , float , int);
+template float ImgSigmaCiel(Image<uint_2> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel(Image< int_2> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel(Image< int_4> const& img, int, int, int, float, int, float , float, int);
+template float ImgSigmaCiel(Image<   r_4> const& img, int, int, int, float, int, float , float, int);
+template void CleanImages(int, Image<uint_2>**, double, double, double);
+template void CleanImages(int, Image< int_2>**, double, double, double);
+template void CleanImages(int, Image< int_4>**, double, double, double);
+template void CleanImages(int, Image<   r_4>**, double, double, double);
+
+
+template Image<uint_2>* FilterImage(Image<uint_2> const *, Image<uint_2>*, ImageR4 *);
+template Image< int_2>* FilterImage(Image< int_2> const *, Image< int_2>*, ImageR4 *);
+template Image< int_4>* FilterImage(Image< int_4> const *, Image< int_4>*, ImageR4 *);
+template Image<   r_4>* FilterImage(Image<   r_4> const *, Image<   r_4>*, ImageR4 *);
+
+template Image<uint_2>* FilterStat(Image<uint_2> const *, Image<uint_2>*,int,int,float,float);
+template Image< int_2>* FilterStat(Image< int_2> const *, Image< int_2>*,int,int,float,float);
+template Image< int_4>* FilterStat(Image< int_4> const *, Image< int_4>*,int,int,float,float);
+template Image<   r_4>* FilterStat(Image<   r_4> const *, Image<   r_4>*,int,int,float,float);
+
+template Image<uint_2>* CSplineImage(Image<uint_2> const &,double,double,double,int);
+template Image< int_2>* CSplineImage(Image< int_2> const &,double,double,double,int);
+template Image< int_4>* CSplineImage(Image< int_4> const &,double,double,double,int);
+template Image<   r_4>* CSplineImage(Image<   r_4> const &,double,double,double,int);
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/imageop.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/imageop.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/imageop.h	(revision 752)
@@ -0,0 +1,69 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+// Operations non elementaires sur les images.
+// Les operations elementaires sont des methodes de la classe.
+
+//    C. Magneville  (Version C)  E. Aubourg / R. Ansari C++
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef IMAGEOP_H_SEEN
+#define IMAGEOP_H_SEEN
+
+#include "cimage.h"
+#include "cspline.h"
+#include "dynccd.h"
+
+template <class T>
+void CleanImages(int nImg, Image<T>** imgTab, double nSig=1,
+                 double lowbad=-1e20, double highbad=1e20);
+
+
+template <class T>
+float ImgFondCielHisto(Image<T> const& img, float binWidth=1, int degre=2, 
+                       float frac=0.5f,
+                       float low=-999999.0, float high=999999.0,
+                       int debug=0);
+template <class T>
+float ImgSigmaCiel(Image<T> const& img, int ndata, int binWidth, int taille,
+                   float frac=0.5f, int degre=2,
+                   float low=-999999.0, float high=999999.0,
+                   int debug=0);
+
+int CalFondImage(RzImage *pim, double low, double high, int action);
+
+int FondSigmaCiel(RzImage *pim, float low, float high, int pvsz=100
+              ,float nbsig1=3.5f,float nbsig2=7.f,float nbsig3=5.f
+              ,float binsg=0.5f,float frac=0.33f,int modu=1,int deb=0);
+
+int RzFondSig2Ciel(RzImage * pim, int vitesse, float FracMax, int NbSigmas, int NBin, 
+	               float *MinPix, float *MaxPix, float *Fond, float *SigFond,
+                   float *MinAff, float *MaxAff, float *FracNul, float *FracSature);
+
+template <class T>
+float FondLocal(Image<T> const & image, float xcentre, float ycentre,
+                float rayon1, float rayon2, float fraclow, float frachigh, int lp=0);
+
+// Filtrage / convolution d'images 
+
+template <class T>
+Image<T> * FilterImage(Image<T> const * pim, Image<T> * pom, ImageR4 *matx);
+
+// Calcul une image de bruit prenant en compte le filtre de convolution
+ImageR4* NoiseFiltImage(ImageR4& img, ImageR4& filtre, DynCCD& dynccd);
+
+///////////////////////////////////////////////////////////////////
+//// Filtre statistique d'images
+template <class T>
+Image<T> * FilterStat(Image<T> const * pim, Image<T> * pom
+                     ,int N,int M,float lowbad,float highbad);
+///////////////////////////////////////////////////////////////////
+//// Spline d'images
+template <class T>
+Image<T> * CSplineImage(Image<T> const& f1,double pxsz=1.,double x0=0.,double y0=0.
+                       ,int natural=(int)CSpline::NaturalAll);
+///////////////////////////////////////////////////////////////////
+
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/integ.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/integ.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/integ.cc	(revision 752)
@@ -0,0 +1,473 @@
+#include "integ.h"
+#include "generalfit.h"
+
+// A faire :
+//   1 dans GLInteg, optimiser recalcul en utilisant des poids
+//     calcules sur [0,1] et chgt de variable
+//   2 dans GLInteg, distinction nStep = subdivisions de l'intervalle,
+//     et on applique GL d'ordre "ordre" sur chaque subdivision, en
+//     utilisant le (1)
+
+//++
+// Class	Integrator
+// Lib		Outils++ 
+// include	integ.h
+//
+//	Classe abstraite d'intégration numérique 1D.
+//	On fournit une fonction double f(double) au constructeur, ou
+//	une GeneralFunction avec des paramètres définis.
+//	L'objet Integrator est convertible en valeur double qui est la valeur
+//	de l'intégrale. Diverses méthodes permettent de choisir des options
+//	de calcul, et ces méthodes retournent une référence sur l'objet, pour
+//	permettre une notation chaînée.
+//--
+//++ 
+// Links	Implementations
+// TrpzInteg
+// GLInteg
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+Integrator::Integrator()
+//
+//	Constructeur par défaut. L'objet n'est pas utilisable en l'état.
+//--
+
+: mFunc(NULL), mGFF(NULL), mGFFParm(NULL),
+  mNStep(50), mDX(-1), mReqPrec(-1),
+  mXMin(0), mXMax(1)
+{}
+
+//++
+Integrator::Integrator(FUNC f, double xmin, double xmax)
+//
+//	Constructeur à partir de la fonction double->double, et des
+//	bornes d'intégration.
+//--
+: mFunc(f), mGFF(NULL), mGFFParm(NULL),
+  mNStep(50), mDX(-1), mReqPrec(-1),
+  mXMin(xmin), mXMax(xmax)
+{}
+
+//++
+Integrator::Integrator(FUNC f)
+// 
+//	Constructeur sans spécifier les bornes. Elles sont positionnées
+//	à [0,1], et on pourra les modifier plus tard.
+//--
+: mFunc(f), mGFF(NULL), mGFFParm(NULL),
+  mNStep(50), mDX(-1), mReqPrec(-1),
+  mXMin(0), mXMax(1)
+{}
+
+//++
+Integrator::Integrator(GeneralFunction* gff, double* par, double xmin, double xmax)
+//
+//	Constructeur à partir d'une GeneralFunction. La fonction doit être une
+//	fonction de une variable, et on fournit les valeurs des paramètres ainsi
+//	que les bornes d'intégration.
+//--
+: mFunc(NULL), mGFF(gff), mGFFParm(par),
+  mNStep(50), mDX(-1), mReqPrec(-1),
+  mXMin(xmin), mXMax(xmax)
+{
+  DBASSERT(gff->NVar() == 1);
+}
+
+//++
+Integrator::Integrator(GeneralFunction* gff, double* par)
+//
+//	Constructeur à partir d'une GeneralFunction. La fonction doit être une
+//	fonction de une variable, et on fournit les valeurs des paramètres. 
+//	On ne spécifie pas les bornes. Elles sont positionnées
+//	à [0,1], et on pourra les modifier plus tard.
+//--
+: mFunc(NULL), mGFF(gff), mGFFParm(par),
+  mNStep(50), mDX(-1), mReqPrec(-1),
+  mXMin(0), mXMax(1)
+{
+  DBASSERT(gff->NVar() == 1);
+}
+
+Integrator::~Integrator()
+{}
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+Integrator& 
+Integrator::NStep(int n)
+//
+//	Spécifie le nombre de pas pour l'intégration numérique.
+//	La signification peut dépendre de la méthode d'intégration.
+//--
+{
+  mNStep = n;
+  mDX = mReqPrec = -1;
+  StepsChanged();
+  return *this;
+}
+
+//++
+Integrator& 
+Integrator::DX(double d)
+//
+//	Spécifie le pas d'intégration.
+//	La signification peut dépendre de la méthode d'intégration.
+//--
+{
+  mDX = d;
+  mNStep = mReqPrec = -1;
+  StepsChanged();
+  return *this;
+}
+
+//++
+Integrator& 
+Integrator::ReqPrec(double p)
+//
+//	Spécifie la précision souhaitée. 
+//	La signification peut dépendre de la méthode d'intégration.
+//	Non disponible dans toutes les méthodes d'intégration.
+//--
+{
+  DBASSERT( !"Pas encore implemente !");
+  mReqPrec = p;
+  mDX = mNStep = -1;
+  StepsChanged();
+  return *this;
+}
+
+//++
+Integrator& 
+Integrator::Limits(double xmin, double xmax)
+//
+//	Spécifie les bornes de l'intégrale.
+//--
+{
+  mXMin = xmin;
+  mXMax = xmax;
+  LimitsChanged();
+  return *this;
+}
+
+//++
+Integrator& 
+Integrator::Func(FUNC f)
+//
+//	Spécifie la fonction à intégrer, sous forme double f(double).
+//--
+{
+  mFunc = f;
+  mGFFParm = NULL;
+  mFunc = NULL;
+  FuncChanged();
+  return *this;
+}
+
+//++
+Integrator& 
+Integrator::Func(GeneralFunction* gff, double* par)
+//
+//	Spécifie la fonction à intégrer, sous forme de GeneralFunction
+//	à une variable, et les paramètres sont fournis.
+//--
+{
+  mGFF = gff;
+  mGFFParm = par;
+  mFunc = NULL;
+  DBASSERT(gff->NVar() == 1);
+  FuncChanged();
+  return *this;
+}
+
+double
+Integrator::FVal(double x) const
+{
+  DBASSERT( mFunc || (mGFF && mGFFParm) );
+  return mFunc ? (*mFunc)(x) : mGFF->Value(&x, mGFFParm); 
+}
+
+double
+Integrator::ValueBetween(double xmin, double xmax)
+{
+  Limits(xmin,xmax);
+  return Value();
+}
+
+//++
+// Class	TrpzInteg
+// Lib		Outils++ 
+// include	integ.h
+//
+//	Classe d'intégration par la méthode des trapèzes.
+//	Voir Integrator pour les méthodes. Le nombre de pas
+//	est le nombre de trapèze, le pas d'intégration est
+//	la largeur des trapèzez. Impossible de demander une
+//	précision.
+//
+//--
+//++
+// Links	Parents
+// Integrator
+//--
+
+//++
+// Titre	Constructeurs
+//	Voir Integrator pour les détails.
+//--
+
+//++
+TrpzInteg::TrpzInteg()
+//
+//--
+{}
+
+//++
+TrpzInteg::TrpzInteg(FUNC f, double xmin, double xmax)
+//
+//--
+: Integrator(f, xmin, xmax)
+{}
+
+//++
+TrpzInteg::TrpzInteg(FUNC f)
+//
+//--
+: Integrator(f)
+{}
+
+//++
+TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
+//
+//--
+: Integrator(gff, par, xmin, xmax)
+{}
+
+//++
+TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par)
+//
+//--
+: Integrator(gff, par)
+{}
+
+TrpzInteg::~TrpzInteg()
+{}
+
+double
+TrpzInteg::Value()
+{
+  double dx = mDX;
+  double nstep = mNStep;
+
+  if (dx > 0)
+    nstep = (mXMax - mXMin)/dx;
+
+  if (nstep <= 0)
+    nstep = 10;
+
+  dx = (mXMax - mXMin) / nstep;
+
+  double s = (FVal(mXMin) + FVal(mXMax))/2;
+  double x = dx + mXMin;
+  for (int i=1; i<nstep; i++, x += dx)
+    s += FVal(x);
+    
+  return s * dx;
+}
+
+
+
+//++
+// Class	GLInteg
+// Lib		Outils++ 
+// include	integ.h
+//
+//	Classe d'intégration par la méthode de Gauss-Legendre.
+//	Voir Integrator pour les méthodes. 
+//	Pour le moment, nstep est l'ordre de la méthode.
+//	Il est prévu un jour de spécifier l'ordre, et que NStep
+//	découpe en intervalles sur chacun desquels on applique GL.
+//	Le principe de la méthode est de calculer les valeurs de la 
+//	fonction aux zéros des polynomes de Legendre. Avec les poids
+//	qui vont bien, GL d'ordre n est exacte pour des polynomes de 
+//	degré <= 2n+1.
+//	Impossible de demander une précision donnée.
+//
+//--
+//++
+// Links	Parents
+// Integrator
+//--
+
+//++
+// Titre	Constructeurs
+//	Voir Integrator pour les détails.
+//--
+
+
+
+
+//++
+GLInteg::GLInteg()
+//
+//--
+: mXPos(NULL), mWeights(NULL)
+{}
+
+
+//++
+GLInteg::GLInteg(FUNC f, double xmin, double xmax)
+//
+//--
+: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
+{
+  NStep(1);
+}
+
+//++
+GLInteg::GLInteg(FUNC f)
+//
+//--
+: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
+{
+  NStep(1);
+}
+
+//++
+GLInteg::GLInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
+//
+//--
+: Integrator(gff, par, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
+{
+  NStep(1);
+}
+
+//++
+GLInteg::GLInteg(GeneralFunction* gff, double* par)
+//
+//--
+: Integrator(gff, par), mXPos(NULL), mWeights(NULL), mOrder(8)
+{
+  NStep(1);
+}
+
+GLInteg::~GLInteg()
+{
+  delete[] mXPos;
+  delete[] mWeights;
+  mXPos = mWeights = NULL;
+}
+
+void
+GLInteg::InvalWeights()
+{
+  delete[] mXPos;
+  delete[] mWeights;
+  mXPos = mWeights = NULL;
+}
+
+
+void
+GLInteg::LimitsChanged()
+{
+  ComputeBounds();
+}
+
+void
+GLInteg::StepsChanged()
+{
+  ComputeBounds();
+}
+
+GLInteg&
+GLInteg::AddBound(double x)
+{
+  if (x<=mXMin || x>=mXMax) THROW(rangeCheckErr); 
+  // On introduira les classes d'exections apres reflexion et de maniere systematique (Rz+cmv)
+  // if (x<=mXMin || x>=mXMax) throw range_error("GLInteg::AddBound  bound outside interval");
+  mBounds.insert(x);
+  return *this;
+}
+
+
+GLInteg&
+GLInteg::SetOrder(int order)
+{
+  mOrder = order;
+  InvalWeights();
+  return *this;
+}
+
+
+
+double
+GLInteg::Value()
+{
+  if (!mXPos) ComputeWeights();
+  double s = 0;
+  set<double>::iterator i=mBounds.begin();
+  set<double>::iterator j=i; j++;
+  while (j != mBounds.end()) {
+    double s1 = 0;
+    double x1 = *i;
+    double x2 = *j;
+    for (int k=0; k<mOrder; k++)
+       s1 += mWeights[k] * FVal(x1 + (x2-x1)*mXPos[k]);
+    s += s1*(x2-x1);
+    i++; j++;
+  }
+  return s;
+}
+
+void
+GLInteg::ComputeBounds()
+{
+  mBounds.erase(mBounds.begin(), mBounds.end());
+  for (int i=0; i<=mNStep; i++) 
+    mBounds.insert(mXMin + (mXMax-mXMin)*i/mNStep);
+}
+
+void
+GLInteg::ComputeWeights()
+{
+   const double EPS_gauleg = 3.0e-11;
+
+   int m=(mOrder+1)/2;
+   const double xxMin = 0;
+   const double xxMax = 1;
+   
+   mXPos    = new double[mOrder];
+   mWeights = new double[mOrder];
+   
+   double xm=0.5*(xxMax+xxMin);
+   double xl=0.5*(xxMax-xxMin);
+   for (int i=1;i<=m;i++)  {
+      double z=cos(3.141592654*(i-0.25)/(mOrder+0.5));
+      double z1, pp;
+      do {
+         double p1=1.0;
+         double p2=0.0;
+         for (int j=1;j<=mOrder;j++) {
+            double p3=p2;
+            p2=p1;
+            p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
+         }
+         pp=mOrder*(z*p1-p2)/(z*z-1.0);
+         z1=z;
+         z=z1-p1/pp;
+      } while (fabs(z-z1) > EPS_gauleg);
+      mXPos[i-1]         = xm-xl*z;
+      mXPos[mOrder-i]    = xm+xl*z;
+      mWeights[i-1]      = 2.0*xl/((1.0-z*z)*pp*pp);
+      mWeights[mOrder-i] = mWeights[i-1];
+   }
+
+}
+
Index: /tags/V_Fev00/SophyaLib/NTools/integ.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/integ.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/integ.h	(revision 752)
@@ -0,0 +1,101 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// integ.h
+//
+// $Id: integ.h,v 1.6 1999-11-05 13:08:29 ansari Exp $
+//
+
+#ifndef INTEG_H_SEEN
+#define INTEG_H_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include <set>
+
+namespace SOPHYA {
+
+class GeneralFunction;
+
+class Integrator EXC_AWARE {
+public:
+  typedef double(*FUNC)(double);
+
+  Integrator();
+  Integrator(FUNC, double xmin, double xmax);
+  Integrator(FUNC);
+  Integrator(GeneralFunction*, double* par, double xmin, double xmax);
+  Integrator(GeneralFunction*, double* par);
+  virtual ~Integrator();
+
+  virtual double Value() = 0;
+  virtual double ValueBetween(double xmin, double xmax);
+  virtual operator double() {return Value();}
+
+  virtual Integrator& NStep(int);
+  virtual Integrator& DX(double);
+  virtual Integrator& ReqPrec(double);   // NOT YET !
+  virtual Integrator& Limits(double xmin, double xmax);
+  virtual Integrator& Func(FUNC);
+  virtual Integrator& Func(GeneralFunction*, double* par);
+
+protected:
+  FUNC             mFunc;
+  GeneralFunction* mGFF;
+  double*          mGFFParm;
+
+  int              mNStep;   // -1 si pas fixe
+  double           mDX;
+  double           mReqPrec;
+  double           mXMin, mXMax;
+  
+  double           FVal(double x) const;
+  virtual void     LimitsChanged() {}
+  virtual void     StepsChanged() {}
+  virtual void     FuncChanged() {}
+};
+
+
+
+class TrpzInteg : public Integrator {
+public:
+  TrpzInteg();
+  TrpzInteg(FUNC, double xmin, double xmax);
+  TrpzInteg(FUNC);
+  TrpzInteg(GeneralFunction*, double* par, double xmin, double xmax);
+  TrpzInteg(GeneralFunction*, double* par);
+
+  ~TrpzInteg();
+
+  virtual double Value();
+};
+
+class GLInteg : public Integrator {
+public:
+  GLInteg();
+  GLInteg(FUNC, double xmin, double xmax);
+  GLInteg(FUNC);
+  GLInteg(GeneralFunction*, double* par, double xmin, double xmax);
+  GLInteg(GeneralFunction*, double* par);
+
+  ~GLInteg();
+
+  virtual double Value();
+  virtual GLInteg& AddBound(double x);
+  virtual GLInteg& SetOrder(int order);
+protected:
+
+  double* mXPos;     // integration entre 0 et 1
+  double* mWeights;  // integration entre 0 et 1
+  int     mOrder;    // ordre GL
+  set<double> mBounds; // limites des intervalles d'integration
+  
+  void ComputeWeights();
+  void LimitsChanged();
+  void StepsChanged();
+  void InvalWeights();
+  void ComputeBounds();
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/linfit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/linfit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/linfit.cc	(revision 752)
@@ -0,0 +1,126 @@
+#include "machdefs.h"
+#include "peida.h"
+#include "linfit.h"
+
+LinFitter::LinFitter()
+{
+}
+
+LinFitter::~LinFitter()
+{
+}
+
+double LinFitter::LinFit(const Vector& x, const Vector& y, int nf, 
+                         double (*f)(int, double), Vector& c)
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  
+  Matrix fx(nf, n);
+  for (int i=0; i<nf; i++)
+    for (int j=0; j<n; j++)
+      fx(i,j) = f(i,x(j));
+
+  return LinFit(fx,y,c);
+}
+
+
+
+double LinFitter::LinFit(const Matrix& fx, const Vector& y, Vector& c)
+{
+  int n = y.NElts();
+  if ( n != fx.NCol()) THROW(sizeMismatchErr);
+
+  int nf = fx.NRows();
+
+  Matrix a(nf,nf);
+
+  for (int j=0; j<nf; j++)
+    for (int k=j; k<nf; k++)
+      a(j,k) = a(k,j) = fx.Row(j) * fx.Row(k);
+   
+  c = fx * y;
+
+  if (Matrix::GausPiv(a,c) == 0) THROW(singMatxErr);
+
+  double xi2 = 0;
+
+  for (int k=0; k<n; k++) {
+    double x = 0;
+    for (int i=0; i<nf; i++)
+      x += c(i) * fx(i,k);
+    x -= y(k);
+    xi2 += x*x;
+  }
+  return xi2;
+}
+
+
+
+double LinFitter::LinFit(const Vector& x, const Vector& y, const Vector& errY2, int nf,
+	                 double (*f)(int, double), Vector& c, Vector& errC)
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  
+  Matrix fx(nf, n);
+  for (int i=0; i<nf; i++)
+    for (int j=0; j<n; j++)
+      fx(i,j) = f(i,x(j));
+
+  return LinFit(fx,y,errY2,c,errC);
+}
+
+
+double LinFitter::LinFit(const Matrix& fx, const Vector& y, const Vector& errY2,
+	   Vector& c, Vector& errC)
+{
+  int n = y.NElts();
+  if ( n != errY2.NElts()) THROW(sizeMismatchErr);
+  if ( n != fx.NCol()) THROW(sizeMismatchErr);
+
+  int nf = fx.NRows();
+
+  Matrix a(nf,nf);
+
+  c.Realloc(nf);
+  errC.Realloc(nf);
+
+  for (int j=0; j<nf; j++)
+    for (int k=j; k<nf; k++) {
+      double x=0;
+      for (int l=0; l<n; l++)
+	x += fx(j,l) * fx(k,l) / errY2(l);        // Matrice a inverser
+      a(j,k) = a(k,j) = x;
+    }
+ 
+  Matrix d(nf,nf+1);
+  for (int k=0; k<nf; k++) {
+    double x=0;
+    for (int l=0; l<n; l++)
+      x += fx(k,l) * y(l) / errY2(l);             // Second membre 1ere colonne
+    d(k,0) = x;
+    for (int m=1; m<=nf; m++)
+      d(k,m) = (k==m) ? 1 : 0;                // Reste second membre = Id.
+  }
+
+  if (Matrix::GausPiv(a,d) == 0) THROW(singMatxErr);
+
+  for (int l=0; l<nf; l++) {
+    c(l) = d(l,0);                            // Parametres = 1ere colonne
+    errC(l) = d(l,l+1);                        // Erreurs = diag inverse.
+  }
+
+  double xi2 = 0;
+
+  for (int jj=0; jj<n; jj++) {
+    double x = 0;
+    for (int ii=0; ii<nf; ii++)
+      x += c(ii) * fx(ii,jj);
+    x -= y(jj);
+    xi2 += x*x/errY2(jj);
+  }
+  return xi2;
+}
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/linfit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/linfit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/linfit.h	(revision 752)
@@ -0,0 +1,47 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: linfit.h,v 1.6 1999-11-05 13:08:30 ansari Exp $
+//
+
+// Routines de fit lineaire, avec ou sans erreurs, en fournissant
+// les fonctions ou les valeurs.
+#ifndef LINFIT_SEEN
+#define LINFIT_SEEN
+
+#include "machdefs.h"
+#include "tvector.h"
+
+namespace SOPHYA {
+
+class LinFitter {
+public :
+		LinFitter();
+  virtual	~LinFitter();
+
+  double	LinFit(const Vector& x, const Vector& y, int nf,
+		       double (*f)(int, double), Vector& c);
+// fit lineaire des y en tant que somme de c(i)f(i,x), i=0..nf-1;
+
+  double	LinFit(const Matrix& fx, const Vector& y, Vector& c);
+// fit lineaire des y en tant que somme de c(i)f(i,x), i=0..nf-1,
+// la matrice fx contient les valeurs des f:
+// fx(i,j) = f(i, x(j)).
+		      
+  double	LinFit(const Vector& x, const Vector& y, const Vector& errY2, int nf,
+		       double (*f)(int, double), Vector& c, Vector& errC);
+// fit lineaire des y en tant que somme de c(i)f(i,x), i=0..nf-1,
+// errY2 contient les carres des erreurs sur les Y.
+// au retour, errC contient les erreurs sur les coefs.
+
+  double	LinFit(const Matrix& fx, const Vector& y, const Vector& errY2,
+		       Vector& c, Vector& errC);
+// fit lineaire des y en tant que somme de c(i)f(i,x), i=0..nf-1,
+// la matrice fx contient les valeurs des f:
+// fx(i,j) = f(i, x(j)).
+// errY2 contient les carres des erreurs sur les Y.
+// au retour, errC contient les erreurs sur les coefs.
+};
+
+} // Fin du namespace
+
+#endif // LINFIT_SEEN 
Index: /tags/V_Fev00/SophyaLib/NTools/matrix.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/matrix.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/matrix.cc	(revision 752)
@@ -0,0 +1,1028 @@
+// $Id: matrix.cc,v 1.6 1999-10-25 10:36:09 ansari Exp $
+
+#include "machdefs.h"
+#include <string.h>
+#include <iostream.h>
+#include <iomanip.h>
+#include <values.h>
+#include "peida.h"
+#include "matrix.h"
+#include "cvector.h"
+#include "generalfit.h"
+#include "tmatrix.h"
+
+// Sous Linux, LN_MAXDOUBLE LN_MINDOUBLE ne semblent pas etre definies
+//   Reza 11/02/99
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef LN_MINDOUBLE
+#define LN_MINDOUBLE  (M_LN2 * (DMINEXP - 1))
+#endif
+#ifndef LN_MAXDOUBLE
+#define LN_MAXDOUBLE  (M_LN2 * DMAXEXP)
+#endif
+
+
+//++
+// Class	OMatrix
+// Lib	Outils++
+// include	matrix.h
+//
+//	Classe générale de matrice, calculs matriciels et algèbre linéaire.
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+OMatrix::OMatrix()
+//
+//	Construit une matrice 1x1 (pour ppersist).
+//--
+: nr(1), nc(1), ndata(1), nalloc(1), data(new double[1]), FromTmatrix(false)
+{
+  // if (r<=0 || c<=0) THROW(rangeCheckErr);
+  memset(data, 0, nalloc*sizeof(double));
+  END_CONSTRUCTOR
+}
+
+//++
+OMatrix::OMatrix(int r, int c)
+//
+//	Construit une matrice de r lignes et c colonnes.
+//--
+: nr(r), nc(c), ndata(r*c), nalloc(r*c), data(new double[r*c]), FromTmatrix(false)
+{
+  // if (r<=0 || c<=0) THROW(rangeCheckErr);
+  memset(data, 0, nalloc*sizeof(double));
+  END_CONSTRUCTOR
+}
+
+//++
+OMatrix::OMatrix(int r, int c, double* values)
+//
+//	Construit une matrice de r lignes et c colonnes. On fournit
+//	le tableau des valeurs : pas d'allocation.
+//--
+: nr(r), nc(c), ndata(r*c), nalloc(0), data(values), FromTmatrix(false)
+{
+  END_CONSTRUCTOR
+}
+
+//++
+OMatrix::OMatrix(const OMatrix& a)
+//
+//	Constructeur par copie.
+//--
+: nr(a.nr), nc(a.nc), ndata(a.nr*a.nc), nalloc(a.nr*a.nc),
+  data(new double[a.nr*a.nc]), FromTmatrix(false)
+{
+  memcpy(data, a.data, nalloc * sizeof(double));
+  END_CONSTRUCTOR
+}
+
+//++
+OMatrix::OMatrix(const TMatrix<r_8>& a)
+//
+//	Constructeur par copie a partir d'une TMatrix<r_8>.
+//	Attention, les donnees sont partagees.
+//--
+: nr(a.NRows()), nc(a.NCols()), ndata(a.NRows()*a.NCols())
+, nalloc(a.NRows()*a.NCols())
+, data(const_cast<r_8 *>(a.Data()))
+, FromTmatrix(true)
+{
+  END_CONSTRUCTOR
+}
+
+
+OMatrix::~OMatrix()
+{
+  DBASSERT(ndata == nr*nc);
+  if (nalloc && !FromTmatrix) delete[] data;
+}
+
+//++
+// Titre	Méthodes
+//--
+
+
+//++
+void OMatrix::Zero()
+//
+//	Remise à zero de tous les éléments
+//--
+{
+  DBASSERT(ndata == nr*nc);
+  for (int i=0; i<ndata; i++) data[i] = 0;
+}
+
+//++
+void OMatrix::Realloc(int r, int c, bool force)
+//
+//	Change la taille de la matrice. Réallocation physique seulement si
+//	pas assez de place, ou forcée si force=true.
+//--
+{
+  DBASSERT(ndata == nr*nc);
+  if (!nalloc) THROW(allocationErr);
+  int ncop = ndata;                      // ancien elements
+  ndata = r*c;
+  if (ndata < ncop) ncop = ndata;
+  nr = r;
+  nc = c;
+  if (nalloc < ndata || force) {
+    double* p = new double[ndata];
+    memcpy(p,data,ncop * sizeof(double));
+    delete[] data;
+    data = p;
+    nalloc = ndata;
+  } else if (nalloc != ndata)                 // Sans doute facultatif, mais plus
+    memset(data+ndata, 0, (nalloc-ndata)*sizeof(double));  //propre
+}
+
+//++
+OMatrix& OMatrix::operator = (const OMatrix& a)
+//
+//	Opérateur d'affectation.
+//--
+{
+  if (this == &a) return *this;
+  Realloc(a.nr, a.nc);
+  memcpy(data, a.data, ndata * sizeof(double));
+  return *this;
+}
+
+
+//++
+OMatrix& OMatrix::operator = (double x)
+//
+//	Opérateur d'affectation depuis scalaire : identité * scalaire.
+//--
+{
+  if (nr != nc) THROW(sizeMismatchErr);
+  for (int r=0; r<nr; r++)
+    for (int c=0; c<nc; c++)
+      (*this)(r,c) = (r==c) ? x : 0.0;
+  return *this;
+}
+
+//++
+// r_8& [const]         operator()(int r, int c) [const]
+//	Accès aux éléments
+//--
+
+//++
+ostream& operator << (ostream& s, const OMatrix& a)
+//
+//	Impression
+//--
+{
+  for (int r=0; r<a.nr; r++) {
+    s << "| ";
+    for (int c=0; c<a.nc; c++)
+      s << setw(6) << a(r,c) << " ";
+    s << "|\n";
+    }
+  return s;
+}
+
+// ****************** MATRIX / SCALAR ******************************
+
+
+//++
+OMatrix& OMatrix::operator *= (double b)
+//
+//--
+{
+  double* p    = data;
+  double* pEnd = data + ndata;
+
+  while (p < pEnd)
+    *p++ *= b;
+
+  return *this;
+}
+
+//++
+OMatrix& OMatrix::operator += (double b)
+//
+//--
+{
+  double* p    = data;
+  double* pEnd = data + ndata;
+
+  while (p < pEnd)
+    *p++ += b;
+
+  return *this;
+}
+
+//++
+OMatrix& OMatrix::operator -= (double b)
+//
+//--
+{
+  double* p    = data;
+  double* pEnd = data + ndata;
+
+  while (p < pEnd)
+    *p++ -= b;
+
+  return *this;
+}
+
+//++
+OMatrix& OMatrix::operator /= (double b)
+//
+//--
+{
+  ASSERT( b != 0. );
+  double* p    = data;
+  double* pEnd = data + ndata;
+
+  while (p < pEnd)
+    *p++ /= b;
+
+  return *this;
+}
+
+//++
+OMatrix operator * (const OMatrix& a, double b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result *= b);
+}
+
+//++
+OMatrix operator * (double b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  return (result *= b);
+}
+
+//++
+OMatrix operator + (const OMatrix& a, double b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result += b);
+}
+
+//++
+OMatrix operator + (double b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  return (result += b);
+}
+
+//++
+OMatrix operator - (const OMatrix& a, double b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result -= b);
+}
+
+//++
+OMatrix operator - (double b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  result *= -1;
+  return (result += b);
+}
+
+//++
+OMatrix operator / (const OMatrix& a, double b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result /= b);
+}
+
+//++
+OMatrix operator * (const OMatrix& a, int b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result *= b);
+}
+
+//++
+OMatrix operator * (int b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  return (result *= b);
+}
+
+//++
+OMatrix operator + (const OMatrix& a, int b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result += b);
+}
+
+//++
+OMatrix operator + (int b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  return (result += b);
+}
+
+//++
+OMatrix operator - (const OMatrix& a, int b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result -= b);
+}
+
+//++
+OMatrix operator - (int b, const OMatrix& a)
+//
+//--
+{
+  OMatrix result(a);
+  result *= -1;
+  return (result += b);
+}
+
+//++
+OMatrix operator / (const OMatrix& a, int b)
+//
+//--
+{
+  OMatrix result(a);
+  return (result /= b);
+}
+
+
+// **************** MATRIX / MATRIX ***********************88
+
+//++
+OMatrix& OMatrix::operator += (const OMatrix& a)
+//
+//--
+{
+  if (nc!=a.nc || nr!=a.nr) THROW(sizeMismatchErr);
+
+  double* p    = data;
+  double* pEnd = data + ndata;
+  double* q    = a.data;
+
+  while (p < pEnd)
+    *p++ += *q++;
+
+  return *this;
+}
+
+//++
+OMatrix& OMatrix::operator -= (const OMatrix& a)
+//
+//--
+{
+  if (nc!=a.nc || nr!=a.nr) THROW(sizeMismatchErr);
+
+  double* p    = data;
+  double* pEnd = data + ndata;
+  double* q    = a.data;
+
+  while (p < pEnd)
+    *p++ -= *q++;
+
+  return *this;
+}
+
+
+//++
+OMatrix& OMatrix::operator *= (const OMatrix& a)
+//
+//--
+{
+  if (nc != a.nc || nr != a.nr || nc != nr) THROW(sizeMismatchErr);
+
+  double* oldRow = new double[nr];
+  double* orEnd = oldRow + nc;
+  double* orp;
+  double* trp;
+
+  for (double* tr = data; tr < data+ndata; tr += nc) {
+    for (orp = oldRow, trp = tr;
+         orp < orEnd;)
+      *orp++ = *trp++;
+
+    double* ac;
+    double* acp;
+
+    for (trp = tr, ac = a.data; ac< a.data+nr; ac++, trp++) {
+      double sum = 0;
+      for (orp = oldRow, acp = ac; acp < ac+ndata; acp += nr, orp++)
+        sum += *orp * *acp;
+      *trp = sum;
+    }
+  }
+  delete[] oldRow;
+  return *this;
+}
+
+//++
+OMatrix operator + (const OMatrix& a, const OMatrix& b)
+//
+//--
+{
+  if (b.nc != a.nc || b.nr != a.nr) THROW(sizeMismatchErr);
+
+  OMatrix c(a);
+  return (c += b);
+}
+
+//++
+OMatrix operator - (const OMatrix& a, const OMatrix& b)
+//
+//--
+{
+  if (b.nc != a.nc || b.nr != a.nr) THROW(sizeMismatchErr);
+
+  OMatrix c(a);
+  return (c -= b);
+}
+
+#if 0
+
+OMatrix operator * (const OMatrix& a, const OMatrix& b)
+{
+  if (a.nc != b.nr) THROW(sizeMismatchErr);
+
+  OMatrix c(a.nr, b.nc);
+
+  double* pc = c.data;
+
+  double* pa = a.data;
+
+  double* pb = b.data;
+
+  for (int rc = 0; rc < c.nr; rc++) {
+    for (int cc = 0; cc < c.nc; cc++) {      // boucle sur c
+      double sum = 0;
+      for (int ca = 0; ca < a.nc; ca++) {     // boucle sur a & b
+        sum += *pa * *pb;
+        pa++;
+        pb += b.nc;
+      }
+      *pc++ = sum;
+      pa -= a.nc;                           // retour meme ligne
+      pb -= b.ndata - 1;                    // haut de la colonne suiv
+    }
+                                            // ligne suivante c
+    pb = b.data;                            // en revient en b(1,1)
+    pa += a.nc;                             // debut ligne suivante
+  }
+
+  return c;
+}
+#endif
+
+//++
+OMatrix operator * (const OMatrix& a, const OMatrix& b)
+//
+//--
+{
+  if (a.nc != b.nr) THROW(sizeMismatchErr);
+
+  OMatrix c(a.nr, b.nc);
+
+  for (int rc = 0; rc < c.nr; rc++)
+    for (int cc = 0; cc < c.nc; cc++) {      // boucle sur c
+      double sum = 0;
+      for (int ca = 0; ca < a.nc; ca++)     // boucle sur a & b
+        sum += a(rc,ca) * b(ca,cc);
+      c(rc,cc) = sum;
+    }
+
+  return c;
+
+}
+
+
+//++
+OMatrix OMatrix::Transpose() const
+//
+//	Retourne la transposée.
+//--
+#if HAS_NAMED_RETURN
+return a(nc,nr)
+#endif
+{
+#if !HAS_NAMED_RETURN
+OMatrix a(nc,nr);
+#endif
+  for (int i=0; i<nr; i++)
+    for (int j=0; j<nc; j++)
+      a(j,i) = (*this)(i,j);
+#if !HAS_NAMED_RETURN
+return a;
+#endif
+}
+
+
+//++
+OMatrix OMatrix::Inverse() const
+//
+//	Retourne la matrice inverse.
+//
+//	*Exception* : singMatxErr si la matrice est singulière.
+//--
+#if HAS_NAMED_RETURN
+return b(nr,nc)
+#endif
+{
+#if !HAS_NAMED_RETURN
+OMatrix b(nc,nr);
+#endif
+  OMatrix a(*this);
+  b = 1.0;
+  if (fabs(OMatrix::GausPiv(a,b)) < 1.e-50) THROW(singMatxErr);
+#if !HAS_NAMED_RETURN
+return b;
+#endif
+}
+
+
+void OMatrix::WriteSelf(POutPersist& s) const
+{
+  ASSERT(ndata == nr*nc);
+  s << nr << nc;
+  s.PutR8s(data, ndata);
+}
+
+void OMatrix::ReadSelf(PInPersist& s)
+{
+  int_4 r,c;
+  s >> r >> c;
+  Realloc(r,c);
+  ASSERT(ndata == nr*nc);
+  s.GetR8s(data, ndata);
+}
+
+
+OMatrixRC::OMatrixRC()
+: matrix(0), data(0), index(0), step(0)
+{}
+
+OMatrixRC::OMatrixRC(OMatrix& m, RCKind rckind, int ind)
+: matrix(&m), data(Org(m,rckind,ind)),
+  index(ind), step(Step(m,rckind)), kind(rckind)
+{
+  if (kind == matrixDiag & m.nc != m.nr) THROW(sizeMismatchErr);
+}
+
+
+int OMatrixRC::Next()
+{
+  if (!matrix) return -1;             // Failure ?
+  if (kind == matrixDiag) return -1;  // Failure ?
+  index++;
+  if (kind == matrixRow) {
+    if (index > matrix->nr) {
+      index = matrix->nr;
+      return -1;
+    }
+    data += matrix->nc;
+  } else {
+    if (index > matrix->nc) {
+      index = matrix->nc;
+      return -1;
+    }
+    data++;
+  }
+  return index;
+}
+
+
+int OMatrixRC::Prev()
+{
+  if (!matrix) return -1;             // Failure ?
+  if (kind == matrixDiag) return -1;  // Failure ?
+  index--;
+  if (index < 0) {
+    index = 0;
+    return -1;
+  }
+  if (kind == matrixRow)
+    data -= matrix->nc;
+  else
+    data--;
+  return index;
+}
+
+
+int OMatrixRC::SetCol(int c)
+{
+  if (!matrix) return -1;             // Failure ?
+  if (c<0 || c>matrix->nc) return -1;
+  kind = matrixCol;
+  index = c;
+  step = Step(*matrix, matrixCol);
+  data = Org(*matrix, matrixCol, c);
+  return c;
+}
+
+
+int OMatrixRC::SetRow(int r)
+{
+  if (!matrix) return -1;             // Failure ?
+  if (r<0 || r>matrix->nr) return -1;
+  kind = matrixRow;
+  index = r;
+  step = Step(*matrix, matrixRow);
+  data = Org(*matrix, matrixRow, r);
+  return r;
+}
+
+
+int OMatrixRC::SetDiag()
+{
+  if (!matrix) return -1;             // Failure ?
+  if (matrix->nc != matrix->nr) THROW(sizeMismatchErr);
+  kind = matrixDiag;
+  index = 0;
+  step = Step(*matrix, matrixDiag);
+  data = Org(*matrix, matrixDiag);
+  return 0;
+}
+
+
+OMatrixRC& OMatrixRC::operator = (const OMatrixRC& rc)
+{
+  matrix = rc.matrix;
+  data   = rc.data;
+  index  = rc.index;
+  step   = rc.step;
+  kind   = rc.kind;
+  return *this;
+}
+
+//OMatrixRC::operator OVector() const
+OVector OMatrixRC::GetVect() const
+#if HAS_NAMED_RETURN
+return v(NElts())
+#endif
+{
+#if !HAS_NAMED_RETURN
+  OVector v(NElts());
+#endif
+  int n = NElts();
+  for (int i=0; i<n; i++)
+    v(i) = (*this)(i);
+#if !HAS_NAMED_RETURN
+  return v;
+#endif
+}
+
+
+OMatrixRC& OMatrixRC::operator += (const OMatrixRC& rc)
+{
+  int n = NElts();
+  if ( n != rc.NElts() ) THROW(sizeMismatchErr);
+  if ( kind != rc.kind ) THROW(sizeMismatchErr);
+
+  for (int i=0; i<n; i++)
+    (*this)(i) += rc(i);
+
+  return *this;
+}
+
+
+
+OMatrixRC& OMatrixRC::operator -= (const OMatrixRC& rc)
+{
+  int n = NElts();
+  if ( n != rc.NElts() ) THROW(sizeMismatchErr);
+  if ( kind != rc.kind ) THROW(sizeMismatchErr);
+
+  for (int i=0; i<n; i++)
+    (*this)(i) -= rc(i);
+
+  return *this;
+}
+
+
+OMatrixRC& OMatrixRC::operator *= (double x)
+{
+  int n = NElts();
+
+  for (int i=0; i<n; i++)
+    (*this)(i) *= x;
+
+  return *this;
+}
+
+
+OMatrixRC& OMatrixRC::operator /= (double x)
+{
+  int n = NElts();
+
+  for (int i=0; i<n; i++)
+    (*this)(i) /= x;
+
+  return *this;
+}
+
+
+OMatrixRC& OMatrixRC::operator -= (double x)
+{
+  int n = NElts();
+
+  for (int i=0; i<n; i++)
+    (*this)(i) -= x;
+
+  return *this;
+}
+
+
+OMatrixRC& OMatrixRC::operator += (double x)
+{
+  int n = NElts();
+
+  for (int i=0; i<n; i++)
+    (*this)(i) += x;
+
+  return *this;
+
+}
+
+
+double operator * (const OMatrixRC& a, const OMatrixRC& b)
+{
+  int n = a.NElts();
+  if ( n != b.NElts() ) THROW(sizeMismatchErr);
+  if ( a.kind != b.kind ) THROW(sizeMismatchErr);
+  double sum = 0;
+  for (int i=0; i<n; i++)
+    sum += a(i)*b(i);
+  return sum;
+}
+
+
+OMatrixRC& OMatrixRC::LinComb(double a, double b, const OMatrixRC& rc, int first)
+{
+  int n = NElts();
+  if ( n != rc.NElts() ) THROW(sizeMismatchErr);
+  if ( kind != rc.kind ) THROW(sizeMismatchErr);
+
+  for (int i=first; i<n; i++)
+    (*this)(i) = (*this)(i)*a + rc(i)*b;
+
+  return *this;
+}
+
+
+OMatrixRC& OMatrixRC::LinComb(double b, const OMatrixRC& rc, int first)
+{
+  int n = NElts();
+  if ( n != rc.NElts() ) THROW(sizeMismatchErr);
+  if ( kind != rc.kind ) THROW(sizeMismatchErr);
+
+  for (int i=first; i<n; i++)
+    (*this)(i) += rc(i)*b;
+
+  return *this;
+}
+
+
+
+OMatrixRC OMatrix::Row(int r) const
+#if HAS_NAMED_RETURN
+return rc((OMatrix&)*this, matrixRow, r)
+#endif
+{
+#if !HAS_NAMED_RETURN
+        OMatrixRC rc((OMatrix&)*this, matrixRow, r);
+        return rc;
+#endif
+}
+
+
+OMatrixRC OMatrix::Col(int c) const
+#if HAS_NAMED_RETURN
+return rc((OMatrix&)*this, matrixCol, c)
+#endif
+{
+#if !HAS_NAMED_RETURN
+        OMatrixRC rc((OMatrix&)*this, matrixCol, c);
+        return rc;
+#endif
+}
+
+
+OMatrixRC OMatrix::Diag() const
+#if HAS_NAMED_RETURN
+return rc((OMatrix&)*this, matrixDiag)
+#endif
+{
+#if !HAS_NAMED_RETURN
+        OMatrixRC rc((OMatrix&)*this, matrixDiag);
+        return rc;
+#endif
+}
+
+
+int OMatrixRC::IMaxAbs(int first)
+{
+  int n=NElts();
+  if (first>n) THROW(rangeCheckErr);
+  int imax=first;
+  double vmax = fabs((*this)(first));
+  double v;
+  for (int i=first+1; i<n; i++)
+    if ((v=fabs((*this)(i))) > vmax) {
+      vmax = v;
+      imax = i;
+    }
+  return imax;
+}
+
+
+void OMatrixRC::Swap(OMatrixRC& rc1, OMatrixRC& rc2)
+{
+  int n=rc1.NElts();
+  if (n != rc2.NElts()) THROW(sizeMismatchErr);
+  if (rc1.kind != rc2.kind) THROW(sizeMismatchErr);
+  if (rc1.data == rc2.data) return; // C'est le meme
+  for (int i=0; i<n; i++)
+    {double tmp = rc1(i); rc1(i) = rc2(i); rc2(i) = tmp;}
+}
+
+
+
+double OMatrix::GausPiv(OMatrix& a, OMatrix& b)
+{
+  int n = a.NRows();
+  if ( n != b.NRows()) THROW(sizeMismatchErr);
+
+  // On fait une normalisation un peu brutale...
+  double vmin=MAXDOUBLE;
+  double vmax=0;
+  for (int iii=0; iii<a.NRows(); iii++)
+    for (int jjj=0; jjj<a.NCol(); jjj++) {
+      if (fabs(a(iii,jjj)) > vmax) vmax = fabs(a(iii,jjj));
+      if (fabs(a(iii,jjj)) < vmin && fabs(a(iii,jjj))>0) vmin = fabs(a(iii,jjj));
+    }
+  double nrm = sqrt(vmin*vmax);
+  if (nrm > 1.e5 || nrm < 1.e-5) {
+    a /= nrm;
+    b /= nrm;
+    //cout << "normalisation matrice " << nrm << endl;
+  } else 
+    nrm=1;
+
+  double det = 1.0;
+  if (nrm != 1) {
+    double ld = a.NRows() * log(nrm);
+    if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
+     // cerr << "OMatrix warning, overflow for det" << endl;
+    } else {
+      det = exp(ld);
+    }
+  }
+
+  OMatrixRC pivRowa(a,matrixRow);
+  OMatrixRC pivRowb(b,matrixRow);
+
+  for (int k=0; k<n-1; k++) {
+    int iPiv = a.Col(k).IMaxAbs(k);
+    if (iPiv != k) {
+      OMatrixRC aIPiv(a.Row(iPiv));
+      OMatrixRC aK(a.Row(k));
+      OMatrixRC::Swap(aIPiv,aK);
+      OMatrixRC bIPiv(b.Row(iPiv));
+      OMatrixRC bK(b.Row(k));
+      OMatrixRC::Swap(bIPiv,bK);
+    }
+    double pivot = a(k,k);
+    if (fabs(pivot) < 1.e-50) return 0.0;
+    //det *= pivot;
+    pivRowa.SetRow(k); // to avoid constructors
+    pivRowb.SetRow(k);
+    for (int i=k+1; i<n; i++) {
+      double r = -a(i,k)/pivot;
+      a.Row(i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa
+      b.Row(i).LinComb(r, pivRowb);
+    }
+  }
+  det *= a(n-1, n-1);
+
+  // on remonte
+
+  for (int kk=n-1; kk>0; kk--) {
+    double pivot = a(kk,kk);
+    if (fabs(pivot) <= 1.e-50) return 0.0;
+    pivRowa.SetRow(kk); // to avoid constructors
+    pivRowb.SetRow(kk);
+    for (int jj=0; jj<kk; jj++) {
+      double r = -a(jj,kk)/pivot;
+      a.Row(jj).LinComb(r, pivRowa);
+      b.Row(jj).LinComb(r, pivRowb);
+    }
+  }
+
+ 
+  for (int l=0; l<n; l++) {
+    if (fabs(a(l,l)) <= 1.e-50) return 0.0;
+    b.Row(l) /= a(l,l);
+  }
+
+  return det;
+}
+
+//++
+double OMatrix::Norm1()
+//
+//	Norme 1 : somme des valeurs absolues.
+//--
+{
+  double s = 0;
+  for (int k = 0; k < nr*nc; k++)
+    s += fabs(data[k]);
+  return s;
+}
+
+//++
+double OMatrix::Norm2()
+//
+//	Norme 2, euclidienne.
+//--
+{
+  double s = 0;
+  for (int k = 0; k < nr*nc; k++)
+    s += data[k] * data[k];
+  return sqrt(s);
+}
+
+//////////////////////////////////////////////////////////
+//++
+OMatrix OMatrix::FitResidus(GeneralFit& gfit
+               ,double xorg,double yorg,double dx,double dy)
+//
+//	Retourne une classe contenant les residus du fit ``gfit''.
+//	Les coordonnees de l'element (i,j) sont :
+//	(i,j) -> x = xorg + j*dx , y = yorg + i*dy
+//--
+{
+if(NCol()<=0||NRows()<=0)
+  throw(SzMismatchError("OMatrix::FitResidus: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("OMatrix::FitResidus: NULL pointer\n"));
+OVector par = gfit.GetParm();
+OMatrix m(*this);
+for(int i=0;i<NRows();i++) for(int j=0;j<NCol();j++) {
+  double x[2] = {xorg+j*dx,yorg+i*dy};
+  m(i,j) -= f->Value(x,par.Data());
+}
+return m;
+}
+
+//++
+OMatrix OMatrix::FitFunction(GeneralFit& gfit
+               ,double xorg,double yorg,double dx,double dy)
+//
+//	Retourne une classe contenant la fonction du fit ``gfit''.
+//	Les coordonnees de l'element (i,j) sont :
+//	(i,j) -> x = xorg + j*dx , y = yorg + i*dy
+//--
+{
+if(NCol()<=0||NRows()<=0)
+  throw(SzMismatchError("OMatrix::FitFunction: size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("OMatrix::FitFunction: NULL pointer\n"));
+OVector par = gfit.GetParm();
+OMatrix m(*this);
+for(int i=0;i<NRows();i++) for(int j=0;j<NCol();j++) {
+  double x[2] = {xorg+j*dx,yorg+i*dy};
+  m(i,j) = f->Value(x,par.Data());
+}
+return m;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/matrix.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/matrix.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/matrix.h	(revision 752)
@@ -0,0 +1,302 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Eric Aubourg, Septembre 94
+#ifndef MATRIX_SEEN
+#define MATRIX_SEEN
+
+#define RGCHECK
+
+#include <stdio.h>
+#include <iostream.h>
+#include "peida.h"
+#include "anydataobj.h"
+#include "ppersist.h"
+
+namespace SOPHYA {
+  class GeneralFit;
+  template <class T> class TMatrix;
+}
+// <summary> Operations matricielles </summary>
+// Operations matricielles, algebre lineaire...
+class OMatrix : public PPersist, public AnyDataObj {
+  friend class OVector;
+  friend class OMatrixRC;
+  friend class TMatrix<r_8>;
+public:
+  OMatrix();
+  // Constructeur, matrice a zero
+  OMatrix(int r, int c);
+  // Constructeur avec des valeurs. Pas d'allocation, juste pointe.
+  OMatrix(int r, int c, double* values);
+  // Constructeur par copie
+  OMatrix(const OMatrix& a);
+  // Constructeur par copie a partir d'une TMatrix<r_8>
+  OMatrix(const TMatrix<r_8>& a);
+  // Destructeur
+  virtual ~OMatrix();
+
+  // Construction automatique pour PPF
+  // <group>
+  enum {classId = ClassId_Matrix};
+  int_4                 ClassId() const         { return classId; }
+  static PPersist*      Create() {return new OMatrix(1,1);}
+  // </group>
+
+  // Remise a zero de tous les elements
+  void Zero();
+  // Change la taille de la matrice. Reallocation physique seulement si
+  // pas assez de place, ou forcee si force=true
+  void Realloc(int r, int c, bool force=false);
+
+  // Operateur d'affectation
+  OMatrix& operator = (const OMatrix& a);
+  // Affectation depuis scalaire : identite * scalaire
+  OMatrix& operator = (double x);
+
+  // Impression
+  friend ostream& operator << (ostream& s, const OMatrix& a);
+
+  // Acces aux elements
+  // <group>
+  r_8&          operator()(int r, int c);
+  r_8 const&    operator()(int r, int c) const;
+  // </group>
+
+  // Acces au tableau des elements
+  // <group>
+  inline r_8* Data() {return data;}
+  inline const r_8* Data() const {return data;}
+  // </group>
+  // Norme 1 : somme des valeurs absolues
+  double  Norm1();
+  // Norme 2, euclidienne
+  double  Norm2();
+  
+  // Operations matricielles avec scalaire, allocation d'une nouvelle matrice
+  // <group>
+  friend OMatrix operator * (const OMatrix& a, double b);
+  friend OMatrix operator * (double b, const OMatrix& a);
+  friend OMatrix operator + (const OMatrix& a, double b);
+  friend OMatrix operator + (double b, const OMatrix& a);
+  friend OMatrix operator - (const OMatrix& a, double b);
+  friend OMatrix operator - (double b, const OMatrix& a);
+  friend OMatrix operator / (const OMatrix& a, double b);
+  // </group>
+
+  // Operations matricielles avec scalaires entiers, pour eviter l'appel
+  // du constructeur de vecteur a partir d'un entier...
+  // sinon v*2 = v * OVector(2), BUG !
+  // <group>
+  friend OMatrix operator * (const OMatrix& a, int b);
+  friend OMatrix operator * (int b, const OMatrix& a);
+  friend OMatrix operator + (const OMatrix& a, int b);
+  friend OMatrix operator + (int b, const OMatrix& a);
+  friend OMatrix operator - (const OMatrix& a, int b);
+  friend OMatrix operator - (int b, const OMatrix& a);
+  friend OMatrix operator / (const OMatrix& a, int b);
+  // </group>
+
+  // Operations matricielles "en place", avec scalaire
+  // <group>
+  OMatrix& operator *= (double b);
+  OMatrix& operator += (double b);
+  OMatrix& operator -= (double b);
+  OMatrix& operator /= (double b);
+  // </group>
+
+  // Operations matricielles
+  // <group>
+  friend OMatrix operator * (const OMatrix& a, const OMatrix& b);
+  friend OMatrix operator + (const OMatrix& a, const OMatrix& b);
+  friend OMatrix operator - (const OMatrix& a, const OMatrix& b);
+
+  OMatrix& operator *= (const OMatrix& a);
+  OMatrix& operator += (const OMatrix& b);
+  OMatrix& operator -= (const OMatrix& b);
+  // </group>
+
+  // Matrice transposee
+  OMatrix Transpose() const;
+  // Matrice inverse
+  // <thrown> singMatxErr </thrown>
+  OMatrix Inverse() const;
+
+  // Nombre de lignes
+  inline int NRows() const {return nr;}
+  // Nombre de colonnes
+  inline int NCol()  const {return nc;}
+
+  // Entrees-sorties PPF
+  // <group>
+  void ReadSelf(PInPersist&);
+  void WriteSelf(POutPersist&) const;
+  // </group>
+
+  // Acces aux rangees et colonnes
+  // <group>
+  OMatrixRC Row(int r) const;
+  OMatrixRC Col(int c) const;
+  OMatrixRC Diag() const;
+  // </group>
+  /* Versions const ? Alors il faut constructeur const pour OMatrixRC,    */
+  /* mais OMatrixRC contient un OMatrix* qui detruit const....             */
+  /* mais en eux-meme, ils ne modifient pas la matrice. Ils permettent   */
+  /* de le faire...                                                      */
+
+  // Pivot de Gauss : diagonalise la matrice A, en effectuant les memes
+  // operations sur la matrice B
+  static double GausPiv(OMatrix& A, OMatrix& B);
+
+  // Residus et fonction fittees.
+  OMatrix FitResidus(GeneralFit& gfit
+            ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
+  OMatrix FitFunction(GeneralFit& gfit
+            ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
+
+protected:
+  int_4 nr;
+  int_4 nc;
+  int ndata;
+  int nalloc;
+  r_8* data;
+  bool FromTmatrix;
+};
+
+
+inline r_8& OMatrix::operator()(int r, int c)
+{
+#ifdef RGCHECK
+  if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr);
+#endif
+  return(data[r*nc + c]);
+}
+
+
+inline r_8 const& OMatrix::operator()(int r, int c) const
+{
+#ifdef RGCHECK
+  if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr);
+#endif
+  return(data[r*nc + c]);
+}
+
+enum RCKind {matrixRow=0, matrixCol=1, matrixDiag=2};
+
+
+// <summary> Acces aux lignes et colonnes des matrices </summary>
+// Permet d'acceder a une ligne ou colonne d'une matrice, en place, comme
+// avec un vecteur.
+class OMatrixRC EXC_AWARE {
+friend class OVector;
+friend class OMatrix;
+public:
+  OMatrixRC();
+
+  virtual ~OMatrixRC() {}
+
+  int Next();
+  int Prev();
+  int SetCol(int c);
+  int SetRow(int r);
+  int SetDiag();
+
+  static int Step(const OMatrix& m, RCKind rckind);
+  static double* Org(const OMatrix&, RCKind rckind, int ind=0);
+
+  int NElts() const;
+  r_8& operator()(int i);
+  r_8  operator()(int i) const;
+
+  OMatrixRC& operator = (const OMatrixRC& rc);
+  //operator OVector() const;
+  OVector GetVect() const;
+
+  OMatrixRC& operator += (const OMatrixRC& rc);
+  OMatrixRC& operator -= (const OMatrixRC& rc);
+
+  OMatrixRC& operator *= (double x);
+  OMatrixRC& operator /= (double x);
+  OMatrixRC& operator -= (double x);
+  OMatrixRC& operator += (double x);
+
+  friend double operator * (const OMatrixRC& a, const OMatrixRC& b);
+
+  OMatrixRC& LinComb(double a, double b, const OMatrixRC& rc, int first=0);
+  OMatrixRC& LinComb(double b, const OMatrixRC& rc, int first=0);
+
+  int IMaxAbs(int first=0);
+
+  static void Swap(OMatrixRC& rc1, OMatrixRC& rc2);
+  // comme c'est symetrique, soit c'est static OMatrixRC, soit static OMatrix,
+  // soit OMatrix avec verification qu'on parle bien de la meme...
+
+protected:
+  OMatrixRC(OMatrix& m, RCKind kind, int index=0);
+  OMatrix* matrix;
+  r_8*    data;
+  int     index;
+  int     step;
+  RCKind  kind;
+};
+
+
+inline int OMatrixRC::Step(const OMatrix& m, RCKind rckind)
+{
+  switch (rckind)
+    {
+    case matrixRow  :
+      return 1;
+    case matrixCol  :
+      return m.nc;
+    case matrixDiag :
+      return m.nc+1;
+    }
+  return -1;
+}
+
+
+inline double* OMatrixRC::Org(const OMatrix& m, RCKind rckind, int index)
+{
+  switch (rckind)
+    {
+    case matrixRow :
+      return m.data + index * m.nc;
+    case matrixCol :
+      return m.data + index;
+    case matrixDiag :
+      return m.data;
+    }
+  return (double*) -1;
+}
+
+
+inline int OMatrixRC::NElts() const
+{
+  if (!matrix) return -1;             // Failure ?
+  switch (kind)
+    {
+    case matrixRow :
+      return matrix->nc;
+    case matrixCol :
+      return matrix->nr;
+    case matrixDiag :
+      return matrix->nc;
+    }
+  return -1;
+}
+
+
+
+inline  double& OMatrixRC::operator()(int i)
+{
+  return data[i*step];
+}
+
+
+inline  double OMatrixRC::operator()(int i) const
+{
+  return data[i*step];
+}
+
+
+#endif /* MATRIX_SEEN */
+
Index: /tags/V_Fev00/SophyaLib/NTools/matxop.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/matxop.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/matxop.c	(revision 752)
@@ -0,0 +1,904 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <math.h>
+
+
+#include "matxop.h"
+#include "nbmath.h"
+
+/*  Fonctions de manipulation de matrices et de vecteurs    */
+/*  Resolution de systemes lineaires                        */
+
+/*                              R. Ansari  Juillet 1993     */
+/*                              LaSilla (Chili)             */
+
+
+#define MXXFLOAT        1.e36
+
+
+
+/* Nouvelle-Fonction */
+
+int IVecxVec(int *v1, int *v2, int n)
+
+/*  Produit scalaire de deux vecteurs entiers       */
+/*  Retour (int) = v1(n) . v2(n)                    */
+
+{
+register int i,rc;
+register int *ip1, *ip2;
+
+ip1 = v1;  ip2 = v2;
+rc = 0;
+/* for(i=0; i<n; i++)  rc += *(ip1+i) * *(ip2+i); */
+for(i=0; i<n; i++)  rc += *ip1++ * *ip2++;
+return(rc);
+}
+
+
+/* Nouvelle-Fonction */
+
+float RVecxVec(float *v1, float *v2, int n)
+
+/*  Produit scalaire de deux vecteurs reels           */
+/*  Retour (float) = v1(n) . v2(n)                    */
+
+{
+register int i;
+register float rc;
+register float *fp1, *fp2;
+
+fp1 = v1;  fp2 = v2;
+rc = 0.0;
+/* for(i=0; i<n; i++)  rc += *(fp1+i) * *(fp2+i); */
+for(i=0; i<n; i++)  rc += *fp1++ * *fp2++;
+return(rc);
+}
+
+
+/* Nouvelle-Fonction */
+
+double DVecxVec(double *v1, double *v2, int n)
+
+/*  Produit scalaire de deux vecteurs double          */
+/*  Retour (float) = v1(n) . v2(n)                    */
+
+{
+register int i;
+register double rc;
+register double *fp1, *fp2;
+
+fp1 = v1;  fp2 = v2;
+rc = 0.0;
+/* for(i=0; i<n; i++)  rc += *(fp1+i) * *(fp2+i); */
+for(i=0; i<n; i++)  rc += *fp1++ * *fp2++;
+return(rc);
+}
+
+
+/* Nouvelle-Fonction */
+
+void  IMatxVec(int *mx, int *vi, int *vo, int n)
+
+/*  Matrice * Vecteur  (Entiers)     Integer           */
+/*  Vecteur Vo(n) = Matrice Mx(n,n) . Vi(n)            */
+
+{
+register  int *vp, *mxp;
+register int s;
+register int j,i;
+
+vp = vi;   mxp = mx;
+
+for (i=0; i<n; i++)
+  { s = 0;  
+  for(j=0; j<n; j++)   s += *(mxp+j) * *(vp+j);
+  *(vo+i) = s;  mxp += n; }
+
+return;
+}
+
+
+/* Nouvelle-Fonction */
+
+void  RMatxVec(float *mx, float *vi, float *vo, int n)
+
+/*  Matrice * Vecteur  (Reels)     float               */
+/*  Vecteur Vo(n) = Matrice Mx(n,n) . Vi(n)            */
+
+
+/*  Matrice * Vecteur  (Reels)  */
+{
+register  float *vp, *mxp;
+register float s;
+register int j,i;
+
+vp = vi;   mxp = mx;
+
+for (i=0; i<n; i++)
+  { s = 0;  
+  for(j=0; j<n; j++)   s += *(mxp+j) * *(vp+j);
+  *(vo+i) = s;  mxp += n; }
+
+return;
+}
+
+
+/* Nouvelle-Fonction */
+
+void  DMatxVec(double *mx, double *vi, double *vo, int n)
+
+/*  Matrice * Vecteur  (double)     double             */
+/*  Vecteur Vo(n) = Matrice Mx(n,n) . Vi(n)            */
+
+
+/*  Matrice * Vecteur  (Reels)  */
+{
+register  double *vp, *mxp;
+register double s;
+register int j,i;
+
+vp = vi;   mxp = mx;
+
+for (i=0; i<n; i++)
+  { s = 0;  
+  for(j=0; j<n; j++)   s += *(mxp+j) * *(vp+j);
+  *(vo+i) = s;  mxp += n; }
+
+return;
+}
+
+
+
+
+/* Nouvelle-Fonction */
+
+float SolveRLinSyst(float *mx, float *b, float *x, int n)
+
+/*  Resolution de systeme lineaire                           */
+/*  Matrice Mx(n,n) * Vecteur X(n) = Vecteur B(n)            */
+/*  Inconnu : vecteur X                                      */
+/*  Retour = Determinant du systeme (=0 Pb)  et X[]          */
+/*  Note : Au retour le vecteur B(n) et la matrice Mx(n,n)   */
+/*  sont modifies. Mx(n,n) contient une matrice triangulaire */
+/*  superieure                                               */                          
+
+{
+int i,k;
+register int j;
+register float *fp1, *fp2;
+double det;
+float vt1;
+register float vt2;
+register float six;
+int pivok;
+
+
+#define  MINPIVOT   1.e-15
+#define  MINDETER   1.e-15
+
+
+
+for (i=0; i<n-1; i++)   /*  Boucle sur les pivots */
+  {
+
+/*  printf("\n Iteration %d : \n",i);
+  for (k=0; k<n; k++)
+    {
+    for (j=0; j<n; j++)  printf(" %10g ",*(mx+k*n+j));
+    printf("    b= %10g \n",*(b+k));
+    }  */
+
+  fp1 = fp2 = mx+i*n;  
+  vt1 = *(fp1+i) ;
+
+  if ((vt1 < MINPIVOT) && (vt1 > -MINPIVOT) )   /* Pivot trop petit  */
+    {
+    pivok = 0;
+    for (k=i+1; k<n; k++)
+      {
+      vt1 = *(mx+k*n+i) ;
+      if ((vt1 > MINPIVOT) || (vt1 < -MINPIVOT) )
+        {
+        fp2 = mx+k*n;  
+        for (j=i; j<n; j++)
+          {
+          *(fp1+j) += *(fp2+j);
+          }
+        *(b+i) += *(b+k);
+        vt1 = *(fp1+i) ;  
+        fp2 = fp1;
+        pivok = 1;
+        break;
+        }
+      }
+    if (!pivok)  return(0.0);
+    }    
+
+  for (k=i+1; k<n; k++)
+    {
+    fp1 += n;
+    vt2 = *(fp1+i) / vt1 ; 
+    for (j=i+1; j<n; j++)  
+      *(fp1+j) -= (vt2 * *(fp2+j));
+
+    *(fp1+i) = 0.0;  
+    *(b+k) -= (vt2 * *(b+i)) ;
+    }
+
+  }
+
+/*   Calcul du determinant  */
+det = 1.0;
+for (i=0; i<n; i++)  det *= *(mx+i*n+i);
+if ((det < MINDETER) && (det > -MINDETER) )  return(0.0);
+if (det > MXXFLOAT)  det = MXXFLOAT;
+if (det < -MXXFLOAT)  det = -MXXFLOAT;
+
+
+for(i=n-1; i>=0; i--)
+  {
+  fp1 = mx+i*n;
+  six = *(b+i);
+  for (j=i+1; j<n; j++)  six -= (x[j] * *(fp1+j) );
+  x[i] = six / (*(fp1+i));
+
+/*  printf("  Solution X[%2d] = %g \n",i,x[i]);  */
+  }
+
+return(det);
+}
+
+
+
+
+
+/* Nouvelle-Fonction */
+
+double SolveDLinSyst(double *mx, double *b, double *x, int n)
+
+/*  Resolution de systeme lineaire                           */
+/*  Matrice Mx(n,n) * Vecteur X(n) = Vecteur B(n)            */
+/*  Inconnu : vecteur X                                      */
+/*  Retour = Determinant du systeme (=0 Pb)  et X[]          */
+/*  Note : Au retour le vecteur B(n) et la matrice Mx(n,n)   */
+/*  sont modifies. Mx(n,n) contient une matrice triangulaire */
+/*  superieure                                               */                          
+
+{
+int i,k;
+register int j;
+register double *fp1, *fp2;
+double det;
+double vt1;
+register double vt2;
+register double six;
+int pivok;
+
+
+#define  DMINPIVOT   1.e-25
+#define  DMINDETER   1.e-30
+
+
+
+for (i=0; i<n-1; i++)   /*  Boucle sur les pivots */
+  {
+
+/*  printf("\n Iteration %d : \n",i);
+  for (k=0; k<n; k++)
+    {
+    for (j=0; j<n; j++)  printf(" %10g ",*(mx+k*n+j));
+    printf("    b= %10g \n",*(b+k));
+    }  */
+
+  fp1 = fp2 = mx+i*n;  
+  vt1 = *(fp1+i) ;
+
+  if ((vt1 < DMINPIVOT) && (vt1 > -DMINPIVOT) )   /* Pivot trop petit  */
+    {
+    pivok = 0;
+    for (k=i+1; k<n; k++)
+      {
+      vt1 = *(mx+k*n+i) ;
+      if ((vt1 > DMINPIVOT) || (vt1 < -DMINPIVOT) )
+        {
+        fp2 = mx+k*n;  
+        for (j=i; j<n; j++)
+          {
+          *(fp1+j) += *(fp2+j);
+          }
+        *(b+i) += *(b+k);
+        vt1 = *(fp1+i) ;  
+        fp2 = fp1;
+        pivok = 1;
+        break;
+        }
+      }
+    if (!pivok)  return(0.0);
+    }    
+
+  for (k=i+1; k<n; k++)
+    {
+    fp1 += n;
+    vt2 = *(fp1+i) / vt1 ; 
+    for (j=i+1; j<n; j++)  
+      *(fp1+j) -= (vt2 * *(fp2+j));
+
+    *(fp1+i) = 0.0;  
+    *(b+k) -= (vt2 * *(b+i)) ;
+    }
+
+  }
+
+/*   Calcul du determinant  */
+det = 1.0;
+for (i=0; i<n; i++)  det *= *(mx+i*n+i);
+if ((det < DMINDETER) && (det > -DMINDETER) )  return(0.0);
+if (det > MXXFLOAT)  det = MXXFLOAT;
+if (det < -MXXFLOAT)  det = -MXXFLOAT;
+
+
+for(i=n-1; i>=0; i--)
+  {
+  fp1 = mx+i*n;
+  six = *(b+i);
+  for (j=i+1; j<n; j++)  six -= (x[j] * *(fp1+j) );
+  x[i] = six / (*(fp1+i));
+
+/*  printf("  Solution X[%2d] = %g \n",i,x[i]);  */
+  }
+
+return(det);
+}
+
+
+
+
+/*    ==============================================================  */
+/*   Fonctions de Fit lineaire de Xi2                                 */
+/*    ==============================================================  */
+
+/*   .......... Fit avec vecteurs depart reels ...............      */
+
+static int FFBusy = -1;                /*  Flag Deja Busy (GetFitVect effectue)  */
+static int FNVarMax = 0;               /*  Nb Maxi de variables a ajuster        */
+static int FVLenMax = 0;               /*  Longueur maxi des vecteurs            */
+static float **FVeci = NULL;           /*  Vecteurs en entree  *Vecf = Y         */
+                                       /*                      *(Vecf+i) = X[i]  */
+static float **FVecf = NULL;           /*  Vecteurs *FVecf = *FVecf+2 = B = M.X  */                                           
+                                       /*           *(FVecf+1) = La sortie = Ai  */
+static float *FVSpace = NULL;          /*  Espace pour les *FVeci                */  
+static float *FVSpacef = NULL;         /*    "   "    "    *FVecf                */
+static double  *FFMtx = NULL;          /*  Matrice a inverser = M                */
+static double  *FFMtx2 = NULL;         /*   Copie de M                           */
+static double  *FFSort = NULL;         /*  RFitLinErr() pour Sortie GausPiv()    */
+                                       /*  FNVarMax Lignes * (FNVarMax+1) Col.   */
+                                       /*  Col1= Solution, Col2..N+1 : MatInv    */        
+
+
+int InitRFitLin(int nvarmx, int szv)
+
+/*  Initialisation du fit de Xi2 Entier             */
+/*  Allocation d'espace memoire                     */
+/*  nvarmx = Nb maxi de variable                    */
+/*  szv = Taille maxi des vecteurs de points        */
+
+{
+int i;
+
+FFBusy = -1;
+nvarmx ++;
+if (nvarmx < 7)  nvarmx = 7;
+if (szv < 25) szv = 25;
+
+if ( (FVeci = (float**) malloc(nvarmx*sizeof(float *))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(Veci)) \n");
+  return(1);
+  }
+
+if ( (FVSpace = (float*)  malloc(nvarmx*szv*sizeof(float))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(VSpace)) \n");
+  free(FVeci);
+  return(2);
+  }
+
+for(i=0; i<nvarmx; i++)  *(FVeci+i) = FVSpace+i*szv;
+
+
+if ( (FVecf = (float**) malloc(3*sizeof(float *))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(Vecf)) \n");
+  free(FVeci);
+  free(FVSpace);
+  return(3);
+  }
+
+if ( (FVSpacef = (float*) malloc(3*szv*sizeof(float))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(VSpacef)) \n");
+  free(FVeci);
+  free(FVSpace);
+  free(FVecf);
+  return(4);
+  }
+
+for(i=0; i<3; i++)  *(FVecf+i) = FVSpacef+i*szv;
+
+
+if ( (FFMtx = (double*) malloc(nvarmx*nvarmx*sizeof(double))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(FMtx)) \n");
+  free(FVeci);
+  free(FVSpace);
+  free(FVecf);
+  free(FVSpacef);
+  return(5);
+  }
+
+if ( (FFMtx2 = (double*) malloc(nvarmx*nvarmx*sizeof(double))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(FMtx2)) \n");
+  free(FVeci);
+  free(FVSpace);
+  free(FVecf);
+  free(FVSpacef);
+  free(FFMtx);
+  return(6);
+  }
+
+if ( (FFSort = (double*) malloc((nvarmx+1)*nvarmx*sizeof(double))) == NULL )
+  { printf("InitRFitLin_Erreur: (Pb malloc(FFSort)) \n");
+  free(FVeci);
+  free(FVSpace);
+  free(FVecf);
+  free(FVSpacef);
+  free(FFMtx);
+  free(FFMtx2);
+  return(7);
+  }
+
+FFBusy = 0;
+FNVarMax = nvarmx-1;
+FVLenMax = szv;
+
+return(0);
+}
+
+
+/* Nouvelle-Fonction */
+void EndRFitLin()
+{
+
+if (FVeci != NULL)  free(FVeci);
+if (FVSpace != NULL)  free(FVSpace);
+if (FVecf != NULL)  free(FVecf);
+if (FVSpacef != NULL)  free(FVSpacef);
+if (FFMtx != NULL)  free(FFMtx);
+if (FFMtx2 != NULL)  free(FFMtx2);
+if (FFSort != NULL)  free(FFSort);
+
+FVeci = NULL;
+FVSpace = NULL;
+FVecf = NULL;
+FVSpacef = NULL;
+FFMtx = NULL;
+FFMtx2 = NULL;
+
+FFBusy = -1;
+FNVarMax = 0;
+FVLenMax = 0;
+return;
+}
+
+
+/* Nouvelle-Fonction */
+
+float **GetRFitVect(int nvar, int vsz)
+/*  reservation de l'espace des vecteurs pour le fit  */
+{
+int nvmx, vszmx;
+
+if (FFBusy > 0)  
+  { printf("GetRFitVect_Erreur:  FFBusy= %d \n",FFBusy);
+  return(NULL);  }
+if ((nvar < 1) || (vsz < 1) )  
+  { printf("GetRFitVect_Erreur:  NVar,VSz= %d %d \n",nvar,vsz);
+  return(NULL);  }
+if ((nvar > FNVarMax) || (vsz > FVLenMax) || (FFBusy < 0))
+  {
+  EndRFitLin();
+  if (nvar > FNVarMax)   nvmx = nvar;
+  else  nvmx = FNVarMax;
+  if (vsz > FVLenMax)  vszmx = vsz;
+  else vszmx = FVLenMax;
+  if (InitRFitLin(nvmx, vszmx) != 0)  return(NULL);
+  }
+
+FFBusy = 1;
+return(FVeci);
+}
+
+
+/* Nouvelle-Fonction */
+void FreeRFitVect()
+{
+FFBusy = 0;
+return;
+}
+
+/* Nouvelle-Fonction */
+
+float RFitLin(int nd, int vsz, float *XVar)
+
+/*  Effectue le fit de Xi2 pour nd inconnu, Taille vecteurs vsz */
+/*  Les vecteurs doivent etre remplis auparavant                */
+/*  Retourne la valeur du Xi2 du fit, Negatif si Pb.            */
+
+{
+int i,j;
+register float *ip;
+register float *fp, *fp2;
+register double x;
+register float y;
+register float *ffmtx, *ffmtx2;
+float det, rc;
+
+
+if ((nd > FNVarMax) || (vsz > FVLenMax) )   {rc = -1000.0;  goto Fin; }
+
+/*  Fabrication matrice du syteme lineaire a resoudre  */
+ffmtx = (float *)FFMtx;
+ffmtx2 = (float *)FFMtx2;
+for(i=0; i<nd; i++)
+  {
+  fp = ffmtx+i*nd;   fp2 = ffmtx2+i*nd;
+  ip = *(FVeci+i+1);
+
+/*  Elements diagonals  */
+  *(fp2+i) = *(fp+i) = RVecxVec( ip, ip, vsz) ;  
+ 
+  for(j=i+1; j<nd; j++)  
+    {                /* Les autres elements  */
+    *(fp2+j) = *(fp+j) = RVecxVec( ip, *(FVeci+j+1), vsz) ;
+  /* Matrice symetrique */ 
+    *(ffmtx2+j*nd+i) = *(ffmtx+j*nd+i) = *(fp+j);  
+    }
+
+/*  Second membre  M.X = B   */
+  fp = *FVecf;  fp2 = *(FVecf+2);
+  *(fp2+i) = *(fp+i) = RVecxVec( ip, *FVeci, vsz) ;
+  
+  }
+
+/*  On resoud le systeme lineaire : */
+det = SolveRLinSyst(ffmtx, *FVecf, *(FVecf+1), nd);
+if (det == 0.0)   {rc = -500.0;  goto Fin; }
+
+/*  On calcule le Xi2  */
+x = RVecxVec( *FVeci, *FVeci, vsz);
+fp = *(FVecf+2);  
+for(i=0; i<nd; i++)
+  {
+  XVar[i] = y = *(*(FVecf+1)+i);  
+  fp2 = ffmtx2+i*nd+i;   
+  x += (y * y * *fp2);
+  x -= ( 2.0 * ( y * *(fp+i) ) );
+  for (j=i+1; j<nd; j++)  
+    { fp2++;  
+    x += 2.0 * y * *(*(FVecf+1)+j) * *fp2 ;  }    
+  }
+
+rc = (float)x;
+
+Fin:
+FreeRFitVect();
+return(rc);
+}
+
+
+
+/* Nouvelle-Fonction */
+
+float RFitLinErr(int nd, int vsz, float *XVar, float *Err)
+
+/*  Effectue le fit de Xi2 pour nd inconnu, Taille vecteurs vsz */
+/*  Les vecteurs doivent etre remplis auparavant                */
+/*  Retourne la valeur du Xi2 du fit, Negatif si Pb.            */
+
+{
+int i,j,md;
+register float *ip;
+register double *dp, *dp2;
+register float *fp;
+register double x,y;
+float rc;
+double det;
+
+
+if ((nd > FNVarMax) || (vsz > FVLenMax) )   {rc = -1000.0;  goto Fin; }
+
+md = nd+1;  
+/*  Mise a zero de la matrice de sortie et creation matrice identite */
+for(i=0; i<nd*md; i++)  FFSort[i] = 0.;
+for(i=1; i<nd*md; i += md+1) FFSort[i] = 1.;  
+
+/*  Fabrication matrice du syteme lineaire a resoudre  */
+
+for(i=0; i<nd; i++)
+  {
+  dp = FFMtx+i*nd;   dp2 = FFMtx2+i*nd;
+  ip = *(FVeci+i+1);
+
+/*  Elements diagonals  */
+  *(dp+i) = *(dp2+i) = RVecxVec( ip, ip, vsz) ;  
+ 
+  for(j=i+1; j<nd; j++)  
+    {                /* Les autres elements  */
+    *(dp+j) = *(dp2+j) = RVecxVec( ip, *(FVeci+j+1), vsz) ;
+  /* Matrice symetrique */ 
+    *(FFMtx+j*nd+i) = *(FFMtx2+j*nd+i) = *(dp+j);  
+    }
+
+/*  Second membre  M.X = B   */
+  dp = FFSort+i*md;  fp = *(FVecf+2);  
+  *dp = *(fp+i) = RVecxVec( ip, *FVeci, vsz) ;
+  
+  }
+
+
+/*  Appel GausPiv pour resoudre le systeme et inverser la matrice */
+det = GausPiv(FFMtx, nd, nd, FFSort, md, md, 0);
+/* printf("Det= %g Resul= %g %g %g \n",det,FFSort[0], FFSort[md], FFSort[2*md]); */
+if (det == 0.0)  {rc = -500.0;  goto Fin; } 
+ 
+/*  On calcule le Xi2   Et remplissage vecteurs sortie */
+
+x = RVecxVec( *FVeci, *FVeci, vsz);
+fp = *(FVecf+2);  
+for(i=0; i<nd; i++)
+  {
+  y = FFSort[1+i*(md+1)]; 
+  Err[i] = (y >= 0.) ? (float)sqrt(y) : -(float)sqrt(-y);
+  XVar[i]= y =FFSort[i*md];
+ 
+  dp2 = FFMtx2+i*nd+i;  
+  x += (y * y * *dp2);
+  x -= ( 2.0 * ( y * (double)*(fp+i) ) );
+  for (j=i+1; j<nd; j++)  
+    { dp2++;  
+    x += 2.0 *  y * FFSort[j*md] * *dp2 ;  }    
+  }
+rc = (float)x;
+
+Fin:
+FreeRFitVect();
+return(rc);
+}
+
+
+
+
+/*   .......... Fit avec vecteurs depart double ...............      */
+
+/*   Voir description des variables ds IniRFitLin()   */
+static int DFBusy = -1;
+static int DNVarMax = 0;
+static int DVLenMax = 0;
+static double **DVeci = NULL;
+static double **DVecf = NULL;
+static double *DVSpace = NULL;
+static double *DVSpacef = NULL;
+static double  *DFMtx = NULL;
+static double  *DFMtx2 = NULL;
+
+
+int InitDFitLin(int nvarmx, int szv)
+
+/*  Initialisation du fit de Xi2 Entier             */
+/*  Allocation d'espace memoire                     */
+/*  nvarmx = Nb maxi de variable                    */
+/*  szv = Taille maxi des vecteurs de points        */
+
+{
+int i;
+
+DFBusy = -1;
+nvarmx ++;
+if (nvarmx < 7)  nvarmx = 7;
+if (szv < 25) szv = 25;
+
+if ( (DVeci = (double**) malloc(nvarmx*sizeof(double *))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(Veci)) \n");
+  return(1);
+  }
+
+if ( (DVSpace = (double*) malloc(nvarmx*szv*sizeof(double))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(VSpace)) \n");
+  free(DVeci);
+  return(2);
+  }
+
+for(i=0; i<nvarmx; i++)  *(DVeci+i) = DVSpace+i*szv;
+
+
+if ( (DVecf = (double**) malloc(3*sizeof(double *))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(Vecf)) \n");
+  free(DVeci);
+  free(DVSpace);
+  return(3);
+  }
+
+if ( (DVSpacef = (double*) malloc(3*szv*sizeof(double))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(VSpacef)) \n");
+  free(DVeci);
+  free(DVSpace);
+  free(DVecf);
+  return(4);
+  }
+
+for(i=0; i<3; i++)  *(DVecf+i) = DVSpacef+i*szv;
+
+
+if ( (DFMtx = (double*) malloc(nvarmx*nvarmx*sizeof(double))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(FMtx)) \n");
+  free(DVeci);
+  free(DVSpace);
+  free(DVecf);
+  free(DVSpacef);
+  return(5);
+  }
+
+if ( (DFMtx2 = (double*) malloc(nvarmx*nvarmx*sizeof(double))) == NULL )
+  { printf("InitDFitLin_Erreur: (Pb malloc(FMtx2)) \n");
+  free(DVeci);
+  free(DVSpace);
+  free(DVecf);
+  free(DVSpacef);
+  free(DFMtx);
+  return(6);
+  }
+
+DFBusy = 0;
+DNVarMax = nvarmx-1;
+DVLenMax = szv;
+
+return(0);
+}
+
+
+/* Nouvelle-Fonction */
+void EndDFitLin()
+{
+
+if (DVeci != NULL)  free(DVeci);
+if (DVSpace != NULL)  free(DVSpace);
+if (DVecf != NULL)  free(DVecf);
+if (DVSpacef != NULL)  free(DVSpacef);
+if (DFMtx != NULL)  free(DFMtx);
+if (DFMtx2 != NULL)  free(DFMtx2);
+
+DVeci = NULL;
+DVSpace = NULL;
+DVecf = NULL;
+DVSpacef = NULL;
+DFMtx = DFMtx2 = NULL;
+
+DFBusy = -1;
+DNVarMax = 0;
+DVLenMax = 0;
+return;
+}
+
+
+/* Nouvelle-Fonction */
+
+double **GetDFitVect(int nvar, int vsz)
+/*  reservation de l'espace des vecteurs pour le fit  */
+{
+int nvmx, vszmx;
+
+if (DFBusy > 0)  return(NULL);
+if ( (nvar < 1) || (vsz < 1) ) return(NULL);
+if ((nvar > DNVarMax) || (vsz > DVLenMax) || (DFBusy < 0))
+  {
+  EndDFitLin();
+  if (nvar > DNVarMax)   nvmx = nvar;
+  else  nvmx = DNVarMax;
+  if (vsz > DVLenMax)  vszmx = vsz;
+  else vszmx = DVLenMax;
+  InitDFitLin(nvmx, vszmx);
+  }
+
+DFBusy = 1;
+return(DVeci);
+}
+
+
+/* Nouvelle-Fonction */
+void FreeDFitVect()
+{
+DFBusy = 0;
+return;
+}
+
+
+/* Nouvelle-Fonction */
+
+double DFitLin(int nd, int vsz, double *XVar)
+
+/*  Effectue le fit de Xi2 pour nd inconnu, Taille vecteurs vsz */
+/*  Les vecteurs doivent etre remplis auparavant                */
+/*  Retourne la valeur du Xi2 du fit, Negatif si Pb.            */
+
+{
+int i,j;
+register double *ip;
+register double *fp, *fp2;
+register double x,y;
+double det,rc;
+
+
+if ((nd > DNVarMax) || (vsz > DVLenMax) )   { rc = -1000.;  goto Fin; }
+
+/*   Impression de debug  */
+/* 
+for(i=0; i<nd+1; i++)
+  {
+  ip = *(DVeci+i);
+  printf("DFitLin_Debug Veci[%d][0..5]= %lg %lg %lg %lg %lg %lg \n",
+       i,*ip, *(ip+1), *(ip+2), *(ip+3), *(ip+4), *(ip+5));  
+  } 
+*/
+
+
+/*  Fabrication matrice du syteme lineaire a resoudre  */
+
+for(i=0; i<nd; i++)
+  {
+  fp = DFMtx+i*nd;   fp2 = DFMtx2+i*nd;
+  ip = *(DVeci+i+1);
+
+/*  Elements diagonals  */
+  *(fp2+i) = *(fp+i) =  DVecxVec( ip, ip, vsz) ;  
+ 
+  for(j=i+1; j<nd; j++)  
+    {                /* Les autres elements  */
+    *(fp2+j) = *(fp+j) = DVecxVec( ip, *(DVeci+j+1), vsz) ;
+  /* Matrice symetrique */ 
+    *(DFMtx2+j*nd+i) = *(DFMtx+j*nd+i) = *(fp+j);  
+    }
+
+/*  Second membre  M.X = B   */
+  fp = *DVecf;  fp2 = *(DVecf+2);
+  *(fp2+i) = *(fp+i) = DVecxVec( ip, *DVeci, vsz) ;
+  
+  }
+
+/* 
+printf("DFitLin_Debug B[0..5]= %lg %lg %lg %lg %lg %lg \n",
+       *fp2, *(fp2+1), *(fp2+2), *(fp2+3), *(fp2+4), *(fp2+5));
+*/
+
+/*  On resoud le systeme lineaire : */
+fp = *(DVecf+1);
+det = SolveDLinSyst(DFMtx, *DVecf, fp, nd);
+if (det == 0.0)   { rc = -500.;  goto Fin; }
+
+/*  On calcule le Xi2  */
+x = DVecxVec( *DVeci, *DVeci, vsz);
+for(i=0; i<nd; i++)   /* Et on remplit le vecteur de sortie */
+  {
+  fp2 = DFMtx2+i*nd+i;   y = XVar[i] = *(*(DVecf+1)+i);  
+  x += (y * y * *fp2);
+  x -= ( 2.0 * ( y * *(*(DVecf+2)+i) ) );
+  for (j=i+1; j<nd; j++)  
+    { fp2++;  
+    x += ( 2.0 * ( y * *(*(DVecf+1)+j) * *fp2 ) );  }    
+  }
+rc = x;
+
+
+Fin:
+FreeDFitVect();
+return(rc);
+}
+
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/matxop.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/matxop.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/matxop.h	(revision 752)
@@ -0,0 +1,57 @@
+/*  Fonctions de manipulation de matrices et de vecteurs    */
+/*  Resolution de systemes lineaires                        */
+
+/*                              R. Ansari  Juillet 1993     */
+/*  Note: 07/94 Fonction GausPiv(Inversion Matrice) CMV     */
+/*        est utilisee pour  R/DFitLinErr()                 */
+
+#ifndef MATXOP_H_SEEN
+#define MATXOP_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*   Declaration des fonctions   */
+
+/*  Operation Vecteurs/ Matrices   */
+int IVecxVec(int *v1, int *v2, int n);
+float RVecxVec(float *v1, float *v2, int n);
+double DVecxVec(double *v1, double *v2, int n);
+void  IMatxVec(int *mx, int *vi, int *vo, int n);
+void  RMatxVec(float *mx, float *vi, float *vo, int n);
+void  DMatxVec(double *mx, double *vi, double *vo, int n);
+
+/*  Resolution  de systemes lineaires  */
+float SolveRLinSyst(float *mx, float *b, float *x, int n);
+double SolveDLinSyst(double *mx, double *b, double *x, int n);
+
+
+/*  Ajustement de Chi2   */
+
+/*  Ajustement avec vecteurs de depart Reels  */
+int InitRFitLin(int nstmx, int szv);
+void EndRFitLin(void);
+float **GetRFitVect(int nvar, int vsz);
+void FreeRFitVect(void);
+float RFitLin(int nd, int vsz, float *XVar);
+float RFitLinErr(int nd, int vsz, float *XVar, float *Err);
+
+/*  Ajustement avec vecteurs de depart double  */
+int InitDFitLin(int nstmx, int szv);
+void EndDFitLin(void);
+double **GetDFitVect(int nvar, int vsz);
+void FreeDFitVect(void);
+double DFitLin(int nd, int vsz, double *XVar);
+double DFitLinErr(int nd, int vsz, double *XVar, double *Err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/median.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/median.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/median.cc	(revision 752)
@@ -0,0 +1,25 @@
+#if 0
+#include "median.h"
+#include <algorithm>
+
+float MedianFilter(float tab[], int n)
+{
+  sort(tab, tab+n);
+  return (n%2 ? tab[n/2] : (tab[n/2]+tab[n/2-1])/2);
+}
+
+double MedianFilter(double tab[], int n)
+{
+  sort(tab, tab+n);
+  return (n%2 ? tab[n/2] : (tab[n/2]+tab[n/2-1])/2);
+}
+
+void   MedianFilterWindowIdx(float const data[], int ndata, int width, 
+			     int index[])
+{
+  float* tab = new float[witdh];
+
+
+  delete[] tab;
+}
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/median.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/median.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/median.h	(revision 752)
@@ -0,0 +1,28 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#include "machdefs.h"
+
+// Filtre median, retourne la valeur mediane du tableau tab.
+//  *** Le tableau est modifie (trie par ordre croissant)
+float  MedianFilter(float  tab[], int n); 
+double MedianFilter(double tab[], int n);
+int    MedianFilterIdx(float tab[], int n); 
+int    MedianFilterIdx(double tab[], int n); 
+
+// Filtre median sur fenetre glissante. 
+// data[index[i]] est la ieme valeur filtree
+void   MedianFilterWindowIdx(float const data[], int ndata, int width, 
+			     int index[]);
+
+// Filtre median sur fenetre glissante. 
+// fdata[] est le tableau filtre
+void   MedianFilterWindow(float const data[], int ndata, int width,
+			  float fdata[]);
+
+// Filtre median sur fenetre glissante. 
+// fdata[] est le tableau filtre. assoc sont des donnees associees,
+// par exemple des erreurs, qui sont reordonnees avec la meme permutation
+// dans fassoc.
+void   MedianFilterWindow(float const data[], float const assoc[],
+			  int ndata, int width,
+			  float[] fdata, float fassoc[]);
Index: /tags/V_Fev00/SophyaLib/NTools/nbconst.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbconst.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbconst.h	(revision 752)
@@ -0,0 +1,81 @@
+/* quelques fonctions mathematiques et constantes utiles */
+/*                                         cmv  23/06/94 */
+#ifndef NBCONST_H_SEEN
+#define NBCONST_H_SEEN
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// EA conflit entre les diverses copies de nbmath.h, nbconst.h... A nettoyer...
+#undef Pi
+#undef Pis2
+#undef DeuxPi
+#undef SPi
+#undef S2Pi
+#undef Rac2
+#undef Log2
+#undef LnPi
+#undef LgPi
+#undef Ln10
+#undef DftoDm
+#undef Hln2pi
+#undef DegenRad
+#undef JourSec
+#undef AnSec
+
+#undef UAenKM
+#undef UAenLY
+#undef KPCenKM
+#undef KPCenUA
+#undef KPenLY
+#undef LYenKM
+#undef RSolenKM
+#undef RTenKM
+#undef MSolenKg
+#undef GC_RE
+
+#undef GRAND  
+#undef GRAND2 
+#undef IGRAND 
+
+#define Pi     (double) (3.1415926535897931)   /* c'est Pi */
+#define Pis2   (double) (1.57079632679489655)  /* c'est Pi/2 */
+#define DeuxPi (double) (6.2831853071795862)   /* c'est 2*Pi */
+#define SPi    (double) (1.7724538509055159)   /* c'est sqrt(Pi) */
+#define S2Pi   (double) (2.5066282746310002)   /* c'est sqrt(2*Pi) */
+#define Rac2   (double) (1.4142135623730950)   /* c'est sqrt(2) */
+#define Log2   (double) (0.30102999566398119)  /* c'est log10(2) */
+#define LnPi   (double) (1.1447298858494002)   /* c'est ln(Pi) */
+#define LgPi   (double) (0.49714987269413385)  /* c'est log10(Pi) */
+#define Ln10   (double) (2.3025850929940456)   /* c'est ln(10) */
+#define DftoDm (double) (1.0857362047581295)   /* c'est 2.5/ln(10) */
+#define Hln2pi (double) (0.91893853320467267)  /* c'est Ln(2*pi)/2 */
+#define DegenRad (double) (0.0174532925199)    /* nombre de radians dans un degre */
+
+#define JourSec (float) (86400.)    /* nombre de secondes dans 24H */
+#define AnSec  (int) (31557600)     /* nombre de secondes dans 365.25 jours */
+
+#define UAenKM (double) (149597870.) /* nombre de kilometres dans une unite astronomique */
+#define UAenLY (double) (1.5812507406e-5) /* unite astronomique en annees lumiere */
+#define KPCenKM (double) (3.0856775807e+16) /* nombre de kilometres dans un kiloparsec */
+#define KPCenUA (double) (206264806.248) /* nombre d'unites astronomiques dans un kiloparsec */
+#define KPenLY (double) (3261.5637763) /* kiloparsec en annees lumiere */
+#define LYenKM (double) (9.4607304725808*e+12) /* annee lumiere en kilometres */
+#define RSolenKM (double) (6.9599e+5) /* Rayon solaire en kilometres */
+#define RTenKM (double) (6378.14) /* rayon equatorial terrestre en kilometres */
+
+#define MSolenKg (double) (1.9891e+30) /* masse solaire en kilogramme */
+
+#define GC_RE ((double) 4.7854172e-17) /* c'est G/c**2 en unites kpc/Mo  */
+
+#define GRAND  (float) (1.e+35)
+#define GRAND2 (double) (1.e+35)
+#define IGRAND (int_4) (2147483647)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/nbinteg.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbinteg.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbinteg.h	(revision 752)
@@ -0,0 +1,146 @@
+/* Pour integration par la methode "higher order gaussian terms" */
+/*                                                cmv   23/06/94 */
+
+#ifndef NBINTEG_H_SEEN
+#define NBINTEG_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=============================================================*/
+static int mIhoq2 = 2;
+static double Ihoq2X[2] =
+   { -0.288675135, 0.288675135 };
+static double Ihoq2W[2] =
+   {  0.500000000, 0.500000000 };
+/*=============================================================*/
+static int mIhoq3 = 3;
+static double Ihoq3X[3] =
+   { -0.387298335, 0.000000000, 0.387298335 };
+static double Ihoq3W[3] =
+   {  0.277777778, 0.444444444, 0.277777778 };
+/*=============================================================*/
+static int mIhoq4 = 4;
+static double Ihoq4X[4] =
+   { -0.430568156,-0.169990522, 0.169990522, 0.430568156 };
+static double Ihoq4W[4] =
+   {  0.173927423, 0.326072577, 0.326072577, 0.173927423 };
+/*=============================================================*/
+static int mIhoq5 = 5;
+static double Ihoq5X[5] =
+   { -0.453089923,-0.269234655, 0.000000000, 0.269234655,
+      0.453089923 };
+static double Ihoq5W[5] =
+   {  0.118463443, 0.239314335, 0.284444444, 0.239314335,
+      0.118463443 };
+/*=============================================================*/
+static int mIhoq6 = 6;
+static double Ihoq6X[6] =
+   { -0.466234757,-0.330604693,-0.119309593, 0.119309593,
+      0.330604693, 0.466234757 };
+static double Ihoq6W[6] =
+   {  0.085662246, 0.180380787, 0.233956967, 0.233956967,
+      0.180380787, 0.085662246 };
+/*=============================================================*/
+static int mIhoq7 = 7;
+static double Ihoq7X[7] =
+   { -0.474553956,-0.370765593,-0.202922576, 0.000000000,
+      0.202922576, 0.370765593, 0.474553956 };
+static double Ihoq7W[7] =
+   {  0.064742483, 0.139852696, 0.190915025, 0.208979592,
+      0.190915025, 0.139852696, 0.064742483 };
+/*=============================================================*/
+static int mIhoq8 = 8;
+static double Ihoq8X[8] =
+   { -0.480144928,-0.398333239,-0.262766205,-0.091717321,
+      0.091717321, 0.262766205, 0.398333239, 0.480144928 };
+static double Ihoq8W[8] =
+   {  0.050614268, 0.111190517, 0.156853323, 0.181341892,
+      0.181341892, 0.156853323, 0.111190517, 0.050614268 };
+/*=============================================================*/
+static int mIhoq9 = 9;
+static double Ihoq9X[9] =
+   { -0.484080120,-0.418015554,-0.306685716,-0.162126712,
+      0.000000000, 0.162126712, 0.306685716, 0.418015554,
+      0.484080120 };
+static double Ihoq9W[9] =
+   {  0.040637194, 0.090324080, 0.130305348, 0.156173539,
+      0.165119678, 0.156173539, 0.130305348, 0.090324080,
+      0.040637194 };
+/*=============================================================*/
+static int mIhoq10 = 10;
+static double Ihoq10X[10] =
+   { -0.486953264,-0.432531683,-0.339704784,-0.216697697,
+     -0.074437169, 0.074437169, 0.216697697, 0.339704784,
+      0.432531683, 0.486953264 };
+static double Ihoq10W[10] =
+   {  0.033335672, 0.074725675, 0.109543181, 0.134633360,
+      0.147762112, 0.147762112, 0.134633360, 0.109543181,
+      0.074725675, 0.033335672 };
+/*=============================================================*/
+static int mIhoq16 = 16;
+static double Ihoq16X[16] =
+   { -0.494700467,-0.472287512,-0.432815601,-0.377702204,
+     -0.308938122,-0.229008389,-0.140801775,-0.047506255,
+      0.047506255, 0.140801775, 0.229008389, 0.308938122,
+      0.377702204, 0.432815601, 0.472287512, 0.494700467 };
+static double Ihoq16W[16] =
+   {  0.013576230, 0.031126762, 0.047579256, 0.062314486,
+      0.074797994, 0.084578260, 0.091301708, 0.094725305,
+      0.094725305, 0.091301708, 0.084578260, 0.074797994,
+      0.062314486, 0.047579256, 0.031126762, 0.013576230 };
+/*=============================================================*/
+
+
+/* Integration 2D domaine carre */
+/* Selon Abramowitz p892-893 formule 25.462, residu ordre 0.5**6 */
+/* 0.387298=0.5*sqrt(3/5)  0.197531=16/81  0.123457=10/81  0.077160=25/324 */
+/*  */
+#if defined(SIMPSON9)
+  static int   nd2d = 9;
+  static float dx2d[9] = { 0.000000 ,  0.000000 ,  0.000000
+                         ,-0.387298 ,  0.387298 , -0.387298
+                         , 0.387298 , -0.387298 ,  0.387298 };
+  static float dy2d[9] = { 0.000000 , -0.387298 ,  0.387298
+                         , 0.000000 ,  0.000000 , -0.387298
+                         , 0.387298 ,  0.387298 , -0.387298 };
+  static float  w2d[9] = { 0.197531 ,  0.123457 ,  0.123457
+                         , 0.123457 ,  0.123457 ,  0.077157
+                         , 0.0771605,  0.0771605,  0.0771605};
+#elif defined(SIMPSON4)
+  static int   nd2d = 4;
+  static float dx2d[4] = { 0.288675, 0.288675,-0.288675,-0.288675 };
+  static float dy2d[4] = { 0.288675,-0.288675, 0.288675,-0.288675 };
+  static float  w2d[4] = { 0.250000, 0.250000, 0.250000, 0.250000 };
+#elif defined(INTEG5)
+  static int   nd2d = 5;
+  static float dx2d[5] = { 0. , -0.3, -0.3,  0.3, 0.3 };
+  static float dy2d[5] = { 0. , -0.3,  0.3, -0.3, 0.3 };
+  static float  w2d[5] = { 0.2,  0.2,  0.2,  0.2, 0.2 };
+#elif  defined(NOINTEG)
+  static int   nd2d = 1;
+  static float dx2d[1] = { 0. };
+  static float dy2d[1] = { 0. };
+  static float  w2d[1] = { 1. };
+#else
+  static int   nd2d = 0;
+  static float dx2d[1] = { 999999. };
+  static float dy2d[1] = { 999999. };
+  static float  w2d[1] = { 0. };
+#endif
+
+
+/* Coeff pour le calcul du volume de f(x,y,z) dans des cubes 3D */
+static int   nd3d = 6;
+static float dx3d[6] = { 0.5, -0.5, 0.0,  0.0, 0.0,  0.0  };
+static float dy3d[6] = { 0.0,  0.0, 0.5, -0.5, 0.0,  0.0  };
+static float dz3d[6] = { 0.0,  0.0, 0.0,  0.0, 0.5, -0.5  };
+static float  w3d[6] = { 0.166667, 0.166667, 0.166667, 
+                         0.166667, 0.166667, 0.166667 };
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/nbmath.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbmath.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbmath.c	(revision 752)
@@ -0,0 +1,2735 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <math.h>
+#include "nbmath.h"
+#include "matxop.h"
+#include "nbinteg.h"
+#include "nbtri.h"
+
+#define ITMAX 256
+#define EPS 3.0e-7
+#define DEB_GausPiv 0
+#define DEB_MeanSig 0
+
+/*
+++ 
+  Module	Fonction mathematiques (C)
+  Lib	LibsUtil
+  include	nbmath.h
+
+	Fonction mathematiques (C)
+--
+*/
+
+void FitFun_MrqCof( double (*FunFit) (double ,double *,double *) ,int_4 type
+           ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
+           ,int_4 *ndata,int_4 I1,int_4 I2
+           ,double *parcur,int_4 npar,int_4 *ind
+           ,double *ATGA,double *BETA,double *ci2,int_4 deb);
+void nbgcf(double *gammcf,double a,double x,double *gln);
+void nbgser(double *gamser,double a,double x,double *gln);
+
+
+static int FITFUN_DPOL = -1;
+
+
+/*=========================================================================*/
+/*                                      Christophe 8/11/93 La Silla */
+/*
+++
+double FitFun
+|        ( double (*FunFit) (double ,double *,double *) ,int_4 type
+|        ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
+|        ,int_4 *ndata,int_4 I1,int_4 I2
+|        ,double *par,double *epar,double *stepar
+|        ,double *minpar,double *maxpar,int_4 npar
+|        ,double stochi2,int_4 NstepMX,int_4 deb)
+
+	Pour fitter une fonction parametrique sur des donnees.
+	(Obsolete, utilisez GeneralFit en C++).
+--
+*/
+/*
+++
+| Fonction de fit de la courbe FunFit sur les donnees
+| - Methode:   fit des moindres carres dans le cas non lineaire
+| - Reference: Statistical and Computational Methods in Data Analysis
+|              Siegmund Brandt, North-Holland 1970  p 204-206.
+|              Introduction des limites pour la variation des parametres (cmv).
+|              Increment des parametres selon la methode de Levenberg-Marquardt
+|              (Numerical Receipes in C p 542)
+| - Remarques diverses:
+|     Les points avec erreurs negatives ou nulles ne sont pas
+|                utilises dans le fit.
+|     Si le fit est hautement non lineaire, il faut donner de bonnes
+|                approximations pour les parametres de depart.
+|     Les limites minpar,maxpar sont des limites absolues mais possibles
+| - Memo personnel:
+|     data = Ti, Fi ERRi  i=0,n-1
+|     parametres Pj  j=1,npar
+|     fonction FunFit(t,P1,P2,..,Pnpar)
+|     matrice A(n,4) = [Aij] = - [dg(T)/dPj]  pour t=Ti
+|     matrice G(n,n) = [Gij] = matrice diagonale 1/ERRj**2
+|     matrice C(n) = [Ci] = (Fi - FunFit(t,P1,P2,..,Pnpar))
+|     Pj(iteration n) = Pj(iteration n-1) + Zj
+--
+*/
+/*
+++
+| -----------
+| | ENTREES |
+| -----------
+| - FunFit  fonction a fiter
+| - type    type des donnees a fiter (union temps,mag,err):
+|           float=FITFUN_FLOAT / double=FITFUN_DOUBLE
+| - temps:  union FLOATDOUBLE des tableaux des temps:
+| - mag:    union FLOATDOUBLE des tableaux des magnitudes:
+| - err:    union FLOATDOUBLE des tableaux des erreurs sur la magnitude
+| - ndata:  nombre de donnees en entree, donc en c:
+| - I1:     indice de depart pour le fit
+| - I2:     indice de fin pour le fit
+|           (si I2 <= I1 defaut: 1,*ndata)
+| - par:    contient les valeurs d'initialisation des parametres
+| - stepar: si >0. on fit le parametre, sinon parametre fixe
+| - minpar: les valeurs minimum pouvant prendre les parametres
+| - maxpar: les valeurs minimum pouvant prendre les parametres
+|           (si maxpar[i] <= minpar[i] pas de limitation sur le parametre i)
+| - stochi2:la valeur de variation du chi2 d'une iteration l'autre
+|           en dessous de laquelle on arrete d'iterer:
+|           (si <=0 le default est 0.01).
+| - npar:   nombre de parametres du fit *par --> *(par+npar-1)
+| - NstepMX:nombre maximum d'iterations
+| - deb:    niveau de print (0/1/2/3)
+--
+*/
+/*
+++
+| ----------
+| | SORTIES |
+| ----------
+| - ndata: nombre de donnees utilisees dans le fit
+| - par: contient les valeurs fitees des parametres
+| - epar: contient les erreurs sur les valeurs fitees des parametres
+| - FitFun: la function elle meme retourne le Xi2 du fit si succes
+|       -1. si l'inversion de la matrice des erreurs n'a pas ete possible
+|       -2. si les parametres initiaux sont en desaccord avec les limites
+|       -3. si le nombre de donnees est inferieur au nombre de parametres
+|       -4. si le fit n'a pas converge (nstep>nNstepMX)
+--
+*/
+/*
+++
+| --------------
+| | MEMO PERSO |
+| --------------
+| la structure FLOATDOUBLE:
+| union FloatDouble {
+|   float  *fx;
+|   double *dx;
+| };
+| - Si les tableaux temps,mag,emag sont des float alors
+|   temps.fx doit contenir l'adresse du tableau des temps
+|            (et idem pour mag.fx et err.fx)
+| - Si les tableaux temps,mag,emag sont des double alors
+|   temps.dx doit contenir l'adresse du tableau des temps
+|            (et idem pour mag.dx et err.dx)
+--
+*/
+double FitFun( double (*FunFit) (double ,double *,double *) ,int_4 type
+             ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
+             ,int_4 *ndata,int_4 I1,int_4 I2
+             ,double *par,double *epar,double *stepar
+             ,double *minpar,double *maxpar,int_4 npar
+             ,double stochi2,int_4 NstepMX,int_4 deb)
+{
+int_4 ind[NPAR_FITFUN], i, j, k, nstep, nparsave, nstop, nstopMX;
+double LimitC2,lambda,eps;
+double ATGA[NPAR_FITFUN][NPAR_FITFUN], COVAR[NPAR_FITFUN][NPAR_FITFUN]
+     , ALPHA[NPAR_FITFUN][NPAR_FITFUN];
+double DA[NPAR_FITFUN], BETA[NPAR_FITFUN];
+double parcur[NPAR_FITFUN],partry[NPAR_FITFUN];
+double ci2, ci20;
+
+/* initialisation */
+if( type != FITFUN_FLOAT && type != FITFUN_DOUBLE) {
+  printf("FitFun: Type de variable non prevue dans union FLOATDOUBLE %d\n",type);
+  exit(-1);
+}
+
+if(npar>NPAR_FITFUN) {
+  printf("FitFun: trop de parametres npar=%d > NPAR_FITFUN=%d\n",npar,NPAR_FITFUN);
+  exit(-1);
+}
+nstopMX = 3;
+eps = 1.e-8;
+LimitC2=0.01;
+if ( stochi2 > 0. ) LimitC2 = stochi2;      /* test des valeurs d'arret */
+nstop = 0;
+
+/* fit du centre autour des valeurs estimees */
+nparsave = npar;
+for (i=0;i<nparsave;i++) parcur[i] = *(par+i);
+
+npar=0;
+for (i=0;i<nparsave;i++) {
+  ind[i]= -1;
+  *(epar+i) = 0.;
+  partry[i] = *(parcur+i);
+  if ( stepar[i] > 0. ) {
+    ind[npar]=i;
+    npar++;
+} }
+
+if ( I2 <= I1 ) { I1 = 0; I2 = *ndata-1;}
+if ( I2-I1+1 < npar ) {
+  printf("le nombre de donnees %d est inferieur au nombre de parametres %d\n"
+        ,I2-I1+1,npar);
+  return(-3.);
+}
+ 
+for (j=0;j<npar;j++) {
+  i = ind[j];
+  if(*(maxpar+i)>*(minpar+i) && (*(parcur+i)<=*(minpar+i) || *(parcur+i)>=*(maxpar+i))) {
+    printf("Parametre %d initialise hors limites: %f # [%f,%f]\n"
+          ,i,*(parcur+i),*(minpar+i),*(maxpar+i));
+    return(-2.);
+} }
+
+if ( deb >= 2 ) {
+  printf("\n******************* ENTREE DANS FitFun ");
+  printf("npar=%d LimitC2=%f\n",npar,LimitC2);
+  printf("parametres"); for(i=0;i<nparsave;i++) printf(" %f",*(parcur+i)); printf("\n");
+  if ( deb >= 3 ) {
+    printf("       ind"); for(i=0;i<nparsave;i++) printf(" %12d",*(ind+i)); printf("\n");
+    printf("    stepar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(stepar+i)); printf("\n");
+    printf("    minpar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(minpar+i)); printf("\n");
+    printf("    maxpar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(maxpar+i)); printf("\n");
+} }
+
+/* premiere essai avec les parametres d'initialisation */
+
+FitFun_MrqCof(FunFit,type,temps,mag,err,ndata,I1,I2,parcur,npar,ind,ALPHA[0],BETA,&ci2,deb);
+
+ci20 = ci2;
+lambda = 0.001;
+
+if ( *ndata < npar ) {
+  printf("le nombre de donnees %d est inferieur au nombre de parametres %d\n",*ndata,npar);
+  return(-3.);
+}
+
+if ( deb >= 2 ) printf("Passage d'initialisation ci2= %e, lambda=%e\n",ci2,lambda);
+
+/* et maintenant les iterations */
+
+nstep = 0;
+/************************ ITERATIONS *******************************************/
+ITERATE:
+nstep++;
+
+if ( deb >= 2 ) printf("------------------------- pas %d\n",nstep);
+
+if(nstep > NstepMX) {
+  printf("FitFun: Le fit n'a pas converge (trop d'iterations %d).\n",nstep);
+  if (deb>0 ) {
+    printf("== Parametres finals:");
+    for(k=0;k<nparsave;k++) printf(" %15.8e",parcur[k]); printf("\n");
+    for(i=0;i<npar;i++) { *(epar+ind[i]) = -1.; par[ind[i]] = parcur[ind[i]];}
+  }
+  return(-4.);
+}
+
+for(j=0;j<npar;j++) {
+  for(i=0;i<npar;i++) ATGA[j][i] = ALPHA[j][i];
+  ATGA[j][j] *= 1.0 + lambda;
+}
+
+/* inversion de   ( At * G * A ) */
+if( GausPiv(ATGA[0],NPAR_FITFUN,npar,COVAR[0],NPAR_FITFUN,npar,1) == 0. ) {
+  printf("La matrice des erreurs n'est pas inversible\n");
+  return(-1.);
+}
+if( deb >= 3 ) {
+  printf("matrice 1/( At * G * A )\n");
+  for ( i=0; i<npar; i++ ) {
+    for ( j=0; j<npar; j++ ) printf(" %15.8e",COVAR[i][j]);
+    printf("\n");
+} }
+
+/* compute next increment */
+for(i=0;i<npar;i++) {
+  DA[i] = 0.;
+  for(j=0;j<npar;j++) DA[i] += COVAR[i][j] * BETA[j];
+}
+if ( deb >= 2 ) {
+  printf("Correction parametres proposee:");
+  for (i=0;i<npar;i++) printf(" %12.5e",DA[i]); printf("\n");
+}
+
+/* on s'arrete la, il y a eu convergence */
+if ( lambda == 0. ) {
+  for(i=0;i<npar;i++) { *(epar+ind[i]) = sqrt(COVAR[i][i]); par[ind[i]] = parcur[ind[i]];}
+  if (deb>0 ) {
+    printf("===============================================================\n");
+    printf("== ci2= %15.8e (%15.8e) ndata= %d nstep= %d\n",ci2,ci2/(*ndata-npar+1),*ndata,nstep);
+    printf("== Parametres finals:"); for(k=0;k<nparsave;k++) printf(" %15.8e", par[k]); printf("\n");
+    printf("==               +/- "); for(k=0;k<nparsave;k++) printf(" %15.8e",epar[k]); printf("\n");
+    printf("===============================================================\n");
+  }
+  return( (float) ci2 );
+}
+
+/* essai des nouveaux parametres */
+for(j=0;j<npar;j++) {
+  k = ind[j];
+  if( nstep == 1 && fabs(DA[j]) > stepar[k] ) {
+    partry[k] = parcur[k] + stepar[k] * DA[j] / fabs(DA[j]);
+  } else {
+    partry[k] = parcur[k] + DA[j];
+  }
+  if(maxpar[k] > minpar[k] ) {
+    if( partry[k] < minpar[k] ) {
+      partry[k] = minpar[k];
+      if(deb>=2) printf("Parametre %3d limite au minimum %e\n",k,partry[k]);
+    }
+    if( partry[k] > maxpar[k] ) {
+      partry[k] = maxpar[k];
+      if(deb>=2) printf("Parametre %3d limite au maximum %e\n",k,partry[k]);
+    }
+} }
+if ( deb>=2)
+  {
+  printf("essai avec");
+  for(k=0;k<nparsave;k++) printf(" %15.8e", partry[k]);
+  printf("\n");
+  }
+
+/* calcul du nouveau ci2 avec partry */
+FitFun_MrqCof(FunFit,type,temps,mag,err,ndata,I1,I2,partry,npar,ind,ATGA[0],DA,&ci2,deb);
+if(deb>=2) printf("Ci2: old=%e new=%e %e\n",ci20,ci2,ci2-ci20);
+
+/* test sur l'evolution du ci2 et la strategie a suivre */
+if ( ci2 < ci20 ) {
+  nstop = 0;
+  for (j=0;j<npar;j++) {
+    for(i=0;i<npar;i++) ALPHA[j][i] = ATGA[j][i];
+    BETA[j] = DA[j];
+    parcur[ind[j]] = partry[ind[j]];
+  }
+  lambda *= 0.1;
+  if( ci20 - ci2 < LimitC2 ) lambda = 0.;
+  ci20 = ci2;
+  if(deb>=2) {
+    printf("lambda divided by 10. %e\n",lambda);
+    printf("Nouveaux parametres"); for(k=0;k<nparsave;k++) printf(" %12.5e",parcur[k]); printf("\n");
+  }
+} else {
+  /* on arrete si pas assez de variation de chi2 + pas assez de variation de parametres */
+  if( ci2 - ci20 < LimitC2 ) {
+    k=0;
+    for(i=0;i<npar;i++) if( fabs( parcur[ind[i]] - partry[ind[i]] ) < eps ) k++;
+    if(k == npar) { nstop++; } else { nstop=0;};
+    /* printf("ci2-ci20=%f npar=%d (%d) nstop=%d\n"
+           ,ci2-ci20,npar,k,nstop); */
+  } else {
+    nstop = 0;
+  }
+  lambda *= 10.;
+  if(nstop>=nstopMX) lambda = 0.;
+  ci2 = ci20;
+  if(deb>=2) printf("Echec essai, lambda multiplied by 10. %e\n",lambda);
+}
+
+goto ITERATE;
+
+}
+
+/*=========================================================================*/
+void FitFun_MrqCof(double (*FunFit) (double ,double *,double *) ,int_4 type
+           ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
+           ,int_4 *ndata,int_4 I1,int_4 I2
+           ,double *parcur,int_4 npar,int_4 *ind
+           ,double *ATGA,double *BETA,double *ci2,int_4 deb)
+{
+int_4 i, j, k;
+double deriv[NPAR_FITFUN], t, f, e, Gkk, Ck, funfit;
+
+for (i=0; i<npar;i++) { BETA[i] = 0.; for (j=0; j<npar;j++) *(ATGA+i*NPAR_FITFUN+j) = 0.;}
+*ci2 = 0.;
+*ndata = 0;
+
+/* calcul de  ( At * G * A ) */
+for (k=I1; k<=I2; k++) {
+  e = (type == FITFUN_FLOAT) ? *(err.fx + k) : *(err.dx + k);
+  if ( e > 0. ) {
+    (*ndata)++;
+    t = (type == FITFUN_FLOAT) ? *(temps.fx + k) : *(temps.dx + k);
+    f = (type == FITFUN_FLOAT) ? *(mag.fx   + k) : *(mag.dx + k);
+    funfit = FunFit(t,parcur,deriv);
+    Gkk = 1./e/e;
+    Ck = f - funfit;
+    *ci2 += Ck*Ck*Gkk;
+    for ( j=0; j<npar; j++ ) {
+      for ( i=j; i<npar; i++ ) *(ATGA+i*NPAR_FITFUN+j) += deriv[ind[i]] * Gkk * deriv[ind[j]];
+      BETA[j] += deriv[ind[j]] * Gkk * Ck;
+} } }
+
+for(j=1;j<npar;j++) for(i=0;i<j;i++) *(ATGA+i*NPAR_FITFUN+j) = *(ATGA+j*NPAR_FITFUN+i);
+
+if( deb >= 3 ) {
+  printf("matrice ( At * G * A )\n");
+  for ( i=0; i<npar; i++ ) {
+    for ( j=0; j<npar; j++ ) printf(" %15.8e",*(ATGA+i*NPAR_FITFUN+j));
+    printf("\n");
+  }
+  printf("BETA:");
+  for ( j=0; j<npar; j++ ) printf(" %15.8e",BETA[j]);
+  printf("\n");
+}
+
+}
+
+/*=========================================================================*/
+/*                                          Christophe 8/11/93 La Silla */
+/*
+++
+double GausPiv(double *A,int_4 nca,int_4 n,double *B,int_4 ncb,int_4 m,int_4 Inv)
+	Inversion de matrice par la methode du pivot de Gauss.
+--
+*/
+/*
+++
+| Inv=0: resolution d'un systeme A(n,n) * X(n,m) = B(n,m)  
+|        en entree matrices A,B de taille A[?>=n][nca>=n] et B[?>=n][ncb>=m]
+|        en sortie la matrice B contient le resultat X
+| Inv#0: inversion de la matrice A(n,n)
+|        en entree matrice A
+|        en sortie la matrice B contient le resultat 1/A 
+| GausPiv: retourne le determinant (0. si non-inversible!)
+--
+*/
+/*
+++
+|Remarque: 
+|-matrice A[?>=n][nca>=n],
+|       element Aij = "A'[i][j] de ss matrice A'[n][n]" = *(A+i*nca+j)
+|       ou 0<=i<n indice de ligne; ou 0<=j<n indice de colonne; 
+|-matrice B[?>=n][ncb>=m],
+|       element Bij = "B'[i][j] de ss matrice B'[n][m]" = *(B+i*ncb+j)
+|       ou 0<=i<n indice de ligne; ou 0<=j<m indice de colonne;
+|exemple 1: on veut resoudre le systeme A(4,4) * X = B(4,3)
+|           et on definit dans le prog appelant: double A[12][7],B[32][5]
+|           on appelle: GausPiv(&A[0][0],7,4,&B[0][0],5,3,0)
+|exemple 2: on veut resoudre le systeme A(4,4) * X = B(4)
+|           et on definit dans le prog appelant: double A[4][4],B[4]
+|           on appelle: GausPiv(A[0],4,4,B,1,1,0)
+|exemple 3: on veut resoudre le systeme A(4,4) * X = B(4)
+|           et on definit dans le prog appelant: double A[9][4],B[7,3]
+|           on appelle: GausPiv(A[0],4,4,B,3,1,0)
+|Methode: methode de gauss avec choix du pivot maximum
+|Reference: Statistical and Computational Methods in Data Analysis
+|           Siegmund Brandt, North-Holland 1970  p 350-361.
+|Attention: la matrice A est detruite et la matrice B aussi (evidemment)
+--
+*/
+double GausPiv(double *A,int_4 nca,int_4 n,double *B,int_4 ncb,int_4 m,int_4 Inv)
+{
+int_4 deb=DEB_GausPiv;
+int_4 i,j,k,l,i1,i2,j1,j2,j3,j4,ij,ii,il,lj,kj,k1,nj,kk,ik,nn,kmax,i1max;
+double amax,save,det;
+
+if ( n < 1 ) {
+  printf("GausPiv: pas de resolution de systeme de dimension %d\n",n);
+  return(0.);
+}
+
+/* ********************************************************** */
+/* cas d'une inversion de matrice: on met B = matrice identite*/
+/* ********************************************************** */
+if ( Inv != 0 ) {
+  if ( m != n ) {
+    printf("GausPiv: Vous voulez inverser une matrice non carree %d %d\n",n,m);
+    return(0.);
+  }
+  for (i=0;i<n;i++) {
+    for (j=0;j<n;j++) {
+      if ( i != j ) { *(B+i*ncb+j) = 0.; } else { *(B+i*ncb+j) = 1.;}
+} } }
+
+if ( deb>0 ) {
+  printf("** Matrices de depart\n");
+  printf("Matrice A %d %d:\n",nca,n);
+  for (i=0;i<n;i++) {
+    for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
+    printf("\n");
+  }
+  printf("Matrice B %d %d:\n",ncb,m);
+  for (i=0;i<n;i++) {
+    for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
+    printf("\n");
+} }
+
+/* ***************************************************************** */
+/*    reduction de la matrice A a la forme triangulaire superieure   */
+/* ***************************************************************** */
+det=1.;
+kmax = n-1;
+for (k=0;k<kmax;k++) {         /* on travaille sur la ligne k */
+  if ( deb>0 ) printf("-----> reduction ligne %d\n",k);
+  amax=0.;    /*recherche du plus grand coeff pour le pivot*/
+  j2=k;       /* dans col k pour les lignes >= k */
+  for (j1=k;j1<n;j1++) {
+    ik = j1*nca+k;
+    if( fabs(amax)-fabs(*(A+ik)) < 0. ) {
+      amax = *(A+ik);
+      j2 = j1;
+  } }
+  if ( deb>0 ) printf("pivot sur la ligne %d max= %f\n",j2,amax);
+  if ( j2 != k ) {      /* echange des lignes k et j2 si necessaire*/
+    for (j=k;j<n;j++) {
+      j3=k*nca+j;
+      j4=j2*nca+j;
+      save = *(A+j3);
+      *(A+j3) = *(A+j4);
+      *(A+j4) = save;
+    }
+    for (j=0;j<m;j++) {
+      j3=k*ncb+j;
+      j4=j2*ncb+j;
+      save = *(B+j3);
+      *(B+j3) = *(B+j4);
+      *(B+j4) = save;
+    }
+    if ( deb>0 ) {
+      printf("Matrice A echange des lignes %d et %d :\n",k,j2);
+      for (i=0;i<n;i++) {
+        for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
+        printf("\n");
+      }
+      printf("Matrice B echange des lignes %d et %d :\n",k,j2);
+      for (i=0;i<n;i++) {
+        for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
+        printf("\n");
+  } } }
+  k1=k+1;  /* on effectue la substitution-soustraction sur les lignes qui suivent*/
+  kk = k*nca+k;      /* c'est le pivot*/
+  if ( deb>0 ) printf("valeur du pivot %f\n",*(A+kk));
+  if ( *(A+kk) == 0. ) {
+    /* printf("Matrice non-inversible: pivot %d nul\n",k); */
+    return(0.);
+  } else { det *= *(A+kk); }
+  for (i=k1;i<n;i++) {
+    ik = i*nca+k;  /* c est le premier element de la ligne i */
+    for (j=k1;j<n;j++) {
+      ij= i*nca+j;
+      kj= k*nca+j;
+      *(A+ij) += -*(A+kj) * *(A+ik) / *(A+kk);
+    }
+    for (j=0;j<m;j++) {
+      ij= i*ncb+j;
+      kj= k*ncb+j;
+      *(B+ij) += -*(B+kj) * *(A+ik) / *(A+kk);
+  } }
+  if ( deb>0 ) {
+    printf("Matrice A:\n");
+    for (i=0;i<n;i++) {
+      for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
+      printf("\n");
+    }
+    printf("Matrice B:\n");
+    for (i=0;i<n;i++) {
+      for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
+      printf("\n");
+} } }     /* fin du travail sur la ligne k */
+det *= *(A+(n-1)*nca+(n-1));
+if ( deb>0 ) printf("Determinant de A= %e\n",det);
+
+/* ********************************************************** */
+/*       back substitution                                    */
+/* ********************************************************** */
+nn=(n-1)*nca+(n-1);     /* l'element (n,n) */
+for (j=0;j<m;j++) {
+  nj=(n-1)*ncb+j;
+  if ( *(A+nn) == 0. ) {
+    /* printf("Matrice non-inversible pivot (%d,%d) nul\n",n-1,n-1); */
+    return(0.);
+  }
+  *(B+nj) /= *(A+nn);   /* la derniere ligne traitee a part*/
+  i1max=n-1;
+  if( i1max >= 0 ) {    /* les lignes n-1 a 1 dans cet ordre*/
+    for(i1=1;i1<=i1max;i1++) {
+      i=n-1-i1;         /* ici i va de n-2 a 0 */
+      ij=i*ncb+j;
+      ii=i*nca+i;
+      i2=i+1;           /* pour la ligne i on somme de i+1 a n */
+      for (l=i2;l<n;l++) {
+        il=i*nca+l;
+        lj=l*ncb+j;
+        *(B+ij) -= *(A+il) * *(B+lj);
+      }
+      if ( *(A+ii) == 0. ) {
+        /* printf("Matrice non-inversible pivot (%d,%d) nul\n",i,i); */
+        return(0.);
+      }
+      *(B+ij) /= *(A+ii);
+} } }
+if ( deb>0 ) {
+  printf("-----> Matrice B resultat:\n");
+  for (i=0;i<n;i++) {
+    for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
+    printf("\n");
+} }
+return(det);
+}
+
+/*=========================================================================*/
+/*                                       CMV 17/11/92  */
+/*
+++
+int_4 paramga -
+  (float sxin, float syin, float rhoin -
+  , float *smax, float *axisrat, float *tiltdeg)
+
+	Pour transformer le sx,sy,rho d'une gaussienne en sa,sc/sa,teta.
+--
+*/
+/*
+++
+| - input : sx ]0,inf] ,sy ]0,inf] ,rho ]-1,+1[
+| - output : smax (longeur du grand axe), axisrat (rapport des axes ]0.,1.])
+|     tiltdeg (angle entre le grand axe et l'axe ox en degre ]-90,+90])
+| - Les fonctions sont:
+| exp[-0.5*{[(x/SX)**2-2*RHO/(SX*SY)*x*y+(y/SY)**2]/(1-RHO**2)}]
+| exp[-0.5*{ (A/SA)**2                  +(C/SC)**2            }]
+| - Remarque: sx,sy representent les sigmas des variables x,y et
+| sont differents des sigmas des coupes x=0 et y=0 qui valent:
+|    sigmaX(y=0) = sx*sqrt(1-ro^2) different de sx
+|    sigmaY(x=0) = sy*sqrt(1-ro^2) different de sy
+--
+*/
+int_4 paramga(float sxin, float syin, float rhoin
+             , float *smax, float *axisrat, float *tiltdeg)
+/*
+Cf Formulae and Methods in Experimental Data Evaluation Vol. 1
+rechercher a Bivariate gaussian distribution
+*/
+{
+double sx,sy,rho,a,b,c,alpha,coscar,sincar,cossin,sa,sc;
+
+*smax = 0.; *axisrat = 0.; *tiltdeg = 0.; a = 0.; b = 0.; c = 0.;
+
+/* lecture des arguments */
+sx = sxin;  sy = syin;  rho = rhoin;
+
+/* cas des coniques degenerees ou erreurs dans les parametres*/
+if ( sx <= 0. || sy <= 0. || rho > 1. || rho < -1. ) return(-1);
+
+/* sortie fit : [(x/SX)**2 - 2*RHO/(SX*SY)*x*y + (y/SY)**2]/(1-RHO**2) = 1
+   equation ellipse: A*x**2 + 2*B*x*y + C*y**2  = 1       */
+sa = (1.-rho*rho);
+a = 1./sx/sx/sa;  b = -rho/sx/sy/sa;  c = 1./sy/sy/sa;
+
+/* cas des coniques degenerees (droites limites) */
+if ( rho == 1. || rho == -1. ) return(-2);
+
+/* axes principaux OX OY pour : x = cos(ALPHA)*X - sin(APLHA)*Y
+        (ALPHA = (ox,oX))       y = sin(ALPHA)*X + cos(APLHA)*Y
+  soit   ( A*cos**2 + C*sin**2 + 2*B*cos*sin )*X**2
+     +   ( A*sin**2 + C*cos**2 - 2*B*cos*sin )*Y**2
+     + 2*( -A*cos*sin + C*cos*sin + B*(cos**2-sin**2) )*X*Y
+                   = (X/SA)**2 + (Y/SC)**2 = 1
+  et oX oY axes principaux pour : Tan ( 2*ALPHA ) = 2*B/(A-C) */
+
+if ( a == c && rho == 0. ) {
+  /*  cas d'un cercle */
+  coscar = 0.5;    sincar = coscar;    cossin = coscar;    alpha = 0.;
+} else {
+  if ( a == c ) {
+    /* cas SX=SY ellipse a +/-45 degres */
+    if ( rho > 0. ) {
+      /* cas +45 degres */
+      alpha = Pi / 4.;
+    } else {
+      /* cas -45 degres */
+      alpha = -Pi / 4.;
+    }
+  } else {
+    /* cas general */
+    alpha = atan(2.*b/(a-c)) /2.;
+  }
+  coscar = cos(alpha);
+  sincar = sin(alpha);
+  cossin = coscar*sincar;
+  coscar *= coscar;
+  sincar *= sincar;
+  alpha *= 180./Pi;
+}
+
+sa = a*coscar+c*sincar+2.*b*cossin;
+sc = c*coscar+a*sincar-2.*b*cossin;
+sa = ( sa < 0. ) ? 1./sqrt(-sa) : 1./sqrt(sa);
+sc = ( sc < 0. ) ? 1./sqrt(-sc) : 1./sqrt(sc);
+
+if ( sa >= sc ) {
+  *smax = sa;
+  *axisrat = sc/sa;
+  *tiltdeg = alpha;
+} else {
+  *smax = sc;
+  *axisrat = sa/sc;
+  *tiltdeg = alpha+90.;
+  if ( *tiltdeg > 90. ) *tiltdeg = *tiltdeg-180.;
+}
+
+return(0);
+}
+
+/*========================================================================*/
+/*                               CMV 21/01/94 */
+/*
+++
+int_4 gaparam -
+  (float smax, float axisrat, float tiltdeg -
+  , float *sxin, float *syin, float *rhoin)
+
+	Pour transformer le sa,sc/sa,tiltdeg d'une gaussienne en sx,sy,rho
+	Pour calculer les parametres d'une gaussienne
+--
+*/
+/*
+++
+| - input : sa ]0,inf] ,axisrat ]0,1] ,tiltdeg ]-90,+90]
+|         sa (longeur du grand axe), axisrat (rapport des axes )
+|         tiltdeg (angle entre le grand axe et l'axe ox en degre)
+| - output : sx ]0,inf] , sy ]0,inf] , rho ]-1,1[
+| - Les fonctions sont:
+| exp[-0.5*{ (A/SA)**2                  +(C/SC)**2            }]
+| exp[-0.5*{[(x/SX)**2-2*RHO/(SX*SY)*x*y+(y/SY)**2]/(1-RHO**2)}]
+| - Voir aussi la remarque de la fonction paramga.
+--
+*/
+int_4 gaparam(float smax, float axisrat, float tiltdeg
+             , float *sxin, float *syin, float *rhoin)
+{
+double sx,sy,rho,alpha,coscar,sincar,cossin,sa,sc,a,b,c;
+
+*sxin = 0.; *syin = 0.; *rhoin = 0.;
+
+/* cas des coniques degenerees ou erreurs dans les parametres*/
+if ( smax <= 0. || axisrat <= 0. || axisrat > 1. ) return(-1);
+
+/* lecture des arguments */
+sa = smax;  sc = sa*axisrat;  alpha = tiltdeg*Pi/180.;
+
+coscar = cos(alpha);
+sincar = sin(alpha);
+cossin = coscar*sincar;
+coscar *= coscar;
+sincar *= sincar;
+
+a = 1./(coscar/sa/sa + sincar/sc/sc);
+  a = sqrt(a);         /* = sqrt(1-ro**2)*sx */
+b = 1./(sincar/sa/sa + coscar/sc/sc);
+  b = sqrt(b);         /* = sqrt(1-ro**2)*sy */
+c = cossin*(-1./sa/sa + 1./sc/sc);
+rho = c*a*b;
+sx = a / sqrt(1.-rho*rho);
+sy = b / sqrt(1.-rho*rho);
+
+*sxin = sx; *syin = sy; *rhoin = rho;
+
+return(0);
+}
+
+/*===================================================================*/
+/*
+++
+double nberfc(double x)
+	Erreur fonction complementaire: -log10(erfc)
+	Pratiquement pour avoir la proba que
+	]-inf,-x] U [x,+inf[ selon une loi gaussiene centree et normee
+	il faut appeler nberfc(x/sqrt(2))
+	Le job tiens compte de la saturation machine pour x grand.
+	La valeur est approximee au developpement limite de erfc
+	( see . Abramowitz p299 7.1.23 )
+--
+*/
+double nberfc(double x)
+{
+double v;
+if(x<0.) return(0.);
+if ( x < 10. ) {
+  v = erfc(x);
+  v = -log10(v);
+} else {
+  v = 2.*x*x;
+  v = 1./v - 3./(v*v) + 15./(v*v*v);
+  v += LnPi/2. + log(x) + x*x;
+  v /= Ln10;
+}
+return(v);
+}
+
+/*=========================================================================*/
+/*
+++
+float probnb(float sci2,int_4 inddl,int_4 *ipass)
+	Retourne -log10(p) ou p est la probabilte que le chi2
+	d'une fluctuation inddl points soit superieur a sci2.
+	ipass est le type de calcul utilise.
+--
+*/
+float probnb(float sci2,int_4 inddl,int_4 *ipass)
+{
+int_4 it;
+float nddl;
+double ci2,a1,a2,p,q,val,terme1,terme2,terme3,terme4,teradd,xnprim;
+
+*ipass = 0;
+val = 0.;
+nddl = inddl;
+ci2 = sci2;
+a1 = nddl/2.;
+a2 = ci2/2.;
+
+q = nbgammq(a1,a2);
+if(q>0. && q<1.) {
+  val = -log10(q);   /* moins le log10 de la proba que le chi2 soit > ci2 */
+  *ipass = 1;
+} else if ( q==1.) {
+  p = nbgammp(a1,a2);
+  val = p/Ln10;      /* -log10(q) = -log(1-p)/Ln10 = -(p)/Ln10 = p/Ln10 */
+  *ipass = 2;
+} else {
+  /* approximation de mimile */
+  xnprim = nddl / 2. - 1.;
+  terme1 = nddl / 2. * Log2;        /* 1/2**n */
+  terme2 = Hln2pi + (xnprim+0.5)*log(xnprim) - xnprim + 1./(12.*xnprim);
+  terme2 /= Ln10;         /* formule de stirling pour Gamma[nddl/2] */
+  terme3 = ci2/2. - xnprim*log(ci2);
+  terme3 /= Ln10;         /* exp(-ci2/2)*ci2**(n/2-1) */
+  terme4 = teradd = 1.;
+  for ( it=1; it <= inddl-2; it +=2) {
+    teradd *= ( (double) (nddl -1.) - (double) it ) / ci2;
+    terme4 += teradd;
+    if ( teradd < 1.e-4 ) break;
+  }
+  terme4 = -log10(2.*terme4);
+  val = terme1 + terme2 + terme3 + terme4;
+  *ipass = 3;
+}
+return ((float) val);
+}
+
+/*=========================================================================*/
+/*
+++
+double nbgammln(double xx)
+	Fonction log de la fonction Gamma
+--
+*/
+double nbgammln(double xx)
+{
+   double x,tmp,ser;
+   static double cof[6]={76.18009173,-86.50532033,24.01409822,
+      -1.231739516,0.120858003e-2,-0.536382e-5};
+   int_4 j;
+
+   x=xx-1.0;
+   tmp=x+5.5;
+   tmp -= (x+0.5)*log(tmp);
+   ser=1.0;
+   for (j=0;j<=5;j++) {
+      x += 1.0;
+      ser += cof[j]/x;
+   }
+   return -tmp+log(2.50662827465*ser);
+}
+
+/*=========================================================================*/
+/*
+++
+double nbgammq(double a,double x)
+	Fonction GammaQ
+--
+*/
+double nbgammq(double a,double x)
+{
+   double gamser,gammcf,gln;
+
+   if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMQ (%f,%f)\n"
+                                    ,a,x); exit(-1);}
+   if (x < (a+1.0)) {
+      nbgser(&gamser,a,x,&gln);
+      return 1.0-gamser;
+   } else {
+      nbgcf(&gammcf,a,x,&gln);
+      return gammcf;
+   }
+}
+
+/*=========================================================================*/
+/*
+++
+double nbgammp(double a,double x)
+	Fonction GammaP
+--
+*/
+double nbgammp(double a,double x)
+{
+   double gamser,gammcf,gln;
+
+   if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMP (%f,%f)\n"
+                                    ,a,x); exit(-1);}
+   if (x < (a+1.0)) {
+      nbgser(&gamser,a,x,&gln);
+      return gamser;
+   } else {
+      nbgcf(&gammcf,a,x,&gln);
+      return 1.0-gammcf;
+   }
+}
+
+/*=========================================================================*/
+void nbgcf(double *gammcf,double a,double x,double *gln)
+{
+   int_4 n;
+   double gold=0.0,g,fac=1.0,b1=1.0;
+   double b0=0.0,anf,ana,an,a1,a0=1.0;
+
+   *gln=nbgammln(a);
+   a1=x;
+   for (n=1;n<=ITMAX;n++) {
+      an=(double) n;
+      ana=an-a;
+      a0=(a1+a0*ana)*fac;
+      b0=(b1+b0*ana)*fac;
+      anf=an*fac;
+      a1=x*a0+anf*a1;
+      b1=x*b0+anf*b1;
+      if (a1) {
+         fac=1.0/a1;
+         g=b1*fac;
+         if (fabs((g-gold)/g) < EPS) {
+            *gammcf=exp(-x+a*log(x)-(*gln))*g;
+            return;
+         }
+         gold=g;
+      }
+   }
+   printf("a too large, ITMAX too small in routine NBGCF (%f,%f)\n",a,x); exit(-1);
+}
+
+/*=========================================================================*/
+void nbgser(double *gamser,double a,double x,double *gln)
+{
+   int_4 n;
+   double sum,del,ap;
+
+   *gln=nbgammln(a);
+   if (x <= 0.0) {
+      if (x < 0.0) { printf("x less than 0 in routine NBGSER (%f,%f)\n",a,x); exit(-1); }
+      *gamser=0.0;
+      return;
+   } else {
+      ap=a;
+      del=sum=1.0/a;
+      for (n=1;n<=ITMAX;n++) {
+         ap += 1.0;
+         del *= x/ap;
+         sum += del;
+         if (fabs(del) < fabs(sum)*EPS) {
+            *gamser=sum*exp(-x+a*log(x)-(*gln));
+            return;
+         }
+      }
+      printf("a too large, ITMAX too small in routine NBGSER (%f,%f)\n",a,x); exit(-1);
+      return;
+   }
+}
+
+/*==========================================================================*/
+/*
+++
+void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW)
+	Set mIhoqN,IhoqNX,IhoqNW pour integration Gauss-Legendre
+--
+*/
+void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW)
+{
+switch (degre) {
+  case  2:
+         *mIhoqN = mIhoq2;
+          IhoqNX = Ihoq2X;
+          IhoqNW = Ihoq2W;
+          break;
+  case  3:
+         *mIhoqN = mIhoq3;
+          IhoqNX = Ihoq3X;
+          IhoqNW = Ihoq3W;
+          break;
+  case  4:
+         *mIhoqN = mIhoq4;
+          IhoqNX = Ihoq4X;
+          IhoqNW = Ihoq4W;
+          break;
+  case  5:
+         *mIhoqN = mIhoq5;
+          IhoqNX = Ihoq5X;
+          IhoqNW = Ihoq5W;
+          break;
+  case  6:
+         *mIhoqN = mIhoq6;
+          IhoqNX = Ihoq6X;
+          IhoqNW = Ihoq6W;
+          break;
+  case  7:
+         *mIhoqN = mIhoq7;
+          IhoqNX = Ihoq7X;
+          IhoqNW = Ihoq7W;
+          break;
+  case  8:
+         *mIhoqN = mIhoq8;
+          IhoqNX = Ihoq8X;
+          IhoqNW = Ihoq8W;
+          break;
+  case  9:
+         *mIhoqN = mIhoq9;
+          IhoqNX = Ihoq9X;
+          IhoqNW = Ihoq9W;
+          break;
+  case 10:
+         *mIhoqN = mIhoq10;
+          IhoqNX = Ihoq10X;
+          IhoqNW = Ihoq10W;
+          break;
+  case 16:
+         *mIhoqN = mIhoq16;
+          IhoqNX = Ihoq16X;
+          IhoqNW = Ihoq16W;
+          break;
+  default:
+         *mIhoqN = mIhoq8;
+          IhoqNX = Ihoq8X;
+          IhoqNW = Ihoq8W;
+          break;
+}
+return;
+}
+
+/*==========================================================================*/
+/*
+++
+int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw)
+	Ecrit les positions et les poids pour l'integration de Gauss-Legendre
+	dans les tableaux *ihoqnx,*ihoqnw.
+	Retourne le nombre de points.
+	Si *ihoqnx==NULL ou *ihoqnw==NULL
+	retourne seulement le nombre de points (cad la taille minimale
+        que doivent les tableaux *ihoqnx,*ihoqnw).
+--
+*/
+int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw)
+{
+int mIhoqN, i;
+double *IhoqNX, *IhoqNW;
+switch (degre) {
+  case  2:
+          mIhoqN = mIhoq2;
+          IhoqNX = Ihoq2X;
+          IhoqNW = Ihoq2W;
+          break;
+  case  3:
+          mIhoqN = mIhoq3;
+          IhoqNX = Ihoq3X;
+          IhoqNW = Ihoq3W;
+          break;
+  case  4:
+          mIhoqN = mIhoq4;
+          IhoqNX = Ihoq4X;
+          IhoqNW = Ihoq4W;
+          break;
+  case  5:
+          mIhoqN = mIhoq5;
+          IhoqNX = Ihoq5X;
+          IhoqNW = Ihoq5W;
+          break;
+  case  6:
+          mIhoqN = mIhoq6;
+          IhoqNX = Ihoq6X;
+          IhoqNW = Ihoq6W;
+          break;
+  case  7:
+          mIhoqN = mIhoq7;
+          IhoqNX = Ihoq7X;
+          IhoqNW = Ihoq7W;
+          break;
+  case  8:
+          mIhoqN = mIhoq8;
+          IhoqNX = Ihoq8X;
+          IhoqNW = Ihoq8W;
+          break;
+  case  9:
+          mIhoqN = mIhoq9;
+          IhoqNX = Ihoq9X;
+          IhoqNW = Ihoq9W;
+          break;
+  case 10:
+          mIhoqN = mIhoq10;
+          IhoqNX = Ihoq10X;
+          IhoqNW = Ihoq10W;
+          break;
+  case 16:
+          mIhoqN = mIhoq16;
+          IhoqNX = Ihoq16X;
+          IhoqNW = Ihoq16W;
+          break;
+  default:
+          mIhoqN = mIhoq8;
+          IhoqNX = Ihoq8X;
+          IhoqNW = Ihoq8W;
+          break;
+}
+if( ihoqnx!=NULL && ihoqnw!=NULL ) {
+  for(i=0;i<mIhoqN;i++) {
+    ihoqnx[i] = IhoqNX[i];
+    ihoqnw[i] = IhoqNW[i];
+  }
+}
+return(mIhoqN);
+}
+
+/*===================================================================*/
+#define EPS_gauleg 3.0e-11
+/*
+++
+void nbgauleg(double x1,double x2,double *x,double *w,int n)
+	Integration des fonctions a une dimension y=f(x)
+	par la Methode de Gauss-Legendre.
+	Calcul des coefficients du developpement
+--
+*/
+/*
+++
+| INPUT:
+|  x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5)
+|  n = degre du developpement
+| OUTPUT:
+|  x[] = valeur des abscisses ou l'on calcule (dim=n)
+|  w[] = valeur des coefficients associes
+| REMARQUES:
+|  - x et w doivent au moins etre dimensionner a n.
+|  - l'integration est rigoureuse si sur l'intervalle d'integration
+|    la fonction f(x) peut etre approximee par un polynome
+|    de degre 2*m (monome le + haut x**(2*n-1) )
+|  - Voir la fonction Integ_Fun pour un calcul d'ordre 8
+--
+*/
+void nbgauleg(double x1,double x2,double *x,double *w,int n)
+{
+   int m,j,i;
+   double z1,z,xm,xl,pp,p3,p2,p1;
+
+   m=(n+1)/2;
+   xm=0.5*(x2+x1);
+   xl=0.5*(x2-x1);
+   for (i=1;i<=m;i++)  {
+      z=cos(3.141592654*(i-0.25)/(n+0.5));
+      do {
+         p1=1.0;
+         p2=0.0;
+         for (j=1;j<=n;j++) {
+            p3=p2;
+            p2=p1;
+            p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
+         }
+         pp=n*(z*p1-p2)/(z*z-1.0);
+         z1=z;
+         z=z1-p1/pp;
+      } while (fabs(z-z1) > EPS_gauleg);
+      x[i-1]=xm-xl*z;
+      x[n-i]=xm+xl*z;
+      w[i-1]=2.0*xl/((1.0-z*z)*pp*pp);
+      w[n-i]=w[i-1];
+   }
+}
+#undef EPS_gauleg
+
+/*==========================================================================*/
+/*
+++
+double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
+	Pour integrer la fonction fonc de xmin a xmax sur npas.
+	On emploit une methode Higher-order-gaussienne d'ordre 8, ce qui
+	fait un calcul equivalent de N*npas pas.
+--
+*/
+double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
+{
+int i,j;
+double dlim,sum,xc,xci;
+
+if( xmax <= xmin ) return(0.);
+if( npas <= 0 ) npas=1;
+sum = 0.;
+dlim = (xmax-xmin)/npas;
+for(i=0;i<npas;i++) {
+  xci = (double) i + 0.5;
+  for(j=0;j<mIhoq8;j++) {
+    xc = xmin + ( xci + Ihoq8X[j] ) * dlim;
+    sum += fonc(xc) * Ihoq8W[j];
+} }
+return(sum*dlim);
+}
+
+/*=========================================================================*/
+/*
+++
+double Integ_Fun_2D -
+  (double (*fonc)(double x,double y) -
+  ,double xmin,double xmax,double ymin,double ymax -
+  ,int npasx,int npasy)
+
+	Integration 2D de fonc(x,y) dans le carre [xmin,xmax] et [ymin,ymax]
+--
+*/
+double Integ_Fun_2D(double (*fonc)(double x,double y)
+                ,double xmin,double xmax,double ymin,double ymax
+                ,int npasx,int npasy)
+{
+int i,j;
+double x,y,pasx,pasy,sum,sumy;
+
+pasx = (xmax-xmin)/npasx;
+pasy = (ymax-ymin)/npasy;
+
+sum = 0.;
+for(i=0;i<npasx;i++) {
+  x = xmin + ((double) i + 0.5 ) * pasx;
+  sumy = 0.;
+  for(j=0;j<npasy;j++) {
+    y = ymin + ((double) j + 0.5 ) * pasy;
+    sumy += fonc(x,y);
+  }
+  sum += sumy;
+}
+return( sum*pasx*pasy);
+}
+
+/*=========================================================================*/
+/*                                    Christophe 01/07/94 */
+/*
+++
+void Set_FitFunDPol(int DPol)
+	Pour donner l'ordre du polynome pour le fit.
+--
+*/
+void Set_FitFunDPol(int DPol) 
+{
+FITFUN_DPOL = DPol;
+}
+
+/*==================================================================*/
+/*                                             Christophe 01/07/94  */
+/*
+++
+double Gauss1DPolF(double x,double *Par,double *DgDpar) 
+	Fonction de fit Gausienne+polynome.
+--
+*/
+/*
+++
+|  f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ]
+|        +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
+|  FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
+--
+*/
+double Gauss1DPolF(double x,double *Par,double *DgDpar) 
+{
+double f,xc,xc2,e,xpow;
+int i;
+
+xc = (x-Par[1])/Par[2];
+xc2 = xc*xc;
+e = exp(-0.5*xc2);
+f = Par[0]*e;
+
+DgDpar[0] = e;
+DgDpar[1] = xc / Par[2] *f;
+DgDpar[2] = xc2/ Par[2] *f;
+
+if(FITFUN_DPOL>=0) {
+  xpow = 1.;
+  for(i=0;i<=FITFUN_DPOL;i++) {
+    DgDpar[3+i] = xpow;
+    f += Par[3+i]*xpow;
+    xpow *= x;
+  }
+}
+
+return (f);
+}
+
+/*==================================================================*/
+/*                                             Christophe 29/08/95  */
+/*
+++
+double GaussI1DPol(double x,double *Par,double *DgDpar) 
+	Fonction de fit Gausienne integree+polynome.
+--
+*/
+/*
+++
+|  f(x) = par[0] / (sqrt(2*Pi)*par[2]) * exp[-0.5*( (x-par[1]) / par[2] )**2 ]
+|        +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
+|  FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
+--
+*/
+double GaussI1DPol(double x,double *Par,double *DgDpar) 
+{
+double f,xc,xc2,e,xpow;
+int i;
+
+xc = (x-Par[1])/Par[2];
+xc2 = xc*xc;
+e = exp(-0.5*xc2)/(S2Pi*Par[2]);
+f = Par[0]*e;
+
+DgDpar[0] = e;
+DgDpar[1] = xc / Par[2] *f;
+DgDpar[2] = (xc2-1.)/ Par[2] *f;
+
+if(FITFUN_DPOL>=0) {
+  xpow = 1.;
+  for(i=0;i<=FITFUN_DPOL;i++) {
+    DgDpar[3+i] = xpow;
+    f += Par[3+i]*xpow;
+    xpow *= x;
+  }
+}
+
+return (f);
+}
+
+/*====================================================================*/
+/*                                             Christophe 01/07/94    */
+/*
+++
+double Polyn1D(double x,double *Par,double *DgDpar) 
+	Fonction de fit de polynome.
+--
+*/
+/*
+++
+|  f(x) = par[0] + par[1]*x + .... + par[FITFUN_DPOL]*x**FITFUN_DPOL
+|  FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
+--
+*/
+double Polyn1D(double x,double *Par,double *DgDpar) 
+{
+double f,xpow;
+int i,DPol;
+
+DPol = (FITFUN_DPOL<0) ? 0 : FITFUN_DPOL ;
+xpow = 1.;
+f = 0.;
+for(i=0;i<=DPol;i++)
+  {
+  DgDpar[i] = xpow;
+  f += Par[i]*xpow;
+  xpow *= x;
+  }
+return (f);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitProp(double *x,double *y,double *ey,int *n,double *a1)
+	Fit d'une proportion a1: y = a1 * x
+--
+*/
+/*
+++
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a1 coefficient
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si pas assez de points
+|    -2. si determinant negatif
+--
+*/
+double FitProp(double *x,double *y,double *ey,int *n,double *a1)
+{
+register int i,np;
+register double X2,XY,Y2,w;
+
+np=0;
+X2=XY=Y2=*a1=0.;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  np++;
+  w = ey[i]*ey[i];
+  X2 += x[i]*x[i]/w;
+  XY += x[i]*y[i]/w;
+  Y2 += y[i]*y[i]/w;
+}
+*n = np;
+if(np<1) return(-1.);
+if(X2==0.) return(-2.);
+*a1 = XY/X2;
+w = Y2 + *a1**a1*X2 -2.**a1*XY;
+return(w);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
+	Fit d'une droite: y=a0+a1*x
+--
+*/
+/*
+++
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a0,a1 coefficients de la droite
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si pas assez de points
+|    -2. si determinant negatif
+--
+*/
+double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
+{
+register int i,np;
+register double I,X,X2,Y,XY,Y2,w;
+
+np=0;
+Y2=I=X=X2=Y=XY=*a0=*a1=0.;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  np++;
+  w = ey[i]*ey[i];
+  I  += 1./w;
+  X  += x[i]/w;
+  X2 += x[i]*x[i]/w;
+  Y  += y[i]/w;
+  Y2 += y[i]*y[i]/w;
+  XY += x[i]*y[i]/w;
+}
+*n = np;
+if(np<2) return(-1.);
+w = X*X-X2*I;
+if(w==0.) return(-2.);
+*a1 = (Y*X-XY*I)/w;
+*a0 = (X*XY-X2*Y)/w;
+w = Y2 + *a0**a0*I + *a1**a1*X2
+    + 2.*( - Y**a0  - *a1*XY + *a0**a1*X );
+return(w);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
+	Fit d'une parabole: y=a0+a1.x+a2.x^2
+--
+*/
+/*
+++
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a0,a1 coefficients de la droite
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si pas assez de points
+|    -2. si determinant negatif
+--
+*/
+double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
+{
+register int i,np;
+register double I,X,X2,X3,X4,Y,Y2,XY,X2Y,w,x2;
+
+np=0;
+I=X=X2=X3=X4=Y=Y2=XY=X2Y=*a0=*a1=*a2=0.;
+
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  np++;
+  x2 = x[i]*x[i];
+  w = ey[i]*ey[i];
+  I   += 1./w;
+  X   += x[i]/w;
+  X2  += x2/w;
+  X3  += x2*x[i]/w;
+  X4  += x2*x2/w;
+  Y   += y[i]/w;
+  Y2  += y[i]*y[i]/w;
+  XY  += x[i]*y[i]/w;
+  X2Y += x2*y[i]/w;
+}
+*n = np;
+if(np<3) return(-1.);
+w = X2*(X2*X2-X3*X) -X*(X3*X2-X4*X) +I*(X3*X3-X4*X2);
+if(w==0.) return(-2.);
+*a2 =  (Y*(X2*X2-X3*X)  -XY*(X*X2-X3*I)  +X2Y*(X*X-X2*I)  )/w;
+*a1 = -(Y*(X3*X2-X4*X)  -XY*(X2*X2-X4*I) +X2Y*(X2*X-X3*I) )/w;
+*a0 =  (Y*(X3*X3-X4*X2) -XY*(X2*X3-X4*X) +X2Y*(X2*X2-X3*X))/w;
+w = Y2 + *a0**a0*I + *a1**a1*X2 + *a2**a2*X4
+    +2.*( -Y**a0  -*a1*XY -*a2*X2Y
+          +*a0**a1*X +*a0**a2*X2+*a1**a2*X3 );
+return(w);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitParLin -
+  (double *xx,double *y,double *ey,int *n,double x0,int Deg_d -
+  ,double *a0,double *a1,double *b1,double *b2)
+
+--
+*/
+/*
+++
+| Fit d'une parabole: y=a0+b1*(x-x0)+b2*(x-x0)**2
+|                                     pour x>x0
+|    et d'une droite: y=a0+a1*(x-x0)  pour x<=x0
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+|    x0 = abscisse du point pivot (il n'est pas fitte)
+|    Deg_d = degre du fit a droite de x0 (1 ou 2)
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a0,a1 coefficients de la droite
+|    a0,b1,b2 coefficients de la parabole
+--
+*/
+/*
+++
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si pas assez de points
+|    -2. si determinant negatif
+| Remarque:
+|    Il faut evidemment au moins 2 points a gauche du pivot x0
+|                       et 3 points a droite du pivot x0
+| Matrices A * a = B :
+|        |   I_   X_g   X_d X2_d |   | a0 |   |    Y_ |
+|        |  X_g  X2_g     0    0 | * | a1 | = |  XY_g |
+|        |  X_d     0  X2_d X3_d |   | b1 |   |  XY_d |
+|        | X2_d     0  X3_d X4_d |   | b2 |   | X2Y_d |
+--
+*/
+double FitParLin(double *xx,double *y,double *ey,int *n,double x0,int Deg_d
+                ,double *a0,double *a1,double *b1,double *b2)
+{
+int i,np,npg,npd,nddl;
+double w,x,x2,A[4][4],B[4];
+double Y2,I,Y,X_g,X2_g,XY_g,X_d,X2_d,X3_d,X4_d,XY_d,X2Y_d;
+
+if( Deg_d<1 || Deg_d>2 ) Deg_d=2;
+nddl = Deg_d + 2;
+*a0=*a1=*b1=*b2=0.;
+Y2=I=Y=X_g=X2_g=XY_g=X_d=X2_d=X3_d=X4_d=XY_d=X2Y_d=0.;
+np=npg=npd=0;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  np++;
+  x = xx[i]-x0;
+  x2 = x*x;
+  w = ey[i]*ey[i];
+  I  += 1./w;
+  Y  += y[i]/w;
+  Y2 += y[i]*y[i]/w;
+  if(x<=0.) {
+    if(x<0.) npg++;
+    X_g  += x/w;
+    X2_g += x2/w;
+    XY_g += x*y[i]/w;;
+  } else {
+    npd++;
+    X_d   += x/w;
+    X2_d  += x2/w;
+    X3_d  += x2*x/w;
+    X4_d  += x2*x2/w;
+    XY_d  += x*y[i]/w;;
+    X2Y_d += x2*y[i]/w;;
+  }
+}
+*n = np;
+A[0][0] = I;
+A[1][1] = X2_g;
+A[3][3] = X4_d;
+A[0][1] = A[1][0] = X_g;
+A[0][2] = A[2][0] = X_d;
+A[3][2] = A[2][3] = X3_d;
+A[0][3] = A[3][0] = A[2][2] = X2_d;
+A[1][2] = A[2][1] = A[1][3] = A[3][1] = 0.;
+B[0] = Y;
+B[1] = XY_g;
+B[2] = XY_d;
+B[3] = X2Y_d;
+if( np<4 || npg < 1 || npd < 2 ) return(-1.);
+w = GausPiv(&A[0][0],4,nddl,B,1,1,0);
+if(w==0.) return(-2.);
+*a0 = B[0];
+*a1 = B[1];
+*b1 = B[2];
+if(nddl==4) *b2 = B[3];
+w = Y2 + *a0**a0*I + *a1**a1*X2_g + *b1**b1*X2_d + *b2**b2*X4_d
+  + 2.*( - *a0*Y - *a1*XY_g + *a0**a1*X_g
+         - *b1*XY_d - *b2*X2Y_d + *a0**b1*X_d + *a0**b2*X2_d + *b1**b2*X3_d
+       );
+return(w);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
+	Fit de y(i) = a1*x(i) en deux passes:
+--
+*/
+/*
+++
+|   1-/ fit avec tous les points
+|   2-/ fit ou on enleve les per_clean*n points les plus eloignes
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+|    per_clean = pourcentage des points a tuer pour la seconde passe
+--
+*/
+/*
+++
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a1 = coefficients de proportionalite
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si echec fit passe no 1
+|    -2. si echec fit passe no 2
+|    -3. si probleme malloc
+|    -4. si probleme nombre de points a tuer
+--
+*/
+double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
+{
+int npt,k,i,nclass;
+double *clas,aa1,c2,cut;
+
+*a1 =0.;
+
+/* 1ere passe */
+npt = *n;
+c2 = FitProp(x,y,ey,&npt,&aa1);
+if(c2<0.) {*n = npt; return(-1.);}
+*a1 = aa1;
+/* printf("pass 1: %g*x c2=%g/%d\n",*a1,c2,npt); */
+
+clas = (double*) malloc( *n * sizeof(double) );
+if( clas == NULL ) {*n=npt; return(-3.);}
+
+/* elimination des mauvais points */
+nclass = 0;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  c2 = (y[i]-aa1*x[i])/ey[i];
+  clas[nclass] = c2*c2;
+  nclass++;
+}
+qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
+k = (int) ( (1. - per_clean ) * (double) nclass );
+if(k<0) k=0;
+if(k>=nclass) k = nclass-1;
+cut = clas[k];
+k = 0;
+for(i=0;i<*n;i++) {
+  clas[i] = ey[i];
+  c2 = (y[i]-aa1*x[i])/ey[i];
+  c2 *= c2;
+  if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
+}
+/* printf("nombre pt tues %d cut=%g\n",k,cut); */
+
+/* 2sd passe */
+npt = *n;
+c2 = FitProp(x,y,clas,&npt,&aa1);
+if(c2<0.) {*n = npt; free(clas); return(-2.);}
+*a1 = aa1;
+*n = npt;
+/* printf("pass 2: %g*x c2=%g/%d\n",*a1,c2,npt); */
+
+free(clas);
+return(c2);
+}
+
+/*=========================================================================*/
+/*
+++
+double FitLinClean -
+  (double *x,double *y,double *ey,int *n -
+  ,double per_clean,double *a0,double *a1)
+
+	Fit de y(i) = a0 + a1*x(i) en deux passes:
+--
+*/
+/*
+++
+|   1-/ fit avec tous les points
+|   2-/ fit ou on enleve les per_clean*n points les plus eloignes
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+|    per_clean = pourcentage des points a tuer pour la seconde passe
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a0,a1 = coefficients de la droite
+--
+*/
+/*
+++
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si echec fit passe no 1
+|    -2. si echec fit passe no 2
+|    -3. si probleme malloc
+|    -4. si probleme nombre de points a tuer
+--
+*/
+double FitLinClean(double *x,double *y,double *ey,int *n
+                  ,double per_clean,double *a0,double *a1)
+{
+int npt,k,i,nclass;
+double *clas,aa0,aa1,c2,cut;
+
+*a0 = *a1 =0.;
+
+/* 1ere passe */
+npt = *n;
+c2 = FitLin(x,y,ey,&npt,&aa0,&aa1);
+if(c2<0.) {*n = npt; return(-1.);}
+*a0 = aa0;
+*a1 = aa1;
+/* printf("pass 1: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
+
+clas = (double*) malloc( *n * sizeof(double) );
+if( clas == NULL ) {*n=npt; return(-3.);}
+
+/* elimination des mauvais points */
+nclass = 0;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
+  clas[nclass] = c2*c2;
+  nclass++;
+}
+qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
+k = (int) ( (1. - per_clean ) * (double) nclass );
+if(k<0) k=0;
+if(k>=nclass) k = nclass-1;
+cut = clas[k];
+k = 0;
+for(i=0;i<*n;i++) {
+  clas[i] = ey[i];
+  c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
+  c2 *= c2;
+  if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
+}
+/* printf("nombre pt tues %d cut=%g\n",k,cut); */
+
+/* 2sd passe */
+npt = *n;
+c2 = FitLin(x,y,clas,&npt,&aa0,&aa1);
+if(c2<0.) {*n = npt; free(clas); return(-2.);}
+*a0 = aa0;
+*a1 = aa1;
+*n = npt;
+/* printf("pass 2: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
+
+free(clas);
+return(c2);
+}
+
+/*===================================================================*/
+/*
+++
+double FitParClean -
+  (double *x,double *y,double *ey,int *n -
+  ,double per_clean,double *a0,double *a1,double *a2)
+
+	Fit de y(i) = a0 + a1*x(i) + a2*x(i)^2 en deux passes:
+--
+*/
+/*
+++
+|   1-/ fit avec tous les points
+|   2-/ fit ou on enleve les per_clean*n points les plus eloignes
+| Input:
+|    x = tableau des abscisses
+|    y = tableau des ordonnees
+|    ey = erreurs sur les y
+|    n = nombre de donnees en entree
+|    per_clean = pourcentage des points a tuer pour la seconde passe
+| Output:
+|    n = nombre de points utilises (point non utilise si ey<=0)
+|    a0,a1,a2 = coefficients de la parabole
+| Return:
+|    valeur du xi2 si fit reussi,
+|    -1. si echec fit passe no 1
+|    -2. si echec fit passe no 2
+|    -3. si probleme malloc
+|    -4. si probleme nombre de points a tuer
+--
+*/
+double FitParClean(double *x,double *y,double *ey,int *n
+                  ,double per_clean,double *a0,double *a1,double *a2)
+{
+int npt,k,i,nclass;
+double *clas,aa0,aa1,aa2,c2,cut;
+
+*a0 = *a1 = *a2 =0.;
+
+/* 1ere passe */
+npt = *n;
+c2 = FitPar(x,y,ey,&npt,&aa0,&aa1,&aa2);
+if(c2<0.) {*n = npt; return(-1.);}
+*a0 = aa0;
+*a1 = aa1;
+*a2 = aa2;
+/* printf("pass 1: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
+
+clas = (double*) malloc( *n * sizeof(double) );
+if( clas == NULL ) {*n=npt; return(-3.);}
+
+/* elimination des mauvais points */
+nclass = 0;
+for(i=0;i<*n;i++) {
+  if(ey[i]<=0.) continue;
+  c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
+  clas[nclass] = c2*c2;
+  nclass++;
+}
+qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
+k = (int) ( (1. - per_clean ) * (double) nclass );
+if(k<0) k=0;
+if(k>=nclass) k = nclass-1;
+cut = clas[k];
+k = 0;
+for(i=0;i<*n;i++) {
+  clas[i] = ey[i];
+  c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
+  c2 *= c2;
+  if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
+}
+/* printf("nombre pt tues %d cut=%g\n",k,cut); */
+
+/* 2sd passe */
+npt = *n;
+c2 = FitPar(x,y,clas,&npt,&aa0,&aa1,&aa2);
+if(c2<0.) {*n = npt; free(clas); return(-2.);}
+*a0 = aa0;
+*a1 = aa1;
+*a2 = aa2;
+*n = npt;
+/* printf("pass 2: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
+
+free(clas);
+return(c2);
+}
+
+/*===========================================================*/
+/*
+++
+float interpole(float m,int n,float *t1,float *t2)
+	Interpolation lineaire y=f(x):
+--
+*/
+/*
+++
+|   t1[n] = tableau des x
+|   t2[n] = tableau des y
+|   m = valeur ou on interpole
+|   RETURN: f(m)
+--
+*/
+float interpole(float m,int n,float *t1,float *t2)
+{
+int i,n1;
+float r;
+
+if ( n == 1 ) return ( t2[0] );
+
+n1=n-1;
+if ( m < t1[0] )  m=t1[0];
+if ( m > t1[n1] ) m=t1[n1];
+
+for(i=0;i<n;i++) if ( m <= t1[i] ) break;
+i = (i==0) ? 1  : i;
+i = (i==n) ? n1 : i;
+
+r = t2[i-1] + (t2[i]-t2[i-1]) / (t1[i]-t1[i-1]) * (m-t1[i-1]);
+
+/*
+printf("interpole: i=%3d m=%g t1=%g %g t2=%g %g r=%g\n"
+      ,i,m,t1[i-1],t1[i],t2[i-1],t2[i],r);
+for(i=0;i<n;i++) printf(" (%g,%g)",t1[i],t2[i]); printf("\n");
+*/
+
+return(r);
+}
+
+/*=========================================================*/
+/*                         Christophe 10/11/93 La Silla    */
+/*
+++
+int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
+	Fonction de calcul de la moyenne tronquee et du sigma d'un tableau
+--
+*/
+/*
+++
+| Methode: 1-/ moyenne-sigma, 2-/ moyenne tronquee et sigma,
+| ENTREE:
+|  mag: magnitude
+|  err: erreur sur la magnitude
+|  ndata: nombre de donnees
+|  nsigma: nombre de sigma dans lequel on calcule le maximum
+|          si <=0, une seule passe pour la moyenne
+| SORTIE:
+|  ndata: nombre de data utilises pour calculer mean et sigma
+|  mean: moyenne des donnees
+|  sigma: sigma des donnees
+|  MeanSig: 0 si calcul ok, <0 sinon
+--
+*/
+int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
+{
+int_4 deb=DEB_MeanSig;
+int_4 pass,passmx,i,n=0;
+double m,s2,v,scut;
+
+*mean = *sigma = 0.;
+passmx = ( nsigma <= 0. ) ? 1 : 2 ;
+for (pass=1;pass<=passmx;pass++) {
+  m = s2 = 0.;
+  n=0;
+  scut = GRAND;
+  if( pass == 2 ) scut=nsigma* *sigma;
+  for (i=0;i<*ndata;i++) {
+    v = *(mag+i);
+    if( *(err+i) > 0. && fabs(v-*mean) < scut ) {
+      n++;
+      m += v;
+      s2 += v * v;
+  } }
+  if ( n >= 2 ) {
+    *mean = m / n;
+    *sigma = sqrt( s2 / n - m/n * m/n );
+  } else {
+    *mean = *sigma = 0.;
+    *ndata=n;
+    return(-1);
+  }
+  if ( deb>0 ) printf("MeanSig: pass=%d mean=%f sigma=%f n=%d\n"
+                   ,pass,*mean,*sigma,n);
+}
+*ndata=n;
+return(0);
+}
+
+/*=========================================================================*/
+/*
+++
+int Most_Probable -
+  ( float *val, int nval, float binin, int nmoy -
+  , float low, float high, float *most, int deb)
+
+	Pour calculer la valeur la plus probable par maximum d'histogramme.
+--
+*/
+/*
+++
+| INPUT:
+|  - val= pointeur sur un tableau de valeurs (float).
+|  - nval= nombre de valeurs a traiter.
+|  - binin= taille du bin.
+|  - nmoy= la valeur retournee est la moyenne de +/- nmoy bins
+|          autour du max de l'histo.
+|  - low, high= les valeurs permises mini et maxi des valeurs
+|                (si low>high calcul automatique).
+|  - deb= niveau de debug.
+| OUTPUT:
+|  - most = valeur la plus probable.
+| RETURN CODE:
+|  -1 : nval <=0
+|  -2 : bin <=0
+|  -3 : low>=high apres cadrage automatique
+|  -4 : nombre de valeurs remplies nul au niveau de la 1ere passe
+|  -51 : pas trouve de maximum 1ere passe
+|  -52 : pas trouve de maximum 2sd passe
+--
+*/
+int Most_Probable( float *val, int nval, float binin, int nmoy
+                 , float low, float high, float *most, int deb)
+{
+int histo[503],i,nbin,n,ib,ibmax,vmax,pass;
+float bin,xmax=0.;
+double moy,sum;
+
+if(deb>1) printf("Most_Probable: nval=%d binin=%f nmoy=%d low,high=%f %f\n"
+                ,nval,binin,nmoy,low,high);
+if (nval<=0) return(-1);
+if (binin<=0.) return(-2);
+nmoy = (nmoy<0) ? 0 : nmoy;
+if(low>= high) {
+  low = GRAND;
+  high = -low;
+  for(i=0;i<nval;i++) {if(val[i]>high) high=val[i]; if(val[i]<low) low=val[i];}
+}
+if(deb>1) printf("nmoy=%d low,high=%f %f\n",nmoy,low,high);
+if(low>= high) return(-3);
+
+/* premiere passe "nbin" bins entre low et high, nbin=min(high-low)/bin+1,501) */
+/* seconde  passe "nbin" autour du maxi 1ere passe, nbin=min(high-low)/bin,501) */
+
+for ( pass=1;pass<=2;pass++) {
+
+  bin=binin;
+  nbin = (int) ( (high-low)/bin ) + 1;
+  if(nbin>501) {
+    nbin = 501;
+    if(pass!=1){
+      low  = xmax - 250*binin - binin/2.;
+      high = xmax + 250*binin + binin/2.;
+  } }
+  /* re-scaling du bin pour etre sur */ 
+  bin=(high-low)/nbin;
+  if(deb>1) printf("pass=%2d low,high=%f %f bin=%f nbin=%d\n"
+                  ,pass,low,high,bin,nbin);
+  for(i=0;i<nbin;i++) histo[i]=0;
+  n=0;
+  for(i=0;i<nval;i++) {
+    if( val[i]>=high || val[i]<low ) continue;
+    ib = (int) ((val[i]-low)/bin);
+    if( ib<0 && ib >= nbin ) continue;
+    histo[ib]++;
+    n++;
+  }
+  if(n<=0) return (-4);
+  vmax = -1; ibmax= -1;
+  if(n<=0) return (-4);
+  for(i=0;i<nbin;i++) {
+    if(histo[i]<vmax) continue;
+    vmax = histo[i];
+    ibmax = i;
+  }
+  if(ibmax<0) return (-50-pass);
+  xmax = low + ibmax*bin + bin/2.;
+  if(deb>1) printf("bin du maximum %5d (%d) abscisse=%f\n",ibmax,vmax,xmax);
+  if(deb>3) {
+    printf("histogramme:\n");
+    for (i= ibmax-25;i<=ibmax+25;i++) {
+      if (i<0) continue;
+      if (i>=nbin) break;
+      printf(" %5d",histo[i]);
+      if(i%10==9) printf("\n");
+    }
+    printf("\n");
+  }
+}
+
+sum = moy =0.; n=0;
+for (i= -nmoy;i<=nmoy;i++) {
+  if (ibmax-i>=0 && ibmax+i<nbin) {
+    moy += ( xmax + i * bin ) * histo[ibmax+i];
+    sum += (double) histo[ibmax+i];
+    n++;
+} }
+
+*most = moy / sum;
+if(deb>0) printf("Most_probable: most=%f (avec %d points)\n",*most,n);
+
+return(0);
+
+}
+
+/*============================================================*/
+/*                                      Christophe 27/01/95   */
+/*
+++
+float Ajust_GaFn
+|    (int Ns,float *fcfr
+|    ,float *haut,float *ehaut,float *mean,float *emean
+|    ,float *sigma,float *esigma,float *fond,float *efond
+|    ,int fixfond,int NBIN_RESOL
+|    ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
+
+	Fonction de fit gaussienne + fond (1D) du tableau fcfr
+	avec reglage des parametres d'entree.
+--
+*/
+/*
+++
+| ATTENTION: le tableau fcfr est modifie !!!              
+| ---------                                               
+| ENTREES:                                                
+|   Ns = nombre d'entrees dans fcfr
+|   fcfr = tableau des valeurs a fitter
+|   fond = valeur a donner au fond si fixfond = 1
+|   fixfond =  1 fond fixe dans le fit a la valeur fond
+|           =  2 fond fixe dans le fit a une valeur
+|                     calculee automatiquement sur
+|                     les bords de l'histogramme 
+|           >  2 fond fixe a zero (<=> 1 + fond=0)
+|           <= 0 fond libre dans le fit
+|   NBIN_RESOL = nombre maxi de bins pour l'histo de fit
+|                de la resolution
+|   perc_net = pourcentage de donnees a nettoyer pour
+|              calculer mean,sigma de la 1ere passe
+|   frac_sgb = le bin de fit sera sigma*fracsgb
+|              ou sigma est calcule en premiere passe
+|   dyn_sgb = limites de l'histo de fit
+|        xmin=mean-dyn_sgb*sigma , xmax=mean+dyn_sgb*sigma
+|   deb = niveau de debug
+--
+*/
+/*
+++
+| SORTIES:                                                
+|   haut = valeur de la hauteur
+|   ehaut = erreur sur la valeur de la hauteur
+|   mean = valeur moyenne du decalage
+|   emean = erreur sur la valeur moyenne du decalage
+|   sigma = valeur de la resolution
+|   esigma = erreur sur la valeur de la resolution
+|   fond = valeur du fond
+|   efond = erreur sur la valeur du fond 
+|   return code = chi2 du fit  (<0 si Pb)
+--
+*/
+float Ajust_GaFn(int Ns,float *fcfr
+           ,float *haut,float *ehaut,float *mean,float *emean
+           ,float *sigma,float *esigma,float *fond,float *efond
+           ,int fixfond,int NBIN_RESOL
+           ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
+{
+int_4 i,j,i1,i2,nbin,ibin,entries;
+float c2,xmin,xmax,binw,ymax;
+float *y,*ey,*x;
+double m,s;
+FLOATDOUBLE X,Y,EY;
+double (*Fun) (double ,double *,double *);
+int_4 npar,n;
+double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
+
+fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
+perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
+NBIN_RESOL = ( NBIN_RESOL <= 0 ) ? 50 : NBIN_RESOL;
+frac_sgb = ( frac_sgb <= 0. ) ? 0.5 : frac_sgb;
+dyn_sgb  = ( dyn_sgb  <= 0. ) ? 5.0 : dyn_sgb;
+x = y = ey = NULL;
+x  = (float *) calloc(NBIN_RESOL+2,sizeof(float));
+y  = (float *) calloc(NBIN_RESOL+2,sizeof(float));
+ey = (float *) calloc(NBIN_RESOL+2,sizeof(float));
+if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
+
+if(deb>0) printf("Ajust_GaFn[%d] perc_net=%f nbin=%d frac_sgb=%f dyn_sgb=%f\n"
+              ,Ns,perc_net,NBIN_RESOL,frac_sgb,dyn_sgb);
+
+/* on vire perc_net % des points a gauche et a droite de la distribution */
+qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
+i = perc_net * Ns;
+if(perc_net>0. && i==0) i=1;
+i1 = i; i2 = Ns-1-i;
+if(deb>1) {
+  printf("  df/f=");
+  for(j=0;j<10;j++) printf("%8.2f ",fcfr[j]);
+  printf("\n");
+  printf("selection de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
+}
+if(i2<=i1) { c2= -101.; goto END;}
+
+/* calcul mean et sigma 1ere passe */
+m = s = 0.; j = 0;
+for(i=i1;i<=i2;i++) {m += fcfr[i]; s += fcfr[i]*fcfr[i]; j++;}
+m /= j;
+s = sqrt(s/j - m*m);
+*mean = m; *sigma = s;
+if(deb>1) printf("premiere passe: mean=%f sigma=%f\n",*mean,*sigma);
+
+/* remplissage histo a +/- dyn_sgb * sigma */
+xmin = *mean - dyn_sgb* *sigma;
+xmax = *mean + dyn_sgb* *sigma;
+if(xmin>=xmax) {c2 = -102.; goto END;}
+binw = *sigma * frac_sgb;
+nbin = (xmax-xmin)/binw;
+if(nbin<6) nbin=6; if(nbin>NBIN_RESOL) nbin=NBIN_RESOL;
+binw = (xmax-xmin)/nbin;
+for(i=0;i<nbin;i++)
+    {x[i] = xmin + ((float) i + 0.5)*binw; y[i] = 0.;}
+if(deb>1) {
+  printf("histo[%d] lim=[%f,%f] bw=%f x=\n"
+        ,nbin,xmin,xmax,binw);
+  for(j=0;j<nbin;j++)
+    {printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
+  if(j%10!=0) printf("\n");
+}
+entries = 0;
+for(i=0;i<Ns;i++) { ibin = (fcfr[i]-xmin)/binw;
+         if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;} }
+ymax = 0.;
+for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
+                    if(y[i]>ymax) ymax=y[i];}
+if(deb>1) {
+  printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
+  for(j=0;j<nbin;j++)
+    {printf("%8.0f ",y[j]); if(j%10==9) printf("\n");}
+  if(j%10!=0) printf("\n");
+  if(deb>2) {
+    printf("histo ey=\n");
+    for(j=0;j<nbin;j++)
+      {printf("%8.0f ",ey[j]); if(j%10==9) printf("\n");}
+    if(j%10!=0) printf("\n"); }
+}
+if(ymax<2.) {c2 = -103.; goto END;}
+
+if(fixfond!=1) {
+  *fond = (y[0]+y[1]+y[nbin-1]+y[nbin-2])/4.;
+  if(fixfond>2) *fond = 0.;
+}
+*haut = ymax - *fond;
+
+/* fit gaussienne + fond constant */
+Fun = Gauss1DPolF ; Set_FitFunDPol(0);
+X.fx  = x;
+Y.fx  = y;
+EY.fx = ey;
+par[0] = *haut;
+par[1] = *mean;
+par[2] = *sigma;
+par[3] = *fond;
+stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
+stepar[2] = par[2]/10.; stepar[3] = 0.5;
+if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
+for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
+minpar[2] = 0.00001; maxpar[2] = 9999.;
+npar = 4;
+stochi2 = 0.0001;
+n = nbin;
+j = (deb>2)? 1:0;
+c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
+           ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
+
+END:
+
+if( c2 > 0. ) {
+  *haut  =  par[0]; *mean  =  par[1]; *sigma  =  par[2]; *fond  =  par[3];
+  *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
+} else {
+  *ehaut = *emean = *esigma = *efond = 0.;
+}
+if(x !=NULL) free(x);
+if(y !=NULL) free(y);
+if(ey!=NULL) free(ey);
+
+return(c2);
+}
+
+/*==========================================================*/
+/*                                    Christophe 27/03/95   */
+/*
+++
+float HFit_GaFn -
+  (int Ns,float *fcfr -
+  ,float *haut,float *ehaut,float *mean,float *emean -
+  ,float *sigma,float *esigma,float *fond,float *efond -
+  ,int fixfond,int nbin,float xmin,float xmax,int deb)
+
+	Fonction de fit gaussienne + fond (1D) du tableau fcfr
+	dans un histo de "nbin" bins de "xmin a xmax"
+--
+*/
+/*
+++
+| ENTREES:
+|   Ns = nombre d'entrees dans fcfr
+|   fcfr = tableau des valeurs a fitter
+|   mean = valeur de depart pour la moyenne
+|   sigma = valeur de depart pour le sigma
+|   fond = valeur de depart pour le fond
+|   fixfond > 0  fond fixe dans le fit a la valeur fond
+|           <= 0 fond libre dans le fit
+|   nbin = nombre de bins pour l'histo de fit
+|   xmin = valeur inferieure de l'histo
+|   xmax = valeur superieure de l'histo
+|   deb = niveau de debug
+--
+*/
+/*
+++
+| SORTIES:
+|   haut = valeur de la hauteur
+|   ehaut = erreur sur la valeur de la hauteur
+|   mean = valeur moyenne du decalage
+|   emean = erreur sur la valeur moyenne du decalage
+|   sigma = valeur de la resolution
+|   esigma = erreur sur la valeur de la resolution
+|   fond = valeur du fond
+|   efond = erreur sur la valeur du fond
+|   return code = chi2 du fit  (<0 si Pb)
+--
+*/
+float HFit_GaFn(int Ns,float *fcfr
+           ,float *haut,float *ehaut,float *mean,float *emean
+           ,float *sigma,float *esigma,float *fond,float *efond
+           ,int fixfond,int nbin,float xmin,float xmax,int deb)
+{
+int_4 i,j,ibin,entries;
+float c2,binw,ymax;
+float *y,*ey,*x;
+FLOATDOUBLE X,Y,EY;
+double (*Fun) (double ,double *,double *);
+int_4 npar,n;
+double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
+
+if(xmax<=xmin) return(-102);
+fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
+nbin = ( nbin <= 0 ) ? 50 : nbin;
+x = y = ey = NULL;
+x  = (float *) calloc(nbin+2,sizeof(float));
+y  = (float *) calloc(nbin+2,sizeof(float));
+ey = (float *) calloc(nbin+2,sizeof(float));
+if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
+
+if(deb>0) printf("HFit_GaFn[%d pts] nbin=%d de %g a %g\n"
+              ,Ns,nbin,xmin,xmax);
+
+/* remplissage histo */
+binw = (xmax-xmin)/nbin;
+for(i=0;i<nbin;i++) {x[i]=xmin+((float) i +0.5)*binw; y[i]=0.;}
+if(deb>1) {
+  printf("histo[%d] lim=[%f,%f] bw=%f x=\n",nbin,xmin,xmax,binw);
+  for(j=0;j<nbin;j++){printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
+  if(j%10!=0) printf("\n");
+}
+entries = 0;
+for(i=0;i<Ns;i++) {
+  ibin = (fcfr[i]-xmin)/binw;
+  if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;}
+}
+
+ymax = 0.;
+for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
+                    if(y[i]>ymax) ymax=y[i];}
+if(deb>1) {
+  printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
+  for(j=0;j<nbin;j++){printf("%8.0f ",y[j]); if(j%10==9)printf("\n");}
+  if(j%10!=0) printf("\n");
+  if(deb>2) {
+    printf("histo ey=\n");
+    for(j=0;j<nbin;j++){printf("%8.0f ",ey[j]); if(j%10==9)printf("\n");}
+    if(j%10!=0) printf("\n");
+} }
+if(ymax<2.) {c2 = -103.; goto END;}
+
+*haut = ymax - *fond;
+
+/* fit gaussienne + fond constant */
+Fun = Gauss1DPolF ; Set_FitFunDPol(0);
+X.fx  = x;
+Y.fx  = y;
+EY.fx = ey;
+par[0] = *haut;
+par[1] = *mean;
+par[2] = *sigma;
+par[3] = *fond;
+stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
+stepar[2] = par[2]/10.; stepar[3] = 0.5;
+if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
+for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
+minpar[2] = 0.00001; maxpar[2] = 9999.;
+npar = 4;
+stochi2 = 0.0001;
+n = nbin;
+j = (deb>2)? 1:0;
+c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
+           ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
+
+END:
+
+if( c2 > 0. ) {
+  *haut  =  par[0]; *mean  =  par[1]; *sigma  =  par[2]; *fond  =  par[3];
+  *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
+} else {
+  *ehaut = *emean = *esigma = *efond = 0.;
+}
+if(x !=NULL) free(x);
+if(y !=NULL) free(y);
+if(ey!=NULL) free(ey);
+
+return(c2);
+}
+
+/*==============================================================*/
+/*                                    Christophe 15/02/95       */
+/*
+++
+int Ajust_MnSg -
+  (int Ns,float *fcfr -
+  ,float *mean,float *emean,float *sigma,float *esigma -
+  ,float perc_net,float n_sigma,int deb)
+
+	Calcul mean sigma tronques du tableau fcfr.
+--
+*/
+/*
+++
+| ATTENTION: le tableau fcfr est modifie
+| ---------
+| Methode:
+|  1- calcul de la moyenne Mcent en enlevant perc_net% des pts
+|     les + faibles et perc_net% des pts les + forts
+|  2- calcul de la valeur cutup correspondant a 2*perc_net%
+|     des pts les + hauts en valeur absolue (fcfr-Mcent)
+|  3- calcul moyenne et sigma en enlevant les points ayant
+|        abs(fcfr-Mcent) > cutup    (1ere passe)
+|  4- calcul moyenne et sigma en enlevant les points ayant
+|        abs(fcfr-Mcent) > cutup   et
+|        abs(fcfr-M(1ere passe)) > n_sigma*sigma(1ere passe)
+--
+*/
+/*
+++
+| ENTREES:
+|   Ns = nombre d'entrees dans fcfr
+|   fcfr = tableau des valeurs a fitter
+|   perc_net = pourcentage de donnees a nettoyer pour
+|              calculer mean,sigma
+|   n_sigma = nombre de sigma en passe 2 pour
+|              calculer mean,sigma
+|   deb = niveau de debug
+| SORTIES:
+|   mean = valeur moyenne du decalage
+|   emean = erreur sur la valeur moyenne du decalage
+|   sigma = valeur de la resolution
+|   esigma = erreur sur la valeur de la resolution
+|   return code = nombre de points utilises (<0 si Pb)
+--
+*/
+int Ajust_MnSg(int Ns,float *fcfr
+           ,float *mean,float *emean,float *sigma,float *esigma
+           ,float perc_net,float n_sigma,int deb)
+{
+int i,i1,i2,n,nvire,pass;
+double m,s,mcent,cutup,cuts;
+float *dum;
+
+/* set up des valeurs par defaut */
+perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
+n_sigma = ( n_sigma <= 0. ) ? 3.0 : n_sigma;
+nvire = perc_net * Ns;
+if(perc_net>0. && nvire==0) nvire=1;
+*emean = *esigma = -1.;
+if(deb>0) printf("Ajust_MnSg[%d] perc_net=%f (vire=%d) n_sigma=%f\n"
+                ,Ns,perc_net,nvire,n_sigma);
+
+/* on ordonne par ordre croissant de fcfr */
+qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
+i1 = nvire; i2 = Ns-1-nvire;
+if(deb>1) printf("    select de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
+if(i2<=i1) return(-101);
+
+/* on vire perc_net % des points a gauche et a droite de la distribution */
+mcent = 0.; n = 0;
+for(i=i1;i<=i2;i++) {mcent += fcfr[i]; n++;}
+if(n<1) return(-102);
+mcent /= (double) n;
+if(deb>1) printf("    mean cent=%f sur %d points\n",mcent,n);
+
+/* allocate space and fill absolute value */
+if( (dum  = (float *) calloc(Ns,sizeof(float))) == NULL ) return(-103);
+for(i=0;i<Ns;i++) dum[i] = fabs( mcent - fcfr[i] );
+
+/* on ordonne par ordre croissant de abs(fcfr-mcent) */
+qsort(dum,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
+i = Ns-1-2*nvire;
+if(i<0) {n= -104; goto END_Ajust_MnSg;}
+
+/* on vire 2.*perc_net % des points les + hauts de la distribution */
+cutup = dum[i];
+if(deb>1) printf("    cutup=%f sur %d points\n",cutup,i);
+
+/* calcul mean et sigma en 2 passes avec coupure n_sigma*sigma(1ere passe)*/
+cuts = GRAND2;
+for(pass=1;pass<=2;pass++) {
+  m = s = 0.; n = 0;
+  for(i=0;i<Ns;i++) {
+    if( fabs(mcent-fcfr[i]) > cutup ) continue;
+    if( fabs((double) (*mean-fcfr[i])) > cuts ) continue;
+    m += fcfr[i];
+    s += fcfr[i]*fcfr[i];
+    n++;
+  }
+  if(n<=2) {n= -105; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
+  m /= n;
+  s = s/n - m*m;
+  if(s<=0.) {n= -106; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
+  s = sqrt(s);
+  *mean = m;
+  *sigma = s;
+  cuts = n_sigma * s;
+  if(deb>1)
+    printf("    pass=%d mean=%g sigma=%g (%d pts) cuts=%f\n"
+          ,pass,*mean,*sigma,n,cuts);
+}
+
+*emean = s/sqrt((double) n);
+*esigma = s/sqrt(2. * (double) n);
+if(deb>0) printf("mean=%g (+/-%g) sigma=%g (+/-%g) sur %d pts\n"
+              ,*mean,*emean,*sigma,*esigma,n);
+
+END_Ajust_MnSg:
+if( dum != NULL ) free(dum);
+return(n);
+}
+
+/*=================================================================*/
+/*                                       Nathalie 16/02/95         */
+/*
+++
+float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
+	Cette fonction calcule l'integrale 3D: f(x,y,z)dx.dy.dz
+	L'integrale est calculee en incrementant des couronnes cubiques
+	centrees sur le point de coordonnees (0,0,0)
+--
+*/
+/*
+++
+| ENTREES:
+|   fonction = f(x,y,z)
+|   step = pas de l'integration
+|   precision = coupure en dV(couronne i)/Vtot(couronnes 0 a i)
+| SORTIES:
+|   return: l'integrale
+| REMARQUES:
+|   la fonction f(x,y,z) doit decroitre tres vite en r**2
+--
+*/
+float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
+{
+
+  float f;
+  double vol,volprec;
+  int ecart,i,j,k,l;
+  int encore,deb=0;
+
+  vol = volprec = 0.;
+
+  /* contribution du cube central */
+  for(l=0;l<nd3d;l++) {
+    f = fonction(dx3d[l]*step,dy3d[l]*step,dz3d[l]*step);
+    vol += f*w3d[l];
+  }
+  ecart = 1;
+
+  /* increment en couronnes cubiques de 2*ecart+1 de cote */  
+  do {
+    volprec = vol;
+    for (i= -ecart;i<=ecart;i++) for(l=0;l<nd3d;l++) {
+      for(j= -ecart;j<=ecart;j++) {
+	f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,(-ecart+dz3d[l])*step);
+	vol += f*w3d[l];
+	f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,( ecart+dz3d[l])*step);
+	vol += f*w3d[l];
+      }
+
+      for(k= -ecart+1;k<=ecart-1;k++) {
+	f=fonction((i+dx3d[l])*step,(-ecart+dy3d[l])*step,(k+dz3d[l])*step);
+	vol += f*w3d[l];
+	f=fonction((i+dx3d[l])*step,( ecart+dy3d[l])*step,(k+dz3d[l])*step);
+	vol += f*w3d[l];
+      }
+    }
+    for (j= -ecart+1;j<=ecart-1;j++) for(k= -ecart+1;k<=ecart-1;k++) 
+      for(l=0;l<nd3d;l++) {
+	f=fonction((-ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
+	vol += f*w3d[l];
+	f=fonction(( ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
+	vol += f*w3d[l];
+    }
+
+    ecart = ecart + 1;
+    encore = ((fabs((vol-volprec)/vol) > precision) || (ecart <= 2) );
+    if(deb>1) printf("ec=%d v=%g deltav/v=%g\n"
+           ,ecart-1,vol*step*step*step,((vol-volprec)/vol));
+  } while(encore);
+
+  vol *= step * step* step;
+  if(deb>0) printf("\nVol = %g\n",vol); 
+  return(vol);
+}
+
+
+/*=================================================================*/
+/*                                             cmv  6/11/97        */
+/*
+++
+int IntFaisDr -
+  (int n,float *cs,float *sn,float *p,float *x0,float *y0 -
+  ,int npass,float perclean,int lp)
+
+	Pour calculer le point d'intersection moyen
+	d'un faisceau de droites.
+--
+*/
+/*
+++
+| L'equation des droites est sous la forme:
+|      cos(alpha)*x + sin(alpha)*y = p
+| [cos(alpha),sin(alpha)] coordonnees du vecteur unitaire joignant
+| l'origine au point de moindre approche de la droite a l'origine.
+| p est la distance de la droite a l'origine.
+--
+*/
+/*
+++
+| -- Input:
+|  n  : nombre de droites
+|  cs : tableau des coefficients cos(alpha)
+|  sn : tableau des coefficients sin(alpha)
+|  p  : tableau des coefficients p
+|  npass    : nombre de passes de nettoyage
+|  perclean : pourcentage d'etoiles a tuer
+|             d'une passe a la suivante
+|      ex: perclean=0.2, si il y a 200 etoiles dans une passe
+|      la passe suivante en utilisera 160 et la suivante 128.
+|  lp : niveau d'impression
+--
+*/
+/*
+++
+| -- Output:
+|  x0 : valeur de l'abscisse du point d'intersection moyen trouve
+|  y0 :             ordonnee
+| -- Return:
+|  nombre de droites utilisees pour le calcul de x0,y0
+--
+*/
+int IntFaisDr(int n,float *cs,float *sn,float *p,float *x0,float *y0
+             ,int npass,float perclean,int lp)
+{
+int i,j,ns, nsuse=-9, ipass;
+double sumC2,sumS2,sumCS,sumCP,sumSP,den;
+float *d2=NULL, d2cut=-1.;
+unsigned short *good=NULL;
+
+*x0 = *y0 = 0.;
+if(n<=1) return(-1);
+if(lp<0) lp=0;\
+if(npass<=0) npass=1;
+if(perclean<=0.) { perclean=0.; npass=1;}
+if(lp)
+  printf("IntFaisDr avec %d points en %d passes avec nettoyage de %g%%\n"
+        ,n,npass,perclean*100);
+
+d2 = (float *) malloc(n * sizeof(float));
+if(d2==NULL) {
+  if(lp)
+    printf("allocation de %d float impossible\n",n);
+  return(-2);
+}
+good = (unsigned short *) malloc(n * sizeof(unsigned short));
+if(good==NULL) {
+  if(lp)
+    printf("allocation de %d unsigned short impossible\n",n);
+  free(d2);
+  return(-3);
+}
+for(i=0;i<n;i++) good[i]=1;
+
+for(ipass=1;ipass<=npass;ipass++) {
+
+  /* Calcul du point d'intersection pour la passe ipass */
+  sumC2=sumS2=sumCS=sumCP=sumSP=0.;
+  ns=0;
+  for(i=0;i<n;i++) {
+    if( !good[i] ) continue;
+    sumC2 += cs[i]*cs[i];
+    sumS2 += sn[i]*sn[i];
+    sumCS += cs[i]*sn[i];
+    sumCP += cs[i]*p[i];
+    sumSP += sn[i]*p[i];
+    ns++;
+  }
+  den = sumCS*sumCS - sumC2*sumS2;
+  if(den==0.) {
+    if(lp)
+      printf("denominateur nul pass=%d, sumCS=%g sumC2=%g sumS2=%g pour %d dr\n"
+            ,ipass,sumCS,sumC2,sumS2,ns);
+    free(d2); free(good);
+    return(-100-ipass);
+  }
+  if(ns<2) {
+    if(lp) printf("Pas ou plus assez de droites %d\n",ns);
+    return(nsuse);
+  }
+  *x0 = (sumSP*sumCS - sumCP*sumS2)/den;
+  *y0 = (sumCP*sumCS - sumSP*sumC2)/den;
+  nsuse = ns;
+  if(lp) printf("Pass=%d, %d dr x0=%g y0=%g\n",ipass,nsuse,*x0,*y0);
+  if(ipass==npass) break;
+
+  /* Calcul de la coupure en distance**2 pour la passe suivante */
+  ns = 0;
+  for(i=0;i<n;i++) {
+    if( !good[i] ) continue;
+    d2[ns] = (*x0*cs[i] * *y0*sn[i]-p[i]);
+    d2[ns] *= d2[ns];
+    ns++;
+  }  
+  qsort(d2,(size_t) ns,sizeof(float),qSort_Float);
+  j = (int) (ns-ns*perclean); if(j<0) j=0;  if(j>=ns) j=ns-1;
+  d2cut = d2[j];
+  ns=0;
+  for(i=0;i<n;i++) {
+    if( !good[i] ) continue;
+    den = (*x0*cs[i] * *y0*sn[i]-p[i]);
+    den *= den;
+    if( den>d2cut ) good[i]=0; else ns++;
+  }
+  if(lp>1)
+    printf("  next pass: i=%d  cut=%g -> restera %d dr\n",j,d2cut,ns);
+}
+
+free(d2); free(good);
+return(nsuse);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/nbmath.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbmath.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbmath.h	(revision 752)
@@ -0,0 +1,134 @@
+/* quelques fonctions mathematiques et constantes utiles */
+/*                                         cmv  23/06/94 */
+#ifndef NBMATH_H_SEEN
+#define NBMATH_H_SEEN
+
+#include "machdefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EA conflit entre les diverses copies de nbmath.h, nbconst.h... A nettoyer... */
+#undef  Pi   
+#undef  Pis2
+#undef  DeuxPi 
+#undef  SPi   
+#undef  S2Pi   
+#undef  Rac2   
+#undef  Log2   
+#undef  LnPi   
+#undef  LgPi   
+#undef  Ln10   
+#undef  DftoDm 
+#undef  Hln2pi 
+#undef  JourSec 
+#undef  AnSec  
+
+#undef  GRAND  
+#undef  GRAND2 
+#undef  IGRAND 
+
+#define  Pi     (double) ( 3.14159265358979310e+00)  /* c'est Pi */
+#define  Pis2   (double) (1.57079632679489655)       /* c'est Pi/2 */
+#define  DeuxPi (double) ( 6.28318530717958620e+00)  /* c'est 2*Pi */
+#define  SPi    (double) ( 1.77245385090551590e+00)  /* c'est sqrt(Pi) */
+#define  S2Pi   (double) ( 2.50662827463100020e+00)  /* c'est sqrt(2*Pi) */
+#define  Rac2   (double) ( 1.41421356237309510e+00)  /* c'est sqrt(2) */
+#define  Log2   (double) ( 3.01029995663981200e-01)  /* c'est log10(2) */
+#define  LnPi   (double) ( 1.14472988584940020e+00)  /* c'est ln(Pi) */
+#define  LgPi   (double) ( 4.97149872694133850e-01)  /* c'est log10(Pi) */
+#define  Ln10   (double) ( 2.30258509299404590e+00)  /* c'est ln(10) */
+#define  DftoDm (double) ( 1.08573620475812940e+00)  /* c'est 2.5/ln(10) */
+#define  Hln2pi (double) ( 9.18938533204672670e-01)  /* c'est Ln(2*pi)/2 */
+
+#define  JourSec (float) (86400.000000) /* nombre de secondes dans 24H */
+#define  AnSec  (int) (31557600) /* nombre de secondes dans 365.25 jours */
+
+#define  GRAND  (float)  (1.e+35)
+#define  GRAND2 (double) (1.e+35)
+#define  IGRAND (int_4) (2147483647)
+
+/* pour le fit 1-dim */
+#define NPAR_FITFUN 10
+#define FITFUN_FLOAT 1
+#define FITFUN_DOUBLE 2
+union FloatDouble { float  *fx; double *dx; };
+typedef union FloatDouble FLOATDOUBLE;
+
+double FitFun( double (*FunFit) (double ,double *,double *) ,int_4 type
+             ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
+             ,int_4 *ndata,int_4 I1,int_4 I2
+             ,double *par,double *epar,double *stepar
+             ,double *minpar,double *maxpar,int_4 npar
+             ,double stochi2,int_4 NstepMX,int_4 deb);
+
+double GausPiv(double *A,int_4 nca,int_4 n,double *B,int_4 ncb,int_4 m,int_4 Inv);
+
+int_4 paramga(float sxin, float syin, float rhoin
+             , float *smax, float *axisrat, float *tiltdeg);
+int_4 gaparam(float smax, float axisrat, float tiltdeg
+             , float *sxin, float *syin, float *rhoin);
+
+double nberfc(double x);
+float probnb(float sci2,int_4 inddl,int_4 *ipass);
+double nbgammln(double xx);
+double nbgammq(double a,double x);
+double nbgammp(double a,double x);
+
+void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW);
+int Get_Ihoq(int degre,double *IhoqNX,double *IhoqNW);
+void nbgauleg(double x1,double x2,double *x,double *w,int n);
+double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas);
+double Integ_Fun_2D(double (*fonc)(double x,double y)
+                ,double xmin,double xmax,double ymin,double ymax
+                ,int npasx,int npasy);
+
+void Set_FitFunDPol(int DPol);
+double Gauss1DPolF(double x,double *Par,double *DgDpar);
+double GaussI1DPol(double x,double *Par,double *DgDpar);
+double Polyn1D(double x,double *Par,double *DgDpar); 
+
+double FitProp(double *x,double *y,double *ey,int *n,double *a1);
+double FitLin(double *x,double *y,double *ey,int *n
+             ,double *a0,double *a1);
+double FitPar(double *x,double *y,double *ey,int *n
+             ,double *a0,double *a1,double *a2);
+double FitParLin(double *xx,double *y,double *ey,int *n,double x0,int Deg_d
+                ,double *a0,double *a1,double *b1,double *b2);
+double FitPropClean(double *x,double *y,double *ey,int *n
+                  ,double per_clean,double *a1);
+double FitLinClean(double *x,double *y,double *ey,int *n
+                  ,double per_clean,double *a0,double *a1);
+double FitParClean(double *x,double *y,double *ey,int *n
+                  ,double per_clean,double *a0,double *a1,double *a2);
+
+float interpole(float x,int n,float *t1,float *t2);
+
+int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma);
+int Most_Probable( float *val, int nval, float binin, int nmoy
+                 , float low, float high, float *most, int deb);
+float Ajust_GaFn(int Ns,float *fcfr
+           ,float *haut,float *ehaut,float *mean,float *emean
+           ,float *sigma,float *esigma,float *fond,float *efond
+           ,int fixfond,int NBIN_RESOL
+           ,float perc_net,float frac_sgb,float dyn_sgb,int deb);
+float HFit_GaFn(int Ns,float *fcfr
+           ,float *haut,float *ehaut,float *mean,float *emean
+           ,float *sigma,float *esigma,float *fond,float *efond
+           ,int fixfond,int nbin,float xmin,float xmax,int deb);
+int Ajust_MnSg(int Ns,float *fcfr
+           ,float *mean,float *emean,float *sigma,float *esigma
+           ,float perc_net,float n_sigma,int deb);
+
+float Int3DCube(float(*fonction)(float, float, float), float step, 
+	       float precision);
+
+int IntFaisDr(int n,float *cs,float *sn,float *p,float *x0,float *y0
+             ,int npass,float perclean,int lp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/nbrandom.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbrandom.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbrandom.c	(revision 752)
@@ -0,0 +1,575 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+#include "machdefs.h"
+#include "nbmath.h"
+#include "nbrandom.h"
+
+static double GAU_RANGE=6.;
+
+/* 
+++ 
+  Module 	Tirages aleatoires (C)
+  Lib	LibsUtil
+  include	nbrandom.h
+--
+*/
+
+/*
+++
+  frand01()
+	tirage aleatoire entre 0 et 1, retourne float  
+  drand01()
+	tirage aleatoire entre 0 et 1, retourne double  
+  rand01()
+	 c'est le defaut: drand01()
+  frandpm1()
+	tirage aleatoire entre -1 et 1, retourne float
+  drandpm1()
+	tirage aleatoire entre -1 et 1, retourne double
+  ranfpm1()
+	c'est le defaut: drandpm1()
+--
+*/
+
+/*=========================================================================*/
+/*
+++
+  void Ini_Ranf_Quick(long seed_val, int lp)
+	Initialisation rapide du generateur (drand48) par un entier
+	de 32 bits de type long (cf srand48).
+--
+*/
+void Ini_Ranf_Quick(long seed_val, int lp)
+{
+if(lp) printf("Ini_Ranf_Quick: %d\n",(int) seed_val);
+srand48(seed_val);
+return;
+}
+
+/*=========================================================================*/
+/*
+++
+  void Ini_Ranf(unsigned short seed_16v[3], int lp)
+	Initialisation complete du generateur (drand48) par
+	48 bits (cf seed48).
+--
+*/
+void Ini_Ranf(unsigned short seed_16v[3], int lp)
+{
+if(lp) printf("Ini_Ranf: %d %d %d\n"
+             ,seed_16v[0],seed_16v[1],seed_16v[2]);
+seed48(seed_16v);
+return;
+}
+
+/*=========================================================================*/
+/*
+++
+  void Get_Ranf(unsigned short seed_16v[3], int lp)
+	Recuperation de l'etat du generateur (drand48) sur
+	de 48 bits (cf seed48).
+--
+*/
+void Get_Ranf(unsigned short seed_16v[3], int lp)
+{
+unsigned short seed[3] = {0,0,0};
+unsigned short *p;
+p = seed48(seed);
+memcpy(seed_16v,p,3*sizeof(unsigned short));
+if(lp) printf("Get_Ranf: %d %d %d\n"
+             ,seed_16v[0],seed_16v[1],seed_16v[2]);
+/* on re-initialise a ce qui etait avant */
+seed48(seed_16v);
+return;
+}
+
+/*=========================================================================*/
+/*
+++
+  void Auto_Ini_Ranf(int lp)
+	Initialisation automatique (pseudo) aleatoire du generateur.
+	L'initialiseur est donne par le nombre de millisecondes
+	ecoulees depuis le dernier jour multiple de 23 du nombre de jours
+	depuis le 0 heure le 1er Janvier 1970 UTC (cf gettimeofday).
+	Pour retomber sur la meme initialisation
+	il faut generer deux aleatoires a moins de 1/1000 seconde
+	ou generer le deuxieme aleatoire 23 jours apres le premier
+	a la meme heure (a 1/1000 de seconde pres). La fonction
+	d'initialisation utilisee est Ini_Ranf_Quick(long).
+--
+*/
+void Auto_Ini_Ranf(int lp)
+{
+struct timeval now;
+long nj,nj23,seed=0;
+double buf;
+
+gettimeofday (&now,0);
+
+/* dans 32 bits signes on met environ 23 jours a 1/1000 de seconde pres! */
+/* Nombre de jours depuis l'origine */
+nj = (long) now.tv_sec / 86400;
+/* Nombre de jours depuis le dernier jour multiple de 23 jours */
+nj23 = nj % 23;
+/* nombre de secondes depuis le dernier jour multiple de 23 jours */
+buf = (double) (nj23*86400 + (now.tv_sec-nj*86400));
+/* nombre de milliemes de secondes depuis ... */
+buf = buf*1000. +  now.tv_usec/1000.;
+seed = (long) buf;
+
+if(lp) {
+  printf("Auto_Ini_Ranf: date %d s %d 10^-6 sec seed=%d:\n"
+        ,now.tv_sec,now.tv_usec,seed);
+  if(lp>1) printf("... njours=%d nj23=%d buf=%.20g\n",nj,nj23,buf);
+}
+Ini_Ranf_Quick(seed,lp);
+return;
+}
+
+/*=========================================================================*/
+/*
+++
+  void SetGauRange(double range)
+	Generation de distribution gaussienne:
+	Changement de l'initialisation de l'excursion du tirage
+	en nombre de sigmas
+--
+*/
+void SetGauRange(double range)
+{
+GAU_RANGE = range;
+}
+
+/*=========================================================================*/
+/*
+++
+  float NorRand(void)
+	Generation aleatoire gaussienne normee centree
+--
+*/
+float NorRand(void)
+{
+double x,A,B;
+
+LAB10:
+A = drand01();
+if ( A == 0. ) goto LAB10;
+B = drand01();
+x = sqrt(-2.*log(A))*cos(DeuxPi*B);
+return( (float) x );
+}
+
+/*=========================================================================*/
+/*
+++
+  float NorRand1(void)
+	Generation aleatoire gaussienne normee centree
+	la distribution est limitee entre +/- GAU_RANGE (obsolete).
+--
+*/
+float NorRand1(void)
+{
+double b, x, y, gauss;
+
+b = 1./sqrt(2.*M_PI);
+LAB10:
+x = GAU_RANGE*drandpm1();
+y = drand01()*b;
+gauss = b*exp(-x*x/2.);
+if ( gauss-y < 0. ) goto LAB10 ;
+return( (float) x );
+}
+
+/*=========================================================================*/
+/*
+++
+  double GauRnd(double am, double s)
+	Generation aleatoire gaussienne de centre "am" et de sigma "s".
+--
+*/
+double GauRnd(double am, double s)
+{
+double x,A,B;
+
+LAB10:
+A = drand01();
+if ( A == 0. ) goto LAB10;
+B = drand01();
+x = am + s * sqrt(-2.*log(A))*cos(DeuxPi*B);
+return(x);
+}
+
+/*=========================================================================*/
+/*
+++
+  double GauRnd1(double am, double s)
+	Generation aleatoire gaussienne de centre "am" et de
+	sigma "s" la distribution est limitee entre am +/- GAU_RANGE (obsolete).
+--
+*/
+double GauRnd1(double am, double s)
+{
+double s2, b, x, y, gauss;
+
+s2 = 2.*s*s;
+b = 1./sqrt(2.*M_PI*s);
+LAB10:
+x = am + GAU_RANGE*s*drandpm1();
+y = drand01()*b;
+gauss = b*exp(-(x-am)*(x-am)/s2);
+if ( gauss-y < 0. ) goto LAB10 ;
+return(x);
+}
+
+/*==========================================================================*/
+/*
+++
+  void NormGau(double *x,double *y,double mx,double my,double sa,double sb,double teta);
+	Tirage de 2 nombres aleatoires x et y distribues sur une gaussienne 2D
+	de centre (x=mx,y=my), de sigmas grand axe et petit axe (sa,sb)
+	et dont le grand axe fait un angle teta (radian) avec l'axe des x.
+--
+*/
+/*
+++
+| - La densite de probabilite (normalisee a 1) sur laquelle on tire est:
+| N*exp[-0.5*{ (A/sa)**2+(C/sc)**2 }],  N=1/(2Pi*sa*sc)
+| ou A et B sont les coordonnees selon le grand axe et le petit axe
+| et teta = angle(x,A), le resultat subit ensuite une rotation d'angle teta.
+| - La matrice des covariances C des variables A,B est:
+|   | sa^2   0   |
+|   |            |  et det(C) = (1-ro^2)*sa^2*sb^2
+|   |  0    sb^2 |
+| - La distribution x,y resultante est:
+| N*exp[-0.5*{[(dx/sx)^2-2*ro/(sx*sy)*dx*dy+(dy/sy)^2]/(1-ro^2)}]
+| ou N est donne dans NormCo et sx,sy,ro sont calcules a partir
+| de sa,sc,teta (voir fonctions paramga ou gaparam). La matrice des
+| covariances des variables x,y est donnee dans la fonction NormCo.
+--
+*/
+void NormGau(double *x,double *y
+            ,double mx,double my,double sa,double sb,double teta)
+{
+double c,s,X,Y;
+
+LAB10:
+ s = drand01();
+ if ( s == 0. ) goto LAB10;
+s = sqrt(-2.*log(s));
+c = DeuxPi * drand01();
+
+X = sa*s*cos(c);
+Y = sb*s*sin(c);
+
+c = cos(teta); s = sin(teta);
+*x = mx + c*X - s*Y;
+*y = my + s*X + c*Y;
+}
+
+/*==========================================================================*/
+/*
+++
+  int NormCo(double *x,double *y,double mx,double my,double sx,double sy,double ro)
+	Tirage de 2 nombres aleatoires x et y distribues sur une gaussienne 2D
+	de centre (mx,my), de coefficient de correlation rho (ro) et telle que
+	les sigmas finals des variables x et y soient sx,sy (ce sont
+	les valeurs des distributions marginales des variables aleatoires x et y
+	c'est a dire les sigmas des projections x et y de l'histogramme 2D
+	de la gaussienne). Retourne 0 si ok.
+--
+*/
+/*
+++
+| - La densite de probabilite (normalisee a 1) sur laquelle on tire est:
+|   N*exp[-0.5*{[(dx/sx)^2-2*ro/(sx*sy)*dx*dy+(dy/sy)^2]/(1-ro^2)}]
+|     avec dx = x-mx, dy = y-my et N = 1/[2Pi*sx*sy*sqrt(1-ro^2)]
+| - Dans ce cas la distribution marginale est (ex en X):
+|   1/(sqrt(2Pi)*sx) * exp[-0.5*{dx^2/sx^2}]
+| - La matrice des covariances C des variables x,y est:
+|   |   sx^2      ro*sx*sy |
+|   |                      |  et det(C) = (1-ro^2)*sx^2*sy^2
+|   | ro*sx*sy      sy^2   |
+| - La matrice inverse C^(-1) est:
+|   |   1/sx^2      -ro/(sx*sy) |
+|   |                           | * 1/(1-ro^2)
+|   | -ro/(sx*sy)      1/sy^2   |
+--
+*/
+/*
+++
+| - Remarque:
+| le sigma que l'on obtient quand on fait une coupe de la gaussienne 2D
+| en y=0 (ou x=0) est: SX0(y=0) = sx*sqrt(1-ro^2) different de sx
+|                      SY0(x=0) = sy*sqrt(1-ro^2) different de sy
+| La distribution qui correspond a des sigmas SX0,SY0
+| pour les coupes en y=0,x=0 de la gaussienne 2D serait:
+|   N*exp[-0.5*{ (dx/SX0)^2-2*ro/(SX0*SY0)*dx*dy+(dy/SY0)^2 }]
+| avec N = sqrt(1-ro^2)/(2Pi*SX0*SY0) et les variances
+| des variables x,y sont toujours
+|  sx=SX0/sqrt(1-ro^2), sy=SY0/sqrt(1-ro^2)
+--
+*/
+int NormCo(double *x,double *y
+          ,double mx,double my,double sx,double sy,double ro)
+{
+double a,b,sa;
+if( ro <= -1. || ro >= 1. ) return(1);
+LAB10:
+ b = drand01();
+ if ( b == 0. ) goto LAB10;
+b = sqrt(-2.*log(b));
+a = DeuxPi * drand01();
+sa = sin(a);
+
+*x = mx + sx*b*(sqrt(1.-ro*ro)*cos(a)+ro*sa);
+*y = my + sy*b*sa;
+
+return(0);
+}
+
+/*==========================================================================*/
+/*
+++
+  Titre	Exemple d'utilisation des aleatoires avec initialisation.
+--
+*/
+/*
+++
+|   #include "nbrandom.h"
+|   
+|   void main() {
+|   long i,ini=123456789;
+|   unsigned short seed[3];
+|   
+|   printf(" 1./ ==> test nitialisation par un long\n");
+|   Ini_Ranf_Quick(ini,1);
+|   for(i=0;i<10;i++) printf("%d  -> %f\n",i,ranf01());
+--
+*/
+/*
+++
+|   
+|   printf("\n 2./ ==> test initialisation par tableau de 3 unsigned short\n");
+|   Ini_Ranf_Quick(ini,1);
+|   for(i=0;i<5;i++) printf("%d  -> %f\n",i,ranf01());
+|   Get_Ranf(seed,1);
+|   for(i=5;i<10;i++) printf("%d  -> %f\n",i,ranf01());
+|   Ini_Ranf(seed,1);
+|   for(i=5;i<10;i++) printf("%d  -> %f\n",i,ranf01());
+|   Get_Ranf(seed,1);
+--
+*/
+/*
+++
+|   
+|   printf("\n 3./ ==> test initialisation automatique\n");
+|   Auto_Ini_Ranf(2);
+|   for(i=0;i<5;i++) printf("%d  -> %f\n",i,ranf01());
+|   i=0; while(i<10000000) i++;
+|   Auto_Ini_Ranf(2);
+|   for(i=0;i<5;i++) printf("%d  -> %f\n",i,ranf01());
+|   i=0; while(i<10000000) i++;
+|   Auto_Ini_Ranf(2);
+|   for(i=0;i<5;i++) printf("%d  -> %f\n",i,ranf01());
+|   }
+--
+*/
+/*
+++
+|    1./ ==> test initialisation par un long
+|   Ini_Ranf_Quick: 123456789
+|   0  -> 0.052468
+|   1  -> 0.025444
+|   2  -> 0.099272
+|   3  -> 0.436130
+|   4  -> 0.327740
+|   5  -> 0.821202
+|   6  -> 0.560493
+|   7  -> 0.018157
+|   8  -> 0.872758
+|   9  -> 0.652496
+--
+*/
+/*
+++
+|   
+|    2./ ==> test initialisation par tableau de 3 unsigned short
+|   Ini_Ranf_Quick: 123456789
+|   0  -> 0.052468
+|   1  -> 0.025444
+|   2  -> 0.099272
+|   3  -> 0.436130
+|   4  -> 0.327740
+--
+*/
+/*
+++
+|   Get_Ranf: 36117 51106 21478
+|   5  -> 0.821202
+|   6  -> 0.560493
+|   7  -> 0.018157
+|   8  -> 0.872758
+|   9  -> 0.652496
+--
+*/
+/*
+++
+|   Ini_Ranf: 36117 51106 21478
+|   5  -> 0.821202
+|   6  -> 0.560493
+|   7  -> 0.018157
+|   8  -> 0.872758
+|   9  -> 0.652496
+|   Get_Ranf: 16576 62373 42761
+--
+*/
+/*
+++
+|   
+|    3./ ==> test initialisation automatique
+|   Auto_Ini_Ranf: date 887117206 s 868138 10^-6 sec seed=826006868:
+|   ... njours=10267 nj23=9 buf=826006868.13800001
+|   Ini_Ranf_Quick: 826006868
+|   0  -> 0.798860
+|   1  -> 0.342478
+|   2  -> 0.401300
+|   3  -> 0.442912
+|   4  -> 0.170912
+--
+*/
+/*
+++
+|   Auto_Ini_Ranf: date 887117207 s 188779 10^-6 sec seed=826007188:
+|   ... njours=10267 nj23=9 buf=826007188.77900004
+|   Ini_Ranf_Quick: 826007188
+|   0  -> 0.455599
+|   1  -> 0.811427
+|   2  -> 0.703880
+|   3  -> 0.409569
+|   4  -> 0.390399
+--
+*/
+/*
+++
+|   Auto_Ini_Ranf: date 887117207 s 489750 10^-6 sec seed=826007489:
+|   ... njours=10267 nj23=9 buf=826007489.75
+|   Ini_Ranf_Quick: 826007489
+|   0  -> 0.567094
+|   1  -> 0.893156
+|   2  -> 0.975995
+|   3  -> 0.531331
+|   4  -> 0.834354
+--
+*/
+/*==========================================================================*/
+
+/*==========================================================================*/
+/* 
+++ 
+  Module 	Tirages aleatoires selon une fonction (C)
+  Lib	LibsUtil
+  include	nbrandom.h
+--
+*/
+/*
+++
+  TIREALEA *init_tirage_alea(int nbin,double xmin,double xmax,double (*fonc) (double))
+	Initialise la structure qui va permettre le tirage aleatoire
+	d'un nombre compris entre xmin et xmax selon la
+	distribution fonc (histo de nbin bins)
+--
+*/
+TIREALEA *init_tirage_alea(int nbin,double xmin,double xmax,double (*fonc) (double))
+{
+int sof,i;
+double x;
+struct tirage_alea *t;
+
+if ( xmax-xmin<0.) return(NULL);
+
+if(nbin<=3) nbin=50;
+
+sof = sizeof(struct tirage_alea);
+if( (t = (struct tirage_alea*)malloc(sof) ) == NULL ) {
+  printf("impossible d'allouer *tirage_alea par malloc \n");
+  return(NULL);
+}
+
+t->Nbin=nbin; t->Min=xmin; t->Max=xmax; t->Lbin=(xmax-xmin) /nbin;
+
+sof = nbin * sizeof(double);
+if( (t->Tab = (double*)malloc(sof) ) == NULL ) {
+  printf("impossible d'allouer *tirage_alea.Tab par malloc \n");
+  return(NULL);
+}
+
+x = xmin + .5*t->Lbin;
+t->Tab[0] =  fonc(x);
+for(i=1;i<nbin;i++) {
+  x = xmin + (i+.5)*t->Lbin;
+  t->Tab[i] = t->Tab[i-1] + fonc(x);
+}
+
+for(i=0;i<nbin-1;i++)  t->Tab[i] /= t->Tab[nbin-1];
+t->Tab[nbin-1] = 1.;
+
+return(t);
+}
+
+/*==========================================================================*/
+/*
+++
+  double tirage_alea( TIREALEA *alea )
+	tirage aleatoire d'un nombre compris entre xmin et xmax
+	selon la fonction fonc (cf init_tirage_alea).
+--
+*/
+double tirage_alea( TIREALEA *alea )
+{ 
+int i,ibin = -1;
+double z,t1,t2,x1,x2,t;
+
+z=drand01();
+/* protections z<=0 ou z>=1 */
+if( z <= 0. ) return ( alea->Min );
+if( z >= 1. ) return ( alea->Max );
+/* cas z <= tab[0] */
+if(z <= alea->Tab[0]) {
+  t = alea->Min + (alea->Lbin/2.)/alea->Tab[0] * z;
+  return (t);
+}
+
+/* recherche du premier bin plus grand que z */
+for(i=0;i<alea->Nbin;i++) {
+  ibin=i;
+  if ( z < alea->Tab[i] ) break;
+}
+
+/* extrapolation pour trouver la valeur du tirage aleatoire */
+if( ibin == alea->Nbin-1 ) ibin--;
+t1=alea->Tab[ibin];
+x1 = alea->Min + (ibin+0.5) * alea->Lbin;
+t2=alea->Tab[ibin+1];
+x2 = x1 + alea->Lbin;
+t = x1 + (x2-x1)/(t2-t1) *(z-t1);
+if ( t < alea->Min ) t = alea->Min;
+if ( t > alea->Max ) t = alea->Max;
+return(t);
+}
+
+/*==========================================================================*/
+/*
+++
+  int end_tirage_alea( TIREALEA *alea )
+	De-allocation de la structure qui a permis le tirage aleatoire.
+--
+*/
+int end_tirage_alea( TIREALEA *alea )
+{ 
+if ( alea != NULL ) { free(alea); return(0);}
+  else return(-1);
+}
Index: /tags/V_Fev00/SophyaLib/NTools/nbrandom.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbrandom.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbrandom.h	(revision 752)
@@ -0,0 +1,56 @@
+/* fonctions pour generateurs aleatoires */
+/*                         cmv  23/06/94 */
+
+#ifndef NBRANDOM_H_SEEN
+#define NBRANDOM_H_SEEN
+
+#include "machdefs.h"
+#include <stdlib.h>
+#ifdef __MWERKS__
+#include "unixmac.h"
+#endif
+
+#define frand01() ( (float) drand48() )
+#define drand01() ( drand48() )
+#define ranf01() drand01()
+
+#define frandpm1() ( 2. * frand01() - 1.)
+#define drandpm1() ( 2. * drand01() - 1.)
+#define ranfpm1() drandpm1()
+
+struct tirage_alea {
+  int Nbin;
+  double Min,Max,Lbin;
+  double *Tab;
+};
+typedef struct tirage_alea TIREALEA;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void Ini_Ranf_Quick(long seed_val, int lp);
+void Ini_Ranf(unsigned short seed_16v[3], int lp);
+void Get_Ranf(unsigned short seed_16v[3], int lp);
+void Auto_Ini_Ranf(int lp);
+
+void SetGauRange(double range);
+float NorRand1(void);
+double GauRnd1(double am, double s);
+float NorRand(void);
+double GauRnd(double am, double s);
+int NormCo(double *a,double *b
+          ,double mx,double my,double sx,double sy,double ro);
+void NormGau(double *x,double *y
+            ,double mx,double my,double sa,double sb,double teta);
+
+TIREALEA *init_tirage_alea(int nbin,double xmin,double xmax,double (*fonc) (double));
+double tirage_alea(TIREALEA *alea);
+int end_tirage_alea(TIREALEA *alea);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/nbtri.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbtri.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbtri.c	(revision 752)
@@ -0,0 +1,785 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "nbtri.h"
+
+/* 
+++ 
+  Module	Tri de tableaux (C)
+  Lib	LibsUtil
+  include	nbtri.h
+
+	Tri de tableaux et indexation.
+--
+*/
+
+/*=========================================================================*/
+/*
+++
+  void HeapSort(int n,double *ra_int)
+	On reordonne par ordre numerique croissant
+	le tableau ra_int[n]: Numerical Recipes mode C.
+--
+*/
+void HeapSort(int n,double *ra_int)
+{
+   int l,j,ir,i;
+   double rra,*ra;
+
+   /* attention, Numerical recipes prend des tableaux de 1 a n on remet
+      de 0 a n-1 en decramentant le pointeur du tableau d'entree*/
+   ra = ra_int-1;
+
+   l=(n >> 1)+1;
+   ir=n;
+   for (;;) {
+      if (l > 1)
+         rra=ra[--l];
+      else {
+         rra=ra[ir];
+         ra[ir]=ra[1];
+         if (--ir == 1) {
+            ra[1]=rra;
+            return;
+         }
+      }
+      i=l;
+      j=l << 1;
+      while (j <= ir) {
+         if (j < ir && ra[j] < ra[j+1]) ++j;
+         if (rra < ra[j]) {
+            ra[i]=ra[j];
+            j += (i=j);
+         }
+         else j=ir+1;
+      }
+      ra[i]=rra;
+   }
+}
+
+/*=========================================================================*/
+/*
+++
+  void HeapSortF(int n,float *ra_int)
+	On reordonne par ordre numerique croissant
+	le tableau ra_int[n]: Numerical Recipes mode C.
+--
+*/
+void HeapSortF(int n,float *ra_int)
+{
+   int l,j,ir,i;
+   float rra,*ra;
+
+   /* attention, Numerical reciepes prend des tableaux de 1 a n on remet
+      de 0 a n-1 en decramentant le pointeur du tableau d'entree*/
+   ra = ra_int-1;
+
+   l=(n >> 1)+1;
+   ir=n;
+   for (;;) {
+      if (l > 1)
+         rra=ra[--l];
+      else {
+         rra=ra[ir];
+         ra[ir]=ra[1];
+         if (--ir == 1) {
+            ra[1]=rra;
+            return;
+         }
+      }
+      i=l;
+      j=l << 1;
+      while (j <= ir) {
+         if (j < ir && ra[j] < ra[j+1]) ++j;
+         if (rra < ra[j]) {
+            ra[i]=ra[j];
+            j += (i=j);
+         }
+         else j=ir+1;
+      }
+      ra[i]=rra;
+   }
+}
+
+/*=========================================================================*/
+/*
+++
+  void HeapSortF2(int n,float *ra_int,float *ra2_int)
+	On reordonne par ordre numerique croissant
+	le tableau ra_int[n] et ra2_int en parralelle.
+	Numerical Recipes mode C.
+--
+*/
+void HeapSortF2(int n,float *ra_int,float *ra2_int)
+{
+   int l,j,ir,i;
+   float rra,rra2,*ra,*ra2;
+
+   /* attention, Numerical reciepes prend des tableaux de 1 a n on remet
+      de 0 a n-1 en decramentant le pointeur du tableau d'entree*/
+   ra = ra_int-1;
+   ra2 = ra2_int-1;
+
+   l=(n >> 1)+1;
+   ir=n;
+   for (;;) {
+      if (l > 1)
+        {rra=ra[--l];   rra2=ra2[l];}
+      else {
+         rra=ra[ir];    rra2=ra2[ir];
+         ra[ir]=ra[1];   ra2[ir]=ra2[1];
+         if (--ir == 1) {
+            ra[1]=rra;  ra2[1]=rra2;
+            return;
+         }
+      }
+      i=l;
+      j=l << 1;
+      while (j <= ir) {
+         if (j < ir && ra[j] < ra[j+1]) ++j;
+         if (rra < ra[j]) {
+            ra[i]=ra[j];  ra2[i]=ra2[j];
+            j += (i=j);
+         }
+         else j=ir+1;
+      }
+      ra[i]=rra;   ra2[i]=rra2;
+   }
+}
+
+/*=========================================================================*/
+/*
+++
+  int_4 tri_double ( double *tab, int_4 *indx,int_4 N)
+	Methode de tri sans finesse (double boucles).
+| entree : tab -> tableau de double de longueur N (0 a N-1 )
+| sortie : indx -> tableau d'entiers de longueur N : la case i   
+|          contient le classement du ieme element dans tab  
+| Retourne:  0 si tri impossible
+|            1 si tri reussi
+--
+*/
+int_4 tri_double ( double *tab, int_4 *indx,int_4 N)
+{
+int_4 i,j,k;
+
+if (N<=0) return (-1);
+
+for (i=0; i<N ; i++) indx[i]=i;
+if (N==1) return (N);
+
+/* classement dans l'ordre croissant */
+for (i=1; i< N ; i++)
+  { 
+
+  if ( *(tab+indx[i]) < *(tab+indx[i-1]) )
+    { 
+     k = indx[i-1];
+     indx[i-1] = indx[i];
+     indx[i] = k;
+
+     if ( i > 1 )
+        for (j=i ; j>=1 ; j--)
+          { if ( *(tab+indx[j]) < *(tab+indx[j-1]) )
+            { 
+            k = indx[j-1];
+            indx[j-1] = indx[j];
+            indx[j] = k;
+    } } } }
+
+return (N) ;
+}
+
+/*=========================================================================*/
+/*
+++
+  int_4 tri_float ( float *tab, int_4 *indx,int_4 N)
+	Methode de tri sans finesse (double boucles).
+| entree : tab -> tableau de flottant de longueur N (0 a N-1 )
+| sortie : indx -> tableau d'entiers de longueur N : la case i   
+|          contient le classement du ieme element dans tab  
+| Retourne:  0 si tri impossible
+|            1 si tri reussi
+--
+*/
+int_4 tri_float ( float *tab, int_4 *indx,int_4 N)
+{
+int_4 i,j,k;
+
+if (N<=0) return (-1);
+
+for (i=0; i<N ; i++) indx[i]=i;
+if (N==1) return (N);
+
+/* classement dans l'ordre croissant */
+for (i=1; i< N ; i++)
+  { 
+
+  if ( *(tab+indx[i]) < *(tab+indx[i-1]) )
+    { 
+     k = indx[i-1];
+     indx[i-1] = indx[i];
+     indx[i] = k;
+
+     if ( i > 1 )
+        for (j=i ; j>=1 ; j--)
+          { if ( *(tab+indx[j]) < *(tab+indx[j-1]) )
+            { 
+            k = indx[j-1];
+            indx[j-1] = indx[j];
+            indx[j] = k;
+    } } } }
+
+return (N) ;
+}
+
+/*=========================================================================*/
+/*
+++
+  int_4 tri_entier ( int_4 *tab,int_4 *indx,int_4 N)
+	Methode de tri sans finesse (double boucles).
+| entree : tab -> tableau d'entiers de longueur N (0 a N-1 )
+| sortie : indx -> tableau d'entiers de longueur N : la case i   
+|          contient le classement du ieme element dans tab  
+| Retourne:  0 si tri impossible
+|            1 si tri reussi
+--
+*/
+int_4 tri_entier ( int_4 *tab,int_4 *indx,int_4 N)
+{
+int_4 i,j,k;
+
+if (N<=0) return (-1);
+
+for (i=0; i<N ; i++) indx[i]=i;
+if (N==1) return (N);
+
+/* classement dans l'ordre croissant */
+for (i=1; i< N ; i++)
+  { 
+
+  if ( *(tab+indx[i]) < *(tab+indx[i-1]) )
+    { 
+     k = indx[i-1];
+     indx[i-1] = indx[i];
+     indx[i] = k;
+
+     if ( i > 1 )
+        for (j=i ; j>=1 ; j--)
+          { if ( *(tab+indx[j]) < *(tab+indx[j-1]) )
+            { 
+            k = indx[j-1];
+            indx[j-1] = indx[j];
+            indx[j] = k;
+    } } } }
+
+return (N) ;
+}
+
+/*=========================================================================*/
+/*
+++
+  int_4 tri_rapide_I (int_4 *datum,int_4 *index,int_4 N)
+	algorythme de tri rapide
+	( p114-119 THE ART OF COMPUTER PROGRAMMING, vol. 3 SORTING AND
+	SEARCHING de D.E. Knuth)
+| datum  ( entree/sortie ) -> vecteur de dimension N contenant des ENTIERS
+|        desordonnes en entree. Ces elements ressortent ordonnes.
+| index  ( sortie ) -> vecteur de dimension N contenant des entiers.
+|        Le contenu de la case i de index nous indique la place
+|        du ieme element du datum originel.
+| tri_rapide = -1 si echec, 1 si reussite de l'operation
+--
+*/
+int_4 tri_rapide_I (int_4 *datum,int_4 *index,int_4 N)
+{
+/* 14 = nb max d'entrees que la pile (stack) peut contenir. Ce 14 limite la longueur 
+             maximale possible pour les vecteurs a 32 768 ( = 2**15 ) */
+
+int_4 stklo[14], stkhi[14], hi, nstak, i, limlo, limhi, lo, ikey;
+int_4 dkey;
+
+/* initialisations */
+
+for (i=0; i<=N-1 ;i++)  index[i]=i;
+
+nstak=0;
+limlo=0; limhi=N-1;
+
+grande_boucle:
+  dkey = *(datum+limlo);
+  ikey = *(index+limlo);
+
+/* compare tous les elements d'un ss-vecteur entre limlo et limhi avec la donnee-cle courante */
+
+  lo=limlo; hi=limhi;
+  
+sous_boucle_1:
+  if ( lo == hi ) goto lo_egal_hi;
+
+  if ( *(datum+hi) <= dkey ) goto remplacement_lo;
+  hi = hi - 1;
+
+/* le pointeur  hi doit pointer une donnee plus petite que la cle qui va etre remplacer */
+
+  goto sous_boucle_1;
+
+remplacement_lo:
+  *(datum+lo) = *(datum+hi);
+  *(index+lo) = *(index+hi);
+  lo = lo + 1;
+  
+sous_boucle_2:
+  if ( lo == hi ) goto lo_egal_hi;
+
+  if ( *(datum+lo) >= dkey ) goto remplacement_hi;
+
+  lo = lo + 1;
+  goto sous_boucle_2;
+
+remplacement_hi:
+  *(datum+hi) = *(datum+lo);
+  *(index+hi) = *(index+lo);
+  hi = hi - 1;
+
+/* le pointeur lo doit pointer une donnee plus grande que la cle qui va etre remplacer */
+
+  goto sous_boucle_1;
+
+lo_egal_hi:
+
+/* lo et hi sont egaux, et pointent sur une valeur qui va etre remplacer. Tant que toutes les valeurs sous ce point sont inferieures a la cle et que toutes les valeurs apres ce point sont superieures a la cle, c'est la que nous remettrons la cle dans le vecteur */
+
+  *(datum+lo) = dkey;
+  *(index+lo) = ikey;
+
+/* A ce point du ss-prog. toutes les donnees entre limlo et lo-1 inclus sont inferieurs a datum(lo), et toutes les donnes entre lo+1 et limhi sont superieures a datum(lo)  
+   Si les deux ss-tableaux ne contiennent pas plus d'un element, on prend l'intervale le plus recent de la pile ( si le stack est vide c'est fini ). Si le plus grand des deux ss-tableaux contient plus d'un element et si le plus petit contient au plus un element, alors on oublie le plus petit et on reduit l'autre. Si le plus petit ss-tableau contient au moins 2 elements, alors on place le plus grand ss-tableau dans la pile et on processe le ss-tableau.  */
+  
+  if ( (limhi-lo) > (lo-limlo) ) goto cas_1;
+
+/* cas 1 : le ss-tableau inferieur est plus long. Si il contient un element au plus, alors on prend l'intervalle du stack le plus recent, on le ramene et on travaille dessus */
+
+  if ( (lo-limlo) <= 1) goto test_fin;
+
+/* si le ss-tableau superieur ( le + court ss-tableau ) contient  un element au plus alors on processe le  ss-tableau inferieur ( le + long), mais si le ss-tableau superieur contient plus d'un element, alors on place le  ss-tableau inferieur ( le + long) sur la pile et on processe le ss-tableau superieur. */
+
+  if ( (limhi-lo) >= 2) goto cas_1b;
+
+/* cas 1a : si le ss-tableau superieur ( le + court ss-tableau ) contient  un element au plus alors on revient en arriere et on agit sur le  ss-tableau inferieur ( le + long) */
+
+  limhi=lo-1;
+  goto grande_boucle;
+
+/* cas 1b :  si le ss-tableau superieur ( le + court ss-tableau ) contient plus d'un element, alors on place le  ss-tableau inferieur ( le + long) sur la pile et on processe le ss-tableau superieur. */
+
+cas_1b:
+  nstak=nstak+1;
+  *(stklo+nstak)=limlo;
+  *(stkhi+nstak)=lo-1;
+  limlo=lo+1;
+  goto grande_boucle;
+ 
+/* cas 2 : le ss-tableau superieur est plus long, si il contient  un element au plus alors on agit sur l'intervalle le plus recent de la pile. */
+
+cas_1:
+  if ( (limhi-lo) <= 1) goto test_fin;
+
+/* si le ss-tableau inferieur ( le + court ss-tableau ) contient  un element au plus alors on processe le  ss-tableau superieur ( le + long), mais si le ss-tableau inferieur contient plus d'un element, alors on place le  ss-tableau superieur ( le + long) sur la pile et on processe le ss-tableau inferieur. */
+
+   if ( (lo-limlo) >= 2) goto cas_2b;
+
+/*  cas 2a : si le ss-tableau inferieur ( le + court ss-tableau ) contient  un element au plus alors on revient en arriere et on agit sur le  ss-tableau superieur ( le + long) */
+
+  limlo=lo+1;
+  goto grande_boucle;
+  
+/* cas 2b :  si le ss-tableau inferieur ( le + court ss-tableau ) contient plus d'un element, alors on place le  ss-tableau superieur ( le + long) sur la pile et on processe le ss-tableau inferieur. */
+
+cas_2b:
+  nstak=nstak+1;
+  *(stklo+nstak)=lo+1;
+  *(stkhi+nstak)=limhi;
+  limlo=lo-1;
+  goto grande_boucle;
+   
+/* on prend l'intervalle le plus recent de la pile. Si le stack est vide, c'est fini !!! */
+        
+test_fin:
+  if (nstak <= 0) return (1);
+  limlo = *(stklo+nstak);
+  limhi = *(stkhi+nstak);
+  nstak=nstak-1;
+  goto grande_boucle;
+
+}
+
+/*=========================================================================*/
+/*
+++
+  int_4 tri_rapide_F (float *datum,int_4 *index,int_4 N)
+	Idem tri_rapide_I mais pour un tableau de flottants
+	 REMPLI avec des ENTIERS.
+--
+*/
+int_4 tri_rapide_F (float *datum,int_4 *index,int_4 N)
+{
+/* ATTENTION, Ce programme tri un tableau de flottants REMPLI avec des ENTIERS!!!!!
+  14 = nb max d'entrees que la pile (stack) peut contenir. Ce 14 limite la longueur 
+             maximale possible pour les vecteurs a 32 768 ( = 2**15 ) */
+
+int_4 stklo[14], stkhi[14], hi, nstak, i, limlo, limhi, lo, ikey;
+float dkey;
+
+/* initialisations */
+
+for (i=0; i<=N-1 ; i++) index[i]=i;
+nstak=0;
+limlo=0; limhi=N-1;
+
+grande_boucle:
+  dkey = *(datum+limlo);
+  ikey = *(index+limlo);
+
+/* compare tous les elements d'un ss-vecteur entre limlo et limhi avec la donnee-cle courante */
+
+  lo=limlo; hi=limhi;
+  
+sous_boucle_1:
+  if ( lo == hi ) goto lo_egal_hi;
+
+  if ( *(datum+hi) <= dkey ) goto remplacement_lo;
+  hi = hi - 1;
+
+/* le pointeur  hi doit pointer une donnee plus petite que la cle qui va etre remplacer */
+
+  goto sous_boucle_1;
+
+remplacement_lo:
+  *(datum+lo) = *(datum+hi);
+  *(index+lo) = *(index+hi);
+  lo = lo + 1;
+  
+sous_boucle_2:
+  if ( lo == hi ) goto lo_egal_hi;
+
+  if ( *(datum+lo) >= dkey ) goto remplacement_hi;
+
+  lo = lo + 1;
+  goto sous_boucle_2;
+
+remplacement_hi:
+  *(datum+hi) = *(datum+lo);
+  *(index+hi) = *(index+lo);
+  hi = hi - 1;
+
+/* le pointeur lo doit pointer une donnee plus grande que la cle qui va etre remplacer */
+
+  goto sous_boucle_1;
+
+lo_egal_hi:
+
+/* lo et hi sont egaux, et pointent sur une valeur qui va etre remplacer. Tant que toutes les valeurs sous ce point sont inferieures a la cle et que toutes les valeurs apres ce point sont superieures a la cle, c'est la que nous remettrons la cle dans le vecteur */
+
+  *(datum+lo) = dkey;
+  *(index+lo) = ikey;
+
+/* A ce point du ss-prog. toutes les donnees entre limlo et lo-1 inclus sont inferieurs a datum(lo), et toutes les donnes entre lo+1 et limhi sont superieures a datum(lo)  
+   Si les deux ss-tableaux ne contiennent pas plus d'un element, on prend l'intervale le plus recent de la pile ( si le stack est vide c'est fini ). Si le plus grand des deux ss-tableaux contient plus d'un element et si le plus petit contient au plus un element, alors on oublie le plus petit et on reduit l'autre. Si le plus petit ss-tableau contient au moins 2 elements, alors on place le plus grand ss-tableau dans la pile et on processe le ss-tableau.  */
+  
+  if ( (limhi-lo) > (lo-limlo) ) goto cas_1;
+
+/* cas 1 : le ss-tableau inferieur est plus long. Si il contient un element au plus, alors on prend l'intervalle du stack le plus recent, on le ramene et on travaille dessus */
+
+  if ( (lo-limlo) <= 1) goto test_fin;
+
+/* si le ss-tableau superieur ( le + court ss-tableau ) contient  un element au plus alors on processe le  ss-tableau inferieur ( le + long), mais si le ss-tableau superieur contient plus d'un element, alors on place le  ss-tableau inferieur ( le + long) sur la pile et on processe le ss-tableau superieur. */
+
+  if ( (limhi-lo) >= 2) goto cas_1b;
+
+/* cas 1a : si le ss-tableau superieur ( le + court ss-tableau ) contient  un element au plus alors on revient en arriere et on agit sur le  ss-tableau inferieur ( le + long) */
+
+  limhi=lo-1;
+  goto grande_boucle;
+
+/* cas 1b :  si le ss-tableau superieur ( le + court ss-tableau ) contient plus d'un element, alors on place le  ss-tableau inferieur ( le + long) sur la pile et on processe le ss-tableau superieur. */
+
+cas_1b:
+  nstak=nstak+1;
+  *(stklo+nstak)=limlo;
+  *(stkhi+nstak)=lo-1;
+  limlo=lo+1;
+  goto grande_boucle;
+ 
+/* cas 2 : le ss-tableau superieur est plus long, si il contient  un element au plus alors on agit sur l'intervalle le plus recent de la pile. */
+
+cas_1:
+  if ( (limhi-lo) <= 1) goto test_fin;
+
+/* si le ss-tableau inferieur ( le + court ss-tableau ) contient  un element au plus alors on processe le  ss-tableau superieur ( le + long), mais si le ss-tableau inferieur contient plus d'un element, alors on place le  ss-tableau superieur ( le + long) sur la pile et on processe le ss-tableau inferieur. */
+
+   if ( (lo-limlo) >= 2) goto cas_2b;
+
+/*  cas 2a : si le ss-tableau inferieur ( le + court ss-tableau ) contient  un element au plus alors on revient en arriere et on agit sur le  ss-tableau superieur ( le + long) */
+
+  limlo=lo+1;
+  goto grande_boucle;
+  
+/* cas 2b :  si le ss-tableau inferieur ( le + court ss-tableau ) contient plus d'un element, alors on place le  ss-tableau superieur ( le + long) sur la pile et on processe le ss-tableau inferieur. */
+
+cas_2b:
+  nstak=nstak+1;
+  *(stklo+nstak)=lo+1;
+  *(stkhi+nstak)=limhi;
+  limlo=lo-1;
+  goto grande_boucle;
+   
+/* on prend l'intervalle le plus recent de la pile. Si le stack est vide, c'est fini !!! */
+        
+test_fin:
+  if (nstak <= 0) return (1);
+  limlo = *(stklo+nstak);
+  limhi = *(stkhi+nstak);
+  nstak=nstak-1;
+  goto grande_boucle;
+
+}
+
+/*===================================================================================*/
+/*
+++
+  int qSort_Float(const void *a1,const void *a2)
+	Fonction de tri de `float' a utiliser dans qsort.
+--
+*/
+int qSort_Float(const void *a1,const void *a2)
+{
+if( *((float *) a1) < *((float *) a2) ) return(-1);
+if( *((float *) a1) > *((float *) a2) ) return( 1);
+return(0);
+}
+
+/*===================================================================================*/
+/*
+++
+  int qSort_Dble(const void *a1,const void *a2)
+	Fonction de tri de `double' a utiliser dans qsort.
+--
+*/
+int qSort_Dble(const void *a1,const void *a2)
+{
+if( *((double *) a1) < *((double *) a2) ) return(-1);
+if( *((double *) a1) > *((double *) a2) ) return( 1);
+return(0);
+}
+
+/*===================================================================================*/
+/*
+++
+  int qSort_Int(const void  *a1,const void  *a2)
+	Fonction de tri de `int' a utiliser dans qsort.
+--
+*/
+int qSort_Int(const void  *a1,const void  *a2)
+{
+if( *((int *) a1) < *((int *) a2) ) return(-1);
+if( *((int *) a1) > *((int *) a2) ) return( 1);
+return(0);
+}
+
+/*===================================================================================*/
+/*
+++
+  int qSort_Ushort(const void  *a1,const void  *a2)
+	Fonction de tri de `unsigned short' a utiliser dans qsort.
+--
+*/
+int qSort_Ushort(const void  *a1,const void  *a2)
+{
+if( *((unsigned short *) a1) < *((unsigned short *) a2) ) return(-1);
+if( *((unsigned short *) a1) > *((unsigned short *) a2) ) return( 1);
+return(0);
+}
+
+/*===================================================================================*/
+/*
+++
+  int qSort_Short(const void  *a1,const void  *a2)
+	Fonction de tri de `short' a utiliser dans qsort.
+--
+*/
+int qSort_Short(const void  *a1,const void  *a2)
+{
+if( *((short *) a1) < *((short *) a2) ) return(-1);
+if( *((short *) a1) > *((short *) a2) ) return( 1);
+return(0);
+}
+
+/*===================================================================================*/
+/*
+++
+  void IndexR4(int_4 n, float* arr_c, int_4* indx_c)
+	Indexes an array arr[1..n], i.e., outputs the array indx[1..n]
+	such that arr[indx[j]] is in ascending order for j=1,2,,N.
+	The input quantities n and arr are not changed.
+--
+*/
+#define SWAP_INDEXR4(a,b) itemp=(a);(a)=(b);(b)=itemp;
+#define M 7
+#define NSTACK 50
+void IndexR4(int_4 n, float* arr_c, int_4* indx_c)
+/* encore du Num.Rec. avec tableaux commencant a 1. */
+{
+        float *arr; int_4 *indx;
+	int_4 i,indxt,ir=n,itemp,j,k,l=1;
+	int_4 jstack=0;
+	float a;
+        int_4 istack[NSTACK+1];
+
+        arr = arr_c-1;
+        indx = indx_c-1;
+
+	for (j=1;j<=n;j++) indx[j]=j;
+	for (;;) {
+		if (ir-l < M) {
+			for (j=l+1;j<=ir;j++) {
+				indxt=indx[j];
+				a=arr[indxt];
+				for (i=j-1;i>=1;i--) {
+					if (arr[indx[i]] <= a) break;
+					indx[i+1]=indx[i];
+				}
+				indx[i+1]=indxt;
+			}
+			if (jstack == 0) break;
+			ir=istack[jstack--];
+			l=istack[jstack--];
+		} else {
+			k=(l+ir) >> 1;
+			SWAP_INDEXR4(indx[k],indx[l+1]);
+			if (arr[indx[l+1]] > arr[indx[ir]]) {
+				SWAP_INDEXR4(indx[l+1],indx[ir])
+			}
+			if (arr[indx[l]] > arr[indx[ir]]) {
+				SWAP_INDEXR4(indx[l],indx[ir])
+			}
+			if (arr[indx[l+1]] > arr[indx[l]]) {
+				SWAP_INDEXR4(indx[l+1],indx[l])
+			}
+			i=l+1;
+			j=ir;
+			indxt=indx[l];
+			a=arr[indxt];
+			for (;;) {
+				do i++; while (arr[indx[i]] < a);
+				do j--; while (arr[indx[j]] > a);
+				if (j < i) break;
+				SWAP_INDEXR4(indx[i],indx[j])
+			}
+			indx[l]=indx[j];
+			indx[j]=indxt;
+			jstack += 2;
+			if (jstack > NSTACK) {
+                          printf("NSTACK too small in indexx. %d>%d",jstack,NSTACK);
+                          exit(-1);
+			}
+			if (ir-i+1 >= j-l) {
+				istack[jstack]=ir;
+				istack[jstack-1]=i;
+				ir=j-1;
+			} else {
+				istack[jstack]=j-1;
+				istack[jstack-1]=l;
+				l=i;
+			}
+		}
+	}
+}
+#undef SWAP_INDEXR4
+#undef M
+#undef NSTACK
+
+/*===================================================================================*/
+/*
+++
+  void IndexR8(int_4 n, double* arr_c, int_4* indx_c)
+	Indexes an array arr[1..n], i.e., outputs the array indx[1..n]
+	such that arr[indx[j]] is in ascending order for j=1,2,,N.
+	The input quantities n and arr are not changed.
+--
+*/
+#define SWAP_INDEXR8(a,b) itemp=(a);(a)=(b);(b)=itemp;
+#define M 7
+#define NSTACK 50
+void IndexR8(int_4 n, double* arr_c, int_4* indx_c)
+/* encore du Num.Rec. avec tableaux commencant a 1. */
+{
+        double *arr; int_4 *indx;
+	int_4 i,indxt,ir=n,itemp,j,k,l=1;
+	int_4 jstack=0;
+	double a;
+        int_4 istack[NSTACK+1];
+
+        arr = arr_c-1;
+        indx = indx_c-1;
+
+	for (j=1;j<=n;j++) indx[j]=j;
+	for (;;) {
+		if (ir-l < M) {
+			for (j=l+1;j<=ir;j++) {
+				indxt=indx[j];
+				a=arr[indxt];
+				for (i=j-1;i>=1;i--) {
+					if (arr[indx[i]] <= a) break;
+					indx[i+1]=indx[i];
+				}
+				indx[i+1]=indxt;
+			}
+			if (jstack == 0) break;
+			ir=istack[jstack--];
+			l=istack[jstack--];
+		} else {
+			k=(l+ir) >> 1;
+			SWAP_INDEXR8(indx[k],indx[l+1]);
+			if (arr[indx[l+1]] > arr[indx[ir]]) {
+				SWAP_INDEXR8(indx[l+1],indx[ir])
+			}
+			if (arr[indx[l]] > arr[indx[ir]]) {
+				SWAP_INDEXR8(indx[l],indx[ir])
+			}
+			if (arr[indx[l+1]] > arr[indx[l]]) {
+				SWAP_INDEXR8(indx[l+1],indx[l])
+			}
+			i=l+1;
+			j=ir;
+			indxt=indx[l];
+			a=arr[indxt];
+			for (;;) {
+				do i++; while (arr[indx[i]] < a);
+				do j--; while (arr[indx[j]] > a);
+				if (j < i) break;
+				SWAP_INDEXR8(indx[i],indx[j])
+			}
+			indx[l]=indx[j];
+			indx[j]=indxt;
+			jstack += 2;
+			if (jstack > NSTACK) {
+                          printf("NSTACK too small in indexx. %d>%d",jstack,NSTACK);
+                          exit(-1);
+			}
+			if (ir-i+1 >= j-l) {
+				istack[jstack]=ir;
+				istack[jstack-1]=i;
+				ir=j-1;
+			} else {
+				istack[jstack]=j-1;
+				istack[jstack-1]=l;
+				l=i;
+			}
+		}
+	}
+}
+#undef SWAP_INDEXR8
+#undef M
+#undef NSTACK
Index: /tags/V_Fev00/SophyaLib/NTools/nbtri.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/nbtri.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/nbtri.h	(revision 752)
@@ -0,0 +1,40 @@
+/* fonction de tri */
+/*    cmv 23/06/94 */
+
+#ifndef NBTRI_H_SEEN
+#define NBTRI_H_SEEN
+
+
+#include "machdefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void HeapSort(int n,double *ra_int);
+void HeapSortF(int n,float *ra_int);
+void HeapSortF2(int n,float *ra_int,float *ra2_int);
+
+int_4 tri_double ( double *tab, int_4 *indx,int_4 N);
+int_4 tri_float ( float *tab, int_4 *indx,int_4 N);
+int_4 tri_entier ( int_4 *tab,int_4 *indx,int_4 N);
+
+int_4 tri_rapide_I (int_4 *datum,int_4 *index,int_4 N);
+int_4 tri_rapide_F (float *datum,int_4 *index,int_4 N);
+
+int qSort_Float(const void *a1,const void *a2);
+int qSort_Dble(const void *a1,const void *a2);
+int qSort_Int(const void *a1,const void *a2);
+int qSort_Ushort(const void *a1,const void *a2);
+int qSort_Short(const void *a1,const void *a2);
+
+void IndexR4(int_4 n, float* arr_c, int_4* indx_c);
+void IndexR8(int_4 n, double* arr_c, int_4* indx_c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/ntupintf.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/ntupintf.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/ntupintf.cc	(revision 752)
@@ -0,0 +1,150 @@
+
+#include "ntupintf.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+//++
+// Class	NTupleInterface
+// Lib	Outils++ 
+// include	ntupintf.h
+//
+//	Interface permettant de construire des vues NTuples (tableau lignes-colonnes) 
+//	pour differents objets. Toutes les methodes ont une implementation par defaut. 
+//--
+
+//++
+// NTupleInterface()
+//	Constructeur.
+// virtual ~NTupleInterface()
+//	Destructeur
+// uint_4  NbLines() const 
+//	Nombre de lignes du tableau
+// uint_4  NbColumns() const 
+//	Nombre de colonnes du tableau
+// r_8 *  GetLineD(int n) const
+//	Renvoie un tableau avec le contenu de la ligne "n"
+// r_8	GetCell(int n, int k) const
+//	Renvoie le contenu de la cellule correspondant a la ligne "n"
+//	et colonne "k"
+// r_8  GetCell(int n, string const & nom) const
+//	Renvoie le contenu de la cellule correspondant a la ligne "n"
+//	pour la colonne identifiee par "nom"
+// string  GetCelltoString(int n, int k) const
+//	Renvoie le contenu de la cellule correspondant a la ligne "n"
+//	et colonne "k", sous forme de chaine de caracteres.
+// string  GetCell(int n, string const & nom) const
+//	Renvoie le contenu de la cellule correspondant a la ligne "n"
+//	pour la colonne identifiee par "nom", sous forme de chaine de caracteres.
+// void GetMinMax(int k, double& min, double& max)  const
+//	Renvoie la valeur mini et maxi de la colonne numero "k"
+// void	GetMinMax(string const & nom, double& min, double& max)
+//	Renvoie la valeur mini et maxi de la colonne identifiee par "nom"
+// int  ColumnIndex(string const & nom)  const
+//	Renvoie le numero de colonne identifiee par "nom". Renvoie -1 (negatif)
+//	si colonne "nom" n'existe pas.
+// string ColumnName(int k) const
+//	Renvoie le nom de la colonne numero "k"
+// string VarList_C(const char* nomx=NULL) const
+//	Renvoie une chaine avec les declarations "C" pour les
+//	variables avec les noms de colonnes
+// string  LineHeaderToString()
+//	Renvoie une chaine avec les noms de colonnes, utilisables pour l'impression
+// string  LineToString(int n)
+//	Renvoie une chaine avec le contenu de la ligne "n", utilisable pour l'impression
+//--
+
+/* --Methode-- */
+NTupleInterface::NTupleInterface()
+{
+}
+/* --Methode-- */
+NTupleInterface::~NTupleInterface()
+{
+}
+
+/* --Methode-- */
+uint_4 NTupleInterface::NbLines() const
+{
+return(0);
+}
+/* --Methode-- */
+uint_4 NTupleInterface::NbColumns() const
+{
+return(0);
+}
+
+/* --Methode-- */
+r_8 * NTupleInterface::GetLineD(int ) const
+{
+return(NULL);
+}
+
+/* --Methode-- */
+r_8 NTupleInterface::GetCell(int , int ) const
+{
+return(0.);
+}
+
+/* --Methode-- */
+r_8 NTupleInterface::GetCell(int n, string const & nom) const
+{
+return(GetCell(n, ColumnIndex(nom)));
+}
+
+string NTupleInterface::GetCelltoString(int n, int k) const
+{
+char strg[64];
+//sprintf(strg,"C%d= %g\n", k, GetCell(n, k));
+sprintf(strg,"%g\n", GetCell(n, k));
+return(strg);
+}
+
+string NTupleInterface::GetCelltoString(int n, string const & nom) const
+{
+return(GetCelltoString(n, ColumnIndex(nom)));
+}
+
+/* --Methode-- */
+void NTupleInterface::GetMinMax(int , double& min, double& max)   const
+{
+min = max = 0.;
+}
+
+/* --Methode-- */
+void NTupleInterface::GetMinMax(string const & , double& min, double& max)   const
+{
+min = max = 0.;
+}
+
+/* --Methode-- */
+int NTupleInterface::ColumnIndex(string const & nom)  const
+{
+return(-1);
+}
+
+/* --Methode-- */
+string NTupleInterface::ColumnName(int k) const
+{
+return("");
+}
+
+/* --Methode-- */
+string NTupleInterface::VarList_C(const char*) const
+{
+return("");
+}
+
+/* --Methode-- */
+string NTupleInterface::LineHeaderToString() const
+{
+return("");
+}
+
+/* --Methode-- */
+string NTupleInterface::LineToString(int ) const
+{
+return("");
+}
+
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/ntupintf.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/ntupintf.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/ntupintf.h	(revision 752)
@@ -0,0 +1,48 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Interface de type NTuple           Reza 05/99
+// LAL-IN2P3/CNRS               CEA-DAPNIA      
+
+#ifndef NTUPLEINTERFACE_H_SEEN
+#define NTUPLEINTERFACE_H_SEEN
+
+#include "machdefs.h"
+#include <string>
+
+class NTupleInterface {
+public:
+  			NTupleInterface(); 
+  virtual		~NTupleInterface();
+// Nombre de lignes du NTuple  (Nb d'entrees)  
+  virtual uint_4        NbLines() const ;
+// Nombre de colonnes (nb de variables)
+  virtual uint_4        NbColumns() const ;
+// La ligne numero n, sous forme d'un tableau de double
+  virtual r_8 *         GetLineD(int n) const ;
+// Cellule de la ligne n, colonne k
+  virtual r_8		GetCell(int n, int k) const ;
+// Cellule de la ligne n, colonne nom
+  virtual r_8		GetCell(int n, string const & nom) const ;
+// Cellule de la ligne n, colonne k, converti en chaine de caracteres
+  virtual string	GetCelltoString(int n, int k) const ;
+// Cellule de la ligne n, colonne nom, converti en chaine de caracteres
+  virtual string	GetCelltoString(int n, string const & nom) const ;
+// Min et Max pour la colonne k
+  virtual void		GetMinMax(int k, double& min, double& max)   const ; 
+// Min et Max pour la colonne nom
+  virtual void		GetMinMax(string const & nom, double& min, double& max)   const ;
+// Numero de colonne pour nom 
+  virtual int           ColumnIndex(string const & nom)  const ;
+// Nom de colonne numero k
+  virtual string        ColumnName(int k) const;
+// Declaration des variables style C
+  virtual string	VarList_C(const char* nomx=NULL) const ;
+// Entete et liste de variable, pouvant servir a l'impression
+  virtual string        LineHeaderToString() const;
+// Contenu de la ligne n, pouvant servir a l'impression
+  virtual string        LineToString(int n) const;  
+};
+
+
+#endif   /*  NTUPLEINTERFACE_H_SEEN  */
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/ntuple.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/ntuple.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/ntuple.cc	(revision 752)
@@ -0,0 +1,611 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "strutil.h"
+#include "perrors.h"
+#include "ntuple.h"
+
+
+#define BADVAL -1.e19
+#define LENNAME 8
+#define LENNAME1  (LENNAME+1)
+
+//++
+// Class	NTuple
+// Lib	Outils++ 
+// include	ntuple.h
+//
+//	Classe de ntuples
+//--
+//++
+// Links        Parents
+// PPersist
+// NTupleInterface
+//--
+
+/* --Methode-- */
+//++
+NTuple::NTuple()
+//
+//	Createur par defaut
+//--
+{
+mNVar = mNEnt = mBlk = mNBlk = 0;
+mVar = NULL;
+mVarD = NULL;
+mNames = NULL;
+mInfo = NULL;
+}
+
+
+//++
+NTuple::NTuple(int nvar, char** noms, int blk)
+//
+//	Createur d'un ntuple de `nvar' variables dont les
+//	noms sont dans le tableau de cahines de caracteres `noms'
+//	avec `blk' d'evenements par blocks.
+//--
+{
+mNVar = mNEnt = mBlk = mNBlk = 0;
+mVar = NULL;
+mVarD = NULL;
+mNames = NULL;
+mInfo = NULL;
+if (nvar <= 0)  THROW(sizeMismatchErr); 
+mNVar = nvar;
+mVar = new r_4[nvar];
+mVarD = new r_8[nvar];
+if (blk < 10) blk = 10;
+mBlk = blk;
+// On prend des noms de LENNAME char pour le moment
+mNames = new char[nvar*LENNAME1];
+r_4* pt = new r_4[nvar*blk];
+mNBlk = 1;
+mPtr.push_back(pt);
+int i;
+for(i=0; i<nvar; i++)
+  { strncpy(mNames+i*LENNAME1, noms[i], LENNAME);  
+  mNames[i*LENNAME1+LENNAME] = '\0'; }
+return;
+}
+
+//                                       cmv 8/10/99
+//++
+NTuple::NTuple(const NTuple& NT)
+//
+//	Createur par copie (clone).
+//--
+: mNVar(0), mNEnt(0), mBlk(0), mNBlk(0)
+, mVar(NULL), mVarD(NULL), mNames(NULL), mInfo(NULL)
+{
+if(NT.mNVar<=0) return; // cas ou NT est cree par defaut
+mNVar = NT.mNVar;
+mBlk = NT.mBlk;
+mVar = new r_4[NT.mNVar];
+mVarD = new r_8[NT.mNVar];
+mNames = new char[NT.mNVar*LENNAME1];
+
+int i;
+r_4* pt = new r_4[mNVar*mBlk];
+mNBlk = 1; mPtr.push_back(pt);
+
+for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i)); 
+
+if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
+
+if(NT.mNEnt<=0) return;
+for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
+
+return;
+}
+
+/* --Methode-- */
+//++
+NTuple::NTuple(char *flnm)
+//
+//	Createur lecture fichier ppersist.
+//--
+{
+mNVar = mNEnt = mBlk = mNBlk = 0;
+mVar = NULL;
+mVarD = NULL;
+mNames = NULL;
+mInfo = NULL;
+PInPersist s(flnm);
+ObjFileIO<NTuple> fiont(this);
+fiont.Read(s);
+}
+
+/* --Methode-- */
+NTuple::~NTuple()
+{
+Clean();
+}
+
+/* --Methode-- */
+void NTuple::Clean()
+{
+if (mVar) delete[] mVar;
+if (mVarD) delete[] mVarD;
+if (mNames)  delete[] mNames;
+if (mInfo) delete mInfo;
+int i;
+if(mNBlk>0) for(i=0; i<mNBlk; i++)  delete[] mPtr[i];
+mPtr.erase(mPtr.begin(), mPtr.end());
+mNVar = mNEnt = mBlk = mNBlk = 0;
+mVar = NULL;
+mVarD = NULL;
+mNames = NULL;
+mInfo = NULL;
+return;
+}
+
+/* --Methode--        cmv 08/10/99 */
+//++
+NTuple& NTuple::operator = (const NTuple& NT)
+//
+//	Operateur egal (clone).
+//--
+{
+if(this == &NT) return *this;
+Clean();
+if(NT.mNVar<=0) return *this; // cas ou NT est cree par defaut
+mNVar = NT.mNVar;
+mBlk = NT.mBlk;
+mVar = new r_4[NT.mNVar];
+mVarD = new r_8[NT.mNVar];
+mNames = new char[NT.mNVar*LENNAME1];
+
+int i;
+r_4* pt = new r_4[mNVar*mBlk];
+mNBlk = 1; mPtr.push_back(pt);
+
+for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i)); 
+
+if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
+
+if(NT.mNEnt<=0) return *this;
+for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
+
+// En fait il faudrait un createur par copie qui partage les donnees
+// quand l'objet est temporaire... trop complique A FAIRE !  cmv.
+return *this;
+}
+
+/* --Methode-- */
+//++
+void  NTuple::Fill(r_4* x)
+//
+//	Remplit le ntuple avec le tableau cd reels `x'.
+//--
+{
+int numb = mNEnt/mBlk;
+if (numb >= mNBlk) {
+  r_4* pt = new r_4[mNVar*mBlk];
+  mNBlk++;
+  mPtr.push_back(pt);
+}
+int offb = mNEnt-numb*mBlk;
+memcpy((mPtr[numb]+offb*mNVar), x, mNVar*sizeof(r_4));
+mNEnt++;
+return;
+}
+
+
+/* --Methode-- */
+//++
+float NTuple::GetVal(int n, int k)  const
+//
+//	Retourne la valeur de la variable `k' de l'evenement `n'.
+//--
+{
+if (n >= mNEnt)   return(BADVAL);
+if ( (k < 0) || (k >= mNVar) )    return(BADVAL);
+int numb = n/mBlk;
+int offb = n-numb*mBlk;
+return(*(mPtr[numb]+offb*mNVar+k));
+}
+
+
+/* --Methode-- */
+//++
+int NTuple::IndexNom(const char* nom)  const
+//
+//	Retourne le numero de la variable de nom `nom'.
+//--
+{
+int i;
+for(i=0; i<mNVar; i++)  
+  if ( strcmp(nom, mNames+i*LENNAME1) == 0)  return(i);
+return(-1);
+}
+
+
+static char nomretour[2*LENNAME1];
+/* --Methode-- */
+//++
+char* NTuple::NomIndex(int k)  const
+//
+//	Retourne le nom de la variable numero 'k'
+//--
+{
+nomretour[0] = '\0';
+if ((k >= 0) && (k < mNVar))  strcpy(nomretour, mNames+k*LENNAME1);
+return(nomretour);
+}
+
+  
+/* --Methode-- */
+//++
+r_4* NTuple::GetVec(int n, r_4* ret)   const
+//
+//	Retourne l'evenement `n' dans le vecteur `ret'.
+//--
+{
+int i;
+if (ret == NULL)   ret = mVar;
+if (n >= mNEnt) {
+  for(i=0; i<mNVar; i++)   ret[i] = BADVAL;
+  return(ret);
+}
+  
+int numb = n/mBlk;
+int offb = n-numb*mBlk;
+memcpy(ret, (mPtr[numb]+offb*mNVar), mNVar*sizeof(r_4));
+return(ret);
+}
+
+/* --Methode-- */
+//++
+r_8* NTuple::GetVecD(int n, r_8* ret)   const
+//
+//	Retourne l'evenement `n' dans le vecteur `ret'.
+//--
+{
+int i;
+if (ret == NULL)   ret = mVarD;
+float *  fr = GetVec(n);
+for(i=0; i<mNVar; i++)   ret[i] = fr[i];
+return(ret);
+}
+
+
+
+/* --Methode-- */
+//++
+DVList&  NTuple::Info()
+//
+//	Renvoie une référence sur l'objet DVList Associé
+//--
+{
+if (mInfo == NULL)  mInfo = new DVList;
+return(*mInfo);
+}
+
+/* --Methode-- */
+//++
+void  NTuple::Print(int num, int nmax)  const
+//
+//	Imprime `nmax' evenements a partir du numero `num'.
+//--
+{
+int i,j;
+
+printf("Num     ");
+for(i=0; i<mNVar; i++)  printf("%8s ", mNames+i*LENNAME1);
+putchar('\n');
+
+if (nmax <= 0)  nmax = 1;
+if (num < 0)  num = 0;
+nmax += num;
+if (nmax > mNEnt) nmax = mNEnt;
+for(i=num; i<nmax; i++) {
+  GetVec(i, NULL); 
+  printf("%6d  ", i);  
+  for(j=0; j<mNVar; j++)  printf("%8g ", (float)mVar[j]);
+  putchar('\n');
+}
+return;
+}
+
+/* --Methode-- */
+//++
+void  NTuple::Show(ostream& os)  const
+//
+//	Imprime l'information generale sur le ntuple.
+//--
+{
+os << "NTuple: NVar= " << mNVar << " NEnt=" << mNEnt  
+   << " (Blk Sz,Nb= " << mBlk << " ," << mNBlk << ")\n";
+os << "            Variables       Min      Max       \n";
+int i;
+double min, max;
+char buff[128];
+for(i=0; i<mNVar; i++) {
+  GetMinMax(i, min, max);
+  sprintf(buff, "%3d  %16s  %10lg  %10lg \n", i, mNames+i*LENNAME1, min, max);
+  os << (string)buff ;
+  }
+os << endl;
+}
+
+
+/* --Methode-- */
+//++
+int  NTuple::FillFromASCIIFile(string const& fn, float defval)
+//
+//	Remplit le ntuple a partir d'un fichier ASCII.
+//	Renvoie le nombre de lignes ajoutees.
+//--
+{
+if (NbColumns() < 1)  { 
+  cout << "NTuple::FillFromASCIIFile() Ntuple has " << NbColumns() << " columns" << endl;
+  return(-1);
+  }
+FILE * fip = fopen(fn.c_str(), "r");
+if (fip == NULL) {
+  cout << "NTuple::FillFromASCIIFile() Error opening file " << fn << endl;
+  return(-2);
+  }
+
+char lineb[4096];
+char *line;
+char buff[64];
+char* ccp;
+int i,j,l,kk;
+int postab, posb;
+float* xv = new float[NbColumns()];
+
+int nlread = 0;
+int nvar = NbColumns();
+// On boucle sur toutes les lignes
+while (fgets(lineb,4096,fip) != NULL) {
+  lineb[4095] = '\0';
+  j = 0; line = lineb;
+//  On enleve les espaces et tab de debut 
+  while ( (line[j] != '\0') && ((line[j] == ' ') || (line[j] == '\t')) )  j++;
+  line = lineb+j; 
+// Il faut que le premier caractere non-espace soit un digit, ou + ou - ou .
+  if (!( isdigit(line[0]) || (line[0] == '+') || (line[0] == '-') || (line[0] == '.') ))  continue;
+  ccp = line;
+  for(kk=0; kk<nvar; kk++)  xv[kk] = defval;
+  for(kk=0; kk<nvar; kk++) {
+// Les mots sont separes par des espaces ou des tab
+    postab = posc(ccp, '\t' );
+    posb = posc(ccp, ' ' );
+    if (postab >= 0) { 
+       if (posb < 0) posb = postab;
+       else if (postab < posb)  posb = postab; 
+       } 
+    if (posb >= 0)  ccp[posb] = '\0';
+    if ( isdigit(line[0]) || (line[0] == '+') || (line[0] == '-') || (line[0] == '.') ) 
+      xv[kk] = atof(ccp);
+    if (posb < 0)  break;
+    ccp += posb+1;   j = 0;
+    while ( (ccp[j] != '\0') && ((ccp[j] == ' ') || (ccp[j] == '\t')) )  j++;
+    ccp += j;
+    }
+  Fill(xv);
+  nlread++;
+  }
+
+delete[] xv;
+cout << "NTuple::FillFromASCIIFile( " << fn << ") " << nlread << " fill from file " << endl;
+return(nlread);
+}
+
+
+// ------- Implementation de  l interface NTuple  ---------
+
+/* --Methode-- */
+uint_4 NTuple::NbLines() const
+{
+return(NEntry());
+}
+/* --Methode-- */
+uint_4 NTuple::NbColumns() const
+{
+return(NVar());
+}
+
+/* --Methode-- */
+r_8 * NTuple::GetLineD(int n) const
+{
+return(GetVecD(n));
+}
+
+/* --Methode-- */
+r_8 NTuple::GetCell(int n, int k) const
+{
+return(GetVal(n, k));
+}
+
+/* --Methode-- */
+r_8 NTuple::GetCell(int n, string const & nom) const
+{
+return(GetVal(n, nom.c_str()));
+}
+
+/* --Methode-- */
+//++
+void  NTuple::GetMinMax(int k, double& min, double& max)  const
+//
+//	Retourne le minimum et le maximum de la variable `k'.
+//--
+{
+min = 9.e19; max = -9.e19;
+if ( (k < 0) || (k >= mNVar) )    return;
+int jb,ib,i;
+double x;
+i=0;
+for(jb=0; jb< mNBlk; jb++)
+  for(ib=0; ib< mBlk; ib++) {
+    if (i >= mNEnt)  break;
+    i++;
+    x = *(mPtr[jb]+ib*mNVar+k);
+    if(i==1) {min = x; max = x;}
+    if (x < min)  min = x;
+    if (x > max)  max = x;
+  }
+return;
+}
+
+/* --Methode-- */
+void NTuple::GetMinMax(string const & nom, double& min, double& max)   const
+{
+GetMinMax(IndexNom(nom.c_str()), min, max);
+}
+
+/* --Methode-- */
+int NTuple::ColumnIndex(string const & nom)  const
+{
+return(IndexNom(nom.c_str()));
+}
+
+/* --Methode-- */
+string NTuple::ColumnName(int k) const
+{
+return(NomIndex(k));
+}
+
+/* --Methode-- */
+//++
+string NTuple::VarList_C(const char* nomx)  const
+//
+//	Retourne une chaine de caracteres avec la declaration des noms de 
+//	variables. si "nomx!=NULL" , des instructions d'affectation
+//	a partir d'un tableau "nomx[i]" sont ajoutees. 
+//--
+{
+string rets="";
+int i;
+for(i=0; i<mNVar; i++) {
+  if ( (i%5 == 0) && (i > 0) )  rets += ";";  
+  if (i%5 == 0)   rets += "\ndouble "; 
+  else rets += ",";
+  rets += mNames+i*LENNAME1;
+  }
+rets += "; \n";
+if (nomx) { 
+  char buff[256];
+  for(i=0; i<mNVar; i++) {
+    sprintf(buff,"%s=%s[%d]; ",  mNames+i*LENNAME1, nomx, i);
+    rets += buff;
+    if ( (i%3 == 0) && (i > 0) )  rets += "\n"; 
+    }
+  }
+
+return(rets);
+}
+
+
+/* --Methode-- */
+//++
+string NTuple::LineHeaderToString() const 
+//	Retourne une chaine de caracteres avec la liste des noms de  
+//	variables, utilisables pour une impression
+//--
+{
+char buff[32];
+string rets=" Num    ";
+for(int i=0; i<mNVar; i++) {
+  sprintf(buff, "%8s ", mNames+i*LENNAME1);
+  rets += buff;
+  }
+rets += '\n';
+return(rets);
+}
+
+/* --Methode-- */
+//++
+string NTuple::LineToString(int n) const
+//	Retourne une chaine de caracteres avec le contenu de la ligne "n"
+//	utilisable pour une impression
+//--
+{
+char buff[32];
+double* val;
+val = GetLineD(n);
+sprintf(buff,"%6d: ",n);  
+string rets=buff;
+int i;
+for(i=0; i<mNVar; i++) {
+  sprintf(buff, "%8.3g ", val[i]);
+  rets += buff;
+  }
+rets += '\n';
+return(rets);
+}
+
+
+/* --Methode-- */
+//++
+void   ObjFileIO<NTuple>::WriteSelf(POutPersist& s)  const
+//
+//	Ecriture ppersist du ntuple.
+//--
+{
+char strg[256];
+if (dobj->mInfo)  sprintf(strg, "NVar=%6d  NEnt=%9d  BlkSz=%6d NBlk=%6d  HasInfo", 
+                          (int)dobj->mNVar, (int)dobj->mNEnt, (int)dobj->mBlk, (int)dobj->mNBlk);
+else sprintf(strg, "NVar=%6d  NEnt=%9d  BlkSz=%6d NBlk=%6d ", 
+                   (int)dobj->mNVar, (int)dobj->mNEnt, (int)dobj->mBlk, (int)dobj->mNBlk);
+s.PutLine(strg);
+s.PutI4(dobj->mNVar);
+s.PutBytes(dobj->mNames, dobj->mNVar*LENNAME1);
+s.PutI4(dobj->mNEnt);
+s.PutI4(dobj->mBlk);
+s.PutI4(dobj->mNBlk);
+if (dobj->mInfo)  s << (*(dobj->mInfo));
+int jb;
+for(jb=0; jb<dobj->mNBlk; jb++)
+  s.PutR4s(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
+return;
+}
+
+/* --Methode-- */
+//++
+void  ObjFileIO<NTuple>::ReadSelf(PInPersist& s)
+//
+//	Lecture ppersist du ntuple.
+//--
+{
+
+dobj->Clean();
+
+char strg[256];
+s.GetLine(strg, 255);
+// Pour savoir s'il y avait un DVList Info associe
+bool hadinfo = false;
+if (strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0)  hadinfo = true;
+
+s.GetI4(dobj->mNVar);
+dobj->mNames = new char[dobj->mNVar*LENNAME1];
+dobj->mVar = new r_4[dobj->mNVar];
+dobj->mVarD = new r_8[dobj->mNVar];
+s.GetBytes(dobj->mNames, dobj->mNVar*LENNAME1);
+s.GetI4(dobj->mNEnt);
+s.GetI4(dobj->mBlk);
+s.GetI4(dobj->mNBlk);
+
+if (hadinfo) {    // Lecture eventuelle du DVList Info
+  if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+  s >> (*(dobj->mInfo));
+  }
+
+int jb; 
+for(jb=0; jb<dobj->mNBlk; jb++) {
+  r_4* pt = new r_4[dobj->mNVar*dobj->mBlk];
+  dobj->mPtr.push_back(pt);
+  s.GetR4s(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
+}
+
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<NTuple>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<NTuple>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/ntuple.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/ntuple.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/ntuple.h	(revision 752)
@@ -0,0 +1,109 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Class NTuple
+//  CMV+Reza     Juillet 97
+//  CEA-DAPNIA      LAL-IN2P3/CNRS
+
+#ifndef NTUPLE_H_SEEN
+#define NTUPLE_H_SEEN
+
+#include "objfio.h"
+
+#include <iostream.h>
+#include <string>
+#include <vector>
+
+#include "ntupintf.h"
+#include "ppersist.h"
+#include "dvlist.h"
+
+namespace SOPHYA {
+
+class NTuple : public AnyDataObj , public NTupleInterface {
+public:
+//  enum {classId = ClassId_NTuple };
+
+  		    NTuple(int nvar, char** noms, int blk=512);
+		    NTuple();
+                    NTuple(const NTuple& NT);
+		    NTuple(char* flnm);
+  virtual           ~NTuple();
+
+  NTuple&           operator = (const NTuple& NT);
+ 
+  void              Fill(r_4* x);
+
+  inline int_4      NEntry() const  { return(mNEnt); }  
+  inline int_4      NVar() const { return(mNVar); }  
+  inline int_4      BLock() const { return(mBlk); }  
+// $CHECK$ Reza 21/10/99 Pourquoi faire BLock() ?
+
+  float             GetVal(int n, int k)   const;
+  inline float	    GetVal(int n, const char* nom) const 
+                            { return(GetVal(n, IndexNom(nom)) ); }
+  int               IndexNom(const char* nom)  const ;
+  char*             NomIndex(int k) const;
+
+  r_4*	            GetVec(int n, r_4* ret=NULL)  const ;
+  r_8*	            GetVecD(int n, r_8* ret=NULL)  const ;
+
+// Impression, I/O
+  void              Print(int num, int nmax=1)  const ;
+  void              Show(ostream& os) const;
+  inline void       Show() const { Show(cout); }
+
+  DVList&           Info();
+
+// Remplissage depuis fichier ASCII 
+  int		    FillFromASCIIFile(string const& fn, float defval=0.);
+
+
+// Declaration de l interface NTuple
+  virtual uint_4        NbLines() const ;
+  virtual uint_4        NbColumns() const ;
+  virtual r_8 *         GetLineD(int n) const ;
+  virtual r_8		GetCell(int n, int k) const ;
+  virtual r_8		GetCell(int n, string const & nom) const ;
+  virtual void		GetMinMax(int k, double& min, double& max)   const ; 
+  virtual void		GetMinMax(string const & nom, double& min, double& max)   const ; 
+  virtual int           ColumnIndex(string const & nom)  const ;
+  virtual string        ColumnName(int k) const;
+  virtual string	VarList_C(const char* nomx=NULL) const ;
+  virtual string        LineHeaderToString() const;
+  virtual string        LineToString(int n) const;  
+
+//  Pour la gestion de persistance
+  friend class ObjFileIO<NTuple> ;
+
+private:
+  void  Clean();
+
+  int_4 mNVar, mNEnt, mBlk, mNBlk;
+  r_4* mVar;
+  r_8* mVarD;
+  char* mNames;
+
+  vector<r_4*> mPtr;
+
+  DVList* mInfo;        // Infos (variables) attachees au NTuple
+  
+};
+
+inline ostream& operator << (ostream& s, NTuple const & nt)
+  {  nt.Show(s);  return(s);  }
+
+inline POutPersist& operator << (POutPersist& os, NTuple & obj)
+{ ObjFileIO<NTuple> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, NTuple & obj)
+{ ObjFileIO<NTuple> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<NTuple>
+
+#ifdef __MWERKS__
+__MSL_FIX_ITERATORS__(r_4*);
+#endif
+
+} // namespace SOPHYA
+
+#endif
+  
Index: /tags/V_Fev00/SophyaLib/NTools/objlist.list
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/objlist.list	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/objlist.list	(revision 752)
@@ -0,0 +1,41 @@
+cimage.o
+cspline.o
+cvector.o
+datacards.o
+datatypes.o
+dates.o
+datime.o
+difeq.o
+dvlist.o
+dynccd.o
+fct1dfit.o
+fct2dfit.o
+fftpackc.o
+fftserver.o
+generaldata.o
+generalfit.o
+hisprof.o
+histos.o
+histos2.o
+imageop.o
+integ.o
+linfit.o
+matrix.o
+matxop.o
+median.o
+nbmath.o
+nbrandom.o
+nbtri.o
+ntupintf.o
+ntuple.o
+outilsinit.o
+perandom.o
+poly.o
+rk4cdifeq.o
+rzimage.o
+simplesort.o
+strutil.o
+tabmath.o
+tmatrix.o
+tvector.o
+utils.o
Index: /tags/V_Fev00/SophyaLib/NTools/outilsinit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/outilsinit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/outilsinit.cc	(revision 752)
@@ -0,0 +1,102 @@
+// Classe d'initialisation du module Outils++ 
+#include <unistd.h>
+
+#include "outilsinit.h"
+
+#include "matrix.h"
+#include "cvector.h"
+#include "poly.h"
+#include "dvlist.h"
+#include "histos.h"
+#include "histos2.h"
+#include "hisprof.h"
+#include "ntuple.h"
+#include "xntuple.h"
+#include "generaldata.h"
+#include "tmatrix.h"
+#include "tvector.h"
+
+#include "cimage.h"
+
+#include "tabmath.h"
+#include "dates.h"
+#include "datime.h"
+
+int PeidaOutilsInitiator::FgInit = 0;
+
+PeidaOutilsInitiator::PeidaOutilsInitiator()
+  : PeidaInitiator()
+{
+  FgInit++;
+  if (FgInit > 1)  return;
+
+//   Enregistrement des classes PPersist du modules Outils++
+  
+  PPRegister(OMatrix);
+  PPRegister(OVector);
+  PPRegister(ObjFileIO<Poly>);
+  PPRegister(ObjFileIO<Poly2>);
+  PPRegister(ObjFileIO<DVList>);
+  PPRegister(ObjFileIO<Histo>);
+  PPRegister(ObjFileIO<Histo2D>);
+  PPRegister(ObjFileIO<HProf>);
+
+  PPRegister(ObjFileIO<NTuple>);
+  PPRegister(ObjFileIO<XNTuple>);
+  PPRegister(ObjFileIO<GeneralFitData>);
+
+  PPRegister(FIO_TMatrix<uint_1>);
+  PPRegister(FIO_TMatrix<uint_2>);
+  PPRegister(FIO_TMatrix<int_2>);
+  PPRegister(FIO_TMatrix<int_4>);
+  PPRegister(FIO_TMatrix<int_8>);
+  PPRegister(FIO_TMatrix<uint_8>);
+  PPRegister(FIO_TMatrix<r_4>);
+  PPRegister(FIO_TMatrix<r_8>);
+  PPRegister(FIO_TMatrix< complex<r_4> >);
+  PPRegister(FIO_TMatrix< complex<r_8> >);
+
+  PPRegister(FIO_TVector<uint_1>);
+  PPRegister(FIO_TVector<uint_2>);
+  PPRegister(FIO_TVector<int_2>);
+  PPRegister(FIO_TVector<int_4>);
+  PPRegister(FIO_TVector<int_8>);
+  PPRegister(FIO_TVector<uint_8>);
+  PPRegister(FIO_TVector<r_4>);
+  PPRegister(FIO_TVector<r_8>);
+  PPRegister(FIO_TVector< complex<r_4> >);
+  PPRegister(FIO_TVector< complex<r_8> >);
+
+
+  PPRegister(RzImage);
+  PPRegister(ImageU2);
+  PPRegister(ImageI2);
+  PPRegister(ImageI4);
+  PPRegister(ImageR4);
+
+  //PPersistMgr::RegisterClass(OMatrix::classId,  OMatrix::Create);
+
+  int pnice;
+  char* snice = getenv("PEIDANICE");
+  if (!snice) pnice=8;
+  else pnice = atoi(snice);
+  nice(pnice);
+
+//  TSidSetupLaSilla();    Old-Eros
+
+  gTimeZone = new TimeZone;
+
+  ptabFExp = new TabFExp;
+
+}
+
+PeidaOutilsInitiator::~PeidaOutilsInitiator()
+{
+  FgInit--;
+}
+
+
+// On met un objet initiator en statique, pour les loaders qui savent 
+// appeler le constructeur des objets statiques   Reza 08/98
+static PeidaOutilsInitiator poutilsinit;
+
Index: /tags/V_Fev00/SophyaLib/NTools/outilsinit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/outilsinit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/outilsinit.h	(revision 752)
@@ -0,0 +1,23 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe d'initialiseur du module Outils++
+
+#ifndef OUTILSINIT_H_SEEN
+#define OUTILSINIT_H_SEEN
+
+
+// Classe d''initialisation pour les modules de PEIDA++
+#include "peidainit.h"
+
+class PeidaOutilsInitiator : public PeidaInitiator {
+private:
+  static int FgInit;
+public:
+  			PeidaOutilsInitiator();
+  virtual		~PeidaOutilsInitiator();
+};
+
+#undef PeidaInit
+#define PeidaInit() PeidaOutilsInitiator peidaoutilsinitiator
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/pclassids.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/pclassids.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/pclassids.h	(revision 752)
@@ -0,0 +1,55 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef PEIDA_CLASS_ID_H
+#define PEIDA_CLASS_ID_H
+
+// ClassIds pour Peida. Il est possible d'en definir d'autres, mais on regroupe
+// ici toutes les classIds pour eviter des collisions.
+//
+// ClassIds pour utilisateur >= 0x4000
+//
+
+enum PeidaClassIds {
+
+   ClassId_Unknown    = 0x0000,
+//  Module Outils++
+   ClassId_Poly1    = 0x0101,
+   ClassId_Poly2    = 0x0102,
+   ClassId_Matrix   = 0x0103,
+   ClassId_Vector   = 0x0104,
+   ClassId_DVList   = 0x0105,
+
+   ClassId_PMatrixF = 0x0110,
+   ClassId_PMatrixD = 0x0111,
+   ClassId_PVectorF = 0x0112,
+   ClassId_PVectorD = 0x0113,
+
+   ClassId_Histo1D  = 0x0201,
+   ClassId_Histo2D  = 0x0202,
+   ClassId_HProf    = 0x0203,
+   ClassId_NTuple   = 0x0210,
+   ClassId_XNTuple  = 0x0211,
+
+   ClassId_GeneralFitData  = 0x0290,
+
+//  Module Images++
+   ClassId_Image    = 0x0300,    // classId = 0x0300 + ImageType pour images types   
+   ClassId_ZFidu    = 0x0330,
+   ClassId_Voronoi  = 0x0340,
+   ClassId_RLEImage = 0x0350,
+
+//  Module StarReco++
+   ClassId_StarList = 0x0500,
+   ClassId_Transfo  = 0x0501,
+   ClassId_PSF      = 0x0510,
+   ClassId_Star     = 0x1000,     // Et ce qui suit, classId = 0x1000 + StarType
+
+//  Module Samba
+   ClassId_SphereTetaPhi  = 0x0611,
+   ClassId_SphereGorski   = 0x0612,
+   ClassId_LocalMap       = 0x0601,
+   ClassId_Scan           = 0x0631,
+   ClassId_MainLobe       = 0x0641
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/peida.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/peida.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/peida.h	(revision 752)
@@ -0,0 +1,17 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef PEIDA_SEEN
+#define PEIDA_SEEN
+
+#include "machdefs.h"
+#include "utils.h"
+#include "perrors.h"
+#include "pexceptions.h"
+#include "fmath.h"
+
+#ifdef __mac__
+#include "unixmac.h"
+#endif
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/pemath.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/pemath.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/pemath.h	(revision 752)
@@ -0,0 +1,26 @@
+/* quelques fonctions mathematiques et constantes utiles */
+/*                                         cmv  23/06/94 */
+
+#ifndef PEMATH_SEEN
+#define PEMATH_SEEN
+
+#include "machdefs.h"
+
+#define  Pi     (double) (3.1415926535898)    /* c'est Pi */
+#define  DeuxPi (double) (6.2831853071796)    /* c'est 2*Pi */
+#define  SPi    (double) (1.772453850906)     /* c'est sqrt(Pi) */
+#define  S2Pi   (double) (2.506628274631)     /* c'est sqrt(2*Pi) */
+#define  Rac2   (double) (1.414213562373)     /* c'est sqrt(2) */
+#define  Log2   (double) (0.301029995664)     /* c'est log10(2) */
+#define  LnPi   (double) (1.14472988585)      /* c'est ln(Pi) */
+#define  LgPi   (double) (0.497149872694)     /* c'est log10(Pi) */
+#define  Ln10   (double) (2.302585092994)     /* c'est ln(10) */
+#define  DftoDm (double) (1.085736204758)     /* c'est 2.5/ln(10) */
+#define  Hln2pi (double) 0.918938533205       /* c'est Ln(2*pi)/2 */
+#define  JourSec (float) (86400.)       /* nombre de secondes dans 24H */
+#define  AnSec  (int) (31557600)   /* nombre de secondes dans 365.25 jours */
+#define  GRAND  (float) (1.e+35)
+#define  GRAND2 (double) (1.e+35)
+#define  IGRAND (int_4) (2147483647)
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/perandom.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/perandom.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/perandom.cc	(revision 752)
@@ -0,0 +1,216 @@
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "perandom.h"
+#include "pemath.h"
+#include <iostream.h>
+
+////////////////////////////////////////////////////////////////////////////
+//++
+// Class	FunRan
+// Lib  Outils++ 
+// include	perandom.h
+//
+//	Tirage aleatoire sur un histogramme 1D.
+//--
+
+//++
+FunRan::FunRan(FunRan::Func f, float xMin, float xMax, int nBin)
+//
+//	Createur.
+//--
+: Histo(xMin, xMax, nBin)
+{
+  (*this)(0) = f(BinLowEdge(0));
+  for(int i=1; i<nBin; i++)
+    (*this)(i) = (*this)(i-1) + f(BinLowEdge(i));
+    
+  for(int j=0; j<nBin; j++)
+    (*this)(j) /= (*this)(nBin-1);
+  END_CONSTRUCTOR
+}
+
+//++
+FunRan::FunRan(double *tab, int nBin)
+//
+//	Createur.
+//--
+: Histo(0, (float)(nBin), nBin)
+{
+  (*this)(0) = tab[0];
+  for(int i=1; i<nBin; i++)
+    (*this)(i) = (*this)(i-1) + tab[i];
+
+  if ((*this)(nBin-1) == 0) {
+    cerr << "FunRan::FunRan : sum(prob) = 0" << endl;
+    exit(-1);
+  }
+
+  for(int j=0; j<nBin; j++)
+    (*this)(j) /= (*this)(nBin-1);
+  END_CONSTRUCTOR
+}
+
+FunRan::FunRan(double *tab, int nBin, float xMin, float xMax)
+: Histo(xMin, xMax, nBin)
+{
+  (*this)(0) = tab[0];
+  for(int i=1; i<nBin; i++)
+    (*this)(i) = (*this)(i-1) + tab[i];
+
+  if ((*this)(nBin-1) == 0) {
+    cerr << "FunRan::FunRan : sum(prob) = 0" << endl;
+    exit(-1);
+  }
+
+  for(int j=0; j<nBin; j++)
+    (*this)(j) /= (*this)(nBin-1);
+  END_CONSTRUCTOR
+}
+
+//++
+int FunRan::BinRandom()
+//
+//	Tirage avec retour du numero de bin.
+//--
+{
+  double z=drand01();
+  if (z <= 0) return 0;
+  if (z >= 1) return bins-1;
+  
+  // recherche du premier bin plus grand que z
+  int iBin = 0;
+  for (; iBin<bins; iBin++)
+    if (z < (*this)(iBin)) break;
+
+  return iBin;
+}
+
+//++
+double FunRan::Random()
+//
+//	Tirage avec retour abscisse du bin interpole.
+//--
+{
+  double z=drand01();
+  if (z <= 0) return min;
+  if (z >= 1) return max;
+  // cas z <= tab[0] 
+  if (z <= (*this)(0)) {
+    double t = min + binWidth/(*this)(0) * z;
+    return t;
+  }
+
+  // recherche du premier bin plus grand que z
+  int iBin = 0;
+  for (; iBin<bins; iBin++)
+    if (z < (*this)(iBin)) break;
+
+  // interpolation pour trouver la valeur du tirage aleatoire
+  double t1 = (*this)(iBin-1);
+  double x1 = BinLowEdge(iBin-1);
+  double t2 = (*this)(iBin);
+  double x2 = x1 + binWidth;
+  double t = x1 + (x2-x1) / (t2-t1) * (z-t1);
+  if (t < min) t = min;
+  if (t > max) t = max;
+  return(t);
+}
+
+                   
+
+////////////////////////////////////////////////////////////////////////////
+//++
+// Class	FunRan2D
+// Lib  Outils++ 
+// include	perandom.h
+//
+//	Tirage aleatoire sur un histogramme 2D.
+//--
+
+//++
+FunRan2D::FunRan2D(double *tab, int nBinX, int nBinY)
+//
+//	Createur.
+//--
+{
+  // Tirage en X, somme sur les Y.
+   double* tabX = new double[nBinX];
+   for (int i=0; i<nBinX; i++) {
+     tabX[i] = 0;
+     for (int j=0; j<nBinY; j++) {
+       tabX[i] += tab[i*nBinY +j];
+     }
+   }
+   ranX = new FunRan(tabX, nBinX);
+   delete[] tabX;
+   
+   ranY = new(FunRan*[nBinX]);
+   
+   for (int k=0; k<nBinX; k++)
+      ranY[k] = new FunRan(tab + nBinY*k, nBinY);
+   
+   nx = nBinX;
+  END_CONSTRUCTOR
+}
+
+//++
+FunRan2D::FunRan2D(double **tab, int nBinX, int nBinY)
+//
+//	Createur.
+//--
+{
+  // Tirage en X, somme sur les Y.
+   double* tabX = new double[nBinX];
+   for (int i=0; i<nBinX; i++) {
+     tabX[i] = 0;
+     for (int j=0; j<nBinY; j++) {
+       tabX[i] += tab[i][j];
+     }
+   }
+   ranX = new FunRan(tabX, nBinX);
+   
+   ranY = new(FunRan*[nBinX]);
+   
+   for (int k=0; k<nBinX; k++)
+    if (tabX[k] != 0) 
+      ranY[k] = new FunRan(tab[k], nBinY);
+    else ranY[k] = NULL;
+   
+   delete[] tabX;
+   nx = nBinX;
+  END_CONSTRUCTOR
+}
+
+FunRan2D::~FunRan2D()
+{
+  for (int i=nx-1; i>=0; i--)
+    delete ranY[i];
+    
+  delete[] ranY;
+  
+  delete ranX;
+}
+
+//++
+void FunRan2D::BinRandom(int& x, int& y)
+//
+//	Tirage avec retour du numeros de bin.
+//--
+{
+  x = ranX->BinRandom();
+  //  FAILNIL(ranY[x]);  Ne compile pas $CHECK$ Reza 22/04/99
+  y = ranY[x]->BinRandom();
+}
+
+//++
+void FunRan2D::Random(double& x, double& y)
+//
+//	Tirage avec retour abscisse et ordonnee
+//	du bin interpole.
+//--
+{
+  x = ranX->Random();
+  int i = int(ceil(x));
+  //  FAILNIL(ranY[i]);  Ne compile pas $CHECK$ Reza 22/04/99
+  y = ranY[i]->Random();
+}
Index: /tags/V_Fev00/SophyaLib/NTools/perandom.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/perandom.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/perandom.h	(revision 752)
@@ -0,0 +1,40 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+// Nombres aleatoires pour Peida.
+
+#ifndef PERANDOM_SEEN
+#define PERANDOM_SEEN
+
+#include "machdefs.h"
+#include <stdlib.h>
+#include "histos.h"
+#include "nbrandom.h"
+
+class FunRan : public Histo {
+public:
+  typedef double (*Func)(double);
+  FunRan(Func f, float xMin=0.0, float xMax=1.0, int nBin=100);
+  FunRan(double *tab, int nBin);
+  FunRan(double *tab, int nBin, float xMin, float xMax);
+  void IFunRan(double *tab, int nBin);
+  double Random(void);
+  int BinRandom(void);
+};
+
+class FunRan2D EXC_AWARE {
+public:
+//  typedef double (*Func)(double, double);
+//  FunRan2D(Func f, float xMin=0.0, float xMax=1.0, int nBinX=100,
+//                   float yMin=0.0, float yMax=1.0, int nBinY=100);
+  FunRan2D(double *tab, int nBinX, int nBinY);
+  FunRan2D(double **tab, int nBinX, int nBinY);
+  ~FunRan2D();
+  void Random(double& x, double& y);
+  void BinRandom(int& x, int& y);
+private:
+  FunRan* ranX;
+  FunRan** ranY;
+  int nx;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/poly.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/poly.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/poly.cc	(revision 752)
@@ -0,0 +1,897 @@
+#include "machdefs.h"
+#include "poly.h"
+#include "linfit.h"
+
+//++
+// Class	Poly
+// Lib  	Outils++ 
+// include	poly.h
+//
+//	Classe de calcul sur polynômes à une variable.
+//--
+
+//++
+// Links	Parents
+// Vector
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+
+//////////////////////////////////////////////////////////////////////////
+//++
+// Poly::Poly(int degre=0)
+//
+//	Crée un nouveau polynôme, en allouant de la place pour 
+//	le degré spécifié. 
+//--
+
+Poly::Poly(int degre)
+: Vector(degre+1), dirty(0), deg(0)
+{
+  END_CONSTRUCTOR
+}
+
+//++
+Poly::Poly(Poly const& a)
+//
+//	Constructeur par copie.
+//--
+:Vector(a), dirty(a.dirty), deg(a.deg)
+{
+  END_CONSTRUCTOR
+}
+
+
+void Poly::UpdateDeg() const
+{
+  int i = NElts()-1;
+  while (Element(i) == 0 && i>0) i--;
+
+  (int&) deg = i;          // bientot mutable dans ANSI C++ 
+  (int&) dirty = 0;
+}
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+// double& Poly::operator[](int i)
+//	Permet d'accéder au coefficient de degré i (avec version 
+//	const).
+//--
+
+//++
+double Poly::operator()(double x) const
+//
+//	Calcule la valeur du polynôme au point x.
+//--
+{
+  UpdateDegIfDirty();
+  double res = Element(deg);
+  for (int i=deg-1; i>=0; i--) {
+    res *= x;
+    res += Element(i);
+  }
+  return res;
+}
+
+//++
+void Poly::Derivate()
+//
+//	Remplace le polynôme par le polynôme dérivé.
+//--
+{
+  UpdateDegIfDirty();
+  if (deg == 0) { Element(0) = 0; return;}
+  for (int i=1; i<=deg; i++)
+    Element(i-1) = Element(i)*i;
+  Element(deg) = 0;
+  deg--;
+}
+
+
+//++
+void Poly::Derivate(Poly& der) const
+//
+//	Retourne dans der le polynôme dérivé.
+//--
+{
+  UpdateDegIfDirty();
+  der.Realloc(deg);
+//  der.Zero();    // on sait que Realloc met a zero le reste.
+  for (int i=1; i<=deg; i++)
+    der.Element(i-1) = Element(i)*i;
+}
+
+
+//++
+int Poly::Roots(Vector& roots) const
+//
+//	Retourne dans roots les racines réelles, si on sait
+//	les calculer. Retourne le nombre de racines.
+//--
+{
+  UpdateDegIfDirty();
+
+  switch (deg)
+    {
+    case 0 :           // degre 0
+      return 0;
+    case 1 :           // degre 1
+      roots.Realloc(1);
+      return Root1(roots(0));
+    case 2 :           // degre 2
+      roots.Realloc(2);
+      return Root2(roots(0),roots(1));
+    default :
+      THROW(parmErr);
+    }
+}
+
+
+//++
+int Poly::Root1(double& r) const
+//
+//	Seulement si le polynôme est de degré 1: retourne
+//	la racine dans "r". Retourne 1 (nombre de racines).
+//--
+{
+  UpdateDegIfDirty();
+  if (deg != 1) THROW(sizeMismatchErr);
+
+  if (Element(1) == 0) return 0;
+  r = -Element(0)/Element(1);
+  return 1;
+}
+
+//++
+int Poly::Root2(double& r1, double& r2) const
+//
+//	Seulement si le polynôme est de degre 2: retourne
+//	les racines dans "r1" et "r2". Retourne 0, 1 ou 2
+//	(nombre de racines).
+//--
+{
+  UpdateDegIfDirty();
+  if (deg != 2) THROW(sizeMismatchErr);
+
+  double delta = Element(1)*Element(1) - 4*Element(0)*Element(2);
+  if (delta < 0) return 0;
+  if (delta == 0) {
+    r1 = r2 = -Element(1)/2/Element(0);
+    return 1;
+  }
+  r1 = (-Element(1) - sqrt(delta))/2/Element(0);
+  r2 = (-Element(1) + sqrt(delta))/2/Element(0);
+  return 2;
+}
+
+//++
+Poly& Poly::operator = (Poly const& a)
+//
+//	Opérateur d'affectation.
+//--
+{
+  if (this == &a) return *this;
+  Vector::operator=(a);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+// Titres	Opérations sur polynômes
+//--
+
+//++
+Poly& Poly::operator += (Poly const& b)
+//
+//--
+{
+  UpdateDegIfDirty();
+  b.UpdateDegIfDirty();
+
+  if (b.deg > deg) Realloc(b.deg);
+
+  int n = (deg > b.deg) ? deg : b.deg;
+  for (int i=0; i<=n; i++) Element(i) += b.Element(i);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+Poly& Poly::operator -= (Poly const& b)
+//
+//--
+{
+  UpdateDegIfDirty();
+  b.UpdateDegIfDirty();
+
+  if (b.deg > deg) Realloc(b.deg);
+
+  int n = (deg > b.deg) ? deg : b.deg;
+  for (int i=0; i<=n; i++) Element(i) -= b.Element(i);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+Poly& Poly::operator *= (double a)
+//
+//--
+{
+  UpdateDegIfDirty();
+  for (int i=0; i<=deg; i++) Element(i) *= a;
+  return *this;
+}
+
+//++
+Poly Poly::Mult(Poly const& b) const
+//
+//--
+{
+Poly c(deg + b.deg);
+  UpdateDegIfDirty();
+  b.UpdateDegIfDirty();
+
+  c.deg = deg + b.deg;
+
+  for (int i=0; i<=c.deg; i++) {
+    c[i] = 0;
+    int kmin = (i <= deg) ? 0 : i - deg;
+    int kmax = (i <= deg) ? i : deg;
+    for (int k=kmin; k<=kmax; k++)
+      c[i] += (*this)[k] * b[i-k];
+  }
+return c;
+}
+
+//++
+void Poly::Print(ostream& s) const
+//
+//	Impresssion.
+//--
+{
+  UpdateDegIfDirty();
+  int nz=0;
+  for (int i = deg; i>=0; i--) {
+    if ((*this)[i] != 0) {
+      nz = 1;
+      if (i < deg && (*this)[i] > 0) s << "+";
+      s << (*this)[i];
+      if (i == 1) s << "*X ";
+      if (i > 1) s << "*X^" << i << " ";
+    }
+  }
+  if (!nz) s << " 0 ";
+}
+
+//++
+double Poly::Fit(Vector const& x, Vector const& y, int degre)
+//
+//	Ajustement polynomial par moindre carrés. Un polynôme de
+//	degré "degre" est ajusté sur les données "x" et "y", et stocké dans
+//	l'objet courant. Retourne le chi2.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degre);
+
+  Matrix a(degre+1, n);
+
+  for (int c=0; c<n; c++) {
+    double xpow = 1.0;
+    for (int l=0; l<=degre; l++) {
+      a(l,c) = xpow;
+      xpow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,y,(Vector&)*this);
+  UpdateDeg();
+  return rc;
+}
+
+//++
+double Poly::Fit(Vector const& x, Vector const& y, Vector const& erry2, int degre,
+                 Vector& errCoef)
+//
+//	Ajustement polynomial par moindre carrés. Un polynôme de
+//	degré est ajusté sur les données x et y, et stocké dans
+//	l'objet courant. erry2 contient le carre des erreurs sur y. 
+//	Retourne le chi2.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  if (n != erry2.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degre);
+  errCoef.Realloc(degre+1);
+
+  Matrix a(degre+1, n);
+
+  for (int c=0; c<n; c++) {
+    double xpow = 1.0;
+    for (int l=0; l<=degre; l++) {
+      a(l,c) = xpow;
+      xpow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,y,erry2,(Vector&)*this,errCoef);
+  UpdateDeg();
+  return rc;
+}
+
+
+//++
+// Poly Poly::power(int n) const
+//
+//	Retourne le polynôme à la puissance n
+//--
+
+Poly Poly::power(int n) const // a accelerer !!!
+{
+  if (n < 0) THROW(rangeCheckErr);
+  if (n == 0) { Poly r(0); r[0] = 1; return r;}
+  if (n == 1) { return *this; }
+  return *this * power(n-1);
+}
+
+//++
+Poly Poly::operator() (Poly const& b) const
+//
+//	Substitution d'un polynôme dans un autre.
+//--
+{
+  Poly c(b.Degre()*Degre());
+  for (int i=0; i<= Degre(); i++)
+    c += (*this)[i] * b.power(i);
+  return c;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ObjFileIO<Poly>::ReadSelf(PInPersist& is)
+{
+if(dobj==NULL) dobj=new Poly;
+int_4 dg;
+is >> dg;
+dobj->Realloc(dg,true);
+is >> *((Vector *) dobj);
+dobj->UpdateDeg();
+}
+
+void ObjFileIO<Poly>::WriteSelf(POutPersist& os) const
+{
+if(dobj == NULL) return;
+dobj->UpdateDegIfDirty();
+dobj->Realloc(dobj->deg,true);
+os << dobj->deg;
+os << *((Vector *) dobj);
+}
+
+//////////////////////////////////////////////////////////////////////////
+int binomial(int n, int p)
+{
+  int c = 1;
+  for (int i=n-p+1; i<=n; i++) c *= i;
+  for (int j=2; j<=p; j++) c /= j;
+  return c;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// ******************* POLY 2 VARIABLES ******************
+//++
+// Class	Poly2
+// Lib  	Outils++ 
+// include	poly.h
+//
+//	Classe de calcul sur polynômes à deux variables.
+//--
+
+//++
+// Links	Parents
+// Vector
+//--
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+Poly2::Poly2(int degreX, int degreY)
+//
+//	Crée un polynôme de degrés partiels degreX et degreY.
+//--
+:Vector((degreX+1)*(degreY+1)), dirty(0),
+ maxDegX(degreX), maxDegY(degreY), degX(0), degY(0), deg(0)
+{
+  END_CONSTRUCTOR
+}
+
+//++
+Poly2::Poly2(Poly const& polX, Poly const& polY)
+//
+//	Crée un polynôme à deux variables comme produit
+//	de deux polynômes à une variable, p2(x,y)=px(x)py(y)
+//--
+:Vector((polX.Degre()+1)*(polY.Degre()+1)), dirty(0),
+ maxDegX(polX.Degre()), maxDegY(polY.Degre()),
+ degX(polX.Degre()), degY(polY.Degre()), deg(degX+degY)
+{
+  for (int i=0; i<=degX; i++)
+    for (int j=0; j<=degY; j++)
+      Coef(i,j) = polX[i]*polY[j];
+  END_CONSTRUCTOR
+}
+
+//++
+Poly2::Poly2(Poly2 const& a)
+//
+//	Constructeur par copie.
+//--
+:Vector(a), dirty(a.dirty),
+ maxDegX(a.maxDegX), maxDegY(a.maxDegY),
+ degX(a.degX), degY(a.degY), deg(a.deg)
+{
+  END_CONSTRUCTOR
+}
+
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+Poly2& Poly2::operator = (Poly2 const& a)
+//
+//	Opérateur d'affectation.
+//--
+{
+  if (this == &a) return *this;
+  if (maxDegX < a.DegX() || maxDegY < a.DegY())
+    Realloc(a.DegX(), a.DegY());
+
+
+  for (int i=0; i<= maxDegX; i++)
+    for (int j=0; j<= maxDegY; j++)
+      Coef(i,j) = a.Coef(i,j);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+void Poly2::Realloc(int degreX, int degreY)
+//
+//	Redimensionne le polynôme comme etant un 
+//	polynôme de degrés partiels degreX et degreY.
+//--
+{
+  UpdateDegIfDirty();
+  Poly2 tmp(*this);
+  Vector::Realloc((degreX+1)*(degreY+1));
+  Reset();
+  maxDegX = degreX;
+  maxDegY = degreY;
+
+// Attention - Reza 30/09/99
+// il faut prendre le min en degre du polynome de depart et le nouveau
+  int cdegx = (tmp.degX < degreX) ? tmp.degX : degreX;
+  int cdegy = (tmp.degY < degreY) ? tmp.degY : degreY;
+  for (int i=0; i<= cdegx; i++)
+    for (int j=0; j<= cdegy; j++)
+      Coef(i,j) = tmp.Coef(i,j);
+}
+
+
+void Poly2::UpdateDeg() const
+{
+  (int&)degX=(int&)degY=(int&)deg=0;
+
+  for (int dx=0; dx<=maxDegX; dx++)
+    for (int dy=0; dy<=maxDegY; dy++)
+      if (Coef(dx,dy) != 0) {
+        if (dx > degX) (int&)degX = dx;
+        if (dy > degY) (int&)degY = dy;
+        if (dx+dy > deg) (int&)deg = dx+dy;
+      }
+
+  (int&)dirty = 0;
+}
+
+//++
+// int Poly2::DegX() const
+//	Degré partiel en X.
+// int Poly2::DegY() const
+//	Degré partiel en Y
+// int Poly2::MaxDegX() const
+//	Degré partiel maximum (alloué) en X
+// int Poly2::MaxDegY() const
+//	Degré partiel maximum (alloué) en Y
+// int Poly2::Deg()  const
+//	Degré total.
+//--
+
+//++
+// double& Poly2::Coef(int dx, int dy)
+//	Retourne le coefficient de x^dx y^dy
+//	(avec aussi version const).
+//--
+
+//++
+double Poly2::operator()(double x, double y) const
+//
+//	Retourne la valeur en (x,y).
+//--
+{
+  UpdateDegIfDirty();
+  double res = 0;
+  double xPow = 1;
+  for (int dx=0; dx<=maxDegX; dx++) {
+    double yPow = 1;
+    for (int dy=0; dy<=maxDegY; dy++) {
+      res += Coef(dx,dy) * xPow * yPow;
+      yPow *= y;
+    }
+    xPow *= x;
+  }
+  return res;
+}
+
+//++
+double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
+                  int degreX, int degreY)
+//
+//	Ajustement par moindre carrés z = P(x,y), degrés partiels imposés.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  if (n != z.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degreX, degreY);
+
+  Matrix a((degreX+1)*(degreY+1), n);
+
+  for (int c=0; c<n; c++) {
+    double xPow = 1.0;
+    for (int dx = 0; dx <= degreX; dx++) {
+      double yPow = 1.0;
+      for (int dy = 0; dy <= degreY; dy++) {
+        a(IndCoef(dx,dy), c) = xPow*yPow;
+        yPow *= y(c);
+      }
+      xPow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,z,(Vector&)*this);
+  UpdateDeg();
+  return rc;
+}
+
+
+//++
+double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
+                  Vector const& errz2, int degreX, int degreY,
+                  Vector& errCoef)
+//
+//	Ajustement par moindre carrés z = P(x,y), degrés partiels imposés,
+//	et erreurs^2 sur z dans errz2.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  if (n != z.NElts()) THROW(sizeMismatchErr);
+  if (n != errz2.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degreX, degreY);
+  errCoef.Realloc((degreX+1)*(degreY+1));
+
+  Matrix a((degreX+1)*(degreY+1), n);
+
+  for (int c=0; c<n; c++) {
+    double xPow = 1.0;
+    for (int dx = 0; dx <= degreX; dx++) {
+      double yPow = 1.0;
+      for (int dy = 0; dy <= degreY; dy++) {
+        a(IndCoef(dx,dy), c) = xPow*yPow;
+        yPow *= y(c);
+      }
+      xPow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,z,errz2,(Vector&)*this,errCoef);
+  UpdateDeg();
+  return rc;
+}
+
+//++
+double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
+                  int degre)
+//
+//	Ajustement par moindre carrés z = P(x,y), degré total imposé.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  if (n != z.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degre, degre);   // certains vaudront 0, impose.
+
+  Matrix a((degre+1)*(degre+2)/2, n);
+  Vector cf((degre+1)*(degre+2)/2);
+#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
+
+  for (int c=0; c<n; c++) {
+    double xPow = 1.0;
+    for (int dx = 0; dx <= degre; dx++) {
+      double yPow = 1.0;
+      for (int dy = 0; dy <= degre; dy++) {
+        if (dy+dx <= degre)
+          a(C_INDEX(dx,dy), c) = xPow*yPow;
+        yPow *= y(c);
+      }
+      xPow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,z,cf);
+
+  for (int dx = 0; dx <= degre; dx++)
+    for (int dy = 0; dy <= degre; dy++)
+      if (dx+dy <= degre)
+        Coef(dx,dy) = cf(C_INDEX(dx,dy));
+      else
+        Coef(dx,dy) = 0;
+
+  UpdateDeg();
+  return rc;
+}
+
+
+//++
+double Poly2::Fit(Vector const& x, Vector const& y, Vector const& z,
+                  Vector const& errz2, int degre,
+                  Vector& errCoef)
+//
+//	Ajustement par moindre carrés z = P(x,y), degré total imposé,
+//	et erreurs^2 sur z dans errz2.
+//--
+{
+  int n = x.NElts();
+  if (n != y.NElts()) THROW(sizeMismatchErr);
+  if (n != z.NElts()) THROW(sizeMismatchErr);
+  if (n != errz2.NElts()) THROW(sizeMismatchErr);
+
+  Realloc(degre, degre);
+  errCoef.Realloc((degre+1)*(degre+1));
+#define C_INDEX(i,j) ((i) + (j)*(2*degre+3-(j))/2)
+
+  Matrix a((degre+1)*(degre+2)/2, n);
+  Vector cf((degre+1)*(degre+2)/2);
+  Vector ecf((degre+1)*(degre+2)/2);
+
+  for (int c=0; c<n; c++) {
+    double xPow = 1.0;
+    for (int dx = 0; dx <= degre; dx++) {
+      double yPow = 1.0;
+      for (int dy = 0; dy <= degre; dy++) {
+        if (dy+dx <= degre)
+          a(C_INDEX(dx,dy), c) = xPow*yPow;
+        yPow *= y(c);
+      }
+      xPow *= x(c);
+    }
+  }
+
+  LinFitter lf;
+  double rc = lf.LinFit(a,z,errz2,cf,ecf);
+
+
+  for (int dx = 0; dx <= degre; dx++)
+    for (int dy = 0; dy <= degre; dy++)
+      if (dx+dy <= degre) {
+        Coef(dx,dy) = cf(C_INDEX(dx,dy));
+        errCoef(IndCoef(dx,dy)) = ecf(C_INDEX(dx,dy));
+      } else {
+        Coef(dx,dy) = 0;
+        errCoef(IndCoef(dx,dy)) = 0;
+      }
+  UpdateDeg();
+  return rc;
+}
+
+//++
+void Poly2::Print(ostream& s) const
+//
+//	Impression sur stream s.
+//--
+{
+  UpdateDegIfDirty();
+  int nz=0;
+  int notfirst=0;
+  for (int dx = degX; dx>=0; dx--)
+    for (int dy= degY; dy>=0; dy--) {
+      double c = Coef(dx,dy);
+      if (c != 0) {
+        nz = 1;
+        if (notfirst && c > 0) {
+          s << "+";
+          notfirst = 1;
+        }
+        s << c << " ";
+        if (dx == 1) s << "* X ";
+        if (dx > 1) s << "* X^" << dx << " ";
+        if (dy == 1) s << "* Y ";
+        if (dy > 1) s << "* Y^" << dy << " ";
+        s << endl;
+    }
+  }
+  if (!nz) s << " 0 ";
+}
+
+//++
+// Titre	Opérations
+//--
+
+//++
+Poly2& Poly2::operator += (Poly2 const& b)
+//
+//--
+{
+  if (maxDegX < b.DegX() || maxDegY < b.DegY())
+    Realloc(b.DegX(),b.DegY());
+
+  UpdateDegIfDirty();
+
+  int mx = b.DegX();
+  int my = b.DegY();
+  for (int i=0; i<= mx; i++)
+    for (int j=0; j<= my; j++)
+      Coef(i,j) += b.Coef(i,j);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+Poly2& Poly2::operator -= (Poly2 const& b)
+//
+//--
+{
+  if (maxDegX < b.DegX() || maxDegY < b.DegY())
+    Realloc(b.DegX(),b.DegY());
+
+  UpdateDegIfDirty();
+
+  int mx = b.DegX();
+  int my = b.DegY();
+  for (int i=0; i<= mx; i++)
+    for (int j=0; j<= my; j++)
+      Coef(i,j) -= b.Coef(i,j);
+
+  UpdateDeg();
+  return *this;
+}
+
+//++
+Poly2& Poly2::operator *= (double a)
+//
+//--
+{
+  for (int i=0; i<NElts(); i++)
+    Element(i) *= a;
+
+  return *this;
+}
+
+//++
+Poly2 Poly2::Mult(Poly2 const& b) const
+//
+//--
+{
+  Poly2 c(DegX() + b.DegX(), DegY() + b.DegY());
+  UpdateDegIfDirty();
+  b.UpdateDegIfDirty();
+
+  for (int i=0; i<=DegX(); i++)
+    for (int j=0; j<=DegY(); j++)
+      for (int k=0; k<=b.DegX(); k++)
+        for (int l=0; l<=b.DegY(); l++)
+          c.Coef(i+k,j+l) += Coef(i,j)*b.Coef(k,l);
+  return c;
+}
+
+//++
+Poly2 Poly2::power(int n) const
+//
+//	Calcule le polynôme P(x,y)^n
+//--
+{
+  if (n < 0) THROW(rangeCheckErr);
+  if (n == 0) { Poly2 r(0); r.Coef(0,0) = 1; return r;}
+  if (n == 1) { return *this; }
+  return *this * power(n-1);
+}
+
+
+//++
+Poly2 Poly2::operator() (Poly const& a, Poly const& b) const
+//
+//	Substitution de deux polynômes en X et Y,
+//	P2(pa(x), pb(y)).
+//--
+{
+  UpdateDegIfDirty();
+  Poly2 c(maxDegX*a.Degre(), maxDegY*b.Degre());
+
+  for (int i=0; i<= degX; i++)
+    for (int j=0; j<= degY; j++) {
+      Poly2 d(a.power(i), b.power(j));
+      c += Coef(i,j) * d;
+    }
+
+  return c;
+}
+
+//++
+Poly2 Poly::operator() (Poly2 const& a) const
+//
+//	Substitution d'un polynôme à deux variables dans
+//	un polynôme à une variable, P(P2(x,y)).
+//--
+{
+  Poly2 c(a.MaxDegX()*Degre(), a.MaxDegY()*Degre());
+
+  for (int i=0; i<= Degre(); i++)
+    c += (*this)[i] * a.power(i);
+  return c;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void ObjFileIO<Poly2>::ReadSelf(PInPersist& is)
+{
+if(dobj==NULL) dobj=new Poly2;
+int_4 dgx, dgy;
+is >> dgx >> dgy;
+dobj->Realloc(dgx,dgy);
+is >> *((Vector *) dobj);
+dobj->UpdateDeg();
+}
+
+void ObjFileIO<Poly2>::WriteSelf(POutPersist& os) const
+{
+if(dobj == NULL) return;
+os << dobj->maxDegX << dobj->maxDegY;
+os << *((Vector *) dobj);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<Poly>
+#pragma define_template ObjFileIO<Poly2>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<Poly>;
+template class ObjFileIO<Poly2>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/poly.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/poly.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/poly.h	(revision 752)
@@ -0,0 +1,224 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: poly.h,v 1.4 1999-11-05 13:08:31 ansari Exp $
+//
+
+// Des polynomes avec des operations de bases et surtout des fits.
+
+#ifndef POLY_SEEN
+#define POLY_SEEN
+
+#include "objfio.h"
+#include <stdio.h>
+#include "peida.h"
+#include "tvector.h"
+#include "ppersist.h"
+#include "anydataobj.h"
+
+namespace SOPHYA {
+
+class Poly2;
+
+//////////////////////////////////////////////////////////////////////////
+class Poly : public Vector {
+  friend class ObjFileIO<Poly>;
+public:
+  Poly(int degre = 0);
+  Poly(Poly const& a);
+
+  enum {classId = ClassId_Poly1};
+  int_4  ClassId() const         { return classId; }
+
+  inline int Degre() const {UpdateDegIfDirty(); return deg;}
+
+  inline void Realloc(int n, bool force=false) {Vector::Realloc(n+1,force);}
+
+  inline double operator[](int i) const {return Element(i);}
+  inline double& operator[](int i) {dirty = 1; return Element(i);}
+  // Retourne le coefficient de degre i
+
+  double operator()(double x) const;
+  // Retourne la valeur prise en x.
+
+  void   Derivate();
+  // Derive le polynome en place
+
+  void   Derivate(Poly& der) const;
+  // Derive le polynome dans un autre
+
+  int    Roots(Vector& roots) const;
+  // retourne les racines si on peut les calculer...
+
+  int    Root1(double& r) const;
+  // special degre 1
+
+  int    Root2(double& r1, double& r2) const;
+  // special degre 2
+
+  Poly& operator = (Poly const& b);
+  Poly& operator += (Poly const& b);
+  Poly& operator -= (Poly const& b);
+
+  Poly& operator *= (double a);
+
+  Poly Mult(Poly const& b) const;
+
+  Poly power(int n) const;
+  Poly operator() (Poly const& b) const;
+  Poly2 operator() (Poly2 const& b) const;
+
+  void Print(ostream& s) const;
+
+  double Fit(Vector const& x, Vector const& y, int degre);
+  // Fit d'un polynome de degre donne sur les x et y.
+
+  double Fit(Vector const& x, Vector const& y, Vector const& erry2, int degre,
+            Vector& errCoef);
+  // En plus, on fournit les carres des erreurs sur y et on a les erreurs
+  // sur les coefficients dans un vecteur.
+
+private:
+  int dirty;
+  int_4 deg;
+  void UpdateDeg() const;
+  void UpdateDegIfDirty() const {if (dirty) UpdateDeg();}
+};
+
+inline Poly operator* (Poly const& a, Poly const& b)
+  { return a.Mult(b); }
+
+inline Poly operator+ (Poly const& a, Poly const& b)
+ { Poly c((a.Degre() > b.Degre())?(a.Degre()+1):(b.Degre()+1));
+   c = a; c += b; return c; }
+
+inline Poly operator- (Poly const& a, Poly const& b)
+  { Poly c((a.Degre() > b.Degre())?(a.Degre()+1):(b.Degre()+1));
+    c = a; c -= b; return c; }
+
+inline Poly operator* (double a, Poly const& b)
+  { Poly c(b); c *= a; return c; }
+
+inline ostream& operator << (ostream& s, const Poly& a)
+  { a.Print(s); return s; }
+
+//////////////////////////////////////////////////////////////////////////
+inline POutPersist& operator << (POutPersist& os, Poly & obj)
+  { ObjFileIO<Poly> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, Poly & obj)
+  { ObjFileIO<Poly> fio(&obj);  fio.Read(is);  return(is); }
+// Classe pour la gestion de persistance
+// ObjFileIO<Poly>
+
+//////////////////////////////////////////////////////////////////////////
+int binomial(int n, int p);
+
+//////////////////////////////////////////////////////////////////////////
+class Poly2 : public Vector {
+  friend class ObjFileIO<Poly2>;
+public:
+  Poly2(int degreX=0, int degreY=0);
+  // degres alloues.
+  Poly2(Poly const& polX, Poly const& polY);
+  Poly2(Poly2 const& a);
+
+  enum {classId = ClassId_Poly2};
+  int_4 ClassId() const         { return classId; }
+
+  inline int DegX() const {UpdateDegIfDirty(); return degX;}
+  inline int DegY() const {UpdateDegIfDirty(); return degY;}
+  inline int MaxDegX() const {return maxDegX;}
+  inline int MaxDegY() const {return maxDegY;}
+  inline int Deg()  const {UpdateDegIfDirty(); return deg;}
+  // les degres partiels en x et y, et totaux.
+
+  double operator()(double x, double y) const;
+  // retourne la valeur en (x,y)
+
+  inline int IndCoef(int dx, int dy) const {
+    if (dx>maxDegX || dy>maxDegY) THROW(rangeCheckErr);
+    return dx + (maxDegX+1)*dy;
+  }
+  // l'indice du coefficient dans le vecteur. Public uniquement parce
+  // que ca sert a recuperer les erreurs sur les coefficients lors
+  // d'un fit...
+
+  inline double Coef(int dx, int dy) const {
+    return (dx>maxDegX || dy>maxDegY) ? 0 : Element(IndCoef(dx,dy));
+  }
+  inline double& Coef(int dx, int dy) {
+    if (dx>maxDegX || dy>maxDegY) THROW(rangeCheckErr);
+    dirty = 1; return Element(IndCoef(dx,dy));
+  }
+  // retourne le coefficient de degre (dx,dy)
+
+  double Fit(Vector const& x, Vector const& y, Vector const& z,
+             int degreX, int degreY);
+  double Fit(Vector const& x, Vector const& y, Vector const& z,
+             Vector const& errz2, int degreX, int degreY,
+             Vector& errCoef);
+  // degres partiels imposes. cf Poly::Fit sinon
+
+
+  double Fit(Vector const& x, Vector const& y, Vector const& z,
+             int degre);
+  double Fit(Vector const& x, Vector const& y, Vector const& z,
+             Vector const& errz2, int degre,
+             Vector& errCoef);
+  // degre total impose. cf Poly::Fit sinon
+
+  Poly2& operator = (Poly2 const& b);
+
+  Poly2& operator += (Poly2 const& b);
+  Poly2& operator -= (Poly2 const& b);
+
+  Poly2& operator *= (double a);
+
+  Poly2 Mult(Poly2 const& b) const;
+
+  Poly2 power(int n) const;
+
+  Poly2 operator() (Poly const& px, Poly const& py) const;
+//  Poly2 operator() (Poly2 const& px, Poly2 const& py) const;
+
+  void Realloc(int degreX, int degreY);
+
+  void Print(ostream& s) const;
+
+private:
+  int dirty;
+  int_4 maxDegX;
+  int_4 maxDegY;
+  int degX;
+  int degY;
+  int deg;
+  void UpdateDeg() const;
+  void UpdateDegIfDirty() const {if (dirty) UpdateDeg();}
+};
+
+inline Poly2 operator* (Poly2 const& a, Poly2 const& b)
+  { return a.Mult(b); }
+
+inline Poly2 operator+ (Poly2 const& a, Poly2 const& b)
+  { Poly2 c(a); c += b; return c; }
+
+inline Poly2 operator- (Poly2 const& a, Poly2 const& b)
+  { Poly2 c(a); c -= b; return c; }
+
+inline Poly2 operator * (double a, Poly2 const& b)
+  { Poly2 c(b); c *= a; return c; }
+
+inline ostream& operator << (ostream& s, const Poly2& a)
+  { a.Print(s); return s; }
+
+//////////////////////////////////////////////////////////////////////////
+inline POutPersist& operator << (POutPersist& os, Poly2 & obj)
+  { ObjFileIO<Poly2> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, Poly2 & obj)
+  { ObjFileIO<Poly2> fio(&obj);  fio.Read(is);  return(is); }
+// Classe pour la gestion de persistance
+// ObjFileIO<Poly2>
+
+
+} // Fin du namespace
+
+#endif // POLY_SEEN
Index: /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.cc	(revision 752)
@@ -0,0 +1,193 @@
+#include "machdefs.h"
+#include "rk4cdifeq.h"
+#include "ctimer.h"
+#include <iostream.h>
+
+inline double max_dbl(double a, double b) { return ((a < b) ? b : a); } 
+
+//++
+// Class	RK4CDiffEq
+// Lib  	Outils++ 
+// include	rk4cdifeq.h
+//
+//	Classe de résolution d'équadif par la méthode de
+//	Runge-Kutta d'ordre 4 adaptatif.
+//	Voir DiffEqSolver et R4KDiffEq pour les méthodes.
+//
+//	On peut demander une précision relative ou absolue
+//	sur chacune des fonctions du système. Le pas d'intégration
+//	est adapté automatiquement pour fournir au moins 
+//	cette précision.
+//--
+
+//++
+// Links	Parents
+// RK4DiffEq
+// DiffEqSolver
+//--
+
+//++
+// Titre	Constructeurs
+//	Voir RK4DiffEq et DiffEqSolver
+//--
+
+//++
+RK4CDiffEq::RK4CDiffEq()
+//
+//--
+: RK4DiffEq(), eps(1.e-4), relAccuracy(true), accScale(10), yTemp(10), ySave(10)
+{}
+
+//++
+RK4CDiffEq::RK4CDiffEq(DiffEqFunction* f)
+//
+//--
+: RK4DiffEq(f), eps(1.e-4), relAccuracy(true), accScale(f->NFuncReal()), yTemp(f->NFuncReal()), ySave(f->NFuncReal())
+{}
+
+//++
+RK4CDiffEq::RK4CDiffEq(DIFEQFCN1 f)
+//
+//--
+: RK4DiffEq(f), eps(1.e-4), relAccuracy(true), accScale(1), yTemp(1), ySave(1)
+{}
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+// RK4CDiffEq& RK4CDiffEq::Accuracy(double eps)
+//	Fixe la précision requise sur les fonctions. Cette précision
+//	est par défaut relative. Elle peut être absolue, auquel cas
+//	il faut fixer, pour chaque fonction, un facteur d'échelle, et
+//	la précision sur chaque fonction est alors scale[i]*eps.
+//--
+
+RK4CDiffEq& 
+RK4CDiffEq::Accuracy(double x)
+{
+  eps = x;
+  return *this;
+}
+
+//++
+RK4CDiffEq&  
+RK4CDiffEq::AbsAccuracy(Vector const& vScal)
+//
+//	On souhaite une précision absolue, et le vecteur vScal contient
+//	le facteur d'échelle pour chaque fonction (voir Accuracy).
+//--
+{
+  accScale = vScal;
+  relAccuracy = false;
+  return *this;
+}
+
+//++
+RK4CDiffEq&  
+RK4CDiffEq::AbsAccuracy(double scal)
+//
+//	On souhaite une précision absolue, et le vecteur scal contient
+//	le facteur d'échelle à appliquer à toutes les fonctions.
+//	La précision absolue souhaitée est alors eps*scal.
+//--
+{
+  for (int i=0; i<accScale.NElts(); i++)
+    accScale(i) = scal;
+  relAccuracy = false;
+  return *this;
+}
+
+//++
+RK4CDiffEq&  
+RK4CDiffEq::RelAccuracy()
+//
+//	On souhaite une précision relative. En quelque sorte, le facteur d'échelle 
+//	pour chaque fonction est alors la valeur de la fonction.
+//--
+{
+  relAccuracy = true;
+  return *this;
+}
+
+static const double pgrow   = -0.20;
+static const double pshrink = -0.25;
+static const double safety  = 0.9;
+static const double errcon = pow((4/safety),1/pgrow);
+
+void
+RK4CDiffEq::RKCStep(Vector& newY, Vector const& y0, Vector const& yScale, 
+	       double dttry, double& dtdone, double& dtnext)
+{
+  double err;
+  ySave = y0;
+  do {
+    // Deux petits pas
+    RKStep(yTemp, ySave, dttry/2.);
+    RKStep(newY, yTemp, dttry/2.);
+    
+    // Un grand pas
+    RKStep(yTemp, ySave, dttry);
+    
+    yTemp -= newY;   // l'erreur courante
+
+    err = 0;
+    for (int i=0; i<yTemp.NElts(); i++) 
+      err = max_dbl(fabs(yScale(i) ? (yTemp(i)/yScale(i)) : yTemp(i)), err);
+    
+    err /= eps;
+    if (err > 1) 
+      dttry *= safety*pow(err,pshrink);
+    else {
+      dtdone = dttry;
+      if (err > errcon)
+	dtnext = safety*dttry*pow(err,pgrow);
+      else
+	dtnext = dttry*4;
+    }
+  }  while (err > 1);
+  
+  // Et on corrige a l'ordre 5
+
+  newY += yTemp/15.;
+}
+
+void
+RK4CDiffEq::SolveArr(Matrix& y, double* t, double tf, int n)
+{
+  //TIMEF;
+  // Les intervalles a stocker dans la matrice des resultats
+
+  double dxres = (tf - mXStart)/n;
+
+  Vector yt = mYStart;
+  
+  k1.Realloc(mFunc->NFuncReal());
+  k2.Realloc(mFunc->NFuncReal());
+  k3.Realloc(mFunc->NFuncReal());
+  k4.Realloc(mFunc->NFuncReal());
+  yTemp.Realloc(mFunc->NFuncReal());
+  ySave.Realloc(mFunc->NFuncReal());
+
+  double x = mXStart;
+  double step = mStep;
+  double nstep;
+
+  for (int i=0; i<n; i++) {
+    double xEndStep = (i+1)*dxres + mXStart;
+    do {
+      if (relAccuracy) accScale = yt;
+      if ((x+step-xEndStep)*(x+step-mXStart)>0) step = xEndStep-x;
+      RKCStep(yt, yt, accScale, step, step, nstep);
+      x += step;
+      //cout << x << " " << step << endl;
+      step = nstep;
+    } while ((x-xEndStep)*(x-mXStart) < 0);
+    for (int j=0; j<mFunc->NFunc(); j++)
+      y(i,j) = yt(j);
+    t[i] = xEndStep;
+    //cout << "fin boucle "<<i<<"  "<<x<<"  "<<yt(0)<<endl;
+  }
+   
+}
Index: /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/rk4cdifeq.h	(revision 752)
@@ -0,0 +1,46 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef RK4CDIFEQ_H_SEEN
+#define RK4CDIFEQ_H_SEEN
+
+#include "difeq.h"
+
+namespace SOPHYA {
+
+// <summary> Runge-Kutta ordre 4 adaptatif </summary>
+// Runge-Kutta ordre 4 adaptatif, avec correction du pas d'integration
+class RK4CDiffEq : public RK4DiffEq {
+public:
+  // Constructeurs. Voir <linkto class=DiffEqSolver>DiffEqSolver</linkto>
+  // <group>
+  RK4CDiffEq();
+  RK4CDiffEq(DiffEqFunction*);
+  RK4CDiffEq(DIFEQFCN1);
+  // </group>
+
+  // Precision souhaitee, en absolu ou relatif, independamment pour chaque
+  // fonction ou globalement
+  // <group>
+  RK4CDiffEq& Accuracy(double);
+  RK4CDiffEq& AbsAccuracy(Vector const& vScal);
+  RK4CDiffEq& AbsAccuracy(double scal);
+  RK4CDiffEq& RelAccuracy();
+  // </group>
+  
+  // Implementation RK4 adaptatif
+  virtual void SolveArr(Matrix& y, double* t, double tf, int n);
+
+protected:
+  // Un pas adaptatif
+  void RKCStep(Vector& newY, Vector const& y0, Vector const& yScale, 
+	       double dttry, double& dtdone, double& dtnext);
+
+  double eps;
+  bool   relAccuracy;
+  Vector accScale;
+  Vector yTemp; // Pour ne pas reallouer
+  Vector ySave;
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/rzimage.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/rzimage.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/rzimage.cc	(revision 752)
@@ -0,0 +1,902 @@
+//  Classe image generique      
+//                  E.Aubourg , E. Lesquoy  01-03/95 
+//                  Modifs R. Ansari   04/95
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+//  $Id: rzimage.cc,v 1.6 1999-10-25 16:40:03 ansari Exp $
+
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "rzimage.h"
+#include "dvlist.h"
+#include "generalfit.h"
+
+
+/* .........  Methodes de la classe  RzVect    .........   */
+//++
+// Class 	RzVect<T>
+// Lib 		Images++
+// include	rzvect.h
+//
+//	Cette classe permet de construire des vecteurs de types T 
+//	"(short, int, float, double, ...)". Cette classe est utilisee
+//	par la classe *RzImage*.
+//--
+
+//++
+// Titre	Constructeurs
+//--
+//++
+// RzVect<T>(int n)
+//	Constructeur avec allocation d'espace pour "n" elements
+//	"RzVect<uint_1>, RzVect<uint_2>, RzVect<int_2>, RzVect<int_4>"
+//	" RzVect<r_4>, RzVect<r_8>"
+// RzVect<T>(int n, T* data)
+//	Constructeur avec specification du tableau de stockage des elements
+//	*Attention* "data" doit etre alloue a la bonne taille ("n")
+// ~RzVect<T>()
+//	Destructeur - Libere l'espace de stockage des elements si l'objet a
+//	ete construit par le premier constructeur
+//	
+//--
+
+/* --Methode-- */
+template <class T>
+RzVect<T>::RzVect(int n)
+: p(new T[n]), nElt(n), nImgRef(1), shareable(1), ownTable(1)
+{END_CONSTRUCTOR}
+
+/* --Methode-- */
+template <class T>
+RzVect<T>::RzVect(int n, T* data)
+: p(data), nElt(n), nImgRef(0), shareable(0), ownTable(0)
+{END_CONSTRUCTOR}
+
+
+/* --Methode-- */
+template <class T>
+RzVect<T>::~RzVect()
+{
+  if (ownTable) delete[] p;
+  #ifdef DEBUG
+  p = (T*) -1;
+  #endif
+}
+
+//++
+// Titre	Acces aux elements
+//--
+//++
+// T& operator[](int i)
+//	Acces a l'element "i" (lecture/ecriture)
+// int  IElem(int k)
+//      Valeur converti en entier "(int)" de l'element "k" (lecture)
+// float  FElem(int k)
+//      Valeur converti en reel "(float)" de l'element "k" (lecture)
+// double  DElem(int k)
+//      Valeur converti en reel "(double)" de l'element "k" (lecture)
+//--
+
+/* ..............   Classe  RzImage    ...............   */
+
+//++
+// Class 	RzImage
+// Lib 		Images++
+// include	rzimage.h
+//
+//	Cette classe permet de gerer les donnees correspondantes a une image.
+//	Une image est un tableau rectangulaire de valeurs de pixels.
+//	*RzImage* offre la possibilite de creer des images de valeurs de
+//	pixels entier ou flottant "(unsigned char uint_1, short int_2," 
+//	"unsigned short uint_2, int int_4, float r_4, double r_8)"
+//	les objets de la classe RzImage sont faiblement types. La classe
+//      *Image<T>* qui derive de RzImage permet la creation d'objets
+//	types. Chaque image peut contenir un objet *DVList* permettant 
+//	a l'utilisateur d'associer un ensemble de valeurs a l'image. 
+//--
+//++
+// Links	Parents
+// PPersist
+//--
+//++
+// Links	Descendants
+// Image<T>
+// FitsImage<T>
+//--
+//++
+// Links	Voir aussi
+// DVList
+//--
+
+//++
+// Titre	Constructeurs
+//--
+//++
+// RzImage()
+//	Creation d'une image vide, non typee.
+// RzImage(PBaseDataTypes dType, int sizx, int sizy, -
+//         int imgId = 0, char const * imgName = 0)
+//	Creation d'une image de taille "sizx * sizy" pixels , de type "dType".
+//      (dType = kuint_1, kuint_2, kint_2, kint_4, kr_4, kr_8).
+//      "imgId" et "imgName" permettent d'indiquer une identification optionnelle.
+// RzImage(const RzImage&, int sharePixels=0)
+//	Constructeur par copie. Permet de partager le tableau des pixels (RzVect)
+//	si "sharePixels" non nul (<> 0)
+// RzImage(char *flnm)
+//	Les RzImage etant des objets persistants (*PPersist*), ils peuvent etre
+//	instancies a partir d'un fichier (nom = "flnm") ecrit par la methode Write()
+// ~RzImage()
+//	Destructeur. 
+//  operator= (RzImage const &)
+//	Copie les valeurs de pixels d'une image a l'autre.
+//	Si la 1ere image a son propre tableau de pixel, il faut que 
+//	les deux images aient le meme type de pixels et la meme taille.
+//	Sinon, une exception ("typeMismatchErr" ou "sizeMismatchErr") est 
+//	generee.  
+//--
+
+/* --Methode-- */
+RzImage::RzImage(PBaseDataTypes dType)
+: dataType(dType)
+{
+  voidP = NULL;
+  isFits = 0;
+  siz_x = siz_y = 0;
+  vect.u2 = 0;
+  mInfo = NULL;
+  SetNameId(0, "");
+  SetOrg(0, 0);
+  SetPxSize();
+  SetAtt();
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+RzImage::RzImage(PBaseDataTypes dType, int sizx, int sizy, int imgId, char const* imgName)
+: dataType(dType)
+{
+  isFits = 0;
+  siz_x = siz_y = 0;
+  vect.u2 = 0;
+  voidP = NULL;
+  mInfo = NULL;
+  Allocate(dType, sizx, sizy);
+  SetNameId(imgId, imgName);
+  SetOrg(0, 0);
+  SetPxSize();
+  SetAtt();
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+RzImage::RzImage(const RzImage& src, int sharePixels)
+: dataType(kpbdt_unknown)
+{
+  isFits = 0;
+  siz_x = siz_y = 0;
+  vect.u2 = 0;
+  voidP = NULL;
+  mInfo = NULL;
+  if (sharePixels) {
+    ImgVectP vs = src.vect;
+    Allocate(src.PixelType(), src.XSize(), src.YSize(), &vs); 
+  }
+  else { 
+    Allocate(src.PixelType(), src.XSize(), src.YSize(), NULL);
+    memcpy(voidP, src.voidP, siz_x*siz_y*DataSize(dataType)); 
+  }
+
+  SetNameId(src.id, src.name);
+  SetOrg(src.XOrg(), src.YOrg());
+  SetPxSize(src.XPxSize(), src.YPxSize());    
+  SetAtt(src.nbNul, src.nbSat,
+       src.minPix, src.maxPix, src.moyPix, src.sigPix,
+       src.fond, src.sigmaFond);
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+RzImage::RzImage(char *flnm)
+: dataType(kpbdt_unknown)
+{
+  isFits = 0;
+  vect.u2 = 0;
+  voidP = NULL;
+  mInfo = NULL;
+  PInPersist s(flnm);
+  Read(s);
+  END_CONSTRUCTOR
+}
+
+/* --Methode-- */
+RzImage::~RzImage()
+{
+if (mInfo) delete mInfo;
+DeAllocPixels();
+}
+
+/* --Methode-- */
+RzImage& RzImage::operator = (const RzImage& src)
+{
+
+if (PixelType() >= 0)
+  {
+  if (src.PixelType() != PixelType())
+    THROW(typeMismatchErr);
+  if (siz_x != src.siz_x || siz_y != src.siz_y) 
+    THROW(sizeMismatchErr);
+  } 
+else  Allocate(src.PixelType(), src.siz_x, src.siz_y);
+  
+memcpy(voidP, src.voidP, siz_x*siz_y*DataSize(dataType));
+SetNameId(src.id, src.name);
+SetOrg(src.XOrg(), src.YOrg());
+SetPxSize(src.XPxSize(), src.YPxSize());    
+SetAtt(src.nbNul, src.nbSat,
+       src.minPix, src.maxPix, src.moyPix, src.sigPix,
+       src.fond, src.sigmaFond);
+ 
+return(*this); 
+}
+
+/* --Methode-- */
+void RzImage::Allocate(PBaseDataTypes dType, int sizx, int sizy, ImgVectP* pvpsh)
+// ATTENTION : Si pvpsh non nul, on partage les pixels 
+{
+  DeAllocPixels(); // EA 090998 -- memory leak...
+  siz_x = sizx;
+  siz_y = sizy;
+  if ((int)dataType<=0)  dataType = dType; // Sinon ERREUR. Exception?
+  switch (dataType) {
+  case kuint_1:
+    vect.u1 = NULL;
+    if (pvpsh)
+      if (pvpsh->u1)  
+        { ASSERT(pvpsh->u1->Shareable());
+        vect.u1 = pvpsh->u1;  vect.u1->NImgRef()++; }
+    if (!vect.u1)  vect.u1 = new RzVect<uint_1> (siz_x * siz_y);
+    voidP   = vect.u1->p;
+    IVal_p = &RzImage::IVal_u1;
+    FVal_p = &RzImage::FVal_u1;
+    DVal_p = &RzImage::DVal_u1;
+    break;
+  case kuint_2:
+    vect.u2 = NULL;
+    if (pvpsh)
+      if (pvpsh->u2)  
+        { ASSERT(pvpsh->u2->Shareable());
+        vect.u2 = pvpsh->u2;  vect.u2->NImgRef()++; }
+    if (!vect.u2)  vect.u2 = new RzVect<uint_2> (siz_x * siz_y);
+    voidP   = vect.u2->p;
+    IVal_p = &RzImage::IVal_u2;
+    FVal_p = &RzImage::FVal_u2;
+    DVal_p = &RzImage::DVal_u2;
+    break;
+  case kint_2:
+    vect.i2 = NULL;
+    if (pvpsh)
+      if (pvpsh->i2)  
+        { ASSERT(pvpsh->i2->Shareable());
+        vect.i2 = pvpsh->i2;  vect.i2->NImgRef()++; }
+    if (!vect.i2)  vect.i2 = new RzVect<int_2> (siz_x * siz_y);
+    voidP   = vect.i2->p;
+    IVal_p = &RzImage::IVal_i2;
+    FVal_p = &RzImage::FVal_i2;
+    DVal_p = &RzImage::DVal_i2;
+    break;
+  case kint_4:
+    vect.i4 = NULL;
+    if (pvpsh)
+      if (pvpsh->i4)  
+        { ASSERT(pvpsh->i4->Shareable());
+        vect.i4 = pvpsh->i4;  vect.i4->NImgRef()++; }
+    if (!vect.i4)  vect.i4 = new RzVect<int_4> (siz_x * siz_y);
+    voidP   = vect.i4->p;
+    IVal_p = &RzImage::IVal_i4;
+    FVal_p = &RzImage::FVal_i4;
+    DVal_p = &RzImage::DVal_i4;
+    break;
+  case kr_4:
+    vect.r4 = NULL;
+    if (pvpsh)
+      if (pvpsh->r4)  
+        { ASSERT(pvpsh->r4->Shareable());
+        vect.r4 = pvpsh->r4;  vect.r4->NImgRef()++; }
+    if (!vect.r4)  vect.r4 = new RzVect<r_4> (siz_x * siz_y);
+    voidP   = vect.r4->p;
+    IVal_p = &RzImage::IVal_r4;
+    FVal_p = &RzImage::FVal_r4;
+    DVal_p = &RzImage::DVal_r4;
+    break;
+  case kr_8:
+    vect.r8 = NULL;
+    if (pvpsh)
+      if (pvpsh->r8)  
+        { ASSERT(pvpsh->r8->Shareable());
+        vect.r8 = pvpsh->r8;  vect.r8->NImgRef()++; }
+    if (!vect.r8)  vect.r8 = new RzVect<r_8> (siz_x * siz_y);
+    voidP   = vect.r8->p;
+    IVal_p = &RzImage::IVal_r8;
+    FVal_p = &RzImage::FVal_r8;
+    DVal_p = &RzImage::DVal_r8;
+    break;
+  default:
+    printf("RzImage::Allocate Error - Unsupported DataType= %d \n", (int)dataType);
+    break;    
+  } 
+}
+
+/* --Methode-- */
+void RzImage::SetPixels(PBaseDataTypes dType, int sizx, int sizy, void* data)
+{
+  if (voidP != data)  DeAllocPixels();
+  siz_x = sizx;
+  siz_y = sizy;
+  //  if (dataType<0) (int&) dataType = (int)dType; // Sinon ERREUR. Exception?
+  if (dataType<0)  dataType = dType; // Sinon ERREUR. Exception?
+  switch (dataType) {
+  case kuint_1:
+    vect.u1 = new RzVect<uint_1> (siz_x * siz_y, (uint_1*)data);
+    voidP   = vect.u1->p;
+    IVal_p = &RzImage::IVal_u1;
+    FVal_p = &RzImage::FVal_u1;
+    DVal_p = &RzImage::DVal_u1;
+    break;
+  case kuint_2:
+    vect.u2 = new RzVect<uint_2> (siz_x * siz_y, (uint_2*)data);
+    voidP   = vect.u2->p;
+    IVal_p = &RzImage::IVal_u2;
+    FVal_p = &RzImage::FVal_u2;
+    DVal_p = &RzImage::DVal_u2;
+    break;
+  case kint_2:
+    vect.i2 = new RzVect<int_2> (siz_x * siz_y, (int_2*)data);
+    voidP   = vect.i2->p;
+    IVal_p = &RzImage::IVal_i2;
+    FVal_p = &RzImage::FVal_i2;
+    DVal_p = &RzImage::DVal_i2;
+    break;
+  case kint_4:
+    vect.i4 = new RzVect<int_4> (siz_x * siz_y, (int_4*)data);
+    voidP   = vect.i4->p;
+    IVal_p = &RzImage::IVal_i4;
+    FVal_p = &RzImage::FVal_i4;
+    DVal_p = &RzImage::DVal_i4;
+    break;
+  case kr_4:
+    vect.r4 = new RzVect<r_4> (siz_x * siz_y, (r_4*)data);
+    voidP   = vect.r4->p;
+    IVal_p = &RzImage::IVal_r4;
+    FVal_p = &RzImage::FVal_r4;
+    DVal_p = &RzImage::DVal_r4;
+    break;
+  case kr_8:
+    vect.r8 = new RzVect<r_8> (siz_x * siz_y, (r_8*)data);
+    voidP   = vect.r8->p;
+    IVal_p = &RzImage::IVal_r8;
+    FVal_p = &RzImage::FVal_r8;
+    DVal_p = &RzImage::DVal_r8;
+    break;
+  default:
+    printf("RzImage::SetPixels Error - Unsupported DataType= %d \n", (int)dataType);
+    break;    
+  } 
+}
+
+/* --Methode-- */
+void RzImage::DeAllocPixels()
+{
+if (!voidP)  return;
+  switch (dataType) {
+  case kuint_1:
+    if (! (--vect.u1->NImgRef()))
+      delete vect.u1;
+    vect.u1 = NULL;
+    break;
+  case kuint_2:
+    if (! (--vect.u2->NImgRef()))
+      delete vect.u2;
+    vect.u2 = NULL;
+    break;
+  case kint_2:
+    if (! (--vect.i2->NImgRef()))
+      delete vect.i2;
+    vect.i2 = NULL;
+    break;
+  case kint_4:
+    if (! (--vect.i4->NImgRef()))
+      delete vect.i4;
+    vect.i4 = NULL;
+    break;
+  case kr_4:
+    if (! (--vect.r4->NImgRef()))
+      delete vect.r4;
+    vect.r4 = NULL;
+    break;
+  case kr_8:
+    if (! (--vect.r8->NImgRef()))
+      delete vect.r8;
+    vect.r8 = NULL;
+    break;
+  default:
+    printf("RzImage::DeAllocPixels Error - Unsupported DataType= %d \n", (int)dataType);
+    break;    
+  }
+
+voidP = NULL;
+siz_x = siz_y = 0;
+vect.u2 = NULL;
+}
+
+//++
+// Titre	Informations globales
+//--
+//++
+// int_4  XSize(), YSize()
+//	Taille de l'image en X, Y
+// int_4  XOrg(),  YOrg()
+//	Origines (X,Y) de l'image. Cette origine permet en particulier 
+//	de conserver l'information de decalage, quand l'image est 
+//	extraite d'une image plus grande. Les valeurs de l'origine
+//	peuvent etre modifiees par la methode "SetOrg()"
+// void SetOrg(int_4 orgx, int_4 orgy)
+//	Modifie l'origine de l'image
+// float  XPxSize()  YPxSize()
+//	Taille des pixels (X,Y) de l'image. Peuvent etre modifiees
+//	par la methode "SetPxSize()"
+// void SetPxSize()
+// PBaseDataTypes   PixelType()
+//	Type des pixels de l'image "(kint_2, kint_4, kr_4, ...)"
+// char * PixelNomType()
+//	Nom du Type des pixels de l'image. Chaine de caracteres = kint_2, kint_4, ...
+// char * Nom()
+//	Nom de l'image. "Ident()" retourne l' "id" associe a l'image
+// void SetNameId(int imgid = 0, char const * nom = NULL)
+//	Permet de modifier l'identificateur et le nom d'une image
+// void SetAtt(int nbnul = -1, int nbsat = -1, -
+//             float minpix = 0, float maxpix = -1., -
+//             float moypix = 0, float sigpix = -1., -
+//             float fnd = -1., float sigfnd = -1.)
+//	Des donnees membres du type reels (float) 
+//	"fond, sigmaFond, minPix, moyPix,sigPix" et entier (int) "nbNul, nbSat"
+//	sont associees a chaque image. Leurs valeurs peuvent etre modifiees
+//	a l'aide de la methode "SetAtt()" ou la methode "CheckDyn()" 
+// int   CheckDyn(double min=-9.e19, double max=9.e19)
+//	Cette methode retourne le nombre de pixels hors dynamique "( <min ou >max )"
+//	Met a jour les donnees membres "min/maxPix nbNul/Sat".
+//	Calcule aussi la moyenne et le sigma des pixels -> "moyPix, sigPix"
+//--
+
+//++
+// Titre	I/O
+//--
+//++
+// void  Write(string const& flnm)
+// void  Save(char *flnm)
+//	Ecrit l'image en format PPF (PPersist) dans le fichier "flnm"
+// void  Read(string const& flnm)
+//	Lit le fichier "flnm" (au format PPF)
+//--
+
+/* --Methode-- */
+DVList&  RzImage::Info()
+{
+if (mInfo == NULL)  mInfo = new DVList;
+return(*mInfo);
+}
+
+/* --Methode-- */
+void RzImage::SetOrg(int_4 orgx, int_4 orgy)
+{
+org_x = orgx;   org_y = orgy;
+return;
+}
+
+/* --Methode-- */
+void RzImage::SetPxSize(float szx, float szy)
+{
+if (szx <= 0.)  szx = 1.;
+if (szy <= 0.)  szy = 1.;
+pxsz_x = szx;   pxsz_y = szy;
+return;
+}
+
+/* --Methode-- */
+void RzImage::SetAtt(int nbnul, int nbsat,
+              float minpix, float maxpix,
+              float moypix, float sigpix,
+              float fnd, float sigfnd)
+{
+nbNul = nbnul;  nbSat = nbsat;
+minPix = minpix;   maxPix = maxpix;
+moyPix = moypix; sigPix = sigpix;
+fond = fnd;  sigmaFond = sigfnd;
+return;
+}
+
+
+/* --Methode-- */
+void RzImage::SetNameId(int imgid, char const * nom)
+{
+id = imgid;
+if (nom)  { strncpy(name, nom, 32);  name[31] = '\0'; }
+else name[0] = '\0';
+return;
+}
+
+/* --Methode-- */
+void RzImage::Save(char *flnm)
+{
+POutPersist s(flnm);
+Write(s);
+}
+
+/* --Methode-- */
+void RzImage::WriteSelf(POutPersist& s) const
+
+/*  Ecriture de la structure image ds un fichier de maniere */ 
+/* brute - (Dump memoire)                                   */
+/* Pour utilisation par PPersist::Write()                   */
+
+{
+char buf[256];
+unsigned long sz;
+int i,j;
+int_4 itab[5];
+
+sprintf(buf,"\nRzImage(%s)[%d*%d]  Org: %d %d  PxSz: %g %g (Id=%d Nom=%s)\n",
+        PixelNomType(),siz_x, siz_y, org_x, org_y, pxsz_x, pxsz_y, id, name);
+i = strlen(buf); 
+sprintf(buf+i,"NbSat,Nul=%d %d Min,Max= %g %g Moy,Sig= %g %g Fond,Sig= %g %g\n",
+        nbSat, nbNul, minPix, maxPix, moyPix, sigPix, fond, sigmaFond);
+i += strlen(buf+i);
+for(j=i; j<255; j++)  buf[j] = ' ';  buf[255] = '\0';
+s.PutBytes(buf, 256);
+
+itab[0] = (int)dataType;
+itab[1] = siz_x;  itab[2] = siz_y;
+itab[3] = itab[4] = 0; 
+if (mInfo)  itab[3] = 1;    // Has DVList as info
+s.PutI4s(itab, 5);
+
+s.PutR4(fond);
+s.PutR4(sigmaFond);
+s.PutI4(nbNul);
+s.PutI4(nbSat);
+s.PutR4s(&minPix, 4); // minPix -> sigPix
+
+s.PutI4(org_x);
+s.PutI4(org_y);
+s.PutR4(pxsz_x);
+s.PutR4(pxsz_y);
+s.PutI4(isFits);
+s.PutBytes(name, 32);
+s.PutI4(id);
+
+sz = XSize()*YSize();
+switch (dataType) {
+case kuint_1:
+  s.PutBytes(voidP, sz);
+  break;
+case kuint_2:
+  s.PutU2s((uint_2*)voidP, sz);
+  break;
+case kint_2:
+  s.PutI2s((int_2*)voidP, sz);
+  break;
+case kint_4:
+  s.PutI4s((int_4*)voidP, sz);
+  break;
+case kr_4:
+  s.PutR4s((r_4*)voidP, sz);
+  break;
+case kr_8:
+  s.PutR8s((r_8*)voidP, sz);
+  break;
+default:
+  printf("RzImage::WriteSelf Error - Unsupported DataType= %d \n", (int)dataType);
+  break;    
+} 
+
+if (mInfo) s << (*mInfo);
+return;
+}
+
+
+/* --Methode-- */
+void RzImage::ReadSelf(PInPersist& s)
+/*  Relecture de fichier cree par WriteSelf()    */
+/*  Pour utilisation par PPersist::Read()        */
+{
+char buf[256];
+unsigned long sz;
+int_4 itab[5];
+int_4 opt;
+
+s.GetBytes(buf, 256);
+s.GetI4s(itab, 5);
+opt = (int_4)PixelType();
+if ((opt > 0) && (opt != itab[0]))  { 
+    cerr << "RzImage::ReadSelf() Image type (=" << opt 
+         << ") mismatch (type in file=" << itab[0] << ")" << endl;
+    THROW(typeMismatchErr); }
+Allocate((PBaseDataTypes)itab[0], itab[1], itab[2]);
+
+s.GetR4(fond);
+s.GetR4(sigmaFond);
+s.GetI4(nbNul);
+s.GetI4(nbSat);
+s.GetR4s(&minPix, 4); // minPix -> sigPix
+
+s.GetI4(org_x);
+s.GetI4(org_y);
+s.GetR4(pxsz_x);
+s.GetR4(pxsz_y);
+s.GetI4(isFits);
+s.GetBytes(name, 32);
+s.GetI4(id);
+
+sz = XSize()*YSize();
+switch (dataType) {
+case kuint_1:
+  s.GetBytes(voidP, sz);
+  break;
+case kuint_2:
+  s.GetU2s((uint_2*)voidP, sz);
+  break;
+case kint_2:
+  s.GetI2s((int_2*)voidP, sz);
+  break;
+case kint_4:
+  s.GetI4s((int_4*)voidP, sz);
+  break;
+case kr_4:
+  s.GetR4s((r_4*)voidP, sz);
+  break;
+case kr_8:
+  s.GetR8s((r_8*)voidP, sz);
+  break;
+default:
+  printf("RzImage::ReadSelf Error - Unsupported DataType= %d \n", (int)dataType);
+  break;    
+} 
+
+if (itab[3])  // has info
+  { if (mInfo == NULL)  mInfo = new DVList;
+  s >> (*mInfo); }
+
+return;
+}
+
+
+//++
+// Titre	Impression
+//--
+//++
+// void  Print(ostream& os)
+//	Imprime sur le flot "os" les informations globales concernant l'image
+// void  Print()
+//	Imprime (sur cout) les informations globales concernant l'image
+// ostream&   operator << (ostream& s, RzImage const & img)
+//      sortie sur flot "s" (Appel a "Print(s)").
+//--
+
+/* --Methode-- */
+void RzImage::Print(ostream& os) const
+{
+char buff[256];
+os << " ---- RzImage::Print() ----- \n";
+sprintf(buff, "RzImage(%s)[%d*%d]  Org: %d %d  PxSz= %g %g (Id=%d Nom=%s)\n",
+       PixelNomType(),siz_x, siz_y, org_x, org_y, pxsz_x, pxsz_y, id, name);
+os << buff;
+sprintf(buff, "NbSat,Nul=%d %d Min,Max= %g %g Moy,Sig= %g %g Fond,Sig= %g %g\n",
+       nbSat, nbNul, minPix, maxPix, moyPix, sigPix, fond, sigmaFond);
+os << buff;
+if (mInfo) mInfo->Print(os);
+os << endl;
+}
+
+/* --Methode-- */
+int RzImage::CheckDyn(double min, double max)
+
+/*  Cette methode retourne le nombre de pixels hors dynamique    */
+/* ds le pave ( <min ou >max )                                   */
+/* Met a jour la structure image Min/MaxPix nbNul/Sat            */
+/* Calcule aussi la moyenne et le sigma des pixels, met a jour   */
+/* moypix et sigpix dans la structure                            */
+
+{
+float pixv=0;
+double dv;
+
+float minadu = PutInRange(min, pixv); 
+float maxadu = PutInRange(max, pixv);
+float minpix = PutInRange(maxadu+1, pixv);
+float maxpix = PutInRange(minadu-1, pixv);
+
+double m = 0.;
+double s = 0.;
+int n9 = 0;
+int n0 = 0;
+int n = XSize()*YSize();
+for(int i=0; i<n; i++) 
+  {
+  pixv = FValue(i);
+  if (pixv <= maxadu && pixv >= minadu) 
+    {  
+    if (pixv < minpix)  minpix = pixv;
+    else if (pixv > maxpix)  maxpix = pixv; 
+    dv = (double)pixv;
+    m += dv;  s += (dv*dv);
+    }
+  else 
+    {  
+    if (pixv > maxadu)  n9++;
+    if (pixv < minadu)  n0++; 
+    }
+  }
+
+nbNul = n0;
+nbSat = n9;
+minPix = minpix;
+maxPix = maxpix;
+
+n -= (n0+n9);
+if (n > 0)
+  { dv = (double)n;  m /= dv;  s = s/dv - m*m;
+  if (s>0.)  s = sqrt(s);  else s = 0.;
+  moyPix = m;  sigPix = s; }
+else { moyPix = 0.;  sigPix = -1.; }
+
+return(n0+n9);
+}
+
+////////////////////////////////////////////////////////////////
+//++
+RzImage* RzImage::FitResidus(GeneralFit& gfit)
+//
+//	Retourne une RzImage R4 contenant les residus du fit ``gfit''.
+//--
+{
+if(XSize()<=0 || YSize()<=0) return NULL;
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL) return NULL;
+Vector par = gfit.GetParm();
+RzImage* img = new RzImage(DataType((r_4)0.),XSize(),YSize());
+img->SetOrg(XOrg(),YOrg());
+img->SetPxSize(XPxSize(),YPxSize());
+r_4* ptr = (r_4 *) img->VoidP();
+for(int i=0;i<XSize();i++) {
+  double x[2];
+  x[0] = XOrg()+(i+0.5)*XPxSize();
+  for(int j=0;j<YSize();j++) {
+    x[1] = YOrg()+(j+0.5)*YPxSize();
+    *(ptr+i+j*img->siz_x) = FValue(i,j) - (float) f->Value(x,par.Data());
+  }
+}
+return img;
+}
+
+//++
+RzImage* RzImage::FitFunction(GeneralFit& gfit)
+//
+//	Retourne RzImage R4 contenant la fonction du fit ``gfit''.
+//--
+{
+if(XSize()<=0 || YSize()<=0) return NULL;
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL) return NULL;
+Vector par = gfit.GetParm();
+RzImage* img = new RzImage(DataType((r_4)0.),XSize(),YSize());
+img->SetOrg(XOrg(),YOrg());
+img->SetPxSize(XPxSize(),YPxSize());
+r_4* ptr = (r_4 *) img->VoidP();
+for(int i=0;i<XSize();i++) {
+  double x[2];
+  x[0] = XOrg()+(i+0.5)*XPxSize();
+  for(int j=0;j<YSize();j++) {
+    x[1] = YOrg()+(j+0.5)*YPxSize();
+    *(ptr+i+j*img->siz_x) = (float) f->Value(x,par.Data());
+  }
+}
+return img;
+}
+
+//++
+// Titre	Acces aux pixels
+//	*Attention:* Les methodes IValue() FValue() et DValue() sont lentes.
+//	Ne pas les utiliser dans les parties du code ou la vitesse de traitement
+//	est critique.
+//--
+//++
+// void * VoidP()
+//	Renvoie un pointeur void sur le tableau des pixels. Doit etre converti
+//	dans le bon type suivant le contenu de l'image.
+// int IValue(int i, int j)
+//	Renvoie la valeur du pixel "(i,j)" converti en int
+// float FValue(int i, int j)
+//	Renvoie la valeur du pixel "(i,j)" converti en float
+// double DValue(int i, int j)
+//	Renvoie la valeur du pixel "(i,j)" converti en double
+// int IValue(int k)
+//	Renvoie la valeur du pixel numero "k" converti en int
+// float FValue(int k)
+//	Renvoie la valeur du pixel numero "k" converti en float
+// double DValue(int k)
+//	envoie la valeur du pixel numero "k" converti en double
+//
+//	Les pixels sont rangees ligne apres ligne 
+//|	{(1,1), (2,1), ... (m, 1), (1,2), ... , (m,2), .... (m,n)}
+//--
+
+/* --Methodes-- */
+int RzImage::IVal_u1(int k) const          {return vect.u1->IElem(k);}
+int RzImage::IVal_u2(int k) const          {return vect.u2->IElem(k);}
+int RzImage::IVal_i2(int k) const          {return vect.i2->IElem(k);}
+int RzImage::IVal_i4(int k) const          {return vect.i4->IElem(k);}
+int RzImage::IVal_r4(int k) const          {return vect.r4->IElem(k);}
+int RzImage::IVal_r8(int k) const          {return vect.r8->IElem(k);}
+
+float RzImage::FVal_u1(int k) const        {return vect.u1->FElem(k);}
+float RzImage::FVal_u2(int k) const        {return vect.u2->FElem(k);}
+float RzImage::FVal_i2(int k) const        {return vect.i2->FElem(k);}
+float RzImage::FVal_i4(int k) const        {return vect.i4->FElem(k);}
+float RzImage::FVal_r4(int k) const        {return vect.r4->FElem(k);}
+float RzImage::FVal_r8(int k) const        {return vect.r8->FElem(k);}
+
+double RzImage::DVal_u1(int k) const       {return vect.u1->DElem(k);}
+double RzImage::DVal_u2(int k) const       {return vect.u2->DElem(k);}
+double RzImage::DVal_i2(int k) const       {return vect.i2->DElem(k);}
+double RzImage::DVal_i4(int k) const       {return vect.i4->DElem(k);}
+double RzImage::DVal_r4(int k) const       {return vect.r4->DElem(k);}
+double RzImage::DVal_r8(int k) const       {return vect.r8->DElem(k);}
+
+
+
+// ******** INSTANCES
+#if defined(__xlC) 
+void instancetemprzimg(int n)
+{
+/* Cette fonction sert uniquement a forcer le compilo a instancier les
+  classes/fonctions template   */
+
+RzVect<uint_1> rzvu1(n);
+RzVect<uint_2> rzvu2(n);
+RzVect<int_2> rzvi2(n);
+RzVect<int_4> rzvi4(n);
+RzVect<r_4> rzvr4(n);
+RzVect<r_8> rzvr8(n);
+return;
+}
+
+#endif
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template RzVect<uint_1>
+#pragma define_template RzVect<uint_2>
+#pragma define_template RzVect<int_2>
+#pragma define_template RzVect<int_4>
+#pragma define_template RzVect<r_4>
+#pragma define_template RzVect<r_8>
+#endif
+
+#ifdef GNU_TEMPLATES
+template class RzVect<uint_1>;
+template class RzVect<uint_2>;
+template class RzVect<int_2>;
+template class RzVect<int_4>;
+template class RzVect<r_4>;
+template class RzVect<r_8>;
+#endif
+
+#if defined(ANSI_TEMPLATES) 
+template class RzVect<uint_1>;
+template class RzVect<uint_2>;
+template class RzVect<int_2>;
+template class RzVect<int_4>;
+template class RzVect<r_4>;
+template class RzVect<r_8>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/rzimage.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/rzimage.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/rzimage.h	(revision 752)
@@ -0,0 +1,232 @@
+// This may look like C code, but it is really -*- C++ -*-
+//  Classe image generique   E.Aubourg , E. Lesquoy     
+//                           Modifs R. Ansari   04/95
+
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef RZIMAGE_SEEN
+#define RZIMAGE_SEEN
+
+#include <iostream.h>
+
+#include "rzvect.h"
+#include "datatypes.h"
+#include "ppersist.h"
+#include "dvlist.h"
+
+namespace SOPHYA {class GeneralFit;}
+
+// Flags de verifications sur les indices 
+
+//#define IMGRGCHECK
+//#define IMGVOIDCHECK
+
+
+// ------------- Classe RzImage ------------------  
+
+typedef union {   // il faut acceder le bon en fonction de datatype
+  RzVect<uint_1>* u1;
+  RzVect<uint_2>* u2;
+  RzVect<int_2>*  i2;
+  RzVect<int_4>*  i4;
+  RzVect<r_4>*    r4;
+  RzVect<r_8>*    r8;
+} ImgVectP ;
+
+
+
+class RzImage : public PPersist , public AnyDataObj {
+  //class RzImage EXC_AWARE {
+public:
+  enum {classId = ClassId_Image };
+
+                RzImage(PBaseDataTypes dType, int sizx, int sizy, 
+                        int imgId = 0, char const * imgName = 0);
+                RzImage(PBaseDataTypes dType=kpbdt_unknown);
+                RzImage(const RzImage&, int sharePixels=0);
+
+                RzImage(char *flnm);    // Creation/Lecture fichier de obtenu par Write()
+
+  virtual       ~RzImage(); 
+
+  int_4                 ClassId() const         { return classId; }
+  static PPersist*      Create()                { return new RzImage;}
+
+  RzImage&      operator= (RzImage const &);
+
+  inline int_4  XSize() const {return siz_x;}
+  inline int_4  YSize() const {return siz_y;}
+
+  inline int_4  XOrg() const {return org_x;}
+  inline int_4  YOrg() const {return org_y;}
+
+  inline float  XPxSize() const {return pxsz_x;}
+  inline float  YPxSize() const {return pxsz_y;}
+
+  inline ImgVectP    Vect() const {return vect;}
+  inline void * VoidP() const {return voidP;}
+  inline int    IsFits() const {return isFits;}
+
+  inline PBaseDataTypes    PixelType() const { return dataType; }
+  inline char * PixelNomType() const { return DataName(dataType); }
+
+  inline char * Nom()  { return name; }
+  inline const char * Nom() const { return name; }
+  inline int_4  Ident() const { return id; }
+
+  DVList&       Info();
+ 
+  void          Allocate(PBaseDataTypes dType, int sizx, int sizy, ImgVectP* pvpsh=NULL);
+  void          DeAllocPixels();
+  void          SetPixels(PBaseDataTypes dType, int sizx, int sizy, void* data);
+
+  void          SetOrg(int_4 orgx, int_4 orgy);
+  void          SetPxSize(float szx=1, float szy=1);
+  void          SetAtt(int nbnul = -1, int nbsat = -1,
+                       float minpix = 0, float maxpix = -1.,
+                       float moypix = 0, float sigpix = -1., 
+                       float fnd = -1., float sigfnd = -1.);
+
+  void          SetNameId(int imgid = 0, char const * nom = NULL);
+
+// Fonctions d'impressions 
+  virtual void  Print(ostream& os) const;
+  inline void   Print() const { Print(cout); }
+
+  virtual int   CheckDyn(double min=-9.e19, double max=9.e19);
+
+// Resultats d'un GeneralFit
+  RzImage* 	FitResidus(GeneralFit& gfit);
+  RzImage* 	FitFunction(GeneralFit& gfit);
+
+  void          Save(char *flnm);
+  virtual void  WriteSelf(POutPersist&) const;
+  virtual void  ReadSelf(PInPersist&);
+
+//  Fonctions d'acces aux pixels avec conversion 
+// ATTENTION LENT ! EVITER AUX ENDROITS CRITIQUES.
+
+  int           IValue(int i, int j) const ;    
+  int           IValue(int k) const ;           
+  float         FValue(int i, int j) const ;    
+  float         FValue(int k) const ;
+  double        DValue(int i, int j) const ;
+  double        DValue(int k) const ;
+
+// Quelques variables caracterisant la distribution des pixels 
+  r_4       fond;         // Fond de l'image 
+  r_4       sigmaFond;    // Fluctuation du fond
+  int_4     nbNul;        // Nb de pixels < min
+  int_4     nbSat;        // Nb de pixels > max 
+  r_4       minPix;       // Valeur mini des pixels >= min <= max 
+  r_4       maxPix;       // Valeur maxi des pixels >= min <= max 
+  r_4       moyPix;       // Valeur moyenne des pixels
+  r_4       sigPix;       // Sigma distribution des pixels 
+
+protected:
+  PBaseDataTypes  dataType;
+  int_4     siz_x,siz_y;        //  Taille x,y    
+  int_4     org_x,org_y;        //  Origines si image lu ds un fichier   
+  r_4       pxsz_x, pxsz_y;     //  Taille des pixels 
+  int_4     isFits;             //  Beurk. Ah que Reza ne me fait-il pas faire! 
+  char name[32];                //  Nom de l'image (Gestion des objets) 
+  int_4 id;                     //  Identificateur (Gestion des objets) 
+
+  void* voidP;          // un pointeur sans type   -
+                        // Vivement le RTTI qu'on puisse eliminer ces choses
+  ImgVectP vect;        // il faut acceder le bon en fonction de datatype
+
+  DVList* mInfo;        // Infos (variables) attachees a l'image
+      
+private:
+  int (RzImage::* IVal_p)(int) const;
+  float (RzImage::* FVal_p)(int) const;
+  double (RzImage::* DVal_p)(int) const;
+  
+  int IVal_u1(int k) const;
+  int IVal_u2(int k) const;
+  int IVal_i2(int k) const;
+  int IVal_r4(int k) const;
+  int IVal_i4(int k) const;
+  int IVal_r8(int k) const;
+  
+  float FVal_u1(int k) const;
+  float FVal_u2(int k) const;
+  float FVal_i2(int k) const;
+  float FVal_r4(int k) const;
+  float FVal_i4(int k) const;
+  float FVal_r8(int k) const;
+  
+  double DVal_u1(int k) const;
+  double DVal_u2(int k) const;
+  double DVal_i2(int k) const;
+  double DVal_r4(int k) const;
+  double DVal_i4(int k) const;
+  double DVal_r8(int k) const;
+};
+
+// Definition de l'operateur << 
+inline ostream& operator << (ostream& s, RzImage const & img)
+  {  img.Print(s);  return(s);  }
+
+// Implementation des methodes d'acces pixels inline 
+
+#ifdef IMGRGCHECK
+#define RZCHECKIMG2(_x_,_y_)                                  \
+      if ((_x_ >= siz_x) || (_y_ >= siz_y) ||              \
+          (_x_ < 0) || (_y_ < 0)) THROW(rangeCheckErr);  \
+      if (!voidP) THROW(nullPtrErr)
+#define RZCHECKIMG1(_x_)                                  \
+      if ((_x_ >= siz_x*siz_y) || (_x_ < 0)) THROW(rangeCheckErr);  \
+      if (!voidP) THROW(nullPtrErr)
+#else
+#if defined(IMGVOIDCHECK)
+#define RZCHECKIMG2(_x_,_y_) \
+      if (!voidP) THROW(NullPtrErr)
+#define RZCHECKIMG1(_x_,_y_) \
+      if (!voidP) THROW(NullPtrErr)
+#else
+#define RZCHECKIMG2(_x_,_y_)
+#define RZCHECKIMG1(_x_)
+#endif
+#endif /* IMGRGCHECK */
+
+// Methodes d'acces pixels inline 
+
+inline int RzImage::IValue(int k) const
+{ 
+RZCHECKIMG1(k);
+return (this->*IVal_p)(k); 
+}
+
+inline int RzImage::IValue(int i, int j) const
+{ 
+RZCHECKIMG2(i,j);
+return IValue(i+j*siz_x); 
+}
+
+inline float RzImage::FValue(int k) const
+{ 
+RZCHECKIMG1(k);
+return (this->*FVal_p)(k); 
+}
+
+inline float RzImage::FValue(int i, int j) const
+{ 
+RZCHECKIMG2(i,j);
+return FValue(i+j*siz_x); 
+}
+
+inline double RzImage::DValue(int k) const
+{ 
+RZCHECKIMG1(k);
+return (this->*DVal_p)(k); 
+}
+
+inline double RzImage::DValue(int i, int j) const
+{ 
+RZCHECKIMG2(i,j);
+return DValue(i+j*siz_x); 
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/rzvect.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/rzvect.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/rzvect.h	(revision 752)
@@ -0,0 +1,76 @@
+// This may look like C code, but it is really -*- C++ -*-
+/*  Classe vecteurs de type non constant (template)     */
+/*                    E. Aubourg, E. Lesquoy            */
+/*        Modifs             R. Ansari 04/95            */
+
+#ifndef RZVECT_SEEN
+#define RZVECT_SEEN
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "perrors.h"
+
+template <class T>
+class RzVect EXC_AWARE {
+public:
+                    RzVect(int n, T* data);
+                    RzVect(int n);
+  virtual           ~RzVect();
+  inline int&       NImgRef()         {return nImgRef;}
+  inline int&       Shareable()       {return shareable;}   
+  inline T&         operator[](int i);
+  inline const T&   operator[](int i) const;
+  int               IElem(int k) const;
+  float             FElem(int k) const;
+  double            DElem(int k) const;
+  
+  T*                p;
+  int               nElt;
+  
+private:
+  int           nImgRef;    // Combien d'images font reference au meme RzVect ?
+                                                // Le constructeur le met a *** 1 ***
+                                                // Donc une image doit le changer lorsqu'elle pointe sans allouer.
+  int           shareable;  // Dit si le RzVect peut etre partage. Mis a 0 par exemple si
+                            // le tableau de nombres est en memoire partagee.
+  int           ownTable;   // Dit si le RzVect peut faire delete du tableau.
+};
+
+template <class T>
+inline T& RzVect<T>::operator[](int i)
+{
+  #ifdef RGCHECK
+  if (i<0 || i>=nElt) THROW(rangeCheckErr);
+  #endif
+  return p[i];
+}
+
+template <class T>
+inline const T& RzVect<T>::operator[](int i) const
+{
+  #ifdef RGCHECK
+  if (i<0 || i>=nElt) THROW(rangeCheckErr);
+  #endif
+  return p[i];
+}
+
+template <class T>
+inline int RzVect<T>::IElem(int k) const
+{
+  return (int) (*this)[k];
+}
+
+template <class T>
+inline float RzVect<T>::FElem(int k) const
+{
+  return (float) (*this)[k];
+}
+
+template <class T>
+inline double RzVect<T>::DElem(int k) const
+{
+  return (double) (*this)[k];
+}
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/simplesort.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/simplesort.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/simplesort.cc	(revision 752)
@@ -0,0 +1,60 @@
+//
+// $Id: simplesort.cc,v 1.2 1999-04-22 16:18:50 ansari Exp $
+//
+
+#include "machdefs.h"
+#include "simplesort.h"
+#include <stdlib.h>
+
+//++
+// Class	SimpleSort
+// Lib  	Outils++ 
+// include	simplesort.h
+//
+//	Classe pour trier. Utiliser plutôt la STL.
+//--
+
+
+SimpleSort::SimpleSort(int nElts)
+: numElts(nElts), index(new TRIPAIRE[nElts])
+{END_CONSTRUCTOR}
+			
+SimpleSort::~SimpleSort()
+{
+  delete[] index;
+}
+
+int SimpleSort::Compare(const void* tp1, const void* tp2)
+{ float x=((TRIPAIRE*)tp1)->value - ((TRIPAIRE*)tp2)->value;
+  if (x>0) return(1);
+  else if (x<0) return(-1);
+  else return(0);
+}
+
+#if !ARG_FUNC_CPP_C
+extern "C" int SimpleSortCompare(const void* tp1, const void* tp2);
+
+int SimpleSortCompare(const void* tp1, const void* tp2)
+{ return SimpleSort::Compare(tp1, tp2);
+}
+#endif
+
+void SimpleSort::Sort()
+{
+#if ARG_FUNC_CPP_C
+  qsort(index, numElts, sizeof(TRIPAIRE), SimpleSort::Compare);
+#else
+  qsort(index, numElts, sizeof(TRIPAIRE), SimpleSortCompare);
+#endif
+}
+
+int SimpleSort::Lookup(float val)
+{
+  int a = 0;
+  int b = numElts-1;
+  while (b>a+1) {
+    int c = (b+a)/2;
+    ((val >= index[c].value) ? a : b) = c;
+  }
+  return a;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/simplesort.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/simplesort.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/simplesort.h	(revision 752)
@@ -0,0 +1,96 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: simplesort.h,v 1.2 1999-10-21 15:25:52 ansari Exp $
+//
+
+// Un tri tout bete sur des reels. On donne un tableau de reels,
+// et on recupere un index trie, et on peut faire des recherches.
+
+#ifndef SIMPLESORT_SEEN
+#define SIMPLESORT_SEEN
+
+#include "peida.h"
+
+class SimpleSort EXC_AWARE {
+public:
+  SimpleSort(int nElts);
+  // On donne au constructeur le nombre d'elements a trier.
+  virtual ~SimpleSort();
+
+  void      Set(int i, float value);
+  // Donne la valeur de l'element i
+
+  void      Sort();
+  // Trie. A faire avant d'appeler la suite.
+
+  float    Value(int i) const {return index[i].value;}
+  // La valeur numero i une fois trie.
+
+  int       Num(int i) const   {return index[i].num;}
+  // L'ancien indice qui est le numero i une fois trie
+
+  int       Lookup(float val);
+  // L'indice - trie - le plus proche de val.
+  
+#if ARG_FUNC_CPP_C
+private:
+#endif
+  typedef struct {
+    int num;
+    float value;
+  } TRIPAIRE;
+
+  static int Compare(const void* tp1, const void* tp2);
+    
+  int numElts;
+  TRIPAIRE* index;
+};
+
+// ************ INLINES
+
+inline
+void SimpleSort::Set(int i, float value)   // Check range ?
+{
+  index[i].num = i;
+  index[i].value = value;
+}
+
+
+
+// Une variante avec la STL, a preferer
+#include <functional>
+#include <algorithm>
+
+
+// On a un vecteur de donnees et un vecteur d'index, on trie les index
+// en comparant les donnees.
+// L'objet-fonction de type dataCompare doit comparer deux objets de type data.
+
+// Comparateur qui agit sur l'index en comparant les donnees avec dataCompare
+template <class data, class index, class dataCompare>
+struct IndexComp : public binary_function<index,index,bool>
+{
+  IndexComp(data* begin_data, index* begin_index, dataCompare comp)
+    : bdata(begin_data), bindex(begin_index), datacomp(comp) {}
+
+  bool operator()(index const& i1, index const& i2)
+    { return datacomp(*(bdata + (&i1 - bindex)), *(bdata + (&i2 - bindex)));}
+    
+  data* bdata;
+  index* bindex;
+  dataCompare datacomp;
+};
+
+// Fonction de tri qui trie un index en comparant des donnees avec dataComp
+template <class data, class index, class dataCompare>
+void TriIndex(data* begin_data, data* end_data, index* begin_index, dataCompare comp)
+{
+  sort(begin_index, begin_index + (end_data-begin_data),
+  	IndexComp<data, index, dataCompare>(begin_data, begin_index, comp));
+}  
+
+
+
+
+
+#endif // SIMPLESORT_SEEN
Index: /tags/V_Fev00/SophyaLib/NTools/simps2d.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/simps2d.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/simps2d.h	(revision 752)
@@ -0,0 +1,40 @@
+#ifndef SIMPS2D_SEEN
+#define SIMPS2D_SEEN
+
+// Integration 2D domaine carre
+// Selon Abramowitz p892-893 formule 25.462, residu ordre 0.5**6
+// 0.387298=0.5*sqrt(3/5)  0.197531=16/81  0.123457=10/81  0.077160=25/324
+#if defined(SIMPSON9)
+  static int   nd2d = 9;
+  static float dx2d[9] = { 0.000000 ,  0.000000 ,  0.000000
+                         ,-0.387298 ,  0.387298 , -0.387298
+                         , 0.387298 , -0.387298 ,  0.387298 };
+  static float dy2d[9] = { 0.000000 , -0.387298 ,  0.387298
+                         , 0.000000 ,  0.000000 , -0.387298
+                         , 0.387298 ,  0.387298 , -0.387298 };
+  static float  w2d[9] = { 0.197531 ,  0.123457 ,  0.123457
+                         , 0.123457 ,  0.123457 ,  0.077157
+                         , 0.0771605,  0.0771605,  0.0771605};
+#elif defined(SIMPSON4)
+  static int   nd2d = 4;
+  static float dx2d[4] = { 0.288675, 0.288675,-0.288675,-0.288675 };
+  static float dy2d[4] = { 0.288675,-0.288675, 0.288675,-0.288675 };
+  static float  w2d[4] = { 0.250000, 0.250000, 0.250000, 0.250000 };
+#elif defined(INTEG5)
+  static int   nd2d = 5;
+  static float dx2d[5] = { 0. , -0.3, -0.3,  0.3, 0.3 };
+  static float dy2d[5] = { 0. , -0.3,  0.3, -0.3, 0.3 };
+  static float  w2d[5] = { 0.2,  0.2,  0.2,  0.2, 0.2 };
+#elif  defined(NOINTEG)
+  static int   nd2d = 1;
+  static float dx2d[1] = { 0. };
+  static float dy2d[1] = { 0. };
+  static float  w2d[1] = { 1. };
+#else
+  static int   nd2d = 0;
+  static float dx2d[1] = { 999999. };
+  static float dy2d[1] = { 999999. };
+  static float  w2d[1] = { 0. };
+#endif
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/strutil.c
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/strutil.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/strutil.c	(revision 752)
@@ -0,0 +1,534 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "strutil.h"
+
+/* 
+++ 
+  Module	Strutil (C)
+  Lib	LibsUtil
+  include	strutil.h
+
+	Groupe de fonction de gestion et manipulation
+	des chaines de caracteres.
+--
+*/
+
+/*
+++
+  char* itoc(int in, char* s, int nDigits)
+	conversion entier-chaine de caracteres
+--
+*/
+/*
+++
+  ctoi(const char* cst, int *ipt)
+	convertit une chaine de caractere en entier
+--
+*/
+/*
+++
+  ctol(const char* cst, long int *lpt)
+	convertit une chaine de caractere en entier long
+--
+*/
+/*
+++
+  ctof(const char* cst, double *fpt)
+	convertit une chaine de caractere en flottant
+--
+*/
+/*
+++
+  posc(const char* cst, char sec)
+	trouve la position d'un caractere dans une chaine
+	(premier charactere rencontre)
+--
+*/
+/*
+++
+  poslc(const char* cst, char sec)
+	trouve la position d'un caractere dans une chaine
+	(dernier charactere rencontre)
+--
+*/
+/*
+++
+  strip(char cst[], char opt, char bc)
+	permet d'enlever les blancs au debut ou a la fin d'une
+	chaine de caractere
+--
+*/
+/*
+++
+  padstr(spo,lpa,bc)
+	Cette  fonction  rajoute  des blancs a la fin de la chaine `spo'
+	pour amener la longueur de la chaine a `lpa'. Les caracteres
+	rajoutes a la fin sont `bc'. La fonction retourne le nombre de
+	blancs (caracteres bc)  rajoutes a la fin.
+--
+*/
+/*
+++
+  tomaj(char *cbuff)
+	Changement en majuscule d'une chaine de caracteres
+--
+*/
+/*
+++
+  tomin(char *cbuff)
+	Changement en minuscule d'une chaine de caracteres
+--
+*/
+/*
+++
+  efface(char *cbuff,int lbuff,char c)
+	Remplace un caractere avec des blancs
+--
+*/
+/*
+++
+  csh_parse(const char* x, const char* yp)
+	Compare la chaine de caracteres `x' avec la chaine `yp'
+	comprenant des regles de substitution type c-shell
+	(asterisque et point d'interrogation).
+--
+*/
+/*
+  DecArgList()
+	Decoder une liste du type a,b,c-d,e,f-g,h...
+*/
+ 
+
+/*            Fonction  itoc()    */
+char* itoc(int in, char* s, int nDigits)
+{
+  int i,j,n;
+  n=abs(in);
+  for(i=0;i<nDigits;i++)
+    s[i]=' ';
+  s[nDigits-1]='\0';
+  j=nDigits-2;
+  for (i=j; i>=0; i--)
+   {
+    int x = n % 10;
+    n /= 10;
+    s[i] = '0' + x;
+    if(n==0) break;
+   }
+  if(in < 0 )
+   {
+    s[i-1]='-';
+   } 
+ return (s);
+ }
+ 
+/*            Fonction  ctoi()    */
+int ctoi(const char* cst, int *ipt)
+{
+int i,j,k,l,ls,isgn;
+ls = strlen(cst)-1;
+if (ls < 0)  return (-1);
+j = -1;
+isgn = l = 1;
+k = 0;
+if(cst[0] == '-')
+  {
+  j = 0;
+  isgn = -1;
+  }
+if(cst[0] == '+') j = 0;
+for(i=ls;i>j;i--)
+  {
+  if(isdigit(cst[i]) == 0)  return (-1);
+  k += (cst[i] - '0')*l;
+  l *= 10;
+  }
+*ipt = k*isgn;
+return (1);
+}
+/*                                                       */
+/*            Fonction  ctol()    */
+int ctol(const char* cst, long int *lpt)
+{
+int i,j,ls,isgn;
+long k,l;
+ls = strlen(cst)-1;
+if (ls < 0)  return (-1);
+j = -1;
+isgn = l = 1;
+k = 0;
+if(cst[0] == '-')
+  {
+  j = 0;
+  isgn = -1;
+  }
+if(cst[0] == '+') j = 0;
+for(i=ls;i>j;i--)
+  {
+  if(isdigit(cst[i]) == 0)  return (-1);
+  k += (cst[i] - '0')*l;
+  l *= 10;
+  }
+*lpt = k*isgn;
+return (1);
+}
+/*              Fonction  ctof()           */
+int ctof(const char* cst, double *fpt)
+{
+int i,jb,pv,ls,isgn;
+double v1,v2;
+ls = strlen(cst);
+if (ls < 0)  return (-1);
+jb = -1;
+isgn = 1;
+v1 = 0.;
+v2 = 1.;
+if (cst[0] == '-')
+  {
+  jb = 0;
+  isgn = -1;
+  }
+if (cst[0] == '+')  jb = 0;
+if ((pv=posc(cst,'.')) != -1)
+  {
+  v2 = 0.1;
+  for(i=pv+1;i<ls;i++)
+    {
+    if(isdigit(cst[i]) == 0)  return (-1);
+    v1 += (cst[i]-'0')*v2;
+    v2 /= 10.;
+    }
+  ls = pv;
+  v2 = 1.;
+  }
+for(i=ls-1;i>jb;i--)
+  {
+  if(isdigit(cst[i]) == 0)  return (-1);
+  v1 += (cst[i]-'0')*v2;
+  v2 *= 10.;
+  }
+*fpt = (isgn == 1)? v1 : -v1;
+return (1);
+}
+/*           Fonction  posc()        */
+int posc(const char* cst, char sec)
+{
+int i,ls;
+ls = strlen(cst);
+for(i=0;i<ls;i++)
+  {
+  if (cst[i] == sec)  return(i);
+  }
+return (-1);
+}
+
+/*           Fonction  poslc()        */
+int poslc(const char* cst, char sec)
+{
+int i,ls;
+ls = strlen(cst);
+for(i=ls-1;i>=0;i--)
+  {
+  if (cst[i] == sec)  return(i);
+  }
+return (-1);
+}
+
+/*                Fonction   strip()             */
+int strip(char cst[], char opt, char bc)
+{
+int i,j,ls;
+ls = strlen(cst);
+if (opt == 'L' || opt == 'B')
+  {
+  i = 0;
+  while(cst[i] == bc) i++;
+  if (i != 0)
+    {
+    for(j=i;j<ls;j++)  cst[j-i] = cst[j];
+    ls -= i;
+    cst[ls] = '\0';
+    }
+  }
+if ((opt == 'T' || opt == 'B') && ls > 0)
+  {
+  i = ls-1;
+  while(cst[i] == bc)  i--;
+  cst[i+1] = '\0';
+  }
+return (0);
+}
+
+/*                Fonction   padstr(spo,lpa,bc)                      */
+/*    Cette  fonction  rajoute  des blancs a la fin de la chaine spo */
+/*   pour amener la longueur de la chaine a lpa. les caracteres      */
+/*   rajoutes a la fin sont bc. La fonction retourne le nombre de    */ 
+/*   blancs (caracteres bc)  rajoutes a la fin.                      */
+
+int padstr(char spo[], int lpa, int bc)
+{
+int li,i;
+li = strlen(spo);
+for(i=li;i<lpa;i++)  spo[i] = bc;
+spo[lpa] = '\0';
+return(lpa-li);
+}
+
+/* Eric L. 11-03-94 */
+/* quelques fonctions utiles */
+
+void tomaj(char *cbuff)
+{
+register int i,l;
+
+l=strlen(cbuff);
+for(i=0; i< l;i++)
+  cbuff[i]=(char) toupper( (int) cbuff[i]);
+}
+
+void tomin(char *cbuff)
+{
+register int i,l;
+
+l=strlen(cbuff);
+for(i=0; i< l;i++)
+  cbuff[i]=(char) tolower( (int) cbuff[i]);
+}
+
+void efface(char *cbuff,int lbuff,char c)
+{
+register int i;
+
+for(i=0; i< lbuff;i++)
+  if(cbuff[i] == c)  cbuff[i] = ' ';
+}
+
+char* rep_char(const char *cbuff,char cin,char crep)
+{
+register int i,l;
+char* buff;
+buff=(char*) cbuff;
+l=strlen(buff);
+for(i=0; i< l;i++)
+  if(buff[i] == cin) buff[i] = crep;
+return(buff);
+}
+
+/* Eric L. 23-03-96 */
+
+int csh_parse(const char* x, const char* yp)
+{
+ int i,lenx,lenyp;
+ int ix,iyp;
+ int faux;
+ char cx, cyp;
+ 
+ lenx=strlen(x);
+ lenyp=strlen(yp);
+ if(!lenx || !lenyp) return(0);
+ faux=0;
+ ix=0;iyp=0;
+ while(ix < lenx && iyp < lenyp)
+  {
+   cx=x[ix];
+   cyp=yp[iyp];
+   if(cx == cyp) 
+    {
+     ix++; 
+     iyp++;
+    }
+   else
+    switch(cyp)
+     {
+       case '?':
+        ix++;
+        iyp++;
+        break;
+       case '*':
+        while((cyp=='*' || cyp=='?') && (iyp < lenyp))
+         {
+          iyp++;
+          if(iyp < lenyp) cyp=yp[iyp];
+         }
+        if(iyp < lenyp)
+         {
+          faux=1;
+          for(i = ix; i < lenx ; i++)
+           {
+            cx=x[i];
+            if(cx == cyp)
+             {
+              faux=0;
+              break;
+             }
+           }
+          ix=i+1;
+          if(ix < lenx) cx=x[ix];
+          iyp++; 
+          if(iyp < lenyp) cyp=yp[iyp];
+         }    
+        break;
+       default:
+        faux=1;
+     }
+    if(faux) return(0);
+  }
+ 
+ for( i= iyp; i < lenyp ; i++)
+  {
+   cyp=yp[i];
+   if( cyp != '*' && cyp != '?') return(0);
+  }
+ 
+ if(cyp == '*') return(1);
+ if((lenx-ix) == 1 && ( cyp == '?' || cx==cyp)) return(1);
+ for( i= ix; i < lenx ; i++)
+  {
+   cx=x[i];
+   if( cx != cyp)  return(0);
+  }
+ return(1);
+}
+ 
+/*-------------------------------------------------------------------*/
+
+/*
+++
+  int DecArgList(char *listin, int *Vec, int nVec)
+	Pour decoder une liste de numeros a,b,c-d,e,f-g,h...
+	avec a,b... entiers
+| Vec est rempli jusqu'a concurrence de nVec elts.
+|     Si Vec==NULL ou nVec<=0 le tableau n'est pas rempli
+|         et seul le nombre d'elements est compte
+| Return: nombre d'elements rempli
+--
+*/
+/*                            (cmv 7/8/97)      */
+int DecArgList(char *listin, int *Vec, int nVec)
+{
+int i,k, num, min, max;
+char *list = NULL, *listfin, *s;
+
+if(strlen(listin) <= 0) return(0);
+list = (char *) malloc(strlen(listin)+1);
+if(list==NULL) return(0);
+strcpy(list,listin); strip(list,'B',' ');
+if( (k=strlen(list)) <= 0 ) {free(list); return(0);}
+for(i=0; i<k; i++) if(list[i] == ',') list[i] = ' ';
+listfin = list + k; *listfin = '\0';
+
+s = list; num = 0; k = 0;
+while(s < listfin) {
+  if ( (k=posc(s,' ')) < 0)  k = strlen(s);
+  s[k] = '\0'; strip(s,'B',' ');
+  sscanf(s,"%d-%d",&min,&max);
+  max = min - 1;
+  sscanf(s,"%d-%d",&min,&max);
+  if(max<min) max = min;
+  for(i=min; i<=max; i++) {
+    if( Vec!=NULL && nVec>0 ) {
+      if( num >= nVec )
+        {printf("DecArgList_Erreur: pas assez de place dans le vecteur (%d)\n"
+               ,nVec); free(list); return(num);}
+      Vec[num] = i;
+    }
+    num++;
+  }
+  s = s+k+1;
+}
+
+free(list);
+return(num);
+}
+ 
+/*-------------------------------------------------------------------*/
+
+/*
+++
+  char *ExtName(char *cout,char *cin,char t)
+	Pour separer les composantes d'un nom de fichier de type unix.
+| cout   = chaine en sortie
+| cin    = chaine en entree
+| t      = type de racine a extraire
+| Return = *cout
+| - Remarque: pas de verification de longeur de la chaine cout!
+| - Exemple: /home/toto.cc  /home/ /home/.cc  .cc  toto.cc
+|    t='d' : /home          /home  /home      ""   ""
+|    t='n' : toto.cc        ""     .cc        .cc  toto.cc
+|    t='r' : toto           ""     ""         ""   toto
+|    t='t' : cc             ""     cc         cc   cc
+--
+*/
+/*                            (cmv 24/4/98)      */
+char *ExtName(char *cout,char *cin,char t)
+{
+int is=-1,ip=-1,i,j;
+int len = strlen(cin);
+/* cas ou le nom se termine par un / qui n'est pas au debut*/
+if(len>1) if(cin[len-1]=='/') len--;
+
+for(i=0;i<len;i++) {
+  if(cin[i]=='/') is=i;         /* position du dernier / */
+  if(cin[i]=='.' && ip<0) ip=i; /* position du 1er point */
+  cout[i]=cin[i];
+}
+cout[len]='\0';
+
+/* mauvais nom de fichier */
+if(is>=0&&ip>=0&&ip<=is) {cout[0]='\0'; return cout;}
+
+/* traitement des differents cas */
+switch(t) {
+  case 'd':
+    if(is==0) {                    /* cas /... */
+      if(ip<0) ip=len-1;             /* cas /home */
+      else ip=0;                     /* cas /toto.c */
+    } else if(is<0) {              /* cas toto.c */
+      is=ip=-1;
+    } else {                       /* cas /home/.../... */
+      ip=is-1; is=0;
+    }
+    break;
+  case 'n':
+    if(is==0) {                        /* cas /... */
+      if(ip<0) ip=is=-1;                 /* cas /home */
+      else {is=1; ip=len-1;}             /* cas /toto.c */
+    } else if(is>0) {                  /* cas /home/toto.c */
+      is++; ip=len-1;
+    } else {                           /* cas toto.c */
+      is=0; ip=len-1;
+    }
+    break;
+  case 'r':
+    if(is==0) {                          /* cas /... */
+      if(ip<0) ip=is=-1;                   /* cas /home */
+      else if(ip==1) is=ip=-1;             /* cas /.c */
+      else {is=1; ip--;}                   /* cas /toto.c */
+    } else if(is>0) {                    /* cas /home/... */
+      if(ip<0) {is++;ip=len-1;}            /* cas /home/toto */
+      else if(ip==is+1) is=ip=-1;          /* cas /home/.c */
+      else {is++; ip--;}                   /* cas /home/toto.c */
+    } else if(is<0) {                    /* cas toto.c */
+      if(ip<0) {is=0;ip=len-1;}            /* cas toto */
+      else if(ip==0) is=ip=-1;             /* cas .c */
+      else {is=0; ip--;}                   /* cas toto.c */
+    }
+    break;
+  case 't':
+    if(ip<0) is=ip=-1;             /* cas sans '.' dans le nom */
+    else {is=ip+1,ip=len-1;}       /* cas blablabla.c */
+    break;
+  default:
+    cout[0]='\0';
+    return cout;
+    break;
+}
+
+j=0;
+if(is>=0&&ip>=is) for(i=is,j=0;i<=ip;i++,j++) cout[j]=cin[i];
+cout[j]='\0';
+/* printf("........ is=%d ip=%d :%s:\n",is,ip,cout); */
+return cout;
+}
Index: /tags/V_Fev00/SophyaLib/NTools/strutil.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/strutil.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/strutil.h	(revision 752)
@@ -0,0 +1,58 @@
+/*                                                                          */
+/*   Ce fichier contient quelques fonctions de manipulation de caracteres   */
+/*   et autres bricoles utiles                                              */
+/*     # char* itoc() : conversion entier-chaine de caracteres              */ 
+/*     # ctoi()   : convertit une chaine de caractere en entier             */
+/*     # ctol()   : convertit une chaine de caractere en entier long        */
+/*     # ctof()   : convertit une chaine de caractere en flottant           */
+/*     # posc()    : trouve la position d'un caractere dans une chaine      */
+/*     # strip()  : permet d'enlever les blancs au debut ou a la fin d'une  */
+/*                  chaine de caractere                                     */ 
+/*     # padstr() : permet d'ajouter des caracteres a la fin d'une chaine   */
+/*                  de caracteres pour amener la longueur de cette chaine   */
+/*                  a une valeur donnee.                                    */
+/*     # tomaj()  : Changement en majuscule d'une chaine de caracteres      */
+/*     # efface() : Remplace un caractere avec des blancs                   */
+/*     # rep_char() : Remplace un caractere par un autre                    */ 
+/*                                                                          */
+/* Derniere modif: csh_parse, E. Lesquoy, le 23-03-96                       */
+/* DecArgList: Decoder une liste du type a,b,c-d,e,f-g,h...(cmv 7/8/97)     */
+/* ExtName: eclatement des nom de fichiers unix (cmv 24/4/98)               */
+
+#ifndef STRUTIL_H_SEEN
+#define STRUTIL_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*    Manipulation de chaines de caracteres     */
+/*                    Reza - 92/93              */
+char* itoc(int in, char* s,int nDigits);
+int ctoi(const char* cst, int *ipt);
+int ctol(const char* cst, long int *lpt);
+int ctof(const char* cst, double *fpt);
+/* retour ctox : 1: OK, -1 erreur */
+int posc(const char* cst, char sec);
+int poslc(const char* cst, char sec);
+int strip(char* cst, char opt, char bc);
+int padstr(char* spo, int lpa, int bc);
+
+/* Eric L. 11-03-94 */
+void tomaj(char *cbuff);
+void tomin(char *cbuff);
+void efface(char *cbuff,int lbuff,char c);
+/* Attention rep_char(const char *cbuff ...) c'est declare const cbuff, mais ca modifie cbuff - Reza 2/09/98  */
+char* rep_char(const char *cbuff,char cin,char crep);  
+/* Eric L. 23-03-96 */
+int csh_parse(const char* x, const char* yp);
+/* cmv 7/8/97 */
+int DecArgList(char *listin, int *Vec, int nVec);
+char *ExtName(char *cin,char *cout,char t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/NTools/swapbytes.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/swapbytes.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/swapbytes.h	(revision 752)
@@ -0,0 +1,40 @@
+/*  Macro pour faire des bytes-swap        */
+/*                   CMV+Reza Fev 98       */
+
+#ifndef  SWAPBYTES_H_SEEN
+#define  SWAPBYTES_H_SEEN
+
+/*  Les arguments des define sont consideres comme pointeur */
+
+#define  Swap_Bytes8(_x8_)                                 \
+{                                                          \
+  uint_8 _tmp_ = *(uint_8*)(_x8_);                         \
+  *(uint_8*)(_x8_) = ((_tmp_ >> (7*8)) & 0x000000FF) |     \
+                     ((_tmp_ >> (5*8)) & 0x0000FF00) |     \
+                     ((_tmp_ >> (3*8)) & 0x00FF0000) |     \
+                     ((_tmp_ >> (1*8)) & 0xFF000000) |     \
+                     ((_tmp_ & 0xFF000000) << (1*8))  |    \
+                     ((_tmp_ & 0x00FF0000) << (3*8))  |    \
+                     ((_tmp_ & 0x0000FF00) << (5*8))  |    \
+                     ((_tmp_ & 0x000000FF) << (7*8));      \
+}
+
+
+#define  Swap_Bytes4(_x4_)                                 \
+{                                                          \
+  uint_4 _tmp_ = *(uint_4*)(_x4_);                         \
+  *(uint_4*)(_x4_) = ((_tmp_ >> 24) & 0x000000FF) |        \
+                     ((_tmp_ >> 8)  & 0x0000FF00) |        \
+                     ((_tmp_ & 0x0000FF00) << 8)  |        \
+                     ((_tmp_ & 0x000000FF) << 24);         \
+}
+
+
+#define  Swap_Bytes2(_x2_)                                 \
+{                                                          \
+  uint_2 _tmp_ = *(uint_2*)(_x2_);                         \
+  *(uint_2*)(_x2_) = ((_tmp_ >> 8) & 0x00FF) |             \
+                     ((_tmp_ & 0x00FF) << 8);              \
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/tabmath.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tabmath.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tabmath.cc	(revision 752)
@@ -0,0 +1,41 @@
+#include "machdefs.h"
+#include "tabmath.h"
+
+///////////////////////////////
+//  Exponentielles tabulees  //
+///////////////////////////////
+
+TabFExp::TabFExp()
+{
+  tab = new double[10000];
+
+  for(int i=0; i<10000; i++)
+    tab[i] = exp(-(double)i*0.001) ;
+}
+
+TabFExp::~TabFExp()
+{
+  delete[] tab;
+}
+
+TabFExp* ptabFExp;
+
+////////////////////////////////////
+//    Sinus tabules (et Cosinus)  //
+////////////////////////////////////
+
+TabFSin::TabFSin(int n)
+{
+  if(n<=1) n=10000;
+  tab = new double[n];
+  delta = Pi/2. / (double) (n-1);
+  for(int i=0; i<n; i++)
+    tab[i] = sin((double)i* delta) ;
+}
+
+TabFSin::~TabFSin()
+{
+  delete[] tab;
+}
+
+TabFSin* ptabFSin;
Index: /tags/V_Fev00/SophyaLib/NTools/tabmath.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tabmath.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tabmath.h	(revision 752)
@@ -0,0 +1,53 @@
+// This may look like C code, but it is really -*- C++ -*-
+#include <math.h>
+#include "peida.h"
+#include "nbconst.h"
+
+
+///////////////////////////////
+//  Exponentielles tabulees  //
+///////////////////////////////
+
+class TabFExp EXC_AWARE {
+public:
+  TabFExp();
+  ~TabFExp();
+  inline double operator()(double x)
+    { if (x > 0) return exp(x);
+      if (x <= -10) return 0;
+          return tab[int(-x*1000)];
+    }
+private:
+  double* tab;
+};
+
+extern TabFExp* ptabFExp;
+#define tabFExp(_x_) ((*ptabFExp)(_x_))
+
+
+////////////////////////////////////
+//    Sinus tabules (et Cosinus)  //
+////////////////////////////////////
+
+class TabFSin EXC_AWARE {
+public:
+  TabFSin(int ntab = 0);
+  ~TabFSin();
+  inline double operator()(double x)
+    {
+    double s = 1.;
+    if(x<0.) {x *=-1.; s = -1.;}
+    x -= DeuxPi * int(x/DeuxPi);
+    if(x>Pi) {x -= Pi; s *= -1.;}
+    if(x>Pi/2.) x = Pi-x;
+    return s * tab[int(x/delta)];
+    }
+private:
+  int ntab;
+  double delta;
+  double* tab;
+};
+
+extern TabFSin* ptabFSin;
+#define tabFSin(_x_) ((*ptabFSin)(_x_))
+#define tabFCos(_x_) ((*ptabFSin)(_x_+Pis2))
Index: /tags/V_Fev00/SophyaLib/NTools/tmatrix.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tmatrix.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tmatrix.cc	(revision 752)
@@ -0,0 +1,682 @@
+// $Id: tmatrix.cc,v 1.13 2000-02-06 15:05:43 ansari Exp $
+//                         C.Magneville          04/99
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <values.h>
+#include <complex>
+#include "pexceptions.h"
+#include "tmatrix.h"
+#include "objfio.h"
+
+////////////////////////////////////////////////////////////////
+//**** Createur, Destructeur
+
+template <class T>
+TMatrix<T>::TMatrix()
+// Constructeur par defaut.
+: mNr(0), mNc(0), mNDBlock()
+{
+}
+
+template <class T>
+TMatrix<T>::TMatrix(uint_4 r,uint_4 c)
+// Construit une matrice de r lignes et c colonnes.
+: mNr(r), mNc(c), mNDBlock(r*c)
+{
+}
+
+template <class T>
+TMatrix<T>::TMatrix(uint_4 r,uint_4 c,T* values,Bridge* br)
+// Construit une matrice de r lignes et c colonnes. On fournit
+// le tableau des valeurs et eventuellement un Bridge.
+: mNr(r), mNc(c), mNDBlock(r*c,values,br)
+{
+}
+
+template <class T>
+TMatrix<T>::TMatrix(const TMatrix<T>& a)
+// Constructeur par copie (partage si "a" temporaire).
+: mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock)
+{
+}
+
+template <class T>
+TMatrix<T>::TMatrix(const TMatrix<T>& a,bool share)
+// Constructeur par copie avec possibilite de forcer le partage ou non.
+: mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock,share)
+{
+}
+
+template <class T>
+TMatrix<T>::~TMatrix()
+// Destructeur
+{
+}
+
+////////////////////////////////////////////////////////////////
+// Operations matricielles
+template <class T>
+TMatrix<T> TMatrix<T>::Transpose(void) const
+// Transposition
+{
+TMatrix<T> a; a.Clone(*this); a.SetTemp(true);
+a.mNr = mNc; a.mNc = mNr;
+{for(uint_4 i=0; i<mNr; i++)
+  for(uint_4 j=0; j<mNc; j++) {
+    a(j,i) = (*this)(i,j);
+}}
+return a;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Impression
+
+template <class T>
+void TMatrix<T>::Print(ostream& os,int lp
+                 ,uint_4 i0,uint_4 ni,uint_4 j0,uint_4 nj) const
+// Impression de la sous-matrice (i:i+ni-1,i:j+nj-1)
+{
+os<<"TMatrix::Print("<<mNr<<","<<mNc<<")"<<endl;
+if(lp>0)
+  {os<<"       this="<<this<<endl; mNDBlock.Print(0,0);}
+if(mNr==0 || mNc==0) return;
+if(i0>=mNr || j0>=mNc || ni==0 || nj==0) return;
+uint_4 i1 = i0+ni; if(i1>mNr) i1 = mNr;
+uint_4 j1 = j0+nj; if(j1>mNc) j1 = mNc;
+for(uint_4 i=i0;i<i1;i++) {
+  for(uint_4 j=j0;j<j1;j++) cout<<" "<<(*this)(i,j);
+  cout<<endl;
+}
+}
+
+////////////////////////////////////////////////////////////////
+//**** Surcharge de *= (INPLACE): TMatrix *= TMatrix;
+
+template <class T>
+TMatrix<T>& TMatrix<T>::operator *= (const TMatrix<T>& a)
+// A = A*B  -> A(n,m) = A(n,m)*B(m,m)
+{
+uint_4 ndata = mNr*mNc;
+if(ndata==0 || mNc!=a.mNr || a.mNr!=a.mNc)
+  throw(SzMismatchError("TMatrix::operator*=A size mismatch"));
+// A(i,j) = Sum(k) A(i,k)*B(k,j) ... il faut sauver la ligne "i" de A
+// Vecteur oi   : vecteur ou est sauve la ligne i de la matrice *this
+//                oi,oe = pointeur de debut et de fin du vecteur temporaire
+//                oij   = pointeur parcourant le vecteur oi
+// Matrice *this: i     = pointeur du debut de la ligne i
+//                ij    = pointeur parcourant la ligne i
+// Matrice a    : aj    = pointeur de debut de la colonne j
+//                aji   = pointeur parcourant la colonne j
+T* oi = new T[mNc]; T* oe = oi+mNc;
+for(T *i=Data(); i<Data()+ndata; i+=mNc) {
+  {for(T *oij=oi,*ij=i; oij<oe;) *oij++ = *ij++;}
+  {for(T *ij=i,*aj=const_cast<T *>(a.Data()); aj<a.Data()+a.mNc; ij++,aj++) {
+    T sum = 0;
+    for(T *oij=oi,*aji=aj; oij<oe; oij++,aji+=a.mNc) sum += *oij * *aji;
+    *ij = sum;
+  }}
+}
+delete [] oi;
+return *this;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Pour surcharge d'operateurs C = A (+,-,*,/) B
+
+template <class T> TMatrix<T> TMatrix<T>::Add(const TMatrix<T>& b) const
+{
+if(mNr!=b.mNr || mNc!=b.mNc)
+    throw(SzMismatchError("TMatrix operator C=A+B size mismatch\n"));
+TMatrix<T> result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc;
+result.mNDBlock = mNDBlock+b.mNDBlock;
+return result;
+}
+
+template <class T> TMatrix<T> TMatrix<T>::Sub(const TMatrix<T>& b) const
+{
+if(mNr!=b.mNr || mNc!=b.mNc)
+    throw(SzMismatchError("TMatrix operator C=A-B size mismatch\n"));
+TMatrix<T> result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc;
+result.mNDBlock = mNDBlock-b.mNDBlock;
+return result;
+}
+
+template <class T> TMatrix<T> TMatrix<T>::Mul(const TMatrix<T>& b) const
+// C = A(this)*B : Cij = Aik Bkj (allocation forcee dans tous les cas)
+{
+if(mNr==0 || mNc==0 || b.mNc==0 || mNc!=b.mNr)
+  throw(SzMismatchError("TMatrix operator C=A*B size mismatch\n"));
+TMatrix<T> r; r.SetTemp(true); r.ReSize(mNr,b.mNc);
+T *ai,*aik,*bj,*bkj,*ri,*rij;
+for(ri=const_cast<T *>(r.Data()),ai=const_cast<T *>(Data());
+    ri<r.Data()+r.mNr*r.mNc;ri+=r.mNc,ai+=mNc) {
+  for(rij=ri,bj=const_cast<T *>(b.Data());rij<ri+r.mNc;rij++,bj++) {
+    *rij = 0;
+    for(aik=ai,bkj=bj;aik<ai+mNc;aik++,bkj+=b.mNc) *rij += *aik * *bkj;
+  }
+}
+return r;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Pour gestion des lignes et des colonnes
+
+template <class T> TMatrixRC<T> TMatrix<T>::Row(uint_4 r) const
+{
+TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixRow, r);
+return rc;
+}
+
+template <class T> TMatrixRC<T> TMatrix<T>::Col(uint_4 c) const
+{
+TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixCol, c);
+return rc;
+}
+
+template <class T> TMatrixRC<T> TMatrix<T>::Diag() const
+{
+TMatrixRC<T> rc((TMatrix<T>&)*this, TmatrixDiag);
+return rc;
+}
+
+////////////////////////////////////////////////////////////////
+//**** Pour inversion
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef LN_MINDOUBLE
+#define LN_MINDOUBLE  (M_LN2 * (DMINEXP - 1))
+#endif
+#ifndef LN_MAXDOUBLE
+#define LN_MAXDOUBLE  (M_LN2 * DMAXEXP)
+#endif
+
+r_8 TMatrix<r_8>::GausPiv(TMatrix<r_8>& a, TMatrix<r_8>& b)
+// Pivot de Gauss
+// * Attention: egcs impose que cette fonction soit mise dans le .cc
+//              avant ::Inverse() (car Inverse() l'utilise)
+// {TMatrix A(a); TMatrix B(b); return (r_8) TMatrix::GausPiv(A,B);}
+{
+uint_4 n = a.NRows();
+if(n!=b.NRows())
+  throw(SzMismatchError("TMatrix::GausPiv size mismatch\n"));
+// On fait une normalisation un peu brutale...
+double vmin=MAXDOUBLE;
+double vmax=0;
+for(uint_4 iii=0; iii<a.NRows(); iii++)
+  for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
+    double v = TMatrixRC<r_8>::Abs_Value(a(iii,jjj));
+    if(v>vmax) vmax = v;
+    if(v<vmin && v>0) vmin = v;
+}
+double nrm = sqrt(vmin*vmax);
+if(nrm > 1.e5 || nrm < 1.e-5) {
+  a /= nrm;
+  b /= nrm;
+  //cout << "normalisation matrice " << nrm << endl;
+} else nrm=1;
+
+double det = 1.0;
+if(nrm != 1) {
+  double ld = a.NRows() * log(nrm);
+  if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
+   // cerr << "TMatrix warning, overflow for det" << endl;
+  } else {
+    det = exp(ld);
+  }
+}
+
+TMatrixRC<r_8> pivRowa(a,TmatrixRow);
+TMatrixRC<r_8> pivRowb(b,TmatrixRow);
+
+for(uint_4 k=0; k<n-1; k++) {
+  uint_4 iPiv = a.Col(k).IMaxAbs(k);
+  if(iPiv != k) {
+    TMatrixRC<r_8> aIPiv(a.Row(iPiv));
+    TMatrixRC<r_8> aK(a.Row(k));
+    TMatrixRC<r_8>::Swap(aIPiv,aK);
+    TMatrixRC<r_8> bIPiv(b.Row(iPiv));
+    TMatrixRC<r_8> bK(b.Row(k));
+    TMatrixRC<r_8>::Swap(bIPiv,bK);
+  }
+  double pivot = a(k,k);
+  if (fabs(pivot) < 1.e-50) return 0.0;
+  //det *= pivot;
+  pivRowa.SetRow(k); // to avoid constructors
+  pivRowb.SetRow(k);
+  for (uint_4 i=k+1; i<n; i++) {
+    double r = -a(i,k)/pivot;
+    a.Row(i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa
+    b.Row(i).LinComb(r, pivRowb);
+  }
+}
+det *= a(n-1, n-1);
+
+// on remonte
+for(uint_4 kk=n-1; kk>0; kk--) {
+  double pivot = a(kk,kk);
+  if (fabs(pivot) <= 1.e-50) return 0.0;
+  pivRowa.SetRow(kk); // to avoid constructors
+  pivRowb.SetRow(kk);
+  for(uint_4 jj=0; jj<kk; jj++) {
+    double r = -a(jj,kk)/pivot;
+    a.Row(jj).LinComb(r, pivRowa);
+    b.Row(jj).LinComb(r, pivRowb);
+  }
+}
+
+for(uint_4 l=0; l<n; l++) {
+  if (fabs(a(l,l)) <= 1.e-50) return 0.0;
+  b.Row(l) /= a(l,l);
+}
+
+return det;
+}
+
+TMatrix<r_8> TMatrix<r_8>::Inverse() const
+// Inversion
+{
+TMatrix<r_8> b(mNc,mNr); TMatrix<r_8> a(*this); b = 1.;
+if(fabs(TMatrix<r_8>::GausPiv(a,b)) < 1.e-50)
+  throw(MathExc("TMatrix Inverse() Singular OMatrix"));
+return b;
+}
+
+#include "generalfit.h"
+//////////////////////////////////////////////////////////
+//**** Residus des fits
+TMatrix<r_8> TMatrix<r_8>::FitResidus(GeneralFit& gfit
+            ,double xorg,double yorg,double dx,double dy)
+// Retourne une classe contenant les residus du fit ``gfit''.
+// On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j).
+// Les coordonnees de l'element (i,j) sont :
+//    (i,j) -> x = xorg+j*dx , y = yorg+i*dy
+{
+if(NCols()<=0||NRows()<=0)
+  throw(SzMismatchError("TMatrix::FitResidus size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("TMatrix::FitResidus GeneraFit==NULL\n"));
+int npar =  gfit.GetNPar();
+if(npar==0)
+  throw(SzMismatchError("TMatrix::FitResidus GeneraFit 0 parametre\n"));
+double* par = new double[npar];
+{for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
+TMatrix<r_8> m(*this);
+for(uint_4 i=0;i<NRows();i++) for(uint_4 j=0;j<NCols();j++) {
+  double x[2] = {xorg+j*dx,yorg+i*dy};
+  m(i,j) -= f->Value(x,par);
+}
+delete [] par;
+return m;
+}
+
+TMatrix<r_8> TMatrix<r_8>::FitFunction(GeneralFit& gfit
+            ,double xorg,double yorg,double dx,double dy)
+// Retourne une classe contenant la fonction du fit ``gfit''.
+// On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j).
+// Les coordonnees de l'element (i,j) sont :
+//    (i,j) -> x = xorg + j*dx , y = yorg + i*dy
+{
+if(NCols()<=0||NRows()<=0)
+  throw(SzMismatchError("TMatrix::FitFunction size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("TMatrix::FitFunction GeneraFit==NULL\n"));
+int npar =  gfit.GetNPar();
+if(npar==0)
+  throw(SzMismatchError("TMatrix::FitFunction GeneraFit 0 parametre\n"));
+double* par = new double[npar];
+{for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
+TMatrix<r_8> m(*this);
+for(uint_4 i=0;i<NRows();i++) for(uint_4 j=0;j<NCols();j++) {
+  double x[2] = {xorg+j*dx,yorg+i*dy};
+  m(i,j) = f->Value(x,par);
+}
+delete [] par;
+return m;
+}
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+template <class T>
+FIO_TMatrix<T>::FIO_TMatrix()
+{
+dobj=new TMatrix<T>;
+ownobj=true;
+}
+
+template <class T>
+FIO_TMatrix<T>::FIO_TMatrix(string const & filename) 
+{
+dobj=new TMatrix<T>;
+ownobj=true; 
+Read(filename);
+}
+
+template <class T>
+FIO_TMatrix<T>::FIO_TMatrix(const TMatrix<T> & obj) 
+{ 
+dobj = new TMatrix<T>(obj);
+ownobj=true; 
+}
+
+template <class T>
+FIO_TMatrix<T>::FIO_TMatrix(TMatrix<T> * obj) 
+{ 
+dobj = obj;
+ownobj=false; 
+}
+
+template <class T>
+FIO_TMatrix<T>::~FIO_TMatrix()
+{
+if (ownobj && dobj) delete dobj;
+}
+
+template <class T>
+AnyDataObj* FIO_TMatrix<T>::DataObj()
+{
+return(dobj);
+}
+
+template <class T>
+void FIO_TMatrix<T>::ReadSelf(PInPersist& is)
+{
+// On lit les 3 premiers uint_4
+//  0: Numero de version,  1 : NRows,  2 : NCol
+uint_4 itab[3];
+is.Get(itab,3);
+if (dobj == NULL) dobj = new TMatrix<T>(itab[1],itab[2]);
+else dobj->ReSize(itab[1],itab[2]);
+// On lit le NDataBlock
+FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+fio_nd.Read(is);
+}
+
+template <class T>
+void FIO_TMatrix<T>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+//  On ecrit 3 uint_4 .... 
+//  0: Numero de version,  1 : NRows,  2 : NCol
+uint_4 itab[3];
+ itab[0] = 1;  // Numero de version a 1
+itab[1] = dobj->NRows();
+itab[2] = dobj->NCols();
+os.Put(itab,3);
+// On ecrit le NDataBlock
+FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+fio_nd.Write(os);
+}
+
+////////////////////////////////////////////////////////////////
+// -------------------------------------------------------------
+//   La classe de gestion des lignes et colonnes d'une matrice
+// -------------------------------------------------------------
+////////////////////////////////////////////////////////////////
+#include "tvector.h"
+
+template <class T> TMatrixRC<T>::TMatrixRC()
+: matrix(NULL), data(NULL), index(0), step(0)
+{}
+
+template <class T> TMatrixRC<T>::TMatrixRC(TMatrix<T>& m,TRCKind rckind,uint_4 ind)
+: matrix(&m), data(Org(m,rckind,ind)),
+  index(ind), step(Step(m,rckind)), kind(rckind)
+{
+if (kind == TmatrixDiag && m.mNc != m.mNr)
+  throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n"));
+}
+
+template <class T> int_4 TMatrixRC<T>::Next()
+{
+if (!matrix || kind==TmatrixDiag) return -1;
+index++;
+if(kind == TmatrixRow) {
+  if(index > (int_4)matrix->mNr) {index = (int_4)matrix->mNr; return -1;}
+  data += matrix->mNc;
+} else {
+  if (index > (int_4)matrix->mNc) {index = (int_4)matrix->mNc; return -1;}
+  data++;
+}
+return index;
+}
+
+template <class T> int_4 TMatrixRC<T>::Prev()
+{
+if (!matrix || kind == TmatrixDiag) return -1;
+index--;
+if(index < 0) {index = 0; return -1;}
+if(kind == TmatrixRow) data -= matrix->mNc;
+else data--;
+return index;
+}
+
+template <class T> int_4 TMatrixRC<T>::SetCol(int_4 c)
+{
+if(!matrix) return -1;
+if(c<0 || c>(int_4)matrix->mNc) return -1;
+kind = TmatrixCol;
+index = c;
+step = Step(*matrix, TmatrixCol);
+data = Org(*matrix, TmatrixCol, c);
+return c;
+}
+
+template <class T> int_4 TMatrixRC<T>::SetRow(int_4 r)
+{
+if(!matrix) return -1;
+if(r<0 && r>(int_4)matrix->mNr) return -1;
+kind = TmatrixRow;
+index = r;
+step = Step(*matrix, TmatrixRow);
+data = Org(*matrix, TmatrixRow, r);
+return r;
+}
+
+template <class T> int_4 TMatrixRC<T>::SetDiag()
+{
+if (!matrix) return -1;
+if (matrix->mNc != matrix->mNr)
+  throw(SzMismatchError("TMatrixRC::SetDiag size mismatch\n"));
+kind = TmatrixDiag;
+index = 0;
+step = Step(*matrix, TmatrixDiag);
+data = Org(*matrix, TmatrixDiag);
+return 0;
+}
+
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator = (const TMatrixRC<T>& rc)
+{
+matrix = rc.matrix;
+data   = rc.data;
+index  = rc.index;
+step   = rc.step;
+kind   = rc.kind;
+return *this;
+}
+
+template <class T> TVector<T> TMatrixRC<T>::GetVect() const
+{
+TVector<T> v(NElts());
+for (uint_4 i=0; i<NElts(); i++) v(i) = (*this)(i);
+return v;
+}
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (const TMatrixRC<T>& rc)
+{
+if ( NElts() != rc.NElts() )
+  throw(SzMismatchError("TMatrixRC::operator+= size mismatch\n"));
+if ( kind != rc.kind )
+  throw(SzMismatchError("TMatrixRC::operator+= type mismatch\n"));
+for (uint_4 i=0; i<NElts(); i++) (*this)(i) += rc(i);
+return *this;
+}
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (const TMatrixRC<T>& rc)
+{
+if( NElts() != rc.NElts() )
+  throw(SzMismatchError("TMatrixRC::operator-= size mismatch\n"));
+if( kind != rc.kind )
+  throw(SzMismatchError("TMatrixRC::operator-= type mismatch\n"));
+for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= rc(i);
+return *this;
+}
+
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator *= (T x)
+{
+for(uint_4 i=0; i<NElts(); i++) (*this)(i) *= x;
+return *this;
+}
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator /= (T x)
+{
+for(uint_4 i=0; i<NElts(); i++) (*this)(i) /= x;
+return *this;
+}
+
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (T x)
+{
+for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= x;
+return *this;
+}
+
+template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (T x)
+{
+for(uint_4 i=0; i<NElts(); i++) (*this)(i) += x;
+return *this;
+}
+
+template <class T>
+TMatrixRC<T>& TMatrixRC<T>::LinComb(T a, T b, const TMatrixRC<T>& rc, uint_4 first)
+{
+if ( NElts() != rc.NElts() )
+  throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
+if ( kind != rc.kind )
+  throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
+for(uint_4 i=first; i<NElts(); i++) (*this)(i) = (*this)(i)*a + rc(i)*b;
+return *this;
+}
+
+template <class T>
+TMatrixRC<T>& TMatrixRC<T>::LinComb(T b, const TMatrixRC<T>& rc, uint_4 first)
+{
+if ( NElts() != rc.NElts() )
+  throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
+if ( kind != rc.kind )
+  throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
+for(uint_4 i=first; i<NElts(); i++) (*this)(i) += rc(i)*b;
+return *this;
+}
+
+template <class T> uint_4 TMatrixRC<T>::IMaxAbs(uint_4 first)
+{
+if (first>NElts())
+  throw(SzMismatchError("TMatrixRC::IMaxAbs size mismatch\n"));
+uint_4 imax = first;
+double vmax = Abs_Value((*this)(first));
+for(uint_4 i=first+1; i<NElts(); i++) {
+  double v = Abs_Value((*this)(i));
+  if(v > vmax) {vmax = v; imax = i;}
+}
+return imax;
+}
+
+template <class T>
+void TMatrixRC<T>::Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2)
+{
+if(rc1.NElts() != rc2.NElts())
+  throw(SzMismatchError("TMatrixRC::Swap size mismatch\n"));
+if(rc1.kind != rc2.kind)
+  throw(SzMismatchError("TMatrixRC::Swap type mismatch\n"));
+if(rc1.data == rc2.data) return;
+for(uint_4 i=0; i<rc1.NElts(); i++)
+  {T tmp = rc1(i); rc1(i) = rc2(i); rc2(i) = tmp;}
+}
+
+///////////////////////////////////////////////////////////////
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template TMatrix<uint_1>
+#pragma define_template TMatrix<uint_2>
+#pragma define_template TMatrix<int_2>
+#pragma define_template TMatrix<int_4>
+#pragma define_template TMatrix<int_8>
+#pragma define_template TMatrix<uint_4>
+#pragma define_template TMatrix<uint_8>
+#pragma define_template TMatrix<r_4>
+#pragma define_template TMatrix<r_8>
+#pragma define_template TMatrix< complex<r_4> > 
+#pragma define_template TMatrix< complex<r_8> > 
+// Instances des delegues FileIO (PPersist)
+#pragma define_template FIO_TMatrix<uint_1>
+#pragma define_template FIO_TMatrix<uint_2>
+#pragma define_template FIO_TMatrix<int_2>
+#pragma define_template FIO_TMatrix<int_4>
+#pragma define_template FIO_TMatrix<int_8>
+#pragma define_template FIO_TMatrix<uint_4>
+#pragma define_template FIO_TMatrix<uint_8>
+#pragma define_template FIO_TMatrix<r_8>
+#pragma define_template FIO_TMatrix<r_4>
+#pragma define_template FIO_TMatrix< complex<r_4> >
+#pragma define_template FIO_TMatrix< complex<r_8> >
+// Instances gestion lignes/colonnes
+#pragma define_template TMatrixRC<uint_1>
+#pragma define_template TMatrixRC<uint_2>
+#pragma define_template TMatrixRC<int_2>
+#pragma define_template TMatrixRC<int_4>
+#pragma define_template TMatrixRC<int_8>
+#pragma define_template TMatrixRC<uint_4>
+#pragma define_template TMatrixRC<uint_8>
+#pragma define_template TMatrixRC<r_4>
+#pragma define_template TMatrixRC<r_8>
+#pragma define_template TMatrixRC< complex<r_4> > 
+#pragma define_template TMatrixRC< complex<r_8> >
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class TMatrix<uint_1>;
+template class TMatrix<uint_2>;
+template class TMatrix<int_2>;
+template class TMatrix<int_4>;
+template class TMatrix<int_8>;
+template class TMatrix<uint_4>;
+template class TMatrix<uint_8>;
+template class TMatrix<r_4>;
+template class TMatrix<r_8>;
+template class TMatrix< complex<r_4> >;
+template class TMatrix< complex<r_8> >;
+// Instances des delegues FileIO (PPersist)
+template class FIO_TMatrix<uint_1>;
+template class FIO_TMatrix<uint_2>;
+template class FIO_TMatrix<int_2>;
+template class FIO_TMatrix<int_4>;
+template class FIO_TMatrix<int_8>;
+template class FIO_TMatrix<uint_4>;
+template class FIO_TMatrix<uint_8>;
+template class FIO_TMatrix<r_8>;
+template class FIO_TMatrix<r_4>;
+template class FIO_TMatrix< complex<r_4> >;
+template class FIO_TMatrix< complex<r_8> >;
+// Instances gestion lignes/colonnes
+template class TMatrixRC<uint_1>;
+template class TMatrixRC<uint_2>;
+template class TMatrixRC<int_2>;
+template class TMatrixRC<int_4>;
+template class TMatrixRC<int_8>;
+template class TMatrixRC<uint_4>;
+template class TMatrixRC<uint_8>;
+template class TMatrixRC<r_4>;
+template class TMatrixRC<r_8>;
+template class TMatrixRC< complex<r_4> >;
+template class TMatrixRC< complex<r_8> >;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/tmatrix.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tmatrix.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tmatrix.h	(revision 752)
@@ -0,0 +1,323 @@
+// This may look like C code, but it is really -*- C++ -*-
+//                         C.Magneville          04/99
+#ifndef TMatrix_SEEN
+#define TMatrix_SEEN
+
+#include "machdefs.h"
+#include <stdio.h>
+#include <iostream.h>
+#include <complex>
+#include "ppersist.h"
+#include "anydataobj.h"
+#include "ndatablock.h"
+
+namespace SOPHYA {
+
+class GeneralFit;
+template <class T> class TVector;
+template <class T> class TMatrixRC;
+
+template <class T>
+class TMatrix : public AnyDataObj {
+  friend class TMatrixRC<T>;
+  friend class TVector<T>;
+public:
+
+  // Creation / destruction 
+  TMatrix();
+  TMatrix(uint_4 r,uint_4 c);
+  TMatrix(uint_4 r,uint_4 c,T* values,Bridge* br=NULL);
+  TMatrix(const TMatrix<T>& a);
+  TMatrix(const TMatrix<T>& a,bool share);
+  virtual ~TMatrix();
+
+  // Temporaire?
+  inline bool IsTemp(void) const {return mNDBlock.IsTemp();}
+  inline void SetTemp(bool temp=false) const {mNDBlock.SetTemp(temp);}
+
+  // Gestion taille/Remplissage
+  inline void Clone(const TMatrix<T>& a)  // Clone: copie des donnees de "a"
+              {mNDBlock.Clone(a.mNDBlock); mNr = a.mNr; mNc = a.mNc;}
+  inline void Reset(T v=0) {mNDBlock.Reset(v);}
+  inline void ReSize(uint_4 r,uint_4 c)  // Reallocation de place
+       {if(r==0||c==0) throw(SzMismatchError("TMatrix::ReSize r ou c==0\n"));
+        mNDBlock.ReSize(r*c); mNr = r; mNc = c;}
+  inline void Realloc(uint_4 r,uint_4 c,bool force=false)
+       {if(r==0||c==0) throw(SzMismatchError("TMatrix::Realloc r ou c==0\n"));
+        mNDBlock.Realloc(r*c,force); mNr = r; mNc = c;}
+
+  // Informations pointeur/data
+  inline uint_4 NRows() const {return mNr;}
+  inline uint_4 NCols() const {return mNc;}
+  inline uint_4 NCol() const {return mNc;} // back-compat Peida
+  inline T const& operator()(uint_4 r,uint_4 c) const
+                            {return *(mNDBlock.Begin()+r*mNc+c);}
+  inline T&       operator()(uint_4 r,uint_4 c)
+                            {return *(mNDBlock.Begin()+r*mNc+c);}
+  inline T const& operator[](uint_4 ip) const
+                            {return *(mNDBlock.Begin()+ip);}
+  inline T&       operator[](uint_4 ip)
+                            {return *(mNDBlock.Begin()+ip);}
+  inline       T* Data()       {return mNDBlock.Begin();}
+  inline const T* Data() const {return mNDBlock.Begin();}
+  inline       NDataBlock<T>& DataBlock()       {return mNDBlock;}
+  inline const NDataBlock<T>& DataBlock() const {return mNDBlock;}
+
+  // Operations matricielles
+  TMatrix<T> Transpose(void) const;
+
+  // Operateur d'affectation
+  // A = x (matrice diagonale x*Identite)
+  inline TMatrix<T>& operator = (T x)
+    {if(mNr!=mNc || mNr==0) throw(SzMismatchError("TMatrix::operator= mNc!=mNr ou ==0\n"));
+     for(uint_4 r=0;r<mNr;r++) for(uint_4 c=0;c<mNc;c++) (*this)(r,c)=(r==c)?x:(T)0;
+     return *this;}
+  // A = B : partage les donnees si "a" est temporaire, clone sinon.
+  inline TMatrix<T>& operator = (const TMatrix<T>& a)
+                {if(this == &a) return *this; CloneOrShare(a); return *this;}
+
+  // Impression
+  void Print(ostream& os,int lp=0,uint_4 i0=0,uint_4 ni=10,uint_4 j0=0,uint_4 nj=10) const;
+  inline void Print(int lp=0,uint_4 i0=0,uint_4 ni=10,uint_4 j0=0,uint_4 nj=10) const
+              {Print(cout,lp,i0,ni,j0,nj);}
+
+  // Surcharge d'operateurs INPLACE: A (+=,-=,*=,/=) (T) x
+  inline TMatrix<T>& operator += (T b) {mNDBlock += b; return *this;}
+  inline TMatrix<T>& operator -= (T b) {mNDBlock -= b; return *this;}
+  inline TMatrix<T>& operator *= (T b) {mNDBlock *= b; return *this;}
+  inline TMatrix<T>& operator /= (T b) {mNDBlock /= b; return *this;}
+
+  // Surcharge d'operateurs INPLACE: A (+=,-=,*=,/=) B
+  inline TMatrix<T>& operator += (const TMatrix<T>& a)
+              {if(mNr==0 || mNc==0 || mNr!=a.mNr || mNc!=a.mNc)
+                  throw(SzMismatchError("TMatrix::operator+=A size mismatch"));
+               mNDBlock += a.mNDBlock; return *this;}
+  inline TMatrix<T>& operator -= (const TMatrix<T>& a)
+              {if(mNr==0 || mNc==0 || mNr!=a.mNr || mNc!=a.mNc)
+                  throw(SzMismatchError("TMatrix::operator-=A size mismatch"));
+               mNDBlock -= a.mNDBlock; return *this;}
+  TMatrix<T>& operator *= (const TMatrix<T>& a);
+
+  // Pour surcharge d'operateurs C = A (+,-,*) B
+  TMatrix<T> Add(const TMatrix<T>& b) const;
+  TMatrix<T> Sub(const TMatrix<T>& b) const;
+  TMatrix<T> Mul(const TMatrix<T>& b) const;
+
+  // Pivot de Gauss : diagonalise la matrice A, en effectuant les memes
+  // operations sur la matrice B
+  TMatrix<T> Inverse() const;
+  static T GausPiv(TMatrix<T>& A, TMatrix<T>& B);
+
+  // Residus et fonction fittees.
+  TMatrix<T> FitResidus(GeneralFit& gfit
+            ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
+  TMatrix<T> FitFunction(GeneralFit& gfit
+            ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
+
+  // Acces aux rangees et colonnes
+  TMatrixRC<T> Row(uint_4 r) const;
+  TMatrixRC<T> Col(uint_4 c) const;
+  TMatrixRC<T> Diag() const;
+
+protected:
+  // partage les donnees si "a" temporaire, clone sinon.
+  inline void CloneOrShare(const TMatrix<T>& a)
+              {mNDBlock.CloneOrShare(a.mNDBlock); mNr=a.mNr; mNc=a.mNc;}
+  // Share: partage les donnees de "a"
+  inline void Share(const TMatrix<T>& a)
+              {mNDBlock.Share(a.mNDBlock); mNr=a.mNr; mNc=a.mNc;}
+
+  uint_4 mNr,mNc;
+  NDataBlock<T> mNDBlock;
+};
+
+////////////////////////////////////////////////////////////////
+// Impression
+
+template <class T>
+inline ostream& operator << (ostream& os, const TMatrix<T>& a)
+                            {a.Print(os); return(os);}
+
+////////////////////////////////////////////////////////////////
+// Surcharge d'operateurs A (+,-,*,/) (T) x
+
+template <class T> inline TMatrix<T> operator + (const TMatrix<T>& a, T b)
+    {TMatrix<T> result(a); result.SetTemp(true); result += b; return result;}
+
+template <class T> inline TMatrix<T> operator + (T b,const TMatrix<T>& a)
+    {TMatrix<T> result(a); result.SetTemp(true); result += b; return result;}
+
+template <class T> inline TMatrix<T> operator - (const TMatrix<T>& a, T b)
+    {TMatrix<T> result(a); result.SetTemp(true); result -= b; return result;}
+
+template <class T> inline TMatrix<T> operator - (T b,const TMatrix<T>& a)
+    {TMatrix<T> result(a); result.SetTemp(true);
+     result.DataBlock() = b-result.DataBlock(); return result;}
+
+template <class T> inline TMatrix<T> operator * (const TMatrix<T>& a, T b)
+    {TMatrix<T> result(a); result.SetTemp(true); result *= b; return result;}
+
+template <class T> inline TMatrix<T> operator * (T b,const TMatrix<T>& a)
+    {TMatrix<T> result(a); result.SetTemp(true); result *= b; return result;}
+
+template <class T> inline TMatrix<T> operator / (const TMatrix<T>& a, T b)
+    {TMatrix<T> result(a); result.SetTemp(true); result /= b; return result;}
+
+////////////////////////////////////////////////////////////////
+// Surcharge d'operateurs C = A (+,-,*,/) B
+
+template <class T>
+inline TMatrix<T> operator + (const TMatrix<T>& a,const TMatrix<T>& b)
+                  {return a.Add(b);}
+
+template <class T>
+inline TMatrix<T> operator - (const TMatrix<T>& a,const TMatrix<T>& b)
+                  {return a.Sub(b);}
+
+template <class T>
+inline TMatrix<T> operator * (const TMatrix<T>& a,const TMatrix<T>& b)
+                  {return a.Mul(b);}
+
+////////////////////////////////////////////////////////////////
+// Typedef pour simplifier et compatibilite Peida
+typedef TMatrix<r_8> Matrix;
+
+/////////////////////////////////////////////////////////////////////////
+// Classe pour la gestion de persistance
+template <class T>
+class FIO_TMatrix : public  PPersist  {
+public:
+  FIO_TMatrix();
+  FIO_TMatrix(string const & filename); 
+  FIO_TMatrix(const TMatrix<T> & obj);
+  FIO_TMatrix(TMatrix<T> * obj);
+  virtual ~FIO_TMatrix();
+  virtual AnyDataObj* DataObj();
+  inline operator TMatrix<T>() { return(*dobj); }
+protected :
+  virtual void ReadSelf(PInPersist&);           
+  virtual void WriteSelf(POutPersist&) const;  
+  TMatrix<T> * dobj;
+  bool ownobj;
+};
+
+template <class T>
+inline POutPersist& operator << (POutPersist& os, TMatrix<T> & obj)
+{ FIO_TMatrix<T> fio(&obj);  fio.Write(os);  return(os); }
+template <class T>
+inline PInPersist& operator >> (PInPersist& is, TMatrix<T> & obj)
+{ FIO_TMatrix<T> fio(&obj);  fio.Read(is);  return(is); }
+
+/////////////////////////////////////////////////////////////////////////
+// Classe de lignes/colonnes de matrices
+enum TRCKind {TmatrixRow=0, TmatrixCol=1, TmatrixDiag=2};
+template <class T>
+class TMatrixRC {
+  friend class TVector<T>;
+  friend class TMatrix<T>;
+public:
+  TMatrixRC();
+
+  virtual ~TMatrixRC() {}
+
+  int_4 Next();
+  int_4 Prev();
+  int_4 SetCol(int_4 c);
+  int_4 SetRow(int_4 r);
+  int_4 SetDiag();
+
+  static uint_4 Step(const TMatrix<T>& m, TRCKind rckind);
+  static T* Org(const TMatrix<T>&, TRCKind rckind, uint_4 ind=0);
+
+  TRCKind Kind() const { return kind; }
+  uint_4 NElts() const;
+  T& operator()(uint_4 i);
+  T  operator()(uint_4 i) const;
+
+  TMatrixRC<T>& operator = (const TMatrixRC<T>& rc);
+  TVector<T> GetVect() const;
+
+  TMatrixRC<T>& operator += (const TMatrixRC<T>& rc);
+  TMatrixRC<T>& operator -= (const TMatrixRC<T>& rc);
+
+  TMatrixRC<T>& operator *= (T x);
+  TMatrixRC<T>& operator /= (T x);
+  TMatrixRC<T>& operator -= (T x);
+  TMatrixRC<T>& operator += (T x);
+
+  TMatrixRC<T>& LinComb(T a, T b, const TMatrixRC& rc, uint_4 first=0);
+  TMatrixRC<T>& LinComb(T b, const TMatrixRC<T>& rc, uint_4 first=0);
+
+  uint_4 IMaxAbs(uint_4 first=0);
+
+  static void Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2);
+
+protected:
+  TMatrixRC(TMatrix<T>& m, TRCKind kind, uint_4 index=0);
+  TMatrix<T>* matrix;
+  inline static double Abs_Value(uint_1 v) {return (double) v;}
+  inline static double Abs_Value(uint_2 v) {return (double) v;}
+  inline static double Abs_Value(int_2 v)  {return (v>0)? (double) v: (double) -v;}
+  inline static double Abs_Value(int_4 v)  {return (v>0)? (double) v: (double) -v;}
+  inline static double Abs_Value(int_8 v)  {return (v>0)? (double) v: (double) -v;}
+  inline static double Abs_Value(uint_4 v) {return (double) v;}
+  inline static double Abs_Value(uint_8 v) {return (double) v;}
+  inline static double Abs_Value(r_4 v)    {return (double) fabsf(v);}
+  inline static double Abs_Value(r_8 v)    {return fabs(v);}
+  inline static double Abs_Value(complex<float> v)
+                {return sqrt(v.real()*v.real()+v.imag()*v.imag());}
+  inline static double Abs_Value(complex<double> v)
+                {return sqrt(v.real()*v.real()+v.imag()*v.imag());}
+
+  T*          data;
+  int_4       index;
+  uint_4      step;
+  TRCKind     kind;
+};
+
+
+template <class T>
+inline T operator * (const TMatrixRC<T>& a, const TMatrixRC<T>& b)
+  {
+  if ( a.NElts() != b.NElts() )
+    throw(SzMismatchError("TMatrixRC::operator * size mismatch\n"));
+  if ( a.Kind() != b.Kind() )
+    throw(SzMismatchError("TMatrixRC::operator * type mismatch\n"));
+  T sum = 0;
+  for(uint_4 i=0; i<a.NElts(); i++) sum += a(i)*b(i);
+  return sum;
+  }
+
+template <class T>
+inline uint_4 TMatrixRC<T>::Step(const TMatrix<T>& m, TRCKind rckind)
+  { switch (rckind) { case TmatrixRow  : return 1;
+                      case TmatrixCol  : return m.mNc;
+                      case TmatrixDiag : return m.mNc+1; }
+    return 0; }
+
+template <class T>
+inline T* TMatrixRC<T>::Org(const TMatrix<T>& m, TRCKind rckind, uint_4 index)
+  { switch (rckind) { case TmatrixRow  : return const_cast<T *>(m.Data()) + index * m.mNc;
+                      case TmatrixCol  : return const_cast<T *>(m.Data()) + index;
+                      case TmatrixDiag : return const_cast<T *>(m.Data()); }
+    return NULL; }
+
+template <class T> inline uint_4 TMatrixRC<T>::NElts() const
+  { if (!matrix) return 0;
+    switch (kind) { case TmatrixRow  : return matrix->mNc;
+                    case TmatrixCol  : return matrix->mNr;
+                    case TmatrixDiag : return matrix->mNc; }
+    return 0; }
+
+template <class T>
+inline T& TMatrixRC<T>::operator()(uint_4 i) {return data[i*step];}
+template <class T>
+inline T  TMatrixRC<T>::operator()(uint_4 i) const {return data[i*step];}
+
+////////////////////////////////////////////////////////////////
+// Typedef pour simplifier et compatibilite Peida
+typedef TMatrixRC<r_8> MatrixRC;
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/trigtbl.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/trigtbl.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/trigtbl.h	(revision 752)
@@ -0,0 +1,169 @@
+#ifndef  TRIGTBL_H_SEEN
+#define  TRIGTBL_H_SEEN
+
+/*
+** Please only distribute this with it's associated FHT routine.
+** This algorithm is apparently patented(!) and the code copyrighted. 
+** See the comment with the fht routine for more info.
+**   -Thanks,
+**   Ron Mayer
+*/
+
+#ifdef REAL
+#else
+#define REAL double
+#endif
+
+#ifdef GOOD_TRIG
+#else
+#define FAST_TRIG
+#endif
+
+#if defined(GOOD_TRIG)
+#define FHT_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
+#define TRIG_VARS					         \
+      int t_lam=0;
+#define TRIG_INIT(k,c,s)					 \
+     {								 \
+      int i;							 \
+      for (i=2 ; i<=k ; i++)					 \
+          {coswrk[i]=costab[i];sinwrk[i]=sintab[i];}		 \
+      t_lam = 0;					         \
+      c = 1;							 \
+      s = 0;							 \
+     }
+#define TRIG_NEXT(k,c,s)					 \
+     {								 \
+	 int i,j;	                                         \
+         (t_lam)++;	  					 \
+         for (i=0 ; !((1<<i)&t_lam) ; i++);			 \
+         i = k-i;						 \
+         s = sinwrk[i];						 \
+         c = coswrk[i];						 \
+         if (i>1)   						 \
+            {	    						 \
+             for (j=k-i+2 ; (1<<j)&t_lam ; j++);		 \
+             j	       = k - j;					 \
+             sinwrk[i] = halsec[i] * (sinwrk[i-1] + sinwrk[j]);  \
+             coswrk[i] = halsec[i] * (coswrk[i-1] + coswrk[j]);  \
+            }                                                    \
+     }
+#define TRIG_RESET(k,c,s)
+#endif
+
+#if defined(FAST_TRIG)
+#define TRIG_VARS					 \
+      REAL t_c,t_s;
+#define TRIG_INIT(k,c,s)				 \
+    {				        		 \
+     t_c  = costab[k];				         \
+     t_s  = sintab[k];				         \
+     c    = 1;				    		 \
+     s    = 0;				    		 \
+    }
+#define TRIG_NEXT(k,c,s)				 \
+    {                                                    \
+     REAL t = c;                                         \
+     c   = t*t_c - s*t_s;				 \
+     s   = t*t_s + s*t_c;				 \
+    }
+#define TRIG_RESET(k,c,s)
+#endif
+
+static REAL halsec[20]=
+    {
+     0,
+     0,
+     .54119610014619698439972320536638942006107206337801,
+     .50979557910415916894193980398784391368261849190893,
+     .50241928618815570551167011928012092247859337193963,
+     .50060299823519630134550410676638239611758632599591,
+     .50015063602065098821477101271097658495974913010340,
+     .50003765191554772296778139077905492847503165398345,
+     .50000941253588775676512870469186533538523133757983,
+     .50000235310628608051401267171204408939326297376426,
+     .50000058827484117879868526730916804925780637276181,
+     .50000014706860214875463798283871198206179118093251,
+     .50000003676714377807315864400643020315103490883972,
+     .50000000919178552207366560348853455333939112569380,
+     .50000000229794635411562887767906868558991922348920,
+     .50000000057448658687873302235147272458812263401372
+    };
+static REAL costab[20]=
+    {
+     .00000000000000000000000000000000000000000000000000,
+     .70710678118654752440084436210484903928483593768847,
+     .92387953251128675612818318939678828682241662586364,
+     .98078528040323044912618223613423903697393373089333,
+     .99518472667219688624483695310947992157547486872985,
+     .99879545620517239271477160475910069444320361470461,
+     .99969881869620422011576564966617219685006108125772,
+     .99992470183914454092164649119638322435060646880221,
+     .99998117528260114265699043772856771617391725094433,
+     .99999529380957617151158012570011989955298763362218,
+     .99999882345170190992902571017152601904826792288976,
+     .99999970586288221916022821773876567711626389934930,
+     .99999992646571785114473148070738785694820115568892,
+     .99999998161642929380834691540290971450507605124278,
+     .99999999540410731289097193313960614895889430318945,
+     .99999999885102682756267330779455410840053741619428
+    };
+static REAL sintab[20]=
+    {
+     1.0000000000000000000000000000000000000000000000000,
+     .70710678118654752440084436210484903928483593768846,
+     .38268343236508977172845998403039886676134456248561,
+     .19509032201612826784828486847702224092769161775195,
+     .09801714032956060199419556388864184586113667316749,
+     .04906767432741801425495497694268265831474536302574,
+     .02454122852291228803173452945928292506546611923944,
+     .01227153828571992607940826195100321214037231959176,
+     .00613588464915447535964023459037258091705788631738,
+     .00306795676296597627014536549091984251894461021344,
+     .00153398018628476561230369715026407907995486457522,
+     .00076699031874270452693856835794857664314091945205,
+     .00038349518757139558907246168118138126339502603495,
+     .00019174759731070330743990956198900093346887403385,
+     .00009587379909597734587051721097647635118706561284,
+     .00004793689960306688454900399049465887274686668768
+    };
+static REAL coswrk[20]=
+    {
+     .00000000000000000000000000000000000000000000000000,
+     .70710678118654752440084436210484903928483593768847,
+     .92387953251128675612818318939678828682241662586364,
+     .98078528040323044912618223613423903697393373089333,
+     .99518472667219688624483695310947992157547486872985,
+     .99879545620517239271477160475910069444320361470461,
+     .99969881869620422011576564966617219685006108125772,
+     .99992470183914454092164649119638322435060646880221,
+     .99998117528260114265699043772856771617391725094433,
+     .99999529380957617151158012570011989955298763362218,
+     .99999882345170190992902571017152601904826792288976,
+     .99999970586288221916022821773876567711626389934930,
+     .99999992646571785114473148070738785694820115568892,
+     .99999998161642929380834691540290971450507605124278,
+     .99999999540410731289097193313960614895889430318945,
+     .99999999885102682756267330779455410840053741619428
+    };
+static REAL sinwrk[20]=
+    {
+     1.0000000000000000000000000000000000000000000000000,
+     .70710678118654752440084436210484903928483593768846,
+     .38268343236508977172845998403039886676134456248561,
+     .19509032201612826784828486847702224092769161775195,
+     .09801714032956060199419556388864184586113667316749,
+     .04906767432741801425495497694268265831474536302574,
+     .02454122852291228803173452945928292506546611923944,
+     .01227153828571992607940826195100321214037231959176,
+     .00613588464915447535964023459037258091705788631738,
+     .00306795676296597627014536549091984251894461021344,
+     .00153398018628476561230369715026407907995486457522,
+     .00076699031874270452693856835794857664314091945205,
+     .00038349518757139558907246168118138126339502603495,
+     .00019174759731070330743990956198900093346887403385,
+     .00009587379909597734587051721097647635118706561284,
+     .00004793689960306688454900399049465887274686668768
+    };
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/tvector.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tvector.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tvector.cc	(revision 752)
@@ -0,0 +1,227 @@
+// $Id: tvector.cc,v 1.6 2000-02-06 15:05:43 ansari Exp $
+//                         C.Magneville          04/99
+#include "machdefs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <complex>
+#include "pexceptions.h"
+#include "tvector.h"
+#include "objfio.h"
+
+template <class T>
+TVector<T>::TVector(uint_4 n)
+// Constructeur d'un vecteur de "n" elements
+: TMatrix<T>(n,1)
+{
+}
+
+template <class T>
+TVector<T>::TVector(uint_4 n, T* values,Bridge* br)
+// Construit un vecteur de n elements. On fournit
+// le tableau des valeurs et eventuellement un Bridge.
+: TMatrix<T>(n,1,values,br)
+{
+}
+
+template <class T>
+TVector<T>::TVector(const TVector<T>& v)
+// Constructeur par copie (partage si "v" temporaire).
+: TMatrix<T>(v)
+{
+}
+
+template <class T>
+TVector<T>::TVector(const TVector<T>& v,bool share)
+// Constructeur par copie avec possibilite de forcer le partage ou non.
+: TMatrix<T>(v,share)
+{
+}
+
+template <class T>
+TVector<T>::TVector(const TMatrix<T>& a)
+// Constructeur a partir d'une matrice "a" de dimension (n,1)
+: TMatrix<T>(a)
+{
+if(a.NCols() != 1)
+  throw(SzMismatchError("TVector(const TMatrix<T>& a) size mismatch, ncol!=1"));
+}
+
+#include "generalfit.h"
+//////////////////////////////////////////////////////////
+//**** Residus des fits
+TVector<r_8> TVector<r_8>::FitResidus(GeneralFit& gfit,double xorg,double dx)
+// Retourne une classe contenant les residus du fit ``gfit''.
+// La coordonnee de l'element (i) est -> x = xorg + i*dx
+{
+if(NElts()<=0)
+  throw(SzMismatchError("TVector::FitResidus size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("TVector::FitResidus GeneraFit==NULL\n"));
+int npar =  gfit.GetNPar();
+if(npar==0)
+  throw(SzMismatchError("TVector::FitResidus GeneraFit 0 parametre\n"));
+double* par = new double[npar];
+{for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
+TVector<r_8> v(*this);
+for(uint_4 i=0;i<NElts();i++) {
+  double x = xorg+i*dx;
+  v(i) -= f->Value(&x,par);
+}
+delete [] par;
+return v;
+}
+
+TVector<r_8> TVector<r_8>::FitFunction(GeneralFit& gfit,double xorg,double dx)
+// Retourne une classe contenant la fonction du fit ``gfit''.
+// La coordonnee de l'element (i) est -> x = xorg + i*dx
+{
+if(NElts()<=0)
+  throw(SzMismatchError("TVector::FitFunction size mismatch\n"));
+GeneralFunction* f = gfit.GetFunction();
+if(f==NULL)
+  throw(NullPtrError("TVector::FitFunction GeneraFit==NULL\n"));
+int npar =  gfit.GetNPar();
+if(npar==0)
+  throw(SzMismatchError("TVector::FitFunction GeneraFit 0 parametre\n"));
+double* par = new double[npar];
+{for(int i=0;i<npar;i++) par[i] = gfit.GetParm(i);}
+TVector<r_8> v(*this);
+for(uint_4 i=0;i<NElts();i++) {
+  double x = xorg+i*dx;
+  v(i) = f->Value(&x,par);
+}
+delete [] par;
+return v;
+}
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+///////////////////////////////////////////////////////////
+
+template <class T>
+FIO_TVector<T>::FIO_TVector()
+{
+dobj=new TVector<T>;
+ownobj=true;
+}
+
+template <class T>
+FIO_TVector<T>::FIO_TVector(string const & filename) 
+{
+dobj=new TVector<T>;
+ownobj=true; 
+Read(filename);
+}
+
+template <class T>
+FIO_TVector<T>::FIO_TVector(const TVector<T> & obj) 
+{ 
+dobj = new TVector<T>(obj);
+ownobj=true; 
+}
+
+template <class T>
+FIO_TVector<T>::FIO_TVector(TVector<T> * obj) 
+{ 
+dobj = obj;
+ownobj=false; 
+}
+
+template <class T>
+FIO_TVector<T>::~FIO_TVector()
+{
+if (ownobj && dobj) delete dobj;
+}
+
+template <class T>
+AnyDataObj* FIO_TVector<T>::DataObj()
+{
+return(dobj);
+}
+
+template <class T>
+void FIO_TVector<T>::ReadSelf(PInPersist& is)
+{
+// On lit les 3 premiers uint_4
+//  0: Numero de version,  1 : NRows=NElts,  2 : NCol=1
+uint_4 itab[3];
+is.Get(itab,3);
+if (dobj == NULL) dobj = new TVector<T>(itab[1]);
+else dobj->ReSize(itab[1]);
+// On lit le NDataBlock
+FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+fio_nd.Read(is);
+}
+
+template <class T>
+void FIO_TVector<T>::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;
+//  On ecrit 3 uint_4 .... 
+//  0: Numero de version,  1 : NRows=NElts,  2 : NCol=1
+uint_4 itab[3];
+ itab[0] = 1;  // Numero de version a 1
+itab[1] = dobj->NElts();
+itab[2] = 1;
+os.Put(itab,3);
+// On ecrit le NDataBlock
+FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+fio_nd.Write(os);
+}
+
+///////////////////////////////////////////////////////////////
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template TVector<uint_1>
+#pragma define_template TVector<uint_2>
+#pragma define_template TVector<int_2>
+#pragma define_template TVector<int_4>
+#pragma define_template TVector<int_8>
+#pragma define_template TVector<uint_4>
+#pragma define_template TVector<uint_8>
+#pragma define_template TVector<r_4>
+#pragma define_template TVector<r_8>
+#pragma define_template TVector< complex<r_4> > 
+#pragma define_template TVector< complex<r_8> > 
+// Instances des delegues FileIO (PPersist)
+#pragma define_template FIO_TVector<uint_1>
+#pragma define_template FIO_TVector<uint_2>
+#pragma define_template FIO_TVector<int_2>
+#pragma define_template FIO_TVector<int_4>
+#pragma define_template FIO_TVector<int_8>
+#pragma define_template FIO_TVector<uint_4>
+#pragma define_template FIO_TVector<uint_8>
+#pragma define_template FIO_TVector<r_8>
+#pragma define_template FIO_TVector<r_4>
+#pragma define_template FIO_TVector< complex<r_4> >
+#pragma define_template FIO_TVector< complex<r_8> >
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class TVector<uint_1>;
+template class TVector<uint_2>;
+template class TVector<int_2>;
+template class TVector<int_4>;
+template class TVector<int_8>;
+template class TVector<uint_4>;
+template class TVector<uint_8>;
+template class TVector<r_4>;
+template class TVector<r_8>;
+template class TVector< complex<r_4> >;
+template class TVector< complex<r_8> >;
+// Instances des delegues FileIO (PPersist)
+template class FIO_TVector<uint_1>;
+template class FIO_TVector<uint_2>;
+template class FIO_TVector<int_2>;
+template class FIO_TVector<int_4>;
+template class FIO_TVector<int_8>;
+template class FIO_TVector<uint_4>;
+template class FIO_TVector<uint_8>;
+template class FIO_TVector<r_8>;
+template class FIO_TVector<r_4>;
+template class FIO_TVector< complex<r_4> >;
+template class FIO_TVector< complex<r_8> >;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/tvector.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/tvector.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/tvector.h	(revision 752)
@@ -0,0 +1,111 @@
+// This may look like C code, but it is really -*- C++ -*-
+//                         C.Magneville          05/99
+#ifndef TVector_SEEN
+#define TVector_SEEN
+
+#include "tmatrix.h"
+
+namespace SOPHYA {
+
+class GeneralFit;
+
+template <class T>
+class TVector : public TMatrix<T> {
+public:
+
+  // Creation / destruction 
+  TVector(uint_4 n=1);
+  TVector(uint_4 n, T* values,Bridge* br=NULL);
+  TVector(const TVector<T>& v);
+  TVector(const TVector<T>& v,bool share);
+  TVector(const TMatrix<T>& a);
+
+  // Gestion taille/Remplissage
+  inline void ReSize(uint_4 n) {TMatrix<T>::ReSize(n,1);} // Reallocation de place
+  inline void Realloc(uint_4 n,bool force=false) {TMatrix<T>::Realloc(n,1,force);}
+
+  // Informations pointeur/data
+  inline uint_4 NElts() const {return NRows();}
+  
+  // Acces aux elements
+  inline T& operator()(uint_4 n) {return (*this)[n];}
+  inline T const& operator()(uint_4 n) const {return (*this)[n];}
+  inline T& Element(uint_4 n) {return (*this)[n];}
+  inline T const& Element(uint_4 n) const {return (*this)[n];}
+
+  // Operateur d'affectation
+  inline TVector& operator = (const TVector& v)
+                  {TMatrix<T>::operator =(v); return *this;}
+  inline TVector& operator = (T x)
+                  {for(uint_4 i=0;i<NRows();i++) (*this)(i)=x; return *this;}
+
+  // Residus et fonction fittees.
+  TVector<T> FitResidus(GeneralFit& gfit,double xorg=0.,double dx=1.);
+  TVector<T> FitFunction(GeneralFit& gfit,double xorg=0.,double dx=1.);
+
+};
+
+// produit scalaire, matrice*vecteur
+template <class T>
+inline T operator* (const TVector<T>& v1, const TVector<T>& v2)
+  {if(v1.NRows() != v2.NRows())
+     throw(SzMismatchError("TVector::operator*(TVector& v1,TVector v2) size mismatch"));
+   T *p = const_cast<T *>(v1.Data()), *pEnd = p+v1.NElts(),
+     *q = const_cast<T *>(v2.Data()), r = 0;
+   while (p<pEnd) r += *p++ * *q++;
+   return r;}
+
+template <class T>
+inline TVector<T> operator* (const TMatrix<T>& a, const TVector<T>& b)
+   {return TVector<T>(a * ((TMatrix<T> const&)(b)));}
+
+// Resolution du systeme A*C = B
+inline r_8 LinSolveInPlace(TMatrix<r_8>& a, TVector<r_8>& b)
+{
+if(a.NCols() != b.NRows() || a.NCols() != a.NRows())
+  throw(SzMismatchError("LinSolveInPlace(TMatrix<r_8>,TVector<r_8>) size mismatch"));
+return TMatrix<r_8>::GausPiv(a,b);
+}
+
+// Resolution du systeme A*C = B, avec C retourne dans B
+inline r_8 LinSolve(const TMatrix<r_8>& a, const TVector<r_8>& b, TVector<r_8>& c)
+{ 
+if(a.NCols() != b.NRows() || a.NCols() != a.NRows())
+  throw(SzMismatchError("LinSolve(TMatrix<r_8>,TVector<r_8>) size mismatch"));
+c = b;
+TMatrix<r_8> a1(a);
+return TMatrix<r_8>::GausPiv(a1,c);
+}
+
+// Typedef pour simplifier et compatibilite Peida
+typedef TVector<r_8> Vector;
+
+/////////////////////////////////////////////////////////////////////////
+// Classe pour la gestion de persistance
+template <class T>
+class FIO_TVector : public  PPersist  {
+public:
+  FIO_TVector();
+  FIO_TVector(string const & filename); 
+  FIO_TVector(const TVector<T> & obj);
+  FIO_TVector(TVector<T> * obj);
+  virtual ~FIO_TVector();
+  virtual AnyDataObj* DataObj();
+  inline operator TVector<T>() { return(*dobj); }
+protected :
+  virtual void ReadSelf(PInPersist&);           
+  virtual void WriteSelf(POutPersist&) const;  
+  TVector<T> * dobj;
+  bool ownobj;
+};
+
+template <class T>
+inline POutPersist& operator << (POutPersist& os, TVector<T> & obj)
+{ FIO_TVector<T> fio(&obj);  fio.Write(os);  return(os); }
+template <class T>
+inline PInPersist& operator >> (PInPersist& is, TVector<T> & obj)
+{ FIO_TVector<T> fio(&obj);  fio.Read(is);  return(is); }
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/utils.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/utils.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/utils.cc	(revision 752)
@@ -0,0 +1,112 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: utils.cc,v 1.2 1999-04-22 16:18:51 ansari Exp $
+//
+
+#include "machdefs.h"
+#include "utils.h"
+#include "pexceptions.h"
+#include <string.h>
+
+// MemCpy marche meme en cas de recouvrement.
+void* MemCpy(void* dest, const void* source, size_t n)
+{
+  int i;   // THINK C ne veut pas du int i dans chaque for...
+  if (dest < source)
+    for (i=0; i<n; i++)
+      ((char*)dest)[i] = ((char*)source)[i];
+  else 
+    for (i=n-1; i>=0; i--)
+      ((char*)dest)[i] = ((char*)source)[i];
+  
+  return dest;
+}
+
+// Dans parmst.cc
+//int PrtLevel = 0;
+//int DebugLevel = 0;
+
+char const* PeidaWorkPath()
+{
+  char const* envWP = getenv("PEIDAWORKPATH");
+  if (envWP) return envWP;
+  #ifdef __mac__
+  return "WORK";
+  #endif
+  return ".";
+}
+
+#ifndef __mac__
+void buildPath(char* dst, const char* dir, const char* file)
+{
+  strcpy(dst, dir);
+  char *p = dst; while (*p) p++; p--;
+  if (*dir && *p != '/') strcat(dst, "/");
+  strcat(dst, file);
+}
+
+void buildPath(string& dst, const string& dir, const string& file)
+{
+  dst = dir;
+  if (dir != "" && dir[dir.length()-1] != '/') dst += "/";
+  dst += file;
+}
+
+#else
+void buildPath(char* dst, const char* dir, const char* file)
+{
+  if (*dir) {
+    strcpy(dst, ":");
+    strcat(dst, dir);
+    char *p = dst; while (*p) p++; p--;
+    strcat(dst, ":");
+    strcat(dst, file);
+  } else
+    strcpy(dst, file);
+}
+
+void buildPath(string& dst, const string& dir, const string& file)
+{
+  if (dir != "") {
+    dst = ":" + dir + ":" + file;
+  } else
+    dst = file;
+}
+
+#endif
+
+
+void changeSuffix(char* file, const char* suffix)
+{
+  char *p = file;
+  while (*p) p++;
+  while (*p != '.' && p > file) p--;
+  if (*p != '.') 
+    strcat(file, suffix);
+  else
+    strcpy(p,suffix);
+}
+
+void changeSuffix(string& file, const string& suffix)
+{
+  size_t pos = file.rfind('.');
+  //  if (pos != NPOS) file.remove(pos);
+  if (pos != NPOS) file = file.substr(0,pos);
+  file += suffix;
+}
+
+string itos(int i)
+{
+  char s[20];
+  sprintf(s, "%d", i);
+  return s;
+}
+
+string ftos(double f)
+{
+  char s[20];
+  sprintf(s, "%g", f);
+  return s;
+}
+
+
Index: /tags/V_Fev00/SophyaLib/NTools/utils.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/utils.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/utils.h	(revision 752)
@@ -0,0 +1,53 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: utils.h,v 1.3 1999-10-21 15:25:53 ansari Exp $
+//
+
+#ifndef UTILS_EA
+#define UTILS_EA
+
+#include "machdefs.h"
+#include <string.h>
+#include <string>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+// MemCpy marche meme en cas de recouvrement.
+// #define memcpy MemCpy
+
+void* MemCpy(void* dest, const void* source, size_t n);
+
+char const* PeidaWorkPath();
+void buildPath(char* dst, const char* dir, const char* file);
+void buildPath(string& dst, const string& dir, const string& file);
+void changeSuffix(char* file, const char* suffix);
+void changeSuffix(string& file, const string& suffix);
+string itos(int);
+string ftos(double);
+
+inline void GetIntEnv(char const* s, int& v)
+{
+  char* pdeb = getenv(s);
+  if (pdeb) v = atoi(pdeb);
+}
+
+/* if defined(__DECCXX) || defined(__xlC) */
+#if defined(__xlC) || defined(__DECCXX)
+#define STRUCTCOMP(s)                        \
+  bool operator==(s const& b) const          \
+{ return memcmp(this, &b, sizeof(s)) == 0; } \
+  bool operator<(s const& b) const           \
+{ return memcmp(this, &b, sizeof(s)) < 0; } 
+  
+#define STRUCTCOMPF(s,f)                        \
+  bool operator==(s const& b) const          \
+{ return f == b.f; }                          \
+  bool operator<(s const& b) const           \
+{ return f < b.f; }
+#else
+#define STRUCTCOMP(s) 
+#define STRUCTCOMPF(s,f)
+#endif
+
+#endif // UTILS_EA
Index: /tags/V_Fev00/SophyaLib/NTools/xntuple.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/xntuple.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/xntuple.cc	(revision 752)
@@ -0,0 +1,932 @@
+// -*- C++ -*- 
+// 
+// xntuple.cc 
+// N. Regnault   -      98-99 
+// Extended NTuples 
+// 
+#include <string.h>
+#include "ppersist.h"
+#include "perrors.h"
+#include "xntuple.h"
+
+#define LENNAME 31 
+#define MAXLEN 128
+#define BADVAL -1.e19
+
+//++
+// Class	XNTuple
+// Lib		Outils++ 
+// include	xntuple.h
+//
+//	Classe de ntuples
+//--
+//++
+// Links	Parents
+// PPersist
+// NTupleInterface
+//--
+//++
+// Links	Voir aussi
+// NTuple
+//--
+
+
+char* XNTuple::glob_swp = NULL ; 
+long int  XNTuple::NbNT = 0 ; 
+
+
+NTBlk::NTBlk(int ndvar, int nfvar, int nivar, int nsvar, int strsz, int sz) 
+    : sw(0), // pas swappe 
+      swoff(-1), 
+      ddata(NULL), fdata(NULL), 
+      idata(NULL), sdata(NULL)
+{
+    if(ndvar) ddata = new double[ndvar*sz] ; 
+    if(nfvar) fdata = new float[nfvar*sz] ; 
+    if(nivar) idata = new int_4[nivar*sz] ; 
+    if(nsvar) sdata = new char[nsvar*(strsz+1)*sz] ; 
+}
+
+NTBlk::~NTBlk()
+{
+    free() ; 
+}
+
+void NTBlk::free() 
+{
+    if(ddata) delete[] ddata ; ddata = NULL ; 
+    if(fdata) delete[] fdata ; fdata = NULL ; 
+    if(idata) delete[] idata ; idata = NULL ; 
+    if(sdata) delete[] sdata ; sdata = NULL ; 
+}
+
+// 
+// relit bloc ds fichier swap 
+// (seulement si bloc n'est plus en memoire) 
+// 
+void XNTuple::read_blk(NTBlk* blk) const 
+{
+    // deja en memoire ? 
+    if( !blk->sw ) return ;  
+    
+    blk->free() ; 
+    
+    // On va --> blk 
+    fseek(swf, blk->swoff, SEEK_SET) ; 
+    
+    if(mD) { 
+	blk->ddata = new double[mD*mBlkSz] ; 
+	fread(blk->ddata, sizeof(double), mD*mBlkSz, swf) ; 
+    }
+    if(mF) { 
+	blk->fdata = new float[mF*mBlkSz] ; 
+	fread(blk->fdata, sizeof(float), mF*mBlkSz, swf) ; 
+    }
+    if(mI) { 
+	blk->idata = new int_4[mI*mBlkSz] ; 
+	fread(blk->idata, sizeof(int), mI*mBlkSz, swf) ; 
+    }
+    if(mS) { 
+	blk->sdata = new char[mS*(mStrSz+1)*mBlkSz] ; 
+	fread(blk->sdata, sizeof(char), mS*mBlkSz*(mStrSz+1), swf) ; 
+    }
+}
+
+// 
+// swappe le bloc present en memoire 
+// depuis le + longtemps 
+// 
+void XNTuple::swap() const 
+{
+    // fichier de swap ouvert ? 
+    if(!swf) { 
+	swf_name = new char[swp.length()+64] ; 
+	strncpy(swf_name, swp.c_str(), swp.length()+1) ; 
+	strcat(swf_name, "NTupleXXXXXX") ; 
+	//	swf_name = strdup("NTupleXXXXXX") ; 
+	mktemp(swf_name) ; 
+	swf = fopen(swf_name, "w+") ; 
+	if(!swf) THROW(fileErr) ; 
+    }
+    
+    // bloc a swapper 
+    NTBlk* blk = sw.front() ; 
+    
+    // bloc dans fichiers de swap ? 
+    //    if( blk->swoff > 0 ) 
+    write_blk(blk) ; 
+    blk->free() ; 
+    
+    blk->sw = 1 ; // on marque le bloc swappe 
+    sw.pop_front() ; // on le vire de la liste de swap 
+    mNSwBlk++ ; 
+}
+
+
+// 
+// unswap() 
+// 
+void XNTuple::get_blk(int i) const 
+{
+    if(i<0 || i>=mNBlk) return ; 
+    read_blk(ptr[i]) ; 
+    ptr[i]->sw = 0 ; 
+    sw.push_back(ptr[i]) ; 
+    mNSwBlk-- ; 
+}
+
+
+// 
+// ecrit le bloc en bout de fichier 
+// (seulement si swoff < 0 ) 
+// 
+void XNTuple::write_blk(NTBlk* blk) const 
+{
+    // deja swappe ? 
+    if( blk->swoff >= 0 ) return ; 
+    fseek(swf, (off_t)0, SEEK_END) ; 
+    // position debut du bloc 
+    blk->swoff = ftell(swf) ; 
+    if(blk->ddata) fwrite(blk->ddata, sizeof(double), mD*mBlkSz, swf) ; 
+    if(blk->fdata) fwrite(blk->fdata, sizeof(float),  mF*mBlkSz, swf) ; 
+    if(blk->idata) fwrite(blk->idata, sizeof(int),    mI*mBlkSz, swf) ; 
+    if(blk->sdata) fwrite(blk->sdata, sizeof(char),   mS*mBlkSz*(mStrSz+1), swf) ; 
+}
+
+
+void  XNTuple::add_blk() 
+{
+    // l'ancien bloc en ecriture peut maintenant 
+    // etre swappe (s'il existe) 
+    if(mBlk>=0) sw.push_back(ptr[mBlk]) ; 
+    
+    // si pas de place, on swappe 
+    if( mNBlk+1 >= mMaxBlk ) swap() ; 
+    
+    // nouveau bloc 
+    NTBlk* tmp = new NTBlk(mD, mF, mI, mS, mStrSz, mBlkSz) ; 
+    ptr.push_back(tmp) ; 
+    
+    //    mNBlk++ ; 
+    //    mOff = 0 ; 
+    //    mBlk++ ; 
+}
+
+
+XNTuple::XNTuple()
+    : mNEnt(0), mNBlk(0), mNSwBlk(0), 
+      mBlkSz(0), mBlk(-1), mOff(0), 
+      mMaxBlk(0), mStrSz(0), 
+      mD(0), mF(0), mI(0), mS(0), 
+      mVarD(NULL), mMin(NULL), mMax(NULL), 
+      mNVars(0), mNames(NULL), 
+  swf(NULL), swf_name(NULL), mInfo(NULL)
+{
+    if(!glob_swp) SetSwapPath("/tmp/") ; 
+    swp = glob_swp ; 
+    NbNT++ ; 
+}
+
+//++
+// Titre	Constructeurs
+//--
+//++
+// XNTuple(int ndvar, int nfvar, int nivar, int nsvar, char** vnames, -
+//	   int blk=512, int maxblk=100, int strsz=30)
+//	Constructeur - Création d'un XNTuple de "ndvar" variables de type "double", -
+//                      "nfvar" de type "float", "nivar" de type "int" et "nsvar" de type -
+//                      "char*". 
+//|            * "blk"    = taille blocs de données (en nombre d'entrées) 
+//|            * "maxblk" = nombre max de blocs présents en mémoire (non swappés) 
+//|            * "strsz"  = taille des données de type char* 
+// XNTuple(XNTuple const& nt)
+//	Constructeur de copie.
+// XNTuple(string const& flnm)
+//	Constructeur - lecture à partir d'un fichier PPersist.
+//--
+
+XNTuple::XNTuple(int ndvar, int nfvar, int nivar, int nsvar, 
+		   char** vnames, 
+		   int blk, int maxblk, int strsz)
+    : mNEnt(0), mNBlk(0), mNSwBlk(0), 
+      mBlkSz(blk), mBlk(-1), mOff(0), 
+      mMaxBlk(maxblk), mStrSz(strsz), 
+      mD(ndvar), mF(nfvar), mI(nivar), mS(nsvar), 
+      mVarD(NULL), mMin(NULL), mMax(NULL), 
+      mNVars(ndvar+nfvar+nivar+nsvar), mNames(NULL), 
+      swf(NULL), swf_name(NULL), mInfo(NULL)
+{
+    if(!glob_swp) SetSwapPath("/tmp/") ; 
+    swp = glob_swp ; 
+    
+    mVarD = new r_8[mNVars] ; 
+    mMin  = new r_8[mD+mF+mI] ; 
+    int i;
+    for(i = 0 ; i < (mD+mF+mI) ; i++) mMin[i] =  9E19 ; 
+    mMax  = new r_8[mD+mF+mI] ; 
+    for(i = 0 ; i < (mD+mF+mI) ; i++) mMax[i] = -9E19 ; 
+    
+    if(mNVars) mNames = new char[mNVars*(LENNAME+1)] ; 
+    memset(mNames, 0, mNVars*(LENNAME+1));
+    for(i = 0 ; i < mNVars ; i++)
+      strncpy(mNames+i*(LENNAME+1), vnames[i], LENNAME);
+
+    NbNT++ ; 
+}
+
+
+
+XNTuple::XNTuple(string const& flnm) 
+    : mNEnt(0), mNBlk(0), mNSwBlk(0), 
+      mBlkSz(0), mBlk(-1), mOff(0), 
+      mMaxBlk(0), mStrSz(0), 
+      mD(0), mF(0), mI(0), mS(0), 
+      mVarD(NULL), mMin(NULL), mMax(NULL), 
+      mNVars(0), mNames(NULL), 
+      swf(NULL), swf_name(NULL), mInfo(NULL)
+{
+    if(!glob_swp) SetSwapPath("/tmp/") ; 
+    swp = glob_swp ; 
+    
+    PInPersist s(flnm);
+    ObjFileIO<XNTuple> fiont(this);
+    fiont.Read(s);
+    NbNT++ ; 
+}
+
+
+XNTuple::XNTuple(XNTuple const& nt) 
+    : mNEnt(0), mNBlk(0), mNSwBlk(0), 
+      mBlkSz(0), mBlk(-1), mOff(0), 
+      mMaxBlk(0), mStrSz(0), 
+      mD(0), mF(0), mI(0), mS(0), 
+      mVarD(NULL), mMin(NULL), mMax(NULL), 
+      mNVars(0), mNames(NULL), 
+      swf(NULL), swf_name(NULL), mInfo(NULL) 
+{
+    if(!glob_swp) SetSwapPath("/tmp/") ; 
+    swp = glob_swp ; 
+    Copy(nt) ; 
+    NbNT++ ; 
+}
+
+
+
+XNTuple::~XNTuple()
+{
+    clean() ; 
+    NbNT-- ; 
+    if(NbNT==0) delete[] glob_swp ; 
+}
+
+
+
+void XNTuple::clean()
+{
+    // On libere tous les blocs 
+    for(int i = 0 ; i < mNBlk ; i++) 
+	if(!ptr[i]->sw) delete ptr[i] ; 
+    ptr.erase(ptr.begin(), ptr.end()) ; 
+    sw.erase(sw.begin(), sw.end()) ; 
+    
+    // on ferme le fichier de swap 
+    if(swf) fclose(swf) ; swf = NULL ; 
+    remove(swf_name) ; 
+    delete swf_name ; swf_name = NULL ; 
+    
+    // tout le monde remis a 0 
+    mNEnt   = 0 ;     mNBlk   = 0 ; 
+    mNSwBlk = 0 ;     mBlkSz  = 0 ;  
+    mBlk    = -1 ;    mOff    = 0 ; 
+    mMaxBlk = 0 ;     mStrSz  = 0 ; 
+    mD      = 0 ;     mF      = 0 ; 
+    mI      = 0 ;     mS      = 0 ; 
+    mNVars  = 0 ; 
+    
+    
+    if(mVarD) { delete[] mVarD ; mVarD = NULL ; } 
+    if(mMin)  { delete[] mMin  ; mMin  = NULL ; } 
+    if(mMax)  { delete[] mMax  ; mMax  = NULL ; } 
+
+    if(mNames) {delete[] mNames ; mNames = NULL ; }
+    if (mInfo) delete mInfo;
+
+}
+
+
+//++
+// Titre	Méthodes
+//--
+//++
+//  void Fill(double* d_data, float* f_data, int* i_data, char** s_data) 
+//	Remplissage d'une ligne dans le NTuple
+//  void Show(ostream& os) const 
+//	Impression de la liste des variables avec min-max sur le flot "oß
+//  void Show() const 
+//	Identique à "Show(cout)"
+//  XNTuple&   operator = (XNTuple const& nt) 
+//	Opérateur égal (=) , copie "nt" dans le premier NTuple
+//--
+void XNTuple::Fill(double* d_data, float* f_data, int* i_data, char** s_data) 
+{
+    // place disponible dans bloc courant ? 
+    if( mOff==mBlkSz || mOff==0 ) {
+	add_blk() ; mOff = 0 ; mNBlk++ ; mBlk++ ; 
+    }
+    
+    if( mD && !ptr[mBlk]->ddata || 
+	mF && !ptr[mBlk]->fdata || 
+	mI && !ptr[mBlk]->idata || 
+	mS && !ptr[mBlk]->sdata )
+	THROW(parmErr) ; 
+    
+    double x ; 
+    // copie variables et update mMin, mMax 
+    if(mD) {
+	memcpy(ptr[mBlk]->ddata+mOff*mD, d_data, mD*sizeof(double)) ; 
+	for(int i = 0 ; i < mD ; i++) {
+	    x = d_data[i] ; 
+	    if(x<mMin[i]) mMin[i] = x ; 
+	    if(x>mMax[i]) mMax[i] = x ; 
+	}
+    }
+    
+    if(mF) {
+	memcpy(ptr[mBlk]->fdata+mOff*mF, f_data, mF*sizeof(float)) ; 
+	for(int i = 0 ; i < mF ; i++) {
+	    x = f_data[i] ; 
+	    if(x<mMin[i+mD]) mMin[i+mD] = x ; 
+	    if(x>mMax[i+mD]) mMax[i+mD] = x ; 
+	}
+    }
+
+    if(mI) {
+	memcpy(ptr[mBlk]->idata+mOff*mI, i_data, mI*sizeof(int)) ; 
+	for(int i = 0 ; i < mI ; i++) {
+	    x = i_data[i] ; 
+	    if(x<mMin[i+mD+mF]) mMin[i+mD+mF] = x ; 
+	    if(x>mMax[i+mD+mF]) mMax[i+mD+mF] = x ; 
+	}
+    }
+    for(int i = 0 ; i < mS ; i++) 
+	memcpy(ptr[mBlk]->sdata+(mOff*mS+i)*(mStrSz+1), 
+	       s_data[i], (strlen(s_data[i])+1)*sizeof(char)) ; 
+    mOff++ ; 
+    mNEnt++ ; 
+}
+
+// 
+// A quel index correspond mon nom ? 
+// 
+int XNTuple::IndexNom(char const* nom) const 
+{
+    int i ; 
+    for(i = 0 ; i < (mD+mF+mI+mS) ; i++)
+	if( !strncmp( mNames+i*(LENNAME+1), nom, LENNAME+1) ) 
+	    return i ; 
+    return -1 ; 
+}
+
+string XNTuple::NomIndex(int k) const 
+{
+    if( k<0 || k>=mNVars ) return "" ; 
+    return mNames + k*(LENNAME+1) ; 
+}
+
+
+// 
+// 
+// 
+double XNTuple::GetDVal(int i, int k) const 
+{
+    if( i<0 || i>=mNEnt || k<0 || k>=mD ) 
+	THROW(rangeCheckErr) ; 
+    
+    // Bloc ? 
+    int blk = (int)(i/mBlkSz) ; 
+    int off = i%mBlkSz ; 
+    
+    // bloc swappe ? 
+    if( ptr[blk]->sw ) { get_blk(blk) ; swap() ; } 
+    return ptr[blk]->ddata[off*mD+k] ; 
+}
+
+// 
+// 
+// 
+float XNTuple::GetFVal(int i, int k) const 
+{
+    if( i<0 || i>=mNEnt || k<mD || k>=(mD+mF) ) 
+	THROW(rangeCheckErr) ; 
+    k -= mD ; 
+    
+    // Bloc ? 
+    int blk = (int)(i/mBlkSz) ; 
+    int off = i%mBlkSz ; 
+    
+    // bloc swappe ? 
+    if( ptr[blk]->sw ) { get_blk(blk) ; swap() ; } 
+    return ptr[blk]->fdata[off*mF+k] ; 
+}
+
+// 
+// 
+// 
+int XNTuple::GetIVal(int i, int k) const 
+{
+    if( i<0 || i>=mNEnt || k<(mD+mF) || k>=(mD+mF+mI) )
+	THROW(rangeCheckErr) ; 
+    k -= (mD+mF) ; 
+
+    // Bloc ? 
+    int blk = (int)(i/mBlkSz) ; 
+    int off = i%mBlkSz ; 
+    
+    // bloc swappe ? 
+    if( ptr[blk]->sw ) { get_blk(blk) ; swap() ; } 
+
+    return ptr[blk]->idata[off*mI+k] ; 
+}
+
+// 
+// 
+// 
+string  XNTuple::GetSVal(int i, int k) const 
+{
+    if( i<0 || i>=mNEnt || k<(mD+mF+mI) || k>=(mD+mF+mI+mS) )
+	THROW(rangeCheckErr) ; 
+    k -= (mD+mF+mI) ; 
+    
+    // Bloc ? 
+    int blk = (int)(i/mBlkSz) ; 
+    int off = i%mBlkSz ; 
+    
+    // bloc swappe ? 
+    if( ptr[blk]->sw ) { get_blk(blk) ; swap() ; } 
+    
+    // copie de la chaine 
+    // string ret = strdup(ptr[blk]->sdata + (off*mS+k)*(mStrSz+1)) ; // $CHECK$ EA fuite de memoire
+       // attention, strdup fait un malloc et on ne fait jamais de free...
+       // a quoi sert ce strdup ?????????
+    string ret = ptr[blk]->sdata + (off*mS+k)*(mStrSz+1) ; 
+    //    return ptr[blk]->sdata[k] ; 
+    return ret ; 
+}
+
+
+// 
+// Copie bloc a bloc, avec meme parametres 
+//  
+void XNTuple::Copy(XNTuple const& nt) 
+{
+    clean() ; 
+    // Parametres 
+    mNEnt = nt.mNEnt ; 
+    mBlkSz = nt.mBlkSz ; 
+    mOff = nt.mOff ; 
+    mMaxBlk = nt.mMaxBlk ; 
+    mStrSz = nt.mStrSz ; 
+    mD = nt.mD ; 
+    mF = nt.mF ; 
+    mI = nt.mI ; 
+    mS = nt.mS ; 
+    mNVars = nt.mNVars ; 
+    
+    // noms 
+    if(mNVars) {
+	mNames = new char[mNVars*(LENNAME+1)] ; 
+        mVarD = new double[mNVars];
+	memcpy(mNames, nt.mNames, mNVars*(LENNAME+1)*sizeof(char)) ; 
+    }
+    // MinMax 
+    if(nt.mMin) { 
+	mMin = new double[(mD+mF+mI)] ; 
+	memcpy(mMin, nt.mMin, (mD+mF+mI)*sizeof(double)) ; 
+    }
+    if(nt.mMax) { 
+	mMax = new double[(mD+mF+mI)] ; 
+	memcpy(mMax, nt.mMax, (mD+mF+mI)*sizeof(double)) ; 
+    }
+    
+    //dup blocs 
+    mNBlk = 0 ; 
+    mBlk  = -1 ; 
+    for(int i = 0 ; i < nt.mNBlk ; i++) {
+	add_blk() ; mBlk++ ; mNBlk++ ; 
+	// si nt.ptr[i] swappe, on le relit 
+	if(nt.ptr[i]->sw) nt.read_blk(nt.ptr[i]) ; 
+	if(mD) 
+	    memcpy(ptr[i]->ddata, nt.ptr[i]->ddata, mD*mBlkSz*sizeof(double)) ; 
+	if(mF)
+	    memcpy(ptr[i]->fdata, nt.ptr[i]->fdata, mF*mBlkSz*sizeof(float)) ; 
+	if(mI)
+	    memcpy(ptr[i]->idata, nt.ptr[i]->idata, mF*mBlkSz*sizeof(int)) ; 
+	if(mS)
+	    memcpy(ptr[i]->sdata, nt.ptr[i]->sdata, mS*mBlkSz*sizeof(char)*(mStrSz+1)) ; 
+	if(nt.ptr[i]->sw) nt.ptr[i]->free() ; 
+    }
+
+    // DVList Info block 
+    if(nt.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(nt.mInfo);}
+
+}
+
+//++
+// DVList& Info()
+//	Renvoie une référence sur l'objet DVList Associé
+//--
+
+DVList&  XNTuple::Info()
+{
+  if (mInfo == NULL)  mInfo = new DVList;
+  return(*mInfo);
+}
+
+void XNTuple::Print(int num, int nmax) const 
+{
+    printf("XNTuple::Print() : \n") ; 
+    printf("  Entrees = %d, Blocs  = %d, Bloc Size = %d\n", 
+	   mNEnt, mNBlk, mBlkSz) ; 
+    int i,j;
+    printf("  D_Vars  = %d : ", mD) ; 
+    for(i = 0 ; i < mD ; i++) 
+	printf("%s ", NomIndex(i).c_str() ) ; 
+    printf("\n") ; 
+    
+    printf("  F_Vars  = %d : ", mF) ; 
+    for(i = 0 ; i < mF ; i++) 
+	printf("%s ", NomIndex(i+mD).c_str() ) ; 
+    printf("\n") ; 
+    
+    printf("  I_Vars  = %d : ", mI) ; 
+    for(i = 0 ; i < mI ; i++) 
+	printf("%s ", NomIndex(i+mD+mF).c_str() ) ; 
+    printf("\n") ; 
+    
+    printf("  S_Vars  = %d : ", mS) ; 
+    for(i = 0 ; i < mS ; i++) 
+	printf("%s ", NomIndex(i+mD+mF+mI).c_str() ) ; 
+    printf("\n") ; 
+    
+    for(i = num ; i < num+nmax ; i++) {
+	for(j = 0 ; j < mD ; j++) printf("%f ", GetDVal(i,j)) ; 
+	printf(" -- ") ; 
+	for(j = 0 ; j < mF ; j++) printf("%f ", GetFVal(i,j+mD)) ; 
+	printf(" -- ") ; 
+	for(j = 0 ; j < mI ; j++) printf("%d ", GetIVal(i,j+mD+mF)) ; 
+	printf(" -- ") ; 
+	for(j = 0 ; j < mS ; j++) printf("%s ", GetSVal(i,j+mD+mF+mI).c_str()) ; 
+	printf("\n") ; 
+    }
+}
+
+
+void   XNTuple::Show(ostream& os) const 
+{
+    os << "XNTuple: NVar= " << mNVars << " NEnt= " << mNEnt 
+       << " (BlkSz,NBlk= " << mBlkSz << ", " << mNBlk << ")" 
+       << " (mNSwBlk= " << mNSwBlk << ")" << endl ; 
+    os << "(Sw File= " ; if(swf_name) os << swf_name ; os << ")" << endl ; 
+    
+    char* buff = new char[80] ; 
+    sprintf(buff, "Variables   :  Type         Min         Max  \n") ; 
+    os << buff ; 
+    
+    double min, max ;
+    int i; 
+    for(i = 0 ; i < mD ; i++) {
+	GetMinMax(i, min, max) ; 
+	sprintf(buff, "  %-10s:   D    %12.6g   %12.6g \n", 
+		NomIndex(i).c_str(), min, max) ; 
+	os << buff ; 
+    }
+    for(i = 0 ; i < mF ; i++) {
+	GetMinMax(i+mD, min, max) ; 
+	sprintf(buff, "  %-10s:   F    %12.6g   %12.6g \n", 
+		NomIndex(i+mD).c_str(), min, max) ; 
+	os << buff ; 
+    }
+    for(i = 0 ; i < mI ; i++) {
+	GetMinMax(i+mD+mF, min, max) ; 
+	sprintf(buff, "  %-10s:   I    %12.6g   %12.6g \n", 
+		NomIndex(i+mD+mF).c_str(), min, max) ; 
+	os << buff ; 
+    }
+    for(i = 0 ; i < mS ; i++) {
+	sprintf(buff, "  %-10s:   S      -----        ----- \n", 
+		NomIndex(i+mD+mF+mI).c_str()) ; 
+	os << buff ; 
+    }
+    delete[] buff ; 
+}
+
+int    XNTuple::FillFromASCIIFile(string const& fn, double ddval,  float dfval,
+                                        int dival, const char * dsval)
+//	Remplit le ntuple a partir d'un fichier ASCII.
+//	Renvoie le nombre de lignes ajoutees.
+{
+// a faire
+return(0);
+}
+
+
+void  XNTuple::SetSwapPath(char* p) 
+{
+    if(!glob_swp) glob_swp = new char[MAXLEN+1] ; 
+    strncpy(glob_swp, p, MAXLEN) ; 
+}
+
+// 
+// 
+// Interface NTuple 
+// 
+// 
+uint_4 XNTuple::NbLines() const
+{
+    return(NEntry());
+}
+
+uint_4 XNTuple::NbColumns() const
+{
+    return(NVar());
+}
+
+r_8* XNTuple::GetLineD(int n) const 
+{
+    // memcpy() impossible
+    // il faut faire des GetVal 
+    int i;
+    for(i = 0 ; i < mD ; i++) 
+	mVarD[i] = GetDVal(n, i) ; 
+    for(i = 0 ; i < mF ; i++) 
+	mVarD[i+mD] = (double)GetFVal(n, i+mD) ; 
+    for(i = 0 ; i < mI ; i++) 
+	mVarD[i+mD+mF] = (double)GetIVal(n, i+mD+mF) ; 
+    for(i = 0 ; i < mS ; i++) 
+	mVarD[i+mD+mF+mI] = atof(GetSVal(n, i+mD+mF+mI).c_str()) ; 
+    return mVarD ; 
+}
+
+
+r_8  XNTuple::GetCell(int n, int k) const 
+{
+    if( k<0 || k>=(mD+mF+mI+mS) ) return BADVAL ; 
+    if(k<mD) return GetDVal(n,k) ; 
+    if(k<(mF+mD)) return GetFVal(n,k) ; 
+    if(k<(mF+mD+mI)) return GetIVal(n,k) ; 
+    if(k<(mD+mF+mI+mS)) return atof(GetSVal(n,k).c_str()) ; 
+    return BADVAL ; 
+}
+
+
+r_8  XNTuple::GetCell(int n, string const& nom) const 
+{
+    int k = IndexNom(nom.c_str()) ; 
+    if(k<0) return BADVAL ; 
+    if(k<mD) return GetDVal(n,k) ; 
+    if(k<(mF+mD)) return GetFVal(n,k) ; 
+    if(k<(mF+mD+mI)) return GetIVal(n,k) ; 
+    if(k<(mD+mF+mI+mS)) return atof(GetSVal(n,k).c_str()) ; 
+    return BADVAL ; 
+}
+
+string   XNTuple::GetCelltoString(int n, int k) const
+{
+    char buff[32];
+    if(k<0) return (""); 
+    else if(k<mD) 
+      { sprintf(buff, "%g", GetDVal(n,k)); return(buff) ; } 
+    else if(k<(mF+mD)) 
+      { sprintf(buff, "%g", (double)GetFVal(n,k)); return(buff) ; } 
+    else if(k<(mF+mD+mI)) 
+      { sprintf(buff, "%d", GetIVal(n,k)); return(buff) ; } 
+    else if(k<(mD+mF+mI+mS)) 
+      return(GetSVal(n,k).c_str()) ; 
+    return("");
+}
+
+void XNTuple::GetMinMax(int k, double& min, double& max)  const
+{
+    min = 9E19 ; max = -9E19 ; 
+    // variables string non traitees 
+    if( k<0 || k>=(mD+mF+mI) ) return ; 
+    
+    min = mMin[k] ; 
+    max = mMax[k] ; 
+    return ; 
+}
+
+
+void XNTuple::GetMinMax(string const & nom, double& min, double& max)   const
+{
+    GetMinMax(IndexNom(nom.c_str()), min, max) ; 
+}
+
+
+int XNTuple::ColumnIndex(string const& nom) const 
+{
+    return IndexNom(nom.c_str()) ; 
+}
+
+
+string XNTuple::ColumnName(int k) const 
+{
+    return NomIndex(k) ; 
+}
+
+
+string XNTuple::VarList_C(const char* nomx) const 
+{
+    string rets = "" ; 
+    rets += "/* double type variables */ \n";
+    // variables double 
+    int i;
+    for(i = 0 ; i < mD ; i++) {
+	if( i>0 && (i%5)==0 ) rets += ";" ; 
+	if( (i%5)==0 ) rets+="\ndouble " ; 
+	else rets += ", " ; 
+	rets += NomIndex(i) ; 
+    }
+    if(mD) rets += ";" ; 
+    
+    // variables float 
+    rets += "/* float type variables */ \n";
+    for(i = 0 ; i < mF ; i++) {
+	if( i>0 && (i%5)==0 ) rets += ";" ; 
+	if( (i%5)==0 ) rets+="\ndouble " ; 
+	else rets += ", " ; 
+	rets += NomIndex(i+mD) ; 
+    }
+    if(mF) rets += ";" ; 
+    
+    // variables int 
+    rets += "/* int type variables */ \n";
+    for(i = 0 ; i < mI ; i++) {
+	if( i>0 && (i%5)==0 ) rets += ";" ; 
+	if( (i%5)==0 ) rets+="\ndouble " ; 
+	else rets += ", " ; 
+	rets += NomIndex(i+mD+mF) ; 
+    }
+    if(mI) rets += ";" ; 
+    
+    // variables string
+    rets += "/* string type variables */ \n"; 
+    for(i = 0 ; i < mS ; i++) {
+	if( i>0 && (i%5)==0 ) rets += ";" ; 
+	if( (i%5)==0 ) rets+="\ndouble " ; 
+	else rets += ", " ; 
+	rets += NomIndex(i+mD+mF+mI) ; 
+    }
+    rets += "; \n" ; 
+
+    if(nomx) {
+	char buff[256] ; 
+	for(i = 0 ; i < mNVars ; i++) {
+	    sprintf(buff, "%s=%s[%d]; ", NomIndex(i).c_str(), nomx, i) ; 
+	    rets+=buff ; 
+	    if( (i%3 == 0) && (i>0) ) rets += "\n" ; 
+	}
+    }
+    return rets ; 
+}
+
+
+string XNTuple::LineHeaderToString() const 
+{
+    char buff[32];
+    string rets=" Num    ";
+    for(int i=0; i<mNVars; i++) {
+	sprintf(buff, "%8s ", NomIndex(i).c_str() );
+	rets += buff;
+    }
+    rets += '\n';
+    return(rets);
+
+}
+
+
+string XNTuple::LineToString(int n) const 
+{
+    char buff[32];
+    double* val;
+    val = GetLineD(n);
+    sprintf(buff,"%6d: ",n); 
+    string rets=buff;
+    int i;
+    for(i=0; i<(mD+mF+mI); i++) {
+	sprintf(buff, "%8.3g ", val[i]);
+	rets += buff;
+    }
+    
+    for(i = mD+mF+mI ; i < mNVars ; i++) {
+	sprintf(buff, "%8s ", GetSVal(n,i).c_str() ) ; 
+	rets += buff ; 
+    }
+    
+    rets += '\n';
+    return(rets);
+}
+
+
+void   ObjFileIO<XNTuple>::WriteSelf(POutPersist& ppout) const 
+{
+  if (dobj == NULL)   return;
+//  On ecrit 3 uint_4 .... 
+//  0: Numero de version,  1 : non nul -> has info,  2 : reserve
+  uint_4 itab[3];
+  itab[0] = 1;  // Numero de version a 1
+  itab[1] = itab[2] = 0;
+  if (dobj->mInfo)  itab[1] = 1;
+  ppout.Put(itab,3);
+  if (dobj->mInfo)  if (dobj->mInfo)  ppout << (*(dobj->mInfo));
+
+  // variables internes 
+  ppout.PutI4(dobj->mNEnt) ; 
+  ppout.PutI4(dobj->mNBlk) ; 
+  ppout.PutI4(dobj->mBlkSz) ; 
+  ppout.PutI4(dobj->mBlk) ; 
+  ppout.PutI4(dobj->mOff) ; 
+  ppout.PutI4(dobj->mMaxBlk) ; 
+  ppout.PutI4(dobj->mStrSz) ; 
+  ppout.PutI4(dobj->mD) ; 
+  ppout.PutI4(dobj->mF) ; 
+  ppout.PutI4(dobj->mI) ; 
+  ppout.PutI4(dobj->mS) ; 
+  ppout.PutI4(dobj->mNVars) ; 
+    
+  // Noms 
+  ppout.PutBytes(dobj->mNames, dobj->mNVars*(LENNAME+1)) ; 
+
+  // MinMax 
+  ppout.PutR8s(dobj->mMin, (dobj->mD+dobj->mF+dobj->mI)) ; 
+  ppout.PutR8s(dobj->mMax, (dobj->mD+dobj->mF+dobj->mI)) ; 
+    
+  // Ecriture blocs N'ecrire que si datas existent 
+  for(int i = 0 ; i < dobj->mNBlk ; i++) {
+    // si bloc swappe, on le relit en douce ... 
+    if( dobj->ptr[i]->sw )  dobj->read_blk(dobj->ptr[i]) ; 
+    ppout.PutR8s(dobj->ptr[i]->ddata, dobj->mD*dobj->mBlkSz) ; 
+    ppout.PutR4s(dobj->ptr[i]->fdata, dobj->mF*dobj->mBlkSz) ; 
+    ppout.PutI4s(dobj->ptr[i]->idata, dobj->mI*dobj->mBlkSz) ; 
+    ppout.PutBytes(dobj->ptr[i]->sdata, dobj->mS*dobj->mBlkSz*(dobj->mStrSz+1)) ; 
+    if(dobj->ptr[i]->sw) dobj->ptr[i]->free() ; 
+    }
+}
+
+
+void   ObjFileIO<XNTuple>::ReadSelf(PInPersist& ppin) 
+{
+  if (dobj == NULL) dobj = new XNTuple;
+  else    dobj->clean() ; 
+//  On lit 3 uint_4 .... 
+//  0: Numero de version,  1 : non nul -> has info,  2 : reserve
+  uint_4 itab[3];
+  ppin.Get(itab,3);
+  if (itab[1] != 0) { // Lecture eventuelle du DVList Info
+    if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+    ppin >> (*(dobj->mInfo));
+  }
+
+  ppin.GetI4(dobj->mNEnt) ; 
+  ppin.GetI4(dobj->mNBlk) ; 
+  ppin.GetI4(dobj->mBlkSz) ; 
+  ppin.GetI4(dobj->mBlk) ; 
+  ppin.GetI4(dobj->mOff) ; 
+  ppin.GetI4(dobj->mMaxBlk) ; 
+  ppin.GetI4(dobj->mStrSz) ; 
+  ppin.GetI4(dobj->mD) ; 
+  ppin.GetI4(dobj->mF) ; 
+  ppin.GetI4(dobj->mI) ; 
+  ppin.GetI4(dobj->mS) ; 
+  ppin.GetI4(dobj->mNVars) ; 
+    
+  // Noms 
+  dobj->mNames = new char[dobj->mNVars*(LENNAME+1)] ;
+  dobj->mVarD = new double[dobj->mNVars]; 
+  ppin.GetBytes(dobj->mNames, dobj->mNVars*(LENNAME+1)) ; 
+
+  // MinMax 
+  dobj->mMin = new r_8[dobj->mD+dobj->mF+dobj->mI] ; 
+  ppin.GetR8s(dobj->mMin, dobj->mD+dobj->mF+dobj->mI) ; 
+  dobj->mMax = new r_8[dobj->mD+dobj->mF+dobj->mI] ; 
+  ppin.GetR8s(dobj->mMax, dobj->mD+dobj->mF+dobj->mI) ; 
+    
+  // lecture Blocs 
+  int nblk = dobj->mNBlk ; 
+  dobj->mBlk = -1 ; dobj->mNBlk = 0 ; 
+  for(int i = 0 ; i < nblk ; i++) {
+    dobj->add_blk() ; dobj->mBlk++ ; dobj->mNBlk++ ; 
+    ppin.GetR8s(dobj->ptr[i]->ddata, dobj->mD*dobj->mBlkSz) ; 
+    ppin.GetR4s(dobj->ptr[i]->fdata, dobj->mF*dobj->mBlkSz) ; 
+    ppin.GetI4s(dobj->ptr[i]->idata, dobj->mI*dobj->mBlkSz) ; 
+    ppin.GetBytes(dobj->ptr[i]->sdata, dobj->mS*dobj->mBlkSz*(dobj->mStrSz+1)) ; 
+  } 
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<XNTuple>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<XNTuple>;
+#endif
Index: /tags/V_Fev00/SophyaLib/NTools/xntuple.h
===================================================================
--- /tags/V_Fev00/SophyaLib/NTools/xntuple.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/NTools/xntuple.h	(revision 752)
@@ -0,0 +1,165 @@
+// -*- C++ -*- 
+// 
+// XNTuple 
+// 
+// N. Regnault 03/98 
+//             07/99 (NTupleInterface)
+// 
+// 
+#ifndef XNTUPLE_H_SEEN
+#define XNTUPLE_H_SEEN
+
+#include "objfio.h"
+
+#include <string.h>
+#include <vector>
+#include <list>
+#include <map>
+
+#include "ntupintf.h"
+#include "ppersist.h"
+#include "dvlist.h"
+
+namespace SOPHYA {
+// 
+// Bloc de donnees 
+// 
+struct NTBlk
+{
+    NTBlk(int ndvar, int nfvar, int nivar, int nsvar, int strsz, int sz) ; 
+    ~NTBlk() ; 
+    
+    void free() ;     // ne libere que les zones de donnees 
+
+    int      sw ;     // swappe ? 
+    long int swoff ;  // offset dans fichier de swap 
+    float*   fdata ;  
+    double*  ddata ;  
+    int_4*   idata ;  
+    char*    sdata ;  
+} ; 
+
+
+class XNTuple : public AnyDataObj , public NTupleInterface {
+public:
+  //    enum {classId = ClassId_XNTuple };
+
+    XNTuple() ; 
+    XNTuple(int ndvar, int nfvar, int nivar, int nsvar, 
+	    char** vnames, 
+	    int blk=512, int maxblk=100, int strsz=30) ; 
+    XNTuple(XNTuple const& nt) ; 
+    XNTuple(string const & flnm); 
+    virtual           ~XNTuple();
+    
+    void              Fill(double* d_data, float* f_data, int* i_data, char** sdata);
+    
+    inline int_4      NEntry() const { return mNEnt ; } 
+    inline int_4      NDVar() const  { return mD ; } 
+    inline int_4      NFVar() const  { return mF ; } 
+    inline int_4      NIVar() const  { return mI ; } 
+    inline int_4      NSVar() const  { return mS ; } 
+    inline int_4      NVar() const   { return mNVars ; } 
+    int               IndexNom(char const* nom) const ; 
+    string            NomIndex(int k) const ; 
+    
+    double            GetDVal(int i, int k) const ; 
+    float             GetFVal(int i, int k) const ; 
+    int               GetIVal(int i, int k) const ; 
+    string            GetSVal(int i, int k) const ; 
+    //    MuTyV             GetVal(char const* nom) ; 
+    
+    void              Copy(XNTuple const& nt) ; 
+    inline XNTuple&   operator=(XNTuple const& nt) { Copy(nt) ; return *this ; } 
+    
+    void              Print(int num, int nmax=1) const ;
+    void              Show(ostream& os) const ; 
+    inline void       Show() const { Show(cout) ; } 
+
+    DVList&           Info() ; 
+
+// Remplissage depuis fichier ASCII 
+   int		      FillFromASCIIFile(string const& fn, double ddfval=0., float dfval=0.,
+                                        int dival=0, const char * dsval="");
+        
+    static  void      SetSwapPath(char* p) ; 
+    string&           SwapPath() { return swp ; } 
+    
+// Declaration de l interface NTuple
+    virtual uint_4    NbLines() const ;
+    virtual uint_4    NbColumns() const ;
+    virtual r_8 *     GetLineD(int n) const ;
+    virtual r_8	      GetCell(int n, int k) const ;
+    virtual r_8	      GetCell(int n, string const & nom) const ;
+    virtual string    GetCelltoString(int n, int k) const ;
+    virtual void      GetMinMax(int k, double& min, double& max)   const ; 
+    virtual void      GetMinMax(string const & nom, double& min, double& max)   const ; 
+    virtual int       ColumnIndex(string const & nom)  const ;
+    virtual string    ColumnName(int k) const;
+    virtual string    VarList_C(const char* nomx=NULL) const ;
+    virtual string    LineHeaderToString() const;
+    virtual string    LineToString(int n) const;  
+
+//  Pour la gestion de persistance
+    friend class ObjFileIO<XNTuple> ;
+   
+private:
+    void    clean();    // remet tout a zero 
+    void    swap() const ;    // swappe le + ancien blk en memoire 
+    void    read_blk(NTBlk*) const ;  // relit le bloc 
+    void    write_blk(NTBlk*) const ; // ecrit un bloc 
+    void    get_blk(int i) const ;  // == unswap() 
+    void    add_blk() ; // ajout d'un nouveau bloc 
+    
+    int_4   mNEnt ;   // nb total d'entrees 
+    int_4   mNBlk ;   // nb total de blocs 
+    mutable int_4   mNSwBlk ; // nb blocs swappes 
+    int_4   mBlkSz ;  // taille bloc 
+    int_4   mBlk ;    // bloc courant en ecriture 
+    int_4   mOff ;    // offset dans bloc en ecriture ; pointe sur le premiere case vide 
+    int_4   mMaxBlk ; // nb max de blocs autorises en memoire 
+    int_4   mStrSz ;  // taille des variables char** 
+    int_4   mNVars ;  // mD + mF + mI + mS 
+    int_4   mD, mF, mI, mS ; // nb variables de chaque type 
+    
+    r_8* mVarD, *mMin, *mMax ; 
+    
+    // 
+    // Noms + Prefix --> indiquer le type 
+    // 
+    //    char* mDNames, *mFNames, *mINames, *mSNames ; 
+    char* mNames ; 
+    //    typedef less<string> SCmp ; 
+    //    map<string,int,SCmp> mNames ; 
+    
+    // Donnees 
+    mutable vector<NTBlk*> ptr ; 
+    mutable list<NTBlk*> sw ; // liste --> swap() 
+
+    mutable FILE* swf ; // fichier --> swap 
+    mutable char* swf_name ; 
+    string  swp ; // swap_path 
+
+    DVList* mInfo;        // Infos (variables) attachees au NTuple
+
+    static  char*  glob_swp ; // swap_path global 
+    static  long int NbNT ; 
+}; 
+
+
+inline ostream& operator << (ostream& s, XNTuple const & nt)
+  {  nt.Show(s);  return(s);  }
+
+inline POutPersist& operator << (POutPersist& os, XNTuple & obj)
+{ ObjFileIO<XNTuple> fio(&obj);  fio.Write(os);  return(os); }
+inline PInPersist& operator >> (PInPersist& is, XNTuple & obj)
+{ ObjFileIO<XNTuple> fio(&obj);  fio.Read(is);  return(is); }
+
+// Classe pour la gestion de persistance
+// ObjFileIO<XNTuple>
+
+
+} // namespace SOPHYA
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/Samba/Makefile
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/Makefile	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/Makefile	(revision 752)
@@ -0,0 +1,118 @@
+include ../Mgr/Makefile.h
+ 
+all: $(LIB)libSamba.a
+clean:
+	rm -f $(OBJ)ana2fast.o $(OBJ)anagen.o $(OBJ)bruit.o $(OBJ)circle.o $(OBJ)gorfph.o $(OBJ)lambuilder.o $(OBJ)localmap.o $(OBJ)longlat.o $(OBJ)mlobe.o $(OBJ)sambainit.o $(OBJ)scan.o $(OBJ)spheregorski.o $(OBJ)spherepos.o $(OBJ)spherethetaphi.o $(OBJ)syn2fast.o $(OBJ)syngen.o $(OBJ)unitvector.o $(OBJ)utilgeom.o $(OBJ)vector3d.o
+	rm -f $(LIB)libSamba.a
+$(LIB)libSamba.a : $(OBJ)bruit.o $(OBJ)circle.o $(OBJ)gorfph.o $(OBJ)localmap.o $(OBJ)longlat.o $(OBJ)mlobe.o $(OBJ)sambainit.o $(OBJ)scan.o $(OBJ)spheregorski.o $(OBJ)spherepos.o $(OBJ)spherethetaphi.o $(OBJ)unitvector.o $(OBJ)utilgeom.o $(OBJ)vector3d.o
+	$(ARCXX) $(ARCXXFLAGS) $@ $?
+ifeq ($(CXX),cxx)
+	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS) -L$(LIB) -lSamba -lNTools -lSysTools -o $(OBJ)xx.x -Hf
+endif 
+ 
+$(OBJ)bruit.o: bruit.cc $(INC)fmath.h bruit.h \
+ $(INC)nbrandom.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h
+$(OBJ)circle.o: circle.cc circle.h vector3d.h longlat.h utilgeom.h \
+ unitvector.h geometry.h
+$(OBJ)gorfph.o: gorfph.cc
+$(OBJ)localmap.o: localmap.cc localmap.h pixelmap.h \
+ $(INC)ppersist.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h spherepos.h unitvector.h \
+ vector3d.h longlat.h utilgeom.h sphericalmap.h \
+ $(INC)nbmath.h \
+ $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ndatablock.h \
+ $(INC)piocmplx.h
+$(OBJ)longlat.o: longlat.cc longlat.h utilgeom.h
+$(OBJ)mlobe.o: mlobe.cc mlobe.h sphericalmap.h \
+ $(INC)nbmath.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h pixelmap.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h spherepos.h unitvector.h \
+ vector3d.h longlat.h utilgeom.h \
+ $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ndatablock.h \
+ $(INC)timing.h
+$(OBJ)sambainit.o: sambainit.cc sambainit.h \
+ $(INC)outilsinit.h \
+ $(INC)peidainit.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h spherethetaphi.h \
+ sphericalmap.h $(INC)nbmath.h pixelmap.h \
+ $(INC)dvlist.h spherepos.h unitvector.h \
+ vector3d.h longlat.h utilgeom.h \
+ $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ndatablock.h spheregorski.h
+$(OBJ)scan.o: scan.cc $(INC)machdefs.h \
+ $(INC)pclassids.h scan.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h \
+ $(INC)piocmplx.h \
+ $(INC)nbmath.h
+$(OBJ)spheregorski.o: spheregorski.cc \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)pexceptions.h spheregorski.h \
+ sphericalmap.h $(INC)nbmath.h pixelmap.h \
+ $(INC)ppersist.h \
+ $(INC)md5.h \
+ $(INC)dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h spherepos.h unitvector.h \
+ vector3d.h longlat.h utilgeom.h \
+ $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ndatablock.h \
+ $(INC)strutil.h
+$(OBJ)spherepos.o: spherepos.cc spherepos.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h unitvector.h vector3d.h \
+ longlat.h utilgeom.h
+$(OBJ)spherethetaphi.o: spherethetaphi.cc spherethetaphi.h sphericalmap.h \
+ $(INC)nbmath.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h pixelmap.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)dvlist.h \
+ $(INC)objfio.h \
+ $(INC)anydataobj.h spherepos.h unitvector.h \
+ vector3d.h longlat.h utilgeom.h \
+ $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ndatablock.h \
+ $(INC)piocmplx.h
+$(OBJ)unitvector.o: unitvector.cc unitvector.h vector3d.h longlat.h \
+ utilgeom.h
+$(OBJ)utilgeom.o: utilgeom.cc utilgeom.h
+$(OBJ)vector3d.o: vector3d.cc vector3d.h longlat.h utilgeom.h
Index: /tags/V_Fev00/SophyaLib/Samba/alm.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/alm.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/alm.cc	(revision 752)
@@ -0,0 +1,88 @@
+#include "alm.h"
+template <class T>
+Alm<T>::Alm(const TVector<T>& clin, const r_8 fwhm) 
+
+{
+
+
+  /*=======================================================================
+     creates the a_lm from the power spectrum, 
+     assuming they are gaussian  and complex 
+     with a variance given by C(l)
+
+     the input file should contain : l and C(l) with *consecutive* l's
+     (missing C(l) are put to 0.)
+
+     because the map is real we have : a_l-m = (-)^m conjug(a_lm)
+     so we actually compute them only for m >= 0
+
+=======================================================================*/
+  int_4 nlmax= clin.NElts()-1;
+
+  //alm.ReSize(nlmax);
+  ReSizeRow(nlmax+1);
+
+  r_8 sig_smooth = fwhm/sqrt(8.*log(2.))/(60.*180.)* M_PI;
+  int_4 n_l = nlmax+1;
+
+
+  //    --- smoothes the initial power spectrum ---
+  TVector<T> cl=clin;
+  for (int l=0;l<n_l;l++)
+    {
+      r_8 gauss=exp(-l*(l+1.)*sig_smooth*sig_smooth);
+      cl(l)*=(T)gauss;
+    }
+  
+
+  //     --- generates randomly the alm according to their power spectrum ---
+  r_8 hsqrt2 = 1.0 / Rac2;
+
+  for (int l=0;l<n_l;l++)
+    {
+      T rms=sqrt(cl(l));
+      //        ------ m = 0 ------
+      complex<T> zeta1(NorRand());
+      (*this)(l,0)   = zeta1 * rms;
+
+      //------ m > 0 ------
+      for (int m=1;m<=l;m++)
+	{
+	  complex<T> aux1(hsqrt2);
+	  complex<T> aux2(NorRand(),NorRand());
+	  zeta1=aux1*aux2;
+	  (*this)(l,m)=rms*zeta1;
+	}
+    }
+}
+
+
+template <class T>
+TVector<T> Alm<T>::powerSpectrum() const
+{
+  int_4 nlmax=Lmax();
+
+  TVector<T>  pow(nlmax+1);
+  pow.SetTemp(true);
+
+  for (int l=0; l<=nlmax;l++)
+    {
+      pow(l)=( (*this)(l,0) ).real()*( (*this)(l,0) ).real();
+      for (int m=1; m<=l; m++)
+	{
+	  pow(l)+=2.*( (*this)(l,m) ).real()*( (*this)(l,m) ).real()+
+	    2.*( (*this)(l,m) ).imag()*( (*this)(l,m) ).imag();
+	}
+      pow(l)/=(2.*l+1.);
+    }
+  return pow;
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template Alm<r_8>
+#pragma define_template Alm<r_4>
+#endif
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class Alm<r_8>;
+template class Alm<r_4>;
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/alm.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/alm.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/alm.h	(revision 752)
@@ -0,0 +1,127 @@
+#ifndef ALM_SEEN
+#define ALM_SEEN
+#include "nbrandom.h"
+#include "nbmath.h"
+#include "tvector.h"
+#include "pexceptions.h"
+/*! Class for inferior triangular matrix (base class for the class Alm) */
+template <class T>
+class TriangularMatrix 
+  {
+    
+  public :
+
+TriangularMatrix()   {};
+  /* instanciate a triangular matrix from the number of rows */
+TriangularMatrix(int rowSize)  : long_diag_((uint_4)rowSize) {elem_.ReSize((uint_4) (rowSize*(rowSize+1)/2) ); };
+TriangularMatrix(const TriangularMatrix<T>& a,  bool share=false)  : elem_(a.elem_, share),  long_diag_(a.long_diag_) {;}
+/*! resize the matrix with a new number of rows */
+inline void ReSizeRow(int rowSize) 
+  {
+    long_diag_=(uint_4)rowSize;
+    elem_.ReSize(long_diag_*(long_diag_+1)/2);
+  }
+ inline void SetTemp(bool temp=false) const {elem_.SetTemp(temp);}
+
+inline TriangularMatrix<T>& operator = (const TriangularMatrix<T>& a)
+{
+  elem_=a.elem_;
+  long_diag_ = a.long_diag_;
+  return *this;
+}
+inline T& operator()(int l, int m) 
+  {
+      return  elem_(adr_ij(l,m));
+  }
+inline T const& operator()(int l, int m) const 
+  {
+      return *(elem_.Begin()+ adr_ij(l,m));
+  }
+ inline  int_4  rowNumber() const {return (int_4)long_diag_;}
+  private: 
+ /*! compute the address of an element in the single array representing the matrix */
+inline uint_4 adr_ij(int i,int j) const 
+{
+  int adr= i*(i+1)/2+j;
+  if ( adr >= elem_.Size() || adr <0 )
+{
+ cout << " attention depassement dans triangularMatrix " << endl;
+ cout << " l= " << i << " m= " << j << " tableau reserve longueur " << elem_.Size() << endl; 
+}
+  return(i*(i+1)/2+j);
+}
+
+ uint_4 long_diag_;
+ NDataBlock<T> elem_;
+
+  };
+
+
+/*! class for the coefficients \f$a_{lm}\f$ of the development of a function defined on a sphere, in spherical harmonics */
+template <class T>
+class Alm : public TriangularMatrix<complex<T> >
+  {
+    public :
+ 
+Alm() : TriangularMatrix<complex<T> >()  {};
+    /* instanciate the class from the maximum value of the index \f$l\f$ in the sequence of the \f$a_{lm}\f$'s */
+Alm(int nlmax) : TriangularMatrix<complex<T> >(nlmax+1) {;}
+Alm(const Alm<T>& a,  bool share=false)  : TriangularMatrix<complex<T> >(a, share)  {;}
+
+Alm(const TVector<T>& clin, const r_8 fwhm) ;
+/*! resize with a new lmax */
+inline void ReSizeToLmax(int_4 nlmax) {ReSizeRow(nlmax+1);}
+inline int_4 Lmax() const {return rowNumber()-1;}
+TVector<T> powerSpectrum() const;
+
+
+};
+/*! class for a vector with an index running from \f$-m_{max}\f$ to \f$+m_{max}\f$ (then the size of the vector will be actually \f$2m_{max}+1)\f$ */
+template <class T>
+class Bm
+  {
+    public :
+Bm(): nmmax_(0) {;};
+    /* instanciate from the maximum absolute value of the index */
+Bm(int mmax) : nmmax_((uint_4)mmax)   { bm_.ReSize( (uint_4)(2*mmax+1) );}
+ Bm(const Bm<T>& b,  bool share=false) : nmmax_(b.nmmax_), bm_(b.bm_, share) {;}
+ /*! resize with a new value of mmax */
+inline void ReSizeToMmax(int_4 mmax) 
+  {
+    nmmax_=(uint_4)l;
+    bm_.ReSize(2* nmmax_+1);
+  }
+//inline int_4 Size() const {return 2*nmmax_+1;};
+inline T& operator()(int m) {return bm_( adr_i(m));};
+inline T const& operator()(int m) const {return *(bm_.Begin()+ adr_i(m));};
+/*! return the current value of the maximum absolute value of the index */
+inline int_4 Mmax() const 
+   {
+     return (int_4)nmmax_;
+   }
+inline Bm<T>& operator = (const Bm<T>& b)
+ {
+   if (this != &b)
+     {
+       nmmax_= b.nmmax_;
+       bm_=  b.bm_;
+     }
+   return *this;
+ }
+
+  private:
+/*! return the address in the array representing the vector */
+inline uint_4 adr_i(int i) const 
+{
+  return(uint_4)(i+nmmax_);
+}
+
+
+
+ uint_4 nmmax_;
+ NDataBlock<T> bm_;
+
+  };
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/bruit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/bruit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/bruit.cc	(revision 752)
@@ -0,0 +1,674 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifdef __MWERKS__
+#include "unixmac.h"
+#endif
+
+#include "fmath.h"
+
+#include "bruit.h"
+#include "nbrandom.h"
+// #include "rancern.h"
+// #include "hbook.h"
+
+//  Le code des classes   NoiseGenerator  RWalkNoise
+
+//++ 
+// Class	NoiseGenerator
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//--
+//++
+//
+// Links	Childs
+//
+//    RWalkNoise OOFNoise EXPNoise MemNoise  SumNoise
+//     
+//-- 
+//++
+// Titre	Constructors
+//--
+
+/* --Methode-- */
+//++
+NoiseGenerator::NoiseGenerator(float sigma)
+//
+//--
+{
+if (sigma < 0.)  sigma = 1.;
+mNCoups = 0;
+mSigma = sigma;
+//printf("-- NoiseGenerator::NoiseGenerator(%g) (Constructeur) ---\n", sigma);
+}
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+NoiseGenerator::~NoiseGenerator()
+//
+//--
+{
+    //printf("-- NoiseGenerator::~NoiseGenerator() (Destructeur) --- \n");
+}
+
+
+//++
+//
+// inline  unsigned long int  NoiseGenerator::NCoups() 
+//--
+//++
+// Titre	Public Methods
+//--
+
+/* --Methode-- */
+//++
+float NoiseGenerator::Noise()
+//
+//--
+{
+mNCoups++;
+return(NorRand()*mSigma);
+}
+//++
+// Class	RWalkNoise
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//--
+//++
+//
+// Links	Parents
+//
+//    NoiseGenerator
+//     
+//-- 
+//++
+// Titre	Constructor
+//--
+
+/* --Methode-- */
+//++
+RWalkNoise::RWalkNoise(float sigma)
+    : NoiseGenerator(sigma)
+//
+//--
+{
+mState = 0.;
+//printf("--  RWalkNoise::RWalkNoise(%g) (Constructeur) ---\n", sigma);
+}
+
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+RWalkNoise::~RWalkNoise()
+//
+//--
+{
+//printf("--  RWalkNoise::~RWalkNoise (Destructeur) ---\n");
+
+}
+
+//++
+// Titre	Public Methods
+//--
+/* --Methode-- */
+//++
+float RWalkNoise::Noise()
+//
+//--
+{
+mState += NoiseGenerator::Noise();
+return(mState);
+}
+
+//++
+// Class	OOFNoise
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//--
+//++
+//
+// Links	Parents
+//
+//    NoiseGenerator
+//     
+//-- 
+//++
+// Titre	Constructor
+//--
+
+/* --Methode-- */
+//++
+OOFNoise::OOFNoise(float sigma, int typacf, int mem, float tau)
+    : NoiseGenerator(sigma)
+//
+//--
+{
+if (typacf != ACF_Exp)   typacf = ACF_Exp;
+// Fonction d'autocorrelation donnant un bruit en 1/f
+//                  
+mTypACF = typacf;
+if (mem < 1)  mem = 1;
+mMemL = mem;
+if (tau < 1.e-6)  tau = 1.e-6;
+mTau = tau;
+mState = new double[mem];
+mDyn = new double[mem];
+int i;
+mDyn[0]=1.;
+mState[0]=0.;
+for(i=1; i<mem; i++) {
+  mState[i] = 0.;   mDyn[i] = 1./sqrt((double)i);
+}
+//printf("--  OOFNoise::OOFNoise(%g,%d,%d,%g) (Constructeur) ---\n", 
+//       sigma, typacf, mem, tau);
+}
+
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+OOFNoise::~OOFNoise()
+//
+//--
+{
+delete[] mState;
+delete[] mDyn;
+// printf("--  OOFNoise::~OOFNoise (Destructeur) ---\n");
+}
+
+
+//++
+// Titre	Public Methods
+//--
+/* --Methode-- */
+//++
+float OOFNoise::Noise()
+//
+//--
+{
+int i;
+double rn;
+
+for(i=(mMemL-1); i>0; i--)   mState[i] = mState[i-1];
+mState[0] = NoiseGenerator::Noise();
+rn = 0.;
+for(i=0; i< mMemL; i++)  rn += mDyn[i]*mState[i];
+return(rn);
+}
+
+/* --Methode-- */
+//++
+void OOFNoise::Print()
+//
+//--
+{
+int i,j;
+printf("OOFNoise::Print()  MemL=%d  Tau= %g \n", mMemL, mTau);
+printf("OOFNoise::Print() Vecteur de Dynamique / Etat : \n");
+for(i=0; i<mMemL-1; i+=2) 
+  printf("%d:   D=%g  S=%g   | %d:  D=%g  S=%g \n", i, 
+         mDyn[i], mState[i], i+1, mDyn[i], mState[i]);   
+return;
+}
+//++
+// Class	EXPNoise
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//--
+//++
+//
+// Links	Parents
+//
+//    NoiseGenerator
+//     
+//-- 
+//++
+// Titre	Constructor
+//--
+
+/* --Methode-- */
+//++
+EXPNoise::EXPNoise(float sigma, int typacf, int mem, float tau)
+    : NoiseGenerator(sigma)
+//
+//--
+{
+if (typacf != ACF_Exp)   typacf = ACF_Exp;
+// Fonction d'autocorrelation exponentiel disponible uniquement
+//                  Reza , Juillet 97
+mTypACF = typacf;
+if (mem < 1)  mem = 1;
+mMemL = mem;
+if (tau < 1.e-6)  tau = 1.e-6;
+mTau = tau;
+mState = new double[mem];
+mDyn = new double[mem];
+int i;
+for(i=0; i<mem; i++) {
+  mState[i] = 0.;   mDyn[i] = exp(-(double)i/tau);
+}
+//printf("--  EXPNoise::EXPNoise(%g,%d,%d,%g) (Constructeur) ---\n", 
+//       sigma, typacf, mem, tau);
+}
+
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+EXPNoise::~EXPNoise()
+//
+//--
+{
+delete[] mState;
+delete[] mDyn;
+//printf("--  EXPNoise::~EXPNoise (Destructeur) ---\n");
+}
+
+
+//++
+// Titre	Public Methods
+//--
+/* --Methode-- */
+//++
+float EXPNoise::Noise()
+//
+//--
+{
+int i;
+double rn;
+
+for(i=(mMemL-1); i>0; i--)   mState[i] = mState[i-1];
+mState[0] = NoiseGenerator::Noise();
+rn = 0.;
+for(i=0; i< mMemL; i++)  rn += mDyn[i]*mState[i];
+return(rn);
+}
+
+/* --Methode-- */
+//++
+void EXPNoise::Print()
+//
+//--
+{
+int i,j;
+printf("EXPNoise::Print()  MemL=%d  Tau= %g \n", mMemL, mTau);
+printf("EXPNoise::Print() Vecteur de Dynamique / Etat : \n");
+for(i=0; i<mMemL-1; i+=2) 
+  printf("%d:   D=%g  S=%g   | %d:  D=%g  S=%g \n", i, 
+         mDyn[i], mState[i], i+1, mDyn[i], mState[i]);   
+
+return;
+}
+
+//++
+// Class	MemNoise
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//--
+//++
+//
+// Links	Parents
+//
+//    NoiseGenerator
+//     
+//-- 
+//++
+// Titre	Constructor
+//--
+
+
+// ----------------      $CHECK$   Reza 1/12/99   ------------
+// ----- MAJ MemNoise et SumNoise / version F. Couchot (~couchot/CoSa/Samba/bruit.cc  )
+// -----------------------------------------------------------
+
+/* --Methode-- */
+//++
+MemNoise::MemNoise(float sigma, int mem, float tau, int ava)
+    : NoiseGenerator(sqrtf(fabsf(tau))*sigma)
+//
+//--
+{
+/* on tire les instants des impulsions successives selon une
+loi de distance exponentielle de duree tau
+*/
+const int place = 1000;
+mTypACF = ACF_Exp;
+if (mem < 1)  mem = 1;
+mMemL = place;
+mCoupHaut=mem;
+if (tau < 1.)  tau = 1.;
+mTau = tau;
+mStPos = new float[place];
+mStNeg = new float[place];
+mTePos = new float[place];
+mTeNeg = new float[place];
+// printf("apres reservation\n");
+int i;
+for(i=0; i<place; i++)
+{
+mStNeg[i] = 0.; mStPos[i] = 0.;
+}
+// printf("apres initialisation tableaux \n");
+
+mNappel=0;
+mNtirage=1;
+mNappLast=0;
+mMemPos=1;
+mMemNeg=1;
+mduree=0.;
+mTePos[0]=0.;
+mTeNeg[0]=0.;
+mTdernier=0.;
+
+Avance(ava);
+// printf("fin du createur MemNoise \n");
+//printf("--  EXPNoise::EXPNoise(%g,%d,%d,%g) (Constructeur) ---\n", 
+//       sigma, typacf, mem, tau);
+}
+
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+MemNoise::~MemNoise()
+//
+//--
+{
+delete[] mStPos;
+delete[] mStNeg;
+delete[] mTePos;
+delete[] mTeNeg;
+//printf("--  EXPNoise::~EXPNoise (Destructeur) ---\n");
+}
+
+//++
+// Titre	Public Methods
+//--
+/* --Methode-- */
+//++
+float MemNoise::Noise()
+//
+//--
+{
+return(Avance(0));
+}
+
+/* --Methode-- */
+//++
+float MemNoise::Avance(long Asauter)
+//
+//--
+{
+int i,j;
+float boum;
+float rn = 0;
+float Somme,SbaryT,Poids,BaryT,Approx,Erreur;
+int nReduit;
+const float epsilon=.05;
+// printf("entree dans methode Noise de MemNoise \n");
+long mNsaut;
+for (mNsaut = Asauter ; mNsaut >= 0 ; mNsaut--)
+    {  // debut mNsaut
+	// printf("mNsaut = %ld\n",mNsaut);
+mNappel++;
+mTdernier += 1.;
+for(i=0; i<mMemPos; i++) mTePos[i] += 1.;
+for(i=0; i<mMemNeg; i++) mTeNeg[i] += 1.;
+
+if (mduree < mTdernier)
+    {
+	/* la duree depuis le dernier tirage est maintenant ecoulee
+	   on commence par remettre a jour le temps ecoule entre la derniere
+	   impulsion (celle qu'on va tirer maintenant) et l'instant present  */
+	   
+	   mTdernier = mTdernier - mduree;
+        
+	/* puis on tire une nouvelle impulsion de bruit */
+
+	   boum =  NoiseGenerator::Noise();
+
+        /* on decale la memoire d'une case vers le passe 
+	   puis on met a jour la case [0] */
+
+if(boum>0)
+    {
+	for(i=mMemPos; i>0; i--)
+	    {
+		mStPos[i] = mStPos[i-1];
+		mTePos[i] = mTePos[i-1];
+	    }
+	mTePos[0] = mTdernier;
+	mStPos[0] = boum;
+	if (mMemPos<mMemL) mMemPos++;
+/* a chaque tirage, on regroupe les impulsions precedentes */
+for(i=mMemPos-2 ; i>0 ; i--)
+    {
+	if(mStPos[i]==0.)continue;
+	//	printf("i,temps,bruit %d,%g,%g \n",i,mTePos[i],mStPos[i]);
+	Somme = mStPos[i]/sqrtf(mTePos[i]);
+	    SbaryT = mStPos[i] * mTePos[i];
+	    Poids = mStPos[i];
+	    for(j=i-1 ; j>=0 ; j--)
+		{
+		    //		printf("  j,temps,bruit %d,%g,%g \n",j,mTePos[j],mStPos[j]);
+		Somme += mStPos[j]/sqrtf(mTePos[j]);
+		    Poids += mStPos[j];
+		    SbaryT += mStPos[j] * mTePos[j];
+		    BaryT = SbaryT / Poids;
+		    Approx = Poids / sqrtf(BaryT);
+		    Erreur = (Approx - Somme) / Somme;
+		    //		    		    printf("i,j = %d %d Approx = %g \n",i,j,fabsf(Erreur));
+		    //		    printf("Temps,Bruit = %g %g \n",BaryT,Poids);
+		    if(fabsf(Erreur)<epsilon)
+			{
+			    mStPos[i]=Poids;
+			    mTePos[i]=BaryT;
+			    mStPos[j]=0.;
+			}
+		    else break;
+		}
+    }
+nReduit=0;
+for(i=0; i<mMemPos-1 ; i++)
+    {
+	if(mStPos[i]!=0)
+	    {
+		mStPos[nReduit]=mStPos[i];
+		mTePos[nReduit]=mTePos[i];
+		nReduit++;
+	    }
+    }
+mMemPos=nReduit+1;
+
+    }
+else
+    {
+	for(i=mMemNeg; i>0; i--)
+	    {
+		mStNeg[i] = mStNeg[i-1];
+		mTeNeg[i] = mTeNeg[i-1];
+	    }
+	mTeNeg[0] = mTdernier;
+	mStNeg[0] = boum;
+	if (mMemNeg<mMemL) mMemNeg++;
+    
+
+/* idem pour negatifs */
+for(i=mMemNeg-2 ; i>0 ; i--)
+    {
+	if(mStNeg[i]==0.)continue;
+	//	printf("i,temps,bruit %d,%g,%g \n",i,mTeNeg[i],mStNeg[i]);
+	Somme = mStNeg[i]/sqrtf(mTeNeg[i]);
+	    SbaryT = mStNeg[i] * mTeNeg[i];
+	    Poids = mStNeg[i];
+	    for(j=i-1 ; j>=0 ; j--)
+		{
+		    //		printf("  j,temps,bruit %d,%g,%g \n",j,mTeNeg[j],mStNeg[j]);
+		Somme += mStNeg[j]/sqrtf(mTeNeg[j]);
+		    Poids += mStNeg[j];
+		    SbaryT += mStNeg[j] * mTeNeg[j];
+		    BaryT = SbaryT / Poids;
+		    Approx = Poids / sqrtf(BaryT);
+		    Erreur = (Approx - Somme) / Somme;
+		    //		    printf("i,j = %d %d Approx = %g \n",i,j,Erreur);
+		    //		    printf("Temps,Bruit = %g %g \n",BaryT,Poids);
+		    if(fabsf(Erreur)<epsilon)
+			{
+			    mStNeg[i]=Poids;
+			    mTeNeg[i]=BaryT;
+			    mStNeg[j]=0.;
+			}
+		    else break;
+		}
+    }
+nReduit=0;
+for(i=0; i<mMemNeg-1 ; i++)
+    {
+	if(mStNeg[i]!=0)
+	    {
+		mStNeg[nReduit]=mStNeg[i];
+		mTeNeg[nReduit]=mTeNeg[i];
+		nReduit++;
+	    }
+    }
+mMemNeg=nReduit+1;
+    }
+/* on tire la duree a attendre avant la prochaine impulsion de bruit */
+// $CHECK$ avec Francois - rndm() remplace par Reza 10/01/99 
+//  passage en drand le 1/12/99
+mduree = -mTau*log(drand01());  
+
+// if(mNtirage<mMemL) mNtirage++;
+mNtirage++;
+/*
+int idn=1;
+float pds=1.;
+float nul=0.;
+hfill_(&idn,&mduree,&nul,&pds);
+*/
+// printf("Ntirage %d,mMemPos,Neg %d,%d, Suppress = %d \n",mNtirage,mMemPos,mMemNeg, Suppress);
+    }
+/* On calcule le bruit total */
+
+//printf("mMemPos,Neg,%d %d\n",mMemPos,mMemNeg);
+//for(i=0;i<mMemPos;i++) printf("mTePos %g \n",mTePos);
+//for(i=0;i<mMemNeg;i++) printf("mTeNeg %g \n",mTeNeg);
+if(mNsaut == 0)
+    {
+	// printf("coucou\n");
+rn = 0.;
+int indlim=0;
+for(i=0; i < mMemPos-1; i++) 
+{
+if(mTePos[i] > .1)break; 
+rn += mStPos[i];
+indlim++;
+}
+// float ajout=0.;
+for(i=indlim; i < mMemPos-1; i++)  rn += mStPos[i]/sqrtf(mTePos[i]);
+indlim=0;
+for(i=0; i < mMemNeg-1; i++) 
+{
+if(mTeNeg[i] > .1) break;
+rn += mStNeg[i];
+indlim++;
+}
+for(i=indlim; i < mMemNeg-1; i++) rn += mStNeg[i]/sqrtf(mTeNeg[i]);
+}
+}
+return(rn);
+}
+/* --Methode-- */
+//++
+int MemNoise::Print()
+//
+//--
+{
+int i,j,rc=0;
+printf("MemNoise::Print()  MemL=%d  Tau= %g \n", mMemL, mTau);
+printf("mNtirage= %d , mMemPos= %d , mMemNeg= %d \n",mNtirage,mMemPos,mMemNeg);
+// printf("MemNoise::Print() Vecteur de Dynamique / Etat : \n");
+/* for(i=0; i<mMemL-1; i+=2) 
+  printf("%d:   D=%g  S=%g   | %d:  D=%g  S=%g \n", i, 
+         mDyn[i], mState[i], i+1, mDyn[i], mState[i]);   
+	 */
+return(rc);
+}
+
+//++
+// Class	SumNoise
+//
+// include      bruit.h math.h fmath.h nbrandom.h
+//
+//    Generateur de bruit blanc + 1/f avec fknee
+
+//--
+//++
+//
+// Links	Parents
+//
+//    NoiseGenerator
+//     
+//-- 
+//++
+// Titre	Constructor
+//--
+// Generateur de bruit blanc + 1/f avec fknee
+
+
+/* --Methode-- */
+//++
+SumNoise::SumNoise(float fknee, float sig, int mem, float tau)
+    : NoiseGenerator(sig)
+//
+//--
+{
+// Reza 27/01/98 :
+// Je calcule les sigma du MemNoise d'apres la formule de Francois 
+// mn = new MemNoise(sig*fknee);  
+// mn = new MemNoise(1.4142*sig*sqrtf(fknee),1,10.,1000000); // modif appel FC 13 mai 98.  
+mn = new MemNoise(1.4142*sig*sqrt((double)fknee),mem,tau,12000); // FC 13 mai 98. -> Reza 1/12/99 
+}
+
+
+//++
+// Titre	Destructor
+//--
+/* --Methode-- */
+//++
+SumNoise::~SumNoise()
+//
+//--
+{
+delete mn;
+}
+
+//++
+// Titre	Public Methods
+//--
+/* --Methode-- */
+//++
+float SumNoise::Noise()
+//
+//--
+{
+return(NoiseGenerator::Noise() + mn->Noise());
+}
Index: /tags/V_Fev00/SophyaLib/Samba/bruit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/bruit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/bruit.h	(revision 752)
@@ -0,0 +1,108 @@
+#ifndef BRUIT_H_SEEN
+#define BRUIT_H_SEEN
+
+class NoiseGenerator {
+public :
+			NoiseGenerator(float sigma=1.); 
+  virtual		~NoiseGenerator();
+  virtual float		Noise();
+  inline  unsigned long int           NCoups() { return(mNCoups); }
+
+protected :
+unsigned long  int mNCoups;
+  float mSigma;
+};
+
+class  RWalkNoise : public NoiseGenerator {
+public :
+			RWalkNoise(float sigma=1.);
+  virtual		~RWalkNoise();
+  virtual float		Noise();
+
+protected:
+  float mState;
+};
+
+class OOFNoise : public NoiseGenerator {
+public :
+  enum {
+     ACF_Def = 0,
+     ACF_Exp = 1
+  };
+			OOFNoise(float sigma=1., int typacf=ACF_Exp, 
+                                 int mem=128, float tau=1.);
+  virtual		~OOFNoise();
+  virtual float         Noise();
+  void                  Print();
+
+protected:
+  int mTypACF;
+  int mMemL;
+  float mTau; 
+  double* mState;
+  double* mDyn;
+};
+
+class EXPNoise : public NoiseGenerator {
+public :
+  enum {
+     ACF_Def = 0,
+     ACF_Exp = 1
+  };
+			EXPNoise(float sigma=1., int typacf=ACF_Exp, 
+                                 int mem=128, float tau=1.);
+  virtual		~EXPNoise();
+  virtual float         Noise();
+  void                  Print();
+
+protected:
+  int mTypACF;
+long  int mMemL;
+  float mTau; 
+  double* mState;
+  double* mDyn;
+};
+
+class MemNoise : public NoiseGenerator {
+public :
+  enum {
+     ACF_Def = 0,
+     ACF_Exp = 1
+  };
+			MemNoise(float sigma=1., int mem=128, float tau=1., int ava=4096);
+  virtual		~MemNoise();
+  virtual float         Noise();
+  virtual float         Avance(long Asauter);
+  int                   Print();
+ 
+protected:
+  int mTypACF;
+  int mMemL; int mCoupHaut;
+unsigned long   mNappel;
+unsigned long   mNappLast;
+  float mTeappel;
+  float mTau;
+  float mduree;
+  float mTdernier;
+  int mNtirage;
+  int mMemPos;
+  int mMemNeg;
+  float* mStPos;
+  float* mTePos;
+  float* mStNeg;
+  float* mTeNeg;
+};
+
+class  SumNoise : public NoiseGenerator {
+public :
+			SumNoise(float fknee, float sig=1., int mem=32, float tau=10.);
+  virtual		~SumNoise();
+  virtual float		Noise();
+
+protected:
+  MemNoise* mn;
+};
+
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/Samba/circle.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/circle.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/circle.cc	(revision 752)
@@ -0,0 +1,292 @@
+#include <math.h>
+#include "circle.h"
+//++ 
+// Class	Circle
+//
+// include      circle.h math.h
+//--
+//++
+//
+// Links	Parents
+//
+//    Geometry
+//    
+//-- 
+//++
+// Titre	Constructors
+//--
+//++
+Circle::Circle() 
+//
+//--
+{
+  UnitVector temp;
+  SetCircle(temp,M_PI/2.);
+}
+//++
+Circle::Circle(double theta, double phi, double aperture) 
+//
+//--
+{
+  UnitVector temp(theta,phi);
+  SetCircle(temp,aperture);
+}
+//++
+Circle::Circle(double x, double y, double z, double aperture) 
+//
+//--
+{
+  UnitVector temp(x,y,z);
+  SetCircle(temp,aperture);
+}
+//++
+Circle::Circle(const Vector3d& v, double aperture) 
+//
+//--
+{
+  UnitVector temp=v;
+  SetCircle(temp,aperture);
+}
+//++
+Circle::Circle(const Circle& c) 
+//
+//    copy constructor
+//--
+{
+  UnitVector temp=c.Omega();
+  SetCircle(temp,c._angouv);
+}
+//++
+// Titre	Public Methods
+//--
+//++
+void Circle::SetCircle(const UnitVector& temp, double aperture) 
+//
+//--
+{
+  _spinunitaxis=temp;
+  _angouv=aperture;
+  _spinaxis=_spinunitaxis*fabs(cos(_angouv));
+  _theta=_spinunitaxis.Theta();
+  _phi=_spinunitaxis.Phi();
+  _x=_spinunitaxis.X();
+  _y=_spinunitaxis.Y();
+  _z=_spinunitaxis.Z();
+}
+//++
+void Circle::SetSpinAxis(double theta, double phi)
+//
+//--
+{ 
+  UnitVector temp(theta,phi);
+  SetCircle(temp,_angouv);
+}
+//++
+void Circle::SetSpinAxis(const Vector3d& u) 
+//
+//--
+{
+  UnitVector temp=u;
+  SetCircle(temp,_angouv);
+}
+//++
+void Circle::SetSpinAxis(double x, double y, double z) 
+//
+//--
+{
+  UnitVector temp(x,y,z);
+  SetCircle(temp,_angouv);
+}
+//++
+void Circle::SetApertureAngle(double aperture) 
+//
+//--
+{ 
+  SetCircle(_spinunitaxis,aperture);
+}
+//++
+void Circle::SetApertureAngle(const Circle& c) 
+//
+//--
+{
+  SetCircle(_spinunitaxis,c._angouv);
+}
+//++
+bool Circle::Intersection(const Circle& c, double* psi) const 
+//
+//    psi contains  4 values of the intersection  angles. 
+//    -1 if  circles do not intersect
+//    psi[0]=psi(i,j,0)
+//    psi[1]=psi(i,j,1)
+//    psi[2]=psi(j,i,0)
+//    psi[3]=psi(j,i,1)
+//--
+{
+  double alphak=_angouv;
+  double alphal=c._angouv;
+  Vector3d ok=_spinaxis;
+  Vector3d ol=c._spinaxis;
+  double gamma=ok.SepAngle(ol);
+  if( fabs(alphak-alphal) < gamma && gamma <= (alphak+alphal) && this != &c ) 
+    { 
+      // then the 2 circles intersect
+      double sg=sin(gamma),cg=cos(gamma);
+      double sak=sin(alphak),cak=cos(alphak);
+      double sal=sin(alphal),cal=cos(alphal);
+      double st=sin(_theta),ct=cos(_theta);
+      double stc=sin(c._theta),ctc=cos(c._theta);
+      double dphi=_phi-c._phi;
+      double sdphi=sin(dphi),cdphi=cos(dphi);
+      double sinusk=stc*sdphi/sg,cosinusk=(ctc*st-stc*ct*cdphi)/sg;
+      double sinusl=-st*sdphi/sg,cosinusl=(ct*stc-st*ctc*cdphi)/sg;
+      double gammaik=scangle(sinusk,cosinusk);
+      double gammail=scangle(sinusl,cosinusl);
+      double omegak=acos((cal-cak*cg)/sg/sak);
+      double omegal=acos((cak-cal*cg)/sg/sal);
+      psi[0]=fmod(gammaik-omegak+pi2,pi2);
+      psi[1]=fmod(gammaik+omegak+pi2,pi2);
+      psi[2]=fmod(gammail-omegal+pi2,pi2);
+      psi[3]=fmod(gammail+omegal+pi2,pi2);
+      if( psi[0] > psi[1] ) 
+	{
+	  // psi[0]=psi(i,j,0)
+	  // psi[1]=psi(i,j,1)
+	  // psi[2]=psi(j,i,0)
+	  // psi[3]=psi(j,i,1)
+	  swap(psi[0],psi[1]); 
+	  swap(psi[2],psi[3]); 
+	}                      
+      return true;
+    }
+  else 
+    {
+      psi[0] = -1.;
+      psi[1] = -1.;
+      psi[2] = -1.;
+      psi[3] = -1.;
+      return false;
+    }
+}
+//++
+UnitVector Circle::ConvToSphere(double psi) const 
+//
+//    Return UnitVector corresponding to a given position donnee on the circle
+//--
+{
+  psi=mod(psi,pi2);
+  double xout, yout, zout;
+  double cosa=cos(_angouv);
+  double sina=sin(_angouv);
+  double cost=cos(_theta);
+  double sint=sin(_theta);
+  double cosphi=cos(_phi);
+  double sinphi=sin(_phi);
+  double cosp=cos(psi);
+  double sinp=sin(psi);
+  xout = cosa*sint*cosphi+sina*(sinphi*sinp-cost*cosphi*cosp);
+  yout = cosa*sint*sinphi-sina*(cosphi*sinp+cost*sinphi*cosp);
+  zout = cosa*cost+sina*sint*cosp;
+  return UnitVector(xout,yout,zout);
+}
+//++
+UnitVector Circle::TanOnCircle(double psi) const 
+//
+//    Return UnitVector corresponding to the tangent to the circle 
+//    at given position on the circle.
+//--
+{
+  psi=mod(psi,pi2);
+  double xout, yout, zout;
+  double cost=cos(_theta);
+  double sint=sin(_theta);
+  double cosphi=cos(_phi);
+  double sinphi=sin(_phi);
+  double cosp=cos(psi);
+  double sinp=sin(psi);
+  xout = cosp*sinphi+sinp*sint*cosphi;
+  yout = -cosp*cosphi+sinp*sint*sinphi;
+  zout = -sinp*cost;
+  return UnitVector(xout,yout,zout);
+}
+//++
+UnitVector Circle::EPhi(double psi) const 
+//
+//    Return the  vector  tangent to the sphere in the plane (xy) 
+//    at a given position on the circle.
+//--
+{
+  psi=mod(psi,pi2);
+  return ConvToSphere(psi).EPhi();
+}
+//++
+UnitVector Circle::ETheta(double psi) const 
+//
+//    Return the other tangent  vector( orthogonal to EPhi)-- 
+//    see previous method
+//--
+{
+  psi=mod(psi,pi2);
+  return ConvToSphere(psi).ETheta();
+}
+//++
+double Circle::SepAngleTanEPhi02PI(double psi) const
+//
+//    Return separation angle in [0,2Pi] at a given position on the 
+//    circle and EPhi
+//--
+{
+  psi=mod(psi,pi2);
+  UnitVector pol=this->TanOnCircle(psi);
+  UnitVector ephi=this->EPhi(psi);
+  double angle=pol.SepAngle(ephi);
+  if( pol.Z() <= 0 ) angle=pi2-angle;
+  return angle;
+}
+//++
+void Circle::Print(ostream& os) const 
+//
+//--
+{
+  os << "1 - Circle - Axe de Spin Unitaire : " << _spinunitaxis << endl;
+  os << "1 - Circle - Axe de Spin : " << _spinaxis << endl;
+  os << "2 - Circle - Angle d'ouverture : " << _angouv << endl;
+  os << "3 - Circle - Theta,Phi : " << _theta << "," << _phi << endl;
+  os << "4 - Circle - x,y,z : " << _x << "," << _y << "," << _z << endl;
+}
+//++
+//
+// inline double Theta() const
+// inline double Phi() const 
+// inline double ApertureAngle() const 
+// inline Vector3d Omega() const 
+//--
+//++
+// Titre	Operators
+//--
+
+Circle& Circle::operator=(const Circle& c) 
+{
+  if( this != &c ) 
+    {
+      UnitVector temp(c.Omega());
+      SetCircle(temp,c.ApertureAngle());
+    } 
+  return *this;
+}
+//++
+bool Circle::operator==(const Circle& c) const 
+//
+//--
+{
+  bool flag;
+  if( this == &c ) flag=true;
+  else flag=false;
+  return flag;
+}
+//++
+bool Circle::operator!=(const Circle& c) const 
+//
+//--
+{
+  return (bool)(1-(this->operator==(c)));
+}
Index: /tags/V_Fev00/SophyaLib/Samba/circle.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/circle.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/circle.h	(revision 752)
@@ -0,0 +1,94 @@
+#ifndef CIRCLE_H_SEEN
+#define CIRCLE_H_SEEN
+
+#include <math.h>
+#include <iostream.h>
+#include "vector3d.h"
+#include "unitvector.h"
+#include "utilgeom.h"
+#include "geometry.h"
+
+class Circle : public Geometry
+{
+  
+ public:
+
+  Circle();
+  Circle(double theta, double phi, double aperture);
+  Circle(double x, double y, double z, double aperture);
+  Circle(const Vector3d& v, double aperture=M_PI/2.);
+  Circle(const Circle& c);
+  virtual ~Circle() {}
+
+  void SetCircle(const UnitVector&, double);
+  void SetSpinAxis(double theta, double phi);
+  void SetSpinAxis(const Vector3d&);
+  void SetSpinAxis(double x, double y, double z);
+  void SetApertureAngle(double aperture);
+  void SetApertureAngle(const Circle&);
+  
+  // psi contient les 4 valeurs des angles d intersection. -1 si les cercles ne se coupent pas
+  // voir la numerotation dans le .cc
+  /*   psi contains  4 values of the intersection  angles. 
+    -1 if  circles do not intersect
+    psi[0]=psi(i,j,0)
+    psi[1]=psi(i,j,1)
+    psi[2]=psi(j,i,0)
+    psi[3]=psi(j,i,1)
+  */
+  bool Intersection(const Circle&, double* psi) const;
+
+  // donne le UnitVector correspondant a une position donnee sur le cercle
+  /*!    Return UnitVector corresponding to a given position donnee on the circle
+   */
+  UnitVector ConvToSphere(double psi) const;
+
+  // donne le UnitVector correspondant la tangente au cercle en une position donnee sur le cercle
+  /*!    Return UnitVector corresponding to the tangent to the circle */
+//    at given position on the circle.
+  UnitVector TanOnCircle(double psi) const;
+
+  // donne le vecteur tangent dans le plan (xy) a la sphere en une position donnee sur le cercle
+  /*!    Return the  vector  tangent to the sphere in the plane (xy) 
+    at a given position on the circle.
+  */
+  UnitVector EPhi(double psi) const;
+
+  // donne l autre vecteur tangent (orthogonal a EPhi)
+  /*!    Return the other tangent  vector( orthogonal to EPhi)-- 
+    see previous method
+  */
+  UnitVector ETheta(double psi) const;
+
+   // donne l angle de separation dans [0,2Pi] en une position donnee sur le cercle et EPhi
+  /*!   Return separation angle in [0,2Pi] at a given position on the 
+    circle and EPhi
+  */
+  double SepAngleTanEPhi02PI(double psi) const;
+
+  double Theta() const {return _spinaxis.Theta();}
+  double Phi() const {return _spinaxis.Phi();}
+  double ApertureAngle() const {return _angouv;}
+  Vector3d Omega() const {return _spinaxis;}
+  virtual void Print(ostream&) const;
+  Circle& operator=(const Circle&);
+  bool operator==(const Circle&) const;
+  bool operator!=(const Circle&) const;
+
+ private:
+
+  Vector3d _spinaxis;
+  UnitVector _spinunitaxis;
+  double _angouv;
+  double _theta,_phi;
+  double _x,_y,_z;
+
+};
+
+inline ostream& operator<<(ostream& s, const Circle& c) 
+{  
+  c.Print(s);  
+  return s;  
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/exclude
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/exclude	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/exclude	(revision 752)
@@ -0,0 +1,2 @@
+anagen.cc
+syngen.cc
Index: /tags/V_Fev00/SophyaLib/Samba/geometry.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/geometry.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/geometry.h	(revision 752)
@@ -0,0 +1,16 @@
+#ifndef GEOMETRY_SEEN
+#define GEOMETRY_SEEN
+
+
+#include "unitvector.h"
+
+class Geometry
+{
+public: 
+Geometry() {;}
+virtual ~Geometry() {;}
+virtual UnitVector  ConvToSphere(double psi) const = 0;
+};
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.cc	(revision 752)
@@ -0,0 +1,230 @@
+#include "lambdaBuilder.h"
+#include "nbconst.h"
+
+
+Legendre::Legendre(r_8 x, int_4 lmax) 
+{
+  if (abs(x) >1 ) 
+    {
+      throw RangeCheckError("variable for Legendre polynomials must have modules inferior to 1" );
+    }
+  x_ = x;
+  array_init(lmax);
+}
+void Legendre::array_init(int_4 lmax)
+{
+  lmax_ = lmax;
+  Pl_.ReSize(lmax_+1);
+  Pl_(0)=1.;
+  Pl_(1)=x_;
+  for (int k=2; k<Pl_.NElts(); k++)
+    {
+      Pl_(k) = ( (2.*k-1)*x_*Pl_(k-1)-(k-1)*Pl_(k-2) )/k;
+    }
+}
+
+TriangularMatrix<r_8>* LambdaLMBuilder::a_recurrence_ = NULL;
+TriangularMatrix<r_8>* LambdaLMBuilder::lam_fact_     = NULL;
+TVector<r_8>* LambdaLMBuilder::normal_l_     = NULL;
+
+LambdaLMBuilder::LambdaLMBuilder(r_8 theta,int_4 lmax, int_4 mmax)
+    {
+      cth_=cos(theta);
+      sth_=sin(theta);
+      array_init(lmax, mmax);
+    }
+void LambdaLMBuilder::array_init(int lmax, int mmax)
+   {
+     if (a_recurrence_ == NULL)
+       {
+	 a_recurrence_ = new TriangularMatrix<r_8>;
+	 updateArrayRecurrence(lmax);
+       }
+     else
+       if ( lmax > (*a_recurrence_).rowNumber()-1     )
+	 {
+	   cout << " WARNING : The classes LambdaXXBuilder will be more efficient if instanciated with parameter lmax = maximum value of l index which will be needed in the whole application (arrays not recomputed) " << endl;
+	   cout << "lmax= " << lmax << " previous instanciation with lmax= " <<  (*a_recurrence_).rowNumber() << endl;
+	 updateArrayRecurrence(lmax);
+	 }
+     lmax_=lmax;
+     mmax_=mmax;
+     r_8 bignorm2 = 1.e268; // = 1e-20*1.d288
+
+     lambda_.ReSizeRow(lmax_+1);
+
+     r_8 lam_mm = 1. / sqrt(4.*Pi) *bignorm2;
+	  
+     for (int m=0; m<=mmax_;m++)
+       {
+
+
+	 lambda_(m,m)= lam_mm / bignorm2; 
+
+	 r_8 lam_0=0.;
+	 r_8 lam_1=1. /bignorm2 ;
+	 //	 r_8 a_rec = LWK->a_recurr(m,m);
+	 r_8 a_rec = (*a_recurrence_)(m,m);
+	 r_8 b_rec = 0.;
+	 for (int l=m+1; l<=lmax_; l++)
+	 {
+	   r_8 lam_2 = (cth_*lam_1-b_rec*lam_0)*a_rec;
+	   lambda_(l,m) = lam_2*lam_mm;
+	   b_rec=1./a_rec;
+	   //	   a_rec= LWK->a_recurr(l,m);
+	   a_rec= (*a_recurrence_)(l,m);
+	   lam_0 = lam_1;
+	   lam_1 = lam_2;
+	 }
+
+	 lam_mm = -lam_mm*sth_* sqrt( (2.*m+3.)/ (2.*m+2.) );
+
+       }
+   }
+
+
+void  LambdaLMBuilder::updateArrayRecurrence(int_4 lmax)
+   {
+     (*a_recurrence_).ReSizeRow(lmax+1);
+     for (int m=0; m<=lmax;m++)
+     {
+       (*a_recurrence_)(m,m) = sqrt( 2.*m +3.);
+       for (int l=m+1; l<=lmax; l++)
+	 {
+	   r_8 fl2 = (l+1.)*(l+1.);
+	   (*a_recurrence_)(l,m)=sqrt( (4.*fl2-1.)/(fl2-m*m) );
+	 }
+     }
+   }
+
+
+void  LambdaLMBuilder::updateArrayLamNorm()
+     {
+       (*lam_fact_).ReSizeRow(lmax_+1);
+       for(int m = 0;m<= lmax_; m++)
+	 {
+	   for (int l=m; l<=lmax_; l++)
+	     {
+	       (*lam_fact_)(l,m) =2.*(r_8)sqrt( (2.*l+1)*(l+m)*(l-m)/(2.*l-1)  );
+	     }
+	 }
+       (*normal_l_).ReSize(lmax_+1);
+       (*normal_l_)(0)=0.;
+       (*normal_l_)(1)=0.;
+       for (int l=2; l< (*normal_l_).NElts(); l++)
+	 {
+	   (*normal_l_)(l) =(r_8)sqrt( 2./( (l+2)*(l+1)*l*(l-1) ) );	
+	 }
+     }
+
+
+
+
+LambdaWXBuilder::LambdaWXBuilder(r_8 theta, int_4 lmax, int_4 mmax) : LambdaLMBuilder(theta, lmax, mmax)
+  {
+    array_init();
+  }
+
+
+void LambdaWXBuilder::array_init()
+   {
+     if (lam_fact_ == NULL || normal_l_ == NULL)
+       {
+	 lam_fact_ = new  TriangularMatrix<r_8>;
+	 normal_l_ = new TVector<r_8>;
+	 updateArrayLamNorm();
+       }
+     else
+       if ( lmax_ > (*lam_fact_).rowNumber()-1  || lmax_ >  (*normal_l_).NElts()-1 )
+	 {
+	   updateArrayLamNorm();
+	 }
+
+     r_8 one_on_s2  = 1. / (sth_*sth_) ;    // 1/sin^2
+     r_8 c_on_s2    = cth_*one_on_s2;
+     lamWlm_.ReSizeRow(lmax_+1);
+     lamXlm_.ReSizeRow(lmax_+1);
+
+     // calcul des lambda
+     for(int m = 0;m<= mmax_; m++)
+       {
+	 for (int l=m; l<=lmax_; l++)
+	   {
+	     lamWlm_(l,m) =  0.;
+	     lamXlm_(l,m) =  0.;	  	
+	   }
+       }
+     for(int l = 2;l<= lmax_; l++)
+       {
+	 r_8 normal_l =  (*normal_l_)(l);	
+	 for (int m=0; m<=l; m++)
+	{
+	  r_8 lam_lm1m = LambdaLMBuilder::lamlm(l-1,m);
+	  r_8 lam_lm = LambdaLMBuilder::lamlm(l,m);
+	  r_8 lam_fact_l_m = (*lam_fact_)(l,m);
+	  r_8  a_w =  2. * (l - m*m) * one_on_s2 + l*(l-1.);
+	  r_8  b_w =  c_on_s2 * lam_fact_l_m;
+	  r_8  a_x =  2. * cth_ * (l-1.);
+	  lamWlm_(l,m) =   normal_l * ( a_w * lam_lm - b_w * lam_lm1m );
+	  lamXlm_(l,m) = - normal_l * m* one_on_s2* ( a_x * lam_lm - lam_fact_l_m * lam_lm1m );
+	}
+       }
+
+   }
+
+
+LambdaPMBuilder::LambdaPMBuilder(r_8 theta, int_4 lmax, int_4 mmax) : LambdaLMBuilder(theta, lmax, mmax)
+  {
+    array_init();
+  }
+
+
+void LambdaPMBuilder::array_init()
+   {
+     if (lam_fact_ == NULL || normal_l_ == NULL)
+       {
+	 lam_fact_ = new  TriangularMatrix<r_8>;
+	 normal_l_ = new TVector<r_8>;
+	 updateArrayLamNorm();
+       }
+     else
+       if ( lmax_ > (*lam_fact_).rowNumber()-1  || lmax_ >  (*normal_l_).NElts()-1 )
+	 {
+	   updateArrayLamNorm();
+	 }
+
+     r_8 one_on_s2 = 1. / (sth_*sth_) ;
+     r_8 c_on_s2 = cth_*one_on_s2;
+     lamPlm_.ReSizeRow(lmax_+1);
+     lamMlm_.ReSizeRow(lmax_+1);
+
+     // calcul des lambda
+     for(int m = 0;m<= mmax_; m++)
+       {
+	 for (int l=m; l<=lmax_; l++)
+	   {
+	     lamPlm_(l,m) =  0.;
+	     lamMlm_(l,m) =  0.;	  	
+	   }
+       }
+
+     for(int l = 2;l<= lmax_; l++)
+       {
+	 r_8 normal_l =  (*normal_l_)(l);	
+	 for (int m=0; m<=l; m++)
+	   {
+	     r_8 lam_lm1m = LambdaLMBuilder::lamlm(l-1,m);
+	     r_8 lam_lm = LambdaLMBuilder::lamlm(l,m);
+	     r_8 lam_fact_l_m = (*lam_fact_)(l,m);
+	     r_8  a_w =  2. * (l - m*m) * one_on_s2 + l*(l-1.);
+	     r_8 f_w =  lam_fact_l_m/(sth_*sth_);
+	     r_8  c_w =  2*m*(l-1.) * c_on_s2;
+
+	     lamPlm_(l,m)  = normal_l * ( -(a_w+c_w) * lam_lm + f_w*( cth_ + m) * lam_lm1m )/Rac2;
+	     lamMlm_(l,m) = normal_l * ( -(a_w-c_w) * lam_lm + f_w*( cth_ - m) * lam_lm1m )/Rac2;
+	   }
+       }
+
+   }
+
+
Index: /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/lambdaBuilder.h	(revision 752)
@@ -0,0 +1,196 @@
+#ifndef LAMBDABUILDER_SEEN
+#define LAMBDABUILDER_SEEN
+
+#include <math.h>
+#include "ndatablock.h"
+#include "tvector.h" 
+#include "alm.h"
+
+/*! 
+generate Legendre polynomials : use in two steps : 
+
+a) instanciate Legendre(\f$x\f$, \f$lmax\f$) ; \f$x\f$ is the value for wich Legendre polynomials will be required (usually equal to \f$\cos \theta\f$) and \f$lmax\f$ is the MAXIMUM value of the order of polynomials wich will be required in the following code (all polynomials, from \f$l=0 to lmax\f$, are computed once for all by an iterative formula).
+
+b) get the value of Legendre polynomial for a particular value of \f$l\f$ by calling the method getPl.
+*/
+class Legendre {
+
+ public :
+Legendre();
+Legendre(r_8 x, int_4 lmax);
+ inline r_8 getPl(int_4 l) 
+{
+  if (l>lmax_) 
+    {
+      throw (" illegal call of Legendre::getPl with index greater than lmax, which Legendre Class was instanciated with : instanciate Legendre with a greater lmax... ");
+    }
+return Pl_(l);
+}
+
+ private : 
+   /*! compute all \f$P_l(x,l_{max})\f$ for \f$l=1,l_{max}\f$ */
+  void array_init(int_4 lmax);
+
+  r_8 x_;
+  int_4 lmax_;
+  TVector<r_8> Pl_;
+};
+
+
+
+/*! 
+This class generate the coefficients :
+\f[
+            \lambda_l^m=\sqrt{\frac{2l+1}{4\pi}\frac{(l-m)!}{(l+m)!}}
+	    P_l^m(\cos{\theta})
+\f]
+where \f$P_l^m\f$ are the associated Legendre polynomials.  The above coefficients contain the theta-dependance of spheric harmonics : 
+\f[
+            Y_{lm}(\cos{\theta})=\lambda_l^m(\cos{\theta}) e^{im\phi}.
+\f]
+
+Each object has a fixed theta (radians), and maximum l and m to be calculated
+(lmax and mmax).
+ use the class in two steps : 
+a) instanciate  LambdaLMBuilder(\f$\theta\f$, \f$lmax\f$, \f$mmax\f$) ;  \f$lmax\f$ and \f$mmax\f$ are  MAXIMUM values for which \f$\lambda_l^m\f$ will be required in the following code (all coefficients, from \f$l=0 to lmax\f$, are computed once for all by an iterative formula).
+b) get the values of coefficients for  particular values of \f$l\f$ and \f$m\f$ by calling the method lamlm.
+*/
+ class LambdaLMBuilder {
+
+ public:
+
+LambdaLMBuilder() {}
+LambdaLMBuilder(r_8 theta,int_4 lmax, int_4 mmax);
+ ~LambdaLMBuilder() {};
+
+ /*! return the value of the coefficient \f$  \lambda_l^m \f$ */
+inline double lamlm(int l, int m) const { return lambda_(l,m); }
+
+ private:
+/*! compute a static array of coefficients independant from theta (common to all instances of the LambdaBuilder Class */
+ void updateArrayRecurrence(int_4 lmax);
+
+ void array_init(int lmax, int mmax);
+
+
+ static TriangularMatrix<r_8>* a_recurrence_;
+ TriangularMatrix<r_8> lambda_;
+
+ protected :
+
+/*! compute  static arrays of coefficients independant from theta (common to all instances of the derived  classes */
+ void updateArrayLamNorm();
+
+ static  TriangularMatrix<r_8>* lam_fact_;
+ static  TVector<r_8>*  normal_l_;
+ int_4 lmax_;
+ int_4 mmax_;
+ r_8 cth_;
+ r_8 sth_;
+ 
+ };
+
+
+
+/*! 
+
+This class generates the coefficients :
+\f[
+            _{w}\lambda_l^m=-2\sqrt{\frac{2(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}} G^+_{lm}
+\f]
+\f[
+            _{x}\lambda_l^m=-2\sqrt{\frac{2(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}}G^-_{lm}
+\f]
+where
+\f[G^+_{lm}(\cos{\theta})=-\left( \frac{l-m^2}{\sin^2{\theta}}+\frac{1}{2}l\left(l-1\right)\right)P_l^m(\cos{\theta})+\left(l+m\right)\frac{\cos{\theta}}{\sin^2{\theta}}P^m_{l-1}(\cos{\theta})
+\f]
+and
+\f[G^-_{lm}(\cos{\theta})=\frac{m}{\sin^2{\theta}}\left(\left(l-1\right)\cos{\theta}P^m_l(\cos{\theta})-\left(l+m\right)P^m_{l-1}(\cos{\theta})\right)
+\f]
+ \f$P_l^m\f$ are the associated Legendre polynomials.
+
+The coefficients express the theta-dependance of the \f$W_{lm}(\cos{\theta})\f$ and \f$X_{lm}(\cos{\theta})\f$ functions :
+\f[W_{lm}(\cos{\theta}) = \sqrt{\frac{(l+2)!}{2(l-2)!}}_w\lambda_l^m(\cos{\theta})e^{im\phi}
+\f]
+\f[X_{lm}(\cos{\theta}) = -i\sqrt{\frac{(l+2)!}{2(l-2)!}}_x\lambda_l^m(\cos{\theta})e^{im\phi}
+\f]
+ where \f$W_{lm}(\cos{\theta})\f$ and \f$X_{lm}(\cos{\theta})\f$ are defined as :
+
+\f[
+W_{lm}(\cos{\theta})=-\frac{1}{2}\sqrt{\frac{(l+2)!}{(l-2)!}}\left(
+_{+2}Y_l^m(\cos{\theta})+_{-2}Y_l^m(\cos{\theta})\right)
+\f]
+\f[X_{lm}(\cos{\theta})=-\frac{i}{2}\sqrt{\frac{(l+2)!}{(l-2)!}}\left(
+_{+2}Y_l^m(\cos{\theta})-_{-2}Y_l^m(\cos{\theta})\right)
+\f]
+
+*/
+class LambdaWXBuilder : public LambdaLMBuilder
+{
+ public:
+
+
+LambdaWXBuilder() {}
+
+LambdaWXBuilder(r_8 theta, int_4 lmax, int_4 mmax);
+ 
+ /*! return the value of the coefficients \f$ _{w}\lambda_l^m\f$ and \f$_{x}\lambda_l^m\f$ */
+inline void lam_wx(int l, int m, r_8& w, r_8& x) const
+   {
+     w=lamWlm_(l,m);
+     x=lamXlm_(l,m);
+   }
+
+ private:
+
+ void array_init();
+
+
+  TriangularMatrix<r_8> lamWlm_;
+  TriangularMatrix<r_8> lamXlm_;
+  
+
+};
+
+/*! 
+
+This class generates the coefficients
+\f[
+            _{\pm}\lambda_l^m=2\sqrt{\frac{(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}}\left( G^+_{lm} \mp G^-_{lm}\right)
+\f]
+where
+\f[G^+_{lm}(\cos{\theta})=-\left( \frac{l-m^2}{\sin^2{\theta}}+\frac{1}{2}l\left(l-1\right)\right)P_l^m(\cos{\theta})+\left(l+m\right)\frac{\cos{\theta}}{\sin^2{\theta}}P^m_{l-1}(\cos{\theta})
+\f]
+and
+\f[G^-_{lm}(\cos{\theta})=\frac{m}{\sin^2{\theta}}\left(\left(l-1\right)\cos{\theta}P^m_l(\cos{\theta})-\left(l+m\right)P^m_{l-1}(\cos{\theta})\right)
+\f]
+and \f$P_l^m\f$ are the associated Legendre polynomials.
+The coefficients express the theta-dependance of the  spin-2 spherical harmonics :
+\f[_{\pm2}Y_l^m(\cos{\theta})=_\pm\lambda_l^m(\cos{\theta})e^{im\phi}
+\f]
+*/
+class LambdaPMBuilder : public LambdaLMBuilder
+{
+ public:
+
+LambdaPMBuilder() {}
+
+ LambdaPMBuilder(r_8 theta, int_4 lmax, int_4 mmax);
+ /*! return the value of the coefficients \f$ _{+}\lambda_l^m\f$ and \f$_{-}\lambda_l^m\f$ */
+inline void lam_pm(int l, int m, r_8& lambda_plus, r_8& lambda_moins) const
+   {
+      lambda_plus = lamPlm_(l,m);
+     lambda_moins = lamMlm_(l,m);
+   }
+
+ private:
+ void array_init();
+
+  TriangularMatrix<r_8> lamPlm_;
+  TriangularMatrix<r_8> lamMlm_;
+
+
+
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/localmap.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/localmap.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/localmap.cc	(revision 752)
@@ -0,0 +1,755 @@
+#include "localmap.h"
+#include "nbmath.h"
+#include <complex>
+#include "piocmplx.h"
+
+#include <string.h>
+#include <iostream.h>
+
+
+//*****************************************************************************
+//++ 
+// Class	LocalMap
+//
+// include      localmap.h nbmath.h
+//
+//    A local map of a region of the sky, in cartesian coordinates.
+//    It has an origin in (theta0, phi0), mapped to pixel(x0, y0)
+//    (x0, y0 might be outside of this local map)
+//    default value of (x0, y0) is middle of the map, center of 
+//    pixel(nx/2, ny/2)
+//
+//    A local map is a 2 dimensional array, with i as column index and j
+//    as row index. The map is supposed to lie on a plan tangent to the 
+//    celestial sphere in a point whose coordinates are (x0,y0) on the local
+//    map and (theta0, phi0) on the sphere. The range of the map is defined
+//    by two values of angles covered respectively by all the pixels in 
+//    x direction and all the pixels in y direction (SetSize()).
+//
+//    A "reference plane" is considered : this plane is tangent to the 
+//    celestial sphere in a point with angles theta=Pi/2 and phi=0. This 
+//    point is the origine of coordinates is of the reference plane. The 
+//    x-axis is the tangent parallel to the equatorial line and oriented 
+//    toward the increasing phi's ; the y-axis is parallel to the meridian 
+//    line and oriented toward the north pole.
+//    
+//    Internally, a map is first defined within this reference plane and
+//    tranported until the point (theta0, phi0) in such a way that both 
+//    axes are kept parallel to meridian and parallel lines of the sphere.
+//    The user can define its own map with axes rotated with respect to
+//    reference axes (this rotation is characterized by angle between 
+//    the local parallel line and the wanted x-axis-- see method 
+//    SetOrigin(...))
+//    
+//
+
+//
+//-- 
+//++
+//
+// Links	Parents
+//
+//    PixelMap
+//    
+//-- 
+//++
+//
+// Links	Childs
+//
+//     
+//-- 
+//++
+// Titre	Constructors
+//--
+//++
+template<class T>
+LocalMap<T>::LocalMap()
+//
+//     
+//--
+{
+  InitNul();
+  pixels_.Reset();
+}
+
+//++
+template<class T>
+LocalMap<T>::LocalMap(int_4 nx, int_4 ny) : nSzX_(nx), nSzY_(ny)
+//
+//    
+//--
+{
+  InitNul();
+  nPix_= nx*ny;
+  pixels_.ReSize(nPix_);
+  pixels_.Reset();
+}
+
+//++
+template<class T>
+LocalMap<T>::LocalMap(const LocalMap<T>& lm, bool share)
+  : pixels_(lm.pixels_, share)
+
+//
+//    copy constructor
+//--
+{
+  cout<<" LocalMap:: Appel du constructeur de recopie " << endl;
+
+  if(lm.mInfo_) mInfo_= new DVList(*lm.mInfo_);
+  nSzX_= lm.nSzX_;
+  nSzY_= lm.nSzY_;
+  nPix_= lm.nPix_;
+  originFlag_= lm.originFlag_;
+  extensFlag_= lm.extensFlag_;
+  x0_= lm.x0_;
+  y0_= lm.y0_;
+  theta0_= lm.theta0_;
+  phi0_= lm.phi0_;
+  angle_= lm.angle_;
+  cos_angle_= lm.cos_angle_;
+  sin_angle_= lm.sin_angle_;
+  angleX_= lm.angleX_;
+  angleY_= lm.angleY_;
+  tgAngleX_= lm.tgAngleX_;
+  tgAngleY_= lm.tgAngleY_;
+}
+
+//++
+// Titre	Destructor
+//--
+//++
+template<class T>
+LocalMap<T>::~LocalMap()
+//
+//--
+{
+  InitNul();
+}
+
+
+
+//++
+// Titre	Public Methods
+//--
+
+//++
+template<class T>
+void LocalMap<T>::ReSize(int_4 nx, int_4 ny) 
+//
+//    Resize storage area for pixels 
+//--
+{
+  InitNul();
+  nSzX_ = nx;
+  nSzY_ = ny;
+  nPix_= nx*ny;
+  pixels_.ReSize(nPix_);
+  pixels_.Reset();
+}
+
+//++
+template<class T>
+int_4 LocalMap<T>::NbPixels() const
+//
+//    Return number of pixels
+//--
+{
+  return(nPix_);
+}
+
+//++
+template<class T>
+T& LocalMap<T>::PixVal(int_4 k)
+//
+//    Return value of pixel with index k
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    {
+      cout << " LocalMap::PIxVal : exceptions  a mettre en place" <<endl;
+      //  THROW(out_of_range("LocalMap::PIxVal Pixel index out of range"));
+      THROW(rangeCheckErr);
+      //throw "LocalMap::PIxVal Pixel index out of range";
+    }
+  return(pixels_(k));
+}
+
+//++
+
+template<class T>
+T const& LocalMap<T>::PixVal(int_4 k) const
+//
+//   const version of previous method
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    {
+      cout << " LocalMap::PIxVal : exceptions  a mettre en place" <<endl;
+      //    THROW(out_of_range("LocalMap::PIxVal Pixel index out of range"));
+      
+      throw "LocalMap::PIxVal Pixel index out of range"; 
+    } 
+  return *(pixels_.Data()+k);
+}
+
+template<class T>
+bool LocalMap<T>::ContainsSph(double theta, double phi) const
+{
+// $CHECK$  Reza 11/11/99 - A modifier
+return(true);
+}
+
+//++
+template<class T>
+int_4 LocalMap<T>::PixIndexSph(double theta,double phi) const
+//
+//    Return index of the pixel with spherical coordinates (theta,phi)
+//--
+{
+  int_4 i,j;
+  if(!(originFlag_) || !(extensFlag_)) 
+    {
+      cout << " LocalMap: correspondance carte-sphere non etablie" << endl;
+      exit(0);
+    }
+
+  // theta et phi en coordonnees relatives (on se ramene a une situation par rapport au plan de reference)
+  double theta_aux= theta;
+  double phi_aux  = phi;
+  UserToReference(theta_aux, phi_aux);
+
+  // coordonnees dans le plan local en unites de pixels
+  double x,y;
+  AngleProjToPix(theta_aux,phi_aux, x, y);
+
+  double xmin= -x0_-0.5;
+  double xmax= xmin+nSzX_;
+  if((x > xmax) || (x < xmin)) return(-1);
+  double xcurrent= xmin;
+  for(i = 0; i < nSzX_; i++ ) 
+    {
+      xcurrent += 1.;
+      if( x < xcurrent ) break;
+    }
+  double ymin= -y0_-0.5;
+  double ymax= ymin+nSzY_;
+  if((y >  ymax) || (y < ymin)) return(-1);
+  double ycurrent= ymin;
+  for(j = 0; j < nSzY_; j++ ) 
+    {
+      ycurrent += 1.;
+      if( y < ycurrent ) break;
+    }
+  return (j*nSzX_+i);
+}
+
+//++
+template<class T>
+void LocalMap<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
+//
+//    Return (theta, phi) coordinates of pixel with index k
+//--
+{
+  if(!(originFlag_) || !(extensFlag_)) 
+    {
+      cout << " LocalMap: correspondance carte-sphere non etablie" << endl;
+      exit(0);
+    }
+
+  int_4 i,j;
+  Getij(k,i,j);
+
+  double X= double(i-x0_);
+  double Y= double(j-y0_);
+  // situation de ce pixel dans le plan de reference
+  double x= X*cos_angle_-Y*sin_angle_;
+  double y= X*sin_angle_+Y* cos_angle_;
+  // projection sur la sphere
+  PixProjToAngle(x, y, theta, phi);
+  // retour au plan utilisateur
+  ReferenceToUser(theta, phi);
+}
+
+template <class T>
+T LocalMap<T>::SetPixels(T v)
+{
+pixels_.Reset(v);
+return(v);
+}
+ 
+//++
+template<class T>
+double LocalMap<T>::PixSolAngle(int_4 k) const
+//
+//    Pixel Solid angle  (steradians)
+//    All the pixels have not necessarly the same size in (theta, phi)
+//    because of the projection scheme which is not yet fixed.   
+//--
+{
+  int_4 i,j;
+  Getij(k,i,j);
+  double X= double(i-x0_);
+  double Y= double(j-y0_);
+  double XR= X+double(i)*0.5;
+  double XL= X-double(i)*0.5;
+  double YU= Y+double(j)*0.5;
+  double YL= Y-double(j)*0.5;
+
+  // situation  dans le plan de reference
+  double x0= XL*cos_angle_-YL*sin_angle_;
+  double y0= XL*sin_angle_+YL*cos_angle_;
+  double xa= XR*cos_angle_-YL*sin_angle_;
+  double ya= XR*sin_angle_+YL*cos_angle_;
+  double xb= XL*cos_angle_-YU*sin_angle_;
+  double yb= XL*sin_angle_+YU*cos_angle_;
+
+  // projection sur la sphere
+  double thet0,phi0,theta,phia,thetb,phib;
+  PixProjToAngle(x0, y0, thet0, phi0);
+  PixProjToAngle(xa, ya, theta, phia);
+  PixProjToAngle(xb, yb, thetb, phib);
+
+  // angle solide
+  double sol= fabs((xa-x0)*(yb-y0)-(xb-x0)*(ya-y0));
+  return sol;
+}
+
+//++
+template<class T>
+void LocalMap<T>::SetOrigin(double theta0,double phi0,double angle)
+//
+//    set the referential of the map (angles in degrees)
+//    (default x0=siz_x/2,  y0=siz_y/2) 
+//--
+{
+  theta0_= theta0;
+  phi0_  = phi0;
+  angle_ = angle;
+  x0_= nSzX_/2;
+  y0_= nSzY_/2;
+  cos_angle_= cos(angle*Pi/180.);
+  sin_angle_= sin(angle*Pi/180.);
+  originFlag_= true; 
+  cout << " LocalMap:: set origin 1 done" << endl;
+}
+ 
+//++
+template<class T>
+void LocalMap<T>::SetOrigin(double theta0,double phi0,int_4 x0,int_4 y0,double angle)
+//
+//    set the referential of the map (angles in degrees)
+//--
+{
+  theta0_= theta0;
+  phi0_  = phi0;
+  angle_ = angle;
+  x0_= x0;
+  y0_= y0;
+  cos_angle_= cos(angle*Pi/180.);
+  sin_angle_= sin(angle*Pi/180.);
+  originFlag_= true;
+  cout << " LocalMap:: set origin 2 done" << endl;
+} 
+
+//++
+template<class T>
+void LocalMap<T>::SetSize(double angleX,double angleY)
+//
+//    angle range of tthe map (angles in degrees)
+//--
+{
+  angleX_= angleX;
+  angleY_= angleY;
+
+  // tangente de la moitie de l'ouverture angulaire totale
+  tgAngleX_= tan(0.5*angleX_*Pi/180.);
+  tgAngleY_= tan(0.5*angleY_*Pi/180.);
+
+  extensFlag_= true;
+  cout << " LocalMap:: set extension done" << endl;
+}
+
+//++
+template<class T>
+void LocalMap<T>::Project(SphericalMap<T>& sphere) const
+//
+//    Projection to a spherical map   
+//--
+{
+  for(int m = 0; m < nPix_; m++) 
+    {
+      double theta,phi;
+      PixThetaPhi(m,theta,phi);
+      sphere(theta,phi)= pixels_(m);
+      // cout << "theta " << theta << " phi " << phi << " valeur " << sphere(theta,phi)<< endl;
+    }
+}
+// Titre	Private Methods
+//++
+template<class T>
+void LocalMap<T>::InitNul()
+//
+//    set some attributes to zero
+//--
+{ 
+  originFlag_= false;
+  extensFlag_= false;
+  cos_angle_= 1.0;
+  sin_angle_= 0.0;
+//  pixels_.Reset(); Pas de reset par InitNul (en cas de share) - Reza 20/11/99 $CHECK$
+}
+
+//++
+template<class T>
+void LocalMap<T>::Getij(int_4 k,int_4& i,int_4& j) const
+//
+//    Return 2 indices corresponding to the pixel number k
+//--
+{
+  i= (k+1)%nSzX_-1;
+  if(i == -1) i= nSzX_-1;
+  j= (k-i+2)/nSzX_;
+}
+
+//++
+template<class T>
+void  LocalMap<T>::ReferenceToUser(double& theta,double& phi) const
+//
+//    Transform a pair of coordinates (theta, phi) given in 
+//    reference coordinates into map coordinates
+//--     
+{
+  if(theta > Pi || theta < 0. || phi < 0. || phi >= 2*Pi) 
+    {
+      throw "LocalMap::ReferenceToUser (theta,phi) out of range"; 
+    } 
+
+  theta= theta0_*Pi/180.+theta-Pi*0.5;
+  if(theta < 0.) 
+    {
+      theta= -theta;
+      phi += Pi;
+    } 
+  else 
+    {
+      if(theta > Pi) 
+	{
+	  theta= 2.*Pi-theta;
+	  phi += Pi;
+	} 
+    }
+
+  phi= phi0_*Pi/180.+phi;
+  while(phi >= 2.*Pi) phi-= 2.*Pi;
+
+  if(theta > Pi || theta < 0. || phi < 0. || phi >= 2*Pi) 
+    {
+      cout <<  " LocalMap::ReferenceToUser : erreur bizarre dans le transfert a la carte utilisateur " << endl;
+      cout << " theta= " << theta << " phi= " << phi << endl;
+      exit(0);
+    }
+}
+
+//++
+template<class T>
+void  LocalMap<T>::UserToReference(double& theta,double& phi) const
+//
+//    Transform a pair of coordinates (theta, phi) given in 
+//    map coordinates into reference coordinates
+//--     
+{
+  if(theta > Pi || theta < 0. || phi < 0. || phi >= 2*Pi) 
+    {
+      cout<<" LocalMap::UserToReference: exceptions a mettre en place" <<endl;
+      // THROW(out_of_range("LocalMap::PIxVal Pixel index out of range"));
+      throw "LocalMap::UserToReference (theta,phi) out of range"; 
+    }
+
+  double phi1= phi-phi0_*Pi/180.;
+  if(phi1 < 0.) phi1+= 2.*Pi;
+
+  double theta1= theta-theta0_*Pi/180.+Pi*0.5;
+  if(theta1 < 0.) 
+    {
+      theta= -theta1;
+      phi1+= Pi;
+    } 
+  else
+    { 
+      if(theta1 > Pi) 
+	{
+	  theta= 2.*Pi-theta1;
+	  phi1+= Pi;
+	}
+    }
+
+  while(phi1 >= 2.*Pi) phi1-= 2.*Pi;
+  phi= phi1;
+  if(theta > Pi || theta < 0. || phi < 0. || phi >= 2*Pi) 
+    {
+      cout <<  " LocalMap::UserToReference : erreur bizarre dans le transfert a la carte de reference " << endl;
+      cout << " theta= " << theta << " phi= " << phi << endl;
+      exit(0);
+    }
+}
+
+//++
+template<class T>
+void LocalMap<T>::PixProjToAngle(double x,double y,double& theta,double& phi) const
+//
+//  
+//    Given coordinates in pixel units in the REFERENCE PLANE, return
+//    (theta, phi) in "absolute" referential theta=pi/2 ,phi=0.   
+//--
+{
+  theta= Pi*0.5-atan(2.*y*tgAngleY_/(double)nSzY_);
+  phi= atan2(2.*x*tgAngleX_,(double)nSzX_);
+  if(phi < 0.) phi += DeuxPi;
+}
+
+//++
+template<class T>
+void LocalMap<T>::AngleProjToPix(double theta,double phi,double& x,double& y) const
+//
+//    Given coordinates  (theta, phi) in "absolute" referential 
+//    theta=pi/2 ,phi=0  return pixel indices  (i,j) in the REFERENCE PLANE.
+//--
+{
+  if(phi >= Pi) phi-= DeuxPi;
+  //  y=0.5*mSzY_*cot(theta)/tgAngleY_;  $CHECK-REZA-04/99$
+  y= 0.5*nSzY_/tan(theta)/tgAngleY_;  // ? cot = 1/tan ?  
+  x= 0.5*nSzX_*tan(phi)/tgAngleX_;
+}
+
+template<class T>
+void LocalMap<T>::print(ostream& os) const
+{
+  os<<" SzX= "<<nSzX_<<", SzY= "<<nSzY_<<", NPix= "<<nPix_<<endl;
+  if(LocalMap_isDone())
+    {
+      os<<" theta0= "<<theta0_<<", phi0= "<<phi0_<<", angle= "<<angle_<<endl;
+      os<<" x0= "<<x0_<<", y0= "<<y0_<<endl;
+      os<<" cos= "<<cos_angle_<<", & sin= "<<sin_angle_<<endl;
+      os<<" angleX= "<<angleX_<<", angleY= "<<angleY_<<endl;
+      os<<" tg(angleX)= "<<tgAngleX_<<", tg(angleY)= "<<tgAngleY_<<endl;
+    }
+
+  os << " contenu de pixels : ";
+  for(int i=0; i < nPix_; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os <<  pixels_(i) <<", ";
+    }
+  os << endl;
+}
+//++
+// Titre	class FIO_LocalMap
+//    Delegated objects for persitance management
+//--
+
+//*******************************************************************
+// class FIO_LocalMap<T>
+//  Les objets delegues pour la gestion de persistance 
+//*******************************************************************
+
+//++
+template <class T>
+FIO_LocalMap<T>::FIO_LocalMap()
+//
+//--
+{
+  dobj= new LocalMap<T>;
+  ownobj= true;
+}
+//++
+template <class T>
+FIO_LocalMap<T>::FIO_LocalMap(string const& filename)
+//
+//--
+{
+  dobj= new LocalMap<T>;
+  dobj->DataBlock().SetTemp(true);
+  ownobj= true;
+  Read(filename);
+}
+
+//++
+template <class T>
+FIO_LocalMap<T>::FIO_LocalMap(const LocalMap<T>& obj)
+//
+//--
+{
+  dobj= new LocalMap<T>(obj, true);
+  dobj->DataBlock().SetTemp(true);
+  ownobj= true;
+}
+
+template <class T>
+FIO_LocalMap<T>::FIO_LocalMap(LocalMap<T>* obj)
+{
+  dobj= obj;
+  ownobj= false;
+}
+
+//++
+template <class T>
+FIO_LocalMap<T>::~FIO_LocalMap()
+//
+//--
+{
+  if (ownobj && dobj) delete dobj;
+}
+//++
+template <class T>
+AnyDataObj* FIO_LocalMap<T>::DataObj()
+//
+//--
+{
+  return(dobj);
+}
+
+//++
+template <class T>
+void FIO_LocalMap<T>::ReadSelf(PInPersist& is)
+//
+//--
+{
+
+  if(dobj == NULL) 
+    {
+      dobj= new LocalMap<T>;
+      dobj->DataBlock().SetTemp(true);
+      ownobj= true;
+    }
+
+  // Pour savoir s'il y avait un DVList Info associe
+  char strg[256];
+  is.GetLine(strg, 255);
+  bool hadinfo= false;
+  if(strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0)  hadinfo= true;
+  if(hadinfo) 
+    {    // Lecture eventuelle du DVList Info
+      is >> dobj->Info(); 
+    }
+
+  int_4 nSzX;
+  is.GetI4(nSzX);
+  //  dobj->setSize_x(nSzX);
+
+  int_4 nSzY;
+  is.GetI4(nSzY);
+  //  dobj->setSize_y(nSzY);
+
+  int_4 nPix;
+  is.GetI4(nPix);
+  //  dobj->setNbPixels(nPix);
+  dobj->ReSize(nSzX, nSzY); 
+  string ss("local mapping is done");
+  string sso;
+  is.GetStr(sso);
+  if(sso == ss)
+    {
+      cout<<" ReadSelf:: local mapping"<<endl;
+      int_4 x0, y0;
+      double theta, phi, angle;
+      is.GetI4(x0);
+      is.GetI4(y0);
+      is.GetR8(theta);
+      is.GetR8(phi);
+      is.GetR8(angle);
+      dobj->SetOrigin(theta, phi, x0, y0, angle);
+
+      double angleX, angleY;
+      is.GetR8(angleX);
+      is.GetR8(angleY);
+      dobj->SetSize(angleX, angleY);
+    }
+
+// On lit le DataBlock;
+  FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+  fio_nd.Read(is);
+}
+
+//++
+template <class T>
+void FIO_LocalMap<T>::WriteSelf(POutPersist& os) const
+//
+//--
+{
+  if(dobj == NULL) 
+    {
+      cout << " FIO_LocalMap::WriteSelf:: dobj= null " << endl;
+      return;
+    }
+
+  char strg[256];
+  int_4 nSzX= dobj->Size_x();
+  int_4 nSzY= dobj->Size_y();
+  int_4 nPix= dobj->NbPixels();
+ 
+  if(dobj->ptrInfo()) 
+    {
+      sprintf(strg,"LocalMap: NPixX=%6d  NPixY=%9d HasInfo",nSzX,nSzY);
+      os.PutLine(strg);
+      os << dobj->Info();
+    }
+  else 
+    { 
+      sprintf(strg,"LocalMap: NPixX=%6d  NPixY=%9d ",nSzX,nSzY);
+      os.PutLine(strg);  
+    }
+
+  os.PutI4(nSzX);
+  os.PutI4(nSzY);
+  os.PutI4(nPix);
+
+  if(dobj->LocalMap_isDone())
+    {
+      string ss("local mapping is done");
+      os.PutStr(ss);
+      int_4 x0, y0;
+      double theta, phi, angle;
+      dobj->Origin(theta, phi, x0, y0, angle);
+      os.PutI4(x0);
+      os.PutI4(y0);
+      os.PutR8(theta);
+      os.PutR8(phi);
+      os.PutR8(angle);
+
+      double angleX, angleY;
+      dobj->Aperture(angleX, angleY);
+      os.PutR8(angleX);
+      os.PutR8(angleY);
+    }
+  else
+    {
+      string ss("no local mapping");
+      os.PutStr(ss);
+    }
+
+// On ecrit le dataBlock 
+  FIO_NDataBlock<T> fio_nd(&dobj->DataBlock());
+  fio_nd.Write(os);
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template LocalMap<double>
+#pragma define_template LocalMap<float>
+#pragma define_template LocalMap< complex<double> >
+#pragma define_template LocalMap< complex<float> >
+#pragma define_template FIO_LocalMap<double>
+#pragma define_template FIO_LocalMap<float>
+#pragma define_template FIO_LocalMap< complex<float> >
+#pragma define_template FIO_LocalMap< complex<double> >
+#endif
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class LocalMap<double>;
+template class LocalMap<float>;
+template class LocalMap< complex<double> >;
+template class LocalMap< complex<float> >;
+template class FIO_LocalMap<double>;
+template class FIO_LocalMap<float>;
+template class FIO_LocalMap< complex<float> >;
+template class FIO_LocalMap< complex<double> >;
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/localmap.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/localmap.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/localmap.h	(revision 752)
@@ -0,0 +1,233 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef LOCALMAP_SEEN
+#define LOCALMAP_SEEN
+
+#include "pixelmap.h"
+#include "sphericalmap.h"
+#include "ndatablock.h"
+
+#include "anydataobj.h"
+#include "ppersist.h"
+
+//! A local map of a region of the sky, in cartesian coordinates.
+/*! A local map has an origin in (theta0, phi0), mapped to pixel(x0, y0)
+   (x0, y0 might be outside of this local map)
+ default value of (x0, y0) is middle of the map, center of pixel(nx/2, ny/2)
+    A local map is a 2 dimensional array, with i as column index and j
+    as row index. The map is supposed to lie on a plan tangent to the 
+    celestial sphere in a point whose coordinates are (x0,y0) on the local
+   map and (theta0, phi0) on the sphere. The range of the map is defined
+    by two values of angles covered respectively by all the pixels in 
+    x direction and all the pixels in y direction (SetSize()).
+
+    A "reference plane" is considered : this plane is tangent to the 
+    celestial sphere in a point with angles theta=Pi/2 and phi=0. This 
+    point is the origine of coordinates is of the reference plane. The 
+    x-axis is the tangent parallel to the equatorial line and oriented 
+    toward the increasing phi's ; the y-axis is parallel to the meridian 
+    line and oriented toward the north pole.
+    
+    Internally, a map is first defined within this reference plane and
+    tranported until the point (theta0, phi0) in such a way that both 
+    axes are kept parallel to meridian and parallel lines of the sphere.
+    The user can define its own map with axes rotated with respect to
+    reference axes (this rotation is characterized by angle between 
+    the local parallel line and the wanted x-axis-- see method 
+    SetOrigin(...))
+*/
+//
+//    la carte est consideree comme un tableau a deux indices i et j, i etant 
+//    indice de colonne et j indice de ligne. La carte est supposee resider 
+//    dans un plan tangent, dont le point de tangence est repere (x0,y0) dans 
+//    la carte et (theta0, phi0) sur la sphere celeste. L extension de la 
+//    carte est definie par les valeurs de deux angles couverts respectivement
+//    par la totalite des pixels en x de la carte et la totalite des pixels 
+//    en y. (SetSize()).
+//    On considere un "plan de reference" : plan tangent a la sphere celeste 
+//    aux angles theta=Pi/2 et phi=0. Dans ce plan L origine des coordonnees 
+//    est le point de tangence. L axe Ox est la tangente parallele a 
+//    lequateur, dirige vers les phi croissants, l axe Oy est parallele 
+//    au meridien, dirige vers le pole nord.
+//    De maniere interne a la classe une carte est definie dans ce plan de 
+//    reference et transportee  jusqu au point (theta0, phi0) de sorte que les //    axes restent paralleles aux meridiens et paralleles. L utilisateur peut 
+//    definir sa carte selon un repere en rotation par rapport au repere de 
+//    reference (par l angle entre le parallele et l axe Ox souhaite -- 
+//    methode SetOrigin(...))
+
+
+// ***************** Class LocalMap *****************************
+
+template<class T>
+class LocalMap : public PixelMap<T>
+{
+
+public:
+
+LocalMap();
+LocalMap(int_4 nx, int_4 ny);
+LocalMap(const LocalMap<T>& lm, bool share=false);
+virtual ~LocalMap();
+
+/*! Setting blockdata to temporary (see ndatablock documentation) */
+inline virtual void SetTemp(bool temp=false) const {pixels_.SetTemp(temp);};
+
+
+// ---------- Overloading of () to access pixel number k ----
+
+inline T& operator()(int_4 k) {return(PixVal(k));}
+inline T const& operator()(int_4 k) const {return(PixVal(k));}
+inline T& operator()(int_4 ix, int_4 iy) {return PixVal(iy*nSzX_+ix);};
+inline T const& operator()(int_4 ix, int_4 iy) const {return PixVal(iy*nSzX_+ix);};
+   
+// ---------- Definition of PixelMap abstract methods -------
+
+/* return/set the number of pixels */
+/*!    Return number of pixels */
+virtual int_4 NbPixels() const;   // D.Y. int change en int_4 rationalisation Mac
+  
+/* return the value of pixel number k */
+/*!    Return value of pixel with index k */
+virtual T& PixVal(int_4 k);
+/*!   const version of previous method */
+virtual T const& PixVal(int_4 k) const;
+
+/* Return true if teta,phi in map  */
+virtual bool ContainsSph(double theta, double phi) const;
+/* return the index of pixel at (theta,phi) */
+/*!    Return index of the pixel with spherical coordinates (theta,phi) */
+virtual int_4 PixIndexSph(double theta,double phi) const;
+   
+/* return the spherical coordinates of center of pixel number k */
+/*!    Return (theta, phi) coordinates of pixel with index k */
+virtual void PixThetaPhi(int_4 k,double& theta,double& phi) const;
+
+/*! Set all pixels to value v */
+virtual T SetPixels(T v);
+
+/* return the Pixel Solid angle  (steradians) */
+/*!    Pixel Solid angle  (steradians)
+
+    All the pixels have not necessarly the same size in (theta, phi)
+    because of the projection scheme which is not yet fixed. 
+*/  
+virtual double PixSolAngle(int_4 k) const; 
+
+// ---------- Specific methods ------------------------------
+
+/*!    Resize storage area for pixels */
+void ReSize(int_4 nx, int_4 ny);
+
+inline virtual char* TypeOfMap() const {return "LOCAL";};
+ 
+/* Origin (with angle between x axis and phi axis, in degrees)  x0,y0  the default: middle of map*/
+/*!    set the referential of the map (angles in degrees)
+
+    (default x0=siz_x/2,  y0=siz_y/2) 
+*/
+virtual void SetOrigin(double theta=90.,double phi=0.,double angle=0.);
+/*!    set the referential of the map (angles in degrees) */
+virtual void SetOrigin(double theta,double phi,int_4 x0,int_4 y0,double angle=0.);
+
+/* Pixel size (degres) */ 
+/*!    angle range of tthe map (angles in degrees) */
+virtual void SetSize(double angleX,double angleY);
+
+/* Check to see if the local mapping is done */
+inline bool LocalMap_isDone() const {return(originFlag_ && extensFlag_);};
+
+/*! Projection to a spherical map */
+virtual void Project(SphericalMap<T>& sphere) const;
+  
+/* There should be a more complex algorithm somewhere to combine *several* local maps to a full sphere.
+      -> static method, or separate class */
+  
+/* provides a integer characterizing the pixelization refinement  (here : number of pixels) */
+inline virtual int_4 SizeIndex() const {return(nPix_);}
+inline int_4 Size_x() const {return nSzX_;}
+inline int_4 XSize() const {return nSzX_;}
+inline int_4 Size_y() const {return nSzY_;}
+inline int_4 YSize() const {return nSzY_;}
+
+inline void Origin(double& theta,double& phi,int_4& x0,int_4& y0,double& angle) const {theta= theta0_; phi= phi0_; x0= x0_; y0= y0_;angle= angle_;}
+
+inline void Aperture(double& anglex,double& angley) const {anglex= angleX_; angley= angleY_;}
+
+
+/*  Acces to the DataBlock  */
+inline       NDataBlock<T>& DataBlock()       {return pixels_;}
+inline const NDataBlock<T>& DataBlock() const {return pixels_;}
+
+/* impression */ 
+void print(ostream& os) const;
+
+// ---------- Méthodes internes -----------------------------
+          
+private :
+
+void InitNul();
+/*!    Return 2 indices corresponding to the pixel number k */
+void Getij(int_4 k,int_4& i,int_4& j) const;
+/*!    Transform a pair of coordinates (theta, phi) given in 
+    reference coordinates into map coordinates
+*/
+void ReferenceToUser(double& theta,double& phi) const; 
+/*!    Transform a pair of coordinates (theta, phi) given in 
+   map coordinates into reference coordinates
+*/
+void UserToReference(double& theta,double& phi) const;
+/*!   Given coordinates in pixel units in the REFERENCE PLANE, return
+    (theta, phi) in "absolute" referential theta=pi/2 ,phi=0.   
+*/
+void PixProjToAngle(double x,double y,double& theta,double& phi) const; 
+/*!    Given coordinates  (theta, phi) in "absolute" referential 
+    theta=pi/2 ,phi=0  return pixel indices  (i,j) in the REFERENCE PLANE.
+*/
+void AngleProjToPix(double theta,double phi,double& x,double& y) const; 
+
+// ---------- Variables internes ----------------------------
+
+int_4 nSzX_;
+int_4 nSzY_;
+int_4 nPix_;
+bool originFlag_;
+bool extensFlag_;
+int_4 x0_;
+int_4 y0_;
+double theta0_;
+double phi0_;
+double angle_;
+double cos_angle_;
+double sin_angle_;
+double angleX_;
+double angleY_;
+double tgAngleX_;
+double tgAngleY_;
+NDataBlock<T> pixels_;
+};
+
+// ------------- Classe pour la gestion de persistance --
+//!    Delegated objects for persitance management
+template <class T>
+class FIO_LocalMap : public PPersist  
+{
+
+public:
+
+FIO_LocalMap();
+FIO_LocalMap(string const & filename); 
+FIO_LocalMap(const LocalMap<T>& obj);
+FIO_LocalMap(LocalMap<T>* obj);
+virtual ~FIO_LocalMap();
+virtual AnyDataObj* DataObj();
+inline operator LocalMap<T>() { return(*dobj); }
+//inline LocalMap<T> getObj() { return(*dobj); }
+
+protected :
+
+virtual void ReadSelf(PInPersist&);           
+virtual void WriteSelf(POutPersist&) const;  
+LocalMap<T>* dobj;
+bool ownobj;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/longlat.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/longlat.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/longlat.cc	(revision 752)
@@ -0,0 +1,82 @@
+#include "longlat.h"
+//++ 
+// Class	LongLat
+//
+// include      longlat.h
+//
+//    translation from  coordinates (longitude, latitude) 
+//    to theta,phi
+//
+//    longitude=phi
+//
+//    latitude=Pi/2-theta
+//
+//--
+//++
+// Titre	Constructors
+//--
+//++
+LongLat::LongLat()
+//
+//--
+{
+  _lon=0.;
+  _lat=0.;
+}
+//++
+LongLat::LongLat(double longitude, double latitude)
+//
+//--
+{
+  _lon=mod(longitude,pi2);
+  if( latitude == pi_over_2 ) _lat=latitude;
+  else _lat=mod(latitude+pi_over_2,M_PI)-pi_over_2; // dans [-Pi/2,Pi/2]
+}
+//++
+LongLat::LongLat(double x, double y, double z)
+//
+//--
+{
+  double norm=sqrt(x*x+y*y+z*z);
+  double theta;
+  if( norm != 0. ) 
+    {
+      theta=acos(z/norm); // dans [0,Pi]
+      if( mod(theta,M_PI) == 0. ) _lon=0.; // on est sur +-Oz, le vecteur z est en phi=0
+      //      else _lon=acos(x/sin(theta)/norm)+M_PI*(y<0);
+      else _lon=scangle(y/sin(theta)/norm,x/sin(theta)/norm);
+    }
+  else // vecteur nul
+    {
+      theta=0.;
+      _lon=0.;
+    }
+  _lat=pi_over_2-theta;
+}
+//++
+// Titre	Public Methods
+//--
+//++
+void LongLat::Set(double longitude, double latitude)
+//
+//--
+{
+  _lon=mod(longitude,pi2);
+  if( latitude == pi_over_2 ) _lat=latitude;
+  else _lat=mod(latitude+pi_over_2,M_PI)-pi_over_2; // dans [-Pi/2,Pi/2]
+}
+//++
+void LongLat::Print(ostream& os) const
+//
+//--
+{
+  os << "LongLat : longitude = " << _lon << " phi   = " << this->Phi() << endl;
+  os << "LongLat : latitude    = " << _lat << " theta = " << this->Theta() << endl;
+}
+//++
+//
+//  double Longitude() const 
+//  double Phi() const 
+//  double Latitude() 
+//  double Theta() const 
+//--
Index: /tags/V_Fev00/SophyaLib/Samba/longlat.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/longlat.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/longlat.h	(revision 752)
@@ -0,0 +1,47 @@
+#ifndef LONGLAT_H_SEEN
+#define LONGLAT_H_SEEN
+
+#include <math.h>
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include "utilgeom.h"
+
+/*
+  passage des coordonnees longitude, latitude en theta,phi
+  longitude=phi
+  latitude=Pi/2-theta
+*/
+
+class LongLat
+{
+  
+ public:
+  
+  LongLat();
+  LongLat(double longitude, double latitude);
+  LongLat(double x, double y, double z);
+  LongLat(const LongLat&);
+  
+  void Set(double longitude, double latitude);
+  double Longitude() const {return _lon;}
+  double Phi() const {return _lon;}
+  double Latitude() const {return _lat;}
+  double Theta() const {return pi_over_2-_lat;}
+
+  void Print(ostream& os) const;
+  
+ private:
+  
+  double _lon; // lambda
+  double _lat; // beta
+  
+};
+
+inline ostream& operator<<(ostream& s, const LongLat& ll) 
+{  
+  ll.Print(s);  
+  return s;  
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/misstime.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/misstime.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/misstime.h	(revision 752)
@@ -0,0 +1,12 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef MISSIONTIME_H_SEEN
+#define MISSIONTIME_H_SEEN
+
+#include "machdefs.h"
+
+namespace SOPHYA {
+// Just a double for the moment, would be converted to a class later
+typedef r_8 MissionTime;
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/mlobe.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/mlobe.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/mlobe.cc	(revision 752)
@@ -0,0 +1,230 @@
+#include "mlobe.h"
+#include "unitvector.h"
+
+#include "timing.h"
+// #include "nbrandom.h"
+//++ 
+// Class	MainLobe
+//
+// include      mlobe.h sphericalmap.h unitvector.h math.h
+//
+//    Class for computation of main lobe.
+//
+//     The lobe values are computed in pixels laying on "nc" slices 
+//     with hexagonal  pavement around theta=0 , phi=0. The lobe is 
+//     gaussian with sigma="sig". The slices are built every 
+//     "dels"*sigma.
+// 
+//--
+//++
+// Titre	Constructor
+//--
+/* --Methode-- */
+//++
+MainLobe::MainLobe(float sig, float dels, int nc)
+//
+//--
+{
+if (sig < 1.e-9)  sig = M_PI/100.;   // Sigma du lobe gaussien (radians)
+mSigma = sig;
+mDels = (dels < 1.e-5) ?  0.5 : dels;   // Epaisseur de chaque couche en unite de sigma
+mNC =  (nc < 1) ? 1 : nc;
+mNpix = 1;    // Nb total de pixels du lobe
+
+int i,j,k;
+for(i=1; i<=mNC; i++)  mNpix += 6*i;
+//  mT0 , mP0  Teta et Phi des pixels, Pixel 0 oriente vers (0, 0)
+mT0 = new float[mNpix];
+mP0 = new float[mNpix];
+//  mTC , mPC  Teta et Phi des pixels, Pixel 0 oriente vers (Teta, phi)
+mTC = new float[mNpix];
+mPC = new float[mNpix];
+mDx = new float[mNpix];
+mDy = new float[mNpix];
+mDr = new float[mNpix];
+// Valeurs des pixels 
+mVal = new double[mNpix];
+
+
+double teta,phi,dphi;
+double val;
+mT0[0] = mP0[0] = mTC[0] = mPC[0] = 0.;
+mVal[0] = 1.;  mDx[0] = mDy[0] = 0.;
+k = 1;  mTotVal = 1.;
+for(i=1; i<=mNC; i++) {
+  teta = (double)i*mDels;
+  val = exp(-teta*teta);
+  teta *= mSigma;
+  if (i%2)  phi = M_PI/6.;
+  else phi = 0.;
+  dphi = M_PI/(3.*i);
+  for(j=0; j<6*i; j++) {
+    mT0[k] = mTC[k] = teta;
+    phi += dphi;
+    mP0[k] = mPC[k] = phi;
+    mVal[k] = val;
+    mTotVal += val;
+    mDx[k] = teta*cos(phi);
+    mDy[k] = teta*sin(phi);
+    mDr[k] = teta;
+    k++;
+    }
+  }
+mDirTet = mDirPhi = 0.;
+return;
+}
+
+
+//++
+// Titre	Constructor
+//--
+/* --Methode-- */
+//++
+MainLobe::~MainLobe()
+//
+//--
+{
+delete mT0;
+delete mP0;
+delete mTC;
+delete mPC;
+delete mDx;
+delete mDy;
+delete mDr;
+delete mVal;
+}
+//++
+// Titre	Public Methods
+//--
+//++
+//
+// inline int      NPix() 
+//    Return the total number of pixels of the lobe            
+// inline float    Sigma()             
+// inline double   Integral()            
+//--
+/* --Methode-- */
+//++
+void MainLobe::SetDirection(float teta, float phi)
+//
+//    orientate  the lobe  toward the direction  (theta, phi)
+//--
+{
+int k;
+
+mDirTet = teta;
+mDirPhi = phi;
+
+if (teta < 0.1*mDels*mSigma) {
+  for(k=0; k<mNpix; k++) {
+    mTC[k] = mT0[k]; mPC[k] = mP0[k]; 
+    }
+  return;
+  }
+
+
+/*
+if (teta > 10.*mSigma*mDels*mNC) {   // On utilise des formules approchees
+  float stet = sin((double)teta);
+  float ctet = cos((double)teta);
+  for(k=0; k<mNpix; k++) {
+    mTC[k] = teta - mDy[k]*stet - mDr[k]*ctet;
+    mPC[k] = phi + mDx[k];
+    }
+  return;
+  }
+  */
+
+// Formules compliquees 
+
+double dx,dy,dz;
+double sphi = sin((double)phi);
+double cphi = cos((double)phi);
+double stet = sin((double)teta);
+double ctet = cos((double)teta);
+
+UnitVector pd((double)teta, (double)phi);
+UnitVector vc;
+for(k=0; k<mNpix; k++) {
+  dz = mDy[k]*stet;
+  dx = -(mDx[k]*sphi+mDy[k]*ctet*cphi);
+  dy = mDx[k]*cphi-mDy[k]*ctet*sphi;
+  vc.Setxyz(pd.X()+dx, pd.Y()+dy, pd.Z()+dz);
+  mTC[k] = vc.Theta();
+  mPC[k] = vc.Phi();
+  if (mTC[k] < 0.)  printf("ERREUR !!!! mTC[%d] = %g \n", k, mTC[k]);
+  if (mPC[k] < 0.) mPC[k] += M_PI*2.;
+  if (mPC[k] >= M_PI*2.) mPC[k] -= M_PI*2.;
+  }
+return;  
+}
+
+/* --Methode-- */
+//++
+double MainLobe::Value(int kpx, float& teta, float& phi)
+//
+//    return the value of the lobe as also the (theta, phi) of the
+//    pixel "kpx"  
+//--
+{
+if ( (kpx < 0) || (kpx >= mNpix) ) { teta = phi = 0.; return(0.); }
+teta = mTC[kpx];
+phi = mPC[kpx];
+return(mVal[kpx]);
+}
+
+/* --Methode-- */
+//++
+double MainLobe::Convol(SphericalMap<double>& sph)
+//
+//    return the value of the lobe convolved with the sky (sphere) "sph"
+//--
+{
+double ret=0.;
+int k;
+for(k=0; k<mNpix; k++)  ret += mVal[k]*sph(mTC[k], mPC[k]);
+/*
+if( (dbg > 0) && (k%dbg) ) 
+  printf("MainLobe::Convol k= %d T,P= %g %g , Lobe=%g Sph= %g  Ret=%g\n", 
+         k, mTC[k], mPC[k], mVal[k], sph(mTC[k], mPC[k]), ret );
+*/
+return(ret/mTotVal);
+}
+
+//++
+//
+// inline void     Print()  
+//--
+
+//++
+// Titre	Operators
+//--
+
+/* --Methode-- */
+//++
+ostream& operator << (ostream& s, MainLobe const& lob)
+//
+//--
+{
+s << "MainLobe_Info() : Sigma= " << lob.mSigma << " Dels= " << lob.mDels << " NC= " 
+  << lob.mNC << " NTotPix= " << lob.mNpix << " Integ= " << lob.mTotVal << endl;
+
+int i,j,k;
+cout << " Direction Teta,Phi = " << lob.mDirTet << " , " << lob.mDirPhi << endl;      
+cout << " Pixel 0 , Teta= " << lob.mT0[0] << " Phi= " << lob.mP0[0] 
+     << " Val= " << lob.mVal[0] << endl;
+k = 1;
+for(i=1; i<lob.mNC; i++) {
+  cout << " Couche # " << i << " NPix= " << i*6 << endl;
+  for(j=0;j<6*i;j++) {
+    cout << "K= " << k << "Teta,Phi= "  << lob.mTC[k] << ", " << lob.mPC[k] 
+         << " (" << lob.mT0[k] << ", " << lob.mP0[k] << ") "
+         << " Val= " << lob.mVal[k] << endl; 
+    k++;
+    }
+  }
+
+
+return s;
+}
+
Index: /tags/V_Fev00/SophyaLib/Samba/mlobe.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/mlobe.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/mlobe.h	(revision 752)
@@ -0,0 +1,50 @@
+#ifndef SCSKYU_H_SEEN
+#define SCSKYU_H_SEEN
+
+#include <math.h>
+#include <iostream.h>
+
+#include "sphericalmap.h"
+
+
+
+// Classe MainLobe
+// Classe pour calcul du lobe principal
+// Les valeurs du lobe sont calcules dans des pixels
+// disposes sur "nc" couches avec pavage hexagonal autour de Teta=0, Phi=0
+// Le lobe est gaussien, de sigma = "sig" - Les couches sont construites 
+// toutes les "dels" * sigma 
+// NPix() renvoie le nombre total de pixels du lobe 
+// SetDirection() permet d orienter le lobe dans la direction "teta, phi"
+// Value() renvoie la valeur du lobe, ainsi que les teta,phi du pixel "kpx"
+// Convol() renvoie la valeur lobe convolue avec le ciel (sphere) "sph"
+
+class MainLobe {
+public:
+			MainLobe(float sig, float dels=0.5, int nc=3);
+			~MainLobe();
+        inline int      NPix() {return mNpix; }            
+        inline float    Sigma() {return mSigma; }            
+        inline double   Integral() {return mTotVal; }            
+               void     SetDirection(float teta, float phi);
+	       double   Value(int kpx, float& teta, float& phi);
+               double   Convol(SphericalMap<double>& sph);
+        friend ostream& operator << (ostream& s, MainLobe const& lob);
+	inline void     Print() { cout << (*this); } 
+
+float mSigma, mDels;
+int mNpix, mNC;
+double mTotVal;
+float mDirTet, mDirPhi;
+float* mT0; 
+float* mP0; 
+float* mTC; 
+float* mPC; 
+float* mDx;
+float* mDy;
+float* mDr;
+double* mVal;
+};
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/objlist.list
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/objlist.list	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/objlist.list	(revision 752)
@@ -0,0 +1,14 @@
+bruit.o
+circle.o
+gorfph.o
+localmap.o
+longlat.o
+mlobe.o
+sambainit.o
+scan.o
+spheregorski.o
+spherepos.o
+spherethetaphi.o
+unitvector.o
+utilgeom.o
+vector3d.o
Index: /tags/V_Fev00/SophyaLib/Samba/pixelmap.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/pixelmap.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/pixelmap.h	(revision 752)
@@ -0,0 +1,138 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef PIXELMAP_SEEN
+#define PIXELMAP_SEEN
+
+#include "ppersist.h" 
+#include "dvlist.h"
+#include "spherepos.h"
+#include <iostream.h>
+
+//! General map of pixels on part of sphere or whole sphere
+/*! Class hierarchy :
+\verbatim
+   PixelMap
+     SphericalMap
+         SphereThetaPhi
+         SphereGorski
+         SphereIco
+      LocalMap
+\endverbatim
+*/
+template<class T>
+class PixelMap  : public AnyDataObj 
+{
+
+public:
+  
+              PixelMap(SphereCoordSys* cs = NULL) : mInfo_(NULL) 
+                    { if (cs) cs_ = cs; else cs_ = new SphereCoordSys; }
+virtual       ~PixelMap() 
+                    { if (mInfo_) delete mInfo_; if (cs_) delete cs_; }
+
+// Set/Change/Get the coordinate system
+virtual void  SetCoordSys(SphereCoordSys* cs)
+                    { if (cs) { delete cs_;  cs_ = cs; } }
+inline SphereCoordSys* GetCoordSys() const { return(cs_); }
+
+/*! Number of pixels */
+virtual int_4 NbPixels() const=0;
+   
+/*! Value of pixel number k */
+virtual T& PixVal(int_4 k)=0;
+virtual T const& PixVal(int_4 k) const=0;
+
+// Map s coverage
+virtual bool ContainsSph(double theta, double phi) const=0;
+virtual bool Contains(const SpherePosition& spos) const;
+
+/*! Index of pixel at (theta,phi) */
+virtual int_4 PixIndexSph(double theta, double phi) const=0;
+// Index of pixel at a sky-position 
+virtual int_4 PixIndex(const SpherePosition& spos);
+
+/*! Value of pixel number at (theta,phi) */
+virtual T& PixValSph(double theta, double phi)
+                           {return PixVal(PixIndexSph(theta,phi));}
+virtual T const& PixValSph(double theta, double phi) const
+                           {return PixVal(PixIndexSph(theta,phi));}
+
+/*! Spherical coordinates of center of pixel number k */
+virtual void PixThetaPhi(int_4 k, double& theta, double& phi) const=0;
+
+/*! provides a integer characterizing the pixelization refinement 
+ (depending of the type of the map) 
+*/             
+virtual int_4 SizeIndex() const=0;
+virtual char* TypeOfMap() const =0;
+
+/*! Pixel  (steradians) */
+virtual double PixSolAngle(int_4 k) const =0; 
+
+/*! Setting blockdata to temporary (see ndatablock documentation) */
+virtual void SetTemp(bool temp=false) const =0;
+
+
+/*! Overloading of () to access pixel number k. */
+inline T& operator()(int_4 k) {return(PixVal(k));}
+inline T const& operator()(int_4 k) const {return(PixVal(k));}
+
+// Overloading of () to access pixel at a sky position .
+inline T& operator()(const SpherePosition& spos) 
+                     { return(PixVal(PixIndex(spos))); }
+inline T const& operator()(const SpherePosition& spos) const 
+                     { return(PixVal(PixIndex(spos))); }
+
+
+// Note : no overloading of (double,double) to access pixel (theta,phi).
+// overloading of (double,double) in SphericalMap
+// overloading of (int,int)     in CartesianMap
+
+/*! Setting pixel values to a constant */
+virtual T SetPixels(T v);
+inline T operator = (T v) { return(SetPixels(v)); }
+
+
+                     
+//++
+DVList& Info()
+//
+// Renvoie une reference sur l''objet DVList Associe
+//--
+  {
+    if (mInfo_ == NULL)  mInfo_ = new DVList;
+    return(*mInfo_);
+  }
+
+const DVList*  ptrInfo() const
+  {
+    return mInfo_;
+  }
+
+protected :
+    SphereCoordSys *cs_;   // Coordinate system used in the map
+    DVList* mInfo_;        // Infos (variables) attachees 
+};
+
+
+template <class T>
+int_4 PixelMap<T>::PixIndex(const SpherePosition& spos)
+{
+UnitVector v = spos.Transform(*cs_);
+return(PixIndexSph(v.Theta(), v.Phi()));
+}
+
+template <class T>
+bool PixelMap<T>::Contains(const SpherePosition& spos) const
+{
+UnitVector v = spos.Transform(*cs_);
+return(ContainsSph(v.Theta(), v.Phi()));
+}
+template <class T>
+T PixelMap<T>::SetPixels(T v)
+{
+int k;
+for(k=0; k<NbPixels(); k++) PixVal(k) = v;
+return(v);
+}
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/prefcount.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/prefcount.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/prefcount.h	(revision 752)
@@ -0,0 +1,65 @@
+#ifndef PREFCOUNT_H
+#define PREFCOUNT_H
+
+// Classe d'objet avec comptage de référence.
+// Le nombre de référence est incrémenté lors de la création et lors d'un Attach
+// (inutile d'appeler Attach si on crée l'objet).
+// Si on cree l'objet avec isTmp = true, alors le possesseur est temporaire,
+// et en tout cas, possede le PRefCount en lecture seule.
+// Par exemple, une fonction qui retourne un objet de type PRefCounted le créera
+// en mode temporaire. Un constructeur par copie appelé derrière ne dupliquera pas
+// les données.
+// HasTmpOnly retourne true si un objet n'est référencé que de façon temporaire.
+
+#ifdef TRACE_REFCOUNT
+#define DBG_DESTROY cerr << "PRefCounted destroyed" << endl;
+#define DBG_ATTACH  cerr << "PRefCounted attached" << endl;
+#define DBG_DETACH  cerr << "PRefCounted detached" << endl;
+#else
+#define DBG_DESTROY 
+#define DBG_ATTACH
+#define DBG_DETACH
+#endif
+
+
+class PRefCounted {
+public:
+                               PRefCounted(bool isTmp=false) 
+                                                        :refcount(1), tmpcount(isTmp?1:0) {}
+  virtual                      ~PRefCounted()           {DBG_DESTROY}
+  
+  void                         Attach(bool isTemp=false) 
+                                                        {if (isTemp && HasTmpOnly()) tmpcount++;
+                                                         DBG_ATTACH
+                                                         refcount++;}
+  void                         Detach()                 {refcount--;
+                                                         DBG_DETACH
+                                                         if (!refcount) delete this;}
+  
+  int                          RefCount() const         {return refcount;}
+  bool                         HasTmpOnly() const       {return tmpcount == refcount;}
+  
+private:
+  int refcount;
+  int tmpcount;
+};
+
+// Macro pour les constructeurs par copie d'objets référençant des PRefCounted
+// Il faut que le PRefCounted ait une méthode T* Clone(bool isTmp);
+
+template <class refcount>
+void PRefCountCopy(refcount*& dest, refcount const* src, bool isTmp=false) {
+  if (dest) dest->Detach();
+  if (!src) {
+    dest=0;
+  } else if (src->HasTmpOnly()) {
+    dest = const_cast<refcount*>(src);
+    dest->Attach(isTmp);
+  } else {
+    dest = src->Clone(isTmp);
+  }
+}
+
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/Samba/sambainit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/sambainit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/sambainit.cc	(revision 752)
@@ -0,0 +1,45 @@
+// Classe d'initialisation du module Outils++ 
+#include <unistd.h>
+
+#include "sambainit.h"
+#include "ppersist.h"
+#include "objfio.h"
+#include "spherethetaphi.h"
+#include "spheregorski.h"
+#include "spherepos.h"
+
+int SambaInitiator::FgInit = 0;
+
+SambaInitiator::SambaInitiator()
+  : PeidaOutilsInitiator()
+{
+  SambaInitiator::FgInit++;
+  if (SambaInitiator::FgInit > 1)  return;
+
+//   Enregistrement des classes PPersist du modules Outils++
+  
+  PPRegister(FIO_SphereCoordSys);
+
+  PPRegister(FIO_SphereThetaPhi<float>);
+  PPRegister(FIO_SphereThetaPhi<double>);
+  PPRegister(FIO_SphereThetaPhi< complex<float> >);
+  PPRegister(FIO_SphereThetaPhi< complex<double> >);
+
+  PPRegister(FIO_SphereGorski<float>);
+  PPRegister(FIO_SphereGorski<double>);
+  PPRegister(FIO_SphereGorski< complex<float> >);
+  PPRegister(FIO_SphereGorski< complex<double> >);
+
+
+}
+
+SambaInitiator::~SambaInitiator()
+{
+  SambaInitiator::FgInit--;
+}
+
+
+// On met un objet initiator en statique, pour les loaders qui savent 
+// appeler le constructeur des objets statiques   Reza 08/98
+static SambaInitiator s_sambainit_;
+
Index: /tags/V_Fev00/SophyaLib/Samba/sambainit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/sambainit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/sambainit.h	(revision 752)
@@ -0,0 +1,23 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe d'initialiseur du module Outils++
+
+#ifndef SAMBAINIT_H_SEEN
+#define SAMBAINIT_H_SEEN
+
+
+// Classe d''initialisation pour les modules de PEIDA++
+#include "outilsinit.h"
+
+class SambaInitiator : public PeidaOutilsInitiator {
+private:
+  static int FgInit;
+public:
+  			SambaInitiator();
+  virtual		~SambaInitiator();
+};
+
+#undef PeidaInit
+#define PeidaInit() SambaInitiator _sambainitiator_
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/Samba/scan.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/scan.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/scan.cc	(revision 752)
@@ -0,0 +1,442 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "scan.h"
+#include <complex>
+#include "piocmplx.h"
+
+// valeurs de Pi, 2*Pi, etc                                              
+#include "nbmath.h"
+
+
+//
+//++
+// Class	Scan
+//
+// include      scan.h  dvlist.h math.h nbmath.h 
+//
+//    Storage and treatment of data for a scanning of a part of the sky
+//    with a set of given values for parameters (see constructor)
+//--
+//++
+Scan::Scan(float Ouv,float* Omega,float Fech,float T, 
+	   float t0=0., float phi0=0.)
+
+//  
+//    * Ouv      = aperture angle (rad)
+//    * Omega[3] = direction of rotation axis of the satellite (teta,phi)
+//    and rotation velocity (rad/s)
+//    * Fech     = sampling frequency  (Hz)
+//    * T        = total time of data acquistion (s)
+//    * t0       = starting time (s)
+//    * phi0     = offset of antenna (rad)
+//--
+{
+  mInfo_=NULL;
+  // On memorise les arguments d'appel
+  Ouverture_= Ouv;
+  OmegaTeta_= Omega[0];
+  //
+  // je ne comprends pas ce qui se passe ci-apres (GLM)
+  if( (Omega[0]== 0.0) || (Omega[0]==(float)Pi) ) 
+    OmegaPhi_ = Omega[1];
+  else
+    OmegaPhi_ = Omega[1]+(float)Pi/2.;
+  OmegaRad_ = Omega[2];
+  FrequenceEch_  = Fech;
+  TempsFinal_    = T;
+  TempsInitial_  = t0;
+  PhiZero_ = phi0;
+
+  float aux= 0.0;
+  // Nombre total de points
+  aux= (TempsFinal_-TempsInitial_)*FrequenceEch_;
+  NmaxPts_= (int_4)(aux);
+
+  // Nombre total de tours
+  aux= OmegaRad_*(TempsFinal_-TempsInitial_)/(2.*Pi);
+  NmaxTrs_= (int_4)(aux);
+
+  // Nombre de points par tour
+  aux= 2.*Pi*FrequenceEch_/OmegaRad_;
+  NPts1Tr_= (int_4)(aux);
+
+  // Creation et initialisation du vecteur des mesures aux points
+  //  sPix_ = new r_8[NmaxPts_];
+  sPix_.ReSize(NmaxPts_);
+  sPix_.Reset();
+  //  for( int_4 i=0; i<NmaxPts_; i++ )  sPix_[i]= 0.;
+    for( int_4 i=0; i<NmaxPts_; i++ )  sPix_(i)= 0.;
+
+  // matrice de passage du systeme lie au satellite au systeme fixe
+
+  Rota_[0]=  cos((double)OmegaPhi_);
+  Rota_[1]= -sin((double)OmegaPhi_)*cos((double)OmegaTeta_);
+  Rota_[2]=  sin((double)OmegaPhi_)*sin((double)OmegaTeta_);
+  Rota_[3]=  sin((double)OmegaPhi_);
+  Rota_[4]=  cos((double)OmegaPhi_)*cos((double)OmegaTeta_);
+  Rota_[5]= -cos((double)OmegaPhi_)*sin((double)OmegaTeta_);
+  Rota_[6]=  0.0;
+  Rota_[7]=  sin((double)OmegaTeta_);
+  Rota_[8]=  cos((double)OmegaTeta_);
+
+
+  // printf("%f  %f  %f \n",Rota_[0],Rota_[1],Rota_[2]);
+  // printf("%f  %f  %f \n",Rota_[3],Rota_[4],Rota_[5]);
+  // printf("%f  %f  %f \n",Rota_[6],Rota_[7],Rota_[8]);
+
+}
+
+
+//++
+Scan::Scan(const Scan& s,  bool share) :  sPix_(s.sPix_ , share)
+
+//    copy  constructor
+//--
+{
+  NmaxPts_      = s.NmaxPts_;
+  Ouverture_    = s.Ouverture_;
+  OmegaTeta_    = s.OmegaTeta_;
+  OmegaPhi_     = s.OmegaPhi_;
+  OmegaRad_     = s.OmegaRad_;
+  FrequenceEch_ = s.FrequenceEch_;
+  TempsFinal_   = s.TempsFinal_;
+  TempsInitial_ = s.TempsInitial_;
+  PhiZero_      = s.PhiZero_;
+  for (int k=0; k<9; k++) Rota_[k]=s. Rota_[k];
+}
+//++
+// Titre	Destructor
+//--
+//++
+Scan::~Scan()
+
+//     
+//--
+{
+  // delete[] sPix_ ;
+}
+
+
+//++
+// Titre	Public Methods
+//--
+
+//++
+int_4 Scan::NbPoints() const
+
+//    Return the number of points in the scan
+//--
+{
+  return(NmaxPts_);
+}
+
+/* --Methode-- */
+//++
+int_4 Scan::NbTours() const
+
+//    Return total nomber of turns
+//--
+{
+  return(NmaxTrs_);
+}
+
+/* --Methode-- */
+//++
+int_4 Scan::NbPts1Tr() const
+
+//    Return  nomber of points for 1 turn
+//--
+{
+  return(NPts1Tr_);
+}
+
+/* --Methode-- */
+//++
+int_4 Scan::ValueIndex(float t) const
+
+//    Return index of pixel associated to time t
+//--
+{
+  int_4 k;
+  float eps= 1.0E-06;
+
+  // verification si t est dans [TempsInitial_,TempsFinal_]
+  if( (t< TempsInitial_) || (t> TempsFinal_) ) {
+    printf("\n ValueIndex:: probleme sur le temps t= %f",t);
+    return(-1);
+  }
+
+  k= (int_4)((t-TempsInitial_)*FrequenceEch_+eps);
+  if ( (k< 0) || (k >= NmaxPts_) ) {
+    printf("\n ValueIndex:: probleme sur l'indice du point k= %d",k); 
+    return(-1);
+  }
+  return(k);
+}
+
+/* --Methode-- */
+//++
+void Scan::Direction(float t, float&  teta , float&  phi)
+
+//    Return  (teta,phi) coordinate of pixel related to time t
+//--
+{
+  r_8 alfa,xs,ys,zs,x,y,z;
+
+  // coordonnees dans le systeme du satellite
+  alfa= OmegaRad_*(t-TempsInitial_)+PhiZero_;
+  xs = sin((double)Ouverture_)*cos(alfa);
+  ys = sin((double)Ouverture_)*sin(alfa);
+  zs = cos((double)Ouverture_);
+
+  // coordonnees dans le systeme fixe
+  x = Rota_[0]*xs+Rota_[1]*ys+Rota_[2]*zs;
+  y = Rota_[3]*xs+Rota_[4]*ys+Rota_[5]*zs;
+  z = Rota_[6]*xs+Rota_[7]*ys+Rota_[8]*zs;
+
+  // angles teta,phi
+  teta = acos(z);
+  phi  = atan2(y,x);
+  if( phi< 0. ) phi= DeuxPi+phi;
+}
+
+/* --Methode-- */
+//++
+void Scan::DirectionIndex(int_4 k, float&  teta, float&  phi)
+
+//    Return  (teta,phi) coordinates of  pixel with index k
+//--
+{
+  float t;
+
+  //recupere le temps associe a l'indice k du pixel
+  t= TempsInitial_+(float)k/FrequenceEch_;
+
+  // angles teta,phi 
+  Direction(t, teta, phi);
+}
+
+static r_8 dummy_pixel = 0;
+/* --Methode-- */
+//++
+r_8 const& Scan::PixelValue(int_4 k) const
+
+//    Retourne la valeur du contenu du pixel d'indice k
+//--
+{
+  if ( (k<0) || (k >=  NmaxPts_) ) {
+    printf("\n ValueIndex::indice du pixel errone k= %d",k); 
+    return(dummy_pixel);
+  }
+  //  return(sPix_[k]);
+  //return(sPix_(k));
+  return *(sPix_.Data()+k);
+}
+//++
+r_8 & Scan::PixelValue(int_4 k) 
+
+//    Retourne la valeur du contenu du pixel d'indice k
+//--
+{
+  if ( (k<0) || (k >=  NmaxPts_) ) {
+    printf("\n ValueIndex::indice du pixel errone k= %d",k); 
+    return(dummy_pixel);
+  }
+  //  return(sPix_[k]);
+  //return(sPix_(k));
+  return *(sPix_.Data()+k);
+}
+
+//void Scan::Clear() {
+//  if (sPix_)  delete[] sPix_;
+//}         
+void Scan::InitNull() {
+  //  sPix_=NULL;
+  //  sPix_.Reset(); pas de reset (pour le cas de share)
+  mInfo_=NULL;
+}         
+Scan&  Scan::operator = (const Scan& s)
+{
+  NmaxPts_      = s.NmaxPts_;
+  Ouverture_    = s.Ouverture_;
+  OmegaTeta_    = s.OmegaTeta_;
+  OmegaPhi_     = s.OmegaPhi_;
+  OmegaRad_     = s.OmegaRad_;
+  FrequenceEch_ = s.FrequenceEch_;
+  TempsFinal_   = s.TempsFinal_;
+  TempsInitial_ = s.TempsInitial_;
+  PhiZero_      = s.PhiZero_;
+  sPix_=s.sPix_;
+  for (int k=0; k<9; k++) Rota_[k]=s. Rota_[k];
+  return *this;
+}
+
+
+//++
+// Titre	Operators
+//--
+//++
+// Links	double&        operator()(int_4 k)
+//--
+//++
+//    fill and/or return value of the pixel with index k
+//--
+
+
+
+
+
+//++
+// Titre	class FIO_Scan
+//    Delegated objects for persitance management
+//--
+
+//*******************************************************************
+// class FIO_Scan
+//  Les objets delegues pour la gestion de persistance 
+//*******************************************************************
+
+//++
+FIO_Scan::FIO_Scan()
+//
+//--
+{
+  dobj= new Scan;
+  ownobj= true;
+}
+//++
+FIO_Scan::FIO_Scan(string const& filename)
+//
+//--
+{
+  dobj= new Scan;
+  ownobj= true;
+  Read(filename);
+}
+//++
+FIO_Scan::FIO_Scan(const Scan& obj)
+//
+//--
+{
+  dobj= new Scan(obj);
+  ownobj= true;
+}
+FIO_Scan::FIO_Scan(Scan* obj)
+{
+  dobj= obj;
+  ownobj= false;
+}
+//++
+FIO_Scan::~FIO_Scan()
+//
+//--
+{
+  if (ownobj && dobj) delete dobj;
+}
+//++
+AnyDataObj* FIO_Scan::DataObj()
+//
+//--
+{
+  return(dobj);
+}
+
+//++
+void FIO_Scan::ReadSelf(PInPersist& is)
+//
+//--
+{
+
+  int_4 NmaxPts, NmaxTrs, NPts1Tr;
+  r_4 Ouverture, OmegaTeta, OmegaPhi, OmegaRad, FrequenceEch; 
+  r_4 TempsFinal,  TempsInitial, PhiZero; 
+  r_8 Rota[9];
+
+  if(dobj == NULL) 
+    {
+      dobj= new Scan;
+    }
+
+  // Pour savoir s'il y avait un DVList Info associe
+  char strg[256];
+  is.GetLine(strg, 255);
+  bool hadinfo= false;
+  if (strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0)  hadinfo = true;
+  if(hadinfo) 
+    {    // Lecture eventuelle du DVList Info
+      is >> dobj->Info(); 
+    }
+
+
+  is.GetI4(NmaxPts);
+  is.GetI4(NmaxTrs);
+  is.GetI4(NPts1Tr);
+  dobj->SetIntParams(NmaxPts,NmaxTrs,NPts1Tr);
+
+  is.GetR4(Ouverture);
+  is.GetR4(OmegaTeta);
+  is.GetR4(OmegaPhi);
+  is.GetR4(OmegaRad);
+  is.GetR4(FrequenceEch);
+  is.GetR4(TempsFinal);
+  is.GetR4(TempsInitial);
+  is.GetR4(PhiZero);
+  is.GetR8s(Rota, 9);
+  dobj->SetFloatParams(Ouverture,OmegaTeta,OmegaPhi,OmegaRad,
+		       FrequenceEch,TempsFinal,TempsInitial,PhiZero,Rota);
+// On lit le DataBlock;
+  FIO_NDataBlock<r_8> fio_nd(&dobj->DataBlock());
+  fio_nd.Read(is);
+}
+//++
+void FIO_Scan::WriteSelf(POutPersist& os) const
+//
+//--
+{
+  r_4 Ouverture, OmegaTeta, OmegaPhi, OmegaRad, FrequenceEch; 
+  r_4 TempsFinal,  TempsInitial, PhiZero; 
+  r_8 Rota[9];
+  char strg[256];
+
+  if(dobj == NULL) 
+    {
+      cout << " FIO_Scan::WriteSelf:: dobj= null " << endl;
+      return;
+    }
+  dobj->GetFloatParams(Ouverture,OmegaTeta,OmegaPhi,OmegaRad,
+		       FrequenceEch,TempsFinal,TempsInitial,PhiZero,Rota);
+  if (dobj->ptrInfo()) 
+    {sprintf(strg, "Scan: Theta=%9f Phi=%9f omega=%9f HasInfo", 
+	     (float)OmegaTeta, (float)OmegaPhi, (float)OmegaRad);
+    os.PutLine(strg);
+    os << dobj->Info();
+    }
+  else 
+    {
+      sprintf(strg, "Scan: Theta=%9f Phi=%9f omega=%9f ", 
+	      (float)OmegaTeta, (float)OmegaPhi, (float)OmegaRad); 
+      os.PutLine(strg);
+    }
+
+  os.PutI4(dobj->NbPoints());
+  os.PutI4(dobj->NbTours());
+  os.PutI4(dobj->NbPts1Tr());
+
+  os.PutR4(Ouverture);
+  os.PutR4(OmegaTeta);
+  os.PutR4(OmegaPhi);
+  os.PutR4(OmegaRad);
+  os.PutR4(FrequenceEch);
+  os.PutR4(TempsFinal);
+  os.PutR4(TempsInitial);
+  os.PutR4(PhiZero);
+  os.PutR8s(Rota, 9);
+
+// On ecrit le dataBlock 
+  FIO_NDataBlock<r_8> fio_nd(&dobj->DataBlock());
+  fio_nd.Write(os);
+
+}
Index: /tags/V_Fev00/SophyaLib/Samba/scan.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/scan.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/scan.h	(revision 752)
@@ -0,0 +1,191 @@
+#ifndef SCAN_H_SEEN
+#define SCAN_H_SEEN
+
+
+// includes PEIDA
+#include "ppersist.h"
+#include <iostream.h>
+#include "dvlist.h"
+#include "ndatablock.h"
+
+class FIO_Scan;
+
+//!   Storage and treatment of data for a scanning of a part of the sky with a set of given values for parameters (see constructor)
+
+class Scan :  public AnyDataObj  {
+    friend class FIO_Scan;
+  public  :
+    /* 
+arguments du constructeur : 
+  . ouverture (radians), 
+  . un tableau de 3 reels (deux angles-en radians- definissant la direction de 
+                      l'axe de rotation du satellite + vitesse de rotation 
+                      en radians/s),
+  . frequence d'echantillonnage (Hz), 
+  . instant final de prise de donnees (s),
+deux arguments optionnels :
+  . instant initial pour la prise de donnees
+  . offset d'antenne en angle phi
+  */
+
+    /*!
+\verbatim
+    * Ouv      = aperture angle (rad)
+    * Omega[3] = direction of rotation axis of the satellite (teta,phi)
+                 and rotation velocity (rad/s)
+    * Fech     = sampling frequency  (Hz)
+    * T        = total time of data acquistion (s)
+    * t0       = starting time (s)
+    * phi0     = offset of antenna (rad)
+\endverbatim
+    */
+Scan(float,float*,float,float,float,float);
+Scan(const Scan&,  bool share=false );
+Scan() { 
+  InitNull();
+}
+~Scan();
+
+// ------------ Persistence handling
+
+//     enum {classId = 0xF003 };
+//int_4                  ClassId() const        { return classId; }
+
+//virtual void           WriteSelf(POutPersist&) const;
+//virtual void           ReadSelf(PInPersist&);
+
+/*!   Return the number of points in the scan */
+int_4     NbPoints() const;
+/*!    Return total nomber of turns */
+int_4     NbTours() const;
+/*!    Return  nomber of points for 1 turn */
+int_4     NbPts1Tr() const; 
+/*!    Return index of pixel associated to time t */
+int_4     ValueIndex(float) const;
+/*!    Return  (teta,phi) coordinate of pixel related to time t */
+void    Direction(float, float& ,float& );
+/*!    Return  (teta,phi) coordinates of  pixel with index k */
+void    DirectionIndex(int_4,float& ,float& );
+/*!    Return value of pixel with index k */
+r_8  & PixelValue(int_4 k) ;
+/*!    const version of previous method */
+r_8 const & PixelValue(int_4 k) const;
+
+/* Surcharge de la parenthese a un indice entier : remplit ou/et renvoie */
+/* la valeur du contenu du pixel d'indice k                              */ 
+  
+  inline  r_8&    operator()(int_4 k)
+                                      { return(PixelValue(k)) ; } ;
+  inline  r_8 const &    operator()(int_4 k) const
+                                      { return(PixelValue(k)) ; } ;
+  Scan& operator = (const Scan& s);
+//++
+DVList&  Info()
+//
+//      Renvoie une reference sur l'objet DVList Associe
+//--
+{  
+if (mInfo_ == NULL)  mInfo_ = new DVList;
+return(*mInfo_);
+}
+
+const DVList*  ptrInfo() const
+  {
+    return mInfo_;
+  }
+
+
+
+
+
+  private :
+    
+    //void          Clear();
+void          InitNull();
+
+/*  Acces to the DataBlock  */
+inline       NDataBlock<r_8>& DataBlock()       {return sPix_;}
+inline const NDataBlock<r_8>& DataBlock() const {return sPix_;}
+
+inline  void  SetIntParams(int_4 NmaxPts, int_4 NmaxTrs, int_4 NPts1Tr)
+  {
+    NmaxPts_=NmaxPts;
+    NmaxTrs_=NmaxTrs;
+    NPts1Tr_=NPts1Tr;
+  }
+ inline void SetFloatParams(r_4 Ouverture, r_4 OmegaTeta, r_4 OmegaPhi, 
+			    r_4 OmegaRad, r_4 FrequenceEch, r_4 TempsFinal, 
+			    r_4 TempsInitial, r_4 PhiZero, r_8* Rota)
+   {
+     Ouverture_    = Ouverture;
+     OmegaTeta_    = OmegaTeta;
+     OmegaPhi_     = OmegaPhi;
+     OmegaRad_     = OmegaRad;
+     FrequenceEch_ = FrequenceEch;
+     TempsFinal_   = TempsFinal;
+     TempsInitial_ = TempsInitial;
+     PhiZero_      = PhiZero;
+     for (int k=0; k<9;k++) Rota_[k]=Rota[k];
+   }
+
+ inline void GetFloatParams(r_4& Ouverture, r_4& OmegaTeta, r_4& OmegaPhi, 
+			    r_4& OmegaRad, r_4& FrequenceEch, r_4& TempsFinal, 
+			    r_4& TempsInitial, r_4& PhiZero, r_8* Rota) const
+   {
+     Ouverture    = Ouverture_;
+     OmegaTeta    = OmegaTeta_;
+     OmegaPhi     = OmegaPhi_;
+     OmegaRad     = OmegaRad_;
+     FrequenceEch = FrequenceEch_;
+     TempsFinal   = TempsFinal_;
+     TempsInitial = TempsInitial_;
+     PhiZero      = PhiZero_;
+     for (int k=0; k<9;k++) Rota[k]=Rota_[k];
+   }
+
+
+ int_4 NmaxPts_;
+ int_4 NmaxTrs_;
+ int_4 NPts1Tr_;
+ r_4   Ouverture_;
+ r_4   OmegaTeta_;     /* direction de l'axe de rotation du satellite */
+ r_4   OmegaPhi_;      /* (radians)                                   */
+ r_4   OmegaRad_;      /* vitesse de rotation du satellite (radians/s) */
+ r_4   FrequenceEch_;  /* frequence d'echantillonnage (Hz)*/
+ r_4   TempsFinal_;
+ r_4   TempsInitial_;
+ r_4   PhiZero_;           /* Offset antenne (radians)  */
+ NDataBlock<r_8>  sPix_;   /* valeurs contenues dans chaque pixel */ 
+ //r_8*  sPix_;            /* valeurs contenues dans chaque pixel */ 
+ r_8   Rota_[9];       /* matrice de passage : [Xf]=[Rota][Xs] */
+                      /* Xs : coordonnees dans un systeme lie au satellite*/ 
+                      /* Xf : coordonnees dans un repere "fixe"           */ 
+ DVList* mInfo_;        // Infos (variables) attachees 
+};
+
+// ------------- Classe pour la gestion de persistance --
+//!    Delegated objects for persitance management
+
+class FIO_Scan : public PPersist  
+{
+
+public:
+
+FIO_Scan(); 
+FIO_Scan(string const & filename); 
+FIO_Scan(const Scan& obj);
+FIO_Scan(Scan* obj);
+virtual ~FIO_Scan();
+virtual AnyDataObj* DataObj();
+inline operator Scan() {return(*dobj); }
+
+protected :
+
+virtual void ReadSelf(PInPersist&);           
+virtual void WriteSelf(POutPersist&) const;  
+Scan* dobj;
+bool ownobj;
+};
+
+
+#endif /* SCAN_H_SEEN */
Index: /tags/V_Fev00/SophyaLib/Samba/spheregorski.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spheregorski.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spheregorski.cc	(revision 752)
@@ -0,0 +1,1315 @@
+#include "machdefs.h"
+#include <math.h>
+#include <complex>
+
+#include "pexceptions.h"
+#include "spheregorski.h"
+#include "strutil.h"
+
+extern "C" 
+{
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+}
+      
+
+//*******************************************************************
+// Class PIXELS_XY 
+// Construction des tableaux necessaires a la traduction des indices RING en 
+// indices NESTED (ou l'inverse)
+//*******************************************************************
+
+PIXELS_XY::PIXELS_XY()
+{
+  pix2x_.ReSize(1024);
+  pix2x_.Reset();
+  pix2y_.ReSize(1024);
+  pix2y_.Reset();
+  x2pix_.ReSize(128);
+  x2pix_.Reset();
+  y2pix_.ReSize(128);
+  y2pix_.Reset();
+  mk_pix2xy(); 
+  mk_xy2pix(); 
+}
+
+PIXELS_XY& PIXELS_XY::instance()
+{
+  static PIXELS_XY single;
+  return (single);
+}
+
+void PIXELS_XY::mk_pix2xy() 
+{
+  /*
+    ==================================================
+    subroutine mk_pix2xy
+    ==================================================
+    c     constructs the array giving x and y in the face from pixel number
+    c     for the nested (quad-cube like) ordering of pixels
+    c
+    c     the bits corresponding to x and y are interleaved in the pixel number
+    c     one breaks up the pixel number by even and odd bits
+    ==================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+
+  int kpix, jpix, IX, IY, IP, ID;
+  
+  for(kpix = 0; kpix < 1024; kpix++) 
+    {
+      jpix = kpix;
+      IX = 0;
+      IY = 0;
+      IP = 1 ;//  ! bit position (in x and y)
+      while( jpix!=0 )
+	{ // ! go through all the bits
+	  ID=jpix%2;//  ! bit value (in kpix), goes in ix
+	  jpix = jpix/2;
+	  IX = ID*IP+IX;
+      
+	  ID=jpix%2;//  ! bit value (in kpix), goes in iy
+	  jpix = jpix/2;
+	  IY = ID*IP+IY;
+     
+	  IP = 2*IP;//        ! next bit (in x and y)
+	}
+      pix2x_(kpix) = IX;//     ! in 0,31
+      pix2y_(kpix) = IY;//     ! in 0,31
+    }
+}
+
+void PIXELS_XY::mk_xy2pix() 
+{
+  /*
+    =================================================
+    subroutine mk_xy2pix
+    =================================================
+    c     sets the array giving the number of the pixel lying in (x,y)
+    c     x and y are in {1,128}
+    c     the pixel number is in {0,128**2-1}
+    c
+    c     if  i-1 = sum_p=0  b_p * 2^p
+    c     then ix = sum_p=0  b_p * 4^p
+    c          iy = 2*ix
+    c     ix + iy in {0, 128**2 -1}
+    =================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+
+  int K,IP,I,J,ID;
+  for(I = 1; I <= 128; I++) 
+    {
+      J  = I-1;//            !pixel numbers
+      K  = 0;//
+      IP = 1;//
+      truc : if( J==0 ) 
+	{
+	  x2pix_(I-1) = K;
+	  y2pix_(I-1) = 2*K;
+	}
+      else 
+	{
+	  ID = (int)fmod(J,2);
+	  J  = J/2;
+	  K  = IP*ID+K;
+	  IP = IP*4;
+	  goto truc;
+	}
+    }     
+}
+
+//*******************************************************************
+//++ 
+// Class	SphereGorski
+//
+// include      spheregorski.h strutil.h
+//
+//    Pixelisation Gorski  
+//
+//
+//|    -----------------------------------------------------------------------
+//|     version 0.8.2  Aug97 TAC  Eric Hivon, Kris Gorski
+//|    -----------------------------------------------------------------------
+//
+//    the sphere is split in 12 diamond-faces containing nside**2 pixels each
+//
+//    the numbering of the pixels (in the nested scheme) is similar to
+//    quad-cube
+//    In each face the first pixel is in the lowest corner of the diamond
+//
+//    the faces are                    (x,y) coordinate on each face
+//|        .   .   .   .   <--- North Pole
+//|       / \ / \ / \ / \                          ^        ^     
+//|      . 0 . 1 . 2 . 3 . <--- z = 2/3             \      /      
+//|       \ / \ / \ / \ /                        y   \    /  x   
+//|      4 . 5 . 6 . 7 . 4 <--- equator               \  /                     
+//|       / \ / \ / \ / \                              \/        
+//|      . 8 . 9 .10 .11 . <--- z = -2/3              (0,0) : lowest corner  
+//|       \ / \ / \ / \ /                                  
+//|        .   .   .   .   <--- South Pole
+//|
+//    phi:0               2Pi                                 
+//
+//    in the ring scheme pixels are numbered along the parallels
+//    the first parallel is the one closest to the north pole and so on
+//    on each parallel, pixels are numbered starting from the one closest
+//    to phi = 0
+//
+//    nside MUST be a power of 2 (<= 8192)
+//--
+//++
+//
+// Links	Parents
+//
+//    SphericalMap 
+//-- 
+
+/* --Methode-- */
+//++
+// Titre	Constructors
+//--
+//++
+
+template<class T>
+SphereGorski<T>::SphereGorski()
+
+//--
+{
+  InitNul();
+  pixels_.Reset();
+}
+
+//++
+template<class T>
+SphereGorski<T>::SphereGorski(int_4 m)
+
+//    m is the "nside" of the Gorski algorithm
+//
+//    The total number of pixels will be Npix =  12*nside**2
+//
+//    nside MUST be a power of 2 (<= 8192)
+//--
+{
+
+  if(m <= 0 || m > 8192) 
+    {
+      cout << "SphereGorski : m hors bornes [0,8192], m= " << m << endl;
+      throw RangeCheckError("SphereGorski<T>::SphereGorski() - Out of bound nside (< 8192)!");
+    }
+  // verifier que m est une puissance de deux 
+  int x= m;
+  while(x%2 == 0) x/=2;
+  if(x != 1) 
+    {  
+      cout<<"SphereGorski: m doit etre une puissance de deux, m= "<<m<<endl;
+      throw ParmError("SphereGorski<T>::SphereGorski() - nside != 2^n !");
+    }
+  InitNul();
+  Pixelize(m);
+  SetThetaSlices();
+}
+//++
+template<class T>
+SphereGorski<T>::SphereGorski(const SphereGorski<T>& s, bool share)
+  : pixels_(s.pixels_, share)
+//    copy constructor
+//--
+{
+  if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
+
+  nSide_= s.nSide_;
+  nPix_ = s.nPix_;
+  omeg_ = s.omeg_;
+}
+
+//++
+// Titre	Destructor
+//--
+//++
+template<class T>
+SphereGorski<T>::~SphereGorski()
+
+//--
+{
+}
+
+//++
+// Titre	Public Methods
+//--
+
+//++
+template<class T>
+void SphereGorski<T>::Resize(int_4 m)
+
+//    m is the "nside" of the Gorski algorithm
+//
+//    The total number of pixels will be Npix =  12*nside**2
+//
+//    nside MUST be a power of 2 (<= 8192)
+//--
+{
+  if (m<=0 || m> 8192) {
+    cout << "SphereGorski : m hors bornes [0,8192], m= " << m << endl;
+    exit(1);
+  }
+  // verifier que m est une puissance de deux 
+  int x= m;
+  while (x%2==0) x/=2;
+  if(x != 1) 
+    {  
+      cout<<"SphereGorski: m doit etre une puissance de deux, m= "<<m<<endl;
+      exit(1);
+    }
+  InitNul();
+  Pixelize(m);
+  SetThetaSlices();
+}
+
+template<class T>
+void  SphereGorski<T>::Pixelize( int_4 m) 
+
+//    prépare la pixelisation Gorski (m a la même signification 
+//    que pour le constructeur)
+//
+//    
+{
+  // On memorise les arguments d'appel
+  nSide_= m;  
+
+  // Nombre total de pixels sur la sphere entiere
+  nPix_= 12*nSide_*nSide_;
+
+  // pour le moment les tableaux qui suivent seront ranges dans l'ordre 
+  // de l'indexation GORSKY "RING"
+  // on pourra ulterieurement changer de strategie et tirer profit
+  // de la dualite d'indexation GORSKY (RING et NEST) : tout dependra 
+  // de pourquoi c'est faire
+
+  // Creation et initialisation du vecteur des contenus des pixels 
+  pixels_.ReSize(nPix_);
+  pixels_.Reset();
+
+  // solid angle per pixel   
+  omeg_= 4.0*Pi/nPix_;
+}
+
+template<class T>
+void SphereGorski<T>::InitNul()
+//
+//    initialise à zéro les variables de classe 
+{
+  nSide_= 0;
+  nPix_ = 0;
+  omeg_ = 0.;
+//  pixels_.Reset();  -  Il ne faut pas mettre les pixels a zero si share !
+}
+
+/* --Methode-- */
+//++
+template<class T>
+int_4 SphereGorski<T>::NbPixels() const
+
+//    Retourne le nombre de pixels du découpage
+//--
+{  
+  return(nPix_);
+}
+
+//++
+template<class T>
+uint_4 SphereGorski<T>::NbThetaSlices() const 
+
+//    Return number of slices in theta direction on the  sphere
+//--
+{
+  uint_4 nbslices = uint_4(4*nSide_-1);
+  if (nSide_<=0) 
+    {
+      nbslices = 0;
+      throw PException(" sphere not pixelized, NbSlice=0 ");
+    }
+  return nbslices;
+}
+
+//++
+template<class T>
+void SphereGorski<T>::GetThetaSlice(int_4 index, r_8& theta,TVector<r_8>& phi,TVector<T>& value) const 
+
+//    For a theta-slice with index 'index', return : 
+//
+//    the corresponding "theta" 
+//
+//    a vector containing the phi's of the pixels of the slice
+//
+//    a vector containing the corresponding values of pixels 
+//
+//--
+{
+
+  if (index<0 || index >= NbThetaSlices()) 
+    {
+      // THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range")); 
+      cout << " SphereGorski::GetThetaSlice : Pixel index out of range" <<endl;
+      THROW(rangeCheckErr);
+    }
+
+
+  int_4 iring= sliceBeginIndex_(index);
+  int_4 lring  =  sliceLenght_(index);
+
+
+  phi.ReSize(lring);
+  value.ReSize(lring);
+  double TH= 0.;
+  double FI= 0.;
+  for(int_4 kk = 0; kk < lring;kk++) 
+    {
+      PixThetaPhi(kk+iring,TH,FI);
+      phi(kk)= FI;
+      value(kk)= PixVal(kk+iring);
+    }
+  theta= TH;
+}
+//++
+//++
+
+template<class T>
+void SphereGorski<T>::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const 
+
+//    For a theta-slice with index 'sliceIndex', return : 
+//
+//    the corresponding "theta" 
+//    the corresponding "phi" for first pixel of the slice 
+//
+//    a vector containing the indices of the pixels of the slice
+//    (equally distributed in phi)
+//
+//    a vector containing the corresponding values of pixels 
+//
+//--
+{
+
+  if (sliceIndex<0 || sliceIndex >= NbThetaSlices()) 
+    {
+      // THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range")); 
+      cout << " SphereGorski::GetThetaSlice : Pixel index out of range" <<endl;
+      THROW(rangeCheckErr);
+    }
+
+  int_4 iring= sliceBeginIndex_(sliceIndex);
+  int_4 lring  =  sliceLenght_(sliceIndex);
+  pixelIndices.ReSize(lring);
+  value.ReSize(lring);
+  for(int_4 kk = 0; kk < lring;kk++) 
+    {
+      pixelIndices(kk)= kk+iring;
+      value(kk)= PixVal(kk+iring);
+    }
+  PixThetaPhi(iring, theta, phi0);
+}
+//++
+template<class T>
+void SphereGorski<T>::SetThetaSlices()  
+
+//--
+{
+  sliceBeginIndex_.ReSize(4*nSide_-1);
+  sliceLenght_.ReSize(4*nSide_-1);
+  for (int sliceIndex=0; sliceIndex<  nSide_-1; sliceIndex++)
+    {
+      sliceBeginIndex_(sliceIndex)  = 2*sliceIndex*(sliceIndex+1);
+      sliceLenght_(sliceIndex) = 4*(sliceIndex+1);
+    }
+  for (int sliceIndex= nSide_-1; sliceIndex<  3*nSide_; sliceIndex++)
+    {
+      sliceBeginIndex_(sliceIndex)  = 2*nSide_*(2*sliceIndex-nSide_+1);
+      sliceLenght_(sliceIndex) = 4*nSide_;
+    }
+  for (int sliceIndex= 3*nSide_; sliceIndex< 4*nSide_-1; sliceIndex++)
+    {
+      int_4 nc= 4*nSide_-1-sliceIndex;
+      sliceBeginIndex_(sliceIndex)  = nPix_-2*nc*(nc+1); 
+      sliceLenght_(sliceIndex) = 4*nc;
+    }
+}
+
+/* --Methode-- */
+//++
+template<class T>
+T& SphereGorski<T>::PixVal(int_4 k)
+
+//    Return value of  pixel with "RING" index k 
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    {
+      // THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range")); 
+      cout << " SphereGorski::PIxVal : exception  a mettre en place, k= " << k <<endl;
+      THROW(rangeCheckErr);
+    }
+  return pixels_(k);
+}
+
+/* --Methode-- */
+//++
+template<class T>
+T const& SphereGorski<T>::PixVal(int_4 k) const
+
+//    Return value of  pixel with "RING" index k 
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    {
+      //THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range")); 
+      cout << " SphereGorski::PIxVal : exception  a mettre en place, k= " << k <<endl;
+      THROW(rangeCheckErr);
+    }
+  return *(pixels_.Data()+k);
+}
+
+//++
+template<class T>
+T& SphereGorski<T>::PixValNest(int_4 k)
+
+//    Return value of  pixel with "NESTED" index k 
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    { 
+      //THROW(out_of_range("SphereGorski::PIxValNest Pixel index out of range")); 
+      cout<<" SphereGorski::PIxValNest : exceptions a mettre en place" <<endl;
+      THROW(rangeCheckErr);
+    }
+  return pixels_(nest2ring(nSide_,k));
+}
+//++
+
+template<class T>
+T const& SphereGorski<T>::PixValNest(int_4 k) const
+
+//    Return value of  pixel with "NESTED" index k 
+//--
+{
+  if((k < 0) || (k >= nPix_)) 
+    { 
+      //THROW(out_of_range("SphereGorski::PIxValNest Pixel index out of range")); 
+      cout<<" SphereGorski::PIxValNest : exceptions a mettre en place" <<endl;
+      THROW(rangeCheckErr);
+  }
+  int_4 pix= nest2ring(nSide_,k);
+  return *(pixels_.Data()+pix);
+}
+
+/* --Methode-- */
+//++
+template<class T>
+bool SphereGorski<T>::ContainsSph(double /*theta*/, double /*phi*/) const
+//--
+{
+return(true);
+}
+
+/* --Methode-- */
+//++
+template<class T>
+int_4 SphereGorski<T>::PixIndexSph(double theta,double phi) const
+
+//    Return "RING" index of the pixel corresponding to 
+//    direction (theta, phi).
+//--
+{
+  return ang2pix_ring(nSide_,theta,phi);
+}
+
+//++
+template<class T>
+int_4 SphereGorski<T>::PixIndexSphNest(double theta,double  phi) const
+
+//    Return "NESTED" index of the pixel corresponding to 
+//    direction (theta, phi).
+//--
+{
+  return ang2pix_nest(nSide_,theta,phi);
+}
+
+
+/* --Methode-- */
+//++
+template<class T>
+void SphereGorski<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
+
+//   Return (theta,phi) coordinates of middle of  pixel with "RING" index k
+//--
+{
+  pix2ang_ring(nSide_,k,theta,phi);
+}
+
+template <class T>
+T SphereGorski<T>::SetPixels(T v)
+{
+pixels_.Reset(v);
+return(v);
+}
+
+//++
+template<class T>
+double SphereGorski<T>::PixSolAngle(int_4 /*dummy*/) const
+//    Pixel Solid angle  (steradians)
+//    All the pixels have the same solid angle. The dummy argument is
+//    for compatibility with eventual pixelizations which would not 
+//    fulfil this requirement.
+//--
+{
+  return omeg_;
+}
+
+//++
+template<class T>
+void SphereGorski<T>::PixThetaPhiNest(int_4 k,double& theta,double& phi) const
+
+//   Return (theta,phi) coordinates of middle of  pixel with "NESTED" index k
+//--
+{   
+  pix2ang_nest(nSide_,k,theta,phi);
+}
+
+//++
+template<class T>
+int_4 SphereGorski<T>::NestToRing(int_4 k) const
+
+//    translation from NESTED index  into RING index 
+//
+//--
+{
+  return  nest2ring(nSide_,k);
+}
+
+//++
+template<class T>
+int_4 SphereGorski<T>::RingToNest(int_4 k) const
+//
+//    translation from  RING index  into NESTED index 
+//
+//--
+{
+  return  ring2nest(nSide_,k);
+}
+
+
+template<class T>
+int_4 SphereGorski<T>::nest2ring(int_4 nside, int_4 ipnest) const 
+{
+  /*
+    ====================================================
+    subroutine nest2ring(nside, ipnest, ipring)
+    ====================================================
+    c     conversion from NESTED to RING pixel number
+    ====================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+  
+  const PIXELS_XY& PXY= PIXELS_XY::instance();
+
+  int npix, npface, face_num, ncap, n_before;
+  int ipf, ip_low, ip_trunc, ip_med, ip_hi;
+  int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4;
+  int ns_max=8192;
+  int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};
+  int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};
+  
+  if(  nside<1 ||  nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+  npix = 12 *  nside* nside;
+  if( ipnest<0 || ipnest>npix-1 ) {
+    cout << "ipnest out of range" << endl;
+    exit(0);
+  }
+
+  ncap  = 2* nside*( nside-1);// ! number of points in the North Polar cap
+  nl4   = 4* nside;
+  
+  //c     finds the face, and the number in the face
+  npface =  nside* nside;
+  //cccccc      ip = ipnest - 1         ! in {0,npix-1}
+  
+  face_num = ipnest/npface;//  ! face number in {0,11}
+  ipf =ipnest%npface;//  ! pixel number in the face {0,npface-1}
+  //c     finds the x,y on the face (starting from the lowest corner)
+  //c     from the pixel number
+  ip_low=ipf%1024;                //   ! content of the last 10 bits
+  ip_trunc =   ipf/1024;         //    ! truncation of the last 10 bits
+  ip_med=ip_trunc%1024;         //     ! content of the next 10 bits
+  ip_hi  =     ip_trunc/1024;//   ! content of the high weight 10 bits
+  
+  ix = 1024*PXY.pix2x_(ip_hi)+32*PXY.pix2x_(ip_med)+PXY.pix2x_(ip_low);
+  iy = 1024*PXY.pix2y_(ip_hi)+32*PXY.pix2y_(ip_med)+PXY.pix2y_(ip_low);
+  
+  //c     transforms this in (horizontal, vertical) coordinates
+  jrt = ix + iy;//  ! 'vertical' in {0,2*(nside-1)}
+  jpt = ix - iy;//  ! 'horizontal' in {-nside+1,nside-1}
+  
+  //c     computes the z coordinate on the sphere
+  //      jr =  jrll[face_num+1]*nside - jrt - 1;//   ! ring number in {1,4*nside-1}
+  jr =  jrll[face_num]*nside - jrt - 1;
+  nr = nside;//                  ! equatorial region (the most frequent)
+  n_before = ncap + nl4 * (jr - nside);
+  kshift=(jr - nside)%2;
+  if( jr<nside ) {//then     ! north pole region
+    nr = jr;
+    n_before = 2 * nr * (nr - 1);
+    kshift = 0;
+  }
+  else if( jr>3*nside ) {//then ! south pole region
+    nr = nl4 - jr;
+    n_before = npix - 2 * (nr + 1) * nr;
+    kshift = 0;
+  }
+  
+  //c     computes the phi coordinate on the sphere, in [0,2Pi]
+  jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2;//  ! 'phi' number in the ring in {1,4*nr}
+  
+  if( jp>nl4 ) jp = jp - nl4;
+  if( jp<1 )   jp = jp + nl4;
+  
+  int aux=n_before + jp - 1;
+  return (n_before + jp - 1);// ! in {0, npix-1}
+}
+
+template<class T>
+int_4 SphereGorski<T>::ring2nest(int_4 nside, int_4 ipring) const 
+{
+  /*
+    ==================================================
+    subroutine ring2nest(nside, ipring, ipnest)
+    ==================================================
+    c     conversion from RING to NESTED pixel number
+    ==================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+
+  const PIXELS_XY& PXY= PIXELS_XY::instance();
+
+  double fihip, hip;
+  int npix, nl2, nl4, ncap, ip, iphi, ipt, ipring1;
+  int     kshift, face_num, nr;
+  int irn, ire, irm, irs, irt, ifm , ifp;
+  int ix, iy, ix_low, ix_hi, iy_low, iy_hi, ipf;
+  int ns_max(8192);
+  
+  // coordinate of the lowest corner of each face
+  int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};// ! in unit of nside
+  int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};//! in unit of nside/2
+  
+  if( nside<1 || nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+  npix = 12 * nside*nside;
+  if( ipring<0 || ipring>npix-1 ) {
+    cout << "ipring out of range" << endl;
+    exit(0);
+  }
+  
+  nl2 = 2*nside;
+  nl4 = 4*nside;
+  npix = 12*nside*nside;//      ! total number of points
+  ncap = 2*nside*(nside-1);// ! points in each polar cap, =0 for nside =1
+  ipring1 = ipring + 1;
+  
+  //c     finds the ring number, the position of the ring and the face number
+  if( ipring1<=ncap ) {//then
+    
+    hip   = ipring1/2.;
+    fihip = floor ( hip );
+    irn   = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from North pole
+    iphi  = ipring1 - 2*irn*(irn - 1);
+    
+    kshift = 0;
+    nr = irn   ;//               ! 1/4 of the number of points on the current ring
+    face_num = (iphi-1) / irn;// ! in {0,3}
+  }
+  else if( ipring1<=nl2*(5*nside+1) ) {//then
+    
+    ip    = ipring1 - ncap - 1;
+    irn   = (int)floor( ip / nl4 ) + nside;//               ! counted from North pole
+    iphi  = (int)fmod(ip,nl4) + 1;
+    
+    kshift  = (int)fmod(irn+nside,2);//  ! 1 if irn+nside is odd, 0 otherwise
+    nr = nside;
+    ire =  irn - nside + 1;// ! in {1, 2*nside +1}
+    irm =  nl2 + 2 - ire;
+    ifm = (iphi - ire/2 + nside -1) / nside;// ! face boundary
+    ifp = (iphi - irm/2 + nside -1) / nside;
+    if( ifp==ifm ) {//then          ! faces 4 to 7
+      face_num = (int)fmod(ifp,4) + 4;
+    }
+    else if( ifp + 1==ifm ) {//then ! (half-)faces 0 to 3
+      face_num = ifp;
+    }
+    else if( ifp - 1==ifm ) {//then ! (half-)faces 8 to 11
+      face_num = ifp + 7;
+    }
+  }
+  else {
+    
+    ip    = npix - ipring1 + 1;
+    hip   = ip/2.;
+    fihip = floor ( hip );
+    irs   = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;//  ! counted from South pole
+    iphi  = 4*irs + 1 - (ip - 2*irs*(irs-1));
+    
+    kshift = 0;
+    nr = irs;
+    irn   = nl4 - irs;
+    face_num = (iphi-1) / irs + 8;// ! in {8,11}
+  }
+  
+  //c     finds the (x,y) on the face
+  irt =   irn  - jrll[face_num]*nside + 1;//       ! in {-nside+1,0}
+  ipt = 2*iphi - jpll[face_num]*nr - kshift - 1;// ! in {-nside+1,nside-1}
+
+
+  if( ipt>=nl2 ) ipt = ipt - 8*nside;// ! for the face #4
+  
+  ix =  (ipt - irt ) / 2;
+  iy = -(ipt + irt ) / 2;
+  
+  ix_low = (int)fmod(ix,128);
+  ix_hi  = ix/128;
+  iy_low = (int)fmod(iy,128);
+  iy_hi  = iy/128;
+  ipf=(PXY.x2pix_(ix_hi)+PXY.y2pix_(iy_hi))*(128*128)+(PXY.x2pix_(ix_low)+PXY.y2pix_(iy_low));
+
+  return (ipf + face_num* nside *nside);//   ! in {0, 12*nside**2 - 1}
+}
+
+template<class T>
+int_4 SphereGorski<T>::ang2pix_ring(int_4 nside, double theta, double phi) const 
+{
+  /*
+    ==================================================
+    c     gives the pixel number ipix (RING) 
+    c     corresponding to angles theta and phi
+    c==================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+
+  int nl2, nl4, ncap, npix, jp, jm, ipix1;
+  double  z, za, tt, tp, tmp;
+  int ir, ip, kshift;
+
+  double piover2(Pi/2.);
+  double twopi(2.*Pi);
+  double z0(2./3.);
+  int ns_max(8192);
+
+  if( nside<1 || nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+
+  if( theta<0. || theta>Pi) {
+    cout << "theta out of range" << endl;
+    exit(0);
+  }
+
+  z = cos(theta);
+  za = fabs(z);
+  if( phi >= twopi)  phi = phi - twopi;
+  if (phi < 0.)     phi = phi + twopi;
+  tt = phi / piover2;//  ! in [0,4)
+
+  nl2 = 2*nside;
+  nl4 = 4*nside;
+  ncap  = nl2*(nside-1);// ! number of pixels in the north polar cap
+  npix  = 12*nside*nside;
+
+  if( za <= z0 ) {
+    
+    jp = (int)floor(nside*(0.5 + tt - z*0.75));// ! index of  ascending edge line 
+    jm = (int)floor(nside*(0.5 + tt + z*0.75));// ! index of descending edge line
+
+    ir = nside + 1 + jp - jm;// ! in {1,2n+1} (ring number counted from z=2/3)
+    kshift = 0;
+    if (fmod(ir,2)==0.) kshift = 1;// ! kshift=1 if ir even, 0 otherwise
+    
+    ip = (int)floor( ( jp+jm - nside + kshift + 1 ) / 2 ) + 1;// ! in {1,4n}
+    if( ip>nl4 ) ip = ip - nl4;
+    
+    ipix1 = ncap + nl4*(ir-1) + ip ;
+  }
+  else {
+
+    tp = tt - floor(tt);//      !MOD(tt,1.d0)
+    tmp = sqrt( 3.*(1. - za) );
+
+    jp = (int)floor( nside * tp * tmp );// ! increasing edge line index
+    jm = (int)floor( nside * (1. - tp) * tmp );// ! decreasing edge line index
+
+    ir = jp + jm + 1;//        ! ring number counted from the closest pole
+    ip = (int)floor( tt * ir ) + 1;// ! in {1,4*ir}
+    if( ip>4*ir ) ip = ip - 4*ir;
+      
+    ipix1 = 2*ir*(ir-1) + ip;
+      if( z<=0. ) {
+	ipix1 = npix - 2*ir*(ir+1) + ip;
+      }
+  }
+    return (ipix1 - 1);// ! in {0, npix-1}
+}
+
+template<class T>
+int_4 SphereGorski<T>::ang2pix_nest(int_4 nside, double theta, double phi) const 
+{
+  /*
+    ==================================================
+    subroutine ang2pix_nest(nside, theta, phi, ipix)
+    ==================================================
+    c     gives the pixel number ipix (NESTED) 
+    c     corresponding to angles theta and phi
+    c
+    c     the computation is made to the highest resolution available (nside=8192)
+    c     and then degraded to that required (by integer division)
+    c     this doesn't cost more, and it makes sure 
+    c     that the treatement of round-off will be consistent 
+    c     for every resolution
+    ==================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+  
+  const PIXELS_XY& PXY= PIXELS_XY::instance();
+
+  double    z, za, z0, tt, tp, tmp;
+  int face_num,jp,jm;
+  int ifp, ifm;
+  int  ix, iy, ix_low, ix_hi, iy_low, iy_hi, ipf, ntt;
+  double piover2(Pi/2.), twopi(2.*Pi);
+  int ns_max(8192);
+  
+  if( nside<1 || nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+  if( theta<0 || theta>Pi ) {
+    cout << "theta out of range" << endl;
+    exit(0);
+  }
+  z  = cos(theta);
+  za = fabs(z);
+  z0 = 2./3.;
+  if( phi>=twopi ) phi = phi - twopi;
+  if( phi<0. )    phi = phi + twopi;
+  tt = phi / piover2;// ! in [0,4[
+  if( za<=z0 ) { // then ! equatorial region
+    
+    //(the index of edge lines increase when the longitude=phi goes up)
+    jp = (int)floor(ns_max*(0.5 + tt - z*0.75));// !  ascending edge line index
+    jm = (int)floor(ns_max*(0.5 + tt + z*0.75));// ! descending edge line index
+    
+    //c        finds the face
+    ifp = jp / ns_max;//  ! in {0,4}
+    ifm = jm / ns_max;
+    if( ifp==ifm ) face_num = (int)fmod(ifp,4) + 4; //then  ! faces 4 to 7
+    else if( ifp<ifm ) face_num = (int)fmod(ifp,4); // (half-)faces 0 to 3
+    else face_num = (int)fmod(ifm,4) + 8;//! (half-)faces 8 to 11
+    
+    ix = (int)fmod(jm, ns_max);
+    iy = ns_max - (int)fmod(jp, ns_max) - 1;
+  }
+  else { //! polar region, za > 2/3
+    
+    ntt = (int)floor(tt);
+    if( ntt>=4 ) ntt = 3;
+    tp = tt - ntt;
+    tmp = sqrt( 3.*(1. - za) );//  ! in ]0,1]
+    
+    //(the index of edge lines increase when distance from the closest pole goes up)
+    jp = (int)floor(ns_max*tp*tmp); // ! line going toward the pole as phi increases
+    jm = (int)floor(ns_max*(1.-tp)*tmp); // ! that one goes away of the closest pole
+    jp = (int)min(ns_max-1, jp);// ! for points too close to the boundary
+    jm = (int)min(ns_max-1, jm);
+    
+    // finds the face and pixel's (x,y)
+    if( z>=0 ) {
+      face_num = ntt;//  ! in {0,3}
+      ix = ns_max - jm - 1;
+      iy = ns_max - jp - 1;
+    }
+    else {
+      face_num = ntt + 8;// ! in {8,11}
+      ix =  jp;
+      iy =  jm;
+    }
+  }
+  
+  ix_low = (int)fmod(ix,128);
+  ix_hi  =     ix/128;
+  iy_low = (int)fmod(iy,128);
+  iy_hi  =     iy/128;
+  ipf= (PXY.x2pix_(ix_hi)+PXY.y2pix_(iy_hi))*(128*128)+(PXY.x2pix_(ix_low)+PXY.y2pix_(iy_low));
+  //  ipf = ipf / pow(ns_max/nside,2.);//  ! in {0, nside**2 - 1}
+  //  return ( ipf + face_num*pow(nside,2));//    ! in {0, 12*nside**2 - 1}
+  // $CHECK$  Reza 25/10/99 , pow remplace par *
+  ipf = ipf / ((ns_max/nside)*(ns_max/nside));
+  return (ipf + face_num*nside*nside);
+}
+
+template<class T>
+void SphereGorski<T>::pix2ang_ring(int_4 nside,int_4 ipix,double& theta,double& phi) const {
+  /*
+    ===================================================
+    c     gives theta and phi corresponding to pixel ipix (RING) 
+    c     for a parameter nside
+    ===================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+  
+  int nl2, nl4, npix, ncap, iring, iphi, ip, ipix1;
+  double  fact1, fact2, fodd, hip, fihip;
+  
+  int ns_max(8192);
+  
+  if( nside<1 || nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+  npix = 12*nside*nside;      // ! total number of points
+  if( ipix<0 || ipix>npix-1 ) {
+    cout << "ipix out of range" << endl;
+    exit(0);
+  }
+  
+  ipix1 = ipix + 1; // in {1, npix}
+  nl2 = 2*nside;
+  nl4 = 4*nside;
+  ncap = 2*nside*(nside-1);// ! points in each polar cap, =0 for nside =1
+  fact1 = 1.5*nside;
+  fact2 = 3.0*nside*nside;
+  
+  if( ipix1 <= ncap ) {  //! North Polar cap -------------
+    
+    hip   = ipix1/2.;
+    fihip = floor(hip);
+    iring = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from North pole
+    iphi  = ipix1 - 2*iring*(iring - 1);
+    
+    theta = acos( 1. - iring*iring / fact2 );
+    phi   = ((double)iphi - 0.5) * Pi/(2.*iring);
+    //    cout << theta << " " << phi << endl;
+  }
+  else if( ipix1 <= nl2*(5*nside+1) ) {//then ! Equatorial region ------
+    
+    ip    = ipix1 - ncap - 1;
+    iring = (int)floor( ip / nl4 ) + nside;// ! counted from North pole
+    iphi  = ip%nl4 + 1;
+    
+    fodd  = 0.5 * (1 + (iring+nside)%2 );//  ! 1 if iring+nside is odd, 1/2 otherwise
+    theta = acos( (nl2 - iring) / fact1 );
+    phi   = ((double)iphi - fodd) * Pi /(2.*nside);
+  }
+  else {//! South Polar cap -----------------------------------
+    
+    ip    = npix - ipix1 + 1;
+    hip   = ip/2.;
+    fihip = floor(hip);
+    iring = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;//     ! counted from South pole
+    iphi  = (int)(4.*iring + 1 - (ip - 2.*iring*(iring-1)));
+    
+    theta = acos( -1. + iring*iring / fact2 );
+    phi   = ((double)iphi - 0.5) * Pi/(2.*iring);
+    //    cout << theta << " " << phi << endl;
+  }
+}
+
+template<class T>
+void SphereGorski<T>::pix2ang_nest(int_4 nside,int_4 ipix,double& theta,double& phi) const {
+  /*
+    ==================================================
+    subroutine pix2ang_nest(nside, ipix, theta, phi)
+    ==================================================
+    c     gives theta and phi corresponding to pixel ipix (NESTED) 
+    c     for a parameter nside
+    ==================================================
+  */
+  // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
+  //  (16/12/98)
+
+  const PIXELS_XY& PXY= PIXELS_XY::instance();
+    
+  int npix, npface, face_num;
+  int ipf, ip_low, ip_trunc, ip_med, ip_hi;
+  int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4;
+  double z, fn, fact1, fact2;
+  double piover2(Pi/2.);
+  int ns_max(8192);
+          
+  // ! coordinate of the lowest corner of each face
+  int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};//! in unit of nside
+  int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};// ! in unit of nside/2
+  
+  if( nside<1 || nside>ns_max ) {
+    cout << "nside out of range" << endl;
+    exit(0);
+  }
+  npix = 12 * nside*nside;
+  if( ipix<0 || ipix>npix-1 ) {
+    cout << "ipix out of range" << endl;
+    exit(0);
+  }
+  
+  fn = 1.*nside;
+  fact1 = 1./(3.*fn*fn);
+  fact2 = 2./(3.*fn);
+  nl4   = 4*nside;
+
+  //c     finds the face, and the number in the face
+  npface = nside*nside;
+  
+  face_num = ipix/npface;//  ! face number in {0,11}
+  ipf = (int)fmod(ipix,npface);//  ! pixel number in the face {0,npface-1}
+  
+  //c     finds the x,y on the face (starting from the lowest corner)
+  //c     from the pixel number
+  ip_low = (int)fmod(ipf,1024);//       ! content of the last 10 bits
+  ip_trunc =   ipf/1024 ;//       ! truncation of the last 10 bits
+  ip_med = (int)fmod(ip_trunc,1024);//  ! content of the next 10 bits
+  ip_hi  =     ip_trunc/1024   ;//! content of the high weight 10 bits
+  
+  ix = 1024*PXY.pix2x_(ip_hi)+32*PXY.pix2x_(ip_med)+PXY.pix2x_(ip_low);
+  iy = 1024*PXY.pix2y_(ip_hi)+32*PXY.pix2y_(ip_med)+PXY.pix2y_(ip_low);
+  
+  //c     transforms this in (horizontal, vertical) coordinates
+  jrt = ix + iy;//  ! 'vertical' in {0,2*(nside-1)}
+  jpt = ix - iy;//  ! 'horizontal' in {-nside+1,nside-1}
+  
+  //c     computes the z coordinate on the sphere
+  //      jr =  jrll[face_num+1]*nside - jrt - 1;//   ! ring number in {1,4*nside-1}
+  jr =  jrll[face_num]*nside - jrt - 1;
+  nr = nside;//                  ! equatorial region (the most frequent)
+  z  = (2*nside-jr)*fact2;
+  kshift = (int)fmod(jr - nside, 2);
+  if( jr<nside ) { //then     ! north pole region
+    nr = jr;
+    z = 1. - nr*nr*fact1;
+    kshift = 0;
+  }
+  else {
+    if( jr>3*nside ) {// then ! south pole region
+      nr = nl4 - jr;
+      z = - 1. + nr*nr*fact1;
+      kshift = 0;
+    }
+  }
+  theta = acos(z);
+  
+  //c     computes the phi coordinate on the sphere, in [0,2Pi]
+  //      jp = (jpll[face_num+1]*nr + jpt + 1 + kshift)/2;//  ! 'phi' number in the ring in {1,4*nr}
+  jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2;
+  if( jp>nl4 ) jp = jp - nl4;
+  if( jp<1 )   jp = jp + nl4;
+  phi = (jp - (kshift+1)*0.5) * (piover2 / nr);
+}
+
+
+
+template <class T>
+void SphereGorski<T>::print(ostream& os) const
+{
+  if(mInfo_) os << "  DVList Info= " << *mInfo_ << endl;
+  //
+  os << " nSide_ = " << nSide_  << endl;
+  os << " nPix_   = " << nPix_   << endl;
+  os << " omeg_ = " << omeg_   << endl;
+
+  os << " content of pixels : ";
+  for(int i=0; i < nPix_; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os <<  pixels_(i) <<", ";
+    }
+  os << endl;
+
+  os << endl;
+  //const PIXELS_XY& PXY= PIXELS_XY::instance();
+
+  //os << endl;  os << " contenu des tableaux conversions "<<endl;
+  //for(int i=0; i < 5; i++)
+  //  {
+  //   os<<PXY.pix2x_(i)<<", "<<PXY.pix2y_(i)<<", "<<PXY.x2pix_(i)<<", "<<PXY.y2pix_(i)<<endl;
+  // }
+  os << endl;
+
+}
+
+//*******************************************************************
+// Class FIO_SphereGorski<T>
+//  Les objets delegues pour la gestion de persistance 
+//*******************************************************************
+
+template <class T>
+FIO_SphereGorski<T>::FIO_SphereGorski()
+{
+  dobj= new SphereGorski<T>;
+  ownobj= true;
+}
+
+template <class T>
+FIO_SphereGorski<T>::FIO_SphereGorski(string const& filename)
+{
+  dobj= new SphereGorski<T>;
+  dobj->pixels_.SetTemp(true);
+  ownobj= true;
+  Read(filename);
+}
+
+template <class T>
+FIO_SphereGorski<T>::FIO_SphereGorski(const SphereGorski<T>& obj)
+{
+  dobj= new SphereGorski<T>(obj, true);
+  dobj->pixels_.SetTemp(true);
+  ownobj= true;
+}
+
+template <class T>
+FIO_SphereGorski<T>::FIO_SphereGorski(SphereGorski<T>* obj)
+{
+  dobj= obj;
+  ownobj= false;
+}
+
+template <class T>
+FIO_SphereGorski<T>::~FIO_SphereGorski()
+{
+  if (ownobj && dobj) delete dobj;
+}
+
+template <class T>
+AnyDataObj* FIO_SphereGorski<T>::DataObj()
+{
+  return(dobj);
+}
+
+template <class T>
+void FIO_SphereGorski<T>::ReadSelf(PInPersist& is)
+{
+
+  if(dobj == NULL) 
+    {
+      dobj= new SphereGorski<T>;
+      dobj->pixels_.SetTemp(true);
+      ownobj= true;      
+    }
+
+// On lit les 3 premiers uint_8
+uint_8 itab[3];
+is.Get(itab, 3);
+// Let's Read the SphereCoordSys object  -- ATTENTIOn - $CHECK$
+  FIO_SphereCoordSys fio_scs( dobj->GetCoordSys());
+  fio_scs.Read(is);
+  // Pour savoir s'il y avait un DVList Info associe
+  char strg[256];
+  is.GetLine(strg, 255);
+  bool hadinfo= false;
+  if(strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0)  hadinfo= true;
+  if(hadinfo) 
+    {    // Lecture eventuelle du DVList Info
+      is >> dobj->Info(); 
+    }
+
+  int_4 nSide;
+  is.GetI4(nSide);
+  int_4 nPix;
+  is.GetI4(nPix);
+  double Omega;
+  is.GetR8(Omega);
+  dobj->setParameters(nSide,nPix, Omega);
+
+// On lit les DataBlocks;
+  FIO_NDataBlock<T> fio_nd(&dobj->pixels_);
+  fio_nd.Read(is);
+  FIO_NDataBlock<int> fio_ndi1(&dobj->sliceBeginIndex_);
+  fio_ndi1.Read(is);
+  FIO_NDataBlock<int> fio_ndi2(&dobj->sliceLenght_);
+  fio_ndi2.Read(is);
+}
+
+template <class T>
+void FIO_SphereGorski<T>::WriteSelf(POutPersist& os) const
+{
+  if(dobj == NULL) 
+    {
+      cout << " WriteSelf:: dobj= null " << endl;
+      return;
+    }
+
+//  On ecrit 3 uint_8 
+//  0 : Numero de version,  1 : Size index,  2  reserve a l
+uint_8 itab[3];
+itab[0] = 1;
+itab[1] = dobj->SizeIndex();
+itab[2] = 0;
+os.Put(itab, 3);
+// Let's write the SphereCoordSys object
+  FIO_SphereCoordSys fio_scs( dobj->GetCoordSys());
+  fio_scs.Write(os);
+
+  char strg[256];
+  int_4 nSide= dobj->SizeIndex();
+  int_4 nPix = dobj->NbPixels();
+ 
+  if(dobj->ptrInfo()) 
+    {
+      sprintf(strg,"SphereGorski: NSide=%6d  NPix=%9d HasInfo",nSide,nPix);
+      os.PutLine(strg);
+      os << dobj->Info();
+    }
+  else 
+    { 
+      sprintf(strg,"SphereGorski: NSide=%6d  NPix=%9d ",nSide,nPix);
+      os.PutLine(strg);  
+    }
+
+  os.PutI4(nSide);
+  os.PutI4(nPix);
+  os.PutR8(dobj->PixSolAngle());
+// On ecrit les dataBlocks 
+  FIO_NDataBlock<T> fio_nd(&dobj->pixels_);
+  fio_nd.Write(os);
+  FIO_NDataBlock<int> fio_ndi1(&dobj->sliceBeginIndex_);
+  fio_ndi1.Write(os);
+  FIO_NDataBlock<int> fio_ndi2(&dobj->sliceLenght_);
+  fio_ndi2.Write(os);
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template SphereGorski<double>
+#pragma define_template SphereGorski<float>
+#pragma define_template SphereGorski< complex<float> >
+#pragma define_template SphereGorski< complex<double> >
+#pragma define_template FIO_SphereGorski<double>
+#pragma define_template FIO_SphereGorski<float>
+#pragma define_template FIO_SphereGorski< complex<float> >
+#pragma define_template FIO_SphereGorski< complex<double> >
+#endif
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class SphereGorski<double>;
+template class SphereGorski<float>;
+template class SphereGorski< complex<float> >;
+template class SphereGorski< complex<double> >;
+template class FIO_SphereGorski<double>;
+template class FIO_SphereGorski<float>;
+template class FIO_SphereGorski< complex<float> >;
+template class FIO_SphereGorski< complex<double> >;
+#endif
+
Index: /tags/V_Fev00/SophyaLib/Samba/spheregorski.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spheregorski.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spheregorski.h	(revision 752)
@@ -0,0 +1,275 @@
+#ifndef SPHEREGORSKI_SEEN
+#define SPHEREGORSKI_SEEN
+
+#include "sphericalmap.h"
+#include "tvector.h"
+#include "ndatablock.h"
+
+#include "anydataobj.h"
+#include "ppersist.h"
+
+
+// ***************** CLASSE SphereGorski *****************************
+
+//!  class SphereGorski
+/*!
+   Pixelisation Gorski  
+
+
+    -----------------------------------------------------------------------
+     version 0.8.2  Aug97 TAC  Eric Hivon, Kris Gorski
+    -----------------------------------------------------------------------
+
+    the sphere is split in 12 diamond-faces containing nside**2 pixels each
+
+    the numbering of the pixels (in the nested scheme) is similar to
+    quad-cube
+    In each face the first pixel is in the lowest corner of the diamond
+
+    the faces are                    (x,y) coordinate on each face
+\verbatim
+        .   .   .   .   <--- North Pole
+       / \ / \ / \ / \                          ^        ^     
+      . 0 . 1 . 2 . 3 . <--- z = 2/3             \      / 
+       \ / \ / \ / \ /                        y   \    /  x  
+      4 . 5 . 6 . 7 . 4 <--- equator               \  /      
+       / \ / \ / \ / \                              \/      
+      . 8 . 9 .10 .11 . <--- z = -2/3              (0,0) : lowest corner 
+       \ / \ / \ / \ /      
+        .   .   .   .   <--- South Pole
+\endverbatim
+    phi:0               2Pi                                 
+
+   in the ring scheme pixels are numbered along the parallels
+   the first parallel is the one closest to the north pole and so on  
+   on each parallel, pixels are numbered starting from the one closest
+    to phi = 0
+
+    nside MUST be a power of 2 (<= 8192)
+
+*/
+
+template<class T>
+class FIO_SphereGorski;
+
+template<class T>
+class SphereGorski : public SphericalMap<T>
+{
+
+  friend class FIO_SphereGorski<T>;
+
+public :
+
+SphereGorski();
+/*!    
+  m is the "nside" of the Gorski algorithm
+
+  The total number of pixels will be Npix =  12*nside**2
+
+  nside MUST be a power of 2 (<= 8192)
+*/
+SphereGorski(int_4 m);
+SphereGorski(const SphereGorski<T>& s, bool share=false);
+//!	Destructor
+virtual ~SphereGorski();
+
+/*! Setting blockdata to temporary (see ndatablock documentation) */
+inline virtual void SetTemp(bool temp=false) const {pixels_.SetTemp(temp);};
+// ------------------ Definition of PixelMap abstract methods
+
+/* Nombre de pixels du decoupage */
+/*!    Return number of  pixels of the  splitting */
+virtual int_4 NbPixels() const;
+
+/* Valeur du contenu du pixel d'indice "RING" k  */
+/*!    Return value of  pixel with "RING" index k */
+virtual T& PixVal(int_4 k);
+virtual T const& PixVal(int_4 k) const;
+
+/* Nombre de tranches en theta */ 
+/*!    Return number of slices in theta direction on the  sphere */
+uint_4 NbThetaSlices() const;
+/*!   For a theta-slice with index 'index', return : 
+
+   the corresponding "theta" 
+
+    a vector containing the phi's of the pixels of the slice
+
+    a vector containing the corresponding values of pixels 
+*/
+void GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const;
+/*!   For a theta-slice with index 'index', return : 
+
+   the corresponding "theta" 
+
+   the corresponding "phi" for first pixel of the slice 
+
+    a vector containing indices of the pixels of the slice
+
+   (equally distributed in phi)
+
+    a vector containing the corresponding values of pixels 
+*/
+ void GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const ;
+
+/* Return true if teta,phi in map  */
+virtual bool ContainsSph(double theta, double phi) const;
+/* Indice "RING" du pixel vers lequel pointe une direction definie par 
+ses  coordonnees spheriques */                                    
+/*!  Return "RING" index of the pixel corresponding to direction (theta, phi).
+ */
+virtual int_4 PixIndexSph(double theta,double phi) const;
+
+/* Coordonnees spheriques du milieu du pixel d'indice "RING" k   */
+virtual void PixThetaPhi(int_4 k,double& theta,double& phi) const;
+
+/*! Set all pixels to value v */
+virtual T SetPixels(T v);
+
+/* Pixel Solid angle  (steradians) */
+/*!    Pixel Solid angle  (steradians)
+
+    All the pixels have the same solid angle. The dummy argument is
+    for compatibility with eventual pixelizations which would not 
+   fulfil this requirement.
+*/
+virtual double PixSolAngle(int_4 dummy=0) const;
+
+/*  Acces to the DataBlock  */
+inline       NDataBlock<T>& DataBlock()       {return pixels_;}
+inline const NDataBlock<T>& DataBlock() const {return pixels_;}
+
+// --------------- Specific methods 
+
+/*!    
+  m is the "nside" of the Gorski algorithm
+
+  The total number of pixels will be Npix =  12*nside**2
+
+  nside MUST be a power of 2 (<= 8192)
+*/
+virtual void Resize(int_4 m);
+
+// pour l'instant le tableau est ordonne selon RING, uniquement
+inline virtual char* TypeOfMap() const {return "RING";};
+
+
+/* Valeur du contenu du pixel d'indice "NEST" k */
+/*!    Return value of  pixel with "NESTED" index k */
+virtual T& PixValNest(int_4 k);
+/*!    Return value of  pixel with "NESTED" index k */
+virtual T const& PixValNest(int_4 k) const;
+
+/* Indice "NEST" du pixel vers lequel pointe une direction definie par 
+ses  coordonnees spheriques */                                    
+/*! Return "NESTED" index of the pixel corresponding to direction (theta, phi).
+ */
+virtual int_4 PixIndexSphNest(double theta,double phi) const;
+
+/* Coordonnees spheriques du milieu du pixel d'indice "NEST" k       */
+/*!   Return (theta,phi) coordinates of middle of  pixel with "NESTED" index k
+ */
+virtual void PixThetaPhiNest(int_4 k,double& theta,double& phi) const;
+
+/* algorithme de pixelisation */
+void Pixelize(int_4); 
+
+/* convertit index nested en ring  */
+/*!    translation from NESTED index  into RING index */
+int_4 NestToRing(int_4) const;
+
+/* convertit index ring en nested" */
+/*!    translation from  RING index  into NESTED index */
+int_4 RingToNest(int_4) const;
+
+
+/* retourne la valeur du parametre Gorski */
+inline virtual int_4 SizeIndex() const {return(nSide_);}
+
+/* retourne les pointeurs /remplit les tableaux */
+
+
+
+
+/* impression */ 
+void print(ostream& os) const;
+         
+private :
+
+// ------------- méthodes internes ----------------------
+void InitNul();
+ void SetThetaSlices(); 
+
+int_4  nest2ring(int_4 nside,int_4 ipnest) const;
+int_4  ring2nest(int_4 nside,int_4 ipring) const;
+
+int_4  ang2pix_ring(int_4 nside,double theta,double phi) const;
+int_4  ang2pix_nest(int_4 nside,double theta,double phi) const;
+void pix2ang_ring(int_4 nside,int_4 ipix,double& theta,double& phi) const;
+void pix2ang_nest(int_4 nside,int_4 ipix,double& theta,double& phi) const;
+inline void setParameters(int_4 nside, int_4 nbpixels, double solangle) 
+  {
+    nSide_= nside;
+    nPix_= nbpixels;
+    omeg_= solangle;
+  }
+
+// ------------- variables internes -----------------------
+
+int_4 nSide_;
+int_4 nPix_;
+double omeg_;
+
+NDataBlock<T> pixels_;
+NDataBlock<int> sliceBeginIndex_;
+ NDataBlock<int> sliceLenght_;
+
+};
+
+//
+// ------------- Classe pour la gestion de persistance --
+//
+template <class T>
+class FIO_SphereGorski : public PPersist  
+{
+public:
+
+FIO_SphereGorski();
+FIO_SphereGorski(string const & filename); 
+FIO_SphereGorski(const SphereGorski<T>& obj);
+FIO_SphereGorski(SphereGorski<T>* obj);
+virtual ~FIO_SphereGorski();
+virtual AnyDataObj* DataObj();
+inline operator SphereGorski<T>() { return(*dobj); }
+//inline SphereGorski<T> getObj() { return(*dobj); }
+
+protected :
+
+virtual void ReadSelf(PInPersist&);           
+virtual void WriteSelf(POutPersist&) const;  
+SphereGorski<T>* dobj;
+bool ownobj;
+};
+
+//
+// ------------- Classe PIXELS_XY -----------------------
+//
+class PIXELS_XY
+{
+
+public :
+
+static PIXELS_XY& instance();
+
+NDataBlock<int_4> pix2x_;
+NDataBlock<int_4> pix2y_;
+NDataBlock<int_4> x2pix_;
+NDataBlock<int_4> y2pix_;
+
+private :
+
+PIXELS_XY();
+void mk_pix2xy();
+void mk_xy2pix();
+};
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/spherepos.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spherepos.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spherepos.cc	(revision 752)
@@ -0,0 +1,131 @@
+// 04/01/00 : implantation de la persistance par classe deleguee - Guy Le Meur
+
+#include "spherepos.h"
+
+static char *head_spherepos_cc_ = "$Header: /Users/garnier/temp/CVSSophya/SophyaLib/Samba/spherepos.cc,v 1.4 2000-01-04 14:27:15 ansari Exp $";
+
+
+//................. SphereCoordSys class .................
+
+SphereCoordSys::SphereCoordSys(){
+  id_ = SphereCoordSys_NEUTRAL;
+  description_ = "NEUTRAL SphereCoordSystem";
+}
+SphereCoordSys::SphereCoordSys(const SphereCoordSys& a )
+{
+  id_ = a.id_;
+  description_ = a.description_;
+}
+
+SphereCoordSys::SphereCoordSys(int id, const string& description){
+  id_ = id;
+  description_ = description;
+}
+
+SphereCoordSys::~SphereCoordSys()
+{
+}
+SphereCoordSys& SphereCoordSys::operator = (const SphereCoordSys& a)
+{
+  id_ = a.id_;
+  description_ = a.description_;
+  return *this;
+}
+
+
+////////////////////////////////////////////////////////////////
+// -------------------------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// -------------------------------------------------------------------------
+
+FIO_SphereCoordSys::FIO_SphereCoordSys()
+  {
+    dobj=new SphereCoordSys;
+    ownobj=true;
+  }
+FIO_SphereCoordSys::FIO_SphereCoordSys(string const & filename)
+  {
+    dobj=new SphereCoordSys;
+    ownobj=true; 
+    Read(filename);
+  }
+FIO_SphereCoordSys::FIO_SphereCoordSys(const SphereCoordSys & obj)
+  {
+    dobj = new SphereCoordSys(obj);
+    ownobj=true; 
+  }
+FIO_SphereCoordSys::FIO_SphereCoordSys(SphereCoordSys * obj)
+  {
+    dobj = obj;
+    ownobj=false; 
+  }
+FIO_SphereCoordSys::~FIO_SphereCoordSys()
+  {
+    if (ownobj && dobj) delete dobj;
+  }
+AnyDataObj* FIO_SphereCoordSys::DataObj()
+  {
+    return(dobj);
+  }
+
+
+void  FIO_SphereCoordSys::ReadSelf(PInPersist& is)
+  {
+uint_8 itab[3];
+ string description;
+is.Get(itab, 3);
+is.GetStr(description);
+if (dobj == NULL) dobj = new SphereCoordSys(itab[1], description);
+ else *dobj= SphereCoordSys(itab[1], description);
+  }           
+void       FIO_SphereCoordSys::WriteSelf(POutPersist& os) const
+{
+if (dobj == NULL)   return;  // Attention - $CHECK$ Guy 04/01/00
+//  On ecrit 3 uint_8 
+//  0 : Numero de version,  1 : Id,  2  reserve a l
+uint_8 itab[3];
+itab[0] = 1;
+itab[1] = dobj->Id();
+itab[2] = 0;
+os.Put(itab, 3);
+os.PutStr(dobj->description());
+} 
+
+
+
+//................. SpherePosition class .................
+
+SpherePosition::SpherePosition() 
+        : UnitVector()
+{
+  cs_ = new SphereCoordSys;
+}
+
+SpherePosition::SpherePosition(double theta, double phi, SphereCoordSys* cs)
+        : UnitVector(theta, phi)
+{
+if (cs == NULL) cs_ = new SphereCoordSys;
+else cs_ = cs;
+}
+
+SpherePosition::SpherePosition(double x, double y, double z, SphereCoordSys* cs)
+        : UnitVector(x, y, z)
+{
+if (cs == NULL) cs_ = new SphereCoordSys;
+else cs_ = cs;
+}
+
+SpherePosition::~SpherePosition()
+{
+if (cs_) delete cs_;
+}
+
+UnitVector SpherePosition::Transform(const SphereCoordSys& /*cs*/) const
+{
+return(*this);
+}
+
+double SpherePosition::Separation(const SpherePosition& gamma) const 
+{
+return(this->SepAngle(gamma));
+}
Index: /tags/V_Fev00/SophyaLib/Samba/spherepos.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spherepos.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spherepos.h	(revision 752)
@@ -0,0 +1,82 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef SPHEREPOS_H_SEEN
+#define SPHEREPOS_H_SEEN
+
+#include "machdefs.h"
+#include "ppersist.h"
+#include <string>
+#include "unitvector.h"
+#include "anydataobj.h"
+
+static char *head_spherepos_h_ = "$Header: /Users/garnier/temp/CVSSophya/SophyaLib/Samba/spherepos.h,v 1.4 2000-01-04 14:27:11 ansari Exp $";
+
+namespace SOPHYA {
+
+enum SphereCoordSysIds { SphereCoordSys_NEUTRAL =0, 
+                         SphereCoordSys_ROTATION =1,
+                         SphereCoordSys_OTHER = 0xFFFF
+};
+
+ 
+class SphereCoordSys : public  AnyDataObj {
+public:
+  
+  SphereCoordSys();
+  SphereCoordSys(const SphereCoordSys& a);
+                 SphereCoordSys(int id, const string& description);
+  virtual        ~SphereCoordSys();
+
+  virtual int    Id() const {return id_; }
+  virtual string description() const {return description_; }
+  SphereCoordSys& operator = (const SphereCoordSys& a);
+
+
+private:
+  int id_;
+  string description_;
+};
+
+// Classe pour la gestion de persistance
+
+class FIO_SphereCoordSys : public  PPersist  {
+public:
+  FIO_SphereCoordSys();
+  FIO_SphereCoordSys(string const & filename);
+  FIO_SphereCoordSys(const SphereCoordSys & obj);
+  FIO_SphereCoordSys(SphereCoordSys * obj);
+  virtual ~FIO_SphereCoordSys();
+  virtual AnyDataObj* DataObj();
+  inline operator SphereCoordSys() { return(*dobj); }
+protected :
+  virtual void       ReadSelf(PInPersist&);
+  virtual void       WriteSelf(POutPersist&) const;  
+  SphereCoordSys * dobj;
+  bool ownobj;
+};
+
+
+class SpherePosition : public UnitVector {
+public:
+  
+                 SpherePosition();
+// cs should be created by new SphereCoordSys...
+// It will be deleted by the destructor
+                 SpherePosition(double theta, double phi, SphereCoordSys* cs = NULL);
+                 SpherePosition(double x, double y, double z, SphereCoordSys* cs = NULL);
+                 SpherePosition(const UnitVector& v, SphereCoordSys* cs = NULL);
+  virtual        ~SpherePosition();
+
+  inline double  phi() const {return Phi(); }
+  inline double  theta() const { return(Theta()); }
+  inline SphereCoordSys *   GetCoordSys() const { return(cs_); } 
+  virtual UnitVector Transform(const SphereCoordSys& cs) const ;
+
+  virtual double     Separation(const SpherePosition& gamma) const;
+
+protected:
+  SphereCoordSys* cs_;
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.cc	(revision 752)
@@ -0,0 +1,815 @@
+#include "spherethetaphi.h"
+#include "nbmath.h"
+#include <complex>
+#include "piocmplx.h"
+#include <iostream.h>
+
+
+//***************************************************************
+//++ 
+// Class	SphereThetaPhi
+// 
+//
+// include      spherethetaphi.h nbmath.h 
+//
+//    sphere splitted with respect to theta, phi : each hemisphere is 
+//    splitted into (m-1) parallels (equator does not enter into account).
+//    This operation defines m slices, each of which is splitted into 
+//    equidistant meridians. This splitting is realized in such a way that 
+//    all pixels have the same area and are as square as possible.
+
+//    One begins with the hemisphere with positive z, starting from the pole
+//    toward the equator. The first pixel is the polar cap ; it is circular
+//    and centered on theta=0. 
+//--
+//++
+//
+// Links	Parents
+//
+//    SphericalMap 
+//-- 
+
+/* --Methode-- */
+//++
+// Titre	Constructors
+//--
+//++
+
+template <class T>
+SphereThetaPhi<T>::SphereThetaPhi()
+
+//--
+{
+  InitNul();
+  pixels_.Reset();
+}
+
+
+/* --Methode-- */
+
+//++
+template <class T>
+SphereThetaPhi<T>::SphereThetaPhi(int_4 m)
+
+//    m is the number of slices in theta on an hemisphere (the polar cap
+//    forms the first slice).
+//    pet is a dummy parameter at the moment. 
+//--
+{
+  InitNul();
+  Pixelize(m);
+}
+
+template <class T>
+SphereThetaPhi<T>::SphereThetaPhi(const SphereThetaPhi<T>& s, bool share)
+  : pixels_(s.pixels_ , share)
+{
+  if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
+  NTheta_= s.NTheta_;
+  NPix_  = s.NPix_;
+  NPhi_.ReSize(NTheta_);
+  Theta_.ReSize(NTheta_+1);
+  TNphi_.ReSize(NTheta_+1);
+
+  NPhi_  = s.NPhi_;
+  TNphi_ = s.TNphi_;
+  Theta_ = s.Theta_;
+  Omega_ = s.Omega_;
+}
+
+//++
+// Titre	Destructor
+//--
+//++
+template <class T>
+SphereThetaPhi<T>::~SphereThetaPhi()
+
+//--
+{}
+
+//++
+// Titre	Public Méthods
+//--
+template <class T>
+void SphereThetaPhi<T>::InitNul()
+//
+{
+  NTheta_= 0;
+  NPix_  = 0;
+//  pixels_.Reset();  Pas de reset par InitNul (en cas de share) - Reza 20/11/99 $CHECK$
+}
+
+
+//++
+template <class T>
+void SphereThetaPhi<T>::Resize(int_4 m)
+//   re-pixelize the sphere
+//--
+{
+  InitNul();
+  Pixelize(m);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+int_4 SphereThetaPhi<T>::NbPixels() const
+
+//    Return total number of pixels 
+//--
+{
+  return(NPix_);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+T& SphereThetaPhi<T>::PixVal(int_4 k)
+
+//    Return value of pixel with index k
+//--
+{
+  if((k < 0) || (k >= NPix_)) 
+    {
+      throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
+    }
+  return pixels_(k);
+}
+
+//++
+template <class T>
+T const& SphereThetaPhi<T>::PixVal(int_4 k) const
+
+//    Return value of pixel with index k
+//--
+{
+  if((k < 0) || (k >= NPix_)) 
+    {
+       throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
+    } 
+  return *(pixels_.Data()+k);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+bool SphereThetaPhi<T>::ContainsSph(double /*theta*/, double /*phi*/) const
+//--
+{
+  return(true);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+int_4 SphereThetaPhi<T>::PixIndexSph(double theta, double phi) const
+
+//    Return index of the pixel corresponding to 
+//    direction (theta, phi).
+//--
+{
+  double dphi;
+  int i,k;
+  bool fgzn = false;
+
+  if((theta > Pi) || (theta < 0.)) return(-1);
+  if((phi < 0.) || (phi > DeuxPi)) return(-1);
+  if(theta > Pi*0.5) {fgzn = true; theta = Pi-theta;}
+  
+  // La bande d'indice kt est limitée par les valeurs de theta contenues dans
+  // Theta_[kt] et Theta_[kt+1]
+  for( i=1; i< NTheta_; i++ ) 
+    if( theta < Theta_(i) ) break;
+  
+  dphi= DeuxPi/(double)NPhi_(i-1);
+  
+  if (fgzn)  k= NPix_-TNphi_(i)+(int_4)(phi/dphi);
+  else k= TNphi_(i-1)+(int_4)(phi/dphi); 
+  return(k);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+void SphereThetaPhi<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
+
+//   Return (theta,phi) coordinates of middle of  pixel with  index k
+//--
+{
+  int i; 
+  bool fgzn = false;
+  
+  if((k < 0) || (k >= NPix_)) {theta = -99999.; phi = -99999.; return; }
+  if( k >= NPix_/2)  {fgzn = true; k = NPix_-1-k;}
+
+  // recupère l'indice i de la tranche qui contient le pixel k
+  for( i=0; i< NTheta_; i++ ) 
+    if( k < TNphi_(i+1) ) break;
+
+  // angle theta
+  theta= 0.5*(Theta_(i)+Theta_(i+1));
+  if (fgzn) theta= Pi-theta;
+  
+  // angle phi
+  k -= TNphi_(i);
+  phi= DeuxPi/(double)NPhi_(i)*(double)(k+.5);
+  if (fgzn) phi= DeuxPi-phi;
+}
+
+template <class T>
+T SphereThetaPhi<T>::SetPixels(T v)
+{
+pixels_.Reset(v);
+return(v);
+}
+
+//++
+template <class T>
+double SphereThetaPhi<T>::PixSolAngle(int_4 /*dummy*/) const
+
+//    Pixel Solid angle  (steradians)
+//    All the pixels have the same solid angle. The dummy argument is
+//    for compatibility with eventual pixelizations which would not 
+//    fulfil this requirement.
+//--
+{
+  return Omega_;
+}
+
+/* --Methode-- */
+//++
+template <class T>
+void SphereThetaPhi<T>::Limits(int_4 k,double& tetMin,double& tetMax,double& phiMin,double& phiMax) 
+
+//   Return values of theta,phi which limit the pixel with  index k
+//--
+  {
+  int j;
+  double dphi;
+  bool fgzn= false;
+  
+  if((k < 0) || (k >= NPix_)) {
+    tetMin= -99999.; 
+    phiMin= -99999.;  
+    tetMax= -99999.; 
+    phiMax= -99999.;  
+    return;
+  }
+  
+  // si on se trouve dans l'hémisphère Sud
+  if(k >= NPix_/2) { 
+    fgzn= true; 
+    k= NPix_-1-k; 
+  }
+  
+  // on recupere l'indice i de la tranche qui contient le pixel k
+  int i;
+  for( i=0; i< NTheta_; i++ ) 
+    if(k < TNphi_(i+1)) break;
+  
+  // valeurs limites de theta dans l'hemisphere Nord
+  tetMin= Theta_(i);
+  tetMax= Theta_(i+1);
+  // valeurs limites de theta dans l'hemisphere Sud
+  if (fgzn) {
+    tetMin= Pi - Theta_(i+1);
+    tetMax= Pi - Theta_(i);
+  }
+  
+  // pixel correspondant dans l'hemisphere Nord
+  if (fgzn) k= TNphi_(i+1)-k+TNphi_(i)-1;
+  
+  // indice j de discretisation ( phi= j*dphi )
+  j= k-TNphi_(i);
+  dphi= DeuxPi/(double)NPhi_(i);
+  
+  // valeurs limites de phi 
+  phiMin= dphi*(double)(j);
+  phiMax= dphi*(double)(j+1);
+  return;
+}
+
+/* --Methode-- */
+//++
+template <class T>
+uint_4 SphereThetaPhi<T>::NbThetaSlices() const
+
+//    Return number of theta-slices on the sphere
+//--
+{
+  if (NTheta_<=0) 
+    {
+      throw PException(" sphere not pixelized, NbSlice=0 ");
+    }
+  return( 2*NTheta_);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+int_4 SphereThetaPhi<T>::NPhi(int_4 kt) const
+
+//    Return number of pixels in phi-direction of the kt-th slice
+//-- 
+{
+  int nbpix;  
+  // verification
+  if((kt < 0) || (kt >= 2*NTheta_)) return(-1);
+  
+  // si on se trouve dans l'hemisphere Sud
+  if(kt >= NTheta_) {
+    kt= 2*NTheta_-1-kt; 
+  }
+  
+  // nombre de pixels
+  nbpix= NPhi_(kt);
+  return(nbpix);
+}
+
+
+/* --Methode-- */
+//++
+template <class T>
+void SphereThetaPhi<T>::Theta(int_4 kt,double& tetMin,double& tetMax) 
+
+//    Return  theta values which limit the slice kt
+//--
+{
+  bool fgzn= false;
+  // verification
+  if( (kt< 0) || (kt>= 2*NTheta_) ) {
+    tetMin= -99999.; 
+    tetMax= -99999.; 
+    return;
+  }
+
+  // si on se trouve dans l'hemisphere Sud
+  if( kt >= NTheta_ ) {
+    fgzn= true;
+    kt= 2*NTheta_-1-kt; 
+  }
+  
+  // valeurs limites de theta dans l'hemisphere Nord
+  tetMin= Theta_(kt);
+  tetMax= Theta_(kt+1);
+  // valeurs limites de theta dans l'hemisphere Sud
+  if (fgzn) {
+    tetMin= Pi - Theta_(kt+1);
+    tetMax= Pi - Theta_(kt);
+  }  
+}
+
+/* --Methode-- */
+//++
+template <class T>
+void SphereThetaPhi<T>::Phi(int_4 kt,int_4 jp,double& phiMin,double& phiMax) 
+
+//   Return values of phi which limit the jp-th pixel of the kt-th slice
+//--
+{
+  // verification
+  if((kt < 0) || (kt >= 2*NTheta_)) {
+    phiMin= -99999.; 
+    phiMax= -99999.; 
+    return;
+  }
+  
+  // si on se trouve dans l'hemisphere Sud
+  if(kt >= NTheta_) kt= 2*NTheta_-1-kt;
+  
+  // verifie si la tranche kt contient au moins jp pixels
+  if( (jp< 0) || (jp >= NPhi_(kt)) ) {
+    phiMin= -88888.; 
+    phiMax= -88888.; 
+    return;
+  }
+  
+  double dphi= DeuxPi/(double)NPhi_(kt);
+  phiMin= dphi*(double)(jp);
+  phiMax= dphi*(double)(jp+1);
+  return;
+}
+
+/* --Methode-- */
+//++
+template <class T>
+int_4 SphereThetaPhi<T>::Index(int_4 kt,int_4 jp) const
+
+//    Return pixel index  with sequence index jp in the slice kt 
+//--
+{
+  int k;
+  bool fgzn= false;
+  
+  // si on se trouve dans l'hemisphere Sud
+  if(kt >= NTheta_) {
+    fgzn= true; 
+    kt= 2*NTheta_-1-kt;
+  }
+  
+  // si la tranche kt contient au moins i pixels
+  if( (jp>=0) && (jp<NPhi_(kt)) ) 
+    {
+      // dans l'hemisphere Sud
+      if (fgzn) k= NPix_-TNphi_(kt+1)+jp;
+      // dans l'hemisphere Nord
+      else k= TNphi_(kt)+jp;
+    }
+  else
+    {
+      k= 9999;
+      printf("\n la tranche %d ne contient pas un pixel de rang %d",kt,jp);
+    }
+  return(k);
+}
+
+/* --Methode-- */
+//++
+template <class T>
+void SphereThetaPhi<T>::ThetaPhiIndex(int_4 k,int_4& kt,int_4& jp) 
+
+//    Return indices kt (theta) and jp (phi) of  pixel with index k
+//--
+{
+  bool fgzn= false;  
+  // si on se trouve dans l'hemisphere Sud
+  if(k >= NPix_/2) 
+    { 
+      fgzn= true; 
+      k= NPix_-1-k; 
+    }
+  
+  // on recupere l'indice kt de la tranche qui contient le pixel k
+  int i;
+  for(i = 0; i < NTheta_; i++) 
+    if(k < TNphi_(i+1)) break;
+  
+  // indice  kt de tranche
+  if (fgzn) kt= 2*NTheta_-1-i;
+  else kt= i;
+  
+  // indice jp de pixel
+  if (fgzn) jp= TNphi_(i+1)-k-1;
+  else jp= k-TNphi_(i);  
+}
+//++
+template <class T>
+void  SphereThetaPhi<T>::Pixelize(int_4 m) 
+
+//    achieve the splitting into pixels (m has the same signification 
+//    as for the constructor)
+//
+//    Each theta-slice of the north hemisphere will be spitted starting f
+//    from  phi=0 ...
+//
+//    South hemisphere is scanned in the same direction according to phi
+//    and from equator to the pole (the pixel following the last one of
+//    the slice closest to the equator with z>0, is the pixel with lowest 
+//    phi of the slice closest of the equator with z<0).
+//--
+{
+  int ntotpix,j;
+  
+  // Decodage et controle des arguments d'appel :
+  // au moins 2 et au plus 16384 bandes d'un hemisphere en theta
+  if (m < 2) m = 2;
+  if (m > 16384) m = 16384;
+  
+  // On memorise les arguments d'appel
+  NTheta_ = m;  
+  
+  // On commence par decouper l'hemisphere z>0.
+  // Creation des vecteurs contenant :
+  // Les valeurs limites de theta (une valeur de plus que le nombre de bandes...)
+  //  Theta_= new double[m+1];
+  Theta_.ReSize(m+1);
+  
+  // Le nombre de pixels en phi de chacune des bandes en theta
+  //  NPhi_ = new int_4[m];
+  NPhi_.ReSize(m);
+  
+  // Le nombre/Deuxpi total des pixels contenus dans les bandes de z superieur a une
+  // bande donnee (mTPphi[m] contient le nombre de pixels total de l'hemisphere)
+  //  TNphi_= new int_4[m+1];
+    TNphi_.ReSize(m+1);
+  
+  // Calcul du nombre total de pixels dans chaque bande pour optimiser
+  // le rapport largeur/hauteur des pixels 
+  
+  //calotte polaire
+  TNphi_(0)= 0;
+  NPhi_(0) = 1;
+  
+  //bandes jusqu'a l'equateur
+  for(j = 1; j < m; j++) 
+    {
+      TNphi_(j)= TNphi_(j-1)+NPhi_(j-1);
+      NPhi_(j) = (int_4)(.5+4.*(double)(m-.5)*sin(Pi*(double)j/(double)(2.*m-1.))) ;
+    }
+  
+  // Nombre total de pixels sur l'hemisphere
+  ntotpix  = TNphi_(m-1)+NPhi_(m-1);
+  TNphi_(m)= ntotpix;
+  // et sur la sphere entiere
+  NPix_= 2*ntotpix;
+  
+  // Creation et initialisation du vecteur des contenus des pixels 
+  pixels_.ReSize(NPix_);
+  pixels_.Reset();
+
+  // Determination des limites des bandes en theta :
+  // omeg est l'angle solide couvert par chaque pixel,
+  // une bande donnee kt couvre un angle solide NPhi_[kt]*omeg
+  // egal a 2* Pi*(cos Theta_[kt]-cos Theta_[kt+1]). De meme, l'angle solide 
+  //de la
+  // calotte allant du pole a la limite haute de la bande kt vaut
+  // 2* Pi*(1.-cos Theta_[kt+1])= TNphi_[kt]*omeg...
+  
+  double omeg2pi= 1./(double)ntotpix;
+  Omega_ = omeg2pi*DeuxPi;
+  
+  for(j=0; j <= m; j++) 
+    {
+      Theta_(j)= acos(1.-(double)TNphi_(j)*omeg2pi);
+    }
+}
+
+//++
+template <class T>
+void SphereThetaPhi<T>::GetThetaSlice(int_4 index,r_8& theta, TVector<r_8>& phi, TVector<T>& value) const 
+
+//    For a theta-slice with index 'index', return : 
+//    the corresponding "theta" 
+//    a vector containing the phi's of the pixels of the slice
+//    a vector containing the corresponding values of pixels 
+//--
+
+{
+
+  if(index < 0 || index >= NbThetaSlices()) 
+    {
+       throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range"); 
+    }
+
+  int iring= Index(index,0);
+  int lring  = NPhi(index);
+
+  phi.ReSize(lring);
+  value.ReSize(lring);
+  double Te= 0.;
+  double Fi= 0.;
+  for(int kk = 0; kk < lring; kk++) 
+    {
+      PixThetaPhi(kk+iring,Te,Fi);
+      phi(kk)= Fi;
+      value(kk)= PixVal(kk+iring);
+    }
+  theta= Te;
+}
+
+//++
+template <class T>
+void SphereThetaPhi<T>::GetThetaSlice(int_4 index,r_8& theta, r_8& phi0,TVector<int_4>& pixelIndices, TVector<T>& value) const 
+
+//    For a theta-slice with index 'index', return : 
+//    the corresponding "theta" 
+//    the corresponding "phi" for first pixel of the slice 
+//    a vector containing the indices of the pixels of the slice
+//    (equally distributed in phi)
+//    a vector containing the corresponding values of pixels 
+//--
+
+{
+
+  if(index < 0 || index >= NbThetaSlices()) 
+    {
+       throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range"); 
+ 
+    }
+
+  int iring= Index(index,0);
+  int lring  = NPhi(index);
+
+  pixelIndices.ReSize(lring);
+  value.ReSize(lring);
+  double Te= 0.;
+  double Fi= 0.;
+  for(int kk = 0; kk < lring; kk++) 
+    {
+      pixelIndices(kk)=kk+iring ;
+      value(kk)= PixVal(kk+iring);
+    }
+      PixThetaPhi(iring,theta,phi0);
+}
+
+
+
+
+template <class T>
+void SphereThetaPhi<T>::print(ostream& os) const
+{
+  if(mInfo_) os << "  DVList Info= " << *mInfo_ << endl;
+  //
+  os << " NTheta_= " << NTheta_ << endl;
+  os << " NPix_    = " << NPix_   << endl;
+  os << " Omega_  =  " << Omega_   << endl;
+
+  os << " contenu de NPhi_ : ";
+  int i;
+  for(i=0; i < NTheta_; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os << NPhi_(i) <<", ";
+    }
+  os << endl;
+
+  os << " contenu de Theta_ : ";
+  for(i=0; i < NTheta_+1; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os << Theta_(i) <<", ";
+    }
+  os << endl;
+
+  os << " contenu de TNphi_ : ";
+  for(i=0; i < NTheta_+1; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os << TNphi_(i) <<", ";
+    }
+  os << endl;
+
+  os << " contenu de pixels : ";
+  for(i=0; i < NPix_; i++)
+    {
+      if(i%5 == 0) os << endl;
+      os <<  pixels_(i) <<", ";
+    }
+  os << endl;
+}
+
+///////////////////////////////////////////////////////////
+// --------------------------------------------------------
+//   Les objets delegues pour la gestion de persistance 
+// --------------------------------------------------------
+//////////////////////////////////////////////////////////
+
+template <class T>
+FIO_SphereThetaPhi<T>::FIO_SphereThetaPhi()
+{
+  dobj= new SphereThetaPhi<T>;
+  ownobj= true;
+}
+
+template <class T>
+FIO_SphereThetaPhi<T>::FIO_SphereThetaPhi(string const& filename)
+{
+  dobj= new SphereThetaPhi<T>;
+  dobj->pixels_.SetTemp(true);
+  ownobj= true;
+  Read(filename);
+}
+
+template <class T>
+FIO_SphereThetaPhi<T>::FIO_SphereThetaPhi(const SphereThetaPhi<T>& obj)
+{
+  dobj= new SphereThetaPhi<T>(obj, true);
+  dobj->pixels_.SetTemp(true);
+  ownobj= true;
+}
+
+template <class T>
+FIO_SphereThetaPhi<T>::FIO_SphereThetaPhi(SphereThetaPhi<T>* obj)
+{
+  dobj= obj;
+  ownobj= false;
+}
+
+template <class T>
+FIO_SphereThetaPhi<T>::~FIO_SphereThetaPhi()
+{
+  if (ownobj && dobj) delete dobj;
+}
+
+template <class T>
+AnyDataObj* FIO_SphereThetaPhi<T>::DataObj()
+{
+  return(dobj);
+}
+
+template <class T>
+void FIO_SphereThetaPhi<T>::ReadSelf(PInPersist& is)
+{
+
+  if(dobj == NULL) 
+    {
+      dobj= new SphereThetaPhi<T>;
+      dobj->pixels_.SetTemp(true);
+      ownobj= true;      
+    }
+
+  // On lit les 3 premiers uint_8
+  uint_8 itab[3];
+  is.Get(itab, 3);
+// Let's Read the SphereCoordSys object  -- ATTENTIOn - $CHECK$
+  FIO_SphereCoordSys fio_scs( dobj->GetCoordSys());
+  fio_scs.Read(is);
+
+  // Pour savoir s'il y avait un DVList Info associe
+  char strg[256];
+  is.GetLine(strg, 255);
+  bool hadinfo= false;
+  if(strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0)  hadinfo= true;
+  if(hadinfo) 
+    {    // Lecture eventuelle du DVList Info
+      is >> dobj->Info(); 
+    }
+
+  int_4 mNTheta;
+  is.GetI4(mNTheta);  
+  int_4 mNPix;
+  is.GetI4(mNPix);
+  double mOmeg;
+  is.GetR8(mOmeg);
+  dobj->setParameters(mNPix, mOmeg, mNTheta); 
+  FIO_NDataBlock<int_4> fio_nd_nphi(&dobj->NPhi_);
+  fio_nd_nphi.Read(is);
+  FIO_NDataBlock<int_4> fio_nd_Tnphi(&dobj->TNphi_);
+  fio_nd_Tnphi.Read(is);
+  FIO_NDataBlock<r_8> fio_nd_Theta(&dobj->Theta_);
+  fio_nd_Theta.Read(is);
+
+FIO_NDataBlock<T> fio_nd(&dobj->pixels_);
+fio_nd.Read(is);
+}
+
+template <class T>
+void FIO_SphereThetaPhi<T>::WriteSelf(POutPersist& os) const
+{
+
+  if(dobj == NULL) 
+    {
+      cout << " WriteSelf:: dobj= null " << endl;
+      return;
+    }
+
+//  On ecrit 3 uint_8 
+//  0 : Numero de version,  1 : Size index,  2  reserve a l
+uint_8 itab[3];
+itab[0] = 1;
+itab[1] = dobj->SizeIndex();
+itab[2] = 0;
+os.Put(itab, 3);
+// Let's write the SphereCoordSys object
+  FIO_SphereCoordSys fio_scs( dobj->GetCoordSys());
+  fio_scs.Write(os);
+  
+  char strg[256];
+  int_4 mNTheta= dobj->SizeIndex();
+  int_4 mNPix  = dobj->NbPixels();
+ 
+  if(dobj->ptrInfo()) 
+    {
+      sprintf(strg,"SphereThetaPhi: NSlices=%6d  NPix=%9d HasInfo",mNTheta,mNPix);
+      os.PutLine(strg);
+      os << dobj->Info();
+    }
+  else 
+    { 
+      sprintf(strg,"SphereThetaPhi: NSlices=%6d  NPix=%9d ",mNTheta,mNPix);
+      os.PutLine(strg);  
+    }
+
+  os.PutI4(mNTheta);  
+  os.PutI4(mNPix);
+  os.PutR8(dobj->PixSolAngle());
+  FIO_NDataBlock<int_4> fio_nd_nphi(&dobj->NPhi_);
+  fio_nd_nphi.Write(os);
+  FIO_NDataBlock<int_4> fio_nd_Tnphi(&dobj->TNphi_);
+  fio_nd_Tnphi.Write(os);
+  FIO_NDataBlock<r_8> fio_nd_Theta(&dobj->Theta_);
+  fio_nd_Theta.Write(os);
+FIO_NDataBlock<T> fio_nd(&dobj->pixels_);
+fio_nd.Write(os);
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template SphereThetaPhi<double>
+#pragma define_template SphereThetaPhi<float>
+#pragma define_template SphereThetaPhi< complex<float> >
+#pragma define_template SphereThetaPhi< complex<double> >
+#pragma define_template FIO_SphereThetaPhi<double>
+#pragma define_template FIO_SphereThetaPhi<float>
+#pragma define_template FIO_SphereThetaPhi< complex<float> >
+#pragma define_template FIO_SphereThetaPhi< complex<double> >
+#endif
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class SphereThetaPhi<double>;
+template class SphereThetaPhi<float>;
+template class SphereThetaPhi< complex<float> >;
+template class SphereThetaPhi< complex<double> >;
+template class FIO_SphereThetaPhi<double>;
+template class FIO_SphereThetaPhi<float>;
+template class FIO_SphereThetaPhi< complex<float> >;
+template class FIO_SphereThetaPhi< complex<double> >;
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/spherethetaphi.h	(revision 752)
@@ -0,0 +1,207 @@
+#ifndef SPHERETHETAPHI_SEEN
+#define SPHERETHETAPHI_SEEN
+
+#include "sphericalmap.h"
+#include "ndatablock.h"
+#include "tvector.h"
+
+#include "anydataobj.h"
+#include "ppersist.h"
+
+template <class T>
+class FIO_SphereThetaPhi;  
+
+
+// ***************** Class SphereThetaPhi *****************************
+/*!    sphere splitted with respect to theta, phi : each hemisphere is 
+    splitted into (m-1) parallels (equator does not enter into account).
+   This operation defines m slices, each of which is splitted into 
+    equidistant meridians. This splitting is realized in such a way that 
+    all pixels have the same area and are as square as possible.
+
+    One begins with the hemisphere with positive z, starting from the pole
+    toward the equator. The first pixel is the polar cap ; it is circular
+    and centered on theta=0. 
+*/
+template <class T>
+class SphereThetaPhi : public SphericalMap<T>
+{
+
+  friend class FIO_SphereThetaPhi<T>;
+
+public :
+
+SphereThetaPhi();
+/*!    m is the number of slices in theta on an hemisphere (the polar cap
+   forms the first slice).
+    pet is a dummy parameter at the moment. 
+*/
+SphereThetaPhi(int_4 m);
+SphereThetaPhi(const SphereThetaPhi<T>& s, bool share=false);
+virtual ~SphereThetaPhi();
+
+/*! Setting blockdata to temporary (see ndatablock documentation) */
+inline virtual void SetTemp(bool temp=false) const {pixels_.SetTemp(temp);};
+
+// ------------ Definition of PixelMap abstract methods -
+
+/* retourne le nombre de pixels */ 
+/*!    Return total number of pixels  */
+virtual int_4 NbPixels() const;
+
+/* retourne la valeur du pixel d'indice k */ 
+/*!    Return value of pixel with index k */
+virtual T&       PixVal(int_4 k);
+virtual T const& PixVal(int_4 k) const;
+
+/* Return true if teta,phi in map  */
+virtual bool ContainsSph(double theta, double phi) const;
+/* retourne l'indice du pixel a (theta,phi) */ 
+/*    Return index of the pixel corresponding to direction (theta, phi). */
+virtual int_4 PixIndexSph(double theta, double phi) const;
+
+/* retourne les coordonnees Spheriques du centre du pixel d'indice k */ 
+/*!   Return (theta,phi) coordinates of middle of  pixel with  index k */
+virtual void PixThetaPhi(int_4 k, double& theta, double& phi) const;
+
+/*! Setting pixel values to a constant */
+virtual T SetPixels(T v);
+
+/* retourne/fixe l'angle Solide de Pixel   (steradians) */ 
+/*!   Pixel Solid angle  (steradians)
+
+    All the pixels have the same solid angle. The dummy argument is
+   for compatibility with eventual pixelizations which would not 
+    fulfil this requirement.
+*/
+virtual double PixSolAngle(int_4 dummy=0) const;
+ 
+/* retourne/fixe la valeur du parametre de decoupage m */ 
+inline virtual int_4 SizeIndex() const { return( NTheta_); }
+
+/*  Acces to the DataBlock  */
+inline       NDataBlock<T>& DataBlock()       {return pixels_;}
+inline const NDataBlock<T>& DataBlock() const {return pixels_;}
+
+// ------------- Specific methods  ----------------------
+
+/*!   re-pixelize the sphere */
+virtual void Resize(int_4 m);
+
+inline virtual char* TypeOfMap() const {return "TETAFI";};
+
+/* Valeurs de theta des paralleles et phi des meridiens limitant le pixel d'indice k */
+/*   Return values of theta,phi which limit the pixel with  index k */
+virtual void Limits(int_4 k,double& th1,double& th2,double& phi1,double& phi2);
+
+/* Nombre de tranches en theta */ 
+/*!    Return number of theta-slices on the sphere */
+uint_4 NbThetaSlices() const;
+
+/* Nombre de pixels en phi de la tranche d'indice kt */ 
+int_4 NPhi(int_4 kt) const;
+
+/* Renvoie dans t1,t2 les valeurs respectives de theta min et theta max  */
+/* de la tranche d'indice kt  */ 
+/*!    Return  theta values which limit the slice kt */
+void Theta(int_4 kt, double& t1, double& t2);
+
+/* Renvoie dans p1,p2 les valeurs phimin et phimax du pixel d'indice jp  */
+/* dans la tranche d'indice kt  */ 
+/*!   Return values of phi which limit the jp-th pixel of the kt-th slice */
+void Phi(int_4 kt, int_4 jp, double& p1, double& p2);
+
+/* Renvoie l'indice k du pixel d'indice jp dans la tranche d'indice kt   */
+/*!   Return pixel index  with sequence index jp in the slice kt */
+int_4 Index(int_4 kt, int_4 jp) const;
+
+/* Indice kt de la tranche et indice jp du pixel d'indice k  */ 
+/*!    Return indices kt (theta) and jp (phi) of  pixel with index k */
+void ThetaPhiIndex(int_4 k,int_4& kt,int_4& jp);
+
+/*!    achieve the splitting into pixels (m has the same signification 
+    as for the constructor)
+
+    Each theta-slice of the north hemisphere will be spitted starting f
+    from  phi=0 ...
+
+    South hemisphere is scanned in the same direction according to phi
+    and from equator to the pole (the pixel following the last one of
+    the slice closest to the equator with z>0, is the pixel with lowest 
+    phi of the slice closest of the equator with z<0).
+*/
+void Pixelize(int_4); 
+
+/*!   For a theta-slice with index 'index', return : 
+
+   the corresponding "theta" 
+
+    a vector containing the phi's of the pixels of the slice
+
+    a vector containing the corresponding values of pixels 
+*/
+void GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const; 
+
+/*!   For a theta-slice with index 'index', return : 
+
+   the corresponding "theta" 
+
+   the corresponding "phi" for first pixel of the slice 
+
+    a vector containing indices of the pixels of the slice
+
+   (equally distributed in phi)
+
+    a vector containing the corresponding values of pixels 
+*/
+ void GetThetaSlice(int_4 index, r_8& theta, r_8& phi0,TVector<int_4>& pixelIndices, TVector<T>& value) const ;
+
+
+/* impression */ 
+void print(ostream& os) const;
+
+private :
+
+// ------------- méthodes internes ----------------------          
+void InitNul();
+inline void setParameters(int nbpix, double omega, int nbThetaIndex) 
+  {
+    NPix_= nbpix;
+    Omega_= omega;
+    NTheta_= nbThetaIndex;
+  }
+
+// ------------- variables internes ---------------------
+ int_4 NTheta_;   // nombre de tranches en theta, pour une demi-sphere
+ int_4 NPix_;     // nombre total de pixels
+ double Omega_; // angle solide constant pour chaque pixel
+ NDataBlock<int_4>  NPhi_;  // tableau donnant, pour chaque bande en theta, 
+                         //le nombre de pixels selon phi
+ NDataBlock<int_4> TNphi_;
+ NDataBlock<r_8> Theta_;
+ NDataBlock<T> pixels_;
+};
+
+// ------------- Classe pour la gestion de persistance --
+template <class T>
+class FIO_SphereThetaPhi : public PPersist  
+{
+public:
+
+FIO_SphereThetaPhi();
+FIO_SphereThetaPhi(string const & filename); 
+FIO_SphereThetaPhi(const SphereThetaPhi<T>& obj);
+FIO_SphereThetaPhi(SphereThetaPhi<T>* obj);
+virtual ~FIO_SphereThetaPhi();
+virtual AnyDataObj* DataObj();
+inline operator SphereThetaPhi<T>() { return(*dobj); }
+
+protected :
+
+virtual void ReadSelf(PInPersist&);           
+virtual void WriteSelf(POutPersist&) const;  
+SphereThetaPhi<T>* dobj;
+bool ownobj;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/sphericalmap.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/sphericalmap.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/sphericalmap.h	(revision 752)
@@ -0,0 +1,47 @@
+#ifndef SPHERICALMAP_SEEN
+#define SPHERICALMAP_SEEN
+
+// valeurs de Pi, 2*Pi, etc                                              
+#include "nbmath.h"
+#include <math.h>
+#include "pixelmap.h"
+#include "tvector.h" 
+
+// Map of pixels on a whole sphere.
+// Class hierarchy :
+//   PixelMap
+//      SphericalMap
+//         SphereThetaPhi
+//         SphereGorski
+//         SphereIco
+//      LocalMap
+
+template<class T>
+class SphericalMap : public PixelMap<T> 
+{
+  
+public :
+
+SphericalMap() {};
+virtual	 ~SphericalMap() {};
+
+// Overloading of () to access pixel number k.
+inline T& operator()(int k) {return(PixVal(k));}
+inline T  const& operator()(int k) const {return(PixVal(k));}
+inline T& operator()(double theta,double phi) {return(PixValSph(theta,phi));};
+inline T  const& operator()(double theta,double phi) const {return(PixValSph(theta,phi));};
+
+// index characterizing the size pixelization : m for SphereThetaPhi
+// nside for Gorski sphere...
+virtual void Resize(int m)=0;
+virtual uint_4 NbThetaSlices() const=0;
+virtual void GetThetaSlice(int_4 index,r_8& theta, TVector<r_8>& phi, TVector<T>& value) const=0; 
+virtual void GetThetaSlice(int_4 sliceIndex, r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const=0 ;
+};
+#endif
+
+
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.cc	(revision 752)
@@ -0,0 +1,856 @@
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+#include <complex>
+#include "sphericaltransformserver.h"
+#include "tvector.h"
+#include "nbrandom.h"
+#include "nbmath.h"
+
+
+template<class T>
+void SphericalTransformServer<T>::GenerateFromAlm( SphericalMap<T>& map, int_4 pixelSizeIndex, const Alm<T>& alm) const
+{
+  /*=======================================================================
+    computes a map form its alm for the HEALPIX pixelisation
+    map(theta,phi) = sum_l_m a_lm Y_lm(theta,phi)
+    = sum_m {e^(i*m*phi) sum_l a_lm*lambda_lm(theta)}
+    
+    where Y_lm(theta,phi) = lambda(theta) * e^(i*m*phi)
+    
+    * the recurrence of Ylm is the standard one (cf Num Rec)
+    * the sum over m is done by FFT
+    
+    =======================================================================*/
+  int_4 nlmax=alm.Lmax();
+  int_4 nmmax=nlmax;
+  int_4 nsmax=0;
+  map.Resize(pixelSizeIndex);
+  char* sphere_type=map.TypeOfMap();
+  if (strncmp(sphere_type,"RING",4) == 0)
+    {
+      nsmax=map.SizeIndex();
+    }
+  else
+    // pour une sphere Gorski le nombre de pixels est 12*nsmax**2
+    // on calcule une quantite equivalente a nsmax pour la sphere-theta-phi
+    // en vue de l'application du critere Healpix : nlmax<=3*nsmax-1
+    // c'est approximatif ; a raffiner.
+    if (strncmp(sphere_type,"TETAFI",6) == 0)
+      {
+	nsmax=(int_4)sqrt(map.NbPixels()/12.);
+      }
+    else
+      {
+	cout << " unknown type of sphere : " << sphere_type << endl;
+	throw IOExc(" unknown type of sphere: " + (string)sphere_type );
+      }
+  cout << "GenerateFromAlm: the sphere is of type : " << sphere_type << endl;
+  cout << "GenerateFromAlm: size index (nside) of the sphere= " << nsmax << endl;
+  cout << "GenerateFromAlm: nlmax (from Alm) = " << nlmax << endl;
+  if (nlmax>3*nsmax-1) 
+    {
+      cout << "GenerateFromAlm: nlmax should be <= 3*nside-1" << endl;
+      if (strncmp(sphere_type,"TETAFI",6) == 0)
+	{
+	  cout << " (for this criterium, nsmax is computed as sqrt(nbPixels/12))" << endl;
+	}
+    }
+  Bm<complex<T> > b_m_theta(nmmax);
+
+  //  map.Resize(nsmax);
+
+
+  // pour chaque tranche en theta
+  for (int_4 ith = 0; ith < map.NbThetaSlices();ith++)
+    {
+      int_4 nph;
+      r_8 phi0;
+      r_8 theta;
+      TVector<int_4> pixNumber; 
+      TVector<T> datan;
+      
+      map.GetThetaSlice(ith,theta,phi0, pixNumber,datan);
+      nph = pixNumber.NElts();
+
+      //       -----------------------------------------------------
+      //	      for each theta, and each m, computes
+      //	      b(m,theta) = sum_over_l>m (lambda_l_m(theta) * a_l_m) 
+      //	      ------------------------------------------------------
+      LambdaLMBuilder lb(theta,nlmax,nmmax);
+      //  somme sur m de 0 a l'infini
+      for (int m = 0; m <= nmmax; m++)
+	{
+	  //  somme sur l de m a l'infini
+	  b_m_theta(m) = (T)( lb.lamlm(m,m) ) * alm(m,m);
+	  //    if (ith==0 && m==0)
+	  //	{
+	  //	  cout << " guy: lmm= " <<  lb.lamlm(m,m) << " alm " << alm(m,m) << "b00= " <<  b_m_theta(m) << endl;
+	  //	} 
+	  for (int l = m+1; l<= nlmax; l++)
+	    {
+	       b_m_theta(m) += (T)( lb.lamlm(l,m) ) * alm(l,m);
+
+
+	       //     if (ith==0 && m==0)
+	       //	 {
+	       //	   cout << " guy:l=" << l << " m= " << m << " lmm= " <<  lb.lamlm(l,m) << " alm " << alm(l,m) << "b00= " <<  b_m_theta(m) << endl;
+
+	       //	 } 
+
+	    }
+	}
+
+    //        obtains the negative m of b(m,theta) (= complex conjugate)
+
+      for (int m=1;m<=nmmax;m++)
+	{
+	  //compiler doesn't have conj()
+	  b_m_theta(-m) = conj(b_m_theta(m));
+	}
+      // ---------------------------------------------------------------
+      //    sum_m  b(m,theta)*exp(i*m*phi)   -> f(phi,theta)
+      // ---------------------------------------------------------------*/
+      //    TVector<complex<T> > Temp = fourierSynthesisFromB(b_m_theta,nph,phi0); 
+	  TVector<T> Temp = RfourierSynthesisFromB(b_m_theta,nph,phi0);
+      for (int i=0;i< nph;i++)
+	{
+	  // 	  map(pixNumber(i))=Temp(i).real();
+	  	  	  map(pixNumber(i))=Temp(i);
+	}
+    }
+}
+
+
+
+template<class T>
+TVector< complex<T> >  SphericalTransformServer<T>::fourierSynthesisFromB(const Bm<complex<T> >& b_m,  int_4 nph, r_8 phi0) const
+{
+  /*=======================================================================
+     dataout(j) = sum_m datain(m) * exp(i*m*phi(j)) 
+     with phi(j) = j*2pi/nph + kphi0*pi/nph and kphi0 =0 or 1
+
+     as the set of frequencies {m} is larger than nph, 
+     we wrap frequencies within {0..nph-1}
+     ie  m = k*nph + m' with m' in {0..nph-1}
+     then
+     noting bw(m') = exp(i*m'*phi0) 
+                   * sum_k (datain(k*nph+m') exp(i*k*pi*kphi0))
+        with bw(nph-m') = CONJ(bw(m')) (if datain(-m) = CONJ(datain(m)))
+     dataout(j) = sum_m' [ bw(m') exp (i*j*m'*2pi/nph) ]
+                = Fourier Transform of bw
+        is real
+
+         NB nph is not necessarily a power of 2
+
+=======================================================================*/
+  //**********************************************************************
+  // pour une valeur de phi (indexee par j) la temperature est la transformee 
+  // de Fourier de bm (somme sur m de -nmax a +nmmax de bm*exp(i*m*phi)).
+  // on demande nph (nombre de pixels sur la tranche) valeurs de transformees, pour nph valeurs de phi, regulierement reparties sur 2*pi. On a:
+  //      DT/T(j) = sum_m b(m) * exp(i*m*phi(j)) 
+  // sommation de -infini a +infini, en fait limitee a -nmamx, +nmmax
+  // On pose m=k*nph + m', avec m' compris entre 0 et nph-1. Alors :
+  // DT/T(j) = somme_k somme_m'  b(k*nph + m')*exp(i*(k*nph + m')*phi(j))
+  // somme_k : de -infini a +infini
+  // somme_m' : de 0 a nph-1
+  // On echange les sommations :
+  // DT/T(j) = somme_k (exp(i*m'*phi(j)) somme_m' b(k*nph + m')*exp(i*(k*nph*phi(j))
+  // mais phi(j) est un multiple entier de 2*pi/nph, la seconde exponentielle 
+  // vaut 1.
+  // Il reste a calculer les transformees de Fourier de somme_m' b(k*nph + m')
+  // si phi0 n'est pas nul, il y a juste un decalage a faire.
+  //**********************************************************************
+
+  TVector< complex<T> > bw(nph);
+  TVector< complex<T> > dataout(nph);
+  TVector< complex<T> > data(nph);
+
+
+  for (int kk=0; kk<bw.NElts(); kk++) bw(kk)=(T)0.;
+  for (int m=-b_m.Mmax();m<=-1;m++)
+    {
+      int maux=m;
+      while (maux<0) maux+=nph;
+      int iw=maux%nph;
+      double aux=(m-iw)*phi0;
+      bw(iw) += b_m(m) * complex<T>( (T)cos(aux),(T)sin(aux) )  ;
+    }
+  for (int m=0;m<=b_m.Mmax();m++)
+    {
+      //      int iw=((m % nph) +nph) % nph; //between 0 and nph = m'
+      int iw=m%nph;
+      double aux=(m-iw)*phi0;
+      bw(iw)+=b_m(m) * complex<T>( (T)cos(aux),(T)sin(aux) );
+    }
+
+  //     applies the shift in position <-> phase factor in Fourier space
+  for (int mprime=0; mprime < nph; mprime++)
+    {
+      complex<double> aux(cos(mprime*phi0),sin(mprime*phi0));
+      data(mprime)=bw(mprime)*
+	               (complex<T>)(complex<double>(cos(mprime*phi0),sin(mprime*phi0)));
+    }
+
+  //sortie.ReSize(nph);
+  TVector< complex<T> > sortie(nph);
+  sortie.SetTemp(true);
+
+  fftIntfPtr_-> FFTBackward(data, sortie);
+  
+  return sortie;
+}
+
+//********************************************
+template<class T>
+TVector<T>  SphericalTransformServer<T>::RfourierSynthesisFromB(const Bm<complex<T> >& b_m,  int_4 nph, r_8 phi0) const
+{
+  /*=======================================================================
+     dataout(j) = sum_m datain(m) * exp(i*m*phi(j)) 
+     with phi(j) = j*2pi/nph + kphi0*pi/nph and kphi0 =0 or 1
+
+     as the set of frequencies {m} is larger than nph, 
+     we wrap frequencies within {0..nph-1}
+     ie  m = k*nph + m' with m' in {0..nph-1}
+     then
+     noting bw(m') = exp(i*m'*phi0) 
+                   * sum_k (datain(k*nph+m') exp(i*k*pi*kphi0))
+        with bw(nph-m') = CONJ(bw(m')) (if datain(-m) = CONJ(datain(m)))
+     dataout(j) = sum_m' [ bw(m') exp (i*j*m'*2pi/nph) ]
+                = Fourier Transform of bw
+        is real
+
+         NB nph is not necessarily a power of 2
+
+=======================================================================*/
+  //**********************************************************************
+  // pour une valeur de phi (indexee par j) la temperature est la transformee 
+  // de Fourier de bm (somme sur m de -nmax a +nmmax de bm*exp(i*m*phi)).
+  // on demande nph (nombre de pixels sur la tranche) valeurs de transformees, pour nph valeurs de phi, regulierement reparties sur 2*pi. On a:
+  //      DT/T(j) = sum_m b(m) * exp(i*m*phi(j)) 
+  // sommation de -infini a +infini, en fait limitee a -nmamx, +nmmax
+  // On pose m=k*nph + m', avec m' compris entre 0 et nph-1. Alors :
+  // DT/T(j) = somme_k somme_m'  b(k*nph + m')*exp(i*(k*nph + m')*phi(j))
+  // somme_k : de -infini a +infini
+  // somme_m' : de 0 a nph-1
+  // On echange les sommations :
+  // DT/T(j) = somme_k (exp(i*m'*phi(j)) somme_m' b(k*nph + m')*exp(i*(k*nph*phi(j))
+  // mais phi(j) est un multiple entier de 2*pi/nph, la seconde exponentielle 
+  // vaut 1.
+  // Il reste a calculer les transformees de Fourier de somme_m' b(k*nph + m')
+  // si phi0 n'est pas nul, il y a juste un decalage a faire.
+  //**********************************************************************
+
+  TVector< complex<T> > bw(nph);
+  TVector< complex<T> > dataout(nph);
+  TVector< complex<T> > data(nph/2+1);
+
+
+  for (int kk=0; kk<bw.NElts(); kk++) bw(kk)=(T)0.;
+  for (int m=-b_m.Mmax();m<=-1;m++)
+    {
+      int maux=m;
+      while (maux<0) maux+=nph;
+      int iw=maux%nph;
+      double aux=(m-iw)*phi0;
+      bw(iw) += b_m(m) * complex<T>( (T)cos(aux),(T)sin(aux) )  ;
+    }
+  for (int m=0;m<=b_m.Mmax();m++)
+    {
+      //      int iw=((m % nph) +nph) % nph; //between 0 and nph = m'
+      int iw=m%nph;
+      double aux=(m-iw)*phi0;
+      bw(iw)+=b_m(m) * complex<T>( (T)cos(aux),(T)sin(aux) );
+    }
+
+  //     applies the shift in position <-> phase factor in Fourier space
+  for (int mprime=0; mprime <= nph/2; mprime++)
+    {
+      complex<double> aux(cos(mprime*phi0),sin(mprime*phi0));
+      data(mprime)=bw(mprime)*
+	               (complex<T>)(complex<double>(cos(mprime*phi0),sin(mprime*phi0)));
+    }
+
+  //sortie.ReSize(nph);
+  TVector<T> sortie;
+  sortie.SetTemp(true);
+
+  fftIntfPtr_-> FFTBackward(data, sortie);
+  
+  return sortie;
+}
+//*******************************************
+
+template<class T>
+ Alm<T> SphericalTransformServer<T>::DecomposeToAlm(const SphericalMap<T>& map, int_4 nlmax, r_8 cos_theta_cut) const
+{
+  
+  /*-----------------------------------------------------------------------
+    computes the integral in phi : phas_m(theta)
+    for each parallele from north to south pole
+    -----------------------------------------------------------------------*/
+  TVector<T> data;
+  TVector<int_4> pixNumber;
+  int_4  nmmax = nlmax;
+  TVector< complex<T> > phase(nmmax+1);
+  Alm<T> alm;
+  alm.SetTemp(true);
+  alm.ReSizeToLmax(nlmax);
+  for (int_4 ith = 0; ith < map.NbThetaSlices(); ith++)
+    {
+      int_4 nph;
+      r_8 phi0;
+      r_8 theta;
+      map.GetThetaSlice(ith,theta,phi0,pixNumber ,data);
+      for (int i=0;i< nmmax+1;i++)
+	{
+	  phase(i)=0; 
+	}
+      nph = pixNumber.NElts(); 
+      double cth = cos(theta);
+      
+      //part of the sky out of the symetric cut
+      bool keep_it = (abs(cth) >= cos_theta_cut); 
+      
+      if (keep_it)
+	{
+	  // tableau datain a supprimer
+	  //  TVector<complex<T> > datain(nph);
+	  // for(int kk=0; kk<nph; kk++) datain(kk)=complex<T>(data(kk),(T)0.);
+
+	  //  phase = CFromFourierAnalysis(nmmax,datain,phi0);
+	  phase = CFromFourierAnalysis(nmmax,data,phi0);
+
+	}
+      
+      /*-----------------------------------------------------------------------
+	computes the a_lm by integrating over theta
+	lambda_lm(theta) * phas_m(theta)
+	for each m and l
+	-----------------------------------------------------------------------*/
+      //      LambdaBuilder lb(theta,nlmax,nmmax);
+      LambdaLMBuilder lb(theta,nlmax,nmmax);
+      r_8 domega=map.PixSolAngle(map.PixIndexSph(theta,phi0));
+      for (int m = 0; m <= nmmax; m++)
+	{
+	  alm(m,m) += (T)lb.lamlm(m,m) * phase(m) * (T)domega; //m,m even
+	  for (int l = m+1; l<= nlmax; l++)
+	    {
+	      alm(l,m) += (T)lb.lamlm(l,m) * phase(m)*(T)domega; 
+	    }
+	}
+    }
+  return alm;
+}
+template<class T>
+TVector< complex<T> > SphericalTransformServer<T>::CFromFourierAnalysis(int_4 nmmax, const TVector<complex<T> >datain, r_8 phi0) const
+{
+  /*=======================================================================
+    integrates (data * phi-dependence-of-Ylm) over phi
+    --> function of m can be computed by FFT
+    
+    datain est modifie
+    =======================================================================*/
+  int_4 nph=datain.NElts();
+  if (nph <= 0) 
+    {
+      throw PException("bizarre : vecteur datain de longueur nulle (CFromFourierAnalysis)");
+    }
+  TVector<complex<T> > transformedData(nph);
+  fftIntfPtr_-> FFTForward(datain, transformedData);
+
+  //dataout.ReSize(nmmax+1);
+  TVector< complex<T> > dataout(nmmax+1);
+  //  dataout.SetTemp(true);
+
+  int im_max=min(nph,nmmax+1);
+  for (int i=0;i< dataout.NElts();i++) dataout(i)=complex<T>((T)0.,(T)0.);
+  for (int i=0;i<im_max;i++) dataout(i)=transformedData(i);
+
+
+  //  for (int i = 0;i <im_max;i++){
+  //    dataout(i)*= (complex<T>)(complex<double>(cos(-i*phi0),sin(-i*phi0)));
+  //  }
+  for (int kk=nph; kk<dataout.NElts(); kk++) dataout(kk)=dataout(kk%nph);
+  for (int i = 0;i <dataout.NElts();i++){
+    dataout(i)*= (complex<T>)(complex<double>(cos(-i*phi0),sin(-i*phi0)));
+  }
+  return dataout;
+}
+
+//&&&&&&&&& nouvelle version
+template<class T>
+TVector< complex<T> > SphericalTransformServer<T>::CFromFourierAnalysis(int_4 nmmax, const TVector<T> datain, r_8 phi0) const
+{
+  //=======================================================================
+  //    integrates (data * phi-dependence-of-Ylm) over phi
+  //    --> function of m can be computed by FFT
+  //   !     with  0<= m <= npoints/2 (: Nyquist)
+  //   !     because the data is real the negative m are the conjugate of the 
+  //   !     positive ones
+    
+  //    datain est modifie
+  //    
+  //    =======================================================================
+  int_4 nph=datain.NElts();
+  if (nph <= 0) 
+    {
+      throw PException("bizarre : vecteur datain de longueur nulle (CFromFourierAnalysis)");
+    }
+  TVector<complex<T> > transformedData;
+    // a remodifier
+  //FFTPackServer ffts;
+  //ffts.setNormalize(false);
+  //ffts.FFTForward(datain, transformedData);
+
+  fftIntfPtr_-> FFTForward(datain, transformedData);
+    //
+
+  //dataout.ReSize(nmmax+1);
+  TVector< complex<T> > dataout(nmmax+1);
+  //  dataout.SetTemp(true); 
+
+  // on transfere le resultat de la fft dans dataout.
+  // on s'assure que ca ne depasse pas la taille de dataout
+  int sizeOfTransformToGet = min(transformedData.NElts(),nmmax+1);
+  //  int im_max=min(transformedData.NElts()-1,nmmax);
+  for (int i=0;i<sizeOfTransformToGet;i++) dataout(i)=transformedData(i);
+
+
+  // si dataout n'est pas plein, on complete jusqu'a  nph valeurs (a moins 
+  // que dataout ne soit plein avant d'atteindre nph)
+  if (sizeOfTransformToGet == (transformedData.NElts()))
+    {
+      for (int i=transformedData.NElts(); i<min(nph,dataout.NElts()); i++)
+	{
+
+	  //	  dataout(i) = conj(dataout(2*sizeOfTransformToGet-i-2) );
+	  dataout(i) = conj(dataout(nph-i) );
+	}
+      // on conplete, si necessaire, par periodicite
+      for (int kk=nph; kk<dataout.NElts(); kk++) 
+	{
+	  dataout(kk)=dataout(kk%nph);
+	}
+    }
+  for (int i = 0;i <dataout.NElts();i++){
+    dataout(i)*= (complex<T>)(complex<double>(cos(-i*phi0),sin(-i*phi0)));
+  }
+  return dataout;
+}
+
+template<class T>
+void SphericalTransformServer<T>::GenerateFromAlm(SphericalMap<T>& mapq,
+					       SphericalMap<T>& mapu, 
+					       int_4 pixelSizeIndex,
+					       const Alm<T>& alme,
+					       const Alm<T>& almb) const
+{
+  /*=======================================================================
+    computes a map form its alm for the HEALPIX pixelisation
+    map(theta,phi) = sum_l_m a_lm Y_lm(theta,phi)
+    = sum_m {e^(i*m*phi) sum_l a_lm*lambda_lm(theta)}
+    
+    where Y_lm(theta,phi) = lambda(theta) * e^(i*m*phi)
+    
+    * the recurrence of Ylm is the standard one (cf Num Rec)
+    * the sum over m is done by FFT
+    
+    =======================================================================*/
+  int_4 nlmax=alme.Lmax();
+  if (nlmax != almb.Lmax())
+    {
+      cout << " SphericalTransformServer: les deux tableaux alm n'ont pas la meme taille" << endl;
+      throw SzMismatchError("SphericalTransformServer: les deux tableaux alm n'ont pas la meme taille");
+    }
+  int_4 nmmax=nlmax;
+  int_4 nsmax=0;
+  mapq.Resize(pixelSizeIndex);
+  mapu.Resize(pixelSizeIndex);
+  char* sphere_type=mapq.TypeOfMap();
+  if (strncmp(sphere_type,mapu.TypeOfMap(),4) != 0)
+    {
+      cout <<  " SphericalTransformServer: les deux spheres ne sont pas de meme type" << endl;
+      cout << " type 1 " << sphere_type << endl;
+      cout << " type 2 " << mapu.TypeOfMap() << endl;
+      throw SzMismatchError("SphericalTransformServer: les deux spheres ne sont pas de meme type");
+      
+    }
+  if (strncmp(sphere_type,"RING",4) == 0)
+    {
+      nsmax=mapq.SizeIndex();
+    }
+  else
+    // pour une sphere Gorski le nombre de pixels est 12*nsmax**2
+    // on calcule une quantite equivalente a nsmax pour la sphere-theta-phi
+    // en vue de l'application du critere Healpix : nlmax<=3*nsmax-1
+    // c'est approximatif ; a raffiner.
+    if (strncmp(sphere_type,"TETAFI",6) == 0)
+      {
+	nsmax=(int_4)sqrt(mapq.NbPixels()/12.);
+      }
+    else
+      {
+	cout << " unknown type of sphere : " << sphere_type << endl;
+	throw IOExc(" unknown type of sphere ");
+      }
+  cout << "GenerateFromAlm: the spheres are of type : " << sphere_type << endl;
+  cout << "GenerateFromAlm: size indices (nside) of  spheres= " << nsmax << endl;
+  cout << "GenerateFromAlm: nlmax (from Alm) = " << nlmax << endl;
+  if (nlmax>3*nsmax-1) 
+    {
+      cout << "GenerateFromAlm: nlmax should be <= 3*nside-1" << endl;
+      if (strncmp(sphere_type,"TETAFI",6) == 0)
+	{
+	  cout << " (for this criterium, nsmax is computed as sqrt(nbPixels/12))" << endl;
+	}
+    }
+  if (alme.Lmax()!=almb.Lmax())
+    {
+      cout << "GenerateFromAlm: arrays Alme and Almb have not the same size ? " << endl; 
+      throw SzMismatchError("SphericalTransformServer: arrays Alme and Almb have not the same size ?  ");
+    }
+    mapFromWX(nlmax, nmmax, mapq, mapu, alme, almb);
+    // mapFromPM(nlmax, nmmax, mapq, mapu, alme, almb);
+}
+
+
+template<class T>
+void SphericalTransformServer<T>::DecomposeToAlm(const SphericalMap<T>& mapq,
+					      const SphericalMap<T>& mapu,
+					      Alm<T>& alme,
+					      Alm<T>& almb,
+					      int_4 nlmax,
+					      r_8 cos_theta_cut) const
+{
+  int_4  nmmax = nlmax;
+  // resize et remise a zero
+  alme.ReSizeToLmax(nlmax);
+  almb.ReSizeToLmax(nlmax);
+
+  
+  TVector<T> dataq;
+  TVector<T> datau;
+  TVector<int_4> pixNumber;
+
+  char* sphere_type=mapq.TypeOfMap();
+  if (strncmp(sphere_type,mapu.TypeOfMap(),4) != 0)
+    {
+      cout <<  " SphericalTransformServer: les deux spheres ne sont pas de meme type" << endl;
+      cout << " type 1 " << sphere_type << endl;
+      cout << " type 2 " << mapu.TypeOfMap() << endl;
+      throw SzMismatchError("SphericalTransformServer: les deux spheres ne sont pas de meme type");
+      
+    }
+  if (mapq.NbPixels()!=mapu.NbPixels())
+    {
+      cout << " DecomposeToAlm: map Q and map U have not same size ?" << endl;
+      throw SzMismatchError("SphericalTransformServer::DecomposeToAlm: map Q and map U have not same size ");
+    }
+  for (int_4 ith = 0; ith < mapq.NbThetaSlices(); ith++)
+    {
+      int_4 nph;
+      r_8 phi0;
+      r_8 theta;
+      mapq.GetThetaSlice(ith,theta,phi0, pixNumber,dataq);
+      mapu.GetThetaSlice(ith,theta,phi0, pixNumber,datau);
+      if (dataq.NElts() != datau.NElts() ) 
+	{
+	  throw  SzMismatchError("the spheres have not the same pixelization");
+	}
+      nph = pixNumber.NElts();
+      r_8 domega=mapq.PixSolAngle(mapq.PixIndexSph(theta,phi0));
+      double cth = cos(theta);
+      //part of the sky out of the symetric cut
+      bool keep_it = (abs(cth) >= cos_theta_cut); 
+      if (keep_it)
+	{
+	  //  almFromPM(nph, nlmax, nmmax, phi0, domega, theta, dataq, datau, alme, almb); 
+	  almFromWX(nlmax, nmmax, phi0, domega, theta, dataq, datau, alme, almb); 
+	}
+    }
+}
+
+
+template<class T>
+void SphericalTransformServer<T>::almFromWX(int_4 nlmax, int_4 nmmax,
+					 r_8 phi0, r_8 domega, 
+					 r_8 theta, 
+					 const TVector<T>& dataq, 
+					 const TVector<T>& datau,
+					 Alm<T>& alme,
+					 Alm<T>& almb) const
+{
+  TVector< complex<T> > phaseq(nmmax+1);
+  TVector< complex<T> > phaseu(nmmax+1);
+  //  TVector<complex<T> > datain(nph);
+  for (int i=0;i< nmmax+1;i++)
+    {
+      phaseq(i)=0; 
+      phaseu(i)=0; 
+    }
+  //  for(int kk=0; kk<nph; kk++) datain(kk)=complex<T>(dataq(kk),0.);
+
+  // phaseq = CFromFourierAnalysis(nmmax,datain,phi0); 
+  phaseq = CFromFourierAnalysis(nmmax,dataq,phi0); 
+
+  // for(int kk=0; kk<nph; kk++) datain(kk)=complex<T>(datau(kk),0.);
+
+  // phaseu=  CFromFourierAnalysis(nlmax,nmmax,datain,phi0); 
+  phaseu=  CFromFourierAnalysis(nmmax,datau,phi0); 
+
+  LambdaWXBuilder lwxb(theta,nlmax,nmmax);
+
+  r_8 sqr2inv=1/Rac2;
+  for (int m = 0; m <= nmmax; m++)
+    {
+      r_8 lambda_w=0.;
+      r_8 lambda_x=0.;
+      lwxb.lam_wx(m, m, lambda_w, lambda_x);
+      complex<T>  zi_lam_x((T)0., (T)lambda_x);
+      alme(m,m) +=  ( (T)(lambda_w)*phaseq(m)-zi_lam_x*phaseu(m) )*(T)(domega*sqr2inv);
+      almb(m,m) +=  ( (T)(lambda_w)*phaseu(m)+zi_lam_x*phaseq(m) )*(T)(domega*sqr2inv);
+      
+      for (int l = m+1; l<= nlmax; l++)
+	{
+	  lwxb.lam_wx(l, m, lambda_w, lambda_x);
+	  zi_lam_x = complex<T>((T)0., (T)lambda_x);
+	  alme(l,m) +=  ( (T)(lambda_w)*phaseq(m)-zi_lam_x*phaseu(m) )*(T)(domega*sqr2inv);
+	  almb(l,m) +=  ( (T)(lambda_w)*phaseu(m)+zi_lam_x*phaseq(m) )*(T)(domega*sqr2inv);
+	}
+    }
+}
+
+
+template<class T>
+void SphericalTransformServer<T>::almFromPM(int_4 nph, int_4 nlmax, int_4 nmmax,
+					 r_8 phi0, r_8 domega,  
+					 r_8 theta, 
+					 const TVector<T>& dataq, 
+					 const TVector<T>& datau,
+					 Alm<T>& alme,
+					 Alm<T>& almb) const
+{
+  TVector< complex<T> > phasep(nmmax+1);
+  TVector< complex<T> > phasem(nmmax+1);
+  TVector<complex<T> > datain(nph);
+  for (int i=0;i< nmmax+1;i++)
+    {
+      phasep(i)=0; 
+      phasem(i)=0; 
+    }
+
+  for(int kk=0; kk<nph; kk++) datain(kk)=complex<T>(dataq(kk),datau(kk));
+
+  phasep = CFromFourierAnalysis(nmmax,datain,phi0); 
+
+  for(int kk=0; kk<nph; kk++) datain(kk)=complex<T>(dataq(kk),-datau(kk));
+  phasem = CFromFourierAnalysis(nmmax,datain,phi0); 
+  LambdaPMBuilder lpmb(theta,nlmax,nmmax);
+	  
+  for (int m = 0; m <= nmmax; m++)
+    {
+      r_8 lambda_p=0.;
+      r_8 lambda_m=0.;
+      complex<T> im((T)0.,(T)1.);
+      lpmb.lam_pm(m, m, lambda_p, lambda_m);
+	      
+      alme(m,m) +=   -( (T)(lambda_p)*phasep(m) + (T)(lambda_m)*phasem(m)  )*(T)(domega*0.5);
+      almb(m,m) +=  im*( (T)(lambda_p)*phasep(m) - (T)(lambda_m)*phasem(m) )*(T)(domega*0.5);
+      for (int l = m+1; l<= nlmax; l++)
+	{
+	  lpmb.lam_pm(l, m, lambda_p, lambda_m);
+	  alme(l,m) +=  -( (T)(lambda_p)*phasep(m) + (T)(lambda_m)*phasem(m)  )*(T)(domega*0.5);
+	  almb(l,m) += im* ( (T)(lambda_p)*phasep(m) - (T)(lambda_m)*phasem(m) )*(T)(domega*0.5);
+	}
+    }
+}
+
+
+template<class T>
+void SphericalTransformServer<T>::mapFromWX(int_4 nlmax, int_4 nmmax,
+					 SphericalMap<T>& mapq,
+					 SphericalMap<T>& mapu, 
+					 const Alm<T>& alme,
+					 const Alm<T>& almb) const
+{
+  Bm<complex<T> > b_m_theta_q(nmmax);
+  Bm<complex<T> > b_m_theta_u(nmmax);
+
+  for (int_4 ith = 0; ith < mapq.NbThetaSlices();ith++)
+    {
+      int_4 nph;
+      r_8 phi0;
+      r_8 theta;
+      TVector<int_4>  pixNumber; 
+      TVector<T> datan;
+      
+      mapq.GetThetaSlice(ith,theta,phi0, pixNumber,datan);
+      nph =  pixNumber.NElts();
+      //       -----------------------------------------------------
+      //	      for each theta, and each m, computes
+      //	      b(m,theta) = sum_over_l>m (lambda_l_m(theta) * a_l_m) 
+      //	      ------------------------------------------------------
+      LambdaWXBuilder lwxb(theta,nlmax,nmmax);
+      //      LambdaPMBuilder lpmb(theta,nlmax,nmmax);
+      r_8 sqr2inv=1/Rac2;
+      for (int m = 0; m <= nmmax; m++)
+	{
+	  r_8 lambda_w=0.;
+	  r_8 lambda_x=0.;
+	  lwxb.lam_wx(m, m, lambda_w, lambda_x);
+	  complex<T>  zi_lam_x((T)0., (T)lambda_x);
+	  
+	  b_m_theta_q(m) =  ( (T)(lambda_w) * alme(m,m) - zi_lam_x * almb(m,m))*(T)sqr2inv ;
+	  b_m_theta_u(m) =  ( (T)(lambda_w) * almb(m,m) + zi_lam_x * alme(m,m))*(T)sqr2inv;
+	  
+	  
+	  for (int l = m+1; l<= nlmax; l++)
+	    {
+	      
+	      lwxb.lam_wx(l, m, lambda_w, lambda_x);
+	      zi_lam_x= complex<T>((T)0., (T)lambda_x);
+	      
+	      b_m_theta_q(m) += ((T)(lambda_w)*alme(l,m)-zi_lam_x *almb(l,m))*(T)sqr2inv;
+	      b_m_theta_u(m) += ((T)(lambda_w)*almb(l,m)+zi_lam_x *alme(l,m))*(T)sqr2inv;
+	      
+	    } 
+	}
+      //        obtains the negative m of b(m,theta) (= complex conjugate)
+      for (int m=1;m<=nmmax;m++)
+	{
+	  b_m_theta_q(-m) = conj(b_m_theta_q(m));
+	  b_m_theta_u(-m) = conj(b_m_theta_u(m));
+	}
+
+      //    TVector<complex<T> > Tempq = fourierSynthesisFromB(b_m_theta_q,nph,phi0);  
+      //     TVector<complex<T> > Tempu = fourierSynthesisFromB(b_m_theta_u,nph,phi0); 
+      TVector<T> Tempq = RfourierSynthesisFromB(b_m_theta_q,nph,phi0);  
+      TVector<T> Tempu = RfourierSynthesisFromB(b_m_theta_u,nph,phi0); 
+      for (int i=0;i< nph;i++)
+	{
+	  //	  mapq(pixNumber(i))=Tempq(i).real();
+	  //	  mapu(pixNumber(i))=Tempu(i).real();
+	  mapq(pixNumber(i))=Tempq(i);
+	  mapu(pixNumber(i))=Tempu(i);
+	  
+	}
+    } 
+}
+template<class T>
+void SphericalTransformServer<T>::mapFromPM(int_4 nlmax, int_4 nmmax,
+					 SphericalMap<T>& mapq,
+					 SphericalMap<T>& mapu, 
+					 const Alm<T>& alme,
+					 const Alm<T>& almb) const
+{
+  Bm<complex<T> > b_m_theta_p(nmmax);
+  Bm<complex<T> > b_m_theta_m(nmmax);
+  for (int_4 ith = 0; ith < mapq.NbThetaSlices();ith++)
+    {
+      int_4 nph;
+      r_8 phi0;
+      r_8 theta;
+      TVector<int_4> pixNumber; 
+      TVector<T> datan;
+      
+      mapq.GetThetaSlice(ith,theta,phi0, pixNumber,datan);
+      nph =  pixNumber.NElts();
+
+      //       -----------------------------------------------------
+      //	      for each theta, and each m, computes
+      //	      b(m,theta) = sum_over_l>m (lambda_l_m(theta) * a_l_m) 
+      //------------------------------------------------------
+
+      LambdaPMBuilder lpmb(theta,nlmax,nmmax);
+      for (int m = 0; m <= nmmax; m++)
+	{
+	  r_8 lambda_p=0.;
+	  r_8 lambda_m=0.;
+	  lpmb.lam_pm(m, m, lambda_p, lambda_m);
+	  complex<T> im((T)0.,(T)1.);
+	  
+	  b_m_theta_p(m) =  (T)(lambda_p )* (-alme(m,m) - im * almb(m,m));
+	  b_m_theta_m(m) =  (T)(lambda_m) * (-alme(m,m) + im * almb(m,m));
+	  
+	  
+	  for (int l = m+1; l<= nlmax; l++)
+	    {
+	      lpmb.lam_pm(l, m, lambda_p, lambda_m);
+	      b_m_theta_p(m) +=  (T)(lambda_p)*(-alme(l,m)-im *almb(l,m));
+	      b_m_theta_m(m) +=  (T)(lambda_m)*(-alme(l,m)+im *almb(l,m));
+	    }
+	}
+      
+      //        obtains the negative m of b(m,theta) (= complex conjugate)
+      for (int m=1;m<=nmmax;m++)
+	{
+	  b_m_theta_p(-m) = conj(b_m_theta_m(m));
+	  b_m_theta_m(-m) = conj(b_m_theta_p(m));
+	}
+
+      TVector<complex<T> > Tempp = fourierSynthesisFromB(b_m_theta_p,nph,phi0);  
+      TVector<complex<T> > Tempm = fourierSynthesisFromB(b_m_theta_m,nph,phi0); 
+
+      for (int i=0;i< nph;i++)
+	{
+	  	  mapq(pixNumber(i))=0.5*(Tempp(i)+Tempm(i)).real();
+	  	  mapu(pixNumber(i))=0.5*(Tempp(i)-Tempm(i)).imag();
+	}
+    }
+}
+
+
+template<class T>
+void SphericalTransformServer<T>::GenerateFromCl(SphericalMap<T>& sphq, 
+					      SphericalMap<T>& sphu, 
+					      int_4 pixelSizeIndex,
+					      const TVector<T>& Cle, 
+					      const TVector<T>& Clb, 
+					      const r_8 fwhm) const
+{
+  if (Cle.NElts() != Clb.NElts())
+    {
+      cout << " SphericalTransformServer: les deux tableaux Cl n'ont pas la meme taille" << endl;
+      throw SzMismatchError("SphericalTransformServer::GenerateFromCl :  two Cl arrays have not same size");
+    }
+
+  //  Alm<T> a2lme,a2lmb;
+  //  almFromCl(a2lme, Cle, fwhm); 
+  //  almFromCl(a2lmb, Clb, fwhm); 
+  //  Alm<T> a2lme = almFromCl(Cle, fwhm);
+  // Alm<T> a2lmb = almFromCl(Clb, fwhm);
+  Alm<T> a2lme(Cle, fwhm);
+  Alm<T> a2lmb(Clb, fwhm);
+
+  GenerateFromAlm(sphq,sphu,pixelSizeIndex,a2lme,a2lmb); 
+}
+template<class T>
+void SphericalTransformServer<T>::GenerateFromCl(SphericalMap<T>& sph,
+						 int_4 pixelSizeIndex, 
+					      const TVector<T>& Cl, 
+						 const r_8 fwhm)  const
+{
+
+  Alm<T> alm(Cl, fwhm);
+  GenerateFromAlm(sph,pixelSizeIndex, alm ); 
+}
+
+
+
+template <class T>
+TVector<T>  SphericalTransformServer<T>::DecomposeToCl(const SphericalMap<T>& sph, int_4 nlmax, r_8 cos_theta_cut) const
+{
+    Alm<T> alm=DecomposeToAlm( sph, nlmax, cos_theta_cut);
+  // power spectrum
+     return  alm.powerSpectrum();
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template SphericalTransformServer<r_8>
+#pragma define_template SphericalTransformServer<r_4>
+#endif
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class SphericalTransformServer<r_8>;
+template class SphericalTransformServer<r_4>;
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/sphericaltransformserver.h	(revision 752)
@@ -0,0 +1,206 @@
+#ifndef SPHERICALTRANFORMSERVER_SEEN
+#define SPHERICALTRANFORMSERVER_SEEN
+
+#include "sphericalmap.h"
+#include "spheregorski.h"
+#include "fftservintf.h"
+#include "fftpserver.h"
+#include "alm.h"
+#include "lambdaBuilder.h"
+
+
+namespace SOPHYA {
+
+//
+/*! Class for performing analysis and synthesis of sky maps using spin-0 or spin-2 spherical harmonics.
+ */
+template <class T>
+class SphericalTransformServer
+{
+
+ public:
+
+ SphericalTransformServer()  
+{
+    fftIntfPtr_=new FFTPackServer;
+    fftIntfPtr_->setNormalize(false);
+};
+ ~SphericalTransformServer(){ if (fftIntfPtr_!=NULL) delete fftIntfPtr_;};
+/*!
+ Set a fft server. The constructor sets a default fft server (fft-pack). So it is not necessary to call this method for a standard use.
+*/
+ void SetFFTServer(FFTServerInterface* srv=NULL) 
+{
+  if (fftIntfPtr_!=NULL) delete fftIntfPtr_;
+  fftIntfPtr_=srv;
+  fftIntfPtr_->setNormalize(false);
+}
+ /*! synthesis of a temperature  map from  Alm coefficients */
+ void GenerateFromAlm( SphericalMap<T>& map, int_4 pixelSizeIndex, const Alm<T>& alm) const; 
+ /*! synthesis of a polarization map from  Alm coefficients. The spheres mapq and mapu contain respectively the Stokes parameters. */
+ void GenerateFromAlm(SphericalMap<T>& mapq, SphericalMap<T>& mapu, int_4 pixelSizeIndex, const Alm<T>& alme,    const Alm<T>& almb) const;
+
+ /*! synthesis of a temperature  map from  power spectrum Cl (Alm's are generated randomly, following a gaussian distribution). */
+ void GenerateFromCl(SphericalMap<T>& sph, int_4 pixelSizeIndex,
+		     const TVector<T>& Cl, const r_8 fwhm) const; 
+  /*! synthesis of a polarization  map from  power spectra electric-Cl and magnetic-Cl (Alm's are generated randomly, following a gaussian distribution). 
+  \param fwhm FWHM in arcmin for random generation of Alm's (eg. 5) 
+
+*/
+ void GenerateFromCl(SphericalMap<T>& sphq, SphericalMap<T>& sphu, 
+		     int_4 pixelSizeIndex,
+		     const TVector<T>& Cle, const TVector<T>& Clb, 
+		    const r_8 fwhm) const; 
+ /*!return the Alm coefficients from analysis of a temperature map.
+
+    nlmax : maximum value of the l index
+
+     cos_theta_cut : cosinus of the symmetric cut EULER angle theta : cos_theta_cut=0 means no cut ; cos_theta_cut=1 all the sphere is cut.
+  */ 
+
+
+Alm<T> DecomposeToAlm(const SphericalMap<T>& map, int_4 nlmax, r_8 cos_theta_cut) const;
+ /*analysis of a polarization map into Alm coefficients.
+
+ The spheres mapq and mapu contain respectively the Stokes parameters. 
+
+ a2lme and a2lmb will receive respectively electric and magnetic Alm's
+    nlmax : maximum value of the l index
+
+    cos_theta_cut : cosinus of the symmetric cut EULER angle theta : cos_theta_cut=0 means no cut ; cos_theta_cut=1 all the sphere is cut.
+ */ 
+
+ void DecomposeToAlm(const SphericalMap<T>& mapq, const SphericalMap<T>& mapu,
+		     Alm<T>& a2lme, Alm<T>& a2lmb,
+		     int_4 nlmax, r_8 cos_theta_cut) const;
+
+ // /*return power spectrum from analysis of a temperature map.
+
+ //    nlmax : maximum value of the l index
+
+ //    cos_theta_cut : cosinus of the symmetric cut EULER angle theta : cos_theta_cut=0 means no cut ; cos_theta_cut=1 all the sphere is cut.
+ // */ 
+ TVector<T>  DecomposeToCl(const SphericalMap<T>& sph,  
+			   int_4 nlmax, r_8 cos_theta_cut) const;
+
+
+  private:
+  /*! return a vector with nph elements  which are  sums :\f$\sum_{m=-mmax}^{mmax}b_m(\theta)e^{im\varphi}\f$ for nph values of \f$\varphi\f$ regularly distributed in \f$[0,\pi]\f$ ( calculated by FFT)
+
+  The object b_m (\f$b_m\f$) of the class Bm is a special vector which index goes from -mmax to mmax. 
+  */
+ TVector< complex<T> >  fourierSynthesisFromB(const Bm<complex<T> >& b_m,  
+				  int_4 nph, r_8 phi0) const;
+/*! same as fourierSynthesisFromB, but return a real vector, taking into account the fact that b(-m) is conjugate of b(m) */
+ TVector<T>  RfourierSynthesisFromB(const Bm<complex<T> >& b_m,  
+				  int_4 nph, r_8 phi0) const;
+
+  /*! return a vector with mmax elements  which are  sums :
+\f$\sum_{k=0}^{nphi}datain(\theta,\varphi_k)e^{im\varphi_k}\f$ for (mmax+1) values of \f$m\f$ from 0 to mmax.
+   */
+ TVector< complex<T> > CFromFourierAnalysis(int_4 mmax, 
+				  const TVector<complex<T> > datain,
+				  r_8 phi0) const;
+/* same as previous one, but with a "datain" which is real (not complex) */
+ TVector< complex<T> > CFromFourierAnalysis(int_4 mmax, 
+			 const TVector<T> datain,  
+				  r_8 phi0) const;
+
+ /*! 
+Compute polarized Alm's as : 
+\f[
+a_{lm}^E=\frac{1}{\sqrt{2}}\sum_{slices}{\omega_{pix}\left(_{w}\lambda_l^m\tilde{Q}-i_{x}\lambda_l^m\tilde{U}\right)}
+\f]
+\f[
+a_{lm}^B=\frac{1}{\sqrt{2}}\sum_{slices}{\omega_{pix}\left(i_{x}\lambda_l^m\tilde{Q}+_{w}\lambda_l^m\tilde{U}\right)}
+\f]
+
+where \f$\tilde{Q}\f$ and \f$\tilde{U}\f$ are C-coefficients computed by FFT (method CFromFourierAnalysis, called by present method) from the Stokes parameters.
+
+\f$\omega_{pix}\f$ are solid angle of each pixel.
+
+dataq, datau : Stokes parameters.
+
+  */
+void almFromWX(int_4 nlmax, int_4 nmmax, r_8 phi0, 
+	       r_8 domega, r_8 theta, 
+	       const TVector<T>& dataq, const TVector<T>& datau,
+	       Alm<T>& alme, Alm<T>& almb) const;
+ /*! 
+Compute polarized Alm's as : 
+\f[
+a_{lm}^E=-\frac{1}{2}\sum_{slices}{\omega_{pix}\left(_{+}\lambda_l^m\tilde{P^+}+_{-}\lambda_l^m\tilde{P^-}\right)}
+\f]
+\f[
+a_{lm}^B=\frac{i}{2}\sum_{slices}{\omega_{pix}\left(_{+}\lambda_l^m\tilde{P^+}-_{-}\lambda_l^m\tilde{P^-}\right)}
+\f]
+
+where \f$\tilde{P^{\pm}}=\tilde{Q}\pm\tilde{U}\f$  computed by FFT (method CFromFourierAnalysis, called by present method) from the Stokes parameters,\f$Q\f$ and \f$U\f$ .
+
+\f$\omega_{pix}\f$ are solid angle of each pixel.
+
+dataq, datau : Stokes parameters.
+
+  */
+void almFromPM(int_4 nph, int_4 nlmax, int_4 nmmax, 
+	       r_8 phi0, r_8 domega, r_8 theta, 
+	       const TVector<T>& dataq, const TVector<T>& datau,
+	       Alm<T>& alme, Alm<T>& almb) const;
+
+/*! synthesis of Stokes parameters following formulae : 
+
+\f[
+Q=\sum_{m=-mmax}^{mmax}b_m^qe^{im\varphi}
+\f]
+\f[
+U=\sum_{m=-mmax}^{mmax}b_m^ue^{im\varphi}
+\f]
+
+computed by FFT (method fourierSynthesisFromB called by the present one)
+
+with :
+
+\f[
+b_m^q=-\frac{1}{\sqrt{2}}\sum_{l=|m|}^{lmax}{\left(_{w}\lambda_l^ma_{lm}^E-i_{x}\lambda_l^ma_{lm}^B\right) }
+\f]
+\f[
+b_m^u=\frac{1}{\sqrt{2}}\sum_{l=|m|}^{lmax}{\left(i_{x}\lambda_l^ma_{lm}^E+_{w}\lambda_l^ma_{lm}^B\right) }
+\f]
+ */
+void mapFromWX(int_4 nlmax, int_4 nmmax,
+	       SphericalMap<T>& mapq, SphericalMap<T>& mapu, 
+	       const Alm<T>& alme, const Alm<T>& almb) const;
+
+/*! synthesis of polarizations following formulae : 
+
+\f[
+P^+ = \sum_{m=-mmax}^{mmax} {b_m^+e^{im\varphi} }
+\f]
+\f[
+P^- = \sum_{m=-mmax}^{mmax} {b_m^-e^{im\varphi} }
+\f]
+
+computed by FFT (method fourierSynthesisFromB called by the present one)
+
+with :
+
+\f[
+b_m^+=-\sum_{l=|m|}^{lmax}{_{+}\lambda_l^m \left( a_{lm}^E+ia_{lm}^B \right) }
+\f]
+\f[
+b_m^-=-\sum_{l=|m|}^{lmax}{_{+}\lambda_l^m \left( a_{lm}^E-ia_{lm}^B \right) }
+\f]
+ */
+
+void mapFromPM(int_4 nlmax, int_4 nmmax,
+	       SphericalMap<T>& mapq, SphericalMap<T>& mapu, 
+	       const Alm<T>& alme, const Alm<T>& almb) const;
+
+
+
+ FFTServerInterface* fftIntfPtr_;
+};
+} // Fin du namespace
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/tod.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/tod.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/tod.h	(revision 752)
@@ -0,0 +1,56 @@
+// This may look like C code, but it is really -*- C++ -*-
+#ifndef TOD_H_SEEN
+#define TOD_H_SEEN
+
+#include "machdefs.h"
+#include "spherepos.h"
+#include "misstime.h"
+
+namespace SOPHYA {
+template<class T>
+class TOD 
+{
+public:
+		TOD(SphereCoordSys* cs = NULL)
+                    { if (cs) cs_ = cs; else cs = new SphereCoordSys; }
+  virtual 	~TOD()
+                    { if (cs_) delete cs_; }
+
+// Set/Change/Get the coordinate system
+  virtual void  SetCoordSys(SphereCoordSys* cs)
+                    { if (cs) { delete cs_;  cs_ = cs; } }
+  inline SphereCoordSys* GetCoordSys() const { return(cs_); }
+
+// Return the size / number of sample
+  virtual int_8 size() const = 0; 
+  inline  int_8 NbSample() const { return(size()); }
+
+// Start/End time
+  virtual MissionTime StartTime();
+  virtual MissionTime EndTime();
+
+// Sample time 
+  virtual const MissionTime& SampleTime(int k) const = 0;
+  virtual MissionTime& SampleTime(int k) = 0;
+
+// Time to sample number - return the closest sample to time t
+  virtual int_8 IndexFromTime(MissionTime const & t) const = 0;
+
+// Sample value
+  virtual const T& SampleValue(int_8 k) const = 0;
+  virtual T& SampleValue(int_8 k) = 0;
+  virtual const T& ValueAtTime(MissionTime const & t) const 
+		{ return SampleValue(IndexFromTime(t)); }
+
+// Sample direction
+  virtual const UnitVector& SamplePointing(int_8 k) const = 0;
+  virtual UnitVector& SamplePointing(int_8 k) = 0;
+// Pointing at time t
+  virtual const UnitVector& PointingAtTime(MissionTime const & t ) const 
+		{ return SamplePointing(IndexFromTime(t)); }
+
+};
+
+} // Fin du namespace
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/unitvector.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/unitvector.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/unitvector.cc	(revision 752)
@@ -0,0 +1,102 @@
+#include <math.h>
+#include "unitvector.h"
+//*****************************************************************************
+//++ 
+// Class	UnitVector
+//
+// include      unitvector.h vector3d.h math.h
+//--
+//++
+//
+// Links	Parents
+//
+//    Vector3d
+//    
+//-- 
+//++
+// Titre	Constructors
+//--
+//++
+UnitVector::UnitVector() : Vector3d(1.,0.,0.) 
+//
+//--
+{
+}
+//++
+UnitVector::UnitVector(double x, double y, double z) : Vector3d(x,y,z) 
+//
+//--
+{
+  this->Normalize();
+}
+//++
+UnitVector::UnitVector(double theta, double phi) : Vector3d(theta,phi) 
+//
+//--
+{
+  this->Normalize();
+}
+//++
+UnitVector::UnitVector(const Vector3d& v) : Vector3d(v) 
+//
+//--
+{
+  this->Normalize();
+}
+//++
+// Titre	Public Method
+//--
+//++
+void UnitVector::Print(ostream& os) const 
+//
+//--
+{
+  os << "UnitVector : (X,Y,Z)= (" << _x << ", " << _y << ", " << _z 
+     << ") Theta,Phi= " << _theta << ", " << _phi << "\n"
+     << "norme =" << this->Norm() << endl;
+}
+//++
+// Titre	Operators
+//--
+//++
+Vector3d& UnitVector::operator = (const Vector3d& v)
+//
+//--
+
+{
+  Setxyz(v.X(),v.Y(),v.Z());
+  this->Normalize();
+  return *this;
+}
+//++
+Vector3d& UnitVector::operator += (const Vector3d& v)
+//
+//--
+{
+  Setxyz(_x+v.X(),_y+v.Y(),_z+v.Z());
+  this->Normalize();
+  return *this;
+}
+//++
+Vector3d& UnitVector::operator -= (const Vector3d& v)
+//
+//--
+{
+  Setxyz(_x-v.X(),_y-v.Y(),_z-v.Z());
+  this->Normalize();
+  return *this;
+}
+//++
+Vector3d UnitVector::operator + (const Vector3d& v) const
+//
+//--
+{
+  return UnitVector(_x+v.X(),_y+v.Y(),_z+v.Z());
+}
+//++
+Vector3d UnitVector::operator - (const Vector3d& v) const
+//
+//--
+{
+  return UnitVector(_x-v.X(),_y-v.Y(),_z-v.Z());
+}
Index: /tags/V_Fev00/SophyaLib/Samba/unitvector.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/unitvector.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/unitvector.h	(revision 752)
@@ -0,0 +1,35 @@
+#ifndef UNITVECTOR_H_SEEN
+#define UNITVECTOR_H_SEEN
+
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include "vector3d.h"
+
+class UnitVector : public Vector3d 
+{
+  
+ public:
+  
+  UnitVector();
+  UnitVector(double x, double y, double z);
+  UnitVector(double theta, double phi=0);
+  UnitVector(const Vector3d&);
+  
+  /*virtual*/ Vector3d& operator=(const Vector3d&);  //$CHECK$ EA 101299 operator = non virtual
+  virtual Vector3d& operator+=(const Vector3d&);
+  virtual Vector3d& operator-=(const Vector3d&);
+  virtual Vector3d operator+(const Vector3d&) const;
+  virtual Vector3d operator-(const Vector3d&) const;
+
+  virtual Vector3d& operator+=(double d) { return Vector3d::operator+= (d); }
+  virtual Vector3d operator+(double d) const { return Vector3d::operator+ (d); }
+  virtual Vector3d operator-(double d) const { return Vector3d::operator- (d); }
+
+  void Print(ostream& os) const;
+  
+};
+
+#endif
+
+
Index: /tags/V_Fev00/SophyaLib/Samba/utilgeom.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/utilgeom.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/utilgeom.cc	(revision 752)
@@ -0,0 +1,125 @@
+#include <math.h>
+#include <iostream.h>
+#include "utilgeom.h"
+//++
+// Titre	Some utilitary functions for geometry (utilgeom.h)...
+//--
+//++
+int sign(double d) 
+//
+//--
+{
+  return (d >= 0) - (d < 0);
+}
+//++
+double absd(double d) 
+//
+//--
+{
+  return sqrt(d*d);
+}
+//++
+double mod(double d, double periode) 
+//
+//--
+{
+  if( d >= 0 ) return d-floor(d/periode)*periode;
+  else return d-ceil(d/periode)*periode+periode;
+}
+//++
+void swap(double& d1, double& d2) 
+//
+//--
+{
+  double temp;
+  temp=d2;
+  d2=d1;
+  d1=temp;
+}
+//++
+double min(double d1, double d2) 
+//
+//--
+{
+  if( d1 >= d2 ) return d2;
+  else return d1;
+}
+//++
+double max(double d1, double d2) 
+//
+//--
+{
+  return -min(-d1,-d2);
+}
+//++
+int arrondi(double d) 
+//
+//--
+{
+  return (int)(((d-floor(d)) >= 0.5)*ceil(d)+((d-floor(d)) < 0.5)*floor(d));
+}
+//++
+long rangijd(int nc, int i, int j, int d) 
+//
+//--
+{
+  if( i < j ) return 2*i*(2*nc-i-1)+4*(j-i-1)+d;
+  if( i > j ) return 2*j*(2*nc-j-1)+4*(i-j-1)+d+2;
+  if( i == j ) 
+    {
+      cout << "pas d'intersection entre le cercle " << i 
+	   << " et le cercle " << j << "." << endl;
+      return -1;
+    }
+  else return -1;
+}
+//++
+long rangdiff(int nc, int i, int j, int d) 
+//
+//--
+{
+  if( i == j ) 
+    {
+      cout << "diff n'est pas defini entre le cercle " << i 
+	   << " et le cercle " << j << "." << endl;
+      return 0;
+    }
+  int indm=(int)min(i,j);
+  int indM=(int)max(i,j);
+  return indm*(2*nc-indm-1)+2*(indM-indm-1)+d;
+}
+//++
+long rangik(int NtotEch, int i, int k)
+//
+//--
+{
+  return NtotEch*i+k;
+}
+//++
+long ranghk(int NtotEch, int h, int k) 
+//
+//--
+{
+  return NtotEch*h+k;
+}
+//++
+double scangle(double sinus, double cosinus) 
+//
+//--
+{	// Modifie par D. Y. pour eviter des plantages aux petis angles
+	double eps=1.e-10;
+	if( fabs(1.-sinus*sinus-cosinus*cosinus) > eps) 
+    {	   // On renormalise D.Y.
+	  // cerr << "angle non valide: "<< "sinus = " << sinus << " cosinus = " << cosinus << '\n'; // BUGGG
+      double norm= cosinus*cosinus+sinus*sinus;
+      cosinus=cosinus/norm;
+      sinus=sinus/norm;     
+    }
+  if( fabs(cosinus) >1. ) cosinus=1.*copysign(1.,cosinus);
+  if( fabs(sinus) >1. ) sinus=1.*copysign(1.,sinus);
+/*  if( fabs(sinus) == 0. ) sinus=0.;
+    if( fabs(cosinus) == 0. ) cosinus=0.;
+*/
+  return acos(cosinus)*copysign(1,sinus);
+}
+
Index: /tags/V_Fev00/SophyaLib/Samba/utilgeom.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/utilgeom.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/utilgeom.h	(revision 752)
@@ -0,0 +1,23 @@
+#ifndef MYFUNC_H_SEEN
+#define MYFUNC_H_SEEN
+#include <math.h>
+#ifdef __MWERKS__
+ #include "mwerksmath.h"		// D.Y. Portage mac/ Math.h Unix
+#include "unixmac.h"
+#endif
+#include <vector>
+
+const double pi2=2.*M_PI;
+const double dtor=M_PI/180.;
+const double pi_over_2=M_PI/2.;
+
+int sign(double);
+double absd(double);
+double mod(double, double=0);
+void swap(double&, double&);
+double min(double, double);
+double max(double, double);
+int arrondi(double);
+double scangle(double sinus, double cosinus);
+
+#endif
Index: /tags/V_Fev00/SophyaLib/Samba/vector3d.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/vector3d.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/vector3d.cc	(revision 752)
@@ -0,0 +1,411 @@
+#include "machdefs.h"
+#include <math.h>
+#include "pexceptions.h"
+#include "vector3d.h"
+#include "utilgeom.h"
+//++ 
+// Class	Vector3d
+//
+// include      vector3d.h utilgeom.h  longlat.h math.h
+//
+//
+//    3-D geometry. 
+//    All computations are made with angles in radians and with spherical
+//    coordinates theta, phi.
+//
+//    Concerning Euler's angles, the reference is :
+// 
+//    "Classical Mechanics" 2nd edition, H. Goldstein, Addison Wesley
+//--
+//++
+// Titre	Constructors
+//--
+//++
+Vector3d::Vector3d()
+//
+//-- 
+{
+  Setxyz(1.,0.,0.);
+}
+//++
+Vector3d::Vector3d(double x, double y, double z) 
+//
+//-- 
+{
+  _x=x;
+  _y=y;
+  _z=z;
+  xyz2ThetaPhi();
+}
+//++
+Vector3d::Vector3d(double theta, double phi) 
+//
+//-- 
+{
+  _theta=mod(theta,M_PI); // dans [0;pi]
+  _phi=mod(phi,pi2); // dans [0;2pi]
+  ThetaPhi2xyz();
+}
+//++
+Vector3d::Vector3d(const LongLat& ll)
+//
+//-- 
+{
+  _theta=ll.Theta(); // dans [0;pi]
+  _phi=ll.Phi(); // dans [0;2pi]
+  ThetaPhi2xyz();
+}
+//++
+Vector3d::Vector3d(const Vector3d& v) 
+//
+//-- 
+{
+  _x=v._x;
+  _y=v._y;
+  _z=v._z;
+  _theta=v._theta;
+  _phi=v._phi;
+}
+//++
+// Titre	Public methods
+//--
+//++
+void Vector3d::SetThetaPhi(double theta, double phi)
+//
+//-- 
+{
+  _theta=mod(theta,M_PI);
+  _phi=mod(phi,pi2);
+  ThetaPhi2xyz();
+}
+//++
+void Vector3d::Setxyz(double x, double y, double z) 
+//
+//-- 
+{
+  _x=x;
+  _y=y;
+  _z=z;
+  xyz2ThetaPhi();
+}
+//++
+void Vector3d::ThetaPhi2xyz()
+//
+//-- 
+{
+  _x=sin(_theta)*cos(_phi);
+  _y=sin(_theta)*sin(_phi);
+  _z=cos(_theta);
+}
+//++
+void Vector3d::xyz2ThetaPhi()
+//
+//-- 
+{
+  double norm=this->Norm();
+  if( norm != 0. ) 
+    {
+      _theta=acos(_z/norm); // dans [0,Pi]
+      if( mod(_theta,M_PI) == 0. ) _phi=0.; // on est sur +-Oz, le vecteur z est en phi=0
+      //      else _phi=acos(_x/sin(_theta)/norm)+M_PI*(_y<0);
+      else _phi=scangle(_y/sin(_theta)/norm,_x/sin(_theta)/norm);
+    }
+  else // vecteur nul
+    {
+      _theta=0.;
+      _phi=0.;
+    }
+}
+//++
+Vector3d& Vector3d::Normalize() 
+//
+//-- 
+{
+  double norm=this->Norm();
+  if( norm != 0. )  (*this)/=norm;
+  else cerr << "Division par zero" << endl;
+  return *this;
+} 
+//++
+double Vector3d::Norm() const 
+//
+//-- 
+{
+  return sqrt(_x*_x+_y*_y+_z*_z);
+}
+//++
+double Vector3d::Psc(const Vector3d& v) const 
+//
+//    dot product
+//-- 
+{
+  return _x*v._x+_y*v._y+_z*v._z;
+}
+//++
+double Vector3d::SepAngle(const Vector3d& v) const 
+//
+//    angular gap between 2 vectors in [0,Pi]
+//-- 
+{
+  double n1=this->Norm();
+  double n2=v.Norm();
+  double ret;
+  if( n1!=0. && n2!=0. ) ret=acos((this->Psc(v))/n1/n2);
+  else 
+    {
+      cerr << "Division par zero" << endl;
+      ret=0.;
+    }
+  return ret;
+}
+//++
+Vector3d Vector3d::Vect(const Vector3d& v) const 
+//
+//    vector product
+//-- 
+{
+  double xo=_y*v._z-_z*v._y;
+  double yo=_z*v._x-_x*v._z;
+  double zo=_x*v._y-_y*v._x;
+  return Vector3d(xo,yo,zo);
+}
+//++
+Vector3d Vector3d::VperpPhi() const 
+//
+//    perpendicular vector, with equal phi
+//-- 
+{
+  double theta;
+  if( _theta != pi_over_2 ) theta=_theta+(0.5-(_theta>pi_over_2))*M_PI; // on tourne theta de +-pi/2
+  else theta=0.;
+  return Vector3d(theta,_phi);
+}
+//++
+Vector3d Vector3d::VperpTheta() const 
+//
+//    perpendicular vector with equal theta
+//-- 
+{ 
+  throw PError("Vector3d::VperpTheta() - Logic Error DY/Reza 20/02/2000"); 
+  // Bug ??? (D. Yvon, Fevrier 2000)
+  //  double phi=mod(_phi+pi_over_2,pi2); // on tourne phi de pi/2
+  //  return Vector3d(_theta,phi);
+}
+
+Vector3d Vector3d::EPhi() const 
+{
+  Vector3d temp;
+  if ( fabs(_z) == 1. ) // si on est en +- Oz
+    {
+      temp=Vector3d(1.,0.,0.);
+    }
+  else 
+    {
+      Vector3d k(0,0,-1);
+      temp=this->Vect(k);
+      temp.Normalize();
+    }
+  return temp;
+}
+//++
+Vector3d Vector3d::ETheta() const 
+//
+//-- 
+{
+  Vector3d temp=this->Vect(EPhi());
+  temp.Normalize();
+  return temp;
+}
+
+//++
+Vector3d Vector3d::Euler(double phi, double theta, double psi) const 
+//
+//    Euler's rotations
+//-- 
+{
+  double cpsi=cos(psi);
+  double ctheta=cos(theta);
+  double cphi=cos(phi);
+  double spsi=sin(psi);
+  double stheta=sin(theta);
+  double sphi=sin(phi);
+  double xnew=(cpsi*cphi-ctheta*sphi*spsi)*_x
+    +(cpsi*sphi+ctheta*cphi*spsi)*_y
+    +spsi*stheta*_z;
+  double ynew=(-spsi*cphi-ctheta*sphi*cpsi)*_x
+    +(-spsi*sphi+ctheta*cphi*cpsi)*_y
+    +cpsi*stheta*_z;
+  double znew=stheta*sphi*_x-stheta*cphi*_y+ctheta*_z;
+  return Vector3d(xnew,ynew,znew);
+}
+//++
+Vector3d Vector3d::InvEuler(double phi, double theta, double psi) const 
+//
+//    inverse rotation
+//-- 
+{
+  double cpsi=cos(psi);
+  double ctheta=cos(theta);
+  double cphi=cos(phi);
+  double spsi=sin(psi);
+  double stheta=sin(theta);
+  double sphi=sin(phi);
+  double xnew=(cpsi*cphi-ctheta*sphi*spsi)*_x
+    -(spsi*cphi+ctheta*sphi*cpsi)*_y
+    +sphi*stheta*_z;
+  double ynew=(cpsi*sphi+ctheta*cphi*spsi)*_x
+    +(-spsi*sphi+ctheta*cphi*cpsi)*_y
+    -cphi*stheta*_z;
+  double znew=stheta*spsi*_x+stheta*cpsi*_y+ctheta*_z;
+  return Vector3d(xnew,ynew,znew);
+}
+//++
+Vector3d Vector3d::Rotate(const Vector3d& omega, double phi)
+//
+//    rotation of angle phi around an axis omega (Maxwell's rule)
+//-- 
+{
+  Vector3d rotationaxis=omega;
+  rotationaxis.Normalize();
+  double n=this->Psc(rotationaxis);
+  Vector3d myself=*this;
+  Vector3d rotate=n*rotationaxis+(myself-n*rotationaxis)*cos(phi)-(myself^rotationaxis)*sin(phi);
+  return rotate;
+} 
+//++  
+void Vector3d::Print(ostream& os) const 
+//
+//--
+{
+  os << "Vector3: (X,Y,Z)= (" << _x << ", " << _y << ", " << _z 
+     << ") --- Theta,Phi= " << _theta << ", " << _phi << "\n"
+     << "Norme = " << this->Norm() << endl;
+}
+//++
+// Titre	Operators
+//--
+//++
+Vector3d& Vector3d::operator += (const Vector3d& v) 
+//
+//-- 
+{
+  *this=*this+v;
+  return *this;
+}
+//++
+Vector3d& Vector3d::operator -= (const Vector3d& v) 
+//
+//-- 
+{
+  *this=*this-v;
+  return *this;
+}
+//++
+Vector3d& Vector3d::operator += (double d) 
+//
+//-- 
+{
+  Setxyz(_x+d,_y+d,_z+d);
+  return *this;
+}
+//++
+Vector3d& Vector3d::operator /= (double d) 
+//
+//-- 
+{
+  if( d != 0. ) Setxyz(_x/d,_y/d,_z/d);
+  else cerr << "Division par zero." << endl;
+  return *this;
+}
+//++
+Vector3d& Vector3d::operator *= (double d) 
+//
+//-- 
+{
+  Setxyz(_x*d,_y*d,_z*d);
+  return *this;
+}
+//++
+Vector3d Vector3d::operator ^ (const Vector3d& v) const 
+//
+//    vector product
+//-- 
+{
+  return this->Vect(v);
+}
+//++
+Vector3d Vector3d::operator + (double d) const 
+//
+//-- 
+{
+  return Vector3d(_x+d,_y+d,_z+d);
+}
+//++
+Vector3d Vector3d::operator + (const Vector3d& v) const 
+//
+//-- 
+{
+  return Vector3d(_x+v._x,_y+v._y,_z+v._z);
+}
+//++
+Vector3d Vector3d::operator - (double d) const 
+//
+//-- 
+{
+  return *this+(-d);
+}
+//++
+Vector3d Vector3d::operator - (const Vector3d& v) const 
+//
+//-- 
+{
+  return *this+(v*(-1.));
+}
+//++
+Vector3d Vector3d::operator * (double d) const 
+//
+//-- 
+{
+  return Vector3d(d*_x,d*_y,d*_z);
+}
+//++
+double Vector3d::operator * (const Vector3d& v) const 
+//
+//    dot product
+//-- 
+{
+  return this->Psc(v);
+}
+//++
+Vector3d Vector3d::operator / (double d) const 
+//
+//-- 
+{
+  Vector3d ret=*this;
+  if( d != 0. ) ret/=d;
+  else  cerr << "Division par zero." << endl;
+  return ret;
+}
+//++
+Vector3d& Vector3d::operator = (const Vector3d& v) 
+//
+//-- 
+{
+  if( this != &v ) 
+    {
+      _x=v._x; 
+      _y=v._y; 
+      _z=v._z; 
+      _theta=v._theta; 
+      _phi=v._phi;
+    }
+  return *this;
+}
+//++
+bool Vector3d::operator == (const Vector3d& v) 
+//
+//-- 
+{
+  return (this==&v);
+}
+
Index: /tags/V_Fev00/SophyaLib/Samba/vector3d.h
===================================================================
--- /tags/V_Fev00/SophyaLib/Samba/vector3d.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/Samba/vector3d.h	(revision 752)
@@ -0,0 +1,146 @@
+#ifndef VECTOR3D_H_SEEN
+#define VECTOR3D_H_SEEN
+
+#include <math.h>
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef __MWERKS__
+#include "unixmac.h"
+#endif
+#include "longlat.h"
+
+/*
+  Geometrie en dimension 3. 
+  Tous les calculs sont faits en radians 
+  et en coordonnees spheriques theta,phi
+  pour les rotations (angles d'Euler) ma source est 
+  "Classical Mechanics" 2nd edition, H. Goldstein, Addison Wesley
+*/
+/*!    3-D geometry. 
+
+    All computations are made with angles in radians and with spherical
+    coordinates theta, phi.
+
+    Concerning Euler's angles, the reference is :
+ 
+    "Classical Mechanics" 2nd edition, H. Goldstein, Addison Wesley
+*/
+
+class Vector3d 
+{
+
+ public:
+  
+  Vector3d();
+  Vector3d(double x, double y, double z);
+  Vector3d(double theta, double phi);
+  Vector3d(const LongLat&);
+  Vector3d(const Vector3d&);
+
+//   To manipulate the vector
+  virtual void Setxyz(double x, double y, double z);
+  virtual void SetThetaPhi(double theta,  double phi);
+  virtual void ThetaPhi2xyz();
+  virtual void xyz2ThetaPhi();
+
+// Acces to coordinates
+  inline double Theta() const {return _theta;}
+  inline double Phi() const {return _phi;}
+  inline double X() const {return _x;}
+  inline double Y() const {return _y;}
+  inline double Z() const {return _z;}
+
+  virtual Vector3d& Normalize();
+  virtual double Norm() const;
+
+  // produit scalaire
+  virtual double Psc(const Vector3d&) const;
+
+  // ecart angulaire entre 2 vecteurs dans [0,Pi]
+  /*!   angular gap between 2 vectors in [0,Pi] */
+  virtual double SepAngle(const Vector3d&) const;
+
+  // produit vectoriel
+  /*!    vector product */
+  virtual Vector3d Vect(const Vector3d&) const;
+
+  // vecteur perpendiculaire de meme phi
+  /*!    perpendicular vector, with equal phi */
+  virtual Vector3d VperpPhi() const;
+
+  // vecteur perpendiculaire de meme theta
+  /*!    perpendicular vector with equal theta */
+  virtual Vector3d VperpTheta() const;
+
+  virtual Vector3d ETheta() const;
+  virtual Vector3d EPhi() const;
+
+  // rotations d'Euler
+  /*!    Euler's rotations */
+  // rotations d Euler
+  virtual Vector3d Euler(double, double, double) const;
+
+  // rotation inverse
+  /*!    inverse rotation */
+  Vector3d InvEuler(double, double, double) const;
+
+  // rotation d'angle phi autour d'un axe omega (regle du tire-bouchon)
+  /*!    rotation of angle phi around an axis omega (Maxwell's rule) */
+  Vector3d Rotate(const Vector3d& omega,double phi);
+
+  /*virtual*/ Vector3d& operator=(const Vector3d&); // $CHECK$ EA 101299
+  virtual Vector3d& operator+=(const Vector3d&);
+  virtual Vector3d& operator-=(const Vector3d&);
+  virtual Vector3d operator+(const Vector3d&) const;
+  virtual Vector3d operator-(const Vector3d&) const;
+
+  virtual Vector3d& operator+=(double);
+  virtual Vector3d& operator/=(double);
+  virtual Vector3d& operator*=(double);
+
+  virtual Vector3d operator+(double) const;
+  virtual Vector3d operator-(double) const;
+  virtual Vector3d operator*(double) const;
+  virtual Vector3d operator/(double) const;
+
+  /*!    vector product */
+  virtual Vector3d operator^(const Vector3d&) const; // produit vectoriel
+  /*!    dot product */
+  virtual double operator*(const Vector3d&) const; // produit scalaire
+
+  bool operator==(const Vector3d&);
+  
+  virtual void Print(ostream& os) const;
+
+ protected:
+
+  double _x;
+  double _y;
+  double _z;
+  double _theta;
+  double _phi;
+
+};
+
+inline ostream& operator<<(ostream& s, const Vector3d& v) 
+{  
+  v.Print(s);  
+  return s;  
+}
+
+// fonctions globales
+
+inline Vector3d operator*(double d, const Vector3d& v) 
+{
+  return v*d;
+}
+
+inline Vector3d operator+(double d, const Vector3d& v) 
+{
+  return v+d;
+}
+
+#endif
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/HowToUse
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/HowToUse	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/HowToUse	(revision 752)
@@ -0,0 +1,53 @@
+#!/bin/csh
+if ($#argv < 2)  then
+  echo 'Usage: HowToUse NSide_HealPix OutFITSfile'
+  exit 1
+endif
+
+
+echo '    *************************************************************';
+echo '		creating spectral response powerlaw';
+echo '    *************************************************************';
+echo '  ' 
+set cmd = "tgrsr 1 .2,120,50,-0.7,100,600 200 pl.fits"
+echo ' ' 
+echo 'Executing' $cmd
+time $cmd
+
+echo '	*************************************************************';
+echo '		creating gaussian radiation spectra sky';
+echo '	*************************************************************';
+set cmd = "tgsky $1 0 140,30 gauss.fits"
+echo ' ' 
+echo 'Executing' $cmd
+time $cmd
+
+echo '	*************************************************************';
+echo '		creating cosine/sine radiation spectra  sky';
+echo '	*************************************************************';
+set cmd = "tgsky $1 2 12,7,9,10 cossin.fits"
+echo ' ' 
+echo 'Executing' $cmd
+time $cmd
+
+echo '	*************************************************************';
+echo '		creating noise radiation spectra sky';
+echo '	*************************************************************';
+set cmd = "tgsky $1 1 160,44 noise.fits"
+echo ' ' 
+echo 'Executing' $cmd
+time $cmd
+
+echo '	*************************************************************'
+echo '		calling skymixer'
+echo '	*************************************************************'
+set xx = "@SKYMIX  3  $1"
+echo $xx > test.d
+cat howto.d >> test.d
+
+set cmd = "skymixer test.d $2"
+echo ' ' 
+echo 'Executing' $cmd
+time $cmd
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/Makefile
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/Makefile	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/Makefile	(revision 752)
@@ -0,0 +1,55 @@
+include ../Mgr/Makefile.h
+ 
+all: $(LIB)libSkyT.a
+clean:
+	rm -f $(OBJ)blackbody.o $(OBJ)convtools.o $(OBJ)easyTest.o $(OBJ)gaussfilt.o $(OBJ)nupower.o $(OBJ)radspec.o $(OBJ)radspecvector.o $(OBJ)skymixer.o $(OBJ)specresp.o $(OBJ)specrespvector.o $(OBJ)squarefilt.o $(OBJ)tgrsr.o $(OBJ)tgsky.o $(OBJ)trianglefilt.o
+	rm -f $(LIB)libSkyT.a
+$(LIB)libSkyT.a : $(OBJ)blackbody.o $(OBJ)convtools.o $(OBJ)gaussfilt.o $(OBJ)nupower.o $(OBJ)radspec.o $(OBJ)radspecvector.o $(OBJ)specresp.o $(OBJ)specrespvector.o $(OBJ)squarefilt.o $(OBJ)trianglefilt.o
+	$(ARCXX) $(ARCXXFLAGS) $@ $?
+ifeq ($(CXX),cxx)
+	$(CXX) $? $(CPPFLAGS) $(CXXFLAGS) -L$(LIB) -lSkyT -lSamba -lNTools -lSysTools -o $(OBJ)xx.x -Hf
+endif 
+ 
+$(OBJ)blackbody.o: blackbody.cc $(INC)machdefs.h \
+ $(INC)pclassids.h blackbody.h radspec.h \
+ specresp.h convtools.h
+$(OBJ)convtools.o: convtools.cc convtools.h
+$(OBJ)gaussfilt.o: gaussfilt.cc $(INC)machdefs.h \
+ $(INC)pclassids.h gaussfilt.h specresp.h
+$(OBJ)nupower.o: nupower.cc $(INC)machdefs.h \
+ $(INC)pclassids.h nupower.h radspec.h \
+ specresp.h convtools.h
+$(OBJ)radspec.o: radspec.cc $(INC)machdefs.h \
+ $(INC)pclassids.h radspec.h specresp.h \
+ $(INC)integ.h \
+ $(INC)pexceptions.h
+$(OBJ)radspecvector.o: radspecvector.cc \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h radspecvector.h radspec.h \
+ specresp.h $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h
+$(OBJ)specresp.o: specresp.cc specresp.h \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h \
+ $(INC)integ.h \
+ $(INC)pexceptions.h
+$(OBJ)specrespvector.o: specrespvector.cc \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h specrespvector.h \
+ specresp.h $(INC)tvector.h \
+ $(INC)tmatrix.h \
+ $(INC)ppersist.h \
+ $(INC)pexceptions.h \
+ $(INC)md5.h \
+ $(INC)anydataobj.h \
+ $(INC)ndatablock.h
+$(OBJ)squarefilt.o: squarefilt.cc $(INC)machdefs.h \
+ $(INC)pclassids.h squarefilt.h specresp.h
+$(OBJ)trianglefilt.o: trianglefilt.cc \
+ $(INC)machdefs.h \
+ $(INC)pclassids.h trianglefilt.h specresp.h
Index: /tags/V_Fev00/SophyaLib/SkyT/RSextract.d
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/RSextract.d	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/RSextract.d	(revision 752)
@@ -0,0 +1,88 @@
+#  EXT_RS  NbComponents  NSide_HealPix
+@EXT_RS  31 
+
+#  RD_EXT_PATH  PathForFITS   
+#  path for input Sky Component FITS files , from which the RadSpec
+#  will be extracted
+@RS_EXT_PATH /tmp_mnt/exp/planck/CartesRT/supertango/templates/
+
+#  ----    Sky map for different frequencies        ---------
+#  ----    From which will be extracted the radspectra   ----
+#  RADSPECMAPi FITSfilename freq(MHz)
+@RADSPECMAP1 	eran102_441_00015000mhz.fits
+@RADSPECMAP2 	eran102_441_00018884mhz.fits 
+@RADSPECMAP3 	eran102_441_00023773mhz.fits 
+@RADSPECMAP4	eran102_441_00029929mhz.fits 
+@RADSPECMAP5 	eran102_441_00037678mhz.fits 
+@RADSPECMAP6 	eran102_441_00047434mhz.fits 
+@RADSPECMAP7 	eran102_441_00059716mhz.fits 
+@RADSPECMAP8  	eran102_441_00075178mhz.fits 
+@RADSPECMAP9 	eran102_441_00094644mhz.fits 
+@RADSPECMAP10 	eran102_441_00119149mhz.fits 
+@RADSPECMAP11 	eran102_441_00150000mhz.fits
+@RADSPECMAP12 	eran102_441_00188839mhz.fits	
+@RADSPECMAP13 	eran102_441_00237734mhz.fits	00237734
+@RADSPECMAP14 	eran102_441_00299289mhz.fits 
+@RADSPECMAP15 	eran102_441_00376783mhz.fits
+@RADSPECMAP16 	eran102_441_00474342mhz.fits
+@RADSPECMAP17 	eran102_441_00597161mhz.fits
+@RADSPECMAP18 	eran102_441_00751781mhz.fits
+@RADSPECMAP19 	eran102_441_00946436mhz.fits
+@RADSPECMAP20 	eran102_441_01191492mhz.fits
+@RADSPECMAP21 	eran102_441_01500000mhz.fits	
+@RADSPECMAP22 	eran102_441_01888388mhz.fits	
+@RADSPECMAP23 	eran102_441_02377340mhz.fits
+@RADSPECMAP24 	eran102_441_02992893mhz.fits	
+@RADSPECMAP25 	eran102_441_03767830mhz.fits	
+@RADSPECMAP26 	eran102_441_04743416mhz.fits
+@RADSPECMAP27 	eran102_441_05971608mhz.fits	
+@RADSPECMAP28 	eran102_441_07517809mhz.fits	
+@RADSPECMAP29 	eran102_441_09464360mhz.fits
+@RADSPECMAP30 	eran102_441_11914924mhz.fits		
+@RADSPECMAP31 	eran102_441_15000000mhz.fits
+
+
+#  ----   Source point map for different frequencies        ---------
+#  ----    From which will be extracted the radspectra   ----
+#  SOURCEPTMAPi FITSfilename freq(MHz)
+@SOURCEPTMAP1 	eran102_441_00015000mhz.s_rare
+@SOURCEPTMAP2 	eran102_441_00018884mhz.s_rare
+@SOURCEPTMAP3 	eran102_441_00023773mhz.s_rare
+@SOURCEPTMAP4	eran102_441_00029929mhz.s_rare
+@SOURCEPTMAP5 	eran102_441_00037678mhz.s_rare
+@SOURCEPTMAP6 	eran102_441_00047434mhz.s_rare 
+@SOURCEPTMAP7 	eran102_441_00059716mhz.s_rare 	
+@SOURCEPTMAP8  	eran102_441_00075178mhz.s_rare 
+@SOURCEPTMAP9 	eran102_441_00094644mhz.s_rare 
+@SOURCEPTMAP10 	eran102_441_00119149mhz.s_rare
+@SOURCEPTMAP11 	eran102_441_00150000mhz.s_rare
+@SOURCEPTMAP12 	eran102_441_00188839mhz.s_rare	
+@SOURCEPTMAP13 	eran102_441_00237734mhz.s_rare
+@SOURCEPTMAP14 	eran102_441_00299289mhz.s_rare 
+@SOURCEPTMAP15 	eran102_441_00376783mhz.s_rare	
+@SOURCEPTMAP16 	eran102_441_00474342mhz.s_rare	
+@SOURCEPTMAP17 	eran102_441_00597161mhz.s_rare	
+@SOURCEPTMAP18 	eran102_441_00751781mhz.s_rare
+@SOURCEPTMAP19 	eran102_441_00946436mhz.s_rare
+@SOURCEPTMAP20 	eran102_441_01191492mhz.s_rare
+@SOURCEPTMAP21 	eran102_441_01500000mhz.s_rare
+@SOURCEPTMAP22 	eran102_441_01888388mhz.s_rare
+@SOURCEPTMAP23 	eran102_441_02377340mhz.s_rare
+@SOURCEPTMAP24 	eran102_441_02992893mhz.s_rare
+@SOURCEPTMAP25 	eran102_441_03767830mhz.s_rare
+@SOURCEPTMAP26 	eran102_441_04743416mhz.s_rare	
+@SOURCEPTMAP27 	eran102_441_05971608mhz.s_rare
+@SOURCEPTMAP28 	eran102_441_07517809mhz.s_rare
+@SOURCEPTMAP29 	eran102_441_09464360mhz.s_rare
+@SOURCEPTMAP30 	eran102_441_11914924mhz.s_rare		
+@SOURCEPTMAP31 	eran102_441_15000000mhz.s_rare
+
+
+# Filter definition now !!
+# define the detector (only one)
+@GAUSSFILTER 143 12 0.84 50. 300.
+
+#  ---- wanna print a lot of stuff..---------
+#  ----  let's try PRINTLEVEL 5          ----
+@PRINTLEVEL  0
+
Index: /tags/V_Fev00/SophyaLib/SkyT/blackbody.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/blackbody.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/blackbody.cc	(revision 752)
@@ -0,0 +1,89 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: blackbody.cc,v 1.4 1999-11-29 16:59:09 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density for a blackbody
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+#include "blackbody.h"
+
+//----------------
+// Constructor --
+//----------------
+BlackBody::BlackBody(double temperature)
+  : RadSpectra(10., 10000.)
+{
+  _temperature = temperature;
+}
+
+
+BlackBody::~BlackBody()
+{
+}
+
+
+double
+BlackBody::flux(double nu) const
+{
+  if(nu < -1.e99) nu = -1.e99;
+  if(nu > 1.e99) nu = 1.e99;
+  double temperature = getTemperature();
+  if(nu==0.) return 0.;
+  double hpl = ConvTools::hpl;
+  double cel = ConvTools::cel;
+  double kb  = ConvTools::kb;
+  double puiss1 = nu*pow(10,9);
+  if(puiss1 >  1.e99)   puiss1=1.e99;
+  if(puiss1 < -1.e99)   puiss1=-1.e99;
+  double puiss2 = hpl*nu*pow(10,9)/(kb*temperature);
+  if(puiss2 >  1.e99)   puiss2=1.e99;
+  if(puiss2 < -1.e99)   puiss2=-1.e99;
+  
+  double result=
+   (2*hpl* pow( puiss1 ,3))/( pow(cel,2)*(exp(puiss2)-1));
+  return result;
+}
+
+
+void
+BlackBody::Print(ostream& os) const
+{
+  os << "BlackBody::Print Temp= " << getTemperature() 
+     << " - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Emission= " << flux(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Emission= " << flux(peakFreq()) << endl;
+
+}
+
+/*
+void 
+BlackBody::WriteSelf(POutPersist& s)  
+{
+  s.PutR8(this->getTemperature());
+  s.PutR8(this->minFreq());
+  s.PutR8(this->maxFreq());
+}
+
+void
+BlackBody::ReadSelf(PInPersist& s)  
+{
+  s.GetR8(_temperature);
+  s.GetR8(_numin);
+  s.GetR8(_numax);
+  cout << " Temperature - minFreq - maxFreq " << endl; 
+  cout << _temperature << "-" << _numin << "-" << _numax << endl;
+}
+
+*/
Index: /tags/V_Fev00/SophyaLib/SkyT/blackbody.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/blackbody.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/blackbody.h	(revision 752)
@@ -0,0 +1,43 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: blackbody.h,v 1.4 1999-11-29 16:59:10 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef BLACKBODY_H_SEEN
+#define BLACKBODY_H_SEEN
+
+#include "radspec.h"
+#include "convtools.h"
+
+class BlackBody : public RadSpectra
+{
+public:   //Constructor
+  //Constructor
+  BlackBody (double temp = ConvTools::tcmb);
+
+  virtual ~BlackBody();
+
+  virtual double flux(double nu) const;
+
+  // returns the value of the temperature
+  inline double getTemperature() const {return _temperature;} 
+
+  // reset the value of the temperature with a new value
+  inline void setTemperature(double newtemp) { _temperature = newtemp; }
+
+  // Redefintion of the Print function
+  virtual void      Print(ostream& os)  const;
+
+protected:
+  double _temperature;
+
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/convtools.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/convtools.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/convtools.cc	(revision 752)
@@ -0,0 +1,24 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: convtools.cc,v 1.2 1999-11-20 21:00:48 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#include "convtools.h"
+
+// Boltzman constant  J/K
+double ConvTools::kb =  1.380662e-23;     
+// Mean value of the cmb temperature (K)
+double ConvTools::tcmb=2.728;
+// constante de Planck en Js
+double ConvTools::hpl=6.626176e-34;   
+// Light speed  PDG 1992 m/s
+double ConvTools::cel=299792458.; 
+
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/convtools.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/convtools.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/convtools.h	(revision 752)
@@ -0,0 +1,26 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: convtools.h,v 1.2 1999-11-20 21:00:48 ansari Exp $
+//
+// Description:
+//      Definition of general constant and some convertion functions
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef CONV_TOOLS_H_SEEN
+#define CONV_TOOLS_H_SEEN
+
+class ConvTools
+{
+public:
+ static double kb;
+ static double tcmb;
+ static double hpl;
+ static double cel;
+
+};
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/easyTest.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/easyTest.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/easyTest.cc	(revision 752)
@@ -0,0 +1,188 @@
+#include <iostream.h>
+#include "blackbody.h"
+#include "radspecvector.h"
+#include "specrespvector.h"
+#include "tvector.h"
+#include "squarefilt.h"
+#include "gaussfilt.h"
+#include "trianglefilt.h"
+
+
+int
+main() 
+{ 
+//   PInPersist in("out");
+//   SR_ReadSelf(in);
+//   cout << " " << endl;
+
+  cout << "BlackBody!" << endl;
+  BlackBody myBB(2.73);
+  double freqmin =  230.;
+  double freqmax = 500;
+  double logIF = myBB.logIntegratedFlux(freqmin,freqmax);
+  double IF    = myBB.integratedFlux(freqmin,freqmax);
+  cout << "log   " << logIF << endl;
+  cout << "nolog " << IF    << endl;
+  cout << "min et max " << myBB.minFreq() << " :: " << myBB.maxFreq() << endl;
+  cout << "full integration no log  " << myBB.integratedFlux(freqmin,freqmax) << endl;
+  cout << "full integration log     " << myBB.logIntegratedFlux(freqmin,freqmax) << endl;
+  cout << "full integration no log nolimit " << myBB.integratedFlux() << endl;
+  cout << "full integration log  nolimit  " << myBB.logIntegratedFlux() << endl;
+
+  cout << "squareFilter " << endl;
+  SquareFilter mySF(200,600);
+  double logSF = mySF.logIntegratedSpect(freqmin,freqmax);
+  double SF    = mySF.IntegratedSpect(freqmin,freqmax);
+  cout << "log   " << logSF << endl;
+  cout << "nolog " << SF    << endl;
+  cout << "min et max " << mySF.minFreq() << " :: " << mySF.maxFreq() << endl;
+  cout << "full integration no log  " << mySF.IntegratedSpect(200,700) << endl;
+  cout << "full integration log     " << mySF.logIntegratedSpect(200,700) << endl;
+  cout << "full integration no log nolimit  " << mySF.IntegratedSpect() << endl;
+  cout << "full integration log  nolimit   " << mySF.logIntegratedSpect() << endl;
+
+
+  cout << "triangleFilter" << endl;
+  TriangleFilter myTF(200,500,120,40);
+  double logTF = myTF.logIntegratedSpect(10.,freqmax);
+  double TF    = myTF.IntegratedSpect(10.,freqmax);
+  cout << "log   " << logTF << endl;
+  cout << "nolog " << TF    << endl;
+  cout << "min et max " << myTF.minFreq() << " :: " << myTF.maxFreq() << endl;
+  cout << "full integration no log  " << myTF.IntegratedSpect() << endl;
+  cout << "full integration log     " << myTF.logIntegratedSpect() << endl;
+  
+  cout << "....Testing RadSpectraVec..." << endl;
+  int maxVal = 10;
+  Vector vecOfNu(maxVal);
+  Vector vecOfFDeNu(maxVal);
+  for (int i=0; i<maxVal; i++)
+    {
+      vecOfNu(i) = (double)i+230.;
+      vecOfFDeNu(i) = 1.; //*(double)i+1;
+      cout << "entry values  " <<  vecOfNu(i) << " " << vecOfFDeNu(i) << endl;
+    }
+  freqmin = 200.;
+  freqmax = 259.;
+  RadSpectraVec myRSV(vecOfNu, vecOfFDeNu);
+  double RSV    = myRSV.integratedFlux(freqmin,freqmax);
+ 
+  double logRSV = myRSV.logIntegratedFlux(freqmin,freqmax);
+  cout << "nolog int " << RSV    << endl; 
+  cout << "log int   " << logRSV << endl;
+  cout << "min et max " << myRSV.minFreq() << " :: " << myRSV.maxFreq() << endl;
+  cout << "full integration no log  " << myRSV.integratedFlux() << endl;
+  cout << "full integration log     " << myRSV.logIntegratedFlux() << endl;
+
+  cout << "....Testing SpecRespVec..." << endl;
+  int SRVmaxVal = 100;
+  Vector vecOfNuRSV(SRVmaxVal);
+  Vector vecOfFDeNuRSV(SRVmaxVal);
+  for (int i=0; i<SRVmaxVal; i++)
+    {
+      vecOfNuRSV(i) = (double)i+130.;
+      vecOfFDeNuRSV(i) = 10*(double)i+1;
+      //      cout << "entry values  " <<  vecOfNuRSV(i) << " " << vecOfFDeNuRSV(i) << endl;
+    }
+  freqmin = vecOfNuRSV(0);
+  freqmax = vecOfNuRSV(SRVmaxVal-1);
+  SpecRespVec mySRV(vecOfNuRSV, vecOfFDeNuRSV);
+
+// Test ecriture en PPF 
+  {
+  cout << " Writing mySRV (RadSpecVec to PPF " << endl;
+  POutPersist s("srvec.ppf");
+  s << mySRV;
+  }
+  {
+  cout << " Reading  mySRV from PPF " << endl;
+  PInPersist s("srvec.ppf");
+  SpecRespVec srv;
+  s >> srv;
+  cout << srv;
+  }
+
+  double SRV    = mySRV.IntegratedSpect(freqmin,freqmax);
+  double logSRV = mySRV.logIntegratedSpect(freqmin,freqmax);
+  cout << "nolog " << SRV    << endl; 
+  cout << "log   " << logSRV << endl;
+  cout << "min et max " << mySRV.minFreq() << " :: " << mySRV.maxFreq() << endl;
+  cout << "full integration no log " << mySRV.IntegratedSpect() << endl;
+  cout << "full integration log    " << mySRV.logIntegratedSpect() << endl;
+  
+  cout << "----------------------------------------------------" << endl;
+  cout << "...Testing filter and integrate !" << endl;
+
+  cout << " BBSF nolog " << myBB.filteredIntegratedFlux(mySF,200.,400.) << endl;
+  cout << " BBSF   log " << myBB.filteredLogIntFlux(mySF,200.,400.) << endl;
+  cout << "full integration no log  " << myBB.integratedFlux(200.,400.) << endl;
+  cout << "full integration log     " << myBB.logIntegratedFlux(200.,400.) << endl;
+  cout << "SF" << endl;
+  cout << "full integration no log  " << mySF.IntegratedSpect(200.,400.) << endl;
+  cout << "full integration log     " << mySF.logIntegratedSpect(200.,400.) << endl;
+
+  cout << " BBTF nolog " << myBB.filteredIntegratedFlux(myTF,200.,400.) << endl;
+  cout << " BBTF   log " << myBB.filteredLogIntFlux(myTF,200.,400.) << endl;
+  cout << "TF" << endl;
+  cout << "full integration no log  " << myTF.IntegratedSpect(200.,400.) << endl;
+  cout << "full integration log     " << myTF.logIntegratedSpect(200.,400.) << endl;
+
+  /*
+  cout << " SZSF nolog " << mySZ.filteredIntegratedFlux(mySF,30.,100.) << endl;
+  cout << " SZSF  log " << mySZ.filteredLogIntFlux(mySF,30.,100.) << endl;
+  cout << "full integration no log  " << mySZ.integratedFlux(30.,100.) << endl;
+  cout << "full integration log     " << mySZ.logIntegratedFlux(30.,100.) << endl;
+
+  cout << " SZTF nolog " << mySZ.filteredIntegratedFlux(myTF,30.,100.) << endl;
+  cout << " SZTF   log " << mySZ.filteredLogIntFlux(myTF,30.,100.) << endl;
+			   */
+  cout << "********" << endl;
+  double min, max;
+  min=232;
+  max=235;
+
+  cout << " RSVSF nolog " << myRSV.filteredIntegratedFlux(mySF,min,max) << endl;
+  cout << " RSVSF   log " << myRSV.filteredLogIntFlux(mySF,min,max) << endl;
+  cout << "full integration no log  " << myRSV.integratedFlux(230.,500.) << endl;
+  cout << "full integration log     " << myRSV.logIntegratedFlux(230.,500.) << endl;
+  cout << "full integration no log min max " << myRSV.integratedFlux(min,max) << endl;
+  cout << "full integration log  min max   " << myRSV.logIntegratedFlux(min,max) << endl;
+
+  cout << " RSVTF nolog " << myRSV.filteredIntegratedFlux(myTF,230.,500.) << endl;
+  cout << " RSVTF   log " << myRSV.filteredLogIntFlux(myTF,230.,500.) << endl;
+  
+//   cout << "New TESTS USING IOBJS!" << endl;
+//   POutPersist out("out");
+//   TriangleFilter* myTF2 = new TriangleFilter(10,200,20,40);
+//   SR_WriteSelf(myTF2,out);
+
+//   POutPersist outV("outV");
+//   cout << "check before anything" << vecOfNu.NElts()<< endl;
+//   SpecRespVec* mySRV2 = new SpecRespVec(vecOfNu, vecOfFDeNu);
+//   SR_WriteSelf(mySRV2,outV);
+  
+//   Vector myVec(10);
+//   myVec.ReSize(10);
+//   cout << myVec.NElts();
+//   return 1;
+
+  cout << "read and write things in file...ppersist!" << endl;
+  TriangleFilter myTF2(10,200,20,40);
+//   PInPersist inTF("outTF");
+//   myTF2.ReadSelf(inTF);
+
+  {  // Test IO PPF GaussianFilter
+  cout << " Writing  GaussianFilter gf(276., 39.6, 0.794, 27., 690.) to PPF " << endl;
+  GaussianFilter gf(276., 39.6, 0.794, 27., 690.);
+  POutPersist s("fgauss.ppf");
+  s << gf ;
+  }
+  {
+  cout << " Reading  GaussianFilter from PPF " << endl;
+  PInPersist s("fgauss.ppf");
+  GaussianFilter gf2;
+  s >> gf2;
+  cout << gf2 << endl;
+  }
+
+} 
Index: /tags/V_Fev00/SophyaLib/SkyT/exclude
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/exclude	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/exclude	(revision 752)
@@ -0,0 +1,5 @@
+extractRS.cc
+easyTest.cc
+tgrsr.cc
+tgsky.cc
+skymixer.cc
Index: /tags/V_Fev00/SophyaLib/SkyT/extractRS.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/extractRS.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/extractRS.cc	(revision 752)
@@ -0,0 +1,508 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <fstream.h>
+#include <iostream.h>
+#include <math.h>
+
+#include <string>
+#include <vector>
+
+#include "tmatrix.h"
+#include "tvector.h"
+#include "vector3d.h"
+
+#include "timing.h"
+#include "sambainit.h"
+#include "pexceptions.h"
+#include "datacards.h"
+#include "fitsioserver.h"
+
+#include "radspecvector.h"
+#include "blackbody.h"
+#include "nupower.h"
+
+#include "squarefilt.h"
+#include "trianglefilt.h"
+#include "specrespvector.h"
+#include "gaussfilt.h"
+
+// -----------------------------------------------------------------
+// ------------- Function declaration ------------------------------
+int CheckCards(DataCards & dc, string & msg);
+char * BuildFITSFileName(string const & fname);
+SpectralResponse * getSpectralResponse(DataCards & dc);
+template <class T>
+void addComponent(SpectralResponse&  sr, PixelMap<T>& finalMap, 
+                  PixelMap<T>& mapToAdd, RadSpectra& rs, double K=1.);
+template <class T>
+void  MeanSig(NDataBlock<T> const & dbl, double& gmoy, double& gsig);
+float ComputeFrequency(DataCards &,string&);
+
+// -----------------------------------------------------------------
+
+//  ----- Global (static) variables ------------
+static bool rdmap = false;    // true -> Read map first 
+static char mapPath[256];     // Path for input maps
+static int  nskycomp = 0;     // Number of sky components
+static int  debuglev = 0;     // Debug Level
+static int  printlev = 0;     // Print Level
+static POutPersist * so = NULL;  // Debug PPFOut file
+
+// -------------------------------------------------------------------------
+//                             main program 
+// -------------------------------------------------------------------------
+int main(int narg, char * arg[])
+{
+  if ((narg < 4) || ((narg > 1) && (strcmp(arg[1], "-h") == 0) )) {
+    cout << "  Usage: extractRS parameterFile outputfitsnameformaps  outputfitsnameforsource [outppfname]" << endl;
+    exit(0);
+  }
+  
+  InitTim();
+  
+  string msg;
+  int rc = 0;
+  RadSpectra * es = NULL;
+  SpectralResponse * sr = NULL;
+  double moy, sig;
+  
+  DataCards dc;
+  so = NULL;
+  
+  try {
+    string dcard = arg[1];
+    cout << " Decoding parameters from file " << dcard << endl;
+    dc.ReadFile(dcard);
+    
+    rc = CheckCards(dc, msg);
+    if (rc) { 
+      cerr << " Error condition -> Rc= " << rc << endl;
+      cerr << " Msg= " << msg << endl;
+      return(rc);
+    }
+  }
+  catch (PException exc) {
+    msg = exc.Msg();
+    cerr << " !!!! extractRS/ Readcard - Catched exception - Msg= " << exc.Msg() << endl;
+    return(90);
+  }   
+  
+  
+  cout << " extractRS/Info : NComp = " <<  nskycomp << endl;
+  cout << "  ... MapPath = " << (string)mapPath << "  DebugLev= " << debuglev 
+       << "  PrintLev= " << printlev << endl;
+  
+
+  // We create an output persist file for writing debug objects
+  if (debuglev > 0) so = new POutPersist("extrRSdbg.ppf");
+  
+  
+  TMatrix<float> outgs;
+  bool okout = false;
+  
+  try {
+    
+    FitsIoServer fios; // Our FITS IO Server
+    char * flnm, buff[90];
+    string key;
+    string key2;
+   
+    double K = 1.;
+    
+    // Loop over sky frequencies components
+    int maxOfSkyComp = nskycomp;
+    int nbOfPix;
+    int sk;
+    Vector freq(maxOfSkyComp);
+    TMatrix<float> spectrum;
+    TMatrix<float> fdenu; //par freq et par pixel
+    int nb_source;
+    TMatrix<float> rareSource; //par freq et par numero de source
+	
+    for(sk = 0; sk<maxOfSkyComp; sk++) 
+      {
+	
+	TMatrix<float> ings;	
+	// Opening the file containing the map
+	
+	if (printlev > 2) cout << " Processing map's frequency component No " << sk+1 << endl;
+	sprintf(buff, "%d", sk+1);
+	key = (string)"RADSPECMAP" + buff;
+	
+	flnm = BuildFITSFileName(dc.SParam(key,0));
+	if (printlev > 2) cout << " Reading Input FITS map " << (string)flnm << endl;
+	
+	fios.load(ings, flnm) ;
+	if (printlev > 2) 
+	  {
+	    MeanSig(ings.DataBlock(), moy, sig );
+	    cout << " MeanSig for input map - Mean= " << moy << " Sigma= " << sig << endl;
+	  }
+
+	// Computing the frequency according to the name of the file
+	freq(sk) =  ComputeFrequency(dc,key);
+	if (printlev > 2)  cout << "filling spectrum for freq = " << freq(sk) << endl;
+	// Opening the file containing the point source
+	sprintf(buff, "%d", sk+1);
+	key2 = (string)"SOURCEPTMAP" + buff;
+	flnm = BuildFITSFileName(dc.SParam(key2,0));
+	const char* nameOfFile = flnm ;
+	if (printlev > 2) cout << " Reading Input FITS map " << nameOfFile << endl;
+	ifstream from(nameOfFile);
+	char ch;
+	string dum;
+	from >> nb_source >> dum;
+	if(sk==0) rareSource.ReSize(maxOfSkyComp,nb_source);
+	for (int ii=0; ii< nb_source; ii++)
+	  {
+	    double value = 0;
+	    from >> value;
+	    rareSource(sk,ii) = value*1.e-26; //for Jansky->W
+	  }
+	from.close();
+
+	nbOfPix = ings.NRows()*ings.NCols();
+	spectrum.ReSize(ings.NRows(),ings.NCols());
+	if(sk==0) fdenu.ReSize(maxOfSkyComp,nbOfPix);
+	int xy=0;
+	for(int x=0;x<ings.NRows(); x++)
+	  {
+	    for(int y=0;x<ings.NCols(); x++)
+	      {
+		spectrum(x,y) = ings(x,y)*1.e-26; //for Jansky->W
+		fdenu(sk,xy) = spectrum(x,y);  
+		xy += 1;
+	      }
+	  }
+	if (printlev > 2) 
+	  {
+	    MeanSig(spectrum.DataBlock(), moy, sig );
+	    cout << " MeanSig for spectrum  map - Mean= " << moy << " Sigma= " << sig << endl;
+	  }
+	
+	
+	K = dc.DParam(key, 1, 1.);
+	if (debuglev > 4) {  // Writing the input map to the outppf
+	  FIO_TMatrix<float> fiog;
+	  fiog.Write(*so, key);
+	}
+	
+	if(printlev>2) 
+	  {	
+	    sprintf(buff, "End of Proc. Comp. %d ", sk+1);
+	    cout << " --------------------------------------- \n" << endl;    
+	    PrtTim(buff);
+	  }
+      }   // End of sky component loop 
+    
+    // ---------------------------------------------------------------------
+    //      Integration in the detector band of the maps
+    // ---------------------------------------------------------------------
+    SpectralResponse* sr = NULL;
+    sr = getSpectralResponse(dc);
+  
+    if (printlev > 2)  cout  << "SpectralResponse!" << *sr << endl;
+    TVector<float> outCoeff(nbOfPix);
+
+    for(int pix=1;pix<nbOfPix;pix++)
+      {
+	Vector smallFDeNu(maxOfSkyComp);
+	for(sk = 0; sk<maxOfSkyComp; sk++) 
+	  {
+	    smallFDeNu(sk) =  fdenu(sk,pix);
+	  }
+	
+	RadSpectraVec radSV(freq,smallFDeNu);
+	if (printlev > 10)  cout << "RadiationSpectra" << radSV << endl;
+
+ 	TVector<float> smallFDeNuT(maxOfSkyComp);
+ 	for(sk = 0; sk<maxOfSkyComp; sk++) 
+ 	  {
+ 	    smallFDeNuT(sk) = smallFDeNu(sk);
+ 	  }
+	outCoeff(pix) = radSV.filteredIntegratedFlux(*sr);
+      }
+
+    FitsIoServer fiosrs;
+    fiosrs.save(outCoeff,arg[2]);
+    cout << "Output Map (TMatrix<float>) written to FITS file "  
+	 << arg[2]<< endl;
+    cout << endl;
+
+    // ---------------------------------------------------------------------
+    //      Integration in the detector band of the sources
+    // ---------------------------------------------------------------------
+    TVector<float> sourceCoeff(nb_source);
+    for(int nsource=0;nsource<nb_source;nsource++)
+      {
+	Vector SourceFDeNu(maxOfSkyComp);
+	for(sk = 0; sk<maxOfSkyComp; sk++) 
+	  {
+	    SourceFDeNu(sk) =  rareSource(sk,nsource);
+	  }
+	RadSpectraVec radSV_Source(freq,SourceFDeNu);
+	sourceCoeff(nsource) = radSV_Source.filteredIntegratedFlux(*sr);
+      }
+    FitsIoServer fiosrs_source;
+    fiosrs_source.save(sourceCoeff,arg[3]);
+    cout << "Output Map (TMatrix<float>) written to FITS file "  
+	 << arg[3]<< endl;
+    cout << endl;
+
+    // ---------------------------------------------------------------------
+    //     Check of write/read on FITS file
+    // ---------------------------------------------------------------------
+    if (printlev > 2)
+    {
+      cout << " Check of write/read on FITS file for skymap!" << endl;
+      TVector<float> outout;
+      FitsIoServer fiotest;
+      fiotest.load(outout, arg[2]);
+      cout << "Coeff(2)" << outout(2) << " ? " << outCoeff(2) << endl;
+      cout << endl;
+    }
+    if (printlev > 2)
+    {
+      cout << " Check of write/read on FITS file for sources!" << endl;
+      FitsIoServer fiotest;
+      TVector<float> outout2;
+      fiotest.load(outout2, arg[3]);
+      cout << "sourceCoeff(2)" << outout2(2) << " ? " << sourceCoeff(2) << endl;
+    }
+
+
+  }   // End of try block
+  
+  
+  catch (PException exc) {
+    msg = exc.Msg();
+    cerr << " !!!! extractRS - Catched PException  - Msg= " << exc.Msg() << endl;
+    rc = 50;
+  }   
+  catch (PThrowable exc) {
+    msg = exc.Msg();
+    cerr << " !!!! extractRS - Catched PThrowable  - Msg= " << exc.Msg() << endl;
+    rc = 50;
+  }   
+  catch (...) {
+    cerr << " Une exception de type inconnue !!! " << endl;
+    exit(99);
+  }
+  
+  // Saving the output map in FITS format 
+  if (okout) {
+    FitsIoServer fios;
+    fios.save(outgs, arg[2]);
+    cout << "Output Map (TMatrix<float>) written to FITS file " 
+	 << (string)(arg[2]) << endl;
+    if(printlev>2) PrtTim("End of WriteFITS ");
+    // Saving the output map in PPF format 
+    if (narg > 3) {
+      POutPersist s(arg[3]); 
+      FIO_TMatrix<float> fiog ;
+      fiog.Write(s);
+      cout << "Output Map (TMatrix<float>) written to POutPersist file "  
+	   << (string)(arg[3]) << endl;
+      if(printlev>2) PrtTim("End of WritePPF ");
+    }
+  }
+  if (so) delete so;  //  Closing the debug ppf file 
+  return(rc);
+}
+
+
+
+/* Nouvelle-Fonction */
+int CheckCards(DataCards & dc, string & msg)
+  //   Function to check datacards
+{
+  rdmap = false;
+  mapPath[0] = '\0';
+  nskycomp = 0;
+  debuglev  = 0;
+  printlev = 0;
+  
+  int rc = 0;
+  string key, key2;
+  
+  //  Checking datacards
+  if (dc.NbParam("EXT_RS") < 1)   {
+     rc = 71; 
+     msg = "Invalid parameters  - Check @EXT_RS card ";
+     return(rc);
+  }
+  int kc;
+  char buff[256];
+  bool pb = false;
+  string key3;
+  int ncomp = 0;
+  ncomp = dc.IParam("EXT_RS", 0);
+  
+  for(kc=0; kc<ncomp; kc++) 
+    {
+      key = "RS_EXT_PATH";
+      if (dc.NbParam(key) < 3)  strncpy(mapPath, dc.SParam(key, 0).c_str(), 255);
+      mapPath[255] = '\0';
+      sprintf(buff, "RADSPECMAP%d", kc+1);
+      key = buff;
+      
+      if (dc.NbParam(key) < 1) {   
+	msg = "Missing or invalid card : " + key;
+	pb = true;  break;
+      }
+    }
+  
+  //  Checking detection filter specification 
+
+  key = "GAUSSFILTER";
+  key2 = "FILTERFITSFILE";
+  if ( (dc.NbParam(key) < 5) && (dc.NbParam(key2) < 3)) { 
+    msg = "Missing card or parameters : Check @GAUSSFILTER or @FILTERFITSFILE";
+    rc = 73;  return(rc); 
+  }
+  
+  if (pb)  {
+    rc = 75;
+    return(75);
+  }
+  
+  
+  // Initialiazing parameters
+  rc = 0;
+  msg = "OK";
+  nskycomp = ncomp;
+  
+  // Checking for PATH definition card
+  key = "RS_EXT_PATH";
+  if (dc.NbParam(key) < 3)  strncpy(mapPath, dc.SParam(key, 0).c_str(), 255);
+  mapPath[255] = '\0';
+  key = "DEBUGLEVEL";
+  debuglev =  dc.IParam(key, 0, 0);
+  key = "PRINTLEVEL";
+  printlev =  dc.IParam(key, 0, 0);
+  return(rc);
+}
+
+static char buff_flnm[1024];   // Mal protege !
+/* Nouvelle-Fonction */
+char* BuildFITSFileName(string const & fname)
+{
+if (mapPath[0] != '\0') sprintf(buff_flnm, "%s/%s", mapPath, fname.c_str());
+else sprintf(buff_flnm, "%s", fname.c_str());
+return(buff_flnm);
+}
+
+
+/* Nouvelle-Fonction */
+template <class T>
+void  MeanSig(NDataBlock<T> const & dbl, double& gmoy, double& gsig)
+
+{
+  gmoy=0.;
+  gsig = 0.; 
+  double valok;
+  for(int k=0; k<(int)dbl.Size(); k++) {
+    valok = dbl(k);
+    gmoy += valok;  gsig += valok*valok; 
+  }
+  gmoy /= (double)dbl.Size();
+  gsig = gsig/(double)dbl.Size() - gmoy*gmoy;
+  if (gsig >= 0.) gsig = sqrt(gsig);
+}
+/* Nouvelle-Fonction */
+template <class T> 
+void addComponent(SpectralResponse&  sr, PixelMap<T>& finalMap, 
+                  PixelMap<T>& mapToAdd, RadSpectra& rs, double K)
+{
+  // finalMap = finalMap + coeff* mapToAdd
+  // coeff    =  convolution of sr and rs 
+  // compute the coefficient corresponding to mapToAdd
+  if (finalMap.NbPixels() != mapToAdd.NbPixels())   
+    throw SzMismatchError("addComponent()/Error: Unequal number of Input/Output map pixels");
+  double coeff = rs.filteredIntegratedFlux(sr) * K;
+  if (printlev > 1) 
+    cout << " addComponent - Coeff= " << coeff << " (K= " << K << ")" << endl; 
+  for(int i=0; i<finalMap.NbPixels(); i++)
+    {
+      finalMap(i) += coeff * mapToAdd(i);
+    }
+}
+
+
+/* Nouvelle-Fonction */
+SpectralResponse * getSpectralResponse(DataCards & dc)
+{
+  SpectralResponse * filt = NULL;
+
+  string key = "FILTERFITSFILE";
+  string key2 = "GAUSSFILTER";
+  string ppfname = "filter";
+
+  if (dc.HasKey(key) ) {      // Reading FITS filter file
+    FitsIoServer fios;
+    char ifnm[256];
+    strncpy(ifnm, dc.SParam(key, 1).c_str(), 255);
+    ifnm[255] = '\0';
+    Matrix mtx(2,10);
+    fios.load(mtx, ifnm);
+    double numin = dc.DParam(key, 2, 1.);
+    double numax = dc.DParam(key, 3, 9999.);
+    Vector nu(mtx.NCols());
+    Vector fnu(mtx.NCols());
+    for(int k=0; k<mtx.NCols(); k++) {
+      nu(k) = mtx(0, k);
+      fnu(k) = mtx(1, k);
+    }
+  filt = new SpecRespVec(nu, fnu, numin, numax);
+  ppfname = key;
+  }
+  else if (dc.HasKey(key2) ) {   // creating GaussianFilter 
+    double nu0 = dc.DParam(key2, 0, 10.);
+    double s = dc.DParam(key2, 1, 1.);
+    double a = dc.DParam(key2, 2, 1.);
+    double numin = dc.DParam(key2, 3, 0.1);
+    double numax = dc.DParam(key2, 4, 9999);
+    filt = new GaussianFilter(nu0, s, a, numin, numax);
+    ppfname = key2;
+    }
+  if (filt == NULL) throw ParmError("datacard error ! No detection filter");
+  cout << " Filter decoded - Created " << endl;
+  cout << *filt << endl;
+
+// for debug
+  //  if (debuglev > 1)  SpectralResponse2Nt(*filt, *so, ppfname);
+  return(filt);
+}
+
+
+float ComputeFrequency(DataCards & dc,string& key)
+{
+  ofstream filename("temp_filename");
+  filename << dc.SParam(key,0) << '\n';
+  filename.close();
+  
+  ifstream fromtempfile("temp_filename");
+  char chtemp;
+  string temp_str;
+  int count = 0;
+  do { 
+    fromtempfile.get(chtemp);    
+    if(count> 12 && count < 20)
+      {
+	temp_str+= chtemp; 
+      }
+    count+=1;
+  } while(chtemp!='\n'); 
+  fromtempfile.close();
+  
+  ofstream filename2("temp_filename");
+  filename2 << temp_str << '\n';
+  filename2.close();
+  
+  int frequency;
+  ifstream fromtempfile2("temp_filename");
+  fromtempfile2 >> frequency;
+  fromtempfile2.close();
+  return ((float)frequency/1000.);
+}
Index: /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.cc	(revision 752)
@@ -0,0 +1,150 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: gaussfilt.cc,v 1.4 1999-11-29 14:16:04 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+
+#include "gaussfilt.h"
+
+//----------------
+// Constructor --
+//----------------
+GaussianFilter::GaussianFilter()
+  : SpectralResponse()
+{
+  setParams(100, 10., 1.);
+}
+
+GaussianFilter::GaussianFilter(double nu0, double s, double a, double numin, double numax)
+  : SpectralResponse(numin, numax)
+{
+  setParams(nu0, s, a);
+}
+
+
+//--------------
+// Destructor --
+//--------------
+GaussianFilter::~GaussianFilter()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+
+double 
+GaussianFilter::transmission(double nu) const
+{
+  if ((nu < _numin) || (nu > _numax)) return(0.);
+  else { 
+    double tmp = (nu-_nu0)/_s;
+    return(_a * exp(-tmp*tmp));
+  }
+}
+
+double 
+GaussianFilter::peakFreq()  const
+{
+return(_nu0);
+}
+
+double 
+GaussianFilter::peakTransmission() const
+{
+return(_a);
+}
+
+
+
+void 
+GaussianFilter::setParams(double nu0, double s, double a)
+{
+  if (s < 1.e-19) s = 1.e-19;
+  _s = s;
+  _nu0 = nu0;
+  _a = a;
+}
+
+
+
+void 
+GaussianFilter::Print(ostream& os)  const
+{ 
+  os << "GaussianFilter::Print - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << " T = A * Exp(-((nu-nu0)/s)^2) : " << " nu0= " << _nu0 << " sig= " 
+     << _s << "  A= " << _a << endl;  
+  os << "PeakFreq= " << peakFreq() << "  Transmission= " << transmission(peakFreq()) << endl;
+
+
+}
+
+void
+ObjFileIO<GaussianFilter>::WriteSelf(POutPersist& s) const
+{
+  if(dobj == NULL)
+    {
+      cout << " ObjFileIO<GaussianFilter>::WriteSelf:: dobj= null " << endl;
+      return;
+    }
+  int_4 version, nothing;
+  version = 1;
+  nothing = 0;   // Reserved for future use 
+  s.PutI4(version);
+  s.PutI4(nothing);
+
+  s.PutR8(dobj->minFreq());
+  s.PutR8(dobj->maxFreq());
+  s.PutR8(dobj->giveNorm());
+  s.PutR8(dobj->giveNu0());
+  s.PutR8(dobj->giveDNu());
+}
+
+void
+ObjFileIO<GaussianFilter>::ReadSelf(PInPersist& s)  
+{
+  int_4 version, nothing;
+  version = 1;
+  nothing = 0;   // Reserved for future use 
+  s.GetI4(version);
+  s.GetI4(nothing);
+
+  if(dobj == NULL)
+    {
+      dobj= new GaussianFilter();
+      ownobj= true;
+    }
+
+  r_8 a, nu0, dnu, numin, numax;
+  s.GetR8(numin);
+  s.GetR8(numax);
+  s.GetR8(a);
+  s.GetR8(nu0);
+  s.GetR8(dnu);
+  dobj->setMinMaxFreq(numin, numax);
+  dobj->setParams(nu0, dnu, a);
+  //  cout << " Norm - Nu0 - DNu - minFreq - maxFreq " << endl; 
+  // cout << _a << "-" << _nu0  << "-" << _s << "-" << _numin << "-" << _numax << endl;
+}
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<GaussianFilter>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<GaussianFilter>;
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/gaussfilt.h	(revision 752)
@@ -0,0 +1,74 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: gaussfilt.h,v 1.4 1999-11-29 14:16:05 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef GAUSSFILT_H_SEEN
+#define GAUSSFILT_H_SEEN
+
+//----------------------
+// Base Class Headers --
+//----------------------
+#include "specresp.h"
+#include "objfio.h"
+
+//------------------------------------
+// Collaborating Class Declarations --
+//------------------------------------
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+// Spectral response in the form  A Exp(-((nu-nu0)/s)^2) 
+
+namespace SOPHYA {
+
+class GaussianFilter:public SpectralResponse
+{
+public:
+  //Constructors
+  GaussianFilter ();
+  GaussianFilter (double nu0, double s, double a=1., double numin=0., double numax= 9.e49); 
+  
+
+  // destructor
+  virtual ~GaussianFilter();
+
+  //
+  //  Function members
+  //
+
+  virtual double transmission(double) const;
+  virtual double peakFreq() const;
+  virtual double peakTransmission() const;
+
+  virtual void   Print(ostream& os)  const;
+
+  virtual inline double giveNorm() const {return _a;};
+  virtual inline double giveNu0() const {return _nu0;};
+  virtual inline double giveDNu() const {return _s;};
+  virtual void setParams(double nu0, double s, double a=1.);
+  
+protected:
+  double _a, _s, _nu0;
+};
+
+
+  // ObjFileIO<SpecRespVec> pour les PPersist 
+  inline POutPersist& operator << (POutPersist& os, GaussianFilter & obj)
+    { ObjFileIO<GaussianFilter> fio(&obj); fio.Write(os); return(os);}
+  
+  inline PInPersist& operator >> (PInPersist& os, GaussianFilter & obj)
+    { ObjFileIO<GaussianFilter> fio(&obj); fio.Read(os); return(os);}
+
+};  // End of namespace 
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/howto.d
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/howto.d	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/howto.d	(revision 752)
@@ -0,0 +1,47 @@
+#  SKYMIX  NbComponents  NSide_HealPix
+SKYMIX  3  128
+
+#  READMAP  FitsName
+#  To Read the already prepared (mixed) Output MAP from FITS file
+#  FitsName should be the complete path to the FITS file
+READMAP xxx.fits
+
+#  Defining the Detection filter pass - band
+#  GAUSSFILTER or FILTERFITSFILE  card
+#  GAUSSFILTER -> Gaussian filter
+#  FILTERFITSFILE -> Filter (nu, T(nu)) from FITS file
+#  GAUSSFILTER  Nu0 Sigma_Nu Tmax NuMin NuMax
+#  FILTERFITSFILE FileName NuMin NuMax
+#       FileName should be a complete path
+@GAUSSFILTER 143 12 0.84 50. 300.
+
+#  MAPPATH  PathForFITS   
+#  path for input Sky Component FITS files , and EmissionSpectra files 
+MAPPATH /data/opus/Rz/SOPHYA/
+
+
+#  ----        Sky components  ---------
+#      ----     HealPix maps   ----
+#  MAPFITSFILEi FITSfilename Normalisation
+@MAPFITSFILE1  gauss.fits  1.0 
+
+#      ---   Emission Spectra definition -----
+#   SPECTRAFITSFILEi  FITSfilename  Fmin Fmax 
+@SPECTRAFITSFILE1  pl.fits 100 600  
+
+#   Other possible definition of emission spectra
+#   BLACKBODYi  temperature
+#  The blackbody object returns flux in units of watt/m2/sr/hz
+#   We thus scale the map (x 1.e17) 
+@MAPFITSFILE2  cossin.fits  1.e17 
+@BLACKBODY2 2.726
+
+#   For power-law spectra  f = a ((nu-nu0)/dnu)^b)
+#   POWERLAWSPECTRAi  a nu0 dnu b Fmin Fmax
+@MAPFITSFILE3  noise.fits    0.1 
+@POWERLAWSPECTRA3 1. 150. 50. -0.5 100. 500.
+
+#  Define the Debug level
+@DEBUGLEVEL  0
+#  Define the Print level
+@PRINTLEVEL  5
Index: /tags/V_Fev00/SophyaLib/SkyT/makeprog
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/makeprog	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/makeprog	(revision 752)
@@ -0,0 +1,49 @@
+MODULECXXREPNAME := SkyT
+# MODULEDECCXXFLAGS := -msg_quiet
+include $(DPCDEVREP)/Include/Makefile.h
+
+ifdef NOSHLIB
+LIBF =  $(LIB)libFitsIOServer.a $(LIB)libSkyT.a $(LIB)libSamba.a $(LIB)libNTools.a $(LIB)libSysTools.a 
+LIBS = -L$(LIB) -lSkyT -lSamba -lNTools -lSysTools -lm
+ifeq ($(CXX),cxx)
+# librairie des instances de templates cxx
+LIBS := $(LIBS) -lertcxx
+endif
+else
+LIBF =  $(SLB)/libtools.so 
+LIBS = -L$(SLB) -ltools -lm 
+ifeq ($(MACHEROS),Linux)
+LIBS := $(LIBS) -ldl
+endif
+endif
+
+
+myexe = $(EXE)easyTest $(EXE)skymixer $(EXE)extractRS $(EXE)tgsky $(EXE)tgrsr 
+
+all : $(myexe)
+
+
+$(EXE)easyTest :  $(OBJ)easyTest.o 
+	$(LINK.cc)  $^ $(LIBS) -o $@
+
+$(EXE)skymixer :  $(OBJ)skymixer.o 
+	$(LINK.cc)  $^ $(LIBS) -o $@
+
+$(EXE)extractRS :  $(OBJ)extractRS.o 
+	$(LINK.cc)  $^ $(LIBS) -o $@
+
+$(EXE)tgsky :  $(OBJ)tgsky.o 
+	$(LINK.cc)  $^ $(LIBS) -o $@
+
+$(EXE)tgrsr :  $(OBJ)tgrsr.o 
+	$(LINK.cc)  $^ $(LIBS) -o $@
+
+$(OBJ)easyTest.o : easyTest.cc
+
+$(OBJ)tgsky.o : tgsky.cc
+
+$(OBJ)tgrsr.o : tgrsr.cc
+
+$(OBJ)skymixer.o : skymixer.cc
+
+$(OBJ)extractRS.o : extractRS.cc
Index: /tags/V_Fev00/SophyaLib/SkyT/nupower.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/nupower.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/nupower.cc	(revision 752)
@@ -0,0 +1,92 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: nupower.cc,v 1.5 1999-11-29 16:59:10 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density for a nupower
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+
+#include "nupower.h"
+
+//----------------
+// Constructor --
+//----------------
+PowerLawSpectra::PowerLawSpectra()
+{
+}
+
+PowerLawSpectra::PowerLawSpectra(double a, double b, double nu0, double dnu, double numin, double numax)
+  : RadSpectra(numin, numax)
+{
+  _a = a;
+  _b = b;
+  _nu0 = nu0;
+  _dnu = (dnu > 1.e-19) ? dnu : 1.;
+}
+
+
+PowerLawSpectra::~PowerLawSpectra()
+{
+}
+
+double
+PowerLawSpectra::flux(double nu) const
+{
+  if ((nu< _numin) || (nu > _numax)) return(0.);
+  double tmp = (nu-_nu0)/_dnu;
+  if (tmp <= 0.)  return(0.); 
+  else return(  _a * pow(tmp, _b) );
+}
+
+
+
+void
+PowerLawSpectra::Print(ostream& os) const
+{
+  os << "PowerLawSpectra::Print f = a ((nu-nu0)/dnu)^b " << _a << "((nu-" << _nu0 
+     << ") / " << _dnu << ") ^ " << _b << endl;
+  os << " - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Emission= " << flux(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Emission= " << flux(peakFreq()) << endl;
+
+}
+
+
+/*
+void 
+PowerLawSpectra::WriteSelf(POutPersist& s)  
+{
+  s.PutR8(this->giveNorm());
+  s.PutR8(this->giveNu0());
+  s.PutR8(this->giveDNu());
+  s.PutR8(this->giveExp());
+  s.PutR8(this->minFreq());
+  s.PutR8(this->maxFreq());
+}
+
+void
+PowerLawSpectra::ReadSelf(PInPersist& s)  
+{
+  s.GetR8(_a);
+  s.GetR8(_nu0);
+  s.GetR8(_dnu);
+  s.GetR8(_b);
+  s.GetR8(_numin);
+  s.GetR8(_numax);
+  cout << " Norm - Nu0 - DNu - Exp - minFreq - maxFreq " << endl; 
+  cout << _a << "-" << _nu0  << "-" << _dnu << "-" << _b << "-" << _numin << "-" << _numax << endl;
+}
+
+*/
Index: /tags/V_Fev00/SophyaLib/SkyT/nupower.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/nupower.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/nupower.h	(revision 752)
@@ -0,0 +1,44 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: nupower.h,v 1.5 1999-11-29 16:59:10 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef NUPOWER_H_SEEN
+#define NUPOWER_H_SEEN
+
+#include "radspec.h"
+#include "convtools.h"
+
+// Power law spectra  f = a ((nu-nu0)/dnu)^b   
+class PowerLawSpectra : public RadSpectra
+{
+public:   //Constructor
+  
+  PowerLawSpectra();
+  PowerLawSpectra(double a, double b, double nu0, double dnu, double numin=0., double numax=9.e49);
+
+  virtual ~PowerLawSpectra();
+
+  virtual double flux(double nu) const;
+
+  // Redefintion of the Print function
+  virtual void      Print(ostream& os)  const;
+  
+  virtual inline double giveNorm() const {return _a;};
+  virtual inline double giveNu0() const {return _nu0;};
+  virtual inline double giveDNu() const {return _dnu;};
+  virtual inline double giveExp() const {return _b;};
+  
+
+protected:
+  double _a, _b, _nu0, _dnu;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/objlist.list
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/objlist.list	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/objlist.list	(revision 752)
@@ -0,0 +1,10 @@
+blackbody.o
+convtools.o
+gaussfilt.o
+nupower.o
+radspec.o
+radspecvector.o
+specresp.o
+specrespvector.o
+squarefilt.o
+trianglefilt.o
Index: /tags/V_Fev00/SophyaLib/SkyT/radspec.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/radspec.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/radspec.cc	(revision 752)
@@ -0,0 +1,245 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: radspec.cc,v 1.3 1999-11-29 14:16:06 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <typeinfo>
+#include <math.h>
+
+#include "radspec.h"
+#include "integ.h"
+
+//----------------
+// Constructor --
+//----------------
+RadSpectra::RadSpectra(double numin, double numax)
+{
+  _numin = numin;
+  _numax = numax;
+}
+
+
+//--------------
+// Destructor --
+//--------------
+RadSpectra::~RadSpectra()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+double 
+RadSpectra::minFreq()  const
+{
+  return _numin;
+}
+
+double 
+RadSpectra::maxFreq()  const
+{
+  return _numax;
+}
+
+double 
+RadSpectra::meanFreq()  const
+{
+  double result = (_numax+_numin)/2.;
+  return result;
+}
+
+
+
+// peakFreq returns the value of the frequency for the
+// peak of the spectrum. 
+double 
+RadSpectra::peakFreq()  const
+{
+  double maxAnswer = -1.e99;
+  double maxNu = -10;
+  double nu;
+  for (int i=1; i<1000;i++)
+    {
+      nu=(_numax-_numin)*i/1000.+_numin;
+      double lookForMax = flux(nu);
+      if(maxAnswer <= lookForMax) {
+	maxAnswer= lookForMax;
+	maxNu    = nu;
+      }
+    }
+  return maxNu;  
+}
+
+// To change min-max frequency
+void
+RadSpectra::setMinMaxFreq(double numin, double numax)
+{
+  _numin = numin;
+  _numax = numax;
+}
+
+// the RadSpectra_fluxFunction function is used to call TrpzInteg double(double) 
+// (integration over a range of frequencies)
+static RadSpectra* _raypourfinteg = NULL;
+static double RadSpectra_fluxFunction(double nu)
+{
+   return(_raypourfinteg->flux(nu));   
+}
+
+double 
+RadSpectra::integratedFlux(double f1, double f2)  const
+{
+//   cout << endl;
+//   cout <<  this->minFreq() << " = " << this->maxFreq() << endl;
+//   cout <<  f1 << " = " << f2 << endl;
+  if(f1 < this->minFreq()) f1 = this->minFreq();
+  if(f2 > this->maxFreq()) f2 = this->maxFreq();
+  _raypourfinteg = const_cast<RadSpectra *>(this);
+  TrpzInteg I(RadSpectra_fluxFunction , f1, f2);  
+  double val = (double)I;
+  _raypourfinteg = NULL;  // On ne peut pas faire ca avant la destruction de I
+  return(val);        
+}
+double 
+RadSpectra::integratedFlux()  const
+{
+  return integratedFlux(this->minFreq(),this->maxFreq());
+}
+
+// integration using the logarithm !!
+// Carefull!! Base 10....
+static RadSpectra* _rayIntLog = NULL;
+
+static double RadSpectra_logFluxFunction(double tau)
+{
+  double value = _rayIntLog->flux(pow(10,tau))*pow(10,tau);
+  return(value);   
+}
+
+double 
+RadSpectra::logIntegratedFlux(double f1, double f2)  const
+{
+  if(f1 < this->minFreq()) f1 = this->minFreq();
+  if(f2 > this->maxFreq()) f2 = this->maxFreq();
+
+  double f1Log = log10(f1);
+  double f2Log = log10(f2);
+  if(f1Log < -1.e99) f1Log = -1.e99;
+  if(f2Log > 1.e99)  f2Log = 1.e99;
+  _rayIntLog = const_cast<RadSpectra *>(this);
+  TrpzInteg I(RadSpectra_logFluxFunction,f1Log,f2Log);
+  double value = (double)I * log(10.);
+  _rayIntLog = NULL;
+  return(value);        
+}
+
+double 
+RadSpectra::logIntegratedFlux()  const
+{
+  return logIntegratedFlux(_numin,_numax);
+}
+
+// the RadSpectra_filteredFlux function is used to call TrpzInteg double(double) 
+// (integration over a range of frequencies with a filter)
+static SpectralResponse* _filter = NULL ;
+static double RadSpectra_filteredFlux(double nu) 
+{
+  double flux = _raypourfinteg->flux(nu);
+  return(flux * _filter->transmission(nu));
+}
+
+
+double 
+RadSpectra::filteredIntegratedFlux(SpectralResponse const& filter, double f1, double f2) const
+{
+  _raypourfinteg = const_cast<RadSpectra *>(this);
+  _filter = const_cast<SpectralResponse *>(&filter);
+   if(f1 < this->minFreq()) f1 = this->minFreq();
+   if(f2 > this->maxFreq()) f2 = this->maxFreq();
+
+  TrpzInteg I(RadSpectra_filteredFlux,f1,f2);
+  double val = (double)I;
+  _raypourfinteg = NULL;
+  _filter = NULL;
+  return(val);        
+}
+
+double 
+RadSpectra::filteredIntegratedFlux(SpectralResponse const& filter)
+{
+  double minOfMin = filter.minFreq();
+  double maxOfMax = filter.maxFreq();
+  if(minOfMin < this->minFreq()) minOfMin = this->minFreq();
+  if(maxOfMax > this->maxFreq()) maxOfMax = this->maxFreq();  
+  return(filteredIntegratedFlux(filter, minOfMin, maxOfMax ) );
+}
+
+
+// the RadSpectraVec_filteredFlux function is used to call TrpzInteg double(double) 
+// (integration over a range of frequencies with a filter)
+static double RadSpectra_logFilteredFlux(double tau) 
+{
+  double nu = pow(10,tau);
+  double flux = _raypourfinteg->flux(nu)*nu;
+  double result = flux * _filter->transmission(nu);
+  return(result);
+}
+
+
+double 
+RadSpectra::filteredLogIntFlux(SpectralResponse const& filter, double f1, double f2) const
+{
+  
+   _raypourfinteg = NULL;
+   _filter = NULL;
+   if(f1 < this->minFreq()) f1 = this->minFreq();
+   if(f2 > this->maxFreq()) f2 = this->maxFreq();
+   
+   double f1Log = log10(f1);
+   double f2Log = log10(f2);
+   if(f1Log < -1.e99) f1Log = -1.e99;
+   if(f2Log > 1.e99)  f2Log = 1.e99;
+   _raypourfinteg = const_cast<RadSpectra *>(this);
+   _filter = const_cast<SpectralResponse *>(&filter);
+   TrpzInteg I(RadSpectra_logFilteredFlux,f1Log,f2Log);  
+   double val = (double)I;
+   _raypourfinteg = NULL;
+   _filter = NULL;
+   return(val* log(10.));        
+}
+
+double 
+RadSpectra::filteredLogIntFlux(SpectralResponse const& filter)
+{
+  return(filteredLogIntFlux(filter, filter.minFreq(), filter.maxFreq() ) );
+}
+
+
+
+
+void
+RadSpectra::Print(ostream& os) const
+{
+  //  os << "RadSpectra::Print (" << typeid(*this).name() 
+  //     << ") - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "RadSpectra::Print  - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Emission= " << flux(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Emission= " << flux(peakFreq()) << endl;
+
+}
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/radspec.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/radspec.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/radspec.h	(revision 752)
@@ -0,0 +1,89 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: radspec.h,v 1.4 1999-11-29 16:59:11 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef RADSPEC_H_SEEN
+#define RADSPEC_H_SEEN
+
+#include "machdefs.h"
+#include <iostream.h>
+
+#include "specresp.h"
+#include "objfio.h"
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+// ***IMPORTANT*** All frequencies are expressed in GHz  (10^9 Hz)
+//                 and flux in Watt/m^2/sr
+
+class RadSpectra
+{
+
+public:
+  //Constructor
+  RadSpectra (double numin=0., double numax=9.e49);
+
+  // destructor
+  virtual ~RadSpectra();
+
+  //
+  //  Member Functions
+  //
+
+  //  The flux() function is virtual: 
+  //  It computes the flux per units of W/m^2/Hz/st
+  // implemented in the subclasses
+  virtual double flux(double nu) const =0;
+  inline double operator() (double nu) const { return(flux(nu)); }
+
+  virtual double minFreq() const;
+  virtual double maxFreq() const;
+  virtual double meanFreq() const;
+  virtual double peakFreq() const;
+
+  // For changing the min/max frequency
+  virtual void	 setMinMaxFreq(double numin, double numax);
+
+  // The IntegratedFlux() function
+  // integrates the flux function between two frequencies: 
+  // numin and numax (in GHz)
+  virtual double integratedFlux( double numin, double numax) const ;
+  virtual double logIntegratedFlux( double numin, double numax) const ;
+
+  // same but integrated over the full spectrum of frequencies
+  virtual  double integratedFlux() const ;
+  virtual  double logIntegratedFlux() const ;
+  
+  // filteredIntegratedFlux integrates the flux function while
+  // taking into account the spectralResponse of a filter
+  virtual double filteredIntegratedFlux(SpectralResponse const & filter, 
+					double numin, double numax) const ;
+  virtual double filteredLogIntFlux(SpectralResponse const & filter, 
+					double numin, double numax) const ;
+
+  // same but integrates over the filter's frequency band
+  virtual double filteredIntegratedFlux(SpectralResponse const & filter);
+  virtual double filteredLogIntFlux(SpectralResponse const & filter);
+
+  virtual void      Print(ostream& os)  const;
+
+protected:
+  double _numin;
+  double _numax;
+};
+
+// Definition de l'operateur <<
+inline ostream& operator << (ostream& s,  RadSpectra const & rs)
+  {  rs.Print(s);  return(s);  }
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/radspecvector.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/radspecvector.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/radspecvector.cc	(revision 752)
@@ -0,0 +1,130 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: radspecvector.cc,v 1.5 1999-11-29 16:59:11 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+// #include <typeinfo>
+
+#include "radspecvector.h"
+#include "pexceptions.h"
+
+//----------------
+// Constructor --
+//----------------
+RadSpectraVec::RadSpectraVec()
+{
+}
+
+RadSpectraVec::RadSpectraVec(Vector const & nu, Vector const & fdenu, double numin, double numax)
+        : RadSpectra(numin, numax)
+{
+  if(nu.NElts() != fdenu.NElts())  
+    throw SzMismatchError("RadSpectraVec::RadSpectraVec() - Non equal vector sizes");
+  _vecOfNu = nu;
+  _vecOfFDeNu = fdenu;
+  _numin = nu(0);
+  _numax = nu(nu.NElts()-1);
+}
+
+
+//--------------
+// Destructor --
+//--------------
+RadSpectraVec::~RadSpectraVec()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+
+
+
+double 
+RadSpectraVec::flux(double nu) const
+{
+  if ( (nu < _numin) || (nu > _numax) ) return(0.);
+  double value = 0.;
+  int sizeVecOfNu = _vecOfNu.NElts();
+  if(nu <=  _vecOfNu(0)) return _vecOfFDeNu(0);
+  if(nu >=  _vecOfNu(sizeVecOfNu-1)) return _vecOfFDeNu(sizeVecOfNu-1);
+  
+  for (int i=1; i<sizeVecOfNu; i++)
+    {
+      if(nu < _vecOfNu(i))
+	{
+	  double up = _vecOfFDeNu(i) ;
+	  double down = _vecOfFDeNu(i-1);
+	  double xmin = _vecOfNu(i-1);
+	  double xmax = _vecOfNu(i);
+	  double a = ((up-down)/(xmax-xmin));
+	  value = a*nu+(up-a*xmax);
+	  return value;
+	}
+    }
+  return _vecOfFDeNu(sizeVecOfNu-1);
+}
+
+
+
+void
+RadSpectraVec::Print(ostream& os) const
+{
+  //  os << "RadSpectraVec::Print (" << typeid(*this).name() 
+  //     << ") - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "RadSpectraVec::Print  - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Emission= " << flux(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Emission= " << flux(peakFreq()) << endl;
+
+}
+
+/*
+void
+RadSpectraVec::WriteSelf(POutPersist& s) 
+{
+  s.PutI4(this->NbElts());
+  for (int i=0; i< this->NbElts(); i++)
+    {
+      s.PutR8(this->getNuVec(i));
+      s.PutR8(this->getFNuVec(i));
+    }
+  s.PutR8(this->minFreq());
+  s.PutR8(this->maxFreq());
+ 
+}
+
+void
+RadSpectraVec::ReadSelf(PInPersist& s) 
+{
+  s.GetI4(_size);
+
+  _vecOfNu.ReSize(_size);
+  _vecOfFDeNu.ReSize(_size);
+  for (int i=0; i< _size; i++)
+    {
+      s.GetR8(_vecOfNu(i));
+      s.GetR8(_vecOfFDeNu(i));
+    } 
+  s.GetR8(_numin);
+  s.GetR8(_numax);
+  cout << "minFreq - maxFreq"<< endl; 
+  cout <<    _numin<< "-" <<  _numax << endl;
+}
+*/
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/radspecvector.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/radspecvector.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/radspecvector.h	(revision 752)
@@ -0,0 +1,60 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef RADSPECTRAVEC_H_SEEN
+#define RADSPECTRAVEC_H_SEEN
+#include "machdefs.h"
+#include <iostream.h>
+
+#include "radspec.h"
+#include "tvector.h"
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+// ***IMPORTANT*** All frequencies are expressed in GHz  (10^9 Hz)
+//                 and flux in Watt/m^2/sr
+
+class RadSpectraVec : public RadSpectra
+{
+
+public:
+  //Constructor
+  RadSpectraVec ();
+  RadSpectraVec (Vector const & nu, Vector const & fdenu, double numin=0., double numax=9.e49);
+
+  // destructor
+  virtual ~RadSpectraVec();
+
+  //
+  //  Member Functions
+  //
+
+  //  The flux() function is virtual: 
+  //  It computes the flux per units of W/m^2/Hz/st
+  // implemented in the subclasses
+  virtual double flux(double nu) const;
+
+  // Acces to Nu and F(nu) vectors 
+  inline Vector& getNuVec() { return _vecOfNu; }
+  inline Vector& getFNuVec() { return _vecOfFDeNu; }
+  inline double getNuVec(int i) const { return _vecOfNu(i); }
+  inline double getFNuVec(int i) const { return _vecOfFDeNu(i); }
+
+  virtual void   Print(ostream& os)  const;
+
+protected:
+  Vector _vecOfNu;
+  Vector _vecOfFDeNu;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/skm.d
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/skm.d	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/skm.d	(revision 752)
@@ -0,0 +1,43 @@
+#  SKYMIX  NbComponents  NSide_HealPix
+@SKYMIX  2  64
+
+#  READMAP  FitsName
+#  To Read the already prepared (mixed) Output MAP from FITS file
+#  FitsName should be the complete path to the FITS file
+READMAP xxx.fits
+
+#  Defining the Detection filter pass - band
+#  GAUSSFILTER or FILTERFITSFILE  card
+#  GAUSSFILTER -> Gaussian filter
+#  FILTERFITSFILE -> Filter (nu, T(nu)) from FITS file
+#  GAUSSFILTER  Nu0 Sigma_Nu Tmax NuMin NuMax
+#  FILTERFITSFILE FileName NuMin NuMax
+#       FileName should be a complete path
+@GAUSSFILTER 143 12 0.84 50. 300.
+
+#  MAPPATH  PathForFITS   
+#  path for input Sky Component FITS files , and EmissionSpectra files 
+MAPPATH /exp/eros/Reza/CartesRT
+
+
+#  ----        Sky components  ---------
+#      ----     HealPix maps   ----
+#  MAPFITSFILEi FITSfilename Normalisation
+@MAPFITSFILE1  map_essai.fits  1.0 
+@MAPFITSFILE2    comp2.fits    0.25 
+
+#      ---   Emission Spectra definition -----
+#   SPECTRAFITSFILEi  FITSfilename  Fmin Fmax 
+@SPECTRAFITSFILE1  spec1.fits  
+
+#   Other possible definition of emission spectra
+#   BLACKBODYi  temperature
+BLACKBODY1 2.726
+#   For power-law spectra  f = a ((nu-nu0)/dnu)^b)
+#   POWERLAWSPECTRAi  a nu0 dnu b Fmin Fmax
+POWERLAWSPECTRA1 1. 150. 50. -0.5 100. 500.
+
+#  Define the Debug level
+@DEBUGLEVEL  0
+#  Define the Print level
+@PRINTLEVEL  0
Index: /tags/V_Fev00/SophyaLib/SkyT/skyinit.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/skyinit.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/skyinit.cc	(revision 752)
@@ -0,0 +1,34 @@
+// Classe d'initialisation du module Outils++ 
+#include <unistd.h>
+
+#include "skyinit.h"
+#include "ppersist.h"
+#include "objfio.h"
+#include "specrespvector.h"
+#include "gaussfilt.h"
+
+int SkyTInitiator::FgInit = 0;
+
+SkyTInitiator::SkyTInitiator()
+  : PeidaOutilsInitiator()
+{
+  SkyTInitiator::FgInit++;
+  if (SkyTInitiator::FgInit > 1)  return;
+
+//   Enregistrement des classes PPersist du modules SkyT
+  
+  PPRegister(ObjFileIO<SpecRespVec>);
+  PPRegister(ObjFileIO<GaussianFilter>);
+
+}
+
+SkyTInitiator::~SkyTInitiator()
+{
+  SkyTInitiator::FgInit--;
+}
+
+
+// On met un objet initiator en statique, pour les loaders qui savent 
+// appeler le constructeur des objets statiques   Reza 08/98
+static SkyTInitiator s_skytinit_;
+
Index: /tags/V_Fev00/SophyaLib/SkyT/skyinit.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/skyinit.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/skyinit.h	(revision 752)
@@ -0,0 +1,23 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe d'initialiseur du module Outils++
+
+#ifndef SKYTINIT_H_SEEN
+#define SKYTINIT_H_SEEN
+
+
+// Classe d''initialisation pour les modules de PEIDA++
+#include "outilsinit.h"
+
+class SkyTInitiator : public PeidaOutilsInitiator {
+private:
+  static int FgInit;
+public:
+  			SkyTInitiator();
+  virtual		~SkyTInitiator();
+};
+
+#undef PeidaInit
+#define PeidaInit() SkyTInitiator _skytinitiator_
+
+#endif
+
Index: /tags/V_Fev00/SophyaLib/SkyT/skymixer.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/skymixer.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/skymixer.cc	(revision 752)
@@ -0,0 +1,478 @@
+#include "machdefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <iostream.h>
+#include <math.h>
+
+#include <string>
+#include <vector>
+
+#include "timing.h"
+#include "sambainit.h"
+#include "pexceptions.h"
+#include "datacards.h"
+#include "fitsioserver.h"
+
+#include "spheregorski.h"
+
+#include "radspecvector.h"
+#include "blackbody.h"
+#include "nupower.h"
+
+#include "squarefilt.h"
+#include "trianglefilt.h"
+#include "specrespvector.h"
+#include "gaussfilt.h"
+
+// -----------------------------------------------------------------
+// ------------- Function declaration ------------------------------
+int CheckCards(DataCards & dc, string & msg);
+char * BuildFITSFileName(string const & fname);
+SpectralResponse * getSpectralResponse(DataCards & dc);
+RadSpectra * getEmissionSpectra(DataCards & dc, int nc);
+void RadSpec2Nt(RadSpectra & rs, POutPersist & so, string name);
+void SpectralResponse2Nt(SpectralResponse& sr, POutPersist & so, string name);
+
+template <class T>
+void addComponent(SpectralResponse&  sr, PixelMap<T>& finalMap, 
+                  PixelMap<T>& mapToAdd, RadSpectra& rs, double K=1.);
+template <class T>
+void  MeanSig(NDataBlock<T> const & dbl, double& gmoy, double& gsig);
+// -----------------------------------------------------------------
+
+//  ----- Global (static) variables ------------
+static bool rdmap = false;    // true -> Read map first 
+static char mapPath[256];     // Path for input maps
+static int  hp_nside = 32;    // HealPix NSide
+static int  nskycomp = 0;     // Number of sky components
+static int  debuglev = 0;     // Debug Level
+static int  printlev = 0;     // Print Level
+static POutPersist * so = NULL;  // Debug PPFOut file
+
+// -------------------------------------------------------------------------
+//                             main program 
+// -------------------------------------------------------------------------
+int main(int narg, char * arg[])
+{
+  if ((narg < 3) || ((narg > 1) && (strcmp(arg[1], "-h") == 0) )) {
+    cout << "  Usage: skymixer parameterFile outputfitsname [outppfname]" << endl;
+    exit(0);
+  }
+
+InitTim();
+
+string msg;
+int rc = 0;
+RadSpectra * es = NULL;
+SpectralResponse * sr = NULL;
+double moy, sig;
+
+DataCards dc;
+so = NULL;
+
+try {
+  string dcard = arg[1];
+  cout << " Decoding parameters from file " << dcard << endl;
+  dc.ReadFile(dcard);
+
+  rc = CheckCards(dc, msg);
+  if (rc) { 
+    cerr << " Error condition -> Rc= " << rc << endl;
+    cerr << " Msg= " << msg << endl;
+    return(rc);
+  }
+}
+catch (PException exc) {
+  msg = exc.Msg();
+  cerr << " !!!! skymixer/ Readcard - Catched exception - Msg= " << exc.Msg() << endl;
+  return(90);
+}   
+
+
+cout << " skymix/Info : NComp = " <<  nskycomp << " SphereGorski_NSide= " << hp_nside << endl;
+cout << "  ... MapPath = " << (string)mapPath << "  DebugLev= " << debuglev 
+     << "  PrintLev= " << printlev << endl;
+
+// We create an output persist file for writing debug objects
+if (debuglev > 0) so = new POutPersist("skymixdbg.ppf");
+
+SphereGorski<float> outgs(hp_nside);
+bool okout = false;
+
+try {
+  if (rdmap) {  // Reading map from FITS file
+    FitsIoServer fios;
+    char ifnm[256];
+    strncpy(ifnm, dc.SParam("READMAP", 0).c_str(), 255);
+    ifnm[255] = '\0';
+    cout << " Reading output HealPix map from FITS file " << (string)ifnm << endl;
+    fios.load(outgs, ifnm, 2);
+    cout << " Output HealPIx Map read - NbPixels= " << outgs.NbPixels() << endl;
+    if (printlev > 0) {
+      MeanSig(outgs.DataBlock(), moy, sig );
+      cout << " MeanSig for outpout map - Mean= " << moy << " Sigma= " << sig << endl;
+    }
+  }
+  else {
+    cout << " Output HealPix Map  created - NbPixels= " << outgs.NbPixels() << endl;
+    outgs.SetPixels(0.);
+  }
+
+  // Decoding detection pass-band filter 
+  sr = getSpectralResponse(dc);
+  PrtTim(" After FilterCreation ");
+
+  FitsIoServer fios; // Our FITS IO Server
+  char * flnm, buff[90];
+  string key;
+
+  SphereGorski<float> ings(hp_nside);  // The input map
+  double K = 1.;
+  // Loop over sky component 
+  int sk;
+  for(sk = 0; sk<nskycomp; sk++) {
+    cout << " Processing sky component No " << sk+1 << endl;
+    sprintf(buff, "%d", sk+1);
+    key = (string)"MAPFITSFILE" + buff;
+    flnm = BuildFITSFileName(dc.SParam(key, 0));
+    cout << " Reading Input FITS map " << (string)flnm << endl;
+    fios.load(ings, flnm, 2);
+    K = dc.DParam(key, 1, 1.);
+    if (debuglev > 4) {  // Writing tne input map to the outppf
+      FIO_SphereGorski<float> fiog(ings);
+      fiog.Write(*so, key);
+      }
+    // getting Emission spectra  
+    if (es) { delete es; es = NULL; }
+    es = getEmissionSpectra(dc, sk);
+    
+    if (printlev > 2) {
+      MeanSig(ings.DataBlock(), moy, sig );
+      cout << " MeanSig for input map - Mean= " << moy << " Sigma= " << sig << endl;
+    }
+    addComponent(*sr, outgs, ings, *es, K);
+    okout = true;
+    if (printlev > 1) {
+      MeanSig(outgs.DataBlock(), moy, sig );
+      cout << " MeanSig for Sum map - Mean= " << moy << " Sigma= " << sig << endl;
+    }
+    sprintf(buff, "End of Proc. Comp. %d ", sk+1);
+    cout << " --------------------------------------- \n" << endl;    
+    PrtTim(buff);
+  }   // End of sky component loop 
+}   // End of try block
+
+catch (PException exc) {
+  msg = exc.Msg();
+  cerr << " !!!! skymixer - Catched exception - Msg= " << exc.Msg() << endl;
+  rc = 50;
+  }   
+
+// Saving the output map in FITS format 
+if (okout) {
+  FitsIoServer fios;
+  fios.save(outgs, arg[2]);
+  cout << "Output Map (SphereGorski<float>) written to FITS file " 
+       << (string)(arg[2]) << endl;
+  PrtTim("End of WriteFITS ");
+// Saving the output map in PPF format 
+  if (narg > 3) {
+   POutPersist s(arg[3]); 
+   FIO_SphereGorski<float> fiog(&outgs) ;
+   fiog.Write(s);
+   cout << "Output Map (SphereGorski<float>) written to POutPersist file "  
+        << (string)(arg[3]) << endl;
+   PrtTim("End of WritePPF ");
+   }
+  }
+  if (so) delete so;  //  Closing the debug ppf file 
+  return(rc);
+}
+
+/* Nouvelle-Fonction */
+int CheckCards(DataCards & dc, string & msg)
+//   Function to check datacards
+{
+rdmap = false;
+mapPath[0] = '\0';
+hp_nside = 32;
+nskycomp = 0;
+debuglev  = 0;
+printlev = 0;
+
+int rc = 0;
+string key, key2;
+
+  //  Cheking datacards
+  if (dc.NbParam("SKYMIX") < 2)   {
+     rc = 71; 
+     msg = "Invalid parameters  - Check @SKYMIX card ";
+     return(rc);
+  }
+  key = "READMAP";
+  if (dc.HasKey(key)) {
+    if (dc.NbParam(key) < 1) {
+     rc = 72; 
+     msg = "Invalid parameters  - Check @READMAP card ";
+     return(rc);
+    }
+   else rdmap = true;
+  }
+
+//  Checking detection filter specification 
+  key = "GAUSSFILTER";
+  key2 = "FILTERFITSFILE";
+  if ( (dc.NbParam(key) < 5) && (dc.NbParam(key2) < 3)) { 
+    msg = "Missing card or parameters : Check @GAUSSFILTER or @FILTERFITSFILE";
+    rc = 73;  return(rc); 
+    }
+
+  // Decoding number of component and pixelisation parameter
+  int mg = 32;
+  int ncomp = 0;
+  ncomp = dc.IParam("SKYMIX", 0, 0);
+  mg = dc.IParam("SKYMIX", 1, 32);
+  if (ncomp < 1)  {
+    msg = "Invalid parameters  - Check datacards @SKYMIX ";
+    rc = 74;
+    return(rc);
+  }
+
+  // Checking detection filter specification
+//  Checking input FITS file specifications 
+  int kc;
+  char buff[256];
+  bool pb = false;
+  string key3;
+  for(kc=0; kc<ncomp; kc++) {
+    sprintf(buff, "MAPFITSFILE%d", kc+1);
+    key = buff;
+    if (dc.NbParam(key) < 1) {   
+      msg = "Missing or invalid card : " + key;
+      pb = true;  break;
+    }
+    sprintf(buff, "SPECTRAFITSFILE%d", kc+1);
+    key = buff;
+    sprintf(buff, "BLACKBODY%d", kc+1);
+    key2 = buff;
+    sprintf(buff, "POWERLAWSPECTRA%d", kc+1);
+    key3 = buff;
+    if ( (dc.NbParam(key) < 3) && (dc.NbParam(key2) < 1) && (dc.NbParam(key3) < 6))  {   
+      msg = "Missing card or invalid parameters : " + key + " " + key2 + " " + key3;
+      pb = true;  break;
+    }
+
+    }
+
+  if (pb)  {
+    rc = 75;
+    return(75);
+  }
+
+
+// Initialiazing parameters
+  rc = 0;
+  msg = "OK";
+  nskycomp = ncomp;
+  hp_nside = mg;  
+
+// Checking for PATH definition card
+  key = "MAPPATH";
+  if (dc.NbParam(key) < 3)  strncpy(mapPath, dc.SParam(key, 0).c_str(), 255);
+  mapPath[255] = '\0';
+  key = "DEBUGLEVEL";
+  debuglev =  dc.IParam(key, 0, 0);
+  key = "PRINTLEVEL";
+  printlev =  dc.IParam(key, 0, 0);
+  return(rc);
+}
+
+static char buff_flnm[1024];   // Mal protege !
+/* Nouvelle-Fonction */
+char* BuildFITSFileName(string const & fname)
+{
+if (mapPath[0] != '\0') sprintf(buff_flnm, "%s/%s", mapPath, fname.c_str());
+else sprintf(buff_flnm, "%s", fname.c_str());
+return(buff_flnm);
+}
+
+/* Nouvelle-Fonction */
+SpectralResponse * getSpectralResponse(DataCards & dc)
+{
+  SpectralResponse * filt = NULL;
+
+  string key = "FILTERFITSFILE";
+  string key2 = "GAUSSFILTER";
+  string ppfname = "filter";
+
+  if (dc.HasKey(key) ) {      // Reading FITS filter file
+    FitsIoServer fios;
+    char ifnm[256];
+    strncpy(ifnm, dc.SParam(key, 1).c_str(), 255);
+    ifnm[255] = '\0';
+    Matrix mtx(2,10);
+    fios.load(mtx, ifnm);
+    double numin = dc.DParam(key, 2, 1.);
+    double numax = dc.DParam(key, 3, 9999.);
+    Vector nu(mtx.NCols());
+    Vector fnu(mtx.NCols());
+    for(int k=0; k<mtx.NCols(); k++) {
+      nu(k) = mtx(0, k);
+      fnu(k) = mtx(1, k);
+    }
+  filt = new SpecRespVec(nu, fnu, numin, numax);
+  ppfname = key;
+  }
+  else if (dc.HasKey(key2) ) {   // creating GaussianFilter 
+    double nu0 = dc.DParam(key2, 0, 10.);
+    double s = dc.DParam(key2, 1, 1.);
+    double a = dc.DParam(key2, 2, 1.);
+    double numin = dc.DParam(key2, 3, 0.1);
+    double numax = dc.DParam(key2, 4, 9999);
+    filt = new GaussianFilter(nu0, s, a, numin, numax);
+    ppfname = key2;
+    }
+  if (filt == NULL) throw ParmError("datacard error ! No detection filter");
+  cout << " Filter decoded - Created " << endl;
+  cout << *filt << endl;
+
+// for debug
+  if (debuglev > 1)  SpectralResponse2Nt(*filt, *so, ppfname);
+  return(filt);
+}
+
+/* Nouvelle-Fonction */
+RadSpectra * getEmissionSpectra(DataCards & dc, int nc)
+{
+  char numb[16];
+  sprintf(numb, "%d", nc+1);
+
+  string key = (string)"SPECTRAFITSFILE" + numb;
+  string key2 = (string)"BLACKBODY" + numb;
+  string key3 = (string)"POWERLAWSPECTRA" + numb;
+  string ppfname = "espectra";
+
+  RadSpectra * rs = NULL;
+  if (dc.HasKey(key) ) {    // Reading emission spectra from file
+    char * ifnm = BuildFITSFileName(dc.SParam(key, 0));
+    cout << " Reading Input FITS spectra file " << (string)ifnm << endl;
+    FitsIoServer fios;
+    Matrix mtx(2,10);
+    fios.load(mtx, ifnm);
+    double numin = dc.DParam(key, 2, 1.);
+    double numax = dc.DParam(key, 3, 9999.);
+    Vector nu(mtx.NCols());
+    Vector tnu(mtx.NCols());
+    for(int k=0; k<mtx.NCols(); k++) {
+      nu(k) = mtx(0, k);
+      tnu(k) = mtx(1, k);
+    }
+  rs = new RadSpectraVec(nu, tnu, numin, numax);
+  ppfname = key;
+  }
+  else if (dc.HasKey(key2) ) { // Creating BlackBody emission spectra
+    rs = new BlackBody(dc.DParam(key2, 0, 2.726));
+    ppfname = key2;
+  }
+  else if (dc.HasKey(key3) ) { // Creating PowerLaw emission spectra
+    double a = dc.DParam(key3, 0, 1.);
+    double nu0 = dc.DParam(key3, 1, 100.);
+    double dnu = dc.DParam(key3, 2, 10.);
+    double b = dc.DParam(key3, 3, 0.);
+    double numin = dc.DParam(key3, 4, 0.1);
+    double numax = dc.DParam(key3, 5, 9999);
+    rs = new PowerLawSpectra(a, b, nu0, dnu, numin, numax);
+    ppfname = key3;
+  }
+  if (rs == NULL) throw ParmError("datacard error ! missing Emission spectra");
+  cout << " Emission spectra decoded - Created (" << ppfname << ")" << endl;
+  cout << *rs << endl;
+// for debug
+  if (debuglev > 2)  RadSpec2Nt(*rs, *so, ppfname);
+  return(rs);
+}
+
+
+
+
+/* Nouvelle-Fonction */
+template <class T> 
+void addComponent(SpectralResponse&  sr, PixelMap<T>& finalMap, 
+                  PixelMap<T>& mapToAdd, RadSpectra& rs, double K)
+{
+  // finalMap = finalMap + coeff* mapToAdd
+  // coeff    =  convolution of sr and rs 
+  // compute the coefficient corresponding to mapToAdd
+  if (finalMap.NbPixels() != mapToAdd.NbPixels())   
+    throw SzMismatchError("addComponent()/Error: Unequal number of Input/Output map pixels");
+  double coeff = rs.filteredIntegratedFlux(sr) * K;
+  if (printlev > 1) 
+    cout << " addComponent - Coeff= " << coeff << " (K= " << K << ")" << endl; 
+  for(int i=0; i<finalMap.NbPixels(); i++)
+    {
+      finalMap(i) += coeff * mapToAdd(i);
+    }
+}
+
+/* Nouvelle-Fonction */
+template <class T>
+void  MeanSig(NDataBlock<T> const & dbl, double& gmoy, double& gsig)
+
+{
+  gmoy=0.;
+  gsig = 0.; 
+  double valok;
+  for(int k=0; k<(int)dbl.Size(); k++) {
+    valok = dbl(k);
+    gmoy += valok;  gsig += valok*valok; 
+  }
+  gmoy /= (double)dbl.Size();
+  gsig = gsig/(double)dbl.Size() - gmoy*gmoy;
+  if (gsig >= 0.) gsig = sqrt(gsig);
+}
+
+/* Nouvelle-Fonction */
+void RadSpec2Nt(RadSpectra & rs, POutPersist & so, string name)
+{
+  char *ntn[2] = {"nu","fnu"};
+  NTuple nt(2,ntn);  // Creation NTuple (AVEC new )
+  float xnt[2];
+  double nu;
+  double numin = rs.minFreq();
+  double numax = rs.maxFreq();
+  int nmax = 500;
+  double dnu = (numax-numin)/nmax;
+  for(int k=0; k<nmax; k++) {
+    nu = numin+k*dnu;
+    xnt[0] = nu;
+    xnt[1] = rs.flux(nu);
+    nt.Fill(xnt);
+  }
+  ObjFileIO<NTuple> oiont(nt);
+  oiont.Write(so, name);
+  return;
+}
+
+/* Nouvelle-Fonction */
+void SpectralResponse2Nt(SpectralResponse& sr, POutPersist & so, string name)
+{
+  char *ntn[2] = {"nu","tnu"};
+  NTuple nt(2,ntn);  // Creation NTuple (AVEC new )
+  float xnt[2];
+  double nu;
+  double numin = sr.minFreq();
+  double numax = sr.maxFreq();
+  int nmax = 500;
+  double dnu = (numax-numin)/nmax;
+  for(int k=0; k<nmax; k++) {
+    nu = numin+k*dnu;
+    xnt[0] = nu;
+    xnt[1] = sr.transmission(nu);
+    nt.Fill(xnt);
+  }
+  ObjFileIO<NTuple> oiont(nt);
+  oiont.Write(so, name);
+  return;
+}
+
Index: /tags/V_Fev00/SophyaLib/SkyT/specresp.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/specresp.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/specresp.cc	(revision 752)
@@ -0,0 +1,174 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: specresp.cc,v 1.3 1999-11-29 14:16:08 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include <typeinfo>
+#include <math.h>
+#include "specresp.h"
+#include "integ.h"
+#include "tvector.h"
+
+//----------------
+// Constructor --
+//----------------
+SpectralResponse::SpectralResponse(double numin, double numax)
+{
+  _numin = numin;
+  _numax = numax;
+}
+
+
+//--------------
+// Destructor --
+//--------------
+SpectralResponse::~SpectralResponse()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+
+double 
+SpectralResponse::minFreq()  const 
+{
+  return _numin;
+}
+
+double 
+SpectralResponse::maxFreq()  const
+{
+  return _numax;
+}
+
+double 
+SpectralResponse::meanFreq()  const
+{
+  return (_numax+_numin)/2.;
+}
+
+ 
+// To change min-max frequency
+void
+SpectralResponse::setMinMaxFreq(double numin, double numax)
+{
+  _numin = numin;
+  _numax = numax;
+}
+ 
+
+// peakFreq returns the value of the frequency for the
+// peak of the spectrum. 
+double 
+SpectralResponse::peakFreq()  const
+{
+  double maxAnswer = -1.e99;
+  double maxNu = -10;
+  double nu;
+  for (int i=1; i<1000;i++)
+    {
+      nu=(_numax-_numin)*i/1000.+_numin;
+      double lookForMax =transmission(nu);
+      if(maxAnswer <= lookForMax) {
+	maxAnswer= lookForMax;
+	maxNu    = nu;
+      }
+    }
+  return maxNu;    
+}
+
+
+double 
+SpectralResponse::peakTransmission()  const
+{
+  double nuPeak = this->peakFreq();
+  return transmission(nuPeak);
+}
+
+static SpectralResponse* _mySpecResp = NULL;
+
+static double SpectralResponse_transmission(double nu)
+{
+   return(_mySpecResp->transmission(nu));   
+}
+
+
+double 
+SpectralResponse::IntegratedSpect()  const
+{
+  double value = this->IntegratedSpect(_numin, _numax);
+  return value;
+}
+
+double 
+SpectralResponse::IntegratedSpect(double numin, double numax) const 
+{
+  if(numin < this->minFreq()) numin = this->minFreq();
+  if(numax > this->maxFreq()) numax = this->maxFreq();
+
+  
+  _mySpecResp = const_cast<SpectralResponse *>(this);
+  TrpzInteg I(SpectralResponse_transmission , numin, numax);  
+  double val = (double)I;
+  _mySpecResp= NULL;
+  return(val);
+}
+
+
+static SpectralResponse* _myLogSpecResp = NULL;
+
+static double SpectralResponse_logTransmission(double tau)
+{
+  double value =  _myLogSpecResp->transmission(pow(10,tau))*pow(10,tau);
+  return(value);   
+}
+
+double 
+SpectralResponse::logIntegratedSpect(double numin, double numax) const 
+{
+  if(numin <= this->minFreq()) numin = this->minFreq();
+  if(numax >= this->maxFreq()) numax = this->maxFreq();
+  if(numin == 0) numin = 1.e-99;
+  double f1Log = log10(numin);
+  double f2Log = log10(numax);
+  if(f1Log < -1.e99) f1Log = -1.e99;
+  if(f2Log > 1.e99)  f2Log = 1.e99;
+  _myLogSpecResp = const_cast<SpectralResponse *>(this); 
+  TrpzInteg I(SpectralResponse_logTransmission ,f1Log,f2Log); 
+  double val = (double)I;
+  _myLogSpecResp= NULL;
+  return(val*log(10.));
+}
+
+double 
+SpectralResponse::logIntegratedSpect()  const
+{
+  double value = this->logIntegratedSpect(_numin, _numax);
+  return value;
+}
+
+
+void
+SpectralResponse::Print(ostream& os) const 
+{
+
+  //   os << "SpectralResponse::Print (" << typeid(*this).name() 
+  //<< ") - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "SpectralResponse::Print - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Transmission= " << transmission(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Transmission= " << transmission(peakFreq()) << endl;
+
+}
Index: /tags/V_Fev00/SophyaLib/SkyT/specresp.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/specresp.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/specresp.h	(revision 752)
@@ -0,0 +1,82 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: specresp.h,v 1.3 1999-11-29 14:16:08 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+#ifndef SPECRESP_H_SEEN
+#define SPECRESP_H_SEEN
+
+#include "machdefs.h"
+#include "anydataobj.h"
+#include <iostream.h>
+//------------------------------------
+// Collaborating Class Declarations --
+//------------------------------------
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+// ***IMPORTANT*** All frequencies are expressed in GHz  (10^9 Hz)
+namespace SOPHYA {
+  
+  class SpectralResponse : public AnyDataObj
+  {
+    
+  public:
+    //Constructor
+    SpectralResponse(double numin=0., double numax=1.);
+    
+    // destructor
+    virtual ~SpectralResponse();
+    
+    //
+    //  Member Functions
+    //
+    
+    //  The transmission() function is virtual: 
+    virtual double transmission(double nu) const =0 ; 
+    
+    inline double operator() (double nu) const { return(transmission(nu)); }
+    
+    virtual void      Print(ostream& os)  const;
+    
+    virtual double minFreq() const;
+    virtual double maxFreq() const;
+    virtual double meanFreq() const;
+    virtual double peakFreq() const;
+    virtual double peakTransmission() const;
+
+    // For changing the min/max frequency
+    virtual void   setMinMaxFreq(double numin, double numax);
+
+    virtual double IntegratedSpect(double numin, double numax) const ;
+    virtual double logIntegratedSpect(double numin, double numax) const ;
+    virtual double IntegratedSpect() const ;
+    virtual double logIntegratedSpect() const ;
+    
+  protected:
+    double _numin;
+    double _numax;
+  };
+  
+  
+  // definition of the << operator
+  inline ostream& operator << (ostream& s,  SpectralResponse const & sr)
+    {  sr.Print(s);  return(s);  }
+  
+  
+  
+};
+
+#endif
+
+
+
+
Index: /tags/V_Fev00/SophyaLib/SkyT/specrespvector.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/specrespvector.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/specrespvector.cc	(revision 752)
@@ -0,0 +1,171 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: specrespvector.cc,v 1.5 1999-11-29 16:59:12 ansari Exp $
+//
+// Description:
+//      Aim of the class: To give the energy density
+//                        The unity used here is W/m^2/Hz/sr
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+// #include <typeinfo>
+
+#include "specrespvector.h"
+#include "pexceptions.h"
+//----------------
+// Constructor --
+//----------------
+SpecRespVec::SpecRespVec()
+        : SpectralResponse()
+{
+}
+
+SpecRespVec::SpecRespVec(Vector const & nu, Vector const & fdenu, double numin, double numax)
+        : SpectralResponse(numin, numax)
+{
+  if(nu.NElts() != fdenu.NElts())  
+    throw SzMismatchError("SpecRespVec::SpecRespVec() - Non equal vector sizes");
+  _vecOfNu = nu;
+  _vecOfFDeNu = fdenu;
+  _size = nu.NElts();
+  if(_vecOfNu.NElts() != _vecOfFDeNu.NElts()) cout << "vectors are not compatible" << exit;
+}
+
+SpecRespVec::SpecRespVec(Vector const & nu, Vector const & fdenu)
+        : SpectralResponse()
+{
+  if(nu.NElts() != fdenu.NElts())  
+    throw SzMismatchError("SpecRespVec::SpecRespVec() - Non equal vector sizes");
+  _vecOfNu = nu;
+  _vecOfFDeNu = fdenu;
+  _numin = nu(0);
+  _numax = nu(nu.NElts()-1);
+  _size = nu.NElts();
+  if(_vecOfNu.NElts() != _vecOfFDeNu.NElts()) cout << "vectors are not compatible" << exit;
+}
+
+
+//--------------
+// Destructor --
+//--------------
+SpecRespVec::~SpecRespVec()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+
+
+ 
+double 
+SpecRespVec::transmission(double nu)  const 
+{
+  if ( (nu < _numin) || (nu > _numax) ) return(0.);
+  double value = 0.;
+  int sizeVecOfNu = _vecOfNu.NElts();
+  if(nu <=  _vecOfNu(0)) return _vecOfFDeNu(0);
+  if(nu >=  _vecOfNu(sizeVecOfNu-1)) return _vecOfFDeNu(sizeVecOfNu-1);
+
+  for (int i=1; i<sizeVecOfNu; i++)
+    {
+      if(nu < _vecOfNu(i))
+	{
+	  double up = _vecOfFDeNu(i) ;
+	  double down = _vecOfFDeNu(i-1);
+	  double xmin = _vecOfNu(i-1);
+	  double xmax = _vecOfNu(i);
+	  double a = ((up-down)/(xmax-xmin));
+	  value = a*nu+(up-a*xmax);
+	  return value;
+	}
+    }
+  return value;
+}
+
+
+
+void
+SpecRespVec::Print(ostream& os) const 
+{
+
+  //   os << "SpecRespVec::Print (" << typeid(*this).name() 
+  //<< ") - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "SpecRespVec ::Print - Fmin,Fmax= " << minFreq() << "," << maxFreq() << endl;
+  os << "MeanFreq= " << meanFreq() << "  Transmission= " << transmission(meanFreq()) << endl;
+  os << "PeakFreq= " << peakFreq() << "  Transmission= " << transmission(peakFreq()) << endl;
+
+}
+
+
+void
+ObjFileIO<SpecRespVec>::WriteSelf(POutPersist& s) const
+{
+  if(dobj == NULL)
+    {
+      cout << " ObjFileIO<SpecRespVec>::WriteSelf:: dobj= null " << endl;
+      return;
+    }
+
+  int_4 version, nothing;
+  version = 1;
+  nothing = 0;   // Reserved for future use 
+  s.PutI4(version);
+  s.PutI4(nothing);
+
+  s.PutR8(dobj->minFreq());
+  s.PutR8(dobj->maxFreq());
+
+  // TVector<T> has Persistence Manager
+  s << dobj->getNuVec();
+  {
+  Vector& xv2 = dobj->getTNuVec();
+  cout << xv2 ;
+  FIO_TVector<double> vio2(&xv2);
+  vio2.Write(s);
+  }
+}
+
+void 
+ObjFileIO<SpecRespVec>::ReadSelf(PInPersist& s) 
+{
+  int_4 version, nothing;
+  version = 1;
+  nothing = 0;   // Reserved for future use 
+  s.GetI4(version);
+  s.GetI4(nothing);
+
+  if(dobj == NULL)
+    {
+    dobj= new SpecRespVec();
+    ownobj= true;
+    }
+  r_8 minf, maxf;
+  s.GetR8(minf);
+  s.GetR8(maxf);
+  dobj->setMinMaxFreq(minf, maxf);
+  // TVector<T> has Persistence Manager 
+  FIO_TVector<double> vio(&(dobj->getNuVec()));
+  vio.Read(s);
+  FIO_TVector<double> vio2(&(dobj->getTNuVec()));
+  vio2.Read(s);
+}
+
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<SpecRespVec>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<SpecRespVec>;
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/specrespvector.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/specrespvector.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/specrespvector.h	(revision 752)
@@ -0,0 +1,76 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: specrespvector.h,v 1.4 1999-11-29 16:59:12 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+#ifndef SPECRESPVEC_H_SEEN
+#define SPECRESPVEC_H_SEEN
+
+#include "machdefs.h"
+#include <iostream.h>
+
+#include "specresp.h"
+#include "tvector.h"
+#include "objfio.h"
+
+//------------------------------------
+// Collaborating Class Declarations --
+//------------------------------------
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+// ***IMPORTANT*** All frequencies are expressed in GHz  (10^9 Hz)
+
+namespace SOPHYA {
+  
+  class SpecRespVec :  public SpectralResponse
+  {
+
+public:
+  //Constructor
+  SpecRespVec();
+  SpecRespVec(Vector const & nu, Vector const & fdenu, double numin, double numax);
+  SpecRespVec(Vector const & nu, Vector const & fdenu);
+
+  // destructor
+  virtual ~SpecRespVec();
+
+  //
+  //  Member Functions
+  //
+
+  //  The transmission() function is virtual: 
+  virtual double transmission(double nu) const; 
+
+  // Acces to Nu and T(nu) vectors 
+  inline Vector&  getNuVec()  { return _vecOfNu; } ;
+  inline Vector& getTNuVec()  { return _vecOfFDeNu; }
+  inline double getNuVec(int i) const { return _vecOfNu(i); }
+  inline double getTNuVec(int i) const { return _vecOfFDeNu(i); }
+  inline int NbElts() const { return _size;}
+  
+  virtual void      Print(ostream& os)  const;
+
+protected:
+  Vector _vecOfNu;
+  Vector _vecOfFDeNu;
+  int _size;
+};
+
+  // ObjFileIO<SpecRespVec> pour les PPersist 
+  inline POutPersist& operator << (POutPersist& os, SpecRespVec & obj)
+    { ObjFileIO<SpecRespVec> fio(&obj); fio.Write(os); return(os);}
+  
+  inline PInPersist& operator >> (PInPersist& os, SpecRespVec & obj)
+    { ObjFileIO<SpecRespVec> fio(&obj); fio.Read(os); return(os);}
+
+};  // End of namespace 
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/squarefilt.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/squarefilt.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/squarefilt.cc	(revision 752)
@@ -0,0 +1,86 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: squarefilt.cc,v 1.4 1999-11-29 16:59:12 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+
+#include "squarefilt.h"
+
+//----------------
+// Constructor --
+//----------------
+SquareFilter::SquareFilter()
+  : SpectralResponse()
+{
+}
+
+SquareFilter::SquareFilter(double numin, double numax)
+  : SpectralResponse(numin, numax)
+{
+  _nuPeak = (numin+numax)/2.;
+  _peakTransmission = transmission(_nuPeak);
+}
+
+
+//--------------
+// Destructor --
+//--------------
+SquareFilter::~SquareFilter()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+
+double 
+SquareFilter::transmission(double nu) const
+{
+  if(nu < -1.e99) nu = -1.e99;
+  if(nu > 1.e99) nu = 1.e99;
+  
+  if(nu>=_numin && nu<=_numax) return 1.;
+  return 0.;
+}
+
+double 
+SquareFilter::peakFreq() const 
+{
+return _nuPeak;
+}
+
+double 
+SquareFilter::peakTransmission() const 
+{
+  return _peakTransmission;
+}
+
+/*
+void 
+SquareFilter::WriteSelf(POutPersist& s) 
+{
+  s.PutR8(this->minFreq());
+  s.PutR8(this->maxFreq());
+}
+
+void 
+SquareFilter::ReadSelf(PInPersist& s) 
+{
+  double minFreq, maxFreq;
+  s.GetR8(_numin);
+  s.GetR8(_numax);
+  cout << "minFreq - maxFreq " <<  _numin << "-" << _numax  << endl;
+}
+*/
Index: /tags/V_Fev00/SophyaLib/SkyT/squarefilt.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/squarefilt.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/squarefilt.h	(revision 752)
@@ -0,0 +1,56 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: squarefilt.h,v 1.4 1999-11-29 16:59:13 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+#ifndef SQUAREFIL_H_SEEN
+#define SQUAREFIL_H_SEEN
+
+//----------------------
+// Base Class Headers --
+//----------------------
+#include "specresp.h"
+
+//------------------------------------
+// Collaborating Class Declarations --
+//------------------------------------
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+class SquareFilter:public SpectralResponse
+{
+
+public:
+  //Constructors
+  SquareFilter (); 
+  SquareFilter (double numin, double numax); 
+  
+
+  // destructor
+  virtual ~SquareFilter();
+
+  //
+  //  Function members
+  //
+
+  virtual double transmission(double) const;
+  virtual double peakFreq() const;
+  virtual double peakTransmission() const;
+  
+
+protected:
+  double _peakTransmission;
+  double _nuPeak;
+};
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SkyT/tgrsr.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/tgrsr.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/tgrsr.cc	(revision 752)
@@ -0,0 +1,151 @@
+#include "machdefs.h"
+#include <iostream.h>
+#include <typeinfo>
+#include <math.h>
+
+#include "tvector.h"
+#include "cimage.h"
+#include "sambainit.h"
+
+#include "radspecvector.h"
+#include "specrespvector.h"
+#include "nupower.h"
+#include "gaussfilt.h"
+
+#include "fitsioserver.h"
+
+#include "timing.h"
+
+// Test program to generate different type of RadSpectra
+// and SpectralResponse in the form of RadSpectraVec and SpecRespVec
+// in FITS format
+
+// ------------- Main program --------------
+int main(int narg, char* arg[]) 
+{
+  PeidaInit();
+  InitTim();   // Initializing the CPU timer 
+
+  if ((narg < 5) || ((narg>1) && (strcmp(arg[1],"-h") == 0)) )  {
+    cout << " tgrsr : Generation of RadSpectraVec and SpecRespVec in FITS  " << endl;
+    cout << " Usage: tgrsr 0/1 Params NPoints FitsFileName [ImageR4FITSName] [ppfname] " << endl;
+    cout << " 0 -> GaussianFilter  T = A exp(((nu-nu0)/dnu)^2" << endl;
+    cout << " Params : A,Nu0,DNu,MinFreq,MaxFreq " << endl;
+    cout << " 1 -> PowerLawSpectra f = a ((nu-nu0)/dnu)^b " << endl;
+    cout << " Params : A,Nu0,dnu,b,MinFreq,MaxFreq " << endl;
+    exit(0);
+    }
+
+  int typ = 0; 
+  typ = atoi(arg[1]);
+  int k, npt = 100;
+  npt = atoi(arg[3]);
+  if (npt < 5) npt = 5;
+  cout << " ---- tgrsr/Info: Type= " << typ << " NPoints= " << npt << endl;
+  Matrix mtx(2, npt);
+  ImageR4 img(npt, 2);
+
+  char buff[256];
+  if (typ == 0) {  // Generation de SpecRespVec from GaussianFilter
+    double a,nu0,dnu,fmin,fmax;
+    a = 1.0;
+    nu0 = 143.;
+    dnu = 10.;
+    fmin = 10.;
+    fmax = 1000.;
+    sscanf(arg[2],"%lg,%lg,%lg,%lg,%lg",&a,&nu0,&dnu,&fmin,&fmax);
+    cout << " GaussianFilter  T = A exp(((nu-nu0)/dnu)^2" << endl;
+    sprintf(buff,"A=%g Nu0=%g DNu=%g FMin=%g FMax=%g",
+            a,nu0,dnu,fmin,fmax);
+    cout << "Decoded params: " << (string)buff << endl;
+    GaussianFilter sr(nu0, dnu, a, fmin, fmax);
+    cout << sr << endl;
+    cout << " Creating SpecRespVec() ... " << endl;
+    Vector v1(10);
+    Vector v2(10);
+    SpecRespVec srv(v1, v2, fmin, fmax);
+    Vector & nu = srv.getNuVec();
+    Vector & tnu = srv.getTNuVec();
+    nu.ReSize(npt);
+    tnu.ReSize(npt);
+    double freq;
+    double dfreq = (fmax-fmin)/(npt-3);
+    for(k=0; k<npt; k++) {
+      freq = fmin+(k-1)*dfreq;
+      nu(k) = freq;
+      tnu(k) = sr.transmission(freq);
+      //      if ((k>10) && (k<25))  cout << " DBG - K = " << k <<
+      //        " Nu= " << nu(k) << " Tnu= " << tnu(k) << endl; 
+      mtx(0,k) = nu(k);
+      mtx(1,k) = tnu(k);
+      img(k,0) = nu(k);
+      img(k,1) = tnu(k);
+    }
+    if ((typ == 0) && (narg > 6)) { // Writing to ppf  file
+      cout << "writing SpecRespVec(" << npt << ") to PPF file: " 
+           << (string)(arg[6]) << endl;
+      cout << sr ; 
+      cout << srv ; 
+      {
+        POutPersist pos(arg[6]);
+        pos << srv;
+      }
+      PrtTim("End of ImageR4->PPF ");
+    }
+
+  }
+  else { // Generation de RadSpectraVec from PowerLawSpectra
+    double a,nu0,dnu,b,fmin,fmax;
+    a = 1.0;
+    nu0 = 143.;
+    b = 0.;
+    dnu = 10.;
+    fmin = 10.;
+    fmax = 1000.;
+    sscanf(arg[2],"%lg,%lg,%lg,%lg,%lg,%lg",&a,&nu0,&dnu,&b,&fmin,&fmax);
+    cout << " PowerLawSpectra f = a ((nu-nu0)/dnu)^b " << endl;
+    sprintf(buff,"A=%g Nu0=%g DNu=%g B=%g FMin=%g FMax=%g",
+            a,nu0,dnu,b,fmin,fmax);
+    cout << "Decoded params: " << (string)buff << endl;
+    PowerLawSpectra rs(a,b, nu0, dnu, fmin, fmax);
+    cout << rs << endl;
+    cout << " Creating RadSpectraVec() ... " << endl;
+    Vector v1(10);
+    Vector v2(10);
+    RadSpectraVec rsv(v1, v2, fmin, fmax);
+    Vector & nu = rsv.getNuVec();
+    Vector & fnu = rsv.getFNuVec();
+    nu.ReSize(npt);
+    fnu.ReSize(npt);
+    double freq;
+    double dfreq = (fmax-fmin)/(npt-3);
+    for(k=0; k<npt; k++) {
+      freq = fmin+(k-1)*dfreq;
+      nu(k) = freq;
+      fnu(k) = rs.flux(freq);
+      //      if ((k>10) && (k<25))  cout << " DBG2 - K = " << k <<
+      //        " Nu= " << nu(k) << " Fnu= " << fnu(k) << endl; 
+      mtx(0,k) = nu(k);
+      mtx(1,k) = fnu(k);
+      img(k,0) = nu(k);
+      img(k,1) = fnu(k);
+    }
+  }
+
+  PrtTim("End of filling ");
+
+  FitsIoServer fios;
+  cout << "\n Writing Matrix NRows= " << mtx.NRows() << "  NCols= " 
+       << mtx.NCols() << " to FITS file: " << (string)(arg[4]) << endl;
+  fios.save(mtx, arg[4]);
+  PrtTim("End of Matrix->FITS ");
+
+  if (narg > 5) { // Writing ImageR4 fo FITS file
+    cout << "wrting ImageR4(" << npt << ", 2) to FITS file: " 
+         << (string)(arg[5]) << endl;
+    fios.save(img, arg[5]);
+    PrtTim("End of ImageR4->FITS ");
+  }
+  cout <<  " ============ End of tgrsr program ======== " << endl;
+  return 0;
+}
Index: /tags/V_Fev00/SophyaLib/SkyT/tgsky.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/tgsky.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/tgsky.cc	(revision 752)
@@ -0,0 +1,116 @@
+#include "machdefs.h"
+#include <iostream.h>
+#include <math.h>
+
+#include "sambainit.h"
+#include "spheregorski.h"
+#include "fitsioserver.h"
+#include "nbrandom.h"
+#include "bruit.h"
+#include "timing.h"
+
+// Test program to generate different type of random skies
+template <class T>
+void  MeanSig(PixelMap<T> const & map, double& gmoy, double& gsig);
+
+// ------------- Main program --------------
+int main(int narg, char* arg[]) 
+{
+  double teta,phi;
+  double gmoy=0., gsig=0.;
+
+  PeidaInit();
+  InitTim();   // Initializing the CPU timer 
+  if ((narg < 5) || ((narg>1) && (strcmp(arg[1],"-h") == 0)) )  {
+    cout << " tgsky : Generation of random skies  " << endl;
+    cout << " Usage: tgsky NSide TypSky Params FitsFileName [PPFName] " << endl;
+    cout << "   - TypSky = 0  Params= m,sig  , Gaussian(m,sig) " << endl;
+    cout << "   - TypSky = 1  Params= m,sig  , OOFNoise(sig) + m" << endl;
+    cout << "   - TypSky = 2  Params= K,a,b,m  K*cos(a*teta)*sin(b*phi)+m" << endl;   
+    exit(0);
+    }
+
+  int  ns = atoi(arg[1]);
+  SphereGorski<float> sph(ns);
+
+  cout << "Filling SphereGorski<float> NSide= " << ns 
+       << "  NPixels= " << sph.NbPixels() << endl;
+
+  int typ = atoi(arg[2]);
+  double m,s,a,b,K;
+  m = 0.;
+  s = 1.;
+  a = b = 1.;
+  K = 1.;
+  if ((typ < 0) || (typ > 2)) typ = 0;
+  if (typ < 2)  { 
+    sscanf(arg[3],"%lg,%lg",&m,&s);
+    cout << "  TypSky= " << typ << " m= " << m << " sig= " << s << endl;
+    if (typ == 1) cout << "  ---> OOFNoise() " << endl;
+    else cout << "  ---> NoiseGenerator() " << endl;
+  }
+  else { 
+    sscanf(arg[3],"%lg,%lg,%lg,%lg",&K,&a,&b,&m);
+    cout << "  TypSky= " << typ << " K= " << m << " a= " << a << " b=" 
+         << b << " m= " << m << endl;
+    cout << "    ---> K * cos(a*teta) * sin(b*teta) + m" << endl;
+    }
+
+  PrtTim("End of Init ");
+
+  if (typ == 2) {
+    for (int j=0;j<sph.NbPixels();j++)   {
+      sph.PixThetaPhi(j,teta,phi);
+      sph(j)= K * cos(a*teta)*sin(b*phi) + m;
+    }
+  }
+  else {
+    NoiseGenerator * ng;
+    if (typ == 0) ng = new NoiseGenerator(s);
+    else ng = new OOFNoise(s);    
+    for (int j=0;j<sph.NbPixels();j++)   sph(j) = ng->Noise()+m;
+    delete ng;
+  }
+  PrtTim("End of Fill ");
+
+  // Computing mean and sigma on the sphere 
+  MeanSig(sph, gmoy, gsig);
+  cout << "SphereGorski<float> Mean= " << gmoy << "  Sigma = " << gsig << endl;
+  PrtTim("End of Mean-Sig ");
+
+  if (narg > 5) {
+   POutPersist s(arg[5]); 
+   FIO_SphereGorski<float> fiog(&sph) ;
+   fiog.Write(s);
+   cout << "SphereGorski<float> written to POutPersist file"  
+        << (string)(arg[5]) << endl;
+   PrtTim("End of WritePPF ");
+   }
+
+
+   
+  FitsIoServer fios;
+  fios.save(sph, arg[4]);
+  cout << "SphereGorski<float> written to FITS file " << (string)(arg[4]) << endl;
+  PrtTim("End of WriteFITS ");
+
+  cout <<  " ============ End of tgsky program ======== " << endl;
+  return 0;
+}
+
+/* Nouvelle-Methode */
+template <class T>
+void  MeanSig(PixelMap<T> const & map, double& gmoy, double& gsig)
+
+{
+  gmoy=0.;
+  gsig = 0.; 
+  double valok;
+  for(int k=0; k<map.NbPixels(); k++) {
+    valok = map(k);
+    gmoy += valok;  gsig += valok*valok; 
+  }
+  gmoy /= (double)map.NbPixels();
+  gsig = gsig/(double)map.NbPixels() - gmoy*gmoy;
+  if (gsig >= 0.) gsig = sqrt(gsig);
+}
Index: /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.cc	(revision 752)
@@ -0,0 +1,93 @@
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: trianglefilt.cc,v 1.4 1999-11-29 16:59:13 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+
+//---------------
+// C++ Headers --
+//---------------
+#include "machdefs.h"
+#include <iostream.h>
+
+#include "trianglefilt.h"
+
+//----------------
+// Constructor --
+//----------------
+
+TriangleFilter::TriangleFilter()
+   : SpectralResponse()
+{
+}
+TriangleFilter::TriangleFilter(double numin, double numax,double nupeak, double valueatpeak)
+   : SpectralResponse(numin, numax)
+{
+  _nuPeak = nupeak ;
+  _peakTransmission = valueatpeak;
+}
+
+//--------------
+// Destructor --
+//--------------
+TriangleFilter::~TriangleFilter()
+{
+}
+
+//              ---------------------------
+//              --  Function Definitions --
+//              ---------------------------
+
+double 
+TriangleFilter::transmission(double nu) const
+{
+  if(nu < -1.e99) nu = -1.e99;
+  if(nu > 1.e99) nu = 1.e99;
+  
+  if(nu>_numin && nu<_nuPeak) return (_peakTransmission*nu/_nuPeak);
+  if(nu>=_nuPeak && nu<_numax) return (_peakTransmission*nu/(_nuPeak-_numax)+_peakTransmission-_peakTransmission*_nuPeak/(_nuPeak-_numax));
+  return 0.;
+}
+
+double 
+TriangleFilter::peakFreq() const 
+{
+return _nuPeak;
+}
+
+double 
+TriangleFilter::peakTransmission() const 
+{
+return _peakTransmission;
+}
+
+/*
+void
+TriangleFilter::WriteSelf(POutPersist& s) 
+{
+  s.PutR8(this->peakFreq());
+  s.PutR8(this->peakTransmission());
+  s.PutR8(this->minFreq());
+  s.PutR8(this->maxFreq());
+  
+}
+
+void
+TriangleFilter::ReadSelf(PInPersist& s)   
+{
+  //  double peakFreq, peakTransmission, minFreq,  maxFreq;
+  s.GetR8(_nuPeak);
+  s.GetR8(_peakTransmission);
+  s.GetR8(_numin);
+  s.GetR8(_numax);
+  cout << "peakFreq - peakTransmission - minFreq - maxFreq " << endl; 
+  cout <<  _nuPeak << "-" <<  _peakTransmission<< "-" <<  _numin << "-" <<  _numax << endl;
+
+}
+
+*/
Index: /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SkyT/trianglefilt.h	(revision 752)
@@ -0,0 +1,53 @@
+// This may look like C code, but it is really -*- C++ -*-
+//--------------------------------------------------------------------------
+// File and Version Information:
+//      $Id: trianglefilt.h,v 1.4 1999-11-29 16:59:13 ansari Exp $
+//
+// Description:
+//
+// History (add to end):
+//      Sophie   Oct, 1999  - creation
+//
+//------------------------------------------------------------------------
+#ifndef TRIANGLEFIL_H_SEEN
+#define TRIANGLEFIL_H_SEEN
+
+//----------------------
+// Base Class Headers --
+//----------------------
+#include "specresp.h"
+
+//------------------------------------
+// Collaborating Class Declarations --
+//------------------------------------
+
+//              ---------------------
+//              -- Class Interface --
+//              ---------------------
+
+class TriangleFilter:public SpectralResponse
+{
+public:
+  //Constructors
+  TriangleFilter (double numin, double numax,double nupeak, double valueatpeak); 
+  TriangleFilter ();
+
+  // destructor
+  ~TriangleFilter();
+
+  //
+  //  Function members
+  //
+
+  virtual double transmission(double) const;  
+  virtual double peakFreq() const; 
+  virtual double peakTransmission() const;
+
+protected:
+  double _peakTransmission;
+  double _nuPeak;
+};
+
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SysTools/ctimer.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/ctimer.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/ctimer.cc	(revision 752)
@@ -0,0 +1,91 @@
+//
+// $Id: ctimer.cc,v 1.2 1999-04-21 13:11:59 ansari Exp $
+//
+
+#include "machdefs.h"
+#include "ctimer.h"
+
+//++
+// Class	Timer
+// Lib  	Outils++
+// include	ctimer.h
+//
+//	Chronométrage de programmes. Le constructeur mémorise l'heure et
+//      le temps CPU, ainsi qu'un message éventuel.
+//
+//	Split affiche le temps partiel.
+//
+//	Le destructeur affiche le temps total (CPU, et écoulé).
+//    
+//      Des macros permettent une utilisation simplifiée :
+//      * TIMEF   crée un objet de type Timer, avec le nom de la function 
+//	courante comme message. Le temps écoulé sera affiché à la sortie 
+//	de la function.
+//      * SPLITTIME affiche le temps partiel du compteur crée par TIMEF
+//      * TIMEN(nom) permet de donner un autre nom que le nom de la fonction.
+//--
+
+
+//++
+// Titre	Constructeurs
+//--
+
+//++
+// Timer::Timer(const char* name)
+//	Crée un objet qui mémorise l'heure et le temps CPU du process courant.
+//	Le destructeur affiche les temps écoulé et CPU utilisé.
+//--
+
+Timer::Timer(const char* name)
+: timerName(name)
+{
+  cpu0 = cpuSplit = clock();
+  elapse0 = elapseSplit = time(0);
+}
+
+//++
+// Titre	Méthodes
+//--
+
+//++
+// Timer::Split(const char* comm)
+//	Affiche le temps partiel.
+//--
+
+
+void Timer::Split(const char* comm)
+{
+  time_t elapse = time(0);
+  clock_t cpu   = clock();
+
+  float cpuSecT = ((float)cpu - (float)cpu0) / (float)(CLOCKS_PER_SEC);
+  float cpuSecP = ((float)cpu - (float)cpuSplit) / (float)(CLOCKS_PER_SEC);
+  
+  int etm  = elapse - elapseSplit;
+  int etmt = elapse - elapse0;
+
+  cout << "***Timing " << (comm ? comm : timerName) << endl;
+
+// Pour des formats comme ca, la syntaxe printf est plus agreable.
+// Pour ne pas melanger stdio/iostream (pb de desynchronisation sur
+// autres C++ que GNU), on fait un cout << chaine.
+
+  char out[200];
+  sprintf(out,"CPU     Time: Total= %g (Partial= %g) Sec.",
+	  cpuSecT, cpuSecP);
+  cout << out << endl;
+
+  sprintf(out,"Elapsed Time: Total= %02d:%02d:%02d (Partial=%02d:%02d:%02d)",
+	  etmt/3600, (etmt%3600)/60, etmt%60, 
+	  etm/3600,  (etm%3600)/60,  etm%60);
+
+  cout << out << endl;
+
+  elapseSplit = elapse;
+  cpuSplit    = cpu;
+}
+
+Timer::~Timer()
+{
+  Split();
+}
Index: /tags/V_Fev00/SophyaLib/SysTools/ctimer.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/ctimer.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/ctimer.h	(revision 752)
@@ -0,0 +1,49 @@
+// This may look like C code, but it is really -*- C++ -*-
+//
+// $Id: ctimer.h,v 1.2 1999-04-21 13:12:00 ansari Exp $
+//
+
+
+#ifndef CTIMER_SEEN
+#define CTIMER_SEEN
+
+#include <sys/types.h>
+#include <time.h>
+#include <iostream.h>
+#include <stdio.h>
+#include "machdefs.h"
+
+// <summary> Permet de chronometrer des fonctions. </summary>
+// La macro TIMEF cree un objet de class Timer qui memorise
+// l'heure de sa creation, et le temps CPU.
+
+// A la fin du bloc ou de la procedure, l'objet est detruit,
+// et son destructeur affiche le temps ecoule.
+
+// La macro SPLITTIME lui permet d'afficher des temps partiels.
+class Timer  {
+public:
+  // L'objet memorise le temps CPU et l'heure, et le nom donne
+  Timer(const char* name=0);
+
+  // Le destructeur appelle split sans parametre.
+  virtual ~Timer();
+
+  // Affiche le temps ecoule total/partiel, avec le nom eventuel.
+  // Si pas de parametre affiche le nom donne a la creation.
+  void Split(const char* comm=0);
+
+  // Sert a eviter que GNU ne pretende qu'on utilise pas l'objet...
+  void Nop() {}
+
+private:
+  clock_t cpu0, cpuSplit;
+  time_t  elapse0, elapseSplit;
+  const char* timerName;
+};
+
+#define TIMEN(x)  Timer timer(x); timer.Nop();
+#define TIMEF     Timer timer(__PRETTY_FUNCTION__); timer.Nop();
+#define SPLITTIME timer.Split();
+
+#endif // CTIMER_SEEN
Index: /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.cc	(revision 752)
@@ -0,0 +1,211 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Gestionnaire de lien dynamique   -   R. Ansari 12/98
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream.h>
+
+#include "pdlmgr.h"
+
+// Extension de noms de fichiers Shared libs
+static const char* sofext = ".so";
+static const char* sofext_HPUX = ".sl";
+
+// Variables et methodes static
+int PDynLinkMgr::numSO = 0;
+string*  PDynLinkMgr::tmpDir = NULL;
+
+/* --Methode-Static-- */
+void PDynLinkMgr::SetTmpDir(string const & path)
+{
+if ( (path.length() > 0) && (path[path.length()] != '/')  ) GetTmpDir() = path + '/';
+else GetTmpDir() = path;
+#if defined(OSF1) || defined(Linux) || defined(SunOS)
+  string cmd = "LD_LIBRARY_PATH=";
+  char* varenv=NULL;
+  varenv=getenv("LD_LIBRARY_PATH");
+#elif defined(IRIX64)
+  string cmd = "LD_LIBRARYN32_PATH=";
+  char* varenv=NULL;
+  varenv=getenv("LD_LIBRARYN32_PATH");
+
+  if (varenv == NULL) { 
+    cmd += '.';  
+    if (path.length() > 0)  cmd += ':' + path; 
+    }
+  else { 
+    if (varenv[0] != '.') cmd += ".:";
+    if (path.length() > 0)  cmd += path + ':';
+    cmd += varenv;
+    putenv(cmd.c_str());
+    }
+#elif defined(AIX)
+  string cmd = "LIBPATH=";
+  char* varenv=NULL;
+  varenv=getenv("LIBPATH");
+  if (varenv == NULL) { 
+    cmd += '.';  
+    if (path.length() > 0)  cmd += ':' + path; 
+    cmd += ":/usr/lib:/lib";
+    }
+  else { 
+    if (varenv[0] != '.') cmd += ".:";
+    if (path.length() > 0)  cmd += path + ':';
+    cmd += varenv;
+    putenv(const_cast<char *>(cmd.c_str()));
+    }
+
+#endif
+return;
+}
+
+/* --Methode-Static-- */
+string& PDynLinkMgr::GetTmpDir()
+{
+if (tmpDir == NULL) { 
+  tmpDir = new string("");
+  char* varenv;
+  if ( (varenv=getenv("PEIDA_TMP")) != NULL )  *tmpDir = varenv; 
+  else if ( (varenv=getenv("TMPDIR")) != NULL )  *tmpDir = varenv; 
+  }
+return(*tmpDir);
+}
+
+/* --Methode-Static-- */
+PDynLinkMgr* PDynLinkMgr::BuildFromCFile(string const & fname)
+{
+size_t l = fname.length();
+if (l < 1)  return(NULL);
+string fnameobj = GetTmpDir()+"tmp_pdl.o";
+
+string cmd;
+int rc;
+
+// Compilation du fichier
+#ifndef __mac__
+cmd = "cc -c -o " + fnameobj + " " + fname;
+#else 
+cmd = "Il faut compiler !!!" + fnameobj + " " + fname;
+#endif
+rc = system(cmd.c_str());
+if (rc != 0)  { 
+  cerr << "PDynLinkMgr::BuildFromCFile() Error Rc(" << cmd <<")= "<< rc << endl; 
+  return(NULL);
+  }
+
+char buff[32];
+numSO++;
+#ifndef HPUX
+sprintf(buff,"pdlmgr%d%s", numSO,sofext);
+#endif
+string fnameso = GetTmpDir()+buff;
+
+// Creation du shared-lib
+#if defined(OSF1) 
+  cmd = "ld -shared -o " + fnameso + " -all " + fnameobj + " -none -lm -lc";
+#elif defined(Linux)
+  cmd = "ld -shared -o " + fnameso + " " + fnameobj + " -lm -lc";
+#elif defined(SunOS)
+  cmd = "ld -G -o " + fnameso + " " + fnameobj + " -lm -lc";
+#elif defined(IRIX64)
+  cmd = "ld -shared -o " + fnameso + " " + fnameobj + " -lm -lc";
+#elif defined(AIX)
+  cmd = "ld -G -bnogc -bexpall -bM:1L -o " + fnameso + " " + fnameobj;
+#elif defined(HPUX)
+  cmd = "ld -b -o " + fnameso + " " + fnameobj + " -lm -lc";
+#else 
+  cmd = "ld -o " + fnameso + " " + fnameobj + " -lm -lc";
+#endif
+rc = system(cmd.c_str());
+if (rc != 0)  { 
+  cerr << "PDynLinkMgr::BuildFromCFile() Error Rc(" << cmd <<")= "<< rc << endl; 
+  return(NULL);
+  }
+PDynLinkMgr* rdyn = new PDynLinkMgr(fnameso, false);
+rdyn->copy = true;
+return(rdyn);
+
+}
+
+/* --Methode-- */
+PDynLinkMgr::PDynLinkMgr(string& soname, bool cp)
+{
+dlhandle = NULL;
+soName = "";
+
+if (soname.find_last_of(".") > soname.length())  
+#ifdef HPUX
+  soname += sofext_HPUX;
+#else
+  soname += sofext;
+#endif
+
+string fnameso;
+if (cp) {
+  numSO++;
+  char buff[32];
+#ifndef HPUX
+  sprintf(buff,"pdlmgr%d%s", numSO,sofext);
+#else
+  sprintf(buff,"pdlmgr%d%s", numSO,sofext_HPUX);
+#endif
+  fnameso = GetTmpDir()+buff;
+  string cmd = "cp " + soname + " " + fnameso;
+  int rc = system(cmd.c_str());
+  if (rc != 0)  { 
+    cerr << "PDynLinkMgr::PDynLinkMgr() Error Rc(" << cmd <<")= "<< rc << endl; 
+    return;
+    }
+  } 
+else fnameso = soname;
+copy = cp;
+soName = fnameso;
+
+#if defined(HPUX)
+dlhandle = NULL;
+cerr << "PDynLinkMgr::PDynLinkMgr() Not yet available on HP-UX " << endl;
+return;
+#else
+dlhandle =  dlopen(fnameso.c_str(), RTLD_NOW);
+if (dlhandle == NULL) { 
+  cerr << "PDynLinkMgr::PDynLinkMgr(): Error opening SO " << fnameso 
+       << " (" << soname << ")" << endl; 
+  string sn = dlerror();
+  cerr << "Loader Error (dlerror()) :" << sn << endl;
+  return; 
+  }
+#endif
+}
+
+/* --Methode-- */
+PDynLinkMgr::~PDynLinkMgr()
+{
+#if defined(HPUX)
+cerr << "PDynLinkMgr::~PDynLinkMgr() Not yet available on HP-UX " << endl;
+return;
+#else
+if (dlhandle) dlclose(dlhandle);    dlhandle = NULL;
+if (copy) {
+  string cmd = "rm -f " + soName;
+  system(cmd.c_str());
+  }
+#endif
+}
+
+/* --Methode-- */
+DlFunction PDynLinkMgr::GetFunction(string const & funcname)
+{
+DlFunction f = NULL;
+#if defined(HPUX)
+cerr << "PDynLinkMgr::GetFunction() Not yet available on HP-UX " << endl;
+return f;
+#else
+if (dlhandle != NULL)  
+  f = (DlFunction)dlsym(dlhandle, funcname.c_str());
+if (f == NULL) cerr << "PDynLinkMgr::GetFunction(): Error linking " << funcname << endl;
+return(f);
+#endif
+}
+
Index: /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/pdlmgr.h	(revision 752)
@@ -0,0 +1,47 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Gestionnaire de lien dynamique   -   R. Ansari 12/98
+// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
+
+#ifndef PDYNLINKMGR_SEEN
+#define PDYNLINKMGR_SEEN
+
+#include "machdefs.h"
+#include <string>
+
+
+#if defined(HPUX)
+#include <dl.h>
+#else
+#include <dlfcn.h>
+#endif
+
+typedef void (* DlFunction) (void);
+
+class PDynLinkMgr {
+public:
+  // ---- Methodes globales (static)
+  static PDynLinkMgr*   BuildFromCFile(string const & fname);  // Compil+link fichier C
+  static void		SetTmpDir(string const & path);        // Repertoire des fichiers temporaires
+
+  // ---- Constructeur et methodes 
+  // Constructeur a partir d'un shared lib - copie en zone temporaire si cp==true
+			PDynLinkMgr(string& soname, bool cp=true);  
+  virtual		~PDynLinkMgr();
+
+  virtual DlFunction	GetFunction(string const & funcname);              
+
+protected :
+  static string&	GetTmpDir();
+  static int	  numSO;
+  static string*  tmpDir;
+
+#if defined(HPUX)
+  shl_t dlhandle;
+#else 
+  void * dlhandle;
+#endif
+  string soName;
+  bool copy;
+};
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SysTools/periodic.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/periodic.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/periodic.cc	(revision 752)
@@ -0,0 +1,109 @@
+/* Classe d'objets avec une methode (DoPeriodic()) appelee periodiquement */
+/*                                  Eric Aubourg     04/96                */
+/*                                  Reza Ansari      06/96                */
+/*                      LAL/IN2P3 (Orsay)  DAPNIA/CEA (Saclay)            */
+
+#include "machdefs.h"
+#include <signal.h>
+#include <unistd.h>
+
+#include "periodic.h"
+
+/* --Methode-- */
+Periodic::Periodic(int dt, UsPeriodicAction act, void * usp)
+{
+mDt = dt;
+mAct = act;
+mUsp = usp;
+if (mDt < 1)  mDt = 5;
+mDtms = 1000*mDt;
+mFgact = false;
+it = -1;
+}
+
+/* --Methode-- */
+Periodic::~Periodic()
+{
+if (mFgact) Stop();
+}
+
+/* --Methode-- */
+void Periodic::SetAction(UsPeriodicAction act, void * usp)
+{
+mAct = act;
+mUsp = usp;
+}
+
+/* --Methode-- */
+void Periodic::SetInterval(int dt)
+{
+mDt = dt;
+if (mDt < 1)  mDt = 5;
+mDtms = 1000*mDt;
+}
+
+/* --Methode-- */
+void Periodic::SetIntervalms(int dtms)
+{
+if (dtms < 1) dtms = 5;
+mDtms = dtms;
+mDt = mDtms/1000;
+if (mDt < 1)  mDt = 1;
+}
+
+/* --Methode-- */
+void Periodic::Start(int dt)
+{
+if (mFgact)  return;
+if (dt > 0)  { mDt = dt;  mDtms = dt*1000; }
+if (!actifs) actifs = new PeriodicList;
+it = 0;
+if (actifs->size() == 0) {
+  signal(SIGALRM, CallBack);
+  alarm(1);
+  }
+actifs->push_back(this);
+mFgact = true;
+return;
+}
+
+/* --Methode-- */
+void Periodic::Stop()
+{
+if (!mFgact)  return;
+
+//remove(actifs->begin(), actifs->end(), this);  // $CHECK$ - Reza
+actifs->remove(this);    // $CHECK$ 
+if (actifs->size() == 0) {
+  signal(SIGALRM, SIG_IGN);
+  alarm(0);
+  delete actifs;
+  actifs = NULL;
+  }
+it = -1;  mFgact = false;
+return;
+}
+
+/* --Methode-- */
+void Periodic::DoPeriodic()
+{
+if (mAct)   mAct(mUsp);
+}
+
+PeriodicList* Periodic::actifs = NULL;
+
+void Periodic::CallBack(int)
+{
+  if (!actifs) return;
+
+  for (PeriodicList::iterator i = actifs->begin(); i != actifs->end(); i++) {
+    Periodic* p = (Periodic*) *i;
+    p->it ++;
+    if (p->it >= p->mDt) {
+      p->it = 0;
+      p->DoPeriodic();
+    }
+  }
+  alarm(1);
+}
+
Index: /tags/V_Fev00/SophyaLib/SysTools/periodic.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/periodic.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/periodic.h	(revision 752)
@@ -0,0 +1,44 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Classe d'objets avec une methode (DoPeriodic()) appelee periodiquement 
+#ifndef PERIODIC_H
+#define PERIODIC_H
+
+#include "machdefs.h"
+#include <list>
+
+class Periodic;
+typedef list<Periodic*> PeriodicList;
+
+typedef void (* UsPeriodicAction) (void *);
+
+class Periodic 
+{
+public:
+  Periodic(int dt, UsPeriodicAction act=NULL, void * usp=NULL);
+  virtual ~Periodic();
+
+  void SetAction(UsPeriodicAction act, void * usp=NULL);
+
+  virtual void SetInterval(int dt);
+  virtual void SetIntervalms(int dtms);
+
+  inline int Interval() { return(mDt); }
+  inline int Intervalms() { return(mDtms); }
+
+  virtual void Start(int dt=-1);
+  virtual void Stop();
+
+  virtual void DoPeriodic();
+
+  static PeriodicList* actifs;
+  static void CallBack(int);
+
+protected:
+  int mDt, mDtms, it;
+  UsPeriodicAction mAct;
+  void * mUsp;
+  bool mFgact;
+};
+
+
+#endif
Index: /tags/V_Fev00/SophyaLib/SysTools/psighand.cc
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/psighand.cc	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/psighand.cc	(revision 752)
@@ -0,0 +1,142 @@
+//  Pour la gestion des signaux a travers des exceptions
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include "psighand.h"
+#include "pexceptions.h"
+
+static bool sigprstate[6] = {false, false, false, false, false, false};
+
+void PeidaProcessSignal(int s);
+
+/* Nouvelle-Fonction */
+void PeidaConfigureSignalhandling(bool cfpe, bool csegv, bool cint, bool cquit, bool cusr1, bool cusr2) 
+{
+  struct sigaction ae, ad;
+
+  ae.sa_handler = PeidaProcessSignal;
+  ad.sa_handler = SIG_DFL;
+  memset( &(ae.sa_mask), 0, sizeof(sigset_t) ); 
+  ae.sa_flags = 0;
+  memset( &(ad.sa_mask), 0, sizeof(sigset_t) ); 
+  ad.sa_flags = 0;
+#ifdef  OSF1
+  ae.sa_flags = SA_RESTART;
+  ad.sa_mask = 0;
+#endif
+
+// SIGFPE 
+  if (sigprstate[0] != cfpe) {
+    if (cfpe)   { 
+      sigaction(SIGFPE, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGFPE handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGFPE, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGFPE handling ...");
+      }
+    sigprstate[0] = cfpe;
+    }
+// SIGSEGV 
+  if (sigprstate[1] != csegv) {
+    if (csegv)   { 
+      sigaction(SIGSEGV, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGSEGV handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGSEGV, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGSEGV handling ...");
+      }
+    sigprstate[1] = csegv;
+    }
+
+// SIGINT
+  if (sigprstate[2] != cint) {
+    if (cint)   { 
+      sigaction(SIGINT, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGINT handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGINT, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGINT handling ...");
+      }
+    sigprstate[2] = cint; 
+    }
+  
+// SIGQUIT
+  if (sigprstate[3] != cquit) {
+    if (cquit)   { 
+      sigaction(SIGQUIT, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGQUIT handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGQUIT, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGQUIT handling ...");
+      }
+    sigprstate[3] = cquit; 
+    }
+  
+// SIGUSR1
+  if (sigprstate[4] != cusr1) {
+    if (cusr1)   { 
+      sigaction(SIGUSR1, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGUSR1 handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGUSR1, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGUSR1 handling ...");
+      }
+    sigprstate[4] = cusr1;
+    }
+// SIGUSR2
+  if (sigprstate[5] != cusr2) {
+    if (cusr2)   { 
+      sigaction(SIGUSR2, &ae, NULL);
+      puts("PeidaConfigureSignalhandling(): Activating SIGUSR2 handling (-> throw) ...");
+      }
+    else  { 
+      sigaction(SIGUSR2, &ad, NULL);
+      puts("PeidaConfigureSignalhandling(): Back to default SIGUSR2 handling ...");
+      }
+    sigprstate[5] = cusr2;
+    }    
+}
+/* Nouvelle-Fonction */
+void PeidaProcessSignal(int s)
+{
+string msg;
+switch(s)
+  {
+  case SIGFPE :
+    puts("PeidaProcessSignal: ###Signal SIGFPE catched, throw catchedSIGFPE ###");
+    msg = "Caught SIGFPE";
+    throw ( CaughtSignalExc(msg, s) );
+  case SIGSEGV :
+    puts("PeidaProcessSignal: ###Signal SIGSEGV catched, throw catchedSIGSEGV ###");
+    msg = "Caught SIGSEGV";
+    throw ( CaughtSignalExc(msg, s) );
+  case SIGINT :
+    puts("PeidaProcessSignal: ###Signal SIGINT catched, throw catchedSIGINT ###");
+    msg = "Caught SIGINT";
+    throw ( CaughtSignalExc(msg, s) );
+  case SIGQUIT :
+    puts("PeidaProcessSignal: ###Signal SIGQUIT catched, throw catchedSIGQUIT ###");
+    msg = "Caught SIGQUIT";
+    throw ( CaughtSignalExc(msg, s) );
+  case SIGUSR1 :
+    puts("PeidaProcessSignal: ###Signal SIGUSR1 catched, throw catchedSIGUSR1 ###");
+    msg = "Caught SIGUSR1";
+    throw ( CaughtSignalExc(msg, s) );
+  case SIGUSR2 :
+    puts("PeidaProcessSignal: ###Signal SIGUSR2 catched, throw catchedSIGUSR2 ###");
+    msg = "Caught SIGUSR2";
+    throw ( CaughtSignalExc(msg, s) );
+  default :
+    printf("PeidaProcessSignal: ###Signal %d catched, throw  inconsistentErr ### \n", s);
+    msg = "Caught SIG???";
+    throw ( CaughtSignalExc(msg, s) );
+  }
+
+// return;
+}
Index: /tags/V_Fev00/SophyaLib/SysTools/psighand.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/psighand.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/psighand.h	(revision 752)
@@ -0,0 +1,11 @@
+// This may look like C code, but it is really -*- C++ -*-
+//  Pour la gestion des signaux a travers des exceptions
+
+#ifndef PSIGHANDLE_SEEN
+#define PSIGHANDLE_SEEN
+
+#include "machdefs.h"
+void PeidaConfigureSignalhandling(bool cfpe=false, bool csegv=false, 
+                                  bool cint=false, bool cquit=false, 
+                                  bool cusr1=false, bool cusr2=false); 
+#endif
Index: /tags/V_Fev00/SophyaLib/SysTools/timing.c
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/timing.c	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/timing.c	(revision 752)
@@ -0,0 +1,69 @@
+/*    Fonction d'impression de temps de calcul et de temps passe  */
+/*                               R.Ansari    Juin 93              */
+
+/*
+++
+  Module	Temps CPU, passé (C)
+  Lib	LibsUtil
+  include	timing.h
+
+	Fonctions permettant d'imprimer le temps CPU consommé et le temps 
+	passé.
+--
+*/ 
+
+/*
+++
+  void InitTim()
+	Initialisation des chronomètres
+  void PrtTim(char *comm)
+	Imprime le temps CPU, et le temps passé depuis 
+	le dernier appel à "PrtTim()" avec le commentaire
+	"comm". Imprime aussi le cumul du temps CPU et du 
+	temps passé depuis l'appel à "InitTim()".
+--
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+ 
+clock_t CPUT0, CPUT;
+time_t ELT0, ELT;
+ 
+void InitTim(void);
+void PrtTim(char *Comm);
+ 
+/* Nouvelle-Fonction */
+void InitTim(void)
+{
+CPUT0 = CPUT = clock();
+ELT0 = ELT = time(NULL);
+return;
+}
+ 
+/* Nouvelle-Fonction */
+void PrtTim(char *Comm)
+{
+float tcal,tcalt;
+clock_t cput;
+time_t elt;
+int etm,etmt;
+ 
+elt = time(NULL);  cput = clock();
+tcalt = ( (float)(cput) - (float)(CPUT0) ) / (float)(CLOCKS_PER_SEC);
+tcal = ( (float)(cput) - (float)(CPUT) ) / (float)(CLOCKS_PER_SEC);
+etm = elt - ELT;
+etmt = elt - ELT0;
+printf("%s CPUTime: Total= %g  (Partial= %g) Sec. \n",
+       Comm, tcalt, tcal);
+printf("ElapsedTime(hh:mm:ss): Total= %02d:%02d:%02d ",
+       etmt/3600, (etmt%3600)/60, etmt%60);
+printf(" (Partial= %02d:%02d:%02d)\n",
+       etm/3600, (etm%3600)/60, etm%60);
+ 
+ELT = elt;
+CPUT = cput;
+return;
+}
Index: /tags/V_Fev00/SophyaLib/SysTools/timing.h
===================================================================
--- /tags/V_Fev00/SophyaLib/SysTools/timing.h	(revision 752)
+++ /tags/V_Fev00/SophyaLib/SysTools/timing.h	(revision 752)
@@ -0,0 +1,19 @@
+/*   Impression temps elapsed / Temps CPU     */
+/*                           Reza  -  93/94   */
+
+#ifndef TIMING_H_SEEN
+#define TIMING_H_SEEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void InitTim(void);                                                             
+void PrtTim(char *Comm);                                                        
+                                                                                
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
