## Let function / segfault

If you're having trouble using Context Free or don't understand the language, ask for help here.

Moderators: MtnViewJohn, chris, mtnviewmark

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Let function / segfault

With the latest hg source, this segfaults:

Code: Select all

``````testf(number a1, number b1) = if(a1==b1,5,10)
shape test
rule{
CIRCLE []
CIRCLE[x let(n=5..10;m=testf(n,2);1,m) a -0.5 sat 1 b 1 y 5 h 90]
}
``````
And I can't figure out how to use let in a function, or define local function variables:

Code: Select all

``````testf(number a1, number b1) = let(c=a1*b1;c)
shape test
rule{
CIRCLE []
CIRCLE[x testf(1,2)]
}
``````

Code: Select all

``````Error in test.cfdg at line 2 - Arguments are expected.
Error in test.cfdg at line 4 - Definition with same name as user function
Error in test.cfdg at line 4 -     user function definition is here.
``````
I also just found out about vector2 (after expanding the complex kissing circles formula) Is there a function that extracts individual terms from vectors?

MtnViewJohn
Posts: 875
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

### Re: Let function / segfault

sicivsibro wrote:With the latest hg source, this segfaults:

Code: Select all

``````testf(number a1, number b1) = if(a1==b1,5,10)
shape test
rule{
CIRCLE []
CIRCLE[x let(n=5..10;m=testf(n,2);1,m) a -0.5 sat 1 b 1 y 5 h 90]
}
``````
Yes, that is a bug. I see no problem with your code. I wonder what you are doing with 1,m as your let expression. This makes let() return a vector2. Giving a vector2 to the x adjustment is equivalent to setting x and y. But then you adjust y later on.

Also, 5..10 returns a real number in the interval [5,10). The odds of this being exactly equal to some integer is extremely small. Maybe you intend to use the randint() function?
sicivsibro wrote: And I can't figure out how to use let in a function, or define local function variables:

Code: Select all

``````testf(number a1, number b1) = let(c=a1*b1;c)
shape test
rule{
CIRCLE []
CIRCLE[x testf(1,2)]
}
``````

Code: Select all

``````Error in test.cfdg at line 2 - Arguments are expected.
Error in test.cfdg at line 4 - Definition with same name as user function
Error in test.cfdg at line 4 -     user function definition is here.
``````
Again, there is something going on with let(). Your code should work. But why have let() at all in this case? You could just have:

Code: Select all

``testf(a1, b1) = a1*b1``
sicivsibro wrote:
I also just found out about vector2 (after expanding the complex kissing circles formula) Is there a function that extracts individual terms from vectors?
Gah! I forgot to document the vector extraction operator! a1 extracts the 1st element of the vector2 a1 and a1 extracts the 2nd element.

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Re: Let function / segfault

That was just example/test code while I was fiddling, trying to get let to work. The actual function is:

Code: Select all

``````dtcrn(a1,b1,k1,a2,b2,k2,a3,b3,k3,k4) =
let(  p1r   = k1*a1 + k2*a2 + k3*a3;
p1i   = k1*b1 + k2*b2 + k3*b3;
p2r   = k1*k2*a1*a2 - k1*k2*b1*b2 + k2*k3*a2*a3 - k2*k3*b2*b3 + k1*k3*a1*a3 - k1*k3*b1*b3;
p2i   = k1*k2*a1*b2 + k1*k2*a2*b1 + k2*k3*a2*b3 + k2*k3*a3*b2 + k1*k3*a1*b3 + k1*k3*a3*b1;
p3r   = sqrt(sqrt((p2r^2) + (p2i^2)))*cos(atan2(p2i/p2r)/2);
p3i   = sqrt(sqrt((p2r^2) + (p2i^2)))*sin(atan2(p2i/p2r)/2);
p4rp  = (p1r + 2*p3r)/k4;
p4rn  = (p1r - 2*p3r)/k4;
p4ip  = (p1i + 2*p3i)/k4;
p4in  = (p1i - 2*p3i)/k4;
p4rn)
``````
a1 extracts the 1st element of the vector2 a1 and a1 extracts the 2nd element.
Great! I'll probably use vectors now to represent the complex numbers; this will make life a lot easier. Most likely I'll end with many more functions Cadd, Cmul, Csub, Csqrt, etc.

I wrote some example code to get a feel of the vector* parameter types:

Code: Select all

``````CF::Background = [b 1]
startshape tests() []

test_vector_parameter2(vector2 a1) = a1
test_vector_parameter3(vector3 a1) = a1
test_vector_parameter4(vector4 a1) = a1

vector2 test_vector_return2(number a1, number b1) = (a1,b1)
vector3 test_vector_return3(number a1, number b1, number c1) = (a1,b1,c1)

shape tests
rule {
CIRCLE [hue 200 sat 1 b 1]

// test vector parameters
CIRCLE [ x test_vector_parameter2((3,-3)) hue 50 sat 0.5 b 0.5]
CIRCLE [ x test_vector_parameter3((3,-3,5)) hue 250 sat 0.5 b 0.5]
CIRCLE [ x test_vector_parameter4((3,-3,5,0)) hue 300 sat 0.5 b 0.5]

// test vector return
CIRCLE [ x test_vector_return2(2,4) hue 25 sat 0.75 b 0.75]
CIRCLE [ x test_vector_return3(-2,4,-3) hue 300 sat 0.75 b 0.75]
CIRCLE [ x (test_vector_return3(-4,6,-5)) hue 300 sat 0.75 b 0.75]
}
``````
It all works fine, except the last CIRCLE entry is a syntax error:

Code: Select all

``````Error in test.cfdg at line 23 - syntax error
``````
Is it not allowed to use vector extraction operator inside a shape adjustment list?

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Re: Let function / segfault

I haven't been able to declare vector variables:

Code: Select all

``````test_vector_parameter3(vector3 a1) = a1

shape tests
rule {
vector = (10,20,3)
CIRCLE [s 0.5 x vector]
r1 = test_vector_parameter3(vector)
}
``````

Code: Select all

``````Error in test.vector.cfdg at line 25 - This argument should be a vector
Error in test.vector.cfdg at line 5 - This is the expected type.
``````
There is some weird behavior in the above too, the circle is shifted by (x,y)->(10,3), as though the vector variable were actually a vector, except it ignores the middle term.

in the meantime, my workaround is to define vector* construction functions:

Code: Select all

``````vector2 test_vector_return2(number a1, number b1) = (a1,b1)
vector2 vector2(number a1, number b1) = (a1,b1)

shape tests
rule {
vector = vector2(10,20)
CIRCLE [s 0.5 x vector]
r1 = test_vector_parameter2(vector)
}
``````

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Re: Let function / segfault

I'm running into some computational problems, and I think it is a problem with CFDG, but it is difficult to debug - could use some sort of print statement. In any case the following math computes correctly in python:

Code: Select all

``````vector2 vector2(number a1, number b1) = (a1,b1)
vector3 vector3(number a1, number b1, number c1) = (a1,b1,c1)

vector2 Cadd(vector2 c1, vector2 c2) =
(c1+c2,c1+c2)

vector2 Csub(vector2 c1, vector2 c2) =
(c1-c2,c1-c2)

vector2 Cmul(vector2 c1, vector2 c2) =
(((c1*c2)-(c1*c2)),((c1*c2)+(c1*c2)))

number Cmulconj(vector2 c1) =
(c1)^2 + (c1)^2

vector2 Cmulnum(vector2 c1, number n1) =
(c1*n1,c1*n1)

vector2 Cconj(vector2 c1) =
(c1,-c1)

vector2 Cdivnum(vector2 c1, number n1) =
(c1/n1,c1/n1)

vector2 Cdiv(vector2 c1, vector2 c2) =
Cdivnum(Cmul(c1,Cconj(c2)),Cmulconj(c2))

vector2 Csqrt(vector2 c1) =
(sqrt(sqrt(c1^2 + c1^2)) * cos(atan2(c1,c1)/2),
sqrt(sqrt(c1^2 + c1^2)) * sin(atan2(c1,c1)/2))

// Descartes' theorem of mutually tangent circles, negative and positive
dtn(k1,k2,k3) = k1 + k2 + k3 - 2*sqrt(k1*k2 + k2*k3 + k1*k3)
dtp(k1,k2,k3) = k1 + k2 + k3 - 2*sqrt(k1*k2 + k2*k3 + k1*k3)

// complex version
vector2 dtcn(vector2 c1, number k1, vector2 c2, number k2, vector2 c3, number k3, number k4) =
Cdivnum(

vector2 dtcp(vector2 c1, number k1, vector2 c2, number k2, vector2 c3, number k3, number k4) =
Cdivnum(

rule{
r1  = 1/2
k1  = 1/r1
c1  = vector2(0,0)
r2  = 1/2
k2  = 1/r2
c2  = vector2(1,0)
r3  = 1/2
k3  = 1/r3
c3  = vector2(1/2,sqrt(3)/2)
CIRCLE [x c1 s (2*r1)]
CIRCLE [x c2 s (2*r2)]
CIRCLE [x c3 s (2*r3)]
k4  = dtn(k1,k2,k3)
r4  = abs(1/k4)
c4  = dtcn(c1,k1,c2,k2,c3,k3,k4)
// the error
CIRCLE [x c4 s (2*r4)]
// no error, proper translation
//CIRCLE [x 0.5 y (sqrt(3)/6) s (2*r4)]
}
``````

Code: Select all

``````A shape got too big.
A shape got too big.
``````

MtnViewJohn
Posts: 875
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

### Re: Let function / segfault

The dtcn() function is returning a NaN. I will figure out where it is coming from.

MtnViewJohn
Posts: 875
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

### Re: Let function / segfault

I misspoke when I called it a vector extraction operator. It can only be used with a vector variable, not with an expression that returns a vector.

I fixed Context Free such that your Apollonian Gasket code works. I would like to send you a developer build so that you can try it and shake out more bugs. Which OS do you use?

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Re: Let function / segfault

Thanks, thats awesome: linux, but I prefer to compile from source (https://code.google.com/p/context-free/), so you need only send a patchset.

MtnViewJohn
Posts: 875
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

### Re: Let function / segfault

I just pushed all the changes up to https://code.google.com/p/context-free/

sicivsibro
Posts: 7
Joined: Mon Aug 20, 2012 12:21 pm

### Re: Let function / segfault

Overview
• segfault: fixed
• let: fixed
• vector variables: enabled/fixed
• weird vector/shape adjustment behavior: fixed
• vector function return: fixed
Overall: all fixed. Thanks!

One slight difference with latest ContextFree is that all functions default to the natural type, instead of number, generating these errors:

Code: Select all

``````Mismatch between declared natural and defined not-natural type of user function
``````
Fixed by a change like:

Code: Select all

``````type_error(number a1, number b1) = 5.5
number type_working_number(number a1, number b1) = 5.5
type_working_natural(number a1, number b1) = 5.0
``````

MtnViewJohn