[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

kcl bug - equalp for vectors with fill pointers + FIX



----------------------------------------------------------------------
There appears to be a bug in kcl when performing an equalp on vectors
(strings, bitvectors) with fill pointers. Rather than comparing only up to the
fill pointer [CtLt p.81], the comparison is done up to the dimension of the
vector. 
----------------------------------------------------------------------
KCl (Kyoto Common Lisp)  June 3, 1987

>(lisp-implementation-version)
"June 3, 1987"

>(setf a (make-array 5 :initial-element 0 :fill-pointer 5))
#(0 0 0 0 0)

>(setf b (make-array 5 :initial-element 1 :fill-pointer 5))
#(1 1 1 1 1)

>(setf (fill-pointer b) 2)
2

>(pprint b)

#(1 1)

>(setf (aref b 0) 0)
0

>(setf (aref b 1) 0)
0

>(pprint b)

#(0 0)

>(pprint a)

#(0 0 0 0 0)

>(equalp a b)
NIL
----------------------------------------------------------------------
equalp should have returned T.

I believe the bug is in the file c/predicate.c in the routine equalp. There is
a block with label ARRAY: that performs the equalp for arrays.
Approximately lines 523-544 in KCL, or lines 540-561 in AKCL:
----------------------------------------------------------------------
Original code:

ARRAY:

	{
		int i, j;

		if (x->a.a_dim != y->a.a_dim)
			return(FALSE);
		vs_push(Cnil);
		vs_push(Cnil);
		for (i = 0, j = x->a.a_dim;  i < j;  i++) {
			vs_top[-2] = aref(x, i);
			vs_top[-1] = aref(y, i);
			if (!equalp(vs_top[-2], vs_top[-1])) {
				vs_pop;
				vs_pop;
				return(FALSE);
			}
		}
		vs_pop;
		vs_pop;
		return(TRUE);
	}
----------------------------------------------------------------------
New Code:

ARRAY:

	{
		int i, j;

		if (x->a.a_dim != y->a.a_dim)
			return(FALSE);
		vs_push(Cnil);
		vs_push(Cnil);
/* correction to code for equalp of two vector, strings or bit vectors. */
/* should compare only up to fill pointer */
		if (ty == t_vector || ty == t_string || ty == t_bitvector){
		        j = x->v.v_fillp;
			if( j > y->v.v_fillp )
			    j = y->v.v_fillp;
		} else {
		        j = x->a.a_dim;
		}
/*		for (i = 0, j = x->a.a_dim;  i < j;  i++) {*/
		for (i = 0;  i < j;  i++) {
/* End of correction */
			vs_top[-2] = aref(x, i);
			vs_top[-1] = aref(y, i);
			if (!equalp(vs_top[-2], vs_top[-1])) {
				vs_pop;
				vs_pop;
				return(FALSE);
			}
		}
		vs_pop;
		vs_pop;
		return(TRUE);
	}

----------------------------------------------------------------------

David Lim
david@ametek.com