[Python-Dev] Python's C interface for types

2007-02-02 Thread Nick Maclaren
Jim Jewett [EMAIL PROTECTED] wrote:
 
  Fine.  A very valid viewpoint.  Would you like to explain that to
  the IEEE 754 people?
 
 When Decimal was being argued, Tim pointed out that the standard
 requires certain operations, but doesn't require specific spelling
 shortcuts.  If you managed to do (and document) it right, people would
 be grateful for methods like
 
 a.exactly(b)
 a.close_enough(b)
 a.same_expected_value(b)
 
 but that doesn't mean any of them should be used when testing a==b

Hmm.  That is misleading, as you state it.  IEEE 754R doesn't include
specific spellings, but IEEE 754 assuredly does.  For example, it
states that the equality operator that delivers False for NaN = NaN
is spelled .EQ. in Fortran.

There was no C standard at the time, but the ad hoc' spellings are
clearly intended for C-like languages, and C99 is very clear that
the above equality operator is spelled '=='.

However, there is no requirement that Python uses those names.  What
IS important is (a) that the comparisons are consistent, (b) that
IEEE 754 (and IEEE 754R) define no reflexivity-preserving equality
operator and (c) that the current float type derives its comparisons
from C.

 (In Lisp, you typically can specify which equality predicate a
 hashtable should use on pairs of keys; in python, you only specify
 which it should use on objects of your class, and if the other object
 in the comparison disagrees, you're out of luck.)

Yup.

  Strictly, it is only the reflexive property that IEEE 754 and the
  Decimal module lack.  Yes, A == A is False, if A is a NaN.
 
 Therefore NaNs should never be used (in python) as dictionary keys.
 Therefore, they should be unhashable.

Again, a very valid point.  Are you suggesting a change? :-)

Currently, on my Linux system, Decimal raises an exception when trying
to hash a NaN value but float doesn't.  Is that a bug?

 Also note that PyObject_RichCompareBool (from Objects/object.c)
 assumes the reflexive property, and if you try to violate it, you will
 get occasional surprises.

Oh, yes, indeed!

  We already have the situation where A == B == 0, but where
  'C op A' != 'C op B' != 'C op 0'.  Both where op is a built-in
  operator and where 'C op' is a standard library function.
 
 That's fine; it just means that numeric equality may not be the
 strongest possible equivalence.  hash in particular just happens to be
 defined in terms of ==, however == is determined.

NO!!!  What it means is that the equality operator may not be the
strongest numeric equivalence!  A much stronger statement.

As I said, I am not grinding an axe, and have no answers.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Python's C interface for types

2007-02-01 Thread Nick Maclaren
Jim Jewett [EMAIL PROTECTED] wrote:
 
  For 0: hash(+0.0)==hash(-0.0)==hash(0)=hash(0L)=0
 
  Unfortunately, that assumes that equality is transitive.
 
 No, but the (transitively closed set of equivalent objects) must have
 the same hash.  ...

Er, how do you have a transitive closure for a non-transitive operation?

I really do mean that quite a lot of floating-point bells and whistles
are non-transitive.  The only one most people will have come across is
IEEE NaNs, where 'a is b' does not imply 'a == b', but there are a
lot of others (and have been since time immemorial).  I don't THINK
that IEEE 754R decimal introduces any, though I am not prepared to
bet on it.

  let us say that I am implementing a special function and want to
  distinguish -0.0 and +0.0.  Why can't I use a dictionary?
 
 Because they are equal.  They aren't identical, but they are equal.

You have missed my point, which is extended floating-points effectively
downgrade the status of the purely numeric comparisons, and therefore
introduce a reasonable requirement for using a tighter match.  Note
that I am merely commenting that this needs bearing in mind, and NOT
that anything should be changed.

  a = float(+0.0)
  b = float(-0.0)
  print a, b
 0.0 -0.0
 
 With the standard windows distribution, I get just
 
 0.0 0.0

Watch that space :-)  Expect it to change.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-02-01 Thread Martin v. Löwis
Nick Maclaren schrieb:
 For 0: hash(+0.0)==hash(-0.0)==hash(0)=hash(0L)=0
 Unfortunately, that assumes that equality is transitive.
 No, but the (transitively closed set of equivalent objects) must have
 the same hash.  ...
 
 Er, how do you have a transitive closure for a non-transitive operation?
 
 I really do mean that quite a lot of floating-point bells and whistles
 are non-transitive.

If so, they just shouldn't use the equal operator (==). == ought to
be transitive. It should be consistent with has().

 You have missed my point, which is extended floating-points effectively
 downgrade the status of the purely numeric comparisons, and therefore
 introduce a reasonable requirement for using a tighter match.  Note
 that I am merely commenting that this needs bearing in mind, and NOT
 that anything should be changed.

If introducing extended floating-points would cause trouble to existing
operations, I think extended floating-points should not be introduced
to Python. If all three of you really need them, come up with method
names to express almost equal or equal only after sunset.

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-02-01 Thread Nick Maclaren
=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?= [EMAIL PROTECTED] wrote:

  I really do mean that quite a lot of floating-point bells and whistles
  are non-transitive.

 If so, they just shouldn't use the equal operator (==). == ought to
 be transitive. It should be consistent with has().

Fine.  A very valid viewpoint.  Would you like to explain that to
the IEEE 754 people?

Strictly, it is only the reflexive property that IEEE 754 and the
Decimal module lack.  Yes, A == A is False, if A is a NaN.  But
the definition of 'transitive' often requires 'reflexive'.

 from decimal import *
 x = Decimal(NaN)
 x == x
False

I don't know any CURRENT systems where basic floating-point doesn't
have the strict transitive relation, but I wouldn't bet that there
aren't any.  You don't need to extend floating-point to have trouble;
even the basic forms often had it.  I sincerely hope that one is dead,
but people keep reinventing old mistakes :-(

The most common form was where comparison was equivalent to subtraction,
and there were numbers such that A-B == 0, B-C == 0 but A-C != 0.  That
could occur even for integers on some systems.  I don't THINK that the
Decimal specification has reintroduced this, but am not quite sure.

  You have missed my point, which is extended floating-points effectively
  downgrade the status of the purely numeric comparisons, and therefore
  introduce a reasonable requirement for using a tighter match.  Note
  that I am merely commenting that this needs bearing in mind, and NOT
  that anything should be changed.
 
 If introducing extended floating-points would cause trouble to existing
 operations, I think extended floating-points should not be introduced
 to Python. If all three of you really need them, come up with method
 names to express almost equal or equal only after sunset.

Fine.  Again, a very valid viewpoint.  Would you like to explain it
to the IEEE 754, Decimal and C99 people, and the Python people who
think that tracking C is a good idea?

We already have the situation where A == B == 0, but where
'C op A' != 'C op B' != 'C op 0'.  Both where op is a built-in
operator and where 'C op' is a standard library function.

This one is NOT going to go away, and is going to get more serious,
especially if extended floating-point formats like Decimal take off.
Note that it is not a fault in Decimal, but a feature of almost all
extended floating-points.  As I said, I have no answer to it.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-02-01 Thread Martin v. Löwis
Nick Maclaren schrieb:
 If so, they just shouldn't use the equal operator (==). == ought to
 be transitive. It should be consistent with has().
 
 Fine.  A very valid viewpoint.  Would you like to explain that to
 the IEEE 754 people?

Why should I? I don't talk about IEEE 754, I talk about Python.

 Strictly, it is only the reflexive property that IEEE 754 and the
 Decimal module lack.  Yes, A == A is False, if A is a NaN.  But
 the definition of 'transitive' often requires 'reflexive'.

I deliberately stated 'transitive', not 'reflexive'. The standard
definition of 'transitive' is if a==b and b==c then a==c.

 The most common form was where comparison was equivalent to subtraction,
 and there were numbers such that A-B == 0, B-C == 0 but A-C != 0.  That
 could occur even for integers on some systems.  I don't THINK that the
 Decimal specification has reintroduced this, but am not quite sure.

I'm not talking about subtraction, either. I'm talking about == and
hash.

 Fine.  Again, a very valid viewpoint.  Would you like to explain it
 to the IEEE 754, Decimal and C99 people, and the Python people who
 think that tracking C is a good idea?

I'm not explaining anything. I'm stating an opinion.

 This one is NOT going to go away, and is going to get more serious,
 especially if extended floating-point formats like Decimal take off.
 Note that it is not a fault in Decimal, but a feature of almost all
 extended floating-points.  As I said, I have no answer to it.

It doesn't look like you *need* to give an answer now. I thought
you were proposing some change to Python (although I'm uncertain
what that change could have been). If you are merely explaining
things (to whom?), just keep going.

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-02-01 Thread Nick Maclaren
=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?= [EMAIL PROTECTED] wrote:
 
  If so, they just shouldn't use the equal operator (==). == ought to
  be transitive. It should be consistent with has().
  
  Fine.  A very valid viewpoint.  Would you like to explain that to
  the IEEE 754 people?
 
 Why should I? I don't talk about IEEE 754, I talk about Python.

The problem is that Python is increasingly assuming IEEE 754 by
implication, and you were stating something as a requirement that
isn't true in IEEE 754.

  Strictly, it is only the reflexive property that IEEE 754 and the
  Decimal module lack.  Yes, A == A is False, if A is a NaN.  But
  the definition of 'transitive' often requires 'reflexive'.
 
 I deliberately stated 'transitive', not 'reflexive'. The standard
 definition of 'transitive' is if a==b and b==c then a==c.

When I was taught mathematics, the lecturer said that a transitive
relation is a reflexive one that has that extra property.  It was
then (and may still be) a fairly common usage.  I apologise for being
confusing!

  The most common form was where comparison was equivalent to subtraction,
  and there were numbers such that A-B == 0, B-C == 0 but A-C != 0.  That
  could occur even for integers on some systems.  I don't THINK that the
  Decimal specification has reintroduced this, but am not quite sure.
 
 I'm not talking about subtraction, either. I'm talking about == and
 hash.

Grrk.  Look again.  So am I.  But let this one pass, as I don't think
that mistake will return - and I sincerely hope not!

  Fine.  Again, a very valid viewpoint.  Would you like to explain it
  to the IEEE 754, Decimal and C99 people, and the Python people who
  think that tracking C is a good idea?
 
 I'm not explaining anything. I'm stating an opinion.

You are, however, stating an opinion that conflicts with the direction
that Python is currently taking.

 It doesn't look like you *need* to give an answer now. I thought
 you were proposing some change to Python (although I'm uncertain
 what that change could have been). If you are merely explaining
 things (to whom?), just keep going.

Thanks.  I hope the above clarifies things a bit.  My purpose in
posting is to point out that some changes are already happening,
by inclusion from other standards, that are introducing problems
to Python.  And to many other languages, incidentally, including
Fortran and C.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Python's C interface for types

2007-02-01 Thread Jim Jewett
Nick Maclaren wrote:
 I really do mean that quite a lot of floating-point bells and whistles
 are non-transitive.

Martin v. Löwis wrote:
 If so, they just shouldn't use the equal operator (==). == ought to
 be transitive. It should be consistent with has().

Nick Maclaren wrote:
 Fine.  A very valid viewpoint.  Would you like to explain that to
 the IEEE 754 people?

When Decimal was being argued, Tim pointed out that the standard
requires certain operations, but doesn't require specific spelling
shortcuts.  If you managed to do (and document) it right, people would
be grateful for methods like

a.exactly(b)
a.close_enough(b)
a.same_expected_value(b)

but that doesn't mean any of them should be used when testing a==b

(In Lisp, you typically can specify which equality predicate a
hashtable should use on pairs of keys; in python, you only specify
which it should use on objects of your class, and if the other object
in the comparison disagrees, you're out of luck.)

 Strictly, it is only the reflexive property that IEEE 754 and the
 Decimal module lack.  Yes, A == A is False, if A is a NaN.

Therefore NaNs should never be used (in python) as dictionary keys.
Therefore, they should be unhashable.

Also note that PyObject_RichCompareBool (from Objects/object.c)
assumes the reflexive property, and if you try to violate it, you will
get occasional surprises.

 We already have the situation where A == B == 0, but where
 'C op A' != 'C op B' != 'C op 0'.  Both where op is a built-in
 operator and where 'C op' is a standard library function.

That's fine; it just means that numeric equality may not be the
strongest possible equivalence.  hash in particular just happens to be
defined in terms of ==, however == is determined.

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Python's C interface for types

2007-01-31 Thread Jim Jewett
Nick Maclaren wrote:
 Martin v. Löwis wrote:


 It may be a bit problematic to implement, but I think a clean
 specification is possible. If a and b are numbers, and a==b,
 then hash(a)==hash(b).

You don't even need that much complication.

If a==b, then hash(a) == hash(b)

If you have to break this, then at least one (preferably both) of
(a,b) must be unhashable, so that it won't get used as a dict key.

Hashing is only ever meaningful as a shortcut to quickly show that two
objects are *not* equal.

 I'm not sure whether approximately 5.0
 equals 5 or not: if it does, it should hash the same as 5,
 if it doesn't, it may or may not hash the same (whatever is
 easier to implement).

agreed.

 For 0: hash(+0.0)==hash(-0.0)==hash(0)=hash(0L)=0

 Unfortunately, that assumes that equality is transitive.

No, but the (transitively closed set of equivalent objects) must have
the same hash.  If

 myfloat(5.0) != 5.0
True

then you could just return 47 as the hash.  It might not be terribly
efficient, but it would work.

If

 myfloat_exact(5.0) == 5.0 == myfloat_approx(5.0) != myfloat_exact(5.0)

then at least one of (myfloat_exact, myfloat_approx) needs to be
unhashable, so that it can't be used as a dictionary key.

 let us say that I am implementing a special function and want to
 distinguish -0.0 and +0.0.  Why can't I use a dictionary?

Because they are equal.  They aren't identical, but they are equal.

 a = float(+0.0)
 b = float(-0.0)
 print a, b
0.0 -0.0

With the standard windows distribution, I get just

0.0 0.0

 No, I don't have an answer.  You are damned if you do, and damned
 if you don't.  It is an insoluble problem, and CURRENTLY doesn't
 justify two hashing mechanisms (i.e. ANY difference and EQUALITY
 difference).

You want something in between __eq__ and is.  (a.identical(b) ?)
Hashing is weaker than either.

 hash (JimJ) == hash (2010274390)
True

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-27 Thread Martin v. Löwis
Tim Peters schrieb:
 Does that mean that they are unstable, in the sense that they may
 change behaviour in new versions of Python?
 
 They /may/ change, but they won't (== only common sense guarantees
 they won't change ;-)).

That, of course, is true for any API. For the documented API, there
is certainly a stronger desire to provide backwards compatibility in
the face of changes, but in some cases, it just means that the change
also gets documented.

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-27 Thread Nick Maclaren
=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?= [EMAIL PROTECTED] wrote:

 [not sure what And so it goes means in English]

I apologise.  I try to restrain myself from using excessive idiom,
but sometimes I forget.  It means That is how things are, and there
is and will be more of the same.

 It may be a bit problematic to implement, but I think a clean
 specification is possible. If a and b are numbers, and a==b,
 then hash(a)==hash(b). I'm not sure whether approximately 5.0
 equals 5 or not: if it does, it should hash the same as 5,
 if it doesn't, it may or may not hash the same (whatever is
 easier to implement).
 For 0: hash(+0.0)==hash(-0.0)==hash(0)=hash(0L)=0

Unfortunately, that assumes that equality is transitive.  With the
advanced floating-point models, it may not be.  For example, if you
want to avoid the loss of error information, exact infinity and
approximate infinity (the result of overflow) have different
semantics.  Similarly with infinitesimals.

Even at present, Python's float (Decimal probably more so) doesn't
allow you to do some things that are quite reasonable.  For example,
let us say that I am implementing a special function and want to
distinguish -0.0 and +0.0.  Why can't I use a dictionary?

 a = float(+0.0)
 b = float(-0.0)
 print a, b
0.0 -0.0
 c = {a: +0.0, b: -0.0}
 print c[a], c[b]
-0.0 -0.0

Well, we all know why.  But it is not what some quite reasonable
programmers will expect.  And Decimal (with its cohorts and variant
precisions) has this problem quite badly - as do I.

No, I don't have an answer.  You are damned if you do, and damned
if you don't.  It is an insoluble problem, and CURRENTLY doesn't
justify two hashing mechanisms (i.e. ANY difference and EQUALITY
difference).



Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
I have a fair amount of my binary floating-point model written,
though even of what I have done only some is debugged (and none
has been rigorously tested).  But I have hit some things that I
can't work out, and one query reduced comp.lang.python to a
stunned silence :-)

Note that I am not intending to do all the following, at least for
now, but I have had to restructure half a dozen times to match my
implementation requirements to the C interface (as I have learnt
more about Python!) and designing to avoid that is always good.

Any pointers appreciated.

I can't find any detailed description of the methods that I need
to provide.  Specifically:

Does Python use classic division (nb_divide) and inversion (nb_invert)
or are they entirely historical?  Note that I can very easily provide
the latter.

Is there any documentation on the coercion function (nb_coerce)?  It
seems to have unusual properties.

How critical is the 'numeric' property of the nb_hash function?  I
can certainly honour it, but is it worth it?

I assume that Python will call nb_richcompare if defined and 
nb_compare if not.  Is that right?

Are the inplace methods used and, if so, what is their specification?

I assume that I can ignore all of the allocation, deallocation and
attribute handling functions, as the default for a VAR object is
fine.  That seems to work.

Except for one thing!  My base type is static, but I create some
space for every derivation (and it can ONLY be used in derived form).
The space creation is donein C but the derivation in Python.  I
assume that I need a class (not instance) destructor, but what
should it do to free the space?  Call C to Py_DECREF it?

I assume that a class structure will never go away until after all
instances have gone away (unless I use Py_DECREF), so a C pointer
from an instance to something owned by the class is OK.

Is there any documentation on how to support marshalling/pickling
and the converse from C types?

I would quite like to provide some attributes.  They are 'simple'
but need code executing to return them.  I assume that means that
they aren't simple enough, and have to be provided as methods
(like conjugate).  That's what I have done, anyway.

Is there any obvious place for a reduction method to be hooked in?
That is a method that takes a sequence, all members of which must
be convertible to a single class, and returns a member of that
class.  Note that it specifically does NOT make sense on a single
value of that class.

Sorry about the length of this!


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Thomas Wouters

On 1/26/07, Nick Maclaren [EMAIL PROTECTED] wrote:


Does Python use classic division (nb_divide) and inversion (nb_invert)
or are they entirely historical?  Note that I can very easily provide
the latter.



nb_divide is used for the division operation (/) when not using 'from
__future__ import division', and PyNumber_Divide(). It doesn't fall back to
foor_divide or true_divide.
nb_invert is used for bitwise inversion (~) and PyNumber_Invert(). It's not
historical, it's actual.

Is there any documentation on the coercion function (nb_coerce)?  It

seems to have unusual properties.



I don't recall ever seeing useful documentation on coerce() and nb_coerce. I
suggest not to use it; it's gone in Python 3.0 anyway.

How critical is the 'numeric' property of the nb_hash function?  I

can certainly honour it, but is it worth it?



Which numeric property? the fact that it returns a C long? Or that, for
natural numbers, it *seems* to return self? The former is quite important,
the latter not very. The important bit is that an object's hash() be equal
to the hash() of objects that it is considered equal to. That is to say, if
you have 'd = {5: five}' and you want 'f = yourtype(5); d[f]' to result in
five, hash(f) must be equal to hash(5). The builtin floats do that.
There's no strict requirement that equal objects must have equal hashes, but
people using sets and dicts really appreciate it. ('f == 5 and f not in
set([5])' to be True would be confusing.)

I assume that Python will call nb_richcompare if defined and

nb_compare if not.  Is that right?



Yes.

Are the inplace methods used and, if so, what is their specification?


(Hah, my specialty.) Inplace methods are used for the augmented-assignment
statements: '+=' and the like. They are free to modify 'self' or return a
new object. Python falls back to the normal, non-inplace operations if the
inplace methods are not defined. I assume your floating-point type is
immutable, so you won't have to implement them. (If the type is to be
mutable, don't forget to make them unhashable, by not defining nb_hash.)

I assume that I can ignore all of the allocation, deallocation and

attribute handling functions, as the default for a VAR object is
fine.  That seems to work.

Except for one thing!  My base type is static, but I create some
space for every derivation (and it can ONLY be used in derived form).
The space creation is donein C but the derivation in Python.  I
assume that I need a class (not instance) destructor, but what
should it do to free the space?  Call C to Py_DECREF it?



Where do you allocate this space, and how do you allocate it? If it's space
you malloc() and store somewhere in the type struct, yecchh. You should not
just allocate stuff at the end of the type struct, as the type struct's
layout is not under your control (we actually extend the type struct as
needed, which is why newer features end up in less logical places at the end
of the struct ;) I would suggest using attributes of the type instead, with
the normal Python refcounting. That means the 'extra space' has to be an
actual Python object, though.


I assume that a class structure will never go away until after all

instances have gone away (unless I use Py_DECREF), so a C pointer
from an instance to something owned by the class is OK.



Correct.

Is there any documentation on how to support marshalling/pickling

and the converse from C types?



I don't you can make your own type marshallable. For pickle it's more or
less the same as for Python types. The pickle docs (and maybe
http://www.python.org/dev/peps/pep-0307/) probably cover what you want to
know. You can also look at one of the complexer builtin types that support
pickling, like the datetime types.

I would quite like to provide some attributes.  They are 'simple'

but need code executing to return them.  I assume that means that
they aren't simple enough, and have to be provided as methods
(like conjugate).  That's what I have done, anyway.



You can use PyGetSetDef to get 'easy' attributes with getters and setters.
http://docs.python.org/api/type-structs.html#l2h-1020

Is there any obvious place for a reduction method to be hooked in?

That is a method that takes a sequence, all members of which must
be convertible to a single class, and returns a member of that
class.  Note that it specifically does NOT make sense on a single
value of that class.



There's nothing I can think of that is a natural match for that in standard
Python methods. I would suggest just making it a classmethod.
(dict.fromkeysis a good example of a classmethod in C.)

As a final note: Python's source itself is a good source of answers and
examples. Almost all of the features of the Python API are used in a builtin
type or stdlib module, and for C source, Python's source is remarkably
readable ;-)

--
Thomas Wouters [EMAIL PROTECTED]

Hi! I'm a .signature virus! copy me into your .signature file to help me
spread!

Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
Thanks very much!  That answers most things.  Yes, I had got many
of my answers from searching the source, but there is clearly some
history there, and it isn't always clear what is current.  Here are
a few responses to the areas of confusion:

 nb_invert is used for bitwise inversion (~) and PyNumber_Invert(). It's not
 historical, it's actual.

Ah!  So it's NOT 1/x!  No relevant to floating-point, then.

 I don't recall ever seeing useful documentation on coerce() and nb_coerce.
 I suggest not to use it; it's gone in Python 3.0 anyway.

Excellent!  Task completed :-)

 Which numeric property? the fact that it returns a C long? Or that, for
 natural numbers, it *seems* to return self? 

The latter.  hash(123) == hash(123.0) for example.  It is a real
pain for advanced formats.  Making it the same for things that compare
equal isn't a problem.

 [inplace ] I assume your floating-point type is
 immutable, so you won't have to implement them.

I haven't done anything special to flag it as such, but it is.

 Where do you allocate this space, and how do you allocate it? If it's space
 you malloc() and store somewhere in the type struct, yecchh. You should not
 just allocate stuff at the end of the type struct, as the type struct's
 layout is not under your control (we actually extend the type struct as
 needed, which is why newer features end up in less logical places at the end
 of the struct ;) I would suggest using attributes of the type instead, with
 the normal Python refcounting. That means the 'extra space' has to be an
 actual Python object, though.

PyMem_Malloc.  I can certainly make it an attribute, as the overhead
isn't large for a per-class object.  It is just a block of mutable
memory, opaque to the Python layer, and NOT containing any pointers!

 I don't you can make your own type marshallable. For pickle it's more or
 less the same as for Python types. The pickle docs (and maybe
 http://www.python.org/dev/peps/pep-0307/) probably cover what you want to
 know. You can also look at one of the complexer builtin types that support
 pickling, like the datetime types.

The only documentation I have found is how to do it in Python.  Is
that what you mean?  I will look at the datetime types.

 You can use PyGetSetDef to get 'easy' attributes with getters and setters.
 http://docs.python.org/api/type-structs.html#l2h-1020

I was put off by some of the warnings.  I will revisit it.

 There's nothing I can think of that is a natural match for that in standard
 Python methods. I would suggest just making it a classmethod.
 (dict.fromkeysis a good example of a classmethod in C.)

Thanks.  That is a useful reference.  Reductions are a problem in
many languages.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
Oops.  Something else fairly major I forgot to ask.  Python long.
I can't find any clean way of converting to or from this, and
would much rather not build a knowledge of long's internals into
my code.  Going via text is, of course, possible - but is not very
efficient, even using hex/octal.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Giovanni Bajo
On 26/01/2007 17.03, Thomas Wouters wrote:

 How critical is the 'numeric' property of the nb_hash function?  I
 can certainly honour it, but is it worth it?
 
 [...]
 There's no strict requirement that 
 equal objects must have equal hashes, 

Uh? I thought that was the *only* strict requirement of hash. In fact the docs 
agree:


__hash__( self)

Called for the key object for dictionary operations, and by the built-in 
function hash(). Should return a 32-bit integer usable as a hash value for 
dictionary operations. The only required property is that objects which 
compare equal have the same hash value; [...]


I personally consider *very* important that hash(5.0) == hash(5) (and that 5.0 
== 5, of course).
-- 
Giovanni Bajo

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Josiah Carlson

Nick Maclaren [EMAIL PROTECTED] wrote:
 
 Oops.  Something else fairly major I forgot to ask.  Python long.
 I can't find any clean way of converting to or from this, and
 would much rather not build a knowledge of long's internals into
 my code.  Going via text is, of course, possible - but is not very
 efficient, even using hex/octal.

See _PyLong_FromByteArray and _PyLong_AsByteArray .

 - Josiah

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
Giovanni Bajo [EMAIL PROTECTED] wrote:

 I personally consider *very* important that hash(5.0) == hash(5) (and
 that 5.0 == 5, of course).

It gets a bit problematic with floating-point, when you can have
different values exactly 5.0 and approximately 5.0.  IEEE 754
has signed zeroes.  And so it goes.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
Josiah Carlson [EMAIL PROTECTED] wrote:

 See _PyLong_FromByteArray and _PyLong_AsByteArray .

Oops!  Thanks very much.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Aahz
On Fri, Jan 26, 2007, Giovanni Bajo wrote:
 On 26/01/2007 17.03, Thomas Wouters wrote:
 
 There's no strict requirement that equal objects must have equal 
 hashes,  

 Uh? I thought that was the *only* strict requirement of hash. In fact
 the docs agree:

 
 __hash__( self)
 
 Called for the key object for dictionary operations, and by the built-in 
 function hash(). Should return a 32-bit integer usable as a hash value for 
 dictionary operations. The only required property is that objects which 
 compare equal have the same hash value; [...]
 

Possibly the docs should be updated, but this is only intended to apply
to objects of the same type.

 I personally consider *very* important that hash(5.0) == hash(5) (and
 that 5.0 == 5, of course).

Well, sure, but That's Different.
-- 
Aahz ([EMAIL PROTECTED])   * http://www.pythoncraft.com/

I disrespectfully agree.  --SJM
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Nick Maclaren
Having looked into the answers a bit more deeply, I am afraid that
I am still a bit puzzled.

1) As I understand it, PyMem_Malloc won't cause trouble, but won't
be automatically freed, either, as it doesn't return a new reference.
I don't think that immediately following it by PyCObject_FromVoidPtr
(which is what I do) helps with that.  What I need is some standard
type that allows me to allocate an anonymous block of memory; yes,
I can define such a type, but that seems excessive.  Is there one?

2) _PyLong_FromByteArray and _PyLong_AsByteArray aren't in the API
and have no comments.  Does that mean that they are unstable, in the
sense that they may change behaviour in new versions of Python?
And will they be there in 3.0?

Thanks for any help, again.


Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QH, England.
Email:  [EMAIL PROTECTED]
Tel.:  +44 1223 334761Fax:  +44 1223 334679
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Martin v. Löwis
Nick Maclaren schrieb:
 I personally consider *very* important that hash(5.0) == hash(5) (and
 that 5.0 == 5, of course).
 
 It gets a bit problematic with floating-point, when you can have
 different values exactly 5.0 and approximately 5.0.  IEEE 754
 has signed zeroes.  And so it goes.

[not sure what And so it goes means in English]

It may be a bit problematic to implement, but I think a clean
specification is possible. If a and b are numbers, and a==b,
then hash(a)==hash(b). I'm not sure whether approximately 5.0
equals 5 or not: if it does, it should hash the same as 5,
if it doesn't, it may or may not hash the same (whatever is
easier to implement).
For 0: hash(+0.0)==hash(-0.0)==hash(0)=hash(0L)=0

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python's C interface for types

2007-01-26 Thread Tim Peters
[Nick Maclaren]
 ...
 2) _PyLong_FromByteArray and _PyLong_AsByteArray aren't in
 the API

They're not in the public API, which is equivalent to that their names
begin with a leading underscore.  They're in the private API :-)

 and have no comments.

The behavior of these functions, including return value and error
conditions, is specified in longobject.h.

 Does that mean that they are unstable, in the sense that they may
 change behaviour in new versions of Python?

They /may/ change, but they won't (== only common sense guarantees
they won't change ;-)).

 And will they be there in 3.0?

Almost certainly so.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com