about summary refs log tree commit diff stats
path: root/021arithmetic.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-12 17:00:56 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-12 17:10:33 -0700
commit827898fc1b41e1974bf4ec2eebbd97fe23ff3d08 (patch)
tree437518c84d6df812c6af440c79f578e0949a5c8e /021arithmetic.cc
parent3663ca6c2d4c42c4a7bf6af4b2edf71dd8d10dd7 (diff)
downloadmu-827898fc1b41e1974bf4ec2eebbd97fe23ff3d08.tar.gz
1357 - temporarily revert floating-point support
Diffstat (limited to '021arithmetic.cc')
-rw-r--r--021arithmetic.cc234
1 files changed, 16 insertions, 218 deletions
diff --git a/021arithmetic.cc b/021arithmetic.cc
index ed852b9e..307bcb18 100644
--- a/021arithmetic.cc
+++ b/021arithmetic.cc
@@ -6,13 +6,13 @@ ADD,
 Recipe_number["add"] = ADD;
 :(before "End Primitive Recipe Implementations")
 case ADD: {
-  double result = 0;
+  long long int result = 0;
   for (index_t i = 0; i < ingredients.size(); ++i) {
     assert(ingredients.at(i).size() == 1);  // scalar
-    result += value(ingredients.at(i).at(0));
+    result += ingredients.at(i).at(0);
   }
   products.resize(1);
-  products.at(0).push_back(mu_noninteger(result));
+  products.at(0).push_back(result);
   break;
 }
 
@@ -53,13 +53,13 @@ Recipe_number["subtract"] = SUBTRACT;
 :(before "End Primitive Recipe Implementations")
 case SUBTRACT: {
   assert(ingredients.at(0).size() == 1);  // scalar
-  double result = value(ingredients.at(0).at(0));
+  long long int result = ingredients.at(0).at(0);
   for (index_t i = 1; i < ingredients.size(); ++i) {
     assert(ingredients.at(i).size() == 1);  // scalar
-    result -= value(ingredients.at(i).at(0));
+    result -= ingredients.at(i).at(0);
   }
   products.resize(1);
-  products.at(0).push_back(mu_noninteger(result));
+  products.at(0).push_back(result);
   break;
 }
 
@@ -99,13 +99,13 @@ MULTIPLY,
 Recipe_number["multiply"] = MULTIPLY;
 :(before "End Primitive Recipe Implementations")
 case MULTIPLY: {
-  double result = 1;
+  long long int result = 1;
   for (index_t i = 0; i < ingredients.size(); ++i) {
     assert(ingredients.at(i).size() == 1);  // scalar
-    result *= value(ingredients.at(i).at(0));
+    result *= ingredients.at(i).at(0);
   }
   products.resize(1);
-  products.at(0).push_back(mu_noninteger(result));
+  products.at(0).push_back(result);
   break;
 }
 
@@ -146,13 +146,13 @@ Recipe_number["divide"] = DIVIDE;
 :(before "End Primitive Recipe Implementations")
 case DIVIDE: {
   assert(ingredients.at(0).size() == 1);  // scalar
-  double result = value(ingredients.at(0).at(0));
+  long long int result = ingredients.at(0).at(0);
   for (index_t i = 1; i < ingredients.size(); ++i) {
     assert(ingredients.at(i).size() == 1);  // scalar
-    result /= value(ingredients.at(i).at(0));
+    result /= ingredients.at(i).at(0);
   }
   products.resize(1);
-  products.at(0).push_back(mu_noninteger(result));
+  products.at(0).push_back(result);
   break;
 }
 
@@ -192,15 +192,11 @@ DIVIDE_WITH_REMAINDER,
 Recipe_number["divide-with-remainder"] = DIVIDE_WITH_REMAINDER;
 :(before "End Primitive Recipe Implementations")
 case DIVIDE_WITH_REMAINDER: {
-  assert(ingredients.at(0).size() == 1);  // scalar
-  long long int a = value(ingredients.at(0).at(0));
-  assert(ingredients.at(1).size() == 1);  // scalar
-  long long int b = value(ingredients.at(1).at(0));
-  long long int quotient = a / b;
-  long long int remainder = a % b;
+  long long int quotient = ingredients.at(0).at(0) / ingredients.at(1).at(0);
+  long long int remainder = ingredients.at(0).at(0) % ingredients.at(1).at(0);
   products.resize(2);
-  products.at(0).push_back(mu_integer(quotient));
-  products.at(1).push_back(mu_integer(remainder));
+  products.at(0).push_back(quotient);
+  products.at(1).push_back(remainder);
   break;
 }
 
@@ -231,201 +227,3 @@ recipe main [
 +mem: storing 2 in location 3
 +run: product 1 is 4
 +mem: storing 5 in location 4
-
-//:: Support for non-integer numbers.
-
-:(scenario divide_with_decimal_point)
-recipe main [
-  # todo: literal floats?
-  1:integer <- divide 5:literal, 2:literal
-]
-+mem: storing 2.5 in location 1
-
-//: Supporting non-integers is hopefully the only place where we need to think
-//: about the size of each location of memory.
-:(after "int main")
-assert(sizeof(long long int) == 8);
-assert(sizeof(double) == 8);
-
-:(before "End Globals")
-//: Conventional hardware uses the most significant bit to represent the sign
-//: in both (2's complement) integers, and so-called floating-point numbers
-//: (with sign, exponent and fraction regions: https://en.wikipedia.org/wiki/Double-precision_floating-point_format)
-
-//: Watch out: perform bitwise operations only on unsigned values to avoid
-//: undefined behavior.
-//: For similar reasons, don't coerce between signed and unsigned, instead
-//: manually interpret the bit-pattern
-
-const unsigned long long int HOST_SET_NEGATIVE = (0x1ULL << 63ULL);
-
-//: As an experiment, we'd like to not have to distinguish between the two in
-//: mu. So we'll use the most-significant bit to represent whether a number is
-//: an integer (MSB 0) or a float (MSB 1). This will halve the set of numbers
-//: we can represent, whether integers or non-integers, but that price seems
-//: reasonable right now.
-const unsigned long long int MU_NUMBER_NONINTEGER_MASK = (0x1ULL << 63ULL);
-//: As a result, the sign bit is now pushed to the second-most significant
-//: bit..
-const unsigned long long int MU_NUMBER_SIGN_MASK = (0x1ULL << 62ULL);
-
-:(after "int main")
-assert(MU_NUMBER_NONINTEGER_MASK == HOST_SET_NEGATIVE);
-
-:(code)
-inline bool is_float(long long int number) {
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number);
-  return tmp & MU_NUMBER_NONINTEGER_MASK;
-}
-
-inline bool is_integer(long long int number) {
-  return !is_float(number);
-}
-
-inline bool is_negative(long long int number) {
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number);
-  return tmp & MU_NUMBER_SIGN_MASK;
-}
-
-inline double value(long long int number) {
-  return is_integer(number) ? to_int(number) : to_float(number);
-}
-
-// convert a mu integer to host representation
-long long int to_int(long long int number) {
-  assert(is_integer(number));
-  if (!is_negative(number)) return number;
-  // negative number
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number);
-  // slide the sign over by one bit
-  tmp = tmp | HOST_SET_NEGATIVE;
-//?   // clear the old sign bit
-//?   // so the range of numbers we can represent shrinks by half
-//?   tmp = tmp & (~MU_NUMBER_SIGN_MASK);
-  // reinterpret back as signed
-  long long int result = *reinterpret_cast<long long int*>(&tmp);
-  return result;
-}
-
-// convert an integer from host representation to mu representation
-long long int mu_integer(long long int n) {
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&n);
-  // slide the sign to the right
-  if (tmp & HOST_SET_NEGATIVE) tmp = tmp | MU_NUMBER_SIGN_MASK;
-  // clear the old sign bit
-  tmp = tmp & (~HOST_SET_NEGATIVE);
-  // reinterpret back as signed
-  long long int result = *reinterpret_cast<long long int*>(&tmp);
-  assert(is_integer(result));
-//?   printf("%llx\n", result); //? 1
-  return result;
-}
-
-// convert a mu non-integer to host representation
-double to_float(long long int number) {
-  assert(is_float(number));
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&number);
-  // slide the entire number over the most significant bit
-  // so the precision of numbers we can represent shrinks by 1 bit
-  tmp = (tmp << 1);
-  double result = *reinterpret_cast<double*>(&tmp);
-  return result;
-}
-
-// convert a float from host representation to mu representation
-long long int mu_noninteger(double n) {
-  unsigned long long int tmp = *reinterpret_cast<unsigned long long int*>(&n);
-  tmp = (tmp >> 1);
-  tmp = (tmp | MU_NUMBER_NONINTEGER_MASK);
-  long long int result = *reinterpret_cast<long long int*>(&tmp);
-  assert(is_float(result));
-  return result;
-}
-
-// Spot-check some bit-patterns and make sure they convert back to themselves.
-void test_integer_representation() {
-  // Assuming long long int is 8 bytes:
-  static const int nbits = 64;
-//?   cerr << '\n'; //? 1
-//?   cerr << nbits << " iterations\n"; //? 1
-//?   cerr << std::hex; //? 1
-//?   cerr << "type mask: " << MU_NUMBER_NONINTEGER_MASK << '\n'; //? 1
-//?   cerr << "sign mask: " << MU_NUMBER_SIGN_MASK << '\n'; //? 1
-//?   cerr << std::dec; //? 1
-  // until the last 2 bits all integers retain their value
-  for (int i = 0; i < nbits-2; ++i) {
-    unsigned long long int x = (0x1ULL << i);
-    long long int n = *reinterpret_cast<long long int*>(&x);
-//?     cerr << i << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_int(n) << '\n'; //? 2
-    CHECK(is_integer(n));
-    CHECK_EQ(n, to_int(n));
-//?     printf("0x%llx\n", mu_integer(to_int(n))); //? 1
-    CHECK_EQ(n, mu_integer(to_int(n)));
-  }
-  // second-last bit
-  unsigned long long int x = (0x1ULL << (nbits-2));
-  long long int n = *reinterpret_cast<long long int*>(&x);
-  CHECK(is_integer(n));
-//?   cerr << nbits-2 << ": " << "0x" << std::hex << n << std::dec << ' ' << n << " => " << to_int(n) << '\n'; //? 1
-  CHECK(is_negative(n));
-  CHECK_EQ(n, mu_integer(to_int(n)));
-  // most significant bit is for non-integers below
-}
-
-// Now go the other way; spot-check a few mu integers and make sure they
-// convert back to themselves.
-void test_small_integers() {
-  for (long long int n = -1000; n < 1000; ++n) {
-//?     printf("0x%llx vs 0x%llx\n", n, to_int(mu_integer(n))); //? 1
-    CHECK_EQ(n, to_int(mu_integer(n)));
-  }
-}
-
-// Spot-check some bit-patterns and make sure they convert back to themselves.
-void test_noninteger_representation() {
-  // Assuming long long int is 8 bytes:
-  static const int nbits = 64;
-  static const long long int FLOAT_MASK = (0x1ULL << (nbits-1));
-//?   double f = -2.0; //? 1
-//?   printf("0x%llx\n", *(long long int*)&f); //? 1
-//?   printf("\n"); //? 1
-  for (int fraction = 0; fraction < 52; ++fraction) {
-    for (int exponent = 52; exponent < 63; ++exponent) {
-      long long int n = (0x1ULL << fraction) | (0x1ULL << exponent) | FLOAT_MASK;
-      CHECK(is_float(n));
-      double result = to_float(n);
-//?       double result_on_host = *reinterpret_cast<double*>(&n); //? 1
-//?       printf("%02d %d: 0x%llx %.30e\n", fraction, exponent, n, result_on_host); //? 1
-//?       printf("=>                        %.30e\n", result); //? 1
-//?       printf("=>     0x%llx\n", mu_noninteger(result)); //? 1
-      CHECK_EQ(n, mu_noninteger(result));
-    }
-    int exponent = 63;
-    long long int n = ((0x1ULL << 62) | (0x1ULL << exponent) | FLOAT_MASK);
-    CHECK(is_float(n));
-    double result = to_float(n);
-//?     double result_on_host = *reinterpret_cast<double*>(&n); //? 1
-//?     printf("%02d %d: 0x%llx %.30e\n", fraction, nbits-1, n, result_on_host); //? 1
-//?     printf("=>                        %.30e\n", result); //? 1
-//?     printf("=>     0x%llx\n", mu_noninteger(result)); //? 1
-    CHECK_EQ(n, mu_noninteger(result));
-  }
-}
-
-:(code)
-// Now go the other way; spot-check a few mu non-integers and make sure they
-// convert back to themselves.
-void test_small_nonintegers() {
-  for (double n = -1000.0; n < 1000.0; n += 0.001) {
-//?     printf("%.30e vs %.30e\n", n, to_float(mu_noninteger(n))); //? 1
-    CHECK(fabs(n - to_float(mu_noninteger(n))) < epsilon);
-  }
-}
-
-:(before "End Globals")
-const double epsilon = 1e-13;
-
-:(before "End Includes")
-#include<iomanip>
-#include<limits>
-#include<math.h>