Discussion:
storing/loading n-ary data via complex numbers...
(too old to reply)
Chris M. Thomasson
2017-06-18 23:11:30 UTC
Permalink
Raw Message
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
function described in the following thread:

"n-ary roots from complex numbers..."
https://groups.google.com/d/topic/comp.lang.c++/05XwgswUnDg/discussion

to actually store data. The following code stores my name "CHRIS" from
the following symbol table:

"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

in a single complex number via root map. For storing data, it maps each
symbol index to a root in the complex number z during iteration. For
loading data, it raises z back up through the root chain. Loading needs
the complex number, the origin number (for termination), and the correct
power, and it can recreate the stored data. It locates each root by
doing a little search in the n-ary roots returned by ct_roots. The
experimental function is ct_try_find. Take note of it because it is key
wrt being able to load the stored data... There has to be a more
efficient way of doing the root search. Humm... For termination, it
compares z iterates to the original number used for storing the information.


the function ct_store stores n-ary tokens in a single complex number.
the function ct_load loads n-ary tokens from a complex number.

The termination condition is iffy and really sensitive to floating point
errors. Its better to store data in strict blocks, so a load knows to
iterate a block length, and then quite. Now it has to compare the
iterates of z to the damn origin. Humm... The can be improved upon.

We cannot store too much data here, or one with get a data-incoherent
error, via assertion. I can store the symbols DEADBEEF for sure. ;^)

This is where floating point errors can really break things down.


Btw, I am wondering if you can run it and perhaps post some of the
output? It would be interesting to compare the results I get on to other
systems.


Before I go on, can anybody run this code? Also, I think this deserved
its own thread? Will get back to the group tomorrow.

Thanks everybody.

In C++:
__________________________________________
// 4/12/2017: n-ary complex storage example by Chris M. Thomasson

#include <complex>
#include <iostream>
#include <vector>
#include <limits>
#include <algorithm> // reverse
#include <cstdint> // want to work with 64-bit numbers
#include <cassert> // want to sanity check run time...
#include <cstring> // faster than iostream's?


// Well, I need some consistent typenames... ;^)
typedef std::int64_t ct_int;
typedef std::uint64_t ct_uint;
typedef double ct_float;
typedef std::numeric_limits<ct_float> ct_float_nlim;
typedef std::complex<ct_float> ct_complex;
typedef std::complex<ct_uint> ct_complex_uint;
typedef std::vector<ct_complex> ct_complex_vec;

#define CT_PI 3.14159265358979323846


// Round up and convert the real and imaginary
// parts of z to unsigned integers of type ct_uint
// return a complex number with unsigned integer parts
ct_complex_uint
ct_round_uint(
ct_complex const& z
) {
ct_uint re = (ct_uint)std::floor(std::abs(z.real()) + .5);
ct_uint im = (ct_uint)std::floor(std::abs(z.imag()) + .5);
return ct_complex_uint(re, im);
}


// the integer p shall not be zero
// create abs(p) roots of z wrt z^(1/p);
// store them in out, and return the average error.
ct_float
ct_roots(
ct_complex const& z,
ct_int p,
ct_complex_vec& out
) {
assert(p != 0);

// Gain the basics
ct_float radius = std::pow(std::abs(z), 1.0 / p);
ct_float angle_base = std::arg(z) / p;
ct_float angle_step = (CT_PI * 2.0) / p;

// Setup the iteration
ct_uint n = std::abs(p);
ct_float avg_err = 0.0;

// Calculate the n roots...
for (ct_uint i = 0; i < n; ++i)
{
// our angle
ct_float angle = angle_step * i;

// our point
ct_complex c = {
std::cos(angle_base + angle) * radius,
std::sin(angle_base + angle) * radius
};

// output data
out.push_back(c);

// Raise our root the the power...
ct_complex raised = std::pow(c, p);

// Sum up the Go% damn floating point errors!
avg_err = avg_err + std::abs(raised - z);
}

// gain the average error sum... ;^o
return avg_err / n;
}


// Try's to find the target root z out of roots using
// eps, return the index of the root, or -1 for failure.
int
ct_try_find(
ct_complex const& z,
ct_complex_vec const& roots,
ct_float eps
) {
std::size_t n = roots.size();

for (std::size_t i = 0; i < n; ++i)
{
ct_complex const& root = roots[i];

ct_float adif = std::abs(root - z);

if (adif < eps)
{
return i;
}
}

return -1;
}





// The Token Table
// Will deal with scrambled token vectors in further posts.
// This is global for now, easy to convert to per store/load
// pairs
static std::string const g_tokens_str =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// Gains the power from the largest token position
// from tokens in g_tokens_str
ct_int
ct_gain_power(
std::string const& tokens
) {
ct_uint n = tokens.length();

std::size_t pmax = 0;

for (ct_uint i = 0; i < n; ++i)
{
std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
assert(fridx != std::string::npos);
pmax = std::max(pmax, fridx);
}

return (ct_int)(pmax + 1);
}


// Store tokens using a power of p starting in z-origin
// Return the complex number holding said tokens.
ct_complex
ct_store(
ct_complex const& z_origin,
ct_int p,
std::string const& tokens
) {
ct_uint n = tokens.length();

ct_complex z = z_origin;
ct_float store_avg_err = 0.0;

std::cout << "Storing Data..." << "\n";
std::cout << "stored:z_origin:" << z_origin << "\n";

for (ct_uint i = 0; i < n; ++i)
{
// Gain all of the roots, and running store error
ct_complex_vec roots;
ct_float avg_err = ct_roots(z, p, roots);
store_avg_err = store_avg_err + avg_err;

// reference our root
std::size_t fridx = g_tokens_str.find_first_of(tokens[i]);
assert(fridx != std::string::npos);

z = roots[fridx];

std::cout << "stored[" << i << "]:" << z << "\n";
}

store_avg_err = store_avg_err / n;
std::cout << "store_avg_err:" << store_avg_err << "\n";

return z;
}


// Load our tokens from z_store, power of p,
// stopping at z_target using eps, storing tokens
// in out_tokens, and the resulting z in out_z
ct_float
ct_load(
ct_complex const& z_store,
ct_complex const& z_target,
ct_int p,
ct_float eps, // epsilon
std::string& out_tokens,
ct_complex& out_z
) {
ct_complex z = z_store;
ct_uint n = 128; // max iter
ct_float load_err_sum = 0.0;

std::cout << "Loading Data..." << "\n";
for (ct_uint i = 0; i < n; ++i)
{
// raise...
ct_complex z_next = std::pow(z, p);

// Gain all of the roots, and running load error
ct_complex_vec roots;
ct_float avg_err = ct_roots(z_next, p, roots);
load_err_sum += avg_err;

// try to find our root...
int root_idx = ct_try_find(z, roots, eps);
if (root_idx < 0 ||
(ct_uint)root_idx >= g_tokens_str.length()) break;

std::cout << "loaded[" << i << "]:" << z << "\n";

out_tokens += g_tokens_str[root_idx];

// advance
z = z_next;

// check for termination condition...
if (std::abs(z - z_target) < eps)
{
std::cout << "fin detected!:[" << i << "]:" << z << "\n";
break;
}
}

// reverse our tokens
std::reverse(out_tokens.begin(), out_tokens.end());

out_z = z;
return load_err_sum;
}


int main()
{
std::cout.precision(ct_float_nlim::max_digits10);

std::cout << "g_tokens_str:" << g_tokens_str << "\n\n";

{
ct_complex z_origin = { -.75, .06 };

// The original data to be stored
std::string stored = "CHRIS";
ct_int power = ct_gain_power(stored);

std::cout << "stored:" << stored << "\n";
std::cout << "power:" << power << "\n\n";
std::cout << "________________________________________\n";

// STORE
ct_complex z_stored = ct_store(z_origin, power, stored);

std::cout << "________________________________________\n";


std::cout << "\nSTORED POINT:" << z_stored << "\n";


std::cout << "________________________________________\n";

// The data loaded from the stored.
std::string loaded;
ct_complex z_loaded;
ct_float eps = .001; // epsilon

// LOAD
ct_float load_err_sum =
ct_load(z_stored, z_origin, power, eps, loaded, z_loaded);

std::cout << "________________________________________\n";

std::cout << "\nORIGIN POINT:" << z_origin << "\n";
std::cout << "LOADED POINT:" << z_loaded << "\n";

std::cout << "\nloaded:" << loaded << "\n"
"load_err_sum:" << load_err_sum << "\n";

// make sure everything is okay...
if (stored == loaded)
{
std::cout << "\n\nDATA COHERENT! :^D" << "\n";
}

else
{
std::cout << "\n\n***** DATA CORRUPTED!!! Shi%! *****" << "\n";
assert(stored == loaded);
}
}

// Fin...
std::cout << "\n\nFin, hit <ENTER> to exit...\n";
std::fflush(stdout);
std::cin.get();

return 0;
}
__________________________________________


Fwiw, here are the outputs of the ct_store function I am getting from
two different compilers, MSVC and GCC:


MSVC 2015
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.8460152306934853e-15
________________________________________


GCC version 5.1.0 (tdm64-1)
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.8460152306934853e-15
________________________________________


If you run this and get different numbers, I would be interested in
looking at them. For instance, when this is executed online at:

http://cpp.sh I get:
________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.89756758958883731,0.41826246336621364)
stored[1]:(-0.8048304823068565,-0.59293470672819726)
stored[2]:(0.86792869817386908,-0.49666532554878623)
stored[3]:(-0.73820338609537295,-0.67457761324417354)
stored[4]:(0.95549545746010056,-0.29500576779591425)
store_avg_err:6.1392213260039921e-15
________________________________________

The store_avg_err is different!


Sorry for the crude nature of my technique. I am hoping readers here can
help me create a more concise, mathematical description.

thank you everybody.

Also, I am doing this in my free time. I wish I had more of it!

;^o
Chris M. Thomasson
2017-06-18 23:19:07 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
"n-ary roots from complex numbers..."
https://groups.google.com/d/topic/comp.lang.c++/05XwgswUnDg/discussion
to actually store data. The following code stores my name "CHRIS" from
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
in a single complex number via root map. For storing data, it maps each
symbol index to a root in the complex number z during iteration. For
loading data, it raises z back up through the root chain. Loading needs
the complex number, the origin number (for termination), and the correct
power, and it can recreate the stored data. It locates each root by
doing a little search in the n-ary roots returned by ct_roots. The
experimental function is ct_try_find. Take note of it because it is key
wrt being able to load the stored data... There has to be a more
efficient way of doing the root search. Humm... For termination, it
compares z iterates to the original number used for storing the information.
[...]
Post by Chris M. Thomasson
Before I go on, can anybody run this code? Also, I think this deserved
its own thread? Will get back to the group tomorrow.
Thanks everybody.
__________________________________________
[...]

Yikes! I forgot to mention that the code needs a C++ 11 compiler!

Sorry about that non-sense. ;^o
Chris M. Thomasson
2017-06-18 23:40:21 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
"n-ary roots from complex numbers..."
https://groups.google.com/d/topic/comp.lang.c++/05XwgswUnDg/discussion
to actually store data. The following code stores my name "CHRIS" from
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
[...]
Post by Chris M. Thomasson
int main()
{
std::cout.precision(ct_float_nlim::max_digits10);
std::cout << "g_tokens_str:" << g_tokens_str << "\n\n";
{
ct_complex z_origin = { -.75, .06 };
// The original data to be stored
std::string stored = "CHRIS";
ct_int power = ct_gain_power(stored);
Just wanted to point out that it also works with negative powers. Change
the line above to:

ct_int power = -ct_gain_power(stored);

and gain the following output:
____________________________
g_tokens_str:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

stored:CHRIS
power:-29

________________________________________
Storing Data...
stored:z_origin:(-0.75,0.059999999999999998)
stored[0]:(-0.91535190113321718,-0.42654987262887645)
stored[1]:(-0.90085434620944727,0.4333418034400674)
stored[2]:(0.94261448083215615,0.33391805934019758)
stored[3]:(-0.71787193351114498,0.69617460640980755)
stored[4]:(0.99091689566132868,0.13447577340611339)
store_avg_err:5.8101727921743071e-015
________________________________________

STORED POINT:(0.99091689566132868,0.13447577340611339)
________________________________________
Loading Data...
loaded[0]:(0.99091689566132868,0.13447577340611339)
loaded[1]:(-0.71787193351113965,0.69617460640981532)
loaded[2]:(0.94261448083202337,0.333918059340434)
loaded[3]:(-0.90085434620729132,0.43334180344764223)
loaded[4]:(-0.91535190100158148,-0.42654987281836065)
fin detected!:[4]:(-0.75000000045429771,0.060000004964319696)
________________________________________

ORIGIN POINT:(-0.75,0.059999999999999998)
LOADED POINT:(-0.75000000045429771,0.060000004964319696)

loaded:CHRIS
load_err_sum:2.8591789162085673e-014


DATA COHERENT! :^D
____________________________

Perry nice!
Bill
2017-06-19 04:29:48 UTC
Permalink
Raw Message
The roots of complex numbers like z^n+c, or even just z^n can store data.
"Coding theory" is an old and broad topic, and is still of current
interest--and not just among mathematicians! ; )
Chris M. Thomasson
2017-06-19 19:39:51 UTC
Permalink
Raw Message
Post by Bill
The roots of complex numbers like z^n+c, or even just z^n can store data.
"Coding theory" is an old and broad topic, and is still of current
interest--and not just among mathematicians! ; )
This is exactly what I am doing here Bill: Trying to code multiple
symbols into the roots of a complex number. I need some help wrt
describing the technique in a mathematical way instead of using C++, or
any other programming language!

Let's take z^n as an example, where z is a complex number and n is an
integer power. z^n has abs(n) roots in the form of z^(1/n). Each of the
n roots can directly map into a symbol table for storing actual data.
Loading data raises the final resulting root back up through the root
chain to recreate the data. Floating point precision issues aside for a
moment, this actually works.

I am having some trouble thinking about how to properly express my
program in something other than a programming language. I need some help!
Julio Di Egidio
2017-06-19 20:34:13 UTC
Permalink
Raw Message
On Monday, June 19, 2017 at 9:40:05 PM UTC+2, Chris M. Thomasson wrote:
<snip>
Post by Chris M. Thomasson
Let's take z^n as an example, where z is a complex number and n is an
integer power. z^n has abs(n) roots in the form of z^(1/n). Each of the
n roots can directly map into a symbol table for storing actual data.
A map is a function from something to something. It is unclear (to me at
least) what you are talking about.
Post by Chris M. Thomasson
Loading data raises the final resulting root back up through the root
chain to recreate the data. Floating point precision issues aside for a
moment, this actually works.
I am having some trouble thinking about how to properly express my
program in something other than a programming language. I need some help!
Can you provide an informal description? Maybe just a function declaration,
with explanation of input arguments and of the expected results.

Julio
Chris M. Thomasson
2017-06-20 19:10:24 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Let's take z^n as an example, where z is a complex number and n is an
integer power. z^n has abs(n) roots in the form of z^(1/n). Each of the
n roots can directly map into a symbol table for storing actual data.
A map is a function from something to something. It is unclear (to me at
least) what you are talking about.
Post by Chris M. Thomasson
Loading data raises the final resulting root back up through the root
chain to recreate the data. Floating point precision issues aside for a
moment, this actually works.
I am having some trouble thinking about how to properly express my
program in something other than a programming language. I need some help!
Can you provide an informal description? Maybe just a function declaration,
with explanation of input arguments and of the expected results.
I am mapping symbols to roots. Let me attempt to give a very crude high
level, simple description of storing data a go here. Okay, pick any
complex number Z[0], except for (0, 0). Now, think of some symbols to
store, say 012. That's three symbols, so we are storing 3-ary data. Lets
say that S[0...2] maps to each one where S[0] = 0, S[1] = 1 and S[2] =
2. Fine.

Lets take the 3 roots of Z[0], as R_0[0...2] such that raising any R_0
to the power of 3 gains Z[0]. Now, we map S[0] to R_0[0]. Lets set Z[1]
equal to R_0[0]. We just stored the first symbol in S via Z[1]. Nice.

Now, we take the 3 roots of Z[1] as R_1[0...2] such that raising any R_1
to the power of 3 gains Z[1]. We map S[1] to R_1[1] as Z[2]. We just
stored the second symbol in S as Z[2], fine.

Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.

The final stored point is Z[3] for it contains the 3 symbols in S.

That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.

Does this make any sense to anybody? Is my high level description total
garbage? I know the procedure works, I need some help on how to properly
describe it mathematically. This is why I posted it to this group in the
first place.
Julio Di Egidio
2017-06-21 09:43:06 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient. It is really akin to mapping
any given string to a node of a tree whose branching is equal to the
size of the alphabet and whose depth at that node is equal to the
length of the string. If you think it that way, it becomes apparent
that using complex numbers (or real) will just make things more difficult:
it is easier, an just as efficient I think, to code a node as a sequence of
indexes in the alphabet for each character; and then it may be apparent that
we can do as well with the simplest coding scheme: just take the binary
representation of the string... If I may am not missing anything.

Julio
Julio Di Egidio
2017-06-21 11:32:21 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient [...]: just take the binary
representation of the string... If I may am not missing anything.
On the other hand, there may be a lossy scheme lurking there...
Have you tried, with the crudest implementation based on the built-in
floating point, what happens when coding-decoding strings of various
lengths? How much "error" do you seem to get? That might be interesting
to investigate.

Julio
Chris M. Thomasson
2017-06-21 20:01:54 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Julio Di Egidio
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient [...]: just take the binary
representation of the string... If I may am not missing anything.
On the other hand, there may be a lossy scheme lurking there...
Oh yes. I think so. Storing too much data will start to give errors on
the last bits when loading it back. Also, wrt loading data, I am
comparing the previous roots to the subsequent roots to allow for
termination of the iteration process. Now, we can use a block method
where we store a fixed block of data and eliminate the comparison of the
raised roots to the original Z[0], so to speak.
Post by Julio Di Egidio
Have you tried, with the crudest implementation based on the built-in
floating point, what happens when coding-decoding strings of various
lengths? How much "error" do you seem to get? That might be interesting
to investigate.
Never really measured the error ratios, damn it! I really need to do
that Julio. Wrt storing too much data, the first part of the symbols are
correct, then things start to softly "break down". I can store around
60-ish bits of data in a complex number with two 64-bit parts. However,
it really depends on the nature of the data. I remember that in binary,
if there are a lot of 0's or 1's in a row, well, then it can actually
start to compress data. Not by much, but it can. I will work on an
example when I get some more time. Perhaps today or sometime tomorrow.

Anyway, thank you for taking the time to take a look at this crazy
stuff! Well, perhaps not so crazy since I have a crude working program
of my highly experimental technique...

;^)
Chris M. Thomasson
2017-06-27 06:48:58 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Julio Di Egidio
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient [...]: just take the binary
representation of the string... If I may am not missing anything.
On the other hand, there may be a lossy scheme lurking there...
Oh yes. I think so. Storing too much data will start to give errors on
the last bits when loading it back. Also, wrt loading data, I am
comparing the previous roots to the subsequent roots to allow for
termination of the iteration process. Now, we can use a block method
where we store a fixed block of data and eliminate the comparison of the
raised roots to the original Z[0], so to speak.
Post by Julio Di Egidio
Have you tried, with the crudest implementation based on the built-in
floating point, what happens when coding-decoding strings of various
lengths? How much "error" do you seem to get? That might be interesting
to investigate.
Never really measured the error ratios, damn it! I really need to do
that Julio. Wrt storing too much data, the first part of the symbols are
correct, then things start to softly "break down". I can store around
60-ish bits of data in a complex number with two 64-bit parts. However,
it really depends on the nature of the data. I remember that in binary,
if there are a lot of 0's or 1's in a row, well, then it can actually
start to compress data. Not by much, but it can. I will work on an
example when I get some more time. Perhaps today or sometime tomorrow.
Anyway, thank you for taking the time to take a look at this crazy
stuff! Well, perhaps not so crazy since I have a crude working program
of my highly experimental technique...
;^)
Wrt to compressing a shi% load of zeros and some ones here and there,
look here:

https://github.com/ChrisMThomasson/fractal_cipher/blob/master/RIFC/cpp/ct_rifc_sample.cpp

Fairly interesting to me.
Chris M. Thomasson
2017-06-27 06:50:15 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Julio Di Egidio
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient [...]: just take the binary
representation of the string... If I may am not missing anything.
On the other hand, there may be a lossy scheme lurking there...
Oh yes. I think so. Storing too much data will start to give errors on
the last bits when loading it back. Also, wrt loading data, I am
comparing the previous roots to the subsequent roots to allow for
termination of the iteration process. Now, we can use a block method
where we store a fixed block of data and eliminate the comparison of
the raised roots to the original Z[0], so to speak.
Post by Julio Di Egidio
Have you tried, with the crudest implementation based on the built-in
floating point, what happens when coding-decoding strings of various
lengths? How much "error" do you seem to get? That might be interesting
to investigate.
Never really measured the error ratios, damn it! I really need to do
that Julio. Wrt storing too much data, the first part of the symbols
are correct, then things start to softly "break down". I can store
around 60-ish bits of data in a complex number with two 64-bit parts.
However, it really depends on the nature of the data. I remember that
in binary, if there are a lot of 0's or 1's in a row, well, then it
can actually start to compress data. Not by much, but it can. I will
work on an example when I get some more time. Perhaps today or
sometime tomorrow.
Anyway, thank you for taking the time to take a look at this crazy
stuff! Well, perhaps not so crazy since I have a crude working program
of my highly experimental technique...
;^)
Wrt to compressing a shi% load of zeros and some ones here and there,
YIKES! the code has ones. However, that many zeros in a row works as well.
Post by Chris M. Thomasson
https://github.com/ChrisMThomasson/fractal_cipher/blob/master/RIFC/cpp/ct_rifc_sample.cpp
Fairly interesting to me.
Chris M. Thomasson
2017-06-21 19:50:46 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
In the detail, there are a couple of errors there, but never mind.
Post by Julio Di Egidio
Return T.
We need to know ... ???
-----------------
There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
It's clever, it's also great to play with complex numbers, but I think
eventually that scheme is not efficient.
Its not efficient. However, I do agree with you that its a pretty neat
way to think of complex numbers.
Post by Julio Di Egidio
It is really akin to mapping
any given string to a node of a tree whose branching is equal to the
size of the alphabet and whose depth at that node is equal to the
length of the string.
Thinking of the roots of complex numbers as a tree is a perfect way of
explaining the overall technique. Thank you.
Post by Julio Di Egidio
If you think it that way, it becomes apparent
it is easier, an just as efficient I think, to code a node as a sequence of
indexes in the alphabet for each character; and then it may be apparent that
we can do as well with the simplest coding scheme: just take the binary
representation of the string... If I may am not missing anything.
I started with binary, and moved onto n-ary simply because I thought its
fairly interesting. We map n-ary data to the roots of a tree for storing
data, then we compare the previous values to the node values of the
level, or subsequent nodes, to load data in reverse order. Actually,
when we use binary, we can use the sign of the real part to gain the
on/off nature of binary wrt loading data.
Julio Di Egidio
2017-06-20 21:50:33 UTC
Permalink
Raw Message
On Tuesday, June 20, 2017 at 9:10:31 PM UTC+2, Chris M. Thomasson wrote:
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
OK, maybe I get it, here is a first attempt:

-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.

Given any string S over A, ***to map S to complex T***:
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
Return T.

Given any complex T obtained as above, ***to map T to string S***:
We need to know ... ???
-----------------

There I have stopped, not only with the problem of finding a clever way for
the second function, but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...

Julio
Chris M. Thomasson
2017-06-21 19:38:55 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Finally, we take the 3 roots of Z[2] as R_2[0...2] such that raising any
R_2 to the power of 3 gains Z[2]. We map S[2] to R_2[2] as Z[3]. We just
stored the third and final symbol in S as Z[3], fine.
The final stored point is Z[3] for it contains the 3 symbols in S.
That is how I am storing data in complex numbers. I will write the
procedure for loading the symbols from Z[3] sometime today.
-----------------
Let A be an (ordered) alphabet of size N.
Let Z be a non-zero complex number.
Let T := Z;
For every symbol C := S[I] in S: // i.e. for I = 1 to length(S)
Let T := Roots^N(T)[I] // i.e. the I-th N-th-root of T
Return T.
We need to know ... ???
-----------------
Thank you for that Julio. I see what you are getting at in that compact
description.
Post by Julio Di Egidio
There I have stopped, not only with the problem of finding a clever way for
the second function,
Here is how I am loading the symbols back from Z[3], or T in your example.

We raise Z[3] to the power of 3 to get Z[2]. Now we take the 3 roots of
Z[2] as R_2[0...2]. We search for Z[3] in R_2[0...2] and find that Z[3]
is equal to R_2[2], the index is 2. So, we know that S[2] is the last
symbol. Lets map that to a new string L[0...2] where L[0] = S[2]. We
compare Z[2] to Z[0], notice that its not equal and continue. Fine.

Now, we raise Z[2] to the power of 3 to get Z[1]. We take the three
roots of Z[1] as R_1[0...2], perform a search in R_1 for Z[2]. We find
that that Z[2] is equal to R_1[1], the index is 1. Therefore, we map
L[1] to S[1]. We compare Z[1] to Z[0], find that is not equal and continue.

Okay. We raise Z[1] to the power of 3 to get Z[0], the "original" Z so
to speak. Take the 3 roots of Z[0] as R_0[0...2] and search it for Z[1].
We find that R_0[0] is equal to Z[1], index 0, and map L[2] to S[0].
Then we compare Z[0] to Z[0], fine that it is indeed equal, and quit.

Now, we have L[0...2] as "210". We reverse L to gain "012", and we have
the original stored data.

This is a very crude explanation, and the code can be much better, but
this is how I am doing it for now. I have some ideas on how to make it
much more efficient!

The storing and loading of symbols are the ct_store and ct_load
functions in my crude C++ code. The function that searches for roots in
the loading part is my ct_try_find function.
Post by Julio Di Egidio
but also with the problem indeed of how to handle the
unavoidable rounding errors: using "complex rationals" won't cut it, as
taking roots is irrational per se, but maybe suitable Z could do the trick,
at least in case there is an absolute maximum length for the strings... etc.
I should think more about it...
Yes: There is a definite limit wrt the amount of symbols we can store! I
am not really worried about that right now because this is, imvvho, a
fairly interesting and highly experimental way to store data. Its not
meant to be compression in any way shape or form, and its not meant to
be efficient. Actually, I am playing around with it as a toy form of
encryption.

I just wanted to get smarter eyes on my technique. Thank you for taking
a look Julio. I really do appreciate it.

:^D
Julio Di Egidio
2017-06-21 21:01:00 UTC
Permalink
Raw Message
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
There I have stopped, not only with the problem of finding a clever way for
the second function,
Here is how I am loading the symbols back from Z[3], or T in your example.
[...]
OK, that was clear and simple.
Post by Chris M. Thomasson
Yes: There is a definite limit wrt the amount of symbols we can store! I
am not really worried about that right now because this is, imvvho, a
fairly interesting and highly experimental way to store data. Its not
meant to be compression in any way shape or form, and its not meant to
be efficient. Actually, I am playing around with it as a toy form of
encryption.
But if it's not efficient (lossless or not), it is not really of interest:
IOW, for coding schemes, it is all about efficiency! (And I am not talking
about fine optimisation: the approach should at least be promising.)

In fact, there are really two separate levels of analysis:

- the "pure" approach with the mathematical complex numbers: there you have
a nice scheme that maps any (finite) string to one and only one complex
number: but the reason why it works, lossless and on strings of any length,
is because real numbers are infinite objects to begin with;

- the "feasible" approach with some effective numbers: here, to reiterate,
I do not think your approach can beat any of the known coding schemes, it's
in fact quite inefficient, while I still think a lossy version might be
worth investigating... -- You know, there may be clever ways to recover
exactness (*), still it won't be more efficient than the simplest binary
encoding of a string.

(*) Suitable Z might do some magic: for example, "on the complex plane
the nth roots of unity are at the vertices of a regular n-sided polygon
inscribed in the unit circle", which, if I am not mistaken, means we can
in fact use the rationals (pairs of integers) and, at least in the context
of arbitrary precision, we recover exact results. As said, it won't be
efficient though: the numbers involved will grow big with the strings.
<https://en.wikipedia.org/wiki/Root_of_unity#Group_of_nth_roots_of_unity>
Post by Chris M. Thomasson
I just wanted to get smarter eyes on my technique. Thank you for taking
a look Julio. I really do appreciate it.
You are very welcome, Chris, and thank you for sharing this interesting
problem.

Julio
Chris M. Thomasson
2017-06-22 18:28:45 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
There I have stopped, not only with the problem of finding a clever way for
the second function,
Here is how I am loading the symbols back from Z[3], or T in your example.
[...]
OK, that was clear and simple.
Post by Chris M. Thomasson
Yes: There is a definite limit wrt the amount of symbols we can store! I
am not really worried about that right now because this is, imvvho, a
fairly interesting and highly experimental way to store data. Its not
meant to be compression in any way shape or form, and its not meant to
be efficient. Actually, I am playing around with it as a toy form of
encryption.
IOW, for coding schemes, it is all about efficiency! (And I am not talking
about fine optimisation: the approach should at least be promising.)
The crappy efficiency isn't really a problem for me right now. I am
having fun experimenting with the technique. When I get some more time
sometime today or tomorrow, I will show you how it relates to Julia set
fractals in the form of z^n+c. When we store data in the roots of the
form of (z-c)^(1/n) and plot the complex numbers, the result is a nice
Julia set related to c: I personally find this aspect to be really
fascinating! Take a look at:

https://en.wikipedia.org/wiki/Julia_set#Using_backwards_.28inverse.29_iteration_.28IIM.29

We can use fractals to store information. All I did was figure out how
to store n-ary data in the tree of roots, and load them back up again.
If n is 2 we gain the power of 2 Julias wrt c, if we use n=5 we get
power of 5 Julias in the plot. Imvvho, that's pretty neat. I will show a
C99 program that stores data and outputs a PPM image to visually show
the plot.
Post by Julio Di Egidio
- the "pure" approach with the mathematical complex numbers: there you have
a nice scheme that maps any (finite) string to one and only one complex
number: but the reason why it works, lossless and on strings of any length,
is because real numbers are infinite objects to begin with;
Agreed. Well, if precision loss did not exist, we can store infinite
data in a single complex number. However, we do lose precision in the
real world of computing. So, what I just wrote is deep in the realm of
fantasy land. Arbitrary precision aside for a moment.
Post by Julio Di Egidio
- the "feasible" approach with some effective numbers: here, to reiterate,
I do not think your approach can beat any of the known coding schemes, it's
in fact quite inefficient, while I still think a lossy version might be
worth investigating... -- You know, there may be clever ways to recover
exactness (*), still it won't be more efficient than the simplest binary
encoding of a string.
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.

;^)
Post by Julio Di Egidio
(*) Suitable Z might do some magic: for example, "on the complex plane
the nth roots of unity are at the vertices of a regular n-sided polygon
inscribed in the unit circle", which, if I am not mistaken, means we can
in fact use the rationals (pairs of integers) and, at least in the context
of arbitrary precision, we recover exact results. As said, it won't be
efficient though: the numbers involved will grow big with the strings.
<https://en.wikipedia.org/wiki/Root_of_unity#Group_of_nth_roots_of_unity>
I think this will work for the first iteration with a magic Z. However,
the integers should break down into the decimal realm after more
iterations. Ahhh, you mentioned arbitrary precision. Well, then we can
store as much data in a single complex number as the memory on the
system we are using to compute the iteration allows.

I have experimented with arbitrary precision, and the complex numbers
get really, really huge depending on the length of the stored symbols.
However, they do gain exact precision when loading the stored data back.
Post by Julio Di Egidio
Post by Chris M. Thomasson
I just wanted to get smarter eyes on my technique. Thank you for taking
a look Julio. I really do appreciate it.
You are very welcome, Chris, and thank you for sharing this interesting
problem.
No problem. :^)

Thanks again.
Chris M. Thomasson
2017-06-22 19:10:45 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
There I have stopped, not only with the problem of finding a clever way for
the second function,
Here is how I am loading the symbols back from Z[3], or T in your example.
[...]
OK, that was clear and simple.
Post by Chris M. Thomasson
Yes: There is a definite limit wrt the amount of symbols we can store! I
am not really worried about that right now because this is, imvvho, a
fairly interesting and highly experimental way to store data. Its not
meant to be compression in any way shape or form, and its not meant to
be efficient. Actually, I am playing around with it as a toy form of
encryption.
IOW, for coding schemes, it is all about efficiency! (And I am not talking
about fine optimisation: the approach should at least be promising.)
[...]

Just one more point... Notice how I am comparing the Z[n] to the
original Z[0] during loading for sole purpose of termination of the
iterative process? Well, this can be turned into a block where we store
n-ary data as a fixed block, as in fixed number of iterations for
loading and storing. The error that arises wrt storing too much data can
be fixed wrt loading them back up. The error rate can be fixed. So,
instead of my load procedure loading up many errors because it cannot
find the end due to precision errors can be cut off at the fixed block
length. Its a limiting feature that turns it into a block cipher.

I am experimenting with this.
Julio Di Egidio
2017-06-23 13:07:24 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.
I know that, I am a subscriber of yours on G+. :) I'll be looking
forward to those Julia sets, and I start seeing how you could use this
for cryptography. Indeed, I'll try your code and play with some code
myself, but next week, I'm totally busy till Monday...

Julio
Chris M. Thomasson
2017-06-23 17:37:36 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Chris M. Thomasson
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.
I know that, I am a subscriber of yours on G+. :) I'll be looking
forward to those Julia sets, and I start seeing how you could use this
for cryptography. Indeed, I'll try your code and play with some code
myself, but next week, I'm totally busy till Monday...
Fwiw, here is the start of the storm, wrt Richards comment, well, not
quite for I am still using complex numbers with real numbers as parts.
Gaining the base of a number in reverse order is just the beginning. As
you know, my complex loading procedure reverses the symbols anyway. So,
if I store n-ary data in reverse form, the load will reverse that
directly into correct form! Cool. Here is some initial code in my base
conversion C program, just part of my complex number fractal cipher PPM
plotter:
______________________________
#include <stdio.h>
#include <stdlib.h>

typedef signed long ct_int;
typedef unsigned long ct_uint;

#define CT_SYMBOLS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

/* converts v to base b using symbol table s in a block n.
the order is reversed, however the load will fix that...
__________________________________________________*/
void
ct_base_block(
ct_uint v,
ct_uint b,
char const* s,
ct_uint n
) {
ct_uint t = v;
size_t l = strlen(s);

for (ct_uint i = 0; i < n; ++i)
{
ct_uint d = t / b;
ct_uint r = t - d * b;
if (r > l)
{
printf("\nsymbol table size error!");
break;
}
printf("%c", s[r]);
//printf("%lu", r);
t = d;
}

printf("\n");
}


int main(int argc, char *argv[])
{
ct_base_block(999, 17, CT_SYMBOLS, 16);

return 0;
}
______________________________

The output is:
______________________________
D730000000000000
______________________________

And when we reverse this base 17 to:

000000000000037D

Well, its equal to 999 in base 10!

All of the zeros can add to the beauty of the fractal. Sometimes, they
will gain spirals, and other wonderful Julia set artifacts.

I am going to use ct_base_block to store a block of data in the fractal.
Each complex number will store one of these blocks. Now, this is in
reverse order. Fine for the loading of the block will reverse it for me
back into normal working order!

The symbol table is there just so we can see the damn things. This will
be directly embedded into the store procedure. Will have the plotter wrt
store/load in complex roots working today or tomorrow.

Yes, I know that this is a Friday, but this is so much fun!

;^)
Chris M. Thomasson
2017-06-23 17:49:51 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Chris M. Thomasson
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.
I know that, I am a subscriber of yours on G+. :) I'll be looking
forward to those Julia sets, and I start seeing how you could use this
for cryptography. Indeed, I'll try your code and play with some code
myself, but next week, I'm totally busy till Monday...
Fwiw, here is the start of the storm, wrt Richards comment, well, not
quite for I am still using complex numbers with real numbers as parts.
Gaining the base of a number in reverse order is just the beginning. As
you know, my complex loading procedure reverses the symbols anyway. So,
if I store n-ary data in reverse form, the load will reverse that
directly into correct form! Cool. Here is some initial code in my base
conversion C program, just part of my complex number fractal cipher PPM
______________________________
#include <stdio.h>
#include <stdlib.h>
typedef signed long ct_int;
typedef unsigned long ct_uint;
#define CT_SYMBOLS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
/* converts v to base b using symbol table s in a block n.
the order is reversed, however the load will fix that...
__________________________________________________*/
void
ct_base_block(
ct_uint v,
ct_uint b,
char const* s,
ct_uint n
) {
ct_uint t = v;
size_t l = strlen(s);
for (ct_uint i = 0; i < n; ++i)
{
ct_uint d = t / b;
ct_uint r = t - d * b;
if (r > l)
^^^^^^^^^^^^^^^^^^^^
[...]

Yikes! For some moronic reason, I forgot about the NULL in C strings.
The if condition in the code above should be:

if (r >= l)

ARGH! So sorry for the bugger!

Corrected function:
___________________________
ct_base_block(
ct_uint v,
ct_uint b,
char const* s,
ct_uint n
) {
ct_uint t = v;
size_t l = strlen(s);

for (ct_uint i = 0; i < n; ++i)
{
ct_uint d = t / b;
ct_uint r = t - d * b;
if (r >= l)
{
printf("\nsymbol table size error!");
break;
}
printf("%c", s[r]);
//printf("%lu", r);
t = d;
}

printf("\n");
}
___________________________

DAMN IT TO HECK! ;^o
Chris M. Thomasson
2017-06-23 18:07:39 UTC
Permalink
Raw Message
[...]

Fwiw, I am going to use my following PPM plotter for the graphics:

https://groups.google.com/d/topic/comp.lang.c/YnEcpH-vRxw/discussion

Output PPM is: ct_cipher_rifc.ppm

Here is the graphic rendered as a jpg:

Loading Image...

Imvvho, a decent visualization of a location in the Seahorse Valley
power of 2 Julia set. The spirals are there due to the drastic weight
differential wrt plotting random roots of (z-c)^(1/n).

C99 code:
_____________________________________
/* Chris M. Thomasson RIFC Renderer ver:0.0.0.0 (pre-alpha)
5/13/2017 - Raw Hyper Experimental
_________________________________________________*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>
#include <stdbool.h>


#define CT_RAND() (rand() / (RAND_MAX - 0.0))


struct ct_axes
{
double xmin;
double xmax;
double ymin;
double ymax;
};


struct ct_canvas
{
unsigned long width;
unsigned long height;
unsigned char* buf;
};

bool
ct_canvas_create(
struct ct_canvas* const self,
unsigned long width,
unsigned long height
){
size_t size = width * height;

self->buf = calloc(1, size);

if (self->buf)
{
self->width = width;
self->height = height;

return true;
}

return false;
}

void
ct_canvas_destroy(
struct ct_canvas const* const self
){
free(self->buf);
}

bool
ct_canvas_save_ppm(
struct ct_canvas const* const self,
char const* fname
){
FILE* fout = fopen(fname, "w");

if (fout)
{
char const ppm_head[] =
"P3\n"
"# Chris M. Thomasson RIFC Cipher Renderer ver:0.0.0.0
(pre-alpha)";

fprintf(fout, "%s\n%lu %lu\n%u\n",
ppm_head,
self->width, self->height,
255U);

size_t size = self->width * self->height;

for (size_t i = 0; i < size; ++i)
{
unsigned int c = self->buf[i];
fprintf(fout, "%u %u %u ", c, 0U, 0U);
}

if (! fclose(fout))
{
return true;
}
}

return false;
}


struct ct_plane
{
struct ct_axes axes;
struct ct_canvas* canvas;
};

size_t
ct_plane_project(
struct ct_plane const* const self,
double complex c
){
double awidth = self->axes.xmax - self->axes.xmin;
double aheight = self->axes.ymax - self->axes.ymin;

double xstep = awidth / (self->canvas->width - 1.0);
double ystep = aheight / (self->canvas->height - 1.0);

size_t x = (creal(c) - self->axes.xmin) / xstep;
size_t y = (self->axes.ymax - cimag(c)) / ystep;

size_t i = x + y * self->canvas->height;

return i;
}

bool
ct_plane_plot(
struct ct_plane* const self,
double complex c,
unsigned char color
){
size_t cp = ct_plane_project(self, c);

if (cp < self->canvas->height * self->canvas->width)
{
self->canvas->buf[cp] = color;
return true;
}

return false;
}


void
ct_ifs(
struct ct_plane* const self,
double complex z,
double complex c,
double ratio,
unsigned long n
){
printf("ct_ifs: %lf%+lfi, ratio:%lf\n", creal(c), cimag(c), ratio);

for (unsigned long i = 0; i < n; ++i)
{
double complex d = z - c;
double complex root = csqrt(d);

z = root;

if (CT_RAND() > ratio)
{
z = -root;
}

ct_plane_plot(self, z, 255);
ct_plane_plot(self, root, 255);

if (! (i % 256))
{
printf("rendering: %lu of %lu\r", i + 1, n);
}
}

printf("rendering: %lu of %lu\n", n, n);
}


#define CT_WIDTH 1024
#define CT_HEIGHT 1024
#define CT_N 10000000

int main(void)
{
struct ct_canvas canvas;

bool status = ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT);
assert(status);

struct ct_axes axes = { -2.0, 2.0, -2.0, 2.0 };
struct ct_plane plane = { axes, &canvas };

double complex z = 0+0*I;
//double complex c = -.75+.06*I;
double complex c = -.75+.06*I;
double ratio = .04;

ct_ifs(&plane, z, c, ratio, CT_N);

status = ct_canvas_save_ppm(&canvas, "ct_cipher_rifc.ppm");
assert(status);
printf("\ncreated: ct_cipher_rifc.ppm\n");

ct_canvas_destroy(&canvas);

return 0;
}
_____________________________________
FromTheRafters
2017-06-24 13:01:58 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Chris M. Thomasson
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.
I know that, I am a subscriber of yours on G+. :) I'll be looking
forward to those Julia sets, and I start seeing how you could use this
for cryptography. Indeed, I'll try your code and play with some code
myself, but next week, I'm totally busy till Monday...
Fwiw, here is the start of the storm, wrt Richards comment, well, not quite
for I am still using complex numbers with real numbers as parts. Gaining the
base of a number in reverse order is just the beginning. As you know, my
complex loading procedure reverses the symbols anyway. So, if I store n-ary
data in reverse form, the load will reverse that directly into correct form!
Cool. Here is some initial code in my base conversion C program, just part of
______________________________
#include <stdio.h>
#include <stdlib.h>
typedef signed long ct_int;
typedef unsigned long ct_uint;
#define CT_SYMBOLS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
/* converts v to base b using symbol table s in a block n.
the order is reversed, however the load will fix that...
__________________________________________________*/
void
ct_base_block(
ct_uint v,
ct_uint b,
char const* s,
ct_uint n
) {
ct_uint t = v;
size_t l = strlen(s);
for (ct_uint i = 0; i < n; ++i)
{
ct_uint d = t / b;
ct_uint r = t - d * b;
if (r > l)
{
printf("\nsymbol table size error!");
break;
}
printf("%c", s[r]);
//printf("%lu", r);
t = d;
}
printf("\n");
}
int main(int argc, char *argv[])
{
ct_base_block(999, 17, CT_SYMBOLS, 16);
return 0;
}
______________________________
______________________________
D730000000000000
______________________________
000000000000037D
Well, its equal to 999 in base 10!
All of the zeros can add to the beauty of the fractal. Sometimes, they will
gain spirals, and other wonderful Julia set artifacts.
It could be that that very beauty is bad for the crypto aspect.
I am going to use ct_base_block to store a block of data in the fractal. Each
complex number will store one of these blocks. Now, this is in reverse order.
Fine for the loading of the block will reverse it for me back into normal
working order!
The symbol table is there just so we can see the damn things. This will be
directly embedded into the store procedure. Will have the plotter wrt
store/load in complex roots working today or tomorrow.
Yes, I know that this is a Friday, but this is so much fun!
;^)
https://en.wikipedia.org/wiki/Heptadecagon
Chris M. Thomasson
2017-06-24 16:41:17 UTC
Permalink
Raw Message
Post by FromTheRafters
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Chris M. Thomasson
Right. Afaict, its probably never going to be more efficient than say,
arithmetic coding. My method was never designed to compete with it. I
had fractals on my mind. Fwiw, I am sort of a fractal nerd, so to speak.
I know that, I am a subscriber of yours on G+. :) I'll be looking
forward to those Julia sets, and I start seeing how you could use this
for cryptography. Indeed, I'll try your code and play with some code
myself, but next week, I'm totally busy till Monday...
Fwiw, here is the start of the storm, wrt Richards comment, well, not
quite for I am still using complex numbers with real numbers as parts.
Gaining the base of a number in reverse order is just the beginning.
As you know, my complex loading procedure reverses the symbols anyway.
So, if I store n-ary data in reverse form, the load will reverse that
directly into correct form! Cool. Here is some initial code in my base
conversion C program, just part of my complex number fractal cipher
______________________________
#include <stdio.h>
#include <stdlib.h>
typedef signed long ct_int;
typedef unsigned long ct_uint;
#define CT_SYMBOLS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
/* converts v to base b using symbol table s in a block n.
the order is reversed, however the load will fix that...
__________________________________________________*/
void
ct_base_block(
ct_uint v,
ct_uint b,
char const* s,
ct_uint n
) {
ct_uint t = v;
size_t l = strlen(s);
for (ct_uint i = 0; i < n; ++i)
{
ct_uint d = t / b;
ct_uint r = t - d * b;
if (r > l)
{
printf("\nsymbol table size error!");
break;
}
printf("%c", s[r]);
//printf("%lu", r);
t = d;
}
printf("\n");
}
int main(int argc, char *argv[])
{
ct_base_block(999, 17, CT_SYMBOLS, 16);
return 0;
}
______________________________
______________________________
D730000000000000
______________________________
000000000000037D
Well, its equal to 999 in base 10!
All of the zeros can add to the beauty of the fractal. Sometimes, they
will gain spirals, and other wonderful Julia set artifacts.
It could be that that very beauty is bad for the crypto aspect.
Yes, that is a problem. Wrt z^n+c, lets say that the initial z, the
power n and c are part of the secret key. Now, Eve can look at the
fractal and guess at n and c. Not good. However, there is a way to hide
the fractal by using a random z, n and c for the last couple of
iterations when storing data. This ends up making strange fractals that
end up hiding the secret key. They look nothing like the secret key.
Post by FromTheRafters
Post by Chris M. Thomasson
I am going to use ct_base_block to store a block of data in the
fractal. Each complex number will store one of these blocks. Now, this
is in reverse order. Fine for the loading of the block will reverse it
for me back into normal working order!
The symbol table is there just so we can see the damn things. This
will be directly embedded into the store procedure. Will have the
plotter wrt store/load in complex roots working today or tomorrow.
Yes, I know that this is a Friday, but this is so much fun!
;^)
https://en.wikipedia.org/wiki/Heptadecagon
Nice. Humm... Wrt to z^n, one of these should pop out if I use a power
of 17. Each root would be on the Heptadecagon.
Chris M. Thomasson
2017-06-25 00:14:29 UTC
Permalink
Raw Message
[...]
Post by FromTheRafters
https://en.wikipedia.org/wiki/Heptadecagon
Okay. I am learning about the roots of unity wrt magic values of z. Here
is a program that produces roots of unity for any given power. Its
hardcoded to gain a 17-gon such that each number when raised to the
17'th power gains the number 1. Well, 1 in the sense of real part 1,
imag part zero. Floating point issues aside for a moment. Here is the
C99 code:
______________________________
#include <stdio.h>
#include <math.h>
#include <complex.h>

#define CT_PI 3.1415926535897932384626433832795
#define CT_PI2 6.283185307179586476925286766559

typedef double ct_real;
typedef double complex ct_complex;

ct_complex
ct_root(
ct_complex const z,
int p,
unsigned int r
){
ct_real radius = cpow(cabs(z), 1.0 / p);

ct_real angle_base = carg(z) / p;
ct_real angle_step = CT_PI2 / p;
ct_real angle = angle_base + angle_step * r;

ct_complex root = cos(angle) * radius + sin(angle) * radius * I;

return root;
}

int main(void)
{
// unity root, real part 1, imaginary part zero.
ct_complex z = 1+0*I;
printf("s:(%lf%+lfi)\n", creal(z), cimag(z));

unsigned int p = 17; // the number of roots

printf("\nRoots of Unity Power: %u\n", p);
printf("__________________________________\n");
for (unsigned int i = 0; i < p; ++i)
{
ct_complex r = ct_root(z, p, i);
ct_complex raised = cpow(r, p);

printf("r[%u]:(%lf%+lfi) raised = (%lf+%lfi)\n",
i,
creal(r), cimag(r),
creal(raised), cimag(raised)
);
}
printf("__________________________________\n");

return 0;
}
______________________________


It outputs the following text:
***************************************
s:(1.000000+0.000000i)

Roots of Unity Power: 17
__________________________________
r[0]:(1.000000+0.000000i) raised = (1.000000+0.000000i)
r[1]:(0.932472+0.361242i) raised = (1.000000+-0.000000i)
r[2]:(0.739009+0.673696i) raised = (1.000000+-0.000000i)
r[3]:(0.445738+0.895163i) raised = (1.000000+-0.000000i)
r[4]:(0.092268+0.995734i) raised = (1.000000+-0.000000i)
r[5]:(-0.273663+0.961826i) raised = (1.000000+-0.000000i)
r[6]:(-0.602635+0.798017i) raised = (1.000000+-0.000000i)
r[7]:(-0.850217+0.526432i) raised = (1.000000+0.000000i)
r[8]:(-0.982973+0.183750i) raised = (1.000000+-0.000000i)
r[9]:(-0.982973-0.183750i) raised = (1.000000+-0.000000i)
r[10]:(-0.850217-0.526432i) raised = (1.000000+-0.000000i)
r[11]:(-0.602635-0.798017i) raised = (1.000000+-0.000000i)
r[12]:(-0.273663-0.961826i) raised = (1.000000+-0.000000i)
r[13]:(0.092268-0.995734i) raised = (1.000000+-0.000000i)
r[14]:(0.445738-0.895163i) raised = (1.000000+0.000000i)
r[15]:(0.739009-0.673696i) raised = (1.000000+0.000000i)
r[16]:(0.932472-0.361242i) raised = (1.000000+-0.000000i)
__________________________________
***************************************


Each root r[0...16] wrt power of 17 gains (1, 0) when raised up to the
power of 17.


Can you run it? Its C99... Wow! Love to learn.
Chris M. Thomasson
2017-06-25 01:08:30 UTC
Permalink
Raw Message
[...]
Post by FromTheRafters
https://en.wikipedia.org/wiki/Heptadecagon
[...]

YIKES! I have an extra % in the printf on line 43 in the original code.

Fwiw, one can set the power by altering line 34. The hardcoded line 34 is:

unsigned int p = 103; // the number of roots

Fwiw, here is fixed code wrt the extra % that shows a 103-gon:
______________
#include <stdio.h>
#include <math.h>
#include <complex.h>

#define CT_PI 3.1415926535897932384626433832795
#define CT_PI2 6.283185307179586476925286766559

typedef double ct_real;
typedef double complex ct_complex;

ct_complex
ct_root(
ct_complex const z,
int p,
unsigned int r
){
ct_real radius = cpow(cabs(z), 1.0 / p);

ct_real angle_base = carg(z) / p;
ct_real angle_step = CT_PI2 / p;
ct_real angle = angle_base + angle_step * r;

ct_complex root = cos(angle) * radius + sin(angle) * radius * I;

return root;
}

int main(void)
{
// unity root, real part 1, imaginary part zero.
ct_complex z = 1+0*I;
printf("s:(%lf, %lf)\n", creal(z), cimag(z));

unsigned int p = 103; // the number of roots

printf("\nRoots of Unity Power: %u\n", p);
printf("__________________________________\n");
for (unsigned int i = 0; i < p; ++i)
{
ct_complex r = ct_root(z, p, i);
ct_complex raised = cpow(r, p);

printf("r[%u]:(%lf, %lf) raised = (%lf, %lf)\n",
i,
creal(r), cimag(r),
creal(raised), cimag(raised)
);
}
printf("__________________________________\n");

return 0;
}
______________

Sorry about that!
Chris M. Thomasson
2017-06-25 06:21:18 UTC
Permalink
Raw Message
[...]
Post by Chris M. Thomasson
The symbol table is there just so we can see the damn things. This will
be directly embedded into the store procedure. Will have the plotter wrt
store/load in complex roots working today or tomorrow.
This is going to take a little more time than I thought. Please try to
cut me some slack. ;^o
richard miller
2017-06-21 21:05:26 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?

It is much better (easier, faster computation etc.) using integer unity (or primitive) roots, i.e. integers that satisfy

x^n == 1 (mod p)

Very briefly, for instance, for prime base p, p = 2.n.l + 1, for some integer l, odd n, you will get n such roots with a lovely integer value. Even exponents are also possible, see Legendre's theorem.

E.g. n=3, p=7, x={1,2,4}

1^3 == 1 (mod 7)
2^3 == 1 (mod 7)
4^3 == 1 (mod 7)

The roots form a cyclic group, prime p, single generator, here '2', i.e.
the three roots are 2^0=1, 2^1=2, 2^2=4.

These are isomorphic to the cubic roots of unity, i.e. 1~e^i.0, 2~e^i.2.pi/3, 4~e^i.4.pi/3.

You can do everything you want in integers, plus p can also be arbitrary, composite, so long as it has prime factors of the requisite form (you will then get more roots than n).

There is some free stuff on unity roots at http://www.urmt.org, otherwise just search the web 'primitive roots', 'Legendre's theorem'

This reply is very terse, and I could give more info. Request it by email to the address given at the below web-site if required.

In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers

Richard Miller
http://www.urmt.org
Chris M. Thomasson
2017-06-22 18:41:40 UTC
Permalink
Raw Message
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
stored data contained within them. Think of:

https://en.wikipedia.org/wiki/Julia_set#Using_backwards_.28inverse.29_iteration_.28IIM.29
Post by richard miller
It is much better (easier, faster computation etc.) using integer unity (or primitive) roots, i.e. integers that satisfy
x^n == 1 (mod p)
Very briefly, for instance, for prime base p, p = 2.n.l + 1, for some integer l, odd n, you will get n such roots with a lovely integer value. Even exponents are also possible, see Legendre's theorem.
E.g. n=3, p=7, x={1,2,4}
1^3 == 1 (mod 7)
2^3 == 1 (mod 7)
4^3 == 1 (mod 7)
The roots form a cyclic group, prime p, single generator, here '2', i.e.
the three roots are 2^0=1, 2^1=2, 2^2=4.
Please try to forgive my ignorance here Richard, but I am having trouble
seeing how this can work in my iterative scheme. I am thinking I would
have to choose a prime base that is large enough to store the data. In
the sense that the loading iteration can recover it wrt giving me a big
enough cyclic group that would allow for both the storing and loading
process. My loading process in a small group might give me false
positives? Hummm.... Need to think!
Post by richard miller
These are isomorphic to the cubic roots of unity, i.e. 1~e^i.0, 2~e^i.2.pi/3, 4~e^i.4.pi/3.
You can do everything you want in integers, plus p can also be arbitrary, composite, so long as it has prime factors of the requisite form (you will then get more roots than n).
There is some free stuff on unity roots at http://www.urmt.org, otherwise just search the web 'primitive roots', 'Legendre's theorem'
This reply is very terse, and I could give more info. Request it by email to the address given at the below web-site if required.
In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers
Wrt Diffie-Hellman, check this out:

https://groups.google.com/d/msg/sci.crypt/CIUkq58Xe_4/seELFfkSAgAJ

When using non-compatible inputs, the keyspace for Diffie-Hellman
drastically decreases. I am thinking that after a couple of iterations,
this problem will show it face.

Thank you for the excellent comment Richard.
richard miller
2017-06-22 19:29:22 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
OK, see my next point
Post by Chris M. Thomasson
Post by richard miller
In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers
Slightly flippant of me, I meant if you can do it with the complex roots of unity, you can do it with integer, primitive roots...

Unity roots pervade maths and mathematical physics. Whilst you are working on cryptography, I'm also currently working on some other industrial application at the mo involving replacing complex unity roots with integers - it is working very nicely (and very fast), which is why I posted a reply to you in the thought that you may also benefit. I will try and read a bit more of your stuff and links.

The primitive roots are basically isomorphic, group-wise, to the complex roots of unity. As regards a large prime-base, I will have to think on this and properly read your stuff. but large number arithmetic is de-rigeur in computational number theory, no base too big - thousand digits to one million plus...
Post by Chris M. Thomasson
https://groups.google.com/d/msg/sci.crypt/CIUkq58Xe_4/seELFfkSAgAJ
I haven't checked this out yet, but I will.

Good luck for now, will try and expend some effort over the next few days...

Richard M.
http://www.urmt.org
Chris M. Thomasson
2017-06-23 01:46:13 UTC
Permalink
Raw Message
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
OK, see my next point
Post by Chris M. Thomasson
Post by richard miller
In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers
Slightly flippant of me, I meant if you can do it with the complex roots of unity, you can do it with integer, primitive roots...
I need to calm down and think. If I gain the roots of a number, and use
that number for the next set of roots, how can this next root under
iteration be used with the same cyclic group that gained the first
iteration? The group would start to get smaller and smaller. Sorry for
my brainstorming here.
Post by richard miller
Unity roots pervade maths and mathematical physics. Whilst you are working on cryptography, I'm also currently working on some other industrial application at the mo involving replacing complex unity roots with integers - it is working very nicely (and very fast), which is why I posted a reply to you in the thought that you may also benefit. I will try and read a bit more of your stuff and links.
The primitive roots are basically isomorphic, group-wise, to the complex roots of unity. As regards a large prime-base, I will have to think on this and properly read your stuff. but large number arithmetic is de-rigeur in computational number theory, no base too big - thousand digits to one million plus...
Post by Chris M. Thomasson
https://groups.google.com/d/msg/sci.crypt/CIUkq58Xe_4/seELFfkSAgAJ
I haven't checked this out yet, but I will.
Good luck for now, will try and expend some effort over the next few days...
Richard M.
http://www.urmt.org
richard miller
2017-06-23 16:41:30 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
OK, see my next point
Post by Chris M. Thomasson
Post by richard miller
In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers
Slightly flippant of me, I meant if you can do it with the complex roots of unity, you can do it with integer, primitive roots...
I need to calm down and think. If I gain the roots of a number, and use
that number for the next set of roots, how can this next root under
iteration be used with the same cyclic group that gained the first
iteration? The group would start to get smaller and smaller. Sorry for
my brainstorming here.
That is likely so, but, right now, it works for me for my application and permits recursive calls.

Hopefully this is your 'calm before the storm' (a storm of your new ideas that is)

For now, some thought required.
Post by Chris M. Thomasson
Post by richard miller
Richard M.
http://www.urmt.org
Chris M. Thomasson
2017-06-23 17:43:58 UTC
Permalink
Raw Message
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
OK, see my next point
Post by Chris M. Thomasson
Post by richard miller
In short, if you can do it in complex numbers of r.[cos(theta) + i.sin(theta)] form, you can do it in integers
Slightly flippant of me, I meant if you can do it with the complex roots of unity, you can do it with integer, primitive roots...
I need to calm down and think. If I gain the roots of a number, and use
that number for the next set of roots, how can this next root under
iteration be used with the same cyclic group that gained the first
iteration? The group would start to get smaller and smaller. Sorry for
my brainstorming here.
That is likely so, but, right now, it works for me for my application and permits recursive calls.
WOW! Okay... Need to calm down again... Can you possibly get my
technique to perform any sort of compression? The integer realm seems
most promising Richard. Fwiw, I can do it in the real number realm if
and _only_ if the stored symbols follow certain patterns. Wrt binary
encoding, a lot of zeros and ones in a row can be exploited, and
compressed: The compression ratio is not that good at all, but it can
work...
Post by richard miller
Hopefully this is your 'calm before the storm' (a storm of your new ideas that is)
For now, some thought required.
Thank you so much for your time and energy: This is perfect for its the
reason why I posted it here in the first place Richard! Need smarter
people looking at the damn thing!

:^D
richard miller
2017-06-23 18:12:32 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
... an espilon of snippagio
Post by Chris M. Thomasson
Post by richard miller
Hopefully this is your 'calm before the storm' (a storm of your new ideas that is)
For now, some thought required.
Thank you so much for your time and energy: This is perfect for its the
reason why I posted it here in the first place Richard! Need smarter
people looking at the damn thing!
:^D
I aint that smart, but... thanks, and you have a good concept and I will take a look over the next few days.

To a wider audience, I hope this gives you some faith in sci.math as a completely uncensored environment. There are a lot of cranks here, but at least they make us think . One has to be able to reason.

Back to thought on your matter...

Richard M.
Chris M. Thomasson
2017-06-23 18:54:38 UTC
Permalink
Raw Message
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
Well, I need to use them in order to plot Julia sets that have the
... an espilon of snippagio
Post by Chris M. Thomasson
Post by richard miller
Hopefully this is your 'calm before the storm' (a storm of your new ideas that is)
For now, some thought required.
Thank you so much for your time and energy: This is perfect for its the
reason why I posted it here in the first place Richard! Need smarter
people looking at the damn thing!
:^D
I aint that smart, but... thanks, and you have a good concept and I will take > a look over the next few days.
Thank you so much for the very kind comment.
Post by richard miller
To a wider audience, I hope this gives you some faith in sci.math as a completely
uncensored environment. There are a lot of cranks here, but at least they make us
think . One has to be able to reason.
I have to admit that some of the cranky trolls make me think as well. :^)
Post by richard miller
Back to thought on your matter...
Perfect for that is the main goal!

:^D
Chris M. Thomasson
2017-06-25 00:20:32 UTC
Permalink
Raw Message
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
[...]

Please excuse my ignorance, again... But getting better at gaining roots
of unity. Take a look at the following c99 program I created:

https://groups.google.com/d/msg/sci.math/fZBCdVwvHGQ/DOjmsGB7AQAJ

It gives output as:

s:(1.000000+0.000000i)

Roots of Unity Power: 17
__________________________________
r[0]:(1.000000+0.000000i) raised = (1.000000+0.000000i)
r[1]:(0.932472+0.361242i) raised = (1.000000+-0.000000i)
r[2]:(0.739009+0.673696i) raised = (1.000000+-0.000000i)
r[3]:(0.445738+0.895163i) raised = (1.000000+-0.000000i)
r[4]:(0.092268+0.995734i) raised = (1.000000+-0.000000i)
r[5]:(-0.273663+0.961826i) raised = (1.000000+-0.000000i)
r[6]:(-0.602635+0.798017i) raised = (1.000000+-0.000000i)
r[7]:(-0.850217+0.526432i) raised = (1.000000+0.000000i)
r[8]:(-0.982973+0.183750i) raised = (1.000000+-0.000000i)
r[9]:(-0.982973-0.183750i) raised = (1.000000+-0.000000i)
r[10]:(-0.850217-0.526432i) raised = (1.000000+-0.000000i)
r[11]:(-0.602635-0.798017i) raised = (1.000000+-0.000000i)
r[12]:(-0.273663-0.961826i) raised = (1.000000+-0.000000i)
r[13]:(0.092268-0.995734i) raised = (1.000000+-0.000000i)
r[14]:(0.445738-0.895163i) raised = (1.000000+0.000000i)
r[15]:(0.739009-0.673696i) raised = (1.000000+0.000000i)
r[16]:(0.932472-0.361242i) raised = (1.000000+-0.000000i)
__________________________________


Each point raised gives 1.... Nice!

BTW, thank you so much for taking the time to help make me smarter!

Well, before I get too happy, notice the +- in there? Even though its
correct, I need to fix that in the output wrt the program. Well, shit.
Its my call to printf damn it!

Please, try to have some patience with me Richard!

;^o
Chris M. Thomasson
2017-06-25 00:30:58 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining roots
https://groups.google.com/d/msg/sci.math/fZBCdVwvHGQ/DOjmsGB7AQAJ
[...]
Post by Chris M. Thomasson
Each point raised gives 1.... Nice!
BTW, thank you so much for taking the time to help make me smarter!
Well, before I get too happy, notice the +- in there? Even though its
correct, I need to fix that in the output wrt the program. Well, shit.
Its my call to printf damn it!
Please, try to have some patience with me Richard!
Fixed my output. Here are the roots of unity for the 103-gon:

s:(1.000000, 0.000000)

Roots of Unity Power: 103
__________________________________
r[0]:(1.000000, 0.000000) raised = (1.000000, 0.000000)
r[1]:(0.998140, 0.060964) raised = (1.000000, -0.000000)
r[2]:(0.992567, 0.121701) raised = (1.000000, -0.000000)
r[3]:(0.983301, 0.181986) raised = (1.000000, -0.000000)
r[4]:(0.970378, 0.241593) raised = (1.000000, -0.000000)
r[5]:(0.953844, 0.300302) raised = (1.000000, -0.000000)
r[6]:(0.933762, 0.357893) raised = (1.000000, -0.000000)
r[7]:(0.910207, 0.414153) raised = (1.000000, -0.000000)
r[8]:(0.883266, 0.468873) raised = (1.000000, -0.000000)
r[9]:(0.853038, 0.521848) raised = (1.000000, -0.000000)
r[10]:(0.819638, 0.572882) raised = (1.000000, -0.000000)
r[11]:(0.783188, 0.621785) raised = (1.000000, 0.000000)
r[12]:(0.743825, 0.668375) raised = (1.000000, -0.000000)
r[13]:(0.701694, 0.712478) raised = (1.000000, -0.000000)
r[14]:(0.656954, 0.753931) raised = (1.000000, -0.000000)
r[15]:(0.609769, 0.792579) raised = (1.000000, -0.000000)
r[16]:(0.560316, 0.828279) raised = (1.000000, -0.000000)
r[17]:(0.508779, 0.860897) raised = (1.000000, -0.000000)
r[18]:(0.455349, 0.890313) raised = (1.000000, -0.000000)
r[19]:(0.400225, 0.916417) raised = (1.000000, -0.000000)
r[20]:(0.343612, 0.939112) raised = (1.000000, -0.000000)
r[21]:(0.285721, 0.958313) raised = (1.000000, 0.000000)
r[22]:(0.226767, 0.973949) raised = (1.000000, 0.000000)
r[23]:(0.166969, 0.985962) raised = (1.000000, -0.000000)
r[24]:(0.106550, 0.994307) raised = (1.000000, -0.000000)
r[25]:(0.045735, 0.998954) raised = (1.000000, -0.000000)
r[26]:(-0.015250, 0.999884) raised = (1.000000, -0.000000)
r[27]:(-0.076178, 0.997094) raised = (1.000000, -0.000000)
r[28]:(-0.136824, 0.990595) raised = (1.000000, -0.000000)
r[29]:(-0.196960, 0.980412) raised = (1.000000, -0.000000)
r[30]:(-0.256363, 0.966581) raised = (1.000000, -0.000000)
r[31]:(-0.314813, 0.949154) raised = (1.000000, -0.000000)
r[32]:(-0.372091, 0.928196) raised = (1.000000, -0.000000)
r[33]:(-0.427986, 0.903785) raised = (1.000000, -0.000000)
r[34]:(-0.482288, 0.876013) raised = (1.000000, -0.000000)
r[35]:(-0.534796, 0.844981) raised = (1.000000, -0.000000)
r[36]:(-0.585315, 0.810806) raised = (1.000000, -0.000000)
r[37]:(-0.633656, 0.773615) raised = (1.000000, -0.000000)
r[38]:(-0.679640, 0.733546) raised = (1.000000, -0.000000)
r[39]:(-0.723096, 0.690748) raised = (1.000000, -0.000000)
r[40]:(-0.763862, 0.645380) raised = (1.000000, -0.000000)
r[41]:(-0.801786, 0.597612) raised = (1.000000, -0.000000)
r[42]:(-0.836727, 0.547620) raised = (1.000000, 0.000000)
r[43]:(-0.868556, 0.495591) raised = (1.000000, -0.000000)
r[44]:(-0.897154, 0.441719) raised = (1.000000, 0.000000)
r[45]:(-0.922414, 0.386203) raised = (1.000000, -0.000000)
r[46]:(-0.944243, 0.329251) raised = (1.000000, -0.000000)
r[47]:(-0.962559, 0.271073) raised = (1.000000, 0.000000)
r[48]:(-0.977294, 0.211888) raised = (1.000000, -0.000000)
r[49]:(-0.988394, 0.151914) raised = (1.000000, -0.000000)
r[50]:(-0.995817, 0.091375) raised = (1.000000, -0.000000)
r[51]:(-0.999535, 0.030496) raised = (1.000000, -0.000000)
r[52]:(-0.999535, -0.030496) raised = (1.000000, -0.000000)
r[53]:(-0.995817, -0.091375) raised = (1.000000, -0.000000)
r[54]:(-0.988394, -0.151914) raised = (1.000000, -0.000000)
r[55]:(-0.977294, -0.211888) raised = (1.000000, -0.000000)
r[56]:(-0.962559, -0.271073) raised = (1.000000, -0.000000)
r[57]:(-0.944243, -0.329251) raised = (1.000000, -0.000000)
r[58]:(-0.922414, -0.386203) raised = (1.000000, -0.000000)
r[59]:(-0.897154, -0.441719) raised = (1.000000, -0.000000)
r[60]:(-0.868556, -0.495591) raised = (1.000000, -0.000000)
r[61]:(-0.836727, -0.547620) raised = (1.000000, -0.000000)
r[62]:(-0.801786, -0.597612) raised = (1.000000, -0.000000)
r[63]:(-0.763862, -0.645380) raised = (1.000000, -0.000000)
r[64]:(-0.723096, -0.690748) raised = (1.000000, -0.000000)
r[65]:(-0.679640, -0.733546) raised = (1.000000, -0.000000)
r[66]:(-0.633656, -0.773615) raised = (1.000000, -0.000000)
r[67]:(-0.585315, -0.810806) raised = (1.000000, -0.000000)
r[68]:(-0.534796, -0.844981) raised = (1.000000, -0.000000)
r[69]:(-0.482288, -0.876013) raised = (1.000000, -0.000000)
r[70]:(-0.427986, -0.903785) raised = (1.000000, -0.000000)
r[71]:(-0.372091, -0.928196) raised = (1.000000, -0.000000)
r[72]:(-0.314813, -0.949154) raised = (1.000000, -0.000000)
r[73]:(-0.256363, -0.966581) raised = (1.000000, -0.000000)
r[74]:(-0.196960, -0.980412) raised = (1.000000, -0.000000)
r[75]:(-0.136824, -0.990595) raised = (1.000000, -0.000000)
r[76]:(-0.076178, -0.997094) raised = (1.000000, -0.000000)
r[77]:(-0.015250, -0.999884) raised = (1.000000, -0.000000)
r[78]:(0.045735, -0.998954) raised = (1.000000, -0.000000)
r[79]:(0.106550, -0.994307) raised = (1.000000, 0.000000)
r[80]:(0.166969, -0.985962) raised = (1.000000, -0.000000)
r[81]:(0.226767, -0.973949) raised = (1.000000, -0.000000)
r[82]:(0.285721, -0.958313) raised = (1.000000, -0.000000)
r[83]:(0.343612, -0.939112) raised = (1.000000, 0.000000)
r[84]:(0.400225, -0.916417) raised = (1.000000, -0.000000)
r[85]:(0.455349, -0.890313) raised = (1.000000, -0.000000)
r[86]:(0.508779, -0.860897) raised = (1.000000, -0.000000)
r[87]:(0.560316, -0.828279) raised = (1.000000, -0.000000)
r[88]:(0.609769, -0.792579) raised = (1.000000, -0.000000)
r[89]:(0.656954, -0.753931) raised = (1.000000, -0.000000)
r[90]:(0.701694, -0.712478) raised = (1.000000, -0.000000)
r[91]:(0.743825, -0.668375) raised = (1.000000, -0.000000)
r[92]:(0.783188, -0.621785) raised = (1.000000, -0.000000)
r[93]:(0.819638, -0.572882) raised = (1.000000, -0.000000)
r[94]:(0.853038, -0.521848) raised = (1.000000, -0.000000)
r[95]:(0.883266, -0.468873) raised = (1.000000, -0.000000)
r[96]:(0.910207, -0.414153) raised = (1.000000, -0.000000)
r[97]:(0.933762, -0.357893) raised = (1.000000, -0.000000)
r[98]:(0.953844, -0.300302) raised = (1.000000, -0.000000)
r[99]:(0.970378, -0.241593) raised = (1.000000, -0.000000)
r[100]:(0.983301, -0.181986) raised = (1.000000, -0.000000)
r[101]:(0.992567, -0.121701) raised = (1.000000, -0.000000)
r[102]:(0.998140, -0.060964) raised = (1.000000, -0.000000)
__________________________________


I just made my call to printf output complex numbers as:

(%lf, %lf)

Results look very nice!

The negative zeros are tweaking me out here....
Chris M. Thomasson
2017-06-25 00:43:16 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining roots
[...]

Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o

Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
Chris M. Thomasson
2017-06-25 01:51:42 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those
of the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining
[...]
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
Getting closer! Let me keep trying.
Chris M. Thomasson
2017-06-25 03:13:47 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those
of the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining
[...]
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I am having trouble with picking an integer i and a power p.

gaining the p integer roots of i as r.

choosing one of roots in r as the new i.

gaining the p roots of i as r.

choosing one of roots in r wrt the symbols that we are storing as the new i.

and on and on until the iteration is complete for storing all of the
symbols.

Then, for loading, raising the final i up to the power of p, gaining the
roots and comparing i to said roots to determine what symbol to load.
setting i to the correct root, raising again, and on and on until all of
the symbols are loaded. This works fine with complex numbers.

So far, I cannot convert my complex number method of storing n-ary data
into a form that uses integers!

Damn it!
richard miller
2017-06-25 18:04:46 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
I am having trouble with picking an integer i and a power p.
Firstly, I have not understood your cryptographic scheme but I believe you required complex roots of unity. Arithmetically, it is very easy to work in the standard exponential form to get p roots, as in exp(2.pi.n/p), n=0 to p-1, as you well know. However, just taking you specific p=103 case to get 103 roots, it is indeed not straightforward. Firstly i and p are related, so I'll take p=103 as the given, i.e. find a modulus i such that

x^103 == 1 mod i

In fact, the smallest, prime i for which you will get 103 roots is actually i=619

where i = 2.3.103 + 1 (i is of the 'l.n+1 form for integer l, here l is even, =6 for prime i). This form is goverend by 'Lagrange's Theorem - I erroneously called it Legendres in an earlier post).
Post by Chris M. Thomasson
gaining the p integer roots of i as r.
For i=619, the 103 roots are = {1,9,20,24,31, ... 605,606,611,616}

The first value = 9 can be used to generate all roots, i.e. the set of 103 roots as

{9^0, 9^1, 9^2, 9^3 ... 9^102} mod 619 = {1, 9, 81, 110, ...

Note that the ordering of this set is not the same as the sequential ordering given above but, of course, they contain the same elements
Post by Chris M. Thomasson
choosing one of roots in r as the new i.
This next bit is probably where I need to understand your cryptographic scheme.
However, I am loathe to spend time if you can already see my integer idea won't work!
Post by Chris M. Thomasson
gaining the p roots of i as r.
Perhaps this is your equivalent of my pre-supposed 'recursive method'. But my recursive method works on the exponent p actually being composite so that the set of unity roots contains cyclic sub-groups, e.g. if you wanted 102 roots (and not 103), then the exponent p=102 factors into 2.3.17 which gives cyclic sub-groups of orders 2,3 and 17.
Post by Chris M. Thomasson
choosing one of roots in r wrt the symbols that we are storing as the new i.
and on and on until the iteration is complete for storing all of the
symbols.
Then, for loading, raising the final i up to the power of p, gaining the
roots and comparing i to said roots to determine what symbol to load.
setting i to the correct root, raising again, and on and on until all of
the symbols are loaded. This works fine with complex numbers.
So far, I cannot convert my complex number method of storing n-ary data
into a form that uses integers!
Damn it!
I'll leave it that for now. I think it is best you experiment with what you have and consider long-term if an integer method is workable. Like I say, I can get a method to work for some other application, but it is definitely not cryptographic and does require some work in determining a suitable exponent and modulus.

Richard M.
http://www.urmt.org
Julio Di Egidio
2017-06-25 17:00:10 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of
the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining roots
[...]
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I don't know what you have in mind, anyway, about using integers, here is a
little plot I have put together in the meantime: the alphabet is binary,
i.e. I am taking square roots, but starting with Z=-1 (which maps to the
empty string): I have stopped at Z000 (which maps to the string "000"),
I think you'll see the pattern. Starting with Z=-1 instead of Z=1 maps
distinct strings to distinct points regardless of string length! Anyway,
even if the points are distinct, I still think we need a pair of integers,
not just one, to index a point: e.g. the ratio of 'the arc from (1,0) to
the point' to the full circle (which is guaranteed to be rational)...
<https://www.desmos.com/calculator/pvcjbgmtrw>

Julio
Chris M. Thomasson
2017-06-25 23:24:33 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by richard miller
Post by Chris M. Thomasson
The roots of complex numbers like z^n+c, or even just z^n can store
data. Fwiw, here is a quick and crude example of using the ct_roots
Do you really need to use 'real' numbered complex roots, i.e. those of
the form exp(i*x)?
[...]
Please excuse my ignorance, again... But getting better at gaining roots
[...]
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I don't know what you have in mind, anyway, about using integers, here is a
little plot I have put together in the meantime: the alphabet is binary,
i.e. I am taking square roots, but starting with Z=-1 (which maps to the
empty string): I have stopped at Z000 (which maps to the string "000"),
I think you'll see the pattern. Starting with Z=-1 instead of Z=1 maps
distinct strings to distinct points regardless of string length! Anyway,
even if the points are distinct, I still think we need a pair of integers,
not just one, to index a point: e.g. the ratio of 'the arc from (1,0) to
the point' to the full circle (which is guaranteed to be rational)...
<https://www.desmos.com/calculator/pvcjbgmtrw>
Are you thinking along the lines of using the convergent's of continued
fractions where the two integers can recreate the values of the complex
numbers? Fwiw, here is a little part of a program that reproduces the
numbers you got over on that extremely nice site, Desmos:
________________________________
ct_complex z = -1 + 0 * I;

printf("z:(%lf%+lfi)\n", creal(z), cimag(z));

ct_complex z0 = sqrt(z);
printf("z0:(%lf%+lfi)\n", creal(z0), cimag(z0));

ct_complex z1 = -sqrt(z);
printf("z1:(%lf%+lfi)\n", creal(z1), cimag(z1));

ct_complex z00 = sqrt(z0);
printf("z00:(%lf%+lfi)\n", creal(z00), cimag(z00));

ct_complex z01 = -sqrt(z0);
printf("z01:(%lf%+lfi)\n", creal(z01), cimag(z01));

ct_complex z10 = sqrt(-z0);
printf("z10:(%lf%+lfi)\n", creal(z10), cimag(z10));

ct_complex z11 = -z10;
printf("z11:(%lf%+lfi)\n", creal(z11), cimag(z11));

ct_complex z000 = sqrt(z00);
printf("z000:(%lf%+lfi)\n", creal(z000), cimag(z000));

return 0;
________________________________


The output is:
________________________________
z:(-1.000000+0.000000i)
z0:(0.000000+1.000000i)
z1:(-0.000000-1.000000i)
z00:(0.707107+0.707107i)
z01:(-0.707107-0.707107i)
z10:(0.707107-0.707107i)
z11:(-0.707107+0.707107i)
z000:(0.923880+0.382683i)
________________________________

Everything lines up. Thank you!
Julio Di Egidio
2017-06-26 01:42:47 UTC
Permalink
Raw Message
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Chris M. Thomasson
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I don't know what you have in mind, anyway, about using integers, here is a
little plot I have put together in the meantime: the alphabet is binary,
i.e. I am taking square roots, but starting with Z=-1 (which maps to the
empty string): I have stopped at Z000 (which maps to the string "000"),
I think you'll see the pattern. Starting with Z=-1 instead of Z=1 maps
distinct strings to distinct points regardless of string length! Anyway,
even if the points are distinct, I still think we need a pair of integers,
not just one, to index a point: e.g. the ratio of 'the arc from (1,0) to
the point' to the full circle (which is guaranteed to be rational)...
<https://www.desmos.com/calculator/pvcjbgmtrw>
Are you thinking along the lines of using the convergent's of continued
fractions where the two integers can recreate the values of the complex
numbers?
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.

That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.

As such, that scheme could be useful e.g. for drawing Julia sets. It's
not suited for cryptography, though: to begin with, Z above is fixed. But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)

Julio
Chris M. Thomasson
2017-06-27 01:51:38 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Chris M. Thomasson
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I don't know what you have in mind, anyway, about using integers, here is a
little plot I have put together in the meantime: the alphabet is binary,
i.e. I am taking square roots, but starting with Z=-1 (which maps to the
empty string): I have stopped at Z000 (which maps to the string "000"),
I think you'll see the pattern. Starting with Z=-1 instead of Z=1 maps
distinct strings to distinct points regardless of string length! Anyway,
even if the points are distinct, I still think we need a pair of integers,
not just one, to index a point: e.g. the ratio of 'the arc from (1,0) to
the point' to the full circle (which is guaranteed to be rational)...
<https://www.desmos.com/calculator/pvcjbgmtrw>
Are you thinking along the lines of using the convergent's of continued
fractions where the two integers can recreate the values of the complex
numbers?
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.
That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.
As such, that scheme could be useful e.g. for drawing Julia sets. It's
not suited for cryptography, though: to begin with, Z above is fixed. But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)
Think I see what you are getting at here... Humm... Fwiw, here is a
little table I made that shows some multiples of ratios of pi2 that
equal your Desmos example:
_____________________
0*(pi2 / 8):z:(-1.000000+0.000000i)
6*(pi2 / 8):z0:(0.000000+1.000000i)
2*(pi2 / 8):z1:(-0.000000-1.000000i)
5*(pi2 / 8):z00:(0.707107+0.707107i)
1*(pi2 / 8):z01:(-0.707107-0.707107i)
3*(pi2 / 8):z10:(0.707107-0.707107i)
7*(pi2 / 8):z11:(-0.707107+0.707107i)
9*(pi2 / 16):z000:(0.923880+0.382683i)
_____________________

This type of data is helping me understand whats going on here.
Chris M. Thomasson
2017-06-27 03:17:23 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Julio Di Egidio
Post by Chris M. Thomasson
Can you please help me figure out how to do the same with integers? I am
having some trouble. ;^o
Complex numbers seem fairly easy to me, the mod cyclic group of integers
is messing me up a bit. DAMN!
I don't know what you have in mind, anyway, about using integers, here is a
little plot I have put together in the meantime: the alphabet is binary,
i.e. I am taking square roots, but starting with Z=-1 (which maps to the
empty string): I have stopped at Z000 (which maps to the string "000"),
I think you'll see the pattern. Starting with Z=-1 instead of Z=1 maps
distinct strings to distinct points regardless of string length!
Anyway,
even if the points are distinct, I still think we need a pair of integers,
not just one, to index a point: e.g. the ratio of 'the arc from (1,0) to
the point' to the full circle (which is guaranteed to be rational)...
<https://www.desmos.com/calculator/pvcjbgmtrw>
Are you thinking along the lines of using the convergent's of continued
fractions where the two integers can recreate the values of the complex
numbers?
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.
That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.
As such, that scheme could be useful e.g. for drawing Julia sets. It's
not suited for cryptography, though: to begin with, Z above is fixed.
But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)
Think I see what you are getting at here... Humm... Fwiw, here is a
little table I made that shows some multiples of ratios of pi2 that
_____________________
0*(pi2 / 8):z:(-1.000000+0.000000i)
6*(pi2 / 8):z0:(0.000000+1.000000i)
2*(pi2 / 8):z1:(-0.000000-1.000000i)
5*(pi2 / 8):z00:(0.707107+0.707107i)
1*(pi2 / 8):z01:(-0.707107-0.707107i)
3*(pi2 / 8):z10:(0.707107-0.707107i)
7*(pi2 / 8):z11:(-0.707107+0.707107i)
9*(pi2 / 16):z000:(0.923880+0.382683i)
_____________________
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols. If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.

Hummm.... Thinking on and on , brainstroming away here! :^)
Julio Di Egidio
2017-06-27 13:45:33 UTC
Permalink
Raw Message
<snip>
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by Julio Di Egidio
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.
That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.
As such, that scheme could be useful e.g. for drawing Julia sets. It's
not suited for cryptography, though: to begin with, Z above is fixed.
But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)
Think I see what you are getting at here... Humm... Fwiw, here is a
little table I made that shows some multiples of ratios of pi2 that
_____________________
0*(pi2 / 8):z:(-1.000000+0.000000i)
6*(pi2 / 8):z0:(0.000000+1.000000i)
2*(pi2 / 8):z1:(-0.000000-1.000000i)
5*(pi2 / 8):z00:(0.707107+0.707107i)
1*(pi2 / 8):z01:(-0.707107-0.707107i)
3*(pi2 / 8):z10:(0.707107-0.707107i)
7*(pi2 / 8):z11:(-0.707107+0.707107i)
9*(pi2 / 16):z000:(0.923880+0.382683i)
_____________________
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
is a little tool I am putting together in the meantime:
<http://julio.diegidio.name/lab/UnityEncoder/>

Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.

Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...

Julio
Julio Di Egidio
2017-06-27 14:04:30 UTC
Permalink
Raw Message
Post by Julio Di Egidio
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
Sorry, that's indeed wrong, but I have no time to fix right now: it's
correct in the code...

Julio
Julio Di Egidio
2017-06-27 14:14:22 UTC
Permalink
Raw Message
Post by Julio Di Egidio
Post by Julio Di Egidio
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
Sorry, that's indeed wrong, but I have no time to fix right now: it's
correct in the code...
It's D=2^(L+1).

Julio
Julio Di Egidio
2017-06-28 14:15:48 UTC
Permalink
Raw Message
<snip>
Post by Julio Di Egidio
Post by Chris M. Thomasson
Post by Chris M. Thomasson
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
OK, it's D = 2^(L+1) and N odd in 0 < N < D. This can be derived from
the fact that distinct strings map to distinct points: we get irreducible
fractions.
Post by Julio Di Egidio
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
<http://julio.diegidio.name/lab/UnityEncoder/>
Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.
I think I've cracked it, and the rule is very simple! For a couple of
days (also because I'm still very busy) I'll leave it as an exercise for
the interested reader. Hint: to a mathematician who knows the properties
of the complex roots of unity the exercise should be trivial... ;)

Julio
Post by Julio Di Egidio
Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...
Chris M. Thomasson
2017-06-28 18:13:26 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Julio Di Egidio
Post by Chris M. Thomasson
Post by Chris M. Thomasson
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
OK, it's D = 2^(L+1) and N odd in 0 < N < D. This can be derived from
the fact that distinct strings map to distinct points: we get irreducible
fractions.
Post by Julio Di Egidio
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
<http://julio.diegidio.name/lab/UnityEncoder/>
Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.
I think I've cracked it, and the rule is very simple! For a couple of
days (also because I'm still very busy) I'll leave it as an exercise for
the interested reader. Hint: to a mathematician who knows the properties
of the complex roots of unity the exercise should be trivial... ;)
Post by Julio Di Egidio
Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...
Yes, I am very interested! Fwiw, here is a full blown store/load
prototype that can "try" to store and load numbers in any base using my
original complex root storage technique. The code uses 5-ary, but this
can be altered by changing line 114. The number it stores is 1234567.
This can be changed by altering line 116. It even handles negative
powers. However, floating point issues can make it act funny for certain
powers and values of z and c. So, its lossy for certain initial values.
Anyway, here is the code:
___________________________________
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>


#define CT_PI2 6.283185307179586476925286766559
#define CT_LOAD_MAX 32
#define CT_FIND_EPS 0.001


typedef double ct_real;
typedef double complex ct_complex;


ct_complex
ct_root(
ct_complex const z,
long p,
unsigned long r
){
ct_real radius = pow(fabs(z), 1.0 / p);
ct_real angle_base = carg(z) / p;
ct_real angle_step = CT_PI2 / p;
ct_real angle = angle_base + angle_step * r;
ct_complex root = cos(angle) * radius + sin(angle) * radius * I;

return root;
}


ct_complex
ct_store(
ct_complex z,
ct_complex c,
unsigned long v,
long p
){
unsigned long b = abs(p);

printf("ct_store:((%lf%+lfi), (%lf%+lfi), %lu, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), v, p);

while (v > 0)
{
unsigned long d = v / b;
unsigned long r = v - d * b;

z = ct_root(z - c, p, r);
printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), r);

v = d;
}

printf("result:(%lf%+lfi)\n", creal(z), cimag(z));
printf("_______________________________\n\n");

return z;
}


ct_complex
ct_load(
ct_complex z0,
ct_complex z,
ct_complex c,
unsigned long* pv,
long p
){
unsigned long v = 0;
unsigned long b = abs(p);

printf("ct_load:((%lf%+lfi), (%lf%+lfi), %p, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), (void*)pv, p);

for (unsigned long i = 0; i < 32; ++i)
{
ct_real d = fabs(z - z0);
if (d < CT_FIND_EPS) break;

ct_complex zn = pow(z, p) + c;

ct_complex r = 0 + 0 * I;
unsigned long ii = 0;

for (ii = 0; ii < b; ++ii)
{
r = ct_root(zn - c, p, ii);
ct_real d = fabs(z - r);
if (d < CT_FIND_EPS) break;
}

v = b * v + ii;

printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), ii);

z = zn;
}

*pv = v;
printf("result:((%lf%+lfi), %lu)\n", creal(z), cimag(z), *pv);
printf("_______________________________\n\n");

return z;
}

int main(void)
{
ct_complex z = 0+0*I;
ct_complex c = -.75*.06*I; // Humm...
long p = 5;

unsigned long v = 1234567;
ct_complex zs = ct_store(z, c, v, p);

unsigned long lv = 0;
ct_load(z, zs, c, &lv, p);

if (lv != v)
{
printf("%lu != %lu\n", v, lv);
}

return 0;
}
___________________________________


Here is the output of the c99 code:

ct_store:((0.000000+0.000000i), (-0.000000-0.045000i), 1234567, 5)
_______________________________
(-0.511504+0.166198i):2
(-0.339789-0.820847i):3
(-0.502111+0.826812i):2
(-0.104444+0.995748i):1
(0.953216+0.330941i):0
(1.002051+0.075429i):0
(0.332289-0.945134i):4
(0.962527-0.239050i):0
(-0.828723-0.553114i):3
result:(-0.828723-0.553114i)
_______________________________

ct_load:((-0.828723-0.553114i), (-0.000000-0.045000i), 000000000060FDFC, 5)
_______________________________
(-0.828723-0.553114i):3
(0.962527-0.239050i):0
(0.332289-0.945134i):4
(1.002051+0.075429i):0
(0.953216+0.330941i):0
(-0.104444+0.995748i):1
(-0.502111+0.826812i):2
(-0.339789-0.820847i):3
(-0.511504+0.166198i):2
result:((-0.000000-0.000000i), 1234567)
_______________________________



304001232 in 5-ary does equal 1234567. So it does "try to work". I say
try because of nasty floating point issues.

If we plot the points, we gain part of a plot for a pow of 5 Julia set.
Chris M. Thomasson
2017-06-28 19:14:51 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
<snip>
Post by Julio Di Egidio
Post by Chris M. Thomasson
Post by Chris M. Thomasson
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
OK, it's D = 2^(L+1) and N odd in 0 < N < D. This can be derived from
the fact that distinct strings map to distinct points: we get irreducible
fractions.
Post by Julio Di Egidio
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
<http://julio.diegidio.name/lab/UnityEncoder/>
Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.
I think I've cracked it, and the rule is very simple! For a couple of
days (also because I'm still very busy) I'll leave it as an exercise for
the interested reader. Hint: to a mathematician who knows the properties
of the complex roots of unity the exercise should be trivial... ;)
Post by Julio Di Egidio
Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...
Yes, I am very interested! Fwiw, here is a full blown store/load
prototype that can "try" to store and load numbers in any base using my
original complex root storage technique. The code uses 5-ary, but this
can be altered by changing line 114. The number it stores is 1234567.
This can be changed by altering line 116. It even handles negative
powers. However, floating point issues can make it act funny for certain
powers and values of z and c. So, its lossy for certain initial values.
___________________________________
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>
#define CT_PI2 6.283185307179586476925286766559
#define CT_LOAD_MAX 32
#define CT_FIND_EPS 0.001
typedef double ct_real;
typedef double complex ct_complex;
ct_complex
ct_root(
ct_complex const z,
long p,
unsigned long r
){
ct_real radius = pow(fabs(z), 1.0 / p);
ct_real angle_base = carg(z) / p;
ct_real angle_step = CT_PI2 / p;
ct_real angle = angle_base + angle_step * r;
ct_complex root = cos(angle) * radius + sin(angle) * radius * I;
return root;
}
ct_complex
ct_store(
ct_complex z,
ct_complex c,
unsigned long v,
long p
){
unsigned long b = abs(p);
printf("ct_store:((%lf%+lfi), (%lf%+lfi), %lu, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), v, p);
while (v > 0)
{
unsigned long d = v / b;
unsigned long r = v - d * b;
z = ct_root(z - c, p, r);
printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), r);
v = d;
}
printf("result:(%lf%+lfi)\n", creal(z), cimag(z));
printf("_______________________________\n\n");
return z;
}
ct_complex
ct_load(
ct_complex z0,
ct_complex z,
ct_complex c,
unsigned long* pv,
long p
){
unsigned long v = 0;
unsigned long b = abs(p);
printf("ct_load:((%lf%+lfi), (%lf%+lfi), %p, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), (void*)pv, p);
for (unsigned long i = 0; i < 32; ++i)
{
ct_real d = fabs(z - z0);
if (d < CT_FIND_EPS) break;
ct_complex zn = pow(z, p) + c;
ct_complex r = 0 + 0 * I;
unsigned long ii = 0;
for (ii = 0; ii < b; ++ii)
{
r = ct_root(zn - c, p, ii);
ct_real d = fabs(z - r);
if (d < CT_FIND_EPS) break;
}
v = b * v + ii;
printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), ii);
z = zn;
}
*pv = v;
printf("result:((%lf%+lfi), %lu)\n", creal(z), cimag(z), *pv);
printf("_______________________________\n\n");
return z;
}
int main(void)
{
ct_complex z = 0+0*I;
ct_complex c = -.75*.06*I; // Humm...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ARGH!!!!!!!!!

I am stupid beyond measure.

The line above at 113 is:

ct_complex c = -.75*.06*I; // Humm...

And should be:

ct_complex c = -.75+.06*I;

The code still works for encode/decode, but God DAMN what a horrible
mistake!

I was wondering why my plots did not gain the right Julia set.

So sorry. Fuc%king damn it!!!!!!

YIKES!!!!!!!!!!!

So sorry....
Chris M. Thomasson
2017-06-28 20:16:47 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
On Tuesday, June 27, 2017 at 5:17:30 AM UTC+2, Chris M. Thomasson
[...]
Post by Chris M. Thomasson
#define CT_PI2 6.283185307179586476925286766559
#define CT_LOAD_MAX 32
#define CT_FIND_EPS 0.001
[...]
One more point. CT_FIND_EPS is the epsilon used for finding roots in the
load function. This is pretty coarse and can induce errors wrt storing
certain bit patterns. Try experimenting with different values. Its
pretty interesting.
Chris M. Thomasson
2017-06-28 17:41:31 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by Julio Di Egidio
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.
That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.
As such, that scheme could be useful e.g. for drawing Julia sets. It's
not suited for cryptography, though: to begin with, Z above is fixed.
But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)
Think I see what you are getting at here... Humm... Fwiw, here is a
little table I made that shows some multiples of ratios of pi2 that
_____________________
0*(pi2 / 8):z:(-1.000000+0.000000i)
6*(pi2 / 8):z0:(0.000000+1.000000i)
2*(pi2 / 8):z1:(-0.000000-1.000000i)
5*(pi2 / 8):z00:(0.707107+0.707107i)
1*(pi2 / 8):z01:(-0.707107-0.707107i)
3*(pi2 / 8):z10:(0.707107-0.707107i)
7*(pi2 / 8):z11:(-0.707107+0.707107i)
9*(pi2 / 16):z000:(0.923880+0.382683i)
_____________________
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
<http://julio.diegidio.name/lab/UnityEncoder/>
Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.
I see.
Post by Julio Di Egidio
Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...
The code is very clean! I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token. Btw, I like your
ratio name of rats in the buildGraph function! Very clever.

:^)

I too am limited on my time. Damn!
Chris M. Thomasson
2017-06-28 18:19:57 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
Post by Chris M. Thomasson
Post by Julio Di Egidio
I have in mind "directly" mapping any string 1-to-1 to a pair of integers,
indeed leveraging the symmetries of the complex plot, but no calculations
with complex numbers actually involved, no taking roots etc., just directly
getting the two integers based on the geometric symmetries: which I haven't
had the time to think about yet, but should be some pretty simple closed
formula.
That said, the two integers (one if the length of the strings is fixed)
anyway directly correspond to a complex number, namely, again as per the
plot, to a point on the unit circle, just expressed as a fraction of 2 pi.
Which means, as an encoding scheme, this could be quite efficient, and with
arbitrary precision it is exact for arbitrary string length.
As such, that scheme could be useful e.g. for drawing Julia sets.
It's
not suited for cryptography, though: to begin with, Z above is fixed.
But
I haven't really had to time to think about this side either, for now I
just have a hunch it could work... :)
Think I see what you are getting at here... Humm... Fwiw, here is a
little table I made that shows some multiples of ratios of pi2 that
_____________________
0*(pi2 / 8):z:(-1.000000+0.000000i)
6*(pi2 / 8):z0:(0.000000+1.000000i)
2*(pi2 / 8):z1:(-0.000000-1.000000i)
5*(pi2 / 8):z00:(0.707107+0.707107i)
1*(pi2 / 8):z01:(-0.707107-0.707107i)
3*(pi2 / 8):z10:(0.707107-0.707107i)
7*(pi2 / 8):z11:(-0.707107+0.707107i)
9*(pi2 / 16):z000:(0.923880+0.382683i)
_____________________
This type of data is helping me understand whats going on here.
Two integers would be fine. a and b such that a/b gives an angle
sufficient enough to generate angles for encode/decode. The string
length would have to be fixed. Humm... Now, I am thinking of how to use
a single integer to reference an angle at a resolution good enough to
gain a fairly lengthy fixed string of symbols.
If we multiplied pi2 by a
large number and kept that constant, then we can use a single integer to
reference some fairly small angles within it.
The relation there is fixed: if we map the empty string to Z=-1 (as I am
doing) with an angle (as a multiple of 2 pi) of 1/2, the two strings of
length 1 will be "0" with an angle of 1/4 and "1" with an angle of 3/4,
and so on, the point being that for a string of length L, the angles are
all of the form N/D, where D=L+2 and 0 < N < D (modulo any mistakes of
mine...)
Post by Chris M. Thomasson
Hummm.... Thinking on and on , brainstroming away here! :^)
Indeed, on the line of exploring those "geometric symmetries", here
<http://julio.diegidio.name/lab/UnityEncoder/>
Enter binary digits and you will see a path forming. Please note that
it's far from finished: the tool itself is just a first proto but, more
importantly, the "direct" mapping I was talking about is not implemented
yet, I am cheating that out by still using complex numbers behind the
scenes.
I see.
Post by Julio Di Egidio
Anyway, should yo be interested, the code can be seen in the browser's
debugger: I hope it is easily readable, but please feel free to ask for
clarifications if needed. The mathematical gist of it is supposed to be
in the UnityEncoder object...
The code is very clean! I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token. Btw, I like your
ratio name of rats in the buildGraph function! Very clever.
:^)
I too am limited on my time. Damn!
Fwiw, the does not use root of unity: It instead uses fractal roots of
unity. If there is sch a thing, damn it!
Julio Di Egidio
2017-06-29 12:28:30 UTC
Permalink
Raw Message
<snip>
Post by Chris M. Thomasson
The code is very clean!
Thanks, that's great to hear.
Post by Chris M. Thomasson
I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token.
I'll have to study your code, I am still missing how we go from here to any
fractals...

OTOH, I don't really know what to do with what I have put together so
far (beside that it's helped some geometric thinking): as an encoding
of strings it's in fact highly inefficient, for an input of size L bits
the corresponding fraction would have size (summing the sizes of num and
den) strictly between L and 2L, 1.5L on the average: it works better the
other way round...
Post by Chris M. Thomasson
Btw, I like your
ratio name of rats in the buildGraph function! Very clever.
LOL, the advantage of not being an English native speaker. :) But I think
in programming it's a pretty conventional abbreviation.

Julio
Chris M. Thomasson
2017-06-29 20:36:53 UTC
Permalink
Raw Message
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
The code is very clean!
Thanks, that's great to hear.
Post by Chris M. Thomasson
I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token.
I'll have to study your code, I am still missing how we go from here to any
fractals...
Here is a full blown C99 fractal storage program that stores data in
16-bit blocks. It will output an ASCII PPM file called:
ct_cipher_rifc.ppm that you can open with the GIMP, or any other image
program that accepts PPM's. Use the following GCC command to compile my
code as an executable:

gcc *.c -std=c99 -lm

You can actually do this online here:

https://www.tutorialspoint.com/compile_c99_online.php

<fractal storage plotter code>
______________________________________
/* Experimental Fractal Data Storage by:
Chris M. Thomasson
Copyright 2017
________________________________________________________*/


#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <complex.h>
#include <tgmath.h>
#include <stdbool.h>


#define CT_PI2 6.283185307179586476925286766559

// Our loading threshold, 32 nits
#define CT_LOAD_MAX 32

// Our epsilon for error
#define CT_FIND_EPS 0.00000001

typedef double ct_real;
typedef double complex ct_complex;


/* Generic Plotter by Chris M. Thomasson
________________________________________________________*/
struct ct_axes
{
ct_real xmin;
ct_real xmax;
ct_real ymin;
ct_real ymax;
};

struct ct_axes
ct_axes_get(
ct_complex center,
ct_real diameter
){
ct_real radius = diameter / 2;

struct ct_axes axes = {
creal(center) - radius,
creal(center) + radius,
cimag(center) - radius,
cimag(center) + radius,
};

return axes;
}


struct ct_canvas_color
{
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
};


struct ct_canvas
{
unsigned long width;
unsigned long height;
struct ct_canvas_color* buf;
};

bool
ct_canvas_create(
struct ct_canvas* const self,
unsigned long width,
unsigned long height
){
size_t size = width * height * sizeof(*self->buf);

self->buf = calloc(1, size);

if (self->buf)
{
self->width = width;
self->height = height;

return true;
}

return false;
}

void
ct_canvas_destroy(
struct ct_canvas const* const self
){
free(self->buf);
}

bool
ct_canvas_save_ppm(
struct ct_canvas const* const self,
char const* fname
){
FILE* fout = fopen(fname, "w");

if (fout)
{
char const ppm_head[] =
"P3\n"
"# Chris M. Thomasson RIFC Cipher Renderer ver:0.0.0.0
(pre-alpha)";

fprintf(fout, "%s\n%lu %lu\n%u\n",
ppm_head,
self->width, self->height,
255U);

size_t size = self->width * self->height;

for (size_t i = 0; i < size; ++i)
{
struct ct_canvas_color c = self->buf[i];
fprintf(fout, "%u %u %u ", c.red, c.green, c.blue);
}

if (! fclose(fout))
{
return true;
}
}

return false;
}


struct ct_plane
{
struct ct_axes axes;
struct ct_canvas* canvas;
};

struct ct_pixel
{
size_t x;
size_t y;
};


struct ct_pixel
ct_plane_project(
struct ct_plane const* const self,
ct_complex c
){
ct_real awidth = self->axes.xmax - self->axes.xmin;
ct_real aheight = self->axes.ymax - self->axes.ymin;

ct_real xstep = awidth / (self->canvas->width - 1.0);
ct_real ystep = aheight / (self->canvas->height - 1.0);

struct ct_pixel pixel = {
(creal(c) - self->axes.xmin) / xstep,
(self->axes.ymax - cimag(c)) / ystep
};

return pixel;
}

bool
ct_plane_plot(
struct ct_plane* const self,
ct_complex c,
struct ct_canvas_color color
){
struct ct_pixel pixel = ct_plane_project(self, c);

if (pixel.x < self->canvas->width && pixel.y < self->canvas->height)
{
size_t cp = pixel.x + pixel.y * self->canvas->height;

if (cp < self->canvas->height * self->canvas->width)
{
self->canvas->buf[cp] = color;
return true;
}
}

return false;
}


/* RIFC (original) by Chris M. Thomasson
________________________________________________________*/
ct_complex
ct_root(
ct_complex const z,
long p,
unsigned long r
){
ct_real radius = pow(fabs(z), 1.0 / p);
ct_real angle_base = carg(z) / p;
ct_real angle_step = CT_PI2 / p;
ct_real angle = angle_base + angle_step * r;
ct_complex root = cos(angle) * radius + sin(angle) * radius * I;

return root;
}

// Stores a number v using a base
ct_complex
ct_store(
struct ct_plane* const plane,
ct_complex z,
ct_complex c,
unsigned long v,
long p
){
unsigned long b = abs(p);

/*
printf("ct_store:((%lf%+lfi), (%lf%+lfi), %lu, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), v, p);
*/
while (v)
{
// Gain the base
unsigned long d = v / b;
unsigned long r = v - d * b;

// Compute the proper root for the base
z = ct_root(z - c, p, r);

//printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), r);

struct ct_canvas_color color = {
v & 0x000000FF,
(v & 0x0000FF00) >> 8,
//(v & 0x00FF0000) >> 16,
255,
0
};

// Plot the point
ct_plane_plot(plane, z, color);

v = d;
}

// printf("result:(%lf%+lfi)\n", creal(z), cimag(z));
//printf("_______________________________\n\n");

return z;
}

// Loads a number at a base from z.
ct_complex
ct_load(
ct_complex z0,
ct_complex z,
ct_complex c,
unsigned long* pv,
long p
){
unsigned long v = 0;
unsigned long b = abs(p);

/*
printf("ct_load:((%lf%+lfi), (%lf%+lfi), %p, %ld)\n"
"_______________________________\n",
creal(z), cimag(z), creal(c), cimag(c), (void*)pv, p);
*/

for (unsigned long i = 0; i < CT_LOAD_MAX; ++i)
{
// Check for termination condition
ct_real d = fabs(z - z0);
if (d < CT_FIND_EPS) break;

// Raise z to the power and add c
ct_complex zn = pow(z, p) + c;

ct_complex r = 0 + 0 * I;
unsigned long ii = 0;

// Search for the stored root
for (ii = 0; ii < b; ++ii)
{
r = ct_root(zn - c, p, ii);
ct_real d = fabs(z - r);
if (d < CT_FIND_EPS) break;
}

// Recreate the number
v = b * v + ii;

//printf("(%lf%+lfi):%lu\n", creal(z), cimag(z), ii);

// Set the next iteration
z = zn;
}

*pv = v;

/*
printf("result:((%lf%+lfi), %lu)\n", creal(z), cimag(z), *pv);
printf("_______________________________\n\n");
*/

return z;
}


// Canvas width and height
#define CT_WIDTH 512
#define CT_HEIGHT CT_WIDTH

int main(void)
{
struct ct_canvas canvas;

bool status = ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT);
assert(status);

// Setup our plotting axes and plane
ct_complex center = 0 + 0 * I;
ct_real zoom_diameter = 3.5;
struct ct_axes axes = ct_axes_get(center, zoom_diameter);
struct ct_plane plane = { axes, &canvas };

// Our initial conditions
ct_complex z = -1+.0;
ct_complex c = -.75+.06*I;

// Power of -2
long p = 2;
unsigned long e = 0;

// Try to store/load values 0 through vmax-1
unsigned long vmax = 65536;
for (unsigned long v = 0; v < vmax; ++v)
{
// Store the data!
ct_complex z0 = z;
z = ct_store(&plane, z, c, v, p);

// Load the data and check for errors!
unsigned long lv = 0;
ct_load(z0, z, c, &lv, p);

if (lv != v)
{
//printf("ERROR: %lu != %lu \n", lv, v);
e += 1;
}

// Display progress
if (! (v % (vmax / 2048)))
{
printf("plotted:%lu of %lu, error: %lu\r", v, vmax, e);
}
}

printf("Plotting Complete:%lu of %lu, %lu errors\r", vmax, vmax, e);

status = ct_canvas_save_ppm(&canvas, "ct_cipher_rifc.ppm");
assert(status);
printf("\ncreated: ct_cipher_rifc.ppm\n");
ct_canvas_destroy(&canvas);

return 0;
}
______________________________________


The final output looks like:

Plotting Complete:65536 of 65536, 0 errors
created: ct_cipher_rifc.ppm


When you get some time, please try to give it a go. Actually, I think a
new thread is in order.

The initial conditions portion of the code, lines 330 and 331 modulo the
comment line:


// Our initial conditions
ct_complex z = -1+.0;
ct_complex c = -.75+.06*I;


Shows the initial z and the c I are using. This produces a PPM that
stores every bit pattern in 2-ary 16-bits. 0-65535 in the Seahorse
Valley of the Mandelbrot Set. Pretty nice!

Here is the image it outputs:

https://plus.google.com/101799841244447089430/posts/hGiM8YpacZR


I will give a more detailed description later on today. Btw, the code
does not produce any loss for me. Its perfect wrt loading the root chain
back up from the stored complex numbers.
Post by Julio Di Egidio
OTOH, I don't really know what to do with what I have put together so
far (beside that it's helped some geometric thinking): as an encoding
of strings it's in fact highly inefficient, for an input of size L bits
the corresponding fraction would have size (summing the sizes of num and
den) strictly between L and 2L, 1.5L on the average: it works better the
other way round...
Imvvho, even if it is inefficient, its still wonderful as an academic
exercise! Wrt using roots of unity on the unit circle, using a pair of
integers to represent an angle that can reproduce a complex number such
that the data can be reloaded is hyper interesting to me! Btw, to make
my code use roots of unity set c to 0+0i. ;^)
Post by Julio Di Egidio
Post by Chris M. Thomasson
Btw, I like your
ratio name of rats in the buildGraph function! Very clever.
LOL, the advantage of not being an English native speaker. :) But I think
in programming it's a pretty conventional abbreviation.
:^D

Fwiw, I am using the term "nits" to describe n-ary data!

Thank you for your interest Julio.

Imvvho, sci.math is NOT dead at all! This thread is proof?

Thanks again. :^)
Chris M. Thomasson
2017-06-29 21:14:21 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
The code is very clean!
Thanks, that's great to hear.
Post by Chris M. Thomasson
I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token.
I'll have to study your code, I am still missing how we go from here to any
fractals...
Here is a full blown C99 fractal storage program that stores data in
ct_cipher_rifc.ppm that you can open with the GIMP, or any other image
program that accepts PPM's. Use the following GCC command to compile my
gcc *.c -std=c99 -lm
https://www.tutorialspoint.com/compile_c99_online.php
<fractal storage plotter code>
______________________________________
[...]


Fwiw, the experimental code can be found here on PasteBin without ads in
raw form:

https://pastebin.com/raw/5UU6vrhP

Tried to post the code on Google+ and it fuc%ed it up. Google Groups
messes it up. Damn it!
Chris M. Thomasson
2017-07-01 04:39:04 UTC
Permalink
Raw Message
Post by Chris M. Thomasson
Post by Julio Di Egidio
<snip>
Post by Chris M. Thomasson
The code is very clean!
Thanks, that's great to hear.
Post by Chris M. Thomasson
I am almost finished with a fractal PPM plotter
that stores nits in blocks. A nit is an n-ary token.
I'll have to study your code, I am still missing how we go from here to any
fractals...
Here is a full blown C99 fractal storage program that stores data in
ct_cipher_rifc.ppm that you can open with the GIMP, or any other image
program that accepts PPM's. Use the following GCC command to compile my
gcc *.c -std=c99 -lm
https://www.tutorialspoint.com/compile_c99_online.php
<fractal storage plotter code>
______________________________________
[...]
Post by Chris M. Thomasson
______________________________________
Plotting Complete:65536 of 65536, 0 errors
created: ct_cipher_rifc.ppm
When you get some time, please try to give it a go. Actually, I think a
new thread is in order.
The initial conditions portion of the code, lines 330 and 331 modulo the
// Our initial conditions
ct_complex z = -1+.0;
ct_complex c = -.75+.06*I;
Shows the initial z and the c I are using. This produces a PPM that
stores every bit pattern in 2-ary 16-bits. 0-65535 in the Seahorse
Valley of the Mandelbrot Set. Pretty nice!
https://plus.google.com/101799841244447089430/posts/hGiM8YpacZR
I will give a more detailed description later on today. Btw, the code
does not produce any loss for me. Its perfect wrt loading the root chain
back up from the stored complex numbers.
Post by Julio Di Egidio
OTOH, I don't really know what to do with what I have put together so
far (beside that it's helped some geometric thinking): as an encoding
of strings it's in fact highly inefficient, for an input of size L bits
the corresponding fraction would have size (summing the sizes of num and
den) strictly between L and 2L, 1.5L on the average: it works better the
other way round...
Imvvho, even if it is inefficient, its still wonderful as an academic
exercise! Wrt using roots of unity on the unit circle, using a pair of
integers to represent an angle that can reproduce a complex number such
that the data can be reloaded is hyper interesting to me! Btw, to make
my code use roots of unity set c to 0+0i. ;^)
Post by Julio Di Egidio
Post by Chris M. Thomasson
Btw, I like your
ratio name of rats in the buildGraph function! Very clever.
LOL, the advantage of not being an English native speaker. :) But I think
in programming it's a pretty conventional abbreviation.
:^D
Fwiw, I am using the term "nits" to describe n-ary data!
Thank you for your interest Julio.
Imvvho, sci.math is NOT dead at all! This thread is proof?
Thanks again. :^)
Very briefly, to make fractals, think of taking the roots of z^n+c
instead of z^n. Now if we set c to zero and z to 1 or -1 we gain roots
of unity, the same as gaining the roots in the z^n version. The fractal
roots are in the form of (z-c)^(1/n) Julia sets. This still gives us n
roots. We map these roots to the n-ary data, or nits, using my method of
storing and loading n-ary data in roots. When we plot these points of
stored data on the plane, well, a fractal pops out wrt c. c = 0 makes a
circle, c = -.75+0.6i where n is 2 gives us the Seahorse valley. Very
nice, and interesting to me.

Humm... Need to create an online version of this thing! Much better than
having to compile and run c99 code, indeed!

Loading...