diff --git a/uppsrc/ScatterDraw/DataSource.h b/uppsrc/ScatterDraw/DataSource.h index 11228ac14..d61965307 100644 --- a/uppsrc/ScatterDraw/DataSource.h +++ b/uppsrc/ScatterDraw/DataSource.h @@ -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 @@ -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 +T LinearInterpolate(const T x, const Point_ *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 -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 +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 +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 +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 +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; }; diff --git a/uppsrc/ScatterDraw/Equation.cpp b/uppsrc/ScatterDraw/Equation.cpp index 098dc8a71..38e9f69c9 100644 --- a/uppsrc/ScatterDraw/Equation.cpp +++ b/uppsrc/ScatterDraw/Equation.cpp @@ -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) { diff --git a/uppsrc/ScatterDraw/Equation.h b/uppsrc/ScatterDraw/Equation.h index e854bdc60..9ee20b3ff 100644 --- a/uppsrc/ScatterDraw/Equation.h +++ b/uppsrc/ScatterDraw/Equation.h @@ -506,10 +506,11 @@ public: class doubleUnit : public Moveable { 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 constants; VectorMap 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 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;} diff --git a/uppsrc/ScatterDraw/Histogram.h b/uppsrc/ScatterDraw/Histogram.h index 995576bc0..fe3bd74bc 100644 --- a/uppsrc/ScatterDraw/Histogram.h +++ b/uppsrc/ScatterDraw/Histogram.h @@ -5,25 +5,26 @@ namespace Upp { class MultiDimMatrixIndex { public: - MultiDimMatrixIndex() {}; - MultiDimMatrixIndex(int numAxis) {axisDim.SetCount(numAxis);}; + MultiDimMatrixIndex() {}; + template + 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 + void SetAxis(int t, Args... args) { + ASSERT(t > 0); + axisDim << t; + SetAxis(args...); } + Upp::Vector &GetAxisDim() {return axisDim;}; int GetIndex(const Vector &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 + 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 axisDim; template - void AddIndex(Vector &index, T t) { + static void AddIndex(Vector &index, T t) { index << t; } template - void AddIndex(Vector &index, T t, Args... args) { + static void AddIndex(Vector &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 &dataAxis, bool isY); + Histogram &Create(DataSource &data, double min, double max, int numVals, bool isY = true); + Histogram &Create(Upp::Array &dataAxis, bool isY = true); Histogram &Create2D(const Vector > &_ranges, const Vector &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) { diff --git a/uppsrc/ScatterDraw/ScatterDraw.t b/uppsrc/ScatterDraw/ScatterDraw.t index e47fb9538..13d9bec23 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.t +++ b/uppsrc/ScatterDraw/ScatterDraw.t @@ -6,7 +6,7 @@ T_("No mark") caES("Sense marca") esES("Sin marca") -euES("Marka gabe")D +euES("Marka gabe") frFR("Sans marque") diff --git a/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tpp b/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tpp index 8e05f35f7..1da830b60 100644 --- a/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tpp +++ b/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tpp @@ -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; ]] \ No newline at end of file diff --git a/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tppi b/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tppi index d65b55ef3..1aff7fd7b 100644 --- a/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tppi +++ b/uppsrc/ScatterDraw/src.tpp/EvalExpr_en-us.tppi @@ -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,