diff --git a/ChangeLog b/ChangeLog
index 795c4d6eb..09e488db2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-02-11 Dietmar Warning
+ * src/spicelib/devices/asrc/*.c,*.h,Makefile.am
+ * src/frontend/inpcom.c,
+ * vngspice.vcproj
+ Add temperature coefficients for B sources
+
2012-02-11 Holger Vogt
* inpcom.c: Robert's patch, reading libs, incs etc.
diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c
index 433004fda..ee1aaf2c9 100644
--- a/src/frontend/inpcom.c
+++ b/src/frontend/inpcom.c
@@ -4871,10 +4871,11 @@ static void inp_bsource_compat(struct line *deck)
}
buf[i] = '\0';
/* no parens {} around time, hertz, temper, the constants
- pi and e which are defined in inpptree.c and around pwl */
+ pi and e which are defined in inpptree.c, around pwl and temp. coeffs */
if ((*str_ptr == '(') || cieq(buf, "hertz") || cieq(buf, "temper")
|| cieq(buf, "time") || cieq(buf, "pi") || cieq(buf, "e")
- || cieq(buf, "pwl")) {
+ || cieq(buf, "pwl")
+ || cieq(buf, "tc") || cieq(buf, "tc1") || cieq(buf, "tc2")) {
/* special handling of pwl lines:
Put braces around tokens and around expressions, use ','
as separator like:
diff --git a/src/spicelib/devices/asrc/Makefile.am b/src/spicelib/devices/asrc/Makefile.am
index b971570dd..a5db57d78 100644
--- a/src/spicelib/devices/asrc/Makefile.am
+++ b/src/spicelib/devices/asrc/Makefile.am
@@ -19,7 +19,8 @@ libasrc_la_SOURCES = \
asrcmdel.c \
asrcpar.c \
asrcpzld.c \
- asrcset.c
+ asrcset.c \
+ asrctemp.c
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
diff --git a/src/spicelib/devices/asrc/asrc.c b/src/spicelib/devices/asrc/asrc.c
index 8bce8a833..11404b229 100644
--- a/src/spicelib/devices/asrc/asrc.c
+++ b/src/spicelib/devices/asrc/asrc.c
@@ -11,9 +11,14 @@ Author: 1987 Kanwar Jit Singh
/* Arbitrary source */
IFparm ASRCpTable[] = { /* parameters */
- IP( "i", ASRC_CURRENT, IF_PARSETREE, "Current source "),
+ IP( "i", ASRC_CURRENT, IF_PARSETREE, "Current source"),
IP( "v", ASRC_VOLTAGE, IF_PARSETREE, "Voltage source"),
- OP( "i", ASRC_OUTPUTCURRENT, IF_REAL, "Current through source "),
+ IOPZU( "temp", ASRC_TEMP, IF_REAL, "Instance operating temperature"),
+ IOPZ( "dtemp", ASRC_DTEMP, IF_REAL,
+ "Instance temperature difference with the rest of the circuit"),
+ IOPU( "tc1", ASRC_TC1, IF_REAL, "First order temp. coefficient"),
+ IOPU( "tc2", ASRC_TC2, IF_REAL, "Second order temp. coefficient"),
+ OP( "i", ASRC_OUTPUTCURRENT, IF_REAL, "Current through source"),
OP( "v", ASRC_OUTPUTVOLTAGE, IF_REAL, "Voltage across source"),
OP( "pos_node", ASRC_POS_NODE, IF_INTEGER, "Positive Node"),
OP( "neg_node", ASRC_NEG_NODE, IF_INTEGER, "Negative Node")
diff --git a/src/spicelib/devices/asrc/asrcacld.c b/src/spicelib/devices/asrc/asrcacld.c
index c84a06cd0..5dea71624 100644
--- a/src/spicelib/devices/asrc/asrcacld.c
+++ b/src/spicelib/devices/asrc/asrcacld.c
@@ -29,6 +29,8 @@ ASRCacLoad(GENmodel *inModel, CKTcircuit *ckt)
int i, j;
double *derivs;
double rhs;
+ double difference;
+ double factor;
NG_IGNORE(ckt);
@@ -42,6 +44,13 @@ ASRCacLoad(GENmodel *inModel, CKTcircuit *ckt)
if (here->ASRCowner != ARCHme)
continue;
+ if(!here->ASRCtc1Given) here->ASRCtc1 = 0.0;
+ if(!here->ASRCtc2Given) here->ASRCtc2 = 0.0;
+
+ difference = (here->ASRCtemp + here->ASRCdtemp) - 300.15;
+ factor = 1.0 + (here->ASRCtc1)*difference +
+ (here->ASRCtc2)*difference*difference;
+
/*
* Get the function and its derivatives from the
* field in the instance structure. The field is
@@ -65,21 +74,21 @@ ASRCacLoad(GENmodel *inModel, CKTcircuit *ckt)
case IF_INSTANCE:
if( here->ASRCtype == ASRC_VOLTAGE) {
/* CCVS */
- *(here->ASRCposptr[j++]) -= derivs[i];
+ *(here->ASRCposptr[j++]) -= derivs[i] / factor;
} else{
/* CCCS */
- *(here->ASRCposptr[j++]) += derivs[i];
- *(here->ASRCposptr[j++]) -= derivs[i];
+ *(here->ASRCposptr[j++]) += derivs[i] / factor;
+ *(here->ASRCposptr[j++]) -= derivs[i] / factor;
}
break;
case IF_NODE:
if(here->ASRCtype == ASRC_VOLTAGE) {
/* VCVS */
- *(here->ASRCposptr[j++]) -= derivs[i];
+ *(here->ASRCposptr[j++]) -= derivs[i] / factor;
} else {
- /*VCCS*/
- *(here->ASRCposptr[j++]) += derivs[i];
- *(here->ASRCposptr[j++]) -= derivs[i];
+ /* VCCS */
+ *(here->ASRCposptr[j++]) += derivs[i] / factor;
+ *(here->ASRCposptr[j++]) -= derivs[i] / factor;
}
break;
default:
diff --git a/src/spicelib/devices/asrc/asrcask.c b/src/spicelib/devices/asrc/asrcask.c
index 339a0e46d..babd823d4 100644
--- a/src/spicelib/devices/asrc/asrcask.c
+++ b/src/spicelib/devices/asrc/asrcask.c
@@ -29,13 +29,25 @@ ASRCask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu
NG_IGNORE(select);
switch(which) {
+ case ASRC_TEMP:
+ value->rValue = here->ASRCtemp - CONSTCtoK;
+ return(OK);
+ case ASRC_DTEMP:
+ value->rValue = here->ASRCdtemp;
+ return(OK);
+ case ASRC_TC1:
+ value->rValue = here->ASRCtc1;
+ return(OK);
+ case ASRC_TC2:
+ value->rValue = here->ASRCtc2;
+ return(OK);
case ASRC_CURRENT:
value->tValue = here->ASRCtype == ASRC_CURRENT ?
- here->ASRCtree : NULL;
+ here->ASRCtree : NULL;
return (OK);
case ASRC_VOLTAGE:
value->tValue = here->ASRCtype == ASRC_VOLTAGE ?
- here->ASRCtree : NULL;
+ here->ASRCtree : NULL;
return (OK);
case ASRC_POS_NODE:
value->iValue = here->ASRCposNode;
@@ -44,12 +56,12 @@ ASRCask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu
value->iValue = here->ASRCnegNode;
return (OK);
case ASRC_OUTPUTCURRENT:
- value->rValue = ckt->CKTrhsOld[here->ASRCbranch];
+ value->rValue = ckt->CKTrhsOld[here->ASRCbranch];
return (OK);
case ASRC_OUTPUTVOLTAGE:
- value->rValue = ckt->CKTrhsOld[here->ASRCposNode] -
- ckt->CKTrhsOld[here->ASRCnegNode];
- return(OK);
+ value->rValue = ckt->CKTrhsOld[here->ASRCposNode] -
+ ckt->CKTrhsOld[here->ASRCnegNode];
+ return(OK);
default:
return (E_BADPARM);
}
diff --git a/src/spicelib/devices/asrc/asrcdefs.h b/src/spicelib/devices/asrc/asrcdefs.h
index 8f347626c..a5419cc69 100644
--- a/src/spicelib/devices/asrc/asrcdefs.h
+++ b/src/spicelib/devices/asrc/asrcdefs.h
@@ -6,34 +6,41 @@ Author: 1985 Thomas L. Quarles
#ifndef ASRC
#define ASRC
-
#include "ngspice/cktdefs.h"
#include "ngspice/ifsim.h"
#include "ngspice/complex.h"
- /*
- * structures to describe Arbitrary sources
- */
+/*
+ * structures to describe Arbitrary sources
+*/
/* information to describe a single instance */
typedef struct sASRCinstance {
struct sASRCmodel *ARRCmodPtr; /* backpointer to model */
struct sASRCinstance *ASRCnextInstance; /* pointer to next instance of
- *current model*/
+ * current model */
IFuid ASRCname; /* pointer to character string naming this instance */
int ASRCowner; /* number of owner process */
int ASRCstates; /* state info */
int ASRCposNode; /* number of positive node of source */
int ASRCnegNode; /* number of negative node of source */
- int ASRCtype; /* Whether source is voltage or current */
+ int ASRCtype; /* Whether source is voltage or current */
int ASRCbranch; /* number of branch equation added for v source */
IFparseTree *ASRCtree; /* The parse tree */
+ double ASRCtemp; /* temperature at which this resistor operates */
+ double ASRCdtemp; /* delta-temperature of a particular instance */
+ double ASRCtc1; /* first temperature coefficient of resistors */
+ double ASRCtc2; /* second temperature coefficient of resistors */
double **ASRCposptr; /* pointer to pointers of the elements
- * in the sparce matrix */
+ * in the sparce matrix */
double ASRCprev_value; /* Previous value for the convergence test */
double *ASRCacValues; /* Store rhs and derivatives for ac anal */
int ASRCcont_br; /* Temporary store for controlling current branch */
+ unsigned ASRCtempGiven : 1; /* indicates temperature specified */
+ unsigned ASRCdtempGiven : 1; /* indicates delta-temp specified */
+ unsigned ASRCtc1Given : 1; /* indicates tc1 parameter specified */
+ unsigned ASRCtc2Given : 1; /* indicates tc2 parameter specified */
} ASRCinstance ;
@@ -59,6 +66,10 @@ typedef struct sASRCmodel { /* model structure for a source */
#define ASRC_PARSE_TREE 5
#define ASRC_OUTPUTVOLTAGE 6
#define ASRC_OUTPUTCURRENT 7
+#define ASRC_TEMP 8
+#define ASRC_DTEMP 9
+#define ASRC_TC1 10
+#define ASRC_TC2 11
/* module-wide variables */
diff --git a/src/spicelib/devices/asrc/asrcext.h b/src/spicelib/devices/asrc/asrcext.h
index e408adbf3..a0a23f636 100644
--- a/src/spicelib/devices/asrc/asrcext.h
+++ b/src/spicelib/devices/asrc/asrcext.h
@@ -15,4 +15,4 @@ extern int ASRCpzLoad(GENmodel*,CKTcircuit*,SPcomplex*);
extern int ASRCacLoad(GENmodel*,CKTcircuit*);
extern int ASRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
extern int ASRCunsetup(GENmodel*,CKTcircuit*);
-
+extern int ASRCtemp(GENmodel*,CKTcircuit*);
diff --git a/src/spicelib/devices/asrc/asrcinit.c b/src/spicelib/devices/asrc/asrcinit.c
index 3484e51fd..a9339deee 100644
--- a/src/spicelib/devices/asrc/asrcinit.c
+++ b/src/spicelib/devices/asrc/asrcinit.c
@@ -47,7 +47,7 @@ SPICEdev ASRCinfo = {
/* DEVsetup */ ASRCsetup,
/* DEVunsetup */ ASRCunsetup,
/* DEVpzSetup */ ASRCsetup,
- /* DEVtemperature*/ NULL,
+ /* DEVtemperature*/ ASRCtemp,
/* DEVtrunc */ NULL,
/* DEVfindBranch */ ASRCfindBr,
/* DEVacLoad */ ASRCacLoad, /* ac and normal load functions NOT identical */
diff --git a/src/spicelib/devices/asrc/asrcload.c b/src/spicelib/devices/asrc/asrcload.c
index e9d83adfe..692b3abac 100644
--- a/src/spicelib/devices/asrc/asrcload.c
+++ b/src/spicelib/devices/asrc/asrcload.c
@@ -13,7 +13,7 @@ Author: 1987 Kanwar Jit Singh
#include "ngspice/suffix.h"
double *asrc_vals, *asrc_derivs;
-int asrc_nvals;
+int asrc_nvals;
/*ARGSUSED*/
int
@@ -28,109 +28,117 @@ ASRCload(GENmodel *inModel, CKTcircuit *ckt)
ASRCinstance *here;
int i, j;
double rhs;
+ double difference;
+ double factor;
/* loop through all the Arbitrary source models */
for( ; model != NULL; model = model->ASRCnextModel ) {
/* loop through all the instances of the model */
for (here = model->ASRCinstances; here != NULL ;
- here=here->ASRCnextInstance)
- {
- if (here->ASRCowner != ARCHme)
- continue;
-
- /*
- * Get the function and its derivatives evaluated
- */
- i = here->ASRCtree->numVars;
- if (asrc_nvals < i) {
- if (asrc_nvals) {
- FREE(asrc_vals);
- FREE(asrc_derivs);
- }
- asrc_nvals = i;
- asrc_vals = NEWN(double, i);
- asrc_derivs = NEWN(double, i);
- }
-
- j=0;
-
- /*
- * Fill the vector of values from the previous solution
- */
- for( i=0; i < here->ASRCtree->numVars; i++)
- if( here->ASRCtree->varTypes[i] == IF_INSTANCE) {
- int branch = CKTfndBranch(ckt, here->ASRCtree->vars[i].uValue);
- asrc_vals[i] = *(ckt->CKTrhsOld + branch);
- } else {
- int node_num = (here->ASRCtree->vars[i].nValue) -> number;
- asrc_vals[i] = *(ckt->CKTrhsOld + node_num);
- }
-
- if (here->ASRCtree->IFeval (here->ASRCtree, ckt->CKTgmin, &rhs, asrc_vals, asrc_derivs) != OK)
- return(E_BADPARM);
-
- /* The convergence test */
- here->ASRCprev_value = rhs;
-
- /* The ac load precomputation and storage */
-
- if (ckt->CKTmode & MODEINITSMSIG) {
- int size = (here->ASRCtree->numVars) + 1 ;
- here->ASRCacValues = NEWN(double, size);
- for ( i = 0; i < here->ASRCtree->numVars; i++)
- here->ASRCacValues[i] = asrc_derivs[i];
- }
-
- if( here->ASRCtype == ASRC_VOLTAGE) {
- *(here->ASRCposptr[j++]) += 1.0;
- *(here->ASRCposptr[j++]) -= 1.0;
- *(here->ASRCposptr[j++]) -= 1.0;
- *(here->ASRCposptr[j++]) += 1.0;
+ here=here->ASRCnextInstance)
+ {
+ if (here->ASRCowner != ARCHme)
+ continue;
+
+ if(!here->ASRCtc1Given) here->ASRCtc1 = 0.0;
+ if(!here->ASRCtc2Given) here->ASRCtc2 = 0.0;
+
+ difference = (here->ASRCtemp + here->ASRCdtemp) - 300.15;
+ factor = 1.0 + (here->ASRCtc1)*difference + (here->ASRCtc2)*difference*difference;
+
+ /*
+ * Get the function and its derivatives evaluated
+ */
+ i = here->ASRCtree->numVars;
+ if (asrc_nvals < i) {
+ if (asrc_nvals) {
+ FREE(asrc_vals);
+ FREE(asrc_derivs);
+ }
+ asrc_nvals = i;
+ asrc_vals = NEWN(double, i);
+ asrc_derivs = NEWN(double, i);
+ }
+
+ j=0;
+
+ /*
+ * Fill the vector of values from the previous solution
+ */
+ for( i=0; i < here->ASRCtree->numVars; i++)
+ if( here->ASRCtree->varTypes[i] == IF_INSTANCE) {
+ int branch = CKTfndBranch(ckt, here->ASRCtree->vars[i].uValue);
+ asrc_vals[i] = *(ckt->CKTrhsOld + branch);
+ } else {
+ int node_num = (here->ASRCtree->vars[i].nValue) -> number;
+ asrc_vals[i] = *(ckt->CKTrhsOld + node_num);
+ }
+
+ if (here->ASRCtree->IFeval (here->ASRCtree, ckt->CKTgmin, &rhs, asrc_vals, asrc_derivs) != OK)
+ return(E_BADPARM);
+
+ /* The convergence test */
+ here->ASRCprev_value = rhs;
+
+ /* The ac load precomputation and storage */
+
+ if (ckt->CKTmode & MODEINITSMSIG) {
+ int size = (here->ASRCtree->numVars) + 1 ;
+ here->ASRCacValues = NEWN(double, size);
+ for ( i = 0; i < here->ASRCtree->numVars; i++)
+ here->ASRCacValues[i] = asrc_derivs[i];
+ }
+
+ if( here->ASRCtype == ASRC_VOLTAGE) {
+ *(here->ASRCposptr[j++]) += 1.0;
+ *(here->ASRCposptr[j++]) -= 1.0;
+ *(here->ASRCposptr[j++]) -= 1.0;
+ *(here->ASRCposptr[j++]) += 1.0;
}
- for(i=0; i < here->ASRCtree->numVars; i++) {
- rhs -= (asrc_vals[i] * asrc_derivs[i]);
-
- switch(here->ASRCtree->varTypes[i]) {
- case IF_INSTANCE:
- if( here->ASRCtype == ASRC_VOLTAGE) {
- /* CCVS */
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
- } else{
- /* CCCS */
- *(here->ASRCposptr[j++]) += asrc_derivs[i];
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
- }
- break;
-
- case IF_NODE:
- if(here->ASRCtype == ASRC_VOLTAGE) {
- /* VCVS */
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
- } else {
- /*VCCS*/
- *(here->ASRCposptr[j++]) += asrc_derivs[i];
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
- }
- break;
-
- default:
- return(E_BADPARM);
+ for(i=0; i < here->ASRCtree->numVars; i++) {
+ rhs -= (asrc_vals[i] * asrc_derivs[i]);
+
+ switch(here->ASRCtree->varTypes[i]) {
+ case IF_INSTANCE:
+ if( here->ASRCtype == ASRC_VOLTAGE) {
+ /* CCVS */
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] * factor;
+ } else{
+ /* CCCS */
+ *(here->ASRCposptr[j++]) += asrc_derivs[i] * factor;
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] * factor;
+ }
+ break;
+
+ case IF_NODE:
+ if(here->ASRCtype == ASRC_VOLTAGE) {
+ /* VCVS */
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] * factor;
+ } else {
+ /* VCCS */
+ *(here->ASRCposptr[j++]) += asrc_derivs[i] * factor;
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] * factor;
+ }
+ break;
+
+ default:
+ return(E_BADPARM);
}
}
/* Insert the RHS */
if( here->ASRCtype == ASRC_VOLTAGE) {
- *(ckt->CKTrhs+(here->ASRCbranch)) += rhs;
+ *(ckt->CKTrhs+(here->ASRCbranch)) += factor * rhs;
} else {
- *(ckt->CKTrhs+(here->ASRCposNode)) -= rhs;
- *(ckt->CKTrhs+(here->ASRCnegNode)) += rhs;
+ *(ckt->CKTrhs+(here->ASRCposNode)) -= factor * rhs;
+ *(ckt->CKTrhs+(here->ASRCnegNode)) += factor * rhs;
}
/* Store the rhs for small signal analysis */
if (ckt->CKTmode & MODEINITSMSIG) {
- here->ASRCacValues[here->ASRCtree->numVars] = rhs;
+ here->ASRCacValues[here->ASRCtree->numVars] = factor * rhs;
}
}
}
diff --git a/src/spicelib/devices/asrc/asrcpar.c b/src/spicelib/devices/asrc/asrcpar.c
index f25d8d80b..e317830ad 100644
--- a/src/spicelib/devices/asrc/asrcpar.c
+++ b/src/spicelib/devices/asrc/asrcpar.c
@@ -24,11 +24,19 @@ ASRCparam(int param, IFvalue *value, GENinstance *fast, IFvalue *select)
switch(param) {
case ASRC_VOLTAGE:
here->ASRCtype = ASRC_VOLTAGE;
- here->ASRCtree = value->tValue;
+ here->ASRCtree = value->tValue;
break;
case ASRC_CURRENT:
here->ASRCtype = ASRC_CURRENT;
- here->ASRCtree = value->tValue;
+ here->ASRCtree = value->tValue;
+ break;
+ case ASRC_TC1:
+ here->ASRCtc1 = value->rValue;
+ here->ASRCtc1Given = TRUE;
+ break;
+ case ASRC_TC2:
+ here->ASRCtc2 = value->rValue;
+ here->ASRCtc2Given = TRUE;
break;
default:
return(E_BADPARM);
diff --git a/src/spicelib/devices/asrc/asrcpzld.c b/src/spicelib/devices/asrc/asrcpzld.c
index 277fb5682..1f1a64155 100644
--- a/src/spicelib/devices/asrc/asrcpzld.c
+++ b/src/spicelib/devices/asrc/asrcpzld.c
@@ -22,6 +22,8 @@ ASRCpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
ASRCinstance *here;
double value;
int i, j;
+ double difference;
+ double factor;
NG_IGNORE(s);
@@ -35,6 +37,13 @@ ASRCpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
if (here->ASRCowner != ARCHme)
continue;
+ if(!here->ASRCtc1Given) here->ASRCtc1 = 0.0;
+ if(!here->ASRCtc2Given) here->ASRCtc2 = 0.0;
+
+ difference = (here->ASRCtemp + here->ASRCdtemp) - 300.15;
+ factor = 1.0 + (here->ASRCtc1)*difference +
+ (here->ASRCtc2)*difference*difference;
+
j = 0;
/* Get the function evaluated and the derivatives too */
@@ -75,21 +84,21 @@ ASRCpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
case IF_INSTANCE:
if( here->ASRCtype == ASRC_VOLTAGE) {
/* CCVS */
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] / factor;
} else {
/* CCCS */
- *(here->ASRCposptr[j++]) += asrc_derivs[i];
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
+ *(here->ASRCposptr[j++]) += asrc_derivs[i] / factor;
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] / factor;
}
break;
case IF_NODE:
if(here->ASRCtype == ASRC_VOLTAGE) {
/* VCVS */
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] / factor;
} else {
/* VCCS */
- *(here->ASRCposptr[j++]) += asrc_derivs[i];
- *(here->ASRCposptr[j++]) -= asrc_derivs[i];
+ *(here->ASRCposptr[j++]) += asrc_derivs[i] / factor;
+ *(here->ASRCposptr[j++]) -= asrc_derivs[i] / factor;
}
break;
default:
diff --git a/visualc/vngspice.vcproj b/visualc/vngspice.vcproj
index a606a93b5..bdf2e7042 100644
--- a/visualc/vngspice.vcproj
+++ b/visualc/vngspice.vcproj
@@ -1,8860 +1,8864 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+