[MATRIX-SIG] Type questions

Timothy A. Hochberg Timothy A. Hochberg" <hochberg@wwa.com
Tue, 9 Sep 1997 10:53:35 -0500 (CDT)


On Tue, 9 Sep 1997, Janko Hauser wrote:

> I have soem problems to hold the type of my arrays because of the
> coercion-rules with regard to simple float numbers.

I'm straining to remember why this is... Here's the info, way back in a
musty corner of my head:

It's not safe to cast arrays of type Int to type 'f'. To see this try:

>>> array((sys.maxint,))
array([2147483647])
>>> array((sys.maxint,)).astype('f')[0] # Array printer breaks on big floats...
2147483648.0
>>> # OOOOPS!

So Int arrays are always cast to type Float when doing multiplication,
etc., which is suprising at first. The casting hiearchy looks something
like: 

Int8(1)--------+->Int16(s)+->Int32(i/l)+
               |          |            |
UnsignedInt8(b)+          +->Float32(f)+->Float64(d)--+
                                       |              |
                                       +->Complex64(F)+->Complex128(D)

( 
Big parentetical comment:

Hmmm. Int32->Complex64 is unsafe but is still allowed. That's probably a
bug. And i/l might cause a problem on 64 bit machines as noted in
PyArray_CanCastSafely.)

The suffixes on Int and Float (8, 16, etc.) may vary depending on machine. 
)

> 
> Example:
> >>> a
> array([[0, 1, 2],
>        [3, 4, 5],
>        [6, 7, 8]])
> >>> b=a*1.2  # this changes to a double array because 1.2 is a double 
> >>> b
> array([[ 0. ,  1.2,  2.4],
>        [ 3.6,  4.8,  6. ],
>        [ 7.2,  8.4,  9.6]])
> >>> b.typecode()
> 'd'
> >>> b=a*array([1.2],'f') # why is this a double?
> >>> b.typecode()
> 'd'

This is a double because the array a cannot be safely coerced to type 'f'.

> >>> b=a.astype('f')*array([1.2],'f')
> >>> b.typecode()
> 'f'
> >>> 
>
> 
> I see no way to say python that a float is not double like the
> ``12L''. The simple way would be to have something like
> asarray(number) (code appended). But isn't it possible to do it
> directly in array?

The funcionality you're looking for is allready (sortof) in array.
array(x, 'f', copy=0) works essentially the same as masarray(x,'f')
does. (The shape of the array returned is different, but I think that's
OK for what your doing.)

One thing to consider is that Int16 ('s') can safely be converted to type
'f', so if you know your integers fit into a 16 bit integer, you can do
something like.

>>> b
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]],'s')
>>> b*array(1.2, 'f')
array([[ 0.        ,  1.20000005,  2.4000001 ],
       [ 3.60000014,  4.80000019,  6.        ],
       [ 7.20000029,  8.40000057,  9.60000038]],'f')

[SNIP] 
> ###################### myasarray.py
> 
> def masarray(a,typecode=None):
>     if typecode == None:
> 	if ((type(a) == type(1)) or (type(a) == type(1.2))):
> 	    return array([a])
> 	else:
> 	    return array(a, copy=0)
>     else:
> 	if ((type(a) == type(1)) or (type(a) == type(1.2))):
> 	    return array([a],typecode)
> 	else:
> 	    return array(a, typecode, copy=0)

 ____   
  /im  

+------------------------------------------------+
|Tim Hochberg            Research Assistant      |
|hochberg <at> wwa.com   University of Illinois  |
|                        Electrical Engineering  |
+------------------------------------------------+




_______________
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
_______________