euler314 commited on
Commit
f22203e
·
verified ·
1 Parent(s): 3940b3d

Update app.cpp

Browse files
Files changed (1) hide show
  1. app.cpp +84 -277
app.cpp CHANGED
@@ -1,4 +1,4 @@
1
- // app.cpp - Modified version for Hugging Face Spaces
2
  #include <opencv2/opencv.hpp>
3
  #include <algorithm>
4
  #include <cmath>
@@ -10,6 +10,7 @@
10
  #include <limits>
11
  #include <sstream>
12
  #include <string>
 
13
 
14
  // Function to compute the theoretical max value
15
  double compute_theoretical_max(double a, double y, double beta) {
@@ -56,7 +57,7 @@ double compute_theoretical_max(double a, double y, double beta) {
56
  }
57
 
58
  // Multiply the result by y before returning
59
- return f((a_gs + b_gs) / 2.0) *y ;
60
  }
61
 
62
  // Function to compute the theoretical min value
@@ -107,13 +108,77 @@ double compute_theoretical_min(double a, double y, double beta) {
107
  }
108
 
109
  // Multiply the result by y before returning
110
- return f((a_gs + b_gs) / 2.0) *y ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
  int main(int argc, char* argv[]) {
114
  // ─── Inputs from command line ───────────────────────────────────────────
115
- if (argc != 6) {
116
- std::cerr << "Usage: " << argv[0] << " <n> <p> <a> <y> <output_file>" << std::endl;
117
  return 1;
118
  }
119
 
@@ -121,15 +186,16 @@ int main(int argc, char* argv[]) {
121
  int p = std::stoi(argv[2]);
122
  double a = std::stod(argv[3]);
123
  double y = std::stod(argv[4]);
124
- std::string output_file = argv[5];
 
125
  const double b = 1.0;
126
 
127
  std::cout << "Running with parameters: n = " << n << ", p = " << p
128
- << ", a = " << a << ", y = " << y << std::endl;
129
  std::cout << "Output will be saved to: " << output_file << std::endl;
130
 
131
  // ─── Beta range parameters ────────────────────────────────────────
132
- const int num_beta_points = 100; // More points for smoother curves
133
  std::vector<double> beta_values(num_beta_points);
134
  for (int i = 0; i < num_beta_points; ++i) {
135
  beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
@@ -183,281 +249,22 @@ int main(int argc, char* argv[]) {
183
  max_eigenvalues[beta_idx] = *std::max_element(eigs.begin(), eigs.end());
184
  min_eigenvalues[beta_idx] = *std::min_element(eigs.begin(), eigs.end());
185
 
186
- // Progress indicator - modified to be less verbose for Streamlit
187
- if (beta_idx % 20 == 0) {
 
 
 
 
188
  std::cout << "Processing beta = " << beta
189
  << " (" << beta_idx+1 << "/" << num_beta_points << ")" << std::endl;
190
  }
191
  }
192
 
193
- // ─── Prepare canvas for plotting ────────────────────────────────
194
- const int H = 950, W = 1200; // Taller canvas to accommodate legend below
195
- cv::Mat canvas(H, W, CV_8UC3, cv::Scalar(250, 250, 250)); // Slightly off-white background
196
-
197
- // ─── Find min/max for scaling ───────────────────────────────────
198
- double min_y = std::numeric_limits<double>::max();
199
- double max_y = std::numeric_limits<double>::lowest();
200
-
201
- for (double v : max_eigenvalues) max_y = std::max(max_y, v);
202
- for (double v : min_eigenvalues) min_y = std::min(min_y, v);
203
- for (double v : theoretical_max_values) max_y = std::max(max_y, v);
204
- for (double v : theoretical_min_values) min_y = std::min(min_y, v);
205
-
206
- // Add some padding
207
- double y_padding = (max_y - min_y) * 0.15; // More padding for better spacing
208
- min_y -= y_padding;
209
- max_y += y_padding;
210
-
211
- // ─── Draw coordinate axes ───────────────────────────────────────
212
- const int margin = 100; // Larger margin for better spacing
213
- const int plot_width = W - 2 * margin;
214
- const int plot_height = H - 2 * margin - 150; // Reduced height to make room for legend below
215
-
216
- // Plot area background (light gray)
217
- cv::rectangle(canvas,
218
- cv::Point(margin, margin),
219
- cv::Point(W - margin, margin + plot_height),
220
- cv::Scalar(245, 245, 245), cv::FILLED);
221
-
222
- // X-axis (beta)
223
- cv::line(canvas,
224
- cv::Point(margin, margin + plot_height),
225
- cv::Point(W - margin, margin + plot_height),
226
- cv::Scalar(40, 40, 40), 2);
227
-
228
- // Y-axis (eigenvalues)
229
- cv::line(canvas,
230
- cv::Point(margin, margin + plot_height),
231
- cv::Point(margin, margin),
232
- cv::Scalar(40, 40, 40), 2);
233
-
234
- // ─── Draw axes labels ────────────────────────────────────────────
235
- cv::putText(canvas, "β",
236
- cv::Point(W - margin/2, margin + plot_height + 30),
237
- cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(0, 0, 0), 2);
238
-
239
- // Y-axis label (fixed - no rotation)
240
- cv::putText(canvas, "Eigenvalues",
241
- cv::Point(margin/4, margin/2 - 10),
242
- cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(0, 0, 0), 2);
243
-
244
- // ─── Draw title ───────────────────────────────────────────────────
245
- std::stringstream title_ss;
246
- title_ss << std::fixed << std::setprecision(2);
247
- title_ss << "Eigenvalue Analysis: a = " << a << ", y = " << y;
248
- cv::putText(canvas, title_ss.str(),
249
- cv::Point(W/2 - 200, 45),
250
- cv::FONT_HERSHEY_COMPLEX, 1.2, cv::Scalar(0, 0, 0), 2);
251
-
252
- // ─── Draw grid lines ────────────────────────────────────────────────
253
- const int num_grid_lines = 11; // 0.0, 0.1, 0.2, ..., 1.0 for beta
254
- for (int i = 0; i < num_grid_lines; ++i) {
255
- // Horizontal grid lines
256
- int y_pos = margin + i * (plot_height / (num_grid_lines - 1));
257
- cv::line(canvas,
258
- cv::Point(margin, y_pos),
259
- cv::Point(W - margin, y_pos),
260
- cv::Scalar(220, 220, 220), 1);
261
-
262
- // Vertical grid lines
263
- int x_pos = margin + i * (plot_width / (num_grid_lines - 1));
264
- cv::line(canvas,
265
- cv::Point(x_pos, margin),
266
- cv::Point(x_pos, margin + plot_height),
267
- cv::Scalar(220, 220, 220), 1);
268
-
269
- // X-axis labels (beta values)
270
- double beta_val = static_cast<double>(i) / (num_grid_lines - 1);
271
- std::stringstream ss;
272
- ss << std::fixed << std::setprecision(1) << beta_val;
273
- cv::putText(canvas, ss.str(),
274
- cv::Point(x_pos - 10, margin + plot_height + 30),
275
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
276
-
277
- // Y-axis labels (eigenvalue values)
278
- double eig_val = min_y + (max_y - min_y) * i / (num_grid_lines - 1);
279
- std::stringstream ss2;
280
- ss2 << std::fixed << std::setprecision(2) << eig_val;
281
- cv::putText(canvas, ss2.str(),
282
- cv::Point(margin/2 - 40, margin + plot_height - i * (plot_height / (num_grid_lines - 1)) + 5),
283
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
284
- }
285
-
286
- // ─── Draw the four curves ───────────────────────────────────────────
287
- // Convert data points to pixel coordinates
288
- auto to_point = [&](double beta, double val) -> cv::Point {
289
- int x = margin + static_cast<int>(beta * plot_width);
290
- int y = margin + plot_height - static_cast<int>((val - min_y) / (max_y - min_y) * plot_height);
291
- return cv::Point(x, y);
292
- };
293
-
294
- // Better colors for visibility
295
- cv::Scalar emp_max_color(60, 60, 220); // Dark red
296
- cv::Scalar emp_min_color(220, 60, 60); // Dark blue
297
- cv::Scalar theo_max_color(30, 180, 30); // Dark green
298
- cv::Scalar theo_min_color(180, 30, 180); // Dark purple
299
-
300
- // Empirical max eigenvalues (red)
301
- std::vector<cv::Point> max_eig_points;
302
- for (int i = 0; i < num_beta_points; ++i) {
303
- max_eig_points.push_back(to_point(beta_values[i], max_eigenvalues[i]));
304
- }
305
- cv::polylines(canvas, max_eig_points, false, emp_max_color, 3);
306
-
307
- // Empirical min eigenvalues (blue)
308
- std::vector<cv::Point> min_eig_points;
309
- for (int i = 0; i < num_beta_points; ++i) {
310
- min_eig_points.push_back(to_point(beta_values[i], min_eigenvalues[i]));
311
- }
312
- cv::polylines(canvas, min_eig_points, false, emp_min_color, 3);
313
-
314
- // Theoretical max values (green)
315
- std::vector<cv::Point> theo_max_points;
316
- for (int i = 0; i < num_beta_points; ++i) {
317
- theo_max_points.push_back(to_point(beta_values[i], theoretical_max_values[i]));
318
- }
319
- cv::polylines(canvas, theo_max_points, false, theo_max_color, 3);
320
-
321
- // Theoretical min values (purple)
322
- std::vector<cv::Point> theo_min_points;
323
- for (int i = 0; i < num_beta_points; ++i) {
324
- theo_min_points.push_back(to_point(beta_values[i], theoretical_min_values[i]));
325
- }
326
- cv::polylines(canvas, theo_min_points, false, theo_min_color, 3);
327
-
328
- // ─── Draw markers on the curves for better visibility ──────────────
329
- const int marker_interval = 10; // Show markers every 10 points
330
- for (int i = 0; i < num_beta_points; i += marker_interval) {
331
- // Max empirical eigenvalue markers
332
- cv::circle(canvas, max_eig_points[i], 5, emp_max_color, cv::FILLED);
333
- cv::circle(canvas, max_eig_points[i], 5, cv::Scalar(255, 255, 255), 1);
334
-
335
- // Min empirical eigenvalue markers
336
- cv::circle(canvas, min_eig_points[i], 5, emp_min_color, cv::FILLED);
337
- cv::circle(canvas, min_eig_points[i], 5, cv::Scalar(255, 255, 255), 1);
338
-
339
- // Theoretical max markers
340
- cv::drawMarker(canvas, theo_max_points[i], theo_max_color, cv::MARKER_DIAMOND, 10, 2);
341
-
342
- // Theoretical min markers
343
- cv::drawMarker(canvas, theo_min_points[i], theo_min_color, cv::MARKER_DIAMOND, 10, 2);
344
- }
345
 
346
- // ─── Draw legend BELOW the graph ────────────────────────────────────
347
- // Set up dimensions for the legend
348
- const int legend_width = 600;
349
- const int legend_height = 100;
350
- // Center the legend horizontally
351
- const int legend_x = W/2 - legend_width/2;
352
- // Position legend below the graph
353
- const int legend_y = margin + plot_height + 70;
354
- const int line_length = 40;
355
- const int line_spacing = 35;
356
-
357
- // Box around legend with shadow effect
358
- cv::rectangle(canvas,
359
- cv::Point(legend_x + 3, legend_y + 3),
360
- cv::Point(legend_x + legend_width + 3, legend_y + legend_height + 3),
361
- cv::Scalar(180, 180, 180), cv::FILLED); // Shadow
362
- cv::rectangle(canvas,
363
- cv::Point(legend_x, legend_y),
364
- cv::Point(legend_x + legend_width, legend_y + legend_height),
365
- cv::Scalar(240, 240, 240), cv::FILLED); // Main box
366
- cv::rectangle(canvas,
367
- cv::Point(legend_x, legend_y),
368
- cv::Point(legend_x + legend_width, legend_y + legend_height),
369
- cv::Scalar(0, 0, 0), 1); // Border
370
-
371
- // Legend title
372
- cv::putText(canvas, "Legend",
373
- cv::Point(legend_x + legend_width/2 - 30, legend_y + 20),
374
- cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 0, 0), 1);
375
- cv::line(canvas,
376
- cv::Point(legend_x + 5, legend_y + 30),
377
- cv::Point(legend_x + legend_width - 5, legend_y + 30),
378
- cv::Scalar(150, 150, 150), 1);
379
-
380
- // Two legend entries per row, in two columns
381
- // First row
382
- // Empirical max (red)
383
- cv::line(canvas,
384
- cv::Point(legend_x + 20, legend_y + 50),
385
- cv::Point(legend_x + 20 + line_length, legend_y + 50),
386
- emp_max_color, 3);
387
- cv::circle(canvas, cv::Point(legend_x + 20 + line_length/2, legend_y + 50), 5, emp_max_color, cv::FILLED);
388
- cv::putText(canvas, "Empirical Max Eigenvalue",
389
- cv::Point(legend_x + 20 + line_length + 10, legend_y + 50 + 5),
390
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
391
-
392
- // Empirical min (blue)
393
- cv::line(canvas,
394
- cv::Point(legend_x + 20 + legend_width/2, legend_y + 50),
395
- cv::Point(legend_x + 20 + line_length + legend_width/2, legend_y + 50),
396
- emp_min_color, 3);
397
- cv::circle(canvas, cv::Point(legend_x + 20 + line_length/2 + legend_width/2, legend_y + 50), 5, emp_min_color, cv::FILLED);
398
- cv::putText(canvas, "Empirical Min Eigenvalue",
399
- cv::Point(legend_x + 20 + line_length + 10 + legend_width/2, legend_y + 50 + 5),
400
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
401
-
402
- // Second row
403
- // Theoretical max (green)
404
- cv::line(canvas,
405
- cv::Point(legend_x + 20, legend_y + 80),
406
- cv::Point(legend_x + 20 + line_length, legend_y + 80),
407
- theo_max_color, 3);
408
- cv::drawMarker(canvas, cv::Point(legend_x + 20 + line_length/2, legend_y + 80),
409
- theo_max_color, cv::MARKER_DIAMOND, 10, 2);
410
- cv::putText(canvas, "Theoretical Max Function",
411
- cv::Point(legend_x + 20 + line_length + 10, legend_y + 80 + 5),
412
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
413
-
414
- // Theoretical min (purple)
415
- cv::line(canvas,
416
- cv::Point(legend_x + 20 + legend_width/2, legend_y + 80),
417
- cv::Point(legend_x + 20 + line_length + legend_width/2, legend_y + 80),
418
- theo_min_color, 3);
419
- cv::drawMarker(canvas, cv::Point(legend_x + 20 + line_length/2 + legend_width/2, legend_y + 80),
420
- theo_min_color, cv::MARKER_DIAMOND, 10, 2);
421
- cv::putText(canvas, "Theoretical Min Function",
422
- cv::Point(legend_x + 20 + line_length + 10 + legend_width/2, legend_y + 80 + 5),
423
- cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 1);
424
-
425
- // ─── Draw mathematical formulas in a box ──────────────────────────────
426
- cv::rectangle(canvas,
427
- cv::Point(margin + 3, H - 80 + 3),
428
- cv::Point(W - margin + 3, H - 20 + 3),
429
- cv::Scalar(180, 180, 180), cv::FILLED); // Shadow
430
- cv::rectangle(canvas,
431
- cv::Point(margin, H - 80),
432
- cv::Point(W - margin, H - 20),
433
- cv::Scalar(240, 240, 240), cv::FILLED); // Main box
434
- cv::rectangle(canvas,
435
- cv::Point(margin, H - 80),
436
- cv::Point(W - margin, H - 20),
437
- cv::Scalar(0, 0, 0), 1); // Border
438
-
439
- std::string formula_text1 = "Max Function: max{k ∈ (0,∞)} [yβ(a-1)k + (ak+1)((y-1)k-1)]/[(ak+1)(k²+k)y]";
440
- std::string formula_text2 = "Min Function: min{t ∈ (-1/a,0)} [yβ(a-1)t + (at+1)((y-1)t-1)]/[(at+1)(t²+t)y]";
441
-
442
- cv::putText(canvas, formula_text1,
443
- cv::Point(margin + 20, H - 55),
444
- cv::FONT_HERSHEY_SIMPLEX, 0.6, theo_max_color, 2);
445
-
446
- cv::putText(canvas, formula_text2,
447
- cv::Point(W/2 + 20, H - 55),
448
- cv::FONT_HERSHEY_SIMPLEX, 0.6, theo_min_color, 2);
449
-
450
- // ─── Draw parameter info ────────────────────────────────────────────
451
- std::stringstream params_ss;
452
- params_ss << std::fixed << std::setprecision(2);
453
- params_ss << "Parameters: n = " << n << ", p = " << p << ", a = " << a << ", y = " << y;
454
- cv::putText(canvas, params_ss.str(),
455
- cv::Point(margin, 80),
456
- cv::FONT_HERSHEY_COMPLEX, 0.8, cv::Scalar(0, 0, 0), 1);
457
-
458
- // ─── Save the image to the output directory ───────────────────────────
459
- cv::imwrite(output_file, canvas);
460
- std::cout << "Plot saved as " << output_file << std::endl;
461
 
462
  return 0;
463
  }
 
1
+ // app.cpp - Modified version for Hugging Face Spaces (calculation only)
2
  #include <opencv2/opencv.hpp>
3
  #include <algorithm>
4
  #include <cmath>
 
10
  #include <limits>
11
  #include <sstream>
12
  #include <string>
13
+ #include <fstream>
14
 
15
  // Function to compute the theoretical max value
16
  double compute_theoretical_max(double a, double y, double beta) {
 
57
  }
58
 
59
  // Multiply the result by y before returning
60
+ return f((a_gs + b_gs) / 2.0) * y;
61
  }
62
 
63
  // Function to compute the theoretical min value
 
108
  }
109
 
110
  // Multiply the result by y before returning
111
+ return f((a_gs + b_gs) / 2.0) * y;
112
+ }
113
+
114
+ // Function to save data as JSON
115
+ void save_as_json(const std::string& filename,
116
+ const std::vector<double>& beta_values,
117
+ const std::vector<double>& max_eigenvalues,
118
+ const std::vector<double>& min_eigenvalues,
119
+ const std::vector<double>& theoretical_max_values,
120
+ const std::vector<double>& theoretical_min_values) {
121
+
122
+ std::ofstream outfile(filename);
123
+
124
+ if (!outfile.is_open()) {
125
+ std::cerr << "Error: Could not open file " << filename << " for writing." << std::endl;
126
+ return;
127
+ }
128
+
129
+ // Start JSON object
130
+ outfile << "{\n";
131
+
132
+ // Write beta values
133
+ outfile << " \"beta_values\": [";
134
+ for (size_t i = 0; i < beta_values.size(); ++i) {
135
+ outfile << beta_values[i];
136
+ if (i < beta_values.size() - 1) outfile << ", ";
137
+ }
138
+ outfile << "],\n";
139
+
140
+ // Write max eigenvalues
141
+ outfile << " \"max_eigenvalues\": [";
142
+ for (size_t i = 0; i < max_eigenvalues.size(); ++i) {
143
+ outfile << max_eigenvalues[i];
144
+ if (i < max_eigenvalues.size() - 1) outfile << ", ";
145
+ }
146
+ outfile << "],\n";
147
+
148
+ // Write min eigenvalues
149
+ outfile << " \"min_eigenvalues\": [";
150
+ for (size_t i = 0; i < min_eigenvalues.size(); ++i) {
151
+ outfile << min_eigenvalues[i];
152
+ if (i < min_eigenvalues.size() - 1) outfile << ", ";
153
+ }
154
+ outfile << "],\n";
155
+
156
+ // Write theoretical max values
157
+ outfile << " \"theoretical_max\": [";
158
+ for (size_t i = 0; i < theoretical_max_values.size(); ++i) {
159
+ outfile << theoretical_max_values[i];
160
+ if (i < theoretical_max_values.size() - 1) outfile << ", ";
161
+ }
162
+ outfile << "],\n";
163
+
164
+ // Write theoretical min values
165
+ outfile << " \"theoretical_min\": [";
166
+ for (size_t i = 0; i < theoretical_min_values.size(); ++i) {
167
+ outfile << theoretical_min_values[i];
168
+ if (i < theoretical_min_values.size() - 1) outfile << ", ";
169
+ }
170
+ outfile << "]\n";
171
+
172
+ // Close JSON object
173
+ outfile << "}\n";
174
+
175
+ outfile.close();
176
  }
177
 
178
  int main(int argc, char* argv[]) {
179
  // ─── Inputs from command line ───────────────────────────────────────────
180
+ if (argc != 7) {
181
+ std::cerr << "Usage: " << argv[0] << " <n> <p> <a> <y> <fineness> <output_file>" << std::endl;
182
  return 1;
183
  }
184
 
 
186
  int p = std::stoi(argv[2]);
187
  double a = std::stod(argv[3]);
188
  double y = std::stod(argv[4]);
189
+ int fineness = std::stoi(argv[5]);
190
+ std::string output_file = argv[6];
191
  const double b = 1.0;
192
 
193
  std::cout << "Running with parameters: n = " << n << ", p = " << p
194
+ << ", a = " << a << ", y = " << y << ", fineness = " << fineness << std::endl;
195
  std::cout << "Output will be saved to: " << output_file << std::endl;
196
 
197
  // ─── Beta range parameters ────────────────────────────────────────
198
+ const int num_beta_points = fineness; // Controlled by fineness parameter
199
  std::vector<double> beta_values(num_beta_points);
200
  for (int i = 0; i < num_beta_points; ++i) {
201
  beta_values[i] = static_cast<double>(i) / (num_beta_points - 1);
 
249
  max_eigenvalues[beta_idx] = *std::max_element(eigs.begin(), eigs.end());
250
  min_eigenvalues[beta_idx] = *std::min_element(eigs.begin(), eigs.end());
251
 
252
+ // Progress indicator for Streamlit
253
+ double progress = static_cast<double>(beta_idx + 1) / num_beta_points;
254
+ std::cout << "PROGRESS:" << progress << std::endl;
255
+
256
+ // Less verbose output for Streamlit
257
+ if (beta_idx % 20 == 0 || beta_idx == num_beta_points - 1) {
258
  std::cout << "Processing beta = " << beta
259
  << " (" << beta_idx+1 << "/" << num_beta_points << ")" << std::endl;
260
  }
261
  }
262
 
263
+ // Save data as JSON for Python to read
264
+ save_as_json(output_file, beta_values, max_eigenvalues, min_eigenvalues,
265
+ theoretical_max_values, theoretical_min_values);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
+ std::cout << "Data saved to " << output_file << std::endl;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
 
269
  return 0;
270
  }