Since x is a symbol, featurep(x, real) is answered directly by kindp, which checks the database, but since nothing is stored on x, it says nil.
featurep(x^2, real) calls $rectform and checks if it contains %i. Since it doesn't, the answer is nil. By the way, I don't like that. Why not check if $imagpart is 0 instead? The test suite seems to work fine with this, and it should be slightly faster.
Maybe featurep(expr, real) should always use the imagpart(expr) = 0 check regardless of whether expr is a symbol or not?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
featurep doesn't have a special case for complex, unlike for real. featurep(%i, complex) is answered by kindp, but featurep(%i+1, complex) isn't handled by any test, and we get nil.
Should featurep(expr, complex) test whether imagpart(expr) # 0? Of course # 0 doesn't mean that it's really non-zero. But that's better than nothing. I definitely wouldn't advocate for using ratsimp or even zeroequiv here.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The test suite is also fine with these changes.
Unless there are objections, I will make these changes within the next couple of days and add some test cases.
Last edit: David Scherfgen 1 day ago
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I do have a problem with featurep, though: it has strayed very far from its original function, which was simply looking up properties in the database. This isn't new -- I think it started at MIT in the 70's -- but that changed it from a simple and clearly-defined lookup to a "best effort" inference function where you don't know how reliable the results are. Simple examples work fine:
But the definitional drift means that its return value is hard to interpret. A best-effort function to determine whether an object has a certain property should not return true/false meaning Yes/Unknown, but rather true/false/unknown. It's perfectly OK that featurep can't determine whether the following cases are true, but wouldn't it be nice if it said unknown instead of false? After all, it is impossible to handle all cases.
Yes, allowing featurep to return unknown would be a great addition.
There's another (smaller) problem: The manual says that real, complex and imaginary can be assigned to variables via declare. However, this also works for (user-defined) functions:
(%i1)declare(f,real,g,complex)$(%i2)rectform(f(x));(%o2)f(x);(%i3)rectform(g(x));(%o3)realpart(g(x))+%i*imagpart(g(x))/* h(x) treated like complex by default */(%i4)rectform(h(x));(%o4)realpart(h(x))+%i*imagpart(h(x))
Seems like that comment is outdated: Maxima treats h(x) like complex by default. The discrepancy: While variables are treated as real by default, functions apparently are treated as complex by default.
The problem: When using declare, there's no way to distinguish between a variable and a function. A declaration always applies to both.
For sign, there is a feature especially for functions: posfun. So if one wants to say that a function f(x) is always positive, one calls declare(f, posfun), while for a variable f, one would call assume(f > 0).
Maybe add a feature realfun?
Last edit: David Scherfgen 2 hours ago
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Good catch!
Since
xis a symbol,featurep(x, real)is answered directly bykindp, which checks the database, but since nothing is stored onx, it saysnil.featurep(x^2, real)calls$rectformand checks if it contains%i. Since it doesn't, the answer isnil. By the way, I don't like that. Why not check if$imagpartis 0 instead? The test suite seems to work fine with this, and it should be slightly faster.Maybe
featurep(expr, real)should always use theimagpart(expr) = 0check regardless of whetherexpris a symbol or not?Similarly wrong:
featurepdoesn't have a special case forcomplex, unlike forreal.featurep(%i, complex)is answered bykindp, butfeaturep(%i+1, complex)isn't handled by any test, and we getnil.Should
featurep(expr, complex)test whetherimagpart(expr) # 0? Of course# 0doesn't mean that it's really non-zero. But that's better than nothing. I definitely wouldn't advocate for usingratsimpor evenzeroequivhere.I suggest using the following
condclauses in$featurep:With these changes:
The test suite is also fine with these changes.
Unless there are objections, I will make these changes within the next couple of days and add some test cases.
Last edit: David Scherfgen 1 day ago
The code looks correct.
I do have a problem with featurep, though: it has strayed very far from its original function, which was simply looking up properties in the database. This isn't new -- I think it started at MIT in the 70's -- but that changed it from a simple and clearly-defined lookup to a "best effort" inference function where you don't know how reliable the results are. Simple examples work fine:
But the definitional drift means that its return value is hard to interpret. A best-effort function to determine whether an object has a certain property should not return true/false meaning Yes/Unknown, but rather true/false/unknown. It's perfectly OK that featurep can't determine whether the following cases are true, but wouldn't it be nice if it said unknown instead of false? After all, it is impossible to handle all cases.
Yes, allowing
featurepto returnunknownwould be a great addition.There's another (smaller) problem: The manual says that
real,complexandimaginarycan be assigned to variables viadeclare. However, this also works for (user-defined) functions:A comment in
rpart.lispsays:Seems like that comment is outdated: Maxima treats
h(x)like complex by default. The discrepancy: While variables are treated as real by default, functions apparently are treated as complex by default.The problem: When using
declare, there's no way to distinguish between a variable and a function. A declaration always applies to both.For sign, there is a feature especially for functions:
posfun. So if one wants to say that a functionf(x)is always positive, one callsdeclare(f, posfun), while for a variablef, one would callassume(f > 0).Maybe add a feature
realfun?Last edit: David Scherfgen 2 hours ago