Chris_M_Thomasson

Text of the link in Google groups, storing data complex

Apr 29th, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.01 KB | None | 0 0
  1. Text of the link:
  2.  
  3. Here is a quick and crude example of using the ct_roots function
  4. described in the following thread:
  5.  
  6. "n-ary roots from complex numbers..."
  7. https://groups.google.com/d/topic/comp.lang.c++/05XwgswUnDg/discussion
  8.  
  9. to actually store data. The following code stores my name "CHRIS" from
  10. the following symbol table:
  11.  
  12. "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  13.  
  14. in a single complex number via root map. For storing data, it maps each
  15. symbol index to a root in the complex number z during iteration. For
  16. loading data, it raises z back up through the root chain. Loading needs
  17. the complex number, the origin number (for termination), and the correct
  18. power, and it can recreate the stored data. It locates each root by
  19. doing a little search in the n-ary roots returned by ct_roots. The
  20. experimental function is ct_try_find. Take note of it because it is key
  21. wrt being able to load the stored data... There has to be a more
  22. efficient way of doing the root search. Humm... For termination, it
  23. compares z iterates to the original number used for storing the information.
  24.  
  25.  
  26. the function ct_store stores n-ary tokens in a single complex number.
  27. the function ct_load loads n-ary tokens from a complex number.
  28.  
  29. The termination condition is iffy and really sensitive to floating point
  30. errors. Its better to store data in strict blocks, so a load knows to
  31. iterate a block length, and then quite. Now it has to compare the
  32. iterates of z to the damn origin. Humm... The can be improved upon.
  33.  
  34. We cannot store too much data here, or one with get a data-incoherent
  35. error, via assertion. I can store the symbols DEADBEEF for sure. ;^)
  36.  
  37. This is where floating point errors can really break things down.
  38.  
  39.  
  40. Btw, I am wondering if you can run it and perhaps post some of the
  41. output? It would be interesting to compare the results I get on to other
  42. systems.
  43.  
  44.  
  45. Before I go on, can anybody run this code? Also, I think this deserved
  46. its own thread? Will get back to the group tomorrow.
  47.  
  48. Thanks everybody.
  49.  
  50. __________________________________________
  51. // 4/12/2017: n-ary complex storage example by Chris M. Thomasson
  52.  
  53. #include <complex>
  54. #include <iostream>
  55. #include <vector>
  56. #include <limits>
  57. #include <algorithm> // reverse
  58. #include <cstdint> // want to work with 64-bit numbers
  59. #include <cassert> // want to sanity check run time...
  60. #include <cstring> // faster than iostream's?
  61.  
  62.  
  63. // Well, I need some consistent typenames... ;^)
  64. typedef std::int64_t ct_int;
  65. typedef std::uint64_t ct_uint;
  66. typedef double ct_float;
  67. typedef std::numeric_limits<ct_float> ct_float_nlim;
  68. typedef std::complex<ct_float> ct_complex;
  69. typedef std::complex<ct_uint> ct_complex_uint;
  70. typedef std::vector<ct_complex> ct_complex_vec;
  71.  
  72. #define CT_PI 3.14159265358979323846
  73.  
  74.  
  75. // Round up and convert the real and imaginary
  76. // parts of z to unsigned integers of type ct_uint
  77. // return a complex number with unsigned integer parts
  78. ct_complex_uint
  79. ct_round_uint(
  80. ct_complex const& z
  81. ) {
  82. ct_uint re = (ct_uint)std::floor(std::abs(z.real()) + .5);
  83. ct_uint im = (ct_uint)std::floor(std::abs(z.imag()) + .5);
  84. return ct_complex_uint(re, im);
  85. }
  86.  
  87.  
  88. // the integer p shall not be zero
  89. // create abs(p) roots of z wrt z^(1/p);
  90. // store them in out, and return the average error.
  91. ct_float
  92. ct_roots(
  93. ct_complex const& z,
  94. ct_int p,
  95. ct_complex_vec& out
  96. ) {
  97. assert(p != 0);
  98.  
  99. // Gain the basics
  100. ct_float radius = std::pow(std::abs(z), 1.0 / p);
  101. ct_float angle_base = std::arg(z) / p;
  102. ct_float angle_step = (CT_PI * 2.0) / p;
  103.  
  104. // Setup the iteration
  105. ct_uint n = std::abs(p);
  106. ct_float avg_err = 0.0;
  107.  
  108. // Calculate the n roots...
  109. for (ct_uint i = 0; i < n; ++i)
  110. {
  111. // our angle
  112. ct_float angle = angle_step * i;
  113.  
  114. // our point
  115. ct_complex c = {
  116. std::cos(angle_base + angle) * radius,
  117. std::sin(angle_base + angle) * radius
  118. };
  119.  
  120. // output data
  121. out.push_back(c);
  122.  
  123. // Raise our root the the power...
  124. ct_complex raised = std::pow(c, p);
  125.  
  126. // Sum up the Go% damn floating point errors!
  127. avg_err = avg_err + std::abs(raised - z);
  128. }
  129.  
  130. // gain the average error sum... ;^o
  131. return avg_err / n;
  132. }
  133.  
  134.  
  135. // Try's to find the target root z out of roots using
  136. // eps, return the index of the root, or -1 for failure.
  137. int
  138. ct_try_find(
  139. ct_complex const& z,
  140. ct_complex_vec const& roots,
  141. ct_float eps
  142. ) {
  143. std::size_t n = roots.size();
  144.  
  145. for (std::size_t i = 0; i < n; ++i)
  146. {
  147. ct_complex const& root = roots[i];
  148.  
  149. ct_float adif = std::abs(root - z);
  150.  
  151. if (adif < eps)
  152. {
  153. return i;
  154. }
  155. }
  156.  
  157. return -1;
  158. }
  159.  
  160.  
  161.  
  162.  
  163.  
  164. // The Token Table
  165. // Will deal with scrambled token vectors in further posts.
  166. // This is global for now, easy to convert to per store/load
  167. // pairs
  168. static std::string const g_tokens_str =
  169. "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  170.  
  171. // Gains the power from the largest token position
  172. // from tokens in g_tokens_str
  173. ct_int
  174. ct_gain_power(
  175. std::string const& tokens
  176. ) {
  177. ct_uint n = tokens.length();
  178.  
  179. std::size_t pmax = 0;
  180.  
  181. for (ct_uint i = 0; i < n; ++i)
  182. {
  183. std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
  184. assert(fridx != std::string::npos);
  185. pmax = std::max(pmax, fridx);
  186. }
  187.  
  188. return (ct_int)(pmax + 1);
  189. }
  190.  
  191.  
  192. // Store tokens using a power of p starting in z-origin
  193. // Return the complex number holding said tokens.
  194. ct_complex
  195. ct_store(
  196. ct_complex const& z_origin,
  197. ct_int p,
  198. std::string const& tokens
  199. ) {
  200. ct_uint n = tokens.length();
  201.  
  202. ct_complex z = z_origin;
  203. ct_float store_avg_err = 0.0;
  204.  
  205. std::cout << "Storing Data..." << "\n";
  206. std::cout << "stored:z_origin:" << z_origin << "\n";
  207.  
  208. for (ct_uint i = 0; i < n; ++i)
  209. {
  210. // Gain all of the roots, and running store error
  211. ct_complex_vec roots;
  212. ct_float avg_err = ct_roots(z, p, roots);
  213. store_avg_err = store_avg_err + avg_err;
  214.  
  215. // reference our root
  216. std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
  217. assert(fridx != std::string::npos);
  218.  
  219. z = roots[fridx];
  220.  
  221. std::cout << "stored[" << i << "]:" << z << "\n";
  222. }
  223.  
  224. store_avg_err = store_avg_err / n;
  225. std::cout << "store_avg_err:" << store_avg_err << "\n";
  226.  
  227. return z;
  228. }
  229.  
  230.  
  231. // Load our tokens from z_store, power of p,
  232. // stopping at z_target using eps, storing tokens
  233. // in out_tokens, and the resulting z in out_z
  234. ct_float
  235. ct_load(
  236. ct_complex const& z_store,
  237. ct_complex const& z_target,
  238. ct_int p,
  239. ct_float eps, // epsilon
  240. std::string& out_tokens,
  241. ct_complex& out_z
  242. ) {
  243. ct_complex z = z_store;
  244. ct_uint n = 128; // max iter
  245. ct_float load_err_sum = 0.0;
  246.  
  247. std::cout << "Loading Data..." << "\n";
  248. for (ct_uint i = 0; i < n; ++i)
  249. {
  250. // raise...
  251. ct_complex z_next = std::pow(z, p);
  252.  
  253. // Gain all of the roots, and running load error
  254. ct_complex_vec roots;
  255. ct_float avg_err = ct_roots(z_next, p, roots);
  256. load_err_sum += avg_err;
  257.  
  258. // try to find our root...
  259. int root_idx = ct_try_find(z, roots, eps);
  260. if (root_idx < 0 ||
  261. (ct_uint)root_idx >= g_tokens_str.length()) break;
  262.  
  263. std::cout << "loaded[" << i << "]:" << z << "\n";
  264.  
  265. out_tokens += g_tokens_str[root_idx];
  266.  
  267. // advance
  268. z = z_next;
  269.  
  270. // check for termination condition...
  271. if (std::abs(z - z_target) < eps)
  272. {
  273. std::cout << "fin detected!:[" << i << "]:" << z << "\n";
  274. break;
  275. }
  276. }
  277.  
  278. // reverse our tokens
  279. std::reverse(out_tokens.begin(), out_tokens.end());
  280.  
  281. out_z = z;
  282. return load_err_sum;
  283. }
  284.  
  285.  
  286. int main()
  287. {
  288. std::cout.precision(ct_float_nlim::max_digits10);
  289.  
  290. std::cout << "g_tokens_str:" << g_tokens_str << "\n\n";
  291.  
  292. {
  293. ct_complex z_origin = { -.75, .06 };
  294.  
  295. // The original data to be stored
  296. std::string stored = "CHRIS";
  297. ct_int power = ct_gain_power(stored);
  298.  
  299. std::cout << "stored:" << stored << "\n";
  300. std::cout << "power:" << power << "\n\n";
  301. std::cout << "________________________________________\n";
  302.  
  303. // STORE
  304. ct_complex z_stored = ct_store(z_origin, power, stored);
  305.  
  306. std::cout << "________________________________________\n";
  307.  
  308.  
  309. std::cout << "\nSTORED POINT:" << z_stored << "\n";
  310.  
  311.  
  312. std::cout << "________________________________________\n";
  313.  
  314. // The data loaded from the stored.
  315. std::string loaded;
  316. ct_complex z_loaded;
  317. ct_float eps = .001; // epsilon
  318.  
  319. // LOAD
  320. ct_float load_err_sum =
  321. ct_load(z_stored, z_origin, power, eps, loaded, z_loaded);
  322.  
  323. std::cout << "________________________________________\n";
  324.  
  325. std::cout << "\nORIGIN POINT:" << z_origin << "\n";
  326. std::cout << "LOADED POINT:" << z_loaded << "\n";
  327.  
  328. std::cout << "\nloaded:" << loaded << "\n"
  329. "load_err_sum:" << load_err_sum << "\n";
  330.  
  331. // make sure everything is okay...
  332. if (stored == loaded)
  333. {
  334. std::cout << "\n\nDATA COHERENT! :^D" << "\n";
  335. }
  336.  
  337. else
  338. {
  339. std::cout << "\n\n***** DATA CORRUPTED!!! Shi%! *****" << "\n";
  340. assert(stored == loaded);
  341. }
  342. }
  343.  
  344. // Fin...
  345. std::cout << "\n\nFin, hit <ENTER> to exit...\n";
  346. std::fflush(stdout);
  347. std::cin.get();
  348.  
  349. return 0;
  350. }
Add Comment
Please, Sign In to add comment