Chris_M_Thomasson

Storing Data in Complex Numbers, an experiment...

Mar 10th, 2020
657
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.61 KB | None | 0 0
  1. // 4/12/2017: n-ary complex storage example by Chris M. Thomasson
  2.  
  3. #include <complex>
  4. #include <iostream>
  5. #include <vector>
  6. #include <limits>
  7. #include <algorithm> // reverse
  8. #include <cstdint> // want to work with 64-bit numbers
  9. #include <cassert> // want to sanity check run time...
  10. #include <cstring> // faster than iostream's?
  11.  
  12.  
  13. // Well, I need some consistent typenames... ;^)
  14. typedef std::int64_t ct_int;
  15. typedef std::uint64_t ct_uint;
  16. typedef double ct_float;
  17. typedef std::numeric_limits<ct_float> ct_float_nlim;
  18. typedef std::complex<ct_float> ct_complex;
  19. typedef std::complex<ct_uint> ct_complex_uint;
  20. typedef std::vector<ct_complex> ct_complex_vec;
  21.  
  22. #define CT_PI 3.14159265358979323846
  23.  
  24.  
  25. // Round up and convert the real and imaginary
  26. // parts of z to unsigned integers of type ct_uint
  27. // return a complex number with unsigned integer parts
  28. ct_complex_uint
  29. ct_round_uint(
  30.      ct_complex const& z
  31. ) {
  32.      ct_uint re = (ct_uint)std::floor(std::abs(z.real()) + .5);
  33.      ct_uint im = (ct_uint)std::floor(std::abs(z.imag()) + .5);
  34.      return ct_complex_uint(re, im);
  35. }
  36.  
  37.  
  38. // the integer p shall not be zero
  39. // create abs(p) roots of z wrt z^(1/p);
  40. // store them in out, and return the average error.
  41. ct_float
  42. ct_roots(
  43.      ct_complex const& z,
  44.      ct_int p,
  45.      ct_complex_vec& out
  46. ) {
  47.      assert(p != 0);
  48.  
  49.      // Gain the basics
  50.      ct_float radius = std::pow(std::abs(z), 1.0 / p);
  51.      ct_float angle_base = std::arg(z) / p;
  52.      ct_float angle_step = (CT_PI * 2.0) / p;
  53.  
  54.      // Setup the iteration
  55.      ct_uint n = std::abs(p);
  56.      ct_float avg_err = 0.0;
  57.  
  58.      // Calculate the n roots...
  59.      for (ct_uint i = 0; i < n; ++i)
  60.      {
  61.          // our angle
  62.          ct_float angle = angle_step * i;
  63.  
  64.          // our point
  65.          ct_complex c = {
  66.              std::cos(angle_base + angle) * radius,
  67.              std::sin(angle_base + angle) * radius
  68.          };
  69.  
  70.          // output data
  71.          out.push_back(c);
  72.  
  73.          // Raise our root the the power...
  74.          ct_complex raised = std::pow(c, p);
  75.  
  76.          // Sum up the Go% damn floating point errors!
  77.          avg_err = avg_err + std::abs(raised - z);
  78.      }
  79.  
  80.      // gain the average error sum... ;^o
  81.      return avg_err / n;
  82. }
  83.  
  84.  
  85. // Try's to find the target root z out of roots using
  86. // eps, return the index of the root, or -1 for failure.
  87. int
  88. ct_try_find(
  89.      ct_complex const& z,
  90.      ct_complex_vec const& roots,
  91.      ct_float eps
  92. ) {
  93.      std::size_t n = roots.size();
  94.  
  95.      for (std::size_t i = 0; i < n; ++i)
  96.      {
  97.          ct_complex const& root = roots[i];
  98.  
  99.          ct_float adif = std::abs(root - z);
  100.  
  101.          if (adif < eps)
  102.          {
  103.              return i;
  104.          }
  105.      }
  106.  
  107.      return -1;
  108. }
  109.  
  110.  
  111.  
  112.  
  113.  
  114. // The Token Table
  115. // Will deal with scrambled token vectors in further posts.
  116. // This is global for now, easy to convert to per store/load
  117. // pairs
  118. static std::string const g_tokens_str =
  119.      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  120.  
  121. // Gains the power from the largest token position
  122. // from tokens in g_tokens_str
  123. ct_int
  124. ct_gain_power(
  125.      std::string const& tokens
  126. ) {
  127.      ct_uint n = tokens.length();
  128.  
  129.      std::size_t pmax = 0;
  130.  
  131.      for (ct_uint i = 0; i < n; ++i)
  132.      {
  133.          std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
  134.          assert(fridx != std::string::npos);
  135.          pmax = std::max(pmax, fridx);
  136.      }
  137.  
  138.      return (ct_int)(pmax + 1);
  139. }
  140.  
  141.  
  142. // Store tokens using a power of p starting in z-origin
  143. // Return the complex number holding said tokens.
  144. ct_complex
  145. ct_store(
  146.      ct_complex const& z_origin,
  147.      ct_int p,
  148.      std::string const& tokens
  149. ) {
  150.      ct_uint n = tokens.length();
  151.  
  152.      ct_complex z = z_origin;
  153.      ct_float store_avg_err = 0.0;
  154.  
  155.      std::cout << "Storing Data..." << "\n";
  156.      std::cout << "stored:z_origin:" << z_origin << "\n";
  157.  
  158.      for (ct_uint i = 0; i < n; ++i)
  159.      {
  160.          // Gain all of the roots, and running store error
  161.          ct_complex_vec roots;
  162.          ct_float avg_err = ct_roots(z, p, roots);
  163.          store_avg_err = store_avg_err + avg_err;
  164.  
  165.          // reference our root
  166.          std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
  167.          assert(fridx != std::string::npos);
  168.  
  169.          z = roots[fridx];
  170.  
  171.          std::cout << "stored[" << i << "]:" << z << "\n";
  172.      }
  173.  
  174.      store_avg_err = store_avg_err / n;
  175.      std::cout << "store_avg_err:" << store_avg_err << "\n";
  176.  
  177.      return z;
  178. }
  179.  
  180.  
  181. // Load our tokens from z_store, power of p,
  182. // stopping at z_target using eps, storing tokens
  183. // in out_tokens, and the resulting z in out_z
  184. ct_float
  185. ct_load(
  186.      ct_complex const& z_store,
  187.      ct_complex const& z_target,
  188.      ct_int p,
  189.      ct_float eps, // epsilon
  190.      std::string& out_tokens,
  191.      ct_complex& out_z
  192. ) {
  193.      ct_complex z = z_store;
  194.      ct_uint n = 128; // max iter
  195.      ct_float load_err_sum = 0.0;
  196.  
  197.      std::cout << "Loading Data..." << "\n";
  198.      for (ct_uint i = 0; i < n; ++i)
  199.      {
  200.          // raise...
  201.          ct_complex z_next = std::pow(z, p);
  202.  
  203.          // Gain all of the roots, and running load error
  204.          ct_complex_vec roots;
  205.          ct_float avg_err = ct_roots(z_next, p, roots);
  206.          load_err_sum += avg_err;
  207.  
  208.          // try to find our root...
  209.          int root_idx = ct_try_find(z, roots, eps);
  210.          if (root_idx < 0 ||
  211.              (ct_uint)root_idx >= g_tokens_str.length()) break;
  212.  
  213.          std::cout << "loaded[" << i << "]:" << z << "\n";
  214.  
  215.          out_tokens += g_tokens_str[root_idx];
  216.  
  217.          // advance
  218.          z = z_next;
  219.  
  220.          // check for termination condition...
  221.          if (std::abs(z - z_target) < eps)
  222.          {
  223.              std::cout << "fin detected!:[" << i << "]:" << z << "\n";
  224.              break;
  225.          }
  226.      }
  227.  
  228.      // reverse our tokens
  229.      std::reverse(out_tokens.begin(), out_tokens.end());
  230.  
  231.      out_z = z;
  232.      return load_err_sum;
  233. }
  234.  
  235.  
  236. int main()
  237. {
  238.      std::cout.precision(ct_float_nlim::max_digits10);
  239.  
  240.      std::cout << "g_tokens_str:" << g_tokens_str << "\n\n";
  241.  
  242.      {
  243.          ct_complex z_origin = { -.75, .06 };
  244.  
  245.          // The original data to be stored
  246.          std::string stored = "CHRIS";
  247.          ct_int power = ct_gain_power(stored);
  248.  
  249.          std::cout << "stored:" << stored << "\n";
  250.          std::cout << "power:" << power << "\n\n";
  251.          std::cout << "________________________________________\n";
  252.  
  253.          // STORE
  254.          ct_complex z_stored = ct_store(z_origin, power, stored);
  255.  
  256.          std::cout << "________________________________________\n";
  257.  
  258.  
  259.          std::cout << "\nSTORED POINT:" << z_stored << "\n";
  260.  
  261.  
  262.          std::cout << "________________________________________\n";
  263.  
  264.          // The data loaded from the stored.
  265.          std::string loaded;
  266.          ct_complex z_loaded;
  267.          ct_float eps = .001; // epsilon
  268.  
  269.          // LOAD
  270.          ct_float load_err_sum =
  271.              ct_load(z_stored, z_origin, power, eps, loaded, z_loaded);
  272.  
  273.          std::cout << "________________________________________\n";
  274.  
  275.          std::cout << "\nORIGIN POINT:" << z_origin << "\n";
  276.          std::cout << "LOADED POINT:" << z_loaded << "\n";
  277.  
  278.          std::cout << "\nloaded:" << loaded << "\n"
  279.              "load_err_sum:" << load_err_sum << "\n";
  280.  
  281.          // make sure everything is okay...
  282.          if (stored == loaded)
  283.          {
  284.              std::cout << "\n\nDATA COHERENT! :^D" << "\n";
  285.          }
  286.  
  287.          else
  288.          {
  289.              std::cout << "\n\n***** DATA CORRUPTED!!! Shi%! *****" << "\n";
  290.              assert(stored == loaded);
  291.          }
  292.      }
  293.  
  294.      return 0;
  295. }
Advertisement
Add Comment
Please, Sign In to add comment