about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-09-14 23:30:03 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-09-14 23:37:12 -0700
commit4082acd24f0049604f840fb5e60977e247aafbdf (patch)
treeee0e15149954af80c20f010c47b2f412961ee199
parente28fa5f1508ef7ffeb0b72406558534928c28f9e (diff)
downloadmu-4082acd24f0049604f840fb5e60977e247aafbdf.tar.gz
2199 - stop printing numbers in scientific notation
Turns out the default format for printing floating point numbers is
neither 'scientific' nor 'fixed' even though those are the only two
options offered. Reading the C++ standard I found out that the default
(modulo locale changes) is basically the same as the printf "%g" format.
And "%g" is basically the shorter of:
  a) %f with trailing zeros trimmed
  b) %e
So we'll just do %f and trim trailing zeros.
-rw-r--r--010vm.cc48
-rw-r--r--020run.cc4
-rw-r--r--029tools.cc4
-rw-r--r--031address.cc6
-rw-r--r--032array.cc4
-rw-r--r--036call_reply.cc4
-rw-r--r--039wait.cc2
-rw-r--r--040brace.cc6
-rw-r--r--042name.cc4
-rw-r--r--044space.cc2
-rw-r--r--050scenario.cc12
-rw-r--r--072scenario_screen.cc10
-rw-r--r--081run_interactive.cc6
13 files changed, 79 insertions, 33 deletions
diff --git a/010vm.cc b/010vm.cc
index c7ac4d0a..5e375409 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -287,9 +287,55 @@ vector<string> property(const reagent& r, const string& name) {
 
 void dump_memory() {
   for (map<long long int, double>::iterator p = Memory.begin(); p != Memory.end(); ++p) {
-    cout << p->first << ": " << p->second << '\n';
+    cout << p->first << ": " << no_scientific(p->second) << '\n';
   }
 }
+
+:(before "End Types")
+struct no_scientific {
+  double x;
+  explicit no_scientific(double y) :x(y) {}
+};
+
+:(code)
+ostream& operator<<(ostream& os, no_scientific x) {
+  if (!isfinite(x.x)) {
+    // Infinity or NaN
+    os << x.x;
+    return os;
+  }
+  ostringstream tmp;
+  tmp << std::fixed << x.x;
+  os << trim_floating_point(tmp.str());
+  return os;
+}
+
+string trim_floating_point(const string& in) {
+  long long int len = SIZE(in);
+  while (len > 1) {
+    if (in.at(len-1) != '0') break;
+    --len;
+  }
+  if (in.at(len-1) == '.') --len;
+//?   cerr << in << ": " << in.substr(0, len) << '\n';
+  return in.substr(0, len);
+}
+
+void test_trim_floating_point() {
+  CHECK_EQ("0", trim_floating_point("000000000"));
+  CHECK_EQ("23.000001", trim_floating_point("23.000001"));
+  CHECK_EQ("23", trim_floating_point("23.000000"));
+  CHECK_EQ("23", trim_floating_point("23.0"));
+  CHECK_EQ("23", trim_floating_point("23."));
+  CHECK_EQ("23", trim_floating_point("23"));
+  CHECK_EQ("3", trim_floating_point("3.000000"));
+  CHECK_EQ("3", trim_floating_point("3.0"));
+  CHECK_EQ("3", trim_floating_point("3."));
+  CHECK_EQ("3", trim_floating_point("3"));
+  CHECK_EQ("1.5", trim_floating_point("1.5000"));
+}
+
 :(before "End Includes")
 #include<utility>
 using std::pair;
+#include<math.h>
diff --git a/020run.cc b/020run.cc
index be127989..d6ce68ec 100644
--- a/020run.cc
+++ b/020run.cc
@@ -270,7 +270,7 @@ vector<double> read_memory(reagent x) {
   long long int size = size_of(x);
   for (long long int offset = 0; offset < size; ++offset) {
     double val = Memory[base+offset];
-    trace(Primitive_recipe_depth, "mem") << "location " << base+offset << " is " << val << end();
+    trace(Primitive_recipe_depth, "mem") << "location " << base+offset << " is " << no_scientific(val) << end();
     result.push_back(val);
   }
   return result;
@@ -285,7 +285,7 @@ void write_memory(reagent x, vector<double> data) {
     return;
   }
   for (long long int offset = 0; offset < SIZE(data); ++offset) {
-    trace(Primitive_recipe_depth, "mem") << "storing " << data.at(offset) << " in location " << base+offset << end();
+    trace(Primitive_recipe_depth, "mem") << "storing " << no_scientific(data.at(offset)) << " in location " << base+offset << end();
     Memory[base+offset] = data.at(offset);
   }
 }
diff --git a/029tools.cc b/029tools.cc
index b03635b0..0011c6e0 100644
--- a/029tools.cc
+++ b/029tools.cc
@@ -76,7 +76,7 @@ string print_mu(const reagent& r, const vector<double>& data) {
   // End print Special-cases(reagent r, data)
   ostringstream out;
   for (long long i = 0; i < SIZE(data); ++i) {
-    out << data.at(i) << ' ';
+    out << no_scientific(data.at(i)) << ' ';
   }
   return out.str();
 }
@@ -215,7 +215,7 @@ case _PRINT: {
       for (long long int j = 0; j < SIZE(ingredients.at(i)); ++j) {
         trace(Primitive_recipe_depth, "run") << "$print: " << ingredients.at(i).at(j) << end();
         if (j > 0) cout << " ";
-        cout << ingredients.at(i).at(j);
+        cout << no_scientific(ingredients.at(i).at(j));
       }
     }
   }
diff --git a/031address.cc b/031address.cc
index 997e3c65..38a891ef 100644
--- a/031address.cc
+++ b/031address.cc
@@ -64,7 +64,7 @@ reagent lookup_memory(reagent x) {
     return result;
   }
   result.set_value(Memory[x.value]);
-  trace(Primitive_recipe_depth, "mem") << "location " << x.value << " is " << result.value << end();
+  trace(Primitive_recipe_depth, "mem") << "location " << x.value << " is " << no_scientific(result.value) << end();
 
   // populate types
   copy(++x.types.begin(), x.types.end(), inserter(result.types, result.types.begin()));
@@ -147,7 +147,7 @@ Recipe_ordinal["$dump"] = _DUMP;
 :(before "End Primitive Recipe Implementations")
 case _DUMP: {
   reagent after_canonize = canonize(current_instruction().ingredients.at(0));
-  cerr << current_recipe_name() << ": " << current_instruction().ingredients.at(0).name << ' ' << current_instruction().ingredients.at(0).value << " => " << after_canonize.value << " => " << Memory[after_canonize.value] << '\n';
+  cerr << current_recipe_name() << ": " << current_instruction().ingredients.at(0).name << ' ' << no_scientific(current_instruction().ingredients.at(0).value) << " => " << no_scientific(after_canonize.value) << " => " << no_scientific(Memory[after_canonize.value]) << '\n';
   break;
 }
 
@@ -162,7 +162,7 @@ Recipe_ordinal["$foo"] = _FOO;
 :(before "End Primitive Recipe Implementations")
 case _FOO: {
   if (current_instruction().ingredients.empty()) {
-    if (foo != -1) cerr << foo << ": " << Memory[foo] << '\n';
+    if (foo != -1) cerr << foo << ": " << no_scientific(Memory[foo]) << '\n';
     else cerr << '\n';
   }
   else {
diff --git a/032array.cc b/032array.cc
index 62021466..1b8d5900 100644
--- a/032array.cc
+++ b/032array.cc
@@ -156,7 +156,7 @@ case INDEX: {
   vector<double> offset_val(read_memory(offset));
   vector<type_ordinal> element_type = array_element(base.types);
   if (offset_val.at(0) < 0 || offset_val.at(0) >= Memory[base_address]) {
-    raise << current_recipe_name() << ": invalid index " << offset_val.at(0) << '\n' << end();
+    raise << current_recipe_name() << ": invalid index " << no_scientific(offset_val.at(0)) << '\n' << end();
     break;
   }
   long long int src = base_address + 1 + offset_val.at(0)*size_of(element_type);
@@ -251,7 +251,7 @@ case INDEX_ADDRESS: {
   vector<double> offset_val(read_memory(offset));
   vector<type_ordinal> element_type = array_element(base.types);
   if (offset_val.at(0) < 0 || offset_val.at(0) >= Memory[base_address]) {
-    raise << current_recipe_name() << ": invalid index " << offset_val.at(0) << '\n' << end();
+    raise << current_recipe_name() << ": invalid index " << no_scientific(offset_val.at(0)) << '\n' << end();
     break;
   }
   long long int result = base_address + 1 + offset_val.at(0)*size_of(element_type);
diff --git a/036call_reply.cc b/036call_reply.cc
index 8d3f1395..2cb4922e 100644
--- a/036call_reply.cc
+++ b/036call_reply.cc
@@ -100,13 +100,13 @@ string to_string(const vector<double>& in) {
   if (in.empty()) return "[]";
   ostringstream out;
   if (SIZE(in) == 1) {
-    out << in.at(0);
+    out << no_scientific(in.at(0));
     return out.str();
   }
   out << "[";
   for (long long int i = 0; i < SIZE(in); ++i) {
     if (i > 0) out << ", ";
-    out << in.at(i);
+    out << no_scientific(in.at(i));
   }
   out << "]";
   return out.str();
diff --git a/039wait.cc b/039wait.cc
index 43efa8cf..9a76e309 100644
--- a/039wait.cc
+++ b/039wait.cc
@@ -40,7 +40,7 @@ case WAIT_FOR_LOCATION: {
   Current_routine->state = WAITING;
   Current_routine->waiting_on_location = loc.value;
   Current_routine->old_value_of_waiting_location = Memory[loc.value];
-  trace(Primitive_recipe_depth, "run") << "waiting for location " << loc.value << " to change from " << Memory[loc.value] << end();
+  trace(Primitive_recipe_depth, "run") << "waiting for location " << loc.value << " to change from " << no_scientific(Memory[loc.value]) << end();
   break;
 }
 
diff --git a/040brace.cc b/040brace.cc
index 81b9560d..a26364e1 100644
--- a/040brace.cc
+++ b/040brace.cc
@@ -115,11 +115,11 @@ void transform_braces(const recipe_ordinal r) {
     inst.ingredients.push_back(target);
     // log computed target
     if (inst.name.find("-if") != string::npos)
-      trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << target.value << ":offset" << end();
+      trace("after-brace") << "jump-if " << inst.ingredients.at(0).name << ", " << no_scientific(target.value) << ":offset" << end();
     else if (inst.name.find("-unless") != string::npos)
-      trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << target.value << ":offset" << end();
+      trace("after-brace") << "jump-unless " << inst.ingredients.at(0).name << ", " << no_scientific(target.value) << ":offset" << end();
     else
-      trace("after-brace") << "jump " << target.value << ":offset" << end();
+      trace("after-brace") << "jump " << no_scientific(target.value) << ":offset" << end();
   }
 }
 
diff --git a/042name.cc b/042name.cc
index 0a7a316a..c430a10f 100644
--- a/042name.cc
+++ b/042name.cc
@@ -209,7 +209,7 @@ if (inst.operation == Recipe_ordinal["get"]
     // since first non-address in base type must be a container, we don't have to canonize
     type_ordinal base_type = skip_addresses(inst.ingredients.at(0).types);
     inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name));
-    trace("name") << "element " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " is at offset " << inst.ingredients.at(1).value << end();
+    trace("name") << "element " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " is at offset " << no_scientific(inst.ingredients.at(1).value) << end();
   }
 }
 
@@ -248,6 +248,6 @@ if (inst.operation == Recipe_ordinal["maybe-convert"]) {
     // since first non-address in base type must be an exclusive container, we don't have to canonize
     type_ordinal base_type = skip_addresses(inst.ingredients.at(0).types);
     inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name));
-    trace("name") << "variant " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " has tag " << inst.ingredients.at(1).value << end();
+    trace("name") << "variant " << inst.ingredients.at(1).name << " of type " << Type[base_type].name << " has tag " << no_scientific(inst.ingredients.at(1).value) << end();
   }
 }
diff --git a/044space.cc b/044space.cc
index 737e80b9..eddf457e 100644
--- a/044space.cc
+++ b/044space.cc
@@ -204,7 +204,7 @@ long long int address(long long int offset, long long int base) {
   if (base == 0) return offset;  // raw
   if (offset >= static_cast<long long int>(Memory[base])) {
     // todo: test
-    raise << "location " << offset << " is out of bounds " << Memory[base] << " at " << base << '\n' << end();
+    raise << "location " << offset << " is out of bounds " << no_scientific(Memory[base]) << " at " << base << '\n' << end();
   }
   return base+1 + offset;
 }
diff --git a/050scenario.cc b/050scenario.cc
index 6e38a80a..5378ff5d 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -274,11 +274,11 @@ void check_memory(const string& s) {
     if (Memory[address] != value) {
       if (Current_scenario && !Scenario_testing_scenario) {
         // genuine test in a mu file
-        raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n' << end();
+        raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end();
       }
       else {
         // just testing scenario support
-        raise << "expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n' << end();
+        raise << "expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end();
       }
       if (!Scenario_testing_scenario) {
         Passed = false;
@@ -313,9 +313,9 @@ void check_string(long long int address, const string& literal) {
   trace(Primitive_recipe_depth, "run") << "checking string length at " << address << end();
   if (Memory[address] != SIZE(literal)) {
     if (Current_scenario && !Scenario_testing_scenario)
-      raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << Memory[address] << '\n' << end();
+      raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end();
     else
-      raise << "expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << Memory[address] << '\n' << end();
+      raise << "expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end();
     if (!Scenario_testing_scenario) {
       Passed = false;
       ++Num_failures;
@@ -328,11 +328,11 @@ void check_string(long long int address, const string& literal) {
     if (Memory[address+i] != literal.at(i)) {
       if (Current_scenario && !Scenario_testing_scenario) {
         // genuine test in a mu file
-        raise << "\nF - " << Current_scenario->name << ": expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << Memory[address+i] << '\n' << end();
+        raise << "\nF - " << Current_scenario->name << ": expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end();
       }
       else {
         // just testing scenario support
-        raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << Memory[address+i] << '\n' << end();
+        raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end();
       }
       if (!Scenario_testing_scenario) {
         Passed = false;
diff --git a/072scenario_screen.cc b/072scenario_screen.cc
index 2b885d58..29ae4c5d 100644
--- a/072scenario_screen.cc
+++ b/072scenario_screen.cc
@@ -219,11 +219,11 @@ void check_screen(const string& expected_contents, const int color) {
         // contents match but color is off
         if (Current_scenario && !Scenario_testing_scenario) {
           // genuine test in a mu file
-          raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ", address " << addr << ", value " << Memory[addr] << ") to be in color " << color << " instead of " << Memory[addr+cell_color_offset] << "\n" << end();
+          raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ", address " << addr << ", value " << no_scientific(Memory[addr]) << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << "\n" << end();
         }
         else {
           // just testing check_screen
-          raise << "expected screen location (" << row << ", " << column << ") to be in color " << color << " instead of " << Memory[addr+cell_color_offset] << '\n' << end();
+          raise << "expected screen location (" << row << ", " << column << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << '\n' << end();
         }
         if (!Scenario_testing_scenario) {
           Passed = false;
@@ -247,12 +247,12 @@ void check_screen(const string& expected_contents, const int color) {
 
       if (Current_scenario && !Scenario_testing_scenario) {
         // genuine test in a mu file
-        raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << " instead of " << Memory[addr] << actual_pretty << '\n' << end();
+        raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end();
         dump_screen();
       }
       else {
         // just testing check_screen
-        raise << "expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << " instead of " << Memory[addr] << actual_pretty << '\n' << end();
+        raise << "expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end();
       }
       if (!Scenario_testing_scenario) {
         Passed = false;
@@ -334,7 +334,7 @@ void dump_screen() {
     cerr << '.';
     for (long long int col = 0; col < screen_width; ++col) {
       if (Memory[curr])
-        cerr << to_unicode(Memory[curr]);
+        cerr << to_unicode(static_cast<uint32_t>(Memory[curr]));
       else
         cerr << ' ';
       curr += /*size of screen-cell*/2;
diff --git a/081run_interactive.cc b/081run_interactive.cc
index ec7f9206..ca314565 100644
--- a/081run_interactive.cc
+++ b/081run_interactive.cc
@@ -259,7 +259,7 @@ void track_most_recent_products(const instruction& instruction, const vector<vec
           cerr << read_mu_string(trace_contents("warn")) << '\n';
           cerr << SIZE(products.at(i)) << ": ";
           for (long long int j = 0; j < SIZE(products.at(i)); ++j)
-            cerr << products.at(i).at(j) << ' ';
+            cerr << no_scientific(products.at(i).at(j)) << ' ';
           cerr << '\n';
         }
         assert(scalar(products.at(i)));
@@ -269,7 +269,7 @@ void track_most_recent_products(const instruction& instruction, const vector<vec
       // End Record Product Special-cases
     }
     for (long long int j = 0; j < SIZE(products.at(i)); ++j)
-      out << products.at(i).at(j) << ' ';
+      out << no_scientific(products.at(i).at(j)) << ' ';
     out << '\n';
   }
   Most_recent_products = out.str();
@@ -293,7 +293,7 @@ string strip_comments(string in) {
 long long int stringified_value_of_location(long long int address) {
   // convert to string
   ostringstream out;
-  out << Memory[address];
+  out << no_scientific(Memory[address]);
   return new_mu_string(out.str());
 }