ScatterDraw: Added more linear interpolation options

git-svn-id: svn://ultimatepp.org/upp/trunk@14845 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
koldo 2020-08-20 10:20:23 +00:00
parent f87ef11370
commit d475c6305d
7 changed files with 276 additions and 108 deletions

View file

@ -718,7 +718,7 @@ inline T LinearInterpolate(T x, T x0, T x1, T y0, T y1) {
if (abs(x1_0) < T(FLT_EPSILON))
return (y0 + y1)/T(2);
return ((x1 - x)/x1_0)*y0 + ((x - x0)/x1_0)*y1;
return y0 + (x - x0)*(y1 - y0)/x1_0;
}
template <class T>
@ -760,16 +760,63 @@ inline T TrilinearInterpolate(T x, T y, T z, T x0, T x1, T y0, T y1, T z0, T z1,
return LinearInterpolate(z, z0, z1, r0, r1);
}
template <class T>
T LinearInterpolate(const T x, const Point_<T> *vec, int len) {
ASSERT(len > 1);
if (x < vec[0].x)
return vec[0].y;
for (int i = 0; i < len-1; ++i) {
if (vec[i+1].x >= x && vec[i].x <= x)
return LinearInterpolate(x, vec[i].x, vec[i+1].x, vec[i].y, vec[i+1].y);
}
return vec[len-1].y;
}
template <class Range, class T>
T LinearInterpolate(const T x, const Range &vecx, const Range &vecy) {
ASSERT(vecx.GetCount() > 1 && vecy.GetCount() > 1);
T LinearInterpolate(const T x, const Range &vec) {
ASSERT(vec.GetCount() > 1);
return LinearInterpolate(x, (const T *)vec, vec.GetCount());
}
template <class T>
void GetInterpolatePos(const T x, const T *vecx, int len, int &x0, int &x1) {
if (x < vecx[0]) {
x0 = x1 = 0;
return;
}
for (int i = 0; i < len-1; ++i) {
if (vecx[i+1] >= x && vecx[i] <= x) {
x0 = i;
x1 = i+1;
return;
}
}
x0 = x1 = len-1;
}
template <class Range, class T>
void GetInterpolatePos(const T x, const Range &vecx, int &x0, int &x1) {
ASSERT(vecx.GetCount() > 1);
GetInterpolatePos(x, (const T *)vecx, vecx.GetCount(), x0, x1);
}
template <class T>
T LinearInterpolate(const T x, const T *vecx, const T *vecy, int len) {
ASSERT(len > 1);
if (x < vecx[0])
return vecy[0];
for (int i = 0; i < vecx.GetCount()-1; ++i) {
for (int i = 0; i < len-1; ++i) {
if (vecx[i+1] >= x && vecx[i] <= x)
return LinearInterpolate(x, vecx[i], vecx[i+1], vecy[i], vecy[i+1]);
}
return vecy[vecx.GetCount()-1];
return vecy[len-1];
}
template <class Range, class T>
T LinearInterpolate(const T x, const Range &vecx, const Range &vecy) {
ASSERT(vecx.GetCount() > 1);
ASSERT(vecx.GetCount() == vecy.GetCount());
return LinearInterpolate(x, (const T *)vecx, (const T *)vecy, vecx.GetCount());
}
class TableInterpolate {
@ -886,11 +933,8 @@ public:
private:
double *pdata;
//int lendata;
double *pxAxis;
//int lenxAxis;
double *pyAxis;
//int lenyAxis;
};

View file

@ -136,9 +136,9 @@ String FourierEquation::GetEquation(int numDigits) {
static inline double DegToRad(double deg) {return deg*M_PI/180.;}
static inline double RadToDeg(double rad) {return rad*180./M_PI;}
void EvalExpr::EvalThrowError(CParser &p, const char *s) {
CParser::Pos pos = p.GetPos();
CParser::Error err(Format("(%d): ", pos.GetColumn()) + s);
void EvalExpr::EvalThrowError(CParserPP &p, const char *s) {
CParserPP::Pos pos = p.GetPos();
CParserPP::Error err(Format("(%d): ", pos.GetColumn()) + s);
throw err;
}
@ -162,6 +162,11 @@ doubleUnit ufloor(doubleUnit val) {
return val;
}
doubleUnit uround(doubleUnit val) {
val.val = round(val.val);
return val;
}
doubleUnit usin(doubleUnit val) {
if (!val.unit.IsAdim())
return Null;
@ -263,6 +268,7 @@ doubleUnit ulog10(doubleUnit val) {
EvalExpr::EvalExpr() {
noCase = false;
errorIfUndefined = false;
allowString = false;
constants.Add("pi", doubleUnit(M_PI));
constants.Add("e", doubleUnit(M_E));
@ -270,6 +276,7 @@ EvalExpr::EvalExpr() {
functions.Add("abs", ufabs);
functions.Add("ceil", uceil);
functions.Add("floor", ufloor);
functions.Add("round", uround);
functions.Add("sqrt", usqrt);
functions.Add("sin", usin);
functions.Add("cos", ucos);
@ -287,10 +294,10 @@ EvalExpr::EvalExpr() {
functions.Add("radToDeg", uRadToDeg);
}
doubleUnit EvalExpr::Term(CParser& p) {
doubleUnit EvalExpr::Term(CParserPP& p) {
bool isneg = p.Char('-');
if (p.IsId()) {
String strId = p.ReadId();
String strId = p.ReadIdPP();
if(doubleUnit (*function)(doubleUnit) = functions.Get(strId, 0)) {
p.PassChar('(');
doubleUnit x = Exp(p);
@ -302,18 +309,21 @@ doubleUnit EvalExpr::Term(CParser& p) {
ret.Neg();
return ret;
}
String strsearch;
String strIdSearch;
if (noCase)
strsearch = ToLower(strId);
strIdSearch = ToLower(strId);
else
strsearch = strId;
doubleUnit ret = constants.Get(strsearch, Null);
strIdSearch = strId;
doubleUnit ret = constants.Get(strIdSearch, Null);
if (IsNull(ret)) {
ret = variables.Get(strsearch, Null);
if (IsNull(ret)) {
int id = FindVariable(strIdSearch);
if (id >= 0)
ret = variables[id];
else {
if (errorIfUndefined)
EvalThrowError(p, Format(t_("Unknown identifier '%s'"), strId));
ret = variables.GetAdd(strsearch, 0);
lastVariableSetId = variables.FindAdd(strIdSearch, 0);
ret = variables[lastVariableSetId];
}
}
if (isneg)
@ -333,7 +343,7 @@ doubleUnit EvalExpr::Term(CParser& p) {
}
}
doubleUnit EvalExpr::Pow(CParser& p) {
doubleUnit EvalExpr::Pow(CParserPP& p) {
doubleUnit x = Term(p);
for(;;) {
if(p.Char('^')) {
@ -345,7 +355,7 @@ doubleUnit EvalExpr::Pow(CParser& p) {
}
}
doubleUnit EvalExpr::Mul(CParser& p) {
doubleUnit EvalExpr::Mul(CParserPP& p) {
doubleUnit x = Pow(p);
for(;;) {
if(p.Char('*'))
@ -353,7 +363,7 @@ doubleUnit EvalExpr::Mul(CParser& p) {
else if (p.Char2('|', '|'))
x.ResParallel(Pow(p));
else if(memcmp(p.GetPtr(), "·", strlen("·")) == 0) {
CParser::Pos pos = p.GetPos();
CParserPP::Pos pos = p.GetPos();
pos.ptr += strlen("·");
p.SetPos(pos);
p.Spaces();
@ -361,7 +371,7 @@ doubleUnit EvalExpr::Mul(CParser& p) {
} else if(p.Char('/')) {
x.Div(Pow(p));
} else if(memcmp(p.GetPtr(), "º", strlen("º")) == 0) {
CParser::Pos pos = p.GetPos();
CParserPP::Pos pos = p.GetPos();
pos.ptr += strlen("º");
p.SetPos(pos);
p.Spaces();
@ -371,7 +381,7 @@ doubleUnit EvalExpr::Mul(CParser& p) {
}
}
doubleUnit EvalExpr::Exp(CParser& p) {
doubleUnit EvalExpr::Exp(CParserPP& p) {
doubleUnit x = Mul(p);
for(;;) {
if(p.Char('+'))
@ -386,29 +396,22 @@ doubleUnit EvalExpr::Exp(CParser& p) {
}
}
doubleUnit EvalExpr::Eval(String line) {
line = TrimBoth(line);
if (line.IsEmpty())
return Null;
p.Set(line);
doubleUnit EvalExpr::AssignVariable(String var, String expr) {
p.Set(expr);
if (noCase)
var = ToLower(var);
int idalloc = FindAddVariable(var);
try {
if(p.IsId()) {
CParser::Pos pos = p.GetPos();
String var = p.ReadId();
if(p.Char('=')) {
doubleUnit ret = Exp(p);
if (noCase)
var = ToLower(var);
SetVariable(var, ret);
return ret;
} else {
p.SetPos(pos);
return Exp(p);
}
} else
return Exp(p);
} catch(CParser::Error e) {
doubleUnit ret = Exp(p);
SetVariable(idalloc, ret);
return ret;
} catch(CParserPP::Error e) {
if (allowString) {
doubleUnit ret;
ret.sval = expr;
SetVariable(idalloc, ret);
return ret;
}
lastError = e;
return Null;
} catch(Exc e) {
@ -417,9 +420,56 @@ doubleUnit EvalExpr::Eval(String line) {
}
}
String EvalExpr::TermStr(CParser& p, int numDigits) {
doubleUnit EvalExpr::AssignVariable(String var, double d) {
if (noCase)
var = ToLower(var);
try {
doubleUnit ret(d);
SetVariable(var, ret);
return ret;
} catch(CParserPP::Error e) {
lastError = e;
return Null;
} catch(Exc e) {
lastError = e;
return Null;
}
}
doubleUnit EvalExpr::Eval(String line) {
line = TrimBoth(line);
if (line.IsEmpty())
return Null;
p.Set(line);
try {
if(p.IsId()) {
CParserPP::Pos pos = p.GetPos();
String var = p.ReadIdPP();
if(p.Char('=')) {
if (noCase)
var = ToLower(var);
doubleUnit ret = Exp(p);
SetVariable(var, ret);
return ret;
} else {
p.SetPos(pos);
return Exp(p);
}
} else
return Exp(p);
} catch(CParserPP::Error e) {
lastError = e;
return Null;
} catch(Exc e) {
lastError = e;
return Null;
}
}
String EvalExpr::TermStr(CParserPP& p, int numDigits) {
if(p.IsId()) {
String strId = p.ReadId();
String strId = p.ReadIdPP();
if(functions.Find(strId) >= 0) {
p.PassChar('(');
String x = ExpStr(p, numDigits);
@ -430,14 +480,14 @@ String EvalExpr::TermStr(CParser& p, int numDigits) {
strId = ToLower(strId);
if (IsNull(numDigits)) {
if (constants.Find(strId) < 0)
variables.GetAdd(strId, 0);
lastVariableSetId = variables.FindAdd(strId, 0);
return strId;
} else {
if (constants.Find(strId) >= 0)
return strId;
else {
double dat = variables.GetAdd(strId, 0).val;
return FormatDoubleFix(dat, numDigits);
lastVariableSetId = variables.FindAdd(strId, 0);
return FormatDoubleFix(variables[lastVariableSetId].val, numDigits);
}
}
}
@ -449,7 +499,7 @@ String EvalExpr::TermStr(CParser& p, int numDigits) {
return FormatDoubleFix(p.ReadDouble(), IsNull(numDigits) ? 3 : numDigits);
}
String EvalExpr::PowStr(CParser& p, int numDigits) {
String EvalExpr::PowStr(CParserPP& p, int numDigits) {
String x = TermStr(p, numDigits);
for(;;)
if(p.Char('^'))
@ -458,7 +508,7 @@ String EvalExpr::PowStr(CParser& p, int numDigits) {
return x;
}
String EvalExpr::MulStr(CParser& p, int numDigits) {
String EvalExpr::MulStr(CParserPP& p, int numDigits) {
String x = PowStr(p, numDigits);
for(;;)
if(p.Char('*'))
@ -469,7 +519,7 @@ String EvalExpr::MulStr(CParser& p, int numDigits) {
return x;
}
String EvalExpr::ExpStr(CParser& p, int numDigits) {
String EvalExpr::ExpStr(CParserPP& p, int numDigits) {
String x = MulStr(p, numDigits);
for(;;) {
if(p.Char('+'))
@ -490,14 +540,14 @@ String EvalExpr::EvalStr(String line, int numDigits) {
if (line.IsEmpty())
return Null;
CParser p(line);
CParserPP p(line);
try {
if(p.IsId()) {
CParser::Pos pos = p.GetPos();
String var = p.ReadId();
CParserPP::Pos pos = p.GetPos();
String var = p.ReadIdPP();
if(p.Char('=')) {
String ret = ExpStr(p, numDigits);
variables.GetAdd(var, 0);
lastVariableSetId = variables.FindAdd(var, 0);
return var + " = " + ret;
} else {
p.SetPos(pos);
@ -505,7 +555,7 @@ String EvalExpr::EvalStr(String line, int numDigits) {
}
} else
return ExpStr(p, numDigits);
} catch(CParser::Error e) {
} catch(CParserPP::Error e) {
lastError = Format(t_("Error evaluating '%s': %s"), line, e);
return Null;
} catch(Exc e) {

View file

@ -506,10 +506,11 @@ public:
class doubleUnit : public Moveable<doubleUnit> {
public:
doubleUnit() : doubleUnit(0) {}
doubleUnit(double _val) : val(_val), unit(0, 0, 0) {}
doubleUnit(double _val) : val(_val), sval(String::GetVoid()), unit(0, 0, 0) {}
doubleUnit(const Nuller&) {SetNull();}
double val;
String sval;
Unit unit;
void Sum(const doubleUnit &d) {
@ -563,15 +564,54 @@ public:
template<> inline bool IsNull(const doubleUnit& r) {return r.val < DOUBLE_NULL_LIM;}
class CParserPP : public CParser {
public:
CParserPP() : CParser() {}
CParserPP(const char *ptr) : CParser(ptr) {}
String ReadIdPP() {
if(!IsId())
ThrowError("missing id");
String result;
const char *b = term;
const char *p = b;
while (true) {
while (iscid(*p))
p++;
if ((*p) == '[') {
p++;
const char *p0 = p;
while ((*p) >= '0' && (*p) <= '9')
p++;
if (p0 == p)
ThrowError("empty vector index");
if ((*p) != ']')
ThrowError("wrong token found closing vector index");
else
p++;
} else if ((*p) == '.')
p++;
else
break;
}
term = p;
DoSpaces();
return String(b, (int)(uintptr_t)(p - b));
}
};
class EvalExpr {
public:
EvalExpr();
void Init() {variables.Clear();}
void Clear() {variables.Clear();}
doubleUnit Eval(String line);
doubleUnit AssignVariable(String var, String expr);
doubleUnit AssignVariable(String var, double d);
String EvalStr(String line, int numDigits = 3);
EvalExpr &SetCaseSensitivity(bool val = true) {noCase = !val; return *this;}
EvalExpr &SetErrorUndefined(bool val = true) {errorIfUndefined = val; return *this;}
EvalExpr &SetCaseSensitivity(bool val = true) {noCase = !val; return *this;}
EvalExpr &SetErrorUndefined(bool val = true) {errorIfUndefined = val; return *this;}
EvalExpr &SetAllowString(bool val = true) {allowString = val; return *this;}
const String &GetFunction(int id) {return functions.GetKey(id);}
int GetFunctionsCount() {return functions.GetCount();}
@ -583,9 +623,15 @@ public:
int GetConstantId(String &name) {return constants.Find(name);}
int GetConstantsCount() {return constants.GetCount();}
void SetVariable(String name, doubleUnit value) {variables.GetAdd(name) = value;}
void SetVariable(int id, doubleUnit value) {variables[id] = value;}
doubleUnit GetVariable(String name) {return variables.GetAdd(name);}
doubleUnit &GetVariable(String name) {
int id = FindVariable(name);
if (id >= 0)
return variables[id];
if (errorIfUndefined)
EvalThrowError(p, Format(t_("Unknown identifier '%s'"), name));
return variables.Add(name, Null);
}
doubleUnit &GetVariable(int id) {return variables[id];}
void GetVariable(int id, String &name, doubleUnit &val) {name = variables.GetKey(id); val = variables[id];}
int GetVariablesCount() {return variables.GetCount();}
void ClearVariables();
@ -594,31 +640,49 @@ public:
VectorMap<String, doubleUnit> constants;
VectorMap<String, doubleUnit (*)(doubleUnit)> functions;
CParser p;
CParserPP p;
static void EvalThrowError(CParser &p, const char *s);
static void EvalThrowError(CParserPP &p, const char *s);
virtual int FindVariable(String strId) {return variables.Find(strId);}
protected:
doubleUnit Exp(CParser& p);
doubleUnit Exp(CParserPP& p);
void SetVariable(String name, doubleUnit value) {
lastVariableSetId = variables.FindAdd(name);
variables[lastVariableSetId] = value;
}
void SetVariable(int id, doubleUnit value) {
lastVariableSetId = id;
variables[id] = value;
}
int FindAddVariable(String name) {
return lastVariableSetId = variables.FindAdd(name);
}
void RemoveVariable(int id) {
variables.Remove(id);
}
bool noCase;
String lastError;
VectorMap<String, doubleUnit> variables;
bool errorIfUndefined;
bool allowString;
int lastVariableSetId = -1;
bool IsFunction(String str) {return functions.Get(str, 0);}
bool IsConstant(String str) {return !IsNull(GetConstant(str));}
private:
void *Functions_Get(CParser& p);
doubleUnit Term(CParser& p);
doubleUnit Pow(CParser& p);
doubleUnit Mul(CParser& p);
void *Functions_Get(CParserPP& p);
doubleUnit Term(CParserPP& p);
doubleUnit Pow(CParserPP& p);
doubleUnit Mul(CParserPP& p);
String TermStr(CParser& p, int numDigits);
String PowStr(CParser& p, int numDigits);
String MulStr(CParser& p, int numDigits);
String ExpStr(CParser& p, int numDigits);
String TermStr(CParserPP& p, int numDigits);
String PowStr(CParserPP& p, int numDigits);
String MulStr(CParserPP& p, int numDigits);
String ExpStr(CParserPP& p, int numDigits);
};
class UserEquation : public ExplicitEquation {
@ -633,7 +697,7 @@ public:
if (parts.IsEmpty())
return;
strEquation = parts[0];
eval.Init();
eval.Clear();
eval.SetConstant(varHoriz, doubleUnit(23));
idx = eval.GetConstantsCount() - 1;
eval.EvalStr(strEquation);
@ -661,7 +725,7 @@ public:
double f(double x) {
eval.SetConstant(idx, doubleUnit(x));
for (int i = 0; i < coeff.GetCount(); ++i)
eval.SetVariable(varNames[i], coeff[i]);
eval.AssignVariable(varNames[i], coeff[i]);
return eval.Eval(strEquation).val;
}
void SetName(String _name) {name = _name;}

View file

@ -5,25 +5,26 @@ namespace Upp {
class MultiDimMatrixIndex {
public:
MultiDimMatrixIndex() {};
MultiDimMatrixIndex(int numAxis) {axisDim.SetCount(numAxis);};
MultiDimMatrixIndex() {};
template<typename... Args>
MultiDimMatrixIndex(Args... args) {SetAxis(args...);}
void SetNumAxis(int numAxis) {axisDim.SetCount(numAxis);};
void SetNumAxis(int numAxis) {axisDim.SetCount(numAxis);};
void SetAxisDim(int axis, int dim) {
ASSERT(axis >= 0 && axis < axisDim.GetCount() && dim > 0);
axisDim[axis] = dim;
}
void SetAxis1D(int dimX) {
void SetAxis(int dimX) {
ASSERT(dimX > 0);
axisDim.SetCount(1);
axisDim[0] = dimX;
axisDim << dimX;
}
void SetAxis2D(int dimX, int dimY) {
ASSERT(dimX > 0 && dimY > 0);
axisDim.SetCount(2);
axisDim[0] = dimX;
axisDim[1] = dimY;
template<typename... Args>
void SetAxis(int t, Args... args) {
ASSERT(t > 0);
axisDim << t;
SetAxis(args...);
}
Upp::Vector<int> &GetAxisDim() {return axisDim;};
int GetIndex(const Vector<int> &index) const {
ASSERT_(index[0] >= 0 && index[0] < axisDim[0], Format("index[0]=%d", index[0]));
@ -45,15 +46,25 @@ public:
return GetIndex(index);
}
inline int GetIndex(int x, int y) const {
template<typename... Args>
inline int operator()(Args... args) const {return GetIndex(args...);}
inline int GetIndex(int x, int y) const {
ASSERT(IsValid(x, y));
return x + axisDim[0]*y;
}
}
inline int operator()(int x, int y) const {return GetIndex(x, y);}
inline bool IsValid(int x, int y) const {
return x >= 0 && x < axisDim[0] && y >= 0 && y < axisDim[1];
}
inline int GetNumAxis() const {return axisDim.GetCount();}
int GetNumData() const {
int ret = 1;
for (auto dim : axisDim)
ret *= dim;
return ret;
}
void Xmlize(XmlIO xml) {
xml
("axisDim", axisDim)
@ -68,11 +79,11 @@ private:
Vector<int> axisDim;
template<typename T>
void AddIndex(Vector<int> &index, T t) {
static void AddIndex(Vector<int> &index, T t) {
index << t;
}
template<typename T, typename... Args>
void AddIndex(Vector<int> &index, T t, Args... args) {
static void AddIndex(Vector<int> &index, T t, Args... args) {
index << t;
AddIndex(index, args...);
}
@ -97,8 +108,8 @@ public:
virtual Histogram &operator=(const Histogram &hist);
void Clear();
Histogram &Create(DataSource &data, double min, double max, int numVals, bool isY);
Histogram &Create(Upp::Array<HistogramDataAxis> &dataAxis, bool isY);
Histogram &Create(DataSource &data, double min, double max, int numVals, bool isY = true);
Histogram &Create(Upp::Array<HistogramDataAxis> &dataAxis, bool isY = true);
Histogram &Create2D(const Vector<Vector<double> > &_ranges, const Vector<double> &data, double total);
Histogram &Normalize(double val = 1);
@ -109,7 +120,7 @@ public:
inline const double &GetRange(int dim, int i) {return ranges[dim][i];};
inline int64 GetCount(int dim) const {return ranges[dim].GetCount();}
inline double GetValue(int index) {return y(index);}
inline double GetValue(int c, int r) {return y(valuesIdx.GetIndex(c, r));}
inline double GetValue(int c, int r) {return y(valuesIdx(c, r));}
inline bool IsValid(int c, int r) {return valuesIdx.IsValid(c, r);}
inline double y(int64 id) {

View file

@ -6,7 +6,7 @@
T_("No mark")
caES("Sense marca")
esES("Sin marca")
euES("Marka gabe")D
euES("Marka gabe")
frFR("Sans marque")

View file

@ -51,7 +51,6 @@ It will be converted private soon.&]
[s4;%- &]
[s5;:EvalExpr`:`:variables:%- [_^VectorMap^ VectorMap]<[_^String^ String],
[@(0.0.255) double]>_[* variables]&]
[s2; [%-* variables] VectorMap includes all variables. It will be
converted private soon.&]
[s2; [%-* variables] VectorMap includes all variables.&]
[s3;%- &]
[s3; ]]

View file

@ -1,7 +1,7 @@
TITLE("3.2 EvalExpr")
COMPRESSED
120,156,173,84,239,111,219,54,16,253,87,14,93,51,216,157,227,240,135,100,201,210,58,4,88,210,110,232,218,13,43,182,47,130,18,209,22,147,16,163,41,67,148,220,4,105,254,247,30,37,89,150,59,103,201,134,249,131,69,29,239,158,238,221,123,100,162,60,47,140,5,243,227,191,222,253,58,143,225,229,75,58,33,223,240,128,242,208,231,212,99,51,252,163,156,50,159,113,143,134,108,238,133,156,135,36,178,85,89,47,43,85,201,85,154,104,22,134,49,195,74,134,149,44,240,25,13,188,208,11,41,15,66,134,0,140,16,70,2,230,83,143,135,204,143,114,105,151,105,66,48,157,99,250,124,198,231,132,18,18,80,74,56,11,8,247,61,74,57,67,8,22,48,74,252,72,154,60,77,126,154,197,174,192,195,2,226,207,8,33,51,68,243,60,130,232,174,204,227,148,19,198,125,58,247,103,209,66,94,43,147,38,251,180,92,119,254,147,188,2,18,45,139,92,182,172,176,130,184,239,61,241,139,206,228,149,168,117,149,38,247,151,15,71,231,31,142,255,248,8,9,220,223,83,183,121,
202,33,177,36,134,228,213,233,136,177,249,216,131,243,141,208,231,183,235,50,77,31,30,190,77,19,203,99,112,15,26,71,219,157,44,202,162,165,22,214,70,71,199,144,156,142,200,148,76,153,239,143,161,9,166,151,201,171,29,136,43,101,45,2,137,93,58,131,159,43,80,171,181,150,43,105,42,11,2,108,243,6,18,211,165,181,170,48,32,177,186,22,85,81,130,50,75,93,231,202,92,195,70,148,74,44,48,239,70,152,92,99,100,154,182,221,33,40,46,182,124,222,140,40,11,199,111,155,255,83,186,229,6,63,22,166,245,3,98,158,201,74,40,189,165,71,58,0,235,239,19,236,215,163,108,220,240,28,144,26,141,59,90,219,8,44,119,248,211,97,91,207,236,143,193,111,245,66,171,37,188,151,171,133,44,225,23,101,171,231,52,152,141,62,86,37,206,162,107,113,32,69,94,32,160,236,181,72,71,201,229,69,155,123,1,237,211,237,161,250,56,74,153,14,249,88,72,142,142,251,157,161,44,181,117,66,228,18,101,46,101,222,114,22,141,134,38,239,245,177,240,73,85,55,128,69,
27,85,212,86,223,1,122,66,93,27,233,82,116,141,251,165,172,234,210,56,40,83,175,100,169,150,66,99,204,162,67,167,131,54,70,104,39,97,96,33,241,161,53,86,11,11,43,97,238,160,82,43,4,193,55,35,101,46,243,109,205,27,84,86,222,10,103,165,168,13,105,119,190,118,18,57,34,241,112,167,29,145,251,52,133,236,117,179,63,109,190,156,189,184,117,1,150,189,24,199,199,159,143,63,159,156,192,239,77,207,22,216,97,0,246,53,0,227,144,125,7,183,217,69,7,50,132,8,14,99,240,175,49,238,154,38,90,28,4,57,217,67,241,6,71,211,251,7,135,160,214,189,73,38,202,84,157,83,14,153,1,186,252,39,188,50,217,243,25,66,118,155,40,230,153,186,86,21,94,0,217,235,203,4,35,252,191,249,106,231,164,199,77,52,117,183,72,217,205,2,109,50,64,59,112,101,116,198,107,140,217,53,177,235,214,45,221,153,43,174,32,111,34,136,125,117,32,77,89,248,80,107,61,217,115,186,214,96,138,202,185,180,148,107,45,150,216,224,226,14,48,127,224,237,230,235,
207,144,171,63,79,157,66,127,74,119,157,188,23,235,11,232,151,233,247,127,215,102,114,232,224,255,224,4,237,17,183,215,176,99,53,136,238,112,187,169,185,131,133,148,250,12,28,5,174,164,200,221,116,154,241,245,228,39,80,221,116,147,117,155,162,47,114,131,114,51,177,55,197,39,211,22,117,198,26,141,27,217,218,177,185,131,93,152,141,44,43,156,217,186,84,27,81,73,176,69,97,246,239,207,199,134,213,247,241,191,13,171,71,220,27,214,46,250,216,176,250,140,127,79,14,13,145,166,95,0,14,184,204,232,
120,156,173,84,219,110,227,54,16,253,149,193,118,83,216,91,199,225,69,178,100,169,91,4,104,178,109,209,238,5,93,180,47,130,18,209,22,147,16,165,41,67,148,188,9,178,249,247,14,37,89,150,83,167,9,138,250,193,162,134,51,71,51,231,28,50,81,158,23,198,130,249,241,95,191,126,156,199,240,250,53,157,144,111,120,64,121,232,115,234,177,25,254,81,78,153,207,184,71,67,54,247,66,206,67,18,217,170,172,151,149,170,228,42,77,52,11,195,152,97,37,195,74,22,248,140,6,94,232,133,148,7,33,67,0,70,8,35,1,243,169,199,67,230,71,185,180,203,52,33,152,206,49,125,62,227,115,66,9,9,40,37,156,5,132,251,30,165,156,33,4,11,24,37,126,36,77,158,38,63,207,98,87,224,97,1,241,103,132,144,25,162,121,30,65,116,87,230,113,202,9,227,62,157,251,179,104,33,175,149,73,147,253,177,92,119,254,179,115,5,36,90,22,185,108,167,194,10,226,190,247,204,47,58,147,87,162,214,85,154,220,95,62,28,157,127,56,254,227,51,36,112,127,79,221,230,
41,135,196,146,24,146,55,167,35,198,230,99,15,206,55,66,159,223,174,203,52,125,120,248,54,77,44,143,193,61,104,28,109,119,178,40,139,150,90,88,27,29,29,67,114,58,34,83,50,101,190,63,134,38,152,94,38,111,118,32,174,148,181,8,36,118,233,12,126,169,64,173,214,90,174,164,169,44,8,176,205,27,72,76,151,214,170,194,128,196,234,90,84,69,9,202,44,117,157,43,115,13,27,81,42,177,192,188,27,97,114,141,145,105,218,118,135,160,184,216,206,243,110,68,89,56,254,169,249,63,165,219,217,224,199,194,180,126,64,204,51,89,9,165,183,227,145,14,192,250,251,3,246,235,81,54,110,230,28,12,53,26,119,99,109,35,176,220,225,79,135,109,189,176,63,6,159,234,133,86,75,120,47,87,11,89,194,111,202,86,47,105,48,27,125,174,74,228,162,107,113,32,69,94,32,160,236,181,72,71,201,229,69,155,123,1,237,211,237,161,250,72,165,76,135,243,88,72,142,142,251,157,161,44,181,117,66,228,18,101,46,101,222,206,44,26,13,77,222,235,99,225,139,170,110,0,
139,54,170,168,173,190,3,244,132,186,54,210,165,232,26,247,75,89,213,165,113,80,166,94,201,82,45,133,198,152,69,135,78,7,109,140,208,78,194,192,66,226,67,107,172,22,22,86,194,220,65,165,86,8,130,111,70,202,92,230,219,154,119,168,172,188,21,206,74,81,27,210,238,124,237,36,114,131,196,195,157,150,34,247,105,10,217,219,102,127,218,124,57,123,117,235,2,44,123,53,142,143,191,30,127,61,57,129,223,155,158,45,176,195,0,236,49,0,227,144,125,7,183,217,69,7,50,132,8,14,99,240,199,24,119,77,19,45,14,130,156,236,161,120,131,163,233,253,139,67,80,235,222,36,19,101,170,206,41,135,204,0,93,254,51,94,153,236,249,12,33,187,77,20,243,76,93,171,10,47,128,236,237,101,130,17,254,223,124,181,115,210,211,38,154,186,91,164,236,184,64,155,12,208,14,92,25,157,241,26,99,118,77,236,186,117,75,119,230,138,43,200,155,8,98,95,29,72,83,22,62,212,90,79,246,156,174,53,152,162,114,46,45,229,90,139,37,54,184,184,3,204,31,120,187,249,
250,11,228,234,207,83,167,208,159,210,93,39,239,197,250,2,250,101,250,253,63,181,153,28,58,248,63,56,65,123,196,237,53,236,166,26,68,119,184,29,107,238,96,225,72,125,6,82,129,43,41,114,199,78,67,95,63,252,4,170,155,142,89,183,41,250,34,71,148,227,196,222,20,95,76,91,212,25,107,52,110,100,107,105,115,7,187,48,27,89,86,200,217,186,84,27,81,73,176,69,97,246,239,207,167,200,234,251,248,223,200,234,17,247,200,218,69,159,34,171,207,120,124,241,67,154,254,13,237,125,192,26,