2000-11-03 23:02:47 +00:00
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
Module: FGCoefficient.cpp
|
|
|
|
Author: Jon S. Berndt
|
|
|
|
Date started: 12/28/98
|
|
|
|
Purpose: Encapsulates the stability derivative class FGCoefficient;
|
|
|
|
Called by: FGAircraft
|
|
|
|
|
|
|
|
------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
|
|
|
|
|
|
|
|
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 of the License, 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.
|
|
|
|
|
|
|
|
Further information about the GNU General Public License can also be found on
|
|
|
|
the world wide web at http://www.gnu.org.
|
|
|
|
|
|
|
|
FUNCTIONAL DESCRIPTION
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
This class models the stability derivative coefficient lookup tables or
|
|
|
|
equations. Note that the coefficients need not be calculated each delta-t.
|
|
|
|
|
|
|
|
Note that the values in a row which index into the table must be the same value
|
|
|
|
for each column of data, so the first column of numbers for each altitude are
|
|
|
|
seen to be equal, and there are the same number of values for each altitude.
|
|
|
|
|
|
|
|
See the header file FGCoefficient.h for the values of the identifiers.
|
|
|
|
|
|
|
|
HISTORY
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
12/28/98 JSB Created
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
INCLUDES
|
2000-11-03 23:02:47 +00:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
1999-02-05 21:26:01 +00:00
|
|
|
|
1999-02-11 21:05:34 +00:00
|
|
|
#include "FGCoefficient.h"
|
|
|
|
#include "FGState.h"
|
|
|
|
#include "FGFDMExec.h"
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-11-14 20:31:58 +00:00
|
|
|
#include <iomanip.h>
|
|
|
|
|
2000-10-14 02:10:10 +00:00
|
|
|
static const char *IdSrc = "$Header$";
|
|
|
|
static const char *IdHdr = "ID_COEFFICIENT";
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
CLASS IMPLEMENTATION
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
FGCoefficient::FGCoefficient(FGFDMExec* fdex, FGConfigFile* AC_cfg)
|
1999-02-05 21:26:01 +00:00
|
|
|
{
|
1999-06-21 05:01:31 +00:00
|
|
|
int r, c, start, end, n;
|
1999-02-05 21:26:01 +00:00
|
|
|
float ftrashcan;
|
2000-04-24 23:49:06 +00:00
|
|
|
string multparms;
|
2000-11-14 20:31:58 +00:00
|
|
|
char nullstring[13] = " ";
|
|
|
|
|
|
|
|
bias =0.0;
|
|
|
|
gain = 1.0;
|
|
|
|
|
1999-02-11 21:05:34 +00:00
|
|
|
FDMExec = fdex;
|
|
|
|
State = FDMExec->GetState();
|
2000-10-02 23:07:30 +00:00
|
|
|
Table = 0;
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
if (AC_cfg) {
|
|
|
|
name = AC_cfg->GetValue("NAME");
|
|
|
|
method = AC_cfg->GetValue("TYPE");
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
AC_cfg->GetNextConfigLine();
|
|
|
|
*AC_cfg >> description;
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-11-14 20:31:58 +00:00
|
|
|
char bolden[5];
|
|
|
|
char unbolden[5];
|
|
|
|
|
|
|
|
bolden[0] = 27;
|
|
|
|
bolden[1] = '[';
|
|
|
|
bolden[2] = '1';
|
|
|
|
bolden[3] = 'm';
|
|
|
|
bolden[4] = '\0';
|
|
|
|
|
|
|
|
unbolden[0] = 27;
|
|
|
|
unbolden[1] = '[';
|
|
|
|
unbolden[2] = '0';
|
|
|
|
unbolden[3] = 'm';
|
|
|
|
unbolden[4] = '\0';
|
|
|
|
|
|
|
|
cout << " " << bolden << name << unbolden << endl;
|
2000-04-24 23:49:06 +00:00
|
|
|
cout << " " << description << endl;
|
|
|
|
cout << " " << method << endl;
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
if (method == "EQUATION") type = EQUATION;
|
|
|
|
else if (method == "TABLE") type = TABLE;
|
|
|
|
else if (method == "VECTOR") type = VECTOR;
|
|
|
|
else if (method == "VALUE") type = VALUE;
|
|
|
|
else type = UNKNOWN;
|
|
|
|
|
|
|
|
if (type == VECTOR || type == TABLE) {
|
|
|
|
*AC_cfg >> rows;
|
|
|
|
cout << " Rows: " << rows << " ";
|
1999-03-02 01:02:51 +00:00
|
|
|
if (type == TABLE) {
|
2000-04-24 23:49:06 +00:00
|
|
|
*AC_cfg >> columns;
|
|
|
|
cout << "Cols: " << columns;
|
1999-06-21 05:01:31 +00:00
|
|
|
}
|
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
cout << endl;
|
|
|
|
|
|
|
|
*AC_cfg >> multparms;
|
2000-10-02 23:07:30 +00:00
|
|
|
LookupR = State->GetParameterIndex(multparms);
|
|
|
|
cout << " Row indexing parameter: " << multparms << endl;
|
2000-04-24 23:49:06 +00:00
|
|
|
}
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
if (type == TABLE) {
|
|
|
|
*AC_cfg >> multparms;
|
2000-10-02 23:07:30 +00:00
|
|
|
LookupC = State->GetParameterIndex(multparms);
|
|
|
|
cout << " Column indexing parameter: " << multparms << endl;
|
2000-04-24 23:49:06 +00:00
|
|
|
}
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
// Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
|
|
|
|
// where each non-dimensionalizing parameter for this coefficient is
|
|
|
|
// separated by a | character
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
*AC_cfg >> multparms;
|
1999-05-08 03:19:08 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
end = multparms.length();
|
|
|
|
n = multparms.find("|");
|
2000-10-02 23:07:30 +00:00
|
|
|
start = 0;
|
1999-05-08 03:19:08 +00:00
|
|
|
|
2000-07-06 21:02:46 +00:00
|
|
|
while (n < end && n >= 0) {
|
2000-04-24 23:49:06 +00:00
|
|
|
n -= start;
|
2000-10-02 23:07:30 +00:00
|
|
|
multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
|
2000-04-24 23:49:06 +00:00
|
|
|
start += n+1;
|
|
|
|
n = multparms.find("|",start);
|
|
|
|
}
|
2000-10-02 23:07:30 +00:00
|
|
|
|
|
|
|
multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
|
2000-04-24 23:49:06 +00:00
|
|
|
|
|
|
|
// End of non-dimensionalizing parameter read-in
|
|
|
|
|
|
|
|
switch(type) {
|
|
|
|
case VALUE:
|
|
|
|
*AC_cfg >> StaticValue;
|
|
|
|
cout << " Value = " << StaticValue << endl;
|
|
|
|
break;
|
|
|
|
case VECTOR:
|
|
|
|
Allocate(rows,2);
|
|
|
|
|
|
|
|
for (r=1;r<=rows;r++) {
|
2000-10-02 23:07:30 +00:00
|
|
|
*AC_cfg >> Table[r][0];
|
|
|
|
*AC_cfg >> Table[r][1];
|
2000-04-24 23:49:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (r=1;r<=rows;r++) {
|
|
|
|
cout << " ";
|
|
|
|
for (c=0;c<columns;c++) {
|
2000-10-02 23:07:30 +00:00
|
|
|
cout << Table[r][c] << " ";
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
2000-04-24 23:49:06 +00:00
|
|
|
cout << endl;
|
|
|
|
}
|
1999-05-08 03:19:08 +00:00
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
break;
|
|
|
|
case TABLE:
|
|
|
|
Allocate(rows, columns);
|
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
Table[0][0] = 0.0;
|
2000-11-14 20:31:58 +00:00
|
|
|
|
|
|
|
// Read the table in -- it should be in matrix format with the row
|
|
|
|
// independents as the first column and the column independents in
|
|
|
|
// the first row. The implication of this layout is that there should
|
|
|
|
// be no value in the upper left corner of the matrix e.g:
|
|
|
|
// 0 10 20 30 ...
|
|
|
|
// -5 1 2 3 4 ...
|
|
|
|
// ...
|
|
|
|
|
|
|
|
for (r=0; r<=rows; r++) {
|
|
|
|
for (c=0; c <= columns; c++) {
|
|
|
|
if ( !((r == 0) && (c == 0)) ) {
|
|
|
|
*AC_cfg >> Table[r][c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for (c=1;c<=columns;c++) {
|
2000-10-02 23:07:30 +00:00
|
|
|
*AC_cfg >> Table[0][c];
|
2000-04-24 23:49:06 +00:00
|
|
|
for (r=1;r<=rows;r++) {
|
2000-10-02 23:07:30 +00:00
|
|
|
if ( c==1 ) *AC_cfg >> Table[r][0];
|
2000-04-24 23:49:06 +00:00
|
|
|
else *AC_cfg >> ftrashcan;
|
2000-10-02 23:07:30 +00:00
|
|
|
*AC_cfg >> Table[r][c];
|
1999-05-08 03:19:08 +00:00
|
|
|
}
|
2000-11-14 20:31:58 +00:00
|
|
|
} */
|
|
|
|
|
2000-04-24 23:49:06 +00:00
|
|
|
for (r=0;r<=rows;r++) {
|
|
|
|
cout << " ";
|
|
|
|
for (c=0;c<=columns;c++) {
|
2000-11-14 20:31:58 +00:00
|
|
|
if( ((r == 0) && (c == 0)) ) {
|
|
|
|
cout << nullstring;
|
|
|
|
} else {
|
|
|
|
cout.flags(ios::left);
|
|
|
|
cout << setw(12) << Table[r][c];
|
|
|
|
}
|
2000-04-24 23:49:06 +00:00
|
|
|
}
|
|
|
|
cout << endl;
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
2000-04-24 23:49:06 +00:00
|
|
|
|
|
|
|
break;
|
2000-10-02 23:07:30 +00:00
|
|
|
case EQUATION:
|
|
|
|
case UNKNOWN:
|
|
|
|
cerr << "Unimplemented coefficient type: " << type << endl;
|
|
|
|
break;
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
2000-04-24 23:49:06 +00:00
|
|
|
AC_cfg->GetNextConfigLine();
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
FGCoefficient::~FGCoefficient(void) {
|
|
|
|
DeAllocate();
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
bool FGCoefficient::DeAllocate(void)
|
1999-02-05 21:26:01 +00:00
|
|
|
{
|
2000-10-02 23:07:30 +00:00
|
|
|
if (Table != NULL ) {
|
|
|
|
for (unsigned int i=0; i<=rows; i++) delete[] Table[i];
|
|
|
|
|
|
|
|
delete[] Table;
|
|
|
|
}
|
|
|
|
|
1999-02-05 21:26:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
bool FGCoefficient::Allocate(int r, int c)
|
1999-02-05 21:26:01 +00:00
|
|
|
{
|
2000-10-02 23:07:30 +00:00
|
|
|
rows = r;
|
|
|
|
columns = c;
|
|
|
|
Table = new float*[r+1];
|
|
|
|
for (int i=0;i<=r;i++) Table[i] = new float[c+1];
|
1999-02-05 21:26:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
float FGCoefficient::Value(float rVal, float cVal)
|
|
|
|
{
|
|
|
|
float rFactor, cFactor, col1temp, col2temp, Value;
|
2000-10-02 23:07:30 +00:00
|
|
|
int r, c;
|
|
|
|
unsigned midx;
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
if (rows < 2 || columns < 2) return 0.0;
|
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
for (r=1;r<=rows;r++) if (Table[r][0] >= rVal) break;
|
|
|
|
for (c=1;c<=columns;c++) if (Table[0][c] >= cVal) break;
|
2000-11-14 20:31:58 +00:00
|
|
|
//cout << "Value(): rVal: " << rVal << " cVal: " << cVal << endl;
|
|
|
|
//cout << "Value(): r: " << r << " c: " << c << endl;
|
1999-02-05 21:26:01 +00:00
|
|
|
c = c < 2 ? 2 : (c > columns ? columns : c);
|
|
|
|
r = r < 2 ? 2 : (r > rows ? rows : r);
|
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
rFactor = (rVal - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
|
|
|
|
cFactor = (cVal - Table[0][c-1]) / (Table[0][c] - Table[0][c-1]);
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
col1temp = rFactor*(Table[r][c-1] - Table[r-1][c-1]) + Table[r-1][c-1];
|
|
|
|
col2temp = rFactor*(Table[r][c] - Table[r-1][c]) + Table[r-1][c];
|
1999-02-05 21:26:01 +00:00
|
|
|
|
2000-11-14 20:31:58 +00:00
|
|
|
Value = col1temp + cFactor*(col2temp - col1temp);
|
|
|
|
Value = (Value + bias)*gain;
|
|
|
|
SD = Value;
|
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
for (midx=0; midx < multipliers.size(); midx++) {
|
|
|
|
Value *= State->GetParameter(multipliers[midx]);
|
1999-02-05 21:26:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
float FGCoefficient::Value(float Val)
|
|
|
|
{
|
2000-10-02 23:07:30 +00:00
|
|
|
|
|
|
|
|
1999-02-05 21:26:01 +00:00
|
|
|
float Factor, Value;
|
2000-10-02 23:07:30 +00:00
|
|
|
int r;
|
|
|
|
unsigned midx;
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
if (rows < 2) return 0.0;
|
1999-06-21 05:01:31 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
for (r=1;r<=rows;r++) if (Table[r][0] >= Val) break;
|
1999-02-05 21:26:01 +00:00
|
|
|
r = r < 2 ? 2 : (r > rows ? rows : r);
|
|
|
|
|
|
|
|
// make sure denominator below does not go to zero.
|
2000-10-02 23:07:30 +00:00
|
|
|
if (Table[r][0] != Table[r-1][0]) {
|
|
|
|
Factor = (Val - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
|
1999-02-05 21:26:01 +00:00
|
|
|
} else {
|
|
|
|
Factor = 1.0;
|
|
|
|
}
|
1999-05-08 03:19:08 +00:00
|
|
|
|
2000-11-14 20:31:58 +00:00
|
|
|
Value = Factor*(Table[r][1] - Table[r-1][1]) + Table[r-1][1];
|
|
|
|
Value = (Value + bias)*gain;
|
|
|
|
SD = Value;
|
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
for (midx=0; midx < multipliers.size(); midx++) {
|
|
|
|
Value *= State->GetParameter(multipliers[midx]);
|
1999-02-05 21:26:01 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-02-05 21:26:01 +00:00
|
|
|
|
1999-05-08 03:19:08 +00:00
|
|
|
float FGCoefficient::Value(void)
|
|
|
|
{
|
|
|
|
float Value;
|
2000-10-02 23:07:30 +00:00
|
|
|
unsigned midx;
|
2000-04-24 23:49:06 +00:00
|
|
|
|
2000-11-14 20:31:58 +00:00
|
|
|
Value = StaticValue;
|
|
|
|
Value = (Value + bias)*gain;
|
|
|
|
SD = Value;
|
1999-05-08 03:19:08 +00:00
|
|
|
|
2000-10-02 23:07:30 +00:00
|
|
|
for (midx=0; midx < multipliers.size(); midx++) {
|
|
|
|
Value *= State->GetParameter(multipliers[midx]);
|
1999-05-08 03:19:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2000-04-24 23:49:06 +00:00
|
|
|
|
1999-05-08 03:19:08 +00:00
|
|
|
float FGCoefficient::TotalValue()
|
1999-02-05 21:26:01 +00:00
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
case 0:
|
|
|
|
return -1;
|
|
|
|
case 1:
|
1999-05-08 03:19:08 +00:00
|
|
|
return (Value());
|
1999-02-05 21:26:01 +00:00
|
|
|
case 2:
|
2000-04-24 23:49:06 +00:00
|
|
|
return (Value(State->GetParameter(LookupR)));
|
1999-02-05 21:26:01 +00:00
|
|
|
case 3:
|
2000-04-24 23:49:06 +00:00
|
|
|
return (Value(State->GetParameter(LookupR),State->GetParameter(LookupC)));
|
1999-02-05 21:26:01 +00:00
|
|
|
case 4:
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-12-30 18:01:59 +00:00
|
|
|
|
|
|
|
void FGCoefficient::DumpSD(void)
|
|
|
|
{
|
2000-04-24 23:49:06 +00:00
|
|
|
cout << " " << name << ": " << SD << endl;
|
1999-12-30 18:01:59 +00:00
|
|
|
}
|
2000-04-24 23:49:06 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2000-04-24 23:49:06 +00:00
|
|
|
|