

# p is a U
iszero = (p) ->
	i = 0
	switch (p.k)
		when NUM
			if (MZERO(p.q.a))
				return 1
		when DOUBLE
			if (p.d == 0.0)
				return 1
		when TENSOR
			for i in [0...p.tensor.nelem]
				if (!iszero(p.tensor.elem[i]))
					return 0
			return 1
	return 0

# p is a U
isnegativenumber = (p) ->
	switch (p.k)
		when NUM
			if (MSIGN(p.q.a) == -1)
				return 1
		when DOUBLE
			if (p.d < 0.0)
				return 1
	return 0

# p is a U
isplusone = (p) ->
	switch (p.k)
		when NUM
			if (MEQUAL(p.q.a, 1) && MEQUAL(p.q.b, 1))
				return 1
		when DOUBLE
			if (p.d == 1.0)
				return 1
	return 0

isminusone = (p) ->
	switch (p.k)
		when NUM
			if (MEQUAL(p.q.a, -1) && MEQUAL(p.q.b, 1))
				return 1
		when DOUBLE
			if (p.d == -1.0)
				return 1
	return 0

isinteger = (p) ->
	if (p.k == NUM && MEQUAL(p.q.b, 1))
		return 1
	else
		return 0

isnonnegativeinteger = (p) ->
	if (isrational(p) && MEQUAL(p.q.b, 1) && MSIGN(p.q.a) == 1)
		return 1
	else
		return 0

isposint = (p) ->
	if (isinteger(p) && MSIGN(p.q.a) == 1)
		return 1
	else
		return 0

# both p,x are U
ispoly = (p,x) ->
	if (Find(p, x))
		return ispoly_expr(p, x)
	else
		return 0

ispoly_expr = (p,x) ->
	if (car(p) == symbol(ADD))
		p = cdr(p)
		while (iscons(p))
			if (!ispoly_term(car(p), x))
				return 0
			p = cdr(p)
		return 1
	else
		return ispoly_term(p, x)

ispoly_term = (p,x) ->
	if (car(p) == symbol(MULTIPLY))
		p = cdr(p)
		while (iscons(p))
			if (!ispoly_factor(car(p), x))
				return 0
			p = cdr(p)
		return 1
	else
		return ispoly_factor(p, x)

ispoly_factor = (p,x) ->
	if (equal(p, x))
		return 1
	if (car(p) == symbol(POWER) && equal(cadr(p), x))
		if (isposint(caddr(p)))
			return 1
		else
			return 0
	if (Find(p, x))
		return 0
	else
		return 1

isnegativeterm = (p) ->
	if (isnegativenumber(p))
		return 1
	else if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
		return 1
	else
		return 0

isimaginarynumber = (p) ->
	if ((car(p) == symbol(MULTIPLY) \
	&& length(p) == 3 \
	&& isnum(cadr(p)) \
	&& equal(caddr(p), imaginaryunit)) \
	|| equal(p, imaginaryunit))
		return 1
	else 
		return 0

iscomplexnumber = (p) ->
	if ((car(p) == symbol(ADD) \
	&& length(p) == 3 \
	&& isnum(cadr(p)) \
	&& isimaginarynumber(caddr(p))) \
	|| isimaginarynumber(p))
		return 1
	else
		return 0

iseveninteger = (p) ->
	if isinteger(p) && p.q.a.isEven()
		return 1
	else
		return 0

isnegative = (p) ->
	if (car(p) == symbol(ADD) && isnegativeterm(cadr(p)))
		return 1
	else if (isnegativeterm(p))
		return 1
	else
		return 0

# returns 1 if there's a symbol somewhere

issymbolic = (p) ->
	if (issymbol(p))
		return 1
	else
		while (iscons(p))
			if (issymbolic(car(p)))
				return 1
			p = cdr(p)
		return 0

# i.e. 2, 2^3, etc.

isintegerfactor = (p) ->
	if (isinteger(p) || car(p) == symbol(POWER) \
	&& isinteger(cadr(p)) \
	&& isinteger(caddr(p)))
		return 1
	else
		return 0

isoneover = (p) ->
	if (car(p) == symbol(POWER) \
	&& isminusone(caddr(p)))
		return 1
	else
		return 0

isfraction = (p) ->
	if (p.k == NUM && !MEQUAL(p.q.b, 1))
		return 1
	else
		return 0

# p is a U, n an int
equaln = (p,n) ->
	switch (p.k)
		when NUM
			if (MEQUAL(p.q.a, n) && MEQUAL(p.q.b, 1))
				return 1
		when DOUBLE
			if (p.d == n)
				return 1
	return 0

# p is a U, a and b ints
equalq = (p, a, b) ->
	switch (p.k)
		when NUM
			if (MEQUAL(p.q.a, a) && MEQUAL(p.q.b, b))
				return 1
		when DOUBLE
			if (p.d == a / b)
				return 1
	return 0

# p == 1/sqrt(2) ?

isoneoversqrttwo = (p) ->
	if (car(p) == symbol(POWER) \
	&& equaln(cadr(p), 2) \
	&& equalq(caddr(p), -1, 2))
		return 1
	else
		return 0

# p == -1/sqrt(2) ?

isminusoneoversqrttwo = (p) ->
	if (car(p) == symbol(MULTIPLY) \
	&& equaln(cadr(p), -1) \
	&& isoneoversqrttwo(caddr(p)) \
	&& length(p) == 3)
		return 1
	else
		return 0

isfloating = (p) ->
	if (p.k == DOUBLE)
		return 1
	while (iscons(p))
		if (isfloating(car(p)))
			return 1
		p = cdr(p)
	return 0

isimaginaryunit = (p) ->
	if (equal(p, imaginaryunit))
		return 1
	else
		return 0

# n/2 * i * pi ?

# return value:

#	0	no

#	1	1

#	2	-1

#	3	i

#	4	-i

isquarterturn = (p) ->
	n = 0
	minussign = 0

	if (car(p) != symbol(MULTIPLY))
		return 0

	if (equal(cadr(p), imaginaryunit))

		if (caddr(p) != symbol(PI))
			return 0

		if (length(p) != 3)
			return 0

		return 2

	if (!isnum(cadr(p)))
		return 0

	if (!equal(caddr(p), imaginaryunit))
		return 0

	if (cadddr(p) != symbol(PI))
		return 0

	if (length(p) != 4)
		return 0

	push(cadr(p))
	push_integer(2)
	multiply()

	n = pop_integer()

	if (n == 0x80000000)
		return 0

	if (n < 1)
		minussign = 1
		n = -n

	switch (n % 4)
		when 0
			n = 1
		when 1
			if (minussign)
				n = 4
			else
				n = 3
		when 2
			n = 2
		when 3
			if (minussign)
				n = 3
			else
				n = 4

	return n

# special multiple of pi?

# returns for the following multiples of pi...

#	-4/2	-3/2	-2/2	-1/2	1/2	2/2	3/2	4/2

#	4	1	2	3	1	2	3	4

isnpi = (p) ->
	n = 0
	if (p == symbol(PI))
		return 2
	if (car(p) == symbol(MULTIPLY) \
	&& isnum(cadr(p)) \
	&& caddr(p) == symbol(PI) \
	&& length(p) == 3)
		doNothing = 0
	else
		return 0
	push(cadr(p))
	push_integer(2)
	multiply()
	n = pop_integer()
	if (n == 0x80000000)
		return 0
	if (n < 0)
		n = 4 - (-n) % 4
	else
		n = 1 + (n - 1) % 4
	return n
